├── 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 | Please refresh the page if the meme doesn't show up. 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 | [![Deploy on Railway](https://railway.app/button.svg)](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 | Run on Repl.it 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 | --------------------------------------------------------------------------------