@@ -21,56 +21,25 @@ const langs = {
2121 'TypeScript' :'typescript-3.9.5' ,
2222} ;
2323
24- module . exports = {
25- data : new SlashCommandBuilder ( )
26- . setName ( 'run' )
27- . setDescription ( '👩💻Runs your <code/>;' )
28- . addStringOption ( option => {
29- option
30- . setName ( 'language' )
31- . setDescription ( 'Select programming language' )
32- . setRequired ( true ) ;
33- for ( const [ lang , val ] of Object . entries ( langs ) ) {
34- option . addChoice ( `${ lang } ` , `${ val } ` ) ;
35- }
36- return option ;
37- } ) ,
38- async execute ( interaction ) {
39- const lang = interaction . options . getString ( 'language' ) ;
40- await interaction . reply ( { content : 'Send your code in this channel enclosed in a code block. Request expires in 15 minutes!' , ephemeral : true } ) ;
41- // Check if the message is a codeblock or not
42- const filter = msg => msg . content . startsWith ( '```' ) && msg . content . endsWith ( '```' ) ;
43- // Create collector to collect multi-line input via codeblock
44- // Waits for codeblock reply. Ends collector after 15 minutes if no response is received
45- const collector = interaction . channel . createMessageCollector ( { max : 1 , filter, time : 900000 } ) ;
46-
47- collector . on ( 'collect' , async message => {
48- const code = format ( message . content ) ;
49- const output = await run ( code , lang ) ;
50- await interaction . followUp ( {
51- content : `[Source code](${ message . url } ) by ${ interaction . user } ` ,
52- embeds : [ embed ( output ) ] ,
53- components : [ link ( output . url ) ] } ) ;
54- } ) ;
55-
56- collector . on ( 'end' , async ( collected ) => {
57- console . log ( `Collected ${ collected . size } items` ) ;
58- if ( collected . size == 0 ) await interaction . followUp ( { content : 'Token expired' , ephemreal : true } ) ;
59- } ) ;
60- } ,
61- } ;
24+ // Version of selected language
25+ // This object is honestly a bad addition, but djs has left no other way to access OptionChoice `name` directly
26+ const versions = { } ;
27+ Object . keys ( langs ) . forEach ( key => {
28+ versions [ langs [ key ] ] = key ;
29+ } ) ;
6230
6331// Parses code from code block
6432const format = code => {
6533 const start = code . indexOf ( '\n' ) + 1 ;
6634 const end = code . lastIndexOf ( '\n' ) ;
6735 return code . slice ( start , end ) ;
6836} ;
37+
6938// POST code to wandbox API
70- const run = async ( code , lang ) => {
39+ const run = async ( code , version ) => {
7140 const form = {
7241 'code' :code ,
73- 'compiler' : lang ,
42+ 'compiler' : version ,
7443 'save' :true ,
7544 } ;
7645 const headers = {
@@ -84,11 +53,17 @@ const run = async (code, lang) => {
8453} ;
8554
8655// EMBED CONSTRUCTORS
87- const embed = output => new MessageEmbed ( )
88- . setColor ( '#15e854' )
89- . setTitle ( 'OUTPUT' )
90- . setDescription ( `\`\`\`\n${ output . program_message } \`\`\`` )
91- . setFooter ( `Exit Status Code: ${ output . status } ` ) ;
56+ const embed = ( output , lang ) => {
57+ let out = output . program_message ;
58+ if ( out == undefined ) out = output . compiler_message ;
59+ return new MessageEmbed ( )
60+ . setColor ( '#15e854' )
61+ . setTitle ( 'output' )
62+ . setDescription ( `\`\`\`\n${ out } \`\`\`` )
63+ . addFields (
64+ { name : 'language' , value : `${ lang } ` } )
65+ . setFooter ( `Exit Status Code: ${ output . status } ` ) ;
66+ } ;
9267
9368// BUTTON CONSTRUCTORS
9469const link = url => new MessageActionRow ( )
@@ -97,4 +72,68 @@ const link = url => new MessageActionRow()
9772 . setLabel ( 'View/Edit 👩🏻💻 code in browser' )
9873 . setURL ( url )
9974 . setStyle ( 'LINK' ) ,
100- ) ;
75+ ) ;
76+
77+ // Active Collectors array, stores userIds with active collectors, follow further code to understand
78+ const active = new Map ( ) ;
79+
80+ module . exports = {
81+ data : new SlashCommandBuilder ( )
82+ . setName ( 'run' )
83+ . setDescription ( '👩💻Runs your <code/>;' )
84+ . addStringOption ( option => {
85+ option
86+ . setName ( 'language' )
87+ . setDescription ( 'Select programming language' )
88+ . setRequired ( true ) ;
89+ for ( const [ lang , version ] of Object . entries ( langs ) ) {
90+ option . addChoice ( `${ lang } ` , `${ version } ` ) ;
91+ }
92+ return option ;
93+ } ) ,
94+ async execute ( interaction ) {
95+
96+ // options.getString('language') will actually return option choice `value`, and not choice `name`
97+ // https://discordjs.guide/interactions/replying-to-slash-commands.html#parsing-options
98+ const version = interaction . options . getString ( 'language' ) ;
99+ const lang = versions [ version ] ;
100+ const user = interaction . user . id ;
101+
102+ // prompt user to send code
103+ await interaction . reply ( { content : `Send your **${ lang } ** code enclosed in a code block. Request expires in 15 minutes!` , ephemeral : true } ) ;
104+
105+ // Check if any received message by user is a codeblock, if not wait for reply until timer ends
106+ // `filter` returns a boolean, code will be processed only when it returns True
107+ function filter ( message ) {
108+ return ( message . author . id == user ) &&
109+ message . content . startsWith ( '```' ) && message . content . endsWith ( '```' ) ;
110+ }
111+
112+ // Collector is created when /run command is triggered
113+
114+ // Check if user has already created a collector
115+ // if yes, destroy previous collector
116+ const activeCollector = active . get ( user ) ;
117+ if ( activeCollector ) activeCollector . stop ( ) ;
118+
119+ // Create new collector to collect multi-line input via codeblock
120+ // Waits for codeblock reply. Ends collector after 15 minutes if no response is received
121+ const collector = interaction . channel . createMessageCollector ( { max : 1 , filter, time : 900000 } ) ;
122+ active . set ( user , collector ) ;
123+
124+ collector . on ( 'collect' , async message => {
125+ const code = format ( message . content ) ;
126+ const output = await run ( code , version ) ;
127+ await message . reply ( {
128+ embeds : [ embed ( output , lang ) ] ,
129+ components : [ link ( output . url ) ] } ) ;
130+ } ) ;
131+
132+ collector . on ( 'end' , async ( collected ) => {
133+ active . delete ( user ) ;
134+ const tag = interaction . user . tag ;
135+ if ( collected . size == 0 ) console . log ( `${ tag } 's /run request expired!` ) ;
136+ else console . log ( `${ tag } 's /run request processed!` ) ;
137+ } ) ;
138+ } ,
139+ } ;
0 commit comments