Exemplo n.º 1
0
def intro_handler(bot: Bot, update: Update):
    #chat_id = update.message.chat_id
    #p, _ = Profile.objects.get_or_create(
    #	external_id = chat_id,
    ###	}
    #)
    intro = update.callback_query.data
    j = JobQueue()
    j.set_dispatcher(dispatcher)
    if intro == CALLBACK_BUTTON1_LEFT:
        chat_id = update.effective_message.chat_id
        text = "Прекрасно! Теперь я буду каждый день отправлять тебе упражнения. Береги глаза друг!"
        j.run_repeating(callback_alarm, 60 * 60 * 24, 60, context=chat_id)
        j.start()
        update.effective_message.reply_text(
            text=text,
            reply_markup=get_keyboard2(),
        )
        return ConversationHandler.END
    elif intro == CALLBACK_BUTTON2_RIGHT:
        text = "Тогда ты можешь просто насладиться статьями, которые будут только улучшаться"
        update.callback_query.message.reply_text(
            text=text,
            reply_markup=get_keyboard2(),
        )
        return ConversationHandler.END
Exemplo n.º 2
0
def start_aoc_handlers(queue: JobQueue, bot: Bot):
    logger.info("registering aoc handlers")
    update_aoc_data(bot, queue)
    queue.run_repeating(
        lambda _: update_aoc_data(bot, queue),
        AOC_UPDATE_INTERVAL,
        name=JOB_AOC_UPDATE,
    )
Exemplo n.º 3
0
def set_handlers(queue: JobQueue, bot: Bot):
    queue.run_daily(lambda _: daily_infection(get_group_chat_id(), bot),
                    DAILY_INFECTION_TIME,
                    name=JOB_QUEUE_DAILY_INFECTION_KEY)

    queue.run_repeating(lambda _: random_cough(bot, queue),
                        REPEATING_COUGHING_INTERVAL,
                        name=JOB_QUEUE_REPEATING_COUGHING_KEY)
Exemplo n.º 4
0
 def _run_scheduler(self, job_queue: JobQueue,
                    schedulers: Iterable[SchedulerDTO]) -> None:
     for scheduler_dto in schedulers:
         job_queue.run_repeating(
             callback=scheduler_dto.callback,
             interval=scheduler_dto.interval,
             first=1,
         )
Exemplo n.º 5
0
def add_job(job_queue: JobQueue, chat: Chat):
    for job in job_queue.jobs():
        if job.context.id == chat.id:
            job.enabled = False
            job.schedule_removal()

    job_queue.run_repeating(send_issue,
                            int(JIRA_REQUESTS_SECONDS_PERIOD),
                            context=chat)
Exemplo n.º 6
0
def main():
    mongoengine.connect(db=config.database.db, host=config.database.host,
                        port=config.database.port,
                        username=config.database.user,
                        password=config.database.password)

    start_handler = CommandHandler('start', commands)
    dispatcher.add_handler(start_handler)

    help_handler = CommandHandler('help', commands)
    dispatcher.add_handler(help_handler)

    register_handler = CommandHandler('register', register)
    dispatcher.add_handler(register_handler)

    info_handler = CommandHandler('info', info)
    dispatcher.add_handler(info_handler)

    balance_handler = CommandHandler('balance', balance)
    dispatcher.add_handler(balance_handler)

    balance_prefix_handler = PrefixHandler(COMMAND_PREFIX, 'balance', balance)
    dispatcher.add_handler(balance_prefix_handler)

    withdraw_handler = CommandHandler('withdraw', withdraw)
    dispatcher.add_handler(withdraw_handler)

    transfer_handler = CommandHandler('transfer', transfer)
    dispatcher.add_handler(transfer_handler)

    transfer_prefix_handler = PrefixHandler(COMMAND_PREFIX, 'transfer',
                                            transfer)
    dispatcher.add_handler(transfer_prefix_handler)

    tip_handler = CommandHandler('tip', tip)
    dispatcher.add_handler(tip_handler)

    tip_prefix_handler = PrefixHandler(COMMAND_PREFIX, 'tip', tip)
    dispatcher.add_handler(tip_prefix_handler)

    outputs_handler = CommandHandler('outputs', outputs)
    dispatcher.add_handler(outputs_handler)

    optimize_handler = CommandHandler('optimize', optimize)
    dispatcher.add_handler(optimize_handler)

    dispatcher.add_error_handler(handle_errors)

    jobqueue = JobQueue()
    jobqueue.set_dispatcher(dispatcher)
    jobqueue.run_repeating(update_balance_wallets,
                           config.wallet_balance_update_interval)
    jobqueue.start()

    updater.start_polling()
Exemplo n.º 7
0
 def test_job_run(self, _dp, use_context):
     _dp.use_context = use_context
     job_queue = JobQueue()
     job_queue.set_dispatcher(_dp)
     if use_context:
         job = job_queue.run_repeating(self.job_context_based_callback, 0.02, context=2)
     else:
         job = job_queue.run_repeating(self.job_run_once, 0.02, context=2)
     assert self.result == 0
     job.run(_dp)
     assert self.result == 1
Exemplo n.º 8
0
def main():
    updater = Updater(token=FreeOnEpic.bot_token, use_context=True)
    dp = updater.dispatcher
    job_queue = JobQueue()
    job_queue.set_dispatcher(dp)
    job_queue.run_repeating(callback=FreeOnEpic.get_links, interval=600)
    logger.info('The bot has started')
    dp.add_handler(CommandHandler('freegame', FreeOnEpic.free_game))
    dp.add_handler(CommandHandler("help", FreeOnEpic.help_command))
    job_queue.start()
    updater.start_polling()
    updater.idle()
Exemplo n.º 9
0
def main():
    """Start the bot."""
    # Create the Updater and pass it your bot's token.
    # Make sure to set use_context=True to use the new context based callbacks
    # Post version 12 this will no longer be necessary
    updater = Updater(config.bottoken, use_context=True)

    # Get the dispatcher to register handlers
    dp = updater.dispatcher

    # on different commands - answer in Telegram
    # dp.add_handler(CommandHandler("start", start))
    dp.add_handler(CommandHandler("hilfe", help))
    dp.add_handler(CommandHandler("status", status))
    dp.add_handler(CommandHandler("forceupdate", force_update))

    # Add conversation handler with the states ASKFORLK, UNIQUELK, MULTIPLELK
    conv_handler = ConversationHandler(
        entry_points=[
            CommandHandler('start', start),
            CommandHandler('neuerlk', newlk),
            CommandHandler('entfernelk', removelk)
        ],
        states={
            ASKFORLK: [MessageHandler(Filters.text, ask_for_landkreis)],
            CHOOSELK: [MessageHandler(Filters.text, choose_landkreis)],
            REMOVELK: [MessageHandler(Filters.text, remove_landkreis)]
        },
        fallbacks=[CommandHandler('cancel', cancel)])
    dp.add_handler(conv_handler)

    # Error handler
    dp.add_error_handler(error)

    # Read the existing data
    casesdata.load_data()

    # Start the Bot
    updater.start_polling()

    # Check for updates of rki numbers and notify users every hour (3600s).
    cronjob = JobQueue()
    cronjob.set_dispatcher(dp)
    cronjob.run_repeating(process_case_updates, 3600)
    cronjob.start()

    # Run the bot until you press Ctrl-C or the process receives SIGINT,
    # SIGTERM or SIGABRT. This should be used most of the time, since
    # start_polling() is non-blocking and will stop the bot gracefully.
    updater.idle()
