Skip to content

Commit

Permalink
/force_counter, command handling simplified
Browse files Browse the repository at this point in the history
  • Loading branch information
lavadk committed Apr 12, 2021
1 parent b55899c commit a16a490
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 135 deletions.
34 changes: 10 additions & 24 deletions liker/command/handler_set_reactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,23 @@ def get_cards(self) -> Iterable[CommandCard]:
is_admin=False),
]

def handle(self,
sender_chat_id,
sender_message: Message,
args: Namespace):
if args.command == '/set_reactions':
channel_id = args.channel_id
if channel_id is None:
self.telegram_bot.send_text(chat_id=sender_chat_id,
text='--channel_id required')
return

reactions = args.reactions
if (reactions is None) or (len(reactions) == 0):
self.telegram_bot.send_text(chat_id=sender_chat_id,
text='--reactions required')
return
def handle(self, context: CommandContext):
if context.command == '/set_reactions':
channel_id = context.get_mandatory_arg('channel_id')
reactions = context.get_mandatory_arg('reactions')

if not telegram_bot_utils.is_proper_chat_id(channel_id):
self.telegram_bot.send_text(chat_id=sender_chat_id,
text='channel_id should be a number or start from @')
context.reply('channel_id should be a number or start from @',
log_level=logging.INFO)
return

set_successfully = self.enabling_manager.try_set_reactions(channel_id=channel_id,
reactions=reactions,
reply_to_chat_id=sender_chat_id)
reply_context=context)
if not set_successfully:
return

logger.info(f'set_reactions {channel_id}, {reactions}')
self.telegram_bot.send_text(chat_id=sender_chat_id,
text=f'for {channel_id} reactions are {reactions}')
context.reply(f'for {channel_id} reactions are {reactions}',
log_level=logging.INFO)
else:
raise ValueError(f'Unhandled command: {args.command}')

raise ValueError(f'Unhandled command: {context.command}')
62 changes: 20 additions & 42 deletions liker/command/handler_take_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,52 +19,29 @@ def get_cards(self) -> Iterable[CommandCard]:
is_admin=True),
]

def handle(self,
sender_chat_id,
sender_message: Message,
args: Namespace):
if args.command == '/take_messages':
channel_id = args.channel_id
if channel_id is None:
self.telegram_bot.send_text(chat_id=sender_chat_id,
text='--channel_id required')
return

prev_bot_token = args.bot_token
if prev_bot_token is None:
self.telegram_bot.send_text(chat_id=sender_chat_id,
text='--bot_id required')
return

from_message_id = args.message_id
if from_message_id is None:
self.telegram_bot.send_text(chat_id=sender_chat_id,
text='--message_id required')
return

n_backward_messages = args.n

if n_backward_messages is None:
n_backward_messages = 1
def handle(self, context: CommandContext):
if context.command == '/take_messages':
channel_id = context.get_mandatory_arg('channel_id')
prev_bot_token = context.get_mandatory_arg('bot_token')
from_message_id = context.get_mandatory_arg('message_id')
n_backward_messages = context.get_optional_arg('n', default=1)

arr_messages = self.telegram_api.get_chat_messages_backward(chat_id=channel_id,
message_id=from_message_id,
n_messages=n_backward_messages)
n_messages = len(arr_messages)
period = 60 / self.config['channel_rate_per_minute']
period = 60 / context.config['channel_rate_per_minute']
response_text = f'There are {n_messages:,} messages, will take approximately {n_messages * period:,.0f} ' \
f'seconds. Bot will not to respond to other commands and buttons clicks till finish'
self.telegram_bot.send_text(chat_id=sender_chat_id,
text=response_text)
context.reply(response_text, log_level=logging.INFO)
n_processed = 0
for msg in arr_messages:
try:
try:
# Verbose
if True:
if (n_processed > 0) and (n_processed % constants.TAKE_MESSAGE_VERBOSE_N == 0):
self.telegram_bot.send_text(chat_id=sender_chat_id,
text=f'Processed {n_processed:,} messages')
context.reply(f'Processed {n_processed:,} messages', log_level=logging.INFO)
n_processed += 1

