Browse Source

Merge remote-tracking branch 'upstream/dev' into dev

pull/1595/head
Paulo 5 years ago
parent
commit
25d1efab1a
10 changed files with 79 additions and 20 deletions
  1. +3
    -0
      src/Discord.Net.Core/Entities/Guilds/IGuild.cs
  2. +15
    -0
      src/Discord.Net.Core/Entities/Messages/IUserMessage.cs
  3. +9
    -0
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  4. +15
    -0
      src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
  5. +1
    -1
      src/Discord.Net.Rest/Entities/Messages/RestMessage.cs
  6. +12
    -0
      src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs
  7. +1
    -11
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  8. +14
    -2
      src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs
  9. +4
    -1
      src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
  10. +5
    -5
      src/Discord.Net.Webhook/DiscordWebhookClient.cs

+ 3
- 0
src/Discord.Net.Core/Entities/Guilds/IGuild.cs View File

@@ -683,6 +683,9 @@ namespace Discord
/// <summary> /// <summary>
/// Downloads all users for this guild if the current list is incomplete. /// Downloads all users for this guild if the current list is incomplete.
/// </summary> /// </summary>
/// <remarks>
/// This method downloads all users found within this guild throught the Gateway and caches them.
/// </remarks>
/// <returns> /// <returns>
/// A task that represents the asynchronous download operation. /// A task that represents the asynchronous download operation.
/// </returns> /// </returns>


+ 15
- 0
src/Discord.Net.Core/Entities/Messages/IUserMessage.cs View File

@@ -57,6 +57,21 @@ namespace Discord
/// </returns> /// </returns>
Task UnpinAsync(RequestOptions options = null); Task UnpinAsync(RequestOptions options = null);


/// <summary>
/// Publishes (crossposts) this message.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous operation for publishing this message.
/// </returns>
/// <remarks>
/// <note type="warning">
/// This call will throw an <see cref="InvalidOperationException"/> if attempted in a non-news channel.
/// </note>
/// This method will publish (crosspost) the message. Please note, publishing (crossposting), is only available in news channels.
/// </remarks>
Task CrosspostAsync(RequestOptions options = null);

/// <summary> /// <summary>
/// Transforms this message's text into a human-readable form by resolving its tags. /// Transforms this message's text into a human-readable form by resolving its tags.
/// </summary> /// </summary>


+ 9
- 0
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -695,6 +695,15 @@ namespace Discord.API
var ids = new BucketIds(channelId: channelId); var ids = new BucketIds(channelId: channelId);
await SendAsync("POST", () => $"channels/{channelId}/typing", ids, options: options).ConfigureAwait(false); await SendAsync("POST", () => $"channels/{channelId}/typing", ids, options: options).ConfigureAwait(false);
} }
public async Task CrosspostAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));
options = RequestOptions.CreateOrClone(options);

var ids = new BucketIds(channelId: channelId);
await SendAsync("POST", () => $"channels/{channelId}/messages/{messageId}/crosspost", ids, options: options).ConfigureAwait(false);
}


//Channel Permissions //Channel Permissions
public async Task ModifyChannelPermissionsAsync(ulong channelId, ulong targetId, ModifyChannelPermissionsParams args, RequestOptions options = null) public async Task ModifyChannelPermissionsAsync(ulong channelId, ulong targetId, ModifyChannelPermissionsParams args, RequestOptions options = null)


+ 15
- 0
src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs View File

@@ -44,8 +44,10 @@ namespace Discord.Rest
}; };
return await client.ApiClient.ModifyMessageAsync(msg.Channel.Id, msg.Id, apiArgs, options).ConfigureAwait(false); return await client.ApiClient.ModifyMessageAsync(msg.Channel.Id, msg.Id, apiArgs, options).ConfigureAwait(false);
} }

public static Task DeleteAsync(IMessage msg, BaseDiscordClient client, RequestOptions options) public static Task DeleteAsync(IMessage msg, BaseDiscordClient client, RequestOptions options)
=> DeleteAsync(msg.Channel.Id, msg.Id, client, options); => DeleteAsync(msg.Channel.Id, msg.Id, client, options);

