mirror of
https://github.com/tgbot-collection/YYeTsBot.git
synced 2025-11-25 03:15:05 +08:00
121 lines
3.2 KiB
Python
121 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
# coding: utf-8
|
|
import contextlib
|
|
import importlib
|
|
import json
|
|
import logging
|
|
import pathlib
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
from http import HTTPStatus
|
|
from pathlib import Path
|
|
|
|
from tornado import gen, web
|
|
from tornado.concurrent import run_on_executor
|
|
|
|
from databases.base import Redis
|
|
from handlers import cf
|
|
|
|
index = (
|
|
pathlib.Path(__file__).parent.parent.joinpath("templates", "index.html").as_posix()
|
|
)
|
|
filename = Path(__file__).name.split(".")[0]
|
|
|
|
|
|
class BaseHandler(web.RequestHandler):
|
|
key = "user_blacklist"
|
|
filename = filename
|
|
|
|
executor = ThreadPoolExecutor(200)
|
|
|
|
def __init__(self, application, request, **kwargs):
|
|
super().__init__(application, request, **kwargs)
|
|
self.json = {}
|
|
with contextlib.suppress(ValueError):
|
|
self.json: dict = json.loads(self.request.body)
|
|
class_name = self.__class__.__name__.split("Handler")[0]
|
|
module = importlib.import_module(f"databases.{self.filename}")
|
|
|
|
self.instance = getattr(module, class_name)()
|
|
self.r = Redis().r
|
|
|
|
def prepare(self):
|
|
if self.check_request():
|
|
self.set_status(HTTPStatus.FORBIDDEN)
|
|
self.finish()
|
|
|
|
def data_received(self, chunk):
|
|
pass
|
|
|
|
def check_request(self):
|
|
ban = self.__ip_check()
|
|
user = self.__user_check()
|
|
result = ban or user
|
|
if result:
|
|
self.ban()
|
|
return result
|
|
|
|
def get_real_ip(self):
|
|
x_real = self.request.headers.get("X-Real-IP")
|
|
remote_ip = self.request.remote_ip
|
|
logging.debug("X-Real-IP:%s, Remote-IP:%s", x_real, remote_ip)
|
|
return x_real or remote_ip
|
|
|
|
def ban(self):
|
|
ip = self.get_real_ip()
|
|
self.r.incr(ip)
|
|
count = int(self.r.get(ip))
|
|
# ban rule: (count-10)*600
|
|
if count <= 10:
|
|
ex = 120
|
|
else:
|
|
ex = (count - 10) * 600
|
|
if count >= 30:
|
|
cf.ban_new_ip(ip)
|
|
self.r.set(ip, count, ex)
|
|
user = self.get_current_user()
|
|
if user:
|
|
self.r.hincrby(self.key, user)
|
|
|
|
def get_current_user(self) -> str:
|
|
username = self.get_secure_cookie("username") or b""
|
|
return username.decode("u8")
|
|
|
|
def __user_check(self):
|
|
count = self.r.hget(self.key, self.get_current_user()) or 0
|
|
count = int(count)
|
|
if count >= 20:
|
|
return True
|
|
|
|
def __ip_check(self):
|
|
d = self.r.get(self.get_real_ip()) or 0
|
|
if int(d) >= 10:
|
|
return True
|
|
|
|
def write_error(self, status_code, **kwargs):
|
|
if status_code in [
|
|
HTTPStatus.FORBIDDEN,
|
|
HTTPStatus.UNAUTHORIZED,
|
|
HTTPStatus.NOT_FOUND,
|
|
HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
]:
|
|
self.write(str(kwargs.get("exc_info")))
|
|
|
|
|
|
class IndexHandler(BaseHandler):
|
|
@run_on_executor()
|
|
def send_index(self):
|
|
with open(index, encoding="u8") as f:
|
|
html = f.read()
|
|
return html
|
|
|
|
@gen.coroutine
|
|
def get(self):
|
|
resp = yield self.send_index()
|
|
self.write(resp)
|
|
|
|
|
|
class NotFoundHandler(BaseHandler):
|
|
def get(self):
|
|
# for react app
|
|
self.render(index)
|