315 lines
11 KiB
Python
315 lines
11 KiB
Python
|
# -*- 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
|