Skip to content

Commit

Permalink
Merge pull request #609 from nyxx-discord/dev
Browse files Browse the repository at this point in the history
Release 6.1.0
  • Loading branch information
l7ssha authored Dec 13, 2023
2 parents e19ead0 + 6ed9657 commit a4c029b
Show file tree
Hide file tree
Showing 27 changed files with 277 additions and 47 deletions.
24 changes: 20 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
## 6.1.0
__09.21.2023__

- feat: Add payload to `EntitlementDeleteEvent`.
- feat: Add `flags` field to `Sku`.
- feat: Add support for select menu default values.
- feat: Add `GuildUpdateBuilder.safetyAlertsChannelId`.
- docs: Enable link to source in package documentation.
- feat: Add AutoMod message types.
- bug: Fix `ButtonBuilder` serialization.
- bug: Fix `GuildUpdateBuilder` not being able to unset certain settings.
- bug: Fix incorrect `PermissionOverwriteBuilder` serialization when creating/updating channels.
- bug: Fix `GuildManager.listBans` ignoring the provided parameters.
- bug: Correctly export `Credentials` from `package:oauth2` for OAuth2 support.
- bug: Fix members in message interactions not having their guild set.

## 6.0.3
__26.11.2023__

- bug: Fix incorrect serialization of autocompletion interaction responses (again)
- bug: Try to fix invalid sessions triggered by Gateway reconnects
- bug: Fix incorrect serialization of autocompletion interaction responses (again).
- bug: Try to fix invalid sessions triggered by Gateway reconnects.

## 6.0.2
__16.11.2023__

- bug: Fix incorrect assertions in interaction.respond
- bug: Fix incorrect serialization of autocompletion interaction responses
- bug: Fix incorrect assertions in interaction.respond.
- bug: Fix incorrect serialization of autocompletion interaction responses.

