Files
Bubberstation/code/controllers/subsystem/discord.dm
AffectedArc07 c4e75bc40b [READY] SSdiscord and Round Notifications (#44231)
* Notify System

* V2

* Adds a hint

* Stoned fixes round 1

* Use grammar wells I can

* This didnt work

* I wish you could test on TGS without committing

* Jordie fixes round 1

* oops

* This took way longer than it should have taken

* Adds in endnotify for serverops

* Spacing
2019-06-30 00:43:25 +10:00

116 lines
5.1 KiB
Plaintext

/*
NOTES:
There is a DB table to track ckeys and associated discord IDs.
This system REQUIRES TGS, and will auto-disable if TGS is not present.
The SS uses fire() instead of just pure shutdown, so people can be notified if it comes back after a crash, where the SS wasnt properly shutdown
It only writes to the disk every 5 minutes, and it wont write to disk if the file is the same as it was the last time it was written. This is to save on disk writes
The system is kept per-server (EG: Terry will not notify people who pressed notify on Sybil), but the accounts are between servers so you dont have to relink on each server.
##################
# HOW THIS WORKS #
##################
ROUNDSTART:
1] The file is loaded and the discord IDs are extracted
2] A ping is sent to the discord with the IDs of people who wished to be notified
3] The file is emptied
MIDROUND:
1] Someone usees the notify verb, it adds their discord ID to the list.
2] On fire, it will write that to the disk, as long as conditions above are correct
END ROUND:
1] The file is force-saved, incase it hasnt fired at end round
This is an absolute clusterfuck, but its my clusterfuck -aa07
*/
SUBSYSTEM_DEF(discord)
name = "Discord"
wait = 3000
init_order = INIT_ORDER_DISCORD
var/list/notify_members = list() // People to save to notify file
var/list/notify_members_cache = list() // Copy of previous list, so the SS doesnt have to fire if no new members have been added
var/list/people_to_notify = list() // People to notify on roundstart
var/list/account_link_cache = list() // List that holds accounts to link, used in conjunction with TGS
var/notify_file = file("data/notify.json")
var/enabled = 0 // Is TGS enabled (If not we wont fire because otherwise this is useless)
/datum/controller/subsystem/discord/Initialize(start_timeofday)
// Check for if we are using TGS, otherwise return and disabless firing
if(world.TgsAvailable())
enabled = 1 // Allows other procs to use this (Account linking, etc)
else
can_fire = 0 // We dont want excess firing
return ..() // Cancel
try
people_to_notify = json_decode(file2text(notify_file))
catch
pass() // The list can just stay as its defualt (blank). Pass() exists because it needs a catch
var/notifymsg = ""
for(var/id in people_to_notify)
// I would use jointext here, but I dont think you can two-side glue with it, and I would have to strip characters otherwise
notifymsg += "<@[id]> " // 22 charaters per notify, 90 notifies per message, so I am not making a failsafe because 90 people arent going to notify at once
if(notifymsg)
send2chat("[notifymsg]", CONFIG_GET(string/chat_announce_new_game)) // Sends the message to the discord, using same config option as the roundstart notification
fdel(notify_file) // Deletes the file
return ..()
/datum/controller/subsystem/discord/fire()
if(!enabled)
return // Dont do shit if its disabled
if(notify_members == notify_members_cache)
return // Dont re-write the file
// If we are all clear
write_notify_file()
/datum/controller/subsystem/discord/Shutdown()
write_notify_file() // Guaranteed force-write on server close
/datum/controller/subsystem/discord/proc/write_notify_file()
if(!enabled) // Dont do shit if its disabled
return
fdel(notify_file) // Deletes the file first to make sure it writes properly
WRITE_FILE(notify_file, json_encode(notify_members)) // Writes the file
notify_members_cache = notify_members // Updates the cache list
// Returns ID from ckey
/datum/controller/subsystem/discord/proc/lookup_id(lookup_ckey)
var/datum/DBQuery/query_get_discord_id = SSdbcore.NewQuery("SELECT discord_id FROM [format_table_name("player")] WHERE ckey = '[sanitizeSQL(lookup_ckey)]'")
if(!query_get_discord_id.Execute())
qdel(query_get_discord_id)
return
if(query_get_discord_id.NextRow())
. = query_get_discord_id.item[1]
qdel(query_get_discord_id)
// Returns ckey from ID
/datum/controller/subsystem/discord/proc/lookup_ckey(lookup_id)
var/datum/DBQuery/query_get_discord_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE discord_id = '[sanitizeSQL(lookup_id)]'")
if(!query_get_discord_ckey.Execute())
qdel(query_get_discord_ckey)
return
if(query_get_discord_ckey.NextRow())
. = query_get_discord_ckey.item[1]
qdel(query_get_discord_ckey)
// Finalises link
/datum/controller/subsystem/discord/proc/link_account(ckey)
var/datum/DBQuery/link_account = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET discord_id = '[sanitizeSQL(account_link_cache[ckey])]' WHERE ckey = '[sanitizeSQL(ckey)]'")
link_account.Execute()
qdel(link_account)
account_link_cache -= ckey
// Unlink account (Admin verb used)
/datum/controller/subsystem/discord/proc/unlink_account(ckey)
var/datum/DBQuery/unlink_account = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET discord_id = NULL WHERE ckey = '[sanitizeSQL(ckey)]'")
unlink_account.Execute()
qdel(unlink_account)
// Clean up a discord account mention
/datum/controller/subsystem/discord/proc/id_clean(input)
var/regex/num_only = regex("\[^0-9\]", "g")
return num_only.Replace(input, "")