/// <summary> /// コメントをダウンロードする /// </summary> private async Task <IAttemptResult> TryDownloadCommentAsync(IDownloadSettings settings, IWatchSession session, Action <string> onMessage, IDownloadContext context, CancellationToken token) { Cdl::ICommentDownloader? v1 = null; V2Comment::ICommentDownloader?v2 = null; if (settings.EnableExperimentalCommentSafetySystem) { v2 = DIFactory.Provider.GetRequiredService <V2Comment::ICommentDownloader>(); } else { v1 = DIFactory.Provider.GetRequiredService <Cdl::ICommentDownloader>(); } IAttemptResult result; try { result = v2 is null ? await v1 !.DownloadComment(session, settings, onMessage, context, token) : await v2.DownloadCommentAsync(session.Video !.DmcInfo, settings, context, token); } catch (Exception e) { this.logger.Error("コメントのダウンロードに失敗しました。", e); return(AttemptResult.Fail($"コメントのダウンロードに失敗しました。({e.Message})")); } return(result); }
private string GetFileName(IWatchSession session, IDownloadSettings settings) { string?economySuffix = session.Video !.DmcInfo.IsEnonomy ? settings.EconomySuffix : null; string?suffix = economySuffix; string ext = settings.SaveWithoutEncode ? FileFolder.TsFileExt : FileFolder.Mp4FileExt; string format = string.IsNullOrEmpty(settings.FileNameFormat) ? Format.DefaultFileNameFormat : settings.FileNameFormat; return(this._pathOrganizer.GetFilePath(format, session.Video !.DmcInfo, ext, settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite, suffix)); }
public DownloadHelper(IDownloadSettings downloadSettings, IDownloadStreamManager downloadStreamManager) { NetworkProtocolProviderFactory networkProtocolProviderFactory = new NetworkProtocolProviderFactory(new UrlProtocolParser()); HttpProtocolProvider httpProtocolProvider = new HttpProtocolProvider(new WebRequestManager(new WebRequestFactory())); networkProtocolProviderFactory.RegisterProvider("http", httpProtocolProvider); networkProtocolProviderFactory.RegisterProvider("https", httpProtocolProvider); m_EventManager = new EventManager(); m_DownloadManager = new DownloadManager( downloadSettings, downloadStreamManager, networkProtocolProviderFactory, m_EventManager); }
/// <summary> /// Initializes a new instance of the <see cref="DownloadTask"/> class. /// </summary> /// <param name="networkProtocolProviderFactory">The network protocol provider factory.</param> /// <param name="downloadSegmentCalculator">The download segment calculator.</param> /// <param name="downloadStreamManager">The download stream manager.</param> /// <param name="settings">The settings.</param> /// <param name="file">The file.</param> /// <param name="eventManager">The event manager.</param> public DownloadTask( INetworkProtocolProviderFactory networkProtocolProviderFactory, IDownloadSegmentPositionsCalculator downloadSegmentCalculator, IDownloadStreamManager downloadStreamManager, IDownloadSettings settings, DownloadFileInfo file, IEventManager eventManager) { m_NetworkProtocolProviderFactory = networkProtocolProviderFactory; m_DownloadSegmentCalculator = downloadSegmentCalculator; m_Settings = settings; m_File = file; m_DownloadStreamManager = downloadStreamManager; m_EventManager = eventManager; m_CreateDate = DateTime.Now; }
/// <summary> /// 非同期で動画をダウンロードする /// </summary> private async Task <IAttemptResult> TryDownloadVideoAsync(IDownloadSettings settings, Action <string> onMessage, IWatchSession session, IDownloadContext context, CancellationToken token) { var videoDownloader = DIFactory.Provider.GetRequiredService <Vdl::IVideoDownloader>(); IAttemptResult result; try { result = await videoDownloader.DownloadVideoAsync(settings, onMessage, context, session, token); } catch (Exception e) { this.logger.Error($"動画のダウンロードに失敗しました。({context.GetLogContent()})", e); return(AttemptResult.Fail($"動画のダウンロードに失敗しました。(詳細:{e.Message})")); } return(result); }
/// <summary> /// 市場情報をダウンロードする /// </summary> private async Task <IAttemptResult> DownloadIchibaInfoAsync(IDownloadSettings settings, IWatchSession session, Action <string> onMessage, IDownloadContext context) { var iDownloader = DIFactory.Provider.GetRequiredService <IIchibaInfoDownloader>(); IAttemptResult result; try { result = await iDownloader.DownloadIchibaInfo(session, settings, onMessage, context); } catch (Exception e) { this.logger.Error("市場情報のダウンロードに失敗しました。", e); return(AttemptResult.Fail($"市場情報のダウンロードに失敗しました。({e.Message})")); } return(result); }
public DownloadManager(IDownloadSettings downloadSettings, IDownloadStreamManager downloadStreamManager, INetworkProtocolProviderFactory networkProtocolProviderFactory, IEventManager eventManager) { if (downloadSettings == null) { throw new ArgumentNullException("downloadSettings"); } m_DownloadTaskList = new DownloadTaskList(); m_DownloadTaskQueue = new DownloadTaskQueue(downloadSettings.MaximumConcurrentDownloads); m_DownloadSettings = downloadSettings; m_LocalFileDownloadStreamManager = downloadStreamManager; m_NetworkProtocolProviderFactory = networkProtocolProviderFactory; m_EventManager = eventManager; }
/// <summary> /// サムネイルをダウンロードする /// </summary> private async Task <IAttemptResult> TryDownloadThumbAsync(IDownloadSettings setting, IWatchSession session) { var thumbDownloader = DIFactory.Provider.GetRequiredService <Tdl::IThumbDownloader>(); IAttemptResult result; try { result = await thumbDownloader.DownloadThumbnailAsync(setting, session); } catch (Exception e) { this.logger.Error($"サムネイルのダウンロードに失敗しました。", e); return(AttemptResult.Fail($"サムネイルのダウンロードに失敗しました。(詳細:{e.Message})")); } return(result); }
public async Task <IAttemptResult> DownloadThumbnailAsync(IDownloadSettings settings, IWatchSession session) { if (session.Video is null) { return(AttemptResult.Fail("動画情報が未取得です。")); } var filepath = this._pathOrganizer.GetFilePath(settings.FileNameFormat, session.Video !.DmcInfo, settings.ThumbnailExt, settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite, settings.ThumbSuffix); string?thumbUrl; try { thumbUrl = session.Video !.DmcInfo.ThumbInfo.GetSpecifiedThumbnail(settings.ThumbSize); } catch (Exception e) { this._logger.Error($"サムネイルURLの取得に失敗しました。", e); return(AttemptResult.Fail("サムネイルのURLを取得できませんでした。")); } byte[] data; try { data = await this.DownloadAsync(thumbUrl); } catch (Exception e) { this._logger.Error($"サムネイルの取得に失敗しました。", e); return(AttemptResult.Fail($"サムネイルの取得に失敗しました。(詳細: {e.Message})")); } try { this.WriteThumb(data, filepath); } catch (Exception e) { this._logger.Error($"サムネイルの保存に失敗しました。", e); return(AttemptResult.Fail($"サムネイルの保存に失敗しました。(詳細: {e.Message})")); } return(AttemptResult.Succeeded()); }
/// <summary> /// 動画情報をダウンロードする /// </summary> private IAttemptResult TryDownloadDescriptionAsync(IDownloadSettings settings, IWatchSession session, Action <string> onMessage) { var descriptionDownloader = DIFactory.Provider.GetRequiredService <DDL::IDescriptionDownloader>(); IAttemptResult result; try { result = descriptionDownloader.DownloadVideoInfoAsync(settings, session, onMessage); } catch (Exception e) { this.logger.Error($"動画情報のダウンロードに失敗しました。", e); return(AttemptResult.Fail($"動画情報のダウンロードに失敗しました。(詳細:{e.Message})")); } return(result); }
/// <summary> /// 動画情報ファイルを保存する /// </summary> /// <param name="setting"></param> /// <param name="dmcInfo"></param> /// <returns></returns> public IAttemptResult DownloadVideoInfoAsync(IDownloadSettings setting, IWatchSession session, Action <string> onMessage) { if (session.Video is null) { return(AttemptResult.Fail("動画情報が未取得です。")); } onMessage($"動画情報の保存を開始します。"); this._logger.Log($"{session.Video.Id}の動画情報保存を開始"); string fileName = this._pathOrganizer.GetFilePath(setting.FileNameFormat, session.Video.DmcInfo, setting.VideoInfoExt, setting.FolderPath, setting.IsReplaceStrictedEnable, setting.Overwrite, setting.VideoInfoSuffix); var filePath = Path.Combine(setting.FolderPath, fileName); string content = setting.VideoInfoType switch { VideoInfoTypeSettings.Json => this._producer.GetJsonContent(session.Video.DmcInfo), VideoInfoTypeSettings.Xml => this._producer.GetXmlContent(session.Video.DmcInfo), _ => this._producer.GetContent(session.Video.DmcInfo), }; try { IOUtils.CreateDirectoryIfNotExist(fileName); this._fileIO.Write(filePath, content); } catch (Exception e) { onMessage("動画情報ファイルの書き込みに失敗しました。"); this._logger.Error("動画情報ファイルの書き込みに失敗しました。", e); return(AttemptResult.Fail($"動画情報ファイルの書き込みに失敗しました。(詳細:{e.Message})")); } onMessage($"動画情報ファイルを保存しました。"); return(AttemptResult.Succeeded()); }
public async Task <IAttemptResult> DownloadIchibaInfo(IWatchSession session, IDownloadSettings settings, Action <string> onMessage, IDownloadContext context) { if (session.Video is null) { return(new AttemptResult() { Message = "セッション情報のVideoがnullです。" }); } onMessage($"市場APIへのアクセスを開始します。({session.Video.Id})"); var getResult = await this._niconicoIchibaHandler.GetIchibaInfo(session.Video.Id); if (!getResult.IsSucceeded || getResult.Data is null) { onMessage($"市場APIからの情報取得に失敗しました。({session.Video.Id})"); if (getResult.Exception is not null) { this._logger.Error($"市場情報の取得に失敗しました。(詳細:{getResult.Message} ,{context.GetLogContent()})", getResult.Exception); } else { this._logger.Error($"市場情報の取得に失敗しました。(詳細:{getResult.Message} ,{context.GetLogContent()})"); } return(new AttemptResult() { Message = getResult.Message }); } onMessage($"市場APIからの情報取得を取得しました。({session.Video.Id})"); string content; if (settings.IchibaInfoType != IchibaInfoTypeSettings.Html) { try { content = this.GetContent(getResult.Data, settings.IchibaInfoType == IchibaInfoTypeSettings.Xml); } catch (Exception e) { this._logger.Error($"市場情報のシリアル化に失敗しました。(詳細:{getResult.Message} ,{context.GetLogContent()})", e); onMessage($"市場情報のシリアル化に失敗しました。({session.Video.Id})"); return(new AttemptResult() { Message = "市場情報のシリアル化に失敗しました。" }); } } else { try { content = this.GetHtmlContent(getResult.Data, session.Video.Id); } catch (Exception e) { this._logger.Error($"市場情報のシリアル化に失敗しました。(詳細:{getResult.Message} ,{context.GetLogContent()})", e); onMessage($"市場情報のシリアル化に失敗しました。({session.Video.Id})"); return(new AttemptResult() { Message = "市場情報のシリアル化に失敗しました。" }); } } string filePath = this._path.GetFilePath(settings.FileNameFormat, session.Video !.DmcInfo, settings.IchibaInfoExt, settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite, settings.IchibaInfoSuffix); try { this._fileIO.Write(filePath, content); } catch (Exception e) { this._logger.Error($"市場情報ファイルの書き込みに失敗しました。({context.GetLogContent()})", e); onMessage($"市場情報ファイルの書き込みに失敗しました。({session.Video.Id})"); return(new AttemptResult() { Message = $"市場情報ファイルの書き込みに失敗しました。(詳細:{e.Message})" }); } onMessage($"市場情報ファイルの保存が完了しました。({session.Video.Id})"); return(new AttemptResult() { IsSucceeded = true }); }
public HtmlLoader(IDownloadSettings settings) { client = new HttpClient(); url = $"{settings.BaseUrl}{settings.RhymeType}/{settings.Word}.html"; }
public Task <IAttemptResult <IDownloadContext> > TryDownloadContentAsync(IListVideoInfo videoInfo, IDownloadSettings setting, Action <string> OnMessage, CancellationToken token) { return(Task.FromResult <IAttemptResult <IDownloadContext> >(AttemptResult <IDownloadContext> .Succeeded(new DownloadContext(string.Empty)))); }
public async Task <IAttemptResult <IDownloadContext> > TryDownloadContentAsync(IListVideoInfo videoInfo, IDownloadSettings setting, Action <string> OnMessage, CancellationToken token) { var context = new DownloadContext(setting.NiconicoId); var session = DIFactory.Provider.GetRequiredService <IWatchSession>(); context.RegisterMessageHandler(OnMessage); await session.GetVideoDataAsync(setting.NiconicoId); if (session.Video is not null) { this.converter.ConvertDomainVideoInfoToListVideoInfo(videoInfo, session.Video); } if (session.Video?.DmcInfo.DownloadStartedOn is not null) { session.Video.DmcInfo.DownloadStartedOn = DateTime.Now; } if (session.State != WatchSessionState.GotPage || session.Video is null) { string message = session.State switch { WatchSessionState.PaymentNeeded => "視聴ページの解析に失敗しました。", WatchSessionState.HttpRequestOrPageAnalyzingFailure => "視聴ページの取得、または視聴ページの解析に失敗しました。", _ => "不明なエラーにより、視聴ページの取得に失敗しました。" }; return(AttemptResult <IDownloadContext> .Fail(message)); } if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } ILocalContentInfo?info = null; if (setting.Skip) { string fileNameFormat = setting.FileNameFormat; info = this.localContentHandler.GetLocalContentInfo(setting.FolderPath, fileNameFormat, session.Video.DmcInfo, setting.IsReplaceStrictedEnable, setting.VideoInfoExt, setting.IchibaInfoExt, setting.ThumbnailExt, setting.IchibaInfoSuffix, setting.VideoInfoSuffix); } if (!Directory.Exists(setting.FolderPath)) { Directory.CreateDirectory(setting.FolderPath); } //動画 if (setting.Video) { if (info?.VideoExist ?? false) { OnMessage("動画を保存済みのためスキップしました。"); } else if (setting.FromAnotherFolder && (info?.VIdeoExistInOnotherFolder ?? false) && info?.LocalPath is not null) { var vResult = this.localContentHandler.MoveDownloadedFile(setting.NiconicoId, info.LocalPath, setting.FolderPath); if (!vResult.IsSucceeded) { return(AttemptResult <IDownloadContext> .Fail(vResult.Message ?? "None")); } else { OnMessage("別フォルダーに保存済みの動画をコピーしました。"); } } else { var vResult = await this.TryDownloadVideoAsync(setting, OnMessage, session, context, token); if (!vResult.IsSucceeded) { OnMessage("DL失敗"); return(AttemptResult <IDownloadContext> .Fail(vResult.Message ?? "None")); } } } if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } //サムネイル if (setting.Thumbnail) { if (!info?.ThumbExist ?? true) { var tResult = await this.TryDownloadThumbAsync(setting, session); if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } if (!tResult.IsSucceeded) { OnMessage("DL失敗"); return(AttemptResult <IDownloadContext> .Fail(tResult.Message ?? "None")); } } else if (info?.ThumbExist ?? false) { OnMessage("サムネイルを保存済みのためスキップしました。"); } } if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } //コメント if (setting.Comment) { if (!info?.CommentExist ?? true) { var cResult = await this.TryDownloadCommentAsync(setting, session, OnMessage, context, token); if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } if (!cResult.IsSucceeded) { OnMessage("DL失敗"); return(AttemptResult <IDownloadContext> .Fail(cResult.Message ?? "None")); } } else if (info?.CommentExist ?? false) { OnMessage("コメントを保存済みのためスキップしました。"); } } if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } //動画情報 if (setting.DownloadVideoInfo) { if (!info?.VideoInfoExist ?? true) { var iResult = this.TryDownloadDescriptionAsync(setting, session, OnMessage); if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } if (!iResult.IsSucceeded) { OnMessage("DL失敗"); return(AttemptResult <IDownloadContext> .Fail(iResult.Message ?? "None")); } } } if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } //市場情報 if (setting.DownloadIchibaInfo) { if (!info?.IchibaInfoExist ?? true) { var iResult = await this.DownloadIchibaInfoAsync(setting, session, OnMessage, context); if (token.IsCancellationRequested) { return(this.CancelledDownloadAndGetResult()); } if (!iResult.IsSucceeded) { OnMessage("DL失敗"); return(AttemptResult <IDownloadContext> .Fail(iResult.Message ?? "None")); } } else { OnMessage("市場情報を保存済みのためスキップしました。"); } } if (session.IsSessionEnsured) { session.Dispose(); } return(AttemptResult <IDownloadContext> .Succeeded(context)); }
private async Task <IAttemptResult> EncodeVideosAsync(IWatchSession session, IDownloadContext context, IDownloadSettings settings, Action <string> onMessage, IEnumerable <string> segmentFilePaths, CancellationToken token) { var encodeSetting = new EncodeSettings() { FilePath = context.FileName, CommandFormat = settings.CommandFormat, TsFilePaths = segmentFilePaths, IsOverwriteEnable = settings.Overwrite, IsOverrideDTEnable = settings.OverrideVideoFileDateToUploadedDT, UploadedOn = session.Video !.DmcInfo.UploadedOn, IsNoEncodeEnable = settings.SaveWithoutEncode, }; try { await this._encorder.EncodeAsync(encodeSetting, onMessage, token); } catch (Exception e) { this._logger.Error($"ファイルの変換中にエラーが発生しました。({this.context!.GetLogContent()})", e); onMessage("動画の変換中にエラー発生"); return(AttemptResult.Fail($"ファイルの変換中にエラーが発生しました。(詳細: {e.Message})")); } return(AttemptResult.Succeeded()); }
private async Task <IAttemptResult> EnsureSessionAsync(IWatchSession session, IDownloadSettings settings) { await session.EnsureSessionAsync(settings.NiconicoId); if (!session.IsSessionEnsured) { string message = session.State switch { WatchSessionState.HttpRequestOrPageAnalyzingFailure => "視聴ページの取得、または解析に失敗しました。", WatchSessionState.EncryptedVideo => "暗号化された動画のため、ダウンロードできません。", WatchSessionState.SessionEnsuringFailure => "セッションの確立に失敗しました。", _ => "不明なエラーにより、セッションの確立に失敗しました。" }; return(AttemptResult.Fail(message)); } else { this._logger.Log($"視聴セッションを確立しました。({this.context!.GetLogContent()})"); return(AttemptResult.Succeeded()); } }
public RhymesDownloader(IParser <T> parser, IDownloadSettings downloadSettings) : this(parser) { Settings = downloadSettings; }
public async Task <IAttemptResult> DownloadVideoAsync(IDownloadSettings settings, Action <string> onMessage, IDownloadContext context, IWatchSession session, CancellationToken token) { IAttemptResult OnCanceled() { this._logger.Log($"ユーザーの操作によって動画のダウンロード処理がキャンセルされました。({context.GetLogContent()})"); onMessage("ダウンロードをキャンセル"); return(AttemptResult.Fail("処理がキャンセルされました")); } this.context = context; this._logger.Log($"動画のダウンロードを開始しました。({context.GetLogContent()})"); if (session.IsSessionExipired) { this._logger.Log($"セッションが失効していたため動画のダウンロードをキャンセルします。({context.GetLogContent()})"); return(AttemptResult <string> .Fail("セッションが失効済のためダウンロード出来ません。")); } if (!session.IsSessionEnsured) { if (token.IsCancellationRequested) { return(OnCanceled()); } IAttemptResult sessionR = await this.EnsureSessionAsync(session, settings); if (!sessionR.IsSucceeded) { onMessage(sessionR.Message ?? ""); return(sessionR); } } //ファイル名取得 string fileName = this.GetFileName(session, settings); context.FileName = fileName; if (token.IsCancellationRequested) { return(OnCanceled()); } //ストリーム系 IAttemptResult <IStreamInfo> streamResult = await this.GetStream(session, settings.VerticalResolution); if (!streamResult.IsSucceeded || streamResult.Data is null) { return(AttemptResult.Fail(streamResult.Message, streamResult.Exception)); } IStreamInfo targetStream = streamResult.Data; List <string> rawsegmentFilePaths = targetStream.StreamUrls.Select(u => u.FileName).ToList(); context.ActualVerticalResolution = targetStream.Resolution?.Vertical ?? 0; context.OriginalSegmentsCount = targetStream.StreamUrls.Count; if (token.IsCancellationRequested) { return(OnCanceled()); } //レジューム系 string segmentDirectoryName; IAttemptResult <string> sResult = settings.ResumeEnable ? this.GetAndSetSegmentsDirectoryInfoIfExists(settings.NiconicoId, targetStream.Resolution?.Vertical ?? 0, targetStream) : AttemptResult <string> .Fail(); if (sResult.IsSucceeded && sResult.Data is not null) { segmentDirectoryName = sResult.Data; onMessage("DLをレジューム"); this._logger.Log($"ダウンロードをレジュームします。({context.GetLogContent()})"); } else { segmentDirectoryName = $"{settings.NiconicoId}-{targetStream.Resolution?.Vertical ?? 0}-{DateTime.Now.ToString("yyyy-MM-dd")}"; } List <string> segmentFilePaths = rawsegmentFilePaths.Select(p => Path.Combine(AppContext.BaseDirectory, "tmp", segmentDirectoryName, p)).ToList(); //DL系 IAttemptResult downloadresult = await this.DownloadVideoInternalAsync(targetStream, onMessage, context, settings.MaxParallelSegmentDLCount, segmentDirectoryName, token); if (!downloadresult.IsSucceeded) { return(downloadresult); } if (token.IsCancellationRequested) { return(OnCanceled()); } onMessage("動画を変換中..."); IAttemptResult encodeResult = await this.EncodeVideosAsync(session, context, settings, onMessage, segmentFilePaths, token); if (!encodeResult.IsSucceeded) { return(encodeResult); } onMessage("動画の変換が完了"); this.DeleteTmpFolder(segmentDirectoryName, onMessage); bool isEconomy = session.Video !.DmcInfo.IsEnonomy; if (settings.IsEconomy && settings.DeleteExistingEconomyFile && !isEconomy) { this.RemoveEconomyFile(settings.FilePath); } this._fileStorehandler.Add(settings.NiconicoId, Path.Combine(settings.FolderPath, fileName)); this._logger.Log($"動画のダウンロードが完了しました。({context.GetLogContent()})"); return(AttemptResult.Succeeded()); }
/// <summary> /// コメントをダウンロードする /// </summary> /// <param name="dmcInfo"></param> /// <param name="settings"></param> /// <returns></returns> public async Task <ICommentCollection> DownloadCommentAsync(IDmcInfo dmcInfo, IDownloadSettings settings, Action <string> onMessage, IDownloadContext context, CancellationToken token) { var(dThread, dFork) = this.GetDefaultPosyTarget(dmcInfo); if (dThread == -1 || dFork == -1) { throw new InvalidOperationException("DefaultPostTargetが見つかりません。"); } var comments = CommentCollection.GetInstance(settings.CommentOffset, dThread, dFork, settings.EnableUnsafeCommentHandle, settings.EnableExperimentalCommentSafetySystem); Response::Chat?first = null; int index = 0; long lastNo = 0; do { int count = comments.Count; if (index > 0) { if (settings.CommentFetchWaitSpan > 0) { onMessage($"待機中...({settings.CommentFetchWaitSpan}ms)"); try { await Task.Delay(settings.CommentFetchWaitSpan, token); } catch { } } onMessage($"過去ログをダウンロード中({index + 1}件目・{count}コメ)"); } long?when = count == 0 ? 0 : first?.Date - 1; List <Response::Comment> retlieved = await this.GetCommentsAsync(dmcInfo, settings, when); comments.Add(retlieved); if (index > 0) { this.logger.Log($"過去ログをダウンロードしました。({index}個目, {retlieved.Count}コメント, {context.GetLogContent()})"); } else { this.logger.Log($"現行スレッドをダウンロードしました。({retlieved.Count}コメント, {context.GetLogContent()})"); } first = comments.GetFirstComment(false); if ((first?.No ?? 0) == lastNo) { break; } else { lastNo = first?.No ?? 0; } if (settings.MaxCommentsCount > 0 && comments.Count > settings.MaxCommentsCount) { var rmCount = comments.Count - settings.MaxCommentsCount; comments.RemoveFor(rmCount); break; } if (!settings.DownloadLog) { break; } else if (index == 0) { onMessage("過去ログのダウンロードを開始します。"); } ++index; } while (first?.No > 1 && !token.IsCancellationRequested); if (token.IsCancellationRequested) { throw new TaskCanceledException("コメントのダウンロードがキャンセルされました。"); } onMessage($"コメントの正規化処理を開始します。"); comments.Distinct(); onMessage($"コメントの正規化処理が完了しました。"); this.logger.Log($"コメントのダウンロードが完了しました。({comments.Count}コメント, {context.GetLogContent()})"); return(comments); }
/// <summary> /// コメントを取得する /// </summary> /// <param name="dmcInfo"></param> /// <param name="settings"></param> /// <param name="when"></param> /// <returns></returns> private async Task <List <Response::Comment> > GetCommentsAsync(IDmcInfo dmcInfo, IDownloadSettings settings, long?when = null) { var option = new CommentOptions() { NoEasyComment = !settings.DownloadEasy, OwnerComment = settings.DownloadOwner, When = when ?? 0 }; var request = await this.requestBuilder.GetRequestDataAsync(dmcInfo, option); string server = dmcInfo.CommentThreads.FirstOrDefault()?.Server ?? @"https://nmsg.nicovideo.jp/api.json"; if (!server.EndsWith("/api.json")) { server += "/api.json"; } var res = await this.http.PostAsync(new Uri(server), new StringContent(request)); if (!res.IsSuccessStatusCode) { throw new HttpRequestException($"コメントの取得に失敗しました。(status_code:{(int)res.StatusCode}, reason_phrase:{res.ReasonPhrase})"); } string content = await res.Content.ReadAsStringAsync(); var data = JsonParser.DeSerialize <List <Response::Comment> >(content); return(data); }
public async Task <IAttemptResult> DownloadComment(IWatchSession session, IDownloadSettings settings, Action <string> onMessage, IDownloadContext context, CancellationToken token) { if (session.Video is null) { return(AttemptResult.Fail("動画情報が未取得です。")); } string filePath = this._pathOrganizer.GetFilePath(settings.FileNameFormat, session.Video !.DmcInfo, ".xml", settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite); string ownerFileName = this._pathOrganizer.GetFilePath(settings.FileNameFormat, session.Video !.DmcInfo, ".xml", settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite, settings.OwnerComSuffix); if (token.IsCancellationRequested) { return(this.GetCancelledResult()); } onMessage("コメントのダウンロードを開始します。"); this._logger.Log($"{settings.NiconicoId}のコメントダウンロードを開始します。({context.GetLogContent()})"); ICommentCollection result; try { result = await this._client.DownloadCommentAsync(session.Video !.DmcInfo, settings, onMessage, context, token); } catch (Exception e) { this._logger.Error($"コメントの取得に失敗しました。({context.GetLogContent()})", e); return(AttemptResult.Fail($"コメントの取得に失敗しました。(詳細:{e.Message})")); } onMessage("コメントのダウンロードが完了しました。"); if (token.IsCancellationRequested) { return(this.GetCancelledResult()); } onMessage("コメントの変換処理を開始します。"); IStoreCommentsData data; try { data = this._commentConverter.ConvertToStoreCommentsData(result, settings); } catch (Exception e) { this._logger.Error($"コメントの解析に失敗しました。({context.GetLogContent()})", e); return(AttemptResult.Fail($"コメントの解析に失敗しました。")); } onMessage("コメントの変換処理が完了しました。"); data.FilePath = filePath; data.OwnerFilPath = ownerFileName; if (token.IsCancellationRequested) { return(this.GetCancelledResult()); } onMessage($"コメントの書き込みを開始します。"); try { this._commentStream.Write(data, settings.Overwrite); } catch (Exception e) { this._logger.Error($"コメントの書き込みに失敗しました。({context.GetLogContent()})", e); return(AttemptResult.Fail("コメントの書き込みに失敗しました。")); } onMessage("コメントのダウンロードが完了しました。"); this._logger.Log($"コメントのダウンロードが完了しました。({context.GetLogContent()})"); return(AttemptResult.Succeeded()); }
public async Task <IAttemptResult> DownloadCommentAsync(IDmcInfo dmcInfo, IDownloadSettings settings, IDownloadContext context, CancellationToken token) { //コメント追記処理 var origination = DateTime.Now; var originationSpecidied = false; var oldComments = new List <Core::IComment>(); if (settings.AppendingToLocalComment && this._commentLoader.CommentExists(settings.FolderPath, settings.NiconicoId)) { IAttemptResult <Local::LocalCommentInfo> localResult = this._commentLoader.LoadComment(settings.FolderPath, settings.NiconicoId); if (localResult.IsSucceeded && localResult.Data is not null) { origination = localResult.Data.LastUpdatedTime; originationSpecidied = true; oldComments.AddRange(localResult.Data.Comments); } } //キャンセル処理 token.ThrowIfCancellationRequested(); //コメント取得処理 var dlOption = new Fetch::CommentClientOption(originationSpecidied, origination); IAttemptResult <(Core::ICommentCollection, Core::IThreadInfo)> dlResult = await this._commentClient.DownloadCommentAsync(dmcInfo, settings, dlOption, context, token); if (!dlResult.IsSucceeded) { return(AttemptResult.Fail(dlResult.Message)); } //キャンセル処理 token.ThrowIfCancellationRequested(); //コメント統合処理 var(collection, threadInfo) = dlResult.Data; if (oldComments.Count > 0) { foreach (var comment in oldComments) { collection.Add(comment); } } //コメント書き込み処理 string path = this._path.GetFilePath(settings.FileNameFormat, dmcInfo, ".xml", settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite); var writerOption = new Local::CommentWriterOption(path, settings.OmittingXmlDeclaration, dmcInfo.Id); IAttemptResult writeResult = this._commentWriter.WriteComment(collection.Comments, threadInfo, writerOption); if (!writeResult.IsSucceeded) { return(writeResult); } //キャンセル処理 token.ThrowIfCancellationRequested(); //コメ数記録 context.CommentCount = collection.Count; return(AttemptResult.Succeeded()); }