SHOW:
|
|
- or go back to the newest paste.
1 | //API ACCESS | |
2 | on ^*:logon:*:{ | |
3 | if ($network == twitch) && ($twitch(# [ $+ [ $mnick ] ]).token) { | |
4 | .raw PASS oauth: $+ $v1 | |
5 | .raw NICK $mnick | |
6 | haltdef | |
7 | } | |
8 | } | |
9 | ||
10 | on @*:text:!commercial*:#:{ | |
11 | if ($nick isop #) twitch.commercial # $iif($2 isnum,$2) | |
12 | } | |
13 | ||
14 | on @*:text:/^!(topic|game)/iS:#:{ | |
15 | var %switch $iif($1 == !topic,status,game) | |
16 | if ($2 != $null) { | |
17 | if ($nick isop #) twitch.topic # %switch $2- | |
18 | } | |
19 | } | |
20 | ||
21 | alias twitch.follow { | |
22 | var %user = $1, %user.chan = #$1, %target = $2, %chan = $3 | |
23 | inc -e %nonce | |
24 | var %sockname = twitch.follow. $+ %nonce | |
25 | ||
26 | hfree -w %sockname | .hmake %sockname | |
27 | hadd %sockname oath.token $twitch(%user.chan).token | |
28 | hadd %sockname request /kraken/users/ $+ %user $+ /follows/channels/ $+ %target | |
29 | hadd %sockname method PUT | |
30 | hadd %sockname data | |
31 | hadd %sockname chan %chan | |
32 | hadd %sockname target %target | |
33 | hadd %sockname signal twitch.follow | |
34 | sockopen -e %sockname api.twitch.tv 443 | |
35 | } | |
36 | ||
37 | on *:signal:twitch.follow:{ | |
38 | var %err = $1, %sockname = $2, %header = $3, %data = $4 | |
39 | var %chan = $hget(%sockname,chan) | |
40 | ||
41 | if (* 200 OK iswm $read(%header,n,1)) $iif(%chan,msg %chan,echo -ag) Successfully followed $json(%data,channel,display_name) | |
42 | else $iif(%chan,msg %chan,echo -ag) Could not follow $hget(%sockname,target) | |
43 | ||
44 | hfree -w %sockname | |
45 | if ($isfile(%header)) .remove %header | |
46 | if ($isfile(%data)) .remove %data | |
47 | } | |
48 | ||
49 | alias followers.update { | |
50 | if (-* iswm $1) { | |
51 | var %switches = $1 | |
52 | tokenize 32 $2- | |
53 | } | |
54 | var %chan = #$$1, %limit = $iif($2,$2,25), %offset = $iif($3,$3,0) | |
55 | var %sockname = twitch.followers. $+ $ticks | |
56 | hfree -w %sockname | .hmake %sockname | |
57 | hadd %sockname chan %chan | |
58 | hadd %sockname limit %limit | |
59 | hadd %sockname offset %offset | |
60 | hadd %sockname request /kraken/channels/ $+ $mid(%chan,2-) $+ /follows?limit= $+ %limit $+ &offset= $+ %offset | |
61 | hadd %sockname method GET | |
62 | hadd %sockname signal followers.update | |
63 | if (s isin %switches) hadd %sockname show 1 | |
64 | if (!$hget(followers. $+ %chan)) hadd %sockname init 1 | |
65 | sockopen -e %sockname api.twitch.tv 443 | |
66 | return %sockname | |
67 | } | |
68 | ||
69 | on *:signal:followers.update:{ | |
70 | var %err = $1, %sockname = $2, %header = $3, %data = $4 | |
71 | var %chan = $hget(%sockname,chan), %init = $hget(%sockname,init), %show = $hget(%sockname,show) | |
72 | ||
73 | if (* 200 OK iswm $read(%header,n,1)) { | |
74 | if (!$hget(followers. $+ %chan)) { | |
75 | .hmake -s followers. $+ %chan $iif($calc($json(%data,_total) / 10) > 100,$v1,$v2) | |
76 | if ($ini(followers.ini,%chan,0) > 0) hload -i followers. $+ %chan followers.ini %chan | |
77 | } | |
78 | ||
79 | var %i = 0, %n = $json(%data,follows).count, %new.count | |
80 | while (%i < %n) { | |
81 | var %name = $json(%data,follows,%i,user,name) | |
82 | var %display_name = $json(%data,follows,%i,user,display_name) | |
83 | if (!$hget(followers. $+ %chan,%name)) { | |
84 | hadd followers. $+ %chan %name 1 | |
85 | if (!%init) && (%show) { | |
86 | set -nz %followers. $+ %chan %followers. [ $+ [ %chan ] ] %display_name | |
87 | if ($calc($len(%followers. [ $+ [ %chan ] ]) + $len(%display_name)) > 350) { | |
88 | var %msg = Welcome to our new follower $+ $iif($numtok(%followers. [ $+ [ %chan ] ],32) > 1,s:,:) $regsubex(%followers. [ $+ [ %chan ] ],/( $+ $chr(32) $+ )/g,$iif(\n == \0,$iif(\0 > 2,$chr(44),$chr(32)) and $chr(32),$chr(44) $+ $chr(32))) $+ ! | |
89 | .timer 1 $iif(%flood.protection,$v1,0) msg %chan $safe(%msg) | |
90 | inc -z %flood.protection 5 | |
91 | unset %followers. [ $+ [ %chan ] ] | |
92 | } | |
93 | } | |
94 | inc %new.count | |
95 | } | |
96 | else break | |
97 | inc %i | |
98 | } | |
99 | ||
100 | if (%new.count == $hget(%sockname,limit)) { | |
101 | followers.update %chan 100 $calc($hget(%sockname,limit) + $hget(%sockname,offset)) | |
102 | var %next = $result | |
103 | if (%init) hadd %next init 1 | |
104 | if (%show) hadd %next show 1 | |
105 | } | |
106 | else { | |
107 | if (!%init) && (%show) && (%new.count) { | |
108 | var %msg = Welcome to our new follower $+ $iif($numtok(%followers. [ $+ [ %chan ] ],32) > 1,s:,:) $regsubex(%followers. [ $+ [ %chan ] ],/( $+ $chr(32) $+ )/g,$iif(\n == \0,$iif(\0 > 2,$chr(44),$chr(32)) and $chr(32),$chr(44) $+ $chr(32))) $+ ! | |
109 | .timer 1 $iif(%flood.protection,$v1,0) msg %chan $safe(%msg) | |
110 | inc -z %flood.protection 5 | |
111 | } | |
112 | unset %followers. [ $+ [ %chan ] ] | |
113 | if ($hget(followers. $+ %chan)) hsave -i followers. $+ %chan followers.ini %chan | |
114 | } | |
115 | } | |
116 | ||
117 | hfree -w %sockname | |
118 | if ($isfile(%header)) .remove %header | |
119 | if ($isfile(%data)) .remove %data | |
120 | } | |
121 | ||
122 | alias twitch.commercial { | |
123 | var %chan = #$$1, %length = $2 | |
124 | var %sockname = twitch.topic. $+ $ticks | |
125 | hfree -w %sockname | .hmake %sockname | |
126 | hadd %sockname oath.token $twitch(%chan).token | |
127 | hadd %sockname method POST | |
128 | hadd %sockname request /kraken/channels/ $+ $mid(%chan,2-) $+ /commercial | |
129 | hadd %sockname signal twitch.commercial | |
130 | if (%length) hadd %sockname data length= $+ %length | |
131 | sockopen -e %sockname api.twitch.tv 443 | |
132 | set -z % [ $+ [ # $+ .commercial ] ] 480 | |
133 | set % [ $+ [ # $+ .titlebar ] ] $window(%chan).title | |
134 | .timer. $+ # $+ .commercial 480 1 titlebar.update.commercial @ [ $+ [ $window(%chan).wid ] ] | |
135 | } | |
136 | ||
137 | on *:signal:twitch.commercial:{ | |
138 | var %err = $1, %sockname = $2, %header = $3, %data = $4 | |
139 | var %chan = $hget(%sockname,chan) | |
140 | ||
141 | if (* 2* !iswm $read(%header,n,1)) { | |
142 | twitch.debug Error: $iif($v2,$v1,could not read header) | |
143 | var %error = $json(%data,error) | |
144 | var %message = $json(%data,message) | |
145 | if (%error != $null) && (%message != $null) { twitch.debug Error: %error $+ , %message } | |
146 | } | |
147 | ||
148 | hfree -w %sockname | |
149 | if ($isfile(%header)) .remove %header | |
150 | if ($isfile(%data)) .remove %data | |
151 | } | |
152 | ||
153 | alias titlebar.update.commercial { | |
154 | if (% [ $+ [ # $+ .commercial ] ] > 0) { titlebar $$1 - Commercial available in $duration($v1) } | |
155 | else { titlebar $$1 % [ $+ [ # $+ .titlebar ] ] | unset % [ $+ [ # $+ .titlebar ] ] | .timer [ $+ [ $ctimer ] ] off } | |
156 | } | |
157 | ||
158 | alias twitch.topic { | |
159 | var %chan = $1, %switch = $2, %topic = 3- | |
160 | var %sockname = twitch.topic. $+ $ticks | |
161 | hfree -w %sockname | .hmake %sockname | |
162 | hadd %sockname chan %chan %switch | |
163 | hadd %sockname oath.token $twitch(%chan).token | |
164 | hadd %sockname request /kraken/channels/ $+ $mid(%chan,2-) | |
165 | if (%topic != $null) { | |
166 | hadd %sockname method PUT | |
167 | hadd %sockname data channel[ $+ $switch $+ ]= $+ $urlencode(%topic) | |
168 | hadd %sockname signal topic.set | |
169 | } | |
170 | else { | |
171 | hadd %sockname method GET | |
172 | hadd %sockname signal topic.get | |
173 | } | |
174 | sockopen -e %sockname api.twitch.tv 443 | |
175 | } | |
176 | ||
177 | on *:signal:topic.get:{ | |
178 | var %err = $1, %sockname = $2, %header = $3, %data = $4, %chan = $5, %switch = $6 | |
179 | var %chan = $hget(%sockname,chan) | |
180 | ||
181 | if (* 200 OK iswm $read(%header,n,1)) msg %chan %switch $+ : $json(%data,%switch) | |
182 | else msg %chan Could not get %switch $+ ! | |
183 | ||
184 | hfree -w %sockname | |
185 | if ($isfile(%header)) .remove %header | |
186 | if ($isfile(%data)) .remove %data | |
187 | } | |
188 | ||
189 | on *:signal:topic.set:{ | |
190 | var %err = $1, %sockname = $2, %header = $3, %data = $4 | |
191 | var %chan = $hget(%sockname,chan) | |
192 | ||
193 | if (* 200 OK iswm $read(%header,n,1)) msg %chan Status set: $json(%data,status) | |
194 | else msg %chan Could not set status. | |
195 | ||
196 | hfree -w %sockname | |
197 | .remove %header | .remove %data | |
198 | } | |
199 | ||
200 | alias twitch.auth.request { | |
201 | var %chan = #$$1, %user = $mid(%chan,2-) | |
202 | var %client_id = $twitch(%chan).client_id | |
203 | var %secret = $twitch(%chan).secret | |
204 | var %redirect_uri = $twitch(%chan).redirect_uri | |
205 | var %scope = $twitch(%chan).scope_request | |
206 | ||
207 | if (!$sock(twitch.auth.request)) socklisten -d 127.0.0.1 twitch.auth.request 80 | |
208 | if (%secret) url $+(https://api.twitch.tv/kraken/oauth2/authorize?response_type=code&client_id=,%client_id,&redirect_uri=,%redirect_uri,&scope=,%scope,&state=,%user) | |
209 | else url $+(https://api.twitch.tv/kraken/oauth2/authorize?response_type=token&client_id=,%client_id,&redirect_uri=,%redirect_uri,&scope=,%scope,&state=,%user) | |
210 | } | |
211 | ||
212 | on *:socklisten:twitch.auth.request:{ | |
213 | var %sockname = twitch.auth.request. $+ $ticks | |
214 | if ($sock(%sockname)) return | |
215 | ||
216 | hfree -w %sockname | .hmake %sockname | |
217 | hadd %sockname header.signal twitch.auth.request | |
218 | ||
219 | sockaccept %sockname | |
220 | } | |
221 | ||
222 | on *:signal:twitch.auth.request:{ | |
223 | var %err = $1, %sockname = $2, %header = $3 | |
224 | var %request = $read(%header,n,1) | |
225 | ||
226 | if ($regex(%request,^GET / HTTP)) { | |
227 | var %document = <!doctype html><html><head><script>var x = null; x = new XMLHttpRequest(); x.open("GET", "/?" + document.location.hash.substring(1), false); x.send(null); document.write(x.responseText);</script></head></html> | |
228 | socket.respond %sockname %document | |
229 | } | |
230 | elseif ($regex(%request,^GET /\?access_token=(\w+).*&scope=([\w+]+).*&state=(\w+))) { | |
231 | var %access_token = $regml(1), %scope = $regml(2), %chan = # [ $+ [ $regml(3) ] ] | |
232 | ||
233 | socket.respond %sockname Successfully received token, return to mIRC. | |
234 | sockclose twitch.auth.request | |
235 | ||
236 | writeini twitch.ini %chan token %access_token | |
237 | ||
238 | remini twitch.ini %chan $+ .scope | |
239 | var %i = 1, %n = $numtok(%scope,43) | |
240 | while (%i <= %n) { | |
241 | writeini twitch.ini %chan $+ .scope $gettok(%scope,%i,43) 1 | |
242 | inc %i | |
243 | } | |
244 | } | |
245 | elseif ($regex(%request,^GET /\?code=(\w+).*&state=(\w+))) { | |
246 | var %code = $regml(1), %chan = # [ $+ [ $regml(2) ] ] | |
247 | ||
248 | twitch.token.request %chan %code %sockname | |
249 | sockclose twitch.auth.request | |
250 | } | |
251 | elseif ($regex(%request,^GET /favicon.ico HTTP)) { | |
252 | sockwrite -n %sockname HTTP/1.1 404 Not Found | |
253 | sockwrite -n %sockname Connection: close | |
254 | sockwrite -n %sockname $crlf | |
255 | } | |
256 | else socket.respond %sockname Could not retrieve token. | |
257 | ||
258 | if ($isfile(%header)) .remove %header | |
259 | } | |
260 | ||
261 | alias twitch.token.request { | |
262 | var %chan = #$$1, %code = $$2, %response.sockname = $$3 | |
263 | var %client_id = $twitch(%chan).client_id | |
264 | var %client_secret = $twitch(%chan).secret | |
265 | var %redirect_uri = $twitch(%chan).redirect_uri | |
266 | var %data = $+(client_id=,%client_id,&client_secret=,%client_secret,&grant_type=authorization_code,&redirect_uri=,%redirect_uri,&code=,%code) | |
267 | ||
268 | var %sockname = twitch.token.request. $+ $ticks | |
269 | hfree -w %sockname | .hmake %sockname | |
270 | hadd %sockname method POST | |
271 | hadd %sockname request /kraken/oauth2/token | |
272 | hadd %sockname data %data | |
273 | hadd %sockname signal twitch.token.request | |
274 | hadd %sockname chan %chan | |
275 | hadd %sockname twitch.code.respond %response.sockname | |
276 | sockopen -e %sockname api.twitch.tv 443 | |
277 | } | |
278 | ||
279 | on *:signal:twitch.token.request:{ | |
280 | var %err = $1, %sockname = $2, %header = $3, %data = $4 | |
281 | var %chan = $hget(%sockname,chan) | |
282 | ||
283 | if (* 200 OK iswm $read(%header,n,1)) { | |
284 | writeini twitch.ini %chan token $json(%data,access_token) | |
285 | ||
286 | remini twitch.ini %chan $+ .scope | |
287 | var %i = 0, %n = $json(%data,scope).count | |
288 | while (%i < %n) { | |
289 | writeini twitch.ini %chan $+ .scope $json(%data,scope,%i) 1 | |
290 | inc %i | |
291 | } | |
292 | ||
293 | socket.respond $hget(%sockname,twitch.code.respond) Successfully received token, return to mIRC. | |
294 | } | |
295 | else { | |
296 | socket.respond $hget(%sockname,twitch.code.respond) Could not retrieve token. | |
297 | } | |
298 | ||
299 | sockclose -w twitch.auth.request | |
300 | hfree -w %sockname | |
301 | if ($isfile(%header)) .remove %header | |
302 | if ($isfile(%data)) .remove %data | |
303 | } | |
304 | ||
305 | on *:sockopen:twitch.*:{ | |
306 | var %a = sockwrite -n $sockname | |
307 | ||
308 | %a $hget($sockname,method) $hget($sockname,request) HTTP/1.1 | |
309 | %a Host: api.twitch.tv | |
310 | %a Connection: close | |
311 | %a Accept: application/vnd.twitchtv.v2+json | |
312 | if ($hget($sockname,oath.token) != $null) %a Authorization: OAuth $v1 | |
313 | if ($hfind($sockname,data).item) { | |
314 | %a Content-Type: application/x-www-form-urlencoded | |
315 | %a Content-Length: $len($hget($sockname,data)) | |
316 | } | |
317 | %a $+($crlf,$hget($sockname,data)) | |
318 | } | |
319 | ||
320 | on *:sockread:twitch.*:{ | |
321 | var %headerfile = $sockname $+ .header.txt | |
322 | var %datafile = $sockname $+ .data.txt | |
323 | ||
324 | if (!$sock($sockname).mark) { | |
325 | var %header | sockread %header | |
326 | while (%header != $null) { | |
327 | write %headerfile %header | |
328 | if (%header == Transfer-Encoding: chunked) { | |
329 | hadd $sockname chunk-size 0 | |
330 | } | |
331 | sockread %header | |
332 | } | |
333 | if ($sockbr) { | |
334 | if ($hget($sockname,header.signal)) .signal $v1 0 $sockname %headerfile | |
335 | sockmark $sockname $true | |
336 | } | |
337 | } | |
338 | if ($sock($sockname).mark) { | |
339 | var %chunk | |
340 | if ($hget($sockname,chunk-size) == 0) { | |
341 | sockread %chunk | |
342 | if ($base(%chunk,16,10) !isnum) sockread %chunk | |
343 | hadd $sockname chunk-size $base(%chunk,16,10) | |
344 | if ($hget($sockname,chunk-size) == 0) { | |
345 | sockread %chunk | |
346 | return | |
347 | } | |
348 | } | |
349 | sockread $hget($sockname,chunk-size) &read | |
350 | while ($sockbr) { | |
351 | if ($hget($sockname,chunk-size) != 0) bwrite %datafile -1 -1 &read | |
352 | if ($hget($sockname,chunk-size)) hdec $sockname chunk-size $sockbr | |
353 | if ($hget($sockname,chunk-size) == 0) { | |
354 | sockread %chunk | |
355 | if ($base(%chunk,16,10) isnum) %chunk = $v1 | |
356 | else { | |
357 | sockread %chunk | |
358 | if ($base(%chunk,16,10) isnum) %chunk = $v1 | |
359 | } | |
360 | if (%chunk isnum) { | |
361 | hadd $sockname chunk-size %chunk | |
362 | if (%chunk == 0) sockread %chunk | |
363 | } | |
364 | } | |
365 | sockread $hget($sockname,chunk-size) &read | |
366 | } | |
367 | } | |
368 | } | |
369 | ||
370 | on *:sockclose:twitch.*:{ | |
371 | var %header = $sockname $+ .header.txt | |
372 | var %data = $sockname $+ .data.txt | |
373 | var %signal = $hget($sockname,signal) | |
374 | ||
375 | if (%signal) .signal %signal 0 $sockname %header %data | |
376 | else { | |
377 | hfree -w $sockname | |
378 | if ($isfile(%header)) .remove %header | |
379 | if ($isfile(%data)) .remove %data | |
380 | } | |
381 | } | |
382 | ||
383 | alias -l twitch { | |
384 | if ($1) && ($readini(twitch.ini,n,$1,$prop)) { return $v1 } | |
385 | else return $readini(twitch.ini,n,global,$prop) | |
386 | } | |
387 | ||
388 | alias twitch.setup { | |
389 | var %chan = $iif($1,$1,# [ $+ [ $mnick ] ]) | |
390 | var %scopes = chat_login+channel_read+channel_editor+channel_commercial+channel_subscriptions+channel_check_subscription+user_follows_edit | |
391 | ||
392 | writeini twitch.ini global redirect_uri http://localhost/ | |
393 | writeini twitch.ini global scope_request %scopes | |
394 | if (!$twitch(%chan).client_id) writeini twitch.ini %chan client_id PASTE_ID_HERE | |
395 | ||
396 | flushini twitch.ini | |
397 | run twitch.ini | |
398 | } | |
399 | ||
400 | menu channel { | |
401 | $iif(!$isfile(twitch.ini),Twitch Setup) : twitch.setup # | |
402 | $iif($twitch(#).client_id && !$twitch(#).token,Request Token) : twitch.auth.request # | |
403 | ||
404 | $iif($twitch(#).token, Commercial) | |
405 | .$iif(% [ $+ [ # $+ .commercial ] ],$style(2)) 30 seconds:twitch.commercial # 30 | |
406 | .$iif(% [ $+ [ # $+ .commercial ] ],$style(2)) 60 seconds:twitch.commercial # 60 | |
407 | .$iif(% [ $+ [ # $+ .commercial ] ],$style(2)) 90 seconds:twitch.commercial # 90 | |
408 | ||
409 | $iif($twitch(#).token, Followers) | |
410 | .Welcome now:followers.update -s # | |
411 | .$iif($timer(.followers. $+ #).delay == 300000,$style(1)) 5 minute interval:if ($timer(.followers. $+ #).delay == 300000) .timer.followers. $+ # off | else .timer.followers. $+ # 0 300 followers.update -s # | |
412 | .$iif($timer(.followers. $+ #).delay == 600000,$style(1)) 10 minute interval:if ($timer(.followers. $+ #).delay == 600000) .timer.followers. $+ # off | else .timer.followers. $+ # 0 600 followers.update -s # | |
413 | .$iif($timer(.followers. $+ #).delay == 1800000,$style(1)) 30 minute interval:if ($timer(.followers. $+ #).delay == 1800000) .timer.followers. $+ # off | else .timer.followers. $+ # 0 1800 followers.update -s # | |
414 | ||
415 | $iif($twitch(#).token,Topic) : twitch.topic # $$?="Enter topic:" | |
416 | ||
417 | $iif($twitch(#).token,Renew Token) : twitch.auth.request # | |
418 | } | |
419 | ||
420 | alias -l twitch.debug { | |
421 | if (!$window(@Twitch.tv)) window -e2hk0xz @Twitch.tv | |
422 | echo -i2t @Twitch.tv $1- | |
423 | } | |
424 | ||
425 | alias -l socket.respond { | |
426 | var %sockname = $$1, %data = $2- | |
427 | sockwrite -n %sockname HTTP/1.1 200 OK | |
428 | sockwrite -n %sockname Connection: close | |
429 | sockwrite -n %sockname Content-Length: $len(%data) | |
430 | sockwrite -n %sockname $+($crlf,%data) | |
431 | } | |
432 | ||
433 | alias safe return $!decode( $encode($1,m) ,m) | |
434 | alias -l urlencode return $regsubex($1-,/([^A-Z0-9])/gi,$+(%,$base($asc(\1),10,16))) |