Skip to content

Commit

Permalink
feat: started working on proper message forwarding implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Lulalaby committed Jul 14, 2024
1 parent fc5a1e3 commit 4c8309b
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 80 deletions.
24 changes: 21 additions & 3 deletions DisCatSharp/Clients/DiscordClient.Dispatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2381,11 +2381,17 @@ internal async Task OnMessageCreateEventAsync(DiscordMessage message, TransportU
{
x.Message.Discord = this;
if (x.Message.MentionedUsersInternal.Count is not 0)
x.Message.MentionedUsers.ForEach(u => u.Discord = this);
x.Message.MentionedUsersInternal.ForEach(u => u.Discord = this);
if (x.Message.AttachmentsInternal.Count is not 0)
x.Message.AttachmentsInternal.ForEach(a => a.Discord = this);
if (x.Message.EmbedsInternal.Count is not 0)
x.Message.EmbedsInternal.ForEach(a => a.Discord = this);
if (message.Reference is { GuildId: not null })
x.Message.GuildId = message.Reference.GuildId;
if (x.Message.MentionedChannelsInternal.Count is not 0)
x.Message.MentionedChannelsInternal.ForEach(u => u.Discord = this);
if (x.Message.MentionedRolesInternal.Count is not 0)
x.Message.MentionedRolesInternal.ForEach(u => u.Discord = this);
});

foreach (var sticker in message.Stickers)
Expand Down Expand Up @@ -2450,22 +2456,34 @@ internal async Task OnMessageUpdateEventAsync(DiscordMessage message, TransportU
{
x.Message.Discord = this;
if (x.Message.MentionedUsersInternal.Count is not 0)
x.Message.MentionedUsers.ForEach(u => u.Discord = this);
x.Message.MentionedUsersInternal.ForEach(u => u.Discord = this);
if (x.Message.AttachmentsInternal.Count is not 0)
x.Message.AttachmentsInternal.ForEach(a => a.Discord = this);
if (x.Message.EmbedsInternal.Count is not 0)
x.Message.EmbedsInternal.ForEach(a => a.Discord = this);
if (message.Reference is { GuildId: not null })
x.Message.GuildId = message.Reference.GuildId;
if (x.Message.MentionedChannelsInternal.Count is not 0)
x.Message.MentionedChannelsInternal.ForEach(u => u.Discord = this);
if (x.Message.MentionedRolesInternal.Count is not 0)
x.Message.MentionedRolesInternal.ForEach(u => u.Discord = this);
});

oldmsg?.MessageSnapshots?.ForEach(x =>
{
x.Message.Discord = this;
if (x.Message.MentionedUsersInternal.Count is not 0)
x.Message.MentionedUsers.ForEach(u => u.Discord = this);
x.Message.MentionedUsersInternal.ForEach(u => u.Discord = this);
if (x.Message.AttachmentsInternal.Count is not 0)
x.Message.AttachmentsInternal.ForEach(a => a.Discord = this);
if (x.Message.EmbedsInternal.Count is not 0)
x.Message.EmbedsInternal.ForEach(a => a.Discord = this);
if (oldmsg.Reference is { GuildId: not null })
x.Message.GuildId = oldmsg.Reference.GuildId;
if (x.Message.MentionedChannelsInternal.Count is not 0)
x.Message.MentionedChannelsInternal.ForEach(u => u.Discord = this);
if (x.Message.MentionedRolesInternal.Count is not 0)
x.Message.MentionedRolesInternal.ForEach(u => u.Discord = this);
});

message.PopulateMentions();
Expand Down
156 changes: 83 additions & 73 deletions DisCatSharp/Entities/Message/DiscordForwardedMessage.cs
Original file line number Diff line number Diff line change
@@ -1,45 +1,67 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;

using DisCatSharp.Attributes;
using DisCatSharp.Enums;
using DisCatSharp.Net.Abstractions;

using Newtonsoft.Json;

namespace DisCatSharp.Entities;

