Exemple #1
0
def convrename(bot, event, *args):
    """renames a single specified conversation"""
    posix_args = get_posix_args(args)

    if len(posix_args) > 1:
        if not posix_args[0].startswith(("id:", "text:")):
            # always force explicit search for single conversation on vague user request
            posix_args[0] = "id:" + posix_args[0]
        convlist = bot.conversations.get(filter=posix_args[0])
        title = ' '.join(posix_args[1:])

        # only act on the first matching conversation

        yield from bot._client.rename_conversation(
            hangups.hangouts_pb2.RenameConversationRequest(
                request_header = bot._client.get_request_header(),
                new_name = title,
                event_request_header = hangups.hangouts_pb2.EventRequestHeader(
                    conversation_id = hangups.hangouts_pb2.ConversationId(
                        id = list(convlist.keys())[0] ),
                    client_generated_id = bot._client.get_client_generated_id() )))

    elif len(posix_args) == 1 and posix_args[0].startswith("id:"):
        """specialised error message for /bot rename (implied convid: <event.conv_id>)"""
        text = _("<em>missing title</em>")
        convlist = bot.conversations.get(filter=event.conv_id)
        yield from command.run(bot, event, *["convecho", "id:" + event.conv_id, text])
    else:
        """general error"""
        text = _("<em>required parameters: convfilter title</em>")
        convlist = bot.conversations.get(filter=event.conv_id)
        yield from command.run(bot, event, *["convecho", "id:" + event.conv_id, text])
Exemple #2
0
    def handle_chat_message(self, event):
        """Handle conversation event"""
        if logging.root.level == logging.DEBUG:
            event.print_debug(self.bot)

        if event.text:
            if event.user.is_self:
                event.from_bot = True
            else:
                event.from_bot = False

            """reprocessor - process event with hidden context from handler.attach_reprocessor()"""
            if len(event.conv_event.segments) > 0:
                for segment in event.conv_event.segments:
                    if segment.link_target:
                        if segment.link_target.startswith(self._prefix_reprocessor):
                            _id = segment.link_target[len(self._prefix_reprocessor):]
                            if _id in self._reprocessors:
                                logger.info("valid reprocessor uuid found: {}".format(_id))
                                self._reprocessors[_id](self.bot, event, _id)
                                del self._reprocessors[_id]

            """auto opt-in - opted-out users who chat with the bot will be opted-in again"""
            if self.bot.conversations.catalog[event.conv_id]["type"] == "ONE_TO_ONE":
                if self.bot.memory.exists(["user_data", event.user.id_.chat_id, "optout"]):
                    if self.bot.memory.get_by_path(["user_data", event.user.id_.chat_id, "optout"]):
                        yield from command.run(self.bot, event, *["optout"])
                        logger.info("auto opt-in for {}".format(event.user.id_.chat_id))
                        return

            yield from self.run_pluggable_omnibus("allmessages", self.bot, event, command)
            if not event.from_bot:
                yield from self.run_pluggable_omnibus("message", self.bot, event, command)
                yield from self.handle_command(event)
Exemple #3
0
def echo(bot, event, *args):
    """echo back text into conversation"""
    raw_arguments = event.text.split(maxsplit=3)
    if len(raw_arguments) >= 3:
        if raw_arguments[2] in bot.conversations.catalog:
            # e.g. /bot echo <convid> <text>
            # only admins can echo messages into other conversations
            admins_list = bot.get_config_suboption(event.conv_id, 'admins')
            if event.user_id.chat_id in admins_list:
                convid = raw_arguments[2]
            else:
                convid = event.conv_id
                raw_arguments = [
                    _("<b>only admins can echo other conversations</b>")
                ]
        else:
            # assumed /bot echo <text>
            convid = event.conv_id
            raw_arguments = event.text.split(maxsplit=2)

        _text = raw_arguments[-1].strip()

        if _text.startswith("raw:"):
            _text = _text[4:].strip()
        else:
            # emulate pre-2.5 bot behaviour and limitations
            _text = re.escape(_text)

        yield from command.run(bot, event,
                               *["convecho", "id:" + convid, _text])
Exemple #4
0
    def handle_chat_message(self, event):
        """Handle conversation event"""
        if event.text:
            if event.user.is_self:
                event.from_bot = True
            else:
                event.from_bot = False
            """reprocessor - process event with hidden context from handler.attach_reprocessor()"""
            if len(event.conv_event.segments) > 0:
                for segment in event.conv_event.segments:
                    if segment.link_target:
                        if segment.link_target.startswith(
                                self._prefix_reprocessor):
                            _id = segment.link_target[
                                len(self._prefix_reprocessor):]
                            yield from self.run_reprocessor(_id, event)
            """auto opt-in - opted-out users who chat with the bot will be opted-in again"""
            if self.bot.conversations.catalog[
                    event.conv_id]["type"] == "ONE_TO_ONE":
                if self.bot.memory.exists(
                    ["user_data", event.user.id_.chat_id, "optout"]):
                    if self.bot.memory.get_by_path(
                        ["user_data", event.user.id_.chat_id, "optout"]):
                        yield from command.run(self.bot, event, *["optout"])
                        logger.info("auto opt-in for {}".format(
                            event.user.id_.chat_id))
                        return

            yield from self.run_pluggable_omnibus("allmessages", self.bot,
                                                  event, command)
            if not event.from_bot:
                yield from self.run_pluggable_omnibus("message", self.bot,
                                                      event, command)
                yield from self.handle_command(event)
