def inlinebutton_timezone(update: Update, context: CallbackContext,
                          query: CallbackQuery, args: List[str]):
    continents = sorted(
        set([x.partition('/')[0] for x in pytz.common_timezones]))
    location = args[0]
    if location == 'region_selection':
        reply = get_timezone_region_markup(continents)
        query.edit_message_text('Choose your region')
        query.edit_message_reply_markup(reply)
    elif location in pytz.all_timezones:
        redis.set(f'chat:{query.message.chat_id}:settings:timezone', location)
        tz = timezone(location)
        local_time = query.message.date.astimezone(tz).strftime('%X')
        reply = InlineKeyboardMarkup([[
            (InlineKeyboardButton('Change timezone',
                                  callback_data='timezone:region_selection'))
        ]])
        query.edit_message_text(
            f'Timezone of this chat was set to {location}. '
            f'Looks like it was {local_time} when you sent the last /timezone command. '
            'If this is incorrect, please execute /timezone again or click the button below.'
        )
        query.edit_message_reply_markup(reply)
    elif location in continents:
        zones = [x for x in pytz.all_timezones if x.startswith(location)]
        reply = InlineKeyboardMarkup([[
            InlineKeyboardButton(x.partition('/')[2],
                                 callback_data=':'.join(['timezone', x]))
        ] for x in zones] + [[(InlineKeyboardButton(
            '« Back', callback_data='timezone:region_selection'))]], )
        query.edit_message_text('Choose your timezone')
        query.edit_message_reply_markup(reply)
def handle_delete_last_command(update: Update, context: CallbackContext):
    chat_id = update.message.chat_id
    queue_size = redis.get(f'chat:{chat_id}:queue_size')
    if queue_size is None:
        queue_size = 0
    queue_size = int(queue_size)
    if queue_size <= 0:
        context.bot.send_message(chat_id=chat_id, text='Queue is empty')
        return
    queue_size -= 1

    tweet_text = redis.get(f'chat:{chat_id}:queue:{queue_size}:text') or ''
    tg_attachment_id = redis.get(
        f'chat:{chat_id}:queue:{queue_size}:tg_attachment_id')

    redis.delete(f'chat:{chat_id}:queue:{queue_size}:text')
    redis.delete(f'chat:{chat_id}:queue:{queue_size}:tg_attachment_id')

    redis.set(f'chat:{chat_id}:queue_size', queue_size)

    context.bot.send_message(
        chat_id=chat_id,
        text="I've deleted your latest tweet. This was the text: " +
        tweet_text)
    if tg_attachment_id:
        context.bot.send_message(chat_id=chat_id,
                                 text='It also had an attachment')
def inlinebutton_tweet_time(update: Update, context: CallbackContext,
                            query: CallbackQuery, args: List[str]):
    try:
        tweet_time = datetime.strptime(':'.join(args),
                                       '%H:%M').strftime("%H:%M")
    except ValueError:
        query.edit_message_text(
            "Sorry, I didn't understand that time. Time must be in format %H:%M"
        )
        return
    redis.set(f'chat:{query.message.chat_id}:settings:tweet_time', tweet_time)
    query.edit_message_text(f'I will tweet at {tweet_time}')
Example #4
0
File: tweets.py Project: cvan/mula
def run():
    # When the run started.
    timestamp = datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S')
    redis_timestamp = datetime.datetime.today().strftime('%Y%m%d%H%M%S')
    print timestamp

    # Sorted Set.
    # key: runs
    # score: redis_timestamp
    # value: timestamp
    redis.zadd('runs', timestamp, redis_timestamp)

    if settings.MOCK:
        counts = {}
        counts['exact'] = {'composed': 1, 'elated': 8, 'energetic': 2, 'tired': 1, 'depressed': 6, 'anxious': 4, 'confident': 1, 'agreeable': 5}
        counts['fuzzy'] = {'composed': 10, 'elated': 80, 'energetic': 20, 'tired': 10, 'depressed': 60, 'anxious': 40, 'confident': 10, 'agreeable': 50}
        #
        # TODO: Add total analyzed, etc.
        #
    else:
        counts = process_tweets(search_terms)
    print counts

    for mood in moods:
        for precision, sub_counts in counts.iteritems():
            # Set.
            # key: runs:<redis_timestamp>:<precision [exact or fuzzy]>:<mood>
            # value: <count>
            redis.set('runs:%s:moods:%s:%s' % (redis_timestamp, precision, mood),
                      sub_counts.get(mood, 0))

    for total in totals:
        for precision, sub_counts in counts.iteritems():
            # Set.
            # key: runs:<redis_timestamp>:<precision [exact or fuzzy]>:<total>
            # value: <count>
            redis.set('runs:%s:totals:%s:%s' % (redis_timestamp, precision, total),
                      sub_counts.get(total, 0))
