The bot that runs the department

Nearly everything SAPD does day to day passes through one bot. It keeps the roster level with the CIT forum, works out who is due a promotion, posts reports and requests to the forum for you, watches the map for high wanted criminals and calls for backup, moderates the server, and writes the log lines moderators paste onto the forum.

You can reach it from three places, and they are all the same thing underneath. Type a command in Discord. Type the same command in game chat. Or fill in a form on this website. Whichever you use, it lands in the same place.

Discord commands and forms Game chat the same commands This website reports and requests One program, one database The website and the bot are the same thing running CIT forum read for the roster, written to for reports

Every arrow points both ways. That is the part worth understanding, and the next section is about what it means in practice.

Do it anywhere, see it everywhere

The site and the bot share one database, so neither has to tell the other anything. Something done on the website shows up in Discord. Something done in Discord shows up on the website. There is no delay and no syncing step, because there is nothing to sync between.

You file a patrol report on the site
  1. You fill in the formHost, date, everyone who came, marks and comments.
  2. It is saved hereBefore anything is sent anywhere else.
  3. Posted to the forumWritten out as BBCode and posted for you.
  4. Logged in DiscordOne entry with a link straight to the post.
  5. Counted on profilesEveryone listed has it added to their record.
You verify in Discord
  1. You run the commandAnd give your CIT account name.
  2. The link is savedYour Discord account is tied to your member record.
  3. Your profile updatesThe site now knows the two are the same person.
  4. Your face appearsYour Discord picture shows on the roster and profile.

It works the same way for the rest of it.

What you doWhereWhat happens elsewhere
File a training reportWebsitePosted to the forum, logged in Discord, added to every participant's record
Request a vacationDiscordPosted to the forum, stored here, shown on your profile
Apply to joinEitherGoes to the voting channel, and into the review queue on the site
Approve an applicationDiscordRecorded here, the applicant is messaged, the site shows the decision
Request a promotionEitherLeadership get the buttons in Discord, the request is on the dashboard here
Ask for a unit numberWebsitePosted to the forum, and the number is held so nobody else takes it
Get promoted on the forumIn gameThe roster here moves you, and your promotion clock starts again
Lock a staff accountDiscordThat login stops working on the site immediately

Every command

The bot answers on a plain ! prefix. Nothing is hidden behind a slash menu, which is what lets the same commands work from game chat.

Everything below works in Discord, and almost all of it works from game chat as well. Only two kinds do not. role means it needs a rank, and game chat carries no ranks. you means the bot has to know which account is yours, and a line of game chat does not say. Everything unmarked works in both.

