From e344facb20f650e7fe2879e3383dd6c7f3921f58 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Fri, 15 Aug 2025 00:31:26 +0330 Subject: [PATCH] Clean code --- .../Client/ActionHandler.java | 26 ++++------------- .../Client/DownloadsIndex.java | 7 ----- .../Client/SocketMediaDownloader.java | 3 -- .../Server/ClientHandler.java | 29 +++++++------------ 4 files changed, 15 insertions(+), 50 deletions(-) diff --git a/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java b/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java index 2fef192..852b96d 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java @@ -3824,12 +3824,11 @@ public class ActionHandler { long declaredSize = att.optLong("file_size", 0L); // ~/Downloads/TeleSock/// - String accFolder = accountFolderName(); // ← از یوزر لاگین‌شده - String chatFolder = chatFolderName(chat); // ← برای پرایوت: اسم طرف مقابل + String accFolder = accountFolderName(); + String chatFolder = chatFolderName(chat); Path saveDir = Paths.get(System.getProperty("user.home"), "Downloads", "TeleSock", accFolder, chatFolder); - // دیباگ اختیاری System.out.println("👤 AccountFolder = " + accFolder); System.out.println("💬 ChatFolder = " + chatFolder); System.out.println("📁 SaveDir = " + saveDir); @@ -3840,7 +3839,6 @@ public class ActionHandler { return; } - // اگر قبلاً دانلود شده (و فایل واقعاً وجود دارد) — ایندکس مخصوص همین اکانت DownloadsIndex di = Session.downloadsIndex; if (di != null) { Path existing = di.find(mediaKey); @@ -3849,11 +3847,8 @@ public class ActionHandler { return; } } - - // جلوگیری از overwrite Path target = uniquePath(saveDir, fileName); - // دانلود روی همان سوکت TelegramClient.mediaBusy.set(true); try { Path saved = TelegramClient.getDownloader() @@ -3873,7 +3868,6 @@ public class ActionHandler { - // نام یکتا اگر فایل موجود است: name.png -> name (1).png private static Path uniquePath(Path dir, String fileName) { Path p = dir.resolve(fileName); if (!Files.exists(p)) return p; @@ -3894,12 +3888,9 @@ public class ActionHandler { } private static String sanitizeFileName(String s) { - // حذف مسیر و کاراکترهای غیرمجاز (برای ویندوز/یونیکس) s = s.replace("\\", "/"); if (s.contains("/")) s = s.substring(s.lastIndexOf('/') + 1); - // کاراکترهای نامعتبر ویندوز: \ / : * ? " < > | s = s.replaceAll("[\\\\/:*?\"<>|]", "_"); - // جلوگیری از parent traversal if (s.equals(".") || s.equals("..") || s.isBlank()) s = "file"; return s; } @@ -4183,7 +4174,6 @@ public class ActionHandler { public void sendMediaMessage(UUID receiverId, String receiverType, String type /* IMAGE/AUDIO */, File file, String caption) { - // اعتبارسنجی ورودی فایل (اگر ورودی از یوزر میاد، قبل از ساخت File کوتیشن‌ها رو حذف کن) if (file == null) { System.out.println("❌ File is null"); return; @@ -4216,21 +4206,19 @@ public class ActionHandler { byte[] headerBytes = header.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8); long contentLen = file.length(); - // صف ACK BlockingQueue q = new LinkedBlockingQueue<>(1); TelegramClient.pendingResponses.put(messageId.toString(), q); try { - // ⛔ مهم: فقط از outBin استفاده کن تا بافرها قاطی نشن - // 1) خط سوئیچ به MEDIA + outBin.write("MEDIA\n".getBytes(java.nio.charset.StandardCharsets.US_ASCII)); outBin.flush(); - // 2) فریم باینری: magic + headerLen + header + contentLen + content + // 2) binary frame: magic + headerLen + header + contentLen + content outBin.writeInt(0x4D444D31); // "MDM1" outBin.writeInt(headerBytes.length); // headerLen (int) outBin.write(headerBytes); // header - outBin.writeLong(contentLen); // contentLen (long) ← مطمئن شو سرور هم Long می‌خونه + outBin.writeLong(contentLen); // contentLen (long) try (InputStream fis = new BufferedInputStream(new FileInputStream(file))) { byte[] buf = new byte[8192]; @@ -4241,7 +4229,6 @@ public class ActionHandler { } outBin.flush(); - // 3) منتظر ACK با تایم‌اوت (فقط یکی!) JSONObject ack = q.poll(20, java.util.concurrent.TimeUnit.SECONDS); if (ack == null) { System.out.println("❌ Media ACK timeout for " + messageId); @@ -4294,7 +4281,6 @@ public class ActionHandler { } private static String accountFolderName() { - // اولویت: username → user_id → profile_name → internal_uuid JSONObject me = Session.currentUser; String acc = me.optString("username", me.optString("user_id", @@ -4304,10 +4290,8 @@ public class ActionHandler { } private static String chatFolderName(ChatEntry chat) { - // پرایوت: اسم طرف مقابل؛ گروه/کانال: اسم چت String name = chat.getName(); if (name == null || name.isBlank()) { - // fallback به displayId یا id name = chat.getDisplayId() != null && !chat.getDisplayId().isBlank() ? chat.getDisplayId() : String.valueOf(chat.getId()); diff --git a/src/main/java/org/to/telegramfinalproject/Client/DownloadsIndex.java b/src/main/java/org/to/telegramfinalproject/Client/DownloadsIndex.java index b3a0f06..50bdc00 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/DownloadsIndex.java +++ b/src/main/java/org/to/telegramfinalproject/Client/DownloadsIndex.java @@ -22,7 +22,6 @@ public final class DownloadsIndex { } - /** مسیر فایل ایندکس مخصوص هر اکانت */ private static Path resolveIndexPath(String accountId) { String os = System.getProperty("os.name", "").toLowerCase(); String home = System.getProperty("user.home"); @@ -40,7 +39,6 @@ public final class DownloadsIndex { return dir.resolve("downloads-index-" + accountId + ".json"); } - /** لود از دیسک (اگر فایل وجود داشته باشد) */ private synchronized void load() { map.clear(); try { @@ -65,7 +63,6 @@ public final class DownloadsIndex { } } - /** ذخیره اتمیک روی دیسک */ private synchronized void save() throws IOException { JSONObject items = new JSONObject(); for (Map.Entry it : map.entrySet()) { @@ -86,12 +83,10 @@ public final class DownloadsIndex { } } - /** ذخیره‌ی بی‌سر‌وصدا */ public void saveQuietly() { try { save(); } catch (Exception ignored) {} } - /** اگر قبلاً دانلود شده و فایلش هست، مسیر را برمی‌گرداند؛ وگرنه رکورد کهنه پاک می‌شود. */ public Path find(UUID mediaKey) { Entry e = map.get(mediaKey); if (e == null) return null; @@ -102,13 +97,11 @@ public final class DownloadsIndex { return null; } - /** بعد از دانلود موفق */ public void put(UUID mediaKey, Path path, long size) { map.put(mediaKey, new Entry(path.toString(), size, System.currentTimeMillis())); saveQuietly(); } - /** اختیاری */ public void remove(UUID mediaKey) { map.remove(mediaKey); saveQuietly(); diff --git a/src/main/java/org/to/telegramfinalproject/Client/SocketMediaDownloader.java b/src/main/java/org/to/telegramfinalproject/Client/SocketMediaDownloader.java index ee72ed2..4a43d89 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/SocketMediaDownloader.java +++ b/src/main/java/org/to/telegramfinalproject/Client/SocketMediaDownloader.java @@ -18,11 +18,9 @@ public final class SocketMediaDownloader { public java.nio.file.Path download(java.util.UUID mediaKey, java.nio.file.Path saveDir, String fileNameHint) throws Exception { - // 1) سوییچ مود با PrintWriter outText.print("MEDIA_DL\n"); outText.flush(); - // 2) هدر باینری درخواست org.json.JSONObject req = new org.json.JSONObject() .put("op","download") .put("media_key", mediaKey.toString()) @@ -34,7 +32,6 @@ public final class SocketMediaDownloader { outBin.write(hb); outBin.flush(); - // 3) پاسخ int magic = inBin.readInt(); if (magic != MAGIC_DL) throw new java.io.IOException("bad magic"); diff --git a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java index d29953d..bc50edd 100644 --- a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java @@ -2681,7 +2681,7 @@ public class ClientHandler implements Runnable { if (len > 0 && sb.charAt(len - 1) == '\r') sb.setLength(len - 1); return sb.toString(); } - sb.append((char) b); // برای کنترل‌لاین‌های ASCII/UTF-8 OK + sb.append((char) b); } } @@ -2853,7 +2853,6 @@ public class ClientHandler implements Runnable { 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".equals(messageType) ? "images" : "audios"; @@ -2865,7 +2864,6 @@ public class ClientHandler implements Runnable { 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; @@ -2881,13 +2879,13 @@ public class ClientHandler implements Runnable { long fileSize = java.nio.file.Files.size(target); - String storagePath = target.toString(); // فقط سرور استفاده کنه - String fileUrl = "/" + subdir.replace('\\','/') + "/" + storedName; // اختیاری/نمایشی (HTTP لازم نیست) + String storagePath = target.toString(); + String fileUrl = "/" + subdir.replace('\\','/') + "/" + storedName; String mt = messageType; // "IMAGE" یا "AUDIO" int safeWidth = ("IMAGE".equals(mt) && width != null) ? width : 0; int safeHeight = ("IMAGE".equals(mt) && height != null) ? height : 0; FileAttachment att = new FileAttachment(); - att.setFileUrl(fileUrl); // اختیاری + att.setFileUrl(fileUrl); att.setFileType(messageType); // IMAGE/AUDIO att.setFileName(fileName); att.setFileSize(fileSize); @@ -2896,8 +2894,7 @@ public class ClientHandler implements Runnable { att.setHeight(safeHeight); att.setDurationSeconds(0); att.setThumbnailUrl(null); - att.setStoragePath(storagePath); // اجباری برای سوکت - // اجازه بده insertAttachmentsTx برایش mediaKey و attachmentId بسازد + att.setStoragePath(storagePath); java.util.List atts = java.util.List.of(att); boolean ok = MessageDatabase.saveMessageWithOptionalAttachments( @@ -2914,18 +2911,17 @@ public class ClientHandler implements Runnable { if (rs.next()) mediaKey = (UUID) rs.getObject(1); } } catch (SQLException sqle) { - // در بدترین حالت بدون media_key ACK می‌دیم، ولی بهتره خطا رو لاگ کنیم sqle.printStackTrace(); } JSONObject ack = new JSONObject() .put("status", ok ? "success" : "error") .put("message_id", messageId.toString()) - .put("media_key", mediaKey != null ? mediaKey.toString() : JSONObject.NULL) // برای دانلود سوکتی + .put("media_key", mediaKey != null ? mediaKey.toString() : JSONObject.NULL) .put("file_name", fileName) .put("file_size", fileSize) .put("mime_type", mimeType) - .put("display_path", fileUrl); // صرفاً نمایشی + .put("display_path", fileUrl); out.println(ack.toString()); out.flush(); @@ -3026,7 +3022,6 @@ public class ClientHandler implements Runnable { logf("MediaRow: chatType=%s chatId=%s sender=%s receiver=%s storage=%s", mr.chatType, mr.chatId, mr.senderId, mr.receiverId, mr.storagePath); - // تست مستقیم دیتابیس (موقت برای دیباگ) try (java.sql.Connection c = ConnectionDb.connect(); java.sql.PreparedStatement st = c.prepareStatement( "SELECT 1 FROM channel_subscribers WHERE channel_id = ? AND user_id = ? LIMIT 1")) { @@ -3105,7 +3100,6 @@ public class ClientHandler implements Runnable { } 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(); @@ -3114,25 +3108,22 @@ public class ClientHandler implements Runnable { 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"; +// if (m.equals("video/mp4")) return ".mp4"; +// if (m.equals("video/webm")) return ".webm"; // fallback - if (m.startsWith("image/")) return ""; // بگذار بدون اکستنشن ذخیره شود + if (m.startsWith("image/")) return ""; if (m.startsWith("audio/")) return ""; if (m.startsWith("video/")) return "";