Skip to content

Commit

Permalink
Merge pull request #54 from milselarch/feat/update_voter_count_for_we…
Browse files Browse the repository at this point in the history
…bapp_votes

feat: update voter count from webapp response
  • Loading branch information
milselarch authored Dec 17, 2024
2 parents f2e5178 + efb145c commit c0196a1
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 15 deletions.
39 changes: 30 additions & 9 deletions base_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from strenum import StrEnum
from requests import PreparedRequest

from helpers.constants import BLANK_ID
from helpers.start_get_params import StartGetParams
from helpers import constants, strings
from helpers.strings import generate_poll_closed_message
Expand Down Expand Up @@ -664,7 +665,20 @@ def generate_poll_message(
)

@classmethod
def generate_poll_url(cls, poll_id: int, tele_user: TeleUser) -> str:
def generate_poll_url(
cls, poll_id: int, tele_user: TeleUser,
ref_message_id: int = BLANK_ID, ref_chat_id: int = BLANK_ID
) -> str:
"""
:param poll_id:
poll to vote for
:param tele_user:
telegram user information
:param ref_message_id:
telegram chat message id of the originating poll message
:param ref_chat_id:
telegram chat id of the originating poll message
"""
req = PreparedRequest()
auth_date = str(int(time.time()))
query_id = cls.generate_secret()
Expand All @@ -676,26 +690,31 @@ def generate_poll_url(cls, poll_id: int, tele_user: TeleUser) -> str:
data_check_string = cls.make_data_check_string(
auth_date=auth_date, query_id=query_id, user=user_info
)
validation_hash = cls.sign_data_check_string(
data_check_string=data_check_string
)
validation_hash = cls.sign_data_check_string(data_check_string)
ref_info = f'{auth_date}:{poll_id}:{ref_message_id}:{ref_chat_id}'
ref_hash = cls.sign_data_check_string(ref_info)

params = {
'poll_id': str(poll_id),
'auth_date': auth_date,
'query_id': query_id,
'user': user_info,
'hash': validation_hash
'hash': validation_hash,

'ref_info': ref_info,
'ref_hash': ref_hash
}
req.prepare_url(WEBHOOK_URL, params)
return req.url

@classmethod
def build_private_vote_markup(
cls, poll_id: int, tele_user: TeleUser
cls, poll_id: int, tele_user: TeleUser,
ref_message_id: int = BLANK_ID, ref_chat_id: int = BLANK_ID
) -> List[List[KeyboardButton]]:
poll_url = cls.generate_poll_url(
poll_id=poll_id, tele_user=tele_user
poll_id=poll_id, tele_user=tele_user,
ref_message_id=ref_message_id, ref_chat_id=ref_chat_id
)
logger.warning(f'POLL_URL = {poll_url}')
# create vote button for reply message
Expand Down Expand Up @@ -1321,14 +1340,16 @@ def __unsafe_register_vote(
@classmethod
def generate_vote_markup(
cls, tele_user: TeleUser | None, chat_type: str,
poll_id: int, open_registration: bool, num_options: int
poll_id: int, open_registration: bool, num_options: int,
ref_message_id: int = BLANK_ID, ref_chat_id: int = BLANK_ID
) -> None | ReplyKeyboardMarkup | InlineKeyboardMarkup:
reply_markup = None
print('CHAT_TYPE', chat_type)
if chat_type == 'private':
# create vote button for reply message
vote_markup_data = cls.build_private_vote_markup(
poll_id=poll_id, tele_user=tele_user
poll_id=poll_id, tele_user=tele_user,
ref_message_id=ref_message_id, ref_chat_id=ref_chat_id
)
reply_markup = ReplyKeyboardMarkup(vote_markup_data)
elif open_registration:
Expand Down
30 changes: 29 additions & 1 deletion bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from handlers.payment_handlers import PaymentHandlers
from handlers.start_handlers import start_handlers
from helpers.commands import Command
from helpers.constants import BLANK_ID
from helpers.locks_manager import PollsLockManager
from helpers.message_buillder import MessageBuilder
from logging import handlers as log_handlers
from datetime import datetime
Expand Down Expand Up @@ -267,7 +269,9 @@ async def post_init(self, _: Application):
)])

@track_errors
async def web_app_handler(self, update: ModifiedTeleUpdate, _):
async def web_app_handler(
self, update: ModifiedTeleUpdate, context: ContextTypes.DEFAULT_TYPE
):
# TODO: update reference poll message with latest voter count
message: Message = update.message
payload = json.loads(update.effective_message.web_app_data.data)
Expand Down Expand Up @@ -306,6 +310,30 @@ async def web_app_handler(self, update: ModifiedTeleUpdate, _):
message=message, poll_id=poll_id
)

