diff --git a/src/Discord.Net/Entities/Channels/DMChannel.cs b/src/Discord.Net/Entities/Channels/DMChannel.cs index 50d275f44..6294e3f21 100644 --- a/src/Discord.Net/Entities/Channels/DMChannel.cs +++ b/src/Discord.Net/Entities/Channels/DMChannel.cs @@ -70,7 +70,7 @@ namespace Discord { var args = new CreateMessageParams { Content = text, IsTTS = isTTS }; var model = await Discord.ApiClient.CreateDMMessageAsync(Id, args).ConfigureAwait(false); - return new Message(this, new User(Discord, model.Author.Value), model); + return new Message(this, new User(model.Author.Value), model); } public async Task SendFileAsync(string filePath, string text, bool isTTS) { @@ -79,33 +79,33 @@ namespace Discord { var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; var model = await Discord.ApiClient.UploadDMFileAsync(Id, file, args).ConfigureAwait(false); - return new Message(this, new User(Discord, model.Author.Value), model); + return new Message(this, new User(model.Author.Value), model); } } public async Task SendFileAsync(Stream stream, string filename, string text, bool isTTS) { var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; var model = await Discord.ApiClient.UploadDMFileAsync(Id, stream, args).ConfigureAwait(false); - return new Message(this, new User(Discord, model.Author.Value), model); + return new Message(this, new User(model.Author.Value), model); } public virtual async Task GetMessageAsync(ulong id) { var model = await Discord.ApiClient.GetChannelMessageAsync(Id, id).ConfigureAwait(false); if (model != null) - return new Message(this, new User(Discord, model.Author.Value), model); + return new Message(this, new User(model.Author.Value), model); return null; } public virtual async Task> GetMessagesAsync(int limit) { var args = new GetChannelMessagesParams { Limit = limit }; var models = await Discord.ApiClient.GetChannelMessagesAsync(Id, args).ConfigureAwait(false); - return models.Select(x => new Message(this, new User(Discord, x.Author.Value), x)).ToImmutableArray(); + return models.Select(x => new Message(this, new User(x.Author.Value), x)).ToImmutableArray(); } public virtual async Task> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit) { var args = new GetChannelMessagesParams { Limit = limit }; var models = await Discord.ApiClient.GetChannelMessagesAsync(Id, args).ConfigureAwait(false); - return models.Select(x => new Message(this, new User(Discord, x.Author.Value), x)).ToImmutableArray(); + return models.Select(x => new Message(this, new User(x.Author.Value), x)).ToImmutableArray(); } public async Task DeleteMessagesAsync(IEnumerable messages) { diff --git a/src/Discord.Net/Entities/Channels/TextChannel.cs b/src/Discord.Net/Entities/Channels/TextChannel.cs index 6f01a263a..4b2fe150e 100644 --- a/src/Discord.Net/Entities/Channels/TextChannel.cs +++ b/src/Discord.Net/Entities/Channels/TextChannel.cs @@ -62,7 +62,7 @@ namespace Discord { var args = new CreateMessageParams { Content = text, IsTTS = isTTS }; var model = await Discord.ApiClient.CreateMessageAsync(Guild.Id, Id, args).ConfigureAwait(false); - return new Message(this, new User(Discord, model.Author.Value), model); + return new Message(this, new User(model.Author.Value), model); } public async Task SendFileAsync(string filePath, string text, bool isTTS) { @@ -71,33 +71,33 @@ namespace Discord { var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; var model = await Discord.ApiClient.UploadFileAsync(Guild.Id, Id, file, args).ConfigureAwait(false); - return new Message(this, new User(Discord, model.Author.Value), model); + return new Message(this, new User(model.Author.Value), model); } } public async Task SendFileAsync(Stream stream, string filename, string text, bool isTTS) { var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; var model = await Discord.ApiClient.UploadFileAsync(Guild.Id, Id, stream, args).ConfigureAwait(false); - return new Message(this, new User(Discord, model.Author.Value), model); + return new Message(this, new User(model.Author.Value), model); } public virtual async Task GetMessageAsync(ulong id) { var model = await Discord.ApiClient.GetChannelMessageAsync(Id, id).ConfigureAwait(false); if (model != null) - return new Message(this, new User(Discord, model.Author.Value), model); + return new Message(this, new User(model.Author.Value), model); return null; } public virtual async Task> GetMessagesAsync(int limit) { var args = new GetChannelMessagesParams { Limit = limit }; var models = await Discord.ApiClient.GetChannelMessagesAsync(Id, args).ConfigureAwait(false); - return models.Select(x => new Message(this, new User(Discord, x.Author.Value), x)).ToImmutableArray(); + return models.Select(x => new Message(this, new User(x.Author.Value), x)).ToImmutableArray(); } public virtual async Task> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit) { var args = new GetChannelMessagesParams { Limit = limit }; var models = await Discord.ApiClient.GetChannelMessagesAsync(Id, args).ConfigureAwait(false); - return models.Select(x => new Message(this, new User(Discord, x.Author.Value), x)).ToImmutableArray(); + return models.Select(x => new Message(this, new User(x.Author.Value), x)).ToImmutableArray(); } public async Task DeleteMessagesAsync(IEnumerable messages) { diff --git a/src/Discord.Net/Entities/Guilds/Guild.cs b/src/Discord.Net/Entities/Guilds/Guild.cs index 44d3fa326..f17cb158c 100644 --- a/src/Discord.Net/Entities/Guilds/Guild.cs +++ b/src/Discord.Net/Entities/Guilds/Guild.cs @@ -149,7 +149,7 @@ namespace Discord public async Task> GetBansAsync() { var models = await Discord.ApiClient.GetGuildBansAsync(Id).ConfigureAwait(false); - return models.Select(x => new User(Discord, x)).ToImmutableArray(); + return models.Select(x => new User(x)).ToImmutableArray(); } public Task AddBanAsync(IUser user, int pruneDays = 0) => AddBanAsync(user, pruneDays); public async Task AddBanAsync(ulong userId, int pruneDays = 0) @@ -254,7 +254,7 @@ namespace Discord { var model = await Discord.ApiClient.GetGuildMemberAsync(Id, id).ConfigureAwait(false); if (model != null) - return new GuildUser(this, new User(Discord, model.User), model); + return new GuildUser(this, new User(model.User), model); return null; } public virtual async Task GetCurrentUserAsync() @@ -266,13 +266,13 @@ namespace Discord { var args = new GetGuildMembersParams(); var models = await Discord.ApiClient.GetGuildMembersAsync(Id, args).ConfigureAwait(false); - return models.Select(x => new GuildUser(this, new User(Discord, x.User), x)).ToImmutableArray(); + return models.Select(x => new GuildUser(this, new User(x.User), x)).ToImmutableArray(); } public virtual async Task> GetUsersAsync(int limit, int offset) { var args = new GetGuildMembersParams { Limit = limit, Offset = offset }; var models = await Discord.ApiClient.GetGuildMembersAsync(Id, args).ConfigureAwait(false); - return models.Select(x => new GuildUser(this, new User(Discord, x.User), x)).ToImmutableArray(); + return models.Select(x => new GuildUser(this, new User(x.User), x)).ToImmutableArray(); } public async Task PruneUsersAsync(int days = 30, bool simulate = false) { diff --git a/src/Discord.Net/Entities/Guilds/GuildIntegration.cs b/src/Discord.Net/Entities/Guilds/GuildIntegration.cs index b0de3518a..0aba4d4e3 100644 --- a/src/Discord.Net/Entities/Guilds/GuildIntegration.cs +++ b/src/Discord.Net/Entities/Guilds/GuildIntegration.cs @@ -46,7 +46,7 @@ namespace Discord _syncedAtTicks = model.SyncedAt.UtcTicks; Role = Guild.GetRole(model.RoleId); - User = new User(Discord, model.User); + User = new User(model.User); } public async Task DeleteAsync() diff --git a/src/Discord.Net/Entities/Invites/InviteMetadata.cs b/src/Discord.Net/Entities/Invites/InviteMetadata.cs index d62148fd7..6c334a79f 100644 --- a/src/Discord.Net/Entities/Invites/InviteMetadata.cs +++ b/src/Discord.Net/Entities/Invites/InviteMetadata.cs @@ -25,7 +25,7 @@ namespace Discord { if (source == UpdateSource.Rest && IsAttached) return; - Inviter = new User(Discord, model.Inviter); + Inviter = new User(model.Inviter); IsRevoked = model.Revoked; IsTemporary = model.Temporary; MaxAge = model.MaxAge != 0 ? model.MaxAge : (int?)null; diff --git a/src/Discord.Net/Entities/Messages/Message.cs b/src/Discord.Net/Entities/Messages/Message.cs index e8100070d..f737ede44 100644 --- a/src/Discord.Net/Entities/Messages/Message.cs +++ b/src/Discord.Net/Entities/Messages/Message.cs @@ -99,7 +99,7 @@ namespace Discord { var mentions = new User[value.Length]; for (int i = 0; i < value.Length; i++) - mentions[i] = new User(discord, value[i]); + mentions[i] = new User(value[i]); MentionedUsers = ImmutableArray.Create(mentions); } else diff --git a/src/Discord.Net/Entities/Users/Game.cs b/src/Discord.Net/Entities/Users/Game.cs index e1daa542f..9b5d891ef 100644 --- a/src/Discord.Net/Entities/Users/Game.cs +++ b/src/Discord.Net/Entities/Users/Game.cs @@ -4,7 +4,7 @@ using Model = Discord.API.Game; namespace Discord { [DebuggerDisplay(@"{DebuggerDisplay,nq}")] - public struct Game + public class Game { public string Name { get; } public string StreamUrl { get; } diff --git a/src/Discord.Net/Entities/Users/GuildUser.cs b/src/Discord.Net/Entities/Users/GuildUser.cs index b0b5cfbdc..bd5826473 100644 --- a/src/Discord.Net/Entities/Users/GuildUser.cs +++ b/src/Discord.Net/Entities/Users/GuildUser.cs @@ -34,7 +34,7 @@ namespace Discord public string Mention => User.Mention; public string Username => User.Username; public virtual UserStatus Status => User.Status; - public virtual Game? Game => User.Game; + public virtual Game Game => User.Game; public DiscordClient Discord => Guild.Discord; public DateTimeOffset? JoinedAt => DateTimeUtils.FromTicks(_joinedAtTicks); @@ -149,8 +149,14 @@ namespace Discord if (channel == null) throw new ArgumentNullException(nameof(channel)); return new ChannelPermissions(Permissions.ResolveChannel(this, channel, GuildPermissions.RawValue)); } + + public async Task CreateDMChannelAsync() + { + var args = new CreateDMChannelParams { RecipientId = Id }; + var model = await Discord.ApiClient.CreateDMChannelAsync(args).ConfigureAwait(false); - public Task CreateDMChannelAsync() => User.CreateDMChannelAsync(); + return new DMChannel(Discord, User, model); + } IGuild IGuildUser.Guild => Guild; IReadOnlyCollection IGuildUser.Roles => Roles; diff --git a/src/Discord.Net/Entities/Users/IGuildUser.cs b/src/Discord.Net/Entities/Users/IGuildUser.cs index f536b3ade..280713d33 100644 --- a/src/Discord.Net/Entities/Users/IGuildUser.cs +++ b/src/Discord.Net/Entities/Users/IGuildUser.cs @@ -31,5 +31,8 @@ namespace Discord Task KickAsync(); /// Modifies this user's properties in this guild. Task ModifyAsync(Action func); + + /// Returns a private message channel to this user, creating one if it does not already exist. + Task CreateDMChannelAsync(); } } diff --git a/src/Discord.Net/Entities/Users/IPresence.cs b/src/Discord.Net/Entities/Users/IPresence.cs index 7f182241b..af7be998a 100644 --- a/src/Discord.Net/Entities/Users/IPresence.cs +++ b/src/Discord.Net/Entities/Users/IPresence.cs @@ -3,7 +3,7 @@ public interface IPresence { /// Gets the game this user is currently playing, if any. - Game? Game { get; } + Game Game { get; } /// Gets the current status of this user. UserStatus Status { get; } } diff --git a/src/Discord.Net/Entities/Users/IUser.cs b/src/Discord.Net/Entities/Users/IUser.cs index d877a4d9f..44297f12e 100644 --- a/src/Discord.Net/Entities/Users/IUser.cs +++ b/src/Discord.Net/Entities/Users/IUser.cs @@ -12,8 +12,5 @@ namespace Discord bool IsBot { get; } /// Gets the username for this user. string Username { get; } - - /// Returns a private message channel to this user, creating one if it does not already exist. - Task CreateDMChannelAsync(); } } diff --git a/src/Discord.Net/Entities/Users/SelfUser.cs b/src/Discord.Net/Entities/Users/SelfUser.cs index bdd90d2ff..fed6f5e58 100644 --- a/src/Discord.Net/Entities/Users/SelfUser.cs +++ b/src/Discord.Net/Entities/Users/SelfUser.cs @@ -11,7 +11,7 @@ namespace Discord public bool IsVerified { get; private set; } public SelfUser(DiscordClient discord, Model model) - : base(discord, model) + : base(model) { } public override void Update(Model model, UpdateSource source) diff --git a/src/Discord.Net/Entities/Users/User.cs b/src/Discord.Net/Entities/Users/User.cs index aa5bf8629..3e32bb954 100644 --- a/src/Discord.Net/Entities/Users/User.cs +++ b/src/Discord.Net/Entities/Users/User.cs @@ -1,4 +1,5 @@ using Discord.API.Rest; +using System; using System.Diagnostics; using System.Threading.Tasks; using Model = Discord.API.User; @@ -14,19 +15,18 @@ namespace Discord public bool IsBot { get; private set; } public string Username { get; private set; } - public override DiscordClient Discord { get; } + public override DiscordClient Discord { get { throw new NotSupportedException(); } } public string AvatarUrl => API.CDN.GetUserAvatarUrl(Id, _avatarId); public string Discriminator => _discriminator.ToString("D4"); public string Mention => MentionUtils.Mention(this, false); public string NicknameMention => MentionUtils.Mention(this, true); - public virtual Game? Game => null; + public virtual Game Game => null; public virtual UserStatus Status => UserStatus.Unknown; - public User(DiscordClient discord, Model model) + public User(Model model) : base(model.Id) { - Discord = discord; Update(model, UpdateSource.Creation); } public virtual void Update(Model model, UpdateSource source) @@ -39,14 +39,6 @@ namespace Discord Username = model.Username; } - public async Task CreateDMChannelAsync() - { - var args = new CreateDMChannelParams { RecipientId = Id }; - var model = await Discord.ApiClient.CreateDMChannelAsync(args).ConfigureAwait(false); - - return new DMChannel(Discord, this, model); - } - public override string ToString() => $"{Username}#{Discriminator}"; private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id})"; } diff --git a/src/Discord.Net/Entities/WebSocket/CachedGuildUser.cs b/src/Discord.Net/Entities/WebSocket/CachedGuildUser.cs index 13dadf5c1..427ad6699 100644 --- a/src/Discord.Net/Entities/WebSocket/CachedGuildUser.cs +++ b/src/Discord.Net/Entities/WebSocket/CachedGuildUser.cs @@ -5,14 +5,14 @@ namespace Discord { internal class CachedGuildUser : GuildUser, ICachedUser { - private Game? _game; + private Game _game; private UserStatus _status; public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient; public new CachedGuild Guild => base.Guild as CachedGuild; public new CachedPublicUser User => base.User as CachedPublicUser; - public override Game? Game => _game; + public override Game Game => _game; public override UserStatus Status => _status; public VoiceState? VoiceState => Guild.GetVoiceState(Id); @@ -35,7 +35,7 @@ namespace Discord base.Update(model, source); _status = model.Status; - _game = model.Game != null ? new Game(model.Game) : (Game?)null; + _game = model.Game != null ? new Game(model.Game) : (Game)null; } public CachedGuildUser Clone() => MemberwiseClone() as CachedGuildUser; diff --git a/src/Discord.Net/Entities/WebSocket/CachedPublicUser.cs b/src/Discord.Net/Entities/WebSocket/CachedPublicUser.cs index 7a3f0663d..17c05d315 100644 --- a/src/Discord.Net/Entities/WebSocket/CachedPublicUser.cs +++ b/src/Discord.Net/Entities/WebSocket/CachedPublicUser.cs @@ -1,5 +1,4 @@ -using Discord.Data; -using ChannelModel = Discord.API.Channel; +using ChannelModel = Discord.API.Channel; using Model = Discord.API.User; using PresenceModel = Discord.API.Presence; @@ -8,25 +7,25 @@ namespace Discord internal class CachedPublicUser : User, ICachedUser { private int _references; - private Game? _game; - private UserStatus _status; + //private Game? _game; + //private UserStatus _status; public CachedDMChannel DMChannel { get; private set; } public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient; - public override UserStatus Status => _status; - public override Game? Game => _game; + public override UserStatus Status => UserStatus.Unknown;// _status; + public override Game Game => null; //_game; - public CachedPublicUser(DiscordSocketClient discord, Model model) - : base(discord, model) + public CachedPublicUser(Model model) + : base(model) { } - public CachedDMChannel AddDMChannel(ChannelModel model) + public CachedDMChannel AddDMChannel(DiscordSocketClient discord, ChannelModel model) { lock (this) { - var channel = new CachedDMChannel(Discord, this, model); + var channel = new CachedDMChannel(discord, this, model); DMChannel = channel; return channel; } @@ -49,10 +48,10 @@ namespace Discord { if (source == UpdateSource.Rest) return; - var game = model.Game != null ? new Game(model.Game) : (Game?)null; + //var game = model.Game != null ? new Game(model.Game) : (Game)null; - _status = model.Status; - _game = game; + //_status = model.Status; + //_game = game; } public void AddRef() @@ -60,12 +59,12 @@ namespace Discord lock (this) _references++; } - public void RemoveRef() + public void RemoveRef(DiscordSocketClient discord) { lock (this) { if (--_references == 0 && DMChannel == null) - Discord.RemoveUser(Id); + discord.RemoveUser(Id); } } diff --git a/src/Discord.Net/Entities/WebSocket/MessageCache.cs b/src/Discord.Net/Entities/WebSocket/MessageCache.cs index 4fd5ea785..7aa99bcd2 100644 --- a/src/Discord.Net/Entities/WebSocket/MessageCache.cs +++ b/src/Discord.Net/Entities/WebSocket/MessageCache.cs @@ -88,7 +88,7 @@ namespace Discord return msg; var model = await _discord.ApiClient.GetChannelMessageAsync(_channel.Id, id).ConfigureAwait(false); if (model != null) - return new CachedMessage(_channel, new User(_discord, model.Author.Value), model); + return new CachedMessage(_channel, new User(model.Author.Value), model); return null; } public async Task> DownloadAsync(ulong? fromId, Direction dir, int limit) @@ -123,7 +123,7 @@ namespace Discord IUser user = _channel.GetUser(x.Author.Value.Id, true); if (user == null) { - var newUser = new User(_channel.Discord, x.Author.Value); + var newUser = new User(x.Author.Value); if (guild != null) user = new GuildUser(guild, newUser); else diff --git a/src/Discord.Net/Format.cs b/src/Discord.Net/Format.cs new file mode 100644 index 000000000..fec9114a3 --- /dev/null +++ b/src/Discord.Net/Format.cs @@ -0,0 +1,27 @@ +namespace Discord +{ + namespace Discord + { + public static class Format + { + /// Returns a markdown-formatted string with bold formatting. + public static string Bold(string text) => $"**{text}**"; + /// Returns a markdown-formatted string with italics formatting. + public static string Italics(string text) => $"*{text}*"; + /// Returns a markdown-formatted string with underline formatting. + public static string Underline(string text) => $"__{text}__"; + /// Returns a markdown-formatted string with strikethrough formatting. + public static string Strikethrough(string text) => $"~~{text}~~"; + + /// Returns a markdown-formatted string with strikeout formatting. + public static string Code(string text, string language = null) + { + if (language != null || text.Contains("\n")) + return $"```{language ?? ""}\n{text}\n```"; + else + return $"`{text}`"; + } + } + } + +}