Music
!play <name or url>Queue a track or a whole playlist. YouTube, SoundCloud, Spotify, Twitch and direct links.
!stopStop and clear the queue.
!skip !nextSkip the track playing now.
!pause !resumeHold playback, then carry on.
!np !nowplayingWhat is playing, and how far through it is.
!volume <0-100>Set the volume.
!seek <time>Jump to a point in the track, such as 1:30.
!lyricsLyrics for whatever is playing.
!join !disconnectBring the bot into voice, or send it away.
!queue !qWhat is lined up next.
!shuffleShuffle everything still to play.
!loop [off/song/queue]Repeat one track or the whole queue.
!remove <#>Take one track out.
!clearEmpty the queue but keep playing.
!jump <#>Skip straight to a position in the queue.
!move <from> <to>Reorder the queue.
!autoplayKeep playing related tracks when the queue runs out.
!musichelpThe full music list.
Field and backup
!backup [message]Call for backup. The criminal count, the highest wanted level and how many cops are online are filled in for you.
!wantedThe live wanted list. Pings nobody, just answers you.
!fieldThe field command list.
!training [message]Tell everyone a training is about to start.
!patrol [message]Tell everyone a patrol is starting.
!checktopsWhere SAPD is sitting on the CIT live boards right now.
Members
!whois <name or @user>Full profile for anyone verified.
!onlinesapdWho is online. Also does status, members, stats, find, health and logs.
!sapdonlineSearch the roster.
!verifyyouTie your Discord account to your CIT account.
!unverifyyouBreak that link again.
!member link unlink list statsroleTie an account to a profile by hand, or check who is linked.
!updateavatarroleRefresh cached Discord pictures, one member or everyone.
!avatarstatsroleHow many members have a picture cached.
Promotions
!checkpromotionyouYour own progress. Days in rank, patrols, trainings, and what is still missing.
!checkpromotion @userroleThe same for somebody else.
!requestpromoyouPut the promotion request button in a channel.
!checkpromotionsroleRun the eligibility check now. Only posts people not announced yet.
!pingeligiblerolePost everyone eligible again, including those already named.
!promotionstatsrolePromotion figures across the department.
Moderation
!mute @user <minutes>roleMute a member. Rank is checked first, so nobody can mute an equal or a senior.
!unmute @userroleLift a mute early.
!mutedEveryone currently muted.
!delete <1-100>roleClear messages in a channel.
!blacklist !ipbanroleBan an address from the website. Add, remove, list, or see who is temporarily blocked.
!admin lock unlock list statusroleStaff website logins, run from Discord.
Information and AI
!sapdWhat the department is, its ranks, and how to join.
!rulesThe full rules.
!linksThe links people ask for most.
!help !commandsThe command list, trimmed to what your roles allow.
!ask !askai <question>Ask the AI something. It follows a conversation for an hour.
!image <description>Make a picture. Works in any channel.
!mode sarcastic normalChange how it answers you.
Server
!roleyouOpen the role centre. Some roles apply straight away, the rest go for approval.
!setbirthdayyouSave your birthday.
!listbirthdays !nextbirthdayThis month's birthdays, and whose is next.
!deletebirthday !updatebirthdayyouChange or remove it.
!reaction list helpEvery keyword the bot reacts to.
!reaction add removeroleTeach it a keyword, a reply and the emoji to use.
!event !createeventyouMake an event with a countdown page on this site.
!application !leaderapplicationyouPost the joining form, or file one for somebody else.
!forumbackuproleBack the forum posts up now instead of waiting for the hour.

Using it without leaving the game

Game chat is mirrored into Discord already. The bot reads that mirror, and when a line turns out to be a command it runs it and sends the answer back the same way. You never alt tab.

  1. You type in game!backup, or !play, or anything else.
  2. The line is mirroredGame chat appears in Discord as it is typed.
  3. The bot spots a commandIt reads your name and what you asked for.
  4. It runs as normalThe same code that runs it in Discord.
  5. You get the answerBack in game chat, in plain text.

Answers are cleaned up first

Bold, emoji and channel links all render as junk in game chat, so they are stripped out and the reply is folded onto one line before it goes back.

Names get the same treatment in the other direction. Some relay bots wrap your name in bold, which would otherwise end up printed in the embed.

Tagging people from in game

Writing @Name in game pings that person's Discord. It matches on roster name or CIT account name, and falls back to roles, so @SAPD Officer pings the role.

Each person is pinged at most once every ten seconds, and no more than three per line, so it cannot be turned into spam.

Music is the one that needed thinking about. An in game name does not tell the bot which Discord account you are, so it cannot look at which voice channel you are in. Instead it stays in the channel it is already in, and if it is not in one it joins the busiest channel with people in it.

Backup calls, and criminals nobody spotted

The bot watches a live feed of wanted players every minute. That is what fills in !backup for you, and it is also watched on its own.

When you call for backup

You type !backup with an optional message. The call goes to the field channel wherever you typed it, and carries the whole picture without you having to describe it.

  • Who is asking, and what they said
  • How bad it is, from the highest wanted level in game
  • Every wanted player, worst first
  • How many criminals, and how many cops are online
  • How fresh the information is

When nobody calls

