Skip to content

Commit

Permalink
feat(guild): guildMemberListUpdate and UpdateGuildSubscriptions gatew…
Browse files Browse the repository at this point in the history
…ay payload

For retrieving the member list of a guild and subscribing to other updates.
  • Loading branch information
cryptoAlgorithm committed Mar 14, 2024
1 parent cdd577e commit 50fb7f3
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 0 deletions.
27 changes: 27 additions & 0 deletions Sources/DiscordKitCore/Objects/Gateway/DataStructs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,33 @@ public struct SubscribeGuildEvts: OutgoingGatewayData {
}
}

/// Guild update subscriptions
public struct UpdateGuildSubscriptions: OutgoingGatewayData {
public struct Subscription: OutgoingGatewayData {
public let activities: Bool?
public let threads: Bool?
public let typing: Bool?
/// Range of members to request from each channel
///
/// - Important: Returned members will only be correctly sorted up to
/// 100 members (e.g. a range of 0-99).
public let channels: [Snowflake : [DiscordRange]]

Check warning on line 130 in Sources/DiscordKitCore/Objects/Gateway/DataStructs.swift

View workflow job for this annotation

GitHub Actions / lint

Colon Spacing Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals (colon)

public init(activities: Bool? = nil, threads: Bool? = nil, typing: Bool? = nil, channels: [Snowflake : [DiscordRange]]) {

Check warning on line 132 in Sources/DiscordKitCore/Objects/Gateway/DataStructs.swift

View workflow job for this annotation

GitHub Actions / lint

Colon Spacing Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals (colon)
self.activities = activities
self.threads = threads
self.typing = typing
self.channels = channels
}
}

public let subscriptions: [Snowflake : Subscription]

Check warning on line 140 in Sources/DiscordKitCore/Objects/Gateway/DataStructs.swift

View workflow job for this annotation

GitHub Actions / lint

Colon Spacing Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals (colon)

public init(subscriptions: [Snowflake : Subscription]) {

Check warning on line 142 in Sources/DiscordKitCore/Objects/Gateway/DataStructs.swift

View workflow job for this annotation

GitHub Actions / lint

Colon Spacing Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals (colon)
self.subscriptions = subscriptions
}
}

/// Current client state, sent with the ``GatewayIdentify`` payload
///
/// > Warning: This should only be sent in identify payloads for user accounts. Bot accounts don't need this!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public enum GatewayEvent: String, Codable {
case guildMemberRemove = "GUILD_MEMBER_REMOVE"
case guildMemberUpdate = "GUILD_MEMBER_UPDATE"
case guildMembersChunk = "GUILD_MEMBERS_CHUNK"
case guildMemberListUpdate = "GUILD_MEMBER_LIST_UPDATE"
// MARK: Guild Roles
case guildRoleCreate = "GUILD_ROLE_CREATE"
case guildRoleUpdate = "GUILD_ROLE_UPDATE"
Expand Down
58 changes: 58 additions & 0 deletions Sources/DiscordKitCore/Objects/Gateway/Event/GuildMemberEvt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,61 @@ public struct GuildMemberUpdate: Codable, GatewayData {
public let pending: Bool?
public let communication_disabled_until: Date?
}