new_reply_markup = telegram_api_utils.api_to_bot_markup(msg.reply_markup)
Expand All @@ -74,30 +51,31 @@ def handle(self,
message_id=msg.id,
reply_markup=None)
# Modify reply markup by the new bot
self.telegram_bot.bot.edit_message_reply_markup(chat_id=channel_id,
message_id=msg.id,
reply_markup=new_reply_markup)
logger.info(f'Took {channel_id} message {msg.id}, will sleep for {period:.1f} seconds')
context.telegram_bot.bot.edit_message_reply_markup(chat_id=channel_id,
message_id=msg.id,
reply_markup=new_reply_markup)
logger.debug(f'Took {channel_id} message {msg.id}, will sleep for {period:.1f} seconds')
time.sleep(period)
except ApiTelegramException as ex:
logger.exception(ex)
if ex.error_code == telegram_error.TOO_MANY_REQUESTS:
logging.warning(ex)
time.sleep(10)
else:
raise ex
except Exception as ex:
try:
self.telegram_bot.send_text(chat_id=sender_chat_id,
text=f'Error processing message {msg.id}: {str(ex)}')
context.reply(f'Error processing message {msg.id}: {str(ex)}',
log_level=logging.ERROR)
except ApiTelegramException as ex:
logger.exception(ex)
if ex.error_code == telegram_error.TOO_MANY_REQUESTS:
logging.warning(ex)
time.sleep(10)
else:
raise ex

logger.info(f'take_messages done {channel_id}')
self.telegram_bot.send_text(chat_id=sender_chat_id,
text=f'for {channel_id} message(s) were taken')
context.reply(f'for {channel_id} {n_messages} message(s) were taken',
log_level=logging.INFO)
else:
raise ValueError(f'Unhandled command: {args.command}')
raise ValueError(f'Unhandled command: {context.command}')
71 changes: 47 additions & 24 deletions liker/command/handler_update_markup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import inject
import logging
from tengine.command.command_handler import *
from telebot.types import InlineKeyboardMarkup
from telebot.types import InlineKeyboardMarkup, Message
from typing import Tuple
from tengine import CommandMissingArgError

from liker.state.enabled_channels import EnabledChannels
from liker.state.space_state import SpaceState
Expand All @@ -18,27 +20,15 @@ class CommandHandlerUpdateMarkup(CommandHandler):
def get_cards(self) -> Iterable[CommandCard]:
return [CommandCard(command_str='/update_markup',
description='Set buttons according to reactions enabled',
is_admin=False),
is_admin=True),
CommandCard(command_str='/force_counter',
description='Set custom value for the reactions counter',
is_admin=True),
]

def handle(self,
sender_chat_id,
sender_message: Message,
args: Namespace):
if args.command == '/update_markup':
ref_message: Message = sender_message.reply_to_message
if (ref_message is None) or (ref_message.forward_from_chat is None):
self.telegram_bot.send_text(chat_id=sender_chat_id,
text='Send /update_markup in comments to target channel post')
return

channel_id = ref_message.forward_from_chat.id
if not self.enabled_channels.is_enabled(str(channel_id)):
self.telegram_bot.send_text(chat_id=sender_chat_id,
text='Liker is not enabled for the given channel')
return

channel_message_id = ref_message.forward_from_message_id
def handle(self, context: CommandContext):
if context.command == '/update_markup':
channel_id, channel_message_id = self._get_root_message_info(context)
str_trail_markup = self.space_state \
.ensure_channel_state(str(channel_id)) \
.markup_trail \
Expand All @@ -50,9 +40,42 @@ def handle(self,
enabled_reactions=enabled_reactions,
handler=constants.CHANNEL_POST_HANDLER,
case_id='')
self.telegram_bot.bot.edit_message_reply_markup(chat_id=channel_id,
message_id=channel_message_id,
reply_markup=reply_markup)
context.telegram_bot.bot.edit_message_reply_markup(chat_id=channel_id,
message_id=channel_message_id,
reply_markup=reply_markup)
context.reply('Done', log_level=logging.INFO)

elif context.command == '/force_counter':
var_name = context.get_mandatory_arg('name')
var_value_int = context.get_mandatory_arg('value', cast_func=int)

channel_id, channel_message_id = self._get_root_message_info(context)

markup_trail = self.space_state.ensure_channel_state(str(channel_id)).markup_trail
reply_markup_str = markup_trail.try_get(str(channel_message_id))
if reply_markup_str is None:
context.reply('Markup is not cached, press a reaction button first')
return

reply_markup = InlineKeyboardMarkup.de_json(reply_markup_str)
markup_utils.change_reaction_counter(reply_markup, reaction=var_name, value=var_value_int, is_delta=False)
context.telegram_bot.bot.edit_message_reply_markup(chat_id=channel_id,
message_id=channel_message_id,
reply_markup=reply_markup)
context.reply('Done', log_level=logging.INFO)
else:
raise ValueError(f'Unhandled command: {args.command}')
raise ValueError(f'Unhandled command: {context.command}')

def _get_root_message_info(self, context: CommandContext) -> Tuple[int, int]:
ref_message: Message = context.sender_message.reply_to_message
if (ref_message is None) or (ref_message.forward_from_chat is None):
context.reply(f'Send {context.command} in comments to target channel post')
raise CommandMissingArgError(f'Command {context.command} sent not as a reply to channel post')

