Refactor set/channelset/serverset/botset in to 'utils.Setting' objects

This commit is contained in:
jesopo 2019-06-28 23:16:05 +01:00
parent f9eb017466
commit ae9d099a41
38 changed files with 203 additions and 219 deletions

View file

@ -2,9 +2,8 @@
from src import ModuleManager, utils from src import ModuleManager, utils
@utils.export("serverset", {"setting": "accept-invites", @utils.export("serverset", utils.BoolSetting("accept-invites",
"help": "Set whether I accept invites on this server", "Set whether I accept invites on this server"))
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.invite") @utils.hook("received.invite")
def on_invite(self, event): def on_invite(self, event):

View file

@ -5,9 +5,8 @@
from src import ModuleManager, utils from src import ModuleManager, utils
@utils.export("channelset", {"setting": "automode", @utils.export("channelset", utils.BoolSetting(
"help": "Disable/Enable automode", "validate": utils.bool_or_none, "automode", "Disable/Enable automode"))
"example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
_name = "AutoMode" _name = "AutoMode"

View file

@ -1,7 +1,7 @@
#--depends-on commands #--depends-on commands
#--depends-on config #--depends-on config
import datetime import datetime, typing
from src import ModuleManager, utils from src import ModuleManager, utils
DATE_YEAR_FORMAT = "%Y-%m-%d" DATE_YEAR_FORMAT = "%Y-%m-%d"
@ -30,20 +30,22 @@ def _format(years, dt):
return _format_year(dt) return _format_year(dt)
else: else:
return _format_noyear(dt) return _format_noyear(dt)
def _check(s):
parsed = _parse(s) class BirthdaySetting(utils.Setting):
if parsed: def parse(self, value: str) -> typing.Any:
years, parsed = parsed parsed = _parse(value)
return _format(years, parsed) if parsed:
return None years, parsed = parsed
return _format(years, parsed)
return None
def _apostrophe(nickname): def _apostrophe(nickname):
if nickname[-1].lower() == "s": if nickname[-1].lower() == "s":
return "%s'" % nickname return "%s'" % nickname
return "%s's" % nickname return "%s's" % nickname
@utils.export("set", {"setting": "birthday", "help": "Set your birthday", @utils.export("set", BirthdaySetting("birthday", "Set your birthday",
"validate": _check, "example": "1995-09-15"}) example="1995-09-15"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.command.birthday") @utils.hook("received.command.birthday")
def birthday(self, event): def birthday(self, event):

View file

@ -2,8 +2,8 @@
from src import ModuleManager, utils from src import ModuleManager, utils
@utils.export("serverset", {"setting": "bot-channel", @utils.export("serverset", utils.Setting("bot-channel",
"help": "Set main channel", "example": "#bitbot"}) "Set main channel", example="#bitbot"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.001") @utils.hook("received.001")
def do_join(self, event): def do_join(self, event):

View file

@ -7,9 +7,8 @@ from src import ModuleManager, utils
ROOT_DIRECTORY = os.path.dirname(os.path.realpath(__file__)) ROOT_DIRECTORY = os.path.dirname(os.path.realpath(__file__))
LOGS_DIRECTORY = os.path.join(ROOT_DIRECTORY, "logs") LOGS_DIRECTORY = os.path.join(ROOT_DIRECTORY, "logs")
@utils.export("channelset", {"setting": "log", @utils.export("channelset", utils.BoolSetting("log",
"help": "Enable/disable channel logging", "validate": utils.bool_or_none, "Enable/disable channel logging"))
"example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _log_file(self, server_name, channel_name): def _log_file(self, server_name, channel_name):
return open(os.path.join(LOGS_DIRECTORY, return open(os.path.join(LOGS_DIRECTORY,

View file

@ -10,21 +10,17 @@ class UserNotFoundException(Exception):
class InvalidTimeoutException(Exception): class InvalidTimeoutException(Exception):
pass pass
@utils.export("channelset", {"setting": "highlight-spam-threshold", @utils.export("channelset", utils.IntSetting("highlight-spam-threshold",
"help": "Set the number of nicknames in a message that qualifies as spam", "Set the number of nicknames in a message that qualifies as spam"))
"validate": utils.int_or_none, "example": "10"}) @utils.export("channelset", utils.BoolSetting("highlight-spam-protection",
@utils.export("channelset", {"setting": "highlight-spam-protection", "Enable/Disable highlight spam protection"))
"help": "Enable/Disable highlight spam protection", @utils.export("channelset", utils.BoolSetting("highlight-spam-ban",
"validate": utils.bool_or_none, "example": "on"}) "Enable/Disable banning highlight spammers instead of just kicking"))
@utils.export("channelset", {"setting": "highlight-spam-ban", @utils.export("channelset", utils.Setting("ban-format",
"help": "Enable/Disable banning highlight spammers " "Set ban format ($n = nick, $u = username, $h = hostname)",
"instead of just kicking", "validate": utils.bool_or_none, example="*!$u@$h"))
"example": "on"}) @utils.export("serverset", utils.Setting("mute-method",
@utils.export("channelset", {"setting": "ban-format", "Set this server's method of muting users", example="qmode"))
"help": "Set ban format ($n = nick, $u = username, $h = hostname)",
"example": "*!$u@$h"})
@utils.export("serverset", {"setting": "mute-method",
"help": "Set this server's method of muting users", "example": "qmode"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
_name = "ChanOp" _name = "ChanOp"

View file

@ -6,12 +6,11 @@ LOWHIGH = {
"low": "v", "low": "v",
"high": "o" "high": "o"
} }
@utils.export("channelset", {"setting": "mode-low",
"help": "Set which channel mode is considered to be 'low' access", @utils.export("channelset", utils.Setting("mode-low",
"example": "v"}) "Set which channel mode is considered to be 'low' access", example="v"))
@utils.export("channelset", {"setting": "mode-high", @utils.export("channelset", utils.Setting("mode-high",
"help": "Set which channel mode is considered to be 'high' access", "Set which channel mode is considered to be 'high' access", example="o"))
"example": "o"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _check_command(self, event, channel, require_mode): def _check_command(self, event, channel, require_mode):
if event["is_channel"] and require_mode: if event["is_channel"] and require_mode:

View file

@ -8,16 +8,12 @@ from src import ModuleManager, utils
URL_VIRUSTOTAL = "https://www.virustotal.com/vtapi/v2/url/report" URL_VIRUSTOTAL = "https://www.virustotal.com/vtapi/v2/url/report"
RE_URL = re.compile(r"https?://\S+", re.I) RE_URL = re.compile(r"https?://\S+", re.I)
@utils.export("channelset", {"setting": "check-urls", @utils.export("channelset", utils.BoolSetting("check-urls",
"help": "Enable/Disable automatically checking for malicious URLs", "Enable/Disable automatically checking for malicious URLs"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("serverset", utils.BoolSetting("check-urls",
@utils.export("serverset", {"setting": "check-urls", "Enable/Disable automatically checking for malicious URLs"))
"help": "Enable/Disable automatically checking for malicious URLs", @utils.export("channelset", utils.BoolSetting("check-urls-kick",
"validate": utils.bool_or_none, "example": "on"}) "Enable/Disable automatically kicking users that send malicious URLs"))
@utils.export("channelset", {"setting": "check-urls-kick",
"help": "Enable/Disable automatically kicking users that "
"send malicious URLs", "validate": utils.bool_or_none,
"example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.message.channel") @utils.hook("received.message.channel")
def message(self, event): def message(self, event):

View file

@ -1,7 +1,7 @@
#--depends-on config #--depends-on config
#--depends-on permissions #--depends-on permissions
import re, string, typing import re, string, traceback, typing
from src import EventManager, ModuleManager, utils from src import EventManager, ModuleManager, utils
from . import outs from . import outs
@ -20,25 +20,28 @@ def _command_method_validate(s):
if s.upper() in COMMAND_METHODS: if s.upper() in COMMAND_METHODS:
return s.upper() return s.upper()
@utils.export("channelset", {"setting": "command-prefix", class CommandMethodSetting(utils.Setting):
"help": "Set the command prefix used in this channel", "example": "!"}) example = "NOTICE"
@utils.export("serverset", {"setting": "command-prefix", def parse(self, value: str) -> typing.Any:
"help": "Set the command prefix used on this server", "example": "!"}) upper = value.upper()
@utils.export("serverset", {"setting": "command-method", if upper in COMMAND_METHODS:
"help": "Set the method used to respond to commands", return upper
"validate": _command_method_validate, "example": "NOTICE"}) return None
@utils.export("channelset", {"setting": "command-method",
"help": "Set the method used to respond to commands", @utils.export("channelset", utils.Setting("command-prefix",
"validate": _command_method_validate, "example": "NOTICE"}) "Set the command prefix used in this channel", example="!"))
@utils.export("channelset", {"setting": "hide-prefix", @utils.export("serverset", utils.Setting("command-prefix",
"help": "Disable/enable hiding prefix in command reponses", "Set the command prefix used on this server", example="!"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("serverset", CommandMethodSetting("command-method",
@utils.export("channelset", {"setting": "commands", "Set the method used to respond to commands"))
"help": "Disable/enable responding to commands in-channel", @utils.export("channelset", CommandMethodSetting("command-method",
"validate": utils.bool_or_none, "example": "on"}) "Set the method used to respond to commands"))
@utils.export("channelset", {"setting": "prefixed-commands", @utils.export("channelset", utils.BoolSetting("hide-prefix",
"help": "Disable/enable responding to prefixed commands in-channel", "Disable/enable hiding prefix in command reponses"))
"validate": utils.bool_or_none, "example": "on"}) @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): class Module(ModuleManager.BaseModule):
@utils.hook("new.user") @utils.hook("new.user")
@utils.hook("new.channel") @utils.hook("new.channel")

View file

@ -84,19 +84,18 @@ class Module(ModuleManager.BaseModule):
if setting_info: if setting_info:
value = target.get_setting(require_setting, None) value = target.get_setting(require_setting, None)
if value == None: if value == None:
example = setting_info.get("example", "<value>") example = setting_info.exaple or "<value>"
return "Please set %s, e.g.: %sconfig %s %s %s" % ( return "Please set %s, e.g.: %sconfig %s %s %s" % (
require_setting, event["command_prefix"], context[0], require_setting, event["command_prefix"], context[0],
require_setting, example) require_setting, example)
def _get_export_setting(self, context): def _get_export_setting(self, context):
settings = self.exports.get_all(context) settings = self.exports.get_all(context)
return {setting["setting"].lower(): setting for setting in settings} return {setting.name.lower(): setting for setting in settings}
def _config(self, export_settings, target, setting, value=None): def _config(self, export_settings, target, setting, value=None):
if not value == None: if not value == None:
validation = export_settings[setting].get("validate", lambda x: x) validated_value = export_settings[setting].parse(value)
validated_value = validation(value)
if not validated_value == None: if not validated_value == None:
target.set_setting(setting, validated_value) target.set_setting(setting, validated_value)
return ConfigResult(ConfigResults.Changed, validated_value) return ConfigResult(ConfigResults.Changed, validated_value)
@ -181,7 +180,7 @@ class Module(ModuleManager.BaseModule):
try: try:
result = self._config(export_settings, target, setting, value) result = self._config(export_settings, target, setting, value)
except ConfigInvalidValue: except ConfigInvalidValue:
example = export_settings[setting].get("example", None) example = export_settings[setting].example
if not example == None: if not example == None:
raise utils.EventError("Invalid value. Example: %s" % raise utils.EventError("Invalid value. Example: %s" %
example) example)

View file

@ -4,9 +4,8 @@ import datetime
from src import IRCBot, ModuleManager, utils from src import IRCBot, ModuleManager, utils
@utils.export("serverset", {"setting": "ctcp-responses", @utils.export("serverset", utils.BoolSetting("ctcp-responses",
"help": "Set whether I respond to CTCPs on this server", "Set whether I respond to CTCPs on this server"))
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.ctcp.request.version") @utils.hook("received.ctcp.request.version")
def ctcp_version(self, event): def ctcp_version(self, event):

View file

@ -9,15 +9,12 @@ NO_DUCK = "There was no duck!"
DEFAULT_MIN_MESSAGES = 100 DEFAULT_MIN_MESSAGES = 100
@utils.export("channelset", {"setting": "ducks-enabled", @utils.export("channelset", utils.BoolSetting("ducks-enabled",
"help": "Whether or not to spawn ducks", "validate": utils.bool_or_none, "Whether or not to spawn ducks"))
"example": "on"}) @utils.export("channelset", utils.IntSetting("ducks-min-messages",
@utils.export("channelset", {"setting": "ducks-min-messages", "Minimum messages between ducks spawning", example="50"))
"help": "Minimum messages between ducks spawning", @utils.export("channelset", utils.BoolSetting("ducks-kick",
"validate": utils.int_or_none, "example": "50"}) "Whether or not to kick someone talking to non-existent ducks"))
@utils.export("channelset", {"setting": "ducks-kick",
"help": "Whether or not to kick someone talking to non-existent ducks",
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("new.channel") @utils.hook("new.channel")
def new_channel(self, event): def new_channel(self, event):

View file

@ -13,15 +13,12 @@ DEFAULT_EVENT_CATEGORIES = [
"ping", "code", "pr", "issue", "repo" "ping", "code", "pr", "issue", "repo"
] ]
@utils.export("channelset", {"setting": "git-prevent-highlight", @utils.export("channelset", utils.BoolSetting("git-prevent-highlight",
"help": "Enable/disable preventing highlights", "Enable/disable preventing highlights"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("channelset", utils.BoolSetting("git-hide-organisation",
@utils.export("channelset", {"setting": "git-hide-organisation", "Hide/show organisation in repository names"))
"help": "Hide/show organisation in repository names", @utils.export("channelset", utils.BoolSetting("git-hide-prefix",
"validate": utils.bool_or_none, "example": "on"}) "Hide/show command-like prefix on git webhook outputs"))
@utils.export("channelset", {"setting": "git-hide-prefix",
"help": "Hide/show command-like prefix on git webhook outputs",
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
_name = "Webhooks" _name = "Webhooks"

View file

@ -22,15 +22,13 @@ REGEX_REF = re.compile(r"(?:\S+(?:\/\S+)?)?#\d+")
API_ISSUE_URL = "https://api.github.com/repos/%s/%s/issues/%s" API_ISSUE_URL = "https://api.github.com/repos/%s/%s/issues/%s"
API_PULL_URL = "https://api.github.com/repos/%s/%s/pulls/%s" API_PULL_URL = "https://api.github.com/repos/%s/%s/pulls/%s"
@utils.export("channelset", {"setting": "github-default-repo", @utils.export("channelset", utils.Setting("github-default-repo",
"help": "Set the default github repo for the current channel", "Set the default github repo for the current channel",
"example": "jesopo/bitbot"}) example="jesopo/bitbot"))
@utils.export("channelset", {"setting": "auto-github", @utils.export("channelset", utils.Setting("auto-github",
"help": "Enable/disable automatically getting github issue/PR info", "Enable/disable automatically getting github issue/PR info"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("channelset", utils.IntSetting("auto-github-cooldown",
@utils.export("channelset", {"setting": "auto-github-cooldown", "Set amount of seconds between auto-github duplicates", example="300"))
"help": "Set amount of seconds between auto-github duplicates",
"validate": utils.int_or_none, "example": "300"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _parse_ref(self, channel, ref): def _parse_ref(self, channel, ref):
repo, _, number = ref.rpartition("#") repo, _, number = ref.rpartition("#")

View file

@ -9,9 +9,8 @@ from src import ModuleManager, utils
URL_GOOGLESEARCH = "https://www.googleapis.com/customsearch/v1" URL_GOOGLESEARCH = "https://www.googleapis.com/customsearch/v1"
URL_GOOGLESUGGEST = "http://google.com/complete/search" URL_GOOGLESUGGEST = "http://google.com/complete/search"
@utils.export("channelset", {"setting": "google-safesearch", @utils.export("channelset", utils.BoolSetting("google-safesearch",
"help": "Turn safe search off/on", "Turn safe search off/on"))
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.command.g", alias_of="google") @utils.hook("received.command.g", alias_of="google")
@utils.hook("received.command.google") @utils.hook("received.command.google")

View file

@ -2,9 +2,9 @@
from src import ModuleManager, utils from src import ModuleManager, utils
@utils.export("channelset", {"setting": "greeting", @utils.export("channelset", utils.Setting("greeting",
"help": "Set a greeting to send to users when they join", "Set a greeting to send to users when they join",
"example": "welcome to the channel!"}) example="welcome to the channel!"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.join") @utils.hook("received.join")
def join(self, event): def join(self, event):

View file

@ -16,9 +16,8 @@ URL_GALLERY = "https://api.imgur.com/3/gallery/%s"
NSFW_TEXT = "(NSFW)" NSFW_TEXT = "(NSFW)"
@utils.export("channelset", {"setting": "auto-imgur", @utils.export("channelset", utils.BoolSetting("auto-imgur",
"help": "Disable/Enable automatically getting info from Imgur URLs", "Disable/Enable automatically getting info from Imgur URLs"))
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _prefix(self, data): def _prefix(self, data):
text = "%s: " % data["id"] text = "%s: " % data["id"]

View file

@ -1,6 +1,6 @@
#--depends-on commands #--depends-on commands
import re, socket import re, socket, typing
from src import ModuleManager, utils from src import ModuleManager, utils
import dns.resolver import dns.resolver
@ -9,13 +9,14 @@ REGEX_IPv6 = r"(?:(?:[a-f0-9]{1,4}:){2,}|[a-f0-9:]*::)[a-f0-9:]*"
REGEX_IPv4 = r"(?:\d{1,3}\.){3}\d{1,3}" REGEX_IPv4 = r"(?:\d{1,3}\.){3}\d{1,3}"
REGEX_IP = re.compile("(%s)|(%s)" % (REGEX_IPv4, REGEX_IPv6), re.I) REGEX_IP = re.compile("(%s)|(%s)" % (REGEX_IPv4, REGEX_IPv6), re.I)
def _dns_validate(s): class DnsSetting(utils.Setting):
if utils.is_ip(s): def parse(self, value: str) -> typing.Any:
return s if utils.is_ip(value):
return None return value
return None
@utils.export("serverset", {"setting": "dns-nameserver", @utils.export("serverset", DnsSetting("dns-nameserver",
"help": "Set DNS nameserver", "example": "8.8.8.8"}) "Set DNS nameserver", example="8.8.8.8"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.command.dns", min_args=1) @utils.hook("received.command.dns", min_args=1)
def dns(self, event): def dns(self, event):

View file

@ -11,7 +11,7 @@ class Module(ModuleManager.BaseModule):
supporting_servers = [] supporting_servers = []
for server in self.bot.servers.values(): for server in self.bot.servers.values():
if not server.connection_params.hostname == "localhost": if server.get_setting("ircv3-stats", False):
if spec in server.server_capabilities: if spec in server.server_capabilities:
port = str(server.connection_params.port) port = str(server.connection_params.port)
if server.connection_params.tls: if server.connection_params.tls:

View file

@ -1,6 +1,6 @@
#--depends-on config #--depends-on config
import base64, hashlib, hmac, uuid import base64, hashlib, hmac, typing, uuid
from src import ModuleManager, utils from src import ModuleManager, utils
from . import scram from . import scram
@ -13,16 +13,16 @@ USERPASS_MECHANISMS = [
"PLAIN" "PLAIN"
] ]
def _validate(s): class SaslSetting(utils.Setting):
mechanism, _, arguments = s.partition(" ") def parse(self, value: str) -> typing.Any:
return {"mechanism": mechanism, "args": arguments} mechanism, _, arguments = value.partition(" ")
return {"mechanism": mechanism, "args": arguments}
@utils.export("serverset", {"setting": "sasl", @utils.export("serverset", SaslSetting("sasl",
"help": "Set the sasl username/password for this server", "Set the sasl username/password for this server",
"validate": _validate, "example": "PLAIN BitBot:hunter2"}) example="PLAIN BitBot:hunter2"))
@utils.export("serverset", {"setting": "sasl-hard-fail", @utils.export("serverset", utils.BoolSetting("sasl-hard-fail",
"help": "Set whether a SASL failure should cause a disconnect", "Set whether a SASL failure should cause a disconnect"))
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _best_userpass_mechanism(self, mechanisms): def _best_userpass_mechanism(self, mechanisms):
for potential_mechanism in USERPASS_MECHANISMS: for potential_mechanism in USERPASS_MECHANISMS:

View file

@ -10,12 +10,10 @@ KARMA_DELAY_SECONDS = 3
REGEX_KARMA = re.compile(r"^(.*)(\+{2}|\-{2})$") REGEX_KARMA = re.compile(r"^(.*)(\+{2}|\-{2})$")
@utils.export("channelset", {"setting": "karma-verbose", @utils.export("channelset", utils.BoolSetting("karma-verbose",
"help": "Enable/disable automatically responding to karma changes", "Enable/disable automatically responding to karma changes"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("serverset", utils.BoolSetting("karma-nickname-only",
@utils.export("serverset", {"setting": "karma-nickname-only", "Enable/disable karma being for nicknames only"))
"help": "Enable/disable karma being for nicknames only",
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _karma_str(self, karma): def _karma_str(self, karma):
karma_str = str(karma) karma_str = str(karma)

View file

@ -7,8 +7,8 @@ from src import ModuleManager, utils
URL_SCROBBLER = "http://ws.audioscrobbler.com/2.0/" URL_SCROBBLER = "http://ws.audioscrobbler.com/2.0/"
@utils.export("set", {"setting": "lastfm", "help": "Set last.fm username", @utils.export("set", utils.Setting("lastfm", "Set last.fm username",
"example": "jesopo"}) example="jesopo"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
_name = "last.fm" _name = "last.fm"

View file

@ -1,14 +1,21 @@
#--depends-on config #--depends-on config
import typing
from src import ModuleManager, utils from src import ModuleManager, utils
URL_OPENCAGE = "https://api.opencagedata.com/geocode/v1/json" URL_OPENCAGE = "https://api.opencagedata.com/geocode/v1/json"
class LocationSetting(utils.Setting):
_func = None
def parse(self, value: str) -> typing.Any:
return self._func(value)
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def on_load(self): def on_load(self):
self.exports.add("set", {"setting": "location", setting = LocationSetting("location", "Set your location",
"help": "Set your location", "validate": self._get_location, example="London, GB")
"example": "London, GB"}) setting._func = self._get_location
self.exports.add("set", setting)
def _get_location(self, s): def _get_location(self, s):
page = utils.http.request(URL_OPENCAGE, get_params={ page = utils.http.request(URL_OPENCAGE, get_params={

View file

@ -3,9 +3,8 @@
import base64 import base64
from src import EventManager, ModuleManager, utils from src import EventManager, ModuleManager, utils
@utils.export("serverset", {"setting": "nickserv-password", @utils.export("serverset", utils.Setting("nickserv-password",
"help": "Set the nickserv password for this server", "Set the nickserv password for this server", example="hunter2"))
"example": "hunter2"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.001", priority=EventManager.PRIORITY_URGENT) @utils.hook("received.001", priority=EventManager.PRIORITY_URGENT)
def on_connect(self, event): def on_connect(self, event):

View file

@ -9,9 +9,8 @@ REQUIRES_IDENTIFY = "You need to be identified to use that command"
REQUIRES_IDENTIFY_INTERNAL = ("You need to be identified to use that command " REQUIRES_IDENTIFY_INTERNAL = ("You need to be identified to use that command "
"(/msg %s register | /msg %s identify)") "(/msg %s register | /msg %s identify)")
@utils.export("serverset", {"setting": "identity-mechanism", @utils.export("serverset", utils.Setting("identity-mechanism",
"help": "Set the identity mechanism for this server", "Set the identity mechanism for this server", example="ircv3-account"))
"example": "ircv3-account"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("new.user") @utils.hook("new.user")
def new_user(self, event): def new_user(self, event):

View file

@ -4,9 +4,8 @@
import datetime import datetime
from src import EventManager, ModuleManager, utils from src import EventManager, ModuleManager, utils
@utils.export("botset", {"setting": "print-motd", @utils.export("botset",
"help": "Set whether I print /motd", "validate": utils.bool_or_none, utils.BoolSetting("print-motd", "Set whether I print /motd"))
"example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _print(self, event): def _print(self, event):
self.bot.log.info("%s%s | %s", [ self.bot.log.info("%s%s | %s", [

View file

@ -3,8 +3,8 @@
from src import ModuleManager, utils from src import ModuleManager, utils
@utils.export("set", {"setting": "pronouns", "help": "Set your pronouns", @utils.export("set", utils.Setting("pronouns", "Set your pronouns",
"example": "she/her"}) example="she/her"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.command.pronouns") @utils.hook("received.command.pronouns")
def pronouns(self, event): def pronouns(self, event):

View file

@ -110,12 +110,10 @@ class Handler(http.server.BaseHTTPRequestHandler):
def log_message(self, format, *args): def log_message(self, format, *args):
return return
@utils.export("botset", {"setting": "rest-api", @utils.export("botset",
"help": "Enable/disable REST API", utils.BoolSetting("rest-api", "Enable/disable REST API"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("botset",
@utils.export("botset", {"setting": "rest-api-minify", utils.BoolSetting("rest-api", "Enable/disable REST API minifying"))
"help": "Enable/disable REST API minifying",
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def on_load(self): def on_load(self):
global _bot global _bot

View file

@ -7,12 +7,10 @@ from src import ModuleManager, utils
REGEX_SPLIT = re.compile("(?<!\\\\)/") REGEX_SPLIT = re.compile("(?<!\\\\)/")
REGEX_SED = re.compile("^s/") REGEX_SED = re.compile("^s/")
@utils.export("channelset", {"setting": "sed", @utils.export("channelset",
"help": "Disable/Enable sed in a channel", utils.BoolSetting("sed","Disable/Enable sed in a channel"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("channelset", utils.BoolSetting("sed-sender-only",
@utils.export("channelset", {"setting": "sed-sender-only", "Disable/Enable sed only looking at the messages sent by the user"))
"help": "Disable/Enable sed only looking at the messages sent by the user",
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _closest_setting(self, event, setting, default): def _closest_setting(self, event, setting, default):
return event["target"].get_setting(setting, return event["target"].get_setting(setting,

View file

@ -6,10 +6,10 @@ from src import ModuleManager, utils
URL_BITLYSHORTEN = "https://api-ssl.bitly.com/v3/shorten" URL_BITLYSHORTEN = "https://api-ssl.bitly.com/v3/shorten"
@utils.export("serverset", {"setting": "url-shortener", @utils.export("serverset", utils.Setting("url-shortener",
"help": "Set URL shortener service", "example": "bitly"}) "Set URL shortener service", example="bitly"))
@utils.export("botset", {"setting": "url-shortener", @utils.export("botset", utils.Setting("url-shortener",
"help": "Set URL shortener service", "example": "bitly"}) "Set URL shortener service", example="bitly"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def on_load(self): def on_load(self):
self.exports.add("shorturl", self._shorturl) self.exports.add("shorturl", self._shorturl)

View file

@ -2,12 +2,10 @@
from src import ModuleManager, utils from src import ModuleManager, utils
@utils.export("serverset", {"setting": "strip-color", @utils.export("serverset", utils.BoolSetting("strip-color",
"help": "Set whether I strip colors from my messages on this server", "Set whether I strip colors from my messages on this server"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("channelset", utils.BoolSetting("strip-color",
@utils.export("channelset", {"setting": "strip-color", "Set whether I strip colors from my messages on in this channel"))
"help": "Set whether I strip colors from my messages on in this channel",
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("preprocess.send.privmsg") @utils.hook("preprocess.send.privmsg")
@utils.hook("preprocess.send.notice") @utils.hook("preprocess.send.notice")

View file

@ -5,16 +5,12 @@
import hashlib, re, urllib.parse import hashlib, re, urllib.parse
from src import EventManager, ModuleManager, utils from src import EventManager, ModuleManager, utils
@utils.export("channelset", {"setting": "auto-title", @utils.export("channelset", utils.BoolSetting("auto-title",
"help": "Disable/Enable automatically getting info titles from URLs", "Disable/Enable automatically getting info titles from URLs"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("channelset", utils.BoolSetting("title-shorten",
@utils.export("channelset", {"setting": "title-shorten", "Enable/disable shortening URLs when getting their title"))
"help": "Enable/disable shortening URLs when getting their title", @utils.export("channelset", utils.BoolSetting("auto-title-first",
"validate": utils.bool_or_none, "example": "on"}) "Enable/disable showing who first posted a URL that was auto-titled"))
@utils.export("channelset", {"setting": "auto-title-first",
"help": ("Enable/disable showing who first posted a URL that was "
"auto-titled"),
"validate": utils.bool_or_none, "exaple": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _url_hash(self, url): def _url_hash(self, url):
return "sha256:%s" % hashlib.sha256(url.lower().encode("utf8") return "sha256:%s" % hashlib.sha256(url.lower().encode("utf8")

View file

@ -7,8 +7,8 @@ from src import ModuleManager, utils
URL_TRAKT = "https://api-v2launch.trakt.tv/users/%s/watching" URL_TRAKT = "https://api-v2launch.trakt.tv/users/%s/watching"
URL_TRAKTSLUG = "https://trakt.tv/%s/%s" URL_TRAKTSLUG = "https://trakt.tv/%s/%s"
@utils.export("set", {"setting": "trakt", "help": "Set username on trakt.tv", @utils.export("set", utils.Setting("trakt", "Set username on trakt.tv",
"example": "jesopo"}) example="jesopo"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
@utils.hook("received.command.nw", alias_of="nowwatching") @utils.hook("received.command.nw", alias_of="nowwatching")
@utils.hook("received.command.nowwatching") @utils.hook("received.command.nowwatching")

View file

@ -42,9 +42,8 @@ class BitBotStreamListener(tweepy.StreamListener):
_events.on("send.stdout").call(target=channel, _events.on("send.stdout").call(target=channel,
module_name="Tweets", server=server, message=tweet) module_name="Tweets", server=server, message=tweet)
@utils.export("channelset", {"setting": "auto-tweet", @utils.export("channelset", utils.BoolSetting("auto-tweet",
"help": "Enable/disable automatically getting tweet info", "Enable/disable automatically getting tweet info"))
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
_stream = None _stream = None
def on_load(self): def on_load(self):

View file

@ -10,9 +10,9 @@ STR_NOVOTE = "Unknown vote '%s'"
class VoteCastResult(enum.Enum): class VoteCastResult(enum.Enum):
Cast = 1 Cast = 1
Changed = 2 Changed = 2
@utils.export("channelset", {"setting": "votes-start-restricted",
"help": "Whether starting a vote should be restricted to ops", @utils.export("channelset", utils.BoolSetting("votes-start-restricted",
"validate": utils.bool_or_none, "example": "on"}) "Whether starting a vote should be restricted to ops"))
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _get_vote(self, channel, vote_id): def _get_vote(self, channel, vote_id):
return channel.get_setting("vote-%s" % vote_id, None) return channel.get_setting("vote-%s" % vote_id, None)

View file

@ -9,9 +9,8 @@ WORD_DELIM = "\"'…~*`"
WORD_START = WORD_DELIM+"“({<" WORD_START = WORD_DELIM+"“({<"
WORD_STOP = WORD_DELIM+"”)}>;:.,!?" WORD_STOP = WORD_DELIM+"”)}>;:.,!?"
@utils.export("set", {"setting": "word-tracking", @utils.export("set", utils.BoolSetting(
"help": "Disable/enable tracking your wordcounts", "word-tracking", "Disable/enable tracking your wordcounts"))
"validate": utils.bool_or_none, "example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def _channel_message(self, user, event): def _channel_message(self, user, event):
if not user.get_setting("word-tracking", True): if not user.get_setting("word-tracking", True):

View file

@ -18,12 +18,10 @@ URL_YOUTUBESHORT = "https://youtu.be/%s"
ARROW_UP = "" ARROW_UP = ""
ARROW_DOWN = "" ARROW_DOWN = ""
@utils.export("channelset", {"setting": "auto-youtube", @utils.export("channelset", utils.BoolSetting("auto-youtube",
"help": "Disable/Enable automatically getting info from youtube URLs", "Disable/Enable automatically getting info from youtube URLs"))
"validate": utils.bool_or_none, "example": "on"}) @utils.export("channelset", utils.BoolSetting("youtube-safesearch",
@utils.export("channelset", {"setting": "youtube-safesearch", "Turn safe search off/on"))
"help": "Turn safe search off/on", "validate": utils.bool_or_none,
"example": "on"})
class Module(ModuleManager.BaseModule): class Module(ModuleManager.BaseModule):
def on_load(self): def on_load(self):
self.exports.add("search-youtube", self._search_youtube) self.exports.add("search-youtube", self._search_youtube)

View file

@ -138,21 +138,6 @@ def parse_number(s: str) -> str:
raise ValueError("Unknown unit '%s' given to parse_number" % unit) raise ValueError("Unknown unit '%s' given to parse_number" % unit)
return str(number) return str(number)
IS_TRUE = ["true", "yes", "on", "y"]
IS_FALSE = ["false", "no", "off", "n"]
def bool_or_none(s: str) -> typing.Optional[bool]:
s = s.lower()
if s in IS_TRUE:
return True
elif s in IS_FALSE:
return False
return None
def int_or_none(s: str) -> typing.Optional[int]:
stripped_s = s.lstrip("0")
if stripped_s.isdigit():
return int(stripped_s)
return None
def prevent_highlight(nickname: str) -> str: def prevent_highlight(nickname: str) -> str:
return nickname[0]+"\u200c"+nickname[1:] return nickname[0]+"\u200c"+nickname[1:]
@ -243,3 +228,32 @@ def is_ip(s: str) -> bool:
def is_main_thread() -> bool: def is_main_thread() -> bool:
return threading.current_thread() is threading.main_thread() return threading.current_thread() is threading.main_thread()
class Setting(object):
def __init__(self, name: str, help: str=None, example: str=None):
self.name = name
self.help = help
self.example = example
def parse(self, value: str) -> typing.Any:
return value
SETTING_TRUE = ["true", "yes", "on", "y"]
SETTING_FALSE = ["false", "no", "off", "n"]
class BoolSetting(Setting):
example = "on"
def parse(self, value: str) -> typing.Any:
value_lower = value.lower()
if value_lower in SETTING_TRUE:
return True
elif value_lower in SETTING_FALSE:
return False
return None
class IntSetting(Setting):
example = "10"
def parse(self, value: str) -> typing.Any:
stripped = value.lstrip("0")
if stripped.isdigit():
return int(stripped)
return None