Example #1
0
def process_updating_entry_callback(job_queue: JobQueue, database: Database, finish_time: dt.datetime):
    """
    This callback function will be called, when an Update operation will be occurred in the database.
    """
    jobs = job_queue.jobs()
    entries = database.get_entries(dt.datetime.now(), finish_time)
    for job in jobs:
        if isinstance(job.context, Entry):
            exist = False
            for entry in entries:
                if job.context.note_id == entry.note_id:
                    if job.context.chat_id == entry.chat_id and job.context.name == entry.name:
                        if job.context.entry_date == entry.entry_date:
                            exist = True
                            break
                        else:
                            job.schedule_removal()
                            if entry.entry_date <= finish_time:
                                job_queue.run_once(callback=recall_send_callback,
                                                   when=entry.entry_date,
                                                   context=entry)
                            break
                    else:
                        job.schedule_removal()
                        if entry.entry_date <= finish_time:
                            job_queue.run_once(callback=recall_send_callback,
                                               when=entry.entry_date,
                                               context=entry)
                        break

            if not exist:
                job.schedule_removal()
Example #2
0
def timer_message(job_queue: JobQueue, chat_id, timer, comment):
    job_queue.run_once(send_timer_massage, timer,
                       dict(
                           timer=timer,
                           chat_id=chat_id,
                           comment=comment,
                       ))
Example #3
0
def edit_message(job_queue: JobQueue,
                 chat_id,
                 message_id,
                 text,
                 parse_mode='HTML'):
    job_queue.run_once(
        lambda _: edit_message_task(chat_id, message_id, text, parse_mode), 0)
Example #4
0
def update_round_message(job_queue: JobQueue,
                         game_round: Round,
                         language_code,
                         refresh=False):
    job_queue.run_once(
        lambda _: update_round_message_task(game_round.chat_id, language_code,
                                            refresh), 0)
Example #5
0
def _remove_message_after(message: Message, job_queue: JobQueue, seconds: int):
    logger.debug(
        "Scheduling cleanup of message %s \
                   in %d seconds",
        message,
        seconds,
    )
    job_queue.run_once(lambda _: message.delete(), seconds, context=message.chat_id)
Example #6
0
def error_message(message: telegram.Message, job_queue: JobQueue, text: str):
    delete_time = 15
    sent = message.reply_text('<b>[ERROR]</b> {}'.format(text), parse_mode='HTML')
    context = dict(
        chat_id=message.chat_id,
        message_id_list=(message.message_id, sent.message_id),
    )
    job_queue.run_once(delay_delete_messages, delete_time, context=context)
Example #7
0
def answer_callback_query(job_queue: JobQueue,
                          query_id,
                          text=None,
                          show_alert=False,
                          cache_time=0):
    job_queue.run_once(
        lambda _: answer_callback_query_task(query_id, text, show_alert,
                                             cache_time), 0)
Example #8
0
def delete_message(job_queue: JobQueue, chat_id, message_id, when=0):
    key = deletion_task_key(chat_id, message_id)
    delete_tasks = job_queue.get_jobs_by_name(key)
    for task in delete_tasks:
        # Deletion will be postponed
        task.schedule_removal()
    job_queue.run_once(lambda _: delete_message_task(chat_id, message_id),
                       when,
                       name=key)
Example #9
0
def send_message(job_queue: JobQueue,
                 chat_id,
                 text,
                 reply_to=None,
                 parse_mode='HTML',
                 delete_after=None):
    job_queue.run_once(
        lambda context: send_message_task(context.job_queue, chat_id, text,
                                          reply_to, parse_mode, delete_after),
        0)
Example #10
0
def handle_roll(message: telegram.Message, name: str, text: str,
                job_queue: JobQueue, hide=False):
    if text.strip() == '':
        text = 'd'
    try:
        result_text = roll_text(message.chat_id, text)
    except dice.RollError as e:
        return error_message(message, job_queue, e.args[0])
    kind = LogKind.ROLL.value
    if hide:
        roll_id = str(uuid.uuid4())
        redis.set('roll:{}'.format(roll_id), pickle.dumps({
            'text': result_text,
            'chat_id': message.chat_id,
        }))
        keyboard = [[InlineKeyboardButton("GM 查看", callback_data=roll_id)]]

        reply_markup = InlineKeyboardMarkup(keyboard)
        text = '<b>{}</b> 投了一个隐形骰子'.format(name)
        kind = LogKind.HIDE_DICE.value
    else:
        text = '{} 🎲 {}'.format(name, result_text)
        reply_markup = None
    chat = get_chat(message.chat)
    if not chat.recording:
        text = '[未记录] ' + text
    sent = message.chat.send_message(
        text,
        reply_markup=reply_markup,
        parse_mode='HTML'
    )
    user = message.from_user
    assert isinstance(user, telegram.User)
    if chat.recording:
        Log.objects.create(
            user_id=user.id,
            message_id=sent.message_id,
            chat=chat,
            content=result_text,
            user_fullname=user.full_name,
            character_name=name,
            gm=is_gm(message.chat_id, user.id),
            kind=kind,
            created=message.date,
        )
    context = dict(
        chat_id=message.chat_id,
        message_id_list=[message.message_id]
    )
    job_queue.run_once(delay_delete_messages, 10, context)
