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 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()
def pins(user=None, limit=5): user = None users = set() me = request.values.get('me') if me: users = redis.sdiff('users', 'users:%s:ugos' % me) else: users = redis.smembers('users') if users: # Filter by location. zipshort = redis.get('users:%s:zipshort' % me) users = users & redis.smembers('zipshort:%s' % zipshort) # Filter by sex. Yes, please. # This person wants my sex. sex_am = redis.get('users:%s:sex_am' % me) users = users & redis.smembers('sex_want:%s' % sex_am) # I want this person's sex. sex_want = redis.get('users:%s:sex_want' % me) users = users & redis.smembers('sex_am:%s' % sex_want) # Filter by users within my age range (+/- 10 years). try: age = int(redis.get('users:%s:birthyear' % me)) except ValueError: pass else: geezers = redis.zrangebyscore('birthyears', '-inf', age - 11) premies = redis.zrangebyscore('birthyears', age + 11, '+inf') users = users - set(geezers) - set(premies) if users: users = list(users) random.shuffle(users) users = users[:limit] data = [] remaining = len(users) for user in users: pins = get_pins(user) pins['remaining'] = remaining remaining -= 1 data.append(pins) print user # Nice to know. return data
def _generate_csv(precision): columns = ['timestamp'] + moods lines = [','.join(columns)] # Get sorted set in descending order by date. runs = redis.zrevrange('runs', 0, -1, 1) for run_timestamp, run_key in runs: # This is the value of the run which we key off of # (e.g., 20130116233651). run_key = str(int(run_key)) line = [run_timestamp] for mood in moods: try: # Get the string of the mood count. count = redis.get('runs:%s:moods:%s:%s' % (run_key, precision, mood)) except: pass count = count or 0 line.append(str(count)) lines.append(','.join(line)) return '\n'.join(lines)
def pins(user=None): user = None users = set() me = request.values.get('me') if me: users = redis.sdiff('users', 'users:%s:ugos' % me) else: users = redis.smembers('users') if users: # Filter by location. zipshort = redis.get('users:%s:zipshort' % me) users = users & redis.smembers('zipshort:%s' % zipshort) # Filter by sex. Yes, please. # This person wants my sex. sex_am = redis.get('users:%s:sex_am' % me) users = users & redis.smembers('sex_want:%s' % sex_am) # I want this person's sex. sex_want = redis.get('users:%s:sex_want' % me) users = users & redis.smembers('sex_am:%s' % sex_want) # Filter by users within my age range (+/- 10 years). try: age = int(redis.get('users:%s:birthyear' % me)) except ValueError: pass else: geezers = redis.zrangebyscore('birthyears', '-inf', age - 11) premies = redis.zrangebyscore('birthyears', age + 11, '+inf') users = users - set(geezers) - set(premies) if users: users = list(users) random.shuffle(users) user = users[0] print user # Nice to know. if user: pins = get_pins(user) pins['remaining'] = len(users) return pins else: return {}
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 _generate_html(precision): runs = [] # Get sorted set in descending order by date. stored_runs = redis.zrevrange('runs', 0, -1, 1) for run_timestamp, run_key in stored_runs: # This is the value of the run which we key off of (e.g., 20130116233651). run_key = str(int(run_key)) run = {'timestamp': run_timestamp, 'counts': []} for mood in moods: try: # Get the string of the mood count. count = redis.get('runs:%s:moods:%s:%s' % (run_key, precision, mood)) except: # Maybe this key is not a set - or some other error occurred. pass count = count or 0 run['counts'].append(int(count)) for total in totals: try: # Get the string of the tally count. count = redis.get('runs:%s:totals:%s:%s' % (run_key, precision, total)) except: # Maybe this key is not a set - or some other error occurred. pass count = count or 0 run['counts'].append(int(count)) runs.append(run) return { 'precision': precision, 'moods': moods, 'totals': totals, 'runs': runs }
def handle_timezone_command(update: Update, context: CallbackContext): continents = sorted( set([x.partition('/')[0] for x in pytz.common_timezones])) current_timezone = redis.get( f'chat:{update.message.chat_id}:settings:timezone') reply = get_timezone_region_markup(continents) context.bot.send_message( chat_id=update.message.chat_id, text=f'Your current timezone is set to "{current_timezone}". ' 'If you want to change it, choose your region', reply_markup=reply)
def handle_clock_command(update: Update, context: CallbackContext): chat_id = update.message.chat_id current_timezone = redis.get(f'chat:{chat_id}:settings:timezone') if not current_timezone: context.bot.send_message( chat_id=chat_id, text="Sorry to interrupt you, but you need to set a /timezone") return tz = timezone(current_timezone) msg_sent_date = update.message.date.astimezone(tz) context.bot.send_message( chat_id=update.message.chat_id, text=f'I received your message at {msg_sent_date}')
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 delete(self, user): """Delete a single user.""" redis.srem('users', user) sets = ['sex_am', 'sex_want', 'zip', 'zipshort', 'birthday', 'birthyear'] for key in sets: value = redis.get('users:%s:%s' % (user, key)) if value is not None: redis.srem('%s:%s' % (key, value), user) keys = ['sex_am', 'sex_want', 'ugos', 'zip', 'zipshort', 'birthday', 'birthyears'] for key in keys: redis.delete('users:%s:%s' % (user, key)) redis.zrem('birthyears', user) return Response()
def handle_tweet_time_command(update: Update, context: CallbackContext): chat_id = update.message.chat_id buttons = [] for hour in range(24): buttons.append([ InlineKeyboardButton(f'{hour:02}:{minute:02}', callback_data=f'tweet_time:{hour}:{minute}') for minute in range(0, 60, 15) ]) buttons.append([InlineKeyboardButton('Cancel', callback_data=f'cancel')]) reply = InlineKeyboardMarkup(buttons, one_time_keyboard=True) tweet_time = redis.get(f'chat:{chat_id}:settings:tweet_time') context.bot.send_message( chat_id=update.message.chat_id, text= f'Your current tweet time is {tweet_time}. Do you want to change it?', reply_markup=reply)
def delete(self, user): """Delete a single user.""" redis.srem('users', user) sets = [ 'sex_am', 'sex_want', 'zip', 'zipshort', 'birthday', 'birthyear' ] for key in sets: value = redis.get('users:%s:%s' % (user, key)) if value is not None: redis.srem('%s:%s' % (key, value), user) keys = [ 'sex_am', 'sex_want', 'ugos', 'zip', 'zipshort', 'birthday', 'birthyears' ] for key in keys: redis.delete('users:%s:%s' % (user, key)) redis.zrem('birthyears', user) return Response()
def get_data(user): data = {} for field in ('sex_am', 'sex_want', 'zip', 'birthday'): data[field] = redis.get('users:%s:%s' % (user, field)) return data
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)