@Override public Message sendFile(File file, Message message) { checkVerification(); if (!checkPermission(getJDA().getSelfInfo(), Permission.MESSAGE_WRITE)) throw new PermissionException(Permission.MESSAGE_WRITE); if (!checkPermission(getJDA().getSelfInfo(), Permission.MESSAGE_ATTACH_FILES)) throw new PermissionException(Permission.MESSAGE_ATTACH_FILES); if (file == null || !file.exists() || !file.canRead()) throw new IllegalArgumentException( "Provided file is either null, doesn't exist or is not readable!"); if (file.length() > 8 << 20) // 8MB throw new IllegalArgumentException("File is to big! Max file-size is 8MB"); JDAImpl api = (JDAImpl) getJDA(); try { MultipartBody body = Unirest.post(Requester.DISCORD_API_PREFIX + "channels/" + getId() + "/messages") .header("authorization", getJDA().getAuthToken()) .header("user-agent", Requester.USER_AGENT) .field("file", file); if (message != null) body.field("content", message.getRawContent()).field("tts", message.isTTS()); String dbg = String.format( "Requesting %s -> %s\n\tPayload: file: %s, message: %s, tts: %s\n\tResponse: ", body.getHttpRequest().getHttpMethod().name(), body.getHttpRequest().getUrl(), file.getAbsolutePath(), message == null ? "null" : message.getRawContent(), message == null ? "N/A" : message.isTTS()); HttpResponse<JsonNode> response = body.asJson(); Requester.LOG.trace(dbg + body); try { int status = response.getStatus(); if (status >= 200 && status < 300) { return new EntityBuilder(api).createMessage(response.getBody().getObject()); } else if (response.getStatus() == 429) { long retryAfter = response.getBody().getObject().getLong("retry_after"); api.setMessageTimeout(guild.getId(), retryAfter); throw new RateLimitedException(retryAfter); } else { throw new RuntimeException( "An unknown status code was returned when attempting to upload file. Status: " + status + " JSON: " + response.getBody().toString()); } } catch (JSONException e) { Requester.LOG.fatal("Following json caused an exception: " + response.getBody().toString()); Requester.LOG.log(e); } } catch (UnirestException e) { Requester.LOG.log(e); } return null; }
@Override public Message sendMessage(Message msg) { checkVerification(); SelfInfo self = getJDA().getSelfInfo(); if (!checkPermission(self, Permission.MESSAGE_WRITE)) throw new PermissionException(Permission.MESSAGE_WRITE); JDAImpl api = (JDAImpl) getJDA(); if (api.getMessageLimit(guild.getId()) != null) { throw new RateLimitedException( api.getMessageLimit(guild.getId()) - System.currentTimeMillis()); } try { Requester.Response response = api.getRequester() .post( Requester.DISCORD_API_PREFIX + "channels/" + getId() + "/messages", new JSONObject().put("content", msg.getRawContent()).put("tts", msg.isTTS())); if (response.isRateLimit()) { long retry_after = response.getObject().getLong("retry_after"); api.setMessageTimeout(guild.getId(), retry_after); throw new RateLimitedException(retry_after); } if (!response.isOk()) // sending failed (Verification-level?) return null; return new EntityBuilder(api).createMessage(response.getObject()); } catch (JSONException ex) { JDAImpl.LOG.log(ex); // sending failed return null; } }
@Override public void run() { sending: // Label so that, if needed, we can completely kill the while loop from inside the // nested loop. while (sender.alive) { Queue<Task> queue = sender.getQueue(); while (sender.alive && !queue.isEmpty()) { Long messageLimit = sender.api.getMessageLimit(sender.ratelimitIdentifier); if (messageLimit != null) { try { Thread.sleep(messageLimit - System.currentTimeMillis()); } catch (InterruptedException e) { JDAImpl.LOG.log(e); } } Task task = queue.peek(); Message msg = task.message; Requester.Response response; if (sender.api.getTextChannelById(msg.getChannelId()) == null && sender.api.getPrivateChannelById(msg.getChannelId()) == null) { // We no longer have access to the MessageChannel that this message is queued to // send to. This is most likely because it was deleted. AsyncMessageSender.stop(sender.api, sender.ratelimitIdentifier); break sending; } if (task.isEdit) { response = sender .api .getRequester() .patch( Requester.DISCORD_API_PREFIX + "channels/" + msg.getChannelId() + "/messages/" + msg.getId(), new JSONObject().put("content", msg.getRawContent())); } else { response = sender .api .getRequester() .post( Requester.DISCORD_API_PREFIX + "channels/" + msg.getChannelId() + "/messages", new JSONObject() .put("content", msg.getRawContent()) .put("tts", msg.isTTS())); } if (response.responseText == null) { JDAImpl.LOG.debug( "Error sending async-message (returned null-text)... Retrying after 1s"); sender.api.setMessageTimeout(sender.ratelimitIdentifier, 1000); } else if (!response.isRateLimit()) // success/unrecoverable error { queue.poll(); // remove from queue try { if (response.isOk()) { if (task.callback != null) task.callback.accept( new EntityBuilder(sender.api).createMessage(response.getObject())); } else { // if response didn't have id, sending failed (due to permission/blocked pm,... JDAImpl.LOG.fatal( "Could not send/update async message to channel: " + msg.getChannelId() + ". Discord-response: " + response.toString()); if (task.callback != null) task.callback.accept(null); } } catch (JSONException ex) { // could not generate message from json JDAImpl.LOG.log(ex); } catch (IllegalArgumentException ex) { JDAImpl.LOG.log(ex); } } else { sender.api.setMessageTimeout( sender.ratelimitIdentifier, response.getObject().getLong("retry_after")); } if (queue.isEmpty()) { queue = sender.getQueue(); } } sender.waitNew(); } }