def handle(self, *args, **options): task_name = self.get_task_name(options) try: start_time = time.time() self.run_task(options) runtime = round(time.time() - start_time, 2) # Monitor duration of the task logger.info("Task " + task_name + " executed in " + str(runtime) + "s", extra={ 'task': task_name, 'success': True, 'runtime': runtime }) except Exception as error: if not settings.DEBUG: # Say if PROD or PRE-PROD and report to sentry a problem has been detected client.user_context({'prod_status': settings.PROD_STATUS}) client.captureException() # Log the error logger.error("Task " + task_name + " failed", extra={ 'task': task_name, 'success': False }) else: raise error
def send_fb_message(self, url, message): if self.client_send: try: response = requests.post(url, headers={"Content-Type": "application/json"}, data=message) if response.status_code != 200: logger.warning("Facebook message sending error", extra={ 'url': url, 'content': str(response.content), 'response_code': response.status_code }) else: logger.info("Facebook message sending success", extra={ 'url': url, 'content': str(response.content), 'response_code': response.status_code }) except Timeout: logger.error("Facebook message sending timed out", extra={ 'url': url, 'data': message }) except: logger.error("Facebook message sending failed", extra={ 'url': url, 'data': message }) else: self.messages.append(message)
def add_image_for_highlight(highlight): img_link = highlight.img_link # No need to upload in debug mode if settings.DEBUG: return # No need to upload default images if _is_default_highlight_img(img_link): return # No need to upload if image already exists if HighlightImage.objects.filter(match_id=highlight.id, img_link=img_link): return # Upload the image to the cloud try: img_uploaded_link = uploader.upload_image(img_link) logger.info("Image added for img_link: " + img_link, extra={ 'img_link': img_link, 'img_uploaded_link': img_uploaded_link }) except: logger.error("Image failed uploading: " + img_link) return HighlightImage.objects.update_or_create(match_id=highlight.id, img_link=img_link, img_uploaded_link=img_uploaded_link, source=highlight.source)
def fetch_highlights(site): highlights = fetcher.fetch(site) # Add new highlights for highlight in highlights: if latest_highlight_manager.has_highlight(highlight): # Skip if highlight already in database continue # Determine if highlight with teams inverted exists (Barcelona - Arsenal instead of Arsenal - Barcelona) inverted_highlights = latest_highlight_manager.get_inverted_teams_highlights( highlight) if len(inverted_highlights) > 1 or any( [h.sent for h in inverted_highlights]): highlight.swap_home_side() # Mark as sent if a similar highlight (same match, different provider) is in database and has already been sent sent = False if latest_highlight_manager.get_same_highlights_sent(highlight): sent = True new_highlight = latest_highlight_manager.add_highlight(highlight, sent=sent) # No highlight has been created if not new_highlight: continue logger.info("Highlight added: " + new_highlight.link, extra={ 'link': new_highlight.link, 'img_link': new_highlight.img_link, 'category': new_highlight.category.name, 'time_since_added': new_highlight.time_since_added, 'team1': new_highlight.team1.name, 'score1': new_highlight.score1, 'team2': new_highlight.team2.name, 'score2': new_highlight.score2, 'source': new_highlight.source, 'goal_data': new_highlight.goal_data, }) # Add the image for this new inserted highlight highlight_image_manager.add_image_for_highlight(new_highlight) # Set to all highlights the best image same_highlights = latest_highlight_manager.get_same_highlights( new_highlight) best_image_link = highlight_image_manager.fetch_best_image_for_highlight( new_highlight) for h in same_highlights: latest_highlight_manager.set_img_link(h, best_image_link)
def get_video_info(link): # Make sure video is from matchat.online or videostreamlet.net if not providers.MATCHAT_ONLINE in link \ and not providers.CONTENT_VENTURES in link \ and not providers.VIDEO_STREAMLET in link \ and not providers.VEUCLIPS in link: return None # Disable temporarily matchat.online as not working anymore if providers.MATCHAT_ONLINE in link or providers.CONTENT_VENTURES in link: return None try: page = requests.get(link) regex = "settings.bitrates = {hls:\"(.*?)\"" streaming_link_search_result = re.compile(regex, 0).search(page.text) streaming_link = 'https://' + streaming_link_search_result.groups( )[0].replace('//', '').replace('0.m3u8', '360p.m3u8') text = requests.get(streaming_link).text regex = "#EXTINF:(.*?)," durations_search_result = re.findall(regex, text) duration = int(sum([float(d) for d in durations_search_result])) info = {'duration': duration, 'video_url': None} scrapping_status_manager.update_scrapping_status('m3u8', True) logger.info('matchat.online SUCCESS | url: ' + link + ' | duration: ' + str(duration)) return info except: client.captureException() logger.error("Failed to fetch info for link {}".format(link)) try: if ressource_checker.check(link): scrapping_status_manager.update_scrapping_status('m3u8', False) logger.error('matchat.online FAILURE | url: ' + link) return { 'duration': 0, # Allow for retries if link is valid but scrapping not working 'video_url': None } else: return None except: client.captureException() logger.error( "Failed to fetch info for link {} and resource check failed". format(link)) return { 'duration': 0, # Allow for retries if link is valid but scrapping not working 'video_url': None }
def send_most_recent_highlights(): # Set incomplete infos for h in latest_highlight_manager.get_recent_highlights_with_incomplete_infos( ): reference_highlight = latest_highlight_manager.get_same_highlight_from_sources( h, sources.get_sources_with_complete_data_in_order_of_priority()) if not reference_highlight: continue latest_highlight_manager.set_goal_data(h, reference_highlight.goal_data) latest_highlight_manager.set_score(h, reference_highlight.score1, reference_highlight.score2) # Send highlights not already sent not_sent_highlights = latest_highlight_manager.get_valid_not_sent_highlights( AVAILABLE_SOURCES) time_now = datetime.now() for highlight in not_sent_highlights: if _should_send_highlight(time_now, highlight): # prevent sending 2 times same highlight with inverted home and away teams inverted_highlights = latest_highlight_manager.get_inverted_teams_highlights( highlight) if any([h.sent for h in inverted_highlights]): new_id = inverted_highlights[0].id latest_highlight_manager.swap_home_side(highlight, new_id) # prevent from sending a highlight if find the same already sent if latest_highlight_manager.get_same_highlights_sent(highlight): latest_highlight_manager.set_sent(highlight) continue # Set highlights for same match to sent similar_highlights = latest_highlight_manager.get_similar_highlights( highlight, not_sent_highlights) for h in similar_highlights: latest_highlight_manager.set_sent(h) logger.info("Highlight preparing to be sent: " + highlight.get_match_name(), extra={ 'match': highlight.get_match_name(), }) # Send highlight to users _send_highlight_to_users(highlight) logger.info("Highlight sent: " + highlight.get_match_name(), extra={ 'match': highlight.get_match_name(), }) # Delete old highlights # FIXME: try to find a way to keep old highlights all_highlights = latest_highlight_manager.get_all_highlights() for highlight in all_highlights: time_since_added = highlight.get_parsed_time_since_added() # Old highlight, delete if (time_now - time_since_added) > timedelta(days=60): latest_highlight_manager.delete_highlight(highlight)
def post(self, request, *args, **kwargs): # Converts the text payload into a python dictionary incoming_message = json.loads(request.body.decode('utf-8')) logger.info("Message received", extra={ 'incoming_message': incoming_message }) response_msg = [] for entry in incoming_message['entry']: for message in entry['messaging']: sender_id = message['sender'].get('id') HighlightsBotView.LATEST_SENDER_ID = sender_id user = user_manager.get_user(sender_id) user_manager.increment_user_message_count(sender_id) logger.log_for_user("Message received", sender_id, extra={ 'full_msg': message }) # Events if 'message' in message: text = message['message'].get('text') if message['message'].get('text') else '' message = language.remove_accents(text.lower()) logger.log_for_user("Text message received", sender_id, extra={ 'full_msg': message, 'msg_type': 'message' }) # Do not respond in those cases if 'no' == message or 'nothing' == message or 'ok' == message or 'shut up' in message or message == '': logger.log_for_user('No response', sender_id) continue # Send typing event - so user is aware received message sender.send_typing(sender_id) # Special replies # TODO: remove at some point if message == EMOJI_TROPHY + ' add nations league': logger.log_for_user("ADD NATIONS LEAGUE", sender_id) context_manager.update_context(sender_id, ContextType.SUBSCRIPTIONS_SETTING) registration_competition_manager.add_competition(sender_id, 'nations league') response_msg.append( manager_response.send_registration_added_message(sender_id, 'Nations League') ) response_msg.append( view_message_helper.send_subscriptions_settings(sender_id) ) # Special replies # TODO: remove at some point elif message == EMOJI_CROSS + ' no thanks': logger.log_for_user("NO THANKS NATIONS LEAGUE", sender_id) response_msg.append( manager_response.send_facebook_message( sender_id, manager_response.create_message("Another time! " + EMOJI_SMILE)) ) # Cancel quick reply elif 'cancel' in message: logger.log_for_user("CANCEL", sender_id) context_manager.set_default_context(sender_id) response_msg.append( manager_response.send_cancel_message(sender_id) ) # Done quick reply elif 'done' in message: logger.log_for_user("DONE", sender_id) context_manager.set_default_context(sender_id) response_msg.append( manager_response.send_done_message(sender_id) ) # HELP elif 'help' in message: logger.log_for_user("HELP", sender_id) context_manager.set_default_context(sender_id) response_msg.append( manager_response.send_help_message(sender_id) ) elif accepted_messages(message, ['thank you', 'thanks', 'cheers', 'merci', 'cimer', 'good job', 'good bot']): logger.log_for_user("THANK YOU MESSAGE", sender_id) context_manager.set_default_context(sender_id) response_msg.append( manager_response.send_thank_you_message(sender_id) ) # TUTORIAL CONTEXT elif context_manager.is_tutorial_context(sender_id): logger.log_for_user("TUTORIAL ADD REGISTRATION", sender_id, extra={ 'action': 'tutorial' }) message = message # Check if team exists, make a recommendation if no teams if football_team_manager.has_football_team(message): # Does team exist check registration_team_manager.add_team(sender_id, message) response_msg.append( manager_highlights.send_tutorial_message(sender_id, text) ) response_msg.append( manager_highlights.send_highlights_for_team_or_competition(sender_id, message, highlight_count=1, default_teams=['psg', 'barcelona', 'real madrid', 'spain', 'france']) ) response_msg.append( view_message_helper.send_subscriptions_settings(sender_id) ) elif football_competition_manager.has_football_competition(message): # Does competition exist check registration_competition_manager.add_competition(sender_id, message) response_msg.append( manager_highlights.send_tutorial_message(sender_id, text) ) response_msg.append( manager_highlights.send_highlights_for_team_or_competition(sender_id, message, highlight_count=1, default_teams=['psg', 'barcelona', 'real madrid', 'spain', 'france']) ) response_msg.append( view_message_helper.send_subscriptions_settings(sender_id) ) elif football_team_manager.similar_football_team_names(message) \ + football_competition_manager.similar_football_competition_names(message): # Registration recommendation # Register wrong search new_football_registration_manager.add_football_registration(message, 'user', user) recommendations = football_team_manager.similar_football_team_names(message) \ + football_competition_manager.similar_football_competition_names(message) # Format recommendation names recommendations = [recommendation.title() for recommendation in recommendations] response_msg.append( manager_highlights.send_recommended_team_or_competition_tutorial_message(sender_id, recommendations) ) else: # No team or recommendation found # Register wrong search new_football_registration_manager.add_football_registration(message, 'user', user) response_msg.append( manager_highlights.send_team_not_found_tutorial_message(sender_id) ) # SEE RESULT CHANGE SETTING elif context_manager.is_see_result_setting_context(sender_id): logger.log_for_user("SEE RESULT CHANGE SETTING", sender_id) if text in [SHOW_BUTTON, HIDE_BUTTON]: user_manager.set_see_result_setting(sender_id, text == SHOW_BUTTON) response_msg.append( manager_response.send_setting_changed(sender_id) ) context_manager.set_default_context(sender_id) else: response_msg.append( manager_response.send_setting_invalid(sender_id) ) response_msg.append( manager_response.send_see_result_setting(sender_id) ) # ADD REGISTRATION SETTING elif accepted_messages(message, ['add']) and context_manager.is_notifications_setting_context(sender_id): logger.log_for_user("ADD REGISTRATION SETTING", sender_id) context_manager.update_context(sender_id, ContextType.ADDING_REGISTRATION) response_msg.append( manager_response.send_add_registration_message(sender_id) ) # REMOVE REGISTRATION SETTING elif accepted_messages(message, ['remove']) and context_manager.is_notifications_setting_context(sender_id): logger.log_for_user("REMOVE REGISTRATION SETTING", sender_id) context_manager.update_context(sender_id, ContextType.REMOVE_REGISTRATION) registrations = view_message_helper.get_registrations_formatted(sender_id) response_msg.append( manager_response.send_delete_registration_message(sender_id, registrations) ) # ADDING REGISTRATION elif context_manager.is_adding_registration_context(sender_id) \ or context_manager.is_notifications_setting_context(sender_id): logger.log_for_user("ADDING REGISTRATION", sender_id) message = message # Check if registration exists, make a recommendation if no registration if message == OTHER_BUTTON.lower() or message == TRY_AGAIN_BUTTON.lower(): context_manager.update_context(sender_id, ContextType.ADDING_REGISTRATION) response_msg.append( manager_response.send_add_registration_message(sender_id) ) elif accepted_messages(message, [I_M_GOOD_BUTTON.lower(), 'stop', 'done', 'good']): response_msg.append( view_message_helper.send_subscriptions_settings(sender_id) ) elif football_team_manager.has_football_team(message): # Does team exist check registration_team_manager.add_team(sender_id, message) response_msg.append( manager_response.send_registration_added_message(sender_id, text) ) response_msg.append( manager_response.send_add_registration_message(sender_id) ) elif football_competition_manager.has_football_competition(message): # Does competition exist check registration_competition_manager.add_competition(sender_id, message) response_msg.append( manager_response.send_registration_added_message(sender_id, text) ) response_msg.append( manager_response.send_add_registration_message(sender_id) ) elif football_team_manager.similar_football_team_names(message) or \ football_competition_manager.similar_football_competition_names(message): # Registration recommendation context_manager.update_context(sender_id, ContextType.ADDING_REGISTRATION) # Register wrong search new_football_registration_manager.add_football_registration(message, 'user', user) recommendations = football_team_manager.similar_football_team_names(message)\ + football_competition_manager.similar_football_competition_names(message) # Format recommendation names recommendations = [recommendation.title() for recommendation in recommendations] response_msg.append( manager_response.send_recommended_registration_message(sender_id, recommendations) ) else: # No registration recommendation found context_manager.update_context(sender_id, ContextType.ADDING_REGISTRATION) # Register wrong search new_football_registration_manager.add_football_registration(message, 'user', user) response_msg.append( manager_response.send_registration_not_found_message(sender_id) ) # REMOVING REGISTRATION elif context_manager.is_deleting_team_context(sender_id): logger.log_for_user("REMOVING REGISTRATION", sender_id) registration_to_delete = message.lower() if football_team_manager.has_football_team(registration_to_delete): # Delete team registration_team_manager.delete_team(sender_id, registration_to_delete) response_msg.append( manager_response.send_registration_deleted_message(sender_id, registration_to_delete.title()) ) response_msg.append( view_message_helper.send_subscriptions_settings(sender_id) ) elif football_competition_manager.has_football_competition(registration_to_delete): # Delete competition registration_competition_manager.delete_competition(sender_id, registration_to_delete) response_msg.append( manager_response.send_registration_deleted_message(sender_id, registration_to_delete.title()) ) response_msg.append( view_message_helper.send_subscriptions_settings(sender_id) ) else: # Registration to delete not found context_manager.update_context(sender_id, ContextType.REMOVE_REGISTRATION) registrations = view_message_helper.get_registrations_formatted(sender_id) response_msg.append( manager_response.send_registration_to_delete_not_found_message(sender_id, registrations) ) # SUBSCRIPTION SETTING elif accepted_messages(message, ['subscription', 'teams', 'subscribe', 'notification', 'add', 'remove']): logger.log_for_user("SUBSCRIPTION SETTING", sender_id, extra={ 'action': 'subscriptions' }) response_msg.append( view_message_helper.send_subscriptions_settings(sender_id) ) # SEE RESULT SETTING elif accepted_messages(message, ['settings', 'see result setting', 'spoiler', 'show result', 'hide result', 'show score', 'hide score', 'no score']): logger.log_for_user("SEE RESULT SETTING", sender_id, extra={ 'action': 'settings' }) response_msg.append( view_message_helper.send_send_see_result_settings(sender_id) ) # SHARE elif accepted_messages(message, ['share', 'send to a friend']): logger.log_for_user("SHARE", sender_id, extra={ 'action': 'share' }) response_msg.append( manager_share.send_share_introduction_message(sender_id) ) response_msg.append( manager_share.send_share_message(sender_id) ) # SEARCH HIGHLIGHT OPTION elif accepted_messages(message, ['search', 'search again']): logger.log_for_user("SEARCH HIGHLIGHTS", sender_id, extra={ 'action': 'search' }) response_msg.append( view_message_helper.search_highlights(sender_id) ) # SEARCHING HIGHLIGHTS elif context_manager.is_searching_highlights_context(sender_id): logger.log_for_user("SEARCHING HIGHLIGHTS", sender_id, extra={ 'action': 'searching' }) team_or_competition = message if football_team_manager.has_football_team(team_or_competition) \ or football_competition_manager.has_football_competition(team_or_competition): # Team or competition found response_msg.append( manager_highlights.send_highlights_for_team_or_competition(sender_id, team_or_competition) ) elif football_team_manager.similar_football_team_names(team_or_competition) \ + football_competition_manager.similar_football_competition_names(team_or_competition): # Recommendation found # Register wrong search new_football_registration_manager.add_football_registration(team_or_competition, 'user', user) recommendations = football_team_manager.similar_football_team_names(team_or_competition) \ + football_competition_manager.similar_football_competition_names(team_or_competition) if len(recommendations) == 1: response_msg.append( manager_highlights.send_highlights_for_team_or_competition(sender_id, recommendations[0]) ) else: # Format recommendation names recommendations = [recommendation.title() for recommendation in recommendations] response_msg.append( manager_highlights.send_recommended_team_or_competition_message(sender_id, recommendations) ) else: # No team or recommendation found # Register wrong search new_football_registration_manager.add_football_registration(team_or_competition, 'user', user) response_msg.append( manager_highlights.send_team_not_found_tutorial_message(sender_id) ) if 'postback' in message: postback = message['postback']['payload'] logger.log_for_user("Postback message received", sender_id, extra={ 'full_msg': message, 'msg_type': 'postback' }) if postback == 'get_started': logger.log_for_user("GET STARTED POSTBACK", sender_id, extra={ 'action': 'start' }) response_msg.append( manager_response.send_getting_started_message(sender_id, user.first_name) ) response_msg.append( manager_response.send_getting_started_message_2(sender_id) ) # Set the user in tutorial context context_manager.update_context(sender_id, ContextType.TUTORIAL_ADD_TEAM) # SEARCH HIGHLIGHT SETTING POSTBACK elif postback == 'search_highlights': logger.log_for_user("SEARCH HIGHLIGHTS POSTBACK", sender_id, extra={ 'action': 'search' }) response_msg.append( view_message_helper.search_highlights(sender_id) ) # SUBSCRIPTION SETTING POSTBACK elif postback == 'my_subscriptions': logger.log_for_user("SUBSCRIPTION SETTING POSTBACK", sender_id, extra={ 'action': 'subscriptions' }) response_msg.append( view_message_helper.send_subscriptions_settings(sender_id) ) # SHARE POSTBACK elif postback == 'share': logger.log_for_user("SHARE POSTBACK", sender_id, extra={ 'action': 'share' }) response_msg.append( manager_share.send_share_introduction_message(sender_id) ) response_msg.append( manager_share.send_share_message(sender_id) ) # SEE RESULT SETTING POSTBACK elif postback == 'see_result_setting': logger.log_for_user("SEE RESULT SETTING POSTBACK", sender_id, extra={ 'action': 'settings' }) response_msg.append( view_message_helper.send_send_see_result_settings(sender_id) ) # Log the responses for msg in response_msg: logger.log_for_user("Message sent", sender_id, extra={ 'full_msg': msg, 'msg_type': 'response' }) HighlightsBotView.LATEST_SENDER_ID = 0 if not settings.DEBUG: return HttpResponse() else: # DEBUG MODE ONLY formatted_response = "[" + ", ".join(response_msg) + "]" return JsonResponse(formatted_response, safe=False)