/// <summary> /// 保存章节 /// </summary> /// <returns></returns> public bool Save() { ThrowExceptionIfValidateFailure(); Data.Entity.Chapter chapter = new Data.Entity.Chapter { ChapterId = ID, Content = Content, Count = Count, CourseId = CourseId, CreateTime = DateTime.Now, ParentId = ParentId, ParentPath = ChapterTools.CreateParentPath(ParentChapter, ID), Status = Status, Title = Title, Video = Video, IsLeaf = true }; bool success = ChapterAccessor.Insert(chapter); if (success) { ComputeStudyProgress(CourseId); } return(success); }
private void ConvertChapter(string Chapter, string LastChapter, string NextChapter, string Format) { var ChapName = Path.GetFileName(Chapter.TrimEnd('\\', '/')); var TmpChapter = Path.Combine(ChapPath, "tmp", ChapName); var ChapReader = Path.Combine(ChapPath, ChapName + ".html"); if (!Directory.Exists(Path.GetDirectoryName(TmpChapter))) { Directory.CreateDirectory(Path.GetDirectoryName(TmpChapter)); } Directory.Move(Chapter, TmpChapter); bool OK = Retry(() => ExportChapter(TmpChapter, ChapPath, Format, Language, true, Language.Converting)); if (!OK) { Directory.Delete(Chapter, true); Directory.Move(TmpChapter, Chapter); Directory.Delete(Path.GetDirectoryName(TmpChapter), true); return; } Directory.Delete(TmpChapter, true); Directory.Delete(Path.GetDirectoryName(TmpChapter), true); if (!File.Exists(ChapReader)) { return; } var Pages = (from x in Directory.GetFiles(Chapter) select Path.GetFileName(x)).ToArray(); ChapterTools.GenerateComicReader(Language, Pages, LastChapter, NextChapter, ChapPath, Chapter, ChapName); }
/// <summary> /// 修改章节信息 /// </summary> /// <param name="state">编辑后的数据状态</param> /// <returns></returns> public bool Modify(ChapterModifyState state) { if (state == null) { return(false); } Data.Entity.Chapter parent = null; if (state.ParentId > 0) { parent = ChapterAccessor.Get(state.ParentId); } ThrowExceptionIfValidateFailure(() => { if (CanModify()) { //所属课程 if (!CourseAccessor.Exists(state.CourseId)) { AddBrokenRule(ChapterManageFailureRule.COURSE_NOT_EXISTS); } //有关联父章节时,父章节不存在 if (state.ParentId > 0 && parent == null) { AddBrokenRule(ChapterManageFailureRule.PAREND_NOT_EXISTS); } //标题不能为空 if (string.IsNullOrWhiteSpace(state.Title)) { AddBrokenRule(ChapterManageFailureRule.TITLE_CANNOT_EMPTY); } //内容不能为空 if (string.IsNullOrWhiteSpace(state.Content)) { AddBrokenRule(ChapterManageFailureRule.CONTENT_CANNOT_EMPTY); } } else { AddBrokenRule(ChapterManageFailureRule.CANNOT_MODIFY); } }); bool success = ChapterAccessor.Update( ID, state.CourseId, state.ParentId, ChapterTools.CreateParentPath(parent, ID), state.Title, state.Content, state.Video, state.Status); if (success && (Chapter.CourseId != state.CourseId || Chapter.Status != state.Status)) { ComputeStudyProgress(state.CourseId); } return(success); }
public VSButton LoadUri(Uri Uri, IHost Host) { Status = CurrentLanguage.LoadingComic; CurrentHost = CreateInstance(Host); CurrentInfo = CurrentHost.LoadUri(Uri); TitleLabel.Text = CurrentInfo.Title; CoverBox.Image = CurrentHost.GetDecoder().Decode(CurrentInfo.Cover); if (CurrentInfo.Url == null) { CurrentInfo.Url = Uri; } CoverBox.Cursor = Cursors.Default; string Dir = DataTools.GetRawName(CurrentInfo.Title.Trim(), FileNameMode: true); ChapterTools.MatchLibraryPath(ref Dir, Settings.LibraryPath, CurrentInfo.Url, ReplaceMode.UpdateURL, CurrentLanguage); RefreshCoverLink(Dir); var OnlinePath = Path.Combine(Settings.LibraryPath, Dir, "Online.url"); if (Directory.Exists(Dir) && !File.Exists(OnlinePath)) { var OnlineData = string.Format(Properties.Resources.UrlFile, CurrentInfo.Url.AbsoluteUri); File.WriteAllText(OnlinePath, OnlineData); } ButtonsContainer.Controls.Clear(); VSButton DownAll = null; var Chapters = new Dictionary <int, string>(); foreach (var Chapter in CurrentHost.EnumChapters()) { if (Chapters.ContainsValue(Chapter.Value)) { continue; } VSButton Button = new VSButton() { Size = new Size(110, 30), Text = string.Format(CurrentLanguage.ChapterName, Chapter.Value), Indentifier = CurrentHost }; Button.Click += (sender, args) => { try { IHost HostIsnt = (IHost)((VSButton)sender).Indentifier; DownloadChapter(Chapters, Chapter.Key, HostIsnt, CurrentInfo); } catch (Exception ex) { if (Program.Debug) { throw; } } StatusBar.SecondLabelText = string.Empty; Status = CurrentLanguage.IDLE; }; DownAll = Button; ButtonsContainer.Controls.Add(Button); Chapters.Add(Chapter.Key, Chapter.Value); } if (Chapters.Count > 1) { VSButton Button = new VSButton() { Size = new Size(110, 30), Text = CurrentLanguage.DownloadAll, Indentifier = CurrentHost }; Button.Click += (sender, args) => { foreach (var Chapter in Chapters.Reverse()) { try { IHost HostIsnt = (IHost)((VSButton)sender).Indentifier; DownloadChapter(Chapters, Chapter.Key, HostIsnt, CurrentInfo); } catch (Exception ex) { if (Program.Debug) { throw; } } StatusBar.SecondLabelText = string.Empty; Status = CurrentLanguage.IDLE; } }; DownAll = Button; ButtonsContainer.Controls.Add(Button); } var PActions = CurrentHost.GetPluginInfo().Actions; if (PActions != null) { var Actions = (from x in PActions where x.Availability.HasFlag(ActionTo.ChapterList) select x); if (Actions.Any()) { foreach (var Action in Actions) { VSButton Bnt = new VSButton() { Size = new Size(110, 30), Text = Action.Name, Indentifier = CurrentHost }; Bnt.Click += (sender, args) => Action.Action(); ButtonsContainer.Controls.Add(Bnt); } ; } } Status = CurrentLanguage.IDLE; return(DownAll); }
private void DownloadChapter(Dictionary <int, string> Chapters, int ID, IHost Host, ComicInfo Info) { string Name = DataTools.GetRawName(Chapters[ID], FileNameMode: true); StatusBar.SecondLabelText = $"{Info.Title} - {string.Format(CurrentLanguage.ChapterName, Name)}"; Status = CurrentLanguage.Loading; int KIndex = Chapters.IndexOfKey(ID); string LName = null; string LastChapterPah = null; if (KIndex + 1 < Chapters.Keys.Count) { LName = DataTools.GetRawName(Chapters.Values.ElementAt(KIndex + 1), FileNameMode: true); } string NName = null; string NextChapterPath = null; if (KIndex > 0) { NName = DataTools.GetRawName(Chapters.Values.ElementAt(KIndex - 1), FileNameMode: true); } string Title = DataTools.GetRawName(Info.Title.Trim(), FileNameMode: true); ChapterTools.MatchLibraryPath(ref Title, Settings.LibraryPath, CurrentInfo.Url, (ReplaceMode)Settings.ReplaceMode, CurrentLanguage); RefreshCoverLink(Title); string TitleDir = Path.Combine(Settings.LibraryPath, Title); if (!Directory.Exists(TitleDir)) { Directory.CreateDirectory(TitleDir); RefreshLibrary(); } if (LName != null) { ChapterTools.GetChapterPath(Languages, CurrentLanguage, TitleDir, LName, out LastChapterPah, false); } ChapterTools.GetChapterPath(Languages, CurrentLanguage, TitleDir, Name, out string ChapterPath, false); if (NName != null) { ChapterTools.GetChapterPath(Languages, CurrentLanguage, TitleDir, NName, out NextChapterPath, false); } string AbsoluteChapterPath = Path.Combine(TitleDir, ChapterPath); if (Settings.SkipDownloaded && File.Exists(AbsoluteChapterPath.TrimEnd('\\', '/') + ".html")) { return; } int PageCount = 1; if (Info.ContentType == ContentType.Comic) { PageCount = Host.GetChapterPageCount(ID); if (Directory.Exists(AbsoluteChapterPath) && Directory.GetFiles(AbsoluteChapterPath, "*").Length < PageCount) { Directory.Delete(AbsoluteChapterPath, true); } if (Settings.SkipDownloaded && Directory.Exists(AbsoluteChapterPath)) { var Pages = (from x in Directory.GetFiles(AbsoluteChapterPath) select Path.GetFileName(x)).ToArray(); ChapterTools.GenerateComicReader(CurrentLanguage, Pages, LastChapterPah, NextChapterPath, TitleDir, ChapterPath, Name); string OnlineData = string.Format(Properties.Resources.UrlFile, Info.Url.AbsoluteUri); File.WriteAllText(Path.Combine(TitleDir, "Online.url"), OnlineData); return; } } if (Info.ContentType == ContentType.Novel) { ChapterPath = Path.Combine(AbsoluteChapterPath, string.Format(CurrentLanguage.ChapterName, Name) + ".epub"); if (Settings.SkipDownloaded && File.Exists(ChapterPath)) { return; } } if (!Directory.Exists(AbsoluteChapterPath)) { Directory.CreateDirectory(AbsoluteChapterPath); } string UrlData = string.Format(Properties.Resources.UrlFile, Info.Url.AbsoluteUri); File.WriteAllText(Path.Combine(TitleDir, "Online.url"), UrlData); switch (Info.ContentType) { case ContentType.Comic: var Decoder = Host.GetDecoder(); List <string> Pages = new List <string>(); foreach (var Data in Host.DownloadPages(ID).CatchExceptions()) { Status = string.Format(CurrentLanguage.Downloading, Pages.Count + 1, PageCount); Application.DoEvents(); bool IsWebP = Data.Length > 12 && BitConverter.ToUInt32(Data, 8) == 0x50424557; try { #if NOASYNCSAVE string PageName = $"{Pages.Count:D3}.png"; string PagePath = Path.Combine(TitleDir, ChapterPath, PageName); Page OutPage = new Page(); OutPage.Data = Data; if ((SaveAs)Settings.SaveAs != SaveAs.RAW) { using (Bitmap Result = Decoder.Decode(Data)) { PageName = $"{Pages.Count:D3}.{GetExtension(Result, out ImageFormat Format)}"; PagePath = OutPage.Path = Path.Combine(TitleDir, ChapterPath, PageName); if (Result.GetImageExtension() == "png" && Settings.APNGBypass) { var OutData = BypassAPNG(Data); OutPage.Data = OutData; } else { using (MemoryStream tmp = new MemoryStream()) { Result.Save(tmp, Format); OutPage.Data = tmp.ToArray(); } } } } if (Settings.ImageClipping) { PostProcessQueue.Enqueue(OutPage); } else { File.WriteAllBytes(OutPage.Path, OutPage.Data); } while (PostProcessQueue.Count > 0) { ThreadTools.Wait(1000, true); } #else string PageName = $"{Pages.Count:D3}.{(IsWebP ? "webp" : "png")}"; string PagePath = Path.Combine(TitleDir, ChapterPath, PageName); Page OutPage = new Page(); OutPage.Data = Data; if ((SaveAs)Settings.SaveAs != SaveAs.RAW) { byte[] ModData = null; if (IsWebP) { ModData = DecodeWebP(Data); } using (MemoryStream Buffer = new MemoryStream()) using (Bitmap Result = Decoder.Decode(ModData ?? Data)) { PageName = $"{Pages.Count:D3}.{GetExtension(Result, out ImageFormat Format)}"; PagePath = Path.Combine(TitleDir, ChapterPath, PageName); if (Result.GetImageExtension() == "png" && Settings.APNGBypass) { using (MemoryStream OutBuffer = new MemoryStream(BypassAPNG(ModData ?? Data))) using (Bitmap Img = new Bitmap(OutBuffer)) { Img.Save(Buffer, Format); OutPage.Data = Buffer.ToArray(); } } else { Result.Save(Buffer, Format); OutPage.Data = Buffer.ToArray(); } } } OutPage.Path = PagePath; if (PostProcessQueue.Count > 5) { const ulong MinMemory = 400000000; while (AvailablePhysicalMemory < MinMemory && PostProcessQueue.Count > 0 || (Settings.MaxPagesBuffer != 0 && PostProcessQueue.Count >= Settings.MaxPagesBuffer)) { ThreadTools.Wait(1000, true); } } PostProcessQueue.Enqueue(OutPage); #endif Pages.Add(PageName); } catch (Exception ex) { if (Program.Debug) { throw; } Console.Error.WriteLine(ex.ToString()); } } if (Settings.ReaderGenerator) { ChapterTools.GenerateComicReader(CurrentLanguage, Pages.ToArray(), LastChapterPah, NextChapterPath, TitleDir, ChapterPath, Name); ChapterTools.GenerateReaderIndex(Languages, CurrentLanguage, Info, TitleDir, Name); } break; case ContentType.Novel: var Chapter = Host.DownloadChapter(ID); AsyncContext.Run(async() => { using (var Epub = await EPubWriter.CreateWriterAsync(File.Create(ChapterPath), Info.Title ?? "Untitled", Chapter.Author ?? "Anon", Chapter.URL ?? "None")) { Chapter.HTML.RemoveNodes("//script"); Chapter.HTML.RemoveNodes("//iframe"); foreach (var Node in Chapter.HTML.DocumentNode.DescendantsAndSelf()) { if (Node.Name == "img" && Node.GetAttributeValue("src", string.Empty) != string.Empty) { string Src = Node.GetAttributeValue("src", string.Empty); string RName = Path.GetFileName(Src.Substring(null, "?", IgnoreMissmatch: true)); string Mime = ResourceHandler.GetMimeType(Path.GetExtension(RName)); if (Node.GetAttributeValue("type", string.Empty) != string.Empty) { Mime = Node.GetAttributeValue("type", string.Empty); } Uri Link = new Uri(Info.Url, Src); if (string.IsNullOrWhiteSpace(RName)) { continue; } byte[] Buffer = await Link.TryDownloadAsync(); if (Buffer == null) { continue; } await Epub.AddResourceAsync(RName, Mime, Buffer); Node.SetAttributeValue("src", RName); } if (Node.Name == "link" && Node.GetAttributeValue("rel", string.Empty) == "stylesheet" && Node.GetAttributeValue("href", string.Empty) != string.Empty) { string Src = Node.GetAttributeValue("href", string.Empty); string RName = Path.GetFileName(Src.Substring(null, "?", IgnoreMissmatch: true)); string Mime = ResourceHandler.GetMimeType(Path.GetExtension(RName)); if (Node.GetAttributeValue("type", string.Empty) != string.Empty) { Mime = Node.GetAttributeValue("type", string.Empty); } Uri Link = new Uri(Info.Url, Src); if (string.IsNullOrWhiteSpace(RName)) { continue; } byte[] Buffer = await Link.TryDownloadAsync(); if (Buffer == null) { continue; } await Epub.AddResourceAsync(RName, Mime, Buffer); Node.SetAttributeValue("href", RName); } } Epub.Publisher = lblTitle.Text; await Epub.AddChapterAsync("chapter.xhtml", Chapter.Title, Chapter.HTML.ToHTML()); await Epub.WriteEndOfPackageAsync(); } }); break; default: throw new Exception("Invalid Content Type"); } }