/// <summary> /// ニコニコ動画コンテンツの情報を取得します。 /// 内部DB、サムネイル、Watchページのアクセス情報から更新されたデータを提供します。 /// /// </summary> /// <param name="rawVideoId"></param> /// <returns></returns> public async Task <Database.NicoVideo> GetNicoVideoInfo(string rawVideoId, bool requireLatest = false) { if (NiconicoSession.ServiceStatus.IsOutOfService()) { return(null); } using (await _ThumbnailAccessLock.LockAsync()) { var info = NicoVideoDb.Get(rawVideoId); // 最新情報が不要な場合は内部DBのキャッシュをそのまま返す if (info != null && !requireLatest) { if (info.ViewCount != 0 && info.LastUpdated > DateTime.Now - ThumbnailExpirationSpan) { return(info); } } if (info == null) { info = new Database.NicoVideo() { RawVideoId = rawVideoId }; } try { var res = await ContextActionAsync(async context => { return(await context.Search.GetVideoInfoAsync(rawVideoId)); }); if (res.Status == "ok") { var video = res.Video; info.Title = video.Title; info.VideoId = video.Id; info.Length = video.Length; info.PostedAt = video.FirstRetrieve; info.ThumbnailUrl = video.ThumbnailUrl.OriginalString; info.ViewCount = (int)video.ViewCount; info.MylistCount = (int)video.MylistCount; info.CommentCount = (int)res.Thread.GetCommentCount(); info.Tags = res.Tags.TagInfo.Select(x => new NicoVideoTag() { Id = x.Tag, } ).ToList(); if (res.Video.ProviderType == "channel") { info.Owner = new NicoVideoOwner() { OwnerId = res.Video.CommunityId, UserType = UserType.Channel }; } else { info.Owner = new NicoVideoOwner() { OwnerId = res.Video.UserId, UserType = res.Video.ProviderType == "regular" ? UserType.User : UserType.Channel }; } info.IsDeleted = res.Video.IsDeleted; if (info.IsDeleted && int.TryParse(res.Video.__deleted, out int deleteType)) { try { info.PrivateReasonType = (PrivateReasonType)deleteType; } catch { } } } else { info.IsDeleted = true; } } catch (Exception ex) when(ex.Message.Contains("DELETE") || ex.Message.Contains("NOT_FOUND")) { info.IsDeleted = true; } finally { NicoVideoDb.AddOrUpdate(info); if (info.Owner != null) { NicoVideoOwnerDb.AddOrUpdate(info.Owner); } } if (info.IsDeleted) { PublishVideoDeletedEvent(info); } await Task.Delay(25); return(info); } }
public async Task <DmcWatchData> GetDmcWatchResponse(string rawVideoId) { if (NiconicoSession.ServiceStatus.IsOutOfService()) { return(null); } // TODO: 有害動画に指定されたページにアクセスした場合の対応 // 有害動画ページにアクセスしたら一度だけ確認ページをダイアログ表示する // (ユーザーのアクションによらず)再度ページを読み込んで、もう一度HurmfulContentが返ってきた場合はnullを返す HarmfulContentReactionType harmfulContentReactionType = HarmfulContentReactionType.None; { try { var data = await Helpers.ConnectionRetryUtil.TaskWithRetry(async() => { return(await ContextActionWithPageAccessWaitAsync(async context => { return await context.Video.GetDmcWatchResponseAsync( rawVideoId , harmfulReactType: harmfulContentReactionType ); })); }); var res = data?.DmcWatchResponse; var info = NicoVideoDb.Get(rawVideoId); if (res != null) { if (info == null) { info = new Database.NicoVideo() { RawVideoId = rawVideoId }; } info.VideoId = res.Video.Id; info.Title = res.Video.Title; info.Length = TimeSpan.FromSeconds(res.Video.Duration); info.PostedAt = DateTime.Parse(res.Video.PostedDateTime); info.ThumbnailUrl = res.Video.ThumbnailURL; info.DescriptionWithHtml = res.Video.Description; info.ViewCount = res.Video.ViewCount; info.MylistCount = res.Video.MylistCount; info.CommentCount = res.Thread.CommentCount; switch (res.Video.MovieType) { case @"mp4": info.MovieType = MovieType.Mp4; break; case @"flv": info.MovieType = MovieType.Flv; break; case @"swf": info.MovieType = MovieType.Swf; break; } info.Tags = res.Tags.Select(x => new NicoVideoTag() { Name = x.Name, IsCategory = x.IsCategory, IsLocked = x.IsLocked, Id = x.Id, IsDictionaryExists = x.IsDictionaryExists }).ToList(); if (res.Owner != null) { info.Owner = new NicoVideoOwner() { ScreenName = res.Owner.Nickname, IconUrl = res.Owner.IconURL, OwnerId = res.Owner.Id, UserType = UserType.User }; NicoVideoOwnerDb.AddOrUpdate(info.Owner); } else if (res.Channel != null) { info.Owner = new NicoVideoOwner() { ScreenName = res.Channel.Name, IconUrl = res.Channel.IconURL, OwnerId = res.Channel.GlobalId, UserType = UserType.Channel }; } if (data.DmcWatchResponse?.Video != null) { info.IsDeleted = data.DmcWatchResponse.Video.IsDeleted; } NicoVideoDb.AddOrUpdate(info); } if (info.IsDeleted) { PublishVideoDeletedEvent(info); } return(data); } catch (AggregateException ea) when(ea.Flatten().InnerExceptions.Any(e => e is ContentZoningException)) { throw new NotImplementedException("not implement hurmful video content."); } catch (Mntone.Nico2.ContentZoningException) { throw new NotImplementedException("not implement hurmful video content."); } } }
public async Task <WatchApiResponse> GetWatchApiResponse(string rawVideoId, bool forceLowQuality = false) { if (NiconicoSession.ServiceStatus.IsOutOfService()) { return(null); } if (!NiconicoSession.IsLoggedIn) { return(null); } // TODO: 有害動画に指定されたページにアクセスした場合の対応 HarmfulContentReactionType harmfulContentReactionType = HarmfulContentReactionType.None; { try { var res = await Helpers.ConnectionRetryUtil.TaskWithRetry(async() => { return(await ContextActionWithPageAccessWaitAsync(async context => { return await context.Video.GetWatchApiAsync( rawVideoId , forceLowQuality: forceLowQuality , harmfulReactType: harmfulContentReactionType ); })); }); var info = NicoVideoDb.Get(rawVideoId); if (info == null) { info = new Database.NicoVideo() { RawVideoId = rawVideoId }; } info.VideoId = res.videoDetail.id; info.Title = res.videoDetail.title; info.Length = res.videoDetail.length.HasValue ? TimeSpan.FromSeconds(res.videoDetail.length.Value) : TimeSpan.Zero; info.PostedAt = DateTime.Parse(res.videoDetail.postedAt); info.ThumbnailUrl = res.videoDetail.thumbnail; info.DescriptionWithHtml = res.videoDetail.description; info.ViewCount = res.videoDetail.viewCount ?? 0; info.MylistCount = res.videoDetail.mylistCount ?? 0; info.CommentCount = res.videoDetail.commentCount ?? 0; switch (res.flashvars.movie_type) { case @"mp4": info.MovieType = MovieType.Mp4; break; case @"flv": info.MovieType = MovieType.Flv; break; case @"swf": info.MovieType = MovieType.Swf; break; } info.Tags = res.videoDetail.tagList.Select(x => new NicoVideoTag() { Name = x.tag, IsCategory = x.cat ?? false, IsLocked = x.lck == "1", /* TODO: lck 値が不明です */ Id = x.id, IsDictionaryExists = x.dic ?? false }).ToList(); info.Owner = new NicoVideoOwner() { ScreenName = res.UploaderInfo?.nickname ?? res.channelInfo?.name, IconUrl = res.UploaderInfo?.icon_url ?? res.channelInfo?.icon_url, OwnerId = res.UploaderInfo?.id ?? res.channelInfo?.id, UserType = res.channelInfo != null ? UserType.Channel : UserType.User }; info.IsDeleted = res.IsDeleted; info.PrivateReasonType = res.PrivateReason; NicoVideoDb.AddOrUpdate(info); // NicoVideoOwnerDb.AddOrUpdate(info.Owner); if (info.IsDeleted) { PublishVideoDeletedEvent(info); } return(res); } catch (AggregateException ea) when(ea.Flatten().InnerExceptions.Any(e => e is ContentZoningException)) { throw new NotImplementedException("not implement hurmful video content."); } catch (ContentZoningException) { throw new NotImplementedException("not implement hurmful video content."); } } }
/// <summary> /// ニコニコ動画コンテンツの情報を取得します。 /// 内部DB、サムネイル、Watchページのアクセス情報から更新されたデータを提供します。 /// /// </summary> /// <param name="rawVideoId"></param> /// <returns></returns> public async Task <Database.NicoVideo> GetNicoVideoInfo(string rawVideoId, bool requireLatest = false) { if (Context == null) { return(null); } using (var releaser = await _ThumbnailAccessLock.LockAsync()) { var info = NicoVideoDb.Get(rawVideoId); // 最新情報が不要な場合は内部DBのキャッシュをそのまま返す if (info != null && !requireLatest) { if (info.LastUpdated > DateTime.Now - ThumbnailExpirationSpan) { return(info); } } if (info == null) { info = new Database.NicoVideo() { RawVideoId = rawVideoId }; } try { var res = await Helpers.ConnectionRetryUtil.TaskWithRetry(() => { return(Context.Search.GetVideoInfoAsync(rawVideoId)); }, retryCount : 5, retryInterval : 1000 ); if (res.Status == "ok") { var video = res.Video; info.Title = video.Title; info.VideoId = video.Id; info.Length = video.Length; info.PostedAt = video.FirstRetrieve; info.ThumbnailUrl = video.ThumbnailUrl.OriginalString; info.ViewCount = (int)video.ViewCount; info.MylistCount = (int)video.MylistCount; info.CommentCount = (int)res.Thread.GetCommentCount(); info.Tags = res.Tags.TagInfo.Select(x => new NicoVideoTag() { Id = x.Tag, } ).ToList(); if (res.Video.ProviderType == "channel") { info.Owner = new NicoVideoOwner() { OwnerId = res.Video.CommunityId, UserType = UserType.Channel }; } else { info.Owner = new NicoVideoOwner() { OwnerId = res.Video.UserId, UserType = res.Video.ProviderType == "regular" ? UserType.User : UserType.Channel }; } info.IsDeleted = res.Video.IsDeleted; if (info.IsDeleted && int.TryParse(res.Video.__deleted, out int deleteType)) { try { info.PrivateReasonType = (PrivateReasonType)deleteType; } catch { } } } else { info.IsDeleted = true; } } catch (Exception ex) when(ex.Message.Contains("DELETE") || ex.Message.Contains("NOT_FOUND")) { info.IsDeleted = true; } finally { NicoVideoDb.AddOrUpdate(info); if (info.Owner != null) { NicoVideoOwnerDb.AddOrUpdate(info.Owner); } } if (info.IsDeleted) { var cacheManager = App.Current.Container.Resolve <VideoCacheManager>(); await cacheManager.VideoDeletedFromNiconicoServer(info.RawVideoId).ConfigureAwait(false); } return(info); } }