diff --git a/AutoZoom/api/changelogs/2.6.json b/AutoZoom/api/changelogs/2.6.json new file mode 100644 index 0000000..a5d2625 --- /dev/null +++ b/AutoZoom/api/changelogs/2.6.json @@ -0,0 +1,5 @@ +{ + "en": ["Adjustments have been made to the Discord RPC system", "Created a temporary fix for Python 3.10 and Discord RPC"], + "uk": ["Внесені коректировки в систему роботи Discord RPC", "Зроблений тимчасовий фікс проблем Python 3.10 та Discord RPC"], + "ru": ["Внесены корректировки в систему работы Discord RPC", "Создан временный фикс проблем Python 3.10 и Discord RPC"] +} diff --git a/AutoZoom/api/version.json b/AutoZoom/api/version.json new file mode 100644 index 0000000..d7bcbff --- /dev/null +++ b/AutoZoom/api/version.json @@ -0,0 +1,4 @@ +{ + "dev": 2.7, + "stable": 2.6 +} diff --git a/config.json b/config.json new file mode 100644 index 0000000..abb898b --- /dev/null +++ b/config.json @@ -0,0 +1,15 @@ +{ + "address": "127.0.0.1", + "port": 8080, + "url": "https://api.end-play.xyz", + "data_location": "data/", + "autozoom_location": "AutoZoom/api/", + "telegram_bot_token": "12345678:asdfghjklzxcvbnm", + "messages": { + "key_expired": "API key expired", + "key_invalid": "Invalid API key", + "key_valid": "Valid API key", + "bad_request": "Bad request", + "ip_blacklisted": "Your IP is blacklisted. Make sure you are using correct API address." + } +} diff --git a/daemon.py b/daemon.py new file mode 100644 index 0000000..c36ecd4 --- /dev/null +++ b/daemon.py @@ -0,0 +1,314 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime +from http.server import HTTPServer, BaseHTTPRequestHandler + +import ujson +import os +import random +import shutil +import requests +import string +import traceback + +from urllib.parse import parse_qs, urlsplit + +def jsonLoad(path): + data = open(path, "r", encoding='utf-8') + out = ujson.load(data) + data.close() + return out + +def jsonSave(path, value): + file = open(path, "w", encoding='utf-8') + file.write(ujson.dumps(value, indent=4)) + file.close() + +def apiKeyInvalid(obj): + obj.send_response(401) + obj.send_header('Content-type', 'application/json; charset=utf-8') + obj.end_headers() + obj.wfile.write(b'{"code":401, "message": "Invalid API key"}') + return + +def apiKeyExpired(obj): + obj.send_response(403) + obj.send_header('Content-type', 'application/json; charset=utf-8') + obj.end_headers() + obj.wfile.write(b'{"code":403, "message": "API key expired"}') + return + +def badRequest(obj): + obj.send_response(400) + obj.send_header('Content-type', 'application/json; charset=utf-8') + obj.end_headers() + obj.wfile.write(b'{"code":400, "message": "Bad request"}') + return + +def okRequest(obj): + obj.send_response(200) + obj.send_header('Content-type', 'application/json; charset=utf-8') + obj.end_headers() + obj.wfile.write(b'{"code":200, "message": "ok"}') + return + +def blacklistedRequest(obj): + obj.send_response(403) + obj.send_header('Content-type', 'application/json; charset=utf-8') + obj.end_headers() + obj.wfile.write(b'{"code":403, "message": "Your IP is blacklisted. Make sure you are using correct API address."}') + obj.close_connection + return + +def azGenKey(ipaddr): + + az_requests = jsonLoad(config["data_location"]+"az_requests.json") + today_day = datetime.now().strftime("%d.%m.%Y") + + if ipaddr in az_requests: + + if today_day in az_requests[ipaddr]: + + if az_requests[ipaddr][today_day] > 4: + return False + + else: + az_requests[ipaddr][today_day] = 0 + + else: + az_requests[ipaddr] = {} + az_requests[ipaddr][today_day] = 0 + + api_keys = jsonLoad(config["data_location"]+"api_keys.json") + + key = ''.join(random.sample(string.ascii_letters + string.digits, 20)) + + api_keys["autozoom"].append(key) + az_requests[ipaddr][today_day] += 1 + + jsonSave(config["data_location"]+"api_keys.json", api_keys) + jsonSave(config["data_location"]+"az_requests.json", az_requests) + + return key + +conffile = open("config.json", "r") +config = ujson.load(conffile) +conffile.close() + + +class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): + + def do_GET(self): + + global config + + blacklist = jsonLoad(config["data_location"]+"blacklist.json") + + for addr in blacklist: + if addr == str(self.headers["X-Real-IP"]): + blacklistedRequest(self) + + keys = jsonLoad(config["data_location"]+"api_keys.json") + expired = jsonLoad(config["data_location"]+"expired_keys.json") + + try: + fullpath = config["url"]+self.path + reqpath = urlsplit(fullpath).path + requery = parse_qs(urlsplit(fullpath).query) + + if reqpath == "/favicon.ico": + + with open("favicon.ico", 'rb') as f: + self.send_response(200) + self.send_header( + "Content-Type", 'application/octet-stream') + self.send_header( + "Content-Disposition", 'attachment; filename="{}"'.format(os.path.basename("favicon.ico"))) + fs = os.fstat(f.fileno()) + self.send_header("Content-Length", str(fs.st_size)) + self.end_headers() + shutil.copyfileobj(f, self.wfile) + f.close() + + elif (reqpath == "/azVersion"): + + if requery["apikey"][0] == "publickey": + + file = open(config["autozoom_location"]+"version.json", "r") + versions = ujson.load(file) + file.close() + + output = versions["stable"] + + if "branch" in reqpath: + if requery["branch"][0] == "dev": + output = versions["dev"] + + self.send_response(200) + self.send_header('Content-type', 'application/json; charset=utf-8') + self.end_headers() + self.wfile.write(bytes(ujson.dumps({"version": output}), encoding='utf-8')) + + elif requery["apikey"][0] in expired: + apiKeyExpired(self) + + else: + apiKeyInvalid(self) + + elif (reqpath == "/azChangelog"): + + if requery["apikey"][0] == "publickey": + + file = open(f'{config["autozoom_location"]}changelogs/{requery["version"][0]}.json', "r") + output = ujson.load(file)[requery["locale"][0]] + file.close() + + self.send_response(200) + self.send_header('Content-type', 'application/json; charset=utf-8') + self.end_headers() + self.wfile.write(bytes(ujson.dumps({"changelog": output}, ensure_ascii=False), encoding='utf-8')) + + elif requery["apikey"][0] in expired: + apiKeyExpired(self) + + else: + apiKeyInvalid(self) + + elif (reqpath == "/azRequestKey"): + + if requery["apikey"][0] == "publickey": + + generated_key = azGenKey(str(self.headers["X-Real-IP"])) + + if not generated_key: + + self.send_response(403) + self.send_header('Content-type', 'application/json; charset=utf-8') + self.end_headers() + self.wfile.write(b'{"code":403, "message": "Too many new key requests for today. Try again later."}') + + else: + + self.send_response(200) + self.send_header('Content-type', 'application/json; charset=utf-8') + self.end_headers() + self.wfile.write(bytes('{"code":200, "message": "ok", "apikey": "' + generated_key + '"}', encoding='utf-8')) + + elif requery["apikey"][0] in expired: + apiKeyExpired(self) + + else: + apiKeyInvalid(self) + + elif (reqpath == "/update"): + + if requery["app"][0] == "autozoom": + + if requery["apikey"][0] == "publickey": + + filepath = config["autozoom_location"]+"AutoZoomLatest.zip" + + with open(filepath, 'rb') as f: + self.send_response(200) + self.send_header("Content-Type", 'application/octet-stream') + self.send_header("Content-Disposition", 'attachment; filename="{}"'.format(os.path.basename(filepath))) + fs = os.fstat(f.fileno()) + self.send_header("Content-Length", str(fs.st_size)) + self.end_headers() + shutil.copyfileobj(f, self.wfile) + f.close() + + else: + apiKeyInvalid(self) + + else: + badRequest(self) + + else: + badRequest(self) + + except Exception as exp: + badRequest(self) + traceback.print_exc() + + def do_POST(self): + + global config + + blacklist = jsonLoad(config["data_location"]+"blacklist.json") + + for addr in blacklist: + if addr == str(self.headers["X-Real-IP"]): + blacklistedRequest(self) + + content_length = int(self.headers['Content-Length']) + body = self.rfile.read(content_length).decode("utf-8") + + keys = jsonLoad(config["data_location"]+"api_keys.json") + expired = jsonLoad(config["data_location"]+"expired_keys.json") + + try: + fullpath = config["url"]+self.path + reqpath = urlsplit(fullpath).path + requery = parse_qs(urlsplit(fullpath).query) + data = body + + if (reqpath == "/azSendMessage"): + + if requery["apikey"][0] in keys["autozoom"]: + + keys_storage = jsonLoad(config["data_location"]+"keys_storage.json") + + if requery["apikey"][0] in keys_storage: + + try: + if "message" in reqpath: + try: + output = requests.post( + url=f'https://api.telegram.org/bot{config["telegram_bot_token"]}/sendMessage?chat_id={keys_storage[requery["apikey"][0]]}&text={requery["message"][0]}' + ) + except: + output = requests.post( + url=f'https://api.telegram.org/bot{config["telegram_bot_token"]}/sendMessage', + data={'chat_id': keys_storage[requery["apikey"][0]], 'text': ujson.loads(data)["message"]} + ) + else: + output = requests.post( + url=f'https://api.telegram.org/bot{config["telegram_bot_token"]}/sendMessage', + data={'chat_id': keys_storage[requery["apikey"][0]], 'text': ujson.loads(data)["message"]} + ) + if output.status_code == requests.codes.ok: + okRequest(self) + else: + badRequest(self) + except: + traceback.print_exc() + badRequest(self) + + else: + + self.send_response(400) + self.send_header('Content-type', 'application/json; charset=utf-8') + self.end_headers() + self.wfile.write(b'{"code":400, "message": "Bad request. This key might not be linked to Telegram user."}') + + elif requery["apikey"][0] in expired: + apiKeyExpired(self) + + else: + apiKeyInvalid(self) + + else: + badRequest(self) + + except Exception as exp: + badRequest(self) + traceback.print_exc() + + +httpd = HTTPServer((config["address"], config["port"]), SimpleHTTPRequestHandler) + +try: + httpd.serve_forever() +except KeyboardInterrupt: + pass diff --git a/data/api_keys.json b/data/api_keys.json new file mode 100644 index 0000000..bcad3a3 --- /dev/null +++ b/data/api_keys.json @@ -0,0 +1,3 @@ +{ + "autozoom": [] +} \ No newline at end of file diff --git a/data/az_requests.json b/data/az_requests.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/data/az_requests.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/data/blacklist.json b/data/blacklist.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/data/blacklist.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/data/expired_keys.json b/data/expired_keys.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/data/expired_keys.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..5e5385d Binary files /dev/null and b/favicon.ico differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2c139cc --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +ujson +requests +shutil +urllib \ No newline at end of file