def handle_authorize_command(update: Update, context: CallbackContext):
    chat_id = update.message.chat_id
    auth = get_twitter_auth()
    if not update.message:
        return
    try:
        _, oauth_token, oauth_verifier = update.message.text.split()
    except ValueError:
        context.bot.send_message(
            chat_id=chat_id,
            text=
            'Invalid authentication details. Expected OAUTH_TOKEN OAUTH_VERIFIER. '
            'If you want to start authorization, click on /start')
        return
    auth.request_token = {
        'oauth_token': oauth_token,
        'oauth_token_secret': oauth_verifier,
    }
    try:
        access_token, access_token_secret = auth.get_access_token(
            oauth_verifier)
    except tweepy.TweepError:
        context.bot.send_message(
            chat_id=chat_id,
            text='I was unable to get an access token. Try again: /start')
        return
    redis.set(f'chat:{chat_id}:oauth:access_token', access_token)
    redis.set(f'chat:{chat_id}:oauth:access_token_secret', access_token_secret)
    if not redis.get(f'chat:{chat_id}:settings:timezone'):
        redis.set(f'chat:{chat_id}:settings:timezone', 'UTC')
    tz = redis.get(f'chat:{chat_id}:settings:timezone')
    if not redis.get(f'chat:{chat_id}:settings:tweet_time'):
        redis.set(f'chat:{chat_id}:settings:tweet_time', '12:00')
    tweet_time = redis.get(f'chat:{chat_id}:settings:tweet_time')
    context.bot.send_message(
        chat_id=chat_id,
        text="You're all set! If you want to, you can test if "
        "everything works by posting a tweet: /test_tweet")
    context.bot.send_message(
        chat_id=chat_id,
        text=
        f'I will tweet at {tweet_time} ({tz}). You can change that: /tweet_time, /timezone'
    )
def handle_messages(update: Update, context: CallbackContext):
    chat_id = update.message.chat_id
    if not redis.get(f'chat:{chat_id}:oauth:access_token'):
        context.bot.send_message(
            chat_id=chat_id,
            text='You need to set me up first. Click on /start')
        return
    text = update.message.text or update.message.caption or ''
    if len(text) > TWEET_CHARACTER_LIMIT:
        context.bot.send_message(
            chat_id=chat_id,
            text=
            f'Sorry, your text exceeds the limit of {TWEET_CHARACTER_LIMIT} characters.'
        )
    queue_size = redis.get(f'chat:{chat_id}:queue_size')
    if queue_size is None:
        queue_size = 0
    queue_size = int(queue_size)
    if queue_size >= MAX_QUEUE_SIZE:
        context.bot.send_message(
            chat_id=chat_id, text='You have exceeded the maximum queue size.')
    redis.set(f'chat:{chat_id}:queue:{queue_size}:text', text)
    if update.message.document:
        redis.set(f'chat:{chat_id}:queue:{queue_size}:tg_attachment_id',
                  update.message.document.file_id)
    elif update.message.photo:
        redis.set(f'chat:{chat_id}:queue:{queue_size}:tg_attachment_id',
                  find_largest_photo(update.message.photo).file_id)
    queue_size += 1
    redis.set(f'chat:{chat_id}:queue_size', queue_size)
    tweet_time = redis.get(f'chat:{chat_id}:settings:tweet_time')
    context.bot.send_message(
        chat_id=chat_id,
        text=
        f'Ok, I will tweet that at {tweet_time}! You now have {queue_size} tweet(s) in your queue.'
    )
