[0.0.3]-redis-fixes

This commit is contained in:
tonyrewin 2023-04-17 15:49:42 +03:00
parent 4fd02fccd6
commit 0a3cdda4be
4 changed files with 100 additions and 53 deletions

20
CHANGELOG.md Normal file
View File

@ -0,0 +1,20 @@
[0.0.3]
- подключение независимого от перезапусков хранилища redis
- многозадачные хранимые сессии пользователей
- доработки логов отладки
- bugfix: пропуск приглашённых участников
- bugfix: учитывание редактируемого сообщения обратной связи
[0.0.2]
- добавлена функция для обратной связи
- исправлена ошибка повторной регистрации хука
[0.0.1]
- фундаментальная кодовая база на основе Sanic и requests
- настройки на основе переменных среды
- функция приветственного сообщения с кнопками
- ограничения для новоприбывших и неверно отвечающих
- распознание приветствия в тексте

View File

@ -1,6 +1,14 @@
## Welcome Bot
Используемые переменные среды:
Для переиспользования этого кода в требуется
1. Cоздать аккаунт бота с помощью @BotFather
2. Аккаунт и деплой кода на vercel.com
3. Назначить бота администратором группы в его профиле, имея права назначать администраторов в группе
4. Настроить переменные среды:
- BOT_TOKEN - токен бота созданный с помощью @BotFather
- CHAT_ID - айди чата, который бот защищает (можно посмотреть в урле веб-версии клиента)

View File

@ -3,10 +3,13 @@ import os
from tgbot.rest import delete_message, register_webhook, send_message, ban_member, forward_message
from sanic import Sanic
from sanic.response import json, text
import redis
app = Sanic()
REDIS_URL = os.environ.get('REDIS_URL') or 'redis://localhost:6379'
storage = redis.from_url(REDIS_URL) # сохраняет сессии и пересылаемые сообщения между перезагрузками
WEBHOOK = os.environ.get('VERCEL_URL')
CHAT_ID = os.environ.get('CHAT_ID').replace("-", "-100")
WELCOME_MSG = os.environ.get('WELCOME_MSG') or 'Welcome! Press the button'
@ -17,9 +20,6 @@ BUTTON_NO = os.environ.get('BUTTON_NO') or 'No'
FEEDBACK_CHAT_ID = os.environ.get('FEEDBACK_CHAT_ID').replace("-", "-100")
# runtime storages
forwarded_ids = {}
newcomers = {}
app.config.REGISTERED = False
@ -30,6 +30,7 @@ async def register(req):
print(f'\n\t\t\tWEBHOOK REGISTERED:\n{r.json()}')
app.config.REGISTERED = True
return json(r.json())
return text('skipped')
@app.post('/')
@ -37,27 +38,26 @@ async def handle(req):
print(req)
try:
update = req.json
if 'message' in update:
print(update)
msg = update.get('message', update.get('my_chat_member'))
if msg:
msg = update.get('message', update.get('edited_message'))
if msg['chat']['type'] == 'private':
if not msg:
msg = update['edited_message']
mid = msg['message_id']
cid = msg['chat']['id']
delete_message(FEEDBACK_CHAT_ID, forwarded_ids[(cid, mid)])
mid = msg['message_id']
cid = msg['chat']['id']
body = msg['text']
r = forward_message(cid, mid, FEEDBACK_CHAT_ID)
print(r.json)
forwarded_ids[(cid,mid)] = r['id']
print(r.json())
storage.set(f'fbk-{cid}-{mid}', r['id'])
elif str(msg['chat']['id']) == CHAT_ID:
print(f'message in chat')
if 'new_chat_member' in msg:
chat_id = str(msg['chat']['id'])
from_id = str(msg['from']['id'])
member_id = str(msg['new_chat_member']['id'])
print(f'new member {member_id}')
s = {
"enter_id": msg['message_id']
}
if from_id == member_id:
print(f'new self-joined member {member_id}')
reply_markup = {
"inline_keyboard": [
[
@ -74,53 +74,71 @@ async def handle(req):
)
welcome_msg_id = r.json()['result']['message_id']
print(f'welcome message id: {welcome_msg_id}')
newcomers[member_id] = f'newcomer:{msg["message_id"]}:{welcome_msg_id}'
s["newcomer"] = True,
s["welcome_id"] = welcome_msg_id
else:
s['newcomer'] = False
# create session
storage.set(f'usr-{member_id}', json.dumps(s))
elif 'text' in msg:
chat_id = str(msg['chat']['id'])
member_id = str(msg['from']['id'])
if member_id in newcomers:
print(f'new member speak {msg["text"]}')
if newcomers[member_id].startswith('newcomer'):
print('watched newcomer')
# check is author is selfjoined newcomer
author = storage.get(f'usr-{member_id}')
if author:
author = json.parse(author)
if author.get("newcomer"):
print(f'new member speaks {msg["text"]}')
answer = msg['text']
if BUTTON_OK.lower() in answer.lower() or BUTTON_OK2.lower() in answer.lower():
if BUTTON_OK.lower() in answer.lower() or \
BUTTON_OK2.lower() in answer.lower():
print('found answer, cleanup')
[_, enter_msg, welcome_msg] = newcomers[member_id].split(':')
r = delete_message(CHAT_ID, welcome_msg)
r = delete_message(CHAT_ID, author["welcome_id"])
print(r.json())
newcomers[member_id] = None
author["newcomer"] = False
# set author as not a newcomer
storage.set(f'usr-{member_id}', json.dumps(author))
else:
print('remove some message')
r = delete_message(CHAT_ID, msg['message_id'])
print(r.json())
else:
print(f'old member speak {msg["text"]}')
print(f'old member speaks {msg["text"]}')
if 'callback_query' in update:
callback_query = update['callback_query']
chat_id = str(callback_query['message']['chat']['id'])
if chat_id == CHAT_ID:
print(f'callback_query in {CHAT_ID}')
member_id = str(callback_query['from']['id'])
callback_data = callback_query['data']
reply_owner = str(callback_query['message']['reply_to_message']['from']['id'])
if reply_owner == member_id:
print(update)
print(f'callback_query in {CHAT_ID}')
s = storage.get(f'usr-{member_id}')
if s:
s = json.parse(s)
if callback_data == BUTTON_NO:
print('wrong answer, cleanup')
[_, enter_msg, welcome_msg] = newcomers[member_id].split(':')
r = delete_message(CHAT_ID, enter_msg)
r = delete_message(CHAT_ID, s['enter_id'])
print(r.json())
r = delete_message(CHAT_ID, welcome_msg)
r = delete_message(CHAT_ID, s['welcome_id'])
print(r.json())
newcomers[member_id] = None
storage.delete(f'usr-{member_id}')
print('ban member')
r = ban_member(CHAT_ID, member_id)
print(r.json())
elif callback_data == BUTTON_OK:
print('proper answer, cleanup')
[_, enter_msg, welcome_msg] = newcomers[member_id].split(':')
r = delete_message(CHAT_ID, welcome_msg)
r = delete_message(CHAT_ID, s['welcome_id'])
print(r.json())
newcomers[member_id] = None
s['newcomer'] = False
storage.set(f'usr-{member_id}', json.dumps(s))
except Exception:
pass
return text('ok')

View File

@ -1,2 +1,3 @@
sanic==19.6.0
requests
redis