
├── README.md ├── client ├── example_1.jpg ├── example_1.json └── python.py ├── server ├── _config.py ├── database.db ├── database.py ├── pages │ ├── 404.html │ └── embed.html ├── utils.py └── web.py └── technicals.html /README.md: -------------------------------------------------------------------------------- 1 | ## Discord Embed API 2 | API that allows users to create urls that have a custom embed displayed on social media's (like Discord). 3 | 4 | Feel free to host, use, steal, change, or take inspiration from this code. 5 | Technical details about how to display embeds with html is in `technicals.html`. 6 | 7 | ### Example 8 | The payload you'd send to the API for this embed is in the client folder. 9 | 10 |  11 | 12 | ### Deployment 13 | This server is not the most efficient or cleanest setup, but it will work out of the box. 14 | 15 | You will need to host the API on a server, with a domain pointing to it. 16 | 17 | The default port is 8080, but this can be changed at the bottom of `web.py`. 18 | 19 | In `_config.py`, change `url` and `url2` with the appropriate domain you are hosting on. 20 | You can also change the rate limits if you want to. 21 | 22 | By default, the server will run as a development server. You can use waitress, or another deployment server to host efficiently. -------------------------------------------------------------------------------- /client/example_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Discord-Embed-API/9c4e8901ebe30da4aa7608b886b57666f67b75a3/client/example_1.jpg -------------------------------------------------------------------------------- /client/example_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Want to advertise YOUR SHOP?", 3 | "description": "💜 - Mass DM on Discord to MILLIONS of users!\n💸 - Tokens starting from $0.02!\n🤩 - Get MORE SALES + MORE PROFIT on your shop!\n\nGet Started Today!", 4 | "redirect": "https://discord.gg/invite", 5 | "color": "#7289da", 6 | "provider": { 7 | "name": "Click here to view our sellix!", 8 | "url": "https://shop.sellix.io/" 9 | }, 10 | "image": { 11 | "thumbnail": false, 12 | "url": "https://i.imgur.com/7v2sRvV.jpg" 13 | } 14 | } -------------------------------------------------------------------------------- /client/python.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | embed_data = { 4 | "title": "Want to advertise YOUR SHOP?", 5 | "description": "💜 - Mass DM on Discord to MILLIONS of users!\n💸 - Tokens starting from $0.02!\n🤩 - Get MORE SALES + MORE PROFIT on your shop!\n\nGet Started Today!", 6 | "redirect": "https://discord.gg/invite", 7 | "color": "#7289da", 8 | "provider": { 9 | "name": "Click here to view our sellix!", 10 | "url": "https://shop.sellix.io/" 11 | }, 12 | "image": { 13 | "thumbnail": False, 14 | "url": "https://i.imgur.com/7v2sRvV.jpg" 15 | } 16 | } 17 | 18 | response = requests.post(f"http://localhost:8080/api/v1/embed", json=embed_data) 19 | 20 | if response.status_code == 200: 21 | print("Embed already existed") 22 | print(response.json()['link']) 23 | 24 | elif response.status_code == 201: 25 | print("Created Embed") 26 | print(response.json()['link']) 27 | 28 | elif response.status_code == 403: 29 | print("You've been blacklisted") 30 | print(response.json()['error']) 31 | print(response.json()['message']) 32 | print(response.json()['reason']) 33 | print("Doesn't Expire" if response.json()['expires'] is False else f"Does Expire: {response.json()['expires']}") 34 | 35 | else: 36 | print(f"Error Code: {response.status_code}") 37 | print(response.json()['error']) 38 | print(response.json()['message']) 39 | -------------------------------------------------------------------------------- /server/_config.py: -------------------------------------------------------------------------------- 1 | # x embed creation allowed every y seconds 2 | post_rate_limit_per_min = 5 3 | post_rate_limit_per_hour = 20 4 | 5 | # x embed GETs allowed every y seconds 6 | get_rate_limit_per_min = 10 7 | get_rate_limit_per_hour = 250 8 | 9 | db_name = "database.db" 10 | 11 | id_length = 7 12 | 13 | url = "https://e.chasa.wtf/e/" # embed url here 14 | url2 = "https://e.chasa.wtf/o/" # o data url here -------------------------------------------------------------------------------- /server/database.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itschasa/Discord-Embed-API/9c4e8901ebe30da4aa7608b886b57666f67b75a3/server/database.db -------------------------------------------------------------------------------- /server/database.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | class DataBase(): 4 | "Used to access a SQLite3 database, using the filename provided." 5 | 6 | def __init__(self, name): 7 | self.conn = sqlite3.connect(name) 8 | self.cursor = self.conn.cursor() 9 | 10 | def insert(self, table : str, values : list) -> None: 11 | """Insert data into a table. 12 | 13 | ---------- 14 | table: :class:`str` 15 | Name of table to insert in. 16 | values: :class:`list` 17 | List of values to be added to the table, in order of columns. 18 | 19 | ---------- 20 | `DataBase.insert("tablename", ["value1", "value2"])` 21 | """ 22 | 23 | data = "" 24 | for _ in range(len(values)): data += "?," 25 | data = data[:-1] 26 | 27 | newvalues = [] 28 | for item in values: 29 | newvalues.append(str(item)) 30 | 31 | self.cursor.execute(f"INSERT INTO {table} VALUES ({data})", newvalues) 32 | self.conn.commit() 33 | 34 | def query(self, table : str, columns : list, where : dict={}, fetchOne : bool=True, orOrAnd="AND"): 35 | """Querys the database. Returns `tuple`, `list`, `[]` or `None`. 36 | 37 | ---------- 38 | table: :class:`str` 39 | Name of table to query in. 40 | columns: :class:`list` 41 | List of column names to gather data from. 42 | where: :class:`dict = {}` 43 | List of columm names used to filter data. 44 | fetchOne: :class:`bool = True` 45 | Fetch the first value which matched the arguements. 46 | Or to fetch all data from the table that matches. 47 | orOrAnd: :class:`str` 48 | Whether to use the "AND" or "OR" statement when using "WHERE". 49 | 50 | ---------- 51 | `DataBase.query("tablename", ["column1", "column2"], {"column1": "value1"}, False)` 52 | 53 | "column1"'s value has to equal "value1"'s value to be valid and to not be filtered out. 54 | """ 55 | 56 | if len(columns) == 0: 57 | raise TypeError("columns can't be empty (len(columns) != 0)") 58 | 59 | columnsdata = "" 60 | for column in columns: 61 | columnsdata += f"{column}, " 62 | columnsdata = columnsdata[:-2] 63 | 64 | values = [] 65 | if len(where) != 0: 66 | wheredata = " WHERE " 67 | for key, value in where.items(): 68 | wheredata += f"{key} = ? {orOrAnd} " 69 | values.append(str(value)) 70 | if orOrAnd == "AND": wheredata = wheredata[:-5] 71 | else: wheredata = wheredata[:-4] 72 | else: wheredata = "" 73 | 74 | cur = self.conn.execute(f"SELECT rowid, {columnsdata} FROM {table}{wheredata}", values) 75 | if fetchOne == True: 76 | res = cur.fetchone() 77 | else: 78 | res = cur.fetchall() 79 | cur.close() 80 | 81 | return res 82 | 83 | def edit(self, table : str, newvalues : dict, where : dict, orOrAnd="AND") -> None: 84 | """Edits an entry in the database. 85 | 86 | ---------- 87 | table: :class:`str` 88 | Name of table to edit in. 89 | newvalues: :class:`dict` 90 | Dict of the new data to be edited. 91 | where: :class:`dict` 92 | Dict of the columns and values to be used. 93 | orOrAnd: :class:`str` 94 | Whether to use the "AND" or "OR" statement when using "WHERE". 95 | 96 | ---------- 97 | `DataBase.edit("tablename", {"column1": "newvalue1"}, {"column2": "value2"})` 98 | 99 | "column2"'s value has to equal "value2"'s value to be valid and to not be filtered out. 100 | """ 101 | 102 | values = [] 103 | 104 | setData = "" 105 | for key, value in newvalues.items(): 106 | setData += f"{key} = ?, " 107 | values.append(str(value)) 108 | setData = setData[:-2] 109 | 110 | wheredata = "" 111 | for key, value in where.items(): 112 | wheredata += f"{key} = ? {orOrAnd} " 113 | values.append(str(value)) 114 | if orOrAnd == "AND": wheredata = wheredata[:-5] 115 | else: wheredata = wheredata[:-4] 116 | 117 | self.conn.execute(f"UPDATE {table} SET {setData} WHERE {wheredata}", values) 118 | self.conn.commit() 119 | 120 | def delete(self, table : str, where : dict, orOrAnd="AND", whereOverRide=None, valuesOverRide=None) -> None: 121 | """Deletes an entry in the database. 122 | 123 | ---------- 124 | table: :class:`str` 125 | Name of table to edit in. 126 | where: :class:`dict` 127 | Dict of the columns and values to be used. 128 | 129 | 130 | ---------- 131 | `DataBase.delete("tablename", {"column2": "value2"})` 132 | 133 | "column2"'s value has to equal "value2"'s value to be valid and to not be filtered out. 134 | """ 135 | 136 | values = [] 137 | 138 | if whereOverRide == None: 139 | wheredata = "" 140 | for key, value in where.items(): 141 | wheredata += f"{key} = ? {orOrAnd} " 142 | values.append(str(value)) 143 | if orOrAnd == "AND": wheredata = wheredata[:-5] 144 | else: wheredata = wheredata[:-4] 145 | 146 | self.cursor.execute(f"DELETE FROM {table} WHERE {wheredata}", values) 147 | self.conn.commit() 148 | else: 149 | self.cursor.execute(f"DELETE FROM {table} WHERE {whereOverRide}", valuesOverRide) 150 | self.conn.commit() 151 | 152 | def close(self) -> None: 153 | """Closes the database connection. 154 | 155 | ---------- 156 | `DataBase.close()` 157 | """ 158 | 159 | self.cursor.close() 160 | self.conn.close() -------------------------------------------------------------------------------- /server/pages/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |