Skip to content

tux.utils.functions

Functions:

Name Description
truncate

Truncates a string to a specified length.

is_harmful

Check if a command is potentially harmful to the system.

strip_formatting

Strip formatting from a string.

parse_time_string

Convert a string representation of time into a datetime.timedelta object.

convert_to_seconds

Converts a formatted time string with the formats Mwdhms

seconds_to_human_readable

Converts a number of seconds into a human readable string

datetime_to_unix

This function accepts a datetime object or None, converts it into a Unix timestamp

datetime_to_elapsed_time

Takes a datetime and computes the elapsed time from then to now in the format: X years, Y months, Z days.

compare_changes

Compares the changes between two dictionaries and returns a list of strings representing the changes.

compare_guild_channel_changes

Compares the changes between two GuildChannel instances and returns a list of strings representing the changes.

compare_member_changes

Compares changes between two Member instances and returns a list of strings representing the changes.

extract_guild_attrs

Extracts relevant attributes from a discord.Guild and returns them as a dictionary.

extract_member_attrs

Extract relevant attributes from a member object.

Functions

truncate(text: str, length: int) -> str

Truncates a string to a specified length.

If the string is longer than the specified length, it will be truncated and an ellipsis will be appended. Otherwise, the original string is returned.

Parameters:

Name Type Description Default
text str

The string to truncate.

required
length int

The maximum length of the string.

required

Returns:

Type Description
str

The truncated string.

Source code in tux/utils/functions.py
Python
def truncate(text: str, length: int) -> str:
    """Truncates a string to a specified length.

    If the string is longer than the specified length, it will be truncated
    and an ellipsis will be appended. Otherwise, the original string is returned.

    Parameters
    ----------
    text : str
        The string to truncate.
    length : int
        The maximum length of the string.

    Returns
    -------
    str
        The truncated string.
    """
    return text if len(text) <= length else f"{text[: length - 3]}..."

is_harmful(command: str) -> str | None

Check if a command is potentially harmful to the system.

Parameters:

Name Type Description Default
command str

The command to check.

required

Returns:

Type Description
bool

True if the command is harmful, False otherwise.

Source code in tux/utils/functions.py
Python
def is_harmful(command: str) -> str | None:
    # sourcery skip: assign-if-exp, boolean-if-exp-identity, reintroduce-else
    """
    Check if a command is potentially harmful to the system.

    Parameters
    ----------
    command : str
        The command to check.

    Returns
    -------
    bool
        True if the command is harmful, False otherwise.
    """
    # Normalize command by removing all whitespace for fork bomb check
    normalized = "".join(command.strip().lower().split())
    if normalized in FORK_BOMB_PATTERNS:
        return "FORK_BOMB"

    # Check for dangerous rm commands
    if re.search(DANGEROUS_RM_COMMANDS, command, re.IGNORECASE):
        return "RM_COMMAND"

    # Check for dangerous dd commands
    if re.search(DANGEROUS_DD_COMMANDS, command, re.IGNORECASE):
        return "DD_COMMAND"

    # Check for format commands
    if bool(re.search(FORMAT_COMMANDS, command, re.IGNORECASE)):
        return "FORMAT_COMMAND"
    return None

strip_formatting(content: str) -> str

Strip formatting from a string.

Parameters:

Name Type Description Default
content str

The string to strip formatting from.

required

Returns:

Type Description
str

The string with formatting stripped.

Source code in tux/utils/functions.py
Python
def strip_formatting(content: str) -> str:
    """
    Strip formatting from a string.

    Parameters
    ----------
    content : str
        The string to strip formatting from.

    Returns
    -------
    str
        The string with formatting stripped.
    """
    # Remove triple backtick blocks
    content = re.sub(r"```[\s\S]*?```", "", content)
    # Remove single backtick code blocks
    content = re.sub(r"`[^`]+`", "", content)
    # Remove Markdown headers
    content = re.sub(r"^#+\s+", "", content, flags=re.MULTILINE)
    # Remove markdown formatting characters, but preserve |
    content = re.sub(r"[\*_~>]", "", content)
    # Remove extra whitespace
    content = re.sub(r"\s+", " ", content)

    return content.strip()