Exemple #5
0
    def handle_command(self, event):
        """Handle command messages"""
        # Test if command handling is enabled
        if not self.bot.get_config_suboption(event.conv_id,
                                             'commands_enabled'):
            return

        # Parse message
        event.text = event.text.replace(
            u'\xa0', u' ')  # convert non-breaking space in Latin1 (ISO 8859-1)
        line_args = shlex.split(event.text, posix=False)

        # Test if command length is sufficient
        if len(line_args) < 2:
            self.bot.send_message(
                event.conv,
                '{}: missing parameter(s)'.format(event.user.full_name))
            return

        # Test if user has permissions for running command
        commands_admin_list = self.bot.get_config_suboption(
            event.conv_id, 'commands_admin')
        if commands_admin_list and line_args[1].lower() in commands_admin_list:
            admins_list = self.bot.get_config_suboption(
                event.conv_id, 'admins')
            if event.user_id.chat_id not in admins_list:
                self.bot.send_message(
                    event.conv,
                    '{}: I\'m sorry. I\'m afraid I can\'t do that.'.format(
                        event.user.full_name))
                return

        # Run command
        yield from command.run(self.bot, event, *line_args[1:])
Exemple #6
0
    def handle_chat_message(self, event):
        """Handle conversation event"""
        if event.text:
            if event.user.is_self:
                event.from_bot = True
            else:
                event.from_bot = False

            """reprocessor - process event with hidden context from handler.attach_reprocessor()"""
            if len(event.conv_event.segments) > 0:
                for segment in event.conv_event.segments:
                    if segment.link_target:
                        if segment.link_target.startswith(self._prefix_reprocessor):
                            _id = segment.link_target[len(self._prefix_reprocessor):]
                            yield from self.run_reprocessor(_id, event)

            """auto opt-in - opted-out users who chat with the bot will be opted-in again"""
            if not event.from_bot and self.bot.conversations.catalog[event.conv_id]["type"] == "ONE_TO_ONE":
                if self.bot.memory.exists(["user_data", event.user.id_.chat_id, "optout"]):
                    optout = self.bot.memory.get_by_path(["user_data", event.user.id_.chat_id, "optout"])
                    if isinstance(optout, bool) and optout:
                        yield from command.run(self.bot, event, *["optout"])
                        logger.info("auto opt-in for {}".format(event.user.id_.chat_id))
                        return

            yield from self.run_pluggable_omnibus("allmessages", self.bot, event, command)
            if not event.from_bot:
                yield from self.run_pluggable_omnibus("message", self.bot, event, command)
                yield from self.handle_command(event)
Exemple #7
0
def echo(bot, event, *args):
    """echo back text into conversation"""
    raw_arguments = event.text.split(maxsplit=3)
    if len(raw_arguments) >= 3:
        if raw_arguments[2] in bot.conversations.catalog:
            # e.g. /bot echo <convid> <text>
            # only admins can echo messages into other conversations
            admins_list = bot.get_config_suboption(event.conv_id, 'admins')
            if event.user_id.chat_id in admins_list:
                convid = raw_arguments[2]
            else:
                convid = event.conv_id
                raw_arguments = [ _("<b>only admins can echo other conversations</b>") ]
        else:
            # assumed /bot echo <text>
            convid = event.conv_id
            raw_arguments = event.text.split(maxsplit=2)

        _text = raw_arguments[-1].strip()

        if _text.startswith("raw:"):
            _text = _text[4:].strip()
        else:
            # emulate pre-2.5 bot behaviour and limitations
            _text = re.escape(_text)

        yield from command.run(bot, event, *["convecho", "id:" + convid, _text])
def approve(bot, event, *args):
    conn = sqlite3.connect('bot.db')
    request = args[0]
    request_number = str(args[1])
    if request.lower() == 'poll':
        if not bot.memory.exists(["requests"]):
            yield from bot.coro_send_message(event.conv, _("No requests"))
            return
        else:
            path = bot.memory.get_by_path(
                ["requests", "polls", str(request_number)])
            conversation_id = path.split()[0]
            command_to_run = path.split()[2:]
            yield from command.run(bot, event, *command_to_run)
            yield from bot.coro_send_message(conversation_id, _("Poll {} approved").format(request_number))
            return
    elif request.lower() == 'quote':
        c = conn.cursor()
        c.execute('SELECT * FROM unapp_quotes WHERE id = ?', [request_number])
        q = c.fetchone() 
        c.execute("INSERT INTO quotes(author, quote) VALUES (?, ?)", [q[0], q[1]])
        conn.commit()
        yield from bot.coro_send_message(event.conv, _("Quote {} approved").format(c.lastrowid))
    else:
        yield from bot.coro_send_message(event.conv, _("Approval for that not yet supported"))
Exemple #9
0
 def handle_mention(self, event):
     """handle @mention"""
     occurrences = [word for word in event.text.split() if word.startswith('@')]
     if len(occurrences) > 0:
         for word in occurrences:
             # strip all special characters
             cleaned_name = ''.join(e for e in word if e.isalnum())
             yield from command.run(self.bot, event, *["mention", cleaned_name])
