|
|
@@ -649,6 +649,235 @@ namespace Discord.Rest |
|
|
|
|
|
|
|
public static async Task DeleteStickerAsync(BaseDiscordClient client, ulong guildId, ISticker sticker, RequestOptions options = null) |
|
|
|
=> await client.ApiClient.DeleteStickerAsync(guildId, sticker.Id, options).ConfigureAwait(false); |
|
|
|
#endregion |
|
|
|
#endregion |
|
|
|
|
|
|
|
#region Events |
|
|
|
|
|
|
|
public static async Task<IReadOnlyCollection<RestUser>> GetEventUsersAsync(BaseDiscordClient client, IGuildScheduledEvent guildEvent, int limit = 100, RequestOptions options = null) |
|
|
|
{ |
|
|
|
var models = await client.ApiClient.GetGuildScheduledEventUsersAsync(guildEvent.Id, guildEvent.Guild.Id, limit, options).ConfigureAwait(false); |
|
|
|
|
|
|
|
return models.Select(x => RestUser.Create(client, guildEvent.Guild, x)).ToImmutableArray(); |
|
|
|
} |
|
|
|
|
|
|
|
public static IAsyncEnumerable<IReadOnlyCollection<RestUser>> GetEventUsersAsync(BaseDiscordClient client, IGuildScheduledEvent guildEvent, |
|
|
|
ulong? fromUserId, int? limit, RequestOptions options) |
|
|
|
{ |
|
|
|
return new PagedAsyncEnumerable<RestUser>( |
|
|
|
DiscordConfig.MaxGuildEventUsersPerBatch, |
|
|
|
async (info, ct) => |
|
|
|
{ |
|
|
|
var args = new GetEventUsersParams |
|
|
|
{ |
|
|
|
Limit = info.PageSize, |
|
|
|
RelativeDirection = Direction.After, |
|
|
|
}; |
|
|
|
if (info.Position != null) |
|
|
|
args.RelativeUserId = info.Position.Value; |
|
|
|
var models = await client.ApiClient.GetGuildScheduledEventUsersAsync(guildEvent.Id, guildEvent.Guild.Id, args, options).ConfigureAwait(false); |
|
|
|
return models |
|
|
|
.Select(x => RestUser.Create(client, guildEvent.Guild, x)) |
|
|
|
.ToImmutableArray(); |
|
|
|
}, |
|
|
|
nextPage: (info, lastPage) => |
|
|
|
{ |
|
|
|
if (lastPage.Count != DiscordConfig.MaxGuildEventUsersPerBatch) |
|
|
|
return false; |
|
|
|
info.Position = lastPage.Max(x => x.Id); |
|
|
|
return true; |
|
|
|
}, |
|
|
|
start: fromUserId, |
|
|
|
count: limit |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
public static IAsyncEnumerable<IReadOnlyCollection<RestUser>> GetEventUsersAsync(BaseDiscordClient client, IGuildScheduledEvent guildEvent, |
|
|
|
ulong? fromUserId, Direction dir, int limit, RequestOptions options = null) |
|
|
|
{ |
|
|
|
if (dir == Direction.Around && limit > DiscordConfig.MaxMessagesPerBatch) |
|
|
|
{ |
|
|
|
int around = limit / 2; |
|
|
|
if (fromUserId.HasValue) |
|
|
|
return GetEventUsersAsync(client, guildEvent, fromUserId.Value + 1, Direction.Before, around + 1, options) //Need to include the message itself |
|
|
|
.Concat(GetEventUsersAsync(client, guildEvent, fromUserId, Direction.After, around, options)); |
|
|
|
else //Shouldn't happen since there's no public overload for ulong? and Direction |
|
|
|
return GetEventUsersAsync(client, guildEvent, null, Direction.Before, around + 1, options); |
|
|
|
} |
|
|
|
|
|
|
|
return new PagedAsyncEnumerable<RestUser>( |
|
|
|
DiscordConfig.MaxGuildEventUsersPerBatch, |
|
|
|
async (info, ct) => |
|
|
|
{ |
|
|
|
var args = new GetEventUsersParams |
|
|
|
{ |
|
|
|
RelativeDirection = dir, |
|
|
|
Limit = info.PageSize |
|
|
|
}; |
|
|
|
if (info.Position != null) |
|
|
|
args.RelativeUserId = info.Position.Value; |
|
|
|
|
|
|
|
var models = await client.ApiClient.GetGuildScheduledEventUsersAsync(guildEvent.Id, guildEvent.Guild.Id, args, options).ConfigureAwait(false); |
|
|
|
var builder = ImmutableArray.CreateBuilder<RestUser>(); |
|
|
|
foreach (var model in models) |
|
|
|
{ |
|
|
|
builder.Add(RestUser.Create(client, guildEvent.Guild, model)); |
|
|
|
} |
|
|
|
return builder.ToImmutable(); |
|
|
|
}, |
|
|
|
nextPage: (info, lastPage) => |
|
|
|
{ |
|
|
|
if (lastPage.Count != DiscordConfig.MaxGuildEventUsersPerBatch) |
|
|
|
return false; |
|
|
|
if (dir == Direction.Before) |
|
|
|
info.Position = lastPage.Min(x => x.Id); |
|
|
|
else |
|
|
|
info.Position = lastPage.Max(x => x.Id); |
|
|
|
return true; |
|
|
|
}, |
|
|
|
start: fromUserId, |
|
|
|
count: limit |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
public static async Task<API.GuildScheduledEvent> ModifyGuildEventAsync(BaseDiscordClient client, Action<GuildScheduledEventsProperties> func, |
|
|
|
IGuildScheduledEvent guildEvent, RequestOptions options = null) |
|
|
|
{ |
|
|
|
var args = new GuildScheduledEventsProperties(); |
|
|
|
|
|
|
|
func(args); |
|
|
|
|
|
|
|
if (args.Status.IsSpecified) |
|
|
|
{ |
|
|
|
switch (args.Status.Value) |
|
|
|
{ |
|
|
|
case GuildScheduledEventStatus.Active when guildEvent.Status != GuildScheduledEventStatus.Scheduled: |
|
|
|
case GuildScheduledEventStatus.Completed when guildEvent.Status != GuildScheduledEventStatus.Active: |
|
|
|
case GuildScheduledEventStatus.Cancelled when guildEvent.Status != GuildScheduledEventStatus.Scheduled: |
|
|
|
throw new ArgumentException($"Cannot set event to {args.Status.Value} when events status is {guildEvent.Status}"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (args.Type.IsSpecified) |
|
|
|
{ |
|
|
|
// taken from https://discord.com/developers/docs/resources/guild-scheduled-event#modify-guild-scheduled-event |
|
|
|
switch (args.Type.Value) |
|
|
|
{ |
|
|
|
case GuildScheduledEventType.External: |
|
|
|
if (!args.Location.IsSpecified) |
|
|
|
throw new ArgumentException("Location must be specified for external events."); |
|
|
|
if (!args.EndTime.IsSpecified) |
|
|
|
throw new ArgumentException("End time must be specified for external events."); |
|
|
|
if (!args.ChannelId.IsSpecified) |
|
|
|
throw new ArgumentException("Channel id must be set to null!"); |
|
|
|
if (args.ChannelId.Value != null) |
|
|
|
throw new ArgumentException("Channel id must be set to null!"); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var apiArgs = new ModifyGuildScheduledEventParams() |
|
|
|
{ |
|
|
|
ChannelId = args.ChannelId, |
|
|
|
Description = args.Description, |
|
|
|
EndTime = args.EndTime, |
|
|
|
Name = args.Name, |
|
|
|
PrivacyLevel = args.PrivacyLevel, |
|
|
|
StartTime = args.StartTime, |
|
|
|
Status = args.Status, |
|
|
|
Type = args.Type |
|
|
|
}; |
|
|
|
|
|
|
|
if(args.Location.IsSpecified) |
|
|
|
{ |
|
|
|
apiArgs.EntityMetadata = new API.GuildScheduledEventEntityMetadata() |
|
|
|
{ |
|
|
|
Location = args.Location, |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
return await client.ApiClient.ModifyGuildScheduledEventAsync(apiArgs, guildEvent.Id, guildEvent.Guild.Id, options).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
public static async Task<RestGuildEvent> GetGuildEventAsync(BaseDiscordClient client, ulong id, IGuild guild, RequestOptions options = null) |
|
|
|
{ |
|
|
|
var model = await client.ApiClient.GetGuildScheduledEventAsync(id, guild.Id, options).ConfigureAwait(false); |
|
|
|
|
|
|
|
if (model == null) |
|
|
|
return null; |
|
|
|
|
|
|
|
return RestGuildEvent.Create(client, guild, model); |
|
|
|
} |
|
|
|
|
|
|
|
public static async Task<IReadOnlyCollection<RestGuildEvent>> GetGuildEventsAsync(BaseDiscordClient client, IGuild guild, RequestOptions options = null) |
|
|
|
{ |
|
|
|
var models = await client.ApiClient.ListGuildScheduledEventsAsync(guild.Id, options).ConfigureAwait(false); |
|
|
|
|
|
|
|
return models.Select(x => RestGuildEvent.Create(client, guild, x)).ToImmutableArray(); |
|
|
|
} |
|
|
|
|
|
|
|
public static async Task<RestGuildEvent> CreateGuildEventAsync(BaseDiscordClient client, IGuild guild, |
|
|
|
string name, |
|
|
|
GuildScheduledEventPrivacyLevel privacyLevel, |
|
|
|
DateTimeOffset startTime, |
|
|
|
GuildScheduledEventType type, |
|
|
|
string description = null, |
|
|
|
DateTimeOffset? endTime = null, |
|
|
|
ulong? channelId = null, |
|
|
|
string location = null, |
|
|
|
RequestOptions options = null) |
|
|
|
{ |
|
|
|
if(location != null) |
|
|
|
{ |
|
|
|
Preconditions.AtMost(location.Length, 100, nameof(location)); |
|
|
|
} |
|
|
|
|
|
|
|
switch (type) |
|
|
|
{ |
|
|
|
case GuildScheduledEventType.Stage or GuildScheduledEventType.Voice when channelId == null: |
|
|
|
throw new ArgumentException($"{nameof(channelId)} must not be null when type is {type}", nameof(channelId)); |
|
|
|
case GuildScheduledEventType.External when channelId != null: |
|
|
|
throw new ArgumentException($"{nameof(channelId)} must be null when using external event type", nameof(channelId)); |
|
|
|
case GuildScheduledEventType.External when location == null: |
|
|
|
throw new ArgumentException($"{nameof(location)} must not be null when using external event type", nameof(location)); |
|
|
|
case GuildScheduledEventType.External when endTime == null: |
|
|
|
throw new ArgumentException($"{nameof(endTime)} must not be null when using external event type", nameof(endTime)); |
|
|
|
} |
|
|
|
|
|
|
|
if (startTime <= DateTimeOffset.Now) |
|
|
|
throw new ArgumentOutOfRangeException(nameof(startTime), "The start time for an event cannot be in the past"); |
|
|
|
|
|
|
|
if (endTime != null && endTime <= startTime) |
|
|
|
throw new ArgumentOutOfRangeException(nameof(endTime), $"{nameof(endTime)} cannot be before the start time"); |
|
|
|
|
|
|
|
var apiArgs = new CreateGuildScheduledEventParams() |
|
|
|
{ |
|
|
|
ChannelId = channelId ?? Optional<ulong>.Unspecified, |
|
|
|
Description = description ?? Optional<string>.Unspecified, |
|
|
|
EndTime = endTime ?? Optional<DateTimeOffset>.Unspecified, |
|
|
|
Name = name, |
|
|
|
PrivacyLevel = privacyLevel, |
|
|
|
StartTime = startTime, |
|
|
|
Type = type |
|
|
|
}; |
|
|
|
|
|
|
|
if(location != null) |
|
|
|
{ |
|
|
|
apiArgs.EntityMetadata = new API.GuildScheduledEventEntityMetadata() |
|
|
|
{ |
|
|
|
Location = location |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
var model = await client.ApiClient.CreateGuildScheduledEventAsync(apiArgs, guild.Id, options).ConfigureAwait(false); |
|
|
|
|
|
|
|
return RestGuildEvent.Create(client, guild, client.CurrentUser, model); |
|
|
|
} |
|
|
|
|
|
|
|
public static async Task DeleteEventAsync(BaseDiscordClient client, IGuildScheduledEvent guildEvent, RequestOptions options = null) |
|
|
|
{ |
|
|
|
await client.ApiClient.DeleteGuildScheduledEventAsync(guildEvent.Id, guildEvent.Guild.Id, options).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
#endregion |
|
|
|
} |
|
|
|
} |