Exemplo n.º 10
0
def scrape_begin_city(bot: Bot,
                      update: Update,
                      job_queue: JobQueue,
                      chat_data,
                      city=None):
    if not city:
        city = update.message.text[19:].lower(
        )  # 19 characters is len('/scrape_begin_city ')
    if city in URLS.keys():
        jobs_for_same_city = [
            job for job in job_queue.jobs() if job.context == city
        ]
        if jobs_for_same_city:
            update.message.reply_text(
                'wg_ges scraper job was already set! /scrape_stop_city {} to kill it'
                .format(city))
        else:
            job = job_queue.run_repeating(callback=job_scrape_city,
                                          interval=75,
                                          first=10,
                                          context=city)
            chat_data[city] = job
            logging.info('start scraping {}'.format(city))
            update.message.reply_text(
                'wg_ges scraper job successfully set! /subscribe {} to test, /unsubscribe to stop, /scrape_stop_city '
                '{} to stop it.'.format(city, city))
    else:
        update.message.reply_text('valid cities: {}'.format(all_cities_string))
Exemplo n.º 11
0
def main():
    with open(os.path.join(dir_path, 'config.json')) as config_file:
        config = json.loads(config_file.read())['main']

    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    fh = logging.FileHandler(os.path.join(dir_path, config["log_filename"]))
    fh.setFormatter(logging.Formatter('%(asctime)s %(levelname)s:%(message)s'))
    logger.addHandler(fh)

    api = OxfordApi(config['api'], logger)

    bot_words_learner = BotWordsLearner(dir_path,
                                        get_bot_token(config["token_path"]),
                                        logger, config["bot_words_learner"],
                                        api)
    bot_words_learner.load_from_disk()

    job_queue = JobQueue(Bot(get_bot_token(config["token_path"])))
    job_queue.run_repeating(
        run_and_log(bot_words_learner.save_to_disk, logger), 60 * 60)
    job_queue.start()

    updater = Updater(token=bot_words_learner.token)
    dispatcher = updater.dispatcher

    dispatcher.add_handler(CommandHandler('start', bot_words_learner.start))
    dispatcher.add_handler(CommandHandler('help', bot_words_learner.help))
    dispatcher.add_handler(CommandHandler('stat', bot_words_learner.stat))
    dispatcher.add_handler(MessageHandler(Filters.text,
                                          bot_words_learner.talk))
    dispatcher.add_handler(
        MessageHandler(Filters.document, bot_words_learner.document_load))
    dispatcher.add_handler(
        CommandHandler('keyboard', bot_words_learner.keyboard))
    dispatcher.add_error_handler(bot_words_learner.error)

    updater.start_polling()
    updater.idle()
    logger.critical('Finish session\n')
    bot_words_learner.save_to_disk()
    api.cash.save()
    job_queue.stop()
Exemplo n.º 12
0
    def __init__(self, logger):
        self.logger = logger

        self.settings = default_settings

        self.token = os.getenv('tbot_api')
        self.spc_url = os.getenv('spc_url')
        self.spc_wallet = os.getenv('spc_wallet')
        self.admin_id = int(os.getenv('spc_admin_id', None))

        self._create_tables()

        self.delays = {}
        self.latest_dices = {}
        self.roll_messages = []
        self.secret_key, self.public_key = self._get_keys(self.spc_wallet)
        self.bot = Bot(self.token)
        self.updater = Updater(self.token, use_context=True)

        msg_filter = Filters.text \
                     & (~Filters.forwarded) \
                     & (~Filters.update.edited_message)

        dice_filter = Filters.dice \
                      & (~Filters.forwarded) \
                      & (~Filters.update.edited_message) \
                      & Filters.group

        msg_handler = MessageHandler(filters=msg_filter,
                                     callback=self.message_callback)
        dice_handler = MessageHandler(filters=dice_filter,
                                      callback=self.dice_callback)
        self.updater.dispatcher.add_handler(msg_handler)
        self.updater.dispatcher.add_handler(dice_handler)

        jobs = JobQueue()
        jobs.set_dispatcher(self.updater.dispatcher)
        jobs.run_repeating(callback=self.job_callback, interval=10)
        jobs.run_repeating(callback=self.message_job_callback, interval=1)
        jobs.start()

        self.updater.start_polling()
        self.updater.idle()
Exemplo n.º 13
0
def subscribe_city_cmd(bot: Bot,
                       update: Update,
                       job_queue: JobQueue,
                       chat_data,
                       city=None):
    if not city:
        city = update.message.text[11:].lower()
    if city in all_cities:
        chat_id = update.message.chat_id
        if chat_id in subscribers and subscribers[chat_id].is_subscribed(city):
            update.message.reply_text(
                'Dein Abo für {} lief schon. /unsubscribe für Stille im Postfach.'
                .format(city))
        else:
            context = {'chat_id': chat_id, 'city': city}
            job = job_queue.run_repeating(callback=job_notify_subscriber,
                                          interval=15,
                                          first=1,
                                          context=context)
            try:
                try:
                    old_jobs = chat_data['jobs']
                    if old_jobs is None:
                        old_jobs = []
                except KeyError:
                    old_jobs = []
                old_jobs.append(job)
                chat_data['jobs'] = old_jobs
            except Unauthorized:
                logging.warning('unauthorized in job notify. removing job')
                job.schedule_removal()
                return

            if chat_id not in subscribers:
                subscribers[chat_id] = Subscriber(chat_id)
            subscribers[chat_id].subscribe(city)

            logging.info('{} subbed {}'.format(chat_id, city))
            update.message.reply_text(
                'Erfolgreich {} abboniert, du liegst jetzt auf der Lauer. Nützliche Filter Beispiele:\n'
                '"/filter_rent 500" - nur Anzeigen bis 500€\n'
                '"/filter_sex m" - keine Anzeigen die nur Frauen suchen\n'
                '"/filter_from 16.03.2018" - keine Anzeigen die erst später frei werden. Datumsformat muss stimmen.\n'
                '"/filter_to 17.03.2018" - keine Anzeigen die nur kürzer frei sind. Datumsformat muss stimmen.\n'
                '"/unsubscribe" - Stille'.format(city))
    else:
        if city == '':
            update.message.reply_text(
                'Bitte gib an in welcher Stadt du deine WG suchen möchtest.'
                'Verfügbare Städte: {} '
                'Beispiel: /subscribe MUC'.format(city, all_cities_string))
        else:
            update.message.reply_text(
                'In {} gibt\'s mich nicht, sorry. Verfügbare Städte: {}'.
                format(city, all_cities_string))
Exemplo n.º 14
0
Arquivo: dxbot.py Projeto: DD5HT/dxbot
def main():
    """Main methode, starts all jobs"""
    # Start DX Cluster in background
    cluster.clustersearch()

    # Create the EventHandler and pass it your bot's token.
    updater = Updater(TOKEN)
    jobquere = JobQueue(Bot(TOKEN))

    # Register Cluster job
    jobquere.run_repeating(realcluster, 15, 0)
    jobquere.start()

    # Get the dispatcher to register handlers
    dp = updater.dispatcher

    # on different commands - answer in Telegram
    dp.add_handler(CallbackQueryHandler(button))
    dp.add_handler(CommandHandler("start", start))
    dp.add_handler(CommandHandler("help", help))
    dp.add_handler(CommandHandler("menu", menu))

    # Call Commands
    dp.add_handler(CommandHandler("add", addcall))
    dp.add_handler(CommandHandler("rm", deletecall))
    dp.add_handler(CommandHandler("list", listcalls))

    # DXCC Commands
    dp.add_handler(CommandHandler("adddx", adddxcc))
    dp.add_handler(CommandHandler("listdx", listdxcc))

    # log all errors
    dp.add_error_handler(error)

    # Start the Bot
    updater.start_polling()

    # Run the bot until you press Ctrl-C or the process receives SIGINT,
    # SIGTERM or SIGABRT. This should be used most of the time, since
    # start_polling() is non-blocking and will stop the bot gracefully.
    updater.idle()
    cluster.clustersearch()