/// <summary>
/// Represents a forwarded <see cref="DiscordMessage"/> which contains only a subset of fields.
/// </summary>
[DiscordInExperiment, Experimental("This is subject to change at any time.")]
public class DiscordForwardedMessage : ObservableApiObject
public sealed class DiscordForwardedMessage : ObservableApiObject
{
/// <summary>
/// Constructs a new <see cref="DiscordForwardedMessage"/>.
/// </summary>
internal DiscordForwardedMessage()
{
this._attachmentsLazy = new(() => new ReadOnlyCollection<DiscordAttachment>(this.AttachmentsInternal));
this._embedsLazy = new(() => new ReadOnlyCollection<DiscordEmbed>(this.EmbedsInternal));
/*this._mentionedChannelsLazy = new(() => this.MentionedChannelsInternal != null
? new ReadOnlyCollection<DiscordChannel>(this.MentionedChannelsInternal)
: Array.Empty<DiscordChannel>());
this._mentionedRolesLazy = new(() => this.MentionedRolesInternal != null ? new ReadOnlyCollection<DiscordRole>(this.MentionedRolesInternal) : Array.Empty<DiscordRole>());
this.MentionedUsersLazy = new(() => new ReadOnlyCollection<DiscordUser>(this.MentionedUsersInternal));*/
this._mentionedChannelsLazy = new(() => new ReadOnlyCollection<DiscordChannel>(this.MentionedChannelsInternal));
this._mentionedRolesLazy = new(() => new ReadOnlyCollection<DiscordRole>(this.MentionedRolesInternal));
this._mentionedUsersLazy = new(() => new ReadOnlyCollection<DiscordUser>(this.MentionedUsersInternal));
}

/// <summary>
/// Gets the type of the message.
/// Constructs a new <see cref="DiscordForwardedMessage"/>.
/// </summary>
/// <param name="guildId">Optional guild id.</param>
internal DiscordForwardedMessage(ulong guildId)
{
this._attachmentsLazy = new(() => new ReadOnlyCollection<DiscordAttachment>(this.AttachmentsInternal));
this._embedsLazy = new(() => new ReadOnlyCollection<DiscordEmbed>(this.EmbedsInternal));
this._mentionedChannelsLazy = new(() => new ReadOnlyCollection<DiscordChannel>(this.MentionedChannelsInternal));
this._mentionedRolesLazy = new(() => new ReadOnlyCollection<DiscordRole>(this.MentionedRolesInternal));
this._mentionedUsersLazy = new(() => new ReadOnlyCollection<DiscordUser>(this.MentionedUsersInternal));
this.GuildId = guildId;
}

/// <summary>
/// Gets the guild id.
/// </summary>
internal ulong? GuildId { get; set; } = null;

/// <summary>
/// Gets the type of the forwarded message.
/// </summary>
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
public MessageType? MessageType { get; internal set; }

/// <summary>
/// Gets the message's content.
/// Gets the forwarded message's content.
/// </summary>
[JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)]
public string Content { get; internal set; }
public string? Content { get; internal set; }

/// <summary>
/// Gets embeds attached to this message.
/// Gets embeds attached to this forwarded message.
/// </summary>
[JsonIgnore]
public IReadOnlyList<DiscordEmbed> Embeds
Expand All @@ -52,7 +74,7 @@ public IReadOnlyList<DiscordEmbed> Embeds
private readonly Lazy<IReadOnlyList<DiscordEmbed>> _embedsLazy;

/// <summary>
/// Gets files attached to this message.
/// Gets files attached to this forwarded message.
/// </summary>
[JsonIgnore]
public IReadOnlyList<DiscordAttachment> Attachments
Expand All @@ -65,114 +87,102 @@ public IReadOnlyList<DiscordAttachment> Attachments
private readonly Lazy<IReadOnlyList<DiscordAttachment>> _attachmentsLazy;

/// <summary>
/// Gets the message's creation timestamp.
/// Gets the forwarded message's creation timestamp.
/// </summary>
[JsonIgnore]
public DateTimeOffset? Timestamp
=> !string.IsNullOrWhiteSpace(this.TimestampRaw) && DateTimeOffset.TryParse(this.TimestampRaw, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dto) ? dto : null;
public DateTimeOffset Timestamp
=> DateTimeOffset.TryParse(this.TimestampRaw, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dto) ? dto : throw new ArithmeticException("Could not convert timestamp to DateTimeOffset");

/// <summary>
/// Gets the message's creation timestamp as raw string.
/// Gets the forwarded message's creation timestamp as raw string.
/// </summary>
[JsonProperty("timestamp", NullValueHandling = NullValueHandling.Ignore)]
internal string TimestampRaw { get; set; }