public static async Task DeleteAsync(ulong channelId, ulong msgId, BaseDiscordClient client, public static async Task DeleteAsync(ulong channelId, ulong msgId, BaseDiscordClient client,
RequestOptions options) RequestOptions options)
{ {
@@ -115,6 +117,7 @@ namespace Discord.Rest
{ {
await client.ApiClient.AddPinAsync(msg.Channel.Id, msg.Id, options).ConfigureAwait(false); await client.ApiClient.AddPinAsync(msg.Channel.Id, msg.Id, options).ConfigureAwait(false);
} }

public static async Task UnpinAsync(IMessage msg, BaseDiscordClient client, public static async Task UnpinAsync(IMessage msg, BaseDiscordClient client,
RequestOptions options) RequestOptions options)
{ {
@@ -240,6 +243,7 @@ namespace Discord.Rest


return tags.ToImmutable(); return tags.ToImmutable();
} }

private static int? FindIndex(IReadOnlyList<ITag> tags, int index) private static int? FindIndex(IReadOnlyList<ITag> tags, int index)
{ {
int i = 0; int i = 0;
@@ -253,6 +257,7 @@ namespace Discord.Rest
return null; //Overlaps tag before this return null; //Overlaps tag before this
return i; return i;
} }

public static ImmutableArray<ulong> FilterTagsByKey(TagType type, ImmutableArray<ITag> tags) public static ImmutableArray<ulong> FilterTagsByKey(TagType type, ImmutableArray<ITag> tags)
{ {
return tags return tags
@@ -260,6 +265,7 @@ namespace Discord.Rest
.Select(x => x.Key) .Select(x => x.Key)
.ToImmutableArray(); .ToImmutableArray();
} }

public static ImmutableArray<T> FilterTagsByValue<T>(TagType type, ImmutableArray<ITag> tags) public static ImmutableArray<T> FilterTagsByValue<T>(TagType type, ImmutableArray<ITag> tags)
{ {
return tags return tags
@@ -279,5 +285,14 @@ namespace Discord.Rest
return MessageSource.Bot; return MessageSource.Bot;
return MessageSource.User; return MessageSource.User;
} }

public static Task CrosspostAsync(IMessage msg, BaseDiscordClient client, RequestOptions options)
=> CrosspostAsync(msg.Channel.Id, msg.Id, client, options);

public static async Task CrosspostAsync(ulong channelId, ulong msgId, BaseDiscordClient client,
RequestOptions options)
{
await client.ApiClient.CrosspostAsync(channelId, msgId, options).ConfigureAwait(false);
}
} }
} }

+ 1
- 1
src/Discord.Net.Rest/Entities/Messages/RestMessage.cs View File

@@ -165,7 +165,7 @@ namespace Discord.Rest
IReadOnlyCollection<IEmbed> IMessage.Embeds => Embeds; IReadOnlyCollection<IEmbed> IMessage.Embeds => Embeds;
/// <inheritdoc /> /// <inheritdoc />
IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray();
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me }); public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me });




+ 12
- 0
src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs View File

@@ -148,6 +148,18 @@ namespace Discord.Rest
TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name) TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name)
=> MentionUtils.Resolve(this, 0, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling); => MentionUtils.Resolve(this, 0, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling);


/// <inheritdoc />
/// <exception cref="InvalidOperationException">This operation may only be called on a <see cref="RestNewsChannel"/> channel.</exception>
public async Task CrosspostAsync(RequestOptions options = null)
{
if (!(Channel is RestNewsChannel))
{
throw new InvalidOperationException("Publishing (crossposting) is only valid in news channels.");
}

await MessageHelper.CrosspostAsync(this, Discord, options);
}

private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})"; private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})";
} }
} }

+ 1
- 11
src/Discord.Net.WebSocket/DiscordSocketClient.cs View File

@@ -1771,17 +1771,7 @@ namespace Discord.WebSocket
return guild; return guild;
} }
internal SocketGuild RemoveGuild(ulong id) internal SocketGuild RemoveGuild(ulong id)
{
var guild = State.RemoveGuild(id);
if (guild != null)
{
foreach (var _ in guild.Channels)
State.RemoveChannel(id);
foreach (var user in guild.Users)
user.GlobalUser.RemoveRef(this);
}
return guild;
}
=> State.RemoveGuild(id);


/// <exception cref="InvalidOperationException">Unexpected channel type is created.</exception> /// <exception cref="InvalidOperationException">Unexpected channel type is created.</exception>
internal ISocketPrivateChannel AddPrivateChannel(API.Channel model, ClientState state) internal ISocketPrivateChannel AddPrivateChannel(API.Channel model, ClientState state)


