Added the new Channel Types, Updated RelationshipTypes, Update all references to PrivateChannels to ONLY select channels that have 1 recipient (DM channels), Set API.Channel.Type to be non-nullable, as all channels are sent with a type.pull/124/head
| @@ -11,14 +11,14 @@ namespace Discord.API | |||||
| public bool IsPrivate { get; set; } | public bool IsPrivate { get; set; } | ||||
| [JsonProperty("last_message_id")] | [JsonProperty("last_message_id")] | ||||
| public ulong? LastMessageId { get; set; } | public ulong? LastMessageId { get; set; } | ||||
| [JsonProperty("type")] | |||||
| public ChannelType Type { get; set; } | |||||
| //GuildChannel | //GuildChannel | ||||
| [JsonProperty("guild_id")] | [JsonProperty("guild_id")] | ||||
| public Optional<ulong> GuildId { get; set; } | public Optional<ulong> GuildId { get; set; } | ||||
| [JsonProperty("name")] | [JsonProperty("name")] | ||||
| public Optional<string> Name { get; set; } | public Optional<string> Name { get; set; } | ||||
| [JsonProperty("type")] | |||||
| public Optional<ChannelType> Type { get; set; } | |||||
| [JsonProperty("position")] | [JsonProperty("position")] | ||||
| public Optional<int> Position { get; set; } | public Optional<int> Position { get; set; } | ||||
| [JsonProperty("permission_overwrites")] | [JsonProperty("permission_overwrites")] | ||||
| @@ -34,8 +34,9 @@ namespace Discord.API | |||||
| [JsonProperty("user_limit")] | [JsonProperty("user_limit")] | ||||
| public Optional<int> UserLimit { get; set; } | public Optional<int> UserLimit { get; set; } | ||||
| //DMChannel | |||||
| [JsonProperty("recipient")] | |||||
| public Optional<User> Recipient { get; set; } | |||||
| //DMChannel or GroupChannel | |||||
| [JsonProperty("recipients")] | |||||
| public Optional<User[]> Recipients { get; set; } | |||||
| } | } | ||||
| } | } | ||||
| @@ -4,6 +4,7 @@ | |||||
| { | { | ||||
| Friend = 1, | Friend = 1, | ||||
| Blocked = 2, | Blocked = 2, | ||||
| Pending = 4 | |||||
| Incoming = 3, | |||||
| Outgoing = 3 | |||||
| } | } | ||||
| } | } | ||||
| @@ -166,7 +166,11 @@ namespace Discord | |||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| return new DMChannel(this, new User(model.Recipient.Value), model); | |||||
| { | |||||
| if (model.Recipients.Value.Count() == 1) | |||||
| return new DMChannel(this, new User(model.Recipients.Value[0]), model); | |||||
| throw new NotImplementedException("Groups are not implemented."); | |||||
| } | |||||
| } | } | ||||
| return null; | return null; | ||||
| } | } | ||||
| @@ -174,7 +178,7 @@ namespace Discord | |||||
| public virtual async Task<IReadOnlyCollection<IDMChannel>> GetDMChannelsAsync() | public virtual async Task<IReadOnlyCollection<IDMChannel>> GetDMChannelsAsync() | ||||
| { | { | ||||
| var models = await ApiClient.GetMyDMsAsync().ConfigureAwait(false); | var models = await ApiClient.GetMyDMsAsync().ConfigureAwait(false); | ||||
| return models.Select(x => new DMChannel(this, new User(x.Recipient.Value), x)).ToImmutableArray(); | |||||
| return models.Where(m => m.Recipients.Value.Count() == 1).Select(x => new DMChannel(this, new User(x.Recipients.Value[0]), x)).ToImmutableArray(); | |||||
| } | } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| @@ -8,7 +8,7 @@ namespace Discord | |||||
| public static string Version { get; } = typeof(DiscordConfig).GetTypeInfo().Assembly?.GetName().Version.ToString(3) ?? "Unknown"; | public static string Version { get; } = typeof(DiscordConfig).GetTypeInfo().Assembly?.GetName().Version.ToString(3) ?? "Unknown"; | ||||
| public static string UserAgent { get; } = $"DiscordBot (https://github.com/RogueException/Discord.Net, v{Version})"; | public static string UserAgent { get; } = $"DiscordBot (https://github.com/RogueException/Discord.Net, v{Version})"; | ||||
| public const int GatewayAPIVersion = 5; | |||||
| public const int GatewayAPIVersion = 6; | |||||
| public const string GatewayEncoding = "json"; | public const string GatewayEncoding = "json"; | ||||
| public const string ClientAPIUrl = "https://discordapp.com/api/"; | public const string ClientAPIUrl = "https://discordapp.com/api/"; | ||||
| @@ -335,7 +335,7 @@ namespace Discord | |||||
| } | } | ||||
| internal CachedDMChannel AddDMChannel(API.Channel model, DataStore dataStore) | internal CachedDMChannel AddDMChannel(API.Channel model, DataStore dataStore) | ||||
| { | { | ||||
| var recipient = GetOrAddUser(model.Recipient.Value, dataStore); | |||||
| var recipient = GetOrAddUser(model.Recipients.Value[0], dataStore); | |||||
| var channel = new CachedDMChannel(this, new CachedDMUser(recipient), model); | var channel = new CachedDMChannel(this, new CachedDMUser(recipient), model); | ||||
| recipient.AddRef(); | recipient.AddRef(); | ||||
| dataStore.AddDMChannel(channel); | dataStore.AddDMChannel(channel); | ||||
| @@ -442,6 +442,9 @@ namespace Discord | |||||
| _lastSeq = seq.Value; | _lastSeq = seq.Value; | ||||
| try | try | ||||
| { | { | ||||
| string writeOutput = $"PACKET ---\n OPCODE: {opCode}\nSEQ: {(seq.HasValue ? seq.Value : -1)}\nTYPE: {type}\n========== BEGIN PAYLOAD ==========\n\n{payload}\n========================="; | |||||
| System.IO.File.WriteAllText($"./discord-debug/{opCode}-{DateTime.Now.ToFileTime()}", writeOutput); | |||||
| switch (opCode) | switch (opCode) | ||||
| { | { | ||||
| case GatewayOpCode.Hello: | case GatewayOpCode.Hello: | ||||
| @@ -505,7 +508,8 @@ namespace Discord | |||||
| await _gatewayLogger.DebugAsync("Received Dispatch (READY)").ConfigureAwait(false); | await _gatewayLogger.DebugAsync("Received Dispatch (READY)").ConfigureAwait(false); | ||||
| var data = (payload as JToken).ToObject<ReadyEvent>(_serializer); | var data = (payload as JToken).ToObject<ReadyEvent>(_serializer); | ||||
| var dataStore = new DataStore( data.Guilds.Length, data.PrivateChannels.Length); | |||||
| var privateChannels = data.PrivateChannels.Where(c => c.Recipients.IsSpecified && c.Recipients.Value.Count() == 1).ToArray(); | |||||
| var dataStore = new DataStore( data.Guilds.Length, privateChannels.Length); | |||||
| var currentUser = new CachedSelfUser(this, data.User); | var currentUser = new CachedSelfUser(this, data.User); | ||||
| int unavailableGuilds = 0; | int unavailableGuilds = 0; | ||||
| @@ -517,8 +521,8 @@ namespace Discord | |||||
| if (model.Unavailable == true) | if (model.Unavailable == true) | ||||
| unavailableGuilds++; | unavailableGuilds++; | ||||
| } | } | ||||
| for (int i = 0; i < data.PrivateChannels.Length; i++) | |||||
| AddDMChannel(data.PrivateChannels[i], dataStore); | |||||
| for (int i = 0; i < privateChannels.Length; i++) | |||||
| AddDMChannel(privateChannels[i], dataStore); | |||||
| _sessionId = data.SessionId; | _sessionId = data.SessionId; | ||||
| _currentUser = currentUser; | _currentUser = currentUser; | ||||
| @@ -740,7 +744,7 @@ namespace Discord | |||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| channel = RemoveDMChannel(data.Recipient.Value.Id); | |||||
| channel = RemoveDMChannel(data.Id); | |||||
| if (channel != null) | if (channel != null) | ||||
| await _channelDestroyedEvent.InvokeAsync(channel).ConfigureAwait(false); | await _channelDestroyedEvent.InvokeAsync(channel).ConfigureAwait(false); | ||||
| else | else | ||||
| @@ -1260,7 +1264,7 @@ namespace Discord | |||||
| catch (Exception ex) | catch (Exception ex) | ||||
| { | { | ||||
| await _gatewayLogger.ErrorAsync($"Error handling {opCode}{(type != null ? $" ({type})" : "")}", ex).ConfigureAwait(false); | await _gatewayLogger.ErrorAsync($"Error handling {opCode}{(type != null ? $" ({type})" : "")}", ex).ConfigureAwait(false); | ||||
| return; | |||||
| throw; | |||||
| } | } | ||||
| #if BENCHMARK | #if BENCHMARK | ||||
| } | } | ||||
| @@ -2,8 +2,9 @@ | |||||
| { | { | ||||
| public enum ChannelType : byte | public enum ChannelType : byte | ||||
| { | { | ||||
| DM, | |||||
| Text, | |||||
| Voice | |||||
| DM = 1, | |||||
| Text = 0, | |||||
| Voice = 2, | |||||
| Group = 3 | |||||
| } | } | ||||
| } | } | ||||
| @@ -30,7 +30,7 @@ namespace Discord | |||||
| { | { | ||||
| if (/*source == UpdateSource.Rest && */IsAttached) return; | if (/*source == UpdateSource.Rest && */IsAttached) return; | ||||
| (Recipient as User).Update(model.Recipient.Value, source); | |||||
| (Recipient as User).Update(model.Recipients.Value[0], source); | |||||
| } | } | ||||
| public async Task UpdateAsync() | public async Task UpdateAsync() | ||||
| @@ -296,14 +296,14 @@ namespace Discord | |||||
| internal GuildChannel ToChannel(API.Channel model) | internal GuildChannel ToChannel(API.Channel model) | ||||
| { | { | ||||
| switch (model.Type.Value) | |||||
| switch (model.Type) | |||||
| { | { | ||||
| case ChannelType.Text: | case ChannelType.Text: | ||||
| return new TextChannel(this, model); | return new TextChannel(this, model); | ||||
| case ChannelType.Voice: | case ChannelType.Voice: | ||||
| return new VoiceChannel(this, model); | return new VoiceChannel(this, model); | ||||
| default: | default: | ||||
| throw new InvalidOperationException($"Unknown channel type: {model.Type.Value}"); | |||||
| throw new InvalidOperationException($"Unknown channel type: {model.Type}"); | |||||
| } | } | ||||
| } | } | ||||
| @@ -311,14 +311,14 @@ namespace Discord | |||||
| new internal ICachedGuildChannel ToChannel(ChannelModel model) | new internal ICachedGuildChannel ToChannel(ChannelModel model) | ||||
| { | { | ||||
| switch (model.Type.Value) | |||||
| switch (model.Type) | |||||
| { | { | ||||
| case ChannelType.Text: | case ChannelType.Text: | ||||
| return new CachedTextChannel(this, model); | return new CachedTextChannel(this, model); | ||||
| case ChannelType.Voice: | case ChannelType.Voice: | ||||
| return new CachedVoiceChannel(this, model); | return new CachedVoiceChannel(this, model); | ||||
| default: | default: | ||||
| throw new InvalidOperationException($"Unknown channel type: {model.Type.Value}"); | |||||
| throw new InvalidOperationException($"Unknown channel type: {model.Type}"); | |||||
| } | } | ||||
| } | } | ||||
| @@ -13,12 +13,17 @@ namespace Discord.Net.Converters | |||||
| public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | ||||
| { | { | ||||
| switch ((string)reader.Value) | |||||
| // TODO: This should probably just be a cast to an enum | |||||
| switch ((long)reader.Value) | |||||
| { | { | ||||
| case "text": | |||||
| case 0: | |||||
| return ChannelType.Text; | return ChannelType.Text; | ||||
| case "voice": | |||||
| case 1: | |||||
| return ChannelType.DM; | |||||
| case 2: | |||||
| return ChannelType.Voice; | return ChannelType.Voice; | ||||
| case 3: | |||||
| return ChannelType.Group; | |||||
| default: | default: | ||||
| throw new JsonSerializationException("Unknown channel type"); | throw new JsonSerializationException("Unknown channel type"); | ||||
| } | } | ||||
| @@ -26,7 +31,7 @@ namespace Discord.Net.Converters | |||||
| public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | ||||
| { | { | ||||
| switch ((ChannelType)value) | |||||
| /*switch ((ChannelType)value) | |||||
| { | { | ||||
| case ChannelType.Text: | case ChannelType.Text: | ||||
| writer.WriteValue("text"); | writer.WriteValue("text"); | ||||
| @@ -36,7 +41,8 @@ namespace Discord.Net.Converters | |||||
| break; | break; | ||||
| default: | default: | ||||
| throw new JsonSerializationException("Invalid channel type"); | throw new JsonSerializationException("Invalid channel type"); | ||||
| } | |||||
| }*/ | |||||
| writer.WriteValue((int)value); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||