/// <summary>
/// Gets the message's edit timestamp. Will be null if the message was not edited.
/// Gets the forwarded message's edit timestamp. Will be null if the forwarded message was not edited.
/// </summary>
[JsonIgnore]
public DateTimeOffset? EditedTimestamp
=> !string.IsNullOrWhiteSpace(this.EditedTimestampRaw) && DateTimeOffset.TryParse(this.EditedTimestampRaw, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dto) ? dto : null;

/// <summary>
/// Gets the message's edit timestamp as raw string. Will be null if the message was not edited.
/// Gets the forwarded message's edit timestamp as raw string. Will be null if the forwarded message was not edited.
/// </summary>
[JsonProperty("edited_timestamp", NullValueHandling = NullValueHandling.Ignore)]
internal string EditedTimestampRaw { get; set; }
internal string? EditedTimestampRaw { get; set; }

/// <summary>
/// Gets whether this message was edited.
/// Gets whether this forwarded message was edited.
/// </summary>
[JsonIgnore]
public bool IsEdited
=> !string.IsNullOrWhiteSpace(this.EditedTimestampRaw);

/// <summary>
/// Gets the bitwise flags for this message.
/// Gets the bitwise flags for this forwarded message.
/// </summary>
[JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)]
public MessageFlags? Flags { get; internal set; }

/// <summary>
/// Gets whether the message mentions everyone.
/// Gets whether the forwarded message mentions everyone.
/// </summary>
[JsonProperty("mention_everyone", NullValueHandling = NullValueHandling.Ignore)]
public bool MentionEveryone { get; internal set; }

/*
TODO: Implement if stable
/// <summary>
/// Gets users or members mentioned by this message.
/// </summary>
[JsonIgnore]
public IReadOnlyList<DiscordUser> MentionedUsers
=> this.MentionedUsersLazy.Value;
*/

[JsonProperty("mentions", NullValueHandling = NullValueHandling.Ignore)]
internal List<TransportUser> MentionedUsersInternal { get; set; } = [];

/// <summary>
/// Gets users mentioned by this message.
/// Gets users or members mentioned by this forwarded message.
/// </summary>
[JsonIgnore]
public List<DiscordUser> MentionedUsers
=> this.MentionedUsersInternal.Count is not 0
? this.MentionedUsersInternal.Select(x => new DiscordUser(x)
{
Discord = this.Discord
}).ToList()
: [];
public IReadOnlyList<DiscordUser> MentionedUsers
=> this._mentionedUsersLazy.Value;

/*
TODO: Implement if stable
[JsonProperty("mentions", NullValueHandling = NullValueHandling.Ignore)]
internal List<DiscordUser> MentionedUsersInternal { get; set; } = [];

[JsonIgnore]
internal readonly Lazy<IReadOnlyList<DiscordUser>> MentionedUsersLazy;
[JsonIgnore]
private readonly Lazy<IReadOnlyList<DiscordUser>> _mentionedUsersLazy;

/// <summary>
/// Gets roles mentioned by this message.
/// </summary>
[JsonIgnore]
public IReadOnlyList<DiscordRole> MentionedRoles
=> this._mentionedRolesLazy.Value;
/// <summary>
/// Gets roles mentioned by this forwarded message.
/// </summary>
[JsonIgnore]
public IReadOnlyList<DiscordRole> MentionedRoles
=> this._mentionedRolesLazy.Value;

[JsonIgnore]
internal List<DiscordRole> MentionedRolesInternal;
*/
[JsonIgnore]
internal List<DiscordRole> MentionedRolesInternal
=> this.GuildId.HasValue && this.Discord.Guilds.ContainsKey(this.GuildId.Value)
? this.MentionedRoleIds.Select(x => this.Discord.Guilds[this.GuildId.Value].GetRole(x)).ToList()
: [];

/// <summary>
/// Gets role ids mentioned by this message.
/// Gets role ids mentioned by this forwarded message.
/// If the bot is in the forwarded guild and has the guild on it's shard, you can use <see cref="MentionedRoles"/> to get the <see cref="DiscordRole"/>'s directly.
/// </summary>
[JsonProperty("mention_roles")]
public List<ulong> MentionedRoleIds = [];