Example #11
0
def variable_message(message: telegram.Message, job_queue: JobQueue,
                     assignment_list: List[Assignment]):
    send_text = ''
    for assignment in assignment_list:
        send_text += assignment.display(message.from_user.language_code) + '\n'
    sent = message.chat.send_message(send_text, parse_mode='HTML')
    user = message.from_user
    assert isinstance(user, telegram.User)

    delete_time = 30
    job_queue.run_once(delay_delete_messages, delete_time, context=dict(
        chat_id=message.chat_id,
        message_id_list=(message.message_id, sent.message_id)
    ))
Example #12
0
def ping(_, update: Update, job_queue: JobQueue):
    msg: Message = update.effective_message
    sent = msg.reply_text("🏓 Pong!", quote=True)
    del_timeout = 4

    def delete_msgs(*_):
        sent.delete()
        try:
            msg.delete()
        except:
            pass

    job_queue.run_once(delete_msgs,
                       del_timeout,
                       name="delete ping pong messages")
Example #13
0
def run_entries_jobs(job_queue: JobQueue, database: Database, start_time: dt.datetime, finish_time: dt.datetime):
    """
    Function will get entries from the database between the specific period and
    run new jobs that will call the function of recalling about events.

    :param job_queue: the JobQueue instance
    :param database: the Database instance
    :param start_time: the start time of the period
    :param finish_time: the end time of the period
    """
    entries = database.get_entries(start_time, finish_time)
    for entry in entries:
        job_queue.run_once(callback=recall_send_callback,
                           when=entry.entry_date,
                           context=entry)
Example #14
0
def add_notify_event(job_queue: JobQueue, job_model: Job):
    job_name = str(job_model.chat_id) + '_' + job_model.name

    if job_model.mode == JobMode.ONCE:
        job_queue.run_once(
            callback=notify_callback,
            name=job_name,
            when=create_time(job_model.time),
        )
    elif job_model.mode == JobMode.DAILY:
        job_queue.run_daily(
            callback=notify_callback,
            name=job_name,
            time=create_time(job_model.time),
            days=(0, 2, 3, 4),  # Monday-Friday
        )
Example #15
0
def error_message(message: telegram.Message, job_queue: JobQueue, text: str):
    _ = partial(get_by_user, user=message.from_user)
    delete_time = 15
    try:
        send_text = '<b>[{}]</b> {}'.format(
            _(Text.ERROR),
            text,
        )
        sent = message.reply_text(send_text, parse_mode='HTML')
    except TelegramError:
        return
    context = dict(
        chat_id=message.chat_id,
        message_id_list=(message.message_id, sent.message_id),
    )
    job_queue.run_once(delay_delete_messages, delete_time, context=context)
Example #16
0
def handle_roll(message: telegram.Message,
                name: str,
                entities: Entities,
                job_queue: JobQueue,
                chat: Chat,
                hide=False):
    _ = partial(get_by_user, user=message.from_user)
    kind = LogKind.ROLL.value
    result_text = entities.to_html()
    if hide:
        hide_roll = HideRoll(message.chat_id, result_text)
        hide_roll.set()
        keyboard = [[
            InlineKeyboardButton(_(Text.GM_LOOKUP),
                                 callback_data=hide_roll.key())
        ]]

        reply_markup = InlineKeyboardMarkup(keyboard)
        text = '<b>{}</b> {}'.format(name, _(Text.ROLL_HIDE_DICE))
        kind = LogKind.HIDE_DICE.value
    else:
        text = '{} 🎲 {}'.format(name, result_text)
        reply_markup = None
    if not chat.recording:
        text = '[{}] '.format(_(Text.NOT_RECORDING)) + text
    sent = message.chat.send_message(text,
                                     reply_markup=reply_markup,
                                     parse_mode='HTML')
    user = message.from_user
    assert isinstance(user, telegram.User)
    if chat.recording:
        Log.objects.create(
            user_id=user.id,
            message_id=sent.message_id,
            chat=chat,
            content=result_text,
            entities=entities.to_object(),
            user_fullname=user.full_name,
            character_name=name,
            gm=is_gm(message.chat_id, user.id),
            kind=kind,
            created=message.date,
        )
    context = dict(chat_id=message.chat_id,
                   message_id_list=[message.message_id])
    job_queue.run_once(delay_delete_messages, 10, context)