ref_info = payload.get('ref_info', str(BLANK_ID))
ref_hash = payload.get('ref_hash', '')
# print('REFS', ref_info, ref_hash)
signed_ref_info = BaseAPI.sign_data_check_string(ref_info)
if signed_ref_info != ref_hash:
# print('REJECT_HASH')
return

# update the poll voter count in the originating poll message
_, raw_poll_id, raw_ref_msg_id, raw_ref_chat_id = ref_info.split(':')

poll_id = int(raw_poll_id)
ref_msg_id = int(raw_ref_msg_id)
ref_chat_id = int(raw_ref_chat_id)
if (ref_msg_id == BLANK_ID) or (ref_chat_id == BLANK_ID):
return

poll_info = BaseAPI.unverified_read_poll_info(poll_id=poll_id)
await TelegramHelpers.update_poll_message(
poll_info=poll_info, chat_id=ref_chat_id,
message_id=ref_msg_id, context=context,
poll_locks_manager=PollsLockManager()
)

@track_errors
async def handle_unknown_command(self, update: ModifiedTeleUpdate, _):
await update.message.reply_text("Command not found")
Expand Down
5 changes: 4 additions & 1 deletion handlers/chat_context_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ async def handle_messages(
tele_user: TeleUser = update.message.from_user
bot_username = context.bot.username
vote_context = vote_context_res.unwrap()
ref_message_id = vote_context.ref_message_id
ref_chat_id = vote_context.ref_chat_id

if is_from_start:
"""
Expand Down Expand Up @@ -254,7 +256,8 @@ async def handle_messages(
reply_markup = BaseAPI.generate_vote_markup(
tele_user=tele_user, poll_id=poll_id, chat_type='private',
open_registration=poll.open_registration,
num_options=poll_message.poll_info.max_options
num_options=poll_message.poll_info.max_options,
ref_message_id=ref_message_id, ref_chat_id=ref_chat_id
)
poll_contents = poll_message.text
await message.reply_text(poll_contents, reply_markup=reply_markup)
Expand Down
3 changes: 2 additions & 1 deletion handlers/inline_keyboard_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,8 @@ async def send_dm(text, markup: Optional[ReplyMarkup] = None):
reply_markup = BaseAPI.generate_vote_markup(
tele_user=tele_user, poll_id=poll_id, chat_type='private',
open_registration=poll.open_registration,
num_options=poll_message.poll_info.max_options
num_options=poll_message.poll_info.max_options,
ref_message_id=message_id, ref_chat_id=current_chat_id
)
# display poll info in chat DMs at the start
poll_contents = poll_message.text
Expand Down
4 changes: 4 additions & 0 deletions handlers/start_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ async def handle_messages(


class StartHandlers(object):
"""
chat context callbacks that get triggered when /start command
is run in telegram DMs
"""
def __init__(self):
self.handlers_mapping: dict[
StartGetParams, Type[BaseMessageHandler]
Expand Down
12 changes: 9 additions & 3 deletions telegram-webapp/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axios, { AxiosResponse } from 'axios';
import axios from 'axios';
// import {ReactComponent as Logo} from './logo.svg';
import './App.scss';
import { MainButton, WebAppProvider } from '@vkruglikov/react-telegram-web-app';
Expand Down Expand Up @@ -83,6 +83,9 @@ function App() {
// const [headers, set_headers] = useState('');
const [has_credential, set_has_credential] = useState(false);
const [poll, set_poll] = useState<Poll | null>(null)
// reference telegram poll message that led to webapp inline prompt
const [ref_info, set_ref_info] = useState<string>("")
const [ref_hash, set_ref_hash] = useState<string>("")
const [loading, set_loading] = useState(false)
const [status, set_status] = useState<string>(null)

Expand Down Expand Up @@ -129,7 +132,8 @@ function App() {
}
// console.log('PAYLOAD', payload)
window.Telegram.WebApp.sendData(JSON.stringify({
'poll_id': poll.metadata.id, 'option_numbers': final_vote_rankings
'poll_id': poll.metadata.id, 'option_numbers': final_vote_rankings,
'ref_info': ref_info, 'ref_hash': ref_hash
}));
}

Expand All @@ -147,6 +151,8 @@ function App() {
const query_params = {};
const params = new URLSearchParams(window.location.search);
params.forEach((value, key) => { query_params[key] = value; });
set_ref_info(query_params['ref_info'] ?? '')
set_ref_hash(query_params['ref_hash'] ?? '')

const poll_id = Number.parseInt(query_params['poll_id'])
if (poll_id === null) {
Expand Down Expand Up @@ -174,7 +180,7 @@ function App() {
} else if (status_code === 401) {
set_status('Unauthorized')
} else {
set_status('Server request failed ;--;')
set_status(`Server request failed (${status_code}) ;--;`)
}
} else {
console.error('Unexpected error:', error);
Expand Down

0 comments on commit c0196a1

Please sign in to comment.