Exemplo n.º 15
0
    def bot_command(self):
        """
        creating the bot instructions
        """
        updater = Updater(self._token, use_context=True)
        dp = updater.dispatcher
        job_queue = JobQueue()
        job_queue.set_dispatcher(dp)
        # repeats the command on repeat
        job_queue.run_repeating(self.bot_audio_repeat,
                                interval=self.interval *
                                60)  # repeated intervals
        # creates the handle for the command
        dp.add_handler(
            CommandHandler(self.command_name,
                           self.bot_audio_on_command))  # command

        updater.start_polling()
        job_queue.start()
        updater.idle()
Exemplo n.º 16
0
    def handle(self, *args, **options):
        request = Request(connect_timeout=5, read_timeout=5, con_pool_size=8)
        bot = Bot(request=request, token=config.bot_token)
        print(bot.get_me())

        job_queue = JobQueue()
        updater = Updater(bot=bot, use_context=True)

        job_queue.set_dispatcher(updater.dispatcher)
        job_queue.run_repeating(upload_hot_video, 30, name="hot")
        job_queue.run_repeating(setup_schedule, 30, name="schedule_setup")
        job_queue.start()

        message_handler = MessageHandler(Filters.text, do_echo)
        updater.dispatcher.add_handler(CommandHandler("help", help_command))
        updater.dispatcher.add_handler(CommandHandler("send", send_post))
        updater.dispatcher.add_handler(CommandHandler("set", job_maker))
        updater.dispatcher.add_handler(CommandHandler("unset", unset))
        updater.dispatcher.add_handler(message_handler)
        updater.start_polling()
        updater.idle()
Exemplo n.º 17
0
def connect(bot: Bot, update: Updater, user_data: dict, job_queue: JobQueue):
    """
    Tries to open a SSH connection from the bot server to the bridge computer.

    After that, sends a message to the chat with the result of the connection
    (successed or failed) and returns to the main menu.

    Args:
        bot (:obj:`telegram.bot.Bot`): The telegram bot instance.
        update (:obj:`telegram.ext.update.Updater`): The Updater associated to
            the bot.
        user_data (:obj:`dict`): The dictionary with user variables.
    """

    session = Session.get_from(user_data)

    # Try to connect to the client
    session.start_connection()

    # Send the status message
    view.connect_output(session).reply(update)

    if session.connected:
        # Check if the bridge computer has all the required dependencies
        initialize_bridge(bot, update, user_data)

        # Check the status of each computers (which are alive or unreachable)
        update_computers_status(user_data)

        job_queue.run_repeating(
            job_update_computers_status,
            interval=states.config_file.check_status_interval,
            context=user_data,
        )

    # Show the main menu again
    menu.new_main(bot, update, user_data)
Exemplo n.º 18
0
    def schedule(self, job_queue: JobQueue, callback: Callable) -> Job:
        """Schedule this event job in the provided job_queue"""
        upcoming_date = helper.get_upcoming_date(date.today(),
                                                 self.day_to_schedule)

        return job_queue.run_repeating(
            callback,
            interval=timedelta(weeks=1),
            first=datetime(
                upcoming_date.year,
                upcoming_date.month,
                upcoming_date.day,
                20,
                0,
                0,
            ),
            context=self.chat_id,
            name=self.job_name,
        )
Exemplo n.º 19
0
def subscribe_city_cmd(bot: Bot, update: Update, job_queue: JobQueue, chat_data, city=None):
    if not city:
        city = update.message.text[11:].lower()
    if city in all_cities:
        chat_id = update.message.chat_id
        if chat_id in subscribers and subscribers[chat_id].is_subscribed(city):
            update.message.reply_text('Das Abo lief schon. /unsubscribe für Stille im Postfach oder um die Stadt zu '
                                      'wechseln.')
        else:
            context = {'chat_id': chat_id, 'city': city}
            job = job_queue.run_repeating(callback=job_notify_subscriber, interval=15, first=1, context=context)
            try:
                chat_data['job'] = job
            except Unauthorized:
                logging.warning('unauthorized in job notify. removing job')
                job.schedule_removal()
                return
            if not chat_id in subscribers:
                subscribers[chat_id] = Subscriber(chat_id)
            subscriber = subscribers[chat_id]
            subscriber.subscribe(city)

            logging.info('{} subbed {}'.format(chat_id, city))
            update.message.reply_text(
                'Erfolgreich {} abboniert, jetzt heißt es warten auf die neue Bude.\n'
                'Zieh die Mietpreisbremse in deinem Kopf und erhalte keine Anzeigen mehr, die du dir eh nicht '
                'leisten kannst mit /filter_rent. Bsp: "/filter_rent 500" für Anzeigen bis 500€.\n'
                'Mit /filter_sex kannst du Angebote herausfiltern, die nicht für dein Geschlecht sind. Bsp: '
                '"/filter_sex m" oder eben w.\n'
                'Beende Benachrichtigungen mit /unsubscribe. Ãœber Feedback oder Fehler an [email protected] würde ich '
                'mich freuen'.format(city)
            )
    else:
        if city == '':
            update.message.reply_text('Bitte gib an in welcher Stadt du deine WG suchen möchtest.'
                                      'Verfügbare Städte: {} '
                                      'Beispiel: /subscribe MUC'.format(city, all_cities_string))
        else:
            update.message.reply_text(
                'In {} gibt\'s mich nicht, sorry. Verfügbare Städte: {}'.format(city, all_cities_string))
Exemplo n.º 20
0
 def set_job(job_queue: JobQueue):
     return job_queue.run_repeating(RepeatedHelloJob.__every_minute, JOB_INTERVAL, JOB_FIRST,
                                    context=CLEANING_GROUP_ID)
Exemplo n.º 21
0
                      InlineKeyboardMarkup, InlineKeyboardButton,
                      InputMediaPhoto)
from update_stats import update_pages
import logging, os, db

with open('secret.token', 'r') as f:
    TOKEN = f.read().split()[1]

logging.basicConfig(filename='log.log', level=logging.INFO)

updater = Updater(token=TOKEN, use_context=True)
dispatcher = updater.dispatcher

jobQ = JobQueue()
jobQ.set_dispatcher(dispatcher)
jobQ.run_repeating(update_pages, interval=1800, first=1)
jobQ.start()

dbase = db.DB('db.db')