Example #17
0
def handle_list_variables(message: telegram.Message, job_queue: JobQueue, name: str, player: Player, **_):
    _ = partial(get_by_user, user=message.from_user)
    content = ''
    have_variable = False
    for variable in player.variable_set.order_by('updated').all():
        have_variable = True
        content += '<code>${}</code> {}\n'.format(variable.name, variable.value)
    if not have_variable:
        content = _(Text.VARIABLE_LIST_EMPTY)

    send_text = '<b>{}</b>\n\n{}'.format(_(Text.VARIABLE_LIST_TITLE).format(character=name), content)
    list_message = message.chat.send_message(send_text, parse_mode='HTML')
    delete_message(message)
    delete_time = 30
    job_queue.run_once(delay_delete_messages, delete_time, context=dict(
        chat_id=message.chat_id,
        message_id_list=(list_message.message_id,)
    ))
    def test_default_tzinfo(self, _dp, tz_bot):
        # we're parametrizing this with two different UTC offsets to exclude the possibility
        # of an xpass when the test is run in a timezone with the same UTC offset
        jq = JobQueue()
        original_bot = _dp.bot
        _dp.bot = tz_bot
        jq.set_dispatcher(_dp)
        try:
            jq.start()

            when = dtm.datetime.now(tz_bot.defaults.tzinfo) + dtm.timedelta(seconds=0.0005)
            jq.run_once(self.job_run_once, when.time())
            sleep(0.001)
            assert self.result == 1

            jq.stop()
        finally:
            _dp.bot = original_bot
Example #19
0
def try_delete_after(
    job_queue: JobQueue,
    messages: Union[List[Union[Message, int]], Union[Message, int]],
    delay: Union[float, int],
):
    if isinstance(messages, (Message, int)):
        _messages = [messages]
    else:
        _messages = messages

    @run_async
    def delete_messages(*args, **kwargs):
        # noinspection PyTypeChecker
        bot: BotListBot = job_queue.bot
        for m in _messages:
            bot.delete_message(m.chat_id, m.message_id, timeout=10, safe=True)

    job_queue.run_once(delete_messages, delay, name="try_delete_after")
Example #20
0
def process_inserting_entry_callback(job_queue: JobQueue, database: Database, finish_time: dt.datetime):
    """
    This callback function will be called, when an Insert operation will be occurred in the database.
    """
    jobs = job_queue.jobs()
    entries = database.get_entries(dt.datetime.now(), finish_time)
    for entry in entries:
        ran = False
        # Check that entry wasn't ran and put into the job_queue
        for job in jobs:
            if isinstance(job.context, Entry):
                if job.context.chat_id == entry.chat_id and job.context.name == entry.name:
                    ran = True
                    break
        if not ran:
            job_queue.run_once(callback=recall_send_callback,
                               when=entry.entry_date,
                               context=entry)
Example #21
0
def hint_handler(bot, update, job_queue: JobQueue):
    chat_id = update.message.chat_id
    if not util.is_group_message(update):
        return
    text = update.message.text
    reply_to = update.message.reply_to_message
    user = User.from_update(update)
    msg, reply_markup, hashtag = get_hint_data(text)

    def _send_hint(hint_text):
        if hint_text is None:
            return
        if reply_to:
            hint_text = f"{user.markdown_short} hints: {hint_text}"

        bot.formatter.send_message(
            chat_id,
            hint_text,
            reply_markup=reply_markup,
            reply_to_message_id=reply_to.message_id if reply_to else None,
        )
        update.effective_message.delete()

    should_reply: bool = HINTS.get(hashtag)["should_reply"]
    if should_reply and not reply_to:
        del_markup = append_free_delete_button(update,
                                               InlineKeyboardMarkup([[]]))
        _send_hint(msg)
        ntfc_msg = update.effective_message.reply_text(
            f"Hey {user.markdown_short}, next time reply to someone 🙃",
            parse_mode=ParseMode.MARKDOWN,
            reply_markup=del_markup,
            quote=False,
            disable_web_page_preview=True,
        )
        job_queue.run_once(lambda *_: ntfc_msg.delete(),
                           7,
                           name="delete notification")
    else:
        _send_hint(msg)
Example #22
0
    def _ptbcontrib_job(self, job_queue: JobQueue) -> None:
        self.logger.info("Getting ptbcontrib data.")

        try:
            files = cast(
                List[Tuple[str, Contents]],
                self.repos[PTBCONTRIB_REPO_NAME].directory_contents(
                    PTBCONTRIB_REPO_NAME),
            )
            with self.ptbcontrib_lock:
                self.ptbcontribs.clear()
                self.ptbcontribs.update({
                    name: PTBContrib(name, content.html_url)
                    for name, content in files if content.type == "dir"
                })

            # Rerun in two hours minutes
            job_queue.run_once(lambda _: self._ptbcontrib_job(job_queue),
                               2 * 60 * 60)
        except GitHubException as exc:
            if "rate limit" in str(exc):
                self.logger.warning(
                    "GH API rate limit exceeded. Retrying in 70 minutes.")
                job_queue.run_once(lambda _: self._ptbcontrib_job(job_queue),
                                   60 * 70)
            else:
                self.logger.exception(
                    "Something went wrong fetching issues. Retrying in 10s.",
                    exc_info=exc)
                job_queue.run_once(lambda _: self._ptbcontrib_job(job_queue),
                                   10)
