134 lines
4.1 KiB
Python
134 lines
4.1 KiB
Python
from telebot import types
|
|
from telebot.async_telebot import Handler, AsyncTeleBot
|
|
from telebot.asyncio_handler_backends import StatesGroup, State, ContinueHandling
|
|
from telebot.types import ReplyKeyboardRemove
|
|
|
|
from account.models import User
|
|
from tg_bot.messages import TGCoreMessage
|
|
from tg_bot.keyboards import TGKeyboards
|
|
from tg_bot.tasks import send_tg_message
|
|
from tg_bot.utils import extract_deep_link
|
|
|
|
|
|
# TODO: step handlers (https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/step_example.py)
|
|
# TODO: state filters
|
|
class BotStates(StatesGroup):
|
|
idle = State()
|
|
send_phone = State()
|
|
|
|
|
|
# Default message handler
|
|
async def default_handler(message: types.Message, bot: AsyncTeleBot):
|
|
cid = message.from_user.id
|
|
|
|
# Set default state for sender
|
|
if await bot.get_state(cid) is None:
|
|
await bot.set_state(cid, BotStates.idle)
|
|
|
|
return ContinueHandling()
|
|
|
|
|
|
# === Command /start ===
|
|
async def start_handler(message: types.Message, bot: AsyncTeleBot):
|
|
cid = message.from_user.id
|
|
|
|
await bot.set_state(cid, BotStates.idle)
|
|
|
|
if not await is_tg_bound_to_user(cid):
|
|
# Send welcome message
|
|
await bot.send_message(cid, TGCoreMessage.START)
|
|
referral_code = extract_deep_link(message.text)
|
|
|
|
# Save referral code in chat context for later usage
|
|
# TODO: use base64-encoded hash here for additional data maybe?
|
|
async with bot.retrieve_data(cid) as data:
|
|
data['referral_code'] = referral_code
|
|
|
|
# Ask for phone number to bind to User
|
|
await request_phone(cid, TGCoreMessage.SHARE_PHONE, bot)
|
|
|
|
else:
|
|
# TODO: if user is signed in, send help text or account info instead
|
|
await bot.send_message(cid, TGCoreMessage.ALREADY_AUTH)
|
|
|
|
|
|
# TODO: implement sometime in the future
|
|
# === Command /add_phone ===
|
|
# async def add_phone_handler(message: types.Message, bot: AsyncTeleBot):
|
|
# cid = message.from_user.id
|
|
# await request_phone(cid, bot, TGCoreMessage.SHARE_PHONE)
|
|
|
|
|
|
async def is_tg_bound_to_user(tg_user_id):
|
|
return await User.objects.filter(tg_user_id=tg_user_id, phone__isnull=False).aexists()
|
|
|
|
|
|
async def request_phone(user_id, text, bot: AsyncTeleBot):
|
|
""" Ask for phone number to bind to User """
|
|
reply_markup = TGKeyboards.SHARE_PHONE
|
|
|
|
await bot.set_state(user_id, BotStates.send_phone)
|
|
await bot.send_message(user_id, text, reply_markup=reply_markup)
|
|
|
|
|
|
def request_phone_sync(user_id, text):
|
|
state = BotStates.send_phone
|
|
reply_markup = TGKeyboards.SHARE_PHONE
|
|
|
|
send_tg_message(user_id, text, state=state.name, reply_markup=reply_markup)
|
|
|
|
|
|
async def contact_handler(message: types.Message, bot: AsyncTeleBot):
|
|
""" User has sent his phone number to authenticate in bot """
|
|
|
|
cid = message.from_user.id
|
|
|
|
async with bot.retrieve_data(cid) as data:
|
|
await User.objects.bind_tg_user(
|
|
tg_user_id=cid,
|
|
phone=message.contact.phone_number,
|
|
referral_code=data.pop('referral_code', None)
|
|
)
|
|
await bot.send_message(cid, TGCoreMessage.AUTH_SUCCESS, reply_markup=ReplyKeyboardRemove())
|
|
|
|
await bot.set_state(cid, BotStates.idle)
|
|
|
|
|
|
def get_handlers():
|
|
return [
|
|
Handler(callback=default_handler),
|
|
Handler(callback=start_handler, commands=['start'], state=BotStates.idle),
|
|
# Handler(callback=add_phone_handler, commands=['add_phone']),
|
|
Handler(callback=contact_handler,
|
|
content_types=['contact'],
|
|
state=BotStates.send_phone,
|
|
func=lambda m: m.from_user.id == m.contact.user_id # Disallow contact forwarding
|
|
),
|
|
]
|
|
|
|
|
|
"""
|
|
- backend: try to find User with tg_user_id of Message
|
|
- no User found -> ask for phone
|
|
|
|
Possible situations:
|
|
1) No user in db:
|
|
- tg: ask for phone
|
|
- backend: create draft user
|
|
- web: login via tg ->
|
|
|
|
2) User exists in DB, but has no phone (phone deleted in web)
|
|
- tg: ask for phone
|
|
- find User with tg_user_id & add phone
|
|
|
|
3) User exists in DB, but no tg_user_id or phone ???
|
|
|
|
"""
|
|
|
|
"""
|
|
Options:
|
|
- login via telegram -> find User with tg_user_id -> if found, login
|
|
- send contact from bot -> find user with phone -> add tg_user_id to User
|
|
-
|
|
"""
|