-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathTwitch.cs
259 lines (205 loc) · 7.51 KB
/
Twitch.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sync.Source;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using Sync.Tools;
using System.Timers;
using Sync.MessageFilter;
using Sync.Tools.ConfigurationAttribute;
using Sync.Plugins;
namespace DefaultPlugin.Sources.Twitch
{
public class Twitch : SendableSource, IConfigurable
{
public const string SOURCE_NAME = "Twitch";
public const string SOURCE_AUTHOR = "DarkProjector";
static Regex parseRawMessageRegex = new Regex(@":(?<UserName>.+)!.+(PRIVMSG\s*#.+:)(?<Message>.+)");
TwitchIRCIO currentIRCIO;
int prev_ViewersCount = int.MinValue;
int onlineViewersCountInv = 6;
int viewersUpdateInterval = 60000;
public Timer viewerUpdateTimer;
Logger logger = new Logger<Twitch>();
public Twitch() : base(SOURCE_NAME, SOURCE_AUTHOR)
{
}
const string DEFAULT_CLIENT_ID = "esmhw2lcvrgtqw545ourqjwlg7twee";
public ConfigurationElement HostChannelName { get; set; } = "";
public ConfigurationElement CurrentClientID { get; set; } = "";
public ConfigurationElement SOAuth { get; set; } = "";
public bool IsUsingDefaultChannelID => string.IsNullOrWhiteSpace(CurrentClientID);
public string ClientID => IsUsingDefaultChannelID ? DEFAULT_CLIENT_ID:(string) CurrentClientID;
#region 接口实现
public void LoadConfig()
{
}
public void SaveConfig()
{
CurrentClientID = ClientID == DEFAULT_CLIENT_ID ? string.Empty : ClientID;
}
public void Connect(string roomName)
{
if (Status==SourceStatus.CONNECTING)
{
Disconnect();
}
if (string.IsNullOrWhiteSpace(HostChannelName))
{
logger.LogError("HostChannelName is empty");
return;
}
while (string.IsNullOrWhiteSpace(SOAuth))
{
var result = RequestSetup();
if (result == false)
return;
}
if (currentIRCIO != null)
{
currentIRCIO.DisConnect();
currentIRCIO.OnRecieveRawMessage -= onRecieveRawMessage;
currentIRCIO = null;
}
try
{
currentIRCIO = new TwitchIRCIO(roomName)
{
OAuth = SOAuth,
ChannelName = HostChannelName,
ClientID = ClientID
};
currentIRCIO.Connect();
currentIRCIO.OnRecieveRawMessage += onRecieveRawMessage;
currentIRCIO.OnError += CurrentIRCIO_OnError;
RaiseEvent(new BaseStatusEvent(SourceStatus.CONNECTED_WORKING));
UpdateChannelViewersCount();
viewerUpdateTimer = new Timer(viewersUpdateInterval);
viewerUpdateTimer.Elapsed += (z,zz) => UpdateChannelViewersCount();
viewerUpdateTimer.Start();
Status = SourceStatus.CONNECTED_WORKING;
}
catch (Exception e)
{
logger.LogError("twitch source connect error!" + e.Message);
Status = SourceStatus.USER_DISCONNECTED;
}
}
public void ReConnect()
{
Disconnect();
Connect();
}
private void CurrentIRCIO_OnError(TwitchIRCIO arg1, Exception arg2)
{
if (arg1 != currentIRCIO)
return;
logger.LogError($"IRC kernel occured exception:\"{arg2.Message}\",try to reconnect.");
try
{
ReConnect();
}
catch(Exception e)
{
logger.LogError($"can't reconnet:\"{e}\".");
RaiseEvent(new BaseStatusEvent(SourceStatus.USER_DISCONNECTED));
}
}
public override void Disconnect()
{
currentIRCIO?.DisConnect();
currentIRCIO = null;
RaiseEvent(new BaseStatusEvent(SourceStatus.USER_DISCONNECTED));
viewerUpdateTimer?.Stop();
viewerUpdateTimer?.Dispose();
Status = SourceStatus.USER_DISCONNECTED;
}
public override void Send(IMessageBase message)
{
currentIRCIO?.SendMessage(message.Message);
}
#endregion
public void onRecieveRawMessage(string rawMessage)
{
var result=parseRawMessageRegex.Match(rawMessage);
if (!result.Success)
return;
string userName = result.Groups["UserName"].Value;
string message = result.Groups["Message"].Value;
base.RaiseEvent<IBaseDanmakuEvent>(new BaseDanmakuEvent(message, userName,DateTime.Now.ToString()));
}
/// <summary>
/// 更新观众人数并汇报
/// </summary>
public async void UpdateChannelViewersCount()
{
//currentIRCIO?.SendRawMessage(@"NAMES");
int nowViewersCount = await Task.Run(() =>
{
string uri = $"https://api.twitch.tv/kraken/streams/{currentIRCIO.ChannelName}&client_id={currentIRCIO.ClientID}";
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "GET";
try
{
var response = (HttpWebResponse)request.GetResponse();
StreamReader stream;
using (stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
string data = stream.ReadToEnd();
string viewers = GetJSONValue(ref data, "viewers");
return int.Parse(viewers);
}
}
catch (Exception)
{
return prev_ViewersCount;//就当做啥事都没发生(
}
});
if (Math.Abs(nowViewersCount - prev_ViewersCount) > onlineViewersCountInv)
{
RaiseEvent(new BaseOnlineCountEvent() { Count = nowViewersCount });
prev_ViewersCount = nowViewersCount;
}
}
private bool RequestSetup()
{
TwitchAuthenticationDialog AuthDialog = new TwitchAuthenticationDialog(this);
var result = AuthDialog.ShowDialog();
return result != System.Windows.Forms.DialogResult.Cancel;
}
private string GetJSONValue(ref string text, string key)
{
var result = Regex.Match(text, $"{key}\":\"(.+?)\"");
if (!result.Success)
return null;
return result.Groups[1].Value;
}
public override void Connect() => Connect(HostChannelName);
public override string ToString()
{
return SOURCE_NAME;
}
public void onConfigurationLoad()
{
LoadConfig();
LiveID = HostChannelName;
}
public void onConfigurationSave()
{
SaveConfig();
HostChannelName = LiveID;
}
public override void Login(string user, string password)
{
RequestSetup();
}
public void onConfigurationReload()
{
onConfigurationLoad();
}
}
}