def get_latest(update: Update, context: CallbackContext): chat_id = update.effective_chat.id try: client.query( q.if_( q.exists(q.ref(q.collection(users), chat_id)), q.update(q.ref(q.collection(users), chat_id), {'data': { 'last_command': 'getlatest' }}), q.create( q.ref(q.collection(users), chat_id), { 'data': { 'name': update.message.chat.first_name, 'last_command': 'getlatest', 'animes_watching': [], 'config': { 'resolution': Resolution.MEDIUM.value } } }))) context.bot.send_message(chat_id=chat_id, text='Enter the anime you want to get!') except Exception as err: log_error(err)
def subscribe(update, context): chat_id = update.effective_chat.id try: client.query( q.if_( q.exists(q.ref(q.collection(users), chat_id)), q.update(q.ref(q.collection(users), chat_id), {'data': { 'last_command': 'subscribe' }}), q.create( q.ref(q.collection(users), chat_id), { 'data': { 'name': update.message.chat.first_name, 'is_admin': False, 'last_command': 'subscribe', 'animes_watching': [], 'config': { 'resolution': Resolution.MEDIUM.value } } }))) context.bot.send_message( chat_id=chat_id, text='Enter the anime you want to get notifications for!') except Exception as err: log_error(err)
def resolution(self, resolution: Resolution): # update user's config in db client.query( q.update(q.ref(q.collection(users), self.chat_id), {'data': { 'config': { 'resolution': resolution.value } }}))
def unsubscribe_from_anime(self, anime_doc_id: str): try: anime = client.query( q.get(q.ref(q.collection(animes), anime_doc_id))) client.query( q.let( { 'anime_ref': q.ref(q.collection(animes), anime_doc_id), 'bot_user': q.ref(q.collection(users), self.chat_id), 'followers': q.select(['data', 'followers'], q.get(q.var('anime_ref'))), }, q.do( q.update( q.var('anime_ref'), { 'data': { 'followers': q.subtract( q.var('followers'), 1) } }), q.update( q.var('bot_user'), { 'data': { 'animes_watching': q.filter_( q.lambda_( 'watched_anime_ref', q.not_( q.equals( q.var('watched_anime_ref'), q.var('anime_ref')))), q.select(['data', 'animes_watching'], q.get(q.var('bot_user')))) } }), q.if_(q.equals(q.var('followers'), 1), q.delete(q.var('anime_ref')), 'successful!')))) updater.bot.send_message(chat_id=self.chat_id, text='You have stopped following ' + anime['data']['title']) except errors.NotFound: logger.info( 'Somehow, a user {0} almost unsubscribed from an anime that did not exist' .format(self.chat_id)) except Exception as err: log_error(err)
def send_broadcast(args): print(args) try: updater.bot.send_message(chat_id=args[0], text=args[1]) except Unauthorized: # user blocked bot so delete user from list user = client.query(q.get(q.ref(q.collection(users), args[0]))) client.query(q.delete(user['ref'], )) logger.info("a user has been deleted from user list") return '' except Exception as err: log_error(err) return '' else: return 'success'
def donate(update, context): try: for message in config['message']['donate']: context.bot.send_message(chat_id=update.effective_chat.id, text=message) client.query( q.let( {'user': q.ref(q.collection(users), update.effective_chat.id)}, q.if_( q.exists(q.var('user')), q.update(q.var('user'), {'data': { 'last_command': '', }}), 'Success!'))) except Exception as err: log_error(err)
def unsubscribe(update: Update, context: CallbackContext): user = User(update.effective_chat.id) try: animes_watched = client.query( q.let({'bot_user': q.ref(q.collection(users), user.chat_id)}, q.if_( q.exists(q.var('bot_user')), q.map_( q.lambda_('doc_ref', q.get(q.var('doc_ref'))), q.select(['data', 'animes_watching'], q.get(q.var('bot_user')))), []))) for anime in animes_watched: markup = [[ InlineKeyboardButton('Unsubscribe', callback_data='unsubscribe=' + anime['ref'].id()) ]] context.bot.send_message(chat_id=user.chat_id, text=anime['data']['title'], reply_markup=InlineKeyboardMarkup(markup)) # update last command user.last_command = '' if not animes_watched: context.bot.send_message( chat_id=user.chat_id, text='You are currently not subscribed to any anime') except Exception as err: log_error(err)
def help_user(update, context): user = User(update.effective_chat.id) if str(user.chat_id) == str(os.getenv('ADMIN_CHAT_ID')): message = config['message']['help_admin'] else: message = config['message']['help'] context.bot.send_message(chat_id=user.chat_id, text=message) try: client.query( q.let({'user': q.ref(q.collection(users), user.chat_id)}, q.if_( q.exists(q.var('user')), q.update(q.var('user'), {'data': { 'last_command': '', }}), 'Success!'))) except Exception as err: log_error(err)
def is_admin(self) -> bool: try: result = client.query( q.select(['data', 'is_admin'], q.get(q.ref(q.collection(users), self.chat_id)))) except errors.NotFound: raise UserNotFoundException(self.chat_id) return result
def get_subscribed_users_for_anime(anime_doc_id): """ This function gets all the user subscribed to a particular anime """ subscribed_users = client.query( q.map_( q.lambda_('doc_ref', q.get(q.var('doc_ref'))), q.paginate(q.match(q.index(all_users_by_anime), q.ref(q.collection(animes), str(anime_doc_id))), size=100000))) subscribed_users = subscribed_users['data'] return subscribed_users
def check_for_update(context: CallbackContext): logger.info("About to run subscription check") # get all anime all_animes = client.query( q.paginate(q.documents(q.collection(animes)), size=100000)) for anime in all_animes['data']: # get anime_info in the function send_update... # if there are new episodes... send_update_to_subscribed_users(anime.id()) logger.info("Subscription check finished")
def recommend(update: Update, context: CallbackContext): chat_id = update.effective_chat.id results = client.query( q.map_(q.lambda_(['followers', 'doc_ref'], q.get(q.var('doc_ref'))), q.paginate(q.match(q.index(sort_anime_by_followers)), size=5))) context.bot.send_message( chat_id=chat_id, text='Here are the top animes people using Anime Alarm are watching') for anime in results['data']: if anime['data']['link'].startswith('https://tinyurl.com/') or anime[ 'data']['link'].startswith('https://bit.ly/'): link = anime['data']['link'] else: link = shorten(anime['data']['link']) markup = [[ InlineKeyboardButton('Subscribe', callback_data='subscribe=' + link) ]] context.bot.send_message(chat_id=chat_id, reply_markup=InlineKeyboardMarkup(markup), text=str(results['data'].index(anime) + 1) + '. ' + anime['data']['title'])
def number_of_anime(update: Update, context: CallbackContext): result = client.query( q.count(q.paginate(q.documents(q.collection(animes)), size=100000))) context.bot.send_message(chat_id=update.effective_chat.id, text='Number of anime: ' + str(result['data'][0]))
def number_of_users(update: Update, context: CallbackContext): user = User(update.effective_chat.id) result = client.query( q.count(q.paginate(q.documents(q.collection(users)), size=100000), )) context.bot.send_message(chat_id=user.chat_id, text='Number of users: ' + str(result['data'][0]))
def last_command(self) -> str: last_command = client.query( q.select(['data', 'last_command'], q.get(q.ref(q.collection(users), self.chat_id)))) return last_command
def last_command(self, new_last_command: str): client.query( q.update(q.ref(q.collection(users), self.chat_id), {'data': { 'last_command': new_last_command }}))
def resolution(self) -> Resolution: print('getting resolution') resolution = client.query( q.select(['data', 'config', 'resolution'], q.get(q.ref(q.collection(users), self.chat_id)))) return Resolution(resolution)
def subscribe_to_anime(self, anime_link: str): try: # create a new anime document anime_info = anime_alarm.utils.GGAScraper().get_anime_info( anime_link) print(anime_info['anime_id']) result = client.query( q.let( { 'user_anime_list': q.select(['data', 'animes_watching'], q.get(q.ref(q.collection(users), self.chat_id))), }, q.if_( # check if this anime exists in the db q.exists( q.match(q.index(anime_by_id), anime_info['anime_id'])), # if it exists... q.let( { 'anime_ref': q.select( 'ref', q.get( q.match(q.index(anime_by_id), anime_info['anime_id']))) }, q.if_( # check if user has subscribed to this anime already q.contains_value(q.var('anime_ref'), q.var('user_anime_list')), 'This anime is already on your watch list!', q.do( q.update( q.ref(q.collection(users), self.chat_id), { 'data': { 'animes_watching': q.append( q.var('user_anime_list'), [q.var('anime_ref')]) } }), q.update( q.var('anime_ref'), { 'data': { 'followers': q.add( q.select([ 'data', 'followers' ], q.get( q.var('anime_ref'))), 1) } }), ))), q.let( {'new_anime_id': q.new_id()}, q.do( # create new anime document q.create( q.ref(q.collection(animes), q.var('new_anime_id')), { 'data': { 'title': anime_info['title'], 'followers': 1, 'link': anime_link, 'anime_id': anime_info['anime_id'], 'anime_alias': anime_info['anime_alias'], 'episodes': anime_info['number_of_episodes'], 'last_episode': { 'link': anime_info[ 'latest_episode_link'], 'title': anime_info[ 'latest_episode_title'], }, } }), # add to user's list of subscribed animes q.update( q.ref(q.collection(users), self.chat_id), { 'data': { 'animes_watching': q.append( q.var('user_anime_list'), [ q.ref( q.collection(animes), q.var('new_anime_id')) ]) } }), ))))) if isinstance(result, str): updater.bot.send_message(chat_id=self.chat_id, text=result) else: updater.bot.send_message( chat_id=self.chat_id, text='You are now listening for updates on ' + anime_info['title']) except Exception as err: log_error(err)
def plain_message(update: Update, context: CallbackContext): print(update.effective_message) try: bot_user = client.query( q.get(q.ref(q.collection('users'), update.effective_chat.id))) except errors.NotFound: context.bot.send_message( chat_id=update.effective_chat.id, text= 'Sorry, I do not understand what you mean.\nPlease use the /help command to ' 'discover what I can help you with.') return user = User(update.effective_chat.id) last_command = bot_user['data']['last_command'] message = update.message.text print(last_command) if last_command == 'subscribe': try: search_results = scraper.get_anime(message, limit=15) if len(search_results) == 0: context.bot.send_message( chat_id=user.chat_id, text= 'Sorry but no search results were available for this anime' ) else: context.bot.send_message( chat_id=user.chat_id, text='Here are the search results for ' + message) for result in search_results: markup = [[ InlineKeyboardButton('Select', callback_data='subscribe=' + shorten(result['link'])) ]] context.bot.send_photo( chat_id=user.chat_id, photo=result['thumbnail'], caption=result['title'], timeout=5, reply_markup=InlineKeyboardMarkup(markup)) # update last command user.last_command = '' except Exception as err: log_error(err) elif last_command == 'getlatest': try: search_results = scraper.get_anime(message, limit=15) if len(search_results) == 0: context.bot.send_message( chat_id=user.chat_id, text= 'Sorry but no search results were available for this anime' ) else: context.bot.send_message( chat_id=user.chat_id, text='Here are the search results for ' + message) for result in search_results: markup = [[ InlineKeyboardButton('Select', callback_data='getlatest=' + shorten(result['link'])) ]] context.bot.send_photo( chat_id=user.chat_id, photo=result['thumbnail'], caption=result['title'], timeout=5, reply_markup=InlineKeyboardMarkup(markup)) # update last command user.last_command = '' except Exception as err: log_error(err) elif last_command == 'broadcast': if user.is_admin(): context.bot.send_message(chat_id=user.chat_id, text='Broadcasting message...') try: results = client.query( q.paginate(q.documents(q.collection(users)), size=100000)) results = results['data'] # spin 5 processes with Pool(5) as p: res = p.map(send_broadcast, [[int(user_ref.id()), message] for user_ref in results]) successful_broadcast = [] for i in res: if i == 'success': successful_broadcast.append(i) logger.info('Message broadcast to ' + str(len(successful_broadcast)) + ' users') print(res) # update user last command user.last_command = '' except Exception as err: log_error(err) else: context.bot.send_message(chat_id=user.chat_id, text="Only admins can use this command!") else: context.bot.send_message( chat_id=user.chat_id, text= "Sorry, I do not understand what you mean.\nPlease use the /help command to " "discover what I can help you with.")
def send_update_to_subscribed_users(anime: Union[Dict[str, Any], str, int], download_links=None, anime_info: Dict = None): """ This function sends updates to all users subscribed to a particular anime """ # download_links is a dict of Resolution -> download_link if download_links is None: download_links = {} download_links = download_links if isinstance(anime, dict): pass elif isinstance(anime, str) or isinstance(anime, int): anime = client.query(q.get(q.ref(q.collection(animes), str(anime)))) if anime_info is None: anime_info = scraper.get_anime_info(anime['data']['link']) # if there is a new episode... if anime_info['number_of_episodes'] > anime['data']['episodes']: if anime_info['latest_episode_link'] != anime['data']['last_episode'][ 'link']: try: subscribed_users = get_subscribed_users_for_anime( anime['ref'].id()) # send message to subscribed users for user in subscribed_users: try: # if link for particular resolution has not been scraped yet... user_resolution = Resolution( user['data']['config']['resolution']) if user_resolution not in download_links: download_links[ user_resolution] = scraper.get_download_link( anime_info['latest_episode_link'], user_resolution) markup = [[ InlineKeyboardButton( text='Download', url=download_links[user_resolution]) ]] text = "Here's the latest episode for {0}:\n\n{1}".format( anime['data']['title'], anime_info['latest_episode_title']) if anime['data']['anime_id'] == '9914': text = "It's AOT Sunday!!\n\n" + text + "\n\nShinzou Wo Sasageyo!!" updater.bot.send_message( chat_id=int(user['ref'].id()), text=text, reply_markup=InlineKeyboardMarkup(markup)) except Unauthorized: # user has blocked bot # delete user from list client.query(q.delete(user['ref'])) logger.info("A user has been deleted from user list") # send message to admin updater.bot.send_message( chat_id=os.getenv('ADMIN_CHAT_ID'), text=anime['data']['title'] + ' just got a new episode and was updated!') logger.info( str(len(subscribed_users)) + " users were notified of an update to " + anime['data']['title']) except CannotDownloadAnimeException as err: log_error(err) subscribed_users = get_subscribed_users_for_anime( anime['ref'].id()) # tell subscribed user episode is available but can't download for user in subscribed_users: text = "A new episode for {0}: {1} is now out.\nSadly, I could not download it\U0001F622".format( anime['data']['title'], anime_info['latest_episode_title']) updater.bot.send_message(chat_id=int(user['ref'].id()), text=text) # send message to admin updater.bot.send_message(chat_id=os.getenv('ADMIN_CHAT_ID'), text=anime['data']['title'] + ' just got a new ' 'episode but could ' 'not be downloaded') finally: # update anime in db after sending messages to users client.query( q.update( anime['ref'], { 'data': { 'episodes': anime_info['number_of_episodes'], 'last_episode': { 'title': anime_info['latest_episode_title'], 'link': anime_info['latest_episode_link'] } } })) else: pass else: pass
def callback_handler_func(update: Update, context: CallbackContext): user = User(update.effective_chat.id) callback_message = update.callback_query.message.reply_markup.inline_keyboard[ 0][0].callback_data [command, payload] = callback_message.split(sep='=') if command == 'subscribe': user.subscribe_to_anime(payload) elif command == 'unsubscribe': user.unsubscribe_from_anime(payload) elif command == 'getlatest': try: anime_info = scraper.get_anime_info(payload) latest_episode_download_link = shorten( scraper.get_download_link(anime_info['latest_episode_link'], resolution=user.resolution)) markup = [[ InlineKeyboardButton(text='Download', url=latest_episode_download_link) ]] context.bot.send_message(chat_id=user.chat_id, text=anime_info['latest_episode_title'], reply_markup=InlineKeyboardMarkup(markup)) except CannotDownloadAnimeException as err: log_error(err) context.bot.send_message(chat_id=user.chat_id, text="Sorry," + payload + "could not be downloaded at this " "time!") context.bot.send_message(chat_id=os.getenv('ADMIN_CHAT_ID'), text='A user tried to download ' + payload + "but could not due to error: " + str(err)) return except Exception as err: log_error(err) return else: # check if anime is in our anime registry try: anime_from_db = client.query( q.if_( q.exists( q.match(q.index(anime_by_id), anime_info['anime_id'])), q.let( { 'anime': q.get( q.match(q.index(anime_by_id), anime_info['anime_id'])) }, q.if_( q.gt( anime_info['number_of_episodes'], q.select(['data', 'episodes'], q.var('anime'))), q.var('anime'), None)), None)) except errors.NotFound: anime_from_db = None if anime_from_db is not None: send_update_to_subscribed_users( anime_from_db, download_links={ user.resolution: latest_episode_download_link }, anime_info=anime_info) elif command == 'set_resolution': try: new_res = Resolution(payload) user.resolution = new_res context.bot.send_message( chat_id=user.chat_id, text= f'Your desired resolution has been set to {new_res.value}({resolutions[new_res]}).\nThis resolution will be used for your future /subscribe and /latest commands.' ) except ValueError: context.bot.send_message(chat_id=user.chat_id, text='Unidentified resolution level!') context.bot.send_message(chat_id=os.getenv('ADMIN_CHAT_ID'), text='Unidentified resolution level!') else: pass