@@ -154,6 +154,7 @@ namespace Discord.Net.WebSockets | |||
while (!cancelToken.IsCancellationRequested) | |||
{ | |||
WebSocketReceiveResult socketResult = await _client.ReceiveAsync(buffer, cancelToken).ConfigureAwait(false); | |||
System.Diagnostics.Debug.WriteLine("Got " + socketResult.Count); | |||
byte[] result; | |||
int resultCount; | |||
@@ -193,6 +194,7 @@ namespace Discord.Net.WebSockets | |||
result = buffer.Array; | |||
} | |||
System.Diagnostics.Debug.WriteLine("Start"); | |||
if (socketResult.MessageType == WebSocketMessageType.Text) | |||
{ | |||
string text = Encoding.UTF8.GetString(result, 0, resultCount); | |||
@@ -200,6 +202,7 @@ namespace Discord.Net.WebSockets | |||
} | |||
else | |||
await BinaryMessage(result, 0, resultCount).ConfigureAwait(false); | |||
System.Diagnostics.Debug.WriteLine("Stop"); | |||
} | |||
} | |||
catch (Win32Exception ex) when (ex.HResult == HR_TIMEOUT) | |||
@@ -269,14 +269,14 @@ namespace Discord.API | |||
options = RequestOptions.CreateOrClone(options); | |||
return await SendRpcAsync<GetGuildsResponse>("GET_GUILDS", null, options: options).ConfigureAwait(false); | |||
} | |||
public async Task<Rpc.RpcGuild> SendGetGuildAsync(ulong guildId, RequestOptions options = null) | |||
public async Task<Rpc.Guild> SendGetGuildAsync(ulong guildId, RequestOptions options = null) | |||
{ | |||
options = RequestOptions.CreateOrClone(options); | |||
var msg = new GetGuildParams | |||
{ | |||
GuildId = guildId | |||
}; | |||
return await SendRpcAsync<Rpc.RpcGuild>("GET_GUILD", msg, options: options).ConfigureAwait(false); | |||
return await SendRpcAsync<Rpc.Guild>("GET_GUILD", msg, options: options).ConfigureAwait(false); | |||
} | |||
public async Task<GetChannelsResponse> SendGetChannelsAsync(ulong guildId, RequestOptions options = null) | |||
{ | |||
@@ -287,33 +287,34 @@ namespace Discord.API | |||
}; | |||
return await SendRpcAsync<GetChannelsResponse>("GET_CHANNELS", msg, options: options).ConfigureAwait(false); | |||
} | |||
public async Task<Rpc.RpcChannel> SendGetChannelAsync(ulong channelId, RequestOptions options = null) | |||
public async Task<Rpc.Channel> SendGetChannelAsync(ulong channelId, RequestOptions options = null) | |||
{ | |||
options = RequestOptions.CreateOrClone(options); | |||
var msg = new GetChannelParams | |||
{ | |||
ChannelId = channelId | |||
}; | |||
return await SendRpcAsync<Rpc.RpcChannel>("GET_CHANNEL", msg, options: options).ConfigureAwait(false); | |||
return await SendRpcAsync<Rpc.Channel>("GET_CHANNEL", msg, options: options).ConfigureAwait(false); | |||
} | |||
public async Task<SetLocalVolumeResponse> SendSetLocalVolumeAsync(int volume, RequestOptions options = null) | |||
public async Task<Rpc.Channel> SendSelectTextChannelAsync(ulong channelId, RequestOptions options = null) | |||
{ | |||
options = RequestOptions.CreateOrClone(options); | |||
var msg = new SetLocalVolumeParams | |||
var msg = new SelectChannelParams | |||
{ | |||
Volume = volume | |||
ChannelId = channelId | |||
}; | |||
return await SendRpcAsync<SetLocalVolumeResponse>("SET_LOCAL_VOLUME", msg, options: options).ConfigureAwait(false); | |||
return await SendRpcAsync<Rpc.Channel>("SELECT_TEXT_CHANNEL", msg, options: options).ConfigureAwait(false); | |||
} | |||
public async Task<Rpc.RpcChannel> SendSelectVoiceChannelAsync(ulong channelId, RequestOptions options = null) | |||
public async Task<Rpc.Channel> SendSelectVoiceChannelAsync(ulong channelId, bool force = false, RequestOptions options = null) | |||
{ | |||
options = RequestOptions.CreateOrClone(options); | |||
var msg = new SelectVoiceChannelParams | |||
var msg = new SelectChannelParams | |||
{ | |||
ChannelId = channelId | |||
ChannelId = channelId, | |||
Force = force | |||
}; | |||
return await SendRpcAsync<Rpc.RpcChannel>("SELECT_VOICE_CHANNEL", msg, options: options).ConfigureAwait(false); | |||
return await SendRpcAsync<Rpc.Channel>("SELECT_VOICE_CHANNEL", msg, options: options).ConfigureAwait(false); | |||
} | |||
public async Task<SubscriptionResponse> SendGlobalSubscribeAsync(string evt, RequestOptions options = null) | |||
@@ -370,10 +371,16 @@ namespace Discord.API | |||
options = RequestOptions.CreateOrClone(options); | |||
return await SendRpcAsync<API.Rpc.VoiceSettings>("GET_VOICE_SETTINGS", null, options: options).ConfigureAwait(false); | |||
} | |||
public async Task<API.Rpc.VoiceSettings> SetVoiceSettingsAsync(API.Rpc.VoiceSettings settings, RequestOptions options = null) | |||
public async Task SetVoiceSettingsAsync(API.Rpc.VoiceSettings settings, RequestOptions options = null) | |||
{ | |||
options = RequestOptions.CreateOrClone(options); | |||
await SendRpcAsync<API.Rpc.VoiceSettings>("SET_VOICE_SETTINGS", settings, options: options).ConfigureAwait(false); | |||
} | |||
public async Task SetUserVoiceSettingsAsync(ulong userId, API.Rpc.UserVoiceSettings settings, RequestOptions options = null) | |||
{ | |||
options = RequestOptions.CreateOrClone(options); | |||
return await SendRpcAsync<API.Rpc.VoiceSettings>("SET_VOICE_SETTINGS", settings, options: options).ConfigureAwait(false); | |||
settings.UserId = userId; | |||
await SendRpcAsync<API.Rpc.UserVoiceSettings>("SET_USER_VOICE_SETTINGS", settings, options: options).ConfigureAwait(false); | |||
} | |||
private bool ProcessMessage(API.Rpc.RpcFrame msg) | |||
@@ -0,0 +1,34 @@ | |||
#pragma warning disable CS1591 | |||
using Newtonsoft.Json; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class Channel | |||
{ | |||
//Shared | |||
[JsonProperty("id")] | |||
public ulong Id { get; set; } | |||
[JsonProperty("type")] | |||
public ChannelType Type { get; set; } | |||
//GuildChannel | |||
[JsonProperty("guild_id")] | |||
public Optional<ulong> GuildId { get; set; } | |||
[JsonProperty("name")] | |||
public Optional<string> Name { get; set; } | |||
[JsonProperty("position")] | |||
public Optional<int> Position { get; set; } | |||
//IMessageChannel | |||
[JsonProperty("messages")] | |||
public Message[] Messages { get; set; } | |||
//VoiceChannel | |||
[JsonProperty("bitrate")] | |||
public Optional<int> Bitrate { get; set; } | |||
[JsonProperty("user_limit")] | |||
public Optional<int> UserLimit { get; set; } | |||
[JsonProperty("voice_states")] | |||
public ExtendedVoiceState[] VoiceStates { get; set; } | |||
} | |||
} |
@@ -2,7 +2,7 @@ | |||
namespace Discord.API.Rpc | |||
{ | |||
public class ChannelCreatedEvent | |||
public class ChannelSummary | |||
{ | |||
[JsonProperty("id")] | |||
public ulong Id { get; set; } |
@@ -3,7 +3,7 @@ using Newtonsoft.Json; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class VoiceStateEvent | |||
public class ExtendedVoiceState | |||
{ | |||
[JsonProperty("user")] | |||
public User User { get; set; } |
@@ -1,11 +1,12 @@ | |||
#pragma warning disable CS1591 | |||
using Newtonsoft.Json; | |||
using System.Collections.Generic; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class GetChannelsResponse | |||
{ | |||
[JsonProperty("channels")] | |||
public RpcChannel[] Channels { get; set; } | |||
public IReadOnlyCollection<ChannelSummary> Channels { get; set; } | |||
} | |||
} |
@@ -1,4 +1,5 @@ | |||
#pragma warning disable CS1591 | |||
namespace Discord.API.Rpc | |||
{ | |||
public class GetGuildsParams | |||
@@ -6,6 +6,6 @@ namespace Discord.API.Rpc | |||
public class GetGuildsResponse | |||
{ | |||
[JsonProperty("guilds")] | |||
public RpcUserGuild[] Guilds { get; set; } | |||
public GuildSummary[] Guilds { get; set; } | |||
} | |||
} |
@@ -1,13 +1,18 @@ | |||
#pragma warning disable CS1591 | |||
using Newtonsoft.Json; | |||
using System.Collections.Generic; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class RpcUserGuild | |||
public class Guild | |||
{ | |||
[JsonProperty("id")] | |||
public ulong Id { get; set; } | |||
[JsonProperty("name")] | |||
public string Name { get; set; } | |||
[JsonProperty("icon_url")] | |||
public string IconUrl { get; set; } | |||
[JsonProperty("members")] | |||
public IEnumerable<GuildMember> Members { get; set; } | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
#pragma warning disable CS1591 | |||
using Newtonsoft.Json; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class GuildMember | |||
{ | |||
[JsonProperty("user")] | |||
public User User { get; set; } | |||
[JsonProperty("status")] | |||
public UserStatus Status { get; set; } | |||
/*[JsonProperty("activity")] | |||
public object Activity { get; set; }*/ | |||
} | |||
} |
@@ -2,7 +2,7 @@ | |||
namespace Discord.API.Rpc | |||
{ | |||
public class GuildCreatedEvent | |||
public class GuildSummary | |||
{ | |||
[JsonProperty("id")] | |||
public ulong Id { get; set; } |
@@ -2,7 +2,7 @@ | |||
namespace Discord.API.Rpc | |||
{ | |||
public class RpcMessage : Message | |||
public class Message : Discord.API.Message | |||
{ | |||
[JsonProperty("blocked")] | |||
public Optional<bool> IsBlocked { get; } |
@@ -7,6 +7,6 @@ namespace Discord.API.Rpc | |||
[JsonProperty("channel_id")] | |||
public ulong ChannelId { get; set; } | |||
[JsonProperty("message")] | |||
public RpcMessage Message { get; set; } | |||
public Message Message { get; set; } | |||
} | |||
} |
@@ -1,11 +0,0 @@ | |||
#pragma warning disable CS1591 | |||
using Newtonsoft.Json; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class RpcChannel : Channel | |||
{ | |||
[JsonProperty("voice_states")] | |||
public VoiceState[] VoiceStates { get; set; } | |||
} | |||
} |
@@ -1,13 +0,0 @@ | |||
#pragma warning disable CS1591 | |||
using Newtonsoft.Json; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class RpcGuild : Guild | |||
{ | |||
[JsonProperty("online")] | |||
public int Online { get; set; } | |||
[JsonProperty("members")] | |||
public GuildMember[] Members { get; set; } | |||
} | |||
} |
@@ -3,9 +3,11 @@ using Newtonsoft.Json; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class SelectVoiceChannelParams | |||
public class SelectChannelParams | |||
{ | |||
[JsonProperty("channel_id")] | |||
public ulong? ChannelId { get; set; } | |||
[JsonProperty("force")] | |||
public Optional<bool> Force { get; set; } | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
#pragma warning disable CS1591 | |||
using Newtonsoft.Json; | |||
namespace Discord.API.Rpc | |||
{ | |||
public class UserVoiceSettings | |||
{ | |||
[JsonProperty("userId")] | |||
internal ulong UserId { get; set; } | |||
[JsonProperty("pan")] | |||
public Optional<Pan> Pan { get; set; } | |||
[JsonProperty("volume")] | |||
public Optional<int> Volume { get; set; } | |||
[JsonProperty("mute")] | |||
public Optional<bool> Mute { get; set; } | |||
} | |||
} |
@@ -26,20 +26,20 @@ namespace Discord.Rpc | |||
private readonly AsyncEvent<Func<Task>> _readyEvent = new AsyncEvent<Func<Task>>(); | |||
//Channel | |||
public event Func<RpcChannel, Task> ChannelCreated | |||
public event Func<RpcChannelSummary, Task> ChannelCreated | |||
{ | |||
add { _channelCreatedEvent.Add(value); } | |||
remove { _channelCreatedEvent.Remove(value); } | |||
} | |||
private readonly AsyncEvent<Func<RpcChannel, Task>> _channelCreatedEvent = new AsyncEvent<Func<RpcChannel, Task>>(); | |||
private readonly AsyncEvent<Func<RpcChannelSummary, Task>> _channelCreatedEvent = new AsyncEvent<Func<RpcChannelSummary, Task>>(); | |||
//Guild | |||
public event Func<RpcGuild, Task> GuildCreated | |||
public event Func<RpcGuildSummary, Task> GuildCreated | |||
{ | |||
add { _guildCreatedEvent.Add(value); } | |||
remove { _guildCreatedEvent.Remove(value); } | |||
} | |||
private readonly AsyncEvent<Func<RpcGuild, Task>> _guildCreatedEvent = new AsyncEvent<Func<RpcGuild, Task>>(); | |||
private readonly AsyncEvent<Func<RpcGuildSummary, Task>> _guildCreatedEvent = new AsyncEvent<Func<RpcGuildSummary, Task>>(); | |||
public event Func<RpcGuildStatus, Task> GuildStatusUpdated | |||
{ | |||
add { _guildStatusUpdatedEvent.Add(value); } | |||
@@ -8,6 +8,7 @@ using Newtonsoft.Json.Linq; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.Linq; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
@@ -265,6 +266,59 @@ namespace Discord.Rpc | |||
await ApiClient.SendChannelUnsubscribeAsync(GetEventName(events[i]), channelId); | |||
} | |||
public async Task<RpcGuild> GetRpcGuildAsync(ulong id) | |||
{ | |||
var model = await ApiClient.SendGetGuildAsync(id).ConfigureAwait(false); | |||
return RpcGuild.Create(this, model); | |||
} | |||
public async Task<IReadOnlyCollection<RpcGuildSummary>> GetRpcGuildsAsync() | |||
{ | |||
var models = await ApiClient.SendGetGuildsAsync().ConfigureAwait(false); | |||
return models.Guilds.Select(x => RpcGuildSummary.Create(x)).ToImmutableArray(); | |||
} | |||
public async Task<RpcChannel> GetRpcChannelAsync(ulong id) | |||
{ | |||
var model = await ApiClient.SendGetChannelAsync(id).ConfigureAwait(false); | |||
return RpcChannel.Create(this, model); | |||
} | |||
public async Task<IReadOnlyCollection<RpcChannelSummary>> GetRpcChannelsAsync(ulong guildId) | |||
{ | |||
var models = await ApiClient.SendGetChannelsAsync(guildId).ConfigureAwait(false); | |||
return models.Channels.Select(x => RpcChannelSummary.Create(x)).ToImmutableArray(); | |||
} | |||
public async Task<IMessageChannel> SelectTextChannelAsync(IChannel channel) | |||
{ | |||
var model = await ApiClient.SendSelectTextChannelAsync(channel.Id).ConfigureAwait(false); | |||
return RpcChannel.Create(this, model) as IMessageChannel; | |||
} | |||
public async Task<IMessageChannel> SelectTextChannelAsync(RpcChannelSummary channel) | |||
{ | |||
var model = await ApiClient.SendSelectTextChannelAsync(channel.Id).ConfigureAwait(false); | |||
return RpcChannel.Create(this, model) as IMessageChannel; | |||
} | |||
public async Task<IMessageChannel> SelectTextChannelAsync(ulong channelId) | |||
{ | |||
var model = await ApiClient.SendSelectTextChannelAsync(channelId).ConfigureAwait(false); | |||
return RpcChannel.Create(this, model) as IMessageChannel; | |||
} | |||
public async Task<IRpcAudioChannel> SelectVoiceChannelAsync(IChannel channel, bool force = false) | |||
{ | |||
var model = await ApiClient.SendSelectVoiceChannelAsync(channel.Id, force).ConfigureAwait(false); | |||
return RpcChannel.Create(this, model) as IRpcAudioChannel; | |||
} | |||
public async Task<IRpcAudioChannel> SelectVoiceChannelAsync(RpcChannelSummary channel, bool force = false) | |||
{ | |||
var model = await ApiClient.SendSelectVoiceChannelAsync(channel.Id, force).ConfigureAwait(false); | |||
return RpcChannel.Create(this, model) as IRpcAudioChannel; | |||
} | |||
public async Task<IRpcAudioChannel> SelectVoiceChannelAsync(ulong channelId, bool force = false) | |||
{ | |||
var model = await ApiClient.SendSelectVoiceChannelAsync(channelId, force).ConfigureAwait(false); | |||
return RpcChannel.Create(this, model) as IRpcAudioChannel; | |||
} | |||
public async Task<VoiceSettings> GetVoiceSettingsAsync() | |||
{ | |||
var model = await ApiClient.GetVoiceSettingsAsync().ConfigureAwait(false); | |||
@@ -279,6 +333,12 @@ namespace Discord.Rpc | |||
func(settings); | |||
await ApiClient.SetVoiceSettingsAsync(settings).ConfigureAwait(false); | |||
} | |||
public async Task SetUserVoiceSettingsAsync(ulong userId, Action<API.Rpc.UserVoiceSettings> func) | |||
{ | |||
var settings = new API.Rpc.UserVoiceSettings(); | |||
func(settings); | |||
await ApiClient.SetUserVoiceSettingsAsync(userId, settings).ConfigureAwait(false); | |||
} | |||
private static string GetEventName(RpcGlobalEvent rpcEvent) | |||
{ | |||
@@ -363,8 +423,8 @@ namespace Discord.Rpc | |||
case "CHANNEL_CREATE": | |||
{ | |||
await _rpcLogger.DebugAsync("Received Dispatch (CHANNEL_CREATE)").ConfigureAwait(false); | |||
var data = (payload.Value as JToken).ToObject<ChannelCreatedEvent>(_serializer); | |||
var channel = RpcChannel.Create(data); | |||
var data = (payload.Value as JToken).ToObject<ChannelSummary>(_serializer); | |||
var channel = RpcChannelSummary.Create(data); | |||
await _channelCreatedEvent.InvokeAsync(channel).ConfigureAwait(false); | |||
} | |||
@@ -374,8 +434,8 @@ namespace Discord.Rpc | |||
case "GUILD_CREATE": | |||
{ | |||
await _rpcLogger.DebugAsync("Received Dispatch (GUILD_CREATE)").ConfigureAwait(false); | |||
var data = (payload.Value as JToken).ToObject<GuildCreatedEvent>(_serializer); | |||
var guild = RpcGuild.Create(data); | |||
var data = (payload.Value as JToken).ToObject<GuildSummary>(_serializer); | |||
var guild = RpcGuildSummary.Create(data); | |||
await _guildCreatedEvent.InvokeAsync(guild).ConfigureAwait(false); | |||
} | |||
@@ -394,7 +454,7 @@ namespace Discord.Rpc | |||
case "VOICE_STATE_CREATE": | |||
{ | |||
await _rpcLogger.DebugAsync("Received Dispatch (VOICE_STATE_CREATE)").ConfigureAwait(false); | |||
var data = (payload.Value as JToken).ToObject<VoiceStateEvent>(_serializer); | |||
var data = (payload.Value as JToken).ToObject<ExtendedVoiceState>(_serializer); | |||
var voiceState = RpcVoiceState.Create(this, data); | |||
await _voiceStateCreatedEvent.InvokeAsync(voiceState).ConfigureAwait(false); | |||
@@ -403,7 +463,7 @@ namespace Discord.Rpc | |||
case "VOICE_STATE_UPDATE": | |||
{ | |||
await _rpcLogger.DebugAsync("Received Dispatch (VOICE_STATE_UPDATE)").ConfigureAwait(false); | |||
var data = (payload.Value as JToken).ToObject<VoiceStateEvent>(_serializer); | |||
var data = (payload.Value as JToken).ToObject<ExtendedVoiceState>(_serializer); | |||
var voiceState = RpcVoiceState.Create(this, data); | |||
await _voiceStateUpdatedEvent.InvokeAsync(voiceState).ConfigureAwait(false); | |||
@@ -412,7 +472,7 @@ namespace Discord.Rpc | |||
case "VOICE_STATE_DELETE": | |||
{ | |||
await _rpcLogger.DebugAsync("Received Dispatch (VOICE_STATE_DELETE)").ConfigureAwait(false); | |||
var data = (payload.Value as JToken).ToObject<VoiceStateEvent>(_serializer); | |||
var data = (payload.Value as JToken).ToObject<ExtendedVoiceState>(_serializer); | |||
var voiceState = RpcVoiceState.Create(this, data); | |||
await _voiceStateDeletedEvent.InvokeAsync(voiceState).ConfigureAwait(false); | |||
@@ -0,0 +1,9 @@ | |||
using System.Collections.Generic; | |||
namespace Discord.Rpc | |||
{ | |||
public interface IRpcAudioChannel : IAudioChannel | |||
{ | |||
IReadOnlyCollection<RpcVoiceState> VoiceStates { get; } | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
using System.Collections.Generic; | |||
namespace Discord.Rpc | |||
{ | |||
public interface IRpcMessageChannel : IMessageChannel | |||
{ | |||
IReadOnlyCollection<RpcMessage> CachedMessages { get; } | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
namespace Discord.Rpc | |||
{ | |||
public interface IRpcPrivateChannel | |||
{ | |||
} | |||
} |
@@ -1,32 +1,40 @@ | |||
using System.Diagnostics; | |||
using Model = Discord.API.Rpc.ChannelCreatedEvent; | |||
using System; | |||
using Model = Discord.API.Rpc.Channel; | |||
namespace Discord.Rpc | |||
{ | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RpcChannel | |||
public class RpcChannel : RpcEntity<ulong> | |||
{ | |||
public ulong Id { get; } | |||
public string Name { get; set; } | |||
public ChannelType Type { get; set; } | |||
public string Name { get; private set; } | |||
internal RpcChannel(ulong id) | |||
internal RpcChannel(DiscordRpcClient discord, ulong id) | |||
: base(discord, id) | |||
{ | |||
Id = id; | |||
} | |||
internal static RpcChannel Create(Model model) | |||
internal static RpcChannel Create(DiscordRpcClient discord, Model model) | |||
{ | |||
var entity = new RpcChannel(model.Id); | |||
entity.Update(model); | |||
return entity; | |||
if (model.GuildId.IsSpecified) | |||
return RpcGuildChannel.Create(discord, model); | |||
else | |||
return CreatePrivate(discord, model); | |||
} | |||
internal void Update(Model model) | |||
internal static RpcChannel CreatePrivate(DiscordRpcClient discord, Model model) | |||
{ | |||
Name = model.Name; | |||
Type = model.Type; | |||
switch (model.Type) | |||
{ | |||
case ChannelType.DM: | |||
return RpcDMChannel.Create(discord, model); | |||
case ChannelType.Group: | |||
return RpcGroupChannel.Create(discord, model); | |||
default: | |||
throw new InvalidOperationException($"Unexpected channel type: {model.Type}"); | |||
} | |||
} | |||
internal virtual void Update(Model model) | |||
{ | |||
if (model.Name.IsSpecified) | |||
Name = model.Name.Value; | |||
} | |||
public override string ToString() => Name; | |||
private string DebuggerDisplay => $"{Name} ({Id}, {Type})"; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
using System.Diagnostics; | |||
using Model = Discord.API.Rpc.ChannelSummary; | |||
namespace Discord.Rpc | |||
{ | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RpcChannelSummary | |||
{ | |||
public ulong Id { get; } | |||
public string Name { get; set; } | |||
public ChannelType Type { get; set; } | |||
internal RpcChannelSummary(ulong id) | |||
{ | |||
Id = id; | |||
} | |||
internal static RpcChannelSummary Create(Model model) | |||
{ | |||
var entity = new RpcChannelSummary(model.Id); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal void Update(Model model) | |||
{ | |||
Name = model.Name; | |||
Type = model.Type; | |||
} | |||
public override string ToString() => Name; | |||
private string DebuggerDisplay => $"{Name} ({Id}, {Type})"; | |||
} | |||
} |
@@ -0,0 +1,124 @@ | |||
using Discord.Rest; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Model = Discord.API.Rpc.Channel; | |||
namespace Discord.Rpc | |||
{ | |||
public class RpcDMChannel : RpcChannel, IRpcMessageChannel, IRpcPrivateChannel, IDMChannel | |||
{ | |||
public IReadOnlyCollection<RpcMessage> CachedMessages { get; private set; } | |||
internal RpcDMChannel(DiscordRpcClient discord, ulong id) | |||
: base(discord, id) | |||
{ | |||
} | |||
internal static new RpcDMChannel Create(DiscordRpcClient discord, Model model) | |||
{ | |||
var entity = new RpcDMChannel(discord, model.Id); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal override void Update(Model model) | |||
{ | |||
base.Update(model); | |||
CachedMessages = model.Messages.Select(x => RpcMessage.Create(Discord, Id, x)).ToImmutableArray(); | |||
} | |||
public Task CloseAsync(RequestOptions options = null) | |||
=> ChannelHelper.DeleteAsync(this, Discord, options); | |||
//TODO: Use RPC cache | |||
public Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null) | |||
=> ChannelHelper.GetMessageAsync(this, Discord, id, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, null, Direction.Before, limit, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit, null, options); | |||
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord, null, options); | |||
public Task<RestUserMessage> SendMessageAsync(string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, null, options); | |||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, null, options); | |||
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, null, options); | |||
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null) | |||
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages, options); | |||
public Task TriggerTypingAsync(RequestOptions options = null) | |||
=> ChannelHelper.TriggerTypingAsync(this, Discord, options); | |||
public IDisposable EnterTypingState(RequestOptions options = null) | |||
=> ChannelHelper.EnterTypingState(this, Discord, options); | |||
public override string ToString() => Id.ToString(); | |||
private string DebuggerDisplay => $"({Id}, DM)"; | |||
//IDMChannel | |||
IUser IDMChannel.Recipient { get { throw new NotSupportedException(); } } | |||
//IPrivateChannel | |||
IReadOnlyCollection<IUser> IPrivateChannel.Recipients { get { throw new NotSupportedException(); } } | |||
//IMessageChannel | |||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return await GetMessageAsync(id, options); | |||
else | |||
return null; | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(fromMessageId, dir, limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(IMessage fromMessage, Direction dir, int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(fromMessage, dir, limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) | |||
=> await GetPinnedMessagesAsync(options); | |||
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, RequestOptions options) | |||
=> await SendFileAsync(filePath, text, isTTS, options); | |||
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, RequestOptions options) | |||
=> await SendFileAsync(stream, filename, text, isTTS, options); | |||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, RequestOptions options) | |||
=> await SendMessageAsync(text, isTTS, options); | |||
IDisposable IMessageChannel.EnterTypingState(RequestOptions options) | |||
=> EnterTypingState(options); | |||
//IChannel | |||
string IChannel.Name { get { throw new NotSupportedException(); } } | |||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,123 @@ | |||
using Discord.Rest; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Model = Discord.API.Rpc.Channel; | |||
namespace Discord.Rpc | |||
{ | |||
public class RpcGroupChannel : RpcChannel, IRpcMessageChannel, IRpcAudioChannel, IRpcPrivateChannel, IGroupChannel | |||
{ | |||
public IReadOnlyCollection<RpcMessage> CachedMessages { get; private set; } | |||
public IReadOnlyCollection<RpcVoiceState> VoiceStates { get; private set; } | |||
internal RpcGroupChannel(DiscordRpcClient discord, ulong id) | |||
: base(discord, id) | |||
{ | |||
} | |||
internal new static RpcGroupChannel Create(DiscordRpcClient discord, Model model) | |||
{ | |||
var entity = new RpcGroupChannel(discord, model.Id); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal override void Update(Model model) | |||
{ | |||
base.Update(model); | |||
CachedMessages = model.Messages.Select(x => RpcMessage.Create(Discord, Id, x)).ToImmutableArray(); | |||
VoiceStates = model.VoiceStates.Select(x => RpcVoiceState.Create(Discord, x)).ToImmutableArray(); | |||
} | |||
public Task LeaveAsync(RequestOptions options = null) | |||
=> ChannelHelper.DeleteAsync(this, Discord, options); | |||
//TODO: Use RPC cache | |||
public Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null) | |||
=> ChannelHelper.GetMessageAsync(this, Discord, id, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, null, Direction.Before, limit, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit, null, options); | |||
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord, null, options); | |||
public Task<RestUserMessage> SendMessageAsync(string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, null, options); | |||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, null, options); | |||
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, null, options); | |||
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null) | |||
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages, options); | |||
public Task TriggerTypingAsync(RequestOptions options = null) | |||
=> ChannelHelper.TriggerTypingAsync(this, Discord, options); | |||
public IDisposable EnterTypingState(RequestOptions options = null) | |||
=> ChannelHelper.EnterTypingState(this, Discord, options); | |||
public override string ToString() => Id.ToString(); | |||
private string DebuggerDisplay => $"({Id}, Group)"; | |||
//IPrivateChannel | |||
IReadOnlyCollection<IUser> IPrivateChannel.Recipients { get { throw new NotSupportedException(); } } | |||
//IMessageChannel | |||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return await GetMessageAsync(id, options); | |||
else | |||
return null; | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(fromMessageId, dir, limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(IMessage fromMessage, Direction dir, int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(fromMessage, dir, limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) | |||
=> await GetPinnedMessagesAsync(options); | |||
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, RequestOptions options) | |||
=> await SendFileAsync(filePath, text, isTTS, options); | |||
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, RequestOptions options) | |||
=> await SendFileAsync(stream, filename, text, isTTS, options); | |||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, RequestOptions options) | |||
=> await SendMessageAsync(text, isTTS, options); | |||
IDisposable IMessageChannel.EnterTypingState(RequestOptions options) | |||
=> EnterTypingState(options); | |||
//IChannel | |||
string IChannel.Name { get { throw new NotSupportedException(); } } | |||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,94 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Threading.Tasks; | |||
using Discord.API.Rest; | |||
using Model = Discord.API.Rpc.Channel; | |||
using Discord.Rest; | |||
namespace Discord.Rpc | |||
{ | |||
public class RpcGuildChannel : RpcChannel, IGuildChannel | |||
{ | |||
public ulong GuildId { get; } | |||
public int Position { get; private set; } | |||
internal RpcGuildChannel(DiscordRpcClient discord, ulong id, ulong guildId) | |||
: base(discord, id) | |||
{ | |||
GuildId = guildId; | |||
} | |||
internal new static RpcGuildChannel Create(DiscordRpcClient discord, Model model) | |||
{ | |||
switch (model.Type) | |||
{ | |||
case ChannelType.Text: | |||
return RpcTextChannel.Create(discord, model); | |||
case ChannelType.Voice: | |||
return RpcVoiceChannel.Create(discord, model); | |||
default: | |||
throw new InvalidOperationException("Unknown guild channel type"); | |||
} | |||
} | |||
internal override void Update(Model model) | |||
{ | |||
base.Update(model); | |||
if (model.Position.IsSpecified) | |||
Position = model.Position.Value; | |||
} | |||
public Task ModifyAsync(Action<ModifyGuildChannelParams> func, RequestOptions options = null) | |||
=> ChannelHelper.ModifyAsync(this, Discord, func, options); | |||
public Task DeleteAsync(RequestOptions options = null) | |||
=> ChannelHelper.DeleteAsync(this, Discord, options); | |||
public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions perms, RequestOptions options = null) | |||
=> ChannelHelper.AddPermissionOverwriteAsync(this, Discord, user, perms, options); | |||
public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions perms, RequestOptions options = null) | |||
=> ChannelHelper.AddPermissionOverwriteAsync(this, Discord, role, perms, options); | |||
public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null) | |||
=> ChannelHelper.RemovePermissionOverwriteAsync(this, Discord, user, options); | |||
public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null) | |||
=> ChannelHelper.RemovePermissionOverwriteAsync(this, Discord, role, options); | |||
public async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(RequestOptions options = null) | |||
=> await ChannelHelper.GetInvitesAsync(this, Discord, options); | |||
public async Task<RestInviteMetadata> CreateInviteAsync(int? maxAge = 3600, int? maxUses = null, bool isTemporary = true, RequestOptions options = null) | |||
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, options); | |||
public override string ToString() => Name; | |||
//IGuildChannel | |||
async Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync(RequestOptions options) | |||
=> await GetInvitesAsync(options); | |||
async Task<IInviteMetadata> IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, RequestOptions options) | |||
=> await CreateInviteAsync(maxAge, maxUses, isTemporary, options); | |||
IReadOnlyCollection<Overwrite> IGuildChannel.PermissionOverwrites { get { throw new NotSupportedException(); } } | |||
OverwritePermissions? IGuildChannel.GetPermissionOverwrite(IUser user) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
OverwritePermissions? IGuildChannel.GetPermissionOverwrite(IRole role) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
//IChannel | |||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
throw new NotSupportedException(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,113 @@ | |||
using Discord.API.Rest; | |||
using Discord.Rest; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.Diagnostics; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Model = Discord.API.Rpc.Channel; | |||
namespace Discord.Rpc | |||
{ | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RpcTextChannel : RpcGuildChannel, IRpcMessageChannel, ITextChannel | |||
{ | |||
public IReadOnlyCollection<RpcMessage> CachedMessages { get; private set; } | |||
public string Mention => MentionUtils.MentionChannel(Id); | |||
internal RpcTextChannel(DiscordRpcClient discord, ulong id, ulong guildId) | |||
: base(discord, id, guildId) | |||
{ | |||
} | |||
internal new static RpcVoiceChannel Create(DiscordRpcClient discord, Model model) | |||
{ | |||
var entity = new RpcVoiceChannel(discord, model.Id, model.GuildId.Value); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal override void Update(Model model) | |||
{ | |||
base.Update(model); | |||
CachedMessages = model.Messages.Select(x => RpcMessage.Create(Discord, Id, x)).ToImmutableArray(); | |||
} | |||
public Task ModifyAsync(Action<ModifyTextChannelParams> func, RequestOptions options = null) | |||
=> ChannelHelper.ModifyAsync(this, Discord, func, options); | |||
//TODO: Use RPC cache | |||
public Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null) | |||
=> ChannelHelper.GetMessageAsync(this, Discord, id, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, null, Direction.Before, limit, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit, null, options); | |||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit, null, options); | |||
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord, null, options); | |||
public Task<RestUserMessage> SendMessageAsync(string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, null, options); | |||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, null, options); | |||
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS, RequestOptions options = null) | |||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, null, options); | |||
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null) | |||
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages, options); | |||
public Task TriggerTypingAsync(RequestOptions options = null) | |||
=> ChannelHelper.TriggerTypingAsync(this, Discord, options); | |||
public IDisposable EnterTypingState(RequestOptions options = null) | |||
=> ChannelHelper.EnterTypingState(this, Discord, options); | |||
private string DebuggerDisplay => $"{Name} ({Id}, Text)"; | |||
//ITextChannel | |||
string ITextChannel.Topic { get { throw new NotSupportedException(); } } | |||
//IMessageChannel | |||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return await GetMessageAsync(id, options); | |||
else | |||
return null; | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(fromMessageId, dir, limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(IMessage fromMessage, Direction dir, int limit, CacheMode mode, RequestOptions options) | |||
{ | |||
if (mode == CacheMode.AllowDownload) | |||
return GetMessagesAsync(fromMessage, dir, limit, options); | |||
else | |||
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); | |||
} | |||
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) | |||
=> await GetPinnedMessagesAsync(options); | |||
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, RequestOptions options) | |||
=> await SendFileAsync(filePath, text, isTTS, options); | |||
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, RequestOptions options) | |||
=> await SendFileAsync(stream, filename, text, isTTS, options); | |||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, RequestOptions options) | |||
=> await SendMessageAsync(text, isTTS, options); | |||
IDisposable IMessageChannel.EnterTypingState(RequestOptions options) | |||
=> EnterTypingState(options); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
using Discord.API.Rest; | |||
using Discord.Audio; | |||
using Discord.Rest; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Model = Discord.API.Rpc.Channel; | |||
namespace Discord.Rpc | |||
{ | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RpcVoiceChannel : RpcGuildChannel, IRpcAudioChannel, IVoiceChannel | |||
{ | |||
public int UserLimit { get; private set; } | |||
public int Bitrate { get; private set; } | |||
public IReadOnlyCollection<RpcVoiceState> VoiceStates { get; private set; } | |||
internal RpcVoiceChannel(DiscordRpcClient discord, ulong id, ulong guildId) | |||
: base(discord, id, guildId) | |||
{ | |||
} | |||
internal new static RpcVoiceChannel Create(DiscordRpcClient discord, Model model) | |||
{ | |||
var entity = new RpcVoiceChannel(discord, model.Id, model.GuildId.Value); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal override void Update(Model model) | |||
{ | |||
base.Update(model); | |||
if (model.UserLimit.IsSpecified) | |||
UserLimit = model.UserLimit.Value; | |||
if (model.Bitrate.IsSpecified) | |||
Bitrate = model.Bitrate.Value; | |||
VoiceStates = model.VoiceStates.Select(x => RpcVoiceState.Create(Discord, x)).ToImmutableArray(); | |||
} | |||
public Task ModifyAsync(Action<ModifyVoiceChannelParams> func, RequestOptions options = null) | |||
=> ChannelHelper.ModifyAsync(this, Discord, func, options); | |||
private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; | |||
//IVoiceChannel | |||
Task<IAudioClient> IVoiceChannel.ConnectAsync() { throw new NotSupportedException(); } | |||
} | |||
} |
@@ -1,27 +1,33 @@ | |||
using System.Diagnostics; | |||
using Model = Discord.API.Rpc.GuildCreatedEvent; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using Model = Discord.API.Rpc.Guild; | |||
namespace Discord.Rpc | |||
{ | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RpcGuild | |||
public class RpcGuild : RpcEntity<ulong> | |||
{ | |||
public ulong Id { get; } | |||
public string Name { get; set; } | |||
public string Name { get; private set; } | |||
public string IconUrl { get; private set; } | |||
public IReadOnlyCollection<RpcGuildUser> Users { get; private set; } | |||
internal RpcGuild(ulong id) | |||
internal RpcGuild(DiscordRpcClient discord, ulong id) | |||
: base(discord, id) | |||
{ | |||
Id = id; | |||
} | |||
internal static RpcGuild Create(Model model) | |||
internal static RpcGuild Create(DiscordRpcClient discord, Model model) | |||
{ | |||
var entity = new RpcGuild(model.Id); | |||
var entity = new RpcGuild(discord, model.Id); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal void Update(Model model) | |||
{ | |||
Name = model.Name; | |||
IconUrl = model.IconUrl; | |||
Users = model.Members.Select(x => RpcGuildUser.Create(Discord, x)).ToImmutableArray(); | |||
} | |||
public override string ToString() => Name; | |||
@@ -6,12 +6,12 @@ namespace Discord.Rpc | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RpcGuildStatus | |||
{ | |||
public RpcGuild Guild { get; } | |||
public RpcGuildSummary Guild { get; } | |||
public int Online { get; private set; } | |||
internal RpcGuildStatus(ulong guildId) | |||
{ | |||
Guild = new RpcGuild(guildId); | |||
Guild = new RpcGuildSummary(guildId); | |||
} | |||
internal static RpcGuildStatus Create(Model model) | |||
{ | |||
@@ -0,0 +1,30 @@ | |||
using System.Diagnostics; | |||
using Model = Discord.API.Rpc.GuildSummary; | |||
namespace Discord.Rpc | |||
{ | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RpcGuildSummary | |||
{ | |||
public ulong Id { get; } | |||
public string Name { get; private set; } | |||
internal RpcGuildSummary(ulong id) | |||
{ | |||
Id = id; | |||
} | |||
internal static RpcGuildSummary Create(Model model) | |||
{ | |||
var entity = new RpcGuildSummary(model.Id); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal void Update(Model model) | |||
{ | |||
Name = model.Name; | |||
} | |||
public override string ToString() => Name; | |||
private string DebuggerDisplay => $"{Name} ({Id})"; | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using Model = Discord.API.Rpc.RpcMessage; | |||
using Model = Discord.API.Rpc.Message; | |||
namespace Discord.Rpc | |||
{ | |||
@@ -1,6 +1,6 @@ | |||
using Discord.Rest; | |||
using System.Diagnostics; | |||
using Model = Discord.API.Rpc.RpcMessage; | |||
using Model = Discord.API.Rpc.Message; | |||
namespace Discord.Rpc | |||
{ | |||
@@ -5,7 +5,7 @@ using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.Diagnostics; | |||
using System.Threading.Tasks; | |||
using Model = Discord.API.Rpc.RpcMessage; | |||
using Model = Discord.API.Rpc.Message; | |||
namespace Discord.Rpc | |||
{ | |||
@@ -0,0 +1,29 @@ | |||
using Model = Discord.API.Rpc.GuildMember; | |||
namespace Discord.Rpc | |||
{ | |||
public class RpcGuildUser : RpcUser | |||
{ | |||
private UserStatus _status; | |||
public override UserStatus Status => _status; | |||
//public object Acitivity { get; private set; } | |||
internal RpcGuildUser(DiscordRpcClient discord, ulong id) | |||
: base(discord, id) | |||
{ | |||
} | |||
internal static RpcGuildUser Create(DiscordRpcClient discord, Model model) | |||
{ | |||
var entity = new RpcGuildUser(discord, model.User.Id); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal void Update(Model model) | |||
{ | |||
base.Update(model.User); | |||
_status = model.Status; | |||
//Activity = model.Activity; | |||
} | |||
} | |||
} |
@@ -6,7 +6,7 @@ using Model = Discord.API.User; | |||
namespace Discord.Rpc | |||
{ | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RpcUser : RpcEntity<ulong>, IUser, IUpdateable | |||
public class RpcUser : RpcEntity<ulong>, IUser | |||
{ | |||
public bool IsBot { get; private set; } | |||
public string Username { get; private set; } | |||
@@ -40,12 +40,6 @@ namespace Discord.Rpc | |||
if (model.Username.IsSpecified) | |||
Username = model.Username.Value; | |||
} | |||
public virtual async Task UpdateAsync(RequestOptions options = null) | |||
{ | |||
var model = await Discord.ApiClient.GetUserAsync(Id, options); | |||
Update(model); | |||
} | |||
public Task<RestDMChannel> CreateDMChannelAsync(RequestOptions options = null) | |||
=> UserHelper.CreateDMChannelAsync(this, Discord, options); | |||
@@ -1,6 +1,6 @@ | |||
using System; | |||
using System.Diagnostics; | |||
using Model = Discord.API.Rpc.VoiceStateEvent; | |||
using Model = Discord.API.Rpc.ExtendedVoiceState; | |||
namespace Discord.Rpc | |||
{ | |||
@@ -1,6 +1,5 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||