public struct GuildMemberListUpdate: Decodable, GatewayData {
public struct Group: Decodable, Identifiable, GatewayData {
public let id: Snowflake
public let count: Int
}

public struct Data: Codable {
public struct Group: Codable {
public let id: Snowflake
}

public let member: Member?
public let group: Group?
}

public enum UpdateOp: Decodable, GatewayData {
private enum Op: String, Codable {

Check warning on line 48 in Sources/DiscordKitCore/Objects/Gateway/Event/GuildMemberEvt.swift

View workflow job for this annotation

GitHub Actions / lint

Type Name Violation: Type name 'Op' should be between 3 and 40 characters long (type_name)
case update = "UPDATE"
case sync = "SYNC"
case delete = "DELETE"
case insert = "INSERT"
}

case update(Data, index: Int)
case insert(Data, index: Int)
case delete(Int)
case sync([Data], range: DiscordRange)

enum CodingKeys: CodingKey {
case index
case range
case item
case items
case op

Check warning on line 65 in Sources/DiscordKitCore/Objects/Gateway/Event/GuildMemberEvt.swift

View workflow job for this annotation

GitHub Actions / lint

Identifier Name Violation: Enum element name 'op' should be between 3 and 40 characters long (identifier_name)
}

public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let op = try container.decode(Op.self, forKey: .op)

Check warning on line 70 in Sources/DiscordKitCore/Objects/Gateway/Event/GuildMemberEvt.swift

View workflow job for this annotation

GitHub Actions / lint

Identifier Name Violation: Variable name 'op' should be between 3 and 40 characters long (identifier_name)
switch op {
case .sync:
self = .sync(try container.decode([Data].self, forKey: .items), range: try container.decode(DiscordRange.self, forKey: .range))
case .update, .insert:
self = .update(try container.decode(Data.self, forKey: .item), index: try container.decode(Int.self, forKey: .index))
case .delete:
self = .delete(try container.decode(Int.self, forKey: .index))
}
}
}

public let groups: [Group]
public let guild_id: Snowflake
public let id: String
public let member_count: Int
public let online_count: Int
public let ops: [UpdateOp]
}
1 change: 1 addition & 0 deletions Sources/DiscordKitCore/Objects/Gateway/Gateway.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public enum GatewayOutgoingOpcodes: Int, Codable {
case resume = 6 // Attempt to resume disconnected session
case requestGuildMembers = 8
case subscribeGuildEvents = 14
case updateGuildSubscriptions = 37
}

public enum GatewayIncomingOpcodes: Int, Codable {
Expand Down
4 changes: 4 additions & 0 deletions Sources/DiscordKitCore/Objects/Gateway/GatewayIO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public struct GatewayIncoming: Decodable {

/// Guild members chunk
case guildMembersChunk(GuildMembersChunk)

Check warning on line 89 in Sources/DiscordKitCore/Objects/Gateway/GatewayIO.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Whitespace Violation: Lines should not have trailing whitespace (trailing_whitespace)
/// Guild member list update
case guildMemberListUpdate(GuildMemberListUpdate)

/// Guild role created
case guildRoleCreate(GuildRoleEvt)
Expand Down Expand Up @@ -262,6 +265,7 @@ public struct GatewayIncoming: Decodable {
case .guildUpdate: data = .guildUpdate(try values.decode(Guild.self, forKey: .data))
case .guildDelete: data = .guildDelete(try values.decode(GuildUnavailable.self, forKey: .data))
case .guildMembersChunk: data = .guildMembersChunk(try values.decode(GuildMembersChunk.self, forKey: .data))
case .guildMemberListUpdate: data = .guildMemberListUpdate(try values.decode(GuildMemberListUpdate.self, forKey: .data))
case .guildRoleCreate: data = .guildRoleCreate(try values.decode(GuildRoleEvt.self, forKey: .data))
case .guildRoleUpdate: data = .guildRoleUpdate(try values.decode(GuildRoleEvt.self, forKey: .data))
case .guildRoleDelete: data = .guildRoleDelete(try values.decode(GuildRoleDelete.self, forKey: .data))
Expand Down
35 changes: 35 additions & 0 deletions Sources/DiscordKitCore/Utils/DiscordRange.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// DiscordRange.swift
//
//
// Created by Vincent Kwok on 14/3/24.
//

import Foundation

public struct DiscordRange: Codable {
public let start: Int
public let end: Int

public var closedRange: ClosedRange<Int> { start...end }

public init(start: Int, end: Int) {
self.start = start
self.end = end
}

public init(from decoder: any Decoder) throws {
var container = try decoder.unkeyedContainer()
self.start = try container.decode(Int.self)
self.end = try container.decode(Int.self)
guard container.isAtEnd else {
throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "Unexpected elements at end of range"))
}
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(start)
try container.encode(end)
}
}

0 comments on commit 50fb7f3

Please sign in to comment.