public YouTubeLiveSiteContext(ICommentOptions options, IYouTubeLibeServer server, ILogger logger) { _options = options; _server = server; _logger = logger; _userStore = CreateUserStore(); }
public YouTubeLiveSiteContext(ICommentOptions options, IYouTubeLibeServer server, ILogger logger, IUserStoreManager userStoreManager) : base(options, userStoreManager, logger) { _options = options; _server = server; _logger = logger; }
internal async Task <IVidResult> GetResultFromChannelId(IYouTubeLibeServer server, string channelId) { if (string.IsNullOrEmpty(channelId)) { throw new ArgumentNullException(nameof(channelId)); } var vids = await GetVidsFromChannelId(server, channelId); if (vids.Count == 1) { return(new VidResult { Vid = vids[0] }); } else if (vids.Count == 0) { return(new NoVidResult()); } else { return(new MultiVidsResult { Vids = vids }); } }
public static async Task <List <string> > GetVidsAsync(IYouTubeLibeServer server, string channelId) { //まずは配信中という前提でデータを取得する { var url = GetChannelLiveListUrl(channelId, ListType.LiveNow); var(ytInitialData, type) = await GetYtinitialData(server, url); if (type == ListType.LiveNow) { return(GetVidsFromYtInitialData(ytInitialData)); } } //配信の予約が入っているのかもしれない { var url = GetChannelLiveListUrl(channelId, ListType.UpcomingLiveStreams); var(ytInitialData, type) = await GetYtinitialData(server, url); if (type == ListType.UpcomingLiveStreams) { return(GetVidsFromYtInitialData(ytInitialData)); } } //これ以外にチャットを取得できる場面は無いから諦める return(new List <string>()); }
public C(ICommentOptions options, IYouTubeLibeServer server, YouTubeLiveSiteOptions siteOptions, ILogger logger, IUserStore userStore, string clientIdPrefix, string sej, string sessionToken) : base(logger, new CookieContainer(), options, server, siteOptions, new Dictionary <string, int>(), new System.Collections.Generic.SynchronizedCollection <string>(), new Mock <ICommentProvider>().Object, userStore) { PostCommentContext = new PostCommentContext { ClientIdPrefix = clientIdPrefix, Sej = sej, SessionToken = sessionToken, }; }
public YouTubeLiveSiteContext(ICommentOptions options, IYouTubeLibeServer server, ILogger logger, IUserStoreManager userStoreManager) { _options = options; _server = server; _logger = logger; _userStoreManager = userStoreManager; var userStore = new SQLiteUserStore(_options.SettingsDirPath + "\\" + "users_" + DisplayName + ".db", _logger); userStoreManager.SetUserStore(SiteType.YouTubeLive, userStore); }
public async Task <IVidResult> GetVid(IYouTubeLibeServer server, string input) { if (string.IsNullOrEmpty(input)) { throw new ArgumentNullException(nameof(input)); } if (TryVid(input, out string vid)) { return(new VidResult { Vid = vid }); } else if (TryWatch(input, out vid)) { return(new VidResult { Vid = vid }); } else if (IsUser(input)) { var userId = ExtractUserId(input); var channelId = await GetChannelIdFromUserId(server, userId); var vids = await GetVidsFromChannelId(server, channelId); if (vids.Count == 0) { return(new NoVidResult()); } else if (vids.Count == 1) { return(new VidResult { Vid = vids[0] }); } else { return(new MultiVidsResult { Vids = vids }); } } else if (IsCustomChannel(input)) { var(channelId, reason) = await TryGetChannelIdFromCustomChannel(server, input); return(await GetResultFromChannelId(server, channelId)); } else if (IsChannel(input)) { var channelId = ExtractChannelId(input); return(await GetResultFromChannelId(server, channelId)); } throw new ParseException(input); }
public CommentProvider(ICommentOptions options, IYouTubeLibeServer server, YouTubeLiveSiteOptions siteOptions, ILogger logger, IUserStoreManager userStoreManager) { _options = options; _siteOptions = siteOptions; _logger = logger; _userStoreManager = userStoreManager; _server = server; CanConnect = true; CanDisconnect = false; }
public EachConnection(ILogger logger, CookieContainer cc, ICommentOptions options, IYouTubeLibeServer server, YouTubeLiveSiteOptions siteOptions, Dictionary <string, int> userCommentCountDict, SynchronizedCollection <string> receivedCommentIds, ICommentProvider cp, IUserStoreManager userStoreManager) { _logger = logger; _cc = cc; _options = options; _server = server; _siteOptions = siteOptions; _userCommentCountDict = userCommentCountDict; _receivedCommentIds = receivedCommentIds; _cp = cp; _userStoreManager = userStoreManager; }
internal async Task <string> GetChannelIdFromUserId(IYouTubeLibeServer server, string userId) { var url = "https://www.youtube.com/user/" + userId; var html = await server.GetAsync(url); var match = Regex.Match(html, "<meta property=\"og:url\" content=\"https://www.youtube.com/channel/([^\"]+)\">"); if (match.Success) { var channelId = match.Groups[1].Value; return(channelId); } throw new ParseException(html); }
public async Task <IVidResult> GetVid(IYouTubeLibeServer server, string input) { if (string.IsNullOrEmpty(input)) { throw new ArgumentNullException(nameof(input)); } if (TryVid(input, out string vid)) { return(new VidResult { Vid = vid }); } else if (TryWatch(input, out vid)) { return(new VidResult { Vid = vid }); } else if (IsUser(input)) { var userId = ExtractUserId(input); var channelId = await GetChannelIdFromUserId(server, userId); return(await GetResultFromChannelId(server, channelId)); } else if (IsCustomChannel(input)) { var(channelId, reason) = await TryGetChannelIdFromCustomChannel(server, input); return(await GetResultFromChannelId(server, channelId)); } else if (IsChannel(input)) { var channelId = ExtractChannelId(input); return(await GetResultFromChannelId(server, channelId)); } else if (IsStudio(input)) { var studioVid = ExtractVidFromStudioUrl(input); if (studioVid != null) { return(new VidResult { Vid = studioVid }); } } return(new InvalidInput(input)); }
internal async Task <List <string> > GetVidsFromChannelId2(IYouTubeLibeServer server, string channelId) { //2021/01/10 生放送履歴が無い場合は投稿された動画の一覧になってしまうっぽい。 var url = $"https://www.youtube.com/channel/{channelId}/videos?view=2&live_view=501"; var html = await server.GetEnAsync(url); var matches = Regex.Matches(html, "\"url\":\"/watch\\?v=([^\"]+)\""); var vids = new List <string>(); foreach (Match match in matches) { if (match == null) { continue; } vids.Add(match.Groups[1].Value); } return(vids); }
internal async Task <List <string> > GetVidsFromChannelId2(IYouTubeLibeServer server, string channelId) { var url = $"https://www.youtube.com/channel/{channelId}/live"; var html = await server.GetEnAsync(url); string ytInitialData; try { ytInitialData = Tools.ExtractYtInitialDataFromChannelHtml(html); } catch (ParseException) { if (!html.Contains("ytInitialData")) { //条件がわからないけど結構よくある。 throw new YtInitialDataNotFoundException(url: url, html: html); } else { //空白が無くなったりだとかそういう系だろうか throw new SpecChangedException(html); } } var vids = new List <string>(); var d = DynamicJson.Parse(ytInitialData); //2019/07/19この方法だと直近の生放送を取得する。今現在生放送中とは限らない。数年間生放送していなければ数年前のものを取得することになる。 //生放送中かどうかの判定ができればこれでも良いと思う。 if (d.IsDefined("currentVideoEndpoint") && d.currentVideoEndpoint.IsDefined("watchEndpoint") && d.currentVideoEndpoint.watchEndpoint.IsDefined("videoId")) { var vid = (string)d.currentVideoEndpoint.watchEndpoint.videoId; vids.Add(vid); } return(vids); }
protected virtual EachConnection CreateConnection(ILogger logger, CookieContainer cc, ICommentOptions options, IYouTubeLibeServer server, YouTubeLiveSiteOptions siteOptions, Dictionary <string, int> userCommentCountDict, SynchronizedCollection <string> receivedCommentIds, ICommentProvider cp, IUserStoreManager userStoreManager, Guid siteContextGuid) { return(new EachConnection(logger, cc, options, server, siteOptions, userCommentCountDict, receivedCommentIds, cp, userStoreManager) { SiteContextGuid = siteContextGuid, }); }
/// <summary> /// /// </summary> /// <param name="server"></param> /// <param name="channelId"></param> /// <returns></returns> /// <exception cref="YtInitialDataNotFoundException"></exception> /// <exception cref="SpecChangedException"></exception> internal async Task <List <string> > GetVidsFromChannelId(IYouTubeLibeServer server, string channelId) { var url = $"https://www.youtube.com/channel/{channelId}/videos?flow=list&view=2"; var html = await server.GetEnAsync(url); var match = Regex.Match(html, "window\\[\"ytInitialData\"\\]\\s*=\\s*({.+?});\\s+", RegexOptions.Singleline); if (!match.Success) { if (!html.Contains("ytInitialData")) { //条件がわからないけど結構よくある。 throw new YtInitialDataNotFoundException(url: url, html: html); } else { //空白が無くなったりだとかそういう系だろうか throw new SpecChangedException(html); } } var list = new List <string>(); try { var ytInitialData = match.Groups[1].Value; var json = JsonConvert.DeserializeObject <Low.ChannelYtInitialData.RootObject>(ytInitialData); var tabs = json.contents.twoColumnBrowseResultsRenderer.tabs; Low.ChannelYtInitialData.Tab videosTab = null; foreach (var tab in tabs) { if (tab.tabRenderer == null) { continue; } if (tab.tabRenderer.title == "Videos") { videosTab = tab; break; } } if (videosTab == null) { return(list); } var contents = videosTab.tabRenderer.content.sectionListRenderer.contents; foreach (var content in contents) { var videoRenderer = content.itemSectionRenderer.contents[0].videoRenderer; //"このチャンネルには動画がありません"のとき、videoRendererがnull if (videoRenderer == null) { continue; } var videoId = videoRenderer.videoId; var isLive = IsLive(videoRenderer.badges); if (isLive) { list.Add(videoId); } } } catch (Exception ex) { throw new SpecChangedException(html, ex); } return(list); }
private static Mock <CommentProvider> CreateCommentProviderMock(ICommentOptions options, IYouTubeLibeServer server, YouTubeLiveSiteOptions siteOptions, ILogger logger, IUserStoreManager userStoreManager) { return(new Mock <CommentProvider>(options, server, siteOptions, logger, userStoreManager)); }
internal async Task <(string channelId, string reason)> TryGetChannelIdFromCustomChannel(IYouTubeLibeServer server, string input) { var match1 = _regexCustomChannel.Match(input); if (match1.Success) { var userId = match1.Groups[1].Value; var html = await server.GetAsync($"https://www.youtube.com/c/{userId}"); var match2 = Regex.Match(html, "property=\"og:url\" content=\"https://www\\.youtube\\.com/channel/(?<channelid>[^/\"?]+)\">"); if (match2.Success) { var channelId = match2.Groups["channelid"].Value; return(channelId, null); } } return(null, ""); }
public ChatProvider(IYouTubeLibeServer server, ILogger logger) { _server = server; _logger = logger; }
public MetadataProvider(IYouTubeLibeServer server, ILogger logger) : base(logger) { _server = server; }
private Mock <EachConnection> CreateConnection(ILogger logger, CookieContainer cc, ICommentOptions options, IYouTubeLibeServer server, YouTubeLiveSiteOptions siteOptions, Dictionary <string, int> userCommentCountDict, SynchronizedCollection <string> receivedCommentIds, ICommentProvider cp, IUserStoreManager userStoreManager, Guid siteContextGuid) { var cpMock = new Mock <EachConnection>(logger, cc, options, server, siteOptions, userCommentCountDict, receivedCommentIds, cp, userStoreManager) { CallBase = true }; cpMock.Object.SiteContextGuid = siteContextGuid; return(cpMock); }
internal Task <List <string> > GetVidsFromChannelId3(IYouTubeLibeServer server, string channelId) { return(ChannelLiveResearcher.GetVidsAsync(server, channelId)); }
private static async Task <(string ytInitialData, ListType)> GetYtinitialData(IYouTubeLibeServer server, string url) { var html = await server.GetEnAsync(url); var ytInitialData = Tools.ExtractYtInitialDataFromChannelHtml(html); var type = GetType(ytInitialData); return(ytInitialData, type); }