COLOR_POSITIVE = utils.consts.GREEN COLOR_NEUTRAL = utils.consts.LIGHTGREY COLOR_NEGATIVE = utils.consts.RED COLOR_ID = utils.consts.PINK REGEX_PR_OR_ISSUE = re.compile( r"https?://github.com/([^/]+)/([^/]+)/(pull|issues)/(\d+)", re.I) REGEX_REF = re.compile(r"(?:\S+(?:\/\S+)?)?#\d+") API_ISSUE_URL = "https://api.github.com/repos/%s/%s/issues/%s" API_PULL_URL = "https://api.github.com/repos/%s/%s/pulls/%s" @utils.export("channelset", utils.Setting( "github-default-repo", "Set the default github repo for the current channel", example="jesopo/bitbot")) @utils.export("channelset", utils.BoolSetting( "auto-github", "Enable/disable automatically getting github issue/PR info")) @utils.export("channelset", utils.IntSetting( "auto-github-cooldown", "Set amount of seconds between auto-github duplicates", example="300")) class Module(ModuleManager.BaseModule): def _parse_ref(self, channel, ref): repo, _, number = ref.rpartition("#") org, _, repo = repo.partition("/")
#--depends-on channel_access #--depends-on check_mode #--depends-on commands #--depends-on config from src import ModuleManager, utils KICK_REASON = "your behavior is not conducive to the desired environment" KICK_REASON_SETTING = utils.Setting("default-kick-reason", "Set the default kick reason", example="have a nice trip") @utils.export( "channelset", utils.Setting( "ban-format", "Set ban format ($n = nick, $u = username, $h = hostname, $a = account)", example="*!$u@$h")) @utils.export( "channelset", utils.Setting("ban-format-account", "Set ban format for users with accounts " "($n = nick, $u = username, $h = hostname, $a = account)", example="~a:$a")) @utils.export("serverset", utils.OptionsSetting(["qmode", "insp", "unreal", "none"], "mute-method", "Set this server's method of muting users")) @utils.export("botset", KICK_REASON_SETTING)
#--depends-on config #--depends-on shorturl import difflib, hashlib, time, urllib.parse from src import ModuleManager, utils import feedparser RSS_INTERVAL = 60 # 1 minute SETTING_BIND = utils.Setting("rss-bindhost", "Which local address to bind to for RSS requests", example="127.0.0.1") @utils.export("botset", utils.IntSetting("rss-interval", "Interval (in seconds) between RSS polls", example="120")) @utils.export("channelset", utils.BoolSetting("rss-shorten", "Whether or not to shorten RSS urls")) @utils.export("serverset", SETTING_BIND) @utils.export("channelset", SETTING_BIND) class Module(ModuleManager.BaseModule): _name = "RSS" def on_load(self): self.timers.add("rss-feeds", self._timer, self.bot.get_setting("rss-interval", RSS_INTERVAL)) def _format_entry(self, server, feed_title, entry, shorten):
from src import ModuleManager, utils SETTING = utils.Setting( "ban-format", "Set ban format " "(${n} = nick, ${u} = username, ${h} = hostname, ${a} = account", example="*!${u}@${h}") @utils.export("channelset", SETTING) @utils.export("serverset", SETTING) class Module(ModuleManager.BaseModule): def _format_hostmask(self, user, s): vars = {} vars["n"] = vars["nickname"] = user.nickname vars["u"] = vars["username"] = user.username vars["h"] = vars["hostname"] = user.hostname vars["a"] = vars["account"] = user.account or "" missing, out = utils.parse.format_token_replace(s, vars) return out @utils.export("ban-mask") def banmask(self, server, channel, user): format = channel.get_setting( "ban-format", server.get_setting("ban-format", "*!${u}@${h}")) return self._format_hostmask(user, format)
#--depends-on config import base64 from src import EventManager, ModuleManager, utils @utils.export("serverset", utils.Setting("nickserv-password", "Set the nickserv password for this server", example="hunter2")) class Module(ModuleManager.BaseModule): @utils.hook("received.001", priority=EventManager.PRIORITY_URGENT) def on_connect(self, event): nickserv_password = event["server"].get_setting("nickserv-password") if nickserv_password: event["server"].send_message("nickserv", "identify %s" % nickserv_password)
#--depends-on commands #--depends-on config from src import ModuleManager, utils @utils.export("set", utils.Setting("pronouns", "Set your pronouns", example="she/her")) class Module(ModuleManager.BaseModule): @utils.hook("received.command.pronouns") def pronouns(self, event): """ :help: Get your, or someone else's, pronouns :usage: [nickname] :require_setting: pronouns :require_setting_unless: 1 """ target_user = event["user"] if event["args"]: target_user = event["server"].get_user(event["args_split"][0]) pronouns = target_user.get_setting("pronouns", None) if not pronouns == None: event["stdout"].write("Pronouns for %s: %s" % (target_user.nickname, pronouns)) else: event["stderr"].write("No pronouns set for %s" % target_user.nickname)
def do_POST(self): self._handle_wrap("POST") def log_message(self, format, *args): return class BitBotIPv6HTTPd(http.server.HTTPServer): address_family = socket.AF_INET6 @utils.export("botset", utils.BoolSetting("rest-api", "Enable/disable REST API")) @utils.export("botset", utils.BoolSetting("rest-api-minify", "Enable/disable REST API minifying")) @utils.export("botset", utils.Setting("rest-api-host", "Public hostname:port for the REST API")) class Module(ModuleManager.BaseModule): _name = "REST" def on_load(self): global _module _module = self global _bot _bot = self.bot global _events _events = self.events global _log _log = self.log
return s.upper() class BadContextException(Exception): def __init__(self, required_context): self.required_context = required_context Exception.__init__(self) class CommandMethodSetting(utils.Setting): example = "NOTICE" def parse(self, value: str) -> typing.Any: upper = value.upper() if upper in COMMAND_METHODS: return upper return None @utils.export("channelset", utils.Setting("command-prefix", "Set the command prefix used in this channel", example="!")) @utils.export("serverset", utils.Setting("command-prefix", "Set the command prefix used on this server", example="!")) @utils.export("serverset", CommandMethodSetting("command-method", "Set the method used to respond to commands")) @utils.export("channelset", CommandMethodSetting("command-method", "Set the method used to respond to commands")) @utils.export("botset", CommandMethodSetting("command-method", "Set the method used to respond to commands")) @utils.export("channelset", utils.BoolSetting("hide-prefix", "Disable/enable hiding prefix in command reponses")) @utils.export("channelset", utils.BoolSetting("commands", "Disable/enable responding to commands in-channel")) @utils.export("channelset", utils.BoolSetting("prefixed-commands", "Disable/enable responding to prefixed commands in-channel")) class Module(ModuleManager.BaseModule):
from src import ModuleManager, utils @utils.export("channelset", utils.Setting("key", "Channel key (password)", example="hunter2")) class Module(ModuleManager.BaseModule): def _get_key(self, server, channel_name): channel_id = server.channels.get_id(channel_name) return self.bot.database.channel_settings.get(channel_id, "key", None) def _set_key(self, channel, key): channel.set_setting("key", key) def _unset_key(self, channel): channel.del_setting("key") @utils.hook("preprocess.send.join") def preprocess_send_join(self, event): if event["line"].args: channels = event["line"].args[0].split(",") keys = event["line"].args[1:] with_keys = {} for channel in channels: if keys: with_keys[channel] = keys.pop(0) else: with_keys[channel] = self._get_key(event["server"], channel)
class CommandEvent(object): def __init__(self, command, args): self.command = command self.args = args SETTING_COMMANDMETHOD = utils.OptionsSetting( COMMAND_METHODS, COMMAND_METHOD, "Set the method used to respond to commands") @utils.export("channelset", utils.Setting("command-prefix", "Set the command prefix used in this channel", example="!")) @utils.export("serverset", utils.Setting("command-prefix", "Set the command prefix used on this server", example="!")) @utils.export("botset", SETTING_COMMANDMETHOD) @utils.export("serverset", SETTING_COMMANDMETHOD) @utils.export("channelset", SETTING_COMMANDMETHOD) @utils.export("set", SETTING_COMMANDMETHOD) @utils.export("channelset", utils.BoolSetting( "hide-prefix", "Disable/enable hiding prefix in command reponses")) @utils.export("channelset", utils.BoolSetting(
#--depends-on commands #--depends-on config #--require-config trakt-api-key from src import ModuleManager, utils URL_TRAKT = "https://api-v2launch.trakt.tv/users/%s/watching" URL_TRAKTSLUG = "https://trakt.tv/%s/%s" @utils.export("set", utils.Setting("trakt", "Set username on trakt.tv", example="jesopo")) class Module(ModuleManager.BaseModule): @utils.hook("received.command.nw", alias_of="nowwatching") @utils.hook("received.command.nowwatching") def now_watching(self, event): """ :help: Get what you or another user is now watching on trakt.tv :usage: [username] """ if event["args"]: username = event["args_split"][0] else: username = event["user"].get_setting("trakt", event["user"].nickname) page = utils.http.request(URL_TRAKT % username, headers={ "Content-Type": "application/json",
#--depends-on commands #--depends-on config #--require-config lastfm-api-key from datetime import datetime, timezone from src import ModuleManager, utils URL_SCROBBLER = "http://ws.audioscrobbler.com/2.0/" @utils.export("set", utils.Setting("lastfm", "Set last.fm username", example="jesopo")) class Module(ModuleManager.BaseModule): _name = "last.fm" @utils.hook("received.command.np", alias_of="nowplaying") @utils.hook("received.command.listening", alias_of="nowplaying") @utils.hook("received.command.nowplaying") def np(self, event): """ :help: Get the last listened to track from a user :usage: [username] """ user = None lastfm_username = None shown_username = None if event["args"]: arg_username = event["args_split"][0] if event["server"].has_user_id(arg_username):
#--depends-on commands from src import ModuleManager, utils LOWHIGH = {"low": "v", "high": "o"} @utils.export("channelset", utils.Setting( "mode-low", "Set which channel mode is considered to be 'low' access", example="v")) @utils.export("channelset", utils.Setting( "mode-high", "Set which channel mode is considered to be 'high' access", example="o")) class Module(ModuleManager.BaseModule): def _check_command(self, event, channel, require_mode): if event["is_channel"] and require_mode: if require_mode.lower() in LOWHIGH: require_mode = event["target"].get_setting( "mode-%s" % require_mode.lower(), LOWHIGH[require_mode.lower()]) if not event["target"].mode_or_above(event["user"], require_mode): return "You do not have permission to do this" else: return utils.consts.PERMISSION_FORCE_SUCCESS @utils.hook("preprocess.command")
#--depends-on commands #--depends-on config #--require-config lastfm-api-key from datetime import datetime, timezone from src import ModuleManager, utils URL_SCROBBLER = "http://ws.audioscrobbler.com/2.0/" @utils.export("set", utils.Setting("lastfm", "Set last.fm username", example="jesopo")) class Module(ModuleManager.BaseModule): _name = "last.fm" @utils.hook("received.command.np", alias_of="nowplaying") @utils.hook("received.command.listening", alias_of="nowplaying") @utils.hook("received.command.nowplaying") def np(self, event): """ :help: Get the last listened to track from a user :usage: [username] """ user = None lastfm_username = None shown_username = None if event["args"]: arg_username = event["args_split"][0] if event["server"].has_user_id(arg_username): user = event["server"].get_user(event["args_split"][0]) else:
from src import ModuleManager, utils @utils.export("set", utils.Setting("species", "*sniffs at*", example="sandcat")) class Module(ModuleManager.BaseModule): _name = "Species" @utils.hook("received.command.species") def species(self, event): """ :require_setting: species :require_setting_unless: 1 """ target_user = event["user"] if event["args"]: target_name = event["args_split"][0] if event["server"].has_user_id(target_name): target_user = event["server"].get_user(target_name) else: raise utils.EventError("I don't know who %s is" % target_name) species = target_user.get_setting("species", None) if not species == None: event["stdout"].write("%s is a %s" % (target_user.nickname, species)) else: event["stderr"].write("%s has no species set" % target_user.nickname)
#--depends-on channel_access #--depends-on check_mode #--depends-on commands #--depends-on config from src import ModuleManager, utils KICK_REASON = "your behavior is not conducive to the desired environment" KICK_REASON_SETTING = utils.Setting("default-kick-reason", "Set the default kick reason", example="have a nice trip") @utils.export("channelset", utils.Setting("ban-format", "Set ban format ($n = nick, $u = username, $h = hostname)", example="*!$u@$h")) @utils.export("serverset", utils.OptionsSetting("mute-method", ["qmode", "insp", "unreal", "none"], "Set this server's method of muting users")) @utils.export("botset", KICK_REASON_SETTING) @utils.export("serverset", KICK_REASON_SETTING) @utils.export("channelset", KICK_REASON_SETTING) class Module(ModuleManager.BaseModule): _name = "ChanOp" def _parse_time(self, args, min_args): if args[0][0] == "+": if len(args[1:]) < min_args: raise utils.EventError("Not enough arguments") time = utils.from_pretty_time(args[0][1:]) if time == None: raise utils.EventError("Invalid timeframe")
#--depends-on config from src import ModuleManager, utils @utils.export("serverset", utils.Setting("bot-channel", "Set main channel", example="#bitbot")) class Module(ModuleManager.BaseModule): @utils.hook("received.001") def do_join(self, event): bot_channel = event["server"].get_setting( "bot-channel", self.bot.config.get("bot-channel", "#bitbot")) event["server"].send_join(bot_channel)
from src import ModuleManager, utils class UserNotFoundException(Exception): pass class InvalidTimeoutException(Exception): pass @utils.export("channelset", utils.IntSetting("highlight-spam-threshold", "Set the number of nicknames in a message that qualifies as spam")) @utils.export("channelset", utils.BoolSetting("highlight-spam-protection", "Enable/Disable highlight spam protection")) @utils.export("channelset", utils.BoolSetting("highlight-spam-ban", "Enable/Disable banning highlight spammers instead of just kicking")) @utils.export("channelset", utils.Setting("ban-format", "Set ban format ($n = nick, $u = username, $h = hostname)", example="*!$u@$h")) @utils.export("serverset", utils.OptionsSetting("mute-method", ["qmode", "insp", "unreal", "none"], "Set this server's method of muting users")) class Module(ModuleManager.BaseModule): _name = "ChanOp" @utils.hook("timer.unban") def _timer_unban(self, event): server = self.bot.get_server_by_id(event["server_id"]) if server and event["channel_name"] in server.channels: channel = server.channels.get(event["channel_name"]) channel.send_unban(event["hostmask"]) def _kick(self, server, channel, nickname, reason):
} ABAN_METHODS = {"chary": "$a:", "insp": "R:", "unreal": "~a:"} KICK_REASON = "your behavior is not conducive to the desired environment" NO_QUIETS = "This network doesn't support quiets" NO_ABANS = "This network doesn't support account bans" class TargetType(enum.Enum): NICKNAME = 1 MASK = 2 ACCOUNT = 3 KICK_REASON_SETTING = utils.Setting("default-kick-reason", "Set the default kick reason", example="have a nice trip") BAN_FORMATTING = "${n} = nick, ${u} = username, ${h} = hostname, ${a} = account" @utils.export("channelset", utils.Setting("ban-format", "Set ban format (%s)" % BAN_FORMATTING, example="*!${u}@${h}")) @utils.export("channelset", utils.Setting("ban-format-account", "Set ban format for users with accounts (%s)" % BAN_FORMATTING, example="~a:${a}")) @utils.export("serverset",
@utils.export( "channelset", utils.IntSetting( "highlight-spam-threshold", "Set the number of nicknames in a message that qualifies as spam")) @utils.export("channelset", utils.BoolSetting("highlight-spam-protection", "Enable/Disable highlight spam protection")) @utils.export( "channelset", utils.BoolSetting( "highlight-spam-ban", "Enable/Disable banning highlight spammers instead of just kicking")) @utils.export("channelset", utils.Setting( "ban-format", "Set ban format ($n = nick, $u = username, $h = hostname)", example="*!$u@$h")) @utils.export("serverset", utils.OptionsSetting("mute-method", ["qmode", "insp", "unreal", "none"], "Set this server's method of muting users")) class Module(ModuleManager.BaseModule): _name = "ChanOp" @utils.hook("timer.unban") def _timer_unban(self, event): server = self.bot.get_server_by_id(event["server_id"]) if server and event["channel_name"] in server.channels: channel = server.channels.get(event["channel_name"]) channel.send_unban(event["hostmask"])
#--depends-on config from src import ModuleManager, utils @utils.export("channelset", utils.Setting("greeting", "Set a greeting to send to users when they join", example="welcome to the channel!")) class Module(ModuleManager.BaseModule): @utils.hook("received.join") def join(self, event): greeting = event["channel"].get_setting("greeting", None) if greeting: event["user"].send_notice("[%s] %s" % (event["channel"].name, greeting))