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