├── Procfile
├── README.md
├── app.py
└── requirements.txt
/Procfile:
--------------------------------------------------------------------------------
1 | web: gunicorn app:app
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Random Memer
2 |
3 | Flask API to return random programming meme images scrapped from [Memedroid](https://www.memedroid.com/memes/tag/programming).
4 |
5 | ### Usage Notes:
6 |
7 | Just add `img` tag in your website / README file and it will display a random meme everytime the website is loaded
8 |
9 | ```html
10 |
11 | ```
12 |
13 | > **Deprecation Note:** The previous Heroku app link has stopped working due to Heroku [discontinuing its free tier services](https://blog.heroku.com/next-chapter). Deploy your own instance of the app using the links below and use them.
14 |
15 | ## How to deploy
16 |
17 | ## Use [Railway](https://railway.app) (500 hours)
18 |
19 | > **Note**
20 | No delay
21 |
22 | [](https://railway.app/new/template/Hp9Kv4?referralCode=dUt24_)
23 |
24 | * Sign in with GitHub to Deploy
25 |
26 | * URL will produce after finish building
27 |
28 | ---
29 |
30 | ## Use [Replit](https://replit.com/) (unlimited hours)
31 | > **Warning**
32 | response delay of up to 30 seconds for the first request that comes in after a period of inactivity
33 |
34 |
35 |
36 |
37 |
38 |
39 | * Click Import from GitHub Button
40 |
41 | * Run `pip install gunicorn==20.0.4` and `pip install lxml` in console on the right
42 |
43 | * Add line `app.run(host='0.0.0.0', port=80)` at the end of 'app.py' file
44 |
45 | * Click the $\color{white} \colorbox{Green} {RUN}$ button on top, the console will run, wait to finish and output URL on the right under "Webview"
46 |
47 | ---
48 |
49 | ## Use [Render](https://render.com/) (750 hours)
50 | > **Warning**
51 | response delay of up to 30 seconds for the first request that comes in after a period of inactivity
52 |
53 | * Sign in https://dashboard.render.com/select-repo?type=static
54 |
55 | * Enter in **Public Git repository** https://github.com/techytushar/random-memer and click 'continue'
56 |
57 | * Enter a name and add `gunicorn app:app` in **Start Command** option
58 |
59 | * Click 'Create Web Service' and wait until "==> Build successful 🎉" and server is Live
60 |
61 | * Click URL link at top left (https://appname-xxxx.onrender.com)
62 |
63 | ---
64 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | @Author : Tushar Mittal (chiragmittal.mittal@gmail.com)
5 | Flask API to return random meme images
6 | """
7 |
8 | import random
9 | import requests
10 | from bs4 import BeautifulSoup
11 | from flask import Flask, send_file
12 | from PIL import Image
13 | from io import BytesIO
14 |
15 | app = Flask(__name__)
16 |
17 | def get_new_memes():
18 | """Scrapers the website and extracts image URLs
19 |
20 | Returns:
21 | imgs [list]: List of image URLs
22 | """
23 | url = 'https://www.memedroid.com/memes/tag/programming'
24 | response = requests.get(url)
25 | soup = BeautifulSoup(response.content, 'lxml')
26 | divs = soup.find_all('div', class_='item-aux-container')
27 | imgs = []
28 | for div in divs:
29 | img = div.find('img')['src']
30 | if img.startswith('http') and img.endswith('jpeg'):
31 | imgs.append(img)
32 | return imgs
33 |
34 |
35 | def serve_pil_image(pil_img):
36 | """Stores the downloaded image file in-memory
37 | and sends it as response
38 |
39 | Args:
40 | pil_img: Pillow Image object
41 |
42 | Returns:
43 | [response]: Sends image file as response
44 | """
45 | img_io = BytesIO()
46 | pil_img.save(img_io, 'JPEG', quality=70)
47 | img_io.seek(0)
48 | return send_file(img_io, mimetype='image/jpeg')
49 |
50 | @app.after_request
51 | def set_response_headers(response):
52 | """Sets Cache-Control header to no-cache so GitHub
53 | fetches new image everytime
54 | """
55 | response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
56 | response.headers['Pragma'] = 'no-cache'
57 | response.headers['Expires'] = '0'
58 | return response
59 |
60 | @app.route("/", methods=['GET'])
61 | def return_meme():
62 | img_url = random.choice(get_new_memes())
63 | res = requests.get(img_url, stream=True)
64 | res.raw.decode_content = True
65 | img = Image.open(res.raw)
66 | return serve_pil_image(img)
67 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask>=1.1.1
2 | requests>=2.22.0
3 | bs4>=0.0.1
4 | Pillow>=5.4.1
5 | gunicorn>=20.0.4
6 | lxml>=4.5.0
7 |
--------------------------------------------------------------------------------