Пример #1
0
        public async void RecordPlaybackPositionAsync(NicoNicoWatchApiData apiData, double pos)
        {
            try {
                var form = new Dictionary <string, string> {
                    ["watch_id"]          = apiData.Video.Id,
                    ["playback_position"] = pos.ToString(),
                    ["csrf_token"]        = apiData.Context.CsrfToken
                };
                var request = new HttpRequestMessage(HttpMethod.Post, RecordPositionApi)
                {
                    Content = new FormUrlEncodedContent(form)
                };

                var a = await App.ViewModelRoot.CurrentUser.Session.GetAsync(request);

                var json = DynamicJson.Parse(a);


                if (json.status == "ok")
                {
                    //再生位置を記録出来た、と
                    //Owner.Status = "再生位置を保存しました。";
                }
                else
                {
                    //Owner.Status = "再生位置の保存に失敗しました";
                }
            } catch (RequestFailed) {
                Owner.Status = "再生位置の保存に失敗しました";
            }
        }
Пример #2
0
        public async Task <bool> ToggleFollowOwnerAsync(NicoNicoWatchApiData apiData)
        {
            try {
                if (apiData.IsChannelVideo)
                {
                    GetRequestQuery query = null;
                    if (apiData.IsUploaderFollowed)
                    {
                        query = new GetRequestQuery(ChannelUnFollowApi);
                    }
                    else
                    {
                        query = new GetRequestQuery(ChannelFollowApi);
                    }

                    query.AddQuery("channel_id", apiData.Channel.Id);
                    query.AddQuery("return_json", 1);
                    query.AddQuery("time", apiData.Channel.FavoriteTokenTime);
                    query.AddQuery("key", apiData.Channel.FavoriteToken);

                    var a = await App.ViewModelRoot.CurrentUser.Session.GetAsync(query.TargetUrl);

                    var json = DynamicJson.Parse(a);

                    if (json.status == "succeed")
                    {
                        if (apiData.IsUploaderFollowed)
                        {
                            Owner.Status = "フォローを解除しました";
                        }
                        else
                        {
                            Owner.Status = "フォローしました";
                        }
                        return(true);
                    }
                }
                else
                {
                    if (apiData.IsUploaderFollowed)
                    {
                        var request = new HttpRequestMessage(HttpMethod.Delete, string.Format(UploaderInfoApi, apiData.Owner.Id))
                        {
                            Content = new FormUrlEncodedContent(new Dictionary <string, string>())
                        };
                        request.Headers.Add("x-request-with", Owner.VideoUrl);

                        var a = await App.ViewModelRoot.CurrentUser.Session.GetAsync(request);

                        var json = DynamicJson.Parse(a);

                        if (json.meta.status == 200D)
                        {
                            Owner.Status = "フォローを解除しました";
                            return(true);
                        }
                        else
                        {
                            Owner.Status = "フォロー解除に失敗しました";
                            return(false);
                        }
                    }
                    else
                    {
                        var request = new HttpRequestMessage(HttpMethod.Post, string.Format(UploaderInfoApi, apiData.Owner.Id))
                        {
                            Content = new FormUrlEncodedContent(new Dictionary <string, string>())
                        };
                        request.Headers.Add("x-request-with", Owner.VideoUrl);

                        var a = await App.ViewModelRoot.CurrentUser.Session.GetAsync(request);

                        var json = DynamicJson.Parse(a);
                        if (json.meta.status == 200D)
                        {
                            Owner.Status = "フォローしました";
                            return(true);
                        }
                        else
                        {
                            Owner.Status = "フォローに失敗しました";
                            return(false);
                        }
                    }
                }
                return(false);
            } catch (RequestFailed) {
                return(false);
            }
        }