Exemple #10
0
    def handle_command(self, event):
        """Handle command messages"""

        # is commands_enabled?

        config_commands_enabled = self.bot.get_config_suboption(event.conv_id, 'commands_enabled')
        tagged_ignore = "ignore" in self.bot.tags.useractive(event.user_id.chat_id, event.conv_id)

        if not config_commands_enabled or tagged_ignore:
            admins_list = self.bot.get_config_suboption(event.conv_id, 'admins') or []
            # admins always have commands enabled
            if event.user_id.chat_id not in admins_list:
                return

        # ensure bot alias is always a list
        if not isinstance(self.bot_command, list):
            self.bot_command = [self.bot_command]

        # check that a bot alias is used e.g. /syrupbot
        if not event.text.split()[0].lower() in self.bot_command:
            return

        # Parse message
        event.text = event.text.replace(u'\xa0', u' ') # convert non-breaking space in Latin1 (ISO 8859-1)
        try:
            line_args = shlex.split(event.text, posix=False)
        except Exception as e:
            logger.exception(e)
            yield from self.bot.coro_send_message(event.conv, _("{}: {}").format(
                event.user.full_name, str(e)))
            return

        # Test if command length is sufficient
        if len(line_args) < 2:
            yield from self.bot.coro_send_message(event.conv, _('{}: Missing parameter(s)').format(
                event.user.full_name))
            return

        commands = command.get_available_commands(self.bot, event.user.id_.chat_id, event.conv_id)

        supplied_command = line_args[1].lower()
        if supplied_command in commands["user"]:
            pass
        elif supplied_command in commands["admin"]:
            pass
        elif supplied_command in command.commands:
            yield from command.blocked_command(self.bot, event, *line_args[1:])
            return
        else:
            yield from command.unknown_command(self.bot, event, *line_args[1:])
            return

        # Run command
        results = yield from command.run(self.bot, event, *line_args[1:])

        if "acknowledge" in dir(event):
            for id in event.acknowledge:
                yield from self.run_reprocessor(id, event, results)
Exemple #11
0
    def handle_command(self, event):
        """Handle command messages"""

        # verify user is an admin
        admins_list = self.bot.get_config_suboption(event.conv_id, 'admins')
        initiator_is_admin = False
        if event.user_id.chat_id in admins_list:
            initiator_is_admin = True

        # Test if command handling is enabled
        # note: admins always bypass this check
        if not initiator_is_admin:
            if not self.bot.get_config_suboption(event.conv_id,
                                                 'commands_enabled'):
                return

        if not isinstance(self.bot_command, list):
            # always a list
            self.bot_command = [self.bot_command]

        if not event.text.split()[0].lower() in self.bot_command:
            return

        # Parse message
        event.text = event.text.replace(
            u'\xa0', u' ')  # convert non-breaking space in Latin1 (ISO 8859-1)
        try:
            line_args = shlex.split(event.text, posix=False)
        except Exception as e:
            print("EXCEPTION in {}: {}".format("handle_command", e))
            self.bot.send_message_parsed(
                event.conv,
                _("{}: {}").format(event.user.full_name, str(e)))
            logger.exception(e)
            return

        # Test if command length is sufficient
        if len(line_args) < 2:
            self.bot.send_message_parsed(
                event.conv,
                _('{}: Missing parameter(s)').format(event.user.full_name))
            return

        # only admins can run admin commands
        commands_admin_list = command.get_admin_commands(
            self.bot, event.conv_id)
        if commands_admin_list and line_args[1].lower() in commands_admin_list:
            if not initiator_is_admin:
                self.bot.send_message_parsed(
                    event.conv,
                    _('{}: Can\'t do that.').format(event.user.full_name))
                return

        # Run command
        yield from command.run(self.bot, event, *line_args[1:])
Exemple #12
0
def convrename(bot, event, *args):
    """renames a single specified conversation"""
    posix_args = get_posix_args(args)

    if len(posix_args) > 1:
        if not posix_args[0].startswith(("id:", "text:")):
            # always force explicit search for single conversation on vague user request
            posix_args[0] = "id:" + posix_args[0]
        convlist = bot.conversations.get(filter=posix_args[0])
        title = ' '.join(posix_args[1:])
        # only act on the first matching conversation
        yield from bot._client.setchatname(list(convlist.keys())[0], title)
    elif len(posix_args) == 1 and posix_args[0].startswith("id:"):
        """specialised error message for /bot rename (implied convid: <event.conv_id>)"""
        text = _("<em>missing title</em>")
        convlist = bot.conversations.get(filter=event.conv_id)
        yield from command.run(bot, event, *["convecho", "id:" + event.conv_id, text])
    else:
        """general error"""
        text = _("<em>required parameters: convfilter title</em>")
        convlist = bot.conversations.get(filter=event.conv_id)
        yield from command.run(bot, event, *["convecho", "id:" + event.conv_id, text])
Exemple #13
0
def leave(bot, event, conversation_id=None, *args):
    """exits current or other specified hangout"""

    arglist = list(args)

    if conversation_id == "quietly":
        arglist.append("quietly")
        conversation_id = False

    if not conversation_id:
        conversation_id = event.conv_id

    yield from command.run(bot, event, *["convleave", "id:" + conversation_id, " ".join(arglist)])
Exemple #14
0
def leave(bot, event, conversation_id=None, *args):
    """exits current or other specified hangout"""

    arglist = list(args)

    if conversation_id == "quietly":
        arglist.append("quietly")
        conversation_id = False

    if not conversation_id:
        conversation_id = event.conv_id

    yield from command.run(bot, event, *["convleave", "id:" + conversation_id, " ".join(arglist)])
Exemple #15
0
def convrename(bot, event, *args):
    """renames a single specified conversation"""
    posix_args = get_posix_args(args)

    if len(posix_args) > 1:
        if not posix_args[0].startswith(("id:", "text:")):
            # always force explicit search for single conversation on vague user request
            posix_args[0] = "id:" + posix_args[0]
        convlist = bot.conversations.get(filter=posix_args[0])
        title = ' '.join(posix_args[1:])
        # only act on the first matching conversation
        yield from bot._client.setchatname(list(convlist.keys())[0], title)
    elif len(posix_args) == 1 and posix_args[0].startswith("id:"):
        """specialised error message for /devilbot rename (implied convid: <event.conv_id>)"""
        text = _("<em>missing title</em>")
        convlist = bot.conversations.get(filter=event.conv_id)
        yield from command.run(bot, event, *["convecho", "id:" + event.conv_id, text])
    else:
        """general error"""
        text = _("<em>required parameters: convfilter title</em>")
        convlist = bot.conversations.get(filter=event.conv_id)
        yield from command.run(bot, event, *["convecho", "id:" + event.conv_id, text])
