Files
Aurora.3/code/modules/admin/banjob.dm
skull132 e4423761ef Admin & Staff adjustments (#2529)
Features:

 Removal of BOREALIS (python module) as it's not used.
 Removes ToR ban feature in lieu of IPIntel.
 New BOREALIS config to alert staff if server starts as hidden.
 Adminhelps now inform admins on discord if dibsed (when they were sent to discord anyways).
 Adds hub visibility to the server access control panel.
 Adds mirror ban spotting via ban panel. It now redirects to the linked ban if one is found.
 CCIAA now get alerted as to how many of them are online and active when receiving faxes and emergency messages via Discord.
 Removed unused C/C++ libraries. The socket_talk module is a generic UDP shipper, of which Arrow implemented a better version. lib nudge is not even compiled for use. lib_nudge module is uncompiled and no longer used, as we use cURL for the bot.
 Removed depracted APIs and config settings related to the previous point.
 Whitelisted jobs now appear properly in the job selection window as [WHITELISTED].
 Job ban reasons can now be viewed from player preferences window.
 Await admin approval for final CCIAA requests and implement. RIP CCIAA.
 Fix age bans for jobs and antags (dynamic ones, ofc).
 Implement https://forums.aurorastation.org/viewtopic.php?f=18&t=8283
2017-06-13 01:37:44 +03:00

782 lines
28 KiB
Plaintext

#define CKEY_OR_MOB(tgt, ref) \
if (istext(ref)) { \
tgt = ckey(ref); \
var/mob/CKM = locate(ref); \
if (CKM && istype(CKM)) { \
if (CKM.ckey) { \
tgt = CKM.ckey; \
} else { \
tgt = null; \
} \
} \
} else if (ismob(ref)) { \
var/mob/CKM = ref; \
tgt = CKM.ckey; \
}
var/list/jobban_keylist = list() // Global jobban list.
/*
* Expected format:
* list("canonckey1" = list("jobname" = list("reason", time),
* "jobname2" = list("reason", time)),
* "canonckey2" = list("jobname" = list("reason", time)))
*
* And yes, this is all actually savefile compatible, as they can load and
* save associated lists quite neatly. Assoc lists remove the stupid amounts
* of for-looping and string searching, and allow you to simply grab a ban with:
*
* jobban_keylist[ckey][job]
*
* If record doesn't exist, he's not banned there. As easy as that.
*
* "time" should be BYOND realtime. For MySQL bans, it's not relevant, so we
* can get away with just using this. For permanent bans, leave 0.
*
* - Skull132, 17APR2017
*/
/**
* Global hook for loading jobbans.
*
* @return num 1
*/
/hook/startup/proc/loadJobBans()
if (config.ban_legacy_system)
jobban_loadbanfile()
else
jobban_loaddatabase()
return 1
/**
* Logs a new jobban for a user.
* Will save the bans to a save file if we're using the legacy system. Otherwise,
* should be called via DB_ban_record.
*
* @param str|mob player The mob object or ckey of the player we're looking for.
* @param str rank The string name of the rank we want to ban the user from.
* @param str reason The reason for the ban.
* @param num minutes The length of the ban in minutes. -1 for permanent.
* @param datum/admins holder The holder of the admin doing the unbanning.
* required to access the DB ban procs.
*/
/proc/jobban_fullban(player, rank, reason, minutes)
var/key = null
CKEY_OR_MOB(key, player)
if (!key)
return
// Create a new record if the client isn't logged already.
if (!jobban_keylist[key])
jobban_keylist[key] = list()
// Sanity catch. This shouldn't happen, but better safe than sorry.
if (jobban_keylist[key][rank] && !jobban_isexpired(jobban_keylist[key][rank], player, rank))
log_and_message_admins("Attempted to apply a jobban to [key] while they already have an active ban. Job: [rank].")
return
// Set the expirey time in case of temp bans.
var/unban_time = minutes
if (minutes > -1)
unban_time = world.realtime + (minutes MINUTES)
// Create the entry.
jobban_keylist[key][rank] = list(reason, unban_time)
// Log the ban to the appropriate place.
if (config.ban_legacy_system)
jobban_savebanfile()
else
DB_ban_record(minutes < 0 ? BANTYPE_JOB_PERMA : BANTYPE_JOB_TEMP, null, minutes, reason, rank, banckey = key)
/**
* Checks if the player attached to the given mob M is banned from
* the given rank. Returns 0 if client is not banned, a reason (str)
* if is banned.
*
* If an antagonist role is sent, then the global "Antagonist" ban rank
* is also checked for.
*
* @param str|mob player The mob object or ckey of the player we're looking for.
* @param str rank The rank name that we're looking for a ban on.
*
* @return mixed str containing the ban reason if user is banned.
* null if user is not banned from given role.
*/
/proc/jobban_isbanned(player, rank)
var/ckey = null
CKEY_OR_MOB(ckey, player)
if (ckey)
if (guest_jobbans(rank))
if (config.guest_jobban && IsGuestKey(ckey))
return "GUEST JOB-BAN"
if (config.usewhitelist && ismob(player) && !check_whitelist(player))
return "WHITELISTED"
var/age_whitelist = player_old_enough_for_role(player, rank)
if (age_whitelist)
return "AGE WHITELISTED"
var/static/list/antag_bantypes
if (isnull(antag_bantypes))
antag_bantypes = list()
for (var/antag_type in all_antag_types)
var/datum/antagonist/antag = all_antag_types[antag_type]
if (antag && antag.bantype)
antag_bantypes |= antag.bantype
// We manage antagonist bans at this end point.
// Alternative is to manage it at each call to jobban_isbanned, however,
// there is no actual reason why you should be able to play an antag if you're banned from all of them.
var/antag_ban = FALSE
if (rank in antag_bantypes)
antag_ban = TRUE
// Get the user's ckey.
var/list/entry = jobban_keylist[ckey]
// If this is false, then we have no entry. As such, they have no active
// bans!
if (entry)
// Look for the rank specific ban.
var/list/ban = entry[rank]
// We have it, return it!
if (ban && !jobban_isexpired(ban, player, rank))
return ban[1]
// Catch for global antagonist bans as a failsafe.
if (antag_ban)
ban = entry["Antagonist"]
if (ban && !jobban_isexpired(ban, player, rank))
return ban[1]
return null
/**
* @name jobban_loadbanfile()
* @desc Loads all currently saved jobbans from the data/job_full.ban file.
*
* @return null
*/
/proc/jobban_loadbanfile()
var/savefile/S = new("data/job_full.ban")
S["bans"] >> jobban_keylist
log_admin("Loading jobban_rank")
if (!jobban_keylist)
jobban_keylist = list()
log_admin("jobban_keylist was empty")
/**
* Loads all currently active bans from the database. Sets expiration
* times to 0, as the query refreshes records every time it's pulled.
* Unlike the hard file bans.
*/
/proc/jobban_loaddatabase()
// No database. Weee.
if (!establish_db_connection(dbcon))
error("Database connection failed. Reverting to the legacy ban system.")
log_misc("Database connection failed. Reverting to the legacy ban system.")
config.ban_legacy_system = 1
jobban_loadbanfile()
return
// All jobbans in one query. Because we don't actually care.
var/DBQuery/query = dbcon.NewQuery("SELECT id, ckey, job, reason FROM ss13_ban WHERE isnull(unbanned) AND ((bantype = 'JOB_PERMABAN') OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now()))")
query.Execute()
while (query.NextRow())
var/ckey = ckey(query.item[2])
var/job = query.item[3]
var/reason = query.item[4]
if (!jobban_keylist[ckey])
jobban_keylist[ckey] = list()
if (!jobban_keylist[ckey][job])
// Insert it with 0 time because the expiration of a temp jobban for
// MySQL is dependent on the database and query itself. So we can just
// politely not care.
jobban_keylist[ckey][job] = list(reason, -1)
else
// Woups. What happened here...?
log_and_message_admins("JOBBANS: Duplicate jobban entry in MySQL for [ckey]. Ban ID: #[query.item[1]]")
/**
* Saves the current bans into the data/job_full.ban file.
*/
/proc/jobban_savebanfile()
var/savefile/S = new("data/job_full.ban")
S["bans"] << jobban_keylist
/**
* Removes a jobban entry from the code and calls the config appropriate
* record removal method. In case of legacy bans, jobban file is updated.
*
* For the DB system, the DB_ban_unban_by_id method calls this to remove the local
* instance of the ban.
*
* @param str|mob player The mob object or ckey of the player we're looking for.
* @param str rank The job from which we want to unban the given player.
*/
/proc/jobban_unban(player, rank)
var/ckey = null
CKEY_OR_MOB(ckey, player)
if (!ckey)
log_debug("JOBBAN: jobban_unban called without a mob and a backup ckey.")
return
// Check for a player record.
var/list/entry = jobban_keylist[ckey]
if (entry)
// Find the specific ban.
var/list/ban = entry[rank]
if (ban)
// Remove said ban. Lists pass by ref, so this is fine.
entry[rank] = null
entry -= rank
// If the entry is now empty, remove the entire ckey from the list.
if (!entry.len)
jobban_keylist[ckey] = null
jobban_keylist -= ckey
// Update appropriate ban files.
if (config.ban_legacy_system)
jobban_savebanfile()
/**
* Checks whether or not a jobban is expired. If a ban is expired,
* it'll call jobban_unban to lift the ban. This allows for temporary
* jobbans with the old file system.
*
* Does not work on the MySQL system. The bans for that refresh every
* round, as per the queries.
*
* @param list tuple The list containing reason and expiery time to check.
* @param str|mob player The mob object or ckey of the player we're looking for.
* @param str rank The job we're checking. To be passed into jobban_unban in case
* of an expired ban.
*
* @return num TRUE if ban is expired.
* FALSE if ban is not expired.
*/
/proc/jobban_isexpired(var/list/tuple, var/player, var/rank)
if (config.ban_legacy_system && tuple[2] && (tuple[2] > 0) && (tuple[2] < world.realtime))
// It's expired. Remove it.
jobban_unban(player, rank)
return TRUE
return FALSE
/**
* Updates the ban_unban_log.txt file by appending formatted_log to its
* contents.
*
* @param str formatted_log The new content to be appended to the log file.
*/
/proc/ban_unban_log_save(var/formatted_log)
text2file(formatted_log, "data/ban_unban_log.txt")
/**
* Opens the jobban panel, showing the bans of the passed mob or ckey.
*
* @param str|mob tgt_ref The target we want to view jobbans of. Can be a reference
* to a mob object (gotten with \ref[M]) or an actual mob object.
*/
/datum/admins/proc/jobban_panel(var/tgt_ref = null)
if (!tgt_ref)
return
// Check against usr's perms.
if (!check_rights(R_ADMIN|R_MOD|R_BAN))
return
var/ckey = null
CKEY_OR_MOB(ckey, tgt_ref)
if (!ckey)
to_chat(src.owner, "This mob has no ckey.")
return
var/dat = ""
var/header = "<head><title>Job-Ban Panel: [ckey]</title></head>"
var/body
var/jobs = ""
/***********************************WARNING!************************************
The jobban stuff looks mangled and disgusting
But it looks beautiful in-game
-Nodrak
************************************WARNING!***********************************/
var/counter = 0
//Regular jobs
//Command (Blue)
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr align='center' bgcolor='ccccff'><th colspan='[length(command_positions)]'><a href='?src=\ref[src];jobban_job=commanddept;jobban_tgt=[ckey]'>Command Positions</a></th></tr><tr align='center'>"
for (var/jobPos in command_positions)
if (!jobPos)
continue
var/datum/job/job = SSjobs.GetJob(jobPos)
if (!job)
continue
if (jobban_isbanned(ckey, job.title))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'><font color=red>[replacetext(job.title, " ", "&nbsp")]</font></a></td>"
counter++
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'>[replacetext(job.title, " ", "&nbsp")]</a></td>"
counter++
if (counter >= 6) //So things dont get squiiiiished!
jobs += "</tr><tr>"
counter = 0
jobs += "</tr></table>"
//Security (Red)
counter = 0
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='ffddf0'><th colspan='[length(security_positions)]'><a href='?src=\ref[src];jobban_job=securitydept;jobban_tgt=[ckey]'>Security Positions</a></th></tr><tr align='center'>"
for (var/jobPos in security_positions)
if (!jobPos)
continue
var/datum/job/job = SSjobs.GetJob(jobPos)
if (!job)
continue
if (jobban_isbanned(ckey, job.title))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'><font color=red>[replacetext(job.title, " ", "&nbsp")]</font></a></td>"
counter++
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'>[replacetext(job.title, " ", "&nbsp")]</a></td>"
counter++
if (counter >= 5) //So things dont get squiiiiished!
jobs += "</tr><tr align='center'>"
counter = 0
jobs += "</tr></table>"
//Engineering (Yellow)
counter = 0
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='fff5cc'><th colspan='[length(engineering_positions)]'><a href='?src=\ref[src];jobban_job=engineeringdept;jobban_tgt=[ckey]'>Engineering Positions</a></th></tr><tr align='center'>"
for (var/jobPos in engineering_positions)
if (!jobPos)
continue
var/datum/job/job = SSjobs.GetJob(jobPos)
if (!job)
continue
if (jobban_isbanned(ckey, job.title))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'><font color=red>[replacetext(job.title, " ", "&nbsp")]</font></a></td>"
counter++
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'>[replacetext(job.title, " ", "&nbsp")]</a></td>"
counter++
if (counter >= 5) //So things dont get squiiiiished!
jobs += "</tr><tr align='center'>"
counter = 0
jobs += "</tr></table>"
//Medical (White)
counter = 0
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='ffeef0'><th colspan='[length(medical_positions)]'><a href='?src=\ref[src];jobban_job=medicaldept;jobban_tgt=[ckey]'>Medical Positions</a></th></tr><tr align='center'>"
for (var/jobPos in medical_positions)
if (!jobPos)
continue
var/datum/job/job = SSjobs.GetJob(jobPos)
if (!job)
continue
if (jobban_isbanned(ckey, job.title))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'><font color=red>[replacetext(job.title, " ", "&nbsp")]</font></a></td>"
counter++
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'>[replacetext(job.title, " ", "&nbsp")]</a></td>"
counter++
if (counter >= 5) //So things dont get squiiiiished!
jobs += "</tr><tr align='center'>"
counter = 0
jobs += "</tr></table>"
//Science (Purple)
counter = 0
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='e79fff'><th colspan='[length(science_positions)]'><a href='?src=\ref[src];jobban_job=sciencedept;jobban_tgt=[ckey]'>Science Positions</a></th></tr><tr align='center'>"
for (var/jobPos in science_positions)
if (!jobPos)
continue
var/datum/job/job = SSjobs.GetJob(jobPos)
if (!job)
continue
if (jobban_isbanned(ckey, job.title))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'><font color=red>[replacetext(job.title, " ", "&nbsp")]</font></a></td>"
counter++
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'>[replacetext(job.title, " ", "&nbsp")]</a></td>"
counter++
if (counter >= 5) //So things dont get squiiiiished!
jobs += "</tr><tr align='center'>"
counter = 0
jobs += "</tr></table>"
//Cargo (Brown ish)
counter = 0
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='f49d50'><th colspan='[length(cargo_positions)]'><a href='?src=\ref[src];jobban_job=cargodept;jobban_tgt=[ckey]'>Cargo Positions</a></th></tr><tr align='center'>"
for (var/jobPos in cargo_positions)
if (!jobPos)
continue
var/datum/job/job = SSjobs.GetJob(jobPos)
if (!job)
continue
if (jobban_isbanned(ckey, job.title))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'><font color=red>[replacetext(job.title, " ", "&nbsp")]</font></a></td>"
counter++
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'>[replacetext(job.title, " ", "&nbsp")]</a></td>"
counter++
if (counter >= 5)
jobs += "</tr><tr align='center'>"
counter = 0
//Civilian (Grey)
counter = 0
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='dddddd'><th colspan='[length(civilian_positions)]'><a href='?src=\ref[src];jobban_job=civiliandept;jobban_tgt=[ckey]'>Civilian Positions</a></th></tr><tr align='center'>"
for (var/jobPos in civilian_positions)
if (!jobPos)
continue
var/datum/job/job = SSjobs.GetJob(jobPos)
if (!job)
continue
if (jobban_isbanned(ckey, job.title))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'><font color=red>[replacetext(job.title, " ", "&nbsp")]</font></a></td>"
counter++
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'>[replacetext(job.title, " ", "&nbsp")]</a></td>"
counter++
if (counter >= 5) //So things dont get squiiiiished!
jobs += "</tr><tr align='center'>"
counter = 0
if (jobban_isbanned(ckey, "Internal Affairs Agent"))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=Internal Affairs Agent;jobban_tgt=[ckey]'><font color=red>Internal Affairs Agent</font></a></td>"
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=Internal Affairs Agent;jobban_tgt=[ckey]'>Internal Affairs Agent</a></td>"
jobs += "</tr></table>"
//Non-Human (Green)
counter = 0
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='ccffcc'><th colspan='[length(nonhuman_positions)+1]'><a href='?src=\ref[src];jobban_job=nonhumandept;jobban_tgt=[ckey]'>Non-human Positions</a></th></tr><tr align='center'>"
for (var/jobPos in nonhuman_positions)
if (!jobPos)
continue
var/datum/job/job = SSjobs.GetJob(jobPos)
if (!job)
continue
if (jobban_isbanned(ckey, job.title))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'><font color=red>[replacetext(job.title, " ", "&nbsp")]</font></a></td>"
counter++
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[job.title];jobban_tgt=[ckey]'>[replacetext(job.title, " ", "&nbsp")]</a></td>"
counter++
if (counter >= 5) //So things dont get squiiiiished!
jobs += "</tr><tr align='center'>"
counter = 0
//pAI isn't technically a job, but it goes in here.
if (jobban_isbanned(ckey, "pAI"))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=pAI;jobban_tgt=[ckey]'><font color=red>pAI</font></a></td>"
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=pAI;jobban_tgt=[ckey]'>pAI</a></td>"
if (jobban_isbanned(ckey, "AntagHUD"))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=AntagHUD;jobban_tgt=[ckey]'><font color=red>AntagHUD</font></a></td>"
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=AntagHUD;jobban_tgt=[ckey]'>AntagHUD</a></td>"
jobs += "</tr></table>"
//Antagonist (Orange)
var/isbanned_dept = jobban_isbanned(ckey, "Antagonist")
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='ffeeaa'><th colspan='10'><a href='?src=\ref[src];jobban_job=Antagonist;jobban_tgt=[ckey]'>Antagonist Positions</a></th></tr><tr align='center'>"
// Antagonists.
counter = 0
for (var/antag_type in all_antag_types)
var/datum/antagonist/antag = all_antag_types[antag_type]
if (!antag || !antag.bantype)
continue
if (isbanned_dept || jobban_isbanned(ckey, antag.bantype))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[antag.bantype];jobban_tgt=[ckey]'><font color=red>[replacetext("[antag.role_text]", " ", "&nbsp")]</font></a></td>"
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=[antag.bantype];jobban_tgt=[ckey]'>[replacetext("[antag.role_text]", " ", "&nbsp")]</a></td>"
counter++
if (counter >= 5) //So things dont get squiiiiished!
jobs += "</tr><tr align='center'>"
counter = 0
jobs += "</tr></table>"
//Other races (BLUE, because I have no idea what other color to make this)
jobs += "<table cellpadding='1' cellspacing='0' width='100%'>"
jobs += "<tr bgcolor='ccccff'><th colspan='1'>Other Races</th></tr><tr align='center'>"
if (jobban_isbanned(ckey, "Dionaea"))
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=Dionaea;jobban_tgt=[ckey]'><font color=red>Dionaea</font></a></td>"
else
jobs += "<td width='20%'><a href='?src=\ref[src];jobban_job=Dionaea;jobban_tgt=[ckey]'>Dionaea</a></td>"
jobs += "</tr></table>"
body = "<body>[jobs]</body>"
dat = "<tt>[header][body]</tt>"
usr << browse(dat, "window=jobban_panel;size=800x490")
return
/**
* Handles the insertion of a new job ban. Currently called from /datum/admins/Topic().
*
* Relays a new ban to jobban_fullban and also manages database insertions where needed.
*
* @param str tgt_ref The \ref[] of the target mob we want to dinbannu.
* @param str job The name of the job we want to ban the target from.
*
* @return num 1 if something was done.
* 0 otherwise.
*/
/datum/admins/proc/jobban_handle(var/tgt_ref, var/job)
if (!check_rights(R_MOD, 0) && !check_rights(R_ADMIN, 0))
to_chat(usr, "<span class='warning'>You do not have the appropriate permissions to add job bans!</span>")
return 0
if (check_rights(R_MOD, 0) && !check_rights(R_ADMIN, 0) && !config.mods_can_job_tempban) // If mod and tempban disabled
to_chat(usr, "<span class='warning'>Mod jobbanning is disabled!</span>")
return 0
var/ckey = null
CKEY_OR_MOB(ckey, tgt_ref)
if (!ckey)
to_chat(usr, "<span class='warning'>No valid target sent. Cancelling.</span>")
return 0
if (admin_datums[ckey])
if (ckey != usr.ckey) //we can jobban ourselves
var/datum/admins/other_holder = admin_datums[ckey]
if(other_holder && (other_holder.rights & R_BAN)) //they can ban too. So we can't ban them
alert("You cannot perform this action. You must be of a higher administrative rank!")
return 0
//get jobs for department if specified, otherwise just returnt he one job in a list.
var/list/joblist = list()
switch (job)
if ("commanddept")
for (var/jobPos in command_positions)
if (!jobPos)
continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if (!temp)
continue
joblist += temp.title
if ("securitydept")
for (var/jobPos in security_positions)
if (!jobPos)
continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if (!temp)
continue
joblist += temp.title
if ("engineeringdept")
for (var/jobPos in engineering_positions)
if (!jobPos)
continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if (!temp)
continue
joblist += temp.title
if ("medicaldept")
for (var/jobPos in medical_positions)
if (!jobPos)
continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if (!temp)
continue
joblist += temp.title
if ("sciencedept")
for (var/jobPos in science_positions)
if (!jobPos)
continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if (!temp)
continue
joblist += temp.title
if ("civiliandept")
for (var/jobPos in civilian_positions)
if (!jobPos)
continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if (!temp)
continue
joblist += temp.title
if ("nonhumandept")
joblist += "pAI"
for (var/jobPos in nonhuman_positions)
if (!jobPos)
continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if (!temp)
continue
joblist += temp.title
if ("cargodept")
for (var/jobPos in cargo_positions)
if (!jobPos)
continue
var/datum/job/temp = SSjobs.GetJob(jobPos)
if (!temp)
continue
joblist += temp.title
else
joblist += job
//Create a list of unbanned jobs within joblist
var/list/notbannedlist = list()
for (var/R in joblist)
if (!jobban_isbanned(ckey, R))
notbannedlist += R
//Banning comes first
if (notbannedlist.len) //at least 1 unbanned job exists in joblist so we have stuff to ban.
switch (alert("Temporary Ban?",,"Yes","No", "Cancel"))
if ("Yes")
if (!check_rights(R_MOD,0) && !check_rights(R_BAN, 0))
to_chat(usr, "<span class='warning'>You Cannot issue temporary job-bans!</span>")
return 0
var/mins = input(usr, "How long (in minutes)?", "Ban time", 1440) as num|null
if (!mins)
return 0
if (check_rights(R_MOD, 0) && !check_rights(R_BAN, 0) && mins > config.mod_job_tempban_max)
to_chat(usr, "<span class='warning'>Moderators can only job tempban up to [config.mod_job_tempban_max] minutes!</span>")
return 0
var/reason = sanitize(input(usr,"Reason?","Please State Reason","") as text|null)
if (!reason)
return 0
var/msg
for (var/R in notbannedlist)
ban_unban_log_save("[key_name(usr)] temp-jobbanned [ckey] from [R] for [mins] minutes. reason: [reason]")
log_admin("[key_name(usr)] temp-jobbanned [ckey] from [R] for [mins] minutes",admin_key=key_name(usr))
feedback_inc("ban_job_tmp", 1)
feedback_add_details("ban_job_tmp","- [R]")
jobban_fullban(ckey, R, reason, mins)
if (!msg)
msg = R
else
msg += ", [R]"
if (config.ban_legacy_system)
notes_add(ckey, "Banned from [msg] - [reason]", usr)
else
notes_add_sql(ckey, "Banned from [msg] - [reason]", usr)
message_admins("<span class='notice'>[key_name_admin(usr)] banned [ckey] from [msg] for [mins] minutes.</span>", 1)
if (ismob(tgt_ref))
var/mob/M = tgt_ref
to_chat(M, "<span class='danger'><BIG>You have been jobbanned by [usr.client.ckey] from: [msg].</BIG></span>")
to_chat(M, "<span class='danger'>The reason is: [reason]</span>")
to_chat(M, "<span class='warning'>This jobban will be lifted in [mins] minutes.</span>")
jobban_panel(ckey)
return 1
if ("No")
if (!check_rights(R_BAN))
return
var/reason = sanitize(input(usr,"Reason?","Please State Reason","") as text|null)
if (reason)
var/msg
for (var/R in notbannedlist)
ban_unban_log_save("[key_name(usr)] perma-jobbanned [ckey] from [R]. reason: [reason]")
log_admin("[key_name(usr)] perma-banned [ckey] from [R]",admin_key=key_name(usr))
feedback_inc("ban_job", 1)
feedback_add_details("ban_job", "- [R]")
jobban_fullban(ckey, R, reason, -1)
if (!msg)
msg = R
else
msg += ", [R]"
if (config.ban_legacy_system)
notes_add(ckey, "Banned from [msg] - [reason]", usr)
else
notes_add_sql(ckey, "Banned from [msg] - [reason]", usr)
message_admins("<span class='notice'>[key_name_admin(usr)] banned [ckey] from [msg]</span>", 1)
if (ismob(tgt_ref))
var/mob/M = tgt_ref
to_chat(M, "<span class='danger'><BIG>You have been jobbanned by [usr.client.ckey] from: [msg].</BIG></span>")
to_chat(M, "<span class='danger'>The reason is: [reason]</span>")
to_chat(M, "<span class='warning'>Jobban can be lifted only upon request.</span>")
jobban_panel(ckey)
return 1
if("Cancel")
return
//Unbanning joblist
//all jobs in joblist are banned already OR we didn't give a reason (implying they shouldn't be banned)
if (joblist.len) //at least 1 banned job exists in joblist so we have stuff to unban.
if (!config.ban_legacy_system)
// This is important. jobban_unban() can't actually lift DB bans. So the DB unban
// panel must be used instead.
to_chat(usr, "Unfortunately, database based unbanning cannot be done through this panel")
DB_ban_panel(ckey)
return 0
var/msg
for (var/R in joblist)
var/reason = jobban_isbanned(ckey, R)
if (!reason)
continue //skip if it isn't jobbanned anyway
switch (alert("Job: '[R]' Reason: '[reason]' Un-jobban?","Please Confirm","Yes","No"))
if ("Yes")
ban_unban_log_save("[key_name(usr)] unjobbanned [ckey] from [R]")
log_admin("[key_name(usr)] unbanned [ckey] from [R]",admin_key=key_name(usr),ckey=ckey)
jobban_unban(ckey, R) // Refer to the jobban API.
feedback_inc("ban_job_unban",1)
feedback_add_details("ban_job_unban","- [R]")
if (!msg)
msg = R
else
msg += ", [R]"
else
continue
if (msg)
message_admins("<span class='notice'>[key_name_admin(usr)] unbanned [ckey] from [msg]</span>", 1)
if (ismob(tgt_ref))
var/mob/M = tgt_ref
to_chat(M, "<span class='danger'><BIG>You have been un-jobbanned by [usr.client.ckey] from [msg].</BIG></span>")
jobban_panel(ckey)
return 1
return 0 //we didn't do anything!
#undef CKEY_OR_MOB