def send_next(bot, update, job_queue: JobQueue, args=None):
    uid = util.uid_from_update(update)
    num_rows = None
    if args:
        try:
            num_rows = int(args[0])
        except:
            num_rows = None

    reply_markup = ReplyKeyboardMarkup(_crapPy_Tr0ll_kbmarkup(num_rows),
                                       one_time_keyboard=False,
                                       per_user=True)
    text = "ɹoʇɐɹǝuǝb ǝɯɐuɹǝsn ɯɐɹbǝןǝʇ"
    util.send_md_message(bot, uid, text, reply_markup=reply_markup)

    if util.is_group_message(update):
        del_msg = bot.formatter.send_message(
            update.effective_chat.id, "Have fun in private ;)\n/easteregg")
        update.effective_message.delete()
        job_queue.run_once(lambda *_: del_msg.delete(safe=True),
                           4,
                           name="delete easteregg hint")
Example #24
0
def welcome(bot: Bot, update: Update, job_queue: JobQueue) -> None:
    user_name = update.effective_message.new_chat_members[0].name
    user_id = update.effective_message.new_chat_members[0].id
    to_welcome, chat, message = False, 0, ''

    if update.effective_chat.id == nmaps_chat:
        bot.delete_message(nmaps_chat, update.effective_message.message_id)
        member = update.effective_chat.get_member(update.effective_user.id)
        if member.status in (ChatMember.RESTRICTED, ChatMember.KICKED):
            return

        msg = bot.send_message(nmaps_chat,
                               BOT_WELCOME_NMAPS.format(user_name),
                               reply_markup=VERIFY_MARKUP,
                               parse_mode='html')
        bot.restrict_chat_member(nmaps_chat, user_id, can_send_messages=False)
        job_queue.run_once(kick_and_delete_message, 300, {
            'user_id': user_id,
            'msg_id': msg.message_id,
            'chat_id': nmaps_chat
        }, str(user_id))
    elif update.effective_chat.id == mods_chat:
        to_welcome = True
        chat = mods_chat
        message = BOT_WELCOME_MODS.format(user_name)
    elif update.effective_chat.id == roads_chat:
        to_welcome = True
        chat = roads_chat
        message = BOT_WELCOME_ROADS.format(user_name)
    elif update.effective_chat.id == english_chat:
        to_welcome = True
        chat = english_chat
        message = BOT_WELCOME_ENG.format(user_name)

    if to_welcome:
        bot.send_message(chat,
                         message,
                         reply_to_message_id=update.message.message_id,
                         disable_web_page_preview=True)
Example #25
0
def run_job(queue: JobQueue, message: ScheduledMessage, chat_id: int):
    if message.period == 'daily':
        insert_job_to_jobs(
            chat_id,
            queue.run_daily(
                create_scheduled_message_callback(chat_id, message),
                message.start_day.time()))
    elif message.period == 'monthly':
        insert_job_to_jobs(
            chat_id,
            queue.run_monthly(create_scheduled_message_callback(
                chat_id, message),
                              message.start_day.time(),
                              message.start_day.date().day,
                              day_is_strict=False))
    elif message.period == 'once':
        insert_job_to_jobs(
            chat_id,
            queue.run_once(create_scheduled_message_callback(chat_id, message),
                           message.start_day))
    else:
        raise RuntimeError("Something strange happen")
Example #26
0
    def _job(self, job_queue: JobQueue) -> None:
        self.logger.info("Getting issues for default repo.")

        try:
            repo = self.repos[self.default_repo]
            if self.issue_iterator is None:
                self.issue_iterator = self.repos[self.default_repo].issues(
                    state="all")
            else:
                # The GitHubIterator automatically takes care of passing the ETag
                # which reduces the number of API requests that count towards the rate limit
                cast(GitHubIterator, self.issue_iterator).refresh(True)

            for i, gh_issue in enumerate(self.issue_iterator):
                # Acquire lock so we don't add while a func (like self.search) is iterating over it
                # We do this for ever single issue instead of before the for-loop, because that
                # would block self.search during the loop which takes a while
                with self.issues_lock:
                    self.issues[gh_issue.number] = Issue(gh_issue, repo)
                # Sleeping a moment after 100 issues to give the API some rest - we're not in a
                # hurry. The 100 is the max. per page number and as of 2.0.0 what github3.py
                # uses. sleeping doesn't block the bot, as jobs run in their own thread.
                # This is outside the lock! (see above commit)
                if (i + 1) % 100 == 0:
                    self.logger.info("Done with %d issues. Sleeping a moment.",
                                     i + 1)
                    time.sleep(10)

            # Rerun in 20 minutes
            job_queue.run_once(lambda _: self._job(job_queue), 60 * 20)
        except GitHubException as exc:
            if "rate limit" in str(exc):
                self.logger.warning(
                    "GH API rate limit exceeded. Retrying in 70 minutes.")
                job_queue.run_once(lambda _: self._job(job_queue), 60 * 70)
            else:
                self.logger.exception(
                    "Something went wrong fetching issues. Retrying in 10s.",
                    exc_info=exc)
                job_queue.run_once(lambda _: self._job(job_queue), 10)
