A few project structure files (main.py, bot.py, init.py, help.py, and embed.py) are pulled from the Radia repository.
- Clone the repo with
git clone
- Rename .env.example to .env and input a discord bot token for Theta to connect to
- Install requirements with
pip install -r requirements.txt
, I recommend setting up a virtual environment first. - In ./theta/staticdata, create a file titled trusted.json; you can simply rename the trusted.json.example and input your own Discord user id.
- Using the prisma cli, run
prisma db push —schema ./data/schema.prisma
to create the database - If you have docker, run the docker-compose file with
docker compose up
, if you do not have Docker, please download it; it’s well worth the learning curve and much easier than it looks at first - Once the bot is up and running, go to a channel it has access to and run
!sync-all
(if development mode is on) or$sync-all
(if development mode is off) to sync slash commands to Discord - Enjoy!
ScrimBoard v1 was not built with scale in mind. It lacks persistence, is slow to update, and is not extensible should we offer future integrations with other projects. It also has a lot of overhead for possible performance optimization and UX improvements.
Expecting a magic bullet? We have a brick. It's not even close.
- Now interacts with message IDs directly, meaning it doesn’t need anywhere near as many perms
- Rest API allowing for web integration
- Persistent posts and data via SQLite to reduce the impact of outages (which should hopefully never happen due to Digital Ocean hosting it)
- Queue system with Redis to update posts in order at a high speed and integrate with APIs (imagine a co-worker coming over to your desk and leaving a pile of paperwork with no other context; that’s what we’re doing here to ScrimBoard)
Command: /setup
Options: “use-this-channel” OR “ create-new-channel ” OR “create-new-category”
Use this channel / New channel (Basic setup)
Sends global posts to that specific channel. By default, only an all-posts channel will be needed because you can now create scrim posts in any channel that allows bot commands, and a majority of servers do not have enough members/focus on scrims to warrant supporting in-house scrims everywhere.
New Category (Full setup)
Creates a category with three channels:
how-to-use (also used for sending announcements/updates)
in-house-scrims (in server scrims only)
global-Scrims (scrims from every server)
Command: /scrim-new
Options: “Team name”, “Skill level / LUTI Division”, “More Information”, “Screen OK?”, “Expiration (default ~3 days, TBD)”, “Destination (all-servers or this server)"
/scrim-new makes a post object, sets an expiration, and deletes it after that period using async.io
If ScrimBoard goes down for any reason, upon restart, it can check the DB and set the timeouts appropriately.
Accepting a post
Find a scrim you like? Just click accept.
Change your mind?
Hit cancel.
Want to delete it?
The author can hit cancel to look for another team (if one was already found), changing the cancel button to a delete button. The author can then hit delete.
Command: /scrim-view
Shows your current post to you as an ephemeral message, with the accepter’s info attached if relevant, alongside the options to cancel or delete your post.
Ok but like ehh how do the thing store the value? Objects? What am I, JSON Borne?
Instance Disk Storage (.csv, not accessible to anyone without local system access)
- Banned user IDs (split between two files)
- Partners
- Local
- Trusted user IDs
- Partners
- Developers
- Logs
- Post actions (CRUD + status + reason)
- Server state changes
ScrimBoard Core Data (Accessible w/ open APIs via Fast API (tbd), auth token required)
Servers = {
- ScrimBoard Category = [category_id : int]
- All-post channels = [global_scrims_id : int]
- In-server-post channels = [local_scrims_id: int]
- How-to-use channels = [how_to_use_id : int] }
SP-Author discord ID = {
Author = {
- Display name
- Discord UID
- PFP URL
- Origin Server }
Acceptor = {
#Is accepted is implied because Discord ID will be set to None if false
#and a normal integer ID if true
- Display name
- Discord ID
- PFP URL
- Origin Server }
StaticScrimInfo = {
- Team name
- Skill level / Division
- Time / Map List
- Screen OK?
- Expiration period (2-120 HOURS) = INT (DEFAULT 72 HOURS)
- Post Message IDs = [] }
BTN-IDs = [button id, button id2, button id3, ...]
Buttons! 🎛️
- Buttons on embeds will have IDs equal to the poster’s UID snowflake followed by -accept, -cancel, or -delete. For example, user ID 4559 would have an accept button ID of 4559-accept
Still a work in progress, routes and strcutures are NOT final!
- ✒️GetAllPosts (GET): /scrims/ => 200 / 400 /401 (OK, Bad Request, Unauthorized)
- authtoken
- ✒️GetPost (GET): /scrims/author_user_id => 200 / 204 / 400 /401 (OK, No Content, Bad Request, Unauthorized)
- authtoken
- ✒️CreatePost (POST): /scrims/create/ => 201 / 208 / 400 / 401 (Created, Already Reported (duplicate), Bad Request, Unauthorized)
- scrim = {} (see above scrim model)
- authtoken
setupNewServer{minimal|local|how-to|complete}()
- Check if the server is already setup using “not in” to be performant
- pin the tail on the donkey- I mean upsert. We use upsert. We throw it on the end of the pile if it doesn’t exist and update it if it does.
updateDiscordPost()
- If async updates list full or matching POST ID in the system
Then
- Add to updates list
- Async.io update 5+ servers at once (switch case for CRUD, eg discordPostCreate, discordPostUpdate, discordPostDelete, etc)
- Remove from updates list returns a list of message IDs that are attached to the post object (or success for delete)
**/**scrim = new post
postCreate()
- Check if banned
- Check if post
- Create DB object (returns discord embed data + snowflake)
- discordPostUpdate()
postAccept()
- Check if banned
- Get post by button ID
- Update post DB object
- Contact both parties
- Queue post update with updateDiscordPost()
postCancel(), delete setup, and postDelete() perform inverse actions in the same order, delete setup (now known as unlink setup) only removes channels from the database and does NOT delete the channels on Discord