Пример #3
0
        public async Task <NicoNicoWatchApiData> GetWatchApiDataAsync()
        {
            try {
                var res = await App.ViewModelRoot.CurrentUser.Session.GetResponseAsync(Owner.VideoUrl);

                //チャンネル動画などでリダイレクトされるURLの可能性があるのでリダイレクトされた場合はリダイレクト先を読み込む
                if (res.StatusCode == HttpStatusCode.MovedPermanently)
                {
                    res = await App.ViewModelRoot.CurrentUser.Session.GetResponseAsync(res.Headers.Location.OriginalString);
                }

                //削除された動画は404を律儀に返してくる
                if (res.StatusCode == HttpStatusCode.NotFound)
                {
                    Owner.Status = "動画が削除されている可能性があります";
                    return(null);
                }

                //鯖落ちかな?
                if (res.StatusCode == HttpStatusCode.ServiceUnavailable)
                {
                    Owner.Status = "サーバーが混み合っているようです";
                    return(null);
                }


                //Cookieを取得してWebBrowserの方に反映させる
                //これがないと動画を取得しようとしても403が返ってくる
                IEnumerable <string> cookie;
                if (res.Headers.TryGetValues("Set-Cookie", out cookie))
                {
                    foreach (string s in cookie)
                    {
                        foreach (string ss in s.Split(';'))
                        {
                            App.SetCookie(new Uri("http://nicovideo.jp/"), ss);
                        }
                    }
                }

                //html
                var a = await res.Content.ReadAsStringAsync();

                //Responsehはもう必要ない
                res.Dispose();

                var doc = new HtmlDocument();
                doc.LoadHtml(a);

                var container = doc.DocumentNode.SelectSingleNode("//div[@id='js-initial-watch-data']");

                if (container == null)
                {
                    container = doc.DocumentNode.SelectSingleNode("//div[@id='watchAPIDataContainer']");

                    //html5版ページで視聴できなかった場合
                    if (container != null)
                    {
                        var json = DynamicJson.Parse(HttpUtility.HtmlDecode(container.InnerText));

                        var flash = json.flashvars;

                        var flv = HttpUtility.UrlDecode(HttpUtility.UrlDecode(flash.flvInfo));

                        var getFlv = HttpUtility.ParseQueryString(flv);

                        var videoDetail = json.videoDetail;

                        var ret = new NicoNicoWatchApiData();
                        //動画情報
                        ret.Video = new NicoNicoVideo()
                        {
                            Id        = videoDetail.id,
                            SmileInfo = new NicoNicoVideo.NicoNicoSmileInfo()
                            {
                                Url = getFlv["url"]
                            },
                            Title                  = videoDetail.title,
                            OriginalTitle          = videoDetail.title_original,
                            Description            = videoDetail.description,
                            OriginalDescription    = videoDetail.description_original,
                            ThumbNailUrl           = videoDetail.thumbnail,
                            PostedDateTime         = DateTime.Parse(videoDetail.postedAt),
                            OriginalPostedDateTime = DateTime.MinValue,
                            Duration               = (int)videoDetail.length,
                            ViewCount              = (int)videoDetail.viewCount,
                            MylistCount            = (int)videoDetail.mylistCount
                        };

                        ret.Thread = new NicoNicoThread()
                        {
                            CommentCount   = (int)videoDetail.commentCount,
                            HasOwnerThread = videoDetail.has_owner_thread,
                            ServerUrl      = getFlv["ms"].Replace("api", "api.json"),
                            SubServerurl   = getFlv["ms_sub"],
                            ThreadIds      = new NicoNicoThreadIds()
                            {
                                Default   = getFlv["thread_id"],
                                Nicos     = getFlv["thread_id"],
                                Community = getFlv["thread_id"]
                            }
                        };

                        ret.Tags = new List <NicoNicoVideoTag>();

                        foreach (var tag in videoDetail.tagList)
                        {
                            var entry = new NicoNicoVideoTag()
                            {
                                Id  = tag.id,
                                Tag = HttpUtility.HtmlDecode(tag.tag),
                                Dic = tag.dic(),
                                Lck = tag.lck == "1" ? true : false,
                                Cat = tag.cat()
                            };
                            entry.Url = "http://dic.nicovideo.jp/a/" + entry.Tag;
                            ret.Tags.Add(entry);
                        }

                        if (json.uploaderInfo())
                        {
                            var owner = json.uploaderInfo;
                            ret.Owner = new NicoNicoVideoOwner()
                            {
                                Id       = owner.id,
                                UserUrl  = "http://www.nicovideo.jp/user/" + owner.id,
                                Nickname = owner.nickname,

                                IconUrl              = owner.icon_url,
                                IsUserVideoPublic    = owner.is_uservideo_public,
                                IsUserMyVideoPublic  = owner.is_user_myvideo_public,
                                IsUserOpenListPublic = owner.is_user_openlist_public
                            };

                            //投稿者をお気に入り登録しているか調べる
                            var follow = await App.ViewModelRoot.CurrentUser.Session.GetAsync(string.Format(UploaderInfoApi, ret.Owner.Id));

                            ret.IsUploaderFollowed = DynamicJson.Parse(follow).data.following;
                        }

                        if (json.channelInfo())
                        {
                            var channel = json.channelInfo;
                            ret.Channel = new NicoNicoVideoChannel()
                            {
                                Id                = channel.id,
                                Name              = channel.name,
                                IconUrl           = channel.icon_url,
                                FavoriteToken     = channel.favorite_token,
                                FavoriteTokenTime = (long)channel.favorite_token_time,
                                IsFavorited       = channel.is_favorited == 1D
                            };
                            ret.Channel.ChannelUrl = "http://ch.nicovideo.jp/ch" + ret.Channel.Id;

                            ret.IsChannelVideo     = true;
                            ret.IsUploaderFollowed = ret.Channel.IsFavorited;
                        }

                        var viewer = json.viewerInfo;
                        ret.Viewer = new NicoNicoVideoViewer()
                        {
                            Id           = Convert.ToString(viewer.id),
                            Nickname     = viewer.nickname,
                            IsPremium    = viewer.isPremium,
                            IsPrivileged = viewer.isPrivileged,
                        };

                        ret.Context = new NicoNicoVideoContext()
                        {
                            HighestRank = videoDetail.highest_rank != null?int.Parse(videoDetail.highest_rank) : null,
                                              YesterdayRank = videoDetail.yesterday_rank != null?int.Parse(videoDetail.yesterday_rank) : null,
                                                                  CsrfToken = flash.csrfToken,
                                                                  UserKey   = getFlv["userkey"]
                        };

                        ret.FmsToken = getFlv["fmst"];

                        return(ret);
                    }
                    Owner.Status = "動画の読み込みに失敗しました";
                    return(null);
                }
                else
                {
                    //htmlから取得したJsonをhtmlデコードしてdynamic型に変える
                    var json = DynamicJson.Parse(HttpUtility.HtmlDecode(container.Attributes["data-api-data"].Value.Trim()));

                    var ret = new NicoNicoWatchApiData();

                    //動画情報
                    var video = json.video;

                    ret.Video = new NicoNicoVideo()
                    {
                        Id        = video.id,
                        SmileInfo = new NicoNicoVideo.NicoNicoSmileInfo()
                        {
                            Url              = video.smileInfo.url,
                            IsSlowLine       = video.smileInfo.isSlowLine,
                            CurrentQualityId = video.smileInfo.currentQualityId
                        },
                        Title                                                      = HttpUtility.HtmlDecode(video.title),
                        OriginalTitle                                              = video.originalTitle,
                        Description                                                = HyperLinkReplacer.Replace(video.description),
                        OriginalDescription                                        = video.originalDescription,
                        ThumbNailUrl                                               = video.thumbnailURL,
                        PostedDateTime                                             = DateTime.Parse(video.postedDateTime),
                        OriginalPostedDateTime                                     = video.originalPostedDateTime() && video.originalPostedDateTime != null?DateTime.Parse(video.originalPostedDateTime) : DateTime.MinValue,
                                                                       Width       = (int?)video.width,
                                                                       Height      = (int?)video.height,
                                                                       Duration    = (int)video.duration,
                                                                       ViewCount   = (int)video.viewCount,
                                                                       MylistCount = (int)video.mylistCount,
                                                                       Translation = video.translation,
                                                                       Translator  = video.translator,
                                                                       MovieType   = video.movieType,
                                                                       Badges      = video.badges,
                                                                       IntroducedNicoliveDJInfo = video.introducedNicoliveDJInfo,
                                                                       DmcInfo = video.dmcInfo != null ? new NicoNicoDmc()
                        {
                            Time              = (long)video.dmcInfo.time,
                            TimeMs            = (long)video.dmcInfo.time_ms,
                            VideoId           = video.dmcInfo.video.video_id,
                            LengthSeconds     = (int)video.dmcInfo.video.length_seconds,
                            Deleted           = (int)video.dmcInfo.video.deleted,
                            ServerUrl         = video.dmcInfo.thread.server_url,
                            SubServerUrl      = video.dmcInfo.thread.sub_server_url,
                            ThreadId          = Convert.ToString(video.dmcInfo.thread.thread_id),
                            NicosThreadId     = Convert.ToString(video.dmcInfo.thread.nicos_thread_id),
                            OptionalThreadId  = Convert.ToString(video.dmcInfo.thread.optional_thread_id),
                            ThreadKeyRequired = video.dmcInfo.thread.thread_key_required,
                            ChannelNGWords    = video.dmcInfo.thread.channel_ng_words,
                            OwnerNGWords      = video.dmcInfo.thread.owner_ng_words,
                            MaintenancesNg    = video.dmcInfo.thread.maintenances_ng,
                            PostkeyAvailable  = video.dmcInfo.thread.postkey_available,
                            NgRevision        = (int?)video.dmcInfo.thread.ng_revision,

                            ApiUrls           = video.dmcInfo.session_api.api_urls,
                            RecipeId          = video.dmcInfo.session_api.recipe_id,
                            PlayerId          = video.dmcInfo.session_api.player_id,
                            Videos            = video.dmcInfo.session_api.videos,
                            Audios            = video.dmcInfo.session_api.audios,
                            Movies            = video.dmcInfo.session_api.movies,
                            Protocols         = video.dmcInfo.session_api.protocols,
                            AuthType          = video.dmcInfo.session_api.auth_types.http,
                            ServiceUserId     = video.dmcInfo.session_api.service_user_id,
                            Token             = video.dmcInfo.session_api.token,
                            Signature         = video.dmcInfo.session_api.signature,
                            ContentId         = video.dmcInfo.session_api.content_id,
                            HeartbeatLifeTime = (int)video.dmcInfo.session_api.heartbeat_lifetime,
                            ContentKeyTimeout = (int)video.dmcInfo.session_api.content_key_timeout,
                            Priority          = video.dmcInfo.session_api.priority
                        } : null,
                        BackCommentType       = video.backCommentType,
                        IsCommentExpired      = video.isCommentExpired,
                        IsWide                = video.isWide,
                        IsOfficialAnime       = (int?)video.isOfficialAnime,
                        IsNoBanner            = video.isNoBanner,
                        IsDeleted             = video.isDeleted,
                        IsTranslated          = video.isTranslated,
                        IsR18                 = video.isR18,
                        IsAdult               = video.isAdult,
                        IsNicowari            = video.isNicowari,
                        IsPublic              = video.isPublic,
                        IsPublishedNicoscript = video.isPublishedNicoscript,
                        IsNoNGS               = video.isNoNGS,
                        IsCommunityMemberOnly = video.isCommunityMemberOnly,
                        IsCommonsTreeExists   = video.isCommonsTreeExists,
                        IsNoIchiba            = video.isNoIchiba,
                        IsOfficial            = video.isOfficial,
                        IsMonetized           = video.isMonetized
                    };

                    var thread = json.thread;
                    ret.Thread = new NicoNicoThread()
                    {
                        CommentCount     = (int)thread.commentCount,
                        HasOwnerThread   = thread.hasOwnerThread,
                        MymemoryLanguage = thread.mymemoryLanguage,
                        ServerUrl        = thread.serverUrl.Replace("api", "api.json"),
                        SubServerurl     = thread.subServerUrl,
                        ThreadIds        = new NicoNicoThreadIds()
                        {
                            Default   = thread.ids.@default,
                            Nicos     = thread.ids.nicos,
                            Community = thread.ids.community
                        }
                    };

                    //タグを走査
                    ret.Tags = new List <NicoNicoVideoTag>();
                    foreach (var tag in json.tags)
                    {
                        var entry = new NicoNicoVideoTag()
                        {
                            Id  = tag.id,
                            Tag = HttpUtility.HtmlDecode(tag.name),
                            Dic = tag.isDictionaryExists,
                            Lck = tag.isLocked,
                            Cat = tag.isCategory
                        };
                        entry.Url = "http://dic.nicovideo.jp/a/" + entry.Tag;
                        ret.Tags.Add(entry);
                    }

                    var owner = json.owner;
                    if (owner != null)
                    {
                        ret.Owner = new NicoNicoVideoOwner()
                        {
                            Id       = owner.id,
                            UserUrl  = "http://www.nicovideo.jp/user/" + owner.id,
                            Nickname = owner.nickname,

                            IconUrl              = owner.iconURL,
                            NicoliveInfo         = owner.nicoliveInfo,
                            ChannelInfo          = owner.channelInfo,
                            IsUserVideoPublic    = owner.isUserVideoPublic,
                            IsUserMyVideoPublic  = owner.isUserMyVideoPublic,
                            IsUserOpenListPublic = owner.isUserOpenListPublic
                        };

                        //投稿者をお気に入り登録しているか調べる
                        var follow = await App.ViewModelRoot.CurrentUser.Session.GetAsync(string.Format(UploaderInfoApi, ret.Owner.Id));

                        ret.IsUploaderFollowed = DynamicJson.Parse(follow).data.following;
                    }

                    var channel = json.channel;
                    if (channel != null)
                    {
                        ret.Channel = new NicoNicoVideoChannel()
                        {
                            Id                = channel.id,
                            Name              = channel.name,
                            IconUrl           = channel.iconURL,
                            FavoriteToken     = channel.favoriteToken,
                            FavoriteTokenTime = (long)channel.favoriteTokenTime,
                            IsFavorited       = channel.isFavorited,
                            NGFilters         = new List <NicoNicoVideoNGFilter>(),
                            ThreadType        = channel.threadType,
                            GlobalId          = channel.globalId
                        };
                        ret.Channel.ChannelUrl = "http://ch.nicovideo.jp/" + ret.Channel.GlobalId;

                        foreach (var filter in channel.ngList)
                        {
                            ret.Channel.NGFilters.Add(new NicoNicoVideoNGFilter()
                            {
                                Source = filter.source, Destination = filter.destination
                            });
                        }

                        ret.IsChannelVideo     = true;
                        ret.IsUploaderFollowed = ret.Channel.IsFavorited;
                    }

                    var viewer = json.viewer;
                    ret.Viewer = new NicoNicoVideoViewer()
                    {
                        Id                  = Convert.ToString(viewer.id),
                        Nickname            = viewer.nickname,
                        Prefecture          = (int)viewer.prefecture,
                        Sex                 = (int)viewer.sex,
                        Age                 = (int)viewer.age,
                        IsPremium           = viewer.isPremium,
                        IsPrivileged        = viewer.isPrivileged,
                        IsPostLocked        = viewer.isPostLocked,
                        IsHtrzm             = viewer.isHtrzm,
                        IsTwitterConnection = viewer.isTwitterConnection
                    };

                    var context = json.context;
                    ret.Context = new NicoNicoVideoContext()
                    {
                        PlayFrom = context.playFrom,
                        InitialPlaybackPosition = (int?)context.initialPlaybackPosition,
                        InitialPlaybackType     = context.initialPlaybackType,
                        PlayLength                       = context.playLength,
                        ReturnId                         = context.returnId,
                        ReturnTo                         = context.returnTo,
                        ReturnMsg                        = context.returnMsg,
                        WatchId                          = context.watchId,
                        IsNoMovie                        = context.isNoMovie,
                        IsNoRelatedVideo                 = context.isNoRelatedVideo,
                        IsDownloadCompleteWait           = context.isDownloadCompleteWait,
                        IsNoNicotic                      = context.isNoNicotic,
                        IsNeedPayment                    = context.isNeedPayment,
                        IsAdultRatingNG                  = context.isAdultRatingNG,
                        IsPlayable                       = context.isPlayable,
                        IsTranslatable                   = context.isTranslatable,
                        IsTagUneditable                  = context.isTagUneditable,
                        IsVideoOwner                     = context.isVideoOwner,
                        IsThreadOwner                    = context.isThreadOwner,
                        IsOwnerThreadEditable            = context.isOwnerThreadEditable,
                        UseChecklistCache                = context.useChecklistCache,
                        IsDisabledMarquee                = context.isDisabledMarquee,
                        IsDictionaryDisplayable          = context.isDictionaryDisplayable,
                        IsDefaultCommentInvisible        = context.isDefaultCommentInvisible,
                        AccessFrom                       = context.accessFrom,
                        CsrfToken                        = context.csrfToken,
                        TranslationVersionJsonUpdateTime = (long)context.translationVersionJsonUpdateTime,
                        UserKey                          = context.userkey,
                        WatchAuthKey                     = context.watchAuthKey,
                        WatchTrackId                     = context.watchTrackId,
                        WatchPageServerTime              = (long)context.watchPageServerTime,
                        IsAuthenticationRequired         = context.isAuthenticationRequired,
                        IsPeakTime                       = context.isPeakTime,
                        NgRevision                       = (int)context.ngRevision,
                        CategoryName                     = context.categoryName,
                        CategoryKey                      = context.categoryKey,
                        CategoryGroupName                = context.categoryGroupName,
                        CategoryGroupKey                 = context.categoryGroupKey,
                        YesterdayRank                    = (int?)context.yesterdayRank,
                        HighestRank                      = (int?)context.highestRank,
                        IsMyMemory                       = context.isMyMemory,
                        OwnerNGFilters                   = new List <NicoNicoVideoNGFilter>()
                    };

                    //垢消しうp主
                    if (ret.Channel == null && ret.Owner == null)
                    {
                        ret.IsOwnerDeleted = true;
                    }

                    if (!Settings.Instance.UseResumePlay)
                    {
                        ret.Context.InitialPlaybackPosition = 0;
                    }

                    foreach (var filter in context.ownerNGList)
                    {
                        ret.Context.OwnerNGFilters.Add(new NicoNicoVideoNGFilter()
                        {
                            Source = filter.source, Destination = filter.destination
                        });
                    }
                    return(ret);
                }
            } catch (RequestFailed) {
                Owner.Status = "動画情報の取得に失敗しました";
                return(null);
            }
        }