8000 Fixed sending files, #182 · discord-php/DiscordPHP@24c0a1e · GitHub
[go: up one dir, main page]

Skip to content

Commit 24c0a1e

Browse files
committed
Fixed sending files, #182
1 parent 6ce5a20 commit 24c0a1e

File tree

1 file changed

+106
-19
lines changed

1 file changed

+106
-19
lines changed

src/Discord/Http/Http.php

Lines changed: 106 additions & 19 deletions
8000
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Discord\Exceptions\Rest\NoPermissionsException;
1717
use Discord\Exceptions\Rest\NotFoundException;
1818
use Discord\Parts\Channel\Channel;
19+
use Exception;
1920
use GuzzleHttp\Psr7\Response;
2021
use Illuminate\Support\Str;
2122
use React\Promise\Deferred;
@@ -46,7 +47,7 @@ class Http
4647
private $token;
4748

4849
/**
49-
* @var string
50+
* @var
5051
*/
5152
private $version;
5253

@@ -107,20 +108,27 @@ public function __call(string $name, array $params): PromiseInterface
107108
*
108109
* @param string $method The request method.
109110
* @param string $url The endpoint that will be queried.
110-
* @param array|null $content Parameters that will be encoded into JSON and sent with the request.
111+
* @param array $content Parameters that will be encoded into JSON and sent with the request.
111112
* @param array $extraHeaders Extra headers to send with the request.
112113
* @param bool|int|null $cache If an integer is passed, used as cache TTL, if null is passed, default TTL is
113114
* used, if false, cache is disabled
114115
* @param array $options Array of options to pass to Guzzle.
115116
*
117+
* @throws ContentTooLongException
118+
* @throws DiscordRequestFailedException
119+
* @throws NoPermissionsException
120+
* @throws NotFoundException
121+
*
116122
* @return PromiseInterface
117123
*/
118-
private function runRequest(string $method, string $url, ?array $content, array $extraHeaders, $cache, array $options): PromiseInterface
124+
private function runRequest($method, $url, $content, $extraHeaders, $cache, $options): PromiseInterface
119125
{
120126
$deferred = new Deferred();
121127
$disable_json = false;
122128

123-
$header['User-Agent'] = $this->getUserAgent();
129+
$headers = [
130+
'User-Agent' => $this->getUserAgent(),
131+
];
124132

125133
if (! isset($options['multipart'])) {
126134
$headers['Content-Length'] = 0;
@@ -183,20 +191,24 @@ function ($content) use ($deferred) {
183191
/**
184192
* Uploads a file to a channel.
185193
*
186-
* @param Channel $channel The channel to send to.
187-
* @param string $filepath The path to the file.
188-
* @param string $filename The name to upload the file as.
189-
* @param string|null $content Extra text content to go with the file.
190-
* @param bool $tts Whether the message should be TTS.
194+
* @param Channel $channel The channel to send to.
195+
* @param string $filepath The path to the file.
196+
* @param string $filename The name to upload the file as.
197+
* @param string $content Extra text content to go with the file.
198+
* @param bool $tts Whether the message should be TTS.
191199
*
192200
* @return PromiseInterface
193201
*/
194-
public function sendFile(Channel $channel, string $filepath, string $filename, ?string $content, bool $tts = false): PromiseInterface
202+
public function sendFile(Channel $channel, $filepath, $filename, $content, $tts): PromiseInterface
195203
{
204+
$deferred = new Deferred();
205+
206+
$boundary = '----DiscordPHPSendFileBoundary';
207+
$body = '';
196208
$multipart = [
197209
[
198210
'name' => 'file',
199-
'contents' => fopen($filepath, 'r'),
211+
'contents' => file_get_contents($filepath),
200212
'filename' => $filename,
201213
],
202214
[
@@ -205,18 +217,88 @@ public function sendFile(Channel $channel, string $filepath, string $filename, ?
205217
],
206218
[
207219
'name' => 'content',
208-
'contents' => $content,
220+
'contents' => (string) $content,
209221
],
210222
];
211223

212-
return $this->runRequest(
224+
$body = $this->arrayToMultipart($multipart, $boundary);
225+
$headers = [
226+
'Content-Type' => 'multipart/form-data; boundary='.substr($boundary, 2),
227+
'Content-Length' => strlen($body),
228+
'authorization' => $this->token,
229+
'User-Agent' => $this->getUserAgent(),
230+
];
231+
232+
$this->driver->runRequest(
213233
'POST',
214234
"channels/{$channel->id}/messages",
215-
null,
216-
[],
217-
false,
218-
['multipart' => $multipart]
235+
$headers,
236+
$body
237+
)->then(
238+
function ($response) use ($deferred) {
239+
$json = json_decode($response->getBody());
240+
$deferred->resolve($json);
241+
},
242+
function ($e) use ($deferred, $channel) {
243+
if (! ($e instanceof \Exception)) {
244+
if (is_callable([$e, 'getStatusCode'])) {
245+
$e = $this->handleError(
246+
$e->getStatusCode(),
247+
$e->getReasonPhrase(),
248+
$e->getBody(),
249+
"channels/{$channel->id}/messages"
250+
);
251+
} else {
252+
$e = $this->handleError(
253+
0,
254+
'unknown',
255+
'unknown',
256+
"channels/{$channel->id}/messages"
257+
);
258+
}
259+
}
260+
261+
$deferred->reject($e);
262+
}
219263
);
264+
265+
return $deferred->promise();
266+
}
267+
268+
/**
269+
* Converts an array of key => value to a multipart body.
270+
*
271+
* @param array $multipart
272+
* @param string $boundary
273+
*
274+
* @return string
275+
*/
276+
private function arrayToMultipart(array $multipart, string $boundary): string
277+
{
278+
$body = '';
279+
280+
foreach ($multipart as $part) {
281+
$body .= $boundary."\n";
282+
$body .= 'Content-Disposition: form-data; name="'.$part['name'].'"';
283+
284+
if (isset($part['filename'])) {
285+
$body .= '; filename="'.$part['filename'].'"';
286+
}
287+
288+
$body .= "\n";
289+
290+
if (isset($part['headers'])) {
291+
foreach ($part['headers'] as $header => $val) {
292+
$body .= $header.': '.$val."\n";
293+
}
294+
}
295+
296+
$body .= "\n".$part['contents']."\n";
297+
}
298+
299+
$body .= $boundary."--\n";
300+
301+
return $body;
220302
}
221303

222304
/**
@@ -227,9 +309,14 @@ public function sendFile(Channel $channel, string $filepath, string $filename, ?
227309
* @param string $content The HTTP response content.
228310
* @param string $url The HTTP url.
229311
*
230-
* @return DiscordRequestFailedException Returned when the request fails.
312+
* @return \Discord\Exceptions\DiscordRequestFailedException Returned when the request fails.
313+
* @return \Discord\Exceptions\Rest\ContentTooLongException Returned when the content is longer than 2000
314+
* characters.
315+
* @return \Discord\Exceptions\Rest\NotFoundException Returned when the server returns 404 Not Found.
316+
* @return \Discord\Exceptions\Rest\NoPermissionsException Returned when you do not have permissions to do
317+
* something.
231318
*/
232-
public function handleError(int $errorCode, $message, string $content, string $url): DiscordRequestFailedException
319+
public function handleError($errorCode, $message, $content, $url): Exception
233320
{
234321
if (! is_string($message)) {
235322
$message = $message->getReasonPhrase();

0 commit comments

Comments
 (0)
0