[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 ## Welcome Bot
Используемые переменные среды: Для переиспользования этого кода в требуется
1. Cоздать аккаунт бота с помощью @BotFather
2. Аккаунт и деплой кода на vercel.com
3. Назначить бота администратором группы в его профиле, имея права назначать администраторов в группе
4. Настроить переменные среды:
- BOT_TOKEN - токен бота созданный с помощью @BotFather - BOT_TOKEN - токен бота созданный с помощью @BotFather
- CHAT_ID - айди чата, который бот защищает (можно посмотреть в урле веб-версии клиента) - 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 tgbot.rest import delete_message, register_webhook, send_message, ban_member, forward_message
from sanic import Sanic from sanic import Sanic
from sanic.response import json, text from sanic.response import json, text
import redis
app = Sanic() 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') WEBHOOK = os.environ.get('VERCEL_URL')
CHAT_ID = os.environ.get('CHAT_ID').replace("-", "-100") CHAT_ID = os.environ.get('CHAT_ID').replace("-", "-100")
WELCOME_MSG = os.environ.get('WELCOME_MSG') or 'Welcome! Press the button' 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") FEEDBACK_CHAT_ID = os.environ.get('FEEDBACK_CHAT_ID').replace("-", "-100")
# runtime storages
forwarded_ids = {}
newcomers = {}
app.config.REGISTERED = False app.config.REGISTERED = False
@ -29,7 +29,8 @@ async def register(req):
r = register_webhook(WEBHOOK) r = register_webhook(WEBHOOK)
print(f'\n\t\t\tWEBHOOK REGISTERED:\n{r.json()}') print(f'\n\t\t\tWEBHOOK REGISTERED:\n{r.json()}')
app.config.REGISTERED = True app.config.REGISTERED = True
return json(r.json()) return json(r.json())
return text('skipped')
@app.post('/') @app.post('/')
@ -37,90 +38,107 @@ async def handle(req):
print(req) print(req)
try: try:
update = req.json update = req.json
print(update) if 'message' in update:
msg = update.get('message', update.get('my_chat_member')) print(update)
if msg: msg = update.get('message', update.get('edited_message'))
if msg['chat']['type'] == 'private': 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'] mid = msg['message_id']
cid = msg['chat']['id'] cid = msg['chat']['id']
body = msg['text']
r = forward_message(cid, mid, FEEDBACK_CHAT_ID) r = forward_message(cid, mid, FEEDBACK_CHAT_ID)
print(r.json) print(r.json())
forwarded_ids[(cid,mid)] = r['id'] storage.set(f'fbk-{cid}-{mid}', r['id'])
elif str(msg['chat']['id']) == CHAT_ID: elif str(msg['chat']['id']) == CHAT_ID:
print(f'message in chat') print(f'message in chat')
if 'new_chat_member' in msg: if 'new_chat_member' in msg:
chat_id = str(msg['chat']['id']) chat_id = str(msg['chat']['id'])
from_id = str(msg['from']['id'])
member_id = str(msg['new_chat_member']['id']) member_id = str(msg['new_chat_member']['id'])
print(f'new member {member_id}') s = {
reply_markup = { "enter_id": msg['message_id']
"inline_keyboard": [
[
{"text": BUTTON_NO, "callback_data": BUTTON_NO},
{"text": BUTTON_OK, "callback_data": BUTTON_OK}
]
]
} }
r = send_message( if from_id == member_id:
chat_id, print(f'new self-joined member {member_id}')
WELCOME_MSG, reply_markup = {
reply_to=msg['message_id'], "inline_keyboard": [
reply_markup=reply_markup [
) {"text": BUTTON_NO, "callback_data": BUTTON_NO},
welcome_msg_id = r.json()['result']['message_id'] {"text": BUTTON_OK, "callback_data": BUTTON_OK}
print(f'welcome message id: {welcome_msg_id}') ]
newcomers[member_id] = f'newcomer:{msg["message_id"]}:{welcome_msg_id}' ]
}
r = send_message(
chat_id,
WELCOME_MSG,
reply_to=msg['message_id'],
reply_markup=reply_markup
)
welcome_msg_id = r.json()['result']['message_id']
print(f'welcome 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: elif 'text' in msg:
chat_id = str(msg['chat']['id']) chat_id = str(msg['chat']['id'])
member_id = str(msg['from']['id']) member_id = str(msg['from']['id'])
if member_id in newcomers:
print(f'new member speak {msg["text"]}') # check is author is selfjoined newcomer
if newcomers[member_id].startswith('newcomer'): author = storage.get(f'usr-{member_id}')
print('watched newcomer')
if author:
author = json.parse(author)
if author.get("newcomer"):
print(f'new member speaks {msg["text"]}')
answer = 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') print('found answer, cleanup')
[_, enter_msg, welcome_msg] = newcomers[member_id].split(':') r = delete_message(CHAT_ID, author["welcome_id"])
r = delete_message(CHAT_ID, welcome_msg)
print(r.json()) 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: else:
print('remove some message') print('remove some message')
r = delete_message(CHAT_ID, msg['message_id']) r = delete_message(CHAT_ID, msg['message_id'])
print(r.json()) print(r.json())
else: else:
print(f'old member speak {msg["text"]}') print(f'old member speaks {msg["text"]}')
if 'callback_query' in update: if 'callback_query' in update:
callback_query = update['callback_query'] callback_query = update['callback_query']
chat_id = str(callback_query['message']['chat']['id']) chat_id = str(callback_query['message']['chat']['id'])
if chat_id == CHAT_ID: if chat_id == CHAT_ID:
print(f'callback_query in {CHAT_ID}')
member_id = str(callback_query['from']['id']) member_id = str(callback_query['from']['id'])
callback_data = callback_query['data'] callback_data = callback_query['data']
reply_owner = str(callback_query['message']['reply_to_message']['from']['id']) reply_owner = str(callback_query['message']['reply_to_message']['from']['id'])
if reply_owner == member_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: if callback_data == BUTTON_NO:
print('wrong answer, cleanup') print('wrong answer, cleanup')
[_, enter_msg, welcome_msg] = newcomers[member_id].split(':') r = delete_message(CHAT_ID, s['enter_id'])
r = delete_message(CHAT_ID, enter_msg)
print(r.json()) print(r.json())
r = delete_message(CHAT_ID, welcome_msg) r = delete_message(CHAT_ID, s['welcome_id'])
print(r.json()) print(r.json())
newcomers[member_id] = None storage.delete(f'usr-{member_id}')
print('ban member') print('ban member')
r = ban_member(CHAT_ID, member_id) r = ban_member(CHAT_ID, member_id)
print(r.json()) print(r.json())
elif callback_data == BUTTON_OK: elif callback_data == BUTTON_OK:
print('proper answer, cleanup') print('proper answer, cleanup')
[_, enter_msg, welcome_msg] = newcomers[member_id].split(':') r = delete_message(CHAT_ID, s['welcome_id'])
r = delete_message(CHAT_ID, welcome_msg)
print(r.json()) print(r.json())
newcomers[member_id] = None s['newcomer'] = False
storage.set(f'usr-{member_id}', json.dumps(s))
except Exception: except Exception:
pass pass
return text('ok') return text('ok')

View File

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