templates/discord-bot: init
This commit is contained in:
parent
7de0f37a07
commit
b29f007e69
8 changed files with 313 additions and 0 deletions
2
templates/discord-bot/.envrc
Normal file
2
templates/discord-bot/.envrc
Normal file
|
@ -0,0 +1,2 @@
|
|||
watch_file "flake.nix" "pyproject.toml"
|
||||
use flake
|
14
templates/discord-bot/.gitignore
vendored
Normal file
14
templates/discord-bot/.gitignore
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Secrets
|
||||
.env
|
||||
|
||||
# Nix
|
||||
.direnv/
|
||||
result
|
||||
|
||||
# Python
|
||||
.ruff_cache
|
||||
.ropeproject
|
||||
|
||||
# Runtime
|
||||
rename.sqlite3
|
||||
rename.sqlite3-journal
|
66
templates/discord-bot/flake.nix
Normal file
66
templates/discord-bot/flake.nix
Normal file
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
description = "Template for Python-based Discord bots";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:Infinidoge/nixpkgs/feat/disnake";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
devshell.url = "github:numtide/devshell";
|
||||
pyproject-nix.url = "github:nix-community/pyproject.nix";
|
||||
|
||||
flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||
devshell.inputs.nixpkgs.follows = "nixpkgs";
|
||||
pyproject-nix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
systems = [ "x86_64-linux" ];
|
||||
|
||||
imports = with inputs; [
|
||||
devshell.flakeModule
|
||||
];
|
||||
|
||||
perSystem = { config, pkgs, ... }:
|
||||
let
|
||||
project = inputs.pyproject-nix.lib.project.loadPyproject {
|
||||
projectRoot = ./.;
|
||||
};
|
||||
|
||||
python = pkgs.python3;
|
||||
|
||||
in
|
||||
{
|
||||
packages.default = (python.pkgs.buildPythonPackage (
|
||||
project.renderers.buildPythonPackage { inherit python; }
|
||||
)).overrideAttrs { allowSubstitutes = false; preferLocalBuild = true; };
|
||||
|
||||
devshells.default =
|
||||
let
|
||||
env = python.withPackages (
|
||||
project.renderers.withPackages {
|
||||
inherit python;
|
||||
extraPackages = p: with p; [
|
||||
python-lsp-server
|
||||
python-lsp-ruff
|
||||
pylsp-rope
|
||||
isort
|
||||
black
|
||||
];
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
devshell = {
|
||||
name = "rename";
|
||||
motd = "";
|
||||
|
||||
packages = [
|
||||
env
|
||||
];
|
||||
};
|
||||
env = [
|
||||
{ name = "PYTHONPATH"; prefix = "${env}/${env.sitePackages}"; }
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
21
templates/discord-bot/pyproject.toml
Normal file
21
templates/discord-bot/pyproject.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[project]
|
||||
name = "rename"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"disnake",
|
||||
"python-dotenv",
|
||||
"aiosqlite"
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
rename = "rename:run"
|
||||
|
||||
[tool.setuptools.packages]
|
||||
find = {}
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
1
templates/discord-bot/rename/__init__.py
Normal file
1
templates/discord-bot/rename/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from .main import run
|
25
templates/discord-bot/rename/db.py
Normal file
25
templates/discord-bot/rename/db.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
import aiosqlite
|
||||
|
||||
|
||||
async def setup_db(db_file):
|
||||
db = await aiosqlite.connect(db_file)
|
||||
|
||||
await db.executescript("""
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS guilds (
|
||||
guild_id INTEGER NOT NULL PRIMARY KEY,
|
||||
prefix TEXT NOT NULL DEFAULT ">"
|
||||
)
|
||||
WITHOUT ROWID;
|
||||
|
||||
# DB Setup here
|
||||
|
||||
COMMIT;
|
||||
|
||||
PRAGMA optimize(0x10002);
|
||||
PRAGMA main.synchronous = NORMAL;
|
||||
""")
|
||||
|
||||
return db
|
||||
|
154
templates/discord-bot/rename/main.py
Normal file
154
templates/discord-bot/rename/main.py
Normal file
|
@ -0,0 +1,154 @@
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from disnake import Guild, Intents, Message
|
||||
from disnake.ext import commands
|
||||
from disnake.ext.commands import Bot
|
||||
from dotenv import find_dotenv, load_dotenv
|
||||
|
||||
from .db import setup_db
|
||||
from .notifications import Notifications
|
||||
from .settings import Settings
|
||||
|
||||
# Logger setup
|
||||
logger_disnake = logging.getLogger("disnake")
|
||||
logger_disnake.setLevel(logging.WARNING)
|
||||
|
||||
log = logging.getLogger("rename")
|
||||
log.setLevel(logging.DEBUG)
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s")
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
handler.setFormatter(formatter)
|
||||
logger_disnake.addHandler(handler)
|
||||
log.addHandler(handler)
|
||||
|
||||
|
||||
if load_dotenv(find_dotenv(usecwd=True)):
|
||||
log.debug("Loaded .env")
|
||||
else:
|
||||
log.debug("Didn't find .env")
|
||||
|
||||
TOKEN = os.getenv("TOKEN")
|
||||
DB_FILE = os.getenv("DB_FILE") or "rename.sqlite3"
|
||||
DEFAULT_PREFIX = os.getenv("DEFAULT_PREFIX") or ">>>"
|
||||
|
||||
|
||||
async def get_prefix(the_bot, message: Message):
|
||||
if not message.guild:
|
||||
return commands.when_mentioned_or(DEFAULT_PREFIX)(the_bot, message)
|
||||
|
||||
gp = await the_bot.get_guild_prefix(message.guild)
|
||||
|
||||
if gp == "":
|
||||
return commands.when_mentioned(the_bot, message)
|
||||
|
||||
return commands.when_mentioned_or(gp)(the_bot, message)
|
||||
|
||||
|
||||
class Rename(Bot):
|
||||
def __init__(self, prefix, description=None, **options):
|
||||
super().__init__(
|
||||
prefix,
|
||||
description=description,
|
||||
command_sync_flags=options.get("sync_flags"),
|
||||
allowed_mentions=options.get("allowed_mentions"),
|
||||
intents=options.get("intents"),
|
||||
)
|
||||
|
||||
self.db = self.loop.run_until_complete(setup_db(DB_FILE))
|
||||
self.prefixes = {}
|
||||
|
||||
async def get_guild_prefix(self, guild: Guild):
|
||||
if guild.id in self.prefixes:
|
||||
return self.prefixes[guild.id]
|
||||
|
||||
cur = await self.db.execute(
|
||||
"SELECT prefix FROM guilds WHERE guild_id=? LIMIT 1",
|
||||
[guild.id],
|
||||
)
|
||||
prefix = await cur.fetchone() or [DEFAULT_PREFIX]
|
||||
prefix = prefix[0]
|
||||
|
||||
self.prefixes[guild.id] = prefix
|
||||
return prefix
|
||||
|
||||
async def set_guild_prefix(self, guild: Guild, prefix):
|
||||
await self.db.execute(
|
||||
"REPLACE INTO guilds VALUES(?, ?)",
|
||||
(guild.id, prefix),
|
||||
)
|
||||
self.prefixes[guild.id] = prefix
|
||||
|
||||
async def close(self):
|
||||
await super().close()
|
||||
await self.db.close()
|
||||
|
||||
|
||||
bot = Rename(
|
||||
prefix=get_prefix,
|
||||
description="@description@",
|
||||
intents=Intents(
|
||||
guilds=True,
|
||||
messages=True,
|
||||
message_content=True,
|
||||
),
|
||||
sync_flags=commands.CommandSyncFlags(
|
||||
sync_commands=False,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@bot.event
|
||||
async def on_ready():
|
||||
log.info("Logged in as:")
|
||||
log.info(bot.user)
|
||||
log.info(bot.user.id)
|
||||
log.info("-------------")
|
||||
|
||||
|
||||
@bot.event
|
||||
async def on_command_error(ctx, error):
|
||||
if isinstance(error, commands.CommandNotFound):
|
||||
return
|
||||
|
||||
if isinstance(error, commands.NoPrivateMessage):
|
||||
await ctx.send(error)
|
||||
return
|
||||
|
||||
log.exception(error)
|
||||
await ctx.send(error)
|
||||
|
||||
|
||||
@bot.command()
|
||||
@commands.is_owner()
|
||||
async def echo(ctx, arg):
|
||||
await ctx.send(arg)
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def ping(ctx):
|
||||
await ctx.send("Pong")
|
||||
|
||||
|
||||
@bot.command()
|
||||
@commands.guild_only()
|
||||
@commands.is_owner()
|
||||
async def prefix(ctx, prefix=None):
|
||||
if prefix is None:
|
||||
prefix = await ctx.bot.get_guild_prefix(ctx.guild)
|
||||
if prefix == "":
|
||||
await ctx.send(f"{ctx.guild.name} prefix is mentioning me only")
|
||||
else:
|
||||
await ctx.send(f"{ctx.guild.name} prefix is `{prefix}`")
|
||||
else:
|
||||
await ctx.bot.set_guild_prefix(ctx.guild, prefix)
|
||||
if prefix == "":
|
||||
await ctx.send(f"Set {ctx.guild.name} prefix to mentioning me only")
|
||||
else:
|
||||
await ctx.send(f"Set {ctx.guild.name} prefix to `{prefix}`")
|
||||
|
||||
|
||||
def run():
|
||||
bot.run(TOKEN)
|
30
templates/discord-bot/setup
Executable file
30
templates/discord-bot/setup
Executable file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env bash
|
||||
# vim: set ft=bash:
|
||||
|
||||
set -e
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "Not enough arguments"
|
||||
echo 'usage: ./setup basename ClassName "description here"'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
nameBase=$1
|
||||
nameClass=$2
|
||||
description=$3
|
||||
files=(
|
||||
"flake.nix"
|
||||
".gitignore"
|
||||
"pyproject.toml"
|
||||
"rename/main.py"
|
||||
)
|
||||
|
||||
for file in ${files[@]}; do
|
||||
sed -i "
|
||||
s/rename/$nameBase/g;
|
||||
s/Rename/$nameClass/g;
|
||||
s/@description@/$description/g;
|
||||
" $file
|
||||
done
|
||||
|
||||
mv rename $nameBase
|
Loading…
Add table
Add a link
Reference in a new issue