+ 14
- 2
src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs View File

@@ -123,7 +123,7 @@ namespace Discord.WebSocket
model.Content = text; model.Content = text;
} }
} }
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="InvalidOperationException">Only the author of a message may modify the message.</exception> /// <exception cref="InvalidOperationException">Only the author of a message may modify the message.</exception>
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
@@ -147,7 +147,19 @@ namespace Discord.WebSocket
public string Resolve(TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name, public string Resolve(TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name,
TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name) TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name)
=> MentionUtils.Resolve(this, 0, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling); => MentionUtils.Resolve(this, 0, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling);

/// <inheritdoc />
/// <exception cref="InvalidOperationException">This operation may only be called on a <see cref="SocketNewsChannel"/> channel.</exception>
public async Task CrosspostAsync(RequestOptions options = null)
{
if (!(Channel is SocketNewsChannel))
{
throw new InvalidOperationException("Publishing (crossposting) is only valid in news channels.");
}

await MessageHelper.CrosspostAsync(this, Discord, options);
}

private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})"; private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})";
internal new SocketUserMessage Clone() => MemberwiseClone() as SocketUserMessage; internal new SocketUserMessage Clone() => MemberwiseClone() as SocketUserMessage;
} }


+ 4
- 1
src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs View File

@@ -44,8 +44,11 @@ namespace Discord.WebSocket
/// <summary> /// <summary>
/// Gets mutual guilds shared with this user. /// Gets mutual guilds shared with this user.
/// </summary> /// </summary>
/// <remarks>
/// This property will only include guilds in the same <see cref="DiscordSocketClient"/>.
/// </remarks>
public IReadOnlyCollection<SocketGuild> MutualGuilds public IReadOnlyCollection<SocketGuild> MutualGuilds
=> Discord.Guilds.Where(g => g.Users.Any(u => u.Id == Id)).ToImmutableArray();
=> Discord.Guilds.Where(g => g.GetUser(Id) != null).ToImmutableArray();


internal SocketUser(DiscordSocketClient discord, ulong id) internal SocketUser(DiscordSocketClient discord, ulong id)
: base(discord, id) : base(discord, id)


+ 5
- 5
src/Discord.Net.Webhook/DiscordWebhookClient.cs View File

@@ -33,7 +33,7 @@ namespace Discord.Webhook
: this(webhookUrl, new DiscordRestConfig()) { } : this(webhookUrl, new DiscordRestConfig()) { }


// regex pattern to match webhook urls // regex pattern to match webhook urls
private static Regex WebhookUrlRegex = new Regex(@"^.*discordapp\.com\/api\/webhooks\/([\d]+)\/([a-z0-9_-]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static Regex WebhookUrlRegex = new Regex(@"^.*(discord|discordapp)\.com\/api\/webhooks\/([\d]+)\/([a-z0-9_-]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);


/// <summary> Creates a new Webhook Discord client. </summary> /// <summary> Creates a new Webhook Discord client. </summary>
public DiscordWebhookClient(ulong webhookId, string webhookToken, DiscordRestConfig config) public DiscordWebhookClient(ulong webhookId, string webhookToken, DiscordRestConfig config)
@@ -132,13 +132,13 @@ namespace Discord.Webhook
if (match != null) if (match != null)
{ {
// ensure that the first group is a ulong, set the _webhookId // ensure that the first group is a ulong, set the _webhookId
// 0th group is always the entire match, so start at index 1
if (!(match.Groups[1].Success && ulong.TryParse(match.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out webhookId)))
// 0th group is always the entire match, and 1 is the domain; so start at index 2
if (!(match.Groups[2].Success && ulong.TryParse(match.Groups[2].Value, NumberStyles.None, CultureInfo.InvariantCulture, out webhookId)))
throw ex("The webhook Id could not be parsed."); throw ex("The webhook Id could not be parsed.");


if (!match.Groups[2].Success)
if (!match.Groups[3].Success)
throw ex("The webhook token could not be parsed."); throw ex("The webhook token could not be parsed.");
webhookToken = match.Groups[2].Value;
webhookToken = match.Groups[3].Value;
} }
else else
throw ex(); throw ex();


Loading…
Cancel
Save