def start(update, context):
    num_of_images = len(os.listdir('./pages'))

    keyboard = [[
        InlineKeyboardButton('⬅', callback_data="p 0"),
        InlineKeyboardButton('🔄', callback_data="p 1"),
        InlineKeyboardButton('➡', callback_data="p 2")
    ],
                [
                    InlineKeyboardButton('⏮', callback_data="p 1"),
Exemplo n.º 22
0
 def _start(self, jobs: List[telegram.ext.Job], job_queue: JobQueue, chat_id) -> None:
     new_job = job_queue.run_repeating(
         self.callback, self.repeat_time, context=chat_id, first=self.first_time)
     new_job.name = self.job_name
     jobs.append(new_job)
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)
def jq_add_festive_stats(jq: JobQueue):
    jq.run_repeating(stat_unprocessed,
                     interval=STAT_UNPROCESSED_INTERVAL,
                     first=1)
Exemplo n.º 25
0
def create_jobs(job_classes: List[BaseJob], jq: JobQueue):
    for job in job_classes:
        jq.run_repeating(job.run,
                         interval=job.get_interval(),
                         first=job.get_delay())
Exemplo n.º 26
0
    if abs(diff_percent) > 0.5:
        news_params = {
            "apiKey": NEWS_API_KEY,  # https://newsapi.org
            "qInTitle": COMPANY_NAME,
        }
        news_response = requests.get(NEWS_ENDPOINT, params=news_params)
        articles = news_response.json()["articles"]
        print(articles)
        three_articles = articles[:3]
        print(three_articles)

        formatted_articles = [
            f"{STOCK}: {up_down}{diff_percent}% " \
            f"\nHeadline: {article['title']}. \nBrief: {article['description']}"
            for article in three_articles
        ]

        for article in formatted_articles:
            context.bot.send_message(chat_id=CHAT_ID, text=article)


updater = Updater(BOT_TOKEN,
                  persistence=PicklePersistence(filename='bot_data'))
job_queue = JobQueue()
job_queue.set_dispatcher(updater.dispatcher)
job_queue.run_repeating(callback=send_notify, interval=60)
updater.start_polling()
job_queue.start()
updater.idle()
Exemplo n.º 27
0
class Bot:
    def __init__(self, logger, postgres):
        self._status = {}
        self._logger = logger
        self._postgres = postgres
        # self._updater = Updater(token=BOT_TOKEN, use_context=True)
        self._bot = TelegramBot(token=BOT_TOKEN)
        self._job_queue = JobQueue()
        self._update_queue = Queue()
        self._dispatcher = Dispatcher(self._bot, self._update_queue, use_context=True)
        self._translator = Translator(file=TRANSLATION_FILE)
        self._set_commands()
        self._load_status()
        self._set_job_queue()

# ------------------------------------------------------------------------------------------
#       INIT METHODS
# ------------------------------------------------------------------------------------------

    def _set_commands(self):
        self._dispatcher.add_handler(CommandHandler(START, self._start))
        self._dispatcher.add_handler(CommandHandler(ADD, self._add))
        self._dispatcher.add_handler(CommandHandler(FRIENDS, self._friends))
        self._dispatcher.add_handler(CommandHandler(LANGUAGE, self._language))
        self._dispatcher.add_handler(CommandHandler(HELP, self._help))
        self._dispatcher.add_handler(CallbackQueryHandler(self._callback_query))
        self._dispatcher.add_handler(MessageHandler(Filters.all, self._other_messages))
        # self._updater.dispatcher.add_handler(CommandHandler(START, self._start))
        # self._updater.dispatcher.add_handler(CommandHandler(ADD, self._add))
        # self._updater.dispatcher.add_handler(CommandHandler(FRIENDS, self._friends))
        # self._updater.dispatcher.add_handler(CommandHandler(LANGUAGE, self._language))
        # self._updater.dispatcher.add_handler(CommandHandler(HELP, self._help))
        # self._updater.dispatcher.add_handler(CallbackQueryHandler(self._callback_query))
        # self._updater.dispatcher.add_handler(MessageHandler(Filters.all, self._other_messages))

    def _load_status(self):
        command = self._postgres.commands().select_account()
        records = self._postgres.execute(command)
        if self._correct_postgres_answer(records):
            for record in records:
                self._status[record[0]] = json.loads(record[5])

    def _set_job_queue(self):
        self._job_queue.set_dispatcher(self._dispatcher)
        now = datetime.utcnow()
        to = now + timedelta(seconds=24 * 60 * 60)
        to = to.replace(hour=0, minute=0, second=30, microsecond=0)
        self._job_queue.run_repeating(
            self._it_is_time_for_birthday,
            interval=24 * 60 * 60,
            first=to.timestamp() - now.timestamp()
        )
        self._job_queue.start()

# ------------------------------------------------------------------------------------------
#       PUBLIC METHODS
# ------------------------------------------------------------------------------------------

    def start_pooling(self):
        # self._updater.start_polling()
        # self._updater.idle()
        self._bot.setWebhook(HEROKU_APP_URL + BOT_TOKEN)

    def get_dispatcher(self):
        # pass
        return self._dispatcher

    def get_update_queue(self):
        # pass
        return self._update_queue

    def get_bot(self):
        # pass
        return self._bot

# ------------------------------------------------------------------------------------------
#       COMMANDS
# ------------------------------------------------------------------------------------------

    def _start(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE] if self._status.get(account_id, None) else STANDARD_LANGUAGE
        translate = self._translator.translate
        if account_id in self._status.keys():
            self._status[account_id][STATUS] = NONE
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Я рад снова тебя приветствовать здесь!", language)
            )
        else:
            self._status[account_id] = {
                LANGUAGE: STANDARD_LANGUAGE,
                STATUS: NONE,
                BIRTHDAY: {}
            }
            command = self._postgres.commands().insert_account(
                account_id=account_id,
                first_name=update.effective_user[FIRST_NAME],
                last_name=update.effective_user[LAST_NAME],
                user_name=update.effective_user[USERNAME],
                language_code=STANDARD_LANGUAGE,
                status=json.dumps(self._status[account_id])
            )
            self._postgres.execute(command)
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Я рад тебя приветствовать у меня в гостях. У меня уютно и есть печеньки!", language)
            )
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Чтобы вы лучше понимали что я могу, воспользуйтесь командой /help. Если у вас есть желание сменить язык общения, то команда /language поможет вам это сделать!", language)
            )
        self._update_status(account_id)

    def _add(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = ADD_CONTACT
        self._status[account_id][BIRTHDAY] = {
            FIO: {
                LAST_NAME: NONE,
                FIRST_NAME: NONE,
                MIDDLE_NAME: NONE
            },
            DATE: {
                YEAR: NONE,
                MONTH: NONE,
                DAY: NONE
            },
            CONGRATULATION: NONE,
            DESIRES: NONE,
            PHONE_NUMBER: NONE,
            TELEGRAM_USER_ID: NONE
        }

        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Давайте начнем заполнение анкеты вашего друга. Сперва пришлите контакт друга", language)
        )
        self._update_status(account_id)

    def _friends(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = NONE

        birthday_command = self._postgres.commands().select_birthday_for_account(account_id)
        birthday_records = self._postgres.execute(birthday_command)
        if self._correct_postgres_answer(birthday_records):
            text = translate("Вот список добавленных друзей:", language) + "\n\n"
            for birthday_record in birthday_records:
                text += "{fio} {birthday}\n".format(
                    fio=str(" ".join([birthday_record[3], birthday_record[1], birthday_record[2]])).strip(),
                    birthday=birthday_record[6].strftime("%Y-%m-%d")
                )
            context.bot.send_message(
                chat_id=update.message.chat_id,
                text=text[:-1]
            )
        else:
            context.bot.send_message(
                chat_id=update.message.chat_id,
                text=translate("Вы еще не добавили ни одного друга!", language)
            )
        self._update_status(account_id)

    def _language(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = LANGUAGE
        languages = [(key, value) for key, value in self._translator.languages().items() if key != language]
        keyboard = [
            [
                InlineKeyboardButton(languages[0][1], callback_data=languages[0][0]),
                InlineKeyboardButton(languages[1][1], callback_data=languages[1][0])
            ]
        ]
        reply_markup = InlineKeyboardMarkup(keyboard)
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Сейчас установленный язык русский. На какой Вы желаете изменить?", language),
            reply_markup=reply_markup
        )
        self._update_status(account_id)

    def _help(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = NONE
        context.bot.send_message(
            chat_id=update.message.chat_id,
            text=translate("BirthdayBot создан для напоминания о днях рождениях твоих друзей! "
                           "Вдруг у вас много работы или дел по дому, то я всегда дам вам знать, "
                           "что особенный день близко!\\n\\n"
                           "Чтобы я смог напомнить вам о дне рождения, вам необходимо заполнить анкету друга! "
                           "Для заполнения анкеты существует команда /add\\n\\n"
                           "При необходимости сменить язык общения - можно отправить команду /language", language)
        )
        self._update_status(account_id)

    def _callback_query(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        query_data = update.callback_query.data
        status = self._status[account_id][STATUS]
        if status == LANGUAGE:
            self._language_in_callback_query(update, context)
        elif status == CREATE:
            context.bot.answer_callback_query(callback_query_id=update.callback_query.id)
            if query_data == ADD_FIO:
                self._add_fio_in_callback_query(update, context)
            elif query_data == ADD_DATE:
                self._add_date_in_callback_query(update, context)
            elif query_data == ADD_CONGRATULATION:
                self._add_congratulation_in_callback_query(update, context)
            elif query_data == ADD_DESIRES:
                self._add_desires_in_callback_query(update, context)
            elif query_data == CREATE:
                self._create_in_callback_query(update, context)
        else:
            self._invalid_in_callback_query(update, context)

    def _other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        status = self._status[account_id][STATUS]

        if status == ADD_CONTACT:
            self._add_contact_in_other_messages(update, context)
        elif status == ADD_DATE_INTERVAL:
            self._add_date_interval_in_other_messages(update, context)
        elif status == ADD_DATE_YEAR:
            self._add_date_year_in_other_messages(update, context)
        elif status == ADD_DATE_MONTH:
            self._add_date_month_in_other_messages(update, context)
        elif status == ADD_DATE_DAY:
            self._add_date_day_in_other_messages(update, context)
        elif status == ADD_FIO_LAST_NAME:
            self._add_fio_last_name_in_other_messages(update, context)
        elif status == ADD_FIO_FIRST_NAME:
            self._add_fio_first_name_in_other_messages(update, context)
        elif status == ADD_FIO_MIDDLE_NAME:
            self._add_fio_middle_name_in_other_messages(update, context)
        elif status == ADD_CONGRATULATION:
            self._add_congratulation_in_other_messages(update, context)
        elif status == ADD_DESIRES:
            self._add_desires_in_other_messages(update, context)
        else:
            self._invalid_in_other_messages(update, context)

# ------------------------------------------------------------------------------------------
#       JOBQUEUE METHODS
# ------------------------------------------------------------------------------------------

    def _it_is_time_for_birthday(self, dispatcher):
        self._logger.info("_it_is_time_for_birthday", "i am here")

        account_command = self._postgres.commands().select_account()
        account_records = self._postgres.execute(account_command)
        translate = self._translator.translate
        if self._correct_postgres_answer(account_records):
            for account_record in account_records:
                account_id = account_record[0]
                language = self._status[account_id][LANGUAGE]

                birthday_command = self._postgres.commands().select_birthday_for_account(account_record[0])
                birthday_records = self._postgres.execute(birthday_command)
                if self._correct_postgres_answer(birthday_records):
                    for birthday_record in birthday_records:
                        datetime_birthday = datetime.strptime(birthday_record[6].strftime("%Y-%m-%d"), "%Y-%m-%d")

                        birthday = {
                            FIO: {
                                LAST_NAME: birthday_record[1],
                                FIRST_NAME: birthday_record[2],
                                MIDDLE_NAME: birthday_record[3]
                            },
                            DATE: {
                                YEAR: str(datetime_birthday.year),
                                MONTH: str(datetime_birthday.month),
                                DAY: str(datetime_birthday.day)
                            }
                        }
                        remind7, remind1 = birthday_record[9], birthday_record[10]
                        datetime_birthday = datetime_birthday.replace(year=datetime.utcnow().year)
                        if datetime.utcnow().timestamp() > datetime_birthday.timestamp():
                            datetime_birthday = datetime_birthday.replace(year=datetime.utcnow().year + 1)
                        if datetime_birthday.timestamp() - datetime.utcnow().timestamp() <= 24 * 60 * 60 and remind1:
                            dispatcher.bot.send_message(
                                chat_id=account_record[0],
                                text=translate("У твоего друга менее чем через сутки день рождения!\\n\\n"
                                               "{fio} исполняется {age}!\\n\\n"
                                               "Не забудь поздравить именинника и постарайся сделать его день рождения незабываемым! "
                                               "Надеюсь, что подарок ты уже приготовил!", language).format(
                                    fio=str(" ".join(birthday[FIO].values())).strip(),
                                    age=str(datetime.utcnow().year - int(birthday[DATE][YEAR])),
                                )
                            )
                            remind7, remind1 = True, True
                        elif datetime_birthday.timestamp() - datetime.utcnow().timestamp() <= 7 * 24 * 60 * 60 and remind7:
                            dispatcher.bot.send_message(
                                chat_id=account_record[0],
                                text=translate(
                                    "У твоего друга менее чем через неделю день рождения!\\n\\n"
                                    "{fio} исполнится {age}!\\n\\n" 
                                    "Приготовь хороший подарок, надеюсь ты знаешь что бы он хотел! "
                                    "Не забудь поздравить именинника и постарайся "
                                    "сделать его день рождения незабываемым!", language).format(
                                    fio=str(" ".join(birthday[FIO].values())).strip(),
                                    age=str(datetime.utcnow().year - int(birthday[DATE][YEAR])),
                                )
                            )
                            remind7, remind1 = False, True
                        command = self._postgres.commands().update_remind(remind7, remind1, birthday_record[0])
                        self._postgres.execute(command)

# ------------------------------------------------------------------------------------------
#       PRIVATE METHODS
# ------------------------------------------------------------------------------------------

    @staticmethod
    def _correct_postgres_answer(answer):
        return True if answer and len(answer) > 0 else False

    def _send_create_message(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = CREATE
        keyboard = [
            [
                InlineKeyboardButton(translate("ФИО", language), callback_data=ADD_FIO),
                InlineKeyboardButton(translate("Дата рождения", language), callback_data=ADD_DATE)
            ],
            [
                InlineKeyboardButton(translate("Поздравление", language), callback_data=ADD_CONGRATULATION),
                InlineKeyboardButton(translate("Пожелания", language), callback_data=ADD_DESIRES)
            ],
            [
                InlineKeyboardButton(translate("Создать", language), callback_data=CREATE)
            ]
        ]
        reply_markup = InlineKeyboardMarkup(keyboard)
        year = self._status[account_id][BIRTHDAY][DATE][YEAR]
        month = self._status[account_id][BIRTHDAY][DATE][MONTH]
        day = self._status[account_id][BIRTHDAY][DATE][DAY]

        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Давай посмотрим что получилось!", language),
            reply_markup=ReplyKeyboardRemove()
        )
        fio_value = ' '.join(value for value in self._status[account_id][BIRTHDAY][FIO].values() if value)
        congratulation = self._status[account_id][BIRTHDAY][CONGRATULATION]
        congratulation_value = congratulation if congratulation else translate("не задано", language)
        desires = self._status[account_id][BIRTHDAY][DESIRES]
        desires_value = desires if desires else translate("не задано", language)
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text="{text}:\n\n"
                 "<b>{fio}</b>: {fio_value}\n"
                 "<b>{date}</b>: {date_value}\n"
                 "<b>{congratulation}</b>: {congratulation_value}\n"
                 "<b>{desires}</b>: {desires_value}".format(
                  text=translate("Анкета друга", language),
                  fio=translate("ФИО", language),
                  date=translate("Дата рождения", language),
                  congratulation=translate("Поздравление", language),
                  desires=translate("Пожелания", language),
                  fio_value=fio_value,
                  date_value="{0}-{1}-{2}".format(year, month, day),
                  congratulation_value=congratulation_value,
                  desires_value=desires_value),
            reply_markup=reply_markup,
            parse_mode=ParseMode.HTML
        )
        self._update_status(account_id)

    def _it_is_time_for_birthday_after_create(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        birthday = self._status[account_id][BIRTHDAY]
        datetime_birthday = datetime(
            int(birthday[DATE][YEAR]),
            int(birthday[DATE][MONTH]),
            int(birthday[DATE][DAY]),
            0, 0, 0
        )
        remind7, remind1 = True, True
        datetime_birthday = datetime_birthday.replace(year=datetime.utcnow().year)
        if datetime.utcnow().timestamp() > datetime_birthday.timestamp():
            datetime_birthday = datetime_birthday.replace(year=datetime.utcnow().year + 1)
        if datetime_birthday.timestamp() - datetime.utcnow().timestamp() <= 24 * 60 * 60:
            context.bot.send_message(
                chat_id=update.callback_query.message.chat_id,
                text=translate("У твоего друга менее чем через сутки день рождения!\\n\\n"
                               "{fio} исполняется {age}!\\n\\n"
                               "Не забудь поздравить именинника и постарайся сделать его день рождения незабываемым! "
                               "Надеюсь, что подарок ты уже приготовил!", language).format(
                         fio=str(" ".join(birthday[FIO].values())).strip(),
                         age=str(datetime.utcnow().year - int(birthday[DATE][YEAR])),
                     )
            )
        elif datetime_birthday.timestamp() - datetime.utcnow().timestamp() <= 7 * 24 * 60 * 60:
            context.bot.send_message(
                chat_id=update.callback_query.message.chat_id,
                text=translate(
                    "У твоего друга менее чем через неделю день рождения!\\n\\n"
                    "{fio} исполнится {age}!\\n\\n" 
                    "Приготовь хороший подарок, надеюсь ты знаешь что бы он хотел! "
                    "Не забудь поздравить именинника и постарайся "
                    "сделать его день рождения незабываемым!", language).format(
                    fio=str(" ".join(birthday[FIO].values())).strip(),
                    age=str(datetime.utcnow().year - int(birthday[DATE][YEAR])),
                )
            )
            remind7 = False
        command = self._postgres.commands().select_specific_birthday(
            account_id=account_id,
            first_name=birthday[FIO][FIRST_NAME],
            last_name=birthday[FIO][LAST_NAME],
            middle_name=birthday[FIO][MIDDLE_NAME]
        )
        specific_birthday = self._postgres.execute(command)
        if self._correct_postgres_answer(specific_birthday):
            command = self._postgres.commands().update_remind(remind7, remind1, specific_birthday[0][0])
            self._postgres.execute(command)

    def _update_status(self, account_id):
        command = self._postgres.commands().update_status(json.dumps(self._status[account_id]), account_id)
        self._postgres.execute(command)

# ------------------------------------------------------------------------------------------
#       CALLBACK QUERY METHODS
# ------------------------------------------------------------------------------------------

    def _language_in_callback_query(self, update, context):
        query_data = update.callback_query.data
        account_id = update.effective_user[ACCOUNT_ID]
        translate = self._translator.translate
        language = query_data
        command = self._postgres.commands().update_language(
            language_code=query_data,
            account_id=account_id
        )
        self._postgres.execute(command)
        self._status[account_id][LANGUAGE] = query_data
        self._status[account_id][STATUS] = NONE
        context.bot.edit_message_text(
            chat_id=update.callback_query.message.chat_id,
            message_id=update.callback_query.message.message_id,
            text=translate("Вы изменили язык на русский!", language)
        )
        self._update_status(account_id)

    def _add_fio_in_callback_query(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = ADD_FIO_LAST_NAME
        context.bot.send_message(
            chat_id=update.callback_query.message.chat_id,
            text=translate("Введите фамилию друга", language)
        )
        self._update_status(account_id)

    def _add_date_in_callback_query(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = ADD_DATE_INTERVAL
        start_year = 1930
        keyboard = [
            [
                "{0} - {1}".format(
                    start_year + (2 * i + j) * 12, start_year + (2 * i + j) * 12 + 11
                ) for j in range(2)
            ] for i in range(4)
        ]
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Введите интервал даты рождения", language),
            reply_markup=ReplyKeyboardMarkup(
                keyboard=keyboard,
                resize_keyboard=True
            )
        )
        self._update_status(account_id)

    def _add_congratulation_in_callback_query(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = ADD_CONGRATULATION
        context.bot.send_message(
            chat_id=update.callback_query.message.chat_id,
            text=translate("Введите поздравление для друга", language)
        )
        self._update_status(account_id)

    def _add_desires_in_callback_query(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = ADD_DESIRES
        context.bot.send_message(
            chat_id=update.callback_query.message.chat_id,
            message_id=update.callback_query.message.message_id,
            text=translate("Введите желания друга", language)
        )
        self._update_status(account_id)

    def _create_in_callback_query(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.answer_callback_query(callback_query_id=update.callback_query.id)
        birthday = self._status[account_id][BIRTHDAY]
        year = birthday[DATE][YEAR]
        month = birthday[DATE][MONTH]
        day = birthday[DATE][DAY]
        command = self._postgres.commands().insert_birthday(
            last_name=birthday[FIO][LAST_NAME],
            first_name=birthday[FIO][FIRST_NAME],
            middle_name=birthday[FIO][MIDDLE_NAME],
            phone_number=birthday[PHONE_NUMBER],
            user_id=birthday[TELEGRAM_USER_ID],
            date="{0}-{1}-{2}".format(year, month, day),
            congratulation=birthday[CONGRATULATION],
            desires=birthday[DESIRES],
            remind7=True,
            remind1=True,
            account_id=account_id
        )
        self._postgres.execute(command)
        context.bot.edit_message_text(
            chat_id=update.callback_query.message.chat_id,
            message_id=update.callback_query.message.message_id,
            text=translate("Вы успешно добавили информацию о друге!", language)
        )
        self._it_is_time_for_birthday_after_create(update, context)
        self._status[account_id][STATUS] = NONE
        self._status[account_id][BIRTHDAY] = {}
        self._update_status(account_id)

    def _invalid_in_callback_query(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.edit_message_text(
            chat_id=update.callback_query.message.chat_id,
            message_id=update.callback_query.message.message_id,
            text=translate("К сожалению, я не поддерживаю данное сообщение!", language)
        )

# ------------------------------------------------------------------------------------------
#       OTHER METHODS
# ------------------------------------------------------------------------------------------

    def _add_contact_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        if update.effective_message[ATTACHMENTS_CONTACT]:
            birthday = self._status[account_id][BIRTHDAY]
            first_name = update.effective_message[CONTACT][FIRST_NAME]
            last_name = update.effective_message[CONTACT][LAST_NAME]
            phone_number = update.effective_message[CONTACT][PHONE_NUMBER]
            user_id = update.effective_message[CONTACT][TELEGRAM_USER_ID]
            birthday[FIO][LAST_NAME] = last_name if last_name and len(last_name) > 0 else NONE
            birthday[FIO][FIRST_NAME] = first_name if first_name and len(first_name) > 0 else NONE
            birthday[PHONE_NUMBER] = phone_number if phone_number and len(phone_number) > 0 else NONE
            birthday[TELEGRAM_USER_ID] = user_id if user_id else 0
            self._status[account_id][STATUS] = ADD_DATE_INTERVAL
            start_year = 1930
            keyboard = [
                [
                    "{0} - {1}".format(
                        start_year + (2 * i + j) * 12, start_year + (2 * i + j) * 12 + 11
                    ) for j in range(2)
                ] for i in range(4)
            ]
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Введите интервал даты рождения", language),
                reply_markup=ReplyKeyboardMarkup(
                    keyboard=keyboard,
                    resize_keyboard=True
                )
            )
        else:
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Будьте так любезны, пришлите мне контакт именинника!", language)
            )
        self._update_status(account_id)

    def _add_date_interval_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = ADD_DATE_YEAR
        interval = update.effective_message.text
        begin = int(interval[0:4])
        keyboard = [
            [
                "{0}".format(begin + 3 * i + j) for j in range(3)
            ] for i in range(4)
        ]
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Введите год даты рождения", language),
            reply_markup=ReplyKeyboardMarkup(
                keyboard=keyboard,
                resize_keyboard=True
            )
        )
        self._update_status(account_id)

    def _add_date_year_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][BIRTHDAY][DATE] = {
            YEAR: NONE,
            MONTH: NONE,
            DAY: NONE
        }
        self._status[account_id][BIRTHDAY][DATE][YEAR] = update.effective_message.text
        self._status[account_id][STATUS] = ADD_DATE_MONTH
        keyboard = [
            [
                translate(MONTH_LIST[3 * i + j], language) for j in range(3)
            ] for i in range(4)
        ]
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Введите месяц даты рождения", language),
            reply_markup=ReplyKeyboardMarkup(
                keyboard=keyboard,
                resize_keyboard=True
            )
        )
        self._update_status(account_id)

    def _add_date_month_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        self._status[account_id][STATUS] = ADD_DATE_DAY
        month_arr = [translate(month, language) for month in MONTH_LIST]
        self._status[account_id][BIRTHDAY][DATE][MONTH] = str(month_arr.index(update.effective_message.text) + 1)
        year = int(self._status[account_id][BIRTHDAY][DATE][YEAR])
        month = int(self._status[account_id][BIRTHDAY][DATE][MONTH])
        days = calendar.monthrange(year, month)[1]
        keyboard = [
            [
                str(4 * i + j + 1) for j in range(4) if 4 * i + j + 1 <= days
            ] for i in range(days // 4 + 1)
        ]
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Введите день даты рождения", language),
            reply_markup=ReplyKeyboardMarkup(
                keyboard=keyboard,
                resize_keyboard=True
            )
        )
        self._update_status(account_id)

    def _add_date_day_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        self._status[account_id][BIRTHDAY][DATE][DAY] = update.effective_message.text
        self._send_create_message(update, context)
        self._update_status(account_id)

    def _add_fio_last_name_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        if update.effective_message.text:
            self._status[account_id][STATUS] = ADD_FIO_FIRST_NAME
            self._status[account_id][BIRTHDAY][FIO][LAST_NAME] = update.effective_message.text
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Введите имя друга", language)
            )
        else:
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Будьте так любезны, введите фамилию друга", language)
            )
        self._update_status(account_id)

    def _add_fio_first_name_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        if update.effective_message.text:
            self._status[account_id][STATUS] = ADD_FIO_MIDDLE_NAME
            self._status[account_id][BIRTHDAY][FIO][FIRST_NAME] = update.effective_message.text
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Введите отчество друга", language)
            )
        else:
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Будьте так любезны, введите имя друга", language)
            )
        self._update_status(account_id)

    def _add_fio_middle_name_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        if update.effective_message.text:
            self._status[account_id][BIRTHDAY][FIO][MIDDLE_NAME] = update.effective_message.text
            self._send_create_message(update, context)
        else:
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Будьте так любезны, введите отчество друга", language)
            )
        self._update_status(account_id)

    def _add_congratulation_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        if update.effective_message.text:
            self._status[account_id][BIRTHDAY][CONGRATULATION] = update.effective_message.text
            self._send_create_message(update, context)
        else:
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Будьте так любезны, пришлите мне поздравление для именинника!", language)
            )
        self._update_status(account_id)

    def _add_desires_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        if update.effective_message.text:
            self._status[account_id][BIRTHDAY][DESIRES] = update.effective_message.text
            self._send_create_message(update, context)
        else:
            context.bot.send_message(
                chat_id=update.effective_message.chat_id,
                text=translate("Будьте так любезны, пришлите мне пожелания к подарку для именинника!", language)
            )
        self._update_status(account_id)

    def _invalid_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        self._status[account_id][STATUS] = CREATE if self._status[account_id][STATUS] == CREATE else NONE

        if update.effective_message[ATTACHMENTS_AUDIO]:
            self._audio_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_DOCUMENT]:
            self._document_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_PHOTO]:
            self._photo_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_STICKER]:
            self._sticker_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_VIDEO]:
            self._video_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_VOICE]:
            self._voice_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_VIDEO_NOTE]:
            self._video_note_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_CONTACT]:
            self._contact_note_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_LOCATION]:
            self._location_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_VENUE]:
            self._venue_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_GAME]:
            self._game_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_ANIMATION]:
            self._animation_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_INVOICE]:
            self._invoice_in_other_messages(update, context)
        elif update.effective_message[ATTACHMENTS_SUCCESSFUL_PAYMENT]:
            self._successful_payment_in_other_messages(update, context)
        else:
            self._unprocessed_other_messages(update, context)
        self._update_status(account_id)