/*
TODO: Implement if stable
[JsonIgnore]
private readonly Lazy<IReadOnlyList<DiscordRole>> _mentionedRolesLazy;
[JsonIgnore]
private readonly Lazy<IReadOnlyList<DiscordRole>> _mentionedRolesLazy;

/// <summary>
/// Gets channels mentioned by this message.
/// </summary>
[JsonIgnore]
public IReadOnlyList<DiscordChannel> MentionedChannels
=> this._mentionedChannelsLazy.Value;
/// <summary>
/// Gets channels mentioned by this forwarded message.
/// </summary>
[JsonIgnore]
public IReadOnlyList<DiscordChannel> MentionedChannels
=> this._mentionedChannelsLazy.Value;

[JsonIgnore]
internal List<DiscordChannel> MentionedChannelsInternal = [];

[JsonIgnore]
internal List<DiscordChannel> MentionedChannelsInternal;
[JsonIgnore]
private readonly Lazy<IReadOnlyList<DiscordChannel>> _mentionedChannelsLazy;

[JsonIgnore]
private readonly Lazy<IReadOnlyList<DiscordChannel>> _mentionedChannelsLazy;
*/
/// <summary>
/// Gets all mentions from this forwarded message.
/// </summary>
internal void GetMentions()
{ }
}
8 changes: 6 additions & 2 deletions DisCatSharp/Entities/Message/DiscordMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ public IReadOnlyList<DiscordReaction> Reactions
/// Gets the message reference.
/// </summary>
[JsonIgnore]
public DiscordMessageReference Reference
public DiscordMessageReference? Reference
=> this.InternalReference.HasValue ? this?.InternalBuildMessageReference() : null;

/// <summary>
Expand Down Expand Up @@ -492,12 +492,16 @@ public async Task<DiscordMessage> EndPollAsync()
internal DiscordMessageReference InternalBuildMessageReference()
{
var client = this.Discord as DiscordClient;
ArgumentNullException.ThrowIfNull(this.InternalReference);
var guildId = this.InternalReference.Value.GuildId;
var channelId = this.InternalReference.Value.ChannelId;
var messageId = this.InternalReference.Value.MessageId;
var type = this.InternalReference.Value.Type;

var reference = new DiscordMessageReference();
var reference = new DiscordMessageReference
{
GuildId = guildId
};

if (guildId.HasValue)
reference.Guild = client.GuildsInternal.TryGetValue(guildId.Value, out var g)
Expand Down
12 changes: 10 additions & 2 deletions DisCatSharp/Entities/Message/DiscordMessageReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,18 @@ public class DiscordMessageReference
/// <summary>
/// Gets the guild of the original message.
/// </summary>
public DiscordGuild Guild { get; internal set; }
public DiscordGuild? Guild { get; internal set; }

/// <summary>
/// Gets the guild id.
/// </summary>
public ulong? GuildId { get; internal set; }

/// <summary>
/// Gets a readable message reference string.
/// </summary>
public override string ToString()
=> $"Guild: {this.Guild.Id}, Channel: {this.Channel.Id}, Message: {this.Message.Id}";
=> $"Guild: {(this.GuildId.HasValue ? this.GuildId.Value : "Not from guild")}, Channel: {this.Channel.Id}, Message: {this.Message.Id}";

/// <summary>
/// Initializes a new instance of the <see cref="DiscordMessageReference"/> class.
Expand All @@ -42,6 +47,9 @@ internal DiscordMessageReference()
{ }
}

/// <summary>
/// Represents raw data from the original message.
/// </summary>
internal struct InternalDiscordMessageReference
{
public InternalDiscordMessageReference()
Expand Down
6 changes: 6 additions & 0 deletions DisCatSharp/Entities/Message/DiscordMessageSnapshots.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@

namespace DisCatSharp.Entities;

/// <summary>
/// Represents a message snapshot.
/// </summary>
[DiscordInExperiment, Experimental]
public class DiscordMessageSnapshot : ObservableApiObject
{
/// <summary>
/// Gets the forwarded message.
/// </summary>
[JsonProperty("message")]
public DiscordForwardedMessage Message { get; internal set; }
}

0 comments on commit 4c8309b

Please sign in to comment.