work on send media
This commit is contained in:
@@ -45,6 +45,7 @@ dependencies {
|
|||||||
exclude group: 'org.openjfx'
|
exclude group: 'org.openjfx'
|
||||||
}
|
}
|
||||||
//For upload files
|
//For upload files
|
||||||
|
implementation 'org.slf4j:slf4j-simple:2.0.13'
|
||||||
implementation 'com.sparkjava:spark-core:2.9.4'
|
implementation 'com.sparkjava:spark-core:2.9.4'
|
||||||
implementation 'com.mpatric:mp3agic:0.9.1' //for mp3
|
implementation 'com.mpatric:mp3agic:0.9.1' //for mp3
|
||||||
implementation 'org.json:json:20231013'
|
implementation 'org.json:json:20231013'
|
||||||
|
|||||||
@@ -3345,69 +3345,69 @@ public class ActionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// public void sendMessage(UUID receiverId, String receiverType) {
|
public void sendMessage(UUID receiverId, String receiverType) {
|
||||||
// Scanner scanner = new Scanner(System.in);
|
Scanner scanner = new Scanner(System.in);
|
||||||
//
|
|
||||||
// System.out.print("Enter your message: ");
|
System.out.print("Enter your message: ");
|
||||||
// String content = scanner.nextLine();
|
String content = scanner.nextLine();
|
||||||
//
|
|
||||||
// System.out.print("Enter message type (TEXT / IMAGE / VIDEO / FILE): ");
|
System.out.print("Enter message type (TEXT / IMAGE / VIDEO / FILE): ");
|
||||||
// String messageType = scanner.nextLine();
|
String messageType = scanner.nextLine();
|
||||||
// Set<String> allowedTypes = Set.of("TEXT", "IMAGE", "VIDEO", "FILE");
|
Set<String> allowedTypes = Set.of("TEXT", "IMAGE", "VIDEO", "FILE");
|
||||||
// while (!allowedTypes.contains(messageType.toUpperCase())) {
|
while (!allowedTypes.contains(messageType.toUpperCase())) {
|
||||||
// System.out.println("❌ Invalid message type. Try again (TEXT / IMAGE / VIDEO / FILE): ");
|
System.out.println("❌ Invalid message type. Try again (TEXT / IMAGE / VIDEO / FILE): ");
|
||||||
// messageType = scanner.nextLine();
|
messageType = scanner.nextLine();
|
||||||
// }
|
}
|
||||||
// messageType = messageType.toUpperCase();
|
messageType = messageType.toUpperCase();
|
||||||
//
|
|
||||||
// JSONArray attachmentsArray = new JSONArray();
|
JSONArray attachmentsArray = new JSONArray();
|
||||||
//
|
|
||||||
// System.out.print("Do you want to attach files? (yes/no): ");
|
System.out.print("Do you want to attach files? (yes/no): ");
|
||||||
// if (scanner.nextLine().equalsIgnoreCase("yes")) {
|
if (scanner.nextLine().equalsIgnoreCase("yes")) {
|
||||||
// while (true) {
|
while (true) {
|
||||||
// System.out.print("File URL: ");
|
System.out.print("File URL: ");
|
||||||
// String fileUrl = scanner.nextLine();
|
String fileUrl = scanner.nextLine();
|
||||||
//
|
|
||||||
// System.out.print("File Type (IMAGE / VIDEO / FILE): ");
|
System.out.print("File Type (IMAGE / VIDEO / FILE): ");
|
||||||
// String fileType = scanner.nextLine();
|
String fileType = scanner.nextLine();
|
||||||
//
|
|
||||||
// JSONObject fileJson = new JSONObject();
|
JSONObject fileJson = new JSONObject();
|
||||||
// fileJson.put("file_url", fileUrl);
|
fileJson.put("file_url", fileUrl);
|
||||||
// fileJson.put("file_type", fileType);
|
fileJson.put("file_type", fileType);
|
||||||
// attachmentsArray.put(fileJson);
|
attachmentsArray.put(fileJson);
|
||||||
//
|
|
||||||
// System.out.print("Add another file? (yes/no): ");
|
System.out.print("Add another file? (yes/no): ");
|
||||||
// if (!scanner.nextLine().equalsIgnoreCase("yes")) {
|
if (!scanner.nextLine().equalsIgnoreCase("yes")) {
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// JSONObject messageJson = new JSONObject();
|
JSONObject messageJson = new JSONObject();
|
||||||
// messageJson.put("action", "send_message");
|
messageJson.put("action", "send_message");
|
||||||
// messageJson.put("receiver_type", receiverType);
|
messageJson.put("receiver_type", receiverType);
|
||||||
// messageJson.put("content", content);
|
messageJson.put("content", content);
|
||||||
// messageJson.put("message_type", messageType);
|
messageJson.put("message_type", messageType);
|
||||||
// if (receiverType.equals("private")) {
|
if (receiverType.equals("private")) {
|
||||||
// messageJson.put("receiver_user_id", receiverId.toString());
|
messageJson.put("receiver_user_id", receiverId.toString());
|
||||||
// } else {
|
} else {
|
||||||
// messageJson.put("receiver_id", receiverId.toString());
|
messageJson.put("receiver_id", receiverId.toString());
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// if (!attachmentsArray.isEmpty()) {
|
if (!attachmentsArray.isEmpty()) {
|
||||||
// messageJson.put("attachments", attachmentsArray);
|
messageJson.put("attachments", attachmentsArray);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// JSONObject response = sendWithResponse(messageJson);
|
JSONObject response = sendWithResponse(messageJson);
|
||||||
// if (response != null && response.getString("status").equals("success")) {
|
if (response != null && response.getString("status").equals("success")) {
|
||||||
// System.out.println("✅ Message sent successfully! ID: " + response.getJSONObject("data").getString("message_id"));
|
System.out.println("✅ Message sent successfully! ID: " + response.getJSONObject("data").getString("message_id"));
|
||||||
// } else {
|
} else {
|
||||||
// System.out.println("❌ Failed to send message: " + (response != null ? response.getString("message") : "no response"));
|
System.out.println("❌ Failed to send message: " + (response != null ? response.getString("message") : "no response"));
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3465,79 +3465,79 @@ public class ActionHandler {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
public void sendMessage(UUID chatId, String receiverType) {
|
// public void sendMessage(UUID chatId, String receiverType) {
|
||||||
Scanner scanner = new Scanner(System.in);
|
// Scanner scanner = new Scanner(System.in);
|
||||||
|
//
|
||||||
System.out.print("Enter your message (leave empty if file only): ");
|
// System.out.print("Enter your message (leave empty if file only): ");
|
||||||
String content = scanner.nextLine();
|
// String content = scanner.nextLine();
|
||||||
|
//
|
||||||
System.out.print("Enter message type (TEXT / IMAGE / AUDIO / FILE / GIF): ");
|
// System.out.print("Enter message type (TEXT / IMAGE / AUDIO / FILE / GIF): ");
|
||||||
String messageType = scanner.nextLine().toUpperCase();
|
// String messageType = scanner.nextLine().toUpperCase();
|
||||||
Set<String> allowedTypes = Set.of("TEXT", "IMAGE", "AUDIO", "FILE", "GIF");
|
// Set<String> allowedTypes = Set.of("TEXT", "IMAGE", "AUDIO", "FILE", "GIF");
|
||||||
while (!allowedTypes.contains(messageType)) {
|
// while (!allowedTypes.contains(messageType)) {
|
||||||
System.out.print("❌ Invalid type. Try again (TEXT / IMAGE / AUDIO / FILE / GIF): ");
|
// System.out.print("❌ Invalid type. Try again (TEXT / IMAGE / AUDIO / FILE / GIF): ");
|
||||||
messageType = scanner.nextLine().toUpperCase();
|
// messageType = scanner.nextLine().toUpperCase();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
JSONArray attachmentsArray = new JSONArray();
|
// JSONArray attachmentsArray = new JSONArray();
|
||||||
System.out.print("Attach files? (yes/no): ");
|
// System.out.print("Attach files? (yes/no): ");
|
||||||
if (scanner.nextLine().equalsIgnoreCase("yes")) {
|
// if (scanner.nextLine().equalsIgnoreCase("yes")) {
|
||||||
while (true) {
|
// while (true) {
|
||||||
System.out.println("Paste the JSON you got from /upload (or leave empty to enter minimal fields):");
|
// System.out.println("Paste the JSON you got from /upload (or leave empty to enter minimal fields):");
|
||||||
String jsonLine = scanner.nextLine().trim();
|
// String jsonLine = scanner.nextLine().trim();
|
||||||
|
//
|
||||||
JSONObject fileJson;
|
// JSONObject fileJson;
|
||||||
if (!jsonLine.isEmpty()) {
|
// if (!jsonLine.isEmpty()) {
|
||||||
// انتظار خروجی کامل /upload
|
// // انتظار خروجی کامل /upload
|
||||||
fileJson = new JSONObject(jsonLine);
|
// fileJson = new JSONObject(jsonLine);
|
||||||
// اگه خروجی /upload تو ریشهست، تبدیلش کن به ساختار attachment
|
// // اگه خروجی /upload تو ریشهست، تبدیلش کن به ساختار attachment
|
||||||
fileJson = new JSONObject()
|
// fileJson = new JSONObject()
|
||||||
.put("file_url", fileJson.optString("file_url", ""))
|
// .put("file_url", fileJson.optString("file_url", ""))
|
||||||
.put("file_type", fileJson.optString("file_type", "FILE"))
|
// .put("file_type", fileJson.optString("file_type", "FILE"))
|
||||||
.put("file_name", fileJson.optString("file_name", ""))
|
// .put("file_name", fileJson.optString("file_name", ""))
|
||||||
.put("file_size", fileJson.optLong("file_size", 0))
|
// .put("file_size", fileJson.optLong("file_size", 0))
|
||||||
.put("mime_type", fileJson.optString("mime_type", ""))
|
// .put("mime_type", fileJson.optString("mime_type", ""))
|
||||||
.put("width", fileJson.isNull("width") ? JSONObject.NULL : fileJson.optInt("width"))
|
// .put("width", fileJson.isNull("width") ? JSONObject.NULL : fileJson.optInt("width"))
|
||||||
.put("height", fileJson.isNull("height") ? JSONObject.NULL : fileJson.optInt("height"))
|
// .put("height", fileJson.isNull("height") ? JSONObject.NULL : fileJson.optInt("height"))
|
||||||
.put("duration_seconds", fileJson.isNull("duration_seconds") ? JSONObject.NULL : fileJson.optInt("duration_seconds"))
|
// .put("duration_seconds", fileJson.isNull("duration_seconds") ? JSONObject.NULL : fileJson.optInt("duration_seconds"))
|
||||||
.put("thumbnail_url", fileJson.isNull("thumbnail_url") ? JSONObject.NULL : fileJson.optString("thumbnail_url", null));
|
// .put("thumbnail_url", fileJson.isNull("thumbnail_url") ? JSONObject.NULL : fileJson.optString("thumbnail_url", null));
|
||||||
} else {
|
// } else {
|
||||||
// ورودی حداقلی
|
// // ورودی حداقلی
|
||||||
System.out.print("File URL: ");
|
// System.out.print("File URL: ");
|
||||||
String fileUrl = scanner.nextLine();
|
// String fileUrl = scanner.nextLine();
|
||||||
System.out.print("File Type (IMAGE / AUDIO / FILE / GIF): ");
|
// System.out.print("File Type (IMAGE / AUDIO / FILE / GIF): ");
|
||||||
String fileType = scanner.nextLine().toUpperCase();
|
// String fileType = scanner.nextLine().toUpperCase();
|
||||||
|
//
|
||||||
fileJson = new JSONObject();
|
// fileJson = new JSONObject();
|
||||||
fileJson.put("file_url", fileUrl);
|
// fileJson.put("file_url", fileUrl);
|
||||||
fileJson.put("file_type", fileType);
|
// fileJson.put("file_type", fileType);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
attachmentsArray.put(fileJson);
|
// attachmentsArray.put(fileJson);
|
||||||
|
//
|
||||||
System.out.print("Add another file? (yes/no): ");
|
// System.out.print("Add another file? (yes/no): ");
|
||||||
if (!scanner.nextLine().equalsIgnoreCase("yes")) break;
|
// if (!scanner.nextLine().equalsIgnoreCase("yes")) break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
JSONObject messageJson = new JSONObject();
|
// JSONObject messageJson = new JSONObject();
|
||||||
messageJson.put("action", "send_message");
|
// messageJson.put("action", "send_message");
|
||||||
messageJson.put("receiver_type", receiverType); // "private"/"group"/"channel"
|
// messageJson.put("receiver_type", receiverType); // "private"/"group"/"channel"
|
||||||
messageJson.put("receiver_id", chatId.toString()); // در private = chat_id
|
// messageJson.put("receiver_id", chatId.toString()); // در private = chat_id
|
||||||
messageJson.put("content", content);
|
// messageJson.put("content", content);
|
||||||
messageJson.put("message_type", messageType);
|
// messageJson.put("message_type", messageType);
|
||||||
if (attachmentsArray.length() > 0) {
|
// if (attachmentsArray.length() > 0) {
|
||||||
messageJson.put("attachments", attachmentsArray);
|
// messageJson.put("attachments", attachmentsArray);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
JSONObject response = sendWithResponse(messageJson);
|
// JSONObject response = sendWithResponse(messageJson);
|
||||||
if (response != null && response.getString("status").equals("success")) {
|
// if (response != null && response.getString("status").equals("success")) {
|
||||||
System.out.println("✅ Message sent! ID: " + response.getJSONObject("data").getString("message_id"));
|
// System.out.println("✅ Message sent! ID: " + response.getJSONObject("data").getString("message_id"));
|
||||||
} else {
|
// } else {
|
||||||
System.out.println("❌ Failed to send message: " + (response != null ? response.optString("message","No message") : "No response"));
|
// System.out.println("❌ Failed to send message: " + (response != null ? response.optString("message","No message") : "No response"));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void refreshContactList() {
|
private void refreshContactList() {
|
||||||
JSONObject req = new JSONObject();
|
JSONObject req = new JSONObject();
|
||||||
req.put("action", "get_contact_list");
|
req.put("action", "get_contact_list");
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package org.to.telegramfinalproject.Client;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class MediaSender {
|
||||||
|
|
||||||
|
public static void sendImageOrAudio(Socket socket,
|
||||||
|
UUID senderId,
|
||||||
|
String receiverType,
|
||||||
|
UUID receiverId,
|
||||||
|
File file,
|
||||||
|
String messageType, // "IMAGE" یا "AUDIO"
|
||||||
|
String captionOrEmpty) throws Exception {
|
||||||
|
|
||||||
|
if (!"IMAGE".equals(messageType) && !"AUDIO".equals(messageType))
|
||||||
|
throw new IllegalArgumentException("Only IMAGE/AUDIO");
|
||||||
|
|
||||||
|
// 1) اعلام سوییچ به باینری
|
||||||
|
PrintWriter textOut = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true);
|
||||||
|
textOut.println("MEDIA");
|
||||||
|
|
||||||
|
// 2) متادیتا
|
||||||
|
String mime = Files.probeContentType(file.toPath());
|
||||||
|
if (mime == null) mime = "application/octet-stream";
|
||||||
|
|
||||||
|
Integer width = null, height = null;
|
||||||
|
if ("IMAGE".equals(messageType)) {
|
||||||
|
try {
|
||||||
|
BufferedImage img = ImageIO.read(file);
|
||||||
|
if (img != null) { width = img.getWidth(); height = img.getHeight(); }
|
||||||
|
} catch (Exception ignore) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID messageId = UUID.randomUUID();
|
||||||
|
JSONObject header = new JSONObject()
|
||||||
|
.put("message_id", messageId.toString())
|
||||||
|
.put("sender_id", senderId.toString())
|
||||||
|
.put("receiver_type", receiverType)
|
||||||
|
.put("receiver_id", receiverId.toString())
|
||||||
|
.put("message_type", messageType)
|
||||||
|
.put("file_name", file.getName())
|
||||||
|
.put("mime_type", mime)
|
||||||
|
.put("file_size", file.length())
|
||||||
|
.put("text", captionOrEmpty == null ? "" : captionOrEmpty);
|
||||||
|
|
||||||
|
if (width != null) header.put("width", width);
|
||||||
|
if (height != null) header.put("height", height);
|
||||||
|
|
||||||
|
byte[] headerBytes = header.toString().getBytes("UTF-8");
|
||||||
|
|
||||||
|
// 3) ارسال فریم باینری
|
||||||
|
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
|
||||||
|
dos.writeInt(0x4D444D31); // MAGIC
|
||||||
|
dos.writeInt(headerBytes.length); // headerLen
|
||||||
|
dos.write(headerBytes); // header
|
||||||
|
dos.writeLong(file.length()); // contentLen
|
||||||
|
|
||||||
|
try (InputStream fis = new BufferedInputStream(new FileInputStream(file))) {
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
int n;
|
||||||
|
while ((n = fis.read(buf)) != -1) {
|
||||||
|
dos.write(buf, 0, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dos.flush();
|
||||||
|
|
||||||
|
// (اختیاری) Ack متنی
|
||||||
|
BufferedReader textIn = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
|
||||||
|
String ack = textIn.readLine();
|
||||||
|
if (!"OK".equalsIgnoreCase(ack)) {
|
||||||
|
throw new IOException("Server did not ACK: " + ack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,11 +29,24 @@ public class ClientHandler implements Runnable {
|
|||||||
UUID userId = null;
|
UUID userId = null;
|
||||||
|
|
||||||
try (
|
try (
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
// BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)
|
// PrintWriter out = new PrintWriter(socket.getOutputStream(), true)
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
|
||||||
|
DataInputStream dis = new DataInputStream(bis); // برای MEDIA و هدرهای باینری
|
||||||
|
|
||||||
|
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), java.nio.charset.StandardCharsets.UTF_8), true);
|
||||||
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
// DataInputStream bin = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
|
||||||
|
|
||||||
String inputLine;
|
String inputLine;
|
||||||
while ((inputLine = in.readLine()) != null) {
|
while ((inputLine = readUtf8Line(bis)) != null) {
|
||||||
|
if ("MEDIA".equalsIgnoreCase(inputLine.trim())) {
|
||||||
|
handleMediaFrame(dis, out);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject requestJson = new JSONObject(inputLine);
|
JSONObject requestJson = new JSONObject(inputLine);
|
||||||
String action = requestJson.getString("action");
|
String action = requestJson.getString("action");
|
||||||
ResponseModel response = null;
|
ResponseModel response = null;
|
||||||
@@ -2579,6 +2592,194 @@ public class ClientHandler implements Runnable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String readUtf8Line(BufferedInputStream bis) throws java.io.IOException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (true) {
|
||||||
|
int b = bis.read();
|
||||||
|
if (b == -1) {
|
||||||
|
return sb.length() == 0 ? null : sb.toString();
|
||||||
|
}
|
||||||
|
if (b == '\n') {
|
||||||
|
int len = sb.length();
|
||||||
|
if (len > 0 && sb.charAt(len - 1) == '\r') sb.setLength(len - 1);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
sb.append((char) b); // برای کنترللاینهای ASCII/UTF-8 OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void handleMediaFrame(DataInputStream dis, PrintWriter out) {
|
||||||
|
try {
|
||||||
|
// MAGIC = "MDM1"
|
||||||
|
final int MAGIC_EXPECTED = 0x4D444D31;
|
||||||
|
int magic = dis.readInt();
|
||||||
|
if (magic != MAGIC_EXPECTED) {
|
||||||
|
out.println(new JSONObject().put("status","error").put("message","bad magic").toString());
|
||||||
|
out.flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int headerLen = dis.readInt();
|
||||||
|
if (headerLen <= 0 || headerLen > (64 * 1024)) {
|
||||||
|
out.println(new JSONObject().put("status","error").put("message","bad header length").toString());
|
||||||
|
out.flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] headerBytes = dis.readNBytes(headerLen);
|
||||||
|
if (headerBytes.length != headerLen) {
|
||||||
|
out.println(new JSONObject().put("status","error").put("message","header truncated").toString());
|
||||||
|
out.flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JSONObject h = new JSONObject(new String(headerBytes, java.nio.charset.StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
long contentLen = dis.readLong();
|
||||||
|
long MAX_MEDIA = 25L * 1024 * 1024;
|
||||||
|
if (contentLen <= 0 || contentLen > MAX_MEDIA) {
|
||||||
|
skip(dis, contentLen);
|
||||||
|
out.println(new JSONObject().put("status","error").put("message","file too large/invalid").toString());
|
||||||
|
out.flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// الزامیها
|
||||||
|
UUID messageId = UUID.fromString(h.getString("message_id"));
|
||||||
|
UUID senderId = UUID.fromString(h.getString("sender_id"));
|
||||||
|
String rType = h.getString("receiver_type"); // private/group/channel
|
||||||
|
UUID receiverId = UUID.fromString(h.getString("receiver_id"));
|
||||||
|
String messageType = h.getString("message_type"); // IMAGE | AUDIO
|
||||||
|
|
||||||
|
if (!"IMAGE".equalsIgnoreCase(messageType) && !"AUDIO".equalsIgnoreCase(messageType)) {
|
||||||
|
skip(dis, contentLen);
|
||||||
|
out.println(new JSONObject().put("status","error").put("message","unsupported message_type").toString());
|
||||||
|
out.flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fileName = h.optString("file_name", "file.bin");
|
||||||
|
String mimeType = h.optString("mime_type", "application/octet-stream");
|
||||||
|
String text = h.optString("text", "");
|
||||||
|
|
||||||
|
Integer width = h.has("width") && !h.isNull("width") ? h.getInt("width") : null;
|
||||||
|
Integer height = h.has("height") && !h.isNull("height") ? h.getInt("height") : null;
|
||||||
|
|
||||||
|
if (fileName.length() > 200) fileName = fileName.substring(0, 200);
|
||||||
|
|
||||||
|
// مسیر ذخیره
|
||||||
|
java.nio.file.Path baseDir = java.nio.file.Paths.get("uploads").toAbsolutePath().normalize();
|
||||||
|
java.nio.file.Files.createDirectories(baseDir);
|
||||||
|
String kind = "IMAGE".equalsIgnoreCase(messageType) ? "images" : "audios";
|
||||||
|
String subdir = kind + "/" + java.time.LocalDate.now();
|
||||||
|
java.nio.file.Path dir = baseDir.resolve(subdir).normalize();
|
||||||
|
java.nio.file.Files.createDirectories(dir);
|
||||||
|
|
||||||
|
String ext = guessExt(fileName, mimeType);
|
||||||
|
String storedName = java.util.UUID.randomUUID() + ext;
|
||||||
|
java.nio.file.Path target = dir.resolve(storedName).normalize();
|
||||||
|
|
||||||
|
// دریافت بایتهای فایل
|
||||||
|
try (OutputStream fos = new BufferedOutputStream(java.nio.file.Files.newOutputStream(
|
||||||
|
target, java.nio.file.StandardOpenOption.CREATE, java.nio.file.StandardOpenOption.TRUNCATE_EXISTING))) {
|
||||||
|
long remaining = contentLen;
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
while (remaining > 0) {
|
||||||
|
int toRead = (int) Math.min(buf.length, remaining);
|
||||||
|
int n = dis.read(buf, 0, toRead);
|
||||||
|
if (n == -1) throw new EOFException("stream ended early");
|
||||||
|
fos.write(buf, 0, n);
|
||||||
|
remaining -= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long fileSize = java.nio.file.Files.size(target);
|
||||||
|
String fileUrl = "/" + subdir.replace('\\','/') + "/" + storedName;
|
||||||
|
|
||||||
|
FileAttachment att = new FileAttachment(
|
||||||
|
fileUrl,
|
||||||
|
messageType.toUpperCase(), // IMAGE/AUDIO
|
||||||
|
fileName,
|
||||||
|
fileSize,
|
||||||
|
mimeType,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
null, // durationSeconds
|
||||||
|
null // thumbnailUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
boolean ok = MessageDatabase.saveMessageWithOptionalAttachments(
|
||||||
|
messageId, senderId, receiverId, rType, text, messageType.toUpperCase(), java.util.List.of(att)
|
||||||
|
);
|
||||||
|
|
||||||
|
JSONObject ack = new JSONObject()
|
||||||
|
.put("status", ok ? "success" : "error")
|
||||||
|
.put("message_id", messageId.toString())
|
||||||
|
.put("file_url", fileUrl)
|
||||||
|
.put("file_size", fileSize)
|
||||||
|
.put("mime_type", mimeType);
|
||||||
|
|
||||||
|
out.println(ack.toString());
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.println(new JSONObject().put("status","error").put("message","exception").toString());
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void skip(DataInputStream dis, long n) throws IOException {
|
||||||
|
if (n <= 0) return;
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
long left = n;
|
||||||
|
while (left > 0) {
|
||||||
|
int toRead = (int) Math.min(buf.length, left);
|
||||||
|
int r = dis.read(buf, 0, toRead);
|
||||||
|
if (r == -1) break; // EOF
|
||||||
|
left -= r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String guessExt(String original, String mime) {
|
||||||
|
// اول از نام اصلی (امن چون فقط برای اکستنشن استفاده میکنی)
|
||||||
|
if (original != null && original.contains(".")) {
|
||||||
|
String ext = original.substring(original.lastIndexOf('.'));
|
||||||
|
if (ext.length() <= 10) return ext.toLowerCase();
|
||||||
|
}
|
||||||
|
if (mime == null) return "";
|
||||||
|
|
||||||
|
String m = mime.toLowerCase();
|
||||||
|
|
||||||
|
// تصاویر
|
||||||
|
if (m.equals("image/png")) return ".png";
|
||||||
|
if (m.equals("image/jpeg") || m.equals("image/jpg")) return ".jpg";
|
||||||
|
if (m.equals("image/gif")) return ".gif";
|
||||||
|
if (m.equals("image/webp")) return ".webp";
|
||||||
|
|
||||||
|
// صوت
|
||||||
|
if (m.equals("audio/mpeg") || m.equals("audio/mp3")) return ".mp3";
|
||||||
|
if (m.equals("audio/ogg")) return ".ogg";
|
||||||
|
if (m.equals("audio/opus")) return ".opus";
|
||||||
|
if (m.equals("audio/wav") || m.equals("audio/x-wav")) return ".wav";
|
||||||
|
if (m.equals("audio/m4a") || m.equals("audio/mp4")) return ".m4a";
|
||||||
|
|
||||||
|
// ویدیو (اگر بعدا اضافه شد)
|
||||||
|
if (m.equals("video/mp4")) return ".mp4";
|
||||||
|
if (m.equals("video/webm")) return ".webm";
|
||||||
|
|
||||||
|
// fallback
|
||||||
|
if (m.startsWith("image/")) return ""; // بگذار بدون اکستنشن ذخیره شود
|
||||||
|
if (m.startsWith("audio/")) return "";
|
||||||
|
if (m.startsWith("video/")) return "";
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// private ResponseModel handleSendMessage(JSONObject json) {
|
// private ResponseModel handleSendMessage(JSONObject json) {
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user