View difference between Paste ID: NSVvAPVe and GYGKyg8r
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)))