Skip to content

Commit

Permalink
feat: even more improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Lulalaby committed Dec 22, 2023
1 parent eb6b7e4 commit a076b2c
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 391 deletions.
45 changes: 20 additions & 25 deletions DisCatSharp/Clients/BaseDiscordClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net.Http;
Expand Down Expand Up @@ -463,24 +464,22 @@ public virtual async Task InitializeAsync()
/// <para>If no value is provided, the configuration value will be used instead.</para>
/// </summary>
/// <returns>A gateway info object.</returns>
public async Task<GatewayInfo> GetGatewayInfoAsync(string token = null)
public async Task<GatewayInfo> GetGatewayInfoAsync(string? token = null)
{
if (this.Configuration.TokenType != TokenType.Bot)
if (this.Configuration.TokenType is not TokenType.Bot)
throw new InvalidOperationException("Only bot tokens can access this info.");

if (string.IsNullOrEmpty(this.Configuration.Token))
{
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Could not locate a valid token.");
if (!string.IsNullOrEmpty(this.Configuration.Token))
return await this.ApiClient.GetGatewayInfoAsync().ConfigureAwait(false);

this.Configuration.Token = token;
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Could not locate a valid token.");

var res = await this.ApiClient.GetGatewayInfoAsync().ConfigureAwait(false);
this.Configuration.Token = null;
return res;
}
this.Configuration.Token = token;

return await this.ApiClient.GetGatewayInfoAsync().ConfigureAwait(false);
var res = await this.ApiClient.GetGatewayInfoAsync().ConfigureAwait(false);
this.Configuration.Token = null;
return res;
}

/// <summary>
Expand All @@ -489,7 +488,13 @@ public async Task<GatewayInfo> GetGatewayInfoAsync(string token = null)
/// <param name="userId">The user id.</param>
internal DiscordUser GetCachedOrEmptyUserInternal(ulong userId)
{
this.TryGetCachedUserInternal(userId, out var user);
if (!this.TryGetCachedUserInternal(userId, out var user))
user = new()
{
Id = userId,
Discord = this
};

return user;
}

Expand All @@ -498,18 +503,8 @@ internal DiscordUser GetCachedOrEmptyUserInternal(ulong userId)
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="user">The user.</param>
internal bool TryGetCachedUserInternal(ulong userId, out DiscordUser user)
{
if (this.UserCache.TryGetValue(userId, out user))
return true;

user = new()
{
Id = userId,
Discord = this
};
return false;
}
internal bool TryGetCachedUserInternal(ulong userId, [MaybeNullWhen(false)] out DiscordUser user)
=> this.UserCache.TryGetValue(userId, out user);