# ------------------------------------------------------------------------------------------
#       ATTACHMENT METHODS
# ------------------------------------------------------------------------------------------

    def _audio_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("У вас определенно хороший музыкальный вкус!", language)
        )

    def _document_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Я обязательно прочту ваш документ и напишу рецензию!", language)
        )

    def _photo_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Как вы смеете мне присылать такие фото!", language)
        )

    def _sticker_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("У меня есть набор стикеров поинтереснее!", language)
        )

    def _video_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Это видео я отправлю в Роскомнадзор, там с вами разберутся!", language)
        )

    def _voice_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Какой милый голосок! Прочитай мне сказку!", language)
        )

    def _video_note_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Если я буду присылать такие видео как проснусь, то я буду выглядеть намного лучше!", language)
        )

    def _contact_note_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("ФСБ проверит твой контакт, я уже передал!", language)
        )

    def _location_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Если там собираются красивые девушки, то я уже выезжаю!", language)
        )

    def _venue_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Там определенно продаются самые вкусные пончики в мире!", language)
        )

    def _game_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Я в такие игры не играю! Я еще маленький!", language)
        )

    def _animation_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Рассмашил так рассмешил! Мне понравилось!", language)
        )

    def _invoice_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Я такого не заказывал! Хочу оформить возврат!", language)
        )

    def _successful_payment_in_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("Если вы отдаете мне это бесплатно, то я готов принять подарок!", language)
        )

    def _unprocessed_other_messages(self, update, context):
        account_id = update.effective_user[ACCOUNT_ID]
        language = self._status[account_id][LANGUAGE]
        translate = self._translator.translate
        context.bot.send_message(
            chat_id=update.effective_message.chat_id,
            text=translate("К сожалению, я не поддерживаю данное сообщение!", language)
        )
