Init
This commit is contained in:
commit
2baff4118e
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
venv/
|
||||||
|
*.txt
|
||||||
|
!requirements.txt
|
||||||
|
*.ini
|
||||||
|
!example_config.ini
|
||||||
|
test.py
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# clash-telegram-bot
|
||||||
|
|
||||||
|
Бот для верификации юзеров. Проверка состояния в клане clash of clans по средствам clash of clans API
|
43
bot.py
Normal file
43
bot.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
from aiogram import executor
|
||||||
|
|
||||||
|
from load import dp, config
|
||||||
|
import filters
|
||||||
|
import handlers
|
||||||
|
|
||||||
|
skip_updates=True
|
||||||
|
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||||
|
level=logging.INFO
|
||||||
|
)
|
||||||
|
|
||||||
|
async def on_startup(dp):
|
||||||
|
webhook_url = "{host}{path}{token}".format(
|
||||||
|
host=config["WebHook"]["webhook_host"],
|
||||||
|
path=config["WebHook"]["webhook_path"],
|
||||||
|
token=config["Bot"]["token"]
|
||||||
|
)
|
||||||
|
await dp.bot.set_webhook(url=webhook_url)
|
||||||
|
|
||||||
|
|
||||||
|
async def on_shutdown(dp):
|
||||||
|
await dp.bot.delete_webhook()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
if config["WebHook"]["use"].lower() in ["yes", "true"]:
|
||||||
|
executor.start_webhook(
|
||||||
|
dispatcher=dp,
|
||||||
|
skip_updates=skip_updates,
|
||||||
|
webhook_path="{}{}".format(config["WebHook"]["webhook_path"], config["Bot"]["token"]),
|
||||||
|
on_startup=on_startup,
|
||||||
|
on_shutdown=on_shutdown,
|
||||||
|
host=config["WebHook"]["app_host"],
|
||||||
|
port=config["WebHook"]["app_port"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
executor.start_polling(dp, skip_updates=skip_updates)
|
6
coc/__init__.py
Normal file
6
coc/__init__.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import imp
|
||||||
|
from .user import Player
|
||||||
|
from .clan import Clan
|
||||||
|
|
||||||
|
class ClashOfClans(Player, Clan):
|
||||||
|
pass
|
26
coc/base.py
Normal file
26
coc/base.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import json
|
||||||
|
import requests
|
||||||
|
from abc import ABC
|
||||||
|
|
||||||
|
class Base(ABC):
|
||||||
|
def __init__(self, api_token:str, clan_tag:str = None) -> None:
|
||||||
|
self.headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": "Bearer {api_token}".format(api_token=api_token)
|
||||||
|
}
|
||||||
|
self.clan_tag = clan_tag
|
||||||
|
|
||||||
|
def get(self, url: str, tag: str):
|
||||||
|
request = requests.get(
|
||||||
|
url.format(tag.replace("#", "")),
|
||||||
|
headers=self.headers
|
||||||
|
)
|
||||||
|
return json.loads(request.text)
|
||||||
|
|
||||||
|
def post(self, url: str, tag: str, payload: dict):
|
||||||
|
request = requests.post(
|
||||||
|
url=url.format(tag.replace("#", "")),
|
||||||
|
headers=self.headers,
|
||||||
|
data=json.dumps(payload)
|
||||||
|
)
|
||||||
|
return json.loads(request.text)
|
17
coc/clan.py
Normal file
17
coc/clan.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from .base import Base
|
||||||
|
|
||||||
|
class Clan(Base):
|
||||||
|
|
||||||
|
def clan_members(self, clan_tag:str = None):
|
||||||
|
if self.clan_tag is not None:
|
||||||
|
clan_tag = self.clan_tag
|
||||||
|
|
||||||
|
url = "https://api.clashofclans.com/v1/clans/%23{}/members"
|
||||||
|
return self.get(url, tag=clan_tag)
|
||||||
|
|
||||||
|
def get_clan(self, clan_tag:str = None):
|
||||||
|
if self.clan_tag is not None:
|
||||||
|
clan_tag = self.clan_tag
|
||||||
|
|
||||||
|
url = "https://api.clashofclans.com/v1/clans/%23{}"
|
||||||
|
return self.get(url, tag=clan_tag)
|
12
coc/user.py
Normal file
12
coc/user.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from .base import Base
|
||||||
|
|
||||||
|
class Player(Base):
|
||||||
|
|
||||||
|
def get_player(self, tag: str):
|
||||||
|
url = "https://api.clashofclans.com/v1/players/%23{}"
|
||||||
|
return self.get(url, tag)
|
||||||
|
|
||||||
|
def verify_token(self, tag: str, token: str):
|
||||||
|
payload = {"token":token}
|
||||||
|
url = "https://api.clashofclans.com/v1/players/%23{}/verifytoken"
|
||||||
|
return self.post(url, tag, payload)
|
16
config.py
Normal file
16
config.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
from configparser import ConfigParser
|
||||||
|
|
||||||
|
CONFIG_FILE ='./config.ini'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data = ConfigParser()
|
||||||
|
data.read(CONFIG_FILE)
|
||||||
|
|
||||||
|
config = dict()
|
||||||
|
|
||||||
|
for section in data.sections():
|
||||||
|
config[section] = dict()
|
||||||
|
|
||||||
|
for key, value in data.items(section):
|
||||||
|
config[section][key] = value
|
BIN
database.sqlite3
Normal file
BIN
database.sqlite3
Normal file
Binary file not shown.
18
database/model.py
Normal file
18
database/model.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from peewee import Model, BigIntegerField, CharField
|
||||||
|
|
||||||
|
from load import db
|
||||||
|
|
||||||
|
|
||||||
|
class Users(Model):
|
||||||
|
user_id = BigIntegerField(null=False)
|
||||||
|
first_name = CharField(64)
|
||||||
|
last_name = CharField(64, null=True)
|
||||||
|
username = CharField(32, null=True)
|
||||||
|
|
||||||
|
tag = CharField()
|
||||||
|
nickname = CharField()
|
||||||
|
townhall = BigIntegerField()
|
||||||
|
attackwins = BigIntegerField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
database = db
|
57
database/worker.py
Normal file
57
database/worker.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
from aiogram import types
|
||||||
|
|
||||||
|
from .model import db, Users
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
db.create_tables([Users])
|
||||||
|
|
||||||
|
|
||||||
|
def register(user: types.User, data: dict):
|
||||||
|
if not Users.select().where(Users.user_id==user.id, Users.tag == data['tag']).exists():
|
||||||
|
Users.create(
|
||||||
|
user_id = user.id,
|
||||||
|
first_name = user.first_name,
|
||||||
|
last_name = user.last_name,
|
||||||
|
username = user.username,
|
||||||
|
|
||||||
|
tag = data['tag'],
|
||||||
|
nickname = data['name'],
|
||||||
|
townhall = data['townHallLevel'],
|
||||||
|
attackwins = data['attackWins']
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
Users.update(
|
||||||
|
user_id = user.id,
|
||||||
|
first_name = user.first_name,
|
||||||
|
last_name = user.last_name,
|
||||||
|
username = user.username,
|
||||||
|
|
||||||
|
tag = data['tag'],
|
||||||
|
nickname = data['name'],
|
||||||
|
townhall = data['townHallLevel'],
|
||||||
|
attackwins = data['attackWins']
|
||||||
|
).where(Users.user_id == user.id, Users.tag == data['tag']).execute()
|
||||||
|
|
||||||
|
def delete(user_id: int):
|
||||||
|
Users.delete().where(Users.user_id == user_id).execute()
|
||||||
|
|
||||||
|
def check_register(user_id: int):
|
||||||
|
return Users.select().where(Users.user_id==user_id).exists()
|
||||||
|
|
||||||
|
def get_users():
|
||||||
|
users = []
|
||||||
|
for p in Users.select():
|
||||||
|
users.append(
|
||||||
|
{
|
||||||
|
'user_id': p.user_id,
|
||||||
|
'first_name': p.first_name,
|
||||||
|
'last_name': p.last_name,
|
||||||
|
'username': p.username,
|
||||||
|
'tag': p.tag,
|
||||||
|
'nickname': p.nickname,
|
||||||
|
'townhall': p.townhall,
|
||||||
|
'attackwins': p.attackwins
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return users
|
26
example_config.ini
Normal file
26
example_config.ini
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
[Bot]
|
||||||
|
token = 123456789:ABCDEABCDEABCD
|
||||||
|
;; Token from @botfather
|
||||||
|
base_server = https://api.telegram.org
|
||||||
|
chat_id = -1001740735953
|
||||||
|
verify_timeout = 120
|
||||||
|
|
||||||
|
|
||||||
|
[WebHook]
|
||||||
|
use = false
|
||||||
|
webhook_host = http://127.0.0.1:3001
|
||||||
|
webhook_path = /bot
|
||||||
|
|
||||||
|
app_host = 127.0.0.1
|
||||||
|
app_port = 3001
|
||||||
|
|
||||||
|
|
||||||
|
[DataBase]
|
||||||
|
link = sqlite:///database.sqlite3
|
||||||
|
;; http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#database-url
|
||||||
|
|
||||||
|
[API]
|
||||||
|
api_file = key.txt
|
||||||
|
;; file with clash of clans API Token
|
||||||
|
;; https://developer.clashofclans.com
|
||||||
|
clan_tag = #QWERTY1
|
5
filters/__init__.py
Normal file
5
filters/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from load import dp
|
||||||
|
|
||||||
|
from .main import ChatFilter
|
||||||
|
|
||||||
|
dp.filters_factory.bind(ChatFilter)
|
15
filters/main.py
Normal file
15
filters/main.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from aiogram.dispatcher.filters import BoundFilter
|
||||||
|
from aiogram import types
|
||||||
|
|
||||||
|
from load import config
|
||||||
|
|
||||||
|
|
||||||
|
class ChatFilter(BoundFilter):
|
||||||
|
key = 'is_chat'
|
||||||
|
|
||||||
|
def __init__(self, is_chat):
|
||||||
|
self.is_chat = is_chat
|
||||||
|
|
||||||
|
async def check(self, message: types.Message):
|
||||||
|
if message.chat.id == int(config["Bot"]["chat_id"]): return True
|
||||||
|
return False
|
5
fsm/base.py
Normal file
5
fsm/base.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||||
|
|
||||||
|
class Verifycation(StatesGroup):
|
||||||
|
tag = State()
|
||||||
|
token = State()
|
2
handlers/__init__.py
Normal file
2
handlers/__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
from . import group
|
||||||
|
from . import private
|
3
handlers/group/__init__.py
Normal file
3
handlers/group/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from . import main
|
||||||
|
from . import users
|
||||||
|
from . import captcha
|
52
handlers/group/captcha.py
Normal file
52
handlers/group/captcha.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
from aiogram import types
|
||||||
|
from aiogram.types.chat_permissions import ChatPermissions
|
||||||
|
|
||||||
|
from load import dp, bot, config
|
||||||
|
from keyboards.inline.keyboard import verify_button
|
||||||
|
from utils.timer import timer_manager, KickTimer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async def captcha_kick_user(message: types.Message, chat_id: int, user_id:int):
|
||||||
|
print("asdasdasd")
|
||||||
|
try:
|
||||||
|
await bot.ban_chat_member(chat_id=chat_id, user_id=user_id)
|
||||||
|
except Exception: pass
|
||||||
|
await bot.unban_chat_member(chat_id, user_id, only_if_banned=True)
|
||||||
|
await message.delete()
|
||||||
|
try:
|
||||||
|
await bot.send_message(user_id, "Время вышло!")
|
||||||
|
except Exception: pass
|
||||||
|
state = dp.current_state(chat=user_id, user=user_id)
|
||||||
|
await state.finish()
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(is_chat=True, content_types=["new_chat_members"])
|
||||||
|
async def on_join(message: types.Message):
|
||||||
|
user_id = message.from_user.id
|
||||||
|
chat_id = message.chat.id
|
||||||
|
|
||||||
|
try:
|
||||||
|
await bot.restrict_chat_member(
|
||||||
|
chat_id=chat_id,
|
||||||
|
user_id=user_id,
|
||||||
|
permissions=ChatPermissions(can_send_messages=False)
|
||||||
|
)
|
||||||
|
except Exception: return
|
||||||
|
|
||||||
|
hello_message = (
|
||||||
|
"Привет, <a href='tg://user?id={user_id}'>{name}</a>! "
|
||||||
|
"Для того чтобы удостоверится что ты наш игрок, мы попросим пройти верификацию!\n"
|
||||||
|
"<b>У вас есть 2 минуты на прохождение верификации!</b>"
|
||||||
|
)
|
||||||
|
|
||||||
|
me = await bot.get_me()
|
||||||
|
captcha_message = await bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
hello_message.format(user_id=user_id, name=message.from_user.first_name),
|
||||||
|
reply_markup=verify_button(message.from_user, me.username)
|
||||||
|
)
|
||||||
|
timer_manager.add_timer(user_id, captcha_message, KickTimer(int(config['Bot']['verify_timeout']), captcha_kick_user,
|
||||||
|
args=[captcha_message, chat_id, user_id]))
|
||||||
|
#Timer(int(config['Bot']['verify_timeout']), captcha_kick_user, args=[captcha_message, chat_id, user_id])
|
||||||
|
await message.delete()
|
12
handlers/group/main.py
Normal file
12
handlers/group/main.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from aiogram import types
|
||||||
|
|
||||||
|
from load import dp, bot, config
|
||||||
|
from database.worker import delete
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(is_chat=True, content_types=['left_chat_member'])
|
||||||
|
async def on_left(message: types.Message):
|
||||||
|
user_id = message.from_user.id
|
||||||
|
delete(user_id)
|
||||||
|
await message.delete()
|
||||||
|
|
18
handlers/group/users.py
Normal file
18
handlers/group/users.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from aiogram import types
|
||||||
|
|
||||||
|
from load import bot, dp
|
||||||
|
from database.worker import get_users
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(is_chat=True, commands=['get'])
|
||||||
|
async def get_users_info(message: types.Message):
|
||||||
|
text = ''
|
||||||
|
users = get_users()
|
||||||
|
if users is not None:
|
||||||
|
for p in users:
|
||||||
|
text += ("<a href='tg://user?id={user_id}'>{first_name}</a> ({nickname} <code>{tag}</code>)\n").format(
|
||||||
|
user_id=p['user_id'], first_name=p['first_name'], nickname=p['nickname'], tag=p['tag']
|
||||||
|
)
|
||||||
|
await bot.send_message(message.chat.id, text)
|
||||||
|
else:
|
||||||
|
await bot.send_message(message.chat.id, "Ничего не найдено!")
|
1
handlers/private/__init__.py
Normal file
1
handlers/private/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from . import register
|
114
handlers/private/register.py
Normal file
114
handlers/private/register.py
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
from aiogram import types
|
||||||
|
from aiogram.types.chat_permissions import ChatPermissions
|
||||||
|
from aiogram.dispatcher import FSMContext
|
||||||
|
from aiogram.dispatcher.filters import ChatTypeFilter
|
||||||
|
|
||||||
|
from load import dp, bot, coc_api, config
|
||||||
|
from fsm.base import Verifycation
|
||||||
|
from database.worker import register, check_register
|
||||||
|
from utils.timer import timer_manager
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(ChatTypeFilter(['private']), commands=['start'], state='*')
|
||||||
|
async def verify(message: types.Message):
|
||||||
|
|
||||||
|
status = await bot.get_chat_member(config['Bot']["chat_id"], message.from_user.id)
|
||||||
|
|
||||||
|
if status["status"] == "left":
|
||||||
|
await bot.send_message(message.chat.id, "Пошёл нахуй! В чат заходить не учили?")
|
||||||
|
return
|
||||||
|
if check_register(message.from_user.id):
|
||||||
|
await bot.send_message(message.chat.id, "Вы уже прошли верификацию!")
|
||||||
|
return
|
||||||
|
|
||||||
|
state = dp.current_state(chat=message.chat.id, user=message.from_user.id)
|
||||||
|
await state.finish()
|
||||||
|
|
||||||
|
await bot.send_message(message.chat.id, "Отправь мне свой тег")
|
||||||
|
await Verifycation.tag.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=Verifycation.tag)
|
||||||
|
async def tag_set(message: types.Message, state: FSMContext):
|
||||||
|
await state.update_data(tag=message.text)
|
||||||
|
|
||||||
|
await bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
("Отправь мне свой токен авторизации\n"
|
||||||
|
"! Владелец или кто-либо не получает доступа к вашему акаунту !\n"
|
||||||
|
"<a href='https://developer.clashofclans.com/#/documentation'>"
|
||||||
|
"Если хотите убедиться в этом, можете посмотреть официальную API, которую использует данный бот</a>")
|
||||||
|
)
|
||||||
|
await Verifycation.token.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=Verifycation.token)
|
||||||
|
async def token_set(message: types.Message, state: FSMContext):
|
||||||
|
chat_id = config['Bot']["chat_id"]
|
||||||
|
|
||||||
|
await state.update_data(token=message.text)
|
||||||
|
info = await state.get_data()
|
||||||
|
await state.finish()
|
||||||
|
|
||||||
|
data = coc_api.verify_token(**info)
|
||||||
|
#{'tag': '#TAG', 'token': 'TOKEN', 'status': 'ok'}
|
||||||
|
|
||||||
|
members = coc_api.clan_members()
|
||||||
|
|
||||||
|
clan_member = False
|
||||||
|
for i in members['items']:
|
||||||
|
if data['tag'] in i['tag']:
|
||||||
|
clan_member = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if clan_member == False:
|
||||||
|
await bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
("Вы не являетесь учасником нашего клана! Ввойдите в клан, чтобы иметь доступ к чату\n"
|
||||||
|
"Вы были кикнуты с чата, вы можете перезайти и пройти проверку повторно!")
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await bot.ban_chat_member(chat_id, message.from_user.id)
|
||||||
|
except Exception: pass
|
||||||
|
await bot.unban_chat_member(chat_id, message.from_user.id, only_if_banned=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (data['status'] == 'ok'):
|
||||||
|
await bot.send_message(message.chat.id, "Вы прошли проверку!")
|
||||||
|
register(message.from_user, coc_api.get_player(data['tag']))
|
||||||
|
|
||||||
|
|
||||||
|
group = await bot.get_chat(chat_id)
|
||||||
|
group_permissions = group["permissions"]
|
||||||
|
permissions = ChatPermissions(
|
||||||
|
can_send_messages= group_permissions["can_send_messages"],
|
||||||
|
can_send_media_messages= group_permissions["can_send_media_messages"],
|
||||||
|
can_send_polls= group_permissions["can_send_polls"],
|
||||||
|
can_send_other_messages= group_permissions["can_send_other_messages"],
|
||||||
|
can_add_web_page_previews= group_permissions["can_add_web_page_previews"],
|
||||||
|
can_change_info= group_permissions["can_change_info"],
|
||||||
|
can_invite_users= group_permissions["can_invite_users"],
|
||||||
|
can_pin_messages= group_permissions["can_pin_messages"]
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
await bot.restrict_chat_member(
|
||||||
|
chat_id=chat_id,
|
||||||
|
user_id=message.from_user.id,
|
||||||
|
permissions=permissions
|
||||||
|
)
|
||||||
|
except Exception: pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
await bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
("Вы ввели неверный токен или тег!\n"
|
||||||
|
"Вы были кикнуты с чата, вы можете перезайти и пройти проверку повторно!")
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await bot.ban_chat_member(chat_id, message.from_user.id)
|
||||||
|
except Exception: pass
|
||||||
|
await bot.unban_chat_member(chat_id, message.from_user.id, only_if_banned=True)
|
||||||
|
|
||||||
|
m = timer_manager.cancel_timer(message.from_user.id)
|
||||||
|
if m is not None:
|
||||||
|
await m.delete()
|
1
keyboards/__init__.py
Normal file
1
keyboards/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from . import inline
|
0
keyboards/inline/__init__.py
Normal file
0
keyboards/inline/__init__.py
Normal file
18
keyboards/inline/keyboard.py
Normal file
18
keyboards/inline/keyboard.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from aiogram import types
|
||||||
|
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||||
|
|
||||||
|
|
||||||
|
def verify_button(user: types.User, bot_username: str) -> InlineKeyboardMarkup:
|
||||||
|
return InlineKeyboardMarkup(
|
||||||
|
inline_keyboard=[
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(
|
||||||
|
"Подтвердить",
|
||||||
|
url="https://t.me/{bot}?start={user_id}".format(
|
||||||
|
bot=bot_username,
|
||||||
|
user_id=user.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
26
load.py
Normal file
26
load.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from aiogram import Dispatcher, Bot
|
||||||
|
from aiogram.bot.api import TelegramAPIServer
|
||||||
|
from aiogram.contrib.fsm_storage.memory import MemoryStorage
|
||||||
|
|
||||||
|
from playhouse.db_url import connect
|
||||||
|
|
||||||
|
from config import config
|
||||||
|
from coc import ClashOfClans
|
||||||
|
|
||||||
|
|
||||||
|
bot = Bot(
|
||||||
|
token=config["Bot"]["token"],
|
||||||
|
server=TelegramAPIServer.from_base(config["Bot"]["base_server"]),
|
||||||
|
parse_mode='HTML'
|
||||||
|
)
|
||||||
|
storage = MemoryStorage()
|
||||||
|
dp = Dispatcher(bot=bot, storage=storage)
|
||||||
|
|
||||||
|
|
||||||
|
db = connect(url=config["DataBase"]["link"])
|
||||||
|
|
||||||
|
|
||||||
|
coc_api = ClashOfClans(
|
||||||
|
api_token=open(config["API"]["api_file"], "r").read(),
|
||||||
|
clan_tag=config["API"]["clan_tag"]
|
||||||
|
)
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
aiogram==2.19
|
||||||
|
requests==2.27.1
|
||||||
|
peewee==3.14.10
|
60
utils/timer.py
Normal file
60
utils/timer.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
|
class KickTimer:
|
||||||
|
def __init__(self, timeout, callback, args):
|
||||||
|
self._timeout = timeout
|
||||||
|
self._callback = callback
|
||||||
|
self._args = args
|
||||||
|
self._task = None
|
||||||
|
|
||||||
|
async def _job(self):
|
||||||
|
await asyncio.sleep(self._timeout)
|
||||||
|
await self._callback(*self._args)
|
||||||
|
await asyncio.sleep(5)
|
||||||
|
self._task.cancel()
|
||||||
|
|
||||||
|
async def _run_now(self):
|
||||||
|
await self._callback(*self._args)
|
||||||
|
await asyncio.sleep(5)
|
||||||
|
self._task.cancel()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self._task = asyncio.ensure_future(self._job())
|
||||||
|
|
||||||
|
def execute_now(self):
|
||||||
|
self._task = asyncio.ensure_future(self._run_now())
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
self._task.cancel()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TimerManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.timers = {}
|
||||||
|
|
||||||
|
def add_timer(self, user_id: int, message, timer: KickTimer):
|
||||||
|
if user_id not in self.timers:
|
||||||
|
timer.start()
|
||||||
|
self.timers[user_id] = [timer, message]
|
||||||
|
|
||||||
|
def cancel_timer(self, user_id):
|
||||||
|
if user_id in self.timers:
|
||||||
|
self.timers[user_id][0].cancel()
|
||||||
|
message = self.timers[user_id][1]
|
||||||
|
del self.timers[user_id]
|
||||||
|
print(f"Timer for user {user_id} canceled")
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
|
def run_now(self, user_id):
|
||||||
|
if user_id in self.timers:
|
||||||
|
self.timers[user_id][0].execute_now()
|
||||||
|
message = self.timers[user_id][1]
|
||||||
|
del self.timers[user_id]
|
||||||
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
timer_manager = TimerManager()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user