Esempio n. 1
0
 def __setitem__(self, key: str, item: typing.Any) -> None:
     key = key.lower()
     logger.info("Setting %s.", key)
     if key not in self.all_keys:
         raise InvalidConfigError(f'Configuration "{key}" is invalid.')
     self._cache[key] = item
Esempio n. 2
0
    def get(self, key: str, convert=True) -> typing.Any:
        key = key.lower()
        if key not in self.all_keys:
            raise InvalidConfigError(f'Configuration "{key}" is invalid.')
        if key not in self._cache:
            self._cache[key] = deepcopy(self.defaults[key])
        value = self._cache[key]

        if not convert:
            return value

        if key in self.colors:
            try:
                return int(value.lstrip("#"), base=16)
            except ValueError:
                logger.error("Invalid %s provided.", key)
            value = int(self.remove(key).lstrip("#"), base=16)

        elif key in self.time_deltas:
            if not isinstance(value, isodate.Duration):
                try:
                    value = isodate.parse_duration(value)
                except isodate.ISO8601Error:
                    logger.warning(
                        "The {account} age limit needs to be a "
                        'ISO-8601 duration formatted duration, not "%s".',
                        value,
                    )
                    value = self.remove(key)

        elif key in self.booleans:
            try:
                value = strtobool(value)
            except ValueError:
                value = self.remove(key)

        elif key in self.enums:
            if value is None:
                return None
            try:
                value = self.enums[key](value)
            except ValueError:
                logger.warning("Invalid %s %s.", key, value)
                value = self.remove(key)

        elif key in self.force_str:
            # Temporary: as we saved in int previously, leading to int32 overflow,
            #            this is transitioning IDs to strings
            new_value = {}
            changed = False
            for k, v in value.items():
                new_v = v
                if isinstance(v, list):
                    new_v = []
                    for n in v:
                        if n != -1 and not isinstance(n, str):
                            changed = True
                            n = str(n)
                        new_v.append(n)
                new_value[k] = new_v

            if changed:
                # transition the database as well
                self.set(key, new_value)

            value = new_value

        return value
Esempio n. 3
0
    async def clean_data(self, key: str,
                         val: typing.Any) -> typing.Tuple[str, str]:
        value_text = val
        clean_value = val

        # when setting a color
        if key in self.colors:
            try:
                hex_ = str(val)

                if hex_.startswith("#"):
                    hex_ = hex_[1:]
                if len(hex_) == 3:
                    hex_ = "".join(s for s in hex_ for _ in range(2))
                if len(hex_) != 6:
                    raise InvalidConfigError("Invalid color name or hex.")
                try:
                    int(hex_, 16)
                except ValueError:
                    raise InvalidConfigError("Invalid color name or hex.")
                hex_ = "#" + hex_
                value_text = clean_value = hex_

            except InvalidConfigError:
                name = str(val).lower()
                name = re.sub(r"[\-+|. ]+", " ", name)
                hex_ = ALL_COLORS.get(name)
                if hex_ is None:
                    name = re.sub(r"[\-+|. ]+", "", name)
                    hex_ = ALL_COLORS.get(name)
                    if hex_ is None:
                        raise

                clean_value = hex_
                value_text = f"{name} ({clean_value})"

        elif key in self.time_deltas:
            try:
                isodate.parse_duration(val)
            except isodate.ISO8601Error:
                try:
                    converter = UserFriendlyTime()
                    time = await converter.convert(None, val)
                    if time.arg:
                        raise ValueError
                except BadArgument as exc:
                    raise InvalidConfigError(*exc.args)
                except Exception:
                    raise InvalidConfigError(
                        "Unrecognized time, please use ISO-8601 duration format "
                        'string or a simpler "human readable" time.')
                clean_value = isodate.duration_isoformat(time.dt -
                                                         converter.now)
                value_text = f"{val} ({clean_value})"

        elif key in self.booleans:
            try:
                clean_value = value_text = strtobool(val)
            except ValueError:
                raise InvalidConfigError("Must be a yes/no value.")

        return clean_value, value_text
Esempio n. 4
0
    def set(self, key: str, item: typing.Any, convert=True) -> None:
        if not convert:
            return self.__setitem__(key, item)

        if key in self.colors:
            try:
                hex_ = str(item)
                if hex_.startswith("#"):
                    hex_ = hex_[1:]
                if len(hex_) == 3:
                    hex_ = "".join(s for s in hex_ for _ in range(2))
                if len(hex_) != 6:
                    raise InvalidConfigError("Invalid color name or hex.")
                try:
                    int(hex_, 16)
                except ValueError:
                    raise InvalidConfigError("Invalid color name or hex.")

            except InvalidConfigError:
                name = str(item).lower()
                name = re.sub(r"[\-+|. ]+", " ", name)
                hex_ = ALL_COLORS.get(name)
                if hex_ is None:
                    name = re.sub(r"[\-+|. ]+", "", name)
                    hex_ = ALL_COLORS.get(name)
                    if hex_ is None:
                        raise
            return self.__setitem__(key, "#" + hex_)

        if key in self.time_deltas:
            try:
                isodate.parse_duration(item)
            except isodate.ISO8601Error:
                try:
                    converter = UserFriendlyTimeSync()
                    time = converter.convert(None, item)
                    if time.arg:
                        raise ValueError
                except BadArgument as exc:
                    raise InvalidConfigError(*exc.args)
                except Exception as e:
                    logger.debug(e)
                    raise InvalidConfigError(
                        "Unrecognized time, please use ISO-8601 duration format "
                        'string or a simpler "human readable" time.'
                    )
                item = isodate.duration_isoformat(time.dt - converter.now)
            return self.__setitem__(key, item)

        if key in self.booleans:
            try:
                return self.__setitem__(key, strtobool(item))
            except ValueError:
                raise InvalidConfigError("Must be a yes/no value.")

        elif key in self.enums:
            if isinstance(item, self.enums[key]):
                # value is an enum type
                item = item.value

        return self.__setitem__(key, item)
Esempio n. 5
0
    async def clean_data(self, key: str,
                         val: typing.Any) -> typing.Tuple[str, str]:
        value_text = val
        clean_value = val

        # when setting a color
        if key in self.colors:
            hex_ = ALL_COLORS.get(val)

            if hex_ is None:
                if not isinstance(val, str):
                    raise InvalidConfigError("Invalid color name or hex.")
                if val.startswith("#"):
                    val = val[1:]
                if len(val) != 6:
                    raise InvalidConfigError("Invalid color name or hex.")
                for letter in val:
                    if letter not in {
                            "0",
                            "1",
                            "2",
                            "3",
                            "4",
                            "5",
                            "6",
                            "7",
                            "8",
                            "9",
                            "a",
                            "b",
                            "c",
                            "d",
                            "e",
                            "f",
                    }:
                        raise InvalidConfigError("Invalid color name or hex.")
                clean_value = "#" + val
                value_text = clean_value
            else:
                clean_value = hex_
                value_text = f"{val} ({clean_value})"

        elif key in self.time_deltas:
            try:
                isodate.parse_duration(val)
            except isodate.ISO8601Error:
                try:
                    converter = UserFriendlyTime()
                    time = await converter.convert(None, val)
                    if time.arg:
                        raise ValueError
                except BadArgument as exc:
                    raise InvalidConfigError(*exc.args)
                except Exception:
                    raise InvalidConfigError(
                        "Unrecognized time, please use ISO-8601 duration format "
                        'string or a simpler "human readable" time.')
                clean_value = isodate.duration_isoformat(time.dt -
                                                         converter.now)
                value_text = f"{val} ({clean_value})"

        return clean_value, value_text