My personal Discord chat bot, written in Python 3
acid-bot
runs on Python 3.4+ (tested only on 3.5) and requires gTTS (Python TTS library), discord.py (Discord Bot API wrapper for Python), youtube-dl (to play songs in voice chat) and requests
. It also requires my postfix calculator implementation, which comes included (postfix.py
).
The bitmap generator requires nodejs
installed, and sandbox
installed via NPM.
The log_server.py
Flask server requires flask
to be installed. It is a separate program which gives users access to view the logs that the bot keeps.
On start-up, the Discord API token must be read from file secrettoken
in the same directory.
\help This helpful message.
\rr [subreddit] Get a random image from [subreddit]
\calc [query] Postfix calculator
\whoami User stats
\whois [username] ^ Ditto
\ping Pong.
\define [word] Lookup the definition of [word]
\ud [word] Lookup the urban definition of [word]
\50/50 You feeling lucky?
\flip Flip a coin
\callvote [message] Calls a vote and counts the tally after 7 seconds.
\tell @[name] [msg] Send [msg] to @[name] next time the bot sees them.
\remind @[name] [msg] in [time] Send a reminder to @[name] after [time].
\imitate [username] (length) (tts) Imitate [username] (Markov Chains!).
\markovusers List users' markov ratings (higher number means better \imitate)
\markovsave Save markov data to disk
\reactionadd [name] [url] Add a new link to the [name] collection
\reactions Lists all the reaction collections
\\[name] Random link from [name] collection (TWO backslashes)
\voice Connect/disconnect from your voice channel
\play [URL or title] Plays the audio at [URL] or searches YouTube for [Title].
Supports playing from 1039 websites (http://bit.ly/2d9yknp)
If already playing, adds query to the queue.
\skip Skip current song.
\queue View the current queue.
\queuepop [n] Removes item [n] from the queue.
\stop Stop playback. Discards queue.
\tts Say something with the tts
\chlang Changes the tts language (from https://pastebin.com/QxdGXShe)
\scores List math scores
\problems Start a short 10 question basic facts test
\ans [ans1] [ans2] ... Answer the basic facts test
\logs Generates a link to the logs.
Debug (Admin) Commands:
\markovload \markovclear [username] \markovfeed [username] [url]
\rename [newname] \setgame [playing] \reactiondel [name] [num]
Everything is functional. Improvements are needed on the math-quiz commands and the markov bot imitation fails to produce correct output.
- The bot logs all messages, edits, and deletions into an sqlite3 database
logs.db
. This is to counter censorship. - The bot saves all reactions to a
reactions.json
. This file can be edited directly, but the bot must be restarted to take the changes. - Word-pair data for the markov bot is stored in
markov.pickle
. This data is not saved unless the\markovsave
command is run. - Math-quiz score data is storred in
mathscores.json
. - The
[url]
supplied to\markovfeed
must point to a resource withContent-Type: text/plain
. - Permissions are defined per-command hardcoded into the bot. Change them to your liking. Use IDs given by
\whoami
and\whois
commands. - You do not need to type the whole username for
\whois
to work. The first few letters will be sufficient.
There really needs to be some documentation on how to fully run this program. I'm going to assume you've installed all the required dependencies.
The program requires a file called secrettoken
which contains the bot token generated by Discord. Put the token
(NOT the client secret) in this file. It will be read when discordbot.py
starts.
When you start discordbot.py
a bunch of files will be loaded and settings will be set. First, it opens an sqlite3 database. This database must already exist. Creation of this table is trivial, just run this line of SQL:
CREATE TABLE logs (time real, channel text, id integer, name text, displayname text, messageid integer, deleted integer, edited integer, message text)
And save the file as logs.db
. Put the file in the same directory as discordbot.py
. The time
field is the unix epoch of the event in UTC, id
is the ID of the author, and messageid
is the unique ID for that message.
Next, the Markov
manager is started. It will load a Python pickle file, markov.pickle
, containing the markov data (if it exists). To save markov data, you must run \markovsave
command. This will save all past conversation data to the disk. The bot will not do this automatically.
Next, the VoiceWrapper
is created. It has no settings. After that, MathRunner
is created. This will load users' math game scores from mathscores.json
(if it exists).
The reaction list is then loaded from reactions.json
. The tells (see \tell
) are loaded from tells.json
. The reminders are loaded from reminders.json
. The banned IDs are hardcoded. IDs in this list cannot execute commands. The settings for the logserver are loaded from logserver_config.json
. This file MUST exist, even if you do not intend to use the logserver.
The log server
log_server.py
contains a Python 3 Flask program which serves up the information contained in logs.db
. It must run in the same directory as the logs.db
file. To access the logs, a token must be generated by accessing /gentoken?password=password
where the password is stored in logserver_config.json
under token_generator_password
. Only the server and the bot can know this password.
When a successful GET request is made to /gentoken
the response body will be, in plaintext, a 12 character token, such as 43247b7fe87F
. Then by accessing /logs/?t=43247b7fe87F
a user will be granted access to view the logs. The token lasts 1 hour by default. This can be modified in logserver_config.json
in the field token_lifetime
.
The commands
\rr
and\rrtop
read JSON data from reddit.com.\calc
runs on the RPN calculator implementation:postfix.py
.\define
makes a GET request to dictionary.com and retrieves the first definition only. Seedictionarycom.py
.\ud
makes an API request to Urban Dictionary. Seedictionarycom.py
.\50/50
makes a request to reddit.com/r/fiftyfifty and reformats the title.\tell
will let you send messages to users. The messages will only be sent the next time they speak.\remind
will send messages after a fixed period, and regardless of whether or not the person is online.\voice
will join/leave the voice channel. It currently joins the first voice channel it finds.\tts
will send text to Google, and Google will return a wav file saved tovoice.wav
. The bot will use ffmpeg to play the wav file on voice chat. The bot hangs while it downloads from Google, so really long tts texts will cause the bot to time out from Discord.\logs
will generate a link and token for a user to access the logs that the bot keeps.\play
takes either a query or a URL. If it is a URL to a video or audio site, or is a video or audio stream, it will attempt to play, asyoutube-dl
is capable of such things, being magic and all. All songs are downloaded into directorydownloaded/
. This folder should probably exist before starting the bot. If a thing is currently playing, then the query (not the song) is added the the queue. When a new audio query starts downloading, the bot will start playing from it as soon as it can (instead of waiting for the download to finish).\vol
Takes a volume for a\play
stream as a value from 0 to 100. Adjusts the volume on the fly.\plop
Takes a javascript function of the formfunction(y,x) { ... }
which must always return a 3 element array. It is safely run on the server in a nodejs sandbox, and the output is used by PIL to populate an image with pixels.
\plop function(y,x){ x -=128; y-=128; x*=4; y*=4; if( Math.abs( Math.tan(Math.hypot(x,y)*Math.PI/180) - y/x) < 2 ) return [255,255,255]; else return [0,0,0]; }