Skip to content

Commit cb69312

Browse files
committed
Update tags, add audio commands, fix emoji codepoint parsing
- Update tags -> Add `{image}`, `{image:ARG}` which will look for the last image url or whatever arg is passed - Fix emoji codepoint parsing - Rework media url parsing - Add audio commands -> Prefixed --> `.audio identify` --> `.video extract audio` -> Slash --> `/a convert` --> `/a identify` --> `/v extract audio`
1 parent e64a5e5 commit cb69312

File tree

24 files changed

+858
-273
lines changed

24 files changed

+858
-273
lines changed

src/api/endpoints.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export const Api = Object.freeze({
1313
URL_PUBLIC: Domains.BETA,
1414
PATH: '/api',
1515

16+
AUDIO_TOOLS_CONVERT:
17+
'/audio/tools/convert',
18+
AUDIO_TOOLS_IDENTIFY:
19+
'/audio/tools/identify',
20+
1621
COMMANDS:
1722
'/commands',
1823

@@ -252,6 +257,8 @@ export const Api = Object.freeze({
252257

253258
VIDEO_TOOLS_CONVERT:
254259
'/video/tools/convert',
260+
VIDEO_TOOLS_EXTRACT_AUDIO:
261+
'/video/tools/extract/audio',
255262
});
256263

257264

@@ -273,4 +280,6 @@ export const CDN = Tools.URIEncodeWrap({
273280
export const CUSTOM = Tools.URIEncodeWrap({
274281
STEAM_EMOJI: (name: string): string =>
275282
`https://steamcommunity-a.akamaihd.net/economy/emoticon/${name}`,
283+
TWEMOJI_SVG: (codepoint: string) =>
284+
`https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/${codepoint}.svg`,
276285
});

src/api/index.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@ export { request } from './raw';
2626
export { Endpoints, RequestContext, raw };
2727

2828

29+
export async function audioToolsConvert(
30+
context: RequestContext,
31+
options: RestOptions.AudioToolsConvertOptions,
32+
) {
33+
return raw.audioToolsConvert(context, options);
34+
}
35+
36+
37+
export async function audioToolsIdentify(
38+
context: RequestContext,
39+
options: RestOptions.AudioBaseOptions,
40+
) {
41+
return raw.audioToolsIdentify(context, options);
42+
}
43+
44+
2945
export async function createGuildAllowlist(
3046
context: RequestContext,
3147
guildId: string,
@@ -1058,3 +1074,11 @@ export async function videoToolsConvert(
10581074
) {
10591075
return raw.videoToolsConvert(context, options);
10601076
}
1077+
1078+
1079+
export async function videoToolsExtractAudio(
1080+
context: RequestContext,
1081+
options: RestOptions.VideoBaseOptions,
1082+
) {
1083+
return raw.videoToolsExtractAudio(context, options);
1084+
}

src/api/raw.ts

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,42 @@ export async function request(
6262
}
6363

6464

65+
export async function audioToolsConvert(
66+
context: RequestContext,
67+
options: RestOptions.AudioToolsConvertOptions,
68+
): Promise<Response> {
69+
const query = {
70+
to: options.to,
71+
url: options.url,
72+
};
73+
return request(context, {
74+
dataOnly: false,
75+
query,
76+
route: {
77+
method: HTTPMethods.POST,
78+
path: Api.AUDIO_TOOLS_CONVERT,
79+
},
80+
});
81+
}
82+
83+
84+
export async function audioToolsIdentify(
85+
context: RequestContext,
86+
options: RestOptions.AudioBaseOptions,
87+
): Promise<RestResponsesRaw.AudioToolsIdentify> {
88+
const query = {
89+
url: options.url,
90+
};
91+
return request(context, {
92+
query,
93+
route: {
94+
method: HTTPMethods.POST,
95+
path: Api.AUDIO_TOOLS_IDENTIFY,
96+
},
97+
});
98+
}
99+
100+
65101
export async function createGuildAllowlist(
66102
context: RequestContext,
67103
guildId: string,
@@ -160,14 +196,11 @@ export async function createUserCommand(
160196
): Promise<RestResponsesRaw.CreateUserCommand> {
161197
const body = {
162198
channel_id: options.channelId,
163-
content: options.content,
164-
content_url: options.contentUrl,
165199
edited_timestamp: options.editedTimestamp,
166200
failed_reason: options.failedReason,
167201
guild_id: options.guildId,
168202
message_id: options.messageId,
169203
response_id: options.responseId,
170-
response_url: options.responseUrl,
171204
};
172205
const params = {userId, command};
173206
return request(context, {
@@ -2224,3 +2257,21 @@ export async function videoToolsConvert(
22242257
},
22252258
});
22262259
}
2260+
2261+
2262+
export async function videoToolsExtractAudio(
2263+
context: RequestContext,
2264+
options: RestOptions.VideoBaseOptions,
2265+
): Promise<Response> {
2266+
const query = {
2267+
url: options.url,
2268+
};
2269+
return request(context, {
2270+
dataOnly: false,
2271+
query,
2272+
route: {
2273+
method: HTTPMethods.POST,
2274+
path: Api.VIDEO_TOOLS_EXTRACT_AUDIO,
2275+
},
2276+
});
2277+
}

src/api/types.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ import { User } from './structures/user';
2626

2727

2828
export namespace RestOptions {
29+
export interface AudioBaseOptions {
30+
url: string,
31+
}
32+
33+
export interface AudioToolsConvertOptions extends AudioBaseOptions {
34+
to: string,
35+
}
36+
2937
export interface CreateGuildLogger {
3038
channelId: string,
3139
type: GuildLoggerTypes,
@@ -35,14 +43,11 @@ export namespace RestOptions {
3543

3644
export interface CreateUserCommand {
3745
channelId: string,
38-
content: string,
39-
contentUrl?: string,
4046
editedTimestamp?: null | number,
4147
failedReason?: string,
4248
guildId?: string,
4349
messageId: string,
4450
responseId?: string,
45-
responseUrl?: string,
4651
}
4752

4853

@@ -482,6 +487,28 @@ export namespace RestResponses {
482487

483488
export namespace RestResponsesRaw {
484489

490+
export interface AudioToolsIdentify {
491+
error: null | {
492+
error_code: number,
493+
error_message: string,
494+
},
495+
result: null | {
496+
album: string,
497+
artist: string,
498+
label: string,
499+
release_date: string,
500+
song_link: string,
501+
timecode: string,
502+
title: string,
503+
apple_music: any,
504+
deezer: any,
505+
musicbrainz: any,
506+
napster: any,
507+
spotify: any,
508+
},
509+
status: string,
510+
}
511+
485512
export type CreateGuildAllowlist = null;
486513
export type CreateGuildBlocklist = null;
487514
export type CreateGuildDisabledCommand = null;

src/commands/interactions/basecommand.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,43 @@ export class BaseInteractionCommandOption<ParsedArgsFinished = Interaction.Parse
188188
}
189189

190190

191+
export class BaseInteractionAudioOrVideoCommandOption<ParsedArgsFinished = Interaction.ParsedArgs> extends BaseInteractionCommandOption<ParsedArgsFinished> {
192+
constructor(data: Interaction.InteractionCommandOptionOptions = {}) {
193+
super({
194+
...data,
195+
options: [
196+
...(data.options || []),
197+
{name: 'media', description: 'Emoji/Media URL/User', label: 'url', default: DefaultParameters.lastMediaUrl({image: false}), value: Parameters.lastMediaUrl({image: false})},
198+
{name: 'file', description: 'Audio/Video File', type: ApplicationCommandOptionTypes.ATTACHMENT},
199+
],
200+
});
201+
}
202+
203+
onBeforeRun(context: Interaction.InteractionContext, args: {url?: null | string}) {
204+
if (args.url) {
205+
context.metadata = Object.assign({}, context.metadata, {contentUrl: args.url});
206+
}
207+
return !!args.url;
208+
}
209+
210+
onCancelRun(context: Interaction.InteractionContext, args: {url?: null | string}) {
211+
if (args.url === undefined) {
212+
return editOrReply(context, '⚠ Unable to find any media in the last 50 messages.');
213+
} else if (args.url === null) {
214+
return editOrReply(context, '⚠ Unable to find that user or it was an invalid url.');
215+
}
216+
return super.onCancelRun(context, args);
217+
}
218+
}
219+
220+
191221
export class BaseInteractionImageCommandOption<ParsedArgsFinished = Interaction.ParsedArgs> extends BaseInteractionCommandOption<ParsedArgsFinished> {
192222
constructor(data: Interaction.InteractionCommandOptionOptions = {}) {
193223
super({
194224
...data,
195225
options: [
196226
...(data.options || []),
197-
{name: 'image', description: 'Emoji/Image URL/User', label: 'url', default: DefaultParameters.lastImageUrl, value: Parameters.lastImageUrl},
227+
{name: 'image', description: 'Emoji/Image URL/User', label: 'url', default: DefaultParameters.lastMediaUrl({audio: false, video: false}), value: Parameters.lastMediaUrl({audio: false, video: false})},
198228
{name: 'file', description: 'Image File', type: ApplicationCommandOptionTypes.ATTACHMENT},
199229
],
200230
});
@@ -224,7 +254,7 @@ export class BaseInteractionVideoCommandOption<ParsedArgsFinished = Interaction.
224254
...data,
225255
options: [
226256
...(data.options || []),
227-
{name: 'video', description: 'Emoji/Media URL/User', label: 'url', default: DefaultParameters.lastVideoUrl, value: Parameters.lastVideoUrl},
257+
{name: 'video', description: 'Emoji/Media URL/User', label: 'url', default: DefaultParameters.lastMediaUrl({audio: false, image: false}), value: Parameters.lastMediaUrl({audio: false, image: false})},
228258
{name: 'file', description: 'Video File', type: ApplicationCommandOptionTypes.ATTACHMENT},
229259
],
230260
});
@@ -239,7 +269,7 @@ export class BaseInteractionVideoCommandOption<ParsedArgsFinished = Interaction.
239269

240270
onCancelRun(context: Interaction.InteractionContext, args: {url?: null | string}) {
241271
if (args.url === undefined) {
242-
return editOrReply(context, '⚠ Unable to find any media in the last 50 messages.');
272+
return editOrReply(context, '⚠ Unable to find any videos in the last 50 messages.');
243273
} else if (args.url === null) {
244274
return editOrReply(context, '⚠ Unable to find that user or it was an invalid url.');
245275
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Interaction } from 'detritus-client';
2+
3+
import { Formatter } from '../../../../utils';
4+
5+
import { BaseInteractionAudioOrVideoCommandOption } from '../../basecommand';
6+
7+
8+
export const COMMAND_NAME = 'convert';
9+
10+
export class AudioConvertCommand extends BaseInteractionAudioOrVideoCommandOption {
11+
description = 'Convert an Audio or Video File';
12+
name = COMMAND_NAME;
13+
14+
constructor() {
15+
super({
16+
options: [
17+
{
18+
name: 'to',
19+
description: 'Conversion Mimetype',
20+
choices: Formatter.Commands.AudioConvert.SLASH_CHOICES,
21+
default: Formatter.Commands.AudioConvert.DEFAULT_MIMETYPE,
22+
},
23+
],
24+
});
25+
}
26+
27+
async run(context: Interaction.InteractionContext, args: Formatter.Commands.AudioConvert.CommandArgs) {
28+
return Formatter.Commands.AudioConvert.createMessage(context, args);
29+
}
30+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Interaction } from 'detritus-client';
2+
3+
import { Formatter } from '../../../../utils';
4+
5+
import { BaseInteractionAudioOrVideoCommandOption } from '../../basecommand';
6+
7+
8+
export const COMMAND_NAME = 'identify';
9+
10+
export class AudioIdentifyCommand extends BaseInteractionAudioOrVideoCommandOption {
11+
description = 'Identify a song in an audio or video file';
12+
name = COMMAND_NAME;
13+
14+
async run(context: Interaction.InteractionContext, args: Formatter.Commands.AudioIdentify.CommandArgs) {
15+
return Formatter.Commands.AudioIdentify.createMessage(context, args);
16+
}
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Permissions } from 'detritus-client/lib/constants';
2+
3+
import { BaseSlashCommand } from '../../basecommand';
4+
5+
import { AudioConvertCommand } from './convert';
6+
import { AudioIdentifyCommand } from './identify';
7+
8+
9+
export default class AudioGroupCommand extends BaseSlashCommand {
10+
description = '.';
11+
name = 'a';
12+
13+
constructor() {
14+
super({
15+
permissions: [Permissions.ATTACH_FILES],
16+
options: [
17+
new AudioConvertCommand(),
18+
new AudioIdentifyCommand(),
19+
],
20+
});
21+
}
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Interaction } from 'detritus-client';
2+
3+
import { Formatter } from '../../../../../utils';
4+
5+
import { BaseInteractionVideoCommandOption } from '../../../basecommand';
6+
7+
8+
export class VideoExtractAudioCommand extends BaseInteractionVideoCommandOption {
9+
description = 'Extract Audio from a Video';
10+
name = 'audio';
11+
12+
async run(context: Interaction.InteractionContext, args: Formatter.Commands.VideoExtractAudio.CommandArgs) {
13+
return Formatter.Commands.VideoExtractAudio.createMessage(context, args);
14+
}
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { BaseInteractionCommandOptionGroup } from '../../../basecommand';
2+
3+
import { VideoExtractAudioCommand } from './audio';
4+
5+
6+
export class VideoExtractGroupCommand extends BaseInteractionCommandOptionGroup {
7+
description = '.';
8+
name = 'extract';
9+
10+
constructor() {
11+
super({
12+
options: [
13+
new VideoExtractAudioCommand(),
14+
],
15+
});
16+
}
17+
}

0 commit comments

Comments
 (0)