def loop():
    now = datetime.now()
    logging.debug(f'Running with timestamp {now}')
    for key in redis.keys('*:settings:tweet_time'):
        chat_id = key.split(':')[1]
        desired_time = redis.get(key).split(':')
        desired_hour = int(desired_time[0])
        desired_minute = int(desired_time[1])
        local_now = now.astimezone(timezone(redis.get(f'chat:{chat_id}:settings:timezone') or 'UTC'))
        if desired_hour != local_now.hour or desired_minute != local_now.minute:
            continue
        queue_size = redis.get(f'chat:{chat_id}:queue_size') or 0
        queue_size = int(queue_size)
        if queue_size <= 0:
            continue
        queue_size -= 1
        tweet_text = redis.get(f'chat:{chat_id}:queue:0:text')
        tg_attachment_id = redis.get(f'chat:{chat_id}:queue:0:tg_attachment_id')

        twitter = get_twitter_api(chat_id)

        if not tg_attachment_id:
            try:
                status = twitter.update_status(tweet_text)
            except tweepy.error.TweepError as e:
                logging.warning(f'Unable to tweet for chat:{chat_id}:queue:{queue_size} (without attachment) '
                                f'Reason: {e.reason}')
                telegram_updater.bot.send_message(chat_id=chat_id, text=e.reason)
                telegram_updater.bot.send_message(chat_id=chat_id, text='Sorry, I was unable to post your daily tweet. '
                                                                        'This is your tweet:')
                telegram_updater.bot.send_message(chat_id=chat_id, text=tweet_text)
                telegram_updater.bot.send_message(chat_id=chat_id,
                                                  text='You may delete it from the queue: /delete_last')
                return
        else:
            # download telegram photo
            logging.debug('Downloading telegram attachment')
            file = telegram_updater.bot.getFile(tg_attachment_id)
            filename = FILE_STORAGE_PATH / tg_attachment_id
            file.download(filename)

            try:
                status = twitter.update_with_media(filename, tweet_text)
            except tweepy.error.TweepError as e:
                logging.warning(f'Unable to tweet for chat:{chat_id}:queue:{queue_size} (with attachment). '
                                f'Reason: {e.reason}')
                telegram_updater.bot.send_message(chat_id=chat_id, text=e.reason)
                telegram_updater.bot.send_message(chat_id=chat_id,
                                                  text='Sorry, I was unable to post your daily tweet. '
                                                       'This is your tweet, and it contained one attachment:')
                telegram_updater.bot.send_message(chat_id=chat_id, text=tweet_text)
                telegram_updater.bot.send_message(chat_id=chat_id,
                                                  text='You may delete it from the queue: /delete_last')
                return
            finally:
                filename.unlink(missing_ok=True)
        logging.debug('Deleting stored tweet and attachment id')
        # Move all elements in the queue one
        for i in range(queue_size):
            k0 = f'chat:{chat_id}:queue:{i}:text'
            k1 = f'chat:{chat_id}:queue:{i+1}:text'
            l0 = f'chat:{chat_id}:queue:{i}:tg_attachment_id'
            l1 = f'chat:{chat_id}:queue:{i + 1}:tg_attachment_id'
            redis.set(k0, redis.get(k1) or '')
            redis.set(l0, redis.get(l1) or '')
        # The last element is now duplicated; delete it
        redis.delete(f'chat:{chat_id}:queue:{queue_size}:text')
        redis.delete(f'chat:{chat_id}:queue:{queue_size}:tg_attachment_id')

        tweet_url = build_tweet_url(status)
        logging.info(f'Tweeted: {tweet_url} for chat_id {chat_id}')
        telegram_updater.bot.send_message(chat_id=chat_id, text=f'I just tweeted this: {tweet_url}\n'
                                                                f'\n'
                                                                f'Tweets in queue: {queue_size}')
        if queue_size <= 0:
            telegram_updater.bot.send_message(chat_id=chat_id, text="Your queue is now empty. I will not tweet "
                                                                    "tomorrow if you won't give me new stuff!")
        redis.set(f'chat:{chat_id}:queue_size', queue_size)
