aboutsummaryrefslogtreecommitdiff
path: root/modules/relay.py
blob: a0fa4fef043a53c63665486427537a198e043d6a (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
from src import EventManager, ModuleManager, utils

class Module(ModuleManager.BaseModule):
    @utils.hook("new.server")
    def new_server(self, event):
        event["server"]._relay_ignore = []

    def _get_relays(self, channel):
        return channel.get_setting("channel-relays", [])

    def _relay(self, event, channel):
        if ("parsed_line" in event and
                event["parsed_line"].id in event["server"]._relay_ignore):
            event["server"]._relay_ignore.remove(event["parsed_line"].id)
            return

        relays = self._get_relays(channel)
        for server_id, channel_name in relays:
            server = self.bot.get_server_by_id(server_id)
            if not server == None and channel_name in server.channels:
                other_channel = server.channels.get(channel_name)

                if not self._has_relay_for(other_channel, event["server"].id,
                        channel.name):
                    self.log.warn(
                        "Tried to relay with one-way config: %s%s -> %s%s",
                        [str(event["server"]), channel.name, str(server),
                        other_channel.name])
                    return

                relay_prefix_channel = ""
                if not other_channel.name == channel.name:
                    relay_prefix_channel = channel.name

                relay_message = "[relay/%s%s] %s" % (str(event["server"]),
                    relay_prefix_channel, event["line"])

                message = utils.irc.protocol.privmsg(other_channel.name,
                    relay_message)
                server._relay_ignore.append(message.id)
                self.bot.trigger(self._send_factory(server, message))

    def _send_factory(self, server, message):
        return lambda: server.send(message)

    def _has_relay_for(self, channel, server_id, channel_name):
        relays = self._get_relays(channel)
        for other_server_id, other_channel_name in relays:
            if (other_server_id == server_id and
                    other_channel_name == channel_name):
                return True
        return False

    @utils.hook("formatted.message.channel")
    @utils.hook("formatted.notice.channel")
    @utils.hook("formatted.join")
    @utils.hook("formatted.part")
    @utils.hook("formatted.nick")
    @utils.hook("formatted.mode.channel")
    @utils.hook("formatted.kick")
    @utils.hook("formatted.quit")
    @utils.hook("formatted.rename")
    @utils.kwarg("priority", EventManager.PRIORITY_LOW)
    def formatted(self, event):
        if event["channel"]:
            self._relay(event, event["channel"])
        elif event["user"]:
            for channel in event["user"].channels:
                self._relay(event, channel)

    @utils.hook("received.command.relay", min_args=3, channel_only=True)
    def relay(self, event):
        """
        :help: Edit configured relays
        :usage: add <server> <channel>
        :usage: remove <server> <channel>
        :permission: relay
        """
        target_server_alias = event["args_split"][1].lower()
        target_server = self.bot.get_server_by_alias(target_server_alias)

        if target_server == None:
            raise utils.EventError("Unknown server provided")

        current_relays = self._get_relays(event["target"])
        target_server_relays = list(filter(
            lambda relay: relay[0] == target_server.id, current_relays))
        target_relays = list(map(lambda relay: relay[1], target_server_relays))

        target_channel_name = target_server.irc_lower(event["args_split"][2])

        changed = False
        message = None

        subcommand = event["args_split"][0].lower()
        if subcommand == "add":
            if target_channel_name in target_relays:
                raise utils.EventError("Already relaying to that channel")

            if not target_channel_name in target_server.channels:
                raise utils.EventError("Cannot find the provided channel")

            current_relays.append((target_server.id, target_channel_name))

            message = "Relay added"
        elif subcommand == "remove":
            if not target_channel_name in target_relays:
                raise utils.EventError("I'm not relaying to that channel")

            for i, (server_id, channel_name) in enumerate(current_relays):
                if (server_id == target_server.id and
                        channel_name == target_channel_name):
                    current_relays.pop(i)
                    break

            message = "Removed relay"
        else:
            raise utils.EventError("Unknown subcommand '%s'" % subcommand)


        event["target"].set_setting("channel-relays", current_relays)
        event["stdout"].write(message)