guilds, lifecycle gateway disconnector, base channels

This commit is contained in:
Cilly Leang 2026-03-21 18:53:24 +11:00
parent fcdd237809
commit 0781606a00
Signed by: cilly
GPG key ID: 6500251E087653C9
14 changed files with 292 additions and 6 deletions

View file

@ -20,7 +20,7 @@ kotlin {
sourceSets {
commonMain.dependencies {
implementation(project(":api:shared"))
api(project(":api:shared"))
implementation(libs.kermit)
implementation(libs.ktor.client.core)

View file

@ -3,6 +3,8 @@ package moe.lava.neon.api.gateway
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import moe.lava.neon.api.ApiConstants
import moe.lava.neon.api.gateway.content.GuildSerializer
import moe.lava.neon.api.objects.Guild
import moe.lava.neon.api.objects.User
sealed interface Payload {
@ -58,7 +60,8 @@ sealed interface Event {
NO_AFFINE_USER_IDS,
DEDUPE_USER_OBJECTS,
USER_SETTINGS_PROTO,
DEBOUNCE_MESSAGE_REACTIONS
DEBOUNCE_MESSAGE_REACTIONS,
CLIENT_STATE_V2,
) },
// TODO: Client state v2
// val clientState: ClientState,
@ -107,7 +110,7 @@ sealed interface Event {
data class Ready(
val v: Int,
val user: User,
// val guilds: List<UnavailableGuild>,
val guilds: List<@Serializable(GuildSerializer::class) Guild>,
val sessionId: String,
val resumeGatewayUrl: String,
// val application: Application,

View file

@ -0,0 +1,19 @@
package moe.lava.neon.api.gateway.content
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.booleanOrNull
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import moe.lava.neon.api.objects.Guild
object GuildSerializer : JsonContentPolymorphicSerializer<Guild>(Guild::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<Guild> {
return if (element.jsonObject["unavailable"]?.jsonPrimitive?.booleanOrNull == true) {
Guild.Unavailable.serializer()
} else {
Guild.Gateway.serializer()
}
}
}

View file

@ -22,7 +22,7 @@ kotlin {
sourceSets {
commonMain.dependencies {
implementation(project(":api:shared"))
api(project(":api:shared"))
implementation(project(":common"))
implementation(libs.kermit)

View file

@ -29,6 +29,8 @@ object ApiConstants {
namingStrategy = JsonNamingStrategy.SnakeCase
ignoreUnknownKeys = true
encodeDefaults = true
// TODO: Distinguish missing vs null fields
explicitNulls = false
}
val superProps = Base64.encode(json.encodeToString(SuperProperties()).encodeToByteArray())

View file

@ -0,0 +1,5 @@
package moe.lava.neon.api.objects
data class Channel(
val id: Snowflake,
)

View file

@ -0,0 +1,145 @@
package moe.lava.neon.api.objects
import kotlinx.serialization.Serializable
import kotlin.time.Instant
@Serializable
sealed class Guild {
abstract val id: Snowflake
abstract val unavailable: Boolean?
@Serializable
data class Unavailable(
override val id: Snowflake,
override val unavailable: Boolean?,
val geoRestricted: Boolean?,
val name: String?,
val icon: String?,
) : Guild()
@Serializable
data class Available(
override val id: Snowflake,
override val unavailable: Boolean?,
val name: String,
val icon: String?,
val banner: String?,
val homeHeader: String?,
val splash: String?,
val discoverySplash: String?,
val ownerId: Snowflake,
val applicationId: Snowflake?,
val description: String?,
val region: String?,
val afkChannelId: Snowflake?,
val afkTimeout: Int,
val widgetEnabled: Boolean?,
val widgetChannelId: Snowflake?,
val verificationLevel: Int,
val defaultMessageNotifications: Int,
val explicitContentFilter: Int,
val features: List<String>,
// val stickers: List<Sticker> = listOf(),
// val roles: List<Role> = listOf(),
// val emojis: List<Emoji> = listOf(),
val mfaLevel: Int,
val systemChannelId: Snowflake?,
val systemChannelFlags: Int,
val rulesChannelId: Snowflake?,
val publicUpdatesChannelId: Snowflake?,
val safetyAlertsChannelId: Snowflake?,
val maxPresences: Int?,
val maxMembers: Int?,
val vanityUrlCode: String?,
val premiumTier: Int,
val premiumSubscriptionCount: Int?,
val preferredLocale: String,
val maxVideoChannelUsers: Int?,
val maxStageVideoChannelUsers: Int?,
val nsfwLevel: Int,
val ownerConfiguredContentLevel: Int?,
val hubType: Int?,
val premiumProgressBarEnabled: Boolean,
val latestOnboardingQuestionId: Snowflake?,
// val incidents_data: AutomodIncidentsData?,
// val premium_features: GuildPremiumFeatures?,
// val profile: GuildIdentity?,
val approximateMemberCount: Int?,
val approximatePresenceCount: Int?,
): Guild()
@Serializable
data class Gateway(
override val id: Snowflake,
override val unavailable: Boolean?,
val joinedAt: Instant,
val large: Boolean,
val geoRestricted: Boolean?,
val memberCount: Int,
// val members: List<GuildMember>,
// val channels: List<Channel>,
// val threads: List<Channel>,
// val presences: List<Presence>,
// val voiceStates: List<VoiceState>,
// val activityInstances: List<EmbeddedActivityInstance>,
// val stageInstances: List<StageInstance>,
// val guildScheduledEvents: List<GuildScheduledEvent>,
val dataMode: String,
val properties: Available, // Client state v2, this is the below fields
// val stickers: List<Sticker>,
// val roles: List<Role>,
// val emojis: List<Emoji>,
// val soundboardSounds: List<SoundboardSound>,
// override val premiumSubscriptionCount: Int,
//
// override val id: Snowflake,
// override val unavailable: Boolean?,
//
// override val name: String,
// override val icon: String?,
// override val banner: String?,
// override val homeHeader: String?,
// override val splash: String?,
// override val discoverySplash: String?,
// override val ownerId: Snowflake,
// override val applicationId: Snowflake?,
// override val description: String?,
// override val region: String?,
// override val afkChannelId: Snowflake?,
// override val afkTimeout: Int,
// override val widgetEnabled: Boolean?,
// override val widgetChannelId: Snowflake?,
// override val verificationLevel: Int,
// override val defaultMessageNotifications: Int,
// override val explicitContentFilter: Int,
// override val features: List<String>,
//
// override val mfaLevel: Int,
// override val systemChannelId: Snowflake?,
// override val systemChannelFlags: Int,
// override val rulesChannelId: Snowflake?,
// override val publicUpdatesChannelId: Snowflake?,
// override val safetyAlertsChannelId: Snowflake?,
// override val maxPresences: Int?,
// override val maxMembers: Int?,
// override val vanityUrlCode: String?,
// override val premiumTier: Int,
// override val preferredLocale: String,
// override val maxVideoChannelUsers: Int?,
// override val maxStageVideoChannelUsers: Int?,
// override val nsfwLevel: Int,
// override val ownerConfiguredContentLevel: Int?,
// override val hubType: Int?,
// override val premiumProgressBarEnabled: Boolean,
// override val latestOnboardingQuestionId: Snowflake?,
// // override val incidents_data: AutomodIncidentsData?
// // override val premium_features: GuildPremiumFeatures?
// // override val profile: GuildIdentity?
// override val approximateMemberCount: Int?,
// override val approximatePresenceCount: Int?,
) : Guild()
}