///|
fn is_thread(channel : @model.Channel) -> Bool {
match channel.typ {
AnnouncementThread | PublicThread | PrivateThread => true
_ => false
}
}
///|
/// What the cache knows of an active thread, kept whether or not channels are
/// retained, so the thread's messages can be found when it goes.
priv struct ThreadEntry {
guild_id : @model.GuildId
parent_id : @model.ChannelId?
private_ : Bool
}
///|
fn ThreadEntry::of(
channel : @model.Channel,
guild_id : @model.GuildId,
) -> ThreadEntry {
{
guild_id,
parent_id: match channel.parent_id {
Some(Value(parent_id)) => Some(parent_id)
_ => None
},
private_: channel.typ is PrivateThread,
}
}
///|
/// Whether a stored or updated channel stays in the cache. Discord keeps
/// archived threads but stops sending their events, so an archived thread
/// leaves the cache rather than going stale there; fetch archived threads
/// over REST.
fn keeps_channel(channel : @model.Channel) -> Bool {
!(is_thread(channel) &&
channel.thread_metadata is Some(metadata) &&
metadata.archived)
}
///|
/// Whether a `THREAD_MEMBERS_UPDATE` removed the current user from a private
/// thread, which it can then no longer see. A public thread stays readable.
fn loses_thread(
removed : Array[@model.UserId]?,
current_user : @model.UserId?,
private_ : Bool,
) -> Bool {
private_ &&
current_user is Some(user_id) &&
removed is Some(removed) &&
removed.contains(user_id)
}
///|
/// Whether a `THREAD_LIST_SYNC` for `guild_id` covering the parents
/// `channel_ids` (the whole guild when absent) and listing `listed` drops
/// `entry`: a thread in its scope that it does not list is gone; one it
/// lists stays, with its messages.
fn synced_away(
entry : ThreadEntry,
listed : Bool,
guild_id : @model.GuildId,
channel_ids : Array[@model.ChannelId]?,
) -> Bool {
!listed &&
entry.guild_id == guild_id &&
(match channel_ids {
None => true
Some(parent_ids) =>
entry.parent_id is Some(parent_id) && parent_ids.contains(parent_id)
})
}