def send_alert_pushbullet(alert, email): pb = PushBullet(settings.PUSHBULLET_ACCESS_TOKEN) title = 'new alert: %s' % (alert.title, ) pb.push_link(title, 'http://127.0.0.1:8000/', body=alert.get_body(), email=email)
def send_notification(api_key, page_title, site_url): print "Sending PushBullet notification" pb_client = PushBullet(api_key) pb_client.push_link("Update on {title}!".format(title=page_title), site_url)
class Notify: def __init__(self, title, link): self.__api = "" self.__title = title self.__link = link self.pb = PushBullet(self.__api) def push(self, message): self.pb.push_link(self.__title, self.__link, body=str(message))
class Notifier(BaseNotifier): def __init__(self, api_key): self.client = PushBullet(api_key) def notify(self, item): site_name = item.get('site') title = f'New property in {site_name}' link = item.get('url') self.client.push_link(title, link)
class Flow: def __init__(self, googleapi, api_key, email, **_): if api_key == 'YOUR_API_KEY_HERE': raise ValueError('Missing api key in settings') self.email = email self.pb = PushBullet(api_key) self.credentials_storage_path = googleapi.credentials_storage_path self.flow = flow_from_clientsecrets( filename=googleapi.client_secrets_path, scope='https://www.googleapis.com/auth/calendar.readonly', redirect_uri='urn:ietf:wg:oauth:2.0:oob') self.last_check = None self.callback = lambda: None def run(self, callback): self.callback = callback authorize_url = self.flow.step1_get_authorize_url() self.pb.push_link('Google Auth Request', authorize_url, email=self.email) self.last_check = datetime.now() def iter_received_codes(self): pushes = self.pb.get_pushes(modified_after=self.last_check.timestamp()) self.last_check = datetime.now() for push in pushes: if push['type'] == 'note' and push['sender_email'] == self.email: self.pb.dismiss_push(push['iden']) yield push['body'].strip() def check_response(self): if self.last_check is None: return for code in self.iter_received_codes(): try: credential = self.flow.step2_exchange(code) Storage(self.credentials_storage_path).put(credential) break except (ValueError, FlowExchangeError) as error: self.pb.push_note('', 'Error: ' + str(error), email=self.email) else: return self.last_check = None self.callback() self.pb.push_note('', 'Authentication complete', email=self.email)
def test_push_link(pb_push, pb_refresh): pb = PushBullet("apikey") pb.push_link( "test_note title", "https://google.com", "test_note body", email="*****@*****.**", ) pb_push.assert_called_with({ "type": "link", "title": "test_note title", "body": "test_note body", "url": "https://google.com", "email": "*****@*****.**", })
class PB_Alarm(Alarm): def __init__(self, api_key): self.client = PushBullet(api_key) log.info("PB_Alarm intialized.") push = self.client.push_note("PokeAlarm activated!", "We will alert you about pokemon.") def pokemon_alert(self, pokemon): #notification_text = "A wild " + pokemon['name'].title() + " has appeared!" # Or retrieve a channel by its channel_tag. Note that an InvalidKeyError is raised if the channel_tag does not exist #your pushbullet channelname my_channel = self.client.get_channel('YOURCHANNELNAME') google_maps_link = gmaps_link(pokemon["lat"], pokemon["lng"]) time_text = pkmn_time_text(pokemon['disappear_time']) notification_text = "("+ pokemon['name'].title() + " found" +"! "+" " + time_text + "." push = self.client.push_link(notification_text, google_maps_link, body=time_text) #send to channel push = self.client.push_link(notification_text, google_maps_link, body=time_text, channel=my_channel)
class PB_Alarm(Alarm): def __init__(self, api_key): self.client = PushBullet(api_key) log.info("PB_Alarm intialized.") push = self.client.push_note("PokeAlarm activated!", "We will alert you about pokemon.") def pokemon_alert(self, pokemon): notification_text = "A wild " + pokemon['name'].title() + " has appeared!" google_maps_link = gmaps_link(pokemon["lat"], pokemon["lng"]) time_text = pkmn_time_text(pokemon['disappear_time']) push = self.client.push_link(notification_text, google_maps_link, body=time_text)
def push(self): """ Push a task """ p = PushBullet(self.api) if self.type == 'text': success, push = p.push_note(self.title, self.message) elif self.type == 'list': self.message = self.message.split(',') success, push = p.push_list(self.title, self.message) elif self.type == 'link': success, push = p.push_link(self.title, self.message) else: success, push = p.push_file(file_url=self.message, file_name="cat.jpg", file_type="image/jpeg")
class StreamNotifier(Observer): '''Sends notifications when a new stream matching key_words begins.''' def __init__(self, config, store): self.key_words = config.key_words self.pushbullet = PushBullet(config.pushbullet_token) self.updated_streams = store.stream_changes.pipe( filter(lambda change: change['type'] == 'add' or (change[ 'type'] == 'change' and 'name' in change['changed_fields'])), pluck('stream')) def on_next(self, updated_stream): '''Responds to updates to the updated_streams observable.''' logger.info('change') for key_word in self.key_words: logger.info('checking for %s in %s', key_word, updated_stream.name) if search(key_word, updated_stream.name, flags=I): self.notify(updated_stream) break def notify(self, stream): '''Sends a notification.''' logger.info('Sending notification for stream \'%s\' by \'%s\'', stream.name, stream.streamer) self.pushbullet.push_link('%s | %s' % (stream.streamer, stream.name), stream.url) def run(self): '''Subscribes the notifier to changes to the store.''' logger.info('Starting stream notifier...') self.disposer = self.updated_streams.subscribe(self) def stop(self): '''Stops notifying on changes to the store.''' if hasattr(self, 'disposer'): logger.info('Stopping stream notifier...') self.disposer.dispose()
class Pushbullet_Alarm(Alarm): def __init__(self, settings): self.client = PushBullet(settings['api_key']) log_msg = "Pushbullet Alarm intialized" if 'name' in settings: self.name = settings['name'] log_mst = log_msg + ": " + self.name log.info(log_msg) push = self.client.push_note("PokeAlarm activated!", "We will alert you about pokemon.") def pokemon_alert(self, pkinfo): notification_text = pkinfo['alert'] if hasattr(self, 'name') : notification_text = self.name + ": " + notification_text gmaps_link = pkinfo['gmaps_link'] time_text = pkinfo['time_text'] push = self.client.push_link(notification_text, gmaps_link, body=time_text)
def mention(bot, event, *args): """alert a @mentioned user""" """allow mentions to be disabled via global or per-conversation config""" config_mentions_enabled = False if bot.get_config_suboption( event.conv.id_, 'mentions.enabled') is False else True if not config_mentions_enabled: logger.info("mentions explicitly disabled by config for {}".format( event.conv_id)) return """minimum length check for @mention""" minimum_length = bot.get_config_suboption(event.conv_id, 'mentionminlength') if not minimum_length: minimum_length = 2 username = args[0].strip() if len(username) < minimum_length: logger.debug("@mention from {} ({}) too short (== '{}')".format( event.user.full_name, event.user.id_.chat_id, username)) return users_in_chat = event.conv.users mention_chat_ids = [] """sync room support""" if bot.get_config_option('syncing_enabled'): sync_room_list = bot.get_config_option('sync_rooms') if sync_room_list: """scan through each room group""" for rooms_group in sync_room_list: if event.conv_id in rooms_group: """current conversation is part of a syncroom group, add "external" users""" for syncedroom in rooms_group: if event.conv_id is not syncedroom: users_in_chat += bot.get_users_in_conversation( syncedroom) users_in_chat = list(set(users_in_chat)) # make unique logger.debug( "@mention in a syncroom: {} user(s) present".format( len(users_in_chat))) break """ /bot mention <fragment> test """ noisy_mention_test = False if len(args) == 2 and args[1] == "test": noisy_mention_test = True initiator_has_dnd = _user_has_dnd(bot, event.user.id_.chat_id) """ quidproquo: users can only @mention if they themselves are @mentionable (i.e. have a 1-on-1 with the bot) """ conv_1on1_initiator = yield from bot.get_1to1( event.user.id_.chat_id, context={'initiator_convid': event.conv_id}) if bot.get_config_option("mentionquidproquo"): if conv_1on1_initiator: if initiator_has_dnd: logger.info("quidproquo: user {} ({}) has DND active".format( event.user.full_name, event.user.id_.chat_id)) if noisy_mention_test or bot.get_config_suboption( event.conv_id, 'mentionerrors'): yield from bot.coro_send_message( event.conv, _("<b>{}</b>, you cannot @mention anyone until your DND status is toggled off." ).format(event.user.full_name)) return else: logger.debug("quidproquo: user {} ({}) has 1-on-1".format( event.user.full_name, event.user.id_.chat_id)) else: logger.info("quidproquo: user {} ({}) has no 1-on-1".format( event.user.full_name, event.user.id_.chat_id)) if noisy_mention_test or bot.get_config_suboption( event.conv_id, 'mentionerrors'): yield from bot.coro_send_message( event.conv, _("<b>{}</b> cannot @mention anyone until they say something to me first." ).format(event.user.full_name)) return """track mention statistics""" user_tracking = { "mentioned": [], "ignored": [], "failed": { "pushbullet": [], "one2one": [], } } """ begin mentioning users as long as they exist in the current conversation... """ conversation_name = bot.conversations.get_name(event.conv) logger.info("@mention '{}' in '{}' ({})".format(username, conversation_name, event.conv.id_)) username_lower = username.lower() username_upper = username.upper() """is @all available globally/per-conversation/initiator?""" if username_lower == "all": if not bot.get_config_suboption(event.conv.id_, 'mentionall'): """global toggle is off/not set, check admins""" logger.debug( "@all in {}: disabled/unset global/per-conversation".format( event.conv.id_)) admins_list = bot.get_config_suboption(event.conv_id, 'admins') if event.user_id.chat_id not in admins_list: """initiator is not an admin, check whitelist""" logger.debug("@all in {}: user {} ({}) is not admin".format( event.conv.id_, event.user.full_name, event.user.id_.chat_id)) all_whitelist = bot.get_config_suboption( event.conv_id, 'mentionallwhitelist') if all_whitelist is None or event.user_id.chat_id not in all_whitelist: logger.warning("@all in {}: user {} ({}) blocked".format( event.conv.id_, event.user.full_name, event.user.id_.chat_id)) if conv_1on1_initiator: yield from bot.coro_send_message( conv_1on1_initiator, _("You are not allowed to mention all users in <b>{}</b>" ).format(conversation_name)) if noisy_mention_test or bot.get_config_suboption( event.conv_id, 'mentionerrors'): yield from bot.coro_send_message( event.conv, _("<b>{}</b> blocked from mentioning all users"). format(event.user.full_name)) return else: logger.info( "@all in {}: allowed, {} ({}) is whitelisted".format( event.conv.id_, event.user.full_name, event.user.id_.chat_id)) else: logger.info("@all in {}: allowed, {} ({}) is an admin".format( event.conv.id_, event.user.full_name, event.user.id_.chat_id)) else: logger.info("@all in {}: enabled global/per-conversation".format( event.conv.id_)) """generate a list of users to be @mentioned""" exact_nickname_matches = [] exact_fragment_matches = [] mention_list = [] for u in users_in_chat: # mentions also checks nicknames if one is configured # exact matches only! see following IF block nickname = "" nickname_lower = "" if bot.memory.exists(['user_data', u.id_.chat_id, "nickname"]): nickname = bot.memory.get_by_path( ['user_data', u.id_.chat_id, "nickname"]) nickname_lower = nickname.lower() _normalised_full_name_upper = remove_accents(u.full_name.upper()) if (username_lower == "all" or username_lower in u.full_name.replace(" ", "").lower() or username_upper in _normalised_full_name_upper.replace( " ", "") or username_lower in u.full_name.replace(" ", "_").lower() or username_upper in _normalised_full_name_upper.replace( " ", "_") or username_lower == nickname_lower or username in u.full_name.split(" ")): logger.info("user {} ({}) is present".format( u.full_name, u.id_.chat_id)) if u.is_self: """bot cannot be @mentioned""" logger.debug("suppressing bot mention by {} ({})".format( event.user.full_name, event.user.id_.chat_id)) continue if u.id_.chat_id == event.user.id_.chat_id and username_lower == "all": """prevent initiating user from receiving duplicate @all""" logger.debug("suppressing @all for {} ({})".format( event.user.full_name, event.user.id_.chat_id)) continue if u.id_.chat_id == event.user.id_.chat_id and not noisy_mention_test: """prevent initiating user from mentioning themselves""" logger.debug("suppressing @self for {} ({})".format( event.user.full_name, event.user.id_.chat_id)) continue if u.id_.chat_id in mention_chat_ids: """prevent most duplicate mentions (in the case of syncouts)""" logger.debug( "suppressing duplicate mention for {} ({})".format( event.user.full_name, event.user.id_.chat_id)) continue if bot.memory.exists(["donotdisturb"]): if _user_has_dnd(bot, u.id_.chat_id): logger.info("suppressing @mention for {} ({})".format( u.full_name, u.id_.chat_id)) user_tracking["ignored"].append(u.full_name) continue if username_lower == nickname_lower: if u not in exact_nickname_matches: exact_nickname_matches.append(u) if (username in u.full_name.split(" ") or username_upper in _normalised_full_name_upper.split(" ")): if u not in exact_fragment_matches: exact_fragment_matches.append(u) if u not in mention_list: mention_list.append(u) if len(exact_nickname_matches) == 1: """prioritise exact nickname matches""" logger.info("prioritising nickname match for {}".format( exact_nickname_matches[0].full_name)) mention_list = exact_nickname_matches elif len(exact_fragment_matches) == 1: """prioritise case-sensitive fragment matches""" logger.info( "prioritising single case-sensitive fragment match for {}".format( exact_fragment_matches[0].full_name)) mention_list = exact_fragment_matches elif len(exact_fragment_matches) > 1 and len(exact_fragment_matches) < len( mention_list): logger.info( "prioritising multiple case-sensitive fragment match for {}". format(exact_fragment_matches[0].full_name)) mention_list = exact_fragment_matches if len(mention_list) > 1 and username_lower != "all": send_multiple_user_message = True if bot.memory.exists([ 'user_data', event.user.id_.chat_id, "mentionmultipleusermessage" ]): send_multiple_user_message = bot.memory.get_by_path([ 'user_data', event.user.id_.chat_id, "mentionmultipleusermessage" ]) if send_multiple_user_message or noisy_mention_test: if conv_1on1_initiator: text_html = _( '{} users would be mentioned with "@{}"! Be more specific. List of matching users:<br />' ).format(len(mention_list), username, conversation_name) for u in mention_list: text_html += u.full_name if bot.memory.exists( ['user_data', u.id_.chat_id, "nickname"]): text_html += ' (' + bot.memory.get_by_path( ['user_data', u.id_.chat_id, "nickname"]) + ')' text_html += '<br />' text_html += "<br /><em>To toggle this message on/off, use <b>/bot bemorespecific</b></em>" yield from bot.coro_send_message(conv_1on1_initiator, text_html) logger.warning( "@{} not sent due to multiple recipients".format(username_lower)) return #SHORT-CIRCUIT """support for reprocessor override the source name by defining event._external_source""" source_name = event.user.full_name if hasattr(event, '_external_source'): source_name = event._external_source """send @mention alerts""" for u in mention_list: alert_via_1on1 = True """pushbullet integration""" if bot.memory.exists(['user_data', u.id_.chat_id, "pushbullet"]): pushbullet_config = bot.memory.get_by_path( ['user_data', u.id_.chat_id, "pushbullet"]) if pushbullet_config is not None: if pushbullet_config["api"] is not None: success = False try: pb = PushBullet(pushbullet_config["api"]) push = pb.push_link( title=_("{} mentioned you in {}").format( source_name, conversation_name), body=event.text, url='https://hangouts.google.com/chat/{}'.format( event.conv.id_)) if isinstance(push, tuple): # backward-compatibility for pushbullet library < 0.8.0 success = push[0] elif isinstance(push, dict): success = True else: raise TypeError( "unknown return from pushbullet library: {}". format(push)) except Exception as e: logger.exception("pushbullet error") if success: user_tracking["mentioned"].append(u.full_name) logger.info("{} ({}) alerted via pushbullet".format( u.full_name, u.id_.chat_id)) alert_via_1on1 = False # disable 1on1 alert else: user_tracking["failed"]["pushbullet"].append( u.full_name) logger.warning( "pushbullet alert failed for {} ({})".format( u.full_name, u.id_.chat_id)) if alert_via_1on1: """send alert with 1on1 conversation""" conv_1on1 = yield from bot.get_1to1( u.id_.chat_id, context={'initiator_convid': event.conv_id}) if username_lower == "all": message_mentioned = _( "<b>{}</b> @mentioned ALL in <i>{}</i>:<br />{}") else: message_mentioned = _( "<b>{}</b> @mentioned you in <i>{}</i>:<br />{}") if conv_1on1: yield from bot.coro_send_message( conv_1on1, message_mentioned.format(source_name, conversation_name, event.text) ) # prevent internal parser from removing <tags> mention_chat_ids.append(u.id_.chat_id) user_tracking["mentioned"].append(u.full_name) logger.info("{} ({}) alerted via 1on1 ({})".format( u.full_name, u.id_.chat_id, conv_1on1.id_)) else: user_tracking["failed"]["one2one"].append(u.full_name) if bot.get_config_suboption(event.conv_id, 'mentionerrors'): yield from bot.coro_send_message( event.conv, _("@mention didn't work for <b>{}</b>. User must say something to me first." ).format(u.full_name)) logger.warning( "user {} ({}) could not be alerted via 1on1".format( u.full_name, u.id_.chat_id)) if noisy_mention_test: text_html = _("<b>@mentions:</b><br />") if len(user_tracking["failed"]["one2one"]) > 0: text_html = text_html + _("1-to-1 fail: <i>{}</i><br />").format( ", ".join(user_tracking["failed"]["one2one"])) if len(user_tracking["failed"]["pushbullet"]) > 0: text_html = text_html + _( "PushBullet fail: <i>{}</i><br />").format(", ".join( user_tracking["failed"]["pushbullet"])) if len(user_tracking["ignored"]) > 0: text_html = text_html + _("Ignored (DND): <i>{}</i><br />").format( ", ".join(user_tracking["ignored"])) if len(user_tracking["mentioned"]) > 0: text_html = text_html + _("Alerted: <i>{}</i><br />").format( ", ".join(user_tracking["mentioned"])) else: text_html = text_html + _( "Nobody was successfully @mentioned ;-(<br />") if len(user_tracking["failed"]["one2one"]) > 0: text_html = text_html + _( "Users failing 1-to-1 need to say something to me privately first.<br />" ) yield from bot.coro_send_message(event.conv, text_html)
def mention(bot, event, *args): """alert a @mentioned user""" """allow mentions to be disabled via global or per-conversation config""" config_mentions_enabled = False if bot.get_config_suboption(event.conv.id_, 'mentions.enabled') is False else True if not config_mentions_enabled: logger.info("mentions explicitly disabled by config for {}".format(event.conv_id)) return """minimum length check for @mention""" minimum_length = bot.get_config_suboption(event.conv_id, 'mentionminlength') if not minimum_length: minimum_length = 2 username = args[0].strip() if len(username) < minimum_length: logger.debug("@mention from {} ({}) too short (== '{}')".format(event.user.full_name, event.user.id_.chat_id, username)) return users_in_chat = event.conv.users mention_chat_ids = [] """sync room support""" if bot.get_config_option('syncing_enabled'): sync_room_list = bot.get_config_option('sync_rooms') if sync_room_list: """scan through each room group""" for rooms_group in sync_room_list: if event.conv_id in rooms_group: """current conversation is part of a syncroom group, add "external" users""" for syncedroom in rooms_group: if event.conv_id is not syncedroom: users_in_chat += bot.get_users_in_conversation(syncedroom) users_in_chat = list(set(users_in_chat)) # make unique logger.debug("@mention in a syncroom: {} user(s) present".format(len(users_in_chat))) break """ /bot mention <fragment> test """ noisy_mention_test = False if len(args) == 2 and args[1] == "test": noisy_mention_test = True initiator_has_dnd = _user_has_dnd(bot, event.user.id_.chat_id) """ quidproquo: users can only @mention if they themselves are @mentionable (i.e. have a 1-on-1 with the bot) """ conv_1on1_initiator = yield from bot.get_1to1(event.user.id_.chat_id, context={ 'initiator_convid': event.conv_id }) if bot.get_config_option("mentionquidproquo"): if conv_1on1_initiator: if initiator_has_dnd: logger.info("quidproquo: user {} ({}) has DND active".format(event.user.full_name, event.user.id_.chat_id)) if noisy_mention_test or bot.get_config_suboption(event.conv_id, 'mentionerrors'): yield from bot.coro_send_message( event.conv, _("<b>{}</b>, you cannot @mention anyone until your DND status is toggled off.").format( event.user.full_name)) return else: logger.debug("quidproquo: user {} ({}) has 1-on-1".format(event.user.full_name, event.user.id_.chat_id)) else: logger.info("quidproquo: user {} ({}) has no 1-on-1".format(event.user.full_name, event.user.id_.chat_id)) if noisy_mention_test or bot.get_config_suboption(event.conv_id, 'mentionerrors'): yield from bot.coro_send_message( event.conv, _("<b>{}</b> cannot @mention anyone until they say something to me first.").format( event.user.full_name)) return """track mention statistics""" user_tracking = { "mentioned":[], "ignored":[], "failed": { "pushbullet": [], "one2one": [], } } """ begin mentioning users as long as they exist in the current conversation... """ conversation_name = bot.conversations.get_name(event.conv) logger.info("@mention '{}' in '{}' ({})".format(username, conversation_name, event.conv.id_)) username_lower = username.lower() username_upper = username.upper() """is @all available globally/per-conversation/initiator?""" if username_lower == "all": if not bot.get_config_suboption(event.conv.id_, 'mentionall'): """global toggle is off/not set, check admins""" logger.debug("@all in {}: disabled/unset global/per-conversation".format(event.conv.id_)) admins_list = bot.get_config_suboption(event.conv_id, 'admins') if event.user_id.chat_id not in admins_list: """initiator is not an admin, check whitelist""" logger.debug("@all in {}: user {} ({}) is not admin".format(event.conv.id_, event.user.full_name, event.user.id_.chat_id)) all_whitelist = bot.get_config_suboption(event.conv_id, 'mentionallwhitelist') if all_whitelist is None or event.user_id.chat_id not in all_whitelist: logger.warning("@all in {}: user {} ({}) blocked".format(event.conv.id_, event.user.full_name, event.user.id_.chat_id)) if conv_1on1_initiator: yield from bot.coro_send_message( conv_1on1_initiator, _("You are not allowed to mention all users in <b>{}</b>").format( conversation_name)) if noisy_mention_test or bot.get_config_suboption(event.conv_id, 'mentionerrors'): yield from bot.coro_send_message( event.conv, _("<b>{}</b> blocked from mentioning all users").format( event.user.full_name)) return else: logger.info("@all in {}: allowed, {} ({}) is whitelisted".format(event.conv.id_, event.user.full_name, event.user.id_.chat_id)) else: logger.info("@all in {}: allowed, {} ({}) is an admin".format(event.conv.id_, event.user.full_name, event.user.id_.chat_id)) else: logger.info("@all in {}: enabled global/per-conversation".format(event.conv.id_)) """generate a list of users to be @mentioned""" exact_nickname_matches = [] exact_fragment_matches = [] mention_list = [] for u in users_in_chat: # mentions also checks nicknames if one is configured # exact matches only! see following IF block nickname = "" nickname_lower = "" if bot.memory.exists(['user_data', u.id_.chat_id, "nickname"]): nickname = bot.memory.get_by_path(['user_data', u.id_.chat_id, "nickname"]) nickname_lower = nickname.lower() _normalised_full_name_upper = remove_accents(u.full_name.upper()) if (username_lower == "all" or username_lower in u.full_name.replace(" ", "").lower() or username_upper in _normalised_full_name_upper.replace(" ", "") or username_lower in u.full_name.replace(" ", "_").lower() or username_upper in _normalised_full_name_upper.replace(" ", "_") or username_lower == nickname_lower or username in u.full_name.split(" ")): logger.info("user {} ({}) is present".format(u.full_name, u.id_.chat_id)) if u.is_self: """bot cannot be @mentioned""" logger.debug("suppressing bot mention by {} ({})".format(event.user.full_name, event.user.id_.chat_id)) continue if u.id_.chat_id == event.user.id_.chat_id and username_lower == "all": """prevent initiating user from receiving duplicate @all""" logger.debug("suppressing @all for {} ({})".format(event.user.full_name, event.user.id_.chat_id)) continue if u.id_.chat_id == event.user.id_.chat_id and not noisy_mention_test: """prevent initiating user from mentioning themselves""" logger.debug("suppressing @self for {} ({})".format(event.user.full_name, event.user.id_.chat_id)) continue if u.id_.chat_id in mention_chat_ids: """prevent most duplicate mentions (in the case of syncouts)""" logger.debug("suppressing duplicate mention for {} ({})".format(event.user.full_name, event.user.id_.chat_id)) continue if bot.memory.exists(["donotdisturb"]): if _user_has_dnd(bot, u.id_.chat_id): logger.info("suppressing @mention for {} ({})".format(u.full_name, u.id_.chat_id)) user_tracking["ignored"].append(u.full_name) continue if username_lower == nickname_lower: if u not in exact_nickname_matches: exact_nickname_matches.append(u) if (username in u.full_name.split(" ") or username_upper in _normalised_full_name_upper.split(" ")): if u not in exact_fragment_matches: exact_fragment_matches.append(u) if u not in mention_list: mention_list.append(u) if len(exact_nickname_matches) == 1: """prioritise exact nickname matches""" logger.info("prioritising nickname match for {}".format(exact_nickname_matches[0].full_name)) mention_list = exact_nickname_matches elif len(exact_fragment_matches) == 1: """prioritise case-sensitive fragment matches""" logger.info("prioritising single case-sensitive fragment match for {}".format(exact_fragment_matches[0].full_name)) mention_list = exact_fragment_matches elif len(exact_fragment_matches) > 1 and len(exact_fragment_matches) < len(mention_list): logger.info("prioritising multiple case-sensitive fragment match for {}".format(exact_fragment_matches[0].full_name)) mention_list = exact_fragment_matches if len(mention_list) > 1 and username_lower != "all": send_multiple_user_message = True if bot.memory.exists(['user_data', event.user.id_.chat_id, "mentionmultipleusermessage"]): send_multiple_user_message = bot.memory.get_by_path(['user_data', event.user.id_.chat_id, "mentionmultipleusermessage"]) if send_multiple_user_message or noisy_mention_test: if conv_1on1_initiator: text_html = _('{} users would be mentioned with "@{}"! Be more specific. List of matching users:<br />').format( len(mention_list), username, conversation_name) for u in mention_list: text_html += u.full_name if bot.memory.exists(['user_data', u.id_.chat_id, "nickname"]): text_html += ' (' + bot.memory.get_by_path(['user_data', u.id_.chat_id, "nickname"]) + ')' text_html += '<br />' text_html += "<br /><em>To toggle this message on/off, use <b>/bot bemorespecific</b></em>" yield from bot.coro_send_message(conv_1on1_initiator, text_html) logger.warning("@{} not sent due to multiple recipients".format(username_lower)) return #SHORT-CIRCUIT """support for reprocessor override the source name by defining event._external_source""" source_name = event.user.full_name if hasattr(event, '_external_source'): source_name = event._external_source """send @mention alerts""" for u in mention_list: alert_via_1on1 = True """pushbullet integration""" if bot.memory.exists(['user_data', u.id_.chat_id, "pushbullet"]): pushbullet_config = bot.memory.get_by_path(['user_data', u.id_.chat_id, "pushbullet"]) if pushbullet_config is not None: if pushbullet_config["api"] is not None: success = False try: pb = PushBullet(pushbullet_config["api"]) push = pb.push_link( title = _("{} mentioned you in {}").format(source_name, conversation_name), body=event.text, url='https://hangouts.google.com/chat/{}'.format(event.conv.id_) ) if isinstance(push, tuple): # backward-compatibility for pushbullet library < 0.8.0 success = push[0] elif isinstance(push, dict): success = True else: raise TypeError("unknown return from pushbullet library: {}".format(push)) except Exception as e: logger.exception("pushbullet error") if success: user_tracking["mentioned"].append(u.full_name) logger.info("{} ({}) alerted via pushbullet".format(u.full_name, u.id_.chat_id)) alert_via_1on1 = False # disable 1on1 alert else: user_tracking["failed"]["pushbullet"].append(u.full_name) logger.warning("pushbullet alert failed for {} ({})".format(u.full_name, u.id_.chat_id)) if alert_via_1on1: """send alert with 1on1 conversation""" conv_1on1 = yield from bot.get_1to1(u.id_.chat_id, context={ 'initiator_convid': event.conv_id }) if username_lower == "all": message_mentioned = _("<b>{}</b> @mentioned ALL in <i>{}</i>:<br />{}") else: message_mentioned = _("<b>{}</b> @mentioned you in <i>{}</i>:<br />{}") if conv_1on1: yield from bot.coro_send_message( conv_1on1, message_mentioned.format( source_name, conversation_name, event.text)) # prevent internal parser from removing <tags> mention_chat_ids.append(u.id_.chat_id) user_tracking["mentioned"].append(u.full_name) logger.info("{} ({}) alerted via 1on1 ({})".format(u.full_name, u.id_.chat_id, conv_1on1.id_)) else: user_tracking["failed"]["one2one"].append(u.full_name) if bot.get_config_suboption(event.conv_id, 'mentionerrors'): yield from bot.coro_send_message( event.conv, _("@mention didn't work for <b>{}</b>. User must say something to me first.").format( u.full_name)) logger.warning("user {} ({}) could not be alerted via 1on1".format(u.full_name, u.id_.chat_id)) if noisy_mention_test: text_html = _("<b>@mentions:</b><br />") if len(user_tracking["failed"]["one2one"]) > 0: text_html = text_html + _("1-to-1 fail: <i>{}</i><br />").format(", ".join(user_tracking["failed"]["one2one"])) if len(user_tracking["failed"]["pushbullet"]) > 0: text_html = text_html + _("PushBullet fail: <i>{}</i><br />").format(", ".join(user_tracking["failed"]["pushbullet"])) if len(user_tracking["ignored"]) > 0: text_html = text_html + _("Ignored (DND): <i>{}</i><br />").format(", ".join(user_tracking["ignored"])) if len(user_tracking["mentioned"]) > 0: text_html = text_html + _("Alerted: <i>{}</i><br />").format(", ".join(user_tracking["mentioned"])) else: text_html = text_html + _("Nobody was successfully @mentioned ;-(<br />") if len(user_tracking["failed"]["one2one"]) > 0: text_html = text_html + _("Users failing 1-to-1 need to say something to me privately first.<br />") yield from bot.coro_send_message(event.conv, text_html)
def push_link(entries_list): print apiKey client = PushBullet(apiKey) for entry in entries_list: client.push_link(entry["title"], entry["link"])