channel_id = ref_message.forward_from_chat.id
if not self.enabled_channels.is_enabled(str(channel_id)):
context.reply('Liker is not enabled for the given channel')
raise CommandMissingArgError(f'Command {context.command} sent for not enabled channel')

channel_message_id = ref_message.forward_from_message_id
return channel_id, channel_message_id
4 changes: 2 additions & 2 deletions liker/command/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
help_str='Channel id',
param_type=str),
CommandParam(name='--reactions',
help_str='Channel id',
help_str='Reaction array separated with " "',
param_type=str,
nargs='*'),
nargs='+'),
CommandParam(name='--message_id',
help_str='Message id',
param_type=int),
Expand Down
14 changes: 10 additions & 4 deletions liker/custom_markup/channel_post_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import inject
from telebot.apihelper import ApiTelegramException
from telebot.types import InlineKeyboardMarkup
from tengine import Config, TelegramBot, telegram_bot_utils, Hasher, AbuseDetector
from tengine import Config, TelegramBot, telegram_bot_utils, Hasher, AbuseDetector, ReplyContextSuppress
from tengine.telegram.inbox_handler import *

from liker.state.space_state import SpaceState
Expand Down Expand Up @@ -32,7 +32,7 @@ def channel_post(self, channel_post: types.Message) -> bool:
if not self.enabled_channels.is_enabled(str_channel_id):
did_enabled = self.enabling_manager.try_set_reactions(channel_id=channel_id,
reactions=constants.DEFAULT_REACTIONS,
reply_to_chat_id=None)
reply_context=ReplyContextSuppress())
if not did_enabled:
return False
else:
Expand Down Expand Up @@ -89,11 +89,17 @@ def callback_query(self, callback_query: types.CallbackQuery) -> bool:
reaction_hash = self.hasher.trimmed(reaction_id, hash_bytes=constants.REACTION_HASH_BYTES)
channel_state = self.space_state.ensure_channel_state(str(channel_id))
if channel_state.last_reactions.has(reaction_hash):
markup_utils.change_reaction_counter(reply_markup=reply_markup_new, reaction=reaction, delta=-1)
markup_utils.change_reaction_counter(reply_markup=reply_markup_new,
reaction=reaction,
value=-1,
is_delta=True)
channel_state.last_reactions.remove(reaction_hash)
response_to_user = self.config['response_reaction_removed'].format(reaction)
else:
markup_utils.change_reaction_counter(reply_markup=reply_markup_new, reaction=reaction, delta=1)
markup_utils.change_reaction_counter(reply_markup=reply_markup_new,
reaction=reaction,
value=1,
is_delta=True)
channel_state.last_reactions.add(reaction_hash)
response_to_user = self.config['response_reaction_added'].format(reaction)

Expand Down
3 changes: 2 additions & 1 deletion liker/custom_markup/comment_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ def _check_reply_to_channel_post(self, message: types.Message) -> bool:
thread_message_id=thread_message_id)
markup_utils.change_reaction_counter(reply_markup,
reaction=constants.COMMENT_TEXT,
delta=1)
value=1,
is_delta=True)
self.markup_synchronizer.add(channel_id=channel_id,
message_id=channel_message_id,
reply_markup=reply_markup,
Expand Down
23 changes: 13 additions & 10 deletions liker/custom_markup/markup_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,23 @@ def extend_reply_markup(current_markup: Optional[types.InlineKeyboardMarkup],
return markup_from_buttons(buttons_obj)


def change_reaction_counter(reply_markup: types.InlineKeyboardMarkup, reaction: str, delta: int):
def change_reaction_counter(reply_markup: types.InlineKeyboardMarkup, reaction: str, value: int, is_delta: bool):
for btn in iterate_markup_buttons(reply_markup):
if reaction in btn.text:
prefix = btn.text.rstrip('0123456789-')
num_str = btn.text.replace(prefix, '')

num = _num_str_to_number(num_str)
if num is None:
logger.error(f'Cannot parse button reaction state: {btn.text}')
continue
num += delta
num_str = '' if (num == 0) else f'{num}'

t_new = f'{prefix}{num_str}'
if is_delta:
old_num_str = btn.text.replace(prefix, '')
old_num = _num_str_to_number(old_num_str)
if old_num is None:
logger.error(f'Cannot parse button reaction state: {btn.text}')
continue
num = old_num + value
else:
num = value
new_num_str = '' if (num == 0) else f'{num}'

t_new = f'{prefix}{new_num_str}'
btn.text = t_new
return
raise Exception(f'Can not change reaction counter: {reply_markup.to_json()}')
Expand Down
Loading

0 comments on commit a16a490

Please sign in to comment.