77use Discord \InteractionType ;
88use Discord \Slash \Parts \Interaction ;
99use Discord \Slash \Parts \RegisteredCommand ;
10+ use Exception ;
1011use InvalidArgumentException ;
11- use React \Http \MEssage \Response ;
12+ use Kambo \Http \Message \Environment \Environment ;
13+ use Kambo \Http \Message \Factories \Environment \ServerRequestFactory ;
14+ use React \Http \Message \Response ;
1215use Monolog \Handler \StreamHandler ;
1316use Monolog \Logger ;
1417use Psr \Http \Message \ServerRequestInterface ;
@@ -116,14 +119,14 @@ private function resolveOptions(array $options): array
116119 */
117120 private function registerServer ()
118121 {
122+ // no uri => cgi/fpm
123+ if (is_null ($ this ->options ['uri ' ])) {
124+ return ;
125+ }
126+
119127 $ this ->server = new HttpServer ($ this ->getLoop (), [$ this , 'handleRequest ' ]);
120128 $ this ->socket = new SocketServer ($ this ->options ['uri ' ], $ this ->getLoop (), $ this ->options ['socket_options ' ]);
121-
122- // future tick so that the socket won't listen
123- // when running in CGI mode
124- $ this ->getLoop ()->futureTick (function () {
125- $ this ->server ->listen ($ this ->socket );
126- });
129+ $ this ->server ->listen ($ this ->socket );
127130 }
128131
129132 /**
@@ -138,7 +141,7 @@ public function handleRequest(ServerRequestInterface $request)
138141 $ timestamp = $ request ->getHeaderLine ('X-Signature-Timestamp ' );
139142
140143 if (empty ($ signature ) || empty ($ timestamp ) || ! DiscordInteraction::verifyKey ((string ) $ request ->getBody (), $ signature , $ timestamp , $ this ->options ['public_key ' ])) {
141- return new Response (401 , [0 ], 'Not verified ' );
144+ return \ React \ Promise \Resolve ( new Response (401 , [0 ], 'Not verified ' ) );
142145 }
143146
144147 $ interaction = new Interaction (json_decode ($ request ->getBody (), true ));
@@ -182,7 +185,7 @@ private function handleApplicationCommand(Interaction $interaction): void
182185 {
183186 $ checkCommand = function ($ command ) use ($ interaction , &$ checkCommand ) {
184187 if (isset ($ this ->commands [$ command ['name ' ]])) {
185- if ($ this ->commands [$ command ['name ' ]]->execute ($ command ['options ' ], $ interaction )) return true ;
188+ if ($ this ->commands [$ command ['name ' ]]->execute ($ command ['options ' ] ?? [] , $ interaction )) return true ;
186189 }
187190
188191 foreach ($ command ['options ' ] ?? [] as $ option ) {
@@ -221,6 +224,28 @@ public function registerCommand($name, callable $callback = null): RegisteredCom
221224 return $ this ->commands [$ baseCommand ]->addSubCommand ($ name , $ callback );
222225 }
223226
227+ /**
228+ * Runs the client on a CGI/FPM server.
229+ */
230+ public function runCgi ()
231+ {
232+ if (empty ($ _SERVER ['REMOTE_ADDR ' ])) {
233+ throw new Exception ('The `runCgi()` method must only be called from PHP-CGI/FPM. ' );
234+ }
235+
236+ if (! class_exists (Environment::class)) {
237+ throw new Exception ('The `kambo/httpmessage` package must be installed to handle slash command interactions with a CGI/FPM server. ' );
238+ }
239+
240+ $ environment = new Environment ($ _SERVER , fopen ('php://input ' , 'w+ ' ), $ _POST , $ _COOKIE , $ _FILES );
241+ $ serverRequest = (new ServerRequestFactory ())->create ($ environment );
242+
243+ $ this ->handleRequest ($ serverRequest )->then (function (Response $ response ) {
244+ http_response_code ($ response ->getStatusCode ());
245+ echo (string ) $ response ->getBody ();
246+ });
247+ }
248+
224249 /**
225250 * Starts the ReactPHP event loop.
226251 */
0 commit comments