Load alien/job whitelists from database, if enabled (#17952)

* Load alien/job whitelists from database, if enabled

* SQL Template for Table

* Fixes

* Commands

* .

* .

* fix

* cannot be a list

* .

* .

* embed

* .

* .

* query test

* query test

* query test

* .

* fix
This commit is contained in:
Selis
2025-09-28 10:28:55 +02:00
committed by GitHub
parent ca27d60647
commit 315fbb415f
12 changed files with 421 additions and 354 deletions
+11 -1
View File
@@ -295,7 +295,7 @@ LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY INVOKER
COMMENT 'Inserts a new row into \'chatlogs_rounds\' and deletes the oldest entry, if the ckey already has 10 round id\'s stored.'
COMMENT 'Inserts a new row into \'chatlogs_rounds\' and deletes the oldest entry, if the ckey already has 10 round ids stored.'
BEGIN
INSERT IGNORE INTO chatlogs_rounds(round_id, ckey) VALUES (p_round_id, p_ckey);
@@ -306,3 +306,13 @@ END IF;
END
DELIMITER ;
-- Table structure for table `whitelist`
CREATE TABLE `whitelist` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`ckey` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_uca1400_ai_ci',
`kind` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_uca1400_ai_ci',
`entry` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_uca1400_ai_ci',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `ckey_kind_entry` (`ckey`, `kind`, `entry`) USING BTREE
) ENGINE=InnoDB COLLATE='utf8mb4_uca1400_ai_ci';
+2 -3
View File
@@ -526,11 +526,10 @@ Ignore_errors instructes mysql to continue inserting rows if some of them have e
Close()
status = DB_QUERY_STARTED
if(async)
/*if(!MC_RUNNING(SSdbcore.init_stage))
if(!MC_RUNNING(SSdbcore.init_stage))
SSdbcore.run_query_sync(src)
else
SSdbcore.queue_query(src)*/
SSdbcore.run_query_sync(src)
SSdbcore.queue_query(src)
sync()
else
var/job_result_str = rustg_sql_query_blocking(connection, sql, json_encode(arguments))
+183 -29
View File
@@ -1,11 +1,68 @@
#define WHITELISTFILE "data/whitelist.txt"
GLOBAL_LIST_EMPTY(whitelist)
GLOBAL_LIST_EMPTY(job_whitelist)
GLOBAL_LIST_EMPTY(alien_whitelist)
/hook/startup/proc/loadWhitelist()
if(CONFIG_GET(flag/usewhitelist))
load_whitelist()
return 1
// Not yet implemented
//ADMIN_VERB(open_whitelist_editor, R_ADMIN, "Open Whitelist Editor", "Opens the editor for alien- and jobwhitelists.", ADMIN_CATEGORY_GAME)
// if(user.holder)
// user.holder.whitelist_editor = new /datum/whitelist_editor()
// user.holder.whitelist_editor.tgui_interact(user.mob)
/datum/whitelist_editor
/datum/whitelist_editor/tgui_state(mob/user)
return ADMIN_STATE(R_ADMIN)
/datum/whitelist_editor/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "WhitelistEdit")
ui.open()
/datum/whitelist_editor/tgui_data(mob/user)
var/list/data = list()
data["alienwhitelist"] = GLOB.alien_whitelist
data["jobwhitelist"] = GLOB.job_whitelist
return data
/datum/whitelist_editor/tgui_static_data(mob/user)
var/list/data = list()
data["species_requiring_whitelist"] = GLOB.whitelisted_species
return data
/datum/whitelist_editor/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
. = ..()
if(.)
return
switch(action)
if("add_alienwhitelist")
if (!CONFIG_GET(flag/sql_enabled))
to_chat(ui.user, "This action is not supported while the database is disabled. Please edit [global.config.directory]/alienwhitelist.txt.")
return
// TODO: Add to database
. = TRUE
if("remove_alienwhitelist")
if (!CONFIG_GET(flag/sql_enabled))
to_chat(ui.user, "This action is not supported while the database is disabled. Please edit [global.config.directory]/alienwhitelist.txt.")
return
// TODO: Remove from database
. = TRUE
if("reload_alienwhitelist")
reload_alienwhitelist()
. = TRUE
if("reload_jobwhitelist")
reload_jobwhitelist()
. = TRUE
/proc/load_whitelist()
GLOB.whitelist = world.file2list(WHITELISTFILE)
@@ -16,33 +73,58 @@ GLOBAL_LIST_EMPTY(whitelist)
return 0
return ("[M.ckey]" in GLOB.whitelist)
GLOBAL_LIST_EMPTY(alien_whitelist)
/proc/load_alienwhitelist(dbfail = FALSE)
if (CONFIG_GET(flag/sql_enabled) && !dbfail)
var/datum/db_query/query_load_alienwhistelist = SSdbcore.NewQuery("SELECT ckey, entry FROM [format_table_name("whitelist")] WHERE kind = 'species'")
if(!query_load_alienwhistelist.Execute())
message_admins("Error loading alienwhitelist from database. Loading from [global.config.directory]/alienwhitelist.txt.")
log_sql("Error loading alienwhitelist from database. Loading from [global.config.directory]/alienwhitelist.txt.")
load_alienwhitelist(dbfail = TRUE)
return
else
while(query_load_alienwhistelist.NextRow())
var/ckey = query_load_alienwhistelist.item[1]
var/entry = query_load_alienwhistelist.item[2]
/hook/startup/proc/loadAlienWhitelist()
if(CONFIG_GET(flag/usealienwhitelist))
load_alienwhitelist()
return 1
/proc/load_alienwhitelist()
var/text = file2text("config/alienwhitelist.txt")
if (!text)
log_world("Failed to load config/alienwhitelist.txt")
var/list/our_whitelists = GLOB.alien_whitelist[ckey]
if(!our_whitelists) // Guess this is their first/only whitelist entry
our_whitelists = list()
GLOB.alien_whitelist[ckey] = our_whitelists
our_whitelists += entry
qdel(query_load_alienwhistelist)
else
var/lines = splittext(text, "\n") // Now we've got a bunch of "ckey = something" strings in a list
for(var/line in lines)
var/list/left_and_right = splittext(line, " - ") // Split it on the dash into left and right
if(LAZYLEN(left_and_right) != 2)
WARNING("Alien whitelist entry is invalid: [line]") // If we didn't end up with a left and right, the line is bad
continue
var/key = left_and_right[1]
if(key != ckey(key))
WARNING("Alien whitelist entry appears to have key, not ckey: [line]") // The key contains invalid ckey characters
continue
var/list/our_whitelists = GLOB.alien_whitelist[key] // Try to see if we have one already and add to it
if(!our_whitelists) // Guess this is their first/only whitelist entry
our_whitelists = list()
GLOB.alien_whitelist[key] = our_whitelists
our_whitelists += left_and_right[2]
var/text = file2text("[global.config.directory]/alienwhitelist.txt")
if (!text)
log_world("Failed to load [global.config.directory]/alienwhitelist.txt")
else
var/lines = splittext(text, "\n") // Now we've got a bunch of "ckey = something" strings in a list
for(var/line in lines)
var/list/left_and_right = splittext(line, " - ") // Split it on the dash into left and right
if(LAZYLEN(left_and_right) != 2)
WARNING("Alien whitelist entry is invalid: [line]") // If we didn't end up with a left and right, the line is bad
continue
var/key = left_and_right[1]
if(key != ckey(key))
WARNING("Alien whitelist entry appears to have key, not ckey: [line]") // The key contains invalid ckey characters
continue
var/list/our_whitelists = GLOB.alien_whitelist[key] // Try to see if we have one already and add to it
if(!our_whitelists) // Guess this is their first/only whitelist entry
our_whitelists = list()
GLOB.alien_whitelist[key] = our_whitelists
our_whitelists += left_and_right[2]
#ifdef TESTING
var/msg = "Alienwhitelist Built:\n"
for(var/key in GLOB.alien_whitelist)
msg += "\t[key]:\n"
for(var/value in GLOB.alien_whitelist[key])
msg += "\t\t- [value]\n"
testing(msg)
#endif
/proc/reload_alienwhitelist()
GLOB.alien_whitelist.Cut()
load_alienwhitelist()
/proc/is_alien_whitelisted(client/C, var/datum/species/species)
//They are admin or the whitelist isn't in use
@@ -67,6 +149,78 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
// Go apply!
return FALSE
/proc/load_jobwhitelist(dbfail = FALSE)
if (CONFIG_GET(flag/sql_enabled) && !dbfail)
var/datum/db_query/query_load_jobwhitelist = SSdbcore.NewQuery("SELECT ckey, entry FROM [format_table_name("whitelist")] WHERE kind = 'job'")
if(!query_load_jobwhitelist.Execute())
message_admins("Error loading jobwhitelist from database. Loading from [global.config.directory]/jobwhitelist.txt.")
log_sql("Error loading jobwhitelist from database. Loading from [global.config.directory]/jobwhitelist.txt.")
load_jobwhitelist(dbfail = TRUE)
return
else
while(query_load_jobwhitelist.NextRow())
var/ckey = query_load_jobwhitelist.item[1]
var/entry = query_load_jobwhitelist.item[2]
var/list/our_whitelists = GLOB.job_whitelist[ckey]
if(!our_whitelists) // Guess this is their first/only whitelist entry
our_whitelists = list()
GLOB.job_whitelist[ckey] = our_whitelists
our_whitelists += entry
qdel(query_load_jobwhitelist)
else
var/text = file2text("[global.config.directory]/jobwhitelist.txt")
if (!text)
log_world("Failed to load [global.config.directory]/jobwhitelist.txt")
else
var/lines = splittext(text, "\n") // Now we've got a bunch of "ckey = something" strings in a list
for(var/line in lines)
var/list/left_and_right = splittext(line, " - ") // Split it on the dash into left and right
if(LAZYLEN(left_and_right) != 2)
warning("Alien whitelist entry is invalid: [line]") // If we didn't end up with a left and right, the line is bad
continue
var/key = left_and_right[1]
if(key != ckey(key))
warning("Alien whitelist entry appears to have key, not ckey: [line]") // The key contains invalid ckey characters
continue
var/list/our_whitelists = GLOB.job_whitelist[key] // Try to see if we have one already and add to it
if(!our_whitelists) // Guess this is their first/only whitelist entry
our_whitelists = list()
GLOB.job_whitelist[key] = our_whitelists
our_whitelists += left_and_right[2]
/proc/reload_jobwhitelist()
GLOB.job_whitelist.Cut()
load_jobwhitelist()
/proc/is_job_whitelisted(mob/M, var/rank)
// Check if the job actually requires a whitelist
var/datum/job/job = job_master.GetJob(rank)
if(!job.whitelist_only)
return TRUE
// Visitor not Assistant
if(rank == JOB_ALT_VISITOR)
return TRUE
// Let R_ADMIN permission bypass the whitelist
if(check_rights(R_ADMIN, 0))
return TRUE
// Whitelist empty
if(!GLOB.job_whitelist)
return FALSE
//Search the whitelist
if(M && M.client && rank)
var/list/our_whitelists = GLOB.job_whitelist[M.client.ckey]
if("All" in our_whitelists)
return TRUE
if(lowertext(rank) in our_whitelists)
return TRUE
return FALSE
/proc/is_lang_whitelisted(mob/M, var/datum/language/language)
//They are admin or the whitelist isn't in use
if(whitelist_overrides(M))
-30
View File
@@ -1,30 +0,0 @@
GLOBAL_LIST_EMPTY(job_whitelist)
/hook/startup/proc/loadJobWhitelist()
load_jobwhitelist()
return 1
/proc/load_jobwhitelist()
var/text = file2text("config/jobwhitelist.txt")
if (!text)
log_world("Failed to load config/jobwhitelist.txt")
else
GLOB.job_whitelist = splittext(text, "\n")
/proc/is_job_whitelisted(mob/M, var/rank)
var/datum/job/job = job_master.GetJob(rank)
if(!job.whitelist_only)
return 1
if(rank == JOB_ALT_VISITOR) //VOREStation Edit - Visitor not Assistant
return 1
if(check_rights(R_ADMIN, 0))
return 1
if(!GLOB.job_whitelist)
return 0
if(M && rank)
for (var/s in GLOB.job_whitelist)
if(findtext(s,"[lowertext(M.ckey)] - [lowertext(rank)]"))
return 1
if(findtext(s,"[M.ckey] - All"))
return 1
return 0
+9
View File
@@ -155,6 +155,15 @@ GLOBAL_VAR(restart_counter)
GLOB.timezoneOffset = get_timezone_offset()
callHook("startup")
// This should probably moved somewhere else
// Maybe even a comsig?
if(CONFIG_GET(flag/usewhitelist))
load_whitelist()
if(CONFIG_GET(flag/usealienwhitelist))
load_alienwhitelist()
load_jobwhitelist()
//Emergency Fix
load_mods()
//end-emergency fix
+1
View File
@@ -31,6 +31,7 @@ GLOBAL_PROTECT(href_token)
var/datum/filter_editor/filteriffic
var/datum/particle_editor/particle_test
var/datum/whitelist_editor/whitelist_editor
/// A lazylist of tagged datums, for quick reference with the View Tags verb
var/list/tagged_datums
+166 -1
View File
@@ -30,7 +30,7 @@
admin_only = FALSE
/datum/tgs_chat_command/parsetest/Run(datum/tgs_chat_user/sender, params)
return "```You passed:[params]```"
return new /datum/tgs_message_content("```You passed:[params]```")
/datum/tgs_chat_command/staffwho
name = "staffwho"
@@ -378,3 +378,168 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
if("dust")
real_target.dust()
return "Smite [smite_name] sent!"
#define VALID_ACTIONS list("add", "remove", "list")
#define VALID_KINDS list("job", "species")
#define VALID_USAGE "whitelist \[[list2text(VALID_ACTIONS, ", ")]\] \[[list2text(VALID_KINDS, ", ")]\] <ckey> (role)"
/datum/tgs_chat_command/whitelist
name = "whitelist"
help_text = "allows the management of player whitelists. Usage: whitelist \[add, remove, list\] \[job, species\] <ckey> (role)"
admin_only = TRUE
/datum/tgs_chat_command/whitelist/Run(datum/tgs_chat_user/sender, params)
var/list/message_as_list = splittext(params, " ")
var/datum/tgs_message_content/message = new("Invalid return message.")
// Check if the command is valid
if(!CONFIG_GET(flag/sql_enabled))
message.text = "```A database is required to be set up for this feature.```"
return message
if(!LAZYLEN(message_as_list))
message.text = "```Invalid command usage: [VALID_USAGE]```"
return message
var/action = message_as_list[1]
if(!(action in VALID_ACTIONS))
message.text = "```First param must be a valid action.```"
return message
message_as_list.Cut(1, 2)
if(!LAZYLEN(message_as_list))
message.text = "```Invalid command usage: [VALID_USAGE]```"
return message
var/kind = message_as_list[1]
if(!(kind in VALID_KINDS))
message.text = "```Second param must be a valid whitelist kind.```"
return message
message_as_list.Cut(1, 2)
if(!LAZYLEN(message_as_list))
message.text = "```Invalid command usage: [VALID_USAGE]```"
return message
var/ckey = message_as_list[1]
if(!istext(ckey))
message.text = "```Third param must be a valid ckey.```"
return message
// Role is not required for listing the roles of a ckey
var/role
if(action != "list")
message_as_list.Cut(1, 2)
if(!LAZYLEN(message_as_list))
message.text = "```Invalid command usage: [VALID_USAGE]```"
return message
role = message_as_list[1]
if(!istext(role))
message.text = "```Fourth param must be a valid whitelist role.```"
return message
// Resolve the action
switch(action)
if("add")
var/datum/db_query/command_add = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("whitelist")] (ckey, kind, entry) VALUES (:ckey, :kind, :entry)",
list("ckey" = ckey, "kind" = kind, "entry" = role)
)
if(!command_add.Execute())
log_sql("Error while trying to add [ckey] to the [role] [kind] whitelist.")
message.text = "Error while trying to add [ckey] to the [role] [kind] whitelist. Please review SQL logs."
return message
qdel(command_add)
var/list/our_whitelists
if(kind == "job")
our_whitelists = GLOB.job_whitelist[ckey]
if(!our_whitelists)
our_whitelists = list()
GLOB.job_whitelist[ckey] = our_whitelists
if(kind == "species")
our_whitelists = GLOB.alien_whitelist[ckey]
if(!our_whitelists)
our_whitelists = list()
GLOB.alien_whitelist[ckey] = our_whitelists
if(our_whitelists)
our_whitelists |= role
if("remove")
var/datum/db_query/command_remove = SSdbcore.NewQuery(
"DELETE FROM [format_table_name("whitelist")] WHERE ckey = :ckey AND kind = :kind AND entry = :entry",
list("ckey" = ckey, "kind" = kind, "entry" = role)
)
if(!command_remove.Execute())
log_sql("Error while trying to remove [ckey] from the [role] [kind] whitelist.")
message.text = "Error while trying to remove [ckey] from the [role] [kind] whitelist. Please review SQL logs."
return message
qdel(command_remove)
var/list/our_whitelists
if(kind == "job")
our_whitelists = GLOB.job_whitelist[ckey]
if(!our_whitelists)
our_whitelists = list()
GLOB.job_whitelist[ckey] = our_whitelists
if(kind == "species")
our_whitelists = GLOB.alien_whitelist[ckey]
if(!our_whitelists)
our_whitelists = list()
GLOB.alien_whitelist[ckey] = our_whitelists
if(our_whitelists && (role in our_whitelists))
our_whitelists -= role
// Listing all whitelists for a specific ckey
if("list")
var/datum/tgs_chat_embed/structure/embed = new()
var/found = FALSE
message.text = ""
message.embed = embed
embed.title = "Whitelists for [ckey]"
var/datum/db_query/query_list = SSdbcore.NewQuery(
"SELECT kind, entry FROM [format_table_name("whitelist")] WHERE ckey = :ckey",
list("ckey" = ckey)
)
if(!query_list.Execute())
log_sql("Error while trying to query whitelists for [ckey].")
embed.description = "Error while trying to query whitelists for [ckey]. Please review SQL logs."
embed.colour = "#FF0000"
return message
else
while(query_list.NextRow())
var/kind_query_result = query_list.item[1]
var/entry_query_result = query_list.item[2]
embed.description += "- [kind_query_result] - [entry_query_result]\n"
found = TRUE
qdel(query_list)
if(!found)
embed.description += "No whitelist entries found for [ckey]"
return message
// Notify the player of the change
var/key_to_find = "[ckey(ckey)]"
if(length(key_to_find))
var/client/user
for(var/client/C in GLOB.clients)
if(C.ckey == key_to_find)
user = C
break
to_chat(user, span_info("You have been [action][action == "remove" ? "d" : "ed"] to the [kind] whitelist of [role] by an administrator."))
// Notify the admins on discord that it was successful
message.text = "\[Whitelist Edit\] [ckey] has been [action][action == "remove" ? "d" : "ed"] to [kind] whitelist: [role]"
log_admin(message.text)
message_admins(message.text)
return message
#undef VALID_USAGE
#undef VALID_KINDS
#undef VALID_ACTIONS
-2
View File
@@ -4,6 +4,4 @@
#Also don't ignore these things because editing them manually on the server is a pain in the fucking ass.
!custom_items.txt
!custom_sprites.txt
!alienwhitelist.txt
!jobwhitelist.txt
!jukebox.json
-250
View File
@@ -1,250 +0,0 @@
1062aphelion - Protean
abyssalamphithere - Vox
admiraldragon - Vox
adriano20037 - Protean
adriano20037 - Xenochimera
aetherelemental - Daemon
afflatuskeeper - Xenochimera
alphaprime1 - Protean
amarewolf - Xenochimera
amshaegaar - Vox
arandomalien - Xenochimera
arminazenith - Protean
arokha - Protean
aruis - Diona
aruis - Protean
aruis - Xenochimera
ashburndracki - Protean
athena14 - Xenochimera
athena14 - Protean
auraribbon - Black-Eyed Shadekin
avianaviator - Protean
avianaviator - Hanner
azmodan412 - Xenochimera
beyondmylife - Protean
bonktrauma - Diona
bothnevarbackwards - Diona
bricker98 - Protean
bricker98 - Black-Eyed Shadekin
bricker98 - Hanner
bricker98 - Gamma Replicant
bubonicsweetie - Protean
burritojustice - Protean
camanis - Protean
cameron653 - Protean
cgr - Protean
chaosdoomsday - Black-Eyed Shadekin
chaosdoomsday - Protean
chargae - Protean
chemlight - Xenochimera
chillyfang - Black-Eyed Shadekin
chloeplayer - Protean
comradenitro - Protean
coolcrow420 - Black-Eyed Shadekin
crossexonar - Protean
cryohydra - Protean
ctrz - Protean
cubejackal - Black-Eyed Shadekin
detectivegoogle - Protean
digi5 - Protean
digi5 - Black-Eyed Shadekin
digitalsquirrel95 - Black-Eyed Shadekin
digitalsquirrel95 - Protean
digitalsquirrel95 - Hanner
draycu - Vox
draykenthedragon - Xenochimera
draykenthedragon - Protean
durandaal - Teppi
essbie - Black-Eyed Shadekin
eucliwood0 - Hanner
exgame - Vox
falloutdog3 - Black-Eyed Shadekin
flaktual - Vox
flurriee - Protean
foxfire53 - Xenochimera
foxglovepurpur - Diona
funnyman2003 - Xenochimera
fuzlet - Protean
grallstonefist - Black-Eyed Shadekin
greennyy - Protean
h0lysquirr3l - Protean
haloren - Black-Eyed Shadekin
hawkerthegreat - Vox
heroman3003 - Xenochimera
hexadood - Protean
hollifex - Diona
huenererschrecker - Xenochimera
hunterbirk - Protean
hunterbirk - Xenochimera
idcaboutaname - Protean
idcaboutaname - Black-Eyed Shadekin
inuzari - Diona
iivoracious - Black-Eyed Shadekin
irkallaepsilon - Protean
jademanique - Black-Eyed Shadekin
jademanique - Protean
jademanique - Teppi
jademanique - Xenochimera
joltze - Black-Eyed Shadekin
jparker890 - Vox
juney7 - Hanner
kered2 - Protean
khanivore - Protean
killjaden - Protean
kira72 - Xenochimera
kira72 - Protean
kiraalitruss - Teppi
kitchifox - Black-Eyed Shadekin
konner1055 - Black-Eyed Shadekin
konner1055 - Protean
ktccd - Diona
kyrendragon - Black-Eyed Shadekin
lavenderrs - Teppi
lazzar - Black-Eyed Shadekin
lazzar - Hanner
lewzharri - Hanner
lewzharri - Glamour Speak
lianvee - Black-Eyed Shadekin
lillianfyre - Xenochimera
liquidfirefly - Protean
lizehrd - Xenochimera
looptyloo - Protean
lordlag - Black-Eyed Shadekin
lorgenz - Protean
losstinspess - Protean
losstinspess - Xenochimera
lykojeyot - Black-Eyed Shadekin
negatist - Protean
madmulk9 - Protean
magpiemayhem - Vox
magpiemayhem - Xenochimera
makkinindorn - Protean
malfestio - Protean
malfestio - Xenochimera
marcobarko - Black-Eyed Shadekin
marcobarko - Protean
maxcaliber50 - Protean
maxine64 - Xenochimera
mewchild - Diona
mewchild - Vox
milu - Xenochimera
mrsebbi - Xenochimera
mullins111 - Black-Eyed Shadekin
murchant - Teppi
natje - Xenochimera
neodraconica - Hanner
nerdass - Protean
newyorks - Protean
obengrad - Diona
obengrad - Protean
obengrad - Xenochimera
omegamech - Black-Eyed Shadekin
oneofmanynames385 - Protean
ontejbjoav - Black-Eyed Shadekin
ontejbjoav - Diona
opheliathedreadful - Hanner
oreganovulgaris - Xenochimera
oscarholmes - Protean
oscarholmes - Gamma Replicant
owwy - Black-Eyed Shadekin
oxenfree - Protean
ozyton - Black-Eyed Shadekin
pandora029 - Protean
paradoxspace - Xenochimera
pastelprincedan - Black-Eyed Shadekin
pastelprincedan - Hanner
pastelprincedan - Protean
pearlprophet - Protean
pemdesos - Protean
phoenixx0 - Vox
pontifexminimus - Black-Eyed Shadekin
pontifexminimus - Protean
pontifexminimus - Xenochimera
pontifexminimus - Hanner
pugly43 - Protean
qrocakes - Black-Eyed Shadekin
radiantaurora - Protean
rainbyplays - Protean
ramomisama - Protean
residentcody - Black-Eyed Shadekin
residentcody - Protean
residentcody - Gamma Replicant
revolvereloise - Protean
rikaru19xjenkins - Xenochimera
rixunie - Diona
romanatcolgate - Hanner
rubyflamewing - Protean
rykkastormheart - Xenochimera
ryumi - Protean
ryumi - Xenochimera
ryumi - Black-Eyed Shadekin
ryumi - Hanner
satinisle - Black-Eyed Shadekin
satinisle - Protean
scoutisafolflol - Xenochimera
seagha - Vox
seiga - Vox
selter - Protean
sepulchre - Vox
sharplight - Protean
shilkon - Hanner
shirosenshi - Xenochimera
silvertalismen - Diona
silvertalismen - Vox
silvertalismen - Xenochimera
silvertalismen - Hanner
sirlionfur - Black-Eyed Shadekin
sixberry - Black-Eyed Shadekin
sixberry - Hanner
skylarks - Black-Eyed Shadekin
slovakiani - Black-Eyed Shadekin
slysilentclaw - Black-Eyed Shadekin
smdytb1 - Black-Eyed Shadekin
spirit1299 - Black-Eyed Shadekin
stackerrobot - Protean
storesund97 - Protean
syzygyrior - Black-Eyed Shadekin
tankthebirb - Black-Eyed Shadekin
tastypred - Black-Eyed Shadekin
tastypred - Protean
tastypred - Xenochimera
terrestris - Common Skrellian
terrestris - Vox
thedavestdave - Protean
theoun - Hanner
thexdkidoflol - Xenochimera
tigercat2000 - Protean
timidvi - Diona
titaania - Protean
tombomb90 - Protean
torquegstc - Protean
trifireblade - Protean
trikonei - Protean
umbraferros - Black-Eyed Shadekin
umbraferros - Protean
umbraferros - Xenochimera
umbraferros - Hanner
umbrenos - Black-Eyed Shadekin
unkindnaysayer - Hanner
varkaselyn - Protean
varonis - Protean
varonis - Xenochimera
verkister - Xenochimera
verysoft - Black-Eyed Shadekin
verysoft - Teppi
vitoras - Protean
voidalynx - Black-Eyed Shadekin
voidalynx - Protean
wickedtemp - Shadekin Empathy
wolfmeme - Protean
xioen - Diona
xioen - Protean
xioen - Xenochimera
xonkon - Protean
yecrowbarman - Protean
yeehawguvnah - Protean
yeehawguvnah - Xenochimera
zalvine - Shadekin Empathy
zammyman215 - Vox
zeracyfr - Xenochimera
zwadstheiguana - Diona
-37
View File
@@ -1,37 +0,0 @@
# Job whitelist in format ckey - jobname
# Like arokha - clown
akram - clown
amshaegaar - mime
auraribbon - clown
awkwarddryad - mime
CGR - mime
chargae - mime
coolcrow420 - clown
coolcrow420 - mime
donnysalmond - clown
h0lysquirr3l - clown
joey4298 - mime
lm40 - clown
losstinspess - mime
maxcaliber50 - mime
murchant - mime
pastelprincedan - mime
pastelprincedan - clown
radishfriend - clown
schrano - mime
seiga - mime
sgtryder - mime
sharplight - clown
siennaathens - clown
silvertalismen - clown
spirit1299 - clown
suicidalpickles - mime
tinybear16 - clown
tygertac - clown
umbraferros - mime
varonis - mime
verkister - clown
whiskyrose - clown
yecrowbarman - clown
yecrowbarman - mime
nullspaceindustries - mime
+49
View File
@@ -0,0 +1,49 @@
input_file = 'config/alienwhitelist.txt'
output_file = 'whitelist.sql'
table_name = 'whitelist'
with open(input_file, 'r', encoding='utf-8') as infile, \
open(output_file, 'w', encoding='utf-8') as outfile:
for line in infile:
line = line.strip()
if not line:
continue
if "#" in line:
print(f"Skipping commented line: {line}")
continue
# Split on ' - ', expecting exactly two parts
parts = line.split(' - ')
if len(parts) != 2:
print(f"Skipping invalid line: {line}")
continue
username, entry = (p.replace("'", "''") for p in parts) # Escape single quotes
kind = "species"
sql = (
f"INSERT INTO {table_name} (ckey, entry, kind) "
f"VALUES ('{username}', '{entry}', '{kind}');\n"
)
outfile.write(sql)
input_file = 'config/jobwhitelist.txt'
with open(input_file, 'r', encoding='utf-8') as infile, \
open(output_file, 'a', encoding='utf-8') as outfile:
for line in infile:
line = line.strip()
if not line:
continue
if "#" in line:
print(f"Skipping commented line: {line}")
continue
# Split on ' - ', expecting exactly two parts
parts = line.split(' - ')
if len(parts) != 2:
print(f"Skipping invalid line: {line}")
continue
username, entry = (p.replace("'", "''") for p in parts) # Escape single quotes
kind = "job"
sql = (
f"INSERT INTO {table_name} (ckey, entry, kind) "
f"VALUES ('{username}', '{entry}', '{kind}');\n"
)
outfile.write(sql)
-1
View File
@@ -1087,7 +1087,6 @@
#include "code\game\jobs\job_controller.dm"
#include "code\game\jobs\jobs.dm"
#include "code\game\jobs\whitelist.dm"
#include "code\game\jobs\whitelist_vr.dm"
#include "code\game\jobs\job\_alt_title.dm"
#include "code\game\jobs\job\assistant.dm"
#include "code\game\jobs\job\captain.dm"