This release is a pre-release and may not be stable for production use.
tflows.py
tflows.py is a lightweight automation and Discord bot framework built around a scripting engine. Instead of writing Python event handlers for every action, you define bot behavior as simple text scripts:
from tflows import FlowBot
bot = FlowBot(prefix="!")
bot.command(
name="ping",
code="""
// Send a reply with the current latency
reply Pong! $ping
""",
)
bot.run("YOUR_BOT_TOKEN")
It is designed for fast bot development, easy customization, and extensible command logic — while staying fully compatible with discord.py so you can mix scripts and regular commands.
Features
- Script-based command system — write bot logic as plain text
- Built-in
$variabletemplates ($user,$server,$args,$ping, ...) - Command arguments:
$args,$arg(0),$argcount - Rich embeds, both as blocks and single-line commands
- Built-in
helpcommand, aliases, and command descriptions - Comment support in scripts (
//,#,--) - Async Discord integration using discord.py 2.x
- Extensible registry: add your own functions and variables
- Mixing with regular discord.py commands, cogs, and listeners
Installation
pip install tflows
Requires Python 3.10+.
Quick Start
from tflows import FlowBot
bot = FlowBot(prefix="!")
bot.command(
name="hello",
code="""
reply Hello $user(display)!
""",
)
bot.run("YOUR_BOT_TOKEN")
Command registration
FlowBot.command(name, code, description="", aliases=()) registers a script
command:
bot.command(
name="greet",
code="reply Hello $args",
description="Greets the given name.",
aliases=("hi", "hey"),
)
Both !greet, !hi and !hey now trigger the same script.
The built-in help command
By default !help lists every script command, and !help <command> shows its
description, aliases, usage, and source script. Disable it with
FlowBot(prefix="!", help_command=False).
Variables
Variables are replaced anywhere in a script, including inside function
arguments. Usage is $name or $name(option).
| Variable | Options | Description |
|---|---|---|
$user / $author |
name, display, id, mention, avatar, bot, created, joined, tag |
Information about the message author |
$server / $guild |
name, id, icon, owner, members, boost, boostlvl, created, description |
Information about the current guild |
$channel |
name, id, mention, topic, nsfw, type, position, category, created |
Information about the current channel |
$bot |
name, id, mention, avatar, status, ping, uptime |
Information about the bot itself |
$args |
— | Everything typed after the command name |
$arg(n) |
0-based index, negative counts from the end, a:b slices |
A single argument |
$argcount |
— | Number of arguments |
$ping |
— | The bot's current latency |
$time |
12h, 24h, nodate, notime |
Current time |
$uptime |
full, short, clock, seconds, custom like d:h:m:s |
Bot uptime |
$membercount |
all, user, bots |
Member counts |
$random |
a, b (inclusive range) |
A random number |
$id |
— | The author's user ID |
$avatar / $image |
— | The author's avatar URL |
$prefix |
— | The bot's command prefix |
$command |
— | The currently running command name |
Unknown variables are left untouched so typos never silently corrupt output.
Example:
!greet world
reply Hello $args # -> Hello world
reply First: $arg(0) # -> First: world
reply Count: $argcount # -> Count: 1
Functions
Every line of a script calls one function:
<function-name> <arguments...>
Core functions
| Function | Example | Description |
|---|---|---|
send |
send hello |
Sends a message to the current channel |
reply |
reply hi $user |
Replies to the invoking message |
log |
log command ran |
Prints a message to the console |
wait |
wait 3s |
Waits (s, m, h, d suffixes supported) |
react |
react ✅ |
Adds reactions to the invoking message |
delete |
delete |
Deletes the invoking message |
clear |
clear 10 |
Purges recent messages (needs Manage Messages) |
ping |
ping |
Replies with the bot's latency |
Embeds
The block form is best for rich, multi-line embeds:
embed
$title[Server Stats]
$desc[
Members: $membercount
Uptime: $uptime(full)
]
$footer[Requested by $user(display)]
$color[blurple]
$thumbnail[$bot(avatar)]
endembed
Supported keys: $title, $desc, $footer, $color (hex or named), $thumbnail,
$image, $author, $timestamp. Named colors include white, black, red,
green, blue, yellow, orange, purple, pink, grey, blurple, gold,
teal, cyan, and brown.
A single-line form using the embed function is also available, with keys
separated by | and fields via field: Name;Value;inline:
embed $embed<title: $user(display) | desc: Level 42 | color: green | field: Role;Admin;true>
Comments
Lines starting with //, #, or -- are ignored.
Mixing with discord.py
Because FlowBot subclasses discord.ext.commands.Bot, everything discord.py
offers keeps working: cogs, listeners, @bot.event, app commands, etc. When a
message matches the prefix but not a script command, it is passed through to
discord.py's command processor automatically.
import discord
from discord.ext import commands
from tflows import FlowBot
class Moderation(commands.Cog):
@commands.command()
async def purge(self, ctx, limit: int):
await ctx.channel.purge(limit=limit)
bot = FlowBot(prefix="!")
bot.command(name="hello", code="reply Hi $user(display)!")
bot.add_cog(Moderation(bot))
bot.run("YOUR_BOT_TOKEN")
Custom functions and variables
Functions are callables fn(ctx, args) and variables are callables
var(ctx, args) that return a string (or an awaitable). Register them on the
shared registry:
from tflows import FlowBot
from tflows.registry import registry
@registry.register("shrug")
async def shrug(ctx, args):
await ctx.channel.send("¯\\_(ツ)_/¯")
@registry.register_var("uptime_hours")
def uptime_hours(ctx, args):
return str(bot_uptime_seconds() // 3600)
bot = FlowBot(prefix="!")
Alternatively, create an isolated bot with its own registry:
FlowBot(prefix="!", registry=FunctionRegistry()).
FlowBot options
| Option | Default | Description |
|---|---|---|
prefix |
"!" |
Command prefix (a string or list of strings) |
help_command |
True |
Enable the built-in !help command |
log_errors |
True |
Log script errors instead of raising |
log_unknown_functions |
True |
Log unknown function names |
case_insensitive |
False |
Match command names case-insensitively |
members_intent |
False |
Enable the privileged members intent |
registry |
shared | Use an isolated FunctionRegistry |
Examples
See the examples/ directory:
basic_bot.py— minimal botvariables.py— variable showcaseembeds.py— block and single-line embedsautomation.py—wait,react,delete,clearmixing.py— scripts alongside discord.py cogs
Run any example after installing the package:
python examples/basic_bot.py
License
Apache License 2.0 — see the License file. Attribution to the original author
is required when redistributing or embedding the software; see NOTICE.
Metadata
Release files for tflows 0.9.dev1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tflows-0.9.dev1-py3-none-any.whl | Python 3 | none | any | Details |
Release files / tflows-0.9.dev1-py3-none-any.whl
| Download URL | tflows-0.9.dev1-py3-none-any.whl |
|---|---|
| Size | 26.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
960f68885d25ae8171cccd5baa497d7346559c744b00e0bdca75a2e6e3f448fd
|
|
BLAKE2b-256 checksum How to use checksums |
7a581217fec9324cde5662a383780055f59930de071776c97090e65fb9ac9461
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|