def try_message(context,
                chat_id,
                text,
                reply_markup=None,
                remove_job_when_blocked=True):
    """
    Send a message to a user.
    """

    try:
        context.bot.send_message(chat_id,
                                 text,
                                 parse_mode='markdown',
                                 reply_markup=reply_markup,
                                 disable_web_page_preview=True)
    except TelegramError as e:
        if 'bot was blocked by the user' in e.message:
            logger.info("Telegram user " + str(chat_id) +
                        " blocked me; removing him from the user list")
            del context.dispatcher.user_data[chat_id]
            del context.dispatcher.chat_data[chat_id]
            del context.dispatcher.persistence.user_data[chat_id]
            del context.dispatcher.persistence.chat_data[chat_id]

            # Somehow session.data does not get updated if all users block the bot.
            # That makes problems on bot restart. That's why we delete the file ourselves.
            if len(context.dispatcher.persistence.user_data
                   ) == 0 and os.path.exists("./storage/session.data"):
                os.remove("./storage/session.data")

            if remove_job_when_blocked:
                context.job.schedule_removal()
        else:
            logger.error(e, exc_info=True)
            logger.info("Telegram user " + str(chat_id))
def on_show_active_proposals_clicked(update, context):
    query = update.callback_query
    _ = query.data.split("-")

    try:
        active_proposals = get_active_proposals()
    except Exception as e:
        logger.error(e, exc_info=True)
        try_message(context=context,
                    chat_id=query['message']['chat']['id'],
                    text=NETWORK_ERROR_MSG)
        return

    title = '🗳 ✅ *Active proposals*🗳 ✅ \n' \
            'Click on any of the proposals to see details and vote options.\n\n'

    def button_builder(proposal_title: str,
                       proposal_id: str) -> InlineKeyboardButton:
        return InlineKeyboardButton(proposal_title,
                                    callback_data=f'proposal-{proposal_id}-1'
                                    )  # 1 - open read and vote view

    _display_proposals(proposals=active_proposals,
                       query=query,
                       title=title,
                       button_builder=button_builder)
def on_proposal_clicked(update, context):
    query = update.callback_query
    _, proposal_id, votable = query.data.split("-")
    votable = int(votable)
    previous_view = 'proposals_show_active' if votable else 'proposals_show_all'

    try:
        proposal = get_proposal(int(proposal_id))
        context.user_data.setdefault('proposals_cache', {})[proposal_id] = {
            'title': proposal['content']['value']['title']
        }
    except Exception as e:
        logger.error(e)
        query.edit_message_text(NETWORK_ERROR_MSG)
        return

    keyboard = [[
        InlineKeyboardButton(BACK_BUTTON_MSG, callback_data=previous_view)
    ]]
    my_wallet = context.user_data['proposals_cache'].get('wallet', None)
    my_vote = None

    if my_wallet:
        my_vote = get_vote(wallet_addr=my_wallet, proposal_id=proposal_id)

    message = ''
    if my_wallet and my_vote:
        message += f'🎉 You voted *{my_vote}* 🎉'
    else:
        if votable:
            keyboard = [
                [
                    InlineKeyboardButton(
                        '✅ Yes',
                        callback_data=f'vote-{proposal_id}-{MsgVote.YES}'),
                    InlineKeyboardButton(
                        '❌ No',
                        callback_data=f'vote-{proposal_id}-{MsgVote.NO}'),
                ],
                [
                    InlineKeyboardButton(
                        '❌❌ No with veto',
                        callback_data=
                        f'vote-{proposal_id}-{MsgVote.NO_WITH_VETO}'),
                    InlineKeyboardButton(
                        '🤷 Abstain',
                        callback_data=f'vote-{proposal_id}-{MsgVote.ABSTAIN}'),
                ],
                [
                    InlineKeyboardButton(BACK_BUTTON_MSG,
                                         callback_data='proposals_show_active')
                ]
            ]

    message += f"\n\n\n{proposal_to_text(proposal)}"

    query.edit_message_text(message,
                            parse_mode='markdown',
                            reply_markup=InlineKeyboardMarkup(keyboard))
def send_slack_message(text):
    if SLACK_WEBHOOK:
        try:
            requests.post(SLACK_WEBHOOK,
                          data=json.dumps({'text': text}),
                          headers={'Content-Type': 'application/json'})
        except RequestException as e:
            logger.error(f"Slack Webhook post request failed with:\n{e}")
Beispiel #5
0
def check_governance_proposals(context):
    """
    Monitoring related to governance proposals
    """

    try:
        governance_proposals = get_governance_proposals()
    except ConnectionError as e:
        logger.error(e)
        return

    check_new_goverance_proposal(context, governance_proposals)
    check_results_of_proposals(context, governance_proposals)
Beispiel #6
0
def check_sentry_node_status(node_ip, sentry_nodes_data) -> [None, str]:
    try:
        is_currently_syncing = is_syncing(node_ip)
    except Exception as e:
        logger.error(e)
        return None

    was_syncing = sentry_nodes_data.setdefault(node_ip, {}).setdefault('syncing', False)

    if was_syncing != is_currently_syncing:
        sentry_nodes_data[node_ip]['syncing'] = is_currently_syncing

        if is_currently_syncing:
            text = NODE_STARTED_SYNCING_MSG.format(node_ip)
        else:
            text = NODE_FINISHED_SYNCING_MSG.format(node_ip)

        return text
    else:
        return None
def setup_existing_user(dispatcher):
    """
    Tasks to ensure smooth user experience for existing users upon Bot restart
    """

    chat_ids = dispatcher.user_data.keys()
    delete_chat_ids = []
    for chat_id in chat_ids:
        try:
            dispatcher.bot.send_message(chat_id, BOT_RESTARTED_MSG)
            dispatcher.job_queue.run_repeating(
                node_checks,
                interval=JOB_INTERVAL_IN_SECONDS,
                context={
                    'chat_id': chat_id,
                    'user_data': dispatcher.user_data[chat_id]
                })
        except TelegramError as e:
            if 'bot was blocked by the user' in e.message:
                delete_chat_ids.append(chat_id)
                continue
            else:
                logger.error("Got Error\n" + str(e) + "\nwith telegram user " +
                             str(chat_id))

    for chat_id in delete_chat_ids:
        logger.info("Telegram user " + str(chat_id) +
                    " blocked me; removing him from the user list")
        del dispatcher.user_data[chat_id]
        del dispatcher.chat_data[chat_id]
        del dispatcher.persistence.user_data[chat_id]
        del dispatcher.persistence.chat_data[chat_id]

        # Somehow session.data does not get updated if all users block the bot.
        # That's why we delete the file ourselves.
        if len(dispatcher.persistence.user_data) == 0 and os.path.exists(
                session_data_path):
            os.remove(session_data_path)