A minimalist discord bot API
from miniscord import Bot
import discord
async def hello(client: discord.client, message: discord.Message, *args: str):
await message.channel.send("Hello!")
bot = Bot(
"test-app", # name
"0.1-alpha", # version
alias="|" # respond to '|command' messages
)
bot.register_command(
"hello", # command text (regex)
hello, # command function
"hello: says 'Hello!'", # short help
"```\n" # long help
"* |help\n"
"\tSays 'Hello!'.\n"
"```"
)
bot.start() # this bot respond to "|help", "|info" and "|hello"
⚠ Disclaimer: I intend to use this project personally, I'm open to ideas but I don't care if it doesn't work for you. Same for the name, feel free to use it, I'm not registering it on PyPI
- Easy command registration
- Automatic help message
- Arguments splitting
- Message watcher registration
- Message handling configuration
- Static and dynamic custom game statuses
1. Install package
pip install git+git://github.com/Klemek/miniscord.git
2. Make a .env file as following
#.env
DISCORD_TOKEN=<bot token from discordapp.com/developers>
bot = Bot(
"test-app", # name
"0.1-alpha", # version
alias="|" # respond to '|command' messages
)
# configure bot and register commands
bot.start() # blocking function
token_env_var
(default:"DISCORD_TOKEN"
)- Which var to read in the
.env
file.
- Which var to read in the
remove_mentions
(default:False
)- Remove any mention in the message / arguments.
any_mention
(default:False
)- If the bot respond to a mention in the middle of messages.
log_calls
(default:False
)- Log any calls to the Python logging.
guild_logs_file
(default:"guilds.log"
)- Log guilds join/leave on a file.
enforce_write_permission
(default:True
)- If the bot can't respond on a channel it was called, it sends a DM to the caller.
lower_command_names
(default:True
)- Use lowercase on command names (if false, commands are case-sensitive).
game_change_delay
(default:10
)- Change the game status every n seconds.
error_restart_delay
(default:2
)- On crash, restart after n seconds.
answer
(default:True
)- Use the answer capability on
help
andinfo
functions
- Use the answer capability on
answer_mention
(default:True
)- Mention author in the answer
Register a custom function to be called on a certain keyword.
Note : You can override the "help" and "info" commands by your own.
async def hello(client: discord.client, message: discord.Message, *args: str):
'''
Parameters
----------
client : discord.client
Discord object used by the bot to interact with Discord API
(see Discord documentation)
message : discord.Message
Discord object describing the message received via the Discord API
(see Discord documentation)
*args : str
The message viewed as string arguments like a CLI
(argument 0 will always be the command itself)
'''
if len(args) > 1:
await message.channel.send(f"Hello {args[1]}!")
else :
await message.channel.send("Hello stranger!")
bot.register_command(
"hello", # command text (regex)
hello, # command function
"hello: says 'Hello!'", # short help
f"```\n" # long help
f"* |help\n"
f"\tSays 'Hello!'.\n"
f"```"
)
Register a custom function to be called when the bot is mentioned but no command was found.
async def mention(client: discord.client, message: discord.Message, *args: str):
"""See 'Registering commands' for arguments description"""
await message.channel.send(f"Did you mention me {message.author.mention}?")
bot.register_fallback(mention) # the bot was mentioned or the alias was used
Register a custom function to be called on every messages except this bot own messages.
async def message(client: discord.client, message: discord.Message):
"""See 'Registering commands' for arguments description"""
if "catapult" on message.content:
await message.channel.send(f"No profanity on this server")
bot.register_watcher(message) # any message was sent (except this bot messages)
Register a discord API event
The function must be exactly named after the event
async def on_ready() -> bool:
print("on_ready")
return True # if False is returned, prevent miniscord's handling of the event
bot.register_event(on_ready)
On starting, the bot will cycle through 2-3 "game status" (under its name as "playing xxx") :
v<version>
: current version registered in code<n> guilds
: number of connected guilds<alias>help
: command for help (if an alias is registered)
It will change its status every game_change_delay
(default as 10 seconds).
You can add custom game statuses like this :
bot.games += ["My custom message"] # static message
value = 0
bot.games += [lambda: f"value:{value}"] # dynamic message, computed at change
You can also remove the pre-existing statuses :
bot.games = ["My custom message"]
Along with the bot are exposed several utility functions.
Delete the given Discord message from the channel. Return True
if the message was deleted successfully.
from miniscord import delete_message
import asyncio
async def message(client: discord.client, message: discord.Message):
if "catapult" in message.content:
sent_msg = await message.channel.send(f"{message.author.mention} No profanity on this server")
if await delete_message(message):
await asyncio.sleep(5)
await delete_message(sent_msg)
Helps identify where the discussion is happening (Might be used as a key in a state dictionary)
An user on multiple channels will have a unique id on each.
from miniscord import channel_id, sender_id
from collections import defaultdict
channels = defaultdict(lambda:0)
senders = defaultdict(lambda:0)
async def mention(client: discord.client, message: discord.Message, *args: str):
channels[channel_id(message)] += 1
senders[sender_id(message)] += 1
await message.channel.send(
f"{message.author.mention} mentioned me {senders[sender_id(message)]} times on this channel\n"
f"{channels[channel_id(message)]} mentions on this channel so far"
)
import logging
import discord
import asyncio
from collections import defaultdict
from miniscord import Bot, delete_message, channel_id, sender_id
channels = defaultdict(lambda:0)
senders = defaultdict(lambda:0)
logging.basicConfig(format="[%(asctime)s][%(levelname)s][%(module)s] %(message)s", level=logging.INFO)
async def hello(client: discord.client, message: discord.Message, *args: str):
'''
Parameters
----------
client : discord.client
Discord object used by the bot to interact with Discord API
(see Discord documentation)
message : discord.Message
Discord object describing the message received via the Discord API
(see Discord documentation)
*args : str
The message viewed as string arguments like a CLI
(argument 0 will always be the command itself)
'''
if len(args) > 1:
await message.channel.send(f"Hello {args[1]}!")
else:
await message.channel.send("Hello stranger!")
async def mention(client: discord.client, message: discord.Message, *args: str):
channels[channel_id(message)] += 1
senders[sender_id(message)] += 1
await message.channel.send(
f"{message.author.mention} mentioned me {senders[sender_id(message)]} times on this channel\n"
f"{channels[channel_id(message)]} mentions on this channel so far"
)
async def message(client: discord.client, message: discord.Message):
if "catapult" in message.content:
sent_msg = await message.channel.send(f"{message.author.mention} No profanity on this server")
if await delete_message(message): # False if "manage messages" permission not allowed
await asyncio.sleep(5)
await delete_message(sent_msg)
bot = Bot(
"test-app", # name
"0.1-alpha", # version
alias="|" # respond to '|command' messages
)
bot.register_command(
"hello", # command text (regex)
hello, # command function
"hello: says 'Hello!'", # short help
"```\n" # long help
"* |help\n"
"\tSays 'Hello!'.\n"
"```"
)
bot.register_fallback(mention) # the bot was mentioned or the alias was used
bot.register_watcher(message) # any message was sent (except this bot messages)
bot.games = [lambda:f"{sum(senders.values())} mentions"] # custom dynamic game status
bot.game_change_delay = 1 # refresh game status every second
bot.start() # this bot respond to "|help", "|info" and "|hello"
- v0.1.0 : Discord v2 API with intents
- v0.0.3 : custom events handling
- v0.0.2 : new answer capability
- v0.0.1 : initial version
- Expose more events
- Write more tests
- Add comments to code
- Separate branches
- Working CI
- Fix bugs