The moment somebody hits five or six stars, the bot raises it by itself and pings the backup role. Nobody has to be watching for it.

You get told once per criminal. Going from five stars to six does not ping again, and somebody who leaves and comes straight back will not either. Alerts clear themselves after fifteen minutes, because old information about where a criminal was is worse than none.

One small thing that matters more than it sounds. The line above every alert says the whole situation in plain words, with no formatting at all: who is asking, how many criminals, how many cops, and the names of the worst ones. On a phone that line is the entire notification. It is what decides whether somebody logs in.

The log lines moderators paste

Every group action taken in game gets announced in chat: promotions, demotions, kicks, warnings, rewards, joins and leaves. All of it then has to be written onto the forum log by hand, worded the right way, with the right date.

The bot does that writing. It reads each announcement, tidies the names by stripping rank prefixes, group tags and unit numbers, and posts it to the moderator channel as a clean entry with the mod role pinged.

  1. Something happens in gameSomeone is promoted, warned, kicked or rewarded.
  2. It is announced in chatAs a plain line of text, names and tags and all.
  3. The bot reads itPulls out who, what, why, and by whom.
  4. Moderators get itA tidy entry, with the forum line already written out.

The last part is the useful part. Every one of those entries ends with a ready made line for the forum log, already worded and already dated. It gets copied across as it is.

EventWhat the entry carries
PromotionWho was promoted, from which rank to which, who signed it off, the account, the reason and the date
DemotionThe same, the other way
KickWho was removed, the rank they held, who did it and why
WarningWho was warned, by whom, the reason, and the percentage added
RewardWho was rewarded, by whom, the reason and the percentage
JoinWho joined, and the date
LeaveWho left, and the date
Alongside that

Applications

Submitted, accepted or denied in game, it reaches the notification channel with the badge holders who vote already pinged.

Rank aware mutes

You cannot mute somebody at your own level or above it. The Chief and Head Leader sit outside the check.

Server log

Messages, joins, leaves, bans, timeouts, role and channel changes, voice moves. Each one names who did it and shows what changed, with buttons to jump straight there.

Login greetings

Every SAPD login is announced. The bot welcomes members back by name and clears the greeting a minute later so the channel stays readable.

Website threats

Suspicious traffic to the site raises an alert in Discord with ban and unban buttons on it, so it is handled where it is seen.

Unverified members

Somebody posting without a linked account gets pointed at verification once, with a wait before it happens again.

Keeping the roster true

The forum is the authority on who is in SAPD and at what rank. Nothing here changes that. Every ten minutes the bot re-reads it and brings this site back in line.

  1. Read the changelogEvery promotion, kick, warning, vacation and name change since last time.
  2. Apply each oneRanks move, statuses change, people who left are marked.
  3. Read the rosterRank by rank, plus each member's account name and playtime.
  4. The site followsRoster, profiles and promotion clocks all read from it.

The changelog is read before the roster, and the order is not arbitrary. If somebody changed their name, that has to be picked up first. Otherwise the roster step looks for a member it has known for two years, fails to find them under the new name, and adds them a second time.

Two lighter jobs run alongside. Every five minutes the bot checks who is in game and matches them to the roster. Every five minutes it also reads the CIT live boards, and says something in Discord when SAPD moves up or down against the other law groups.

Nobody pastes BBCode any more

Training reports, patrol reports, vacations, promotions, tests, badges and unit numbers all end up as a post on the CIT forum. You fill in a form and the bot writes the post.

  1. Your form is savedFirst, before anything is sent out. It cannot be lost after this point.
  2. The post is writtenNames become links to profiles here, the report number links back to the full report.
  3. It goes to the forumPosted under the department account, in the right topic.
  4. You get the linkStraight to your post, not to page forty of a thread.

If the forum is down, you are told so plainly and given a Retry button, and only then does the BBCode appear so you can paste it yourself. When it worked there is nothing to copy, so you just get the link.

