/proc/create_message(type, target_ckey, admin_ckey, text, timestamp, server, secret, logged = 1, browse)
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
if(!type)
return
if(!target_ckey && (type == "note" || type == "message" || type == "watchlist entry"))
var/new_ckey = ckey(input(usr,"Who would you like to create a [type] for?","Enter a ckey",null) as null|text)
if(!new_ckey)
return
new_ckey = sanitizeSQL(new_ckey)
var/datum/DBQuery/query_find_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
if(!query_find_ckey.warn_execute())
return
if(!query_find_ckey.NextRow())
if(alert(usr, "[new_ckey] has not been seen before, are you sure you want to create a [type] for them?", "Unknown ckey", "Yes", "No", "Cancel") != "Yes")
return
target_ckey = new_ckey
if(target_ckey)
target_ckey = sanitizeSQL(target_ckey)
if(!admin_ckey)
admin_ckey = usr.ckey
if(!admin_ckey)
return
admin_ckey = sanitizeSQL(admin_ckey)
if(!target_ckey)
target_ckey = admin_ckey
if(!text)
text = input(usr,"Write your [type]","Create [type]") as null|message
if(!text)
return
text = sanitizeSQL(text)
if(!timestamp)
timestamp = SQLtime()
if(!server)
if (config && config.server_sql_name)
server = config.server_sql_name
server = sanitizeSQL(server)
if(isnull(secret))
switch(alert("Hide note from being viewed by players?", "Secret note?","Yes","No","Cancel"))
if("Yes")
secret = 1
if("No")
secret = 0
else
return
var/datum/DBQuery/query_create_message = SSdbcore.NewQuery("INSERT INTO [format_table_name("messages")] (type, targetckey, adminckey, text, timestamp, server, server_ip, server_port, round_id, secret) VALUES ('[type]', '[target_ckey]', '[admin_ckey]', '[text]', '[timestamp]', '[server]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]','[secret]')")
if(!query_create_message.warn_execute())
return
if(logged)
log_admin_private("[key_name(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]: [text]")
var/header = "[key_name_admin(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]"
message_admins("[header]:
[text]")
admin_ticket_log(target_ckey, "[header]")
admin_ticket_log(target_ckey, text)
if(browse)
browse_messages("[type]")
else
browse_messages(target_ckey = target_ckey, agegate = TRUE)
/proc/delete_message(message_id, logged = 1, browse)
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
message_id = text2num(message_id)
if(!message_id)
return
var/type
var/target_ckey
var/text
var/datum/DBQuery/query_find_del_message = SSdbcore.NewQuery("SELECT type, targetckey, adminckey, text FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
if(!query_find_del_message.warn_execute())
return
if(query_find_del_message.NextRow())
type = query_find_del_message.item[1]
target_ckey = query_find_del_message.item[2]
text = query_find_del_message.item[4]
var/datum/DBQuery/query_del_message = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET deleted = 1 WHERE id = [message_id]")
if(!query_del_message.warn_execute())
return
if(logged)
log_admin_private("[key_name(usr)] has deleted a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for" : " made by"] [target_ckey]: [text]")
message_admins("[key_name_admin(usr)] has deleted a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for" : " made by"] [target_ckey]:
[text]")
if(browse)
browse_messages("[type]")
else
browse_messages(target_ckey = target_ckey, agegate = TRUE)
/proc/edit_message(message_id, browse)
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
message_id = text2num(message_id)
if(!message_id)
return
var/datum/DBQuery/query_find_edit_message = SSdbcore.NewQuery("SELECT type, targetckey, adminckey, text FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
if(!query_find_edit_message.warn_execute())
return
if(query_find_edit_message.NextRow())
var/type = query_find_edit_message.item[1]
var/target_ckey = query_find_edit_message.item[2]
var/admin_ckey = query_find_edit_message.item[3]
var/old_text = query_find_edit_message.item[4]
var/editor_ckey = sanitizeSQL(usr.ckey)
var/new_text = input("Input new [type]", "New [type]", "[old_text]") as null|message
if(!new_text)
return
new_text = sanitizeSQL(new_text)
var/edit_text = sanitizeSQL("Edited by [editor_ckey] on [SQLtime()] from
[old_text]
to
[new_text]
")
var/datum/DBQuery/query_edit_message = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET text = '[new_text]', lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id] AND deleted = 0")
if(!query_edit_message.warn_execute())
return
log_admin_private("[key_name(usr)] has edited a [type] [(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""] made by [admin_ckey] from [old_text] to [new_text]")
message_admins("[key_name_admin(usr)] has edited a [type] [(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""] made by [admin_ckey] from
[old_text]
to
[new_text]")
if(browse)
browse_messages("[type]")
else
browse_messages(target_ckey = target_ckey, agegate = TRUE)
/proc/toggle_message_secrecy(message_id)
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
message_id = text2num(message_id)
if(!message_id)
return
var/datum/DBQuery/query_find_message_secret = SSdbcore.NewQuery("SELECT type, targetckey, adminckey, secret FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
if(!query_find_message_secret.warn_execute())
return
if(query_find_message_secret.NextRow())
var/type = query_find_message_secret.item[1]
var/target_ckey = query_find_message_secret.item[2]
var/admin_ckey = query_find_message_secret.item[3]
var/secret = text2num(query_find_message_secret.item[4])
var/editor_ckey = sanitizeSQL(usr.ckey)
var/edit_text = "Made [secret ? "not secret" : "secret"] by [editor_ckey] on [SQLtime()]
"
var/datum/DBQuery/query_message_secret = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET secret = NOT secret, lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id]")
if(!query_message_secret.warn_execute())
return
log_admin_private("[key_name(usr)] has toggled [target_ckey]'s [type] made by [admin_ckey] to [secret ? "not secret" : "secret"]")
message_admins("[key_name_admin(usr)] has toggled [target_ckey]'s [type] made by [admin_ckey] to [secret ? "not secret" : "secret"]")
browse_messages(target_ckey = target_ckey, agegate = TRUE)
/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE)
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
var/output
var/ruler = "
"
var/navbar = "\[All\]|\[#\]"
for(var/letter in GLOB.alphabet)
navbar += "|\[[letter]\]"
navbar += "|\[Memos\]|\[Watchlist\]"
navbar += "
"
if(!linkless)
output = navbar
if(type == "memo" || type == "watchlist entry")
if(type == "memo")
output += "Admin memos
"
output += "\[Add memo\]"
else if(type == "watchlist entry")
output += "Watchlist entries
"
output += "\[Add watchlist entry\]"
if(filter)
output += "|\[Unfilter clients\]"
else
output += "|\[Filter offline clients\]"
output += ruler
var/datum/DBQuery/query_get_type_messages = SSdbcore.NewQuery("SELECT id, targetckey, adminckey, text, timestamp, server, lasteditor FROM [format_table_name("messages")] WHERE type = '[type]' AND deleted = 0")
if(!query_get_type_messages.warn_execute())
return
while(query_get_type_messages.NextRow())
var/id = query_get_type_messages.item[1]
var/t_ckey = query_get_type_messages.item[2]
if(type == "watchlist entry" && filter && !(t_ckey in GLOB.directory))
continue
var/admin_ckey = query_get_type_messages.item[3]
var/text = query_get_type_messages.item[4]
var/timestamp = query_get_type_messages.item[5]
var/server = query_get_type_messages.item[6]
var/editor_ckey = query_get_type_messages.item[7]
output += ""
if(type == "watchlist entry")
output += "[t_ckey] | "
output += "[timestamp] | [server] | [admin_ckey]"
output += " \[Delete\]"
output += " \[Edit\]"
if(editor_ckey)
output += " Last edit by [editor_ckey] (Click here to see edit log)"
output += "
[text]
"
if(target_ckey)
target_ckey = sanitizeSQL(target_ckey)
var/datum/DBQuery/query_get_messages = SSdbcore.NewQuery("SELECT type, secret, id, adminckey, text, timestamp, server, lasteditor, DATEDIFF(NOW(), timestamp) AS `age` FROM [format_table_name("messages")] WHERE type <> 'memo' AND targetckey = '[target_ckey]' AND deleted = 0 ORDER BY timestamp DESC")
if(!query_get_messages.warn_execute())
return
var/messagedata
var/watchdata
var/notedata
var/skipped = 0
while(query_get_messages.NextRow())
type = query_get_messages.item[1]
if(type == "memo")
continue
var/secret = text2num(query_get_messages.item[2])
if(linkless && secret)
continue
var/id = query_get_messages.item[3]
var/admin_ckey = query_get_messages.item[4]
var/text = query_get_messages.item[5]
var/timestamp = query_get_messages.item[6]
var/server = query_get_messages.item[7]
var/editor_ckey = query_get_messages.item[8]
var/age = text2num(query_get_messages.item[9])
var/alphatext = ""
if (agegate && type == "note" && isnum(config.note_stale_days) && isnum(config.note_fresh_days) && config.note_stale_days > config.note_fresh_days)
var/alpha = Clamp(100 - (age - config.note_fresh_days) * (85 / (config.note_stale_days - config.note_fresh_days)), 15, 100)
if (alpha < 100)
if (alpha <= 15)
if (skipped)
skipped++
continue
alpha = 10
skipped = TRUE
alphatext = "filter: alpha(opacity=[alpha]); opacity: [alpha/100];"
var/data
data += " [timestamp] | [server] | [admin_ckey]"
if(!linkless)
data += " \[Delete\]"
if(type == "note")
data += " [secret ? "\[Secret\]" : "\[Not secret\]"]"
if(type == "message sent")
data += " Message has been sent"
if(editor_ckey)
data += "|"
else
data += " \[Edit\]"
if(editor_ckey)
data += " Last edit by [editor_ckey] (Click here to see edit log)"
data += "
[text]
"
switch(type)
if("message")
messagedata += data
if("message sent")
messagedata += data
if("watchlist entry")
watchdata += data
if("note")
notedata += data
output += "[target_ckey]
"
if(!linkless)
output += "\[Add note\]"
output += " \[Add message\]"
output += " \[Add to watchlist\]"
output += " \[Refresh page\]"
else
output += " \[Refresh page\]"
output += ruler
if(messagedata)
output += "Messages
"
output += messagedata
if(watchdata)
output += "Watchlist
"
output += watchdata
if(notedata)
output += "Notes
"
output += notedata
if(!linkless)
if (agegate)
if (skipped) //the first skipped message is still shown so that we can put this link over it.
output += " \[Show [skipped] hidden messages\]"
else
output += " \[Show All\]"
else
output += " \[Hide Old\]"
if(index)
var/index_ckey
var/search
output += "\[Add message\]\[Add watchlist entry\]\[Add note\]"
output += ruler
if(!isnum(index))
index = sanitizeSQL(index)
switch(index)
if(1)
search = "^."
if(2)
search = "^\[^\[:alpha:\]\]"
else
search = "^[index]"
var/datum/DBQuery/query_list_messages = SSdbcore.NewQuery("SELECT DISTINCT targetckey FROM [format_table_name("messages")] WHERE type <> 'memo' AND targetckey REGEXP '[search]' AND deleted = 0 ORDER BY targetckey")
if(!query_list_messages.warn_execute())
return
while(query_list_messages.NextRow())
index_ckey = query_list_messages.item[1]
output += "[index_ckey]
"
else if(!type && !target_ckey && !index)
output += " \[Add message\]\[Add watchlist entry\]\[Add note\]"
output += ruler
usr << browse({"[output]"}, "window=browse_messages;size=900x500")
proc/get_message_output(type, target_ckey)
if(!SSdbcore.Connect())
to_chat(usr, "Failed to establish database connection.")
return
if(!type)
return
var/output
if(target_ckey)
target_ckey = sanitizeSQL(target_ckey)
var/query = "SELECT id, adminckey, text, timestamp, lasteditor FROM [format_table_name("messages")] WHERE type = '[type]' AND deleted = 0"
if(type == "message" || type == "watchlist entry")
query += " AND targetckey = '[target_ckey]'"
var/datum/DBQuery/query_get_message_output = SSdbcore.NewQuery(query)
if(!query_get_message_output.warn_execute())
return
while(query_get_message_output.NextRow())
var/message_id = query_get_message_output.item[1]
var/admin_ckey = query_get_message_output.item[2]
var/text = query_get_message_output.item[3]
var/timestamp = query_get_message_output.item[4]
var/editor_ckey = query_get_message_output.item[5]
switch(type)
if("message")
output += "Admin message left by [admin_ckey] on [timestamp]"
output += "
[text]
"
var/datum/DBQuery/query_message_read = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET type = 'message sent' WHERE id = [message_id]")
if(!query_message_read.warn_execute())
return
if("watchlist entry")
message_admins("Notice: [key_name_admin(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
send2irc_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
if("memo")
output += "Memo by [admin_ckey] on [timestamp]"
if(editor_ckey)
output += "
Last edit by [editor_ckey] (Click here to see edit log)"
output += "
[text]
"
return output
#define NOTESFILE "data/player_notes.sav"
//if the AUTOCONVERT_NOTES is turned on, anytime a player connects this will be run to try and add all their notes to the databas
/proc/convert_notes_sql(ckey)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile)
log_game("Error: Cannot access [NOTESFILE]")
return
notesfile.cd = "/[ckey]"
while(!notesfile.eof)
var/notetext
notesfile >> notetext
var/server
if(config && config.server_sql_name)
server = config.server_sql_name
var/regex/note = new("^(\\d{2}-\\w{3}-\\d{4}) \\| (.+) ~(\\w+)$", "i")
note.Find(notetext)
var/timestamp = note.group[1]
notetext = note.group[2]
var/admin_ckey = note.group[3]
var/datum/DBQuery/query_convert_time = SSdbcore.NewQuery("SELECT ADDTIME(STR_TO_DATE('[timestamp]','%d-%b-%Y'), '0')")
if(!query_convert_time.Execute())
return
if(query_convert_time.NextRow())
timestamp = query_convert_time.item[1]
if(ckey && notetext && timestamp && admin_ckey && server)
create_message("note", ckey, admin_ckey, notetext, timestamp, server, 1, 0)
notesfile.cd = "/"
notesfile.dir.Remove(ckey)
/*alternatively this proc can be run once to pass through every note and attempt to convert it before deleting the file, if done then AUTOCONVERT_NOTES should be turned off
this proc can take several minutes to execute fully if converting and cause DD to hang if converting a lot of notes; it's not advised to do so while a server is live
/proc/mass_convert_notes()
to_chat(world, "Beginning mass note conversion")
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile)
log_game("Error: Cannot access [NOTESFILE]")
return
notesfile.cd = "/"
for(var/ckey in notesfile.dir)
convert_notes_sql(ckey)
to_chat(world, "Deleting NOTESFILE")
fdel(NOTESFILE)
to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES")*/
#undef NOTESFILE