Exemple #16
0
    def handle_command(self, event):
        """Handle command messages"""

        # verify user is an admin
        admins_list = self.bot.get_config_suboption(event.conv_id, 'admins')
        initiator_is_admin = False
        if event.user_id.chat_id in admins_list:
            initiator_is_admin = True

        # Test if command handling is enabled
        # note: admins always bypass this check
        if not initiator_is_admin:
            if not self.bot.get_config_suboption(event.conv_id, 'commands_enabled'):
                return

        if not isinstance(self.bot_command, list):
            # always a list
            self.bot_command = [self.bot_command]

        if not event.text.split()[0].lower() in self.bot_command:
            return

        # Parse message
        event.text = event.text.replace(u'\xa0', u' ') # convert non-breaking space in Latin1 (ISO 8859-1)
        try:
            line_args = shlex.split(event.text, posix=False)
        except Exception as e:
            print("EXCEPTION in {}: {}".format("handle_command", e))
            self.bot.send_message_parsed(event.conv, _("{}: {}").format(
                event.user.full_name, str(e)))
            logger.exception(e)
            return

        # Test if command length is sufficient
        if len(line_args) < 2:
            self.bot.send_message_parsed(event.conv, _('{}: Missing parameter(s)').format(
                event.user.full_name))
            return

        # only admins can run admin commands
        commands_admin_list = command.get_admin_commands(self.bot, event.conv_id)
        if commands_admin_list and line_args[1].lower() in commands_admin_list:
            if not initiator_is_admin:
                self.bot.send_message_parsed(event.conv, _('{}: Can\'t do that.').format(
                    event.user.full_name))
                return

        # Run command
        yield from command.run(self.bot, event, *line_args[1:])
