public async Task GetIllustDetail(params int[] ids) { foreach (var id in ids) { var message = await ReplyAsync($"``数据检索中…… Pixiv ID: {id}``"); var detail = await Illust.Get(id); if (detail == null) { await message.ModifyAsync(x => x.Content = $"数据(pid:{id})获取失败,请稍后再试"); } else { var sb = new StringBuilder() .AppendLine(detail.Title) .AppendLine($"Author: {detail.Author}") .AppendLine(detail.Caption) .AppendLine($"Tags: {string.Join(" | ", detail.Tags)}") .AppendLine($"Publish Date: {detail.CreateDate:yyyy-MM-dd HH:mm:ss}") .AppendLine($"Bookmarks: {detail.TotalBookmarks} Comments:{detail.TotalComments} Views:{detail.TotalView}") .Append(detail.Url); await message.ModifyAsync(x => x.Content = sb.ToString()); await SendImage(detail); } } }
protected override async Task DownloadAsync( IList <ImageEntry> entries, Action <double>?onProgress = null, CancellationToken cancellationToken = default) { string filename = $"{Illust.Id}.gif"; var details = await Illust.GetAnimatedDetailAsync(cancellationToken).ConfigureAwait(false); var(relative, absolute) = WithDirectory(filename); using var fs = File.Create(absolute, 8192, FileOptions.Asynchronous); using var mms = new MemoryStream(); using (var response = await details.GetZipAsync(cancellationToken).ConfigureAwait(false)) await ReadAsync(response, mms, onProgress, cancellationToken).ConfigureAwait(false); mms.Seek(0, SeekOrigin.Begin); using (var zipArchive = new ZipArchive(mms)) await GifHelper.ComposeGifAsync(zipArchive, details.Frames.Select(x => (x.File, x.Delay)), fs, cancellationToken) .ConfigureAwait(false); await fs.FlushAsync(cancellationToken).ConfigureAwait(false); entries.Add(new(ImageType.Animated, relative) { PostOrderId = 0 });
public static async void GetIllustDetail(SoraMessage e, int id) { var detail = await Illust.Get(id); if (detail == null) { await e.ReplyToOriginal("数据获取失败,请稍后再试"); } else { ArrayList msg = new(); foreach (var img in detail.Images) { msg.Add(CQCode.CQImage(ImageUrls.ToPixivCat(img.Medium))); } msg.Add(new StringBuilder().AppendLine() .AppendLine(detail.Title) .AppendLine($"Author: {detail.Author}") .AppendLine(detail.Caption) .AppendLine($"Tags: {string.Join(" | ", detail.Tags)}") .AppendLine($"Publish Date: {detail.CreateDate:yyyy-MM-dd hh:mm:ss}") .AppendLine($"Bookmarks: {detail.TotalBookmarks} Comments:{detail.TotalComments} Views:{detail.TotalView}") .Append(detail.Url) .ToString()); await e.Reply(msg.ToArray()); await e.RemoveCoins(5); } }
// Download image test static async Task DownloadImageTest() { Console.Write("Enter the ID of the image to download\n> "); // Error handling try { Stopwatch timer = new Stopwatch(); timer.Start(); Illust result = await Client.ViewIllustAsync(Console.ReadLine()); timer.Stop(); Console.WriteLine("Getting info - {0} milliseconds", timer.Elapsed.TotalMilliseconds); timer.Reset(); string url = result.MetaSinglePage.OriginalImageUrl ?? result.MetaPages[0].ImageUrls.Original; timer.Start(); Stream image = await Client.GetImageAsync(url); using (FileStream file = File.Open(url.Split("/").Last(), FileMode.OpenOrCreate)) { await image.CopyToAsync(file); } timer.Stop(); Console.WriteLine("Downloading - {0} milliseconds", timer.Elapsed.TotalMilliseconds); } catch (HttpRequestException e) { Console.WriteLine(e.Message); } }
public static Task <UgoiraData> GetUgoiraData(this Illust illust) { if (illust.Type != IllustType.Ugoira) { throw new ArgumentException("this illust isn't ugoira", nameof(illust)); } return(PixivClient.GlobalClient.GetUgoiraMetadataAsync(illust.Id)); }
public static void TestIllust(Illust illust) { Console.WriteLine("Illust: "); Console.WriteLine("-------------------------------------------------------------------------------"); Console.WriteLine("Illust ID: {0}", illust.ID.ToString()); Console.WriteLine("Illust title: {0}", illust.Title); Console.WriteLine("Illust type: {0}", illust.Type); Console.WriteLine("Illust medium image url: {0}", illust.ImageUrls.Medium); Console.WriteLine("Illust square medium url: {0}", illust.ImageUrls.SquareMedium); Console.WriteLine("Illust large image url: {0}", illust.ImageUrls.large); Console.WriteLine("Illust caption: {0}", illust.Caption); Console.WriteLine("Illust restrict: {0}", illust.Restrict.ToString()); Console.WriteLine("-------------------------------------------------------------------------------"); TestUser(illust.User); if (illust.Tags.Length != 0) { Console.WriteLine("Illust tag: {0} | Illust translated tag: {1}", illust.Tags[0].Name, illust.Tags[0].TranslatedName); } if (illust.Tools.Length != 0) { Console.WriteLine("Illust tools: {0}", illust.Tools[0]); } Console.WriteLine("Illust creation date: {0}", illust.CreateDate); Console.WriteLine("Illust page count: {0}", illust.PageCount.ToString()); Console.WriteLine("Illust width: {0}", illust.Width.ToString()); Console.WriteLine("Illust height: {0}", illust.Height.ToString()); Console.WriteLine("Illust sanity level: {0}", illust.SanityLevel.ToString()); Console.WriteLine("Illust x restrict: {0}", illust.XRestrict.ToString()); Console.WriteLine("-------------------------------------------------------------------------------"); Console.WriteLine("Series:"); Console.WriteLine("-------------------------------------------------------------------------------"); if (illust.Series != null) { Console.WriteLine("Series ID: {0}", illust.Series.ID); Console.WriteLine("Series title: {0}", illust.Series.Title); } else { Console.WriteLine("Not part of a series"); } Console.WriteLine("-------------------------------------------------------------------------------"); if (illust.MetaSinglePage != null) { Console.WriteLine("Page url: {0}", illust.MetaSinglePage.OriginalImageUrl); } else if (illust.MetaSinglePage == null) { Console.WriteLine("First page url: {0}", illust.MetaPages[0].ImageUrls.Original); } Console.WriteLine("Illust view count: {0}", illust.TotalView.ToString()); Console.WriteLine("Illust bookmarks: {0}", illust.TotalBookmarks.ToString()); Console.WriteLine("Is bookmarked: {0}", illust.IsBookmarked); Console.WriteLine("Is illust visible: {0}", illust.Visible); Console.WriteLine("Is illust muted: {0}", illust.IsMuted); Console.WriteLine("-------------------------------------------------------------------------------"); }
private protected DownloadTask(Illust illust, DirectoryInfo storageRoot, IDbContextFactory <EHunterDbContext> eFactory, IDbContextFactory <PixivDbContext> pFactory) { Illust = illust; StorageRoot = storageRoot; _eFactory = eFactory; _pFactory = pFactory; }
//标记当前为已读 private void MarkReaded() { Illust illust = illust_list[index]; if ((!illust.bookmarked) && !illust.readed) { illust.readed = true; pixivClient.database.UpdateIllustReaded(illust.id).Wait(); } }
public static async Task <Image <Rgba32> > GetUgoira(this Illust illust, Action <DownloadStartedEventArgs> DownloadStartedAction = null, Action <DownloadProgressChangedEventArgs> DownloadProgressChangedAction = null, Action <DownloadFileCompletedEventArgs> DownloadFileCompletedAction = null, int UpdateInfoDelay = 1000) { string head = $"Pixiv Illust(id: {illust.Id})"; ConsoleLog.Debug(head, $"Getting illust ugoira metadata..."); var meta = await illust.GetUgoiraMetadata(); if (meta.Frames == null || meta.Frames.Length <= 0) { ConsoleLog.Debug(head, $"Getting illust ugoira metadata failed."); return(null); } ConsoleLog.Debug(head, $"Succeed."); var downloadFile = await DownloadManager.Download(meta.ZipUrl, illust.Url, DownloadStartedAction : DownloadStartedAction, DownloadProgressChangedAction : DownloadProgressChangedAction, DownloadFileCompletedAction : DownloadFileCompletedAction, UpdateInfoDelay : UpdateInfoDelay); var stream = File.OpenRead(downloadFile); ConsoleLog.Debug(head, "Start to decompression ugoira data pack..."); using var zip = ZipPackage.OpenStream(stream); List <Image <Rgba32> > imgs = new List <Image <Rgba32> >(); foreach (var frame in meta.Frames) { using var zipStream = zip.GetFileStream(frame.File); var img = Image.Load <Rgba32>(zipStream); imgs.Add(img); zipStream.Dispose(); } zip.Dispose(); stream.Dispose(); ConsoleLog.Debug(head, "Decompression completed."); ConsoleLog.Debug(head, "Start compositing GIF images.."); var baseimg = imgs.First(); var gif = new Image <Rgba32>(new Configuration(new GifConfigurationModule()), baseimg.Width, baseimg.Height); gif.Metadata.GetGifMetadata().RepeatCount = 0; for (var i = 0; i < imgs.Count; i++) { var frame = gif.Frames.AddFrame(imgs[i].Frames[0]); frame.Metadata.GetGifMetadata().FrameDelay = meta.Frames[i].Delay / 10; } gif.Frames.RemoveFrame(0); ConsoleLog.Debug(head, "Finished."); return(gif); }
private async void LoadOrigin() { LoadingOrigin = true; var progress = new Progress <double>(p => Dispatcher.Invoke(() => LoadingIndicator = p)); await using var mem = await PixivIO.Download(Illust.GetDownloadUrl(), progress, cancellationTokenSource.Token); ImgSource = InternalIO.CreateBitmapImageFromStream(mem); LoadingOrigin = false; ((BlurEffect)ContentImage.Effect).Radius = 0; }
public AnimatedDownloadTask(Illust illust, DirectoryInfo storageRoot, IDbContextFactory <EHunterDbContext> eFactory, IDbContextFactory <PixivDbContext> pFactory) : base(illust, storageRoot, eFactory, pFactory) { if (!illust.IsAnimated) { throw new InvalidOperationException("Please use non-animated download task."); } }
public DownloadTask CreateDownloadTask(Illust illust) { var pFactory = _pixivDbContextResolver.Resolve() ?? throw new InvalidOperationException("No database connetion"); var eFactory = _eHunterContextResolver.Resolve() ?? throw new InvalidOperationException("No database connetion"); var storageRoot = _storageSetting.StorageRoot.Value ?? throw new InvalidOperationException("No storage"); return(illust.IsAnimated ? new AnimatedDownloadTask(illust, storageRoot, eFactory, pFactory) : new NonAnimatedDownloadTask(illust, storageRoot, eFactory, pFactory)); }
//切图实现 private void SlideTo(int i, int j, bool force_update = false) { if (i >= illust_list.Count || i < 0) { return; } Illust illust = illust_list[i]; ImageCache cache = Load(illust); if (j < cache.data.Count) { this.Image = cache.data[j]; } else { this.Image = empty_image; } bool index_changed = index != i; bool sub_index_changed = sub_index != j; index = i;//index和sub_index需要都更新完才能刷新 sub_index = j; if (index_changed || force_update) { this.NotifyChangeRange <string>(new List <string> { "IdText", "DescText", "TotalPageText" }); this.NotifyChange <int>("UserId"); this.NotifyChange <List <string> >("Tags"); this.NotifyChange <Bitmap>("FavIcon"); } this.NotifyChange <bool>("PageInvalid"); this.NotifyChange <string>("IndexText"); for (int idx = i - 5; idx < i + 5; ++idx) { if (idx >= 0 && idx < illust_list.Count) { //不能写成Task.Run(() => Load(illust_list[idx]));否则[]运行函数时才执行,此时idx的值已经改变 Illust tmp = illust_list[idx]; Task.Run(() => Load(tmp)); } } if (next_random_index >= 0 && next_random_index < illust_list.Count) { Illust tmp = illust_list[next_random_index];//同上 Task.Run(() => Load(tmp)); } }
public async Task GetIllustWithNoDetail(params int[] ids) { foreach (var id in ids) { var message = await ReplyAsync($"``Pixiv ID: {id} 数据检索中……``"); var detail = await Illust.Get(id); if (detail == null) { await message.ModifyAsync(x => x.Content = $"数据(pid:{id})获取失败,请稍后再试"); } else { await SendImage(detail, message); } } }
public IllustDownloadVM(Illust illust, DownloadManager downloadManager) { Illust = illust; _downloadManager = downloadManager; _downloadCommand = new(Download); _cancelCommand = new(Cancel); CheckDownloadable(); async void CheckDownloadable() { var downloadable = await _downloadManager.Downloader.CanDownloadAsync(Illust.Id) .ConfigureAwait(true); if (State == NotLoaded) { State = (downloadable switch { DownloadableState.AlreadyDownloaded => Completed, _ => Idle }); }
public async Task GetIllustDetail(int id) { if (await Context.User.CheckCoins(5)) { var msg = await ReplyAsync("``数据检索中……``"); var detail = await Illust.Get(id); if (detail == null) { await msg.ModifyAsync(x => x.Content = "数据获取失败,请稍后再试"); } else { StringBuilder sb = new(); foreach (var img in detail.Images) { sb.AppendLine(ImageUrls.ToPixivCat(img.Medium)); } sb.AppendLine(detail.Title) .AppendLine($"Author: {detail.Author}") .AppendLine(detail.Caption) .AppendLine($"Tags: {string.Join(" | ", detail.Tags)}") .AppendLine($"Publish Date: {detail.CreateDate:yyyy-MM-dd hh:mm:ss}") .AppendLine($"Bookmarks: {detail.TotalBookmarks} Comments:{detail.TotalComments} Views:{detail.TotalView}") .Append(detail.Url); await msg.ModifyAsync(x => x.Content = msg.ToString()); await Context.User.RemoveCoins(5); } } else { await ReplyAsync("幻币数量不足"); } }
async Task SendImage(Illust detail, IUserMessage message = null) { int id = detail.Id; if (message == null) { message = await ReplyAsync(string.Format(TitleContent, id)); } else { await UpdateMessage(message, string.Format(TitleContent, id)); } var info = await ReplyAsync("``== loading ==``"); int total = detail.Images.Length; int successed = 0, failed = 0; int current = -1; long receivedbyte = 0, totalbyte = 0; double percentage = 0; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); if (detail.IsUgoira) { current++; var ugoira = await detail.GetUgoira( DownloadStartedAction : async(e) => { receivedbyte = 0; totalbyte = e.FileSize; percentage = 0; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); }, DownloadProgressChangedAction : async(e) => { receivedbyte = e.ReceivedBytes; totalbyte = e.TotalBytes; percentage = e.DownloadPercentage; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); }, DownloadFileCompletedAction : async(e) => { if (e.Status == DownloadTaskStatus.Completed) { receivedbyte = totalbyte; percentage = 100; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); } }, UpdateInfoDelay : 2000); if (ugoira == null) { await UpdateInfo(message, $"动图数据(pid: {id})获取失败"); } else { var img = await ugoira.LimitGifScale(350, 350); var stream = await img.SaveGifToStream(); await Context.Channel.SendFileAsync(stream, $"pixiv-{id}.gif"); } } else { Stream[] streams = new Stream[total]; foreach (var img in detail.Images) { current++; var cache = await DownloadManager.GetCache(img.Medium); if (string.IsNullOrEmpty(cache)) { var url = ImageUrls.ToPixivCat(img.Medium); cache = await DownloadManager.GetCache(url); if (string.IsNullOrEmpty(cache)) { cache = await DownloadManager.Download(url, DownloadStartedAction : async(e) => { receivedbyte = 0; totalbyte = e.FileSize; percentage = 0; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); }, DownloadProgressChangedAction : async(e) => { receivedbyte = e.ReceivedBytes; totalbyte = e.TotalBytes; percentage = e.DownloadPercentage; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); }, DownloadFileCompletedAction : async(e) => { if (e.Status == DownloadTaskStatus.Completed) { receivedbyte = totalbyte; percentage = 100; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); } }, UpdateInfoDelay : 2000); if (string.IsNullOrEmpty(cache)) { cache = await DownloadManager.Download(img.Medium, detail.Url, DownloadStartedAction : async(e) => { receivedbyte = 0; totalbyte = e.FileSize; percentage = 0; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); }, DownloadProgressChangedAction : async(e) => { receivedbyte = e.ReceivedBytes; totalbyte = e.TotalBytes; percentage = e.DownloadPercentage; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); }, DownloadFileCompletedAction : async(e) => { if (e.Status == DownloadTaskStatus.Completed) { receivedbyte = totalbyte; percentage = 100; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); } }, UpdateInfoDelay : 2000); if (string.IsNullOrEmpty(cache)) { failed++; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); continue; } } } } ImageUtils.LimitImageScale(cache, 1500, 1500); streams[current] = CopyFile(cache); successed++; await UpdateInfo(info, current + 1, total, receivedbyte, totalbyte, percentage, successed, failed); } for (int i = 0; i < total; i++) { var stream = streams[i]; if (stream == null) { await ReplyAsync($"[图像 pixiv-{id}_p{i}.png 下载失败]"); } else { await Context.Channel.SendFileAsync(stream, $"pixiv-{id}_p{i}.png"); } } } try { await info.DeleteAsync(); } catch { } try { await message.DeleteAsync(); } catch { } }
//载入某个Illust的全部图片 private ImageCache Load(Illust illust) { {//hit ImageCache cache; if (cache_pool.TryGetValue(illust.id, out cache)) { cache.required_time = DateTime.UtcNow; return(cache); } } {//not hit ImageCache cache = new ImageCache(); cache.illust = illust; cache.required_time = DateTime.UtcNow; cache.data = new List <Image>(); for (int i = 0; i < illust.pageCount; i++) { if (illust.bookmarked && !illust.isPageValid(i)) { continue; } string path = String.Format("{0}/{1}", pixivClient.download_dir_main, illust.storeFileName(i)); if (File.Exists(path)) { try { var img = Image.FromFile(path); //我内存贼大,不用裁剪 img.Tag = i;//图片在illust中的原本index cache.data.Add(img); } catch (Exception e) { //视同文件损坏,删除 Console.WriteLine("Can't Load Image " + path); Console.WriteLine(e.Message); Console.WriteLine("Delete Image"); File.Delete(path); var img = (Image)empty_image.Clone(); img.Tag = -1; cache.data.Add(img); } } else { var img = (Image)empty_image.Clone(); img.Tag = -1; cache.data.Add(img); } } if (!cache_pool.TryAdd(illust.id, cache))//开头就检测过hit,如果此时已经存在,那肯定是刚加进去的,没必要更新required_time { cache.Dispose(); } while (cache_pool.Count > cache_size) { //C#里可修改的Pair类是什么? int oldest_cache = -1; DateTime oldest_cache_time = DateTime.MaxValue; foreach (var tmp_cache in cache_pool) { if (tmp_cache.Value.required_time < oldest_cache_time) { oldest_cache = tmp_cache.Key; oldest_cache_time = tmp_cache.Value.required_time; } } if (oldest_cache < 0) { continue; } ImageCache ignored; if (cache_pool.TryRemove(oldest_cache, out ignored)) { ignored.Dispose(); } } return(cache); } }
public IllustVM CreateViewModel(Illust illust, int indexInCollection = -1) => new(illust, _downloadManager.GetOrAddDownloadable(illust), indexInCollection);
internal IllustVM(Illust illust, IllustDownloadVM downloadable, int indexInCollection = -1) { Illust = illust; Downloadable = downloadable; IndexInCollection = indexInCollection; }
public static void OpenBrowser(this Illust illust) { var url = $"https://www.pixiv.net/member_illust.php?mode=medium&illust_id={illust.Id}"; url.OpenProcess(); }
public void Add(Illust illust) { this.Add(illust.Id, illust.ImageUrl, illust.Title, illust.Description); }
public static Uri[] GetImageUrls(this Illust illust) { return(illust.MetaPages.Length == 0 ? illust.MetaSinglePage.OriginalImageUrl.AsArray() : illust.MetaPages.Select(page => page.ImageUrls.Original).ToArray()); }
static async void _GetIllustDetail(int id, Action <object[]> Reply, Action <object[]> SendMessage, bool slient = false) { try { var detail = await Illust.Get(id); if (detail == null) { if (!slient) { Reply?.Invoke(new object[] { $"数据(pid:{id})获取失败,请稍后再试" }); } return; } ArrayList msg = new(); if (detail.IsUgoira) { var ugoira = await detail.GetUgoira(); if (ugoira == null) { if (!slient) { Reply?.Invoke(new object[] { $"动图数据(pid:{id})获取失败" }); } } else { if (!slient) { Reply?.Invoke(new object[] { $"动图数据(pid:{id})获取成功,正在进行压缩..." }); } var img = await ugoira.LimitGifScale(500, 500); var file = await img.SaveGifToTempFile(); msg.Add(CQCode.CQImage(file)); } } else { foreach (var img in detail.Images) { var cache = await DownloadManager.GetCache(img.Medium); if (string.IsNullOrEmpty(cache)) { var url = ImageUrls.ToPixivCat(img.Medium); cache = await DownloadManager.GetCache(url); if (string.IsNullOrEmpty(cache)) { cache = await DownloadManager.Download(url); if (string.IsNullOrEmpty(cache)) { cache = await DownloadManager.Download(img.Medium, detail.Url); if (string.IsNullOrEmpty(cache)) { msg.Add("[图像缓存失败]"); continue; } } } } ImageUtils.LimitImageScale(cache, 1500, 1500); msg.Add(CQCode.CQImage(cache)); } } msg.Add(detail.ToString()); SendMessage?.Invoke(msg.ToArray()); } catch (Exception ex) { ConsoleLog.Debug("QQ Command - Pixiv", ex.GetFormatString(true)); if (!slient) { Reply?.Invoke(new object[] { $"处理作品(pid:{id})时发生异常错误,任务已终止" }); } } }