Exemplo n.º 28
0
def setup():
    bot = Bot(token=conf['BOT_TOKEN'])
    update_queue = Queue()
    dp = Dispatcher(bot, update_queue)
    jq = JobQueue(bot)

    # Commands for admin
    dp.add_handler(CommandHandler('start', start))
    dp.add_handler(
        CommandHandler('apod',
                       apod,
                       pass_args=True,
                       filters=Filters.user(username=conf['ADMIN'])))
    dp.add_handler(
        CommandHandler('epic',
                       epic,
                       pass_args=True,
                       filters=Filters.user(username=conf['ADMIN'])))
    dp.add_handler(
        CommandHandler('mars',
                       mars_photos,
                       pass_args=True,
                       filters=Filters.user(username=conf['ADMIN'])))
    dp.add_handler(
        CommandHandler('db',
                       test_db_command,
                       filters=Filters.user(username=conf['ADMIN'])))
    dp.add_error_handler(error)

    #
    jq.run_repeating(check_apod_updates,
                     interval=3600,
                     first=0,
                     context=make_apod_context(bot, TESTING))
    jq.run_repeating(check_epic_updates,
                     interval=3600,
                     first=15 if TESTING else 500,
                     context=make_epic_context(bot, TESTING))
    jq.run_daily(check_mars_photos_updates,
                 time=time(9),
                 context={
                     'Curiosity': 2320,
                     'Opportunity': 5111,
                     'Spirit': 2208,
                     'all': ['Curiosity', 'Opportunity', 'Spirit']
                 })

    s = bot.set_webhook(
        url='https://salty-escarpment-89606.herokuapp.com/hook/' +
        conf['BOT_TOKEN'])
    if s:
        print(s)
        logger.info('webhook setup ok')
    else:
        print(s)
        logger.info('webhook setup failed')

    thread = Thread(target=dp.start, name='dispatcher')
    thread.start()
    jq.start()

    return update_queue, bot
Exemplo n.º 29
0
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)
Exemplo n.º 30
0
def photos_post(job_queue: JobQueue):
    def job(context: CallbackContext):
        log.debug('Start photos post job')
        upload()

    job_queue.run_repeating(job, interval=30, first=30)
Exemplo n.º 31
0
class Bot(object):

    START_MESSAGE = "Hello, I am a bot, nice to meet you. You may use /help to read what my commands do."
    ADD_USAGE = "/add <url> <m> <keyword 1> <keyword 2> ..."
    LIST_USAGE = "/list"
    REMOVE_USAGE = "/remove <url>"

    # Help message.
    HELP_MESSAGE = f"""*KeywordScrapeBot*:\n
{ADD_USAGE}
Add a job that runs every m minutes (minimum 15), scanning the url for links containing the keywords.
Running the command again for the same url will overwrite the job.\n
{LIST_USAGE}
List your running jobs.\n
{REMOVE_USAGE}
Remove a job.
    """

    def __init__(self,
                 bot_token: str,
                 database_file: Union[str, Path],
                 minimum_interval: int = 15):
        """
        :param bot_token: The token to run the bot on.
        :param database_file: The database file.
        :param minimum_interval: The minimum update interval in minutes. Defaults to 15.
        """
        self._database_file = database_file
        self._minimum_interval = minimum_interval

        self._updater = Updater(token=bot_token, use_context=True)
        self._updater.dispatcher.add_handler(
            CommandHandler("start", self._add_user))
        self._updater.dispatcher.add_handler(
            CommandHandler("list", self._list_jobs))
        self._updater.dispatcher.add_handler(
            CommandHandler("add", self._add_job))
        self._updater.dispatcher.add_handler(
            CommandHandler("remove", self._remove_job))
        self._updater.dispatcher.add_handler(
            CommandHandler("help", self._send_help))

        self._job_queue = JobQueue()
        self._job_queue.set_dispatcher(self._updater.dispatcher)
        self._job_queue.start()

        # Keep map {(user, url) : telegram.ext.Job} to allow canceling jobs.
        self._job_map = dict()

        # Load all Jobs in the database.
        for job in Database(self._database_file).get_jobs():
            self._schedule(job)

    def start(self):
        self._updater.start_polling()

    def idle(self):
        self._updater.idle()

    def _add_user(self, update: telegram.Update,
                  context: telegram.ext.CallbackContext):
        """
        Callback for the addition of a user.
        """
        user = update.effective_chat.id
        # Add user to database.
        Database(self._database_file).add_user(user)
        # Answer user.
        context.bot.send_message(chat_id=user, text=self.START_MESSAGE)
        # Log the info about the new user.
        logging.info(f"/start command received by user: {user}.")

    def _add_job(self, update: telegram.Update,
                 context: telegram.ext.CallbackContext):
        f"""
        Callback for the update of a job. Message must be:
        ```
        {Bot.ADD_USAGE}
        ```
        """
        user = update.effective_chat.id
        try:
            # Extract info.
            url = context.args[0]

            # Check url validity.
            if not utils.is_valid_url(url):
                update.message.reply_text(f"{url} is not a valid url.",
                                          disable_web_page_preview=True)
                logging.warning(f"Invalid url from user {user}.")
                return

            # Check minimum time
            freq = int(context.args[1])
            if freq < self._minimum_interval:
                update.message.reply_text(
                    f"{self._minimum_interval} minutes is the minimum time. I'll just set it for you."
                )
                freq = self._minimum_interval

            keywords = context.args[2::] if len(context.args) > 2 else list()

            # Update database.
            job = Job(user, url, freq, keywords)
            Database(self._database_file).add_job(job)

            # Schedule job.
            self._schedule(job)

            # Send back a response as a confirmation.
            response = f"Will start searching {url} for links containing {', '.join(keywords)} every {freq} minutes."
            update.message.reply_text(response, disable_web_page_preview=True)
            logging.info(f"/add command received by user: {user}. {response}")

        except (IndexError, ValueError):
            update.message.reply_text(f"Usage: {Bot.ADD_USAGE}")
            logging.warning(f"Inappropriate /add command from user {user}.")

    def _list_jobs(self, update: telegram.Update,
                   context: telegram.ext.CallbackContext):
        """
        Send a message containing the scheduled jobs for the user.
        """
        user = update.effective_chat.id
        jobs = Database(self._database_file).get_jobs(user)
        if jobs:
            update.message.reply_markdown("\n---\n".join([
                f"*JOB {i + 1}*\nurl: {j.url}\nkeywords: {j.keywords}\nEvery {j.freq} hours."
                for i, j in enumerate(jobs)
            ]),
                                          disable_web_page_preview=True)
        else:
            update.message.reply_text(f"No jobs scheduled.")
        logging.info(f"Sent job list to {user}.")

    def _remove_job(self, update: telegram.Update,
                    context: telegram.ext.CallbackContext):
        f"""
        Callback for the removal of a job. Message must be:
        ```
        {Bot.REMOVE_USAGE}
        ```
        """
        user = update.effective_chat.id
        try:
            url = context.args[0]
            db = Database(self._database_file)
            jobs = db.get_jobs(user)

            # Job not in database.
            if url not in [j.url for j in jobs]:
                update.message.reply_text(f"You have no job for url: {url}",
                                          disable_web_page_preview=True)
                logging.info(
                    f"User {user} asked for removal of non-existing job {url}")
                return

            # Job in db, delete and unschedule job.
            db.delete_job(user, url)
            self._unschedule(user, url)

            # Send back a response.
            update.message.reply_text(
                f"You will receive no more updates from: {url}",
                disable_web_page_preview=True)
            logging.info(f"Removed job {url} for user {user}.")

        except IndexError:
            update.message.reply_text(f"Usage: {Bot.REMOVE_USAGE}")
            logging.warning(f"Inappropriate /remove command from user {user}.")

    def _send_help(self, update: telegram.Update,
                   context: telegram.ext.CallbackContext):
        """
        Send help message.
        """
        user = update.effective_chat.id
        # Answer user.
        context.bot.send_message(chat_id=user,
                                 text=self.HELP_MESSAGE,
                                 parse_mode="markdown")
        logging.info(f"Sent help to user: {user}.")

    def _schedule(self, job: Job):
        """
        Schedule a new job for the bot. Tries to remove any previous job for the same key (user, url)

        :param job: The new job to schedule.
        """
        # Safely remove any old matching job.
        self._unschedule(job.user, job.url)

        # Set job to run every x hours and keep track to cancel it later.
        self._job_map[(job.user, job.url)] = self._job_queue.run_repeating(
            make_job_callback(job, self._database_file), 60 * job.freq, 1)
        logging.info(f"Started job on url {job.url} for user {job.user}.")

    def _unschedule(self, user: int, url: str):
        """
        Remove the corresponding job from the queue.

        :param user: The user of the job.
        :param url: The url of the job.
        """
        old_job = self._job_map.pop((user, url), 0)
        if old_job != 0:
            old_job.schedule_removal()
            logging.info(f"Removed Telegram job on url {url} for user {user}.")

    def __del__(self):
        # Stop za bot.
        self._job_queue.stop()
        self._updater.stop()