version-0.2.0
This commit is contained in:
parent
bc05b93c47
commit
908529b5bb
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -7,4 +7,6 @@ update.json
|
|||
.vscode
|
||||
.idea
|
||||
venv
|
||||
*.rdb
|
||||
*.rdb
|
||||
.venv
|
||||
poetry.lock
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
## [0.2.0]
|
||||
|
||||
- реорганизация кодовой базы
|
||||
- удаление зависимости от aiogram
|
||||
- удаление остатков зависимостей от vercel
|
||||
- переход на poetry
|
||||
|
||||
|
||||
## [0.0.12]
|
||||
|
||||
- множество исправлений в роутинге сообщений
|
||||
|
|
18
Dockerfile
18
Dockerfile
|
@ -1,6 +1,14 @@
|
|||
FROM python:3.11-slim
|
||||
FROM python:slim
|
||||
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
COPY . .
|
||||
CMD ["python", "bot/main.py"]
|
||||
COPY . /app
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y git curl && \
|
||||
curl -sSL https://install.python-poetry.org | python - && \
|
||||
echo "export PATH=$PATH:/root/.local/bin" >> ~/.bashrc && \
|
||||
. ~/.bashrc && \
|
||||
poetry config virtualenvs.create false && \
|
||||
poetry install --no-dev
|
||||
|
||||
CMD python main.py
|
||||
|
|
22
README.md
22
README.md
|
@ -2,14 +2,22 @@
|
|||
|
||||
Для переиспользования этого кода в требуется
|
||||
|
||||
1. Cоздать аккаунт бота с помощью @BotFather
|
||||
1. Cоздать аккаунт бота с помощью `@BotFather`
|
||||
|
||||
2. Аккаунт и деплой кода на vercel.com
|
||||
2. Назначить бота администратором группы в его профиле, имея права назначать администраторов в группе
|
||||
|
||||
3. Назначить бота администратором группы в его профиле, имея права назначать администраторов в группе
|
||||
3. Настроить переменные среды:
|
||||
|
||||
4. Настроить переменные среды:
|
||||
- `BOT_TOKEN` - токен бота созданный с помощью @BotFather
|
||||
- `FEEDBACK_CHAT_ID` - айди чата для обратной связи
|
||||
- `REDIS_URL`
|
||||
|
||||
- BOT_TOKEN - токен бота созданный с помощью @BotFather
|
||||
- FEEDBACK_CHAT_ID - айди чата для обратной связи
|
||||
- REDIS_URL
|
||||
### Локальная разработка
|
||||
|
||||
```sh
|
||||
mkdir .venv
|
||||
python3.12 -m venv .venv
|
||||
poetry env use .venv/bin/python3.12
|
||||
poetry update
|
||||
poetry run python main.py
|
||||
```
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
from bot.handlers.routing import handle_routing
|
||||
from bot.handlers.callback_vouch import handle_button
|
||||
from bot.handlers.callback_unlink import handle_unlink
|
||||
from bot.handlers.handle_startup import handle_startup
|
||||
from bot.handlers.handle_join_request import handle_join_request
|
||||
from bot.api import register_webhook, send_message
|
||||
from bot.config import FEEDBACK_CHAT_ID, WEBHOOK
|
||||
from bot.state import State
|
||||
from sanic.app import Sanic
|
||||
from sanic.response import text
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
app = Sanic(name="welcomecenter")
|
||||
app.config.LOGGING = True
|
||||
app.config.REGISTERED = False
|
||||
state = State()
|
||||
|
||||
@app.get("/")
|
||||
async def register(req):
|
||||
if not app.config.REGISTERED:
|
||||
logger.info(register_webhook())
|
||||
app.config.REGISTERED = True
|
||||
await handle_startup()
|
||||
return text("ok")
|
||||
|
||||
|
||||
@app.post("/")
|
||||
async def handle(req):
|
||||
logger.debug(req)
|
||||
try:
|
||||
update = req.json
|
||||
logger.debug(update)
|
||||
|
||||
# видимые сообщения
|
||||
msg = update.get("message", update.get("edited_message"))
|
||||
if msg:
|
||||
msg["edit"] = "edited_message" in update
|
||||
await handle_routing(msg)
|
||||
|
||||
# кнопки
|
||||
elif "callback_query" in update:
|
||||
data = update["callback_query"]["data"]
|
||||
if data.startswith("vouch"):
|
||||
await handle_button(update["callback_query"])
|
||||
elif data.startswith("unlink"):
|
||||
await handle_unlink(update["callback_query"])
|
||||
|
||||
# заявки
|
||||
elif "chat_join_request" in update:
|
||||
logger.info("chat join request")
|
||||
await handle_join_request(update["chat_join_request"])
|
||||
|
||||
except Exception:
|
||||
import traceback
|
||||
await send_message(FEEDBACK_CHAT_ID, f"<pre>\n{traceback.format_exc()}\n</pre>")
|
||||
traceback.print_exc()
|
||||
logger.error(traceback.format_exc())
|
||||
return text("ok")
|
|
@ -1,6 +1,6 @@
|
|||
import aiohttp
|
||||
import json
|
||||
from config import BOT_TOKEN, WEBHOOK
|
||||
from bot.config import BOT_TOKEN, WEBHOOK
|
||||
import logging
|
||||
|
||||
# Create a logger instance
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from api import send_message, delete_message, kick_member
|
||||
from bot.api import send_message, delete_message, kick_member
|
||||
from handlers.command_my import handle_command_my
|
||||
from handlers.callback_vouch import update_button
|
||||
from utils.mention import userdata_extract
|
||||
from storage import Profile
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
from api import approve_chat_join_request, edit_replymarkup
|
||||
from bot.api import approve_chat_join_request, edit_replymarkup
|
||||
from storage import Profile, storage
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
from storage import Profile
|
||||
from handlers.send_button import show_request_msg
|
||||
from api import get_member
|
||||
from bot.api import get_member
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
|
@ -1,5 +1,5 @@
|
|||
from utils.graph import generate_chart
|
||||
from api import send_document
|
||||
from bot.api import send_document
|
||||
from storage import storage, scan
|
||||
import json
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from storage import Profile, scan
|
||||
from api import get_member, send_message
|
||||
from bot.api import get_member, send_message
|
||||
from utils.mention import userdata_extract
|
||||
import json
|
||||
import logging
|
|
@ -1,4 +1,4 @@
|
|||
from api import send_message, delete_message, get_chat_administrators
|
||||
from bot.api import send_message, delete_message, get_chat_administrators
|
||||
from handlers.command_my import handle_command_my
|
||||
from storage import Profile, storage
|
||||
from handlers.send_button import show_request_msg
|
|
@ -1,13 +1,15 @@
|
|||
import json
|
||||
|
||||
from api import (
|
||||
from bot.api import (
|
||||
send_message,
|
||||
forward_message,
|
||||
get_chat_administrators,
|
||||
)
|
||||
from storage import storage
|
||||
from config import FEEDBACK_CHAT_ID
|
||||
from bot.config import FEEDBACK_CHAT_ID
|
||||
import logging
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from api import approve_chat_join_request, delete_message
|
||||
from bot.api import approve_chat_join_request, delete_message
|
||||
from handlers.send_button import show_request_msg
|
||||
from storage import Profile, storage
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from handlers.send_button import show_request_msg
|
||||
from api import delete_message
|
||||
from bot.api import delete_message
|
||||
from storage import Profile, storage
|
||||
from config import FEEDBACK_CHAT_ID
|
||||
from bot.config import FEEDBACK_CHAT_ID
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
|
@ -1,10 +1,11 @@
|
|||
from config import FEEDBACK_CHAT_ID
|
||||
from bot.config import FEEDBACK_CHAT_ID
|
||||
from storage import scan, Profile
|
||||
from api import approve_chat_join_request, kick_member, send_message
|
||||
from bot.api import approve_chat_join_request, kick_member, send_message
|
||||
from handlers.callback_vouch import update_button
|
||||
from utils.mention import userdata_extract
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
|
@ -3,7 +3,7 @@ from handlers.handle_default import handle_default
|
|||
from handlers.command_my import handle_command_my
|
||||
from handlers.command_graph import handle_command_graph
|
||||
from handlers.command_ask import handle_command_ask
|
||||
from config import FEEDBACK_CHAT_ID
|
||||
from bot.config import FEEDBACK_CHAT_ID
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
|
@ -1,7 +1,10 @@
|
|||
from api import send_message, send_photo, get_userphotos, delete_message
|
||||
from bot.api import send_message, send_photo, get_userphotos, delete_message
|
||||
from utils.mention import mention, userdata_extract
|
||||
from storage import storage
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
|
@ -1,38 +1,30 @@
|
|||
import asyncio
|
||||
import logging
|
||||
import signal
|
||||
import sys
|
||||
import signal # Import the signal module
|
||||
from aiogram import Bot, Dispatcher, Router
|
||||
from aiogram.enums import ParseMode
|
||||
from aiogram.filters import CommandStart
|
||||
from aiogram.types import Message, ChatJoinRequest, CallbackQuery, ChatMemberUpdated
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
from config import BOT_TOKEN, FEEDBACK_CHAT_ID
|
||||
from aiohttp import web
|
||||
from bot.api import send_message
|
||||
from handlers.routing import handle_routing
|
||||
from handlers.callback_unlink import handle_unlink
|
||||
from handlers.callback_vouch import handle_button
|
||||
from handlers.handle_join_request import handle_join_request
|
||||
from handlers.handle_startup import handle_startup
|
||||
from handlers.handle_members_change import handle_join, handle_left
|
||||
from state import State
|
||||
from storage import Profile
|
||||
from storage.profile import Profile
|
||||
from bot.state import State
|
||||
from bot.config import FEEDBACK_CHAT_ID
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
router = Router()
|
||||
bot = Bot(BOT_TOKEN, parse_mode=ParseMode.HTML)
|
||||
dp = Dispatcher()
|
||||
state = State()
|
||||
|
||||
|
||||
@router.message(CommandStart())
|
||||
async def command_start_handler(message: Message) -> None:
|
||||
async def command_start_handler(message):
|
||||
caption = "Напишите своё сообщение для нас" if message.from_user.llanguage_code == 'ru' else "Write your message for us"
|
||||
await message.answer(caption)
|
||||
|
||||
|
||||
@router.callback_query()
|
||||
async def process_callback(callback_query: CallbackQuery):
|
||||
async def process_callback(callback_query):
|
||||
cbq = vars(callback_query)
|
||||
try:
|
||||
cbq["from"] = vars(callback_query.from_user)
|
||||
|
@ -47,11 +39,10 @@ async def process_callback(callback_query: CallbackQuery):
|
|||
logger.debug(cbq)
|
||||
import traceback
|
||||
text = traceback.format_exc()
|
||||
await bot.send_message(FEEDBACK_CHAT_ID, text)
|
||||
await send_message(FEEDBACK_CHAT_ID, text)
|
||||
|
||||
|
||||
@router.chat_join_request()
|
||||
async def join_request_handler(update: ChatJoinRequest) -> None:
|
||||
async def join_request_handler(update):
|
||||
print("chat join request")
|
||||
join_request = vars(update)
|
||||
try:
|
||||
|
@ -63,11 +54,10 @@ async def join_request_handler(update: ChatJoinRequest) -> None:
|
|||
logger.debug(join_request)
|
||||
import traceback
|
||||
text = traceback.format_exc()
|
||||
await bot.send_message(FEEDBACK_CHAT_ID, text)
|
||||
await send_message(FEEDBACK_CHAT_ID, text)
|
||||
|
||||
|
||||
@router.message()
|
||||
async def all_handler(message: Message) -> None:
|
||||
async def all_handler(message):
|
||||
msg = vars(message)
|
||||
try:
|
||||
msg["from"] = vars(message.from_user)
|
||||
|
@ -81,11 +71,10 @@ async def all_handler(message: Message) -> None:
|
|||
logger.debug(msg)
|
||||
import traceback
|
||||
text = traceback.format_exc()
|
||||
await bot.send_message(FEEDBACK_CHAT_ID, text)
|
||||
await send_message(FEEDBACK_CHAT_ID, text)
|
||||
|
||||
|
||||
@router.my_chat_member()
|
||||
async def chat_members_change(update: ChatMemberUpdated):
|
||||
async def chat_members_change(update):
|
||||
member_updated = vars(update)
|
||||
try:
|
||||
member_updated["chat"] = vars(update.chat)
|
||||
|
@ -100,33 +89,38 @@ async def chat_members_change(update: ChatMemberUpdated):
|
|||
await handle_join(member_updated)
|
||||
else:
|
||||
logger.info("unhandled members update")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[main.my_chat_member] ERROR {e}")
|
||||
logger.debug(member_updated)
|
||||
import traceback
|
||||
text = traceback.format_exc()
|
||||
await bot.send_message(FEEDBACK_CHAT_ID, text)
|
||||
await send_message(FEEDBACK_CHAT_ID, text)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
# connect router
|
||||
dp.include_router(router)
|
||||
async def main(request):
|
||||
# storage revalidation
|
||||
await handle_startup()
|
||||
# Start event dispatching
|
||||
await dp.start_polling(bot)
|
||||
|
||||
# Получение обновлений
|
||||
updates = await request.json()
|
||||
|
||||
for update in updates["result"]:
|
||||
if "message" in update:
|
||||
await all_handler(update["message"])
|
||||
elif "callback_query" in update:
|
||||
await process_callback(update["callback_query"])
|
||||
elif "join_chat_request" in update:
|
||||
await join_request_handler(update["join_chat_request"])
|
||||
elif "my_chat_member" in update:
|
||||
await chat_members_change(update["my_chat_member"])
|
||||
|
||||
return web.Response()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
|
||||
|
||||
# Define a function to handle SIGTERM
|
||||
def handle_sigterm(signum, frame):
|
||||
logger.info("Received SIGTERM. Shutting down gracefully...")
|
||||
asyncio.get_event_loop().stop()
|
||||
|
||||
# Register the SIGTERM signal handler
|
||||
signal.signal(signal.SIGTERM, handle_sigterm)
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(main())
|
||||
app = web.Application()
|
||||
app.router.add_post('/your_bot_token', main) # Замените 'your_bot_token' на реальный токен вашего бота
|
||||
web.run_app(app, host='0.0.0.0', port=3000) # Выберите подходящий порт
|
86
pyproject.toml
Normal file
86
pyproject.toml
Normal file
|
@ -0,0 +1,86 @@
|
|||
[tool.poetry]
|
||||
name = "welcomecenterbot"
|
||||
version = "0.2.0"
|
||||
description = "telegram group helper"
|
||||
authors = ["rainbowdev circle"]
|
||||
license = "Open Source"
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.12"
|
||||
aiohttp = "^3.9.1"
|
||||
redis = "^5.0.1"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
setuptools = "^69.0.2"
|
||||
mypy = "^1.6.1"
|
||||
black = "^23.10.1"
|
||||
ruff = "^0.1.2"
|
||||
isort = "^5.12.0"
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
target-version = ['py312']
|
||||
include = '\.pyi?$'
|
||||
exclude = '''
|
||||
(
|
||||
/(
|
||||
\.eggs
|
||||
| \.git
|
||||
| \.hg
|
||||
| \.mypy_cache
|
||||
| \.tox
|
||||
| \.venv
|
||||
| _build
|
||||
| buck-out
|
||||
| build
|
||||
| dist
|
||||
)/
|
||||
| foo.py
|
||||
)
|
||||
'''
|
||||
|
||||
[tool.isort]
|
||||
multi_line_output = 3
|
||||
include_trailing_comma = true
|
||||
force_grid_wrap = 0
|
||||
use_parentheses = true
|
||||
ensure_newline_before_comments = true
|
||||
line_length = 120
|
||||
|
||||
[tool.ruff]
|
||||
select = ["E4", "E7", "E9", "F"]
|
||||
ignore = []
|
||||
line-length = 120
|
||||
target-version = "py312"
|
||||
|
||||
[tool.pyright]
|
||||
venvPath = "."
|
||||
venv = ".venv"
|
||||
include = ["bot/."]
|
||||
useLibraryCodeForTypes = false
|
||||
disableLanguageServices = false
|
||||
disableOrganizeImports = false
|
||||
reportMissingImports = true
|
||||
reportMissingModuleSource = "warning"
|
||||
reportImportCycles = "warning"
|
||||
maxMemoryForLargeFile = 4096
|
||||
pythonVersion = "3.12"
|
||||
autoImportCompletions = true
|
||||
useVirtualEnv = true
|
||||
typeCheckingMode = "basic"
|
||||
disableJediCompletion = true
|
||||
disableCompletion = false
|
||||
disableSnippetCompletion = false
|
||||
disableGoToDefinition = false
|
||||
disableRenaming = false
|
||||
disableSignatureHelp = false
|
||||
diagnostics = true
|
||||
logLevel = "debug"
|
||||
pluginSearchPaths = []
|
||||
typings = {}
|
||||
mergeTypeStubPackages = false
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
|
@ -1,5 +0,0 @@
|
|||
# sanic==19.6.0
|
||||
redis
|
||||
asyncio
|
||||
aiohttp
|
||||
aiogram
|
|
@ -1,6 +1,6 @@
|
|||
from redis import Redis
|
||||
from storage.profile import Profile as ProfileObj
|
||||
from config import REDIS_URL
|
||||
from bot.config import REDIS_URL
|
||||
import json
|
||||
|
||||
|
15
vercel.json
15
vercel.json
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"version": 2,
|
||||
"functions": {
|
||||
"api/webhook.py": {
|
||||
"memory": 1024,
|
||||
"maxDuration": 10
|
||||
}
|
||||
},
|
||||
"routes": [
|
||||
{
|
||||
"src": "/",
|
||||
"dest": "/api/webhook.py"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user