How promotions are worked out

Every rank up to Inspector has a minimum time to serve and a set of patrols and trainings to do. The bot works out where you are against them and !checkpromotion tells you what is left.

0 30 60 Days you must serve before the next rank 7 14 14 14 30 40 50 60 Trial Recruit Constable Officer Station Ofc Sergeant Staff Sgt Inspector Scoring stops here Chief Inspector and above are given out by leadership, not earned by a count.

Chief Inspector and above is staff and leadership, and those seats are the Chief's to give. Working out a percentage for them only ever produced a number nobody was going to act on, and left a Superintendent queued behind a Constable.

RankPromotes toMin daysWhat you need to have done
TrialRecruit72 patrols
RecruitConstable142 patrols, 1 training
ConstableOfficer143 patrols, 1 training
OfficerStation Officer145 patrols, 3 trainings
Station OfficerSergeant3010 patrols, 1 training hosted, 1 patrol hosted
SergeantStaff Sergeant4012 patrols, 2 trainings hosted, 2 patrols hosted
Staff SergeantInspector505 trainings hosted, 5 patrols hosted
InspectorChief Inspector608 trainings hosted, 8 patrols hosted

Time served and activity are not the whole of it. The marks you were given in the reports you appear in count too, and they count for more the higher you go. At Trial they barely register. By Inspector they are about a third of the picture.

Getting from eligible to promoted
  1. The bot names youOnce a day it posts whoever has newly qualified. Nobody is named twice for the same promotion.
  2. A request goes inYou press the button, or staff file it for you.
  3. Leadership decideApprove, deny or hold, each with a reason that gets kept.
  4. The forum makes it realIt is posted, and when it reaches the changelog your rank moves here too.

Recruitment

Joining works the same whether you start on the website or in Discord. It used to be a second bot with its own database, which meant two records of the same application that slowly stopped agreeing. Now there is one.

  1. Three short formsOne at a time, so there is no wall of questions to lose.
  2. It reaches the channelWith Approve and Deny for the members who hold forum rights.
  3. A decision with a reasonWhich is stored, and sent to you.
  4. Nothing is overwrittenThe record keeps every step it went through, not just the ending.

The rest of what it runs

Music

A full player with buttons, a queue, loop, shuffle and seek. It reads several sources and switches to another when one refuses to play.

The AI channel

!ask follows a conversation for an hour so you can ask follow ups. !image draws things and works anywhere. !mode switches between a straight answer and a sarcastic one.

Keyword reactions

Staff teach the bot a word, a reply and the emoji to react with. Only one fires per message, and several channels are left out.

Role centre

One panel. Some roles you take yourself, the rest go to leadership. Both the request and the decision are logged with everyone named.

Birthdays

Saved once and announced on the day. The month's list and whose is next are a command away.

Events

An event made through the bot gets a countdown page on this site and a post in Discord linking to it.

Forum backup

Every hour the department's forum posts are copied and kept, with a fuller copy overnight. If a post is ever wiped, what is needed to rebuild it is already saved.

Programming lessons

A lesson series with tasks, homework and a leaderboard, posted into its own channel on a timer.

Pictures on the roster

Discord profile pictures are kept against member records and refreshed on a schedule, so the roster shows faces without asking Discord every time somebody opens it.

What it does without being asked

How oftenWhat happens
Every minuteChecks for five and six star criminals, and calls the backup role if there are any
Every 5 minutesReads who is in game and matches them to the roster
Every 5 minutesReads the CIT live boards, and says something when SAPD moves
Every 5 minutesWorks out everyone's time in rank again
Every 10 minutesRe-reads the forum changelog and roster
Every 30 minutesRecounts patrols and trainings per member
Every hourBacks up the department's forum posts
Every day at 18:00Posts whoever has newly qualified for promotion
Every night at 02:00Locks staff website accounts nobody has used
Every night at 03:30Takes the full forum backup