Example #27
0
def new_member(bot: Bot, update: Update, job_queue: JobQueue):
    chat = update.effective_chat
    user = update.effective_user
    msg = update.effective_message

    should_welc, cust_welcome, welc_type = sql.get_welc_pref(chat.id)
    welc_mutes = sql.welcome_mutes(chat.id)
    human_checks = sql.get_human_checks(user.id, chat.id)

    new_members = update.effective_message.new_chat_members

    for new_mem in new_members:

        welcome_log = None
        sent = None
        should_mute = True
        welcome_bool = True

        if should_welc:

            # Give the owner a special welcome
            if new_mem.id == OWNER_ID:
                update.effective_message.reply_text(
                    "Oh, Genos? Let's get this moving.")
                welcome_log = (f"{html.escape(chat.title)}\n"
                               f"#USER_JOINED\n"
                               f"Bot Owner just joined the chat")

            # Welcome Devs
            elif new_mem.id in DEV_USERS:
                update.effective_message.reply_text(
                    "Whoa! A member of the Penguin Logistics just joined!")

            # Welcome Sudos
            elif new_mem.id in SUDO_USERS:
                update.effective_message.reply_text(
                    "Huh! A S tier just joined! Stay Alert!")

            # Welcome Support
            elif new_mem.id in SUPPORT_USERS:
                update.effective_message.reply_text(
                    "Huh! Someone with a Demon tier level just joined!")

            # Welcome Whitelisted
            elif new_mem.id in B_USERS:
                update.effective_message.reply_text(
                    "Oof! A B tier just joined!")

            # Welcome B
            elif new_mem.id in WHITELIST_USERS:
                update.effective_message.reply_text(
                    "Oof! A Wolf tier just joined!")

            # Welcome yourself
            elif new_mem.id == bot.id:
                update.effective_message.reply_text("Watashi ga kitta!")

            else:
                # If welcome message is media, send with appropriate function
                if welc_type not in (sql.Types.TEXT, sql.Types.BUTTON_TEXT):
                    ENUM_FUNC_MAP[welc_type](chat.id, cust_welcome)
                    continue

                # else, move on
                first_name = new_mem.first_name or "PersonWithNoName"  # edge case of empty name - occurs for some bugs.

                if cust_welcome:
                    if cust_welcome == sql.DEFAULT_WELCOME:
                        cust_welcome = random.choice(
                            sql.DEFAULT_WELCOME_MESSAGES).format(
                                first=escape_markdown(first_name))

                    if new_mem.last_name:
                        fullname = escape_markdown(
                            f"{first_name} {new_mem.last_name}")
                    else:
                        fullname = escape_markdown(first_name)
                    count = chat.get_members_count()
                    mention = mention_markdown(new_mem.id,
                                               escape_markdown(first_name))
                    if new_mem.username:
                        username = "******" + escape_markdown(new_mem.username)
                    else:
                        username = mention

                    valid_format = escape_invalid_curly_brackets(
                        cust_welcome, VALID_WELCOME_FORMATTERS)
                    res = valid_format.format(
                        first=escape_markdown(first_name),
                        last=escape_markdown(new_mem.last_name or first_name),
                        fullname=escape_markdown(fullname),
                        username=username,
                        mention=mention,
                        count=count,
                        chatname=escape_markdown(chat.title),
                        id=new_mem.id)
                    buttons = sql.get_welc_buttons(chat.id)
                    keyb = build_keyboard(buttons)

                else:
                    res = random.choice(sql.DEFAULT_WELCOME_MESSAGES).format(
                        first=escape_markdown(first_name))
                    keyb = []

                backup_message = random.choice(
                    sql.DEFAULT_WELCOME_MESSAGES).format(
                        first=escape_markdown(first_name))
                keyboard = InlineKeyboardMarkup(keyb)

        else:
            welcome_bool = False
            res = None
            keyboard = None
            backup_message = None

        # User exceptions from welcomemutes
        if is_user_ban_protected(chat, new_mem.id, chat.get_member(
                new_mem.id)) or human_checks:
            should_mute = False
        # Join welcome: soft mute
        if new_mem.is_bot:
            should_mute = False

        if user.id == new_mem.id:
            if should_mute:
                if welc_mutes == "soft":
                    bot.restrict_chat_member(chat.id,
                                             new_mem.id,
                                             can_send_messages=True,
                                             can_send_media_messages=False,
                                             can_send_other_messages=False,
                                             can_add_web_page_previews=False,
                                             until_date=(int(time.time() +
                                                             24 * 60 * 60)))

                if welc_mutes == "strong":
                    welcome_bool = False
                    VERIFIED_USER_WAITLIST.update({
                        new_mem.id: {
                            "should_welc": should_welc,
                            "status": False,
                            "update": update,
                            "res": res,
                            "keyboard": keyboard,
                            "backup_message": backup_message
                        }
                    })
                    new_join_mem = f"[{escape_markdown(new_mem.first_name)}](tg://user?id={user.id})"
                    message = msg.reply_text(
                        f"{new_join_mem}, click the button below to prove you're human.\nYou have 160 seconds.",
                        reply_markup=InlineKeyboardMarkup([{
                            InlineKeyboardButton(
                                text="Yes, I'm human.",
                                callback_data=f"user_join_({new_mem.id})")
                        }]),
                        parse_mode=ParseMode.MARKDOWN)
                    bot.restrict_chat_member(chat.id,
                                             new_mem.id,
                                             can_send_messages=False,
                                             can_send_media_messages=False,
                                             can_send_other_messages=False,
                                             can_add_web_page_previews=False)

                    job_queue.run_once(partial(check_not_bot, new_mem, chat.id,
                                               message.message_id),
                                       160,
                                       name="welcomemute")

        if welcome_bool:
            sent = send(update, res, keyboard, backup_message)

            prev_welc = sql.get_clean_pref(chat.id)
            if prev_welc:
                try:
                    bot.delete_message(chat.id, prev_welc)
                except BadRequest:
                    pass

                if sent:
                    sql.set_clean_welcome(chat.id, sent.message_id)

        if welcome_log:
            return welcome_log

        return (f"{html.escape(chat.title)}\n"
                f"#USER_JOINED\n"
                f"<b>User</b>: {mention_html(user.id, user.first_name)}\n"
                f"<b>ID</b>: <code>{user.id}</code>")

    return ""
