├── data ├── images.json └── config.json ├── readme.md ├── app.py ├── routes ├── index.py └── api.py ├── utils ├── discord.py └── images.py ├── licence └── templates ├── register.html ├── viewer.html └── index.html /data/images.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /data/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "uploadKey": "epic-upload-key" 4 | }, 5 | "discord": { 6 | "botToken": "", 7 | "channelId": "" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Discord Image Host 2 | An image uploader that uses Discord to host the images. 3 | ⚠️ Use this at your own risk, hosting files using Discord's CDN may be against the TOS. 4 | 5 | ### How to setup 6 | > 1. Clone this repo. 7 | > 2. Open `data/config.json` and enter all the required details. 8 | > 3. Once thats all done run `app.py` 9 | > *If you need any help, please check the wiki.* 10 | 11 | ### Need help? 12 | > Please dont create an issue or email me for support! 13 | > If you require support please go to the wiki first. -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | # Made by @bentettmar 2 | 3 | import flask 4 | import os 5 | import importlib 6 | 7 | app = flask.Flask(__name__, template_folder='templates') 8 | extra_files = ["data/images.json"] 9 | 10 | for route_file in os.listdir("routes"): 11 | if route_file.endswith(".py"): 12 | lib = importlib.import_module("routes.{}".format(route_file[:-3])) 13 | app.register_blueprint(lib.blueprint) 14 | 15 | if __name__ == "__main__": 16 | for _ in range(10): 17 | print("Made by @bentettmar") 18 | app.run(debug=True, extra_files=extra_files, host="0.0.0.0") -------------------------------------------------------------------------------- /routes/index.py: -------------------------------------------------------------------------------- 1 | # Made by @bentettmar 2 | 3 | import flask 4 | 5 | from utils import images 6 | 7 | blueprint = flask.Blueprint("index", __name__, url_prefix="/") 8 | db = images.Images() 9 | 10 | @blueprint.route("/") 11 | def index(): 12 | return flask.render_template("index.html") 13 | 14 | @blueprint.get("/") 15 | def get(shorturl): 16 | img = db.get_img(shorturl) 17 | 18 | if img: 19 | return flask.render_template( 20 | "viewer.html", 21 | image_filename=img["filename"], 22 | embed_title=img["embed"]["title"], 23 | embed_author=img["embed"]["author"], 24 | embed_description=img["embed"]["description"], 25 | embed_colour=img["embed"]["colour"], 26 | embed_image=img["url"] 27 | ) 28 | 29 | return flask.jsonify({ 30 | "error": "Image not found" 31 | }) 32 | 33 | @blueprint.get("/register") 34 | def register(): 35 | return flask.redirect("https://benny.fun/") -------------------------------------------------------------------------------- /utils/discord.py: -------------------------------------------------------------------------------- 1 | # Made by @bentettmar 2 | 3 | import json 4 | import requests 5 | 6 | BOT_JSON = json.load(open("data/config.json"))["discord"] 7 | API_URL = "https://discordapp.com/api/v9" 8 | 9 | def upload_file(file_path): 10 | url = f"{API_URL}/channels/{BOT_JSON['channelId']}/messages" 11 | file_name = file_path.split("/")[-1] 12 | 13 | payload={'payload_json': json.dumps({ 14 | "content": "", 15 | "channel_id": BOT_JSON['channelId'], 16 | "type": 0, 17 | "sticker_ids": [], 18 | "attachments": [ 19 | {"id": "0", "filename": file_name} 20 | ] 21 | }) 22 | } 23 | 24 | files=[('files[0]', (file_name, open(file_path,'rb'),'image/png'))] 25 | headers = {'Authorization': f'Bot {BOT_JSON["botToken"]}'} 26 | response = requests.request("POST", url, headers=headers, data=payload, files=files) 27 | response_json = response.json() 28 | attachments = response_json["attachments"] 29 | 30 | return attachments[0]["url"] -------------------------------------------------------------------------------- /utils/images.py: -------------------------------------------------------------------------------- 1 | # Made by @bentettmar 2 | 3 | import json 4 | import random 5 | import string 6 | 7 | class Images: 8 | def __init__(self): 9 | self.json = json.load(open("data/images.json")) 10 | 11 | def add_img(self, url: str, embed: dict): 12 | short_url = self.generate_short_url() 13 | filename = url.split("/")[-1] 14 | 15 | self.json[short_url] = { 16 | "url": url, 17 | "filename": filename, 18 | "embed": embed 19 | } 20 | self.save() 21 | 22 | return short_url 23 | 24 | def get_img(self, short_url: str): 25 | return self.json.get(short_url) 26 | 27 | def generate_short_url(self): 28 | short_url = "".join(random.choice(string.ascii_lowercase) for i in range(8)) 29 | 30 | while short_url in self.json: 31 | short_url = "".join(random.choice(string.ascii_lowercase) for i in range(8)) 32 | 33 | return short_url 34 | 35 | def save(self): 36 | with open("data/images.json", "w") as f: 37 | json.dump(self.json, f, indent=4) -------------------------------------------------------------------------------- /licence: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ben Tettmar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /templates/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | discord img host made by @bentettmar - register 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /routes/api.py: -------------------------------------------------------------------------------- 1 | # Made by @bentettmar 2 | 3 | import os 4 | import json 5 | import flask 6 | 7 | from utils import images 8 | from utils import discord 9 | 10 | blueprint = flask.Blueprint("api", __name__, url_prefix="/api") 11 | db = images.Images() 12 | config = json.load(open("data/config.json")) 13 | 14 | @blueprint.post("/upload") 15 | def upload(): 16 | upload_key = config["auth"]["uploadKey"] 17 | 18 | if not upload_key: return flask.jsonify({"error": "Upload key not set"}) 19 | if flask.request.headers.get("upload-key") != upload_key or not flask.request.headers.get("upload-key"): return flask.jsonify({"error": "Invalid upload key"}) 20 | if not flask.request.files: return flask.jsonify({"error": "No file provided"}) 21 | 22 | file = flask.request.files["file"] 23 | 24 | if file: 25 | filename = file.filename 26 | args = flask.request.form.to_dict() 27 | embed = { 28 | "title": args.get("embed-title", f"filename"), 29 | "author": args.get("embed-author", ""), 30 | "description": args.get("embed-description", ""), 31 | "colour": args.get("embed-colour", "000000") 32 | } 33 | 34 | file.save("data/cache/{}".format(filename)) 35 | url = discord.upload_file("data/cache/{}".format(filename)) 36 | os.remove("data/cache/{}".format(filename)) 37 | 38 | short_url = db.add_img(url, embed) 39 | 40 | # get flask request domain 41 | domain = flask.request.headers.get("Host") 42 | protocol = "https" if flask.request.headers.get("X-Forwarded-Proto") == "https" else "http" 43 | short_url = f"{protocol}://{domain}/{short_url}" 44 | 45 | return short_url 46 | -------------------------------------------------------------------------------- /templates/viewer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ image_filename }} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 40 | 41 | 42 |
43 |
44 |
45 |
{{ image_filename }}
46 |
47 |
48 | 49 |
50 |
51 |

made by @bentettmar

52 |
53 | 54 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | discord img host made by @bentettmar 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 41 | 42 | 43 |
44 |
45 |
46 |
discord img host made by @bentettmar
47 |
48 |
49 | 50 | get access 51 |
52 |
53 |
54 | 55 | --------------------------------------------------------------------------------