From 1b9593599f68cedb5aa49487ac23077237ec7141 Mon Sep 17 00:00:00 2001 From: Ryu Shinmura Date: Tue, 23 Nov 2021 00:47:28 +0900 Subject: [PATCH 01/12] =?UTF-8?q?=E3=83=8B=E3=82=B3=E7=94=9F=E3=81=AE?= =?UTF-8?q?=E8=87=AA=E5=88=86=E8=87=AA=E8=BA=AB=E3=81=AE=E6=83=85=E5=A0=B1?= =?UTF-8?q?=E3=81=AE=E5=8F=96=E5=BE=97=E6=96=B9=E6=B3=95=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NicoSitePlugin2/Api.cs | 48 +++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/NicoSitePlugin2/Api.cs b/NicoSitePlugin2/Api.cs index c64c29e7..b1f331cb 100644 --- a/NicoSitePlugin2/Api.cs +++ b/NicoSitePlugin2/Api.cs @@ -68,43 +68,29 @@ public static async Task GetUserInfo(IDataSource server, CookieContain } public static async Task GetMyInfo(IDataSource server, CookieContainer cc) { - var url = "https://com.nicovideo.jp/community/co1034396"; + var url = "https://www.nicovideo.jp/my"; var html = await server.GetAsync(url, cc); - var match = Regex.Match(html, "user:\\s*({[^}]+?})"); + var match = Regex.Match(html, "data-common-header=\"(.+)\">"); if (!match.Success) { throw new SpecChangedException(html); } - var data = match.Groups[1].Value; - var myInfo = new MyInfo(); - var matchUserId = Regex.Match(data, "id\\s*:\\s*(\\d+)"); - if (matchUserId.Success) - { - myInfo.UserId = matchUserId.Groups[1].Value; - } - var matchNickname = Regex.Match(data, "nickname\\s*:\\s*'([^']+)'"); - if (matchNickname.Success) - { - myInfo.Nickname = matchNickname.Groups[1].Value; - } - var matchIcon = Regex.Match(data, "iconUrl\\s*:\\s*'([^']+)'"); - if (matchIcon.Success) - { - myInfo.IconUrl = matchIcon.Groups[1].Value; - } - var matchPremium = Regex.Match(data, "isPremium\\s*:\\s*(true|false)"); - if (matchPremium.Success) - { - myInfo.IsPremium = matchPremium.Groups[1].Value == "true"; - } - var matchLogin = Regex.Match(data, "isLogin\\s*:\\s*(true|false)"); - if (matchLogin.Success) - { - myInfo.IsLogin = matchLogin.Groups[1].Value == "true"; - } + var json = match.Groups[1].Value.Replace(""", "\""); + dynamic d = JsonConvert.DeserializeObject(json); + var isLogin = (bool)d.initConfig.user.isLogin; + var userId = (long)d.initConfig.user.id; + var isPremium = (bool)d.initConfig.user.isPremium; + var nickname = (string)d.initConfig.user.nickname; + var iconUrl = (string)d.initConfig.user.iconUrl; - - return myInfo; + return new MyInfo + { + IsLogin = isLogin, + Nickname = nickname, + IconUrl = iconUrl, + IsPremium = isPremium, + UserId = userId.ToString(), + }; } /// /// From 082a06d7e1518d66c70ce25f209a929980947e28 Mon Sep 17 00:00:00 2001 From: Ryu Shinmura Date: Tue, 23 Nov 2021 01:25:23 +0900 Subject: [PATCH 02/12] =?UTF-8?q?=E3=83=8B=E3=82=B3=E7=94=9F=E3=81=AE?= =?UTF-8?q?=E3=82=B3=E3=83=9F=E3=83=A5=E3=83=8B=E3=83=86=E3=82=A3=E3=81=AE?= =?UTF-8?q?=E9=85=8D=E4=BF=A1=E6=83=85=E5=A0=B1=E3=82=92=E5=8F=96=E5=BE=97?= =?UTF-8?q?=E3=81=99=E3=82=8BAPI=E3=81=AE=E4=BB=95=E6=A7=98=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NicoSitePlugin2/Api.cs | 68 +++++++++++---------- NicoSitePlugin2/Low/CommunityLives.cs | 85 +-------------------------- 2 files changed, 39 insertions(+), 114 deletions(-) diff --git a/NicoSitePlugin2/Api.cs b/NicoSitePlugin2/Api.cs index b1f331cb..9d1d7b4a 100644 --- a/NicoSitePlugin2/Api.cs +++ b/NicoSitePlugin2/Api.cs @@ -3,6 +3,8 @@ using System.Net; using Newtonsoft.Json; using System; +using System.Collections.Generic; +using System.Linq; namespace NicoSitePlugin { @@ -38,33 +40,47 @@ public static async Task GetUserInfo(IDataSource server, CookieContain }; return userInfo; } - /// - /// - /// - /// - /// - /// co\d+ - /// - /// - /// - public static async Task GetCommunityLives(IDataSource server, CookieContainer cc, string communityId, int limit, int offset) + public static async Task GetCommunityLives(IDataSource server, CookieContainer cc, string communityId) { - var url = $"https://com.nicovideo.jp/api/v1/communities/{communityId.Substring(2)}/lives.json?limit={limit}&offset={offset}"; + //以下のAPIだとON_AIRだけ取れる。 + //https://com.nicovideo.jp/api/v1/communities/{communityIdWithoutCo}/lives/onair.json + //でも配信していないと + //{"meta":{"status":404,"error-code":"RESOURCE_NOT_FOUND","error-message":"このコミュニティは生放送中ではありません。"}} + //が返ってくる + + + var communityIdWithoutCo = communityId.Substring(2); + var url = $"https://com.nicovideo.jp/api/v1/communities/{communityIdWithoutCo}/lives.json"; var res = await server.GetAsync(url, cc); dynamic d = JsonConvert.DeserializeObject(res); - //{"meta":{"status":404,"error-code":"RESOURCE_NOT_FOUND","error-message":"対象のコミュニティが存在しません。"}} - //{"meta":{"status":404,"error-code":"RESOURCE_NOT_FOUND","error-message":"リソース communities の値の形式が不正です"}} - var status = (int)d.meta.status; - if (status == 200) + if(d.meta.status != 200) { - var obj = JsonConvert.DeserializeObject(res); - return obj.Data.Lives; - + throw new ApiGetCommunityLivesException(); } - else + var lives = new List(); + foreach(var liveDyn in d.data.lives) { - throw new ApiGetCommunityLivesException(); + var live = new CommunityLiveInfo + { + Description = (string)liveDyn.description, + LiveId = (string)liveDyn.id, + Status = (string)liveDyn.status, + Title = (string)liveDyn.title, + UserId = (long)liveDyn.user_id, + WatchUrl = (string)liveDyn.watch_url, + }; + lives.Add(live); } + return lives.ToArray(); + } + public class CommunityLiveInfo + { + public string LiveId { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public string Status { get; set; } + public long UserId { get; set; } + public string WatchUrl { get; set; } } public static async Task GetMyInfo(IDataSource server, CookieContainer cc) { @@ -116,16 +132,8 @@ internal static async Task GetCurrentChannelLiveId(IDataSource dataSourc /// 配信中であればその配信のID、そうでなければnull internal static async Task GetCurrentCommunityLiveId(IDataSource dataSource, string communityId, CookieContainer cc) { - var lives = await GetCommunityLives(dataSource, cc, communityId, 1, 0); - if (lives.Length > 0 && lives[0].Status == "ON_AIR") - { - return lives[0].Id; - } - else - { - return null; - } - + var lives = await GetCommunityLives(dataSource, cc, communityId); + return lives.FirstOrDefault(a => a.Status == "ON_AIR")?.LiveId; } } } diff --git a/NicoSitePlugin2/Low/CommunityLives.cs b/NicoSitePlugin2/Low/CommunityLives.cs index 2a50d839..5f282702 100644 --- a/NicoSitePlugin2/Low/CommunityLives.cs +++ b/NicoSitePlugin2/Low/CommunityLives.cs @@ -1,84 +1 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NicoSitePlugin2.Low.CommunityLives -{ - public class RootObject - { - [JsonProperty("meta")] - public Meta Meta { get; set; } - - [JsonProperty("data")] - public Data Data { get; set; } - } - - public class Data - { - [JsonProperty("total")] - public long Total { get; set; } - - [JsonProperty("lives")] - public Live[] Lives { get; set; } - } - - public class Live - { - [JsonProperty("id")] - public string Id { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("description")] - public string Description { get; set; } - - [JsonProperty("status")] - public string Status { get; set; } - - [JsonProperty("user_id")] - public long UserId { get; set; } - - [JsonProperty("watch_url")] - public Uri WatchUrl { get; set; } - - [JsonProperty("features")] - public Features Features { get; set; } - - [JsonProperty("timeshift")] - public Timeshift Timeshift { get; set; } - - [JsonProperty("started_at")] - public string StartedAt { get; set; } - - [JsonProperty("finished_at", NullValueHandling = NullValueHandling.Ignore)] - public string FinishedAt { get; set; } - } - - public class Features - { - [JsonProperty("is_member_only")] - public bool IsMemberOnly { get; set; } - } - - public class Timeshift - { - [JsonProperty("enabled")] - public bool Enabled { get; set; } - - [JsonProperty("can_view", NullValueHandling = NullValueHandling.Ignore)] - public bool? CanView { get; set; } - - [JsonProperty("finished_at", NullValueHandling = NullValueHandling.Ignore)] - public string FinishedAt { get; set; } - } - - public class Meta - { - [JsonProperty("status")] - public long Status { get; set; } - } -} + \ No newline at end of file From 00f3e95dceaea0843f396ba8056f50829d49699f Mon Sep 17 00:00:00 2001 From: Ryu Shinmura Date: Tue, 23 Nov 2021 01:29:37 +0900 Subject: [PATCH 03/12] =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E7=95=AA=E5=8F=B7=E3=82=92=E3=82=A4=E3=83=B3=E3=82=AF?= =?UTF-8?q?=E3=83=AA=E3=83=A1=E3=83=B3=E3=83=88=200.6.14->0.6.15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MultiCommentViewer/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiCommentViewer/Properties/AssemblyInfo.cs b/MultiCommentViewer/Properties/AssemblyInfo.cs index 73f1ffb1..1cbea287 100644 --- a/MultiCommentViewer/Properties/AssemblyInfo.cs +++ b/MultiCommentViewer/Properties/AssemblyInfo.cs @@ -3,4 +3,4 @@ [assembly: InternalsVisibleTo("MultiCommentViewerTests")] -[assembly: AssemblyVersion("0.6.14")] +[assembly: AssemblyVersion("0.6.15")] From 40c3b276f7eb06ec06f116867db6b1b957e5f389 Mon Sep 17 00:00:00 2001 From: Ryu Shinmura Date: Tue, 23 Nov 2021 03:58:15 +0900 Subject: [PATCH 04/12] =?UTF-8?q?YouTubeLive=E3=81=AE=E7=B5=B5=E6=96=87?= =?UTF-8?q?=E5=AD=97=E3=82=92=E6=A3=92=E8=AA=AD=E3=81=BF=E3=81=A1=E3=82=83?= =?UTF-8?q?=E3=82=93=E3=81=AB=E8=AA=AD=E3=81=BE=E3=81=9B=E3=82=8B=E9=9A=9B?= =?UTF-8?q?=E3=81=AE=E6=8C=99=E5=8B=95=E3=82=92=E4=BB=A5=E5=89=8D=E3=81=AE?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=81=AB=E8=BF=91=E3=81=A5=E3=81=91=E3=81=9F?= =?UTF-8?q?=E3=81=A4=E3=82=82=E3=82=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tiwtterで絵文字を読まなくなったという報告があったため対応した --- BouyomiPlugin/main.cs | 8 ++++++++ YouTubeLiveSitePlugin/Message.cs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/BouyomiPlugin/main.cs b/BouyomiPlugin/main.cs index 6ed4bcf8..e560646f 100644 --- a/BouyomiPlugin/main.cs +++ b/BouyomiPlugin/main.cs @@ -40,6 +40,14 @@ public static string ToTextWithImageAlt(this IEnumerable parts) { s += image.Alt; } + else if(part is IMessageRemoteSvg remoteSvg) + { + s += remoteSvg.Alt; + } + else + { + + } } } return s; diff --git a/YouTubeLiveSitePlugin/Message.cs b/YouTubeLiveSitePlugin/Message.cs index ba07394f..d179115d 100644 --- a/YouTubeLiveSitePlugin/Message.cs +++ b/YouTubeLiveSitePlugin/Message.cs @@ -163,7 +163,7 @@ public static IMessagePart Parse(ryu_s.YouTubeLive.Message.IMessagePart a) return new Common.MessageSvgImage { Url = emoji.Url, - Alt = "", + Alt = emoji.EmojiId, Height = 24, Width = 24, }; From 5ce6f28b67c4967208b64733c3764cfea5895f58 Mon Sep 17 00:00:00 2001 From: Ryu Shinmura Date: Tue, 23 Nov 2021 03:59:42 +0900 Subject: [PATCH 05/12] =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E7=95=AA=E5=8F=B7=E3=82=92=E3=82=A4=E3=83=B3=E3=82=AF?= =?UTF-8?q?=E3=83=AA=E3=83=A1=E3=83=B3=E3=83=88=200.6.15->0.6.16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MultiCommentViewer/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiCommentViewer/Properties/AssemblyInfo.cs b/MultiCommentViewer/Properties/AssemblyInfo.cs index 1cbea287..05aa3ca4 100644 --- a/MultiCommentViewer/Properties/AssemblyInfo.cs +++ b/MultiCommentViewer/Properties/AssemblyInfo.cs @@ -3,4 +3,4 @@ [assembly: InternalsVisibleTo("MultiCommentViewerTests")] -[assembly: AssemblyVersion("0.6.15")] +[assembly: AssemblyVersion("0.6.16")] From b5e497fb66d17f341340371647769e2b848df86a Mon Sep 17 00:00:00 2001 From: usuda Date: Fri, 13 Sep 2024 12:02:41 +0900 Subject: [PATCH 06/12] =?UTF-8?q?Openrec=E3=81=8B=E3=82=89BLive=E3=81=AB?= =?UTF-8?q?=E3=82=B3=E3=83=94=E3=83=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Openrec -> BLive 文字列一括書き換え ファイル名の変更 Guidの変更 対象サイトにBLIVEを選べるようにする プロジェクトにBLIVEを追加 表示名をB-LIVEに変更 --- BLiveIF/BLiveIF.csproj | 41 ++ BLiveIF/Message.cs | 70 ++ BLiveIF/Properties/AssemblyInfo.cs | 1 + BLiveSitePlugin/API.cs | 231 +++++++ BLiveSitePlugin/BLiveCommentData.cs | 23 + BLiveSitePlugin/BLiveCommentViewModel.cs | 111 ++++ BLiveSitePlugin/BLiveOptionsPanel.xaml | 21 + BLiveSitePlugin/BLiveOptionsPanel.xaml.cs | 32 + BLiveSitePlugin/BLiveOptionsTabPage.cs | 28 + BLiveSitePlugin/BLiveOptionsViewModel.cs | 121 ++++ BLiveSitePlugin/BLiveSiteContext.cs | 97 +++ BLiveSitePlugin/BLiveSiteOptions.cs | 100 +++ BLiveSitePlugin/BLiveSitePlugin.csproj | 78 +++ BLiveSitePlugin/BLiveWebsocket.cs | 105 +++ BLiveSitePlugin/BlackListProvider.cs | 65 ++ BLiveSitePlugin/CommentPostPanel.xaml | 16 + BLiveSitePlugin/CommentPostPanel.xaml.cs | 28 + BLiveSitePlugin/CommentPostPanelViewModel.cs | 77 +++ BLiveSitePlugin/CommentProvider.cs | 612 +++++++++++++++++ BLiveSitePlugin/Context.cs | 17 + BLiveSitePlugin/DataSource.cs | 72 ++ BLiveSitePlugin/DynamicJson.cs | 431 ++++++++++++ BLiveSitePlugin/Exceptions.cs | 17 + BLiveSitePlugin/IBLiveCommentData.cs | 23 + BLiveSitePlugin/IBLiveWebsocket.cs | 17 + BLiveSitePlugin/IBlackListProvider.cs | 14 + BLiveSitePlugin/Low/BlackList/Class1.cs | 72 ++ BLiveSitePlugin/Low/Chats/Class1.cs | 132 ++++ BLiveSitePlugin/Low/External/Movies/Class1.cs | 363 ++++++++++ BLiveSitePlugin/Low/LivePage/Class1.cs | 627 ++++++++++++++++++ BLiveSitePlugin/Low/Movies/Class1.cs | 309 +++++++++ BLiveSitePlugin/Message/BLiveComment.cs | 54 ++ BLiveSitePlugin/Message/BLiveConnected.cs | 17 + BLiveSitePlugin/Message/BLiveDisconnected.cs | 17 + .../Message/BLiveMessageContext.cs | 19 + .../Message/BLiveMessageMethods.cs | 13 + BLiveSitePlugin/Message/MessageMetadata.cs | 257 +++++++ BLiveSitePlugin/Metadata.cs | 15 + BLiveSitePlugin/MovieInfo.cs | 23 + BLiveSitePlugin/Packet.cs | 220 ++++++ BLiveSitePlugin/Properties/AssemblyInfo.cs | 7 + .../Properties/Resources.Designer.cs | 113 ++++ BLiveSitePlugin/Properties/Resources.resx | 136 ++++ BLiveSitePlugin/Tools.cs | 479 +++++++++++++ BLiveSitePlugin/UserViewModel.cs | 36 + BLiveSitePlugin/Websocket.cs | 107 +++ BLiveSitePlugin/app.config | 11 + BLiveSitePlugin/sprite_premium_landing.png | Bin 0 -> 50666 bytes BLiveSitePlugin/sprite_v4.png | Bin 0 -> 90500 bytes BLiveSitePlugin/sprite_v5.png | Bin 0 -> 91954 bytes BLiveSitePlugin/sprite_v6.png | Bin 0 -> 70294 bytes BLiveSitePlugin/sprites.png | Bin 0 -> 335188 bytes ISitePlugin/SiteType.cs | 1 + MultiCommentViewer.sln | 36 + MultiCommentViewer/IOptions.cs | 2 + MultiCommentViewer/MultiCommentViewer.csproj | 2 + MultiCommentViewer/Test/DynamicOptionsTest.cs | 4 + .../Test/SitePluginLoaderTest.cs | 1 + .../CommentViewModel/BLiveCommentViewModel.cs | 321 +++++++++ .../ViewModels/MainViewModel.cs | 24 + .../Views/MainOptionsPanel.xaml | 4 + .../Views/MainOptionsPanel.xaml.cs | 10 + PluginCommon/PluginCommon.csproj | 1 + PluginCommon/Tools.cs | 8 + PluginCommonTests/Class1.cs | 12 + SitePluginTests/SitePluginTests.csproj | 1 + 66 files changed, 5902 insertions(+) create mode 100644 BLiveIF/BLiveIF.csproj create mode 100644 BLiveIF/Message.cs create mode 100644 BLiveIF/Properties/AssemblyInfo.cs create mode 100644 BLiveSitePlugin/API.cs create mode 100644 BLiveSitePlugin/BLiveCommentData.cs create mode 100644 BLiveSitePlugin/BLiveCommentViewModel.cs create mode 100644 BLiveSitePlugin/BLiveOptionsPanel.xaml create mode 100644 BLiveSitePlugin/BLiveOptionsPanel.xaml.cs create mode 100644 BLiveSitePlugin/BLiveOptionsTabPage.cs create mode 100644 BLiveSitePlugin/BLiveOptionsViewModel.cs create mode 100644 BLiveSitePlugin/BLiveSiteContext.cs create mode 100644 BLiveSitePlugin/BLiveSiteOptions.cs create mode 100644 BLiveSitePlugin/BLiveSitePlugin.csproj create mode 100644 BLiveSitePlugin/BLiveWebsocket.cs create mode 100644 BLiveSitePlugin/BlackListProvider.cs create mode 100644 BLiveSitePlugin/CommentPostPanel.xaml create mode 100644 BLiveSitePlugin/CommentPostPanel.xaml.cs create mode 100644 BLiveSitePlugin/CommentPostPanelViewModel.cs create mode 100644 BLiveSitePlugin/CommentProvider.cs create mode 100644 BLiveSitePlugin/Context.cs create mode 100644 BLiveSitePlugin/DataSource.cs create mode 100644 BLiveSitePlugin/DynamicJson.cs create mode 100644 BLiveSitePlugin/Exceptions.cs create mode 100644 BLiveSitePlugin/IBLiveCommentData.cs create mode 100644 BLiveSitePlugin/IBLiveWebsocket.cs create mode 100644 BLiveSitePlugin/IBlackListProvider.cs create mode 100644 BLiveSitePlugin/Low/BlackList/Class1.cs create mode 100644 BLiveSitePlugin/Low/Chats/Class1.cs create mode 100644 BLiveSitePlugin/Low/External/Movies/Class1.cs create mode 100644 BLiveSitePlugin/Low/LivePage/Class1.cs create mode 100644 BLiveSitePlugin/Low/Movies/Class1.cs create mode 100644 BLiveSitePlugin/Message/BLiveComment.cs create mode 100644 BLiveSitePlugin/Message/BLiveConnected.cs create mode 100644 BLiveSitePlugin/Message/BLiveDisconnected.cs create mode 100644 BLiveSitePlugin/Message/BLiveMessageContext.cs create mode 100644 BLiveSitePlugin/Message/BLiveMessageMethods.cs create mode 100644 BLiveSitePlugin/Message/MessageMetadata.cs create mode 100644 BLiveSitePlugin/Metadata.cs create mode 100644 BLiveSitePlugin/MovieInfo.cs create mode 100644 BLiveSitePlugin/Packet.cs create mode 100644 BLiveSitePlugin/Properties/AssemblyInfo.cs create mode 100644 BLiveSitePlugin/Properties/Resources.Designer.cs create mode 100644 BLiveSitePlugin/Properties/Resources.resx create mode 100644 BLiveSitePlugin/Tools.cs create mode 100644 BLiveSitePlugin/UserViewModel.cs create mode 100644 BLiveSitePlugin/Websocket.cs create mode 100644 BLiveSitePlugin/app.config create mode 100644 BLiveSitePlugin/sprite_premium_landing.png create mode 100644 BLiveSitePlugin/sprite_v4.png create mode 100644 BLiveSitePlugin/sprite_v5.png create mode 100644 BLiveSitePlugin/sprite_v6.png create mode 100644 BLiveSitePlugin/sprites.png create mode 100644 MultiCommentViewer/ViewModels/CommentViewModel/BLiveCommentViewModel.cs diff --git a/BLiveIF/BLiveIF.csproj b/BLiveIF/BLiveIF.csproj new file mode 100644 index 00000000..c91b685b --- /dev/null +++ b/BLiveIF/BLiveIF.csproj @@ -0,0 +1,41 @@ + + + net462 + 8.0 + Release;Beta;Alpha;Debug + + + bin\Release\ + TRACE + 4 + pdbonly + true + prompt + 4 + + + bin\Beta\ + TRACE;BETA + 4 + true + pdbonly + AnyCPU + prompt + + + TRACE;DEBUG;ALPHA + 4 + full + true + false + + + DEBUG;TRACE + 4 + full + true + + + + + \ No newline at end of file diff --git a/BLiveIF/Message.cs b/BLiveIF/Message.cs new file mode 100644 index 00000000..8892d4a6 --- /dev/null +++ b/BLiveIF/Message.cs @@ -0,0 +1,70 @@ +using SitePlugin; +using System; +using System.Collections.Generic; + +namespace BLiveSitePlugin +{ + public enum BLiveMessageType + { + Unknown, + Comment, + //Item, + Stamp, + Yell, + Connected, + Disconnected, + } + + + public interface IBLiveMessage : ISiteMessage + { + BLiveMessageType BLiveMessageType { get; } + } + public interface IBLiveConnected : IBLiveMessage + { + string Text { get; } + } + public interface IBLiveDisconnected : IBLiveMessage + { + string Text { get; } + } + public interface IBLiveComment : IBLiveMessage + { + IEnumerable NameItems { get; } + IEnumerable MessageItems { get; } + string Id { get; } + DateTime PostTime { get; } + string UserId { get; } + } + public interface IBLiveStamp : IBLiveMessage + { + IMessageImage Stamp { get; } + string Message { get; } + IEnumerable NameItems { get; set; } + IMessageImage UserIcon { get; } + DateTime PostTime { get; } + string Id { get; } + } + public interface IBLiveYell : IBLiveMessage + { + string YellPoints { get; } + string Message { get; } + IEnumerable NameItems { get; } + IMessageImage UserIcon { get; } + DateTime PostTime { get; } + string Id { get; } + } + //public interface IBLiveItem : IBLiveMessage + //{ + // string ItemName { get; } + // int ItemCount { get; } + // //string Comment { get; } + // long Id { get; } + // //string UserName { get; } + // string UserPath { get; } + // long UserId { get; } + // string AccountName { get; } + // long PostedAt { get; } + // string UserIconUrl { get; } + //} +} \ No newline at end of file diff --git a/BLiveIF/Properties/AssemblyInfo.cs b/BLiveIF/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/BLiveIF/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/BLiveSitePlugin/API.cs b/BLiveSitePlugin/API.cs new file mode 100644 index 00000000..54dee792 --- /dev/null +++ b/BLiveSitePlugin/API.cs @@ -0,0 +1,231 @@ +using Codeplex.Data; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace BLiveSitePlugin.Low.BanList +{ + public class Item + { + public string banned_user_id { get; set; } + } + + public class Data + { + public List items { get; set; } + } + + public class RootObject + { + public int status { get; set; } + public Data data { get; set; } + } +} +namespace BLiveSitePlugin +{ + class Me + { + public string DisplayName { get; set; } + public string UserPath { get; set; } + } + static class API + { + public static async Task GetMeAsync(IDataSource server, CookieContainer cc) + { + var me = new Me(); + var url = "https://www.blive.tv"; + var res = await server.GetAsync(url, cc); + var match0 = Regex.Match(res, "
\\s*([^<\\s]*)?\\s*
"); + if (match0.Success) + { + var displayName = match0.Groups[1].Value; + me.DisplayName = displayName; + } + //
kv510k
+ var match1 = Regex.Match(res, "
([^<]+)
"); + if (match1.Success) + { + var userPath = match1.Groups[1].Value; + me.UserPath = userPath; + } + return me; + } + public static async Task GetMovieInfo(IDataSource dataSource, string liveId, CookieContainer cc) + { + //https://public.blive.tv/external/api/v5/movies/pC8n3HQX5gh + var url = "https://public.blive.tv/external/api/v5/movies/" + liveId; + var ret = await dataSource.GetAsync(url, cc); + var obj = Tools.Deserialize(ret); + return new MovieInfo(obj); + } + public static async Task GetChannelMovies(IDataSource dataSource, string channelId) + { + //https://public.blive.tv/external/api/v5/movies?channel_id=rainbow6jp + var url = "https://public.blive.tv/external/api/v5/movies?channel_id=" + channelId; + var ret = await dataSource.GetAsync(url); + var obj = Tools.Deserialize(ret); + return obj; + } + public static async Task GetMovies(IDataSource dataSource, string channelId) + { + var url = $"https://public.blive.tv/external/api/v5/movies?channel_id={channelId}&sort=onair_status"; + var res = await dataSource.GetAsync(url); + var obj = Tools.Deserialize(res); + return obj; + } + public static async Task> GetBanList(IDataSource dataSource, Context context) + { + //var url=$"https://www.blive.tv/viewapp/api/v3/blacklist/list?movie_id={movieId}&user_type=2&Uuid={context.Uuid}&Token={context.Token}&Random={context.Random}"; + //var res = await dataSource.GetAsync(url); + //var json = JsonConvert.DeserializeObject(res); + //var list = new List(); + //if (json.data!= null && json.data.items != null) + //{ + // foreach (var item in json.data.items) + // { + // list.Add(item.banned_user_id); + // } + //} + //return list; + var list = new List(); + var url = "https://apiv5.blive.tv/api/v5/users/me/blacklists"; + var headers = new Dictionary + { + { "uuid", context.Uuid }, + {"access-token", context.AccessToken }, + }; + var res = await dataSource.GetAsync(url, headers); + var d = DynamicJson.Parse(res); + if (!d.IsDefined("status")) + { + return list; + } + switch ((int)d.status) + { + case 0: + var s = (string)d.data.items.ToString(); + var low = JsonConvert.DeserializeObject(s); + foreach(var item in low) + { + list.Add(item.Id); + } + break; + default: + //{"message":"authorization required","status":-4} + return list; + } + + + return list; + + } + public static async Task GetWebsocketContext2(IDataSource dataSource, string movieId, CookieContainer cc) + { + var url = $"https://chat.blive.tv/socket.io/?movieId={movieId}&EIO=3&transport=polling&t={Tools.Yeast()}"; + var bytes = await dataSource.GetByteArrayAsync(url,cc); + var str = Tools.Bytes2String(bytes); + var packet = Packet.Parse(str) as PacketOpen; + return packet.Context; + } + public static async Task<(Low.Chats.RootObject[], string raw)> GetChats(IDataSource dataSource, string liveId, DateTime toCreatedAt, CookieContainer cc) + { + //https://public.blive.tv/external/api/v5/movies/9PgmVnlqtMz/chats?to_created_at=2018-07-24T19:32:50.395Z + var url = "https://public.blive.tv/external/api/v5/movies/" + liveId + "/chats?to_created_at=" + toCreatedAt.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); + var res = await dataSource.GetAsync(url, cc); + var obj = Tools.Deserialize(res); + return (obj, res); + } + /// + /// + /// + /// + /// + /// + /// 投稿日時(JST) + /// + /// + public static async Task PostCommentAsync(IDataSource server, string liveId, string comment, DateTime postTime, Context context) + { + var headers = new Dictionary + { + { "uuid", context.Uuid }, + { "access-token", context.AccessToken }, + }; + var url = $"https://apiv5.blive.tv/api/v5/movies/{liveId}/chats"; + var data = $"{{\"message\":\"{comment}\",\"quality_type\":0,\"messaged_at\":\"{postTime.ToString("yyyy-MM-ddTHH:mm:ss.fff+09:00")}\",\"league_key\":\"\",\"to_user_id\":\"\"}}"; + var res = await server.PostJsonAsync(url, headers, data); + //{"message":"authorization required","status":-4} + //{"status":0,"data":{"type":"chat","items":[{"id":213829498,"message":"a_a","quality_type":0,"posted_at":"2018-11-01T02:35:25+09:00","stamp":null,"yell_type":null,"yell":null,"user":{"id":"kv510k","blive_user_id":137594,"recxuser_id":20487471,"nickname":"たこやき","introduction":"","icon_image_url":"https://hayabusa.io/blive-image/user/204875/20487471.w90.v1470867009.png?format=png","l_icon_image_url":"https://hayabusa.io/blive-image/user/204875/20487471.w320.v1470867009.png?format=png","cover_image_url":"","follows":5,"followers":1,"is_premium":false,"premium_start_at":null,"premium_charge_type":null,"is_official":false,"is_fresh":false,"is_warned":false,"is_team":false,"is_league_yell":false,"is_live":false,"live_views":0},"to_user":null,"chat_setting":{"name_color":"#F6A434","is_premium_hidden":false},"is_moderating":false,"has_banned_word":false}]}} + return; + } + } +} +namespace BLiveSitePlugin.Low +{ + public class WebsocketContext2 + { + public string sid { get; set; } + public List upgrades { get; set; } + public int pingInterval { get; set; } + public int pingTimeout { get; set; } + } + public class Item + { + public string user_id { get; set; } + public string user_name { get; set; } + public string user_type { get; set; } + public string user_key { get; set; } + public int user_rank { get; set; } + public string user_icon { get; set; } + public string chat_id { get; set; } + public string message { get; set; } + public Stamp stamp { get; set; } + public string item { get; set; } + public int supporter_rank { get; set; } + public int is_creaters { get; set; } + public string golds { get; set; } + public string cre_dt { get; set; } + public int is_fresh { get; set; } + public int is_warned { get; set; } + public int has_banned_word { get; set; } + public int is_moderator { get; set; } + public int is_premium { get; set; } + public int is_premium_hidden { get; set; } + public string user_color { get; set; } + public Yell yell { get; set; } + public string display_dt { get; set; } + public string del_flg { get; set; } + public string quality_type { get; set; } + } + public class Yell + { + public string yell_id { get; set; } + public string name { get; set; } + public string label { get; set; } + public string image_url { get; set; } + public string points { get; set; } + public string yells { get; set; } + public string ticker_seconds { get; set; } + } + public class Stamp + { + public string stamp_id { get; set; } + public string group_id { get; set; } + public string image_url { get; set; } + } + public class Data + { + public List items { get; set; } + } + + public class ChatList + { + public int status { get; set; } + public Data data { get; set; } + } +} \ No newline at end of file diff --git a/BLiveSitePlugin/BLiveCommentData.cs b/BLiveSitePlugin/BLiveCommentData.cs new file mode 100644 index 00000000..50a663ca --- /dev/null +++ b/BLiveSitePlugin/BLiveCommentData.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using SitePlugin; + +namespace BLiveSitePlugin +{ + class BLiveCommentData : IBLiveCommentData + { + public bool IsYell => !string.IsNullOrEmpty(YellPoints); + public string YellPoints { get; set; } + public string Message { get; set; } + public string Id { get; set; } + public string UserId { get; set; } + public DateTime PostTime { get; set; } + public string UserKey { get; set; } + public string UserType { get; set; } + public IMessageImage Stamp { get; set; } + public string Name { get; set; } + public List NameIcons { get; set; } + public TimeSpan Elapsed { get; set; } + public string UserIconUrl { get; set; } + } +} diff --git a/BLiveSitePlugin/BLiveCommentViewModel.cs b/BLiveSitePlugin/BLiveCommentViewModel.cs new file mode 100644 index 00000000..ec1cf8ec --- /dev/null +++ b/BLiveSitePlugin/BLiveCommentViewModel.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Common; +using SitePlugin; + +namespace BLiveSitePlugin +{ + public interface IBLiveCommentViewModel : ICommentViewModel + { + string PostDate { get; } + string Elapsed { get; } + bool IsStamp { get; } + bool IsYell { get; } + } + class BLiveCommentViewModel : CommentViewModelBase, IBLiveCommentViewModel + { + public override MessageType MessageType { get; protected set; } + private ICommentOptions _options; + private readonly IBLiveSiteOptions _siteOptions; + + public string PostDate { get; } + public string Elapsed { get; } + public override string UserId { get; } + public bool IsStamp { get; } + public bool IsYell { get; } + public BLiveCommentViewModel(IBLiveCommentData commentData, ICommentOptions options, IBLiveSiteOptions siteOptions, ICommentProvider commentProvider, bool isFirstComment, IUser user) + : base(options, user, commentProvider, isFirstComment) + { + MessageType = MessageType.Comment; + _options = options; + _siteOptions = siteOptions; + UserId = commentData.UserId; + Id = commentData.Id; + PostDate = commentData.PostTime.ToString("HH:mm:ss"); + var elapsed = commentData.Elapsed; + Elapsed = Tools.ElapsedToString(elapsed); + IsStamp = commentData.Stamp != null; + IsYell = commentData.IsYell; + if (!string.IsNullOrEmpty(commentData.UserIconUrl)) + { + Thumbnail = new MessageImage { Url = commentData.UserIconUrl }; + } + if (siteOptions.IsAutoSetNickname) + { + var nick = ExtractNickname(commentData.Message); + if (!string.IsNullOrEmpty(nick)) + { + user.Nickname = nick; + } + } + //Name + { + var nameItems = new List(); + nameItems.Add(MessagePartFactory.CreateMessageText(commentData.Name)); + nameItems.AddRange(commentData.NameIcons); + NameItemsInternal = nameItems; + } + //Message + { + var messageItems = new List(); + if (commentData.IsYell) + { + MessageType = MessageType.BroadcastInfo; + messageItems.Add(MessagePartFactory.CreateMessageText("エールポイント:" + commentData.YellPoints + Environment.NewLine)); + } + messageItems.Add(MessagePartFactory.CreateMessageText(commentData.Message)); + if (commentData.Stamp != null) + { + MessageType = MessageType.BroadcastInfo; + messageItems.Add(commentData.Stamp); + } + MessageItems = messageItems; + } + Init(); + } + protected virtual void PlaySound(string filePath) + { + var player = new System.Media.SoundPlayer(filePath); + player.Play(); + } + public override async Task AfterCommentAdded() + { + await Task.Yield(); + try + { + if (IsStamp) + { + if (_siteOptions.IsPlayStampMusic && !string.IsNullOrEmpty(_siteOptions.StampMusicFilePath)) + { + PlaySound(_siteOptions.StampMusicFilePath); + } + } + if (IsYell) + { + if (_siteOptions.IsPlayYellMusic && !string.IsNullOrEmpty(_siteOptions.YellMusicFilePath)) + { + PlaySound(_siteOptions.YellMusicFilePath); + } + } + } + catch (Exception ex) + { + Debug.WriteLine(ex.Message); + } + } + } +} diff --git a/BLiveSitePlugin/BLiveOptionsPanel.xaml b/BLiveSitePlugin/BLiveOptionsPanel.xaml new file mode 100644 index 00000000..658afee2 --- /dev/null +++ b/BLiveSitePlugin/BLiveOptionsPanel.xaml @@ -0,0 +1,21 @@ + + + + +