Example #28
0
 def init_ptb_contribs(self, job_queue: JobQueue) -> None:
     job_queue.run_once(lambda _: self._ptbcontrib_job(job_queue), 5)
class JobQueueTest(BaseTest, unittest.TestCase):
    """
    This object represents Tests for Updater, Dispatcher, WebhookServer and
    WebhookHandler
    """

    def setUp(self):
        self.jq = JobQueue(MockBot('jobqueue_test'))
        self.jq.start()
        self.result = 0
        self.job_time = 0

    def tearDown(self):
        if self.jq is not None:
            self.jq.stop()

    def job1(self, bot, job):
        self.result += 1

    def job2(self, bot, job):
        raise Exception("Test Error")

    def job3(self, bot, job):
        self.result += 1
        job.schedule_removal()

    def job4(self, bot, job):
        self.result += job.context

    def job5(self, bot, job):
        self.job_time = time.time()

    def test_basic(self):
        self.jq.put(Job(self.job1, 0.1))
        sleep(1.5)
        self.assertGreaterEqual(self.result, 10)

    def test_job_with_context(self):
        self.jq.put(Job(self.job4, 0.1, context=5))
        sleep(1.5)
        self.assertGreaterEqual(self.result, 50)

    def test_noRepeat(self):
        self.jq.put(Job(self.job1, 0.1, repeat=False))
        sleep(0.5)
        self.assertEqual(1, self.result)

    def test_nextT(self):
        self.jq.put(Job(self.job1, 0.1), next_t=0.5)
        sleep(0.45)
        self.assertEqual(0, self.result)
        sleep(0.1)
        self.assertEqual(1, self.result)

    def test_multiple(self):
        self.jq.put(Job(self.job1, 0.1, repeat=False))
        self.jq.put(Job(self.job1, 0.2, repeat=False))
        self.jq.put(Job(self.job1, 0.4))
        sleep(1)
        self.assertEqual(4, self.result)

    def test_disabled(self):
        j0 = Job(self.job1, 0.1)
        j1 = Job(self.job1, 0.2)

        self.jq.put(j0)
        self.jq.put(Job(self.job1, 0.4))
        self.jq.put(j1)

        j0.enabled = False
        j1.enabled = False

        sleep(1)
        self.assertEqual(2, self.result)

    def test_schedule_removal(self):
        j0 = Job(self.job1, 0.1)
        j1 = Job(self.job1, 0.2)

        self.jq.put(j0)
        self.jq.put(Job(self.job1, 0.4))
        self.jq.put(j1)

        j0.schedule_removal()
        j1.schedule_removal()

        sleep(1)
        self.assertEqual(2, self.result)

    def test_schedule_removal_from_within(self):
        self.jq.put(Job(self.job1, 0.4))
        self.jq.put(Job(self.job3, 0.2))

        sleep(1)
        self.assertEqual(3, self.result)

    def test_longer_first(self):
        self.jq.put(Job(self.job1, 0.2, repeat=False))
        self.jq.put(Job(self.job1, 0.1, repeat=False))
        sleep(0.15)
        self.assertEqual(1, self.result)

    def test_error(self):
        self.jq.put(Job(self.job2, 0.1))
        self.jq.put(Job(self.job1, 0.2))
        sleep(0.5)
        self.assertEqual(2, self.result)

    def test_jobs_tuple(self):
        self.jq.stop()
        jobs = tuple(Job(self.job1, t) for t in range(5, 25))

        for job in jobs:
            self.jq.put(job)

        self.assertTupleEqual(jobs, self.jq.jobs())

    def test_inUpdater(self):
        u = Updater(bot="MockBot")
        u.job_queue.start()
        try:
            u.job_queue.put(Job(self.job1, 0.5))
            sleep(0.75)
            self.assertEqual(1, self.result)
            u.stop()
            sleep(2)
            self.assertEqual(1, self.result)
        finally:
            u.stop()

    def test_time_unit_int(self):
        # Testing seconds in int
        delta = 2
        expected_time = time.time() + delta

        self.jq.put(Job(self.job5, delta, repeat=False))
        sleep(2.5)
        self.assertAlmostEqual(self.job_time, expected_time, delta=0.1)

    def test_time_unit_dt_timedelta(self):
        # Testing seconds, minutes and hours as datetime.timedelta object
        # This is sufficient to test that it actually works.
        interval = datetime.timedelta(seconds=2)
        expected_time = time.time() + interval.total_seconds()

        self.jq.put(Job(self.job5, interval, repeat=False))
        sleep(2.5)
        self.assertAlmostEqual(self.job_time, expected_time, delta=0.1)

    def test_time_unit_dt_datetime(self):
        # Testing running at a specific datetime
        delta = datetime.timedelta(seconds=2)
        next_t = datetime.datetime.now() + delta
        expected_time = time.time() + delta.total_seconds()

        self.jq.put(Job(self.job5, repeat=False), next_t=next_t)
        sleep(2.5)
        self.assertAlmostEqual(self.job_time, expected_time, delta=0.1)

    def test_time_unit_dt_time_today(self):
        # Testing running at a specific time today
        delta = 2
        next_t = (datetime.datetime.now() + datetime.timedelta(seconds=delta)).time()
        expected_time = time.time() + delta

        self.jq.put(Job(self.job5, repeat=False), next_t=next_t)
        sleep(2.5)
        self.assertAlmostEqual(self.job_time, expected_time, delta=0.1)

    def test_time_unit_dt_time_tomorrow(self):
        # Testing running at a specific time that has passed today. Since we can't wait a day, we
        # test if the jobs next_t has been calculated correctly
        delta = -2
        next_t = (datetime.datetime.now() + datetime.timedelta(seconds=delta)).time()
        expected_time = time.time() + delta + 60 * 60 * 24

        self.jq.put(Job(self.job5, repeat=False), next_t=next_t)
        self.assertAlmostEqual(self.jq.queue.get(False)[0], expected_time, delta=0.1)

    def test_run_once(self):
        delta = 2
        expected_time = time.time() + delta

        self.jq.run_once(self.job5, delta)
        sleep(2.5)
        self.assertAlmostEqual(self.job_time, expected_time, delta=0.1)

    def test_run_repeating(self):
        interval = 0.1
        first = 1.5

        self.jq.run_repeating(self.job1, interval, first=first)
        sleep(2.505)
        self.assertAlmostEqual(self.result, 10, delta=1)

    def test_run_daily(self):
        delta = 1
        time_of_day = (datetime.datetime.now() + datetime.timedelta(seconds=delta)).time()
        expected_time = time.time() + 60 * 60 * 24 + delta

        self.jq.run_daily(self.job1, time_of_day)
        sleep(2 * delta)
        self.assertEqual(self.result, 1)
        self.assertAlmostEqual(self.jq.queue.get(False)[0], expected_time, delta=0.1)
