diff --git a/TelegramDownloader/Controllers/FileController.cs b/TelegramDownloader/Controllers/FileController.cs index 560e883..59e0bfe 100644 --- a/TelegramDownloader/Controllers/FileController.cs +++ b/TelegramDownloader/Controllers/FileController.cs @@ -9,13 +9,16 @@ using Syncfusion.Blazor.Inputs; using Syncfusion.EJ2.FileManager.Base; using Syncfusion.EJ2.FileManager.PhysicalFileProvider; +using Syncfusion.EJ2.Notifications; using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; +using System.Linq; using System.Net; using System.Net.Http.Headers; using System.Runtime.Serialization.Formatters.Binary; +using System.Web; using System.Xml.Linq; using TelegramDownloader.Data; using TelegramDownloader.Data.db; @@ -234,7 +237,7 @@ public async Task GetImage(string path) } [Route("GetFile/{id}")] - public async Task GetFile(string id, string? idChannel, string? idFile ) + public async Task GetFile(string id, string? idChannel, string? idFile) { var fileName = id; var mimeType = FileService.getMimeType(id.Split(".").Last()); @@ -242,7 +245,7 @@ public async Task GetFile(string id, string? idChannel, string? i if ( file == null ) { // HttpResponseMessage fullResponse = new HttpResponseMessage(HttpStatusCode.OK); // Request.CreateResponse(HttpStatusCode.OK); - Message idM = await _ts.getMessageFile(idChannel, Convert.ToInt32(idFile)); + TL.Message idM = await _ts.getMessageFile(idChannel, Convert.ToInt32(idFile)); ChatMessages cm = new ChatMessages(); cm.message = idM; file = new FileStream(System.IO.Path.Combine(FileService.TEMPDIR, "_temp", $"{idChannel}-{idFile}-{id}"), FileMode.Create, FileAccess.ReadWrite); @@ -253,6 +256,8 @@ public async Task GetFile(string id, string? idChannel, string? i await _ts.DownloadFileAndReturn(cm, file, model: dm); file.Position = 0; } + var request = HttpContext.Request; + var rangeHeader = request.Headers["Range"].ToString(); return new FileStreamResult(file, mimeType) { @@ -260,6 +265,231 @@ public async Task GetFile(string id, string? idChannel, string? i EnableRangeProcessing = true }; + } + + [Route("GetFileStream/{idChannel}/{idFile}/{name}")] + public async Task GetFileStream(string idChannel, string idFile, string name) + { + var fileName = name; + var mimeType = FileService.getMimeType(name.Split(".").Last()); + + var request = HttpContext.Request; + var rangeHeader = request.Headers["Range"].ToString(); + + var file = await _fs.getItemById(idChannel, idFile); + + TL.Message idM = await _ts.getMessageFile(idChannel, file.MessageId ?? file.ListMessageId.FirstOrDefault()); + + long totalLength = 0; // (await _fs.getItemById(idChannel, idFile)).Size; + + if(idM.media is MessageMediaDocument { document: Document document }) + { + totalLength = document.size; + } + + long from = 0; + long initialFrom = 0; + long to = 0; + + if (!string.IsNullOrEmpty(rangeHeader) && rangeHeader.StartsWith("bytes=")) + { + var range = rangeHeader.Replace("bytes=", "").Split('-'); + from = long.Parse(range[0]); + initialFrom = from; + if (range.Length > 1 && !string.IsNullOrEmpty(range[1])) + to = long.Parse(range[1]); + } + + if (from > 0) + { + from = (from / 524288) * 524288; + } + + Console.WriteLine("Fom:" + from); + + if (to == 0) + if (string.IsNullOrEmpty(rangeHeader) || from == 0) + to = (12 * 524288) + from; + else + to = (5 * 524288) + from; + else + to = ((to + 524288) / 524288) * 524288; + + if (to > totalLength) + { + to = totalLength; + } + + if (totalLength == initialFrom) + { + Response.StatusCode = 416; // Range Not Satisfiable + Response.Headers["Content-Range"] = $"bytes */{totalLength}"; + return new EmptyResult(); + } + + long length = to - from; + //Console.WriteLine("To length: " + to); + //Console.WriteLine("future download length: " + length); + + byte[] data = await _ts.DownloadFileStream(idM, from, (int)length); + + //Console.WriteLine("Total download length: " + data.Length); + + long skipedBytes = initialFrom - from - (length - data.Length); + + if (skipedBytes < 0) skipedBytes = 0; + + if (skipedBytes > data.Length) + return StatusCode(500, "No hay suficientes bytes en el bloque descargado"); + + long dataLength = data.Length - skipedBytes; + Response.ContentLength = dataLength; //(dataLength + initialFrom) >= totalLength ? totalLength - initialFrom : dataLength; + // Response.StatusCode = (int)HttpStatusCode.PartialContent; // 206 + Response.StatusCode = StatusCodes.Status206PartialContent; // StatusCodes.Status206PartialContent; + Response.ContentType = mimeType; + Response.Headers["Content-Disposition"] = $"inline; filename=\"{HttpUtility.UrlEncode(fileName)}\""; + Response.Headers.Add("Content-Range", $"bytes {(initialFrom >= totalLength ? totalLength - 1 : initialFrom)}-{(initialFrom >= totalLength ? totalLength - 1 : initialFrom + Response.ContentLength - 1)}/{totalLength}"); + Response.Headers.Add("Accept-Ranges", "bytes"); + + //if (Request.Headers.ContainsKey("Range")) + //{ + // Console.WriteLine("Range header recibido:"); + // Console.WriteLine(Request.Headers["Range"]); + //} + + //foreach (var header in Response.Headers) + //{ + // Console.WriteLine($"{header.Key}: {header.Value}"); + //} + + + // Console.WriteLine("Skiped bytes: " + skipedBytes); + + var stream = new MemoryStream(data, (int)skipedBytes, (int)Response.ContentLength); + stream.Position = 0; + + // Console.WriteLine("Real Data length: " + stream.Length); + + // Console.WriteLine("---------------------------------------------------"); + + var cancellationToken = HttpContext.RequestAborted; + + try + { + await stream.CopyToAsync(Response.Body, 64 * 1024, cancellationToken); + await Response.Body.FlushAsync(cancellationToken); + + return new EmptyResult(); + } + catch (OperationCanceledException) + { + Console.WriteLine("❌ El cliente cerró la conexión."); + } + + return new EmptyResult(); + + } + + [Route("GetFileStream2/{idChannel}/{idFile}/{name}")] + public async Task GetFileStream2(string idChannel, string idFile, string name) + { + var fileName = name; + var mimeType = FileService.getMimeType(name.Split(".").Last()); + + var request = HttpContext.Request; + var rangeHeader = request.Headers["Range"].ToString(); + + var file = await _fs.getItemById(idChannel, idFile); + + // HttpResponseMessage fullResponse = new HttpResponseMessage(HttpStatusCode.OK); // Request.CreateResponse(HttpStatusCode.OK); + TL.Message idM = await _ts.getMessageFile(idChannel, file.MessageId ?? file.ListMessageId.FirstOrDefault()); + //byte[] data = await _ts.DownloadFileStream(idM, 0, 512); + //var stream = new MemoryStream(data); + + // Supón que puedes obtener el tamaño total del archivo remoto + long totalLength = (await _fs.getItemById(idChannel, idFile)).Size; + + long from = 0; + long initialFrom = 0; + long to = 0; + + + + if (!string.IsNullOrEmpty(rangeHeader) && rangeHeader.StartsWith("bytes=")) + { + var range = rangeHeader.Replace("bytes=", "").Split('-'); + from = long.Parse(range[0]); + initialFrom = from; + if (range.Length > 1 && !string.IsNullOrEmpty(range[1])) + to = long.Parse(range[1]); + } + + if (from > 0) + { + from = (from / 524288) * 524288; + } + + if (to == 0) + to = (25 * 524288) + from; + else + to = ((to + 524288) / 524288) * 524288; + + if (to > totalLength) + { + to = totalLength - 1; + } + + long length = to - from; + + byte[] data = await _ts.DownloadFileStream(idM, from, (int)length); + + long skipedBytes = initialFrom - from; // (data.Length + initialFrom) >= totalLength ? data.Length - (totalLength - initialFrom) : initialFrom - from; + + if (skipedBytes < 0) skipedBytes = 0; + + if (skipedBytes >= data.Length) + return StatusCode(500, "No hay suficientes bytes en el bloque descargado"); + + long dataLength = data.Length - skipedBytes; + Response.ContentLength = (dataLength + initialFrom) >= totalLength ? totalLength - initialFrom : dataLength; + // Response.StatusCode = (int)HttpStatusCode.PartialContent; // 206 + Response.StatusCode = StatusCodes.Status206PartialContent; + Response.ContentType = mimeType; + Response.Headers.Add("Content-Range", $"bytes {initialFrom}-{(initialFrom + Response.ContentLength - 1)}/{totalLength}"); + Response.Headers.Add("Accept-Ranges", "bytes"); + + if (Request.Headers.ContainsKey("Range")) + { + Console.WriteLine("Range header recibido:"); + Console.WriteLine(Request.Headers["Range"]); + } + + foreach (var header in Response.Headers) + { + Console.WriteLine($"{header.Key}: {header.Value}"); + } + + + + + var stream = new MemoryStream(data, (int)skipedBytes, (int)Response.ContentLength); + + Console.WriteLine("Real Data length: " + stream.Length); + + Console.WriteLine("---------------------------------------------------"); + + //return new FileStreamResult(stream, mimeType); + var cancellationToken = HttpContext.RequestAborted; + + await stream.CopyToAsync(Response.Body, 64 * 1024, cancellationToken); + await Response.Body.FlushAsync(cancellationToken); + + return new EmptyResult(); + // return File(stream, mimeType, enableRangeProcessing: false); + //return new FileStreamResult(stream, mimeType) + //{ + // EnableRangeProcessing = false + //}; } diff --git a/TelegramDownloader/Data/FileService.cs b/TelegramDownloader/Data/FileService.cs index eae4b4a..94c5b67 100644 --- a/TelegramDownloader/Data/FileService.cs +++ b/TelegramDownloader/Data/FileService.cs @@ -117,7 +117,7 @@ public class FileService : IFileService {"mid", "audio/midi"}, {"midi", "audio/midi"}, {"mif", "application/vnd.mif"}, - {"mkv", "video/webm" }, + {"mkv", "video/x-matroska" }, {"mov", "video/quicktime"}, {"movie", "video/x-sgi-movie"}, {"mp2", "audio/mpeg"}, diff --git a/TelegramDownloader/Data/ITelegramService.cs b/TelegramDownloader/Data/ITelegramService.cs index f636d87..71fbdf4 100644 --- a/TelegramDownloader/Data/ITelegramService.cs +++ b/TelegramDownloader/Data/ITelegramService.cs @@ -1,4 +1,5 @@ -using TelegramDownloader.Models; +using BlazorBootstrap; +using TelegramDownloader.Models; using TL; using WTelegram; @@ -16,17 +17,21 @@ public interface ITelegramService Task joinChatInvitationHash(string? hash); Task CallQrGenerator(Action func, CancellationToken ct, bool logoutFirst = false); Task DownloadFile(ChatMessages message, string fileName = null, string folder = null, DownloadModel model = null, bool shouldAddToList = false); + Task DownloadFileStream(Message message, long offset, int limit); Task DownloadFileAndReturn(ChatMessages message, Stream ms = null, string fileName = null, string folder = null, DownloadModel model = null); Task> GetFouriteChannels(bool mustRefresh = true); Task AddFavouriteChannel(long id); Task RemoveFavouriteChannel(long id); Task> getAllChats(); Task> getAllSavedChats(); - Task> getAllMessages(long id); + Task> getAllMessages(long id, Boolean onlyFiles = false); + Task> getPaginatedMessages(long id, int page, int size, Boolean onlyFiles = false); + Task> getAllMediaMessages(long id, Boolean onlyFiles = false); Task> getChatHistory(long id, int limit = 30, int addOffset = 0); string getChatName(long id); Task getMessageFile(string chatId, int idMessage); Task getPhotoThumb(ChatBase chat); + Task downloadPhotoThumb(Photo thumb); Task logOff(); Task sendVerificationCode(string vc); Task uploadFile(string chatId, Stream file, string fileName, string mimeType = null, UploadModel um = null, string caption = null); diff --git a/TelegramDownloader/Data/TelegramService.cs b/TelegramDownloader/Data/TelegramService.cs index a500e8c..92f8c92 100644 --- a/TelegramDownloader/Data/TelegramService.cs +++ b/TelegramDownloader/Data/TelegramService.cs @@ -1,8 +1,19 @@ -using Microsoft.AspNetCore.Components; +using BlazorBootstrap; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using Syncfusion.Blazor.Inputs; +using Syncfusion.Blazor.Kanban.Internal; +using Syncfusion.Blazor.Sparkline.Internal; +using System.Collections.Generic; +using System.Reflection.Metadata; +using System.Threading.Tasks; using TelegramDownloader.Data.db; using TelegramDownloader.Models; using TelegramDownloader.Services; using TL; +using TL.Layer23; +using TL.Methods; +using WTelegram; namespace TelegramDownloader.Data { @@ -10,6 +21,7 @@ public class TelegramService : ITelegramService { public static bool isPremium = false; public static int splitSizeGB = 2; + private const int FILESPLITSIZE = 524288; // 512 * 1024; private TransactionInfoService _tis { get; set; } private IDbService _db { get; set; } private static WTelegram.Client client = null; @@ -317,7 +329,180 @@ public async Task getMessageFile(string chatId, int idMessage) //return m; } - public async Task> getAllMessages(long id) + public async Task> getAllMessages(long id, Boolean onlyFiles = false) + { + List cm = new List(); + InputPeer peer = chats.chats[id]; + for (int offset_id = 0; ;) + { + var messages = await client.Messages_GetHistory(peer, offset_id); + if (messages.Messages.Length == 0) break; + foreach (MessageBase msgBase in messages.Messages) + { + if (msgBase is Message msg) + { + ChatMessages cm2 = new ChatMessages(); + cm2.message = msg; + cm2.isDocument = false; + if (msg.media is MessageMediaDocument { document: TL.Document document }) + { + cm2.isDocument = true; + } + if (onlyFiles) + { + if (cm2.isDocument) + cm.Add(cm2); + } else + { + cm2.htmlMessage = client.EntitiesToHtml(msg.message, msg.entities); + cm2.user = messages.UserOrChat(msg.From ?? msg.Peer); + cm.Add(cm2); + } + + + } + } + offset_id = messages.Messages[^1].ID; + } + return cm; + } + + public async Task> getAllMediaMessages(long id, Boolean onlyFiles = false) + { + List cm = new List(); + InputPeer peer = chats.chats[id]; + int size = 100; + int page = 1; + + var messages = await client.Messages_GetHistory(peer, add_offset: page -1, limit: size); + if (messages.Messages.Length == 0) return await Task.FromResult(cm); + foreach (MessageBase msgBase in messages.Messages) + { + if (msgBase is Message msg) + { + ChatMessages cm2 = new ChatMessages(); + cm2.message = msg; + cm2.isDocument = false; + if (msg.media is MessageMediaDocument { document: TL.Document document }) + { + cm2.isDocument = true; + } + if (onlyFiles) + { + if (cm2.isDocument) + cm.Add(cm2); + } + else + { + cm2.htmlMessage = client.EntitiesToHtml(msg.message, msg.entities); + cm2.user = messages.UserOrChat(msg.From ?? msg.Peer); + cm.Add(cm2); + } + } + } + + int totalMessages = messages.Count; + int gettedMessages = messages.Messages.Length; + int maxParalellTasks = 50; + int totalTasks = 0; + page++; + List>> tasks = new List>>(); + + while (gettedMessages < totalMessages) + { + int sizeGetted = gettedMessages + size >= totalMessages ? totalMessages - gettedMessages : size; + + tasks.Add(getPaginatedMessagesAsync(peer, page, sizeGetted, onlyFiles)); + page++; + totalTasks++; + gettedMessages += sizeGetted; + + if (totalTasks == maxParalellTasks || gettedMessages == totalMessages) + { + var results = await Task.WhenAll(tasks); + totalTasks = 0; + + foreach (var result in results) + { + cm.AddRange(result); + } + } + } + + return await Task.FromResult(cm); + } + + private async Task> getPaginatedMessagesAsync(InputPeer peer, int page, int size, Boolean onlyFiles = false) + { + List cm = new List(); + var messages = await client.Messages_GetHistory(peer, add_offset: (page - 1) * 100, limit: size); + if (messages.Messages.Length == 0) return cm; + foreach (MessageBase msgBase in messages.Messages) + { + if (msgBase is Message msg) + { + ChatMessages cm2 = new ChatMessages(); + cm2.message = msg; + cm2.isDocument = false; + if (msg.media is MessageMediaDocument { document: TL.Document document }) + { + cm2.isDocument = true; + } + if (onlyFiles) + { + if (cm2.isDocument) + cm.Add(cm2); + } + else + { + cm2.htmlMessage = client.EntitiesToHtml(msg.message, msg.entities); + cm2.user = messages.UserOrChat(msg.From ?? msg.Peer); + cm.Add(cm2); + } + + + } + } + return cm; + } + + public async Task> getPaginatedMessages(long id, int page, int size, Boolean onlyFiles = false) + { + List cm = new List(); + InputPeer peer = chats.chats[id]; + + var messages = await client.Messages_GetHistory(peer, add_offset: (page - 1) * 100, limit: size); + if (messages.Messages.Length == 0) return await Task.FromResult(new GridDataProviderResult { Data = cm, TotalCount = messages.Count }); + foreach (MessageBase msgBase in messages.Messages) + { + if (msgBase is Message msg) + { + ChatMessages cm2 = new ChatMessages(); + cm2.message = msg; + cm2.isDocument = false; + if (msg.media is MessageMediaDocument { document: TL.Document document }) + { + cm2.isDocument = true; + } + if (onlyFiles) + { + if (cm2.isDocument) + cm.Add(cm2); + } + else + { + cm2.htmlMessage = client.EntitiesToHtml(msg.message, msg.entities); + cm2.user = messages.UserOrChat(msg.From ?? msg.Peer); + cm.Add(cm2); + } + + + } + } + return await Task.FromResult(new GridDataProviderResult { Data = cm, TotalCount = messages.Count }); + } + + public async Task> getAllFileMessages(long id) { List cm = new List(); InputPeer peer = chats.chats[id]; @@ -335,7 +520,7 @@ public async Task> getAllMessages(long id) cm2.user = messages.UserOrChat(msg.From ?? msg.Peer); cm2.isDocument = false; - if (msg.media is MessageMediaDocument { document: Document document }) + if (msg.media is MessageMediaDocument { document: TL.Document document }) { cm2.isDocument = true; } @@ -371,7 +556,7 @@ public async Task> getChatHistory(long id, int limit = 30, in cm2.user = mess.UserOrChat(mb.From ?? mb.Peer); cm2.isDocument = false; - if (msg.media is MessageMediaDocument { document: Document document }) + if (msg.media is MessageMediaDocument { document: TL.Document document }) { cm2.isDocument = true; } @@ -395,6 +580,17 @@ public async Task getPhotoThumb(ChatBase chat) } + public async Task downloadPhotoThumb(Photo thumb) + { + MemoryStream ms = new MemoryStream(); + if (await client.DownloadFileAsync(thumb, ms) != 0) + { + return $"data:image/jpeg;base64,{Convert.ToBase64String(ms.ToArray())}"; + }; + return ""; + + } + public async Task AddFavouriteChannel(long id) { if (!GeneralConfigStatic.config.FavouriteChannels.Contains(id)) @@ -414,6 +610,84 @@ public async Task RemoveFavouriteChannel(long id) await GetFouriteChannels(); } } + public async Task DownloadFileStream(Message message, long offset, int limit) + { + int totalLimit = limit; + long currentOffset = offset; + Byte[] response; + if (message is Message msg && msg.media is MessageMediaDocument doc) + { + try + { + using (var memoryStream = new MemoryStream()) + { + while (totalLimit > 0) + { + int totalDownloadBytes = FILESPLITSIZE; + if (totalLimit >= FILESPLITSIZE) + { + totalDownloadBytes = FILESPLITSIZE; + + } + //else if (totalLimit >= 4096) + //{ + // // Busca el mayor múltiplo de 4096 menor o igual a totalLimit + // totalDownloadBytes = (totalLimit / 4096) * 4096; + //} + else + { + // Último trozo, menor de 4096 + totalDownloadBytes = FILESPLITSIZE; // totalLimit; + //totalDownloadBytes = totalLimit; + } + + InputDocument inputFile = doc.document; + var location = new InputDocumentFileLocation + { + id = inputFile.id, + access_hash = inputFile.access_hash, + file_reference = inputFile.file_reference, + thumb_size = "" + }; + + //var file = await client.Invoke(new Upload_GetFile + //{ + // location = new InputDocumentFileLocation + // { + // id = inputFile.id, + // access_hash = inputFile.access_hash, + // file_reference = inputFile.file_reference, + // thumb_size = "" + // }, + // offset = currentOffset, + // limit = totalDownloadBytes + //}); + + var file = await client.Upload_GetFile(location, currentOffset, limit: totalDownloadBytes); + + if (file is Upload_File uploadFile) + { + //uploadFile.WriteTL(new BinaryWriter(memoryStream)); + var fileBytes = uploadFile.bytes; + memoryStream.Write(fileBytes, 0, fileBytes.Length); + currentOffset += (totalDownloadBytes); + totalLimit -= (totalDownloadBytes); + continue; + } + throw new InvalidOperationException("Unexpected file type returned."); + } + + return memoryStream.ToArray(); + } + } + catch (Exception e) + { + throw new InvalidOperationException("Unexpected file type returned."); + } + } + + throw new ArgumentException("Invalid message or media type."); + } public async Task DownloadFileAndReturn(ChatMessages message, Stream ms = null, string fileName = null, string folder = null, DownloadModel model = null) { @@ -426,7 +700,7 @@ public async Task DownloadFileAndReturn(ChatMessages message, Stream ms model.m = message; model.channel = message.user; - if (message.message.media is MessageMediaDocument { document: Document document }) + if (message.message.media is MessageMediaDocument { document: TL.Document document }) { model._transmitted = 0; @@ -441,6 +715,7 @@ public async Task DownloadFileAndReturn(ChatMessages message, Stream ms MemoryStream dest = new MemoryStream(); // using var dest = new FileStream($"{Path.Combine(folder != null ? folder : Path.Combine(Environment.CurrentDirectory, "download"), filename)}", FileMode.Create, FileAccess.Write); await client.DownloadFileAsync(document, ms ?? dest, null, model.ProgressCallback); + return ms ?? dest; // fileStream.CopyTo(dest); Console.WriteLine("Download finished"); @@ -453,7 +728,7 @@ public async Task DownloadFileAndReturn(ChatMessages message, Stream ms Console.WriteLine("Downloading " + filename); MemoryStream dest = new MemoryStream(); // using var dest = new FileStream($"{Path.Combine(Environment.CurrentDirectory!, "wwwroot", "img", "telegram", filename)}", FileMode.Create, FileAccess.Write); - var type = await client.DownloadFileAsync(photo, ms ?? dest, null, model.ProgressCallback); + var type = await client.DownloadFileAsync(photo, ms ?? dest, (PhotoSizeBase)null, model.ProgressCallback); dest.Close(); // necessary for the renaming Console.WriteLine("Download finished"); //if (type is not Storage_FileType.unknown and not Storage_FileType.partial) @@ -479,7 +754,7 @@ public async Task DownloadFile(ChatMessages message, string fileName = n model.m = message; model.channel = message.user; - if (message.message.media is MessageMediaDocument { document: Document document }) + if (message.message.media is MessageMediaDocument { document: TL.Document document }) { model._transmitted = 0; diff --git a/TelegramDownloader/Data/db/DbService.cs b/TelegramDownloader/Data/db/DbService.cs index cc37686..85f6086 100644 --- a/TelegramDownloader/Data/db/DbService.cs +++ b/TelegramDownloader/Data/db/DbService.cs @@ -333,7 +333,7 @@ public async Task> getAllFilesInDirectoryPath2(string { if (collectionName == null) collectionName = "directory"; - var result = await (await getDatabase(dbName).GetCollection(collectionName).FindAsync(Builders.Filter.Where(x => x.FilePath + "/" == path || x.FilterPath == path))).ToListAsync(); + var result = await (await getDatabase(dbName).GetCollection(collectionName).FindAsync(Builders.Filter.Where(x => x.FilterId == path || x.FilePath + "/" == path || x.FilterPath == path))).ToListAsync(); return result; } diff --git a/TelegramDownloader/Models/GeneralConfig.cs b/TelegramDownloader/Models/GeneralConfig.cs index 4bd4374..9b04aca 100644 --- a/TelegramDownloader/Models/GeneralConfig.cs +++ b/TelegramDownloader/Models/GeneralConfig.cs @@ -74,6 +74,7 @@ public class GeneralConfig public bool CheckHash { get; set; } = false; public bool ShouldShowCaptionPath { get; set; } = false; public bool ShouldShowLogInTerminal { get; set; } = false; + public bool ShouldShowPaginatedFileChannel { get; set; } = false; public List FavouriteChannels { get; set; } = new List(); } diff --git a/TelegramDownloader/Pages/Config.razor b/TelegramDownloader/Pages/Config.razor index 1ee4a3b..0390990 100644 --- a/TelegramDownloader/Pages/Config.razor +++ b/TelegramDownloader/Pages/Config.razor @@ -53,6 +53,15 @@ + + +
+
+ + +
+ +
@@ -71,7 +80,6 @@
-
@if (TelegramService.isPremium) diff --git a/TelegramDownloader/Pages/FileGrid.razor b/TelegramDownloader/Pages/FileGrid.razor new file mode 100644 index 0000000..4f01531 --- /dev/null +++ b/TelegramDownloader/Pages/FileGrid.razor @@ -0,0 +1,117 @@ +@page "/filegrid/{id}" + +@using TL +@using TelegramDownloader.Data; +@using TelegramDownloader.Models; +@using TelegramDownloader.Services; + +@inject ITelegramService ts; +@inject PreloadService PreloadService; + +

File Grid

+ +@if (SelectedItems.Any()) +{ + +} + + + + + + @context.message.id + + + @context.message.message + + + @context.message.Date.ToString("dd/MM/yyyy HH:mm:ss") + + + @(context.message.edit_date.Year > 1900 + ? context.message.edit_date.ToString("dd/MM/yyyy HH:mm:ss") + : "") + + + @if (context.message.media is MessageMediaDocument { document: Document document }) + { + @document.Filename + } + + + @if (context.message.media is MessageMediaDocument { document: Document document }) + { + @HelperService.SizeSuffix(document.size) + } + + + @if (context.message.media is MessageMediaDocument { document: Document document }) + { + @document.mime_type + } + + + @context.videoThumb + @if (context.message.media is MessageMediaPhoto { photo: Photo photo }) + { + + } else { + + } + + + + +
+ Selected Items Count: @SelectedItems.Count +
+ + + + + +@code { + [Parameter] + public string id { get; set; } + public List messages = default!; + private int pageSize = 100; + + private Modals.DowloadFromTelegram Modal { get; set; } + private HashSet SelectedItems { get; set; } = new(); + + private async Task> ChatsDataProvider(GridDataProviderRequest request) + { + if (messages is null) + { + PreloadService.Show(SpinnerColor.Light, "Loading data..."); + messages = await ts.getAllMediaMessages(Convert.ToInt64(id), true); + PreloadService.Hide(); + } + + return await Task.FromResult(request.ApplyTo(messages)); + } + + private void GetSelectedItems() + { + Modal.chatMessages = SelectedItems.ToList(); + Modal.isDownloadingChatMessages = true; + Modal.Open(); + // Aquí puedes manejar los elementos seleccionados + // Console.WriteLine($"Elementos seleccionados: {SelectedItems.Count}"); + // foreach (var item in SelectedItems) + // { + // Console.WriteLine($"Id: {item.message.id}, Name: {item.message.message}"); + // } + } +} diff --git a/TelegramDownloader/Pages/Modals/DowloadFromTelegram.razor b/TelegramDownloader/Pages/Modals/DowloadFromTelegram.razor index 38938b6..7a13315 100644 --- a/TelegramDownloader/Pages/Modals/DowloadFromTelegram.razor +++ b/TelegramDownloader/Pages/Modals/DowloadFromTelegram.razor @@ -45,7 +45,10 @@ [Parameter] public BsonSharedInfoModel bsi { get; set; } public string filePath { get; set; } + public List fileList { get; set; } + public List chatMessages { get; set; } + public bool isDownloadingChatMessages { get; set; } = false; public string filename = ""; public string size = ""; @@ -79,6 +82,12 @@ private async Task Submit() { + if (isDownloadingChatMessages) + { + chatMessages.ForEach(message => fs.DownloadFileFromChat(message, null, ddtree.selectedNode == null ? null : ddtree.selectedNode.FirstOrDefault(), null)); + Close(); + return; + } // ts. if (isShare) fs.downloadFile(DbService.SHARED_DB_NAME, fileList.ToList(), ddtree.selectedNode == null ? null : ddtree.selectedNode.FirstOrDefault(), bsi.CollectionId, bsi.ChannelId); diff --git a/TelegramDownloader/Pages/Partials/impl/FileManagerImpl.razor b/TelegramDownloader/Pages/Partials/impl/FileManagerImpl.razor index e7504b8..4833273 100644 --- a/TelegramDownloader/Pages/Partials/impl/FileManagerImpl.razor +++ b/TelegramDownloader/Pages/Partials/impl/FileManagerImpl.razor @@ -6,6 +6,8 @@ @using TelegramDownloader.Data @using TelegramDownloader.Data.db @using TelegramDownloader.Models +@using TelegramDownloader.Pages.Modals.InfoModals +@using TelegramDownloader.Pages.Modals @using TelegramDownloader.Pages.Partials @inject IFileService fs @inject ITelegramService ts @@ -18,18 +20,18 @@ + ToolbarItemClicked="toolBarClicked" + ItemsMoving="ItemsMovingAsync" + ItemRenaming="ItemRenamingAsync" + Searching="SearchingAsync" + OnFileOpen="fileOpen" + FileSelection="FileSelectionAsync" + FileSelected="FileSelectedAsync" + OnRead="OnReadAsync" + FolderCreating="FolderCreatingAsync" + BeforeDownload="BeforeDownload" + ItemsDeleting="ItemsDeletingAsync" + ItemsUploaded="ItemsUploadedAsync"> @@ -37,6 +39,8 @@ + + @@ -53,6 +57,9 @@ public static string[] selectedItems = new string[] { "" }; public static bool downloadToServer = true; LocalFileManager lfm { get; set; } + private VideoPlayerModal videoPlayer { get; set; } = default!; + + private MediaUrlModal mediaUrlModal { get; set; } = default!; public string[] ContextItems = new string[] { "Open", "Delete", "Download", "Rename", "Details"}; @@ -68,6 +75,8 @@ new ToolBarItemModel() { Name = "Selection" }, new ToolBarItemModel() { Name = "View" }, new ToolBarItemModel() { Name = "Details" }, + new ToolBarItemModel() { Name = "UrlMedia", Text = "Url Media", TooltipText = "Url Media", PrefixIcon = "bi bi-collection-play-fill", Visible = false } + }; // protected override async Task OnParametersSetAsync() @@ -81,6 +90,7 @@ } + protected override async Task OnInitializedAsync() { if (!isShared) @@ -121,23 +131,24 @@ // args.Response = await FileManagerService.Rename(args.Path, args.File.Name, args.NewName, false, args.ShowFileExtension, args.File); } - public async Task FileOpen(FileOpenEventArgs args) + public async Task fileOpen(FileOpenEventArgs args) { - if (!isShared && args != null && args.FileDetails != null && args.FileDetails.IsFile && new List { ".mp3", ".ogg", ".flac", ".aac", ".wav" }.Contains(args.FileDetails.Type.ToLower())) + if (args != null && args.FileDetails != null && args.FileDetails.IsFile && new List { ".mp3", ".ogg", ".flac", ".aac", ".wav" }.Contains(args.FileDetails.Type.ToLower())) { await playAudio(args); - // string localdir = "/" + FileService.STATICRELATIVELOCALDIR.Replace("\\", "/"); - // string path = Path.Combine(localdir, args.FileDetails.FilterPath.Substring(1).Replace("\\", "/"), args.FileDetails.Name); - // await JSRuntime.InvokeVoidAsync("open", path, "_blank"); + } + else + { + if (args != null && args.FileDetails != null && args.FileDetails.IsFile && new List { ".mov", ".mp4", ".m4v", ".ogv", ".webm", ".flv", ".f4v" }.Contains(args.FileDetails.Type.ToLower())) + { + videoPlayer.ShowModal(getMediaUrl(args.FileDetails.Id, args.FileDetails.Name)); + } } } private async Task playAudio(FileOpenEventArgs args) { - var file = await fs.getItemById(id, args.FileDetails.Id); - string path = MyNavigationManager.BaseUri + "api/file/getfile/" + args.FileDetails.Name + $"?idChannel={id}&idFile={file.MessageId}"; - // string path = new System.Uri((Path.Combine(localdir, args.FileDetails.FilterPath.Substring(1).Replace("\\", "/"), args.FileDetails.Name)).Replace("\\", "/")).AbsoluteUri; - await JSRuntime.InvokeVoidAsync("openAudioPlayerModal", path, FileService.getMimeType(args.FileDetails.Name.Split(".").Last()), args.FileDetails.Name); + await JSRuntime.InvokeVoidAsync("openAudioPlayerModal", getMediaUrl(args.FileDetails.Id, args.FileDetails.Name), null, args.FileDetails.Name); } public async Task SearchingAsync(SearchEventArgs args) @@ -188,6 +199,18 @@ Console.WriteLine(""); } + private async Task ShowMediaURLModal(string idFile, String name) + { + mediaUrlModal.url = getMediaUrl(idFile, name); + await mediaUrlModal.OnShowModalClick(); + } + + private string getMediaUrl(string idFile, String name) + { + string localdir = MyNavigationManager.BaseUri; + return new System.Uri(Path.Combine(localdir, "api/file/GetFileStream", id, idFile, name).Replace("\\", "/")).AbsoluteUri; + } + public async Task toolBarClicked(ToolbarClickEventArgs args) { if (args.Item.Text == "Download To Local") @@ -207,6 +230,10 @@ { MyNavigationManager.NavigateTo("/api/file/share/" + id + $"?bsonId={args.FileDetails.FirstOrDefault().Id}&fileName={args.FileDetails.FirstOrDefault().Name}", true); } + if (args.Item.Text == "Url Media" && args.FileDetails.Count() > 0) + { + await ShowMediaURLModal(args.FileDetails[0].Id, args.FileDetails[0].Name); + } Console.WriteLine(""); } @@ -226,7 +253,17 @@ public async Task FileSelectionAsync(FileSelectionEventArgs args) { - Console.WriteLine(""); + List selectedList = fm.GetSelectedFiles(); + if ((selectedList.Count() + (args.Action == "UnSelect" ? -1 : 1)) == 1) + { + if (args.FileDetails.IsFile) + { + Items.Where(x => x.Name == "UrlMedia").FirstOrDefault().Visible = true; + return; + } + + } + Items.Where(x => x.Name == "UrlMedia").FirstOrDefault().Visible = false; } public async Task FileSelectedAsync(FileSelectEventArgs args) diff --git a/TelegramDownloader/Pages/_Layout.cshtml b/TelegramDownloader/Pages/_Layout.cshtml index 2c703e6..c31aa84 100644 --- a/TelegramDownloader/Pages/_Layout.cshtml +++ b/TelegramDownloader/Pages/_Layout.cshtml @@ -45,7 +45,7 @@ - + diff --git a/TelegramDownloader/Program.cs b/TelegramDownloader/Program.cs index c3c8d15..98433bc 100644 --- a/TelegramDownloader/Program.cs +++ b/TelegramDownloader/Program.cs @@ -33,7 +33,7 @@ var builder = WebApplication.CreateBuilder(args); -Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("MzY0NjIwOUAzMjM4MmUzMDJlMzBZdngxNkEzSjRTQTczaDdlWkxEd1BIeUovNjh1eHByNEg5SkRVZ1lmWHc4PQ=="); +Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("MzgzMTc5MUAzMjM5MmUzMDJlMzAzYjMyMzkzYmw1ZDhSMmlTeTVTMFl0Ky9YaHBpZlRhd0NZS2RuQlVvenpnRVduRHFtZkE9"); builder.Services.AddSyncfusionBlazor(); if (!Directory.Exists(FileService.IMGDIR)) diff --git a/TelegramDownloader/Services/TransactionInfoService.cs b/TelegramDownloader/Services/TransactionInfoService.cs index 73cede0..8f5a46e 100644 --- a/TelegramDownloader/Services/TransactionInfoService.cs +++ b/TelegramDownloader/Services/TransactionInfoService.cs @@ -85,8 +85,8 @@ public void stopTimer() private void OnTimedEvent(Object source, ElapsedEventArgs e) { - _logger.LogInformation("El evento Elapsed se disparó a las {0:HH:mm:ss.fff}", e.SignalTime); - _logger.LogInformation("Upload: {0}, download: {1}", bytesUploaded, bytesDownloaded); + //_logger.LogInformation("El evento Elapsed se disparó a las {0:HH:mm:ss.fff}", e.SignalTime); + //_logger.LogInformation("Upload: {0}, download: {1}", bytesUploaded, bytesDownloaded); if (bytesDownloaded > 0) setDownloadSpeed(HelperService.SizeSuffixPerTime(bytesDownloaded)); if (bytesUploaded > 0) @@ -104,7 +104,6 @@ public async Task addDownloadBytes(long bytes) public async Task addUploadBytes(long bytes) { - _logger.LogInformation("Add bytes to upload {0}", bytes); UploadBytesMutex.WaitOne(); bytesUploaded += bytes; UploadBytesMutex.ReleaseMutex(); @@ -132,7 +131,7 @@ public void setDownloadSpeed(String speed) public void setUploadSpeed(String speed) { - _logger.LogInformation("Set bytes speed upload {0}", speed); + //_logger.LogInformation("Set bytes speed upload {0}", speed); uploadSpeed = speed; TaskEventChanged.Invoke(null, EventArgs.Empty); } diff --git a/TelegramDownloader/Shared/NavMenu.razor b/TelegramDownloader/Shared/NavMenu.razor index 6f5ba76..6993525 100644 --- a/TelegramDownloader/Shared/NavMenu.razor +++ b/TelegramDownloader/Shared/NavMenu.razor @@ -11,7 +11,7 @@ @inject IJSRuntime JS; - + @@ -76,6 +76,12 @@
+ @if (GeneralConfigStatic.config.ShouldShowPaginatedFileChannel) + { + + } @@ -109,6 +115,13 @@
+ @if(GeneralConfigStatic.config.ShouldShowPaginatedFileChannel) + { + + } + @@ -191,7 +204,12 @@
- + @if (GeneralConfigStatic.config.ShouldShowPaginatedFileChannel) + { + + } diff --git a/TelegramDownloader/TelegramDownloader.csproj b/TelegramDownloader/TelegramDownloader.csproj index 1ba72ce..f3d1bac 100644 --- a/TelegramDownloader/TelegramDownloader.csproj +++ b/TelegramDownloader/TelegramDownloader.csproj @@ -13,15 +13,15 @@ - + - + - - - - - + + + + + diff --git a/TelegramDownloader/wwwroot/css/site.css b/TelegramDownloader/wwwroot/css/site.css index 1d7b996..47b4982 100644 --- a/TelegramDownloader/wwwroot/css/site.css +++ b/TelegramDownloader/wwwroot/css/site.css @@ -103,3 +103,6 @@ a, .btn-link { padding-bottom: 5%; } +.download-btn { + margin-bottom: 2% !important; +} \ No newline at end of file