Skip to content

Commit

Permalink
Merge pull request #8 from SPLURT-Station/discord-verif
Browse files Browse the repository at this point in the history
Ports the discord verification features
  • Loading branch information
MosleyTheMalO authored Jul 6, 2024
2 parents fcf6923 + 11c149c commit 60553ac
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 8 deletions.
8 changes: 4 additions & 4 deletions code/controllers/subsystem/discord.dm
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ SUBSYSTEM_DEF(discord)

/datum/controller/subsystem/discord/proc/get_or_generate_one_time_token_for_ckey(ckey)
// Is there an existing valid one time token
var/datum/discord_link_record/link = find_discord_link_by_ckey(ckey, timebound = TRUE)
var/datum/discord_link_record/link = find_discord_link_by_ckey(ckey, timebound = TRUE, only_valid = TRUE) //SPLURT EDIT - Lookup only valid links
if(link)
return link.one_time_token

Expand Down Expand Up @@ -191,7 +191,7 @@ SUBSYSTEM_DEF(discord)
var/timeboundsql = ""
if(timebound)
timeboundsql = "AND timestamp >= Now() - INTERVAL 4 HOUR"
var/query = "SELECT CAST(discord_id AS CHAR(25)), ckey, MAX(timestamp), one_time_token FROM [format_table_name("discord_links")] WHERE one_time_token = :one_time_token [timeboundsql] GROUP BY ckey, discord_id, one_time_token LIMIT 1"
var/query = "SELECT CAST(discord_id AS CHAR(25)), ckey, MAX(timestamp), one_time_token FROM [format_table_name("discord_links")] WHERE one_time_token = :one_time_token [timeboundsql] GROUP BY ckey, discord_id, one_time_token ORDER BY timestamp DESC LIMIT 1" //SPLURT EDIT - Order by timestamp
var/datum/db_query/query_get_discord_link_record = SSdbcore.NewQuery(
query,
list("one_time_token" = one_time_token)
Expand Down Expand Up @@ -227,7 +227,7 @@ SUBSYSTEM_DEF(discord)
if(only_valid)
validsql = "AND valid = 1"

var/query = "SELECT CAST(discord_id AS CHAR(25)), ckey, MAX(timestamp), one_time_token FROM [format_table_name("discord_links")] WHERE ckey = :ckey [timeboundsql] [validsql] GROUP BY ckey, discord_id, one_time_token LIMIT 1"
var/query = "SELECT CAST(discord_id AS CHAR(25)), ckey, MAX(timestamp), one_time_token FROM [format_table_name("discord_links")] WHERE ckey = :ckey [timeboundsql] [validsql] GROUP BY ckey, discord_id, one_time_token ORDER BY timestamp DESC LIMIT 1" //SPLURT EDIT - Order by timestamp
var/datum/db_query/query_get_discord_link_record = SSdbcore.NewQuery(
query,
list("ckey" = ckey)
Expand Down Expand Up @@ -265,7 +265,7 @@ SUBSYSTEM_DEF(discord)
if(only_valid)
validsql = "AND valid = 1"

var/query = "SELECT CAST(discord_id AS CHAR(25)), ckey, MAX(timestamp), one_time_token FROM [format_table_name("discord_links")] WHERE discord_id = :discord_id [timeboundsql] [validsql] GROUP BY ckey, discord_id, one_time_token LIMIT 1"
var/query = "SELECT CAST(discord_id AS CHAR(25)), ckey, MAX(timestamp), one_time_token FROM [format_table_name("discord_links")] WHERE discord_id = :discord_id [timeboundsql] [validsql] GROUP BY ckey, discord_id, one_time_token ORDER BY timestamp DESC LIMIT 1" //SPLURT EDIT - Order by timestamp
var/datum/db_query/query_get_discord_link_record = SSdbcore.NewQuery(
query,
list("discord_id" = discord_id)
Expand Down
18 changes: 14 additions & 4 deletions code/modules/discord/accountlink.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,22 @@


else
// Will generate one if an expired one doesn't exist already, otherwise will grab existing token
var/one_time_token = SSdiscord.get_or_generate_one_time_token_for_ckey(ckey)
SSdiscord.reverify_cache[usr.ckey] = one_time_token
message = "Your one time token is: [one_time_token]. Assuming you have the required living minutes in game, you can now verify yourself on Discord by using the command: <span class='code user-select'>[prefix]verify [one_time_token]</span>"
//SPLURT EDIT - Only one linked account
var/datum/discord_link_record/existing_link = SSdiscord.find_discord_link_by_ckey(usr?.ckey, only_valid = TRUE)
//Do not create a new entry if they already have a linked account
if(existing_link?.discord_id)
message = "You already have a linked account with discord ID ([existing_link.discord_id]) linked on [existing_link.timestamp]. If you desire to change your account please contact staff."
else
// Will generate one if an expired one doesn't exist already, otherwise will grab existing token
var/one_time_token = SSdiscord.get_or_generate_one_time_token_for_ckey(ckey)
SSdiscord.reverify_cache[usr.ckey] = one_time_token
message = "Your one time token is: [one_time_token]. Assuming you have the required living minutes in game, you can now verify yourself on Discord by using the command: <span class='code user-select'>[prefix]verify [one_time_token]</span>"
//SPLURT EDIT END

//Now give them a browse window so they can't miss whatever we told them
//SPLURT EDIT - Notify if they must stay in our discord server
if(CONFIG_GET(flag/forced_discord_stay))
message += span_warning("Remember that to mantain verification you MUST stay in the discord server")
var/datum/browser/window = new/datum/browser(usr, "discordverification", "Discord Verification")
window.set_content("<div>[message]</div>")
window.open()
Expand Down
3 changes: 3 additions & 0 deletions config/config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ $include interviews.txt
$include lua.txt
$include auxtools.txt

# SPLURT configs
$include splurt/discord.txt

# You can use the @ character at the beginning of a config option to lock it from being edited in-game
# Example usage:
# @SERVERNAME tgstation
Expand Down
20 changes: 20 additions & 0 deletions config/splurt/discord.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Discord verification channel name
## This config has no actual function, it's only aesthetic lol ##
## Use the actual name of the channel ##
#VERIFICATION_CHANNEL verification

# Discord verification command name
## The name of the command you use for verification, only in case you've set up an alias for it ##
## Defaults to "verify" ##
#VERIFICATION_COMMAND verify

# Need discord account to join
## Uncomment to make players need to link their discord accounts to ckeys in order to join the game_mode ##
## The discord verification system makes use of https://github.com/optimumtact/orangescogs ##
## Needs a working database with the station's current schema ##
#DISCORD_BUNKER

# Discord forcing mode
## Uncomment this if your players need to remain in the discord to keep verification ##
## Note, this only produces aesthetic changes, the real magic happens with the redbot modules
#FORCED_DISCORD_STAY
1 change: 1 addition & 0 deletions modular_zzplurt/code/_globalvars/mobs.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GLOBAL_LIST_EMPTY(discord_passthrough)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/datum/config_entry/string/verification_channel
default = "verification"

/datum/config_entry/string/verification_command
default = "verify"

/datum/config_entry/flag/discord_bunker

/datum/config_entry/flag/forced_discord_stay
33 changes: 33 additions & 0 deletions modular_zzplurt/code/controllers/subsystem/discord.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/datum/controller/subsystem/discord/Initialize()
. = ..()
delete_nulls()


/datum/controller/subsystem/discord/proc/check_login(mob/dead/new_player/player)
. = TRUE
if(!(SSdbcore.IsConnected() && CONFIG_GET(flag/discord_bunker) && CONFIG_GET(string/discordbotcommandprefix))) //If not configured/using DB
return TRUE
if(!player.client) //Safety check
return FALSE
if(player.client?.ckey in GLOB.discord_passthrough) //If they have bypass
return TRUE

var/datum/discord_link_record/player_link = find_discord_link_by_ckey(player.client?.ckey, only_valid = TRUE)

if(!(player_link && player_link?.discord_id))
return FALSE

/datum/controller/subsystem/discord/proc/delete_nulls()
var/query = "DELETE FROM [format_table_name("discord_links")] WHERE discord_id IS NULL"
var/datum/db_query/query_delete_nulls = SSdbcore.NewQuery(
query
)
if(!query_delete_nulls.Execute())
log_runtime("DATABASE: There was an error while deleting NULL discord IDs") // This codebase doesn't have a subsystem_log()
message_admins(span_warning("There was an error while deleting NULL IDs, please delete them manually using the Delete Null Discords verb"))
send2adminchat("Discord Subsystem", "There was an error while deleting NULL IDs, please delete them manually using `!tgs discordnulls`")
qdel(query_delete_nulls)
return FALSE

qdel(query_delete_nulls)
return TRUE
10 changes: 10 additions & 0 deletions modular_zzplurt/code/modules/client/verbs/looc.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/client/looc(msg as text)
var/vibe_check = SSdiscord?.check_login(usr)
if(isnull(vibe_check))
to_chat(usr, span_notice("The server is still starting up. Please wait... "))
return
else if(!vibe_check) //Dirty but I guess we gotta tell when the subsystem hasn't started
to_chat(usr, span_warning("You must link your discord account to your ckey in order to join the game. Join our <a style=\"color: #ff00ff;\" href=\"[CONFIG_GET(string/discord_link)]\">discord</a> and use the <span style=\"color: #ff00ff;\">[CONFIG_GET(string/discordbotcommandprefix)][CONFIG_GET(string/verification_command)]</span> command [CONFIG_GET(string/verification_channel) ? "as indicated in #[CONFIG_GET(string/verification_channel)] " : ""]. It won't take you more than two minutes :)<br>Ahelp or ask staff in the discord if this is an error."))
return

. = ..()
10 changes: 10 additions & 0 deletions modular_zzplurt/code/modules/client/verbs/ooc.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/client/ooc(msg as text)
var/vibe_check = SSdiscord?.check_login(usr)
if(isnull(vibe_check))
to_chat(usr, span_notice("The server is still starting up. Please wait... "))
return
else if(!vibe_check) //Dirty but I guess we gotta tell when the subsystem hasn't started
to_chat(usr, span_warning("You must link your discord account to your ckey in order to join the game. Join our <a style=\"color: #ff00ff;\" href=\"[CONFIG_GET(string/discord_link)]\">discord</a> and use the <span style=\"color: #ff00ff;\">[CONFIG_GET(string/discordbotcommandprefix)][CONFIG_GET(string/verification_command)]</span> command [CONFIG_GET(string/verification_channel) ? "as indicated in #[CONFIG_GET(string/verification_channel)] " : ""]. It won't take you more than two minutes :)<br>Ahelp or ask staff in the discord if this is an error."))
return

. = ..()
46 changes: 46 additions & 0 deletions modular_zzplurt/code/modules/discord/tgs_commands.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/datum/tgs_chat_command/adddiscordpass
name = "adddiscordpass"
help_text = "adddiscordpass <ckey> | Add someone to the discord bunker bypass list"
admin_only = TRUE

/datum/tgs_chat_command/adddiscordpass/Run(datum/tgs_chat_user/sender, params)
if(!SSdbcore.IsConnected())
return "The Database is not connected!"
if(!SSdiscord)
return "The discord subsystem hasn't initialized yet!"
if(!CONFIG_GET(flag/discord_bunker))
return "The Discord Bunker is deactivated!"

GLOB.discord_passthrough |= ckey(params)
GLOB.discord_passthrough[ckey(params)] = world.realtime
log_admin("[sender.friendly_name] has added [params] to the current round's discord bypass list.")
message_admins("[sender.friendly_name] has added [params] to the current round's discord bypass list.")
return "[params] has been added to the current round's bunker bypass list."

/datum/tgs_chat_command/revdiscordpass
name = "revdiscordpass"
help_text = "revdiscordpass <ckey> | Remove someone from the discord bypass list"
admin_only = TRUE

/datum/tgs_chat_command/revdiscordpass/Run(datum/tgs_chat_user/sender, params)
if(!SSdbcore.IsConnected())
return "The Database is not connected!"
if(!SSdiscord)
return "The discord subsystem hasn't initialized yet!"
if(!CONFIG_GET(flag/discord_bunker))
return "The Discord Bunker is deactivated!"

GLOB.discord_passthrough -= ckey(params)
log_admin("[sender.friendly_name] has removed [params] from the current round's discord bypass list.")
message_admins("[sender.friendly_name] has removed [params] from the current round's discord bypass list.")
return "[params] has been removed from the current round's discord bypass list."

/datum/tgs_chat_command/discordnulls
name = "discordnulls"
help_text = "Deletes all rows in the database where discord_id is NULL."
admin_only = TRUE

/datum/tgs_chat_command/discordnulls/Run(datum/tgs_chat_user/sender, params)
log_admin("[sender.friendly_name] has attempted to delete the NULLs from the discord database.")
message_admins("[sender.friendly_name] has attempted to delete the NULLs from the discord database.")
return "[SSdiscord.delete_nulls() ? "NULL rows deleted successfully" : "There was a problem while deleting NULLs"]"
45 changes: 45 additions & 0 deletions modular_zzplurt/code/modules/discord/verbs.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
ADMIN_VERB(discordbunker, R_SERVER, "Toggle Discord Bunker", "Toggles the Discord Bunker on or off.", ADMIN_CATEGORY_SERVER)
if(!SSdbcore.IsConnected())
to_chat(user, span_adminnotice("The Database is not connected/enabled!"))
return

var/new_dbun = !CONFIG_GET(flag/discord_bunker)
CONFIG_SET(flag/discord_bunker, new_dbun)

log_admin("[key_name(user)] has toggled the Discord Bunker, it is now [new_dbun ? "on" : "off"]")
message_admins("[key_name_admin(user)] has toggled the Discord Bunker, it is now [new_dbun ? "enabled" : "disabled"].")
SSblackbox.record_feedback("nested tally", "discord_toggle", 1, list("Toggle Discord Bunker", "[new_dbun ? "Enabled" : "Disabled"]"))
send2adminchat("Discord Bunker", "[key_name(user)] has toggled the Discord Bunker, it is now [new_dbun ? "enabled" : "disabled"].")

ADMIN_VERB(adddiscordbypass, R_SERVER, "Add Discord Bypass", "Allows a given ckey to connect through the discord bunker for the round even if they haven't verified yet.", ADMIN_CATEGORY_SERVER, ckeytobypass as text)
if(!SSdbcore.IsConnected())
to_chat(user, span_adminnotice("The Database is not connected!"))
return
if(!SSdiscord)
to_chat(user, span_adminnotice("The discord subsystem hasn't initialized yet!"))
return
if(!CONFIG_GET(flag/discord_bunker))
to_chat(user, span_adminnotice("The Discord Bunker is deactivated!"))
return

GLOB.discord_passthrough |= ckey(ckeytobypass)
GLOB.discord_passthrough[ckey(ckeytobypass)] = world.realtime
log_admin("[key_name(user)] has added [ckeytobypass] to the current round's discord bypass list.")
message_admins("[key_name_admin(user)] has added [ckeytobypass] to the current round's discord bypass list.")
send2adminchat("Discord Bunker", "[key_name(user)] has added [ckeytobypass] to the current round's discord bypass list.")

ADMIN_VERB(revokediscordbypass, R_SERVER, "Revoke Discord Bypass", "Revoke's a ckey's permission to bypass the discord bunker for a given round.", ADMIN_CATEGORY_SERVER, ckeytobypass as text)
if(!SSdbcore.IsConnected())
to_chat(user, span_adminnotice("The Database is not connected!"))
return
if(!SSdiscord)
to_chat(user, span_adminnotice("The discord subsystem hasn't initialized yet!"))
return
if(!CONFIG_GET(flag/discord_bunker))
to_chat(user, span_adminnotice("The Discord Bunker is deactivated!"))
return

GLOB.discord_passthrough -= ckey(ckeytobypass)
log_admin("[key_name(user)] has removed [ckeytobypass] from the current round's discord bypass list.")
message_admins("[key_name_admin(user)] has removed [ckeytobypass] from the current round's discord bypass list.")
send2adminchat("Discord Bunker", "[key_name(user)] has removed [ckeytobypass] from the current round's discord bypass list.")
10 changes: 10 additions & 0 deletions modular_zzplurt/code/modules/mob/dead/new_player/new_player.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/mob/dead/new_player/Topic(href, list/href_list)
var/vibe_check = SSdiscord?.check_login(src)
if(isnull(vibe_check))
to_chat(usr, span_notice("The server is still starting up. Please wait... "))
return
if(href_list["observe"] || href_list["toggle_ready"] || href_list["late_join"])
if(!vibe_check)
to_chat(src, span_warning("You must link your discord account to your ckey in order to join the game. Join our <a style=\"color: #ff00ff;\" href=\"[CONFIG_GET(string/discord_link)]\">discord</a> and use the <span style=\"color: #ff00ff;\">[CONFIG_GET(string/discordbotcommandprefix)][CONFIG_GET(string/verification_command)]</span> command [CONFIG_GET(string/verification_channel) ? "as indicated in #[CONFIG_GET(string/verification_channel)] " : ""]. It won't take you more than two minutes :)<br>Ahelp or ask staff in the discord if this is an error."))
return
. = ..()
8 changes: 8 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -9074,4 +9074,12 @@
#include "modular_zubbers\master_files\skyrat\modules\cortical_borer\code\cortical_borer_antag.dm"
#include "modular_zubbers\master_files\skyrat\modules\opposing_force\code\opposing_force_subsystem.dm"
#include "modular_zubbers\master_files\skyrat\modules\verbs\code\subtle.dm"
#include "modular_zzplurt\code\_globalvars\mobs.dm"
#include "modular_zzplurt\code\controllers\configuration\entries\discord.dm"
#include "modular_zzplurt\code\controllers\subsystem\discord.dm"
#include "modular_zzplurt\code\modules\client\verbs\looc.dm"
#include "modular_zzplurt\code\modules\client\verbs\ooc.dm"
#include "modular_zzplurt\code\modules\discord\tgs_commands.dm"
#include "modular_zzplurt\code\modules\discord\verbs.dm"
#include "modular_zzplurt\code\modules\mob\dead\new_player\new_player.dm"
// END_INCLUDE

0 comments on commit 60553ac

Please sign in to comment.