|
- # -*- coding: utf-8 -*-
- #
- # Copyright (C) 2021 Ben Kurtovic <ben.kurtovic@gmail.com>
- #
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
- #
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
- #
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- # SOFTWARE.
-
- import base64
- import cPickle as pickle
- import re
-
- from earwigbot.commands import Command
- from earwigbot.config.permissions import User
-
- class PartWhen(Command):
- """Ask the bot to part the channel when a condition is met."""
- name = "partwhen"
- commands = ["partwhen", "unpartwhen"]
- hooks = ["join", "msg"]
-
- def setup(self):
- self._conds = self._load_conditions()
-
- def check(self, data):
- if data.is_command and data.command in self.commands:
- return True
- try:
- if data.line[1] == "JOIN":
- if data.chan in self._conds and "join" in self._conds[data.chan]:
- return True
- except IndexError:
- pass
- return False
-
- def process(self, data):
- if data.line[1] == "JOIN":
- self._handle_join(data)
- return
-
- if not self.config.irc["permissions"].is_admin(data):
- self.reply(data, "You must be a bot admin to use this command.")
- return
-
- channel = data.chan
- args = data.args
- if args and args[0].startswith("#"):
- # "!partwhen #channel <event> <args>..."
- channel = args[0]
- args = args[1:]
-
- if data.command == "unpartwhen":
- if self._conds.get(channel):
- del self._conds[channel]
- self._save_conditions()
- self.reply(data, "Cleared part conditions for {0}.".format(
- "this channel" if channel == data.chan else channel))
- else:
- self.reply(data, "No part conditions set.")
- return
-
- if not args:
- conds = self._conds.get(channel, {})
- existing = "; ".join("{0} {1}".format(cond, ", ".join(str(user) for user in users))
- for cond, users in conds.iteritems())
- if existing:
- status = "Current part conditions: {0}.".format(existing)
- else:
- status = "No part conditions set for {0}.".format(
- "this channel" if channel == data.chan else channel)
- self.reply(data, "{0} Usage: !{1} [<channel>] <event> <args>...".format(
- status, data.command))
- return
-
- event = args[0]
- args = args[1:]
- if event == "join":
- if not args:
- self.reply(data, "Join event requires an argument for the user joining, "
- "in nick!ident@host syntax.")
- return
- cond = args[0]
- match = re.match(r"(.*?)!(.*?)@(.*?)$", cond)
- if not match:
- self.reply(data, "User join pattern is invalid; should use "
- "nick!ident@host syntax.")
- return
- conds = self._conds.setdefault(channel, {}).setdefault("join", [])
- conds.append(User(match.group(1), match.group(2), match.group(3)))
- self._save_conditions()
- self.reply(data, "Okay, I will leave {0} when {1} joins.".format(
- "the channel" if channel == data.chan else channel, cond))
- else:
- self.reply(data, "Unknown event: {0} (valid events: join).".format(event))
-
- def _handle_join(self, data):
- user = User(data.nick, data.ident, data.host)
- conds = self._conds.get(data.chan, {}).get("join", {})
- for cond in conds:
- if user in cond:
- self.logger.info("Parting {0} because {1} met join condition {2}".format(
- data.chan, str(user), str(cond)))
- self.part(data.chan, "Requested to leave when {0} joined".format(data.nick))
- break
-
- def _load_conditions(self):
- permdb = self.config.irc["permissions"]
- try:
- raw = permdb.get_attr("command:partwhen", "data")
- except KeyError:
- return {}
- return pickle.loads(base64.b64decode(raw))
-
- def _save_conditions(self):
- permdb = self.config.irc["permissions"]
- raw = base64.b64encode(pickle.dumps(self._conds, pickle.HIGHEST_PROTOCOL))
- permdb.set_attr("command:partwhen", "data", raw)
|