## 6.0.1
__01.11.2023__
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ void main() async {
## Other nyxx packages

- [nyxx_commands](https://pub.dev/packages/nyxx_commands): A command framework for handling both simple & complex commands.
- [nyxx_pagination](https://pub.dev/packages/nyxx_pagination): Pagination support for nyxx.
- [nyxx_extensions](https://pub.dev/packages/nyxx_extensions): Pagination, emoji utilities and other miscellaneous helpers for developing bots using nyxx.
- [nyxx_lavalink](https://pub.dev/packages/nyxx_lavalink): Lavalink support for playing audio in voice channels.
- [nyxx_extensions](https://pub.dev/packages/nyxx_extensions): Miscellaneous helpers for common situations when developing bots.

## More examples

Expand Down
4 changes: 4 additions & 0 deletions dartdoc_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dartdoc:
linkToSource:
root: .
uriTemplate: 'https://github.com/nyxx-discord/nyxx/blob/main/%f%#L%l%'
5 changes: 4 additions & 1 deletion lib/nyxx.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ export 'src/models/message/component.dart'
MessageComponent,
SelectMenuComponent,
SelectMenuOption,
SelectMenuDefaultValue,
SelectMenuDefaultValueType,
TextInputComponent,
ButtonStyle,
MessageComponentType,
Expand Down Expand Up @@ -295,7 +297,7 @@ export 'src/models/interaction.dart'
ModalSubmitInteraction,
PingInteraction;
export 'src/models/entitlement.dart' show Entitlement, PartialEntitlement, EntitlementType;
export 'src/models/sku.dart' show Sku, SkuType;
export 'src/models/sku.dart' show Sku, SkuType, SkuFlags;

export 'src/utils/flags.dart' show Flag, Flags;
export 'src/intents.dart' show GatewayIntents;
Expand All @@ -316,3 +318,4 @@ export 'package:http/http.dart'
StreamedResponse;
export 'package:logging/logging.dart' show Logger, Level;
export 'package:runtime_type/runtime_type.dart' show RuntimeType;
export 'package:oauth2/oauth2.dart' show Credentials;
2 changes: 1 addition & 1 deletion lib/src/api_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:oauth2/oauth2.dart';
/// Options for connecting to the Discord API.
abstract class ApiOptions {
/// The version of nyxx used in [defaultUserAgent].
static const nyxxVersion = '6.0.3';
static const nyxxVersion = '6.1.0';

/// The URL to the nyxx repository used in [defaultUserAgent].
static const nyxxRepositoryUrl = 'https://github.com/nyxx-discord/nyxx';
Expand Down
14 changes: 14 additions & 0 deletions lib/src/builders/channel/group_dm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,17 @@ class GroupDmUpdateBuilder extends UpdateBuilder<GroupDmChannel> {
if (icon != null) 'icon': base64Encode(icon!),
};
}

class DmRecipientBuilder extends CreateBuilder<DmRecipientBuilder> {
String accessToken;

String nick;

DmRecipientBuilder({required this.accessToken, required this.nick});

@override
Map<String, Object?> build() => {
'access_token': accessToken,
'nick': nick,
};
}
36 changes: 20 additions & 16 deletions lib/src/builders/guild/guild.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class GuildUpdateBuilder extends UpdateBuilder<Guild> {

bool? premiumProgressBarEnabled;

Snowflake? safetyAlertsChannelId;

GuildUpdateBuilder({
this.name,
this.verificationLevel,
Expand All @@ -113,36 +115,38 @@ class GuildUpdateBuilder extends UpdateBuilder<Guild> {
this.splash = sentinelImageBuilder,
this.discoverySplash = sentinelImageBuilder,
this.banner = sentinelImageBuilder,
this.systemChannelId,
this.systemChannelId = sentinelSnowflake,
this.systemChannelFlags,
this.rulesChannelId,
this.publicUpdatesChannelId,
this.rulesChannelId = sentinelSnowflake,
this.publicUpdatesChannelId = sentinelSnowflake,
this.preferredLocale,
this.features,
this.description = sentinelString,
this.premiumProgressBarEnabled,
this.safetyAlertsChannelId = sentinelSnowflake,
});

@override
Map<String, Object?> build() => {
if (name != null) 'name': name,
if (verificationLevel != null) 'verificationLevel': verificationLevel!.value,
if (defaultMessageNotificationLevel != null) 'defaultMessageNotificationLevel': defaultMessageNotificationLevel!.value,
if (explicitContentFilterLevel != null) 'explicitContentFilterLevel': explicitContentFilterLevel!.value,
if (!identical(afkChannelId, sentinelSnowflake)) 'afkChannelId': afkChannelId?.toString(),
if (afkTimeout != null) 'afkTimeout': afkTimeout!.inSeconds,
if (verificationLevel != null) 'verification_level': verificationLevel!.value,
if (defaultMessageNotificationLevel != null) 'default_message_notification_level': defaultMessageNotificationLevel!.value,
if (explicitContentFilterLevel != null) 'explicit_content_filter_level': explicitContentFilterLevel!.value,
if (!identical(afkChannelId, sentinelSnowflake)) 'afk_channel_id': afkChannelId?.toString(),
if (afkTimeout != null) 'afk_timeout': afkTimeout!.inSeconds,
if (!identical(icon, sentinelImageBuilder)) 'icon': icon?.buildDataString(),
if (newOwnerId != null) 'newOwnerId': newOwnerId!.toString(),
if (newOwnerId != null) 'owner_id': newOwnerId!.toString(),
if (!identical(splash, sentinelImageBuilder)) 'splash': splash?.buildDataString(),
if (!identical(discoverySplash, sentinelImageBuilder)) 'discoverySplash': discoverySplash?.buildDataString(),
if (!identical(discoverySplash, sentinelImageBuilder)) 'discovery_splash': discoverySplash?.buildDataString(),
if (!identical(banner, sentinelImageBuilder)) 'banner': banner?.buildDataString(),
if (systemChannelId != null) 'systemChannelId': systemChannelId!.toString(),
if (systemChannelFlags != null) 'systemChannelFlags': systemChannelFlags!.value,
if (rulesChannelId != null) 'rulesChannelId': rulesChannelId!.toString(),
if (publicUpdatesChannelId != null) 'publicUpdatesChannelId': publicUpdatesChannelId!.toString(),
if (preferredLocale != null) 'preferredLocale': preferredLocale!.identifier,
if (!identical(systemChannelId, sentinelSnowflake)) 'system_channel_id': systemChannelId?.toString(),
if (systemChannelFlags != null) 'system_channel_flags': systemChannelFlags!.value,
if (!identical(rulesChannelId, sentinelSnowflake)) 'rules_channel_id': rulesChannelId?.toString(),
if (!identical(publicUpdatesChannelId, sentinelSnowflake)) 'public_updates_channel_id': publicUpdatesChannelId?.toString(),
if (preferredLocale != null) 'preferred_locale': preferredLocale!.identifier,
if (features != null) 'features': GuildManager.serializeGuildFeatures(features!),
if (!identical(description, sentinelString)) 'description': description,
if (premiumProgressBarEnabled != null) 'premiumProgressBarEnabled': premiumProgressBarEnabled,
if (premiumProgressBarEnabled != null) 'premium_progress_bar_enabled': premiumProgressBarEnabled,
if (!identical(safetyAlertsChannelId, sentinelSnowflake)) 'safety_alerts_channel_id': safetyAlertsChannelId?.toString(),
};
}
4 changes: 2 additions & 2 deletions lib/src/builders/message/component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class ButtonBuilder extends MessageComponentBuilder {
if (label != null) 'label': label,
if (emoji != null)
'emoji': {
'id': emoji!.id == Snowflake.zero ? null : emoji!.id,
'id': emoji!.id == Snowflake.zero ? null : emoji!.id.toString(),
'name': emoji!.name,
if (emoji is GuildEmoji) 'animated': (emoji as GuildEmoji).isAnimated == true,
},
Expand Down Expand Up @@ -223,7 +223,7 @@ class SelectMenuOptionBuilder extends CreateBuilder<SelectMenuOption> {
if (description != null) 'description': description,
if (emoji != null)
'emoji': {
'id': emoji!.id.value,
'id': emoji!.id.toString(),
'name': emoji!.name,
'animated': emoji is GuildEmoji && (emoji as GuildEmoji).isAnimated == true,
},
Expand Down
1 change: 1 addition & 0 deletions lib/src/builders/permission_overwrite.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class PermissionOverwriteBuilder extends CreateBuilder<PermissionOverwrite> {

@override
Map<String, Object?> build() => {
'id': id.toString(),
'type': type.value,
if (allow != null) 'allow': allow!.value.toString(),
if (deny != null) 'deny': deny!.value.toString(),
Expand Down
2 changes: 1 addition & 1 deletion lib/src/client_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class RestClientOptions extends ClientOptions {
});
}

/// Options for controlling the behavior of a [NyxxWebsocket] client.
/// Options for controlling the behavior of a [NyxxGateway] client.
class GatewayClientOptions extends RestClientOptions {
/// The minimum number of session starts this client needs to connect.
///
Expand Down
7 changes: 6 additions & 1 deletion lib/src/gateway/gateway.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,12 @@ class Gateway extends GatewayManager with EventParser {

/// Parse an [EntitlementDeleteEvent] from [raw].
EntitlementDeleteEvent parseEntitlementDelete(Map<String, Object?> raw) {
return EntitlementDeleteEvent(gateway: this);
final applicationId = Snowflake.parse(raw['application_id']!);

return EntitlementDeleteEvent(
gateway: this,
entitlement: client.applications[applicationId].entitlements.parse(raw),
);
}

/// Stream all members in a guild that match [query] or [userIds].
Expand Down
1 change: 1 addition & 0 deletions lib/src/http/managers/application_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class ApplicationManager {
applicationId: Snowflake.parse(raw['application_id']!),
name: raw['name'] as String,
slug: raw['slug'] as String,
flags: SkuFlags(raw['flags'] as int),
);
}

Expand Down
21 changes: 20 additions & 1 deletion lib/src/http/managers/channel_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:convert';

import 'package:http/http.dart' show MultipartFile;
import 'package:nyxx/src/builders/builder.dart';
import 'package:nyxx/src/builders/channel/group_dm.dart';
import 'package:nyxx/src/builders/channel/stage_instance.dart';
import 'package:nyxx/src/builders/channel/thread.dart';
import 'package:nyxx/src/builders/invite.dart';
Expand Down Expand Up @@ -607,7 +608,7 @@ class ChannelManager extends ReadOnlyManager<Channel> {

request = MultipartRequest(
route,
method: 'PATCH',
method: 'POST',
jsonPayload: jsonEncode(payload),
files: files,
);
Expand Down Expand Up @@ -825,4 +826,22 @@ class ChannelManager extends ReadOnlyManager<Channel> {

stageInstanceCache.remove(channelId);
}

Future<void> addRecipient(Snowflake channelId, Snowflake userId, DmRecipientBuilder builder) async {
final route = HttpRoute()
..channels(id: channelId.toString())
..recipients(id: userId.toString());
final request = BasicRequest(route, method: 'PUT', body: jsonEncode(builder.build()));

await client.httpHandler.executeSafe(request);
}

Future<void> removeRecipient(Snowflake channelId, Snowflake userId) async {
final route = HttpRoute()
..channels(id: channelId.toString())
..recipients(id: userId.toString());
final request = BasicRequest(route, method: 'DELETE');

await client.httpHandler.executeSafe(request);
}
}
6 changes: 5 additions & 1 deletion lib/src/http/managers/guild_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,11 @@ class GuildManager extends Manager<Guild> {
final route = HttpRoute()
..guilds(id: id.toString())
..bans();
final request = BasicRequest(route);
final request = BasicRequest(route, queryParameters: {
if (limit != null) 'limit': limit.toString(),
if (after != null) 'after': after.toString(),
if (before != null) 'before': before.toString(),
});

final response = await client.httpHandler.executeSafe(request);
final bans = parseMany(response.jsonBody as List, parseBan);
Expand Down
15 changes: 11 additions & 4 deletions lib/src/http/managers/message_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class MessageManager extends Manager<Message> {
referencedMessage: maybeParse(raw['referenced_message'], parse),
interaction: maybeParse(
raw['interaction'],
(Map<String, Object?> raw) => parseMessageInteraction(raw),
(Map<String, Object?> raw) => parseMessageInteraction(raw, guildId: guildId),
),
thread: maybeParse(raw['thread'], client.channels.parse) as Thread?,
components: maybeParseMany(raw['components'], parseMessageComponent),
Expand Down Expand Up @@ -274,6 +274,7 @@ class MessageManager extends Manager<Message> {
options: maybeParseMany(raw['options'], parseSelectMenuOption),
channelTypes: maybeParseMany(raw['channel_types'], ChannelType.parse),
placeholder: raw['placeholder'] as String?,
defaultValues: maybeParseMany(raw['default_values'], parseSelectMenuDefaultValue),
minValues: raw['min_values'] as int?,
maxValues: raw['max_values'] as int?,
isDisabled: raw['disabled'] as bool?,
Expand All @@ -291,18 +292,24 @@ class MessageManager extends Manager<Message> {
);
}

MessageInteraction parseMessageInteraction(Map<String, Object?> raw) {
SelectMenuDefaultValue parseSelectMenuDefaultValue(Map<String, Object?> raw) {
return SelectMenuDefaultValue(
id: Snowflake.parse(raw['id']!),
type: SelectMenuDefaultValueType.parse(raw['type'] as String),
);
}

MessageInteraction parseMessageInteraction(Map<String, Object?> raw, {Snowflake? guildId}) {
final user = client.users.parse(raw['user'] as Map<String, Object?>);

return MessageInteraction(
id: Snowflake.parse(raw['id']!),
type: InteractionType.parse(raw['type'] as int),
name: raw['name'] as String,
user: user,
// TODO: Find a way to get the guild ID.
member: maybeParse(
raw['member'],
(Map<String, Object?> raw) => client.guilds[Snowflake.zero].members[user.id],
(Map<String, Object?> raw) => client.guilds[guildId ?? Snowflake.zero].members[user.id],
),
);
}
Expand Down
15 changes: 12 additions & 3 deletions lib/src/http/managers/webhook_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ class WebhookManager extends Manager<Webhook> {
}

/// Execute a webhook.
Future<Message?> execute(Snowflake id, MessageBuilder builder, {required String token, bool? wait, Snowflake? threadId}) async {
Future<Message?> execute(Snowflake id, MessageBuilder builder,
{required String token, bool? wait, Snowflake? threadId, String? threadName, List<Snowflake>? appliedTags}) async {
final route = HttpRoute()
..webhooks(id: id.toString())
..add(HttpRoutePart(token));
Expand All @@ -160,7 +161,11 @@ class WebhookManager extends Manager<Webhook> {
final HttpRequest request;
if (!identical(builder.attachments, sentinelList) && builder.attachments?.isNotEmpty == true) {
final attachments = builder.attachments!;
final payload = builder.build();
final payload = {
...builder.build(),
if (threadName != null) 'thread_name': threadName,
if (appliedTags != null) 'applied_tags': appliedTags.map((e) => e.toString()),
};

final files = <MultipartFile>[];
for (int i = 0; i < attachments.length; i++) {
Expand All @@ -185,7 +190,11 @@ class WebhookManager extends Manager<Webhook> {
request = BasicRequest(
route,
method: 'POST',
body: jsonEncode(builder.build()),
body: jsonEncode({
...builder.build(),
if (threadName != null) 'thread_name': threadName,
if (appliedTags != null) 'applied_tags': appliedTags.map((e) => e.toString()),
}),
queryParameters: queryParameters,
authenticated: false,
);
Expand Down
5 changes: 4 additions & 1 deletion lib/src/http/route.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class HttpRoutePart {

/// A parameter in a [HttpRoutePart].
///
/// {@template http_route_part}
/// {@template http_route_param}
/// This is not a query parameter, it is a parameter encoded in the path of the request itself, such
/// as the id of a guild in `/guilds/0123456789`.
/// {@endtemplate}
Expand Down Expand Up @@ -311,4 +311,7 @@ extension RouteHelpers on HttpRoute {

/// Adds the [`avatar-decorations`](https://discord.com/developers/docs/reference#image-formatting-cdn-endpoints) part to this [HttpRoute].
void avatarDecorations({String? id}) => add(HttpRoutePart('avatar-decorations', [if (id != null) HttpRouteParam(id)]));

/// Adds the [`recipients`](https://discord.com/developers/docs/resources/channel#group-dm-add-recipient) part to this [HttpRoute].
void recipients({String? id}) => add(HttpRoutePart('recipients', [if (id != null) HttpRouteParam(id)]));
}
2 changes: 1 addition & 1 deletion lib/src/models/gateway/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class HeartbeatEvent extends GatewayEvent {
/// Emitted when the client receives a request to reconnect.
/// {@endtemplate}
class ReconnectEvent extends GatewayEvent {
/// {@macro reconnect_events}
/// {@macro reconnect_event}
ReconnectEvent() : super(opcode: Opcode.reconnect);
}

Expand Down
5 changes: 3 additions & 2 deletions lib/src/models/gateway/events/entitlement.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ class EntitlementUpdateEvent extends DispatchEvent {
/// Emitted when an entitlement is deleted.
/// {@endtemplate}
class EntitlementDeleteEvent extends DispatchEvent {
// TODO: What is the payload here?
/// The entitlement that was deleted.
final Entitlement entitlement;

/// {@macro entitlement_delete_event}
EntitlementDeleteEvent({required super.gateway});
EntitlementDeleteEvent({required super.gateway, required this.entitlement});
}
Loading

0 comments on commit a4c029b

Please sign in to comment.