def command_msg_count_rank(chat, msgs_count, count_mode): print("mode of !rank: ", count_mode) contacts = msgs_count[chat['contact']] count_sorted = sorted( [participant['id'] for participant in chat['participants']], key=lambda x: reset_count(contacts[x], count_mode), reverse=True) reset_day = 0 ghost = '👻' total_count = 0 rank_str = '' for i, contact_id in enumerate(count_sorted, 1): contact_info = contacts[contact_id] count = reset_count(contact_info, count_mode) rank_str += f'\t*{i}. {contact_info["contact"]} [{count}]*' if count < 100: rank_str += f' {ghost}' rank_str += f'\n - Número: ({contact_id})' if count > 0: first_msg_date = contact_info['messages'][0]['time'] rank_str += f'\n - 1ª msg: {first_msg_date}' rank_str += '\n' total_count += count rank_str = f'Rank de mensagens (Total: ' \ f'{total_count})\n{read_more()}{rank_str}' send_message(chat['id'], rank_str)
def command_anime_release(driver, chat, anime): # Starting searching using MyAnimeList because the searching engine is # way better, only get the 10 first results search_url = f'https://api.jikan.moe/v3/search/anime?page=1&q={anime}' search_results = requests.get(search_url).json()['results'][:10] mal_ids = [] for mal_anime in search_results: mal_ids.append(mal_anime['mal_id']) # Querying with the mal_ids from the MAL search q = get_release_from_anime_q() variables = {'idMal_in': mal_ids, 'page': 1, 'perPage': 50} result = requests.post(get_anilist_api_url(), json={ 'query': q, 'variables': variables }).json() s = '' for anime_r in result['data']['Page']['media']: anime_title = anime_r["title"]["romaji"] airing_data = anime_r['nextAiringEpisode'] # If doesn't have a airing schedule, show release start date if airing_data is None: st_date = anime_r['startDate'] d = st_date['day'] if st_date['day'] is not None else '?' m = st_date['month'] if st_date['month'] is not None else '?' y = st_date['year'] if st_date['year'] is not None else '?' dv = '28' if d == '?' else d mv = '12' if m == '?' else m yv = '3000' if y == '?' else y if datetime.strptime(f'{dv}{mv}{yv}', '%d%m%Y') >= datetime.today(): s += f'O anime *"{anime_title}"* ' \ f'não tem uma data de lançamento específica.\n' \ f'*Data mais próxima:* {d}/{m}/{y}\n\n' continue tua = get_date_from_sec(airing_data['timeUntilAiring']) air_datetime = datetime.fromtimestamp(airing_data['airingAt']) release_weekday_i = air_datetime.weekday() release_weekday = dias_da_semana[release_weekday_i] episodes = anime_r['episodes'] s += f'*{anime_title}*\n' episode = airing_data["episode"] if 60 * 60 * 24 <= airing_data['timeUntilAiring'] <= 60 * 60 * 24 * 7 \ and release_weekday_i == datetime.today().weekday(): s += f'O episódio lança hoje! ep: {episode - 1}\n' s += f'*Próximo episódio: {episode}* / ' \ f'{"?" if episodes is None else episodes}\n' \ f'O próximo episódio será lançado daqui a ' \ f'{tua}' \ f' *({release_weekday})*\n\n' if s == '': send_message( chat['id'], f'O anime "{anime}" não foi encontrado ' f'ou já foi finalizado.') else: send_message(chat['id'], s)
def command_search_studio(driver, chat, wpp_message): studio_pattern = re.compile('!(estúdio|estudio)\\s+(.+)') studio_name = studio_pattern.match(wpp_message['message']).groups()[1] q = get_studio_search_q() variables = { 'search': studio_name, 'page': 1, 'perPage': 50 } results = requests.post(get_anilist_api_url(), json={'query': q, 'variables': variables}).json() studio_results = results['data']['Page']['studios'] total_results = len(studio_results) studio = None if total_results == 0: # No results, send warning and that's it send_message(chat['id'], f'Estúdio {studio_name} não encontrado.') return elif total_results == 1: # Don't need to choose, only one option studio = studio_results[0] else: # send a list to choose a studio choose_list_str = '' time_limit = 30 i = 1 for studio_result in studio_results[:20]: choose_list_str += f'*[{i:02}] {studio_result["name"]}*\n' i += 1 choose_msg = send_choose_list(chat_id=chat['id'], q_type='estúdio', choose_list_str=choose_list_str, time_limit=time_limit) for cur_chat, cur_message in wait_for_response_generator(time_limit): msg = cur_message['message'] if can_make_element_choice(wpp_message, cur_message, max_value=i): studio = studio_results[int(msg) - 1] delete_message(driver, chat['id'], choose_msg) break elif msg == '0': # cancel sentinel delete_message(driver, chat['id'], choose_msg) return if studio is None: # Did not send any value send_message(chat['id'], 'Tempo terminado.') delete_message(driver, chat['id'], msg=choose_msg) return animes = [] for anime in studio['media']['nodes'][:25]: anime_info = f'Ano: {anime["startDate"]["year"]}\n' \ f'Tipo: {anime["format"]}' animes.append(BotImageElement(title=anime['title']['romaji'], image_info=anime_info, image_url=anime['coverImage']['large'])) studio_image_result = get_list_image(animes, studio['name']) send_media(chat['id'], msg=f'*Estúdio {studio["name"]}*', img_base64=studio_image_result, msg_id=wpp_message['msg_id'], image_url=None)
def command_spoiler(chat, wpp_message): spoiler_pattern = re.compile('!spoiler\s+([^/|]+)[/|](.+)') command = wpp_message['message'] if 'contact' not in wpp_message.keys(): wpp_message['contact'] = 'Eu' if spoiler_pattern.match(command): spoiler_data = spoiler_pattern.match(command).groups() spoiler_warning = spoiler_data[0].strip() spoiler_content = spoiler_data[1].strip() send_message( chat['id'], f'*[SPOILER {spoiler_warning}]* ({wpp_message["contact"]})' f'{read_more()}\n\n\n{spoiler_content}')
def command_anime_manga_list(driver, chat, user, q, q_type, wpp_message): response = requests.get( f'https://api.jikan.moe/v3/user/{user}/{q_type}list/{q}') if response.status_code == 400: send_message( chat['id'], f'Ocorreu um erro ao pesquisar a lista do usuário ' f'*"{user}"* verifique se o nome está correto') results = response.json()[q_type] results = sorted(results, key=lambda k: k['score'], reverse=True) i = 1 head = f"Continuação da lista de {q_type} {q} de *'{user}'*:\n" s = '' elements = [] for e in results: title = e["title"] e_str = '' e_str += f'*{e["title"]}* ' if q_type == 'manga': e_info = f'c.{e["read_chapters"]} v.{e["read_volumes"]}' e_str += f'*c.{e["read_chapters"]} v.{e["read_volumes"]}*' else: total_episodes = e['total_episodes'] total_episodes = '?' if total_episodes == 0 else total_episodes e_info = f'Episodes: {e["watched_episodes"]}/{total_episodes}' e_str += f'_{e["watched_episodes"]} eps_' e_info += f'\nScore: {e["score"]}' elements.append( BotImageElement(title=title, image_info=e_info, image_url=e['image_url'])) e_str += f' [ {e["score"]} ] \n' if i == 16: s += read_more() if i > 16: s += e_str i += 1 # send_message(driver, chat['id'], s) if len(elements) > 0: header_text = f"lista de {q_type} {q} de '{user}':" list_image = get_list_image(elements[:16], header_text) send_media(chat['id'], image_url=None, msg=head + s, msg_id=wpp_message['msg_id'], img_base64=list_image) else: send_message(chat['id'], f"Não há nada na lista de {q_type} {q} de *'{user}'*:\n")
def command_user_manager(driver, chat, wpp_message): command = wpp_message['message'] user_profile_pattern = re.compile('!user\\s+(perfil\\s+)?(.+)') user_history_pattern = re.compile('!user\\s+(historico|histórico)\\s+(.+)') if user_history_pattern.match(command): user = user_history_pattern.match(command).groups()[1] send_message(chat['id'], command_user_history(user)) elif user_profile_pattern.match(command): user = user_profile_pattern.match(command).groups()[1] user_profile = command_user_profile(user) # If the user does not have a photo if user_profile[1] is not None: send_media(chat['id'], user_profile[0], user_profile[1], wpp_message['msg_id']) else: send_message(chat['id'], user_profile[0]) else: # if command if incorrect, send explanation # send_message(driver, chat['id'], help_user()) get_help(driver, chat, '!user', wpp_message)
def command_help(driver, chat, wpp_message): """Return all the commands and their descriptions""" # get_help(driver, chat, '!help', wpp_message) send_message(chat['id'], 'MyAnimeList bot help\n' + '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n' + read_more() + '\n' + bot_help() + help_anime() + help_manga() + help_personagem() + help_studio() + help_monogatari() + '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n' '*[ !contador* _help_ *]* – Mostra todos os comandos relacionados ao ' 'contador de mensagens e ranks.\n' '*[ !user ]* - Mostra comandos relacionados ao perfil do usuário' '\n*[ !favorite ]* - Mostra os comandos que mostra os favoritos de um ' 'usuário no MAL\n' '*[ !list ]* - Mostra comandos relacionados às listas de usuários do ' 'MAL\n' '*[ !semanal ]* - Mostra todos os comandos relacionados a ' 'lançamentos de animes na semana\n' '*[ !top ]* - Mostra todos os comandos que mostram os tops do ' 'MyAnimeList, inclusive os top animes da temporada\n')
def command_msg_count(chat, driver, wpp_message, msgs_count): command = wpp_message['message'] contacts = msgs_count[chat['contact']] number_choose_pat = re.compile( '!contador\\s+(\\d+)\\s*(all|mes|mês|mensal|hoje|dia|diário|diario|semana|semanal)?$' ) person_pattern = re.compile( '!contador\\s+@(\\d+)\\s*(all|mes|mês|hoje|dia|mensal|diário|diario|semana|semanal)?' ) default_pattern = re.compile( '!contador\\s*(all|mes|mês|mensal|hoje|dia|diário|diario|semana|semanal)?' ) if number_choose_pat.match(command): mode = number_choose_pat.match(command).groups()[1] elif person_pattern.match(command): mode = person_pattern.match(command).groups()[1] elif default_pattern.match(command): mode = default_pattern.match(command).groups()[0] count_sorted = sorted( [participant['id'] for participant in chat['participants']], key=lambda x: reset_count(contacts[x], mode), reverse=True) if person_pattern.match(command): m_id = person_pattern.match(command).groups()[0] try: contact = contacts[m_id] except KeyError: send_message(chat['id'], f'Número "{m_id}" não encontrado') return elif number_choose_pat.match(command): n = int(number_choose_pat.match(command).groups()[0]) try: if n - 1 < 0: raise IndexError('Go f**k yourself you f*****g c**t') m_id = count_sorted[n - 1] contact = contacts[m_id] except IndexError: send_message(chat['id'], f'Número {n} fora de alcance') return elif default_pattern.match(command): contact = contacts[wpp_message['id']] m_id = wpp_message['id'] contagem = f"{contact['contact']}, enquanto o bot esteve ligado," \ f" escreveu {reset_count(contact, mode)} mensagens. " \ f"({count_sorted.index(m_id) + 1}º lugar)" \ f" " send_message(chat['id'], contagem)
def command_user_favorites(driver, chat, wpp_message): command = wpp_message['message'] favorite_pattern = re.compile( '!favorit(e|o)\\s+(anime|manga|personagem)\\s+(.+)') if favorite_pattern.match(command): user = favorite_pattern.match(command).groups()[2] q_type = favorite_pattern.match(command).groups()[1] q_type = q_type.replace('personagem', 'characters') # If user is not found, send a warning response = requests.get("https://api.jikan.moe/v3/user/" + user) if response.status_code == 404: send_message(chat['id'], f'O usuário "{user}" não foi encontrado.') return elif 'error' in response.json().keys(): send_message(chat['id'], f'Ocorreu um erro ao analisar' f' *"{user}"*, verifique se o ' f'usuário está correto, ou sua conta está vazia.') elements = [] favorites = response.json()['favorites'] user = response.json()['username'] s = f"{user}'s favorite {q_type}:" for i, anime in enumerate(favorites[q_type], 1): elements.append(BotImageElement(title=anime['name'], image_info=f'{i}', image_url=anime['image_url'])) if len(elements) > 0: list_image = get_list_image(elements, s) send_media(chat['id'], s, None, wpp_message['msg_id'], list_image) else: send_message(chat['id'], s) else: get_help(driver, chat, '!favorite', wpp_message)
def command_day_releases(driver, chat, week_day, wpp_message): send_message(chat['id'], 'Pesquisando lançamentos...') q = get_release_from_anime_q() variables = { 'page': 1, 'perPage': 50, 'startDate_greater': 19000000, 'format_in': ['TV', 'TV_SHORT', 'ONA'] } result = requests.post(get_anilist_api_url(), json={ 'query': q, 'variables': variables }).json() pages = result['data']['Page']['pageInfo']['lastPage'] results = [result['data']['Page']['media'][0]] threads = [ threading.Thread(target=get_day_results, args=[page, results]) for page in range(2, pages) ] [thread.start() for thread in threads] [thread.join() for thread in threads] elements = [] i = 1 for anime_r in results: anime_title = anime_r["title"]["romaji"] airing_data = anime_r['nextAiringEpisode'] image_url = anime_r['coverImage']['large'] anime_info = '' if airing_data is None: continue # if will release air_at = airing_data['airingAt'] air_remain = airing_data['timeUntilAiring'] air_date = datetime.fromtimestamp(air_at) # if is the requested day and is less than a week needed if air_date.weekday() == week_day \ and air_remain <= 7 * 24 * 60 * 60: episodes = anime_r['episodes'] episode = airing_data["episode"] if air_remain < 60 * 60 * 24 \ or air_date.weekday() != datetime.today().weekday(): anime_info += f'EP: {episode} / ' \ f'{"?" if episodes is None else episodes}\n' elif episode - 1 > 0: anime_info += f'Ep: {episode - 1} / ' \ f'{"?" if episodes is None else episodes}' \ f' (Lançado)\n' i += 1 anime_info += f'Próximo Ep: {get_date_from_sec(air_remain)}' elements.append( BotImageElement(title=anime_title, image_info=anime_info, image_url=image_url)) if len(elements) == 0: send_message(chat['id'], 'Nada encontrado') else: header_text = f'Episódios que lançam {dias_da_semana[week_day]}:' list_image = get_list_image(elements, header_text) send_media(chat['id'], f"*{header_text}*", None, wpp_message['msg_id'], list_image)
def make_call(driver, chat, wpp_message, msgs_count): """Sends the response message to a command, if there is one :Args: - driver: The webdriver to execute the JS scrips - chat: the chat to send the message - message: the message send by the user :Usage: chat = Output.output[0] message = chat['messages'][0] threading.Thread( target=make_call, args=[driver, chat, message]).start() """ wpp_message['message'] = wpp_message['message'].strip().lower() # stripping spaces after ! wpp_message['message'] = \ re.sub('!\\s+(.+)', r'!\1', wpp_message['message']) command = wpp_message['message'] if command == '!help': command_help(driver, chat, wpp_message) elif command.startswith('!anime'): command_anime_search(driver, chat, wpp_message) elif command.startswith('!manga') or command.startswith('!mangá'): command_manga_search(driver, chat, wpp_message) elif command.startswith('!personagem'): command_character_search(driver, chat, wpp_message) elif command.startswith('!estúdio') or command.startswith('estúdio'): command_search_studio(driver, chat, wpp_message) elif command.startswith('!user'): command_user_manager(driver, chat, wpp_message) elif command.startswith('!favorit'): command_user_favorites(driver, chat, wpp_message) elif command.startswith('!semana') or command.startswith('!lançamento'): command_release_manager(driver, chat, wpp_message) elif command.startswith('!top'): command_top_manager(driver, chat, wpp_message) elif command == '!monogatari': command_monogatari_order(driver, chat, wpp_message) elif command.startswith('!list'): command_list_manager(driver, chat, wpp_message) elif command.startswith('!spoiler'): command_spoiler(chat, wpp_message) elif command == '!temp': command_measure_temp(chat) elif command.startswith('!rank') or command.startswith("!contador rank"): print(Last.last) if chat['id'] in Last.last.keys() and command not in Last.last[ chat['id']]: print('iffffffff') Last.last[chat['id']][command] = time() - wait_rank - 1 elif chat['id'] not in Last.last: print('elseeeeee') Last.last[chat['id']] = {} Last.last[chat['id']][command] = time() - wait_rank - 1 time_passed = time() - Last.last[chat['id']][command] if time_passed > wait_rank: command_msg_count_manager(chat, driver, wpp_message, msgs_count) Last.last[chat['id']][command] = time() else: remain = wait_rank - time_passed mn = remain // 60 sec = remain % 60 send_message( chat['id'], f'Espere *{mn:.0f} min* e *{sec:.0f}s* para' f' usar !rank novamente nesse chat (15 em 15 min)') elif command.startswith('!contador'): command_msg_count_manager(chat, driver, wpp_message, msgs_count)
def command_words_count(chat, wpp_message, msgs_count): command = wpp_message['message'] person_pattern = re.compile('!contador\\s+palavras\\s+@(\d+)') if person_pattern.match(command): contact_number = person_pattern.match(command).groups()[0] else: contact_number = wpp_message['id'] messages = msgs_count[chat['contact']][contact_number]['messages'] contact = msgs_count[chat['contact']][contact_number]['contact'] word_counter = {} types_counter = {} times_counter = {} excluded_words = [ 'eles', 'elas', 'comigo', 'contigo', 'conosco', 'convosco', 'lhes', 'você', 'voce', 'minha', 'mais', 'meus', 'minhas', 'teus', 'tuas', 'seus', 'suas', 'nosso', 'nossa', 'nossos', 'nossas', 'vosso', 'vossa', 'vossos', 'vossas', 'seus', 'suas', 'mesmo', 'mesma', 'mesmos', 'mesmas', 'tais', 'quem', 'qual', 'quais', 'quanto', 'quanta', 'quantos', 'quantas', 'assim', 'então', 'logo', 'pois', 'portanto', 'porque', 'pois', 'porquanto', 'como', 'embora', 'conquanto', 'caso', 'quando' 'esses', 'essas', 'esse', 'essa', 'isso', 'isto' ] total_words = 0 for message in messages: # counting types msg_type = '!comandos' if message['message'].startswith( '!') else message['type'] if msg_type in types_counter: types_counter[msg_type] += 1 else: types_counter[msg_type] = 1 msg_txt = message['message'] if msg_txt == '(Sem mensagem)': continue # gets all words and count them, includes pitch accents words = re.findall('[a-zA-ZáéíóúâêîôûãõüÁÉÍÓÚÂÊÎÔÛÃÕÜ]+', msg_txt) total_words += len(words) for word in words: word = word.lower() word = 'kkkk (e variantes)' if word == 'k' * len(word) else word if len(word) < 4 or (word in excluded_words): continue if word in word_counter: word_counter[word] += 1 else: word_counter[word] = 1 # couting hours date = datetime.strptime(message['time'], '%d/%m/%Y (%H:%M)') if date.hour in times_counter: times_counter[date.hour] += 1 else: times_counter[date.hour] = 1 ordered_words = sorted(word_counter.keys(), key=lambda x: word_counter[x], reverse=True) s = f'*Palavras mais usadas de {contact}:*' s += f'{read_more()}\n*Total:* {len(messages)}\n' chat_count = 1 if 'chat' not in types_counter else types_counter['chat'] s += f'*Média de palavras {(total_words / chat_count):.2f} por mensagem*\n' for i, word in enumerate(ordered_words[:10], 1): s += f'*{i}. {word}* [{word_counter[word]}]\n' s += '\n*Tipos de mensagens e contagem:*\n' ordered_types = sorted(types_counter.keys(), key=lambda x: types_counter[x], reverse=True) for i, msg_type in enumerate(ordered_types, 1): s += f'*{i}. {msg_type}* [{types_counter[msg_type]}]\n' s += '\n*Horários e contagem:*\n' ordered_times = sorted(times_counter.keys(), key=lambda x: times_counter[x], reverse=True) for msg_time in ordered_times: s += (f'*{msg_time:02}:00~{((msg_time + 1) % 24):02}:00-* ' f'{times_counter[msg_time]}\n') send_message(chat['id'], s) pass
def command_measure_temp(chat): temp = os.popen('vcgencmd measure_temp').readline() temp = temp.replace('temp=', '') temp = temp.replace("'", "º") send_message(chat['id'], f'A temperatura do bot no momento é {temp}')