# -*- 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