def __init__(self, command: str, *, flag: Optional[str] = None, owner_only: bool = False, chan: bool = True, pm: bool = False, playing: bool = False, silenced: bool = False, phases: Iterable[str] = (), roles: Iterable[str] = (), users: Iterable[User] = None): # the "d" flag indicates it should only be enabled in debug mode if flag == "d" and not botconfig.DEBUG_MODE: return # handle command localizations commands = messages.raw("_commands")[command] self.commands = frozenset(commands) self.flag = flag self.owner_only = owner_only self.chan = chan self.pm = pm self.playing = playing self.silenced = silenced self.phases = phases self.roles = roles self.users = users # iterable of users that can use the command at any time (should be a mutable object) self.func = None self.aftergame = False self.name = commands[0] self.key = "{0}_{1}".format(command, id(self)) self.alt_allowed = bool(flag or owner_only) alias = False self.aliases = [] if var.DISABLED_COMMANDS.intersection(commands): return # command is disabled, do not add to COMMANDS for name in commands: for func in COMMANDS[name]: if func.owner_only != owner_only or func.flag != flag: raise ValueError("unmatching access levels for {0}".format( func.name)) COMMANDS[name].append(self) if name in botconfig.ALLOWED_ALT_CHANNELS_COMMANDS: self.alt_allowed = True if name in getattr(botconfig, "OWNERS_ONLY_COMMANDS", ()): self.owner_only = True if alias: self.aliases.append(name) alias = True if playing: # Don't restrict to owners or allow in alt channels self.owner_only = False self.alt_allowed = False
def _join_simple(self, value, arg, sort=False): from src.messages import messages # join using only a comma (in English), regardless of the number of list items normal_chars = messages.raw("_metadata", "list") simple = normal_chars[1] return self._join(value, arg, join_chars=[simple, simple, simple], sort=sort)
def _article(self, value, arg): from src.messages import messages for rule in messages.raw("_metadata", "articles"): if rule["pattern"] is None or fnmatch.fnmatch( value, rule["pattern"]): return rule["article"] raise ValueError( "No article rules matched the value {0!r} in language metadata!". format(value))
def convert_field(self, value, conversion): from src.messages import messages, LocalRole, LocalMode, LocalTotem if conversion == "role": if isinstance(value, LocalRole): # FIXME: this doesn't necessarily match the roles metadata (which can have lists of arbitrary length) return [value.singular, value.plural] return messages.raw("_roles", value) if conversion == "mode": if isinstance(value, LocalMode): return value.local return messages.raw("_gamemodes", value) if conversion == "command": return messages.raw("_commands", value)[0] if conversion == "totem": if isinstance(value, LocalTotem): return value.local return messages.raw("_totems", value) if conversion == "cat": return messages.raw("_role_categories", value) if conversion == "phase": return messages.raw("_phases", value) # not one of our custom things return super().convert_field(value, conversion)
def _parse_expires(expires: str, base: Optional[str] = None) -> Optional[datetime]: if expires in messages.raw("never_aliases"): return None try: # if passed a raw int, treat it as days amount = int(expires) suffix = messages.raw("day_suffix") except ValueError: amount = int(expires[:-1]) suffix = expires[-1] if amount <= 0: raise ValueError("amount cannot be negative") if not base: base = datetime.utcnow() else: base = datetime.strptime(base, "%Y-%m-%d %H:%M:%S") if suffix == messages.raw("day_suffix"): expires = base + timedelta(days=amount) elif suffix == messages.raw("hour_suffix"): expires = base + timedelta(hours=amount) elif suffix == messages.raw("minute_suffix"): expires = base + timedelta(minutes=amount) else: raise ValueError("unrecognized time suffix") round_add = 0 if expires.second >= 30: round_add = 1 expires -= timedelta(seconds=expires.second, microseconds=expires.microsecond) expires += timedelta(minutes=round_add) return expires
def _plural(self, value, arg): from src.messages import messages if not arg: num = None else: try: num = int(arg) except TypeError: num = len(arg) for rule in messages.raw("_metadata", "plural"): if rule["number"] is None or rule["number"] == num: return value[rule["index"]] raise ValueError( "No plural rules matched the number {0!r} in language metadata!". format(num))
def _join(self, value, arg, join_chars=None, sort=False): from src.messages import messages spec = None conv = None if arg: if arg[0] == "!": parts = arg[1:].split(":", maxsplit=1) conv = parts[0] if len(parts) > 1: spec = parts[1] elif arg[0] == ":": spec = arg[1:] else: spec = arg if not join_chars: join_chars = messages.raw("_metadata", "list") value = list(value) # make sure we can index it def fmt(s): if conv: s = self.convert_field(s, conv) return self.format_field(s, spec) value = [fmt(v) for v in value] if sort: # FIXME make this transport-agnostic value = sorted(value, key=lambda v: v.replace("\u0002", "").lower()) if not value: return "" elif len(value) == 1: return value[0] elif len(value) == 2: return join_chars[0].join(value) else: return (join_chars[1].join(value[:-1]) + join_chars[2] + value[-1])
def _join(self, value, arg, join_chars=None): from src.messages import messages spec = None if arg: spec = arg if not join_chars: join_chars = messages.raw("_metadata", "list") value = list(value) # make sure we can index it if not value: return "" elif len(value) == 1: return self.format_field(value[0], spec) elif len(value) == 2: return join_chars[0].join( self.format_field(v, spec) for v in value) else: return (join_chars[1].join( self.format_field(v, spec) for v in value[:-1]) + join_chars[2] + self.format_field(value[-1], spec))
def convert_field(self, value, conversion): from src.messages import messages if conversion == "role": return messages.raw("_roles", value) if conversion == "mode": return messages.raw("_gamemodes", value) if conversion == "command": return messages.raw("_commands", value)[0] if conversion == "totem": return messages.raw("_totems", value) if conversion == "cat": return messages.raw("_role_categories", value) if conversion == "phase": return messages.raw("_phases", value) # not one of our custom things return super().convert_field(value, conversion)
if "stasis" in warning["sanctions"]: sanctions.append(messages["warn_view_stasis"].format( warning["sanctions"]["stasis"])) if "deny" in warning["sanctions"]: sanctions.append(messages["warn_view_deny"].format( warning["sanctions"]["deny"])) if "tempban" in warning["sanctions"]: sanctions.append(messages["warn_view_tempban"].format( warning["sanctions"]["tempban"])) if sanctions: wrapper.pm(messages["warn_view_sanctions"].format(sanctions)) warn_parser = LineParser(prog="warn") warn_subparsers = warn_parser.add_subparsers() _waccount = messages.raw("_commands", "warn opt account") # type: List[str] _wall = messages.raw("_commands", "warn opt all") # type: List[str] _wban = messages.raw("_commands", "warn opt ban") # type: List[str] _wdeny = messages.raw("_commands", "warn opt deny") # type: List[str] _wexpires = messages.raw("_commands", "warn opt expires") # type: List[str] _whelp = messages.raw("_commands", "warn opt help") # type: List[str] _wnotes = messages.raw("_commands", "warn opt notes") # type: List[str] _wreason = messages.raw("_commands", "warn opt reason") # type: List[str] _wstasis = messages.raw("_commands", "warn opt stasis") # type: List[str] _wl = messages.raw("_commands", "warn list") # type: List[str] _warn_list = warn_subparsers.add_parser(_wl[0], aliases=_wl[1:]) _warn_list.add_argument(*_wall, dest="all", action="store_true") _warn_list.add_argument(*_whelp, dest="help", action="help") _warn_list.add_argument("page", type=int, nargs="?", default=1) _warn_list.set_defaults(func=warn_list)