fix: use case converter for json component serialization (#7464)

Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
This commit is contained in:
Suneet Tipirneni
2022-02-16 08:01:41 -05:00
committed by GitHub
parent 7959a68d8e
commit 2d4554440e
11 changed files with 40 additions and 83 deletions

View File

@@ -53,6 +53,7 @@
"@sapphire/snowflake": "^3.1.0",
"@types/ws": "^8.2.2",
"discord-api-types": "^0.27.0",
"lodash.snakecase": "^4.1.1",
"node-fetch": "^2.6.7",
"ws": "^8.5.0"
},

View File

@@ -1,13 +1,11 @@
'use strict';
const { ActionRow: BuildersActionRow } = require('@discordjs/builders');
const Components = require('../util/Components');
const Transformers = require('../util/Transformers');
class ActionRow extends BuildersActionRow {
constructor(data) {
// TODO: Simplify when getters PR is merged.
const initData = Components.transformJSON(data);
super({ ...initData, components: initData.components ?? [] });
super(Transformers.toSnakeCase(data));
}
}

View File

@@ -1,11 +1,11 @@
'use strict';
const { ButtonComponent: BuildersButtonComponent } = require('@discordjs/builders');
const Components = require('../util/Components');
const Transformers = require('../util/Transformers');
class ButtonComponent extends BuildersButtonComponent {
constructor(data) {
super(Components.transformJSON(data));
super(Transformers.toSnakeCase(data));
}
}

View File

@@ -1,11 +1,11 @@
'use strict';
const { Embed: BuildersEmbed } = require('@discordjs/builders');
const Embeds = require('../util/Embeds');
const Transformers = require('../util/Transformers');
class Embed extends BuildersEmbed {
constructor(data) {
super({ ...Embeds.transformJSON(data) });
super(Transformers.toSnakeCase(data));
}
}

View File

@@ -4,10 +4,9 @@ const { Buffer } = require('node:buffer');
const { Embed, isJSONEncodable } = require('@discordjs/builders');
const { MessageFlags } = require('discord-api-types/v9');
const { RangeError } = require('../errors');
const Components = require('../util/Components');
const DataResolver = require('../util/DataResolver');
const Embeds = require('../util/Embeds');
const MessageFlagsBitField = require('../util/MessageFlagsBitField');
const Transformers = require('../util/Transformers');
const Util = require('../util/Util');
/**
@@ -134,7 +133,7 @@ class MessagePayload {
}
const components = this.options.components?.map(c =>
isJSONEncodable(c) ? c.toJSON() : Components.transformJSON(c),
isJSONEncodable(c) ? c.toJSON() : Transformers.toSnakeCase(c),
);
let username;
@@ -195,7 +194,7 @@ class MessagePayload {
tts,
nonce,
embeds: this.options.embeds?.map(embed =>
embed instanceof Embed ? embed.toJSON() : Embeds.transformJSON(embed),
embed instanceof Embed ? embed.toJSON() : Transformers.toSnakeCase(embed),
),
components,
username,

View File

@@ -1,11 +1,11 @@
'use strict';
const { SelectMenuComponent: BuildersSelectMenuComponent } = require('@discordjs/builders');
const Components = require('../util/Components');
const Transformers = require('../util/Transformers');
class SelectMenuComponent extends BuildersSelectMenuComponent {
constructor(data) {
super(Components.transformJSON(data));
super(Transformers.toSnakeCase(data));
}
}

View File

@@ -42,29 +42,3 @@
/**
* @typedef {ActionRowData|ButtonComponentData|SelectMenuComponentData} ComponentData
*/
class Components extends null {
/**
* Transforms json data into api-compatible json data.
* @param {ComponentData|APIMessageComponent} data The data to transform.
* @returns {APIMessageComponentData}
*/
static transformJSON(data) {
return {
type: data?.type,
custom_id: data?.customId ?? data?.custom_id,
disabled: data?.disabled,
style: data?.style,
label: data?.label,
emoji: data?.emoji,
url: data?.url,
options: data?.options,
placeholder: data?.placeholder,
min_values: data?.minValues ?? data?.min_values,
max_values: data?.maxValues ?? data?.max_values,
components: data?.components?.map(c => Components.transformJSON(c)),
};
}
}
module.exports = Components;

View File

@@ -46,36 +46,3 @@
* @property {string} value
* @property {?boolean} inline
*/
class Embeds extends null {
/**
* Transforms json data into api-compatible json data.
* @param {EmbedData|APIEmbed} data The data to transform.
* @returns {APIEmbed}
*/
static transformJSON(data) {
return {
title: data?.title,
type: data?.type,
description: data?.description,
url: data?.url,
timestamp: data?.timestamp,
color: data?.color,
footer: {
test: data?.footer?.text,
icon_url: data?.footer?.iconURL ?? data?.footer?.icon_url,
},
image: data?.image,
thumbnail: data?.thumbnail,
provider: data?.provider,
author: {
name: data?.author?.name,
text: data?.author?.text,
icon_url: data?.author?.iconURL ?? data?.author?.icon_url,
},
fields: data?.fields,
};
}
}
module.exports = Embeds;

View File

@@ -0,0 +1,20 @@
'use strict';
const snakeCase = require('lodash.snakecase');
class Transformers extends null {
/**
* Transforms camel-cased keys into snake cased keys
* @param {*} obj The object to transform
* @returns {*}
*/
static toSnakeCase(obj = {}) {
if (typeof obj !== 'object' || !obj) return obj;
if (Array.isArray(obj)) return obj.map(Transformers.toSnakeCase);
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [snakeCase(key), Transformers.toSnakeCase(value)]),
);
}
}
module.exports = Transformers;

View File

@@ -2411,16 +2411,6 @@ export class Formatters extends null {
export type ComponentData = ActionRowComponentData | ButtonComponentData | SelectMenuComponentData;
export class Components extends null {
private constructor();
public static transformJSON(data: ComponentData | APIMessageComponent): APIMessageComponent;
}
export class Embeds extends null {
private constructor();
public static transformJSON(data: EmbedData | APIEmbed): APIEmbed;
}
export class VoiceChannel extends BaseGuildVoiceChannel {
public readonly speakable: boolean;
public type: ChannelType.GuildVoice;