Example #1
0
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))
Example #4
0
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)
Example #5
0
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": "*****@*****.**",
    })
Example #7
0
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)
Example #8
0
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)
Example #9
0
 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")
Example #10
0
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()
Example #11
0
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)
Example #12
0
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)
Example #13
0
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)
Example #14
0
def push_link(entries_list):
  print apiKey
  client = PushBullet(apiKey)
  for entry in entries_list:
    client.push_link(entry["title"], entry["link"])
Example #15
0
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)
Example #16
0
def push_link(entries_list):
    print apiKey
    client = PushBullet(apiKey)
    for entry in entries_list:
        client.push_link(entry["title"], entry["link"])