def _new_group_conversation(bot, initiator_id):
    _response = yield from bot._client.create_conversation(
        hangups.hangouts_pb2.CreateConversationRequest(
            request_header = bot._client.get_request_header(),
            type = hangups.hangouts_pb2.CONVERSATION_TYPE_GROUP,
            client_generated_id = bot._client.get_client_generated_id(),
            invitee_id = [ hangups.hangouts_pb2.InviteeID(gaia_id = initiator_id) ]))
    new_conversation_id = _response.conversation.conversation_id.id

    yield from bot.coro_send_message(new_conversation_id, _("<i>group created</i>"))
    yield from asyncio.sleep(1) # allow convmem to update
    yield from command.run( bot,
                            event,
                            *[ "convrename",
                               "id:" + new_conversation_id,
                               _("GROUP: {}").format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M")) ])
    return new_conversation_id
Exemple #18
0
def _new_group_conversation(bot, initiator_id):
    _response = yield from bot._client.create_conversation(
        hangups.hangouts_pb2.CreateConversationRequest(
            request_header=bot._client.get_request_header(),
            type=hangups.hangouts_pb2.CONVERSATION_TYPE_GROUP,
            client_generated_id=bot._client.get_client_generated_id(),
            invitee_id=[hangups.hangouts_pb2.InviteeID(gaia_id=initiator_id)]))
    new_conversation_id = _response.conversation.conversation_id.id

    yield from bot.coro_send_message(new_conversation_id,
                                     _("<i>group created</i>"))
    yield from asyncio.sleep(1)  # allow convmem to update
    yield from command.run(
        bot, event, *[
            "convrename", "id:" + new_conversation_id,
            _("GROUP: {}").format(
                datetime.datetime.now().strftime("%Y-%m-%d %H:%M"))
        ])
    return new_conversation_id
Exemple #19
0
def topic(bot, event, *args):
    """locks a conversation title. if no parameters supplied, clear and unlock the title"""

    topic = ' '.join(args).strip()

    bot.initialise_memory(event.conv_id, "conv_data")
    bot.memory.set_by_path(["conv_data", event.conv_id, "topic"], topic)
    bot.memory.save()

    if(topic == ''):
        message = _("Removing topic")
        logger.info("topic cleared from {}".format(event.conv_id))

    else:
        message = _("Setting topic to '{}'").format(topic)
        logger.info("topic for {} set to: {}".format(event.conv_id, topic))

    yield from bot.coro_send_message(event.conv, message)

    """Rename Hangout"""
    yield from command.run(bot, event, *["convrename", "id:" + event.conv_id, topic])
def kick(bot, event, *args):
    """kick users from a conversation
    Usage: /bot kick
    [<optional conversation id, current if not specified>]
    [<user ids, space-separated if more than one>]
    [quietly]"""
    parameters = list(args)

    source_conv = event.conv_id
    remove = []
    test = False
    quietly = False

    for parameter in parameters:
        if parameter in bot.conversations.catalog:
            source_conv = parameter
        elif parameter in bot.conversations.catalog[source_conv][
                "participants"]:
            remove.append(parameter)
        elif parameter == "test":
            test = True
        elif parameter == "quietly":
            quietly = True
        else:
            raise ValueError(
                _("supply optional conversation id and valid user ids to kick")
            )

    if len(remove) <= 0:
        raise ValueError(_("supply at least one valid user id to kick"))

    arguments = ["refresh", source_conv, "without"] + remove

    if test:
        arguments.append("test")

    if quietly:
        arguments.append("quietly")

    yield from command.run(bot, event, *arguments)
Exemple #21
0
def _watch_rename(bot, event, command):

    memory_topic_path = ["conv_data", event.conv_id, "topic"]

    topic = False
    if bot.memory.exists(memory_topic_path):
        topic = bot.memory.get_by_path(memory_topic_path)

    if topic:
        # seems to be a valid topic set for the current conversation

        authorised_topic_change = False

        if not authorised_topic_change and event.user.is_self:
            # bot is authorised to change the name
            authorised_topic_change = True

        if not authorised_topic_change:
            # admins can always change the name
            admins_list = bot.get_config_suboption(event.conv_id, 'admins')
            if event.user_id.chat_id in admins_list:
                authorised_topic_change = True

        if authorised_topic_change:
            bot.memory.set_by_path(memory_topic_path, event.conv_event.new_name)
            bot.memory.save()
            topic = event.conv_event.new_name

        if event.conv_event.new_name != topic:
            hangups_user = bot.get_hangups_user(event.user_id.chat_id)
            logger.warning(
                "unauthorised topic change by {} ({}) in {}, resetting: {} to: {}"
                    .format( hangups_user.full_name,
                             event.user_id.chat_id,
                             event.conv_id,
                             event.conv_event.new_name,
                             topic ))

            yield from command.run(bot, event, *["convrename", "id:" + event.conv_id, topic])
def kick(bot, event, *args):
    """kick users from a conversation
    Usage: /bot kick
    [<optional conversation id, current if not specified>]
    [<user ids, space-separated if more than one>]
    [quietly]"""
    parameters = list(args)

    source_conv = event.conv_id
    remove = []
    test = False
    quietly = False

    for parameter in parameters:
        if parameter in bot.conversations.catalog:
            source_conv = parameter
        elif parameter in bot.conversations.catalog[source_conv]["participants"]:
            remove.append(parameter)
        elif parameter == "test":
            test = True
        elif parameter == "quietly":
            quietly = True
        else:
            raise ValueError(
                _("supply optional conversation id and valid user ids to kick"))

    if len(remove) <= 0:
        raise ValueError(_("supply at least one valid user id to kick"))

    arguments = ["refresh", source_conv, "without"] + remove

    if test:
        arguments.append("test")

    if quietly:
        arguments.append("quietly")

    yield from command.run(bot, event, *arguments)
Exemple #23
0
def rename(bot, event, *args):
    """rename current hangout"""
    yield from command.run(bot, event, *["convrename", "id:" + event.conv_id, " ".join(args)])
Exemple #24
0
def users(bot, event, *args):
    """list all users in current hangout (include g+ and email links)"""
    yield from command.run(bot, event, *["convusers", "id:" + event.conv_id])
Exemple #25
0
    def handle_command(self, event):
        """Handle command messages"""

        # is commands_enabled?
        if not self.bot.get_config_suboption(event.conv_id,
                                             'commands_enabled'):
            admins_list = self.bot.get_config_suboption(
                event.conv_id, 'admins') or []
            # admins always have commands enabled
            if event.user_id.chat_id not in admins_list:
                return

        # ensure bot alias is always a list
        if not isinstance(self.bot_command, list):
            self.bot_command = [self.bot_command]

        # check that a bot alias is used e.g. /bot
        if not event.text.split()[0].lower() in self.bot_command:
            return

        # Parse message
        event.text = event.text.replace(
            u'\xa0', u' ')  # convert non-breaking space in Latin1 (ISO 8859-1)
        try:
            line_args = shlex.split(event.text, posix=False)
        except Exception as e:
            logger.exception(e)
            yield from self.bot.coro_send_message(
                event.conv,
                _("{}: {}").format(event.user.full_name, str(e)))
            return

        # Test if command length is sufficient
        if len(line_args) < 2:
            yield from self.bot.coro_send_message(
                event.conv,
                _('{}: Missing parameter(s)').format(event.user.full_name))
            return

        commands = command.get_available_commands(self.bot,
                                                  event.user.id_.chat_id,
                                                  event.conv_id)

        supplied_command = line_args[1].lower()
        if supplied_command in commands["user"]:
            pass
        elif supplied_command in commands["admin"]:
            pass
        elif supplied_command in command.commands:
            yield from command.blocked_command(self.bot, event, *line_args[1:])
            return
        else:
            yield from command.unknown_command(self.bot, event, *line_args[1:])
            return

        # Run command
        results = yield from command.run(self.bot, event, *line_args[1:])

        if "acknowledge" in dir(event):
            for id in event.acknowledge:
                yield from self.run_reprocessor(id, event, results)
Exemple #26
0
def refresh(bot, event, *args):
    """refresh a chat
    Usage: /bot refresh
    [conversation] <conversation id>
    [without|remove <user ids, space-separated if more than one>]
    [with|add <user id(s)>]
    [quietly]
    [norename]"""
    parameters = list(args)

    test = False
    quietly = False
    source_conv = False
    renameold = True
    list_removed = []
    list_added = []

    state = ["conversation"]

    for parameter in parameters:
        if parameter == "remove" or parameter == "without":
            state.append("removeuser")
        elif parameter == "add" or parameter == "with":
            state.append("adduser")
        elif parameter == "conversation":
            state.append("conversation")
        elif parameter == "quietly":
            quietly = True
            renameold = False
        elif parameter == "test":
            test = True
        elif parameter == "norename":
            renameold = False
        else:
            if state[-1] == "adduser":
                list_added.append(parameter)
                if parameter in list_removed:
                    list_removed.remove(parameter)

            elif state[-1] == "removeuser":
                list_removed.append(parameter)
                if parameter in list_added:
                    list_added.remove(parameter)

            elif state[-1] == "conversation":
                source_conv = parameter

            else:
                raise ValueError("UNKNOWN STATE: {}".format(state[-1]))

    list_removed = list(set(list_removed))

    if not source_conv:
        raise ValueError("conversation id not supplied")

    if source_conv not in bot.conversations.catalog:
        raise ValueError(_("conversation {} not found").format(source_conv))

    if bot.conversations.catalog[source_conv]["type"] != "GROUP":
        raise ValueError(_("conversation {} is not a GROUP").format(source_conv))

    new_title = bot.conversations.get_name(source_conv)
    old_title = _("[DEFUNCT] {}".format(new_title))

    text_removed_users = []
    list_all_users = bot.get_users_in_conversation(source_conv)
    for u in list_all_users:
        if u.id_.chat_id not in list_removed:
            list_added.append(u.id_.chat_id)
        else:
            hangups_user = bot.get_hangups_user(u.id_.chat_id)
            text_removed_users.append("<pre>{}</pre> ({})".format(hangups_user.full_name, u.id_.chat_id))

    list_added = list(set(list_added))

    logger.debug("refresh: from conversation {} removed {} added {}".format(source_conv, len(list_removed), len(list_added)))

    if test:
        yield from bot.coro_send_message(event.conv_id,
                                         _("<b>refresh:</b> {}<br />"
                                           "<b>rename old: {}</b><br />"
                                           "<b>removed {}:</b> {}<br />"
                                           "<b>added {}:</b> {}").format(source_conv,
                                                                         old_title if renameold else _("<em>unchanged</em>"),
                                                                         len(text_removed_users),
                                                                         ", ".join(text_removed_users) or _("<em>none</em>"),
                                                                         len(list_added),
                                                                         " ".join(list_added) or _("<em>none</em>")))
    else:
        if len(list_added) > 1:

            _response = yield from bot._client.create_conversation(
                hangups.hangouts_pb2.CreateConversationRequest(
                    request_header = bot._client.get_request_header(),
                    type = hangups.hangouts_pb2.CONVERSATION_TYPE_GROUP,
                    client_generated_id = bot._client.get_client_generated_id(),
                    invitee_id = []))
            new_conversation_id = _response.conversation.conversation_id.id

            yield from bot.coro_send_message(new_conversation_id, _("<i>refreshing group...</i><br />"))
            yield from asyncio.sleep(1)
            yield from _batch_add_users(bot, new_conversation_id, list_added)
            yield from bot.coro_send_message(new_conversation_id, _("<i>all users added</i><br />"))
            yield from asyncio.sleep(1)
            yield from command.run(bot, event, *["convrename", "id:" + new_conversation_id, new_title])

            if renameold:
                yield from command.run(bot, event, *["convrename", "id:" + source_conv, old_title])

            if not quietly:
                yield from bot.coro_send_message(source_conv, _("<i>group has been obsoleted</i>"))

            yield from bot.coro_send_message( event.conv_id,
                                              _("refreshed: <b><pre>{}</pre></b> (original id: <pre>{}</pre>).<br />"
                                                "new conversation id: <b><pre>{}</pre></b>.<br />"
                                                "removed {}: {}").format( new_title,
                                                                          source_conv,
                                                                          new_conversation_id,
                                                                          len(text_removed_users),
                                                                          ", ".join(text_removed_users) or _("<em>none</em>") ))

        else:
            yield from bot.coro_send_message(event.conv_id, _("<b>nobody to add in the new conversation</b>"))
Exemple #27
0
def users(bot, event, *args):
    """list all users in current hangout (include g+ and email links)"""
    yield from command.run(bot, event, *["convusers", "id:" + event.conv_id])
Exemple #28
0
def echo(bot, event, *args):
    """echo back text into current conversation"""
    yield from command.run(bot, event, *["convecho", "id:" + event.conv_id, " ".join(args)])
def refresh(bot, event, *args):
    """refresh a chat
    Usage: /bot refresh
    [conversation] <conversation id>
    [without|remove <user ids, space-separated if more than one>]
    [with|add <user id(s)>]
    [quietly]
    [norename]"""
    parameters = list(args)

    test = False
    quietly = False
    source_conv = False
    renameold = True
    list_removed = []
    list_added = []

    state = ["conversation"]

    for parameter in parameters:
        if parameter == "remove" or parameter == "without":
            state.append("removeuser")
        elif parameter == "add" or parameter == "with":
            state.append("adduser")
        elif parameter == "conversation":
            state.append("conversation")
        elif parameter == "quietly":
            quietly = True
            renameold = False
        elif parameter == "test":
            test = True
        elif parameter == "norename":
            renameold = False
        else:
            if state[-1] == "adduser":
                list_added.append(parameter)
                if parameter in list_removed:
                    list_removed.remove(parameter)

            elif state[-1] == "removeuser":
                list_removed.append(parameter)
                if parameter in list_added:
                    list_added.remove(parameter)

            elif state[-1] == "conversation":
                source_conv = parameter

            else:
                raise ValueError("UNKNOWN STATE: {}".format(state[-1]))

    list_removed = list(set(list_removed))

    if not source_conv:
        raise ValueError("conversation id not supplied")

    if source_conv not in bot.conversations.catalog:
        raise ValueError(_("conversation {} not found").format(source_conv))

    if bot.conversations.catalog[source_conv]["type"] != "GROUP":
        raise ValueError(
            _("conversation {} is not a GROUP").format(source_conv))

    new_title = bot.conversations.get_name(source_conv)
    old_title = _("[DEFUNCT] {}".format(new_title))

    text_removed_users = []
    list_all_users = bot.get_users_in_conversation(source_conv)
    for u in list_all_users:
        if u.id_.chat_id not in list_removed:
            list_added.append(u.id_.chat_id)
        else:
            hangups_user = bot.get_hangups_user(u.id_.chat_id)
            text_removed_users.append("<pre>{}</pre> ({})".format(
                hangups_user.full_name, u.id_.chat_id))

    list_added = list(set(list_added))

    logger.debug("refresh: from conversation {} removed {} added {}".format(
        source_conv, len(list_removed), len(list_added)))

    if test:
        yield from bot.coro_send_message(
            event.conv_id,
            _("<b>refresh:</b> {}<br />"
              "<b>rename old: {}</b><br />"
              "<b>removed {}:</b> {}<br />"
              "<b>added {}:</b> {}").format(
                  source_conv,
                  old_title if renameold else _("<em>unchanged</em>"),
                  len(text_removed_users),
                  ", ".join(text_removed_users) or _("<em>none</em>"),
                  len(list_added), " ".join(list_added) or _("<em>none</em>")))
    else:
        if len(list_added) > 1:

            _response = yield from bot._client.create_conversation(
                hangups.hangouts_pb2.CreateConversationRequest(
                    request_header=bot._client.get_request_header(),
                    type=hangups.hangouts_pb2.CONVERSATION_TYPE_GROUP,
                    client_generated_id=bot._client.get_client_generated_id(),
                    invitee_id=[]))
            new_conversation_id = _response.conversation.conversation_id.id

            yield from bot.coro_send_message(
                new_conversation_id, _("<i>refreshing group...</i><br />"))
            yield from asyncio.sleep(1)
            yield from _batch_add_users(bot, new_conversation_id, list_added)
            yield from bot.coro_send_message(new_conversation_id,
                                             _("<i>all users added</i><br />"))
            yield from asyncio.sleep(1)
            yield from command.run(
                bot, event,
                *["convrename", "id:" + new_conversation_id, new_title])

            if renameold:
                yield from command.run(
                    bot, event,
                    *["convrename", "id:" + source_conv, old_title])

            if not quietly:
                yield from bot.coro_send_message(
                    source_conv, _("<i>group has been obsoleted</i>"))

            yield from bot.coro_send_message(
                event.conv_id,
                _("refreshed: <b><pre>{}</pre></b> (original id: <pre>{}</pre>).<br />"
                  "new conversation id: <b><pre>{}</pre></b>.<br />"
                  "removed {}: {}").format(
                      new_title, source_conv, new_conversation_id,
                      len(text_removed_users), ", ".join(text_removed_users)
                      or _("<em>none</em>")))

        else:
            yield from bot.coro_send_message(
                event.conv_id,
                _("<b>nobody to add in the new conversation</b>"))
Exemple #30
0
    def handle_command(self, event):
        """Handle command messages"""

        # is commands_enabled?

        config_commands_enabled = self.bot.get_config_suboption(
            event.conv_id, 'commands_enabled')
        tagged_ignore = "ignore" in self.bot.tags.useractive(
            event.user_id.chat_id, event.conv_id)

        if not config_commands_enabled or tagged_ignore:
            admins_list = self.bot.get_config_suboption(
                event.conv_id, 'admins') or []
            # admins always have commands enabled
            if event.user_id.chat_id not in admins_list:
                return

        # ensure bot alias is always a list
        if not isinstance(self.bot_command, list):
            self.bot_command = [self.bot_command]

        # check that a bot alias is used e.g. /bot
        if not event.text.split()[0].lower() in self.bot_command:
            if self.bot.conversations.catalog[event.conv_id][
                    "type"] == "ONE_TO_ONE" and self.bot.get_config_option(
                        'auto_alias_one_to_one'):
                event.text = u" ".join((
                    self.bot_command[0],
                    event.text))  # Insert default alias if not already present
            else:
                return

        # Parse message
        event.text = event.text.replace(
            u'\xa0', u' ')  # convert non-breaking space in Latin1 (ISO 8859-1)
        try:
            line_args = shlex.split(event.text, posix=False)
        except Exception as e:
            logger.exception(e)
            yield from self.bot.coro_send_message(
                event.conv,
                _("{}: {}").format(event.user.full_name, str(e)))
            return

        # Test if command length is sufficient
        if len(line_args) < 2:
            config_silent = bot.get_config_suboption(event.conv.id_,
                                                     'silentmode')
            tagged_silent = "silent" in bot.tags.useractive(
                event.user_id.chat_id, event.conv.id_)
            if not (config_silent or tagged_silent):
                yield from self.bot.coro_send_message(
                    event.conv,
                    _('{}: Missing parameter(s)').format(event.user.full_name))
            return

        commands = command.get_available_commands(self.bot,
                                                  event.user.id_.chat_id,
                                                  event.conv_id)

        supplied_command = line_args[1].lower()
        if supplied_command in commands["user"]:
            pass
        elif supplied_command in commands["admin"]:
            pass
        elif supplied_command in command.commands:
            yield from command.blocked_command(self.bot, event, *line_args[1:])
            return
        else:
            yield from command.unknown_command(self.bot, event, *line_args[1:])
            return

        # Run command
        results = yield from command.run(self.bot, event, *line_args[1:])

        if "acknowledge" in dir(event):
            for id in event.acknowledge:
                yield from self.run_reprocessor(id, event, results)
Exemple #31
0
    def handle_chat_message(self, event):
        """Handle conversation event"""
        if event.text:
            if event.user.is_self:
                event.from_bot = True
            else:
                event.from_bot = False
            """EventAnnotation - allows metadata to survive a trip to Google"""

            event.passthru = {}
            event.context = {}
            for annotation in event.conv_event._event.chat_message.annotation:
                if annotation.type == 1025:
                    # reprocessor - process event with hidden context from handler.attach_reprocessor()
                    yield from self.run_reprocessor(annotation.value, event)
                elif annotation.type == 1026:
                    if annotation.value in self._passthrus:
                        event.passthru = self._passthrus[annotation.value]
                        del self._passthrus[annotation.value]
                elif annotation.type == 1027:
                    if annotation.value in self._contexts:
                        event.context = self._contexts[annotation.value]
                        del self._contexts[annotation.value]

            if len(event.conv_event.segments) > 0:
                for segment in event.conv_event.segments:
                    if segment.link_target:
                        if segment.link_target.startswith(
                                self._prefix_reprocessor):
                            _id = segment.link_target[
                                len(self._prefix_reprocessor):]
                            yield from self.run_reprocessor(_id, event)
            """auto opt-in - opted-out users who chat with the bot will be opted-in again"""
            if not event.from_bot and self.bot.conversations.catalog[
                    event.conv_id]["type"] == "ONE_TO_ONE":
                if self.bot.memory.exists(
                    ["user_data", event.user.id_.chat_id, "optout"]):
                    optout = self.bot.memory.get_by_path(
                        ["user_data", event.user.id_.chat_id, "optout"])
                    if isinstance(optout, bool) and optout:
                        yield from command.run(self.bot, event, *["optout"])
                        logger.info("auto opt-in for {}".format(
                            event.user.id_.chat_id))
                        return
            """map image ids to their public uris in absence of any fixed server api
               XXX: small memory leak over time as each id gets cached indefinitely"""

            if (event.passthru and "original_request" in event.passthru
                    and "image_id" in event.passthru["original_request"]
                    and event.passthru["original_request"]["image_id"]
                    and len(event.conv_event.attachments) == 1):

                _image_id = event.passthru["original_request"]["image_id"]
                _image_uri = event.conv_event.attachments[0]

                if _image_id not in self._image_ids:
                    self._image_ids[_image_id] = _image_uri
                    logger.info("associating image_id={} with {}".format(
                        _image_id, _image_uri))
            """first occurence of an actual executable id needs to be handled as an event
               XXX: small memory leak over time as each id gets cached indefinitely"""

            if (event.passthru and "executable" in event.passthru
                    and event.passthru["executable"]):
                if event.passthru["executable"] not in self._executables:
                    original_message = event.passthru["original_request"][
                        "message"]
                    linked_hangups_user = event.passthru["original_request"][
                        "user"]
                    logger.info("current event is executable: {}".format(
                        original_message))
                    self._executables[
                        event.passthru["executable"]] = time.time()
                    event.from_bot = False
                    event.text = original_message
                    event.user = linked_hangups_user

            yield from self.run_pluggable_omnibus("allmessages", self.bot,
                                                  event, command)
            if not event.from_bot:
                yield from self.run_pluggable_omnibus("message", self.bot,
                                                      event, command)
                yield from self.handle_command(event)
Exemple #32
0
def rename(bot, event, *args):
    """rename current hangout"""
    yield from command.run(
        bot, event, *["convrename", "id:" + event.conv_id, " ".join(args)])
Exemple #33
0
async def on_message(msg):
    if msg.author == client.user:
        return

    a = command.run(msg.content.lower())
    await msg.channel.send(a)
Exemple #34
0
    def handle_chat_message(self, event):
        """Handle conversation event"""
        if event.text:
            if event.user.is_self:
                event.from_bot = True
            else:
                event.from_bot = False

            """EventAnnotation - allows metadata to survive a trip to Google"""

            event.passthru = {}
            event.context = {}
            for annotation in event.conv_event._event.chat_message.annotation:
                if annotation.type == 1025:
                    # reprocessor - process event with hidden context from handler.attach_reprocessor()
                    yield from self.run_reprocessor(annotation.value, event)
                elif annotation.type == 1026:
                    if annotation.value in self._passthrus:
                        event.passthru = self._passthrus[annotation.value]
                        del self._passthrus[annotation.value]
                elif annotation.type == 1027:
                    if annotation.value in self._contexts:
                        event.context = self._contexts[annotation.value]
                        del self._contexts[annotation.value]

            if len(event.conv_event.segments) > 0:
                for segment in event.conv_event.segments:
                    if segment.link_target:
                        if segment.link_target.startswith(self._prefix_reprocessor):
                            _id = segment.link_target[len(self._prefix_reprocessor):]
                            yield from self.run_reprocessor(_id, event)

            """auto opt-in - opted-out users who chat with the bot will be opted-in again"""
            if not event.from_bot and self.bot.conversations.catalog[event.conv_id]["type"] == "ONE_TO_ONE":
                if self.bot.memory.exists(["user_data", event.user.id_.chat_id, "optout"]):
                    optout = self.bot.memory.get_by_path(["user_data", event.user.id_.chat_id, "optout"])
                    if isinstance(optout, bool) and optout:
                        yield from command.run(self.bot, event, *["optout"])
                        logger.info("auto opt-in for {}".format(event.user.id_.chat_id))
                        return

            """map image ids to their public uris in absence of any fixed server api
               XXX: small memory leak over time as each id gets cached indefinitely"""

            if( event.passthru
                    and "original_request" in event.passthru
                    and "image_id" in event.passthru["original_request"]
                    and event.passthru["original_request"]["image_id"]
                    and len(event.conv_event.attachments) == 1 ):

                _image_id = event.passthru["original_request"]["image_id"]
                _image_uri = event.conv_event.attachments[0]

                if _image_id not in self._image_ids:
                    self._image_ids[_image_id] = _image_uri
                    logger.info("associating image_id={} with {}".format(_image_id, _image_uri))

            """first occurence of an actual executable id needs to be handled as an event
               XXX: small memory leak over time as each id gets cached indefinitely"""

            if( event.passthru and "executable" in event.passthru and event.passthru["executable"] ):
                if event.passthru["executable"] not in self._executables:
                    original_message = event.passthru["original_request"]["message"]
                    linked_hangups_user = event.passthru["original_request"]["user"]
                    logger.info("current event is executable: {}".format(original_message))
                    self._executables[event.passthru["executable"]] = time.time()
                    event.from_bot = False
                    event.text = original_message
                    event.user = linked_hangups_user

            yield from self.run_pluggable_omnibus("allmessages", self.bot, event, command)
            if not event.from_bot:
                yield from self.run_pluggable_omnibus("message", self.bot, event, command)
                yield from self.handle_command(event)