def ether(self, bot, update): """ Call for Ether miner status and restarting service. """ chat_id = update.message.chat.id bot.send_chat_action(chat_id=chat_id, action=ChatAction.TYPING) try: Chat.get(id=chat_id) except peewee.DoesNotExist: self.logger.error('Chat unregistered') response_text = 'Configure me first' bot.send_message(chat_id, response_text) else: keyboard = [ [ InlineKeyboardButton("Status", callback_data='[ether_status]'), InlineKeyboardButton("Nanopool", callback_data='[ether_nanopool]') ], [ InlineKeyboardButton("Restart", callback_data='[ether_restart]'), ], ] reply_markup = InlineKeyboardMarkup(keyboard) bot.send_message(chat_id, 'Select an option:', reply_markup=reply_markup)
def miner(self, bot, update): """ Asks for a miner. """ chat_id = update.message.chat.id bot.send_chat_action(chat_id=chat_id, action=ChatAction.TYPING) try: chat = Chat.get(id=chat_id) buttons = [ InlineKeyboardButton(api.name, callback_data=f'[miner_status][{api.id}]') for api in chat.apis if api.superuser ] keyboard = [ buttons[i:max(len(buttons), i + 4)] for i in range(0, len(buttons), 4) ] reply_markup = InlineKeyboardMarkup(keyboard) except peewee.DoesNotExist: self.logger.error('Chat unregistered') response_text = 'Configure me first' bot.send_message(chat_id, response_text) else: if reply_markup: bot.send_message(text='Select miner:', reply_markup=reply_markup, chat_id=chat_id) else: bot.send_message(text='No options available', chat_id=chat_id)
def wallet_job_transactions(self, bot, job): """ Check last transaction and notify if there are new payments. """ self.logger.debug('Job: Check transactions') for chat in Chat.select(): api = random.choice(chat.apis) data = Barrenero.wallet(api.url, api.token) try: self.logger.debug('Current transaction: %s', str(chat.last_transaction)) self.logger.debug('Retrieved transactions: %s', str(data['transactions'])) first_transaction_hash = data['transactions'][0]['hash'] if not chat.last_transaction: # If last transaction is unknown, simply update it chat.last_transaction = first_transaction_hash else: # Show transactions until last known for tx in takewhile(lambda x: x['hash'] != chat.last_transaction, data['transactions']): text = f'\n\n*Transaction completed*\n' \ f' - Token: `{tx["token"]["name"]}`\n' \ f' - Value: `{tx["value"]} {tx["token"]["symbol"]}`\n' \ f' - Date: `{humanize_iso_date(tx["timestamp"])}`' bot.send_message(text=text, parse_mode=ParseMode.MARKDOWN, chat_id=chat.id) chat.last_transaction = first_transaction_hash chat.save() except (KeyError, IndexError): self.logger.debug('No transactions found for Chat %s', chat.id) time.sleep(1)
def _remove_api_choice(self, bot, update): """ Asks for removing a Barrenero API already configured. """ chat_id = update.message.chat_id try: chat = Chat.get(id=chat_id) except peewee.DoesNotExist: update.message.reply_text( 'There is not a Barrenero API configured yet') result = self.start(bot, update) else: buttons = [str(i.id) for i in chat.apis] keyboard = [ buttons[i:min(len(buttons), i + 4)] for i in range(0, len(buttons), 4) ] keyboard.append([StartOptions.DONE.value]) markup = ReplyKeyboardMarkup(keyboard, one_time_keyboard=True) response_text = f'*APIs configured*\n' + '\n'.join( [f'*{a.id}*: `{a.url}`' for a in chat.apis]) update.message.reply_text(response_text, parse_mode=ParseMode.MARKDOWN, reply_markup=markup) result = StartState.CHOICE_REMOVE_API return result
def _add_api_config_done(self, bot, update): """ Adds configured api. """ chat_id = update.message.chat_id try: chat, _ = Chat.get_or_create(id=chat_id, defaults={'last_transaction': None}) config = Barrenero.get_token_or_register( url=self.tmp_config[chat_id]['url'], username=self.tmp_config[chat_id]['username'], password=self.tmp_config[chat_id]['password'], account=self.tmp_config[chat_id]['wallet'], api_password=self.tmp_config[chat_id]['api_password'], ) API.create(name=self.tmp_config[chat_id]['name'], url=self.tmp_config[chat_id]['url'], token=config['token'], superuser=config['superuser'], chat=chat) except: self.logger.exception('Cannot register Barrenero API') update.message.reply_text('Cannot register Barrenero API') else: update.message.reply_text('Api stored successfully') return self.start(bot, update)
def cmd_alias(self, _, update): chat = Chat.from_tg(update.message.chat) ret = '\n'.join('%s. %s → %s' % (alias.id, alias.regexp, alias.replace) for alias in chat.aliases) if not ret: ret = 'no aliases' return ret, True
def wallet(self, bot, update): """ Call for Storj miner status and restarting service. """ chat_id = update.message.chat.id bot.send_chat_action(chat_id=chat_id, action=ChatAction.TYPING) try: chat = Chat.get(id=chat_id) api = random.choice(chat.apis) data = Barrenero.wallet(api.url, api.token) response_text = f'*Tokens*\n' response_text += '\n'.join( [f' - {t["name"]}: `{t["balance"]} {t["symbol"]}` ({t.get("balance_usd", "Unknown")} $)' for t in data['tokens'].values()]) for i, tx in zip(range(1, 4), data['transactions']): response_text += f'\n\n*Last transaction #{i}*\n' \ f' - Token: `{tx["token"]["name"]}`\n' \ f' - Hash: `{tx["hash"]}`\n' \ f' - Source: `{tx["source"]}`\n' \ f' - Value: `{tx["value"]} {tx["token"]["symbol"]}`\n' \ f' - Date: `{humanize_iso_date(tx["timestamp"])}`' except peewee.DoesNotExist: self.logger.error('Chat unregistered') response_text = 'Configure me first' except BarreneroRequestException as e: self.logger.exception(e.message) response_text = e.message except: self.logger.exception('Error retrieving wallet info') response_text = 'Cannot retrieve wallet info' bot.send_message(chat_id, response_text, parse_mode=ParseMode.MARKDOWN)
def cmd_settings(self, _, update): chat = Chat.from_tg(update.message.chat) reply = ('settings:\n' ' context: %s\n' ' markov chain order: %s\n' ' learn: %s\n' ' trigger: %s\n' ' max reply length: %s\n') % ( chat.context, chat.order, bool( chat.learn), chat.trigger, chat.reply_max_length) return reply
def cb_learn_mode(self, _, update): query = update.callback_query chat = Chat.from_tg(query.message.chat) learn = query.data.lower() == 'on' self.logger.info('set_learn %s %s', chat.id, learn) context = self.state.get_chat_context(chat) if learn and not context.is_writable: raise CommandError('context %s is read only' % context) prev = bool(chat.learn) chat.learn = int(learn) return 'learn: %s -> %s' % (prev, learn)
def cb_delete_private_context(self, _, update): query = update.callback_query chat = query.message.chat if query.data.lower() == 'yes': chat = Chat.from_tg(chat) context = chat.context if context == str(chat.id): chat.context = None self.state.context.delete_private(chat) return 'deleted private context "%s"' % chat.id return 'cancelled'
def allow_chat(bot, update, args): if args: chat_id = args[0] chat = bot.get_chat(chat_id) session = create_session(bind=engine) session.add(Chat(id=chat_id, title=chat.title)) session.commit() session.close() msg = 'Allowed wisdom posting at chat with id "{}"'.format(chat_id) else: msg = 'Empty chat_id, please place chat_id after command' update.message.reply_text(msg)
def cb_order(self, _, update): query = update.callback_query chat = query.message.chat order = int(query.data) self.logger.info('set_order %s %s', chat.id, order) chat = Chat.from_tg(chat) context = self.state.get_chat_context(chat) if order not in context.get_orders(): raise CommandError('invalid order: %s: not in %s' % (order, context.get_orders())) prev = chat.order chat.order = order return 'order: %s -> %s' % (prev, order)
def _save_chat(self): # Create or get the chat where the link was sent chat, was_created = Chat.get_or_create( id=self.update.message.chat_id, defaults={ 'name': self.update.message.chat.title or self.update.message.chat.username or self.update.message.chat.first_name }) if was_created: Logger.log_db_operation(Logger.DBOperation.CREATE, chat) return chat
def cmd_aadd(self, _, update): help_ = 'usage: /aadd <regexp>=<string>' args = get_command_args(update.message, help=help_) match = self.RE_ALIAS.match(args) if match is None: return help_ expr, repl = match.groups() expr = expr.strip() repl = repl.strip() re.compile(expr) chat = Chat.from_tg(update.message.chat) Alias(chat=chat, regexp=expr, replace=repl) return 'done'
def cmd_setreplylength(self, _, update): message = update.message length = strip_command(message.text) if not length: raise CommandError('usage: /setreplylength <number>') try: length = max(8, min(int(length), 256)) except ValueError as ex: raise CommandError(ex) chat = Chat.from_tg(message.chat) prev = chat.reply_max_length chat.reply_max_length = length return 'max reply length: %d -> %d' % (prev, length)
class DataMiddleware(BaseMiddleware): @staticmethod async def setup_chat(data: dict, user: types.User, chat: Optional[types.Chat] = None): user_id = int(user.id) chat_id = int(chat.id) chat_type = chat.type if chat else "private" session: AsyncSession = data["session"] if not (user := await session.get(User, user_id)): session.add(user := User(id=user_id)) if not (chat := await session.get(Chat, chat_id)): session.add(chat := Chat(id=chat_id, type=chat_type))
def cmd_settrigger(self, _, update): message = update.message expr = strip_command(message.text) if not expr: raise CommandError('usage: /settrigger <regexp>') else: try: re.compile(expr) except re.error as ex: raise CommandError(ex) chat = Chat.from_tg(message.chat) prev = chat.trigger chat.trigger = expr return 'trigger: %s -> %s' % (prev, expr)
def get_chat_by_telegram_id(telegram_chat_id: int, update_last_used_at: bool, source: str) -> Chat: chat = Chat.get_by_telegram_id(telegram_chat_id) if chat is None: chat = Chat(telegram_id=telegram_chat_id, last_used_at=now(), source=source) if update_last_used_at: chat.last_used_at = now() chat.save() return chat
def _remove_api_config(self, bot, update): text = update.message.text chat_id = update.message.chat_id try: chat = Chat.get(id=chat_id) api = API.get(id=text, chat=chat) name = api.name api.delete_instance() update.message.reply_text( f'Barrenero API `{name}` removed successfully', parse_mode=ParseMode.MARKDOWN) except: self.logger.exception('Cannot remove Barrenero API') update.message.reply_text('Cannot remove Barrenero API') return StartState.CHOICE_REMOVE_API
def cmd_unsetcontext(self, _, update): chat = update.message.chat self.logger.info('unset_context %s', chat.id) chat = Chat.from_tg(chat) prev_context = chat.context prev_order = chat.order prev_learn = chat.learn chat.context = None chat.order = 0 chat.learn = False return 'context: %s -> %s\norder: %s -> %s\nlearn: %s -> %s' % ( prev_context, chat.context, prev_order, chat.order, bool(prev_learn), bool(chat.learn))
def ether_nanopool(self, bot, update): """ Query for Nanopool account info. """ query = update.callback_query chat_id = query.message.chat_id bot.send_chat_action(chat_id=chat_id, action=ChatAction.TYPING) try: chat = Chat.get(id=chat_id) api = random.choice(chat.apis) data = Barrenero.ether(api.url, api.token) response_text = f'*Ether miner*\n' \ f' - Balance: `{data["nanopool"]["balance"]["confirmed"]} ETH`\n\n' \ f'*Hashrate*\n' \ f' - Current: `{data["nanopool"]["hashrate"]["current"]} MH/s`\n' \ f' - 1 hour: `{data["nanopool"]["hashrate"]["one_hour"]} MH/s`\n' \ f' - 3 hours: `{data["nanopool"]["hashrate"]["three_hours"]} MH/s`\n' \ f' - 6 hours: `{data["nanopool"]["hashrate"]["six_hours"]} MH/s`\n' \ f' - 12 hours: `{data["nanopool"]["hashrate"]["twelve_hours"]} MH/s`\n' \ f' - 24 hours: `{data["nanopool"]["hashrate"]["twenty_four_hours"]} MH/s`\n\n' \ f'*Last payment*\n' \ f' - Date: `{humanize_iso_date(data["nanopool"]["last_payment"]["date"])}`\n' \ f' - Value: `{data["nanopool"]["last_payment"]["value"]} ETH`\n\n' \ f'*Workers*\n' + \ '\n'.join(f' - {w}: `{v} MH/s`' for w, v in data['nanopool']['workers'].items()) except peewee.DoesNotExist: self.logger.error('Chat unregistered') response_text = 'Configure me first' except BarreneroRequestException as e: self.logger.exception(e.message) response_text = e.message except: response_text = 'Cannot retrieve Nanopool info' self.logger.exception( 'Barrenero API wrong response for Nanopool info: %s', str(data)) bot.edit_message_text(text=response_text, parse_mode=ParseMode.MARKDOWN, chat_id=query.message.chat_id, message_id=query.message.message_id)
def _current_config_choice(self, bot, update): """ Shows current config. """ chat_id = update.message.chat_id try: chat = Chat.get(id=chat_id) except peewee.DoesNotExist: response_text = 'No configuration found' else: response_text = f'*Current config*\n' \ f' - Last Transaction: `{chat.last_transaction}`\n\n' for i, api in enumerate(chat.apis, 1): response_text += f'*API #{i}*\n' \ f' - Name: `{api.name}`\n' \ f' - URL: `{api.url}`\n' \ f' - Token: `{api.token}`\n' \ f' - Superuser: `{"Yes" if api.superuser else "No"}`\n\n' update.message.reply_text(response_text, parse_mode=ParseMode.MARKDOWN) return StartState.CHOICE_ROOT
def cb_context(self, _, update): query = update.callback_query chat = query.message.chat name = query.data self.logger.info('set_context %s %s', chat.id, name) chat = Chat.from_tg(chat) prev_context = chat.context prev_order = chat.order prev_learn = chat.learn if name == 'new private context': self.logger.info('creating private context %s', chat.id) context = self.state.context.get_private(chat) name = context.name learn = True else: context = self.state.context.get(name) learn = prev_learn if not context.is_writable: learn = False orders = context.get_orders() if prev_order not in orders: order = next(iter(orders)) else: order = prev_order chat.context = name chat.order = order chat.learn = learn return 'context: %s -> %s\norder: %s -> %s\nlearn: %s -> %s' % ( prev_context, name, prev_order, order, bool(prev_learn), bool(learn))
def ether_miner_choice(self, bot, update, groups): """ Call for Ether miner status and restarting service. """ query = update.callback_query action = groups[0] chat_id = query.message.chat_id bot.send_chat_action(chat_id=chat_id, action=ChatAction.TYPING) try: chat = Chat.get(id=chat_id) except peewee.DoesNotExist: chat = False if chat: buttons = [ InlineKeyboardButton( api.name, callback_data=f'[ether_{action}][{api.id}]') for api in chat.apis if api.superuser ] keyboard = [ buttons[i:max(len(buttons), i + 4)] for i in range(0, len(buttons), 4) ] reply_markup = InlineKeyboardMarkup(keyboard) else: reply_markup = None if reply_markup: bot.edit_message_text(text='Select miner:', reply_markup=reply_markup, chat_id=chat_id, message_id=query.message.message_id) else: bot.edit_message_text(text='No options available', chat_id=chat_id, message_id=query.message.message_id)
def cmd_unsettrigger(self, _, update): chat = Chat.from_tg(update.message.chat) prev = chat.trigger chat.trigger = None return 'trigger: %s -> None' % prev
def cmd_aclear(self, _, update): chat = Chat.from_tg(update.message.chat) delete(a for a in Alias if a.chat == chat) return 'done'