/// <summary>
/// Disposes this client.
Expand Down
171 changes: 16 additions & 155 deletions DisCatSharp/Clients/DiscordClient.Dispatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,52 +29,20 @@ public sealed partial class DiscordClient
{
#region Private Fields

private string _resumeGatewayUrl;
private string _sessionId;
private bool _guildDownloadCompleted;

private readonly Dictionary<string, KeyValuePair<TimeoutHandler, Timer>> _tempTimers = [];

/// <summary>
/// Represents a timeout handler.
/// </summary>
internal class TimeoutHandler
{
/// <summary>
/// Gets the member.
/// </summary>
internal readonly DiscordMember Member;

/// <summary>
/// Gets the guild.
/// </summary>
internal readonly DiscordGuild Guild;

/// <summary>
/// Gets the old timeout value.
/// </summary>
internal DateTime? TimeoutUntilOld;

/// <summary>
/// Gets the new timeout value.
/// </summary>
internal DateTime? TimeoutUntilNew;

/// <summary>
/// Constructs a new <see cref="TimeoutHandler"/>.
/// </summary>
/// <param name="mbr">The affected member.</param>
/// <param name="guild">The affected guild.</param>
/// <param name="too">The old timeout value.</param>
/// <param name="ton">The new timeout value.</param>
internal TimeoutHandler(DiscordMember mbr, DiscordGuild guild, DateTime? too, DateTime? ton)
{
this.Guild = guild;
this.Member = mbr;
this.TimeoutUntilOld = too;
this.TimeoutUntilNew = ton;
}
}
/// <summary>
/// /Gets the resume gateway url.
/// </summary>
private string? _resumeGatewayUrl;

/// <summary>
/// Gets the session id.
/// </summary>
private string? _sessionId;

/// <summary>
/// Gets whether the guild download has been completed.
/// </summary>
private bool _guildDownloadCompleted = false;

#endregion

Expand Down Expand Up @@ -398,7 +366,7 @@ internal async Task HandleDispatchAsync(GatewayPayload payload)
case "message_ack":
cid = (ulong)dat["channel_id"]!;
var mid = (ulong)dat["message_id"]!;
await this.OnMessageAckEventAsync(this.InternalGetCachedChannel(cid), mid).ConfigureAwait(false);
await this.OnMessageAckEventAsync(this.InternalGetCachedChannel(cid) ?? this.InternalGetCachedThread(cid), mid).ConfigureAwait(false);
break;

case "message_create":
Expand Down Expand Up @@ -636,7 +604,7 @@ internal async Task HandleDispatchAsync(GatewayPayload payload)
if (rawMbr != null)
mbr = DiscordJson.DeserializeObject<TransportMember>(rawMbr.ToString(), this);

await this.OnTypingStartEventAsync((ulong)dat["user_id"], cid, this.InternalGetCachedChannel(cid), (ulong?)dat["guild_id"], Utilities.GetDateTimeOffset((long)dat["timestamp"]), mbr).ConfigureAwait(false);
await this.OnTypingStartEventAsync((ulong)dat["user_id"], cid, this.InternalGetCachedChannel(cid) ?? this.InternalGetCachedThread(cid), (ulong?)dat["guild_id"], Utilities.GetDateTimeOffset((long)dat["timestamp"]), mbr).ConfigureAwait(false);
break;

case "webhooks_update":
Expand Down Expand Up @@ -2084,113 +2052,6 @@ internal async Task OnGuildMemberUpdateEventAsync(TransportMember member, Discor
await this._guildMemberUpdated.InvokeAsync(this, eargs).ConfigureAwait(false);
}

/// <summary>
/// Handles timeout events.
/// </summary>
/// <param name="state">Internally used as uid for the timer data.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "<Pending>")]
private async void TimeoutTimer(object state)
{
var tid = (string)state;
var data = this._tempTimers.First(x => x.Key == tid).Value.Key;
var timer = this._tempTimers.First(x => x.Key == tid).Value.Value;

IReadOnlyList<DiscordAuditLogEntry> auditlog = null;
DiscordAuditLogMemberUpdateEntry filtered = null;
try
{
auditlog = await data.Guild.GetAuditLogsAsync(10, null, AuditLogActionType.MemberUpdate).ConfigureAwait(false);
var preFiltered = auditlog.Select(x => x as DiscordAuditLogMemberUpdateEntry).Where(x => x.Target.Id == data.Member.Id);
filtered = preFiltered.First();
}
catch (UnauthorizedException)
{ }
catch (Exception)
{
this.Logger.LogTrace("Failing timeout event.");
await timer.DisposeAsync().ConfigureAwait(false);
this._tempTimers.Remove(tid);
return;
}

var actor = filtered?.UserResponsible as DiscordMember;

this.Logger.LogTrace("Trying to execute timeout event.");

if (data is { TimeoutUntilOld: not null, TimeoutUntilNew: not null })
{
// A timeout was updated.

if (filtered != null && auditlog == null)
{
this.Logger.LogTrace("Re-scheduling timeout event.");
timer.Change(2000, Timeout.Infinite);
return;
}

var ea = new GuildMemberTimeoutUpdateEventArgs(this.ServiceProvider)
{
Guild = data.Guild,
Target = data.Member,
TimeoutBefore = data.TimeoutUntilOld.Value,
TimeoutAfter = data.TimeoutUntilNew.Value,
Actor = actor,
AuditLogId = filtered?.Id,
AuditLogReason = filtered?.Reason
};
await this._guildMemberTimeoutChanged.InvokeAsync(this, ea).ConfigureAwait(false);
}
else if (!data.TimeoutUntilOld.HasValue && data.TimeoutUntilNew.HasValue)
{
// A timeout was added.

if (filtered != null && auditlog == null)
{
this.Logger.LogTrace("Re-scheduling timeout event.");
timer.Change(2000, Timeout.Infinite);
return;
}

var ea = new GuildMemberTimeoutAddEventArgs(this.ServiceProvider)
{
Guild = data.Guild,
Target = data.Member,
Timeout = data.TimeoutUntilNew.Value,
Actor = actor,
AuditLogId = filtered?.Id,
AuditLogReason = filtered?.Reason
};
await this._guildMemberTimeoutAdded.InvokeAsync(this, ea).ConfigureAwait(false);
}
else if (data is { TimeoutUntilOld: not null, TimeoutUntilNew: null })
{
// A timeout was removed.

if (filtered != null && auditlog == null)
{
this.Logger.LogTrace("Re-scheduling timeout event.");
timer.Change(2000, Timeout.Infinite);
return;
}

var ea = new GuildMemberTimeoutRemoveEventArgs(this.ServiceProvider)
{
Guild = data.Guild,
Target = data.Member,
TimeoutBefore = data.TimeoutUntilOld.Value,
Actor = actor,
AuditLogId = filtered?.Id,
AuditLogReason = filtered?.Reason
};
await this._guildMemberTimeoutRemoved.InvokeAsync(this, ea).ConfigureAwait(false);
}

// Ending timer because it worked.
this.Logger.LogTrace("Removing timeout event.");
await timer.DisposeAsync().ConfigureAwait(false);
this._tempTimers.Remove(tid);
}

/// <summary>
/// Handles the guild members chunk event.
/// </summary>
Expand Down
Loading

0 comments on commit a076b2c

Please sign in to comment.