Fixes newscaster channels having a random chance of breaking upon creation of a new channel, refactors how channels are tracked in the first place (#92371)

## About The Pull Request

So in a recent round I noticed the newscaster UI was acting kind of
funky, where two channels seemed to overlap and weirdly pick between the
two in unpredictable ways. Looking into it, it seemed that somehow the
channels had managed to get their unique IDs to overlap-
Oh.

5d3353e7af/code/game/machinery/newscaster/newscaster_data.dm (L109-L131)
I see.

...I think that code speaks for itself, in how this could've gone wrong.

Anyhow, in this pr we entirely ditch this system, and instead make it
use an incremental and thus guaranteed to be unique ID.
This fixes our issues.

While we're here, we also remove the unused `channel_IDs` list, and
replace it with the associative lists `network_channels_by_id` and
`network_channels_by_name`. This allows us to also stop iterating over
every network channel until we find the one with the right name or ID.
We also rename some confusing, wrong, or non-standard vars while we're
here.
This commit is contained in:
_0Steven
2025-08-12 23:22:35 +02:00
committed by nevimer
parent 410f85475f
commit 1718c70f2f
8 changed files with 152 additions and 159 deletions

View File

@@ -158,8 +158,7 @@ GLOBAL_LIST_INIT(achievements_unlocked, list())
var/json_file = file("[GLOB.log_directory]/newscaster.json") var/json_file = file("[GLOB.log_directory]/newscaster.json")
var/list/file_data = list() var/list/file_data = list()
var/pos = 1 var/pos = 1
for(var/V in GLOB.news_network.network_channels) for(var/datum/feed_channel/channel as anything in GLOB.news_network.network_channels)
var/datum/feed_channel/channel = V
if(!istype(channel)) if(!istype(channel))
stack_trace("Non-channel in newscaster channel list") stack_trace("Non-channel in newscaster channel list")
continue continue

View File

@@ -305,14 +305,8 @@
var/author_key = input["author_ckey"] var/author_key = input["author_ckey"]
var/channel_name = input["message"] var/channel_name = input["message"]
var/found_channel = FALSE var/datum/feed_channel/chosen_channel = GLOB.news_network.network_channels_by_name[channel_name]
for(var/datum/feed_channel/channel as anything in GLOB.news_network.network_channels) if(isnull(chosen_channel)) // No channel with a matching name, abort
if(channel.channel_name == channel_name)
found_channel = TRUE
break
// No channel with a matching name, abort
if (!found_channel)
return return
message_admins(span_adminnotice("Incoming cross-sector newscaster article by [author_key] in channel [channel_name].")) message_admins(span_adminnotice("Incoming cross-sector newscaster article by [author_key] in channel [channel_name]."))

View File

@@ -42,9 +42,9 @@ GLOBAL_LIST_EMPTY(request_list)
///Referece to the photo used in picture messages. ///Referece to the photo used in picture messages.
var/photo_file var/photo_file
///What is the channel ID of the parent channel? ///What is the channel ID of the parent channel?
var/parent_ID var/parent_id
///What number message is this? IE: The first message sent in a round including automated messages is message 1. ///What number message is this? IE: The first message sent in a round including automated messages is message 1.
var/message_ID var/message_id
/datum/feed_message/proc/return_author(censor) /datum/feed_message/proc/return_author(censor)
if(censor == -1) if(censor == -1)
@@ -99,37 +99,13 @@ GLOBAL_LIST_EMPTY(request_list)
var/author_censor var/author_censor
/// Is this an admin channel? Allows for actions to be taken by the admin only. /// Is this an admin channel? Allows for actions to be taken by the admin only.
var/is_admin_channel = FALSE var/is_admin_channel = FALSE
/// Channel ID is a random number sequence similar to account ID number that allows for us to link messages to the proper channels through the UI backend. /// Channel ID is a unique number sequence similar to account ID number that allows for us to link messages to the proper channels through the UI backend.
var/channel_ID var/channel_id
/// Should this channel send cross-server messages? /// Should this channel send cross-server messages?
var/cross_sector = FALSE var/cross_sector = FALSE
/// Is this a cross-sector channel? If so, this channel can only receive messages via topics /// Is this a cross-sector channel? If so, this channel can only receive messages via topics
var/receiving_cross_sector = FALSE var/receiving_cross_sector = FALSE
/datum/feed_channel/New()
. = ..()
channel_ID = random_channel_id_setup()
/**
* This proc assigns each feed_channel a random integer, from 1-999 as a unique identifier.
* Using this value, the TGUI window has a unique identifier to attach to messages that can be used to reattach them
* to their parent channels back in dreammaker.
* Based on implementation, we're limiting ourselves to only 998 player made channels maximum. How we'd use all of them, I don't know.
*/
/datum/feed_channel/proc/random_channel_id_setup()
if(!GLOB.news_network)
return //Should only apply to channels made before setup is finished, use hardset_channel for these
if(!GLOB.news_network.channel_IDs)
GLOB.news_network.channel_IDs += rand(1,999)
return //This will almost always be the station announcements channel here.
var/channel_id
for(var/i in 1 to 10000)
channel_id = rand(1, 999)
if(!GLOB.news_network.channel_IDs["[channel_ID]"])
break
channel_ID = channel_id
return channel_ID
/datum/feed_channel/proc/return_author(censor) /datum/feed_channel/proc/return_author(censor)
if(censor == -1) if(censor == -1)
censor = author_censor censor = author_censor
@@ -173,36 +149,47 @@ GLOBAL_LIST_EMPTY(request_list)
/datum/feed_network /datum/feed_network
/// All the feed channels that have been made on the feed network. /// All the feed channels that have been made on the feed network.
var/list/datum/feed_channel/network_channels = list() var/list/datum/feed_channel/network_channels = list()
/// Associative list of all the feed channels that have been made on the feed network, from channel ID to channel.
var/list/datum/feed_channel/network_channels_by_id = list()
/// Associative list of all the feed channels that have been made on the feed network, from channel name to channel.
var/list/datum/feed_channel/network_channels_by_name = list()
/// What is the wanted issue being sent out to all newscasters. /// What is the wanted issue being sent out to all newscasters.
var/datum/wanted_message/wanted_issue var/datum/wanted_message/wanted_issue
/// What time was the last action taken on the feed_network? /// What time was the last action taken on the feed_network?
var/last_action var/last_action
/// What does this feed network say when a message/author is redacted? /// What does this feed network say when a message/author is redacted?
var/redacted_text = "\[REDACTED\]" var/redacted_text = "\[REDACTED\]"
/// List of all the network_channels Channel Id numbers, kept in a global easy to find place. /// Channel ID to use when next making a new channel, to maintain unique IDs.
var/list/channel_IDs = list() var/next_channel_id = 1
/// How many messages currently exist on this feed_network? Increments as new messages are written. /// How many messages currently exist on this feed_network? Increments as new messages are written.
var/message_count = 0 var/message_count = 0
/datum/feed_network/New() /datum/feed_network/New()
create_feed_channel(NEWSCASTER_STATION_ANNOUNCEMENTS, "SS13", "Company news, staff announcements, and all the latest information. Have a secure shift!", locked = TRUE, hardset_channel = 1000) create_feed_channel(NEWSCASTER_STATION_ANNOUNCEMENTS, "SS13", "Company news, staff announcements, and all the latest information. Have a secure shift!", locked = TRUE)
create_feed_channel(NEWSCASTER_SPACE_BETTING, "NtOS", "News from the SpaceBet PDA App! Download now and make your own bets!", locked = TRUE, hardset_channel = 1001) create_feed_channel(NEWSCASTER_SPACE_BETTING, "NtOS", "News from the SpaceBet PDA App! Download now and make your own bets!", locked = TRUE)
wanted_issue = new /datum/wanted_message wanted_issue = new /datum/wanted_message
/datum/feed_network/proc/create_feed_channel(channel_name, author, desc, locked, adminChannel = FALSE, hardset_channel = null, author_ckey = null, cross_sector = FALSE, cross_sector_delay = null, receiving_cross_sector = FALSE) /datum/feed_network/proc/add_feed_channel(datum/feed_channel/new_channel)
var/datum/feed_channel/newChannel = new /datum/feed_channel network_channels += new_channel
newChannel.channel_name = channel_name network_channels_by_id["[new_channel.channel_id]"] = new_channel
newChannel.author = author network_channels_by_name["[new_channel.channel_name]"] = new_channel
newChannel.channel_desc = desc
newChannel.locked = locked /datum/feed_network/proc/create_feed_channel(channel_name, author, desc, locked, adminChannel = FALSE, author_ckey = null, cross_sector = FALSE, cross_sector_delay = null, receiving_cross_sector = FALSE)
newChannel.is_admin_channel = adminChannel var/datum/feed_channel/new_channel = new /datum/feed_channel
newChannel.receiving_cross_sector = receiving_cross_sector new_channel.channel_name = channel_name
if(hardset_channel) new_channel.author = author
newChannel.channel_ID = hardset_channel new_channel.channel_desc = desc
network_channels += newChannel new_channel.locked = locked
new_channel.is_admin_channel = adminChannel
new_channel.receiving_cross_sector = receiving_cross_sector
new_channel.channel_id = next_channel_id
next_channel_id++
add_feed_channel(new_channel)
if(!cross_sector) if(!cross_sector)
return return
newChannel.cross_sector = TRUE new_channel.cross_sector = TRUE
var/list/payload = list( var/list/payload = list(
"author" = author, "author" = author,
"author_ckey" = author_ckey, "author_ckey" = author_ckey,
@@ -212,31 +199,32 @@ GLOBAL_LIST_EMPTY(request_list)
send2otherserver(html_decode(station_name()), channel_name, "create_news_channel", additional_data = payload) send2otherserver(html_decode(station_name()), channel_name, "create_news_channel", additional_data = payload)
/datum/feed_network/proc/submit_article(msg, author, channel_name, datum/picture/picture, adminMessage = FALSE, allow_comments = TRUE, update_alert = TRUE, mob/author_mob = null) /datum/feed_network/proc/submit_article(msg, author, channel_name, datum/picture/picture, adminMessage = FALSE, allow_comments = TRUE, update_alert = TRUE, mob/author_mob = null)
var/datum/feed_message/newMsg = new /datum/feed_message var/datum/feed_channel/chosen_channel = network_channels_by_name[channel_name]
newMsg.author = author if(isnull(chosen_channel))
newMsg.body = msg stack_trace("Article submitted to non-existent newscaster channel: [channel_name]")
newMsg.time_stamp = "[station_time_timestamp()]" return
newMsg.is_admin_message = adminMessage
newMsg.locked = !allow_comments var/datum/feed_message/new_article = new /datum/feed_message
new_article.author = author
new_article.body = msg
new_article.time_stamp = "[station_time_timestamp()]"
new_article.is_admin_message = adminMessage
new_article.locked = !allow_comments
message_count++ message_count++
last_action++ last_action++
newMsg.creation_time = last_action new_article.creation_time = last_action
newMsg.message_ID = message_count new_article.message_id = message_count
if(picture) if(picture)
newMsg.img = picture.picture_image new_article.img = picture.picture_image
newMsg.caption = picture.caption new_article.caption = picture.caption
newMsg.photo_file = save_photo(picture.picture_image) new_article.photo_file = save_photo(picture.picture_image)
for(var/datum/feed_channel/channel in network_channels) chosen_channel.messages += new_article
if(channel.channel_name != channel_name) new_article.parent_id = chosen_channel.channel_id
continue
channel.messages += newMsg if(chosen_channel.cross_sector)
newMsg.parent_ID = channel.channel_ID
if (!channel.cross_sector)
break
// Newscaster articles could be huge, and usefulness of first 50 symbols is dubious // Newscaster articles could be huge, and usefulness of first 50 symbols is dubious
message_admins(span_adminnotice("Outgoing cross-sector newscaster article by [key_name(author_mob) || author] in channel [channel_name].")) message_admins(span_adminnotice("Outgoing cross-sector newscaster article by [key_name(author_mob) || author] in channel [channel_name]."))
var/list/payload = list( var/list/payload = list(
@@ -245,11 +233,10 @@ GLOBAL_LIST_EMPTY(request_list)
"msg" = msg, "msg" = msg,
) )
send2otherserver(html_decode(station_name()), channel_name, "create_news_article", additional_data = payload) send2otherserver(html_decode(station_name()), channel_name, "create_news_article", additional_data = payload)
break
for(var/obj/machinery/newscaster/caster in GLOB.allCasters) for(var/obj/machinery/newscaster/caster in GLOB.allCasters)
caster.news_alert(channel_name, update_alert) caster.news_alert(channel_name, update_alert)
return newMsg return new_article
///Submits a comment on the news network ///Submits a comment on the news network
/datum/feed_network/proc/submit_comment(mob/user, comment_text, newscaster_username, datum/feed_message/current_message) /datum/feed_network/proc/submit_comment(mob/user, comment_text, newscaster_username, datum/feed_message/current_message)

View File

@@ -196,11 +196,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
//Then, breaks down the messages that have been made on those channels. //Then, breaks down the messages that have been made on those channels.
if(current_channel) if(current_channel)
for(var/datum/feed_message/feed_message as anything in current_channel.messages) for(var/datum/feed_message/feed_message as anything in current_channel.messages)
var/photo_ID = null var/photo_id = null
var/list/comment_list var/list/comment_list
if(feed_message.img) if(feed_message.img)
user << browse_rsc(feed_message.img, "tmp_photo[feed_message.message_ID].png") user << browse_rsc(feed_message.img, "tmp_photo[feed_message.message_id].png")
photo_ID = "tmp_photo[feed_message.message_ID].png" photo_id = "tmp_photo[feed_message.message_id].png"
for(var/datum/feed_comment/comment_message as anything in feed_message.comments) for(var/datum/feed_comment/comment_message as anything in feed_message.comments)
comment_list += list(list( comment_list += list(list(
"auth" = comment_message.author, "auth" = comment_message.author,
@@ -211,16 +211,16 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
"auth" = feed_message.author, "auth" = feed_message.author,
"body" = feed_message.body, "body" = feed_message.body,
"time" = feed_message.time_stamp, "time" = feed_message.time_stamp,
"channel_num" = feed_message.parent_ID, "channel_num" = feed_message.parent_id,
"censored_message" = feed_message.body_censor, "censored_message" = feed_message.body_censor,
"censored_author" = feed_message.author_censor, "censored_author" = feed_message.author_censor,
"ID" = feed_message.message_ID, "ID" = feed_message.message_id,
"photo" = photo_ID, "photo" = photo_id,
"comments" = comment_list "comments" = comment_list
)) ))
data["viewing_channel"] = current_channel?.channel_ID data["viewing_channel"] = current_channel?.channel_id
data["paper"] = paper_remaining data["paper"] = paper_remaining
//Here we display all the information about the current channel. //Here we display all the information about the current channel.
data["channelName"] = current_channel?.channel_name data["channelName"] = current_channel?.channel_name
@@ -264,7 +264,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
"author" = channel.author, "author" = channel.author,
"censored" = channel.censored, "censored" = channel.censored,
"locked" = channel.locked, "locked" = channel.locked,
"ID" = channel.channel_ID, "ID" = channel.channel_id,
)) ))
data["channels"] = channel_list data["channels"] = channel_list
@@ -293,19 +293,20 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
switch(action) switch(action)
if("setChannel") if("setChannel")
var/prototype_channel = params["channel"] var/selected_channel_id = params["channel"]
if(isnull(prototype_channel)) if(isnull(selected_channel_id))
return TRUE
var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[selected_channel_id]"]
if(isnull(potential_channel))
return TRUE return TRUE
for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels)
if(prototype_channel == potential_channel.channel_ID)
current_channel = potential_channel current_channel = potential_channel
if("createStory") if("createStory")
if(!current_channel) if(!current_channel)
balloon_alert(user, "select a channel first!") balloon_alert(user, "select a channel first!")
return TRUE return TRUE
var/prototype_channel = params["current"] var/current_channel_id = params["current"]
create_story(user, channel_name = prototype_channel) create_story(user, channel_id = current_channel_id)
if("togglePhoto") if("togglePhoto")
toggle_photo(user) toggle_photo(user)
@@ -352,7 +353,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
return TRUE return TRUE
var/questionable_message = params["messageID"] var/questionable_message = params["messageID"]
for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages) for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages)
if(iterated_feed_message.message_ID == questionable_message) if(iterated_feed_message.message_id == questionable_message)
iterated_feed_message.toggle_censor_body() iterated_feed_message.toggle_censor_body()
break break
@@ -366,7 +367,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
return TRUE return TRUE
var/questionable_message = params["messageID"] var/questionable_message = params["messageID"]
for(var/datum/feed_message/iterated_feed_message in current_channel.messages) for(var/datum/feed_message/iterated_feed_message in current_channel.messages)
if(iterated_feed_message.message_ID == questionable_message) if(iterated_feed_message.message_id == questionable_message)
iterated_feed_message.toggle_censor_author() iterated_feed_message.toggle_censor_author()
break break
@@ -378,11 +379,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
if(!(admin_access in id_card?.GetAccess())) if(!(admin_access in id_card?.GetAccess()))
say("Clearance not found.") say("Clearance not found.")
return TRUE return TRUE
var/prototype_channel = (params["channel"]) var/selected_channel_id = (params["channel"])
for(var/datum/feed_channel/potential_channel in GLOB.news_network.network_channels) if(isnull(selected_channel_id))
if(prototype_channel == potential_channel.channel_ID) return TRUE
var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[selected_channel_id]"]
if(isnull(potential_channel))
return TRUE
current_channel = potential_channel current_channel = potential_channel
break
current_channel.toggle_censor_D_class() current_channel.toggle_censor_D_class()
if("startComment") if("startComment")
@@ -394,7 +397,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
if(!commentable_message) if(!commentable_message)
return TRUE return TRUE
for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages) for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages)
if(iterated_feed_message.message_ID == commentable_message) if(iterated_feed_message.message_id == commentable_message)
current_message = iterated_feed_message current_message = iterated_feed_message
return TRUE return TRUE
@@ -660,8 +663,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
if(isnull(channel_locked)) if(isnull(channel_locked))
return TRUE return TRUE
for(var/datum/feed_channel/iterated_feed_channel as anything in GLOB.news_network.network_channels) var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_name[channel_name]
if(iterated_feed_channel.channel_name == channel_name) if(potential_channel)
tgui_alert(user, "ERROR: Feed channel with that name already exists on the Network.", list("Okay")) tgui_alert(user, "ERROR: Feed channel with that name already exists on the Network.", list("Okay"))
return TRUE return TRUE
@@ -769,13 +772,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
* Verifies that the message is being written to a real feed_channel, then provides a text input for the feed story to be written into. * Verifies that the message is being written to a real feed_channel, then provides a text input for the feed story to be written into.
* Finally, it submits the message to the network, is logged globally, and clears all message-specific variables from the machine. * Finally, it submits the message to the network, is logged globally, and clears all message-specific variables from the machine.
*/ */
/obj/machinery/newscaster/proc/create_story(mob/user, channel_name) /obj/machinery/newscaster/proc/create_story(mob/user, channel_id)
for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels) var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[channel_id]"]
if(channel_name == potential_channel.channel_ID) if(isnull(potential_channel))
return
current_channel = potential_channel current_channel = potential_channel
break
if (current_channel.receiving_cross_sector) if(current_channel.receiving_cross_sector)
return return
var/temp_message = tgui_input_text(user, "Write your Feed story", "Network Channel Handler", feed_channel_message, max_length = MAX_BROADCAST_LEN, multiline = TRUE) var/temp_message = tgui_input_text(user, "Write your Feed story", "Network Channel Handler", feed_channel_message, max_length = MAX_BROADCAST_LEN, multiline = TRUE)

