private static void download(INovelDownloadPlugin plugin, string url, NDTBook bookToken = null) { if (bookToken == null && !plugin.TryGetBookToken(new Uri(url, UriKind.RelativeOrAbsolute), out bookToken)) { return; } Console.WriteLine(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(string.Format("{0}({1}) v{2}\n{3}", plugin.DisplayName, plugin.Name, plugin.Version, plugin.Description)); Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine(); if (bookToken is NovelDownloader.Plugin.luoqiu.com.BookToken || bookToken is NovelDownloader.Plugin._81zw.com.BookToken || bookToken is NovelDownloader.Plugin.顶点小说.BookToken) { downloadNormal(plugin, bookToken); } else if (bookToken is NovelDownloader.Plugin.wenku8.com.BookToken || bookToken is NovelDownloader.Plugin.qidian.com.BookToken) { downloadLight(plugin, bookToken); } else { Console.WriteLine("无法下载《{0]》", bookToken.Title); } }
/// <summary> /// 寻找合适的书籍输出器,并异步保存书籍到文件。 /// </summary> /// <param name="bookToken">书籍节点。</param> /// <param name="outputDir">输出目录。</param> /// <exception cref="ArgumentNullException"><paramref name="bookToken"/> 的值为 <see langword="null"/> 。</exception> /// <exception cref="NotSupportedException">未找到支持节点的小说下载插件。</exception> /// <exception cref="NotSupportedException">不支持的插件类型。</exception> public Task SaveToAsync(NDTBook bookToken, string outputDir) { if (bookToken == null) { throw new ArgumentNullException(nameof(bookToken)); } IBookWriter bookWriter = this.FindBookWriterForBookToken(bookToken); // 异步写入文件。 return(bookWriter.WriteAsync(bookToken, outputDir)); }
/// <summary> /// 寻找合适的书籍输出器,并保存书籍到文件。 /// </summary> /// <param name="bookToken">书籍节点。</param> /// <param name="outputDir">输出目录。</param> /// <exception cref="ArgumentNullException"><paramref name="bookToken"/> 的值为 <see langword="null"/> 。</exception> /// <exception cref="NotSupportedException">未找到支持节点的小说下载插件。</exception> /// <exception cref="NotSupportedException">不支持的插件类型。</exception> public void SaveTo(NDTBook bookToken, string outputDir) { if (bookToken == null) { throw new ArgumentNullException(nameof(bookToken)); } IBookWriter bookWriter = this.FindBookWriterForBookToken(bookToken); // 写入文件。 bookWriter.Write(bookToken, outputDir); }
/// <summary> /// 尝试获取位于指定的 <see cref="Uri"/> 位置的小说标签。 /// </summary> /// <param name="uri">指定的统一资源标识符。</param> /// <param name="bookToken">位于指定的 <see cref="Uri"/> 位置的小说标签。</param> /// <returns>是否获取成功。</returns> public override bool TryGetBookToken(Uri uri, out NDTBook bookToken) { try { bookToken = this.GetBookToken(uri); return(bookToken != null); } catch (Exception) { bookToken = null; return(false); } }
public BookInfo(NDTBook bookToken) { if (bookToken == null) { throw new ArgumentNullException(nameof(bookToken)); } this.Title = bookToken.Title; this.Author = bookToken.Author; var description = bookToken.Description; var lines = description.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); if (lines.Length == 0) { this.Description = string.Empty; } else if (lines.Length == 1) { this.Description = lines[0].Trim(); } else { this.Description = string.Join(Environment.NewLine, new[] { string.Empty }.Concat(lines.Select(line => " " + line.Trim()))); } this.Cover = bookToken.Cover; bookToken.StartCreep(); foreach (var token in bookToken.Children.OfType <NDTChapter>().Select(token => new ChapterInfo(token))) { this.Chapters.Add(token); } if (this.Chapters.Count == 0) { foreach (var token in bookToken.Children.OfType <NDTVolume>().SelectMany(token => { token.StartCreep(); return(token.Children.OfType <NDTChapter>()); }).Select(token => new ChapterInfo(token))) { this.Chapters.Add(token); } } }
private static void downloadNormal(INovelDownloadPlugin plugin, NDTBook bookToken) { new Thread(() => { using (StreamWriter writer = new StreamWriter(string.Format("{0}.txt", process(bookToken.Title)), false, Encoding.UTF8)) { //StringBuilder sb = new StringBuilder(); Console.WriteLine("{0} - {1}", bookToken.Type, bookToken.Title); writer.WriteLine(string.Format("书名:{0}", bookToken.Title)); writer.WriteLine(string.Format("作者:{0}", bookToken.Author)); writer.WriteLine(); writer.WriteLine(); bookToken.CreepStarted += (sender, e) => Console.WriteLine("\t开始下载书籍《{0}》", bookToken.Title); bookToken.CreepFetched += (sender, e) => Console.WriteLine("\t获取 【{0}】", e.Data); bookToken.CreepFinished += (sender, e) => Console.WriteLine("\t下载书籍《{0}》完成。", bookToken.Title); bookToken.StartCreep(); foreach (NDTChapter chapterToken in bookToken.Children) { chapterToken.CreepStarted += (sender, e) => { Console.WriteLine("\t开始下载章节【{0}】”", chapterToken.Title); writer.WriteLine("--------------------"); writer.WriteLine(); writer.WriteLine(chapterToken.Title); }; chapterToken.CreepFetched += (sender, e) => { //Console.WriteLine("{0}", e.Data); writer.WriteLine(string.Format(" {0}", e.Data)); }; chapterToken.CreepFinished += (sender, e) => { Console.WriteLine("\t下载章节【{0}】完成。\n", chapterToken.Title); writer.WriteLine(); }; chapterToken.StartCreep(); } //Console.WriteLine(sb.ToString()); } }).Start(); }
public virtual void Write(NDTBook bookToken, string outputDir) { if (bookToken == null) { throw new ArgumentNullException(nameof(bookToken)); } if (outputDir == null) { throw new ArgumentNullException(nameof(outputDir)); } var di = new DirectoryInfo(outputDir); if (!di.Exists) { di.Create(); } this.WriteInternal(bookToken, outputDir); }
/// <summary> /// 提供输出书籍的实现。 /// </summary> /// <param name="bookToken">书籍节点。</param> /// <param name="outputDir">输出目录。</param> protected override void WriteInternal(NDTBook bookToken, string outputDir) { using (StreamWriter writer = new StreamWriter(Path.Combine(outputDir, $"{bookToken.Title}.txt"), false, Encoding.UTF8)) { //StringBuilder sb = new StringBuilder(); this.LogWriter.WriteLine("{0} - {1}", bookToken.Type, bookToken.Title); writer.WriteLine(string.Format("书名:{0}", bookToken.Title)); writer.WriteLine(string.Format("作者:{0}", bookToken.Author)); writer.WriteLine(); writer.WriteLine(); bookToken.CreepStarted += (sender, e) => this.LogWriter.WriteLine("\t开始获取书籍《{0}》", bookToken.Title); bookToken.CreepFetched += (sender, e) => this.LogWriter.WriteLine("\t获取 【{0}】", e.Data); bookToken.CreepFinished += (sender, e) => this.LogWriter.WriteLine("\t书籍《{0}》获取完成。", bookToken.Title); bookToken.StartCreep(); foreach (NDTChapter chapterToken in bookToken.Children) { chapterToken.CreepStarted += (sender, e) => { this.LogWriter.WriteLine("\t开始获取章节【{0}】”", chapterToken.Title); writer.WriteLine("--------------------"); writer.WriteLine(); writer.WriteLine(chapterToken.Title); }; chapterToken.CreepFetched += (sender, e) => { //this.LogWriter.WriteLine("{0}", e.Data); writer.WriteLine(string.Format(" {0}", e.Data)); }; chapterToken.CreepFinished += (sender, e) => { this.LogWriter.WriteLine("\t章节【{0}】获取完成。\n", chapterToken.Title); writer.WriteLine(); }; chapterToken.StartCreep(); } //this.LogWriter.WriteLine(sb.ToString()); } }
/// <summary> /// 寻找合适的书籍输出器。 /// </summary> /// <param name="bookToken">书籍节点。</param> /// <returns>支持指定书籍节点的书籍输出器。</returns> /// <exception cref="NotSupportedException">未找到支持节点的小说下载插件。</exception> /// <exception cref="NotSupportedException">不支持的插件类型。</exception> protected internal IBookWriter FindBookWriterForBookToken(NDTBook bookToken) { NovelDownLoadPluginBookTokenAttribute attribute = bookToken.GetType().GetCustomAttribute <NovelDownLoadPluginBookTokenAttribute>(true); if (attribute == null) { throw new NotSupportedException("未找到支持节点的小说下载插件。"); } // 获取已注册的插件实例。 if (this.Plugins.TryGetValue(attribute.PluginGuid, out IPlugin plugin) && plugin is INovelDownloadPlugin ndPlugin) { if (!this.BookWriters.TryGetValue(ndPlugin.Guid, out IBookWriter bookWriter)) // 尝试从已注册的书籍输出器中寻找。 { // 指定插件未注册书籍输出器,采用默认书籍输出器。 if (ndPlugin is ILightNovelDownloadPlugin) { bookWriter = new LightNovelBookWriter(); } else { bookWriter = new NormalBookWriter(); } } // 组装组件。 var catalog = new TypeCatalog(typeof(NovelDownloadPluginBase), typeof(BookWriterBase), typeof(PluginManager)); var container = new CompositionContainer(catalog); container.ComposeParts(plugin, bookWriter, this); return(bookWriter); } else { throw new NotSupportedException("不支持的插件类型。"); } }
static async void download(NDTBook bookToken) { await manager.SaveToAsync(bookToken, @"downloads\"); }
private static void downloadLight(INovelDownloadPlugin plugin, NDTBook bookToken) { new Thread(() => { Console.WriteLine("{0} - {1}", bookToken.Type, bookToken.Title); DirectoryInfo directory = new DirectoryInfo(process(bookToken.Title)); bookToken.CreepStarted += (sender, e) => { Console.WriteLine("\t开始下载书籍《{0}》", bookToken.Title); if (!directory.Exists) { directory.Create(); } }; bookToken.CreepFetched += (sender, e) => Console.WriteLine("\t获取 ({0})", e.Data); bookToken.CreepFinished += (sender, e) => Console.WriteLine("\t下载书籍《{0}》完成。", bookToken.Title); bookToken.StartCreep(); foreach (NDTVolume volumeToken in bookToken.Children) { FileInfo file = new FileInfo(Path.Combine(directory.FullName, process(volumeToken.Title) + ".txt")); StreamWriter writer = null; volumeToken.CreepStarted += (sender, e) => { Console.WriteLine("\t\t开始下载卷({0})", volumeToken.Title); writer = file.CreateText(); }; volumeToken.CreepFetched += (sender, e) => Console.WriteLine("\t\t获取 【{0}】", e.Data); volumeToken.CreepFinished += (sender, e) => Console.WriteLine("\t\t下载卷({0})完成。", volumeToken.Title); volumeToken.StartCreep(); writer.WriteLine("[{0}][{1}][{2}]", bookToken.Author, bookToken.Title, volumeToken.Title); writer.WriteLine(); writer.WriteLine("≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡"); writer.WriteLine(); writer.WriteLine(" 书名:{0}", bookToken.Title); writer.WriteLine(" 作者:{0}", bookToken.Author); writer.WriteLine(" 来源:{0}", bookToken.Uri.Host); writer.WriteLine(); writer.WriteLine(" 本资源由小说下载插件 {0}({1}) v{2} 【{3}】 扫描提供。", plugin.DisplayName, plugin.Name, plugin.Version, plugin.Description); writer.WriteLine(); writer.WriteLine("≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡"); writer.WriteLine(); writer.WriteLine(); writer.WriteLine(volumeToken.Title); writer.WriteLine(); writer.Flush(); foreach (NDTChapter chapterToken in volumeToken.Children) { chapterToken.CreepStarted += (sender, e) => { Console.WriteLine("\t\t\t开始下载章节【{0}】”", chapterToken.Title); writer.WriteLine(); writer.WriteLine(); writer.WriteLine(chapterToken.Title); writer.WriteLine(); }; chapterToken.CreepFetched += (sender, e) => { writer.WriteLine(" {0}", e.Data); }; chapterToken.CreepFinished += (sender, e) => { Console.WriteLine("\t\t\t下载章节【{0}】完成。\n", chapterToken.Title); writer.WriteLine(); }; chapterToken.StartCreep(); } writer.Flush(); writer.Close(); writer.Dispose(); } }).Start(); }
/// <summary> /// 提供输出书籍的实现。 /// </summary> /// <param name="bookToken">书籍节点。</param> /// <param name="outputDir">输出目录。</param> protected override void WriteInternal(NDTBook bookToken, string outputDir) { this.LogWriter.WriteLine("{0} - {1}", bookToken.Type, bookToken.Title); DirectoryInfo book = null; bookToken.CreepStarted += (sender, e) => { this.LogWriter.WriteLine("\t开始获取书籍《{0}》", bookToken.Title); // 创建书籍根目录。 book = new DirectoryInfo(outputDir).CreateSubdirectory(bookToken.Title); }; bookToken.CreepFetched += (sender, e) => this.LogWriter.WriteLine("\t获取({0})", e.Data); bookToken.CreepFinished += (sender, e) => this.LogWriter.WriteLine("\t书籍《{0}》获取完成。", bookToken.Title); bookToken.StartCreep(); foreach (NDTVolume volumeToken in bookToken.Children) { FileInfo file = new FileInfo(Path.Combine(book.FullName, volumeToken.Title + ".txt")); StreamWriter writer = null; volumeToken.CreepStarted += (sender, e) => { this.LogWriter.WriteLine("\t\t开始获取卷({0})", volumeToken.Title); writer = file.CreateText(); }; volumeToken.CreepFetched += (sender, e) => this.LogWriter.WriteLine("\t\t获取 【{0}】", e.Data); volumeToken.CreepFinished += (sender, e) => this.LogWriter.WriteLine("\t\t卷({0})获取完成。", volumeToken.Title); volumeToken.StartCreep(); writer.WriteLine("[{0}][{1}][{2}]", bookToken.Author, bookToken.Title, volumeToken.Title); writer.WriteLine(); writer.WriteLine("≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡"); writer.WriteLine(); writer.WriteLine(" 书名:{0}", bookToken.Title); writer.WriteLine(" 作者:{0}", bookToken.Author); writer.WriteLine(" 来源:{0}", bookToken.Uri.Host); writer.WriteLine(); writer.WriteLine(" 本资源由小说下载插件 {0}({1}) v{2} 【{3}】 扫描提供。", this.Plugin.DisplayName, this.Plugin.Name, this.Plugin.Version, this.Plugin.Description); writer.WriteLine(); writer.WriteLine("≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡"); writer.WriteLine(); writer.WriteLine(); writer.WriteLine(volumeToken.Title); writer.WriteLine(); writer.Flush(); foreach (NDTChapter chapterToken in volumeToken.Children) { chapterToken.CreepStarted += (sender, e) => { this.LogWriter.WriteLine("\t\t\t开始下载章节【{0}】”", chapterToken.Title); writer.WriteLine(); writer.WriteLine(); writer.WriteLine(chapterToken.Title); writer.WriteLine(); }; chapterToken.CreepFetched += (sender, e) => { writer.WriteLine(" {0}", e.Data); }; chapterToken.CreepFinished += (sender, e) => { this.LogWriter.WriteLine("\t\t\t章节【{0}】下载完成。\n", chapterToken.Title); writer.WriteLine(); }; chapterToken.StartCreep(); } writer.Flush(); writer.Close(); writer.Dispose(); } }
public void SaveTo(NDTBook bookToken, string outputDir) { this.manager.SaveTo(bookToken, outputDir); }
public abstract bool TryGetBookToken(Uri uri, out NDTBook bookToken);
/// <summary> /// 异步将书籍输出到文件。 /// </summary> /// <param name="bookToken">书籍节点。</param> /// <param name="outputDir">输出目录。</param> public virtual Task WriteAsync(NDTBook bookToken, string outputDir) { return(Task.Run(() => Write(bookToken, outputDir))); }
/// <summary> /// 子类提供输出书籍的实现。 /// </summary> /// <param name="bookToken">书籍节点。</param> /// <param name="outputDir">输出目录。</param> protected abstract void WriteInternal(NDTBook bookToken, string outputDir);