Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
havebeenfitz committed Sep 19, 2022
2 parents c8d02b8 + af4d92a commit 20d9d2e
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 67 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ Dependencies:
- AWS cron job
- Generate pairs weekly
- Bot asks if a user contacted his/her pair on Wed/Thu
- Inline Menu
- Pause/Resume buttons
- Generate pairs for admins
- Provide Feedback button + send to separate channel
- ~~Inline Menu~~
- ~~Pause/Resume buttons~~
- ~~Generate pairs for admins~~
- ~~Provide Feedback button + send to separate channel~~


### Nice to have:

- Select offline location from a list
- Notify members about the next round
- Edit profile from inline menu
- ~~Edit profile from inline menu~~
- Move all strings to a separate file/module
4 changes: 3 additions & 1 deletion bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ def debug_main():

def add_handlers():
application.add_handler(CommandHandler(command=Command.start, callback=start_handler))
application.add_handler(CommandHandler(command=Command.menu, callback=menu_handler))

application.add_handler(CallbackQueryHandler(callback=pause_handler, pattern=f"^{MenuCallback.pause}$"))

application.add_handler(profile_conversation_handler())
Expand Down Expand Up @@ -97,7 +99,7 @@ def profile_conversation_handler() -> ConversationHandler:
CommandHandler(Command.cancel, cancel_handler)
],
FillProfileCallback.city: [
MessageHandler(filters=filters.LOCATION & ~filters.COMMAND, callback=city_handler),
MessageHandler(filters=filters.LOCATION & ~filters.COMMAND & ~filters.TEXT, callback=city_handler),
CommandHandler(Command.cancel, cancel_handler)
],
FillProfileCallback.bio: [
Expand Down
13 changes: 6 additions & 7 deletions src/db_helper.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
from collections import namedtuple
from typing import Optional
from src.vars import PROD
from src.models.user import User
from src.models.static_models import MeetingFormatCallback

import boto3
from boto3.dynamodb.conditions import Key, Attr

from src.models.static_models import MeetingFormatCallback
from src.models.user import User
from src.vars import PROD


class DBHelper(object):

def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(DBHelper, cls).__new__(cls)
Expand Down Expand Up @@ -55,9 +54,9 @@ def update_user_profile(
'bio': user.bio,
'is_paused': user.is_paused
}
if user.meeting_format == MeetingFormatCallback.offline:
if user.meeting_format == MeetingFormatCallback.offline.id:
item['city'] = user.city
item['country']: user.country
item['country'] = user.country

self._usersTable.put_item(Item=item)

Expand Down
153 changes: 103 additions & 50 deletions src/handlers/menu_handlers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import logging

from telegram import (
error,
ChatMember,
ChatMemberBanned,
ChatMemberLeft,
Update,
InlineKeyboardButton,
InlineKeyboardMarkup
)
Expand All @@ -17,32 +15,60 @@
logging.getLogger().setLevel('INFO')
db_helper = DBHelper()

current_session_user: User
current_db_user: User
chat_member: ChatMember


async def start_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
logging.info('Getting chat member..')
member = await context.bot.get_chat_member(chat_id=MEMBERSHIP_CHAT_ID, user_id=update.effective_user.id)
member = await _get_chat_member(update, context)
logging.info('Done..')

if member.status is not (ChatMemberLeft or ChatMemberBanned):
logging.info('Member is fine, show keyboard..')
db_user = db_helper.get_user(user_id=member.user.id)
db_user = _get_db_user(update, context)

if db_user is None:
await update.message.reply_text(
text="Привет, я Random Coffee bot!\n\n"
"Чтобы начать, заполни профиль ниже. Еще можно временно остановить участие и оставить отзыв",
)

reply_keyboard: list[list] = []
menu_markup = _menu_buttons(context, member, db_user)

if db_user is not None:
_add_existing_user_buttons(context, member, db_user, reply_keyboard)
await update.message.reply_text(
text='Меню',
reply_markup=menu_markup
)
else:
reply_keyboard.append(
[InlineKeyboardButton('👤 Заполнить профиль', callback_data=MenuCallback.fill_profile)]
await update.message.reply_text(
text="Ты уже стартовал, вызови /menu, чтобы заполнить или отредактировать профиль"
)
else:
logging.info('Sending membership message request...')
await send_membership_message(update, context)
logging.info('Done')
except error.BadRequest as e:
logging.info('Bad request')
logging.info(e)
await send_membership_message(update, context)


async def menu_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
logging.info('Getting chat member..')
member = await _get_chat_member(update, context)
logging.info('Done..')

if member.status is not (ChatMemberLeft or ChatMemberBanned):
logging.info('Member is fine, show keyboard..')
db_user = _get_db_user(update, context)
reply_keyboard_markup = _menu_buttons(context, member, db_user)

await update.message.reply_text(
"Привет, я Random Coffee bot!\n\n"
"Чтобы начать, заполни профиль ниже. Еще можно временно остановить участие и оставить отзыв",
reply_markup=InlineKeyboardMarkup(reply_keyboard)
'Меню',
reply_markup=reply_keyboard_markup
)

logging.info('Keyboard shown')
Expand All @@ -56,39 +82,36 @@ async def start_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):


async def pause_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()

logging.info('Setting pause on/off')

global current_session_user
db_user = _get_db_user(update, context)

try:
current_session_user
except NameError:
current_session_user = db_helper.get_user(str(update.effective_user.id))
should_pause = not db_user.is_paused
db_user.is_paused = should_pause
context.user_data['is_paused'] = db_user.is_paused

should_pause = not current_session_user.is_paused
current_session_user.is_paused = should_pause
member = await _get_chat_member(update, context)

db_helper.pause_user(should_pause, current_session_user)
inline_keyboard = update.callback_query.message.reply_markup.inline_keyboard
db_helper.pause_user(should_pause, db_user)
inline_markup = _menu_buttons(context, member, db_user)

for idx, inline_buttons in enumerate(inline_keyboard):
if inline_buttons[0].callback_data == MenuCallback.pause:
if not should_pause:
inline_keyboard[idx] = \
[InlineKeyboardButton(text='⏸️ Поставить на паузу', callback_data=MenuCallback.pause)]
else:
inline_keyboard[idx] = \
[InlineKeyboardButton(text='▶️ Снять с паузы', callback_data=MenuCallback.pause)]
break
await update.effective_message.edit_reply_markup(inline_markup)

await update.callback_query.message.edit_reply_markup(
InlineKeyboardMarkup(inline_keyboard=inline_keyboard)
await update.effective_message.reply_text(
text='Скрыл твою анкету. Если захочешь участвовать снова, сними с паузы' if should_pause
else 'Открыл твою анкету, ты снова участвуешь'
)

logging.info('Done pause')


async def feedback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
query = update.callback_query
await query.answer()

user_id = update.effective_user.id

await context.bot.send_message(
Expand Down Expand Up @@ -125,33 +148,63 @@ async def send_membership_message(update: Update, context: ContextTypes.DEFAULT_

# Private

def _add_existing_user_buttons(context, member, db_user, reply_keyboard_markup):
context.user_data['is_paused'] = db_user.is_paused
global current_session_user
current_session_user = db_user
def _get_db_user(update, context) -> User:
global current_db_user

try:
current_db_user
except NameError:
current_db_user = db_helper.get_user(str(update.effective_user.id))

if current_db_user is not None:
context.user_data['is_paused'] = current_db_user.is_paused

return current_db_user


async def _get_chat_member(update, context) -> ChatMember:
global chat_member

try:
chat_member
except NameError:
chat_member = await context.bot.get_chat_member(chat_id=MEMBERSHIP_CHAT_ID, user_id=update.effective_user.id)

return chat_member

reply_keyboard_markup.append(
[InlineKeyboardButton('👤 Редактировать профиль', callback_data=MenuCallback.fill_profile)]
)

if not db_user.is_paused:
reply_keyboard_markup.append(
[InlineKeyboardButton(text='⏸️ Поставить на паузу', callback_data=MenuCallback.pause)]
def _menu_buttons(context, member, db_user) -> InlineKeyboardMarkup:
reply_keyboard: list[list[InlineKeyboardButton]] = []

if db_user is not None:
reply_keyboard.append(
[InlineKeyboardButton('👤 Редактировать профиль', callback_data=MenuCallback.fill_profile)]
)

if not db_user.is_paused:
reply_keyboard.append(
[InlineKeyboardButton(text='⏸️ Поставить на паузу', callback_data=MenuCallback.pause)]
)
else:
reply_keyboard.append(
[InlineKeyboardButton(text='▶️ Снять с паузы', callback_data=MenuCallback.pause)]
)

reply_keyboard.append(
[InlineKeyboardButton(text='💡 Отправить отзыв', callback_data=MenuCallback.send_feedback)]
)
else:
reply_keyboard_markup.append(
[InlineKeyboardButton(text='▶️ Снять с паузы', callback_data=MenuCallback.pause)]
reply_keyboard.append(
[InlineKeyboardButton('👤 Заполнить профиль', callback_data=MenuCallback.fill_profile)]
)

if str(member.user.id) in ADMIN_ACCOUNTS:
logging.info(f'{member.user.id} is admin. adding generate pairs handler...')
reply_keyboard_markup.append(
reply_keyboard.append(
[InlineKeyboardButton(text='🎲 Сгенерировать пары', callback_data=MenuCallback.generate_pairs)]
)
context.application.add_handler(
CallbackQueryHandler(callback=generate_pairs_handler, pattern=f"{MenuCallback.generate_pairs}")
)

reply_keyboard_markup.append(
[InlineKeyboardButton(text='💡 Отправить отзыв', callback_data=MenuCallback.send_feedback)]
)
return InlineKeyboardMarkup(inline_keyboard=reply_keyboard)
5 changes: 4 additions & 1 deletion src/handlers/pair_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@


async def generate_pairs(update: Update, context: CallbackContext):
query = update.callback_query
await query.answer()

logging.info('Generating pairs...')

pairs: list[list] = []
Expand Down Expand Up @@ -67,7 +70,7 @@ async def _send_pair_messages(update, context, pair: (User, User)):
chat_id=first_user_id if PROD else update.effective_user.id,
text=f"Штош, @{first_user_name}!\n\n" \
f"Твоя пара на эту неделю @{second_user_name}. " \
f"Вы оба хотели {meeting_format}.\n\n" \
f"Вы хотели {meeting_format}.\n\n" \
f"Можно начать разговор с обсуждения интересов собеседника: {second_user_bio}"
)
await context.bot.send_photo(
Expand Down
7 changes: 5 additions & 2 deletions src/handlers/profile_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
# Conversation handlers

async def profile_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
query = update.callback_query
await query.answer()

await context.bot.send_chat_action(chat_id=update.effective_chat.id, action=ChatAction.TYPING)

logging.info('Member is fine, show keyboard..')
Expand Down Expand Up @@ -101,7 +104,7 @@ async def meeting_format_handler(update: Update, context: CallbackContext) -> in
new_keyboard = [[KeyboardButton(text='Поделиться локацией', request_location=True)]]
await context.bot.send_message(
chat_id=update.effective_user.id,
text='Где ты находишься? В локации будут использованы только страна и город',
text='Где ты находишься? Нажми кнопку "Поделиться локацией" снизу. \n\nИз локации будут использованы только страна и город',
reply_markup=ReplyKeyboardMarkup(new_keyboard, one_time_keyboard=True, resize_keyboard=True)
)
return FillProfileCallback.city
Expand Down Expand Up @@ -178,5 +181,5 @@ async def update_user_in_db(update, context):
db_helper.update_user_profile(user)

await update.message.reply_text(
"Записано, жди понедельника!"
"Записано, жди понедельника! Можно вызвать меню, чтобы отредактировать профиль, поставить на паузу или оставить отзыв"
)
2 changes: 1 addition & 1 deletion src/models/static_models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from collections import namedtuple
from dataclasses import dataclass


class Command:
start = 'start'
menu = 'menu'
generate_pairs = 'generate'
cancel = 'cancel'

Expand Down

0 comments on commit 20d9d2e

Please sign in to comment.