parse_time_string(time_str: str) -> timedelta

Convert a string representation of time into a datetime.timedelta object.

Parameters:

Name Type Description Default
time_str str

The string representation of time to convert. (e.g., '60s', '1m', '2h', '10d')

required

Returns:

Type Description
timedelta

The timedelta object representing the time string.

Source code in tux/utils/functions.py
Python
def parse_time_string(time_str: str) -> timedelta:
    """
    Convert a string representation of time into a datetime.timedelta object.

    Parameters
    ----------
    time_str : str
        The string representation of time to convert. (e.g., '60s', '1m', '2h', '10d')

    Returns
    -------
    timedelta
        The timedelta object representing the time string.
    """

    # Define regex pattern to parse time strings
    time_pattern = re.compile(r"^(?P<value>\d+)(?P<unit>[smhdw])$")

    # Match the input string with the pattern
    match = time_pattern.match(time_str)

    if not match:
        msg = f"Invalid time format: '{time_str}'"
        raise ValueError(msg)

    # Extract the value and unit from the pattern match
    value = int(match["value"])
    unit = match["unit"]

    # Define the mapping of units to keyword arguments for timedelta
    unit_map = {"s": "seconds", "m": "minutes", "h": "hours", "d": "days", "w": "weeks"}

    # Check if the unit is in the map
    if unit not in unit_map:
        msg = f"Unknown time unit: '{unit}'"
        raise ValueError(msg)

    # Create the timedelta with the appropriate keyword argument
    kwargs = {unit_map[unit]: value}

    return timedelta(**kwargs)

convert_to_seconds(time_str: str) -> int

Converts a formatted time string with the formats Mwdhms Any unexpected format leads to returning 0.

Parameters:

Name Type Description Default
time_str str

The formatted time string to convert to total seconds.

required

Returns:

Type Description
int

The total seconds from the formatted time string.

Source code in tux/utils/functions.py
Python
def convert_to_seconds(time_str: str) -> int:
    """
    Converts a formatted time string with the formats Mwdhms
    Any unexpected format leads to returning 0.

    Parameters
    ----------
    time_str : str
        The formatted time string to convert to total seconds.

    Returns
    -------
    int
        The total seconds from the formatted time string.
    """

    # Time conversion factors from units to seconds
    time_units = {
        "M": 2592000,  # Months to seconds
        "w": 604800,  # Weeks to seconds
        "d": 86400,  # Days to seconds
        "h": 3600,  # Hours to seconds
        "m": 60,  # Minutes to seconds
        "s": 1,  # Seconds to seconds
    }

    total_seconds = 0
    current_value = 0

    for char in time_str:
        if char.isdigit():
            # Build the current number
            current_value = current_value * 10 + int(char)
        elif char in time_units:
            # If the unit is known, update total_seconds
            if current_value == 0:
                return 0  # No number specified for the unit, thus treat as invalid input
            total_seconds += current_value * time_units[char]
            current_value = 0  # Reset for next number-unit pair
        else:
            # Unknown character indicates an invalid format
            return 0

    return 0 if current_value != 0 else total_seconds

seconds_to_human_readable(seconds: int) -> str

Converts a number of seconds into a human readable string

Parameters:

Name Type Description Default
seconds int

The number of seconds to convert

required

Returns:

Type Description
str

A string that breaks the time down by months, weeks, days, hours, minutes, and seconds.