Example #30
0
 def init_issues(self, job_queue: JobQueue) -> None:
     job_queue.run_once(lambda _: self._job(job_queue), 10)
Example #31
0
def new_member(bot: Bot, update: Update, job_queue: JobQueue):
    chat = update.effective_chat
    user = update.effective_user
    msg = update.effective_message

    should_welc, cust_welcome, welc_type = sql.get_welc_pref(chat.id)
    welc_mutes = sql.welcome_mutes(chat.id)
    human_checks = sql.get_human_checks(user.id, chat.id)

    new_members = update.effective_message.new_chat_members

    for new_mem in new_members:

        welcome_log = None
        res = None
        sent = None
        should_mute = True
        welcome_bool = True

        if should_welc:

            reply = update.message.message_id
            cleanserv = sql.clean_service(chat.id)
            # Clean service welcome
            if cleanserv:
                try:
                    dispatcher.bot.delete_message(chat.id,
                                                  update.message.message_id)
                except BadRequest:
                    pass
                reply = False

            # Give the owner a special welcome
            if new_mem.id == OWNER_ID:
                update.effective_message.reply_text(
                    "Oh, Genos? Hadi bunu hareket ettirelim.",
                    reply_to_message_id=reply)
                welcome_log = (f"{html.escape(chat.title)}\n"
                               f"#USER_JOINED\n"
                               f"Bot Yetkilisi sohbete katıldı")

            # Welcome Devs
            elif new_mem.id in DEV_USERS:
                update.effective_message.reply_text(
                    "Oha! Kahramanlar Derneği üyesi yeni katıldı!",
                    reply_to_message_id=reply)

            # Welcome Sudos
            elif new_mem.id in SUDO_USERS:
                update.effective_message.reply_text(
                    "Huh! Bir Ejderha felaketi daha yeni katıldı! Dikkatli ol!",
                    reply_to_message_id=reply)

            # Welcome Support
            elif new_mem.id in SUPPORT_USERS:
                update.effective_message.reply_text(
                    "Huh! Demon afet düzeyine sahip biri katıldı!",
                    reply_to_message_id=reply)

            # Welcome Whitelisted
            elif new_mem.id in TIGER_USERS:
                update.effective_message.reply_text(
                    "Oof! Bir Tiger felaketi daha yeni katıldı!",
                    reply_to_message_id=reply)

            # Welcome Tigers
            elif new_mem.id in WHITELIST_USERS:
                update.effective_message.reply_text(
                    "Oof! Bir kurt felaketi daha yeni katıldı!",
                    reply_to_message_id=reply)

            # Welcome yourself
            elif new_mem.id == bot.id:
                update.effective_message.reply_text("Watashi ga kita!",
                                                    reply_to_message_id=reply)

            else:
                # If welcome message is media, send with appropriate function
                if welc_type not in (sql.Types.TEXT, sql.Types.BUTTON_TEXT):
                    ENUM_FUNC_MAP[welc_type](chat.id, cust_welcome)
                    continue

                # else, move on
                first_name = new_mem.first_name or "PersonWithNoName"  # edge case of empty name - occurs for some bugs.

                if cust_welcome:
                    if cust_welcome == sql.DEFAULT_WELCOME:
                        cust_welcome = random.choice(
                            sql.DEFAULT_WELCOME_MESSAGES).format(
                                first=escape_markdown(first_name))

                    if new_mem.last_name:
                        fullname = escape_markdown(
                            f"{first_name} {new_mem.last_name}")
                    else:
                        fullname = escape_markdown(first_name)
                    count = chat.get_members_count()
                    mention = mention_markdown(new_mem.id,
                                               escape_markdown(first_name))
                    if new_mem.username:
                        username = "******" + escape_markdown(new_mem.username)
                    else:
                        username = mention

                    valid_format = escape_invalid_curly_brackets(
                        cust_welcome, VALID_WELCOME_FORMATTERS)
                    res = valid_format.format(
                        first=escape_markdown(first_name),
                        last=escape_markdown(new_mem.last_name or first_name),
                        fullname=escape_markdown(fullname),
                        username=username,
                        mention=mention,
                        count=count,
                        chatname=escape_markdown(chat.title),
                        id=new_mem.id)
                    buttons = sql.get_welc_buttons(chat.id)
                    keyb = build_keyboard(buttons)

                else:
                    res = random.choice(sql.DEFAULT_WELCOME_MESSAGES).format(
                        first=escape_markdown(first_name))
                    keyb = []

                backup_message = random.choice(
                    sql.DEFAULT_WELCOME_MESSAGES).format(
                        first=escape_markdown(first_name))
                keyboard = InlineKeyboardMarkup(keyb)

        else:
            welcome_bool = False
            res = None
            keyboard = None
            backup_message = None
            reply = None

        # User exceptions from welcomemutes
        if is_user_ban_protected(chat, new_mem.id, chat.get_member(
                new_mem.id)) or human_checks:
            should_mute = False
        # Join welcome: soft mute
        if new_mem.is_bot:
            should_mute = False

        if user.id == new_mem.id:
            if should_mute:
                if welc_mutes == "soft":
                    bot.restrict_chat_member(chat.id,
                                             new_mem.id,
                                             can_send_messages=True,
                                             can_send_media_messages=False,
                                             can_send_other_messages=False,
                                             can_add_web_page_previews=False,
                                             until_date=(int(time.time() +
                                                             24 * 60 * 60)))

                if welc_mutes == "strong":
                    welcome_bool = False
                    VERIFIED_USER_WAITLIST.update({
                        new_mem.id: {
                            "should_welc": should_welc,
                            "status": False,
                            "update": update,
                            "res": res,
                            "keyboard": keyboard,
                            "backup_message": backup_message
                        }
                    })
                    new_join_mem = f"[{escape_markdown(new_mem.first_name)}](tg://user?id={user.id})"
                    message = msg.reply_text(
                        f"{new_join_mem},insan olduğunuzu kanıtlamak için aşağıdaki düğmeyi tıklayın.\n120 saniyeniz var.",
                        reply_markup=InlineKeyboardMarkup([{
                            InlineKeyboardButton(
                                text="Evet ben insanım.",
                                callback_data=f"user_join_({new_mem.id})")
                        }]),
                        parse_mode=ParseMode.MARKDOWN,
                        reply_to_message_id=reply)
                    bot.restrict_chat_member(chat.id,
                                             new_mem.id,
                                             can_send_messages=False,
                                             can_send_media_messages=False,
                                             can_send_other_messages=False,
                                             can_add_web_page_previews=False)

                    job_queue.run_once(partial(check_not_bot, new_mem, chat.id,
                                               message.message_id),
                                       120,
                                       name="welcomemute")

        if welcome_bool:
            sent = send(update, res, keyboard, backup_message)

            prev_welc = sql.get_clean_pref(chat.id)
            if prev_welc:
                try:
                    bot.delete_message(chat.id, prev_welc)
                except BadRequest:
                    pass

                if sent:
                    sql.set_clean_welcome(chat.id, sent.message_id)

        if welcome_log:
            return welcome_log

        return (f"{html.escape(chat.title)}\n"
                f"#USER_JOINED\n"
                f"<b>Kullanıcı</b>: {mention_html(user.id, user.first_name)}\n"
                f"<b>ID</b>: <code>{user.id}</code>")

    return ""