# Utilities

> Small helpers for lists, numbers, random picks, loops and JSON, plus the Python you can use.

These helpers save you from writing the same few lines again and again.

None of them need `await`, except `loop` and `ping`, which the bot awaits for you.

## listify

Turns a list into lines with bullets or numbers.

```python
listify(items, prefix="dot", new_line=True)
```

| Argument | What it does |
|---|---|
| `items` | The list. |
| `prefix` | `dot` gives •, `dash` gives -, `number` gives 1. 2. 3. |
| `new_line` | `False` puts everything on one line. |

```python
set_content(listify(user.role_names, "number"))
```

```text
1. Member
2. Gamer
3. VIP
```

## find

Returns the first item that passes your check, or `None`.

```python
find(items, check)
```

```python
vip = find(user.roles, lambda r: r.name == "VIP")
if vip is None:
    set_error("You need the VIP role.")
```

## max_concat

Adds text to a string only if it still fits under a length. Returns `[text, overflowed]`.

```python
max_concat(prev, new, max_length)
```

```python
text = ""
for name in names:
    text, full = max_concat(text, name + "\n", 2000)
    if full:
        break
set_content(text)
```

Good for staying under Discord's 2,000-character message limit.

## to_id_array

Turns a list of members, roles or channels into a list of their IDs.

```python
to_id_array(items)
```

```python
if 123456789012345678 in to_id_array(user.roles):
    set_content("You have the role.")
```

## mention_command

Makes a clickable mention of one of your slash commands.

```python
mention_command(command_name)
```

```python
set_content(f"Try {mention_command('daily')} to claim coins.")
```

Works for subcommands too, like `mention_command("shop buy")`. Falls back to plain `/name` text when the command is not synced yet.

## get_color

Turns a hex color into a number. Bad input gives white.

```python
get_color(code)
```

```python
get_color("#5865F2")   # 5793266
```

## ping

The bot's connection delay to Discord, in milliseconds.

```python
ping(precision=2)
```

```python
set_content(f"Pong! {ping()} ms")
```

## random

Picks one item at random.

```python
random(items, *more, exclude=None)
```

```python
random(["rock", "paper", "scissors"])
random("heads", "tails")
random(range(1, 7), exclude=[6])
```

## randomNumber

A random whole number from `a` to `b`. Both ends can come up.

```python
randomNumber(a, b)
```

```python
roll = randomNumber(1, 6)
```

## number

Turns text into a number. Bad or empty input gives `default`.

```python
number(val, default=0)
```

```python
number("42")      # 42
number("3.5")     # 3.5
number("abc", 1)  # 1
```

Handy for saved values, which come back as text.

## loop

Runs a function for each item, or a number of times. The bot awaits it for you.

```python
loop(items, callback, *args, **kwargs)
```

| Argument | What it does |
|---|---|
| `items` | A list, or a number of times. |
| `callback` | A named function. It gets `(item, index, *args)`. |

```python
lines = []

def add_line(member, index):
    lines.append(f"{index + 1}. {member.mention}")

loop(winners, add_line)
set_content("\n".join(lines))
```

Inside the function:

- `break_loop(data)` stops the loop. `loop` returns `data`.
- `iterate_again()` runs the same item again, up to 10 times.

> **Note:** `loop` takes a named function, not a `lambda`. Loops can nest 3 deep. A plain `for` loop works too, and is often simpler.

## JSON

| Function | What it does |
|---|---|
| `json_parse(text)` | Text to a dict or list. Same as `load_json`. |
| `json_gen(obj)` | A dict or list to text. Same as `to_json`. |

```python
data = json_parse('{"coins": 10}')
update_member_var("profile", json_gen({"coins": data["coins"] + 5}))
```

## calc

Works out a math sum written as text. Safe to use on what users type.

```python
calc("2 + 3 * 4")   # 14
```

## Python you can use

Most everyday Python works: `if`, `for`, `while`, functions, classes, lists, dicts, f-strings, `try` / `except`.

**Built in:** `int`, `float`, `bool`, `str`, `list`, `set`, `tuple`, `dict`, `len`, `max`, `min`, `sum`, `abs`, `round`, `pow`, `divmod`, `sorted`, `reversed`, `zip`, `enumerate`, `range`, `all`, `any`, `next`, `map`, `filter`, `isinstance`, `slice`.

**Also here:** `text` (same as `str`), `count` (same as `len`), `double` (same as `float`), `emojize`.

**Errors you can raise or catch:** `Exception`, `ValueError`, `TypeError`, `KeyError`, `ReferenceError`.

**Modules, ready to use:** `math`, `string`, `collections`, `pyrandom` (Python's `random`), `fuzz` (fuzzy text matching).

`map` and `filter` return lists, not iterators.

> **Not available:** `import` does nothing, because everything is already loaded. `print` does not exist. To see a value, put it in the reply with `set_content`.

See [Common mistakes](https://ccbot.app/docs/concepts/common-mistakes) and [Limits](https://ccbot.app/docs/concepts/limits) for loop limits.