Source code in tux/utils/functions.py
Python
def seconds_to_human_readable(seconds: int) -> str:
    """
    Converts a number of seconds into a human readable string

    Parameters
    ----------
    seconds : int
        The number of seconds to convert

    Returns
    -------
    str
        A string that breaks the time down by months, weeks, days, hours, minutes, and seconds.
    """
    units = (
        ("month", 2592000),
        ("week", 604800),
        ("day", 86400),
        ("hour", 3600),
        ("minute", 60),
        ("second", 1),
    )
    if seconds == 0:
        return "zero seconds"
    parts: list[str] = []
    for unit, div in units:
        amount, seconds = divmod(int(seconds), div)
        if amount > 0:
            parts.append(f"{amount} {unit}{'' if amount == 1 else 's'}")
    return ", ".join(parts)

datetime_to_unix(dt: datetime | None) -> str

This function accepts a datetime object or None, converts it into a Unix timestamp and returns it as a formatted Discord timestamp string or 'Never'

Parameters:

Name Type Description Default
dt datetime

The datetime object to convert to a Discord timestamp string.

required

Returns:

Type Description
str

The formatted Discord timestamp string or 'Never'

Source code in tux/utils/functions.py
Python
def datetime_to_unix(dt: datetime | None) -> str:
    """
    This function accepts a datetime object or None, converts it into a Unix timestamp
    and returns it as a formatted Discord timestamp string or 'Never'

    Parameters
    ----------
    dt : datetime
        The datetime object to convert to a Discord timestamp string.

    Returns
    -------
    str
        The formatted Discord timestamp string or 'Never'
    """

    if dt is None:
        return "Never"

    unix_timestamp = int(dt.timestamp())

    return f"<t:{unix_timestamp}>"

datetime_to_elapsed_time(dt: datetime | None) -> str

Takes a datetime and computes the elapsed time from then to now in the format: X years, Y months, Z days.

Parameters:

Name Type Description Default
dt datetime

The datetime object to compute the elapsed time from.

required

Returns:

Type Description
str

The elapsed time in the format: X years, Y months, Z days.

Source code in tux/utils/functions.py
Python
def datetime_to_elapsed_time(dt: datetime | None) -> str:
    """
    Takes a datetime and computes the elapsed time from then to now in the format: X years, Y months, Z days.

    Parameters
    ----------
    dt : datetime
        The datetime object to compute the elapsed time from.

    Returns
    -------
    str
        The elapsed time in the format: X years, Y months, Z days.
    """

    if dt is None:
        return "Never"

    elapsed_time = datetime.now(UTC) - dt
    elapsed_days = elapsed_time.days

    years, days_left = divmod(elapsed_days, 365)
    months, days_left = divmod(days_left, 30)

    return f"{years} years, {months} months, {days_left} days"

compare_changes(before: dict[str, Any], after: dict[str, Any]) -> list[str]

Compares the changes between two dictionaries and returns a list of strings representing the changes.

Parameters:

Name Type Description Default
before dict

The dictionary representing the state before the changes.

required
after dict

The dictionary representing the state after the changes.

required

Returns:

Type Description
list

A list of strings showing the changes made in the dictionaries.

Source code in tux/utils/functions.py
Python
def compare_changes(before: dict[str, Any], after: dict[str, Any]) -> list[str]:
    """
    Compares the changes between two dictionaries and returns a list of strings representing the changes.

    Parameters
    ----------
    before : dict
        The dictionary representing the state before the changes.
    after : dict
        The dictionary representing the state after the changes.

    Returns
    -------
    list
        A list of strings showing the changes made in the dictionaries.
    """

    return [f"{key}: {before[key]} -> {after[key]}" for key in before if key in after and before[key] != after[key]]

compare_guild_channel_changes(before: discord.abc.GuildChannel, after: discord.abc.GuildChannel) -> list[str]

Compares the changes between two GuildChannel instances and returns a list of strings representing the changes.

Parameters:

Name Type Description Default
before GuildChannel

The GuildChannel instance representing the state before the changes.

required
after GuildChannel

The GuildChannel instance representing the state after the changes.

required

Returns:

Type Description
list

A list of strings showing the changes made in the GuildChannel instances.

Source code in tux/utils/functions.py
Python
def compare_guild_channel_changes(
    before: discord.abc.GuildChannel,
    after: discord.abc.GuildChannel,
) -> list[str]:
    """
    Compares the changes between two GuildChannel instances and returns a list of strings representing the changes.

    Parameters
    ----------
    before : discord.abc.GuildChannel
        The GuildChannel instance representing the state before the changes.
    after : discord.abc.GuildChannel
        The GuildChannel instance representing the state after the changes.

    Returns
    -------
    list
        A list of strings showing the changes made in the GuildChannel instances.
    """

    keys = [
        "category",
        "changed_roles",
        "created_at",
        "guild",
        "name",
        "overwrites",
        "permissions_synced",
        "position",
    ]

    return [
        f"{key}: {getattr(before, key)} -> {getattr(after, key)}"
        for key in keys
        if getattr(before, key) != getattr(after, key)
    ]

compare_member_changes(before: discord.Member | discord.User, after: discord.Member | discord.User) -> list[str]

Compares changes between two Member instances and returns a list of strings representing the changes.

Parameters:

Name Type Description Default
before Member

The Member instance representing the state before the changes.

required
after Member

The Member instance representing the state after the changes.

required

Returns:

Type Description
list

A list of strings showing the changes made in the Member instances.

Source code in tux/utils/functions.py
Python
def compare_member_changes(
    before: discord.Member | discord.User,
    after: discord.Member | discord.User,
) -> list[str]:
    """
    Compares changes between two Member instances and returns a list of strings representing the changes.

    Parameters
    ----------
    before : discord.Member
        The Member instance representing the state before the changes.
    after : discord.Member
        The Member instance representing the state after the changes.

    Returns
    -------
    list
        A list of strings showing the changes made in the Member instances.
    """

    keys = ["name", "display_name", "global_name"]

    return [
        f"{key}: {getattr(before, key)} -> {getattr(after, key)}"
        for key in keys
        if getattr(before, key) != getattr(after, key)
    ]

extract_guild_attrs(guild: discord.Guild) -> dict[str, Any]

Extracts relevant attributes from a discord.Guild and returns them as a dictionary.

Parameters:

Name Type Description Default
guild Guild

The discord.Guild instance to extract attributes from.

required

Returns:

Type Description
dict

A dictionary containing the extracted attributes of the guild.

Source code in tux/utils/functions.py
Python
def extract_guild_attrs(guild: discord.Guild) -> dict[str, Any]:
    """
    Extracts relevant attributes from a discord.Guild and returns them as a dictionary.

    Parameters
    ----------
    guild : discord.Guild
        The discord.Guild instance to extract attributes from.

    Returns
    -------
    dict
        A dictionary containing the extracted attributes of the guild.
    """

    return {
        "name": guild.name,
        "description": guild.description,
        "member_count": guild.member_count,
        "verification_level": str(guild.verification_level),
        "system_channel": guild.system_channel,
    }

extract_member_attrs(member: discord.Member) -> dict[str, Any]

Extract relevant attributes from a member object.

Parameters:

Name Type Description Default
member Member

The member object to extract attributes from.

required

Returns:

Type Description
dict[str, Any]

A dictionary containing the extracted attributes.

Source code in tux/utils/functions.py
Python
def extract_member_attrs(member: discord.Member) -> dict[str, Any]:
    """Extract relevant attributes from a member object.

    Parameters
    ----------
    member : discord.Member
        The member object to extract attributes from.

    Returns
    -------
    dict[str, Any]
        A dictionary containing the extracted attributes.
    """
    return {
        "name": member.name,
        "id": member.id,
        "discriminator": member.discriminator,
        "display_name": member.display_name,
        "roles": [role.name for role in member.roles],
        "joined_at": member.joined_at,
        "status": str(member.status),
        "activity": str(member.activity) if member.activity else None,
    }