You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

604 lines
31 KiB

  1. /proc/create_message(type, target_key, admin_ckey, text, timestamp, server, secret, logged = 1, browse, expiry, note_severity)
  2. if(!SSdbcore.Connect())
  3. to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
  4. return
  5. if(!type)
  6. return
  7. var/target_ckey = ckey(target_key)
  8. if(!target_key && (type == "note" || type == "message" || type == "watchlist entry"))
  9. var/new_key = input(usr,"Who would you like to create a [type] for?","Enter a key or ckey",null) as null|text
  10. if(!new_key)
  11. return
  12. var/new_ckey = sanitizeSQL(ckey(new_key))
  13. var/datum/DBQuery/query_find_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
  14. if(!query_find_ckey.warn_execute())
  15. qdel(query_find_ckey)
  16. return
  17. if(!query_find_ckey.NextRow())
  18. if(alert(usr, "[new_key]/([new_ckey]) has not been seen before, are you sure you want to create a [type] for them?", "Unknown ckey", "Yes", "No", "Cancel") != "Yes")
  19. qdel(query_find_ckey)
  20. return
  21. qdel(query_find_ckey)
  22. target_ckey = new_ckey
  23. target_key = new_key
  24. if(QDELETED(usr))
  25. return
  26. if(target_ckey)
  27. target_ckey = sanitizeSQL(target_ckey)
  28. if(!target_key)
  29. target_key = target_ckey
  30. if(!admin_ckey)
  31. admin_ckey = usr.ckey
  32. if(!admin_ckey)
  33. return
  34. admin_ckey = sanitizeSQL(admin_ckey)
  35. if(!target_ckey)
  36. target_ckey = admin_ckey
  37. if(!text)
  38. text = input(usr,"Write your [type]","Create [type]") as null|message
  39. if(!text)
  40. return
  41. text = sanitizeSQL(text)
  42. if(!timestamp)
  43. timestamp = SQLtime()
  44. if(!server)
  45. var/ssqlname = CONFIG_GET(string/serversqlname)
  46. if (ssqlname)
  47. server = ssqlname
  48. server = sanitizeSQL(server)
  49. if(isnull(secret))
  50. switch(alert("Hide note from being viewed by players?", "Secret note?","Yes","No","Cancel"))
  51. if("Yes")
  52. secret = 1
  53. if("No")
  54. secret = 0
  55. else
  56. return
  57. if(isnull(expiry))
  58. if(alert(usr, "Set an expiry time? Expired messages are hidden like deleted ones.", "Expiry time?", "Yes", "No", "Cancel") == "Yes")
  59. var/expire_time = input("Set expiry time for [type] as format YYYY-MM-DD HH:MM:SS. All times in server time. HH:MM:SS is optional and 24-hour. Must be later than current time for obvious reasons.", "Set expiry time", SQLtime()) as null|text
  60. if(!expire_time)
  61. return
  62. expire_time = sanitizeSQL(expire_time)
  63. var/datum/DBQuery/query_validate_expire_time = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[expire_time]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[expire_time]','%Y-%c-%d %T'), 0)")
  64. if(!query_validate_expire_time.warn_execute())
  65. qdel(query_validate_expire_time)
  66. return
  67. if(query_validate_expire_time.NextRow())
  68. var/checktime = text2num(query_validate_expire_time.item[1])
  69. if(!checktime)
  70. to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.", confidential = TRUE)
  71. qdel(query_validate_expire_time)
  72. return
  73. expiry = query_validate_expire_time.item[1]
  74. qdel(query_validate_expire_time)
  75. if(type == "note" && isnull(note_severity))
  76. note_severity = input("Set the severity of the note.", "Severity", null, null) as null|anything in list("High", "Medium", "Minor", "None")
  77. if(!note_severity)
  78. return
  79. note_severity = sanitizeSQL(note_severity)
  80. 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, expire_timestamp, severity) 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]', [expiry ? "'[expiry]'" : "NULL"], [note_severity ? "'[note_severity]'" : "NULL"])")
  81. var/pm = "[key_name(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_key]" : ""]: [text]"
  82. var/header = "[key_name_admin(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_key]" : ""]"
  83. if(!query_create_message.warn_execute())
  84. qdel(query_create_message)
  85. return
  86. qdel(query_create_message)
  87. if(logged)
  88. log_admin_private(pm)
  89. message_admins("[header]:<br>[text]")
  90. admin_ticket_log(target_ckey, "<font color='blue'>[header]</font>")
  91. admin_ticket_log(target_ckey, text)
  92. if(browse)
  93. browse_messages("[type]")
  94. else
  95. browse_messages(target_ckey = target_ckey, agegate = TRUE)
  96. /proc/delete_message(message_id, logged = 1, browse)
  97. if(!SSdbcore.Connect())
  98. to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
  99. return
  100. message_id = text2num(message_id)
  101. if(!message_id)
  102. return
  103. var/type
  104. var/target_key
  105. var/text
  106. var/user_key_name = key_name(usr)
  107. var/user_name_admin = key_name_admin(usr)
  108. var/datum/DBQuery/query_find_del_message = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), text FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
  109. if(!query_find_del_message.warn_execute())
  110. qdel(query_find_del_message)
  111. return
  112. if(query_find_del_message.NextRow())
  113. type = query_find_del_message.item[1]
  114. target_key = query_find_del_message.item[2]
  115. text = query_find_del_message.item[3]
  116. qdel(query_find_del_message)
  117. var/datum/DBQuery/query_del_message = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET deleted = 1 WHERE id = [message_id]")
  118. if(!query_del_message.warn_execute())
  119. qdel(query_del_message)
  120. return
  121. qdel(query_del_message)
  122. if(logged)
  123. var/m1 = "[user_key_name] has deleted a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for" : " made by"] [target_key]: [text]"
  124. var/m2 = "[user_name_admin] has deleted a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for" : " made by"] [target_key]:<br>[text]"
  125. log_admin_private(m1)
  126. message_admins(m2)
  127. if(browse)
  128. browse_messages("[type]")
  129. else
  130. browse_messages(target_ckey = ckey(target_key), agegate = TRUE)
  131. /proc/edit_message(message_id, browse)
  132. if(!SSdbcore.Connect())
  133. to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
  134. return
  135. message_id = text2num(message_id)
  136. if(!message_id)
  137. return
  138. var/editor_ckey = sanitizeSQL(usr.ckey)
  139. var/editor_key = sanitizeSQL(usr.key)
  140. var/kn = key_name(usr)
  141. var/kna = key_name_admin(usr)
  142. var/datum/DBQuery/query_find_edit_message = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), targetckey), text FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
  143. if(!query_find_edit_message.warn_execute())
  144. qdel(query_find_edit_message)
  145. return
  146. if(query_find_edit_message.NextRow())
  147. var/type = query_find_edit_message.item[1]
  148. var/target_key = query_find_edit_message.item[2]
  149. var/admin_key = query_find_edit_message.item[3]
  150. var/old_text = query_find_edit_message.item[4]
  151. var/new_text = input("Input new [type]", "New [type]", "[old_text]") as null|message
  152. if(!new_text)
  153. qdel(query_find_edit_message)
  154. return
  155. new_text = sanitizeSQL(new_text)
  156. var/edit_text = sanitizeSQL("Edited by [editor_key] on [SQLtime()] from<br>[old_text]<br>to<br>[new_text]<hr>")
  157. 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")
  158. if(!query_edit_message.warn_execute())
  159. qdel(query_edit_message)
  160. return
  161. qdel(query_edit_message)
  162. log_admin_private("[kn] has edited a [type] [(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_key]" : ""] made by [admin_key] from [old_text] to [new_text]")
  163. message_admins("[kna] has edited a [type] [(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_key]" : ""] made by [admin_key] from<br>[old_text]<br>to<br>[new_text]")
  164. if(browse)
  165. browse_messages("[type]")
  166. else
  167. browse_messages(target_ckey = ckey(target_key), agegate = TRUE)
  168. qdel(query_find_edit_message)
  169. /proc/edit_message_expiry(message_id, browse)
  170. if(!SSdbcore.Connect())
  171. to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
  172. return
  173. message_id = text2num(message_id)
  174. if(!message_id)
  175. return
  176. var/editor_ckey = sanitizeSQL(usr.ckey)
  177. var/editor_key = sanitizeSQL(usr.key)
  178. var/kn = key_name(usr)
  179. var/kna = key_name_admin(usr)
  180. var/datum/DBQuery/query_find_edit_expiry_message = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), expire_timestamp FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
  181. if(!query_find_edit_expiry_message.warn_execute())
  182. qdel(query_find_edit_expiry_message)
  183. return
  184. if(query_find_edit_expiry_message.NextRow())
  185. var/type = query_find_edit_expiry_message.item[1]
  186. var/target_key = query_find_edit_expiry_message.item[2]
  187. var/admin_key = query_find_edit_expiry_message.item[3]
  188. var/old_expiry = query_find_edit_expiry_message.item[4]
  189. var/new_expiry
  190. var/expire_time = input("Set expiry time for [type] as format YYYY-MM-DD HH:MM:SS. All times in server time. HH:MM:SS is optional and 24-hour. Must be later than current time for obvious reasons. Enter -1 to remove expiry time.", "Set expiry time", old_expiry) as null|text
  191. if(!expire_time)
  192. qdel(query_find_edit_expiry_message)
  193. return
  194. if(expire_time == "-1")
  195. new_expiry = "non-expiring"
  196. else
  197. expire_time = sanitizeSQL(expire_time)
  198. var/datum/DBQuery/query_validate_expire_time_edit = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[expire_time]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[expire_time]','%Y-%c-%d %T'), 0)")
  199. if(!query_validate_expire_time_edit.warn_execute())
  200. qdel(query_validate_expire_time_edit)
  201. qdel(query_find_edit_expiry_message)
  202. return
  203. if(query_validate_expire_time_edit.NextRow())
  204. var/checktime = text2num(query_validate_expire_time_edit.item[1])
  205. if(!checktime)
  206. to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.", confidential = TRUE)
  207. qdel(query_validate_expire_time_edit)
  208. qdel(query_find_edit_expiry_message)
  209. return
  210. new_expiry = query_validate_expire_time_edit.item[1]
  211. qdel(query_validate_expire_time_edit)
  212. var/edit_text = sanitizeSQL("Expiration time edited by [editor_key] on [SQLtime()] from [old_expiry] to [new_expiry]<hr>")
  213. var/datum/DBQuery/query_edit_message_expiry = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET expire_timestamp = [expire_time == "-1" ? "NULL" : "'[new_expiry]'"], lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id] AND deleted = 0")
  214. if(!query_edit_message_expiry.warn_execute())
  215. qdel(query_edit_message_expiry)
  216. qdel(query_find_edit_expiry_message)
  217. return
  218. qdel(query_edit_message_expiry)
  219. log_admin_private("[kn] has edited the expiration time of a [type] [(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_key]" : ""] made by [admin_key] from [old_expiry] to [new_expiry]")
  220. message_admins("[kna] has edited the expiration time of a [type] [(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_key]" : ""] made by [admin_key] from [old_expiry] to [new_expiry]")
  221. if(browse)
  222. browse_messages("[type]")
  223. else
  224. browse_messages(target_ckey = ckey(target_key), agegate = TRUE)
  225. qdel(query_find_edit_expiry_message)
  226. /proc/edit_message_severity(message_id)
  227. if(!SSdbcore.Connect())
  228. to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
  229. return
  230. message_id = text2num(message_id)
  231. if(!message_id)
  232. return
  233. var/kn = key_name(usr)
  234. var/kna = key_name_admin(usr)
  235. var/datum/DBQuery/query_find_edit_note_severity = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), severity FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
  236. if(!query_find_edit_note_severity.warn_execute())
  237. qdel(query_find_edit_note_severity)
  238. return
  239. if(query_find_edit_note_severity.NextRow())
  240. var/type = query_find_edit_note_severity.item[1]
  241. var/target_key = query_find_edit_note_severity.item[2]
  242. var/admin_key = query_find_edit_note_severity.item[3]
  243. var/old_severity = query_find_edit_note_severity.item[4]
  244. if(!old_severity)
  245. old_severity = "NA"
  246. var/editor_key = sanitizeSQL(usr.key)
  247. var/editor_ckey = sanitizeSQL(usr.ckey)
  248. var/new_severity = input("Set the severity of the note.", "Severity", null, null) as null|anything in list("high", "medium", "minor", "none") //lowercase for edit log consistency
  249. if(!new_severity)
  250. qdel(query_find_edit_note_severity)
  251. return
  252. new_severity = sanitizeSQL(new_severity)
  253. var/edit_text = sanitizeSQL("Note severity edited by [editor_key] on [SQLtime()] from [old_severity] to [new_severity]<hr>")
  254. var/datum/DBQuery/query_edit_note_severity = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET severity = '[new_severity]', lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id] AND deleted = 0")
  255. if(!query_edit_note_severity.warn_execute(async = TRUE))
  256. qdel(query_edit_note_severity)
  257. qdel(qdel(query_find_edit_note_severity))
  258. return
  259. qdel(query_edit_note_severity)
  260. log_admin_private("[kn] has edited the severity of a [type] for [target_key] made by [admin_key] from [old_severity] to [new_severity]")
  261. message_admins("[kna] has edited the severity time of a [type] for [target_key] made by [admin_key] from [old_severity] to [new_severity]")
  262. browse_messages(target_ckey = ckey(target_key), agegate = TRUE)
  263. qdel(query_find_edit_note_severity)
  264. /proc/toggle_message_secrecy(message_id)
  265. if(!SSdbcore.Connect())
  266. to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
  267. return
  268. message_id = text2num(message_id)
  269. if(!message_id)
  270. return
  271. var/editor_ckey = sanitizeSQL(usr.ckey)
  272. var/editor_key = sanitizeSQL(usr.key)
  273. var/kn = key_name(usr)
  274. var/kna = key_name_admin(usr)
  275. var/datum/DBQuery/query_find_message_secret = SSdbcore.NewQuery("SELECT type, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), targetckey), secret FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
  276. if(!query_find_message_secret.warn_execute())
  277. qdel(query_find_message_secret)
  278. return
  279. if(query_find_message_secret.NextRow())
  280. var/type = query_find_message_secret.item[1]
  281. var/target_key = query_find_message_secret.item[2]
  282. var/admin_key = query_find_message_secret.item[3]
  283. var/secret = text2num(query_find_message_secret.item[4])
  284. var/edit_text = "Made [secret ? "not secret" : "secret"] by [editor_key] on [SQLtime()]<hr>"
  285. 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]")
  286. if(!query_message_secret.warn_execute())
  287. qdel(query_find_message_secret)
  288. qdel(query_message_secret)
  289. return
  290. qdel(query_message_secret)
  291. log_admin_private("[kn] has toggled [target_key]'s [type] made by [admin_key] to [secret ? "not secret" : "secret"]")
  292. message_admins("[kna] has toggled [target_key]'s [type] made by [admin_key] to [secret ? "not secret" : "secret"]")
  293. browse_messages(target_ckey = ckey(target_key), agegate = TRUE)
  294. qdel(query_find_message_secret)
  295. /proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE)
  296. if(!SSdbcore.Connect())
  297. to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
  298. return
  299. var/list/output = list()
  300. var/ruler = "<hr style='background:#000000; border:0; height:3px'>"
  301. var/list/navbar = list("<a href='?_src_=holder;[HrefToken()];nonalpha=1'>All</a><a href='?_src_=holder;[HrefToken()];nonalpha=2'>#</a>")
  302. for(var/letter in GLOB.alphabet)
  303. navbar += "<a href='?_src_=holder;[HrefToken()];showmessages=[letter]'>[letter]</a>"
  304. navbar += "<a href='?_src_=holder;[HrefToken()];showmemo=1'>Memos</a><a href='?_src_=holder;[HrefToken()];showwatch=1'>Watchlist</a>"
  305. navbar += "<br><form method='GET' name='search' action='?'>\
  306. <input type='hidden' name='_src_' value='holder'>\
  307. [HrefTokenFormField()]\
  308. <input type='text' name='searchmessages' value='[index]'>\
  309. <input type='submit' value='Search'></form>"
  310. if(!linkless)
  311. output = navbar
  312. if(type == "memo" || type == "watchlist entry")
  313. if(type == "memo")
  314. output += "<h2><center>Admin memos</h2>"
  315. output += "<a href='?_src_=holder;[HrefToken()];addmemo=1'>Add memo</a></center>"
  316. else if(type == "watchlist entry")
  317. output += "<h2><center>Watchlist entries</h2>"
  318. output += "<a href='?_src_=holder;[HrefToken()];addwatchempty=1'>Add watchlist entry</a>"
  319. if(filter)
  320. output += "<a href='?_src_=holder;[HrefToken()];showwatch=1'>Unfilter clients</a></center>"
  321. else
  322. output += "<a href='?_src_=holder;[HrefToken()];showwatchfilter=1'>Filter offline clients</a></center>"
  323. output += ruler
  324. var/datum/DBQuery/query_get_type_messages = SSdbcore.NewQuery("SELECT id, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), targetckey, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), text, timestamp, server, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor), expire_timestamp FROM [format_table_name("messages")] WHERE type = '[type]' AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL)")
  325. if(!query_get_type_messages.warn_execute())
  326. qdel(query_get_type_messages)
  327. return
  328. while(query_get_type_messages.NextRow())
  329. if(QDELETED(usr))
  330. return
  331. var/id = query_get_type_messages.item[1]
  332. var/t_key = query_get_type_messages.item[2]
  333. var/t_ckey = query_get_type_messages.item[3]
  334. if(type == "watchlist entry" && filter && !(t_ckey in GLOB.directory))
  335. continue
  336. var/admin_key = query_get_type_messages.item[4]
  337. var/text = query_get_type_messages.item[5]
  338. var/timestamp = query_get_type_messages.item[6]
  339. var/server = query_get_type_messages.item[7]
  340. var/editor_key = query_get_type_messages.item[8]
  341. var/expire_timestamp = query_get_type_messages.item[9]
  342. output += "<b>"
  343. if(type == "watchlist entry")
  344. output += "[t_key] | "
  345. output += "[timestamp] | [server] | [admin_key]"
  346. if(expire_timestamp)
  347. output += " | Expires [expire_timestamp]"
  348. output += "</b>"
  349. output += " <a href='?_src_=holder;[HrefToken()];editmessageexpiryempty=[id]'>Change Expiry Time</a>"
  350. output += " <a href='?_src_=holder;[HrefToken()];deletemessageempty=[id]'>Delete</a>"
  351. output += " <a href='?_src_=holder;[HrefToken()];editmessageempty=[id]'>Edit</a>"
  352. if(editor_key)
  353. output += " <font size='2'>Last edit by [editor_key] <a href='?_src_=holder;[HrefToken()];messageedits=[id]'>(Click here to see edit log)</a></font>"
  354. output += "<br>[text]<hr style='background:#000000; border:0; height:1px'>"
  355. qdel(query_get_type_messages)
  356. if(target_ckey)
  357. target_ckey = sanitizeSQL(target_ckey)
  358. var/target_key
  359. var/datum/DBQuery/query_get_messages = SSdbcore.NewQuery("SELECT type, secret, id, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), text, timestamp, server, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor), DATEDIFF(NOW(), timestamp), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey), targetckey), expire_timestamp, severity FROM [format_table_name("messages")] WHERE type <> 'memo' AND targetckey = '[target_ckey]' AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) ORDER BY timestamp DESC")
  360. if(!query_get_messages.warn_execute())
  361. qdel(query_get_messages)
  362. return
  363. var/list/messagedata = list()
  364. var/list/watchdata = list()
  365. var/list/notedata = list()
  366. var/skipped = 0
  367. while(query_get_messages.NextRow())
  368. if(QDELETED(usr))
  369. return
  370. type = query_get_messages.item[1]
  371. if(type == "memo")
  372. continue
  373. var/secret = text2num(query_get_messages.item[2])
  374. if(linkless && secret)
  375. continue
  376. var/id = query_get_messages.item[3]
  377. var/admin_key = query_get_messages.item[4]
  378. var/text = query_get_messages.item[5]
  379. var/timestamp = query_get_messages.item[6]
  380. var/server = query_get_messages.item[7]
  381. var/editor_key = query_get_messages.item[8]
  382. var/age = text2num(query_get_messages.item[9])
  383. target_key = query_get_messages.item[10]
  384. var/expire_timestamp = query_get_messages.item[11]
  385. var/severity = query_get_messages.item[12]
  386. var/alphatext = ""
  387. var/nsd = CONFIG_GET(number/note_stale_days)
  388. var/nfd = CONFIG_GET(number/note_fresh_days)
  389. if (agegate && type == "note" && isnum(nsd) && isnum(nfd) && nsd > nfd)
  390. var/alpha = clamp(100 - (age - nfd) * (85 / (nsd - nfd)), 15, 100)
  391. if (alpha < 100)
  392. if (alpha <= 15)
  393. if (skipped)
  394. skipped++
  395. continue
  396. alpha = 10
  397. skipped = TRUE
  398. alphatext = "filter: alpha(opacity=[alpha]); opacity: [alpha/100];"
  399. var/list/data = list("<div style='margin:0px;[alphatext]'><p class='severity'>")
  400. if(severity)
  401. data += "<img src='[severity]_button.png' height='24' width='24'></img> "
  402. data += "<b>[timestamp] | [server] | [admin_key][secret ? " | <i>- Secret</i>" : ""]"
  403. if(expire_timestamp)
  404. data += " | Expires [expire_timestamp]"
  405. data += "</b></p><center>"
  406. if(!linkless)
  407. if(type == "note")
  408. if(severity)
  409. data += "<a href='?_src_=holder;[HrefToken()];editmessageseverity=[id]'>[severity=="none" ? "No" : "[capitalize(severity)]"] Severity</a>"
  410. else
  411. data += "<a href='?_src_=holder;[HrefToken()];editmessageseverity=[id]'>N/A Severity</a>"
  412. data += " <a href='?_src_=holder;[HrefToken()];editmessageexpiry=[id]'>Change Expiry Time</a>"
  413. data += " <a href='?_src_=holder;[HrefToken()];deletemessage=[id]'>Delete</a>"
  414. if(type == "note")
  415. data += " <a href='?_src_=holder;[HrefToken()];secretmessage=[id]'>[secret ? "<b>Secret</b>" : "Not secret"]</a>"
  416. if(type == "message sent")
  417. data += " <font size='2'>Message has been sent</font>"
  418. if(editor_key)
  419. data += "|"
  420. else
  421. data += " <a href='?_src_=holder;[HrefToken()];editmessage=[id]'>Edit</a>"
  422. if(editor_key)
  423. data += " <font size='2'>Last edit by [editor_key] <a href='?_src_=holder;[HrefToken()];messageedits=[id]'>(Click here to see edit log)</a></font>"
  424. data += "</div></center>"
  425. data += "<p style='[alphatext]'>[text]</p><hr style='background:#000000; border:0; height:1px; [alphatext]'>"
  426. switch(type)
  427. if("message")
  428. messagedata += data
  429. if("message sent")
  430. messagedata += data
  431. if("watchlist entry")
  432. watchdata += data
  433. if("note")
  434. notedata += data
  435. qdel(query_get_messages)
  436. if(!target_key)
  437. var/datum/DBQuery/query_get_message_key = SSdbcore.NewQuery("SELECT byond_key FROM [format_table_name("player")] WHERE ckey = '[target_ckey]'")
  438. if(!query_get_message_key.warn_execute())
  439. qdel(query_get_message_key)
  440. return
  441. if(query_get_message_key.NextRow())
  442. target_key = query_get_message_key.item[1]
  443. qdel(query_get_message_key)
  444. output += "<h2><center>[target_key]</center></h2><center>"
  445. if(!linkless)
  446. output += "<a href='?_src_=holder;[HrefToken()];addnote=[target_key]'>Add note</a>"
  447. output += " <a href='?_src_=holder;[HrefToken()];addmessage=[target_key]'>Add message</a>"
  448. output += " <a href='?_src_=holder;[HrefToken()];addwatch=[target_key]'>Add to watchlist</a>"
  449. output += " <a href='?_src_=holder;[HrefToken()];showmessageckey=[target_ckey]'>Refresh page</a></center>"
  450. else
  451. output += " <a href='?_src_=holder;[HrefToken()];showmessageckeylinkless=[target_ckey]'>Refresh page</a></center>"
  452. output += ruler
  453. if(messagedata)
  454. output += "<h2>Messages</h2>"
  455. output += messagedata
  456. if(watchdata)
  457. output += "<h2>Watchlist</h2>"
  458. output += watchdata
  459. if(notedata)
  460. output += "<h2>Notes</h2>"
  461. output += notedata
  462. if(!linkless)
  463. if (agegate)
  464. if (skipped) //the first skipped message is still shown so that we can put this link over it.
  465. output += "<center><a href='?_src_=holder;[HrefToken()];showmessageckey=[target_ckey];showall=1' style='position: relative; top: -3em;'>Show [skipped] hidden messages</a></center>"
  466. else
  467. output += "<center><a href='?_src_=holder;[HrefToken()];showmessageckey=[target_ckey];showall=1'>Show All</a></center>"
  468. else
  469. output += "<center><a href='?_src_=holder;[HrefToken()];showmessageckey=[target_ckey]'>Hide Old</a></center>"
  470. if(index)
  471. var/search
  472. output += "<center><a href='?_src_=holder;[HrefToken()];addmessageempty=1'>Add message</a><a href='?_src_=holder;[HrefToken()];addwatchempty=1'>Add watchlist entry</a><a href='?_src_=holder;[HrefToken()];addnoteempty=1'>Add note</a></center>"
  473. output += ruler
  474. if(!isnum(index))
  475. index = sanitizeSQL(index)
  476. switch(index)
  477. if(1)
  478. search = "^."
  479. if(2)
  480. search = "^\[^\[:alpha:\]\]"
  481. else
  482. search = "^[index]"
  483. var/datum/DBQuery/query_list_messages = SSdbcore.NewQuery("SELECT DISTINCT targetckey, (SELECT byond_key FROM [format_table_name("player")] WHERE ckey = targetckey) FROM [format_table_name("messages")] WHERE type <> 'memo' AND targetckey REGEXP '[search]' AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL) ORDER BY targetckey")
  484. if(!query_list_messages.warn_execute())
  485. qdel(query_list_messages)
  486. return
  487. while(query_list_messages.NextRow())
  488. if(QDELETED(usr))
  489. return
  490. var/index_ckey = query_list_messages.item[1]
  491. var/index_key = query_list_messages.item[2]
  492. if(!index_key)
  493. index_key = index_ckey
  494. output += "<a href='?_src_=holder;[HrefToken()];showmessageckey=[index_ckey]'>[index_key]</a><br>"
  495. qdel(query_list_messages)
  496. else if(!type && !target_ckey && !index)
  497. output += "<center><a href='?_src_=holder;[HrefToken()];addmessageempty=1'>Add message</a><a href='?_src_=holder;[HrefToken()];addwatchempty=1'>Add watchlist entry</a><a href='?_src_=holder;[HrefToken()];addnoteempty=1'>Add note</a></center>"
  498. output += ruler
  499. var/datum/browser/browser = new(usr, "Note panel", "Manage player notes", 1000, 500)
  500. var/datum/asset/notes_assets = get_asset_datum(/datum/asset/simple/notes)
  501. notes_assets.send(usr.client)
  502. browser.set_content(jointext(output, ""))
  503. browser.open()
  504. /proc/get_message_output(type, target_ckey)
  505. if(!SSdbcore.Connect())
  506. to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
  507. return
  508. if(!type)
  509. return
  510. var/output
  511. if(target_ckey)
  512. target_ckey = sanitizeSQL(target_ckey)
  513. var/query = "SELECT id, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = adminckey), adminckey), text, timestamp, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE ckey = lasteditor), lasteditor) FROM [format_table_name("messages")] WHERE type = '[type]' AND deleted = 0 AND (expire_timestamp > NOW() OR expire_timestamp IS NULL)"
  514. if(type == "message" || type == "watchlist entry")
  515. query += " AND targetckey = '[target_ckey]'"
  516. var/datum/DBQuery/query_get_message_output = SSdbcore.NewQuery(query)
  517. if(!query_get_message_output.warn_execute())
  518. qdel(query_get_message_output)
  519. return
  520. while(query_get_message_output.NextRow())
  521. var/message_id = query_get_message_output.item[1]
  522. var/admin_key = query_get_message_output.item[2]
  523. var/text = query_get_message_output.item[3]
  524. var/timestamp = query_get_message_output.item[4]
  525. var/editor_key = query_get_message_output.item[5]
  526. switch(type)
  527. if("message")
  528. output += "<font color='red' size='3'><b>Admin message left by <span class='prefix'>[admin_key]</span> on [timestamp]</b></font>"
  529. output += "<br><font color='red'>[text]</font><br>"
  530. var/datum/DBQuery/query_message_read = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET type = 'message sent' WHERE id = [message_id]")
  531. if(!query_message_read.warn_execute())
  532. qdel(query_get_message_output)
  533. qdel(query_message_read)
  534. return
  535. qdel(query_message_read)
  536. if("watchlist entry")
  537. message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(target_ckey)] has been on the watchlist since [timestamp] and has just connected - Reason: [text]</font>")
  538. send2tgs_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
  539. if("memo")
  540. output += "<span class='memo'>Memo by <span class='prefix'>[admin_key]</span> on [timestamp]"
  541. if(editor_key)
  542. output += "<br><span class='memoedit'>Last edit by [editor_key] <A href='?_src_=holder;[HrefToken()];messageedits=[message_id]'>(Click here to see edit log)</A></span>"
  543. output += "<br>[text]</span><br>"
  544. qdel(query_get_message_output)
  545. return output
  546. #define NOTESFILE "data/player_notes.sav"
  547. //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
  548. /proc/convert_notes_sql(ckey)
  549. if(!fexists(NOTESFILE))
  550. return
  551. var/savefile/notesfile = new(NOTESFILE)
  552. if(!notesfile)
  553. log_game("Error: Cannot access [NOTESFILE]")
  554. return
  555. notesfile.cd = "/[ckey]"
  556. while(!notesfile.eof)
  557. var/notetext
  558. notesfile >> notetext
  559. var/server
  560. var/ssqlname = CONFIG_GET(string/serversqlname)
  561. if (ssqlname)
  562. server = ssqlname
  563. var/regex/note = new("^(\\d{2}-\\w{3}-\\d{4}) \\| (.+) ~(\\w+)$", "i")
  564. note.Find(notetext)
  565. var/timestamp = note.group[1]
  566. notetext = note.group[2]
  567. var/admin_ckey = note.group[3]
  568. var/datum/DBQuery/query_convert_time = SSdbcore.NewQuery("SELECT ADDTIME(STR_TO_DATE('[timestamp]','%d-%b-%Y'), '0')")
  569. if(!query_convert_time.Execute())
  570. qdel(query_convert_time)
  571. return
  572. if(query_convert_time.NextRow())
  573. timestamp = query_convert_time.item[1]
  574. qdel(query_convert_time)
  575. if(ckey && notetext && timestamp && admin_ckey && server)
  576. create_message("note", ckey, admin_ckey, notetext, timestamp, server, 1, 0, null, 0, 0)
  577. notesfile.cd = "/"
  578. notesfile.dir.Remove(ckey)
  579. /*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
  580. 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
  581. /proc/mass_convert_notes()
  582. to_chat(world, "Beginning mass note conversion", confidential = TRUE)
  583. var/savefile/notesfile = new(NOTESFILE)
  584. if(!notesfile)
  585. log_game("Error: Cannot access [NOTESFILE]")
  586. return
  587. notesfile.cd = "/"
  588. for(var/ckey in notesfile.dir)
  589. convert_notes_sql(ckey)
  590. to_chat(world, "Deleting NOTESFILE", confidential = TRUE)
  591. fdel(NOTESFILE)
  592. to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES", confidential = TRUE)*/
  593. #undef NOTESFILE