Example #8
0
    def put(self, user):
        """Update a single user."""

        sex_am = request.form.get('sex_am')
        if sex_am in ('guy', 'gal'):
            previous = redis.get('users:%s:sex_am' % user)
            if previous and previous != sex_am:
                redis.srem('sex_am:%s' % previous, user)

            redis.set('users:%s:sex_am' % user, sex_am)
            redis.sadd('sex_am:%s' % sex_am, user)

        sex_want = request.form.get('sex_want')
        if sex_want in ('guy', 'gal'):
            previous = redis.get('users:%s:sex_want' % user)
            if previous and previous != sex_want:
                redis.srem('sex_want:%s' % previous, user)

            redis.set('users:%s:sex_want' % user, sex_want)
            redis.sadd('sex_want:%s' % sex_want, user)

        zipcode = request.form.get('zip', '')
        zipshort = zipcode[:2]

        previous = redis.get('users:%s:zip' % user)
        if previous and previous != zipcode:
            redis.srem('zip:%s' % previous, user)
        redis.set('users:%s:zip' % user, zipcode)

        previous = redis.get('users:%s:zipshort' % user)
        if previous and previous != zipshort:
            redis.srem('zipshort:%s' % previous, user)
        redis.set('users:%s:zipshort' % user, zipshort)

        redis.sadd('zip:%s' % zipcode, user)
        redis.sadd('zipshort:%s' % zipshort, user)

        birthday = request.form.get('birthday', '')
        birthyear = birthday.split('-')[0]

        previous = redis.get('users:%s:birthyear' % user)
        if previous and previous != birthyear:
            redis.srem('birthyears:%s' % previous, user)

        redis.set('users:%s:birthday' % user, birthday)
        redis.set('users:%s:birthyear' % user, birthyear)

        redis.sadd('users:%s:birthday' % birthday, user)
        redis.sadd('users:%s:birthyear' % birthyear, user)

        # Birthyear is the score.
        redis.zadd('birthyears', user, birthyear)

        return Response()
Example #9
0
    def put(self, user):
        """Update a single user."""

        sex_am = request.form.get('sex_am')
        if sex_am in ('guy', 'gal'):
            previous = redis.get('users:%s:sex_am' % user)
            if previous and previous != sex_am:
                redis.srem('sex_am:%s' % previous, user)

            redis.set('users:%s:sex_am' % user, sex_am)
            redis.sadd('sex_am:%s' % sex_am, user)

        sex_want = request.form.get('sex_want')
        if sex_want in ('guy', 'gal'):
            previous = redis.get('users:%s:sex_want' % user)
            if previous and previous != sex_want:
                redis.srem('sex_want:%s' % previous, user)

            redis.set('users:%s:sex_want' % user, sex_want)
            redis.sadd('sex_want:%s' % sex_want, user)

        zipcode = request.form.get('zip', '')
        zipshort = zipcode[:2]

        previous = redis.get('users:%s:zip' % user)
        if previous and previous != zipcode:
            redis.srem('zip:%s' % previous, user)
        redis.set('users:%s:zip' % user, zipcode)

        previous = redis.get('users:%s:zipshort' % user)
        if previous and previous != zipshort:
            redis.srem('zipshort:%s' % previous, user)
        redis.set('users:%s:zipshort' % user, zipshort)

        redis.sadd('zip:%s' % zipcode, user)
        redis.sadd('zipshort:%s' % zipshort, user)

        birthday = request.form.get('birthday', '')
        birthyear = birthday.split('-')[0]

        previous = redis.get('users:%s:birthyear' % user)
        if previous and previous != birthyear:
            redis.srem('birthyears:%s' % previous, user)

        redis.set('users:%s:birthday' % user, birthday)
        redis.set('users:%s:birthyear' % user, birthyear)

        redis.sadd('users:%s:birthday' % birthday, user)
        redis.sadd('users:%s:birthyear' % birthyear, user)

        # Birthyear is the score.
        redis.zadd('birthyears', user, birthyear)

        return Response()