View File

@@ -268,10 +268,10 @@
var/has_image = FALSE var/has_image = FALSE
if(feed_messages.img) if(feed_messages.img)
has_image = TRUE has_image = TRUE
user << browse_rsc(feed_messages.img, "tmp_photo[feed_messages.message_ID].png") user << browse_rsc(feed_messages.img, "tmp_photo[feed_messages.message_id].png")
channel_data["channel_messages"] += list(list( channel_data["channel_messages"] += list(list(
"message" = "-[feed_messages.return_body(censored_check(feed_messages.body_censor_time))]", "message" = "-[feed_messages.return_body(censored_check(feed_messages.body_censor_time))]",
"photo" = (has_image ? "tmp_photo[feed_messages.message_ID].png" : null), "photo" = (has_image ? "tmp_photo[feed_messages.message_id].png" : null),
"author" = feed_messages.return_author(censored_check(feed_messages.author_censor_time)), "author" = feed_messages.return_author(censored_check(feed_messages.author_censor_time)),
)) ))
data["channel_data"] = list(channel_data) data["channel_data"] = list(channel_data)

View File

@@ -86,15 +86,15 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo
"author" = channel.author, "author" = channel.author,
"censored" = channel.censored, "censored" = channel.censored,
"locked" = channel.locked, "locked" = channel.locked,
"ID" = channel.channel_ID, "ID" = channel.channel_id,
)) ))
if(current_channel) if(current_channel)
for(var/datum/feed_message/feed_message as anything in current_channel.messages) for(var/datum/feed_message/feed_message as anything in current_channel.messages)
var/photo_ID = null var/photo_id = null
var/list/comment_list var/list/comment_list
if(feed_message.img) if(feed_message.img)
user << browse_rsc(feed_message.img, "tmp_photo[feed_message.message_ID].png") user << browse_rsc(feed_message.img, "tmp_photo[feed_message.message_id].png")
photo_ID = "tmp_photo[feed_message.message_ID].png" photo_id = "tmp_photo[feed_message.message_id].png"
for(var/datum/feed_comment/comment_message as anything in feed_message.comments) for(var/datum/feed_comment/comment_message as anything in feed_message.comments)
comment_list += list(list( comment_list += list(list(
"auth" = comment_message.author, "auth" = comment_message.author,
@@ -105,16 +105,16 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo
"auth" = feed_message.author, "auth" = feed_message.author,
"body" = feed_message.body, "body" = feed_message.body,
"time" = feed_message.time_stamp, "time" = feed_message.time_stamp,
"channel_num" = feed_message.parent_ID, "channel_num" = feed_message.parent_id,
"censored_message" = feed_message.body_censor, "censored_message" = feed_message.body_censor,
"censored_author" = feed_message.author_censor, "censored_author" = feed_message.author_censor,
"ID" = feed_message.message_ID, "ID" = feed_message.message_id,
"photo" = photo_ID, "photo" = photo_id,
"comments" = comment_list "comments" = comment_list
)) ))
data["viewing_channel"] = current_channel?.channel_ID data["viewing_channel"] = current_channel?.channel_id
//Here we display all the information about the current channel. //Here we display all the information about the current channel.
data["channelName"] = current_channel?.channel_name data["channelName"] = current_channel?.channel_name
data["channelAuthor"] = current_channel?.author data["channelAuthor"] = current_channel?.author
@@ -141,19 +141,20 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo
switch(action) switch(action)
if("setChannel") if("setChannel")
var/prototype_channel = params["channel"] var/selected_channel_id = params["channel"]
if(isnull(prototype_channel)) if(isnull(selected_channel_id))
return TRUE
var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[selected_channel_id]"]
if(isnull(potential_channel))
return TRUE return TRUE
for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels)
if(prototype_channel == potential_channel.channel_ID)
current_channel = potential_channel current_channel = potential_channel
if("createStory") if("createStory")
if(!current_channel) if(!current_channel)
to_chat(usr, "select a channel first!") to_chat(usr, "select a channel first!")
return TRUE return TRUE
var/prototype_channel = params["current"] var/current_channel_id = params["current"]
create_story(channel_name = prototype_channel) create_story(channel_id = current_channel_id)
if("togglePhoto") if("togglePhoto")
toggle_photo() toggle_photo()
@@ -189,23 +190,25 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo
if("storyCensor") if("storyCensor")
var/questionable_message = params["messageID"] var/questionable_message = params["messageID"]
for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages) for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages)
if(iterated_feed_message.message_ID == questionable_message) if(iterated_feed_message.message_id == questionable_message)
iterated_feed_message.toggle_censor_body() iterated_feed_message.toggle_censor_body()
break break
if("author_censor") if("author_censor")
var/questionable_message = params["messageID"] var/questionable_message = params["messageID"]
for(var/datum/feed_message/iterated_feed_message in current_channel.messages) for(var/datum/feed_message/iterated_feed_message in current_channel.messages)
if(iterated_feed_message.message_ID == questionable_message) if(iterated_feed_message.message_id == questionable_message)
iterated_feed_message.toggle_censor_author() iterated_feed_message.toggle_censor_author()
break break
if("channelDNotice") if("channelDNotice")
var/prototype_channel = (params["channel"]) var/selected_channel_id = (params["channel"])
for(var/datum/feed_channel/potential_channel in GLOB.news_network.network_channels) if(isnull(selected_channel_id))
if(prototype_channel == potential_channel.channel_ID) return TRUE
var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[selected_channel_id]"]
if(isnull(potential_channel))
return TRUE
current_channel = potential_channel current_channel = potential_channel
break
current_channel.toggle_censor_D_class() current_channel.toggle_censor_D_class()
if("startComment") if("startComment")
@@ -214,7 +217,7 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo
if(!commentable_message) if(!commentable_message)
return TRUE return TRUE
for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages) for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages)
if(iterated_feed_message.message_ID == commentable_message) if(iterated_feed_message.message_id == commentable_message)
current_message = iterated_feed_message current_message = iterated_feed_message
return TRUE return TRUE
@@ -284,8 +287,8 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo
/datum/newspanel/proc/create_channel(channel_locked) /datum/newspanel/proc/create_channel(channel_locked)
if(!channel_name) if(!channel_name)
return return
for(var/datum/feed_channel/iterated_feed_channel as anything in GLOB.news_network.network_channels) var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_name[channel_name]
if(iterated_feed_channel.channel_name == channel_name) if(potential_channel)
tgui_alert(usr, "ERROR: Feed channel with that name already exists on the Network.", list("Okay")) tgui_alert(usr, "ERROR: Feed channel with that name already exists on the Network.", list("Okay"))
return TRUE return TRUE
if(!channel_desc) if(!channel_desc)
@@ -334,11 +337,12 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo
* Verifies that the message is being written to a real feed_channel, then provides a text input for the feed story to be written into. * Verifies that the message is being written to a real feed_channel, then provides a text input for the feed story to be written into.
* Finally, it submits the message to the network, is logged globally, and clears all message-specific variables from the machine. * Finally, it submits the message to the network, is logged globally, and clears all message-specific variables from the machine.
*/ */
/datum/newspanel/proc/create_story(channel_name) /datum/newspanel/proc/create_story(channel_id)
for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels) var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[channel_id]"]
if(channel_name == potential_channel.channel_ID) if(isnull(potential_channel))
return
current_channel = potential_channel current_channel = potential_channel
break
var/temp_message = tgui_input_text(usr, "Write your Feed story", "Network Channel Handler", feed_channel_message, max_length = MAX_BROADCAST_LEN, multiline = TRUE) var/temp_message = tgui_input_text(usr, "Write your Feed story", "Network Channel Handler", feed_channel_message, max_length = MAX_BROADCAST_LEN, multiline = TRUE)
if(length(temp_message) <= 1) if(length(temp_message) <= 1)
return TRUE return TRUE

View File

@@ -507,12 +507,8 @@ GLOBAL_VAR_INIT(library_table_modified, 0)
return return
if(!GLOB.news_network) if(!GLOB.news_network)
say("No news network found on station. Aborting.") say("No news network found on station. Aborting.")
var/channelexists = FALSE var/datum/feed_channel/library_channel = GLOB.news_network.network_channels_by_name[LIBRARY_NEWSFEED]
for(var/datum/feed_channel/feed in GLOB.news_network.network_channels) if(isnull(library_channel))
if(feed.channel_name == LIBRARY_NEWSFEED)
channelexists = TRUE
break
if(!channelexists)
GLOB.news_network.create_feed_channel(LIBRARY_NEWSFEED, "Library", "The official station book club!", null) GLOB.news_network.create_feed_channel(LIBRARY_NEWSFEED, "Library", "The official station book club!", null)
var/obj/machinery/libraryscanner/scan = get_scanner() var/obj/machinery/libraryscanner/scan = get_scanner()

View File

@@ -170,19 +170,32 @@ GLOBAL_LIST_EMPTY_TYPED(active_bets, /datum/active_bet)
for(var/option in options) for(var/option in options)
if(!length(options[option])) if(!length(options[option]))
options[option] = list() options[option] = list()
//we'll only advertise it on the first bet of the round, as to not make this overly annoying. advertise_bet()
var/should_alert = FALSE
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == NEWSCASTER_SPACE_BETTING)
if(!length(FC.messages))
should_alert = TRUE
newscaster_message = GLOB.news_network.submit_article("The bet [name] has started, place your bets now!", "NtOS Space Betting App", NEWSCASTER_SPACE_BETTING, null, update_alert = should_alert)
/datum/active_bet/Destroy(force) /datum/active_bet/Destroy(force)
GLOB.active_bets -= src GLOB.active_bets -= src
newscaster_message = null newscaster_message = null
return ..() return ..()
/// Place a feed article advertising our bet.
/datum/active_bet/proc/advertise_bet()
var/datum/feed_channel/betting_channel = GLOB.news_network.network_channels_by_name[NEWSCASTER_SPACE_BETTING]
if(isnull(betting_channel))
return
// We'll only advertise it on the first bet of the round, as to not make this overly annoying.
var/should_alert = !length(betting_channel.messages)
newscaster_message = GLOB.news_network.submit_article("The bet [name] has started, place your bets now!", "NtOS Space Betting App", NEWSCASTER_SPACE_BETTING, null, update_alert = should_alert)
/// Reply to our previously placed advertisement feed article.
/datum/active_bet/proc/reply_to_feed(winning_option)
if(isnull(newscaster_message))
return
GLOB.news_network.submit_comment(
comment_text = "The bet [name] has ended, the winner was [winning_option]!",
newscaster_username = "NtOS Betting Results",
current_message = newscaster_message,
)
///Returns how many bets there is per option ///Returns how many bets there is per option
/datum/active_bet/proc/get_bets(datum/bank_account/user_account) /datum/active_bet/proc/get_bets(datum/bank_account/user_account)
var/list/bets_per_option = list() var/list/bets_per_option = list()
@@ -206,11 +219,8 @@ GLOBAL_LIST_EMPTY_TYPED(active_bets, /datum/active_bet)
var/datum/bank_account/refunded_account = existing_bets[1] var/datum/bank_account/refunded_account = existing_bets[1]
refunded_account.adjust_money(text2num(existing_bets[2]), "Refund: [name] gamble cancelled.") refunded_account.adjust_money(text2num(existing_bets[2]), "Refund: [name] gamble cancelled.")
return return
GLOB.news_network.submit_comment(
comment_text = "The bet [name] has ended, the winner was [winning_option]!", reply_to_feed(winning_option)
newscaster_username = "NtOS Betting Results",
current_message = newscaster_message,
)
var/list/winners = options[winning_option] var/list/winners = options[winning_option]
if(!length(winners)) if(!length(winners))
return return