Coders-IRC


IRC for Coders

Clone detector


image

on *:Join:#: {
  var %host_to_search_for = $address($nick,2)
  var %number_from_that_host = $ialchan(%host_to_search_for,$chan,0)
  if (%number_from_that_host > 1) {
    ;we have clones!
    ;first set up our vars and loop
    var %count = 0
    unset %clones
    :loop
    inc %count
    ;loop through every nick, adding the nicks to %clones
    var %clones = %clones $ialchan(%host_to_search_for,$chan,%count).nick
    if (%count < %number_from_that_host) { goto loop }
    echo -t $chan 5(Clones Detected) 0 %count 7Clones From 5 $address($nick,2)
    echo -t $chan 5(Clones Nicks) 12 %clones
  }
}

Expand


Read More

AntiProxyScan v1.0


image

#####################################################################
#   Name: AntiProxyScan v1.0
#   Author: Epic (epicnet@mail.ru, http://epicnet.ru)
#   Description: Automatically scans all incoming connections to the server for proxy addresses and sets a server ban if found.
#####################################################################

alias -l proxyscanner_set {
  %ps_servers = all
  %ps_snomask = +cC
  %ps_btype = ZLINE
  %ps_btime = 3d
  %ps_breason = Your IP was found in DNSBL and it is suspected that is (VPN/Tor/Proxy). To unlock contact the chat administration.
  %ps_blogo = DNSBL: 01,04 BAN 
  %ps_mchan = #Services
  %ps_admins = Epic,Sleepyhead,Admin
}
alias -l proxyscanner_list {
  if ($hget(ps-dnsbl,0).item) .hfree -sw ps-dnsbl
  .hadd -m ps-dnsbl dnsbl.dronebl.org 4,5,6,7,8,9,10,13,15,17,255
  .hadd -m ps-dnsbl rbl.efnetrbl.org 1,3,4,5,6,7,8,9,10,11,12,13,14,15
  .hadd -m ps-dnsbl rbl.efnet.org 1,4,5
  .hadd -m ps-dnsbl tor.efnet.org 1
  .hadd -m ps-dnsbl cbl.abuseat.org 1,3,4,5,6,7,8,9,10,11,12,13,14,15
  .hadd -m ps-dnsbl sbl.spamhaus.org 1,5,6,7,8,9,10,12,13,14,15,255
  .hadd -m ps-dnsbl abuse-contacts.abusix.org 2,3,4
  .hadd -m ps-dnsbl safe.dnsbl.sorbs.net 1,3
  .hadd -m ps-dnsbl all.s5h.net 1,3
  .hadd -m ps-dnsbl bl-h1.rbl.polspam.pl 1
  .hadd -m ps-dnsbl postmaster.rfc-clueless.org 3
}
====================================================
on *:LOAD:{ proxyscanner_set | proxyscanner_list | if (!%ps_work) %ps_work = on }
on *:CONNECT: proxyscanner_set | proxyscanner_list | if (!%ps_work) %ps_work = on | if ($istok(%ps_servers,$server,44)) || (%ps_servers == all) { /mode $me +s %ps_snomask }
on *:TEXT:!ps*:#:{
  if ($1 == !ps && $istok(%ps_admins,$nick,44)) {
    if (!$2) { .notice $nick Syntax: !ps <start/stop/reload> | halt }
    if ($2 == start) { %ps_work = on | .notice $nick ProxyScanner on } | if ($2 == stop) { %ps_work = off | .notice $nick ProxyScanner off }
    if ($2 == reload) { proxyscanner_set | proxyscanner_list | .notice $nick ProxyScanner reload }
  }
}
on *:SNOTICE:*Client connecting*:{
  if (%ps_work == on) {
    if ($istok(%ps_servers,$nick,44)) || ($hget(ps,servers) == all) {
      var %ps_mask $remove($wildtok($1-,*@*,1,32),$chr(40),$chr(41)) | var %ps_nick $gettok(%ps_mask,1,33) | var %ps_ip $gettok(%ps_mask,2,64) | var %ps_id $gettok($gettok(%ps_mask,1,64),2,33)
      if ($ps_detectip(%ps_ip)) proxyscanner_check %ps_ip %ps_id %ps_nick
    }
  }
}
====================================================
alias -l proxyscanner_check {
  var %ps_reverse $ps_revip($1) | .hadd -mu60 ps-oip %ps_reverse $1 | .hadd -mu60 ps-oid %ps_reverse $2 | .hadd -mu60 ps-onick %ps_reverse $3
  var %ps_all $hget(ps-dnsbl,0).item | var %ps_q 1 | while (%ps_q <= %ps_all) {
    var %ps_name $hget(ps-dnsbl,%ps_q).item | var %ps_check $+(%ps_reverse,.,%ps_name)
    .dns %ps_check | inc %ps_q
  }
}
on *:DNS:{
  var %ps_i $dns(0) | while (%ps_i > 0) {
    var %ps_dnsname $dns(%ps_i) | var %ps_dnsip $dns(%ps_i).ip | var %ps_dnsnum $gettok(%ps_dnsip,4,46) | var %ps_dnsrip $gettok(%ps_dnsname,1-4,46) | var %ps_dnsrname $gettok(%ps_dnsname,5-,46)
    if (!$hget(ps-banip,%ps_dnsrip) && $istok($hget(ps-dnsbl,%ps_dnsrname),%ps_dnsnum,44)) {
      ;------------------------------------
      if ($me ison %ps_mchan) /msg %ps_mchan %ps_blogo $+(07,$hget(ps-onick,%ps_dnsrip),) => $+(04,$hget(ps-oid,%ps_dnsrip),@,$hget(ps-oip,%ps_dnsrip),) => $+(06,%ps_dnsrname,) $+($chr(40),07,%ps_dnsnum,,$chr(41)) - $ps_gettype(%ps_dnsname,%ps_dnsnum)
      if (%ps_btype == ZLINE) .ZLINE $hget(ps-oip,%ps_dnsrip) %ps_btime %ps_breason
      if (%ps_btype == KLINE) .KLINE $+(*@,$hget(ps-oip,%ps_dnsrip)) %ps_btime %ps_breason
      if (%ps_btype == GLINE) .GLINE $+(*@,$hget(ps-oip,%ps_dnsrip)) %ps_btime %ps_breason
      ;------------------------------------
      .hadd -mu30 ps-banip %ps_dnsrip 1 | .break
    } | dec %ps_i
  }
}
alias -l ps_revip { tokenize 46 $1 | return $+($4,.,$3,.,$2,.,$1) }
alias -l ps_detectip { tokenize 46 $1 | if ($0 == 4 && $1 isnum 0-255 && $2 isnum 0-255 && $3 isnum 0-255 && $4 isnum 0-255) { return 1 } }
alias -l ps_gettype {
  if (dronebl isin $1) { 
    if ($2 == 2) { return Sample }
    if ($2 == 3) { return IRC Drone }
    if ($2 == 5) { return Bottler }
    if ($2 == 6) { return Unknown Spambot/Drone }
    if ($2 == 7) { return DDOS Drone }
    if ($2 == 8) { return SOCKS Proxy }
    if ($2 == 9) { return HTTP Proxy }
    if ($2 == 10) { return Proxy Chain }
    if ($2 == 11) { return Web Page Proxy }
    if ($2 == 12) { return Open DNS Resolver }
    if ($2 == 13) { return Brute Force Attackers }
    if ($2 == 14) { return Open Wingate Proxy }
    if ($2 == 15) { return Compromised Router/Gateway }
    if ($2 == 16) { return Autorooting worms }
    if ($2 == 17) { return Automatically determined botnet IPs (experimental) }
    if ($2 == 18) { return DNS/MX type hostname detected on IRC }
  }
  if (rbl.efnet isin $1) { 
    if ($2 == 1) { return Open Proxy }
    if ($2 == 2) { return Spamtrap666 }
    if ($2 == 3) { return Spamtrap50 }
    if ($2 == 4) { return TOR } 
    if ($2 == 5) { return Drones/Flooding }
  }
  if (tor.efnet isin $1) { return Tor Server }
  if ($2 == 255) { return 10Unknown }
  else { return Unknown Proxy }
}

Expand


Read More

[DE] YouTube Announcer (mSL)


image

; #-> Allgemeine Informationen <-#
; Name: YouTube Announcer
; Author: Kylar
; Date: 25.09.2020
; Version: 1.0.0 - Erster Release
; Beschreibung: YouTube Announcer tut genau das, was der Name vermuten/befürchten lässt.
; Das Script sucht aktiv in allen Channels (die nicht ignoriert werden sollen) nach YouTube Links und liefert, über die Google API, Informationen zum Video.
; Dabei kann die Ausgabe für sich selbst (über Echo) oder als MSG im Channel erfolgen.
;
; Voraussetzungen: AdiIRC in der Version 3.8 oder höher oder mIRC in der Version 7.62 oder höher.
;                               Einen Google API-Key für die YouTube Data API v3 (siehe https://developers.google.com/youtube/v3/getting-started)
;
; #-> Installation <-#
; Script entsprechend in AdiIRC/mIRC laden und den Befehl /youtube_announcer aufrufen, um das Script einzustellen.
; Nachdem die Einstellungen vorgenommen wurden, reagiert das Script entsprechend auf Nachrichten.
;
; #-> Deinstallation <-#
; Einfach den Befehl /youtube_announcer deinstall eingeben und das Script entfernt alle globalen Variablen.
; ACHTUNG: Die aktuellen Einstellungen werden in der yta_settings.ini gespeichert und beim erneuten aufrufen von /youtube_announcer geladen.
; Für eine vollständige Deinstallation den Befehl /youtube_announcer deinstall aufrufen, das Script und die yta_settings.ini löschen.

;;   ##############
;;  # Dialog/GUI #
;; ##############
alias youtube_announcer {
  if ( $0 == 0 ) {
    dialog -m yta_d_main yta_d_main
  } 
  else {
    if ( $lower($1) == deinstall || $lower($1) == uninstall || $lower($1) == deinstallation ) {
      yta_uninstall
    }
  }
}

; TODO Unter Nachricht einstellen, dass die Vorschau auch per Echo erfolgen kann (für Farbe usw.)
; Haupt Dialog zum einstellen des Scripts
Dialog yta_d_main {

  ;; Main 
  title "YouTube Announcer"
  ; -1 -1 setzt den Dialog in die Mitte vom Hauptfenster
  size -1 -1 200 150
  option dbu

  menu "About", 100
  ;  menu "Hilfe", 101

  ;; Tab Allgemeine Einstellen
  tab "Allgemeine Einstellungen", 1, 0 0 200 150
  box "Parsing", 10, 5 15 190 70, tab 1
  ; Abstand in der Höhe bei Check muss mindestens 8 sein
  check "Channel Nachrichten Parsen", 11, 10 24 76 8, tab 1
  check "Privat Nachrichten Parsen", 12, 10 32 70 8, tab 1
  check "YT-Infos nur über Echo ausgeben", 22, 95 24 88 8, tab 1
  text "Anbieter die geparst werden sollen", 13, 10 43 180 8, tab 1
  list 14, 10 52 180 28, tab 1 size extsel check multse vsbar

  box "API", 15, 5 90 190 50, tab 1
  text "Damit das Script Informationen über YouTube Videos abrufen kann,", 16, 10 99 180 8, nowrap tab 1
  text "wird ein API-Key von "17, 10 107 50 8, nowrap tab 1
  link "Google", 18, 62 107 18 8, tab 1
  text "benötigt.  Der Key wird auschließlich zum ", 19, 80 107 100 8, tab 1
  text "Abrufen der Videoinformationen verwendet." 20, 10 115 180 12, tab 1
  edit "", 21, 20 125 150 10, tab 1

  ;; Anpassen der Nachricht die ausgegeben wird
  tab "Nachrichten-Formatierung", 3, 0 0 200 150  
  box "Nachricht", 30, 5 15 190 57, tab 3
  edit "", 31, 10 24 180 10, tab 3 autohs
  text "Vorschau", 32, 10 36 100 8, tab 3
  edit "", 33, 10 44 180 10, tab 3 rich read autohs
  check "Vorschau als  Echo ausgeben?", 38, 10 58 80 8, tab 3
  box "Platzhalter", 34, 5 75 190 40 , tab 3
  text "Die folgenden aufgelisteten Zeichenfolgen werden automatisch ersetzt.", 35, 10 84 180 8, tab 3
  text "<duration>, <title>, <channeltitle>, <publishedat>, <favoritecount>", 36, 10 94 180 8, tab 3
  text "<viewcount>, <likecount>, <dislikecount>, <commentcount>", 37, 10 102 180 8, tab 3

  ;; Channels/Nicks die ignoriert werden sollen
  tab "Ignorieren", 4, 0 0 200 150
  text "Server, Channel und Nicknames eintragen, die ignoriert werden sollen.", 40, 5 15 190 12, tab 4

  box "Eingabe", 41, 5 30 190 37, tab 4
  text "Format: [network:][#]Ziel.", 42, 10 40 75 8, tab 4 
  edit "", 43, 10 50 150 10, tab 4
  button "Hinzfügen", 44, 163 50 30 10, tab 4

  box "Liste der zu ignorierenden Objekte", 45, 5 72 190 70, tab 4
  list 46, 10 82 153 55, tab 4 size extsel vsbar
  button "Entfernen", 47, 165 82 27 55, tab 4 multi
}

; About Dialog (zeigt momentan nur Basic-Informationen an)
dialog yta_d_about {
  title "About - YouTube Announcer"
  size -1 -1 100 70
  option dbu

  text "Script Name: YouTube Announcer", 1, 5 5 100 8
  text "Author: Kylar", 2 , 5 13 100 8
  text "Date: September 2020", 3, 5 21 100 8
  text "Kurzbeschreibung: Liefert Informationen zu erkannten YouTube Links", 4, 5 29 190 20
  text "Voraussetzung: YouTube/Goole API-Key", 5, 5 50 100 14
}

;;#
;; Dialog Events
;;#
; Settings laden und die Tabs mit Inhalt befüllen
on *:DIALOG:yta_d_main:init:0: {
  did -a yta_d_main 14 youtube.com
  did -a yta_d_main 14 yu2.be
  did -a yta_d_main 14 youtu.be

  ; Wenn keine Settings vorhanden sind, entsprechend die settings ini laden oder erstellen
  if ( !$var(%yta/settings/*)) {
    yta_load_config   
  }

  var %i = 1
  while ( %i <= $var(%yta/settings/*) ) {
    var %j = 1, %fp = $var(%yta/settings/*, %i) ,%sec = $token(%fp, $calc($numtok(%fp, 47) - 1), 47), %item = $token(%fp, $numtok(%fp, 47), 47)
    var %val = $var(%yta/settings/*, %i).value

    ; Liste der zu ignorierenden Ziele befüllen
    if (%item == list ) { 
      $iif(%val != $chr(7), yta_fill_ignorelist, noop)

    }
    ; Die Nachricht, die ausgegeben werden soll, befüllen 
    elseif ( %item == msg ) {
      $iif(%val != $chr(7), yta_fill_msg, noop ) 

    }
    ; API-Key Feld befüllen   
    elseif ( %item == apikey ) {
      $iif(%val != $chr(7), yta_fill_apikey, noop )

    }
    ; URLS in der Liste markieren
    elseif ( %item == urls ) {
      if ( %val != $chr(7) ) {
        var %j = 1
        while ( %j <= $numtok(%val, 44) ) {
          var %k = 1, %val1 = $token(%val, %j, 44)          
          while ( %k <= $did(14).lines ) {
            if ($did(14, %k).text == %val1) {
              did -s yta_d_main 14 %k
            }
            inc %k
          }
          inc %j
        }
      }
    } 
    ; Checkbox für die Ausgabe der über Echo
    elseif ( %sec == General && %item == echo ) {
      if ( %val == 1 ) {
        did -c $dname 22
      }
    }
    ; Checkbox, ob Channel-Nachrichten geparst werden sollen
    elseif ( %item == cmsg ) {
      if ( %val == 1 ) {
        did -c $dname 11
      }      

    } 
    ; Checkbox, ob Private-Nachrichten geparst werden sollen
    elseif ( %item == pmsg ) {
      if ( %val == 1 ) {
        did -c $dname 12
      }
    }
    ; Einstellung für die Ausgabe der Vorschau    
    elseif ( %sec == Message && %item == echo ) {
      if ( %val == 1 ) {
        did -c $dname 38
      }
    }
    inc %i
  }
}

; Einstellungen beim Verlassen des Dialogs in die ini schreiben
on *:DIALOG:yta_d_main:close:0: {
  yta_save_config
}

; API-Key in Variable speichern
on *:DIALOG:yta_d_main:edit:21: {
  set %yta/settings/General/apikey $did(21).text
}

; Verarbeitung der Click-Events
; Im Tab IgnoreList: Multiselektion kann nicht als ganzes entfernt werden, nur einzelne Ziele können entfernt werden.
on *:DIALOG:yta_d_main:sclick:*: {
  if ( $did == 11 ) {
    ; channel nachricht
    set %yta/settings/General/cmsg $did(11).state
  } 
  elseif ( $did == 12 ) {
    ; private nachricht
    set %yta/settings/General/pmsg $did(12).state
  }
  elseif ( $did == 22 ) {
    set %yta/settings/General/echo $did(22).state
  }
  elseif ( $did == 14 ) {
    ;listbox mit urls
    if ( $did(14, $did(14).sel ).cstate == 1 ) {
      set %yta/settings/General/urls $addtok($did(14, $did(14).sel).text, %yta/settings/General/urls, 44)
    } 
    else {
      set %yta/settings/General/urls $remtok(%yta/settings/General/urls, $did(14, $did(14).sel).text, 0, 44)
    }
  } 
  elseif ($did == 44) { ; Tab Ignorelist 
    ; Hinzufügen
    if ($len($did(43).text) > 0) {
      if ( (, !isin $did(43).text) && $regex($did(43).text, /^(?:\w+:)?#?[a-zA-Z0-9:#\|]+/) ) {
        set %yta/settings/IgnoreList/list $addtok($did(43).text, %yta/settings/IgnoreList/list, 44)
        did -r yta_d_main 43
        yta_fill_ignorelist
      }
    }
  }
  elseif ( $did == 47 ) { ; Tab Ignorelist 
    ; Entfernen
    if ( $len($did(46).seltext) > 0 ) {
      set %yta/settings/IgnoreList/list $remtok(%yta/settings/IgnoreList/list, $did(46).seltext, 0,44)
      did -r yta_d_main 46
      didtok yta_d_main 46 44 %yta/settings/IgnoreList/list
    }
  } 
  elseif ( $did == 38 ) {
    set %yta/settings/Message/echo $did(38).state
  }
  elseif ( $did == 18 ) {
    .url https://developers.google.com/youtube/v3/getting-started
  }
}

; Das Textfeld "Vorschau" mit den Inhalt aus "Nachricht" befüllen und 
; Platzhalter durch Dummy-Daten ersetzen
on *:DIALOG:yta_d_main:edit:31: {
  if ($len($did(31).text) > 0) {
    var %t1 = publishedAt $+ $chr(7) $+ title $+ $chr(7) $+ channelTitle $+ $chr(7) $+ duration $+ $chr(7) $+favoritecount $+ $chr(7) $+ viewcount $+ $chr(7) $+ likecount $+ $chr(7) $+ dislikecount  $+ $chr(7) $+ commentcount
    var %t2 = 2012-10-01T15:27:35Z $+ $chr(7) $+ A very special Title $+ $chr(7) $+ TheChan Nel $+ $chr(7) $+ PT7H3M33S $+ $chr(7) $+ 60 $+ $chr(7) $+ 1250 $+ $chr(7) $+ 1000 $+ $chr(7) $+ 250 $+ $chr(7) $+ 450

    ; Vorschau soll auch per Echo erfolgen
    if ( %yta/settings/Message/echo == 1 ) { 
      echo -ga $yta_replace_placeholder($did(31).text, %t1, %t2)
    } 
    did -ri yta_d_main 33 1 $yta_replace_placeholder($did(31).text, %t1, %t2)
  } 
  else {
    did -r yta_d_main 33
  }
  set %yta/settings/Message/msg $did(31).text
}

; About Dialog öffnen 
on *:DIALOG:yta_d_main:menu:100 {
  ; Diese Operation blockt die UI und das Fenster MUSS geschlossen werden
  noop $dialog(yta_d_about, yta_d_about)
}

;;#
;;  Helfer-Funktionen
;;#

; Liste der zu ignorierenden Ziele füllen
alias yta_fill_ignorelist {
  did -r yta_d_main 46

  var %i = 1 
  while ( %i <= $numtok(%yta/settings/IgnoreList/list, 44) ) {
    var %val = $token(%yta/settings/IgnoreList/list, %i, 44)
    did -a yta_d_main 46 %val
    inc %i
  }
}

; Wird beim Dialog-Start aufgerufen, um "Vorschau" und "Nachricht" zu befüllen
alias yta_fill_msg {
  if ( $len(%yta/settings/Message/msg) > 0 ) {
    did -r yta_d_main 31
    did -a yta_d_main 31 %yta/settings/Message/msg

    var %t1 = publishedAt $+ $chr(7) $+ title $+ $chr(7) $+ channelTitle $+ $chr(7) $+ duration $+ $chr(7) $+favoritecount $+ $chr(7) $+ viewcount $+ $chr(7) $+ likecount $+ $chr(7) $+ dislikecount  $+ $chr(7) $+ commentcount
    var %t2 = 2012-10-01T15:27:35Z $+ $chr(7) $+ A very special Title $+ $chr(7) $+ TheChan Nel $+ $chr(7) $+ PT7H3M33S $+ $chr(7) $+ 60 $+ $chr(7) $+ 1250 $+ $chr(7) $+ 1000 $+ $chr(7) $+ 250 $+ $chr(7) $+ 450

    did -ri yta_d_main 33  1 $yta_replace_placeholder($did(31).text, %t1, %t2)
  }
}

; Wird beim Dialog-Start aufgerufen, um das Feld "APIKEY" zu befüllen
alias yta_fill_apikey {
  if ( $len(%yta/settings/General/apikey) > 0 ) {
    did -r yta_d_main 21
    did -a yta_d_main 21 %yta/settings/General/apikey
  }
}

; Ersetzt im Text ($1) alle Platzhalter ($2) mit den enstprechenden Werten ($3)
; Die Funktion erwartet 3 Token
; $1 = Text in dem ersetzt werden soll
; $2 = Eine Tokenliste (Trennzeichen $chr(7)) mit Wörtern die Ersetzt werden sollen (ohne < und >)
; $3 = Eine Tokenliste (Trennzeichen $chr(7)) mit der gleichen Länge wie $2 und den entrechpenden Werten die eingesetzt werden sollen.
; Rückgabe: Der übergebene Text ($1) mit den ersetzten Platzhaltern oder bei Fehler den gleichen Text
; Beispiel: //echo -ag $yta_replace_placeholder(Der <title> ist von <channeltitle>., title $+ $chr(7) $+ channeltitle, TESTTITLE $+ $chr(7) $+ Channel Title ist Super!)
alias yta_replace_placeholder {
  var %msg = $1

  if ($isid && $0 == 3) {

    if ( $numtok($2, 7) == $numtok($2, 7) ) {
      var %i = 1 
      while ( %i <= $numtok($2, 7) ) {
        var %key = $lower($token($2, %i, 7)), %val = $token($3, %i, 7)

        if ( (%key != title) && (%key != channelTitle) ) {
          var %val $yt_placeholder_format(%val)
        }

        noop $regsub(%msg, /< $+ %key $+ >/gi, %val, %msg)
        inc %i
      }
    }

    return %msg
  }
}

; Helferfunktion die Zahlen (1000 wird zu 1 Tsd), Published-Datum (2012-10-01T15:27:35Z zu 01.10.2012) und Lauflänge (PT3D1H5M30S zu 03:01:05:30) umwandelt
; Zahlen werden nur bis Mrd umgewandelt, alles was größer ist, wird normal ausgegeben
; Zeit wird, bei Fehler und so weiter, als 00:00:00 ausgegeben
; TODO Funktion mathematisch aufarbeiten und nicht so einen Quark nutzen :P aber so lange es funktioniert?
alias yt_placeholder_format {
  if ($isid && $0 == 1) {
    if ( $1 isnum ) {
      var %i = 3, %j = 1, %suff = Tsd.Mio.Mrd

      while ( %i <= 9 ) {
        var %v = $round($calc($1 / (10^%i)), 2)

        if ( $len($int(%v)) <= 3 && $int(%v) > 0  ) {
          return %v $token(%suff, %j, 46)
        }

        inc %i 3
        inc %j
      }

    }
    elseif ( $lower($left($1, 2)) == $lower(PT) ) {
      var %t = $lower($mid($1, 3, $len($1)))
      var %d = 00, %h = 00, %m = 00, %s = 00

      while ( $len(%t) >= 1 ) {
        if ( $left(%t, 1) isnum ) {
          var %tmp = %tmp $+ $left(%t, 1)
        } 
        else {
          var  % $+ $left(%t, 1) $iif($len(%tmp) == 1, 0) $+ %tmp
          unset %tmp
        }
        var %t = $mid(%t, 2, $len(%t))
      }

      return $iif(%d != 00, %d $+ :) $+ $iif(%h != 00, %h $+ :, 00:) $+ $iif(%m != 00, %m $+ :, 00:) $+ %s
    }
    elseif ( $numtok($1, 84) == 2  ) {
      var %date = $token($1, 1, 84)
      return $token(%date, 3, 45) $+ . $+ $token(%date, 2, 45) $+ . $+ $token(%date, 1, 45)
    } 
  }

  return $1
}

; Überprüft, ob eines der angegebenen Argumente in der Ignorelist ist
; Folgende Angaben sind möglich:
; Wenn nur $1: $1 = Channel/Nickname/Server der geprüft wird
; Wenn $1 und $2: $1 = Server, $2 = Nickname/Channel der in Kombination geprüft werden soll
; Wenn $1, $2, und $3: $1 = Server, $2 = Channel und $3 = Nickname
; Rückgabe: $true wenn eins der übergebenen Argumente in der Liste gefunden wird, ansonsten $false
alias yta_is_in_ignorelist {
  if ( $isid ) {
    if ( $0 >= 1 ) {
      var %i = 1, %1 = $lower($1), %2 = $lower($2), %3 = $lower($3)
      while ( %i <=  $numtok(%yta/settings/IgnoreList/list, 44) ) {
        var %target = $lower($token(%yta/settings/IgnoreList/list, %i, 44))

        if ( %1 $+ : == %target || %1 == %target ) { 
          return $true
        } 
        elseif ( %2 != $null && ( %2 == %target || %1 $+ : $+ %2 == %target ) ) {
          return $true

        }
        elseif ( %3 != $null && (%3 == %target || %1 $+ : $+ %3 == %target) ) {
          return $true
        }
        inc %i
      }
    }  
    return $false
  }
}

; Testet, ob in $1 der Text nach möglichen URLS geparst werden soll.
; $1 muss entweder chan oder priv sein
; Rückgabe: $true wenn parsing aktiv sein soll, ansonsten $false
alias yta_is_parsing_active {
  if ( $isid ) {
    if ( ($1 == chan && %yta/settings/General/cmsg == 1) || ($1 == priv && %yta/settings/General/pmsg == 1) ) {
      return $true
    }
    return $false
  }
}

; Testet, ob $1 eine URL ist die aktiv abgefragt werden soll
; Rückgabe: $true wenn sie aktiv ist, ansonsten $false
alias yta_is_active_url {
  if ( $isid ) {
    var %i 1 
    while ( %i <= $numtok(%yta/settings/General/urls, 44) ) {
      if ( $1 == $token(%yta/settings/General/urls, %i, 44) ) {
        return $true
      }
      inc %i
    }
    return $false
  }
}

;; #
;; Konfiguration laden/speichern
;; Nur über das Dialog Event Init aufrufen!
;; #
alias yta_load_config {
  var %settings/General = cmsg pmsg echo urls apikey
  var %settings/Message = msg echo
  var %settings/IgnoreList = list

  var %i = 1
  while (%i <= $var(%settings/*)) {
    var %tmpk = $token($var(%settings/*, %i), 2, 47) 
    var %tmpv =  %settings/ [ $+ [ %tmpk ] ]
    var %j = 1

    while (%j <= $numtok(%tmpv, 32)) {
      var %item = $token(%tmpv, %j, 32)
      var %val = $readini($mircdir $+ yta_settings.ini, n, %tmpk, %item)

      set %yta/settings/ $+ %tmpk $+  / $+ %item $iif(%val == $chr(7), $null, %val)
      inc %j
    }

    inc %i
  }
}

alias yta_save_config {
  var %i = 1

  while ( %i <= $var(%yta/settings/*) ) {
    var %fp = $var(%yta/settings/*, %i)
    var %val = $var(%yta/settings/*, %i).value
    var %key = $token(%fp, $calc($numtok(%fp, 47) - 1), 47)
    var %item = $token(%fp, $numtok(%fp, 47), 47)

    ; Damit kein Fehler geworfen wird, representiert 7 (BEL) keinen Inhalt
    writeini $mircdir $+ yta_settings.ini  %key  %item  $iif(%val == $null, $chr(7), %val)

    inc %i
  }
}

;;   ######################################
;;  # Nachrichtenverarbeitung und Socket #
;; ######################################
;; <# Haupt-Event
; Reagiert auf Texte (Channel/Privat) die 
; https?://(www)?youtu(.be|be.com) oder https?://(www)?yu2.be beinhalten
; Abbruch des Events passiert in mehreren Stufen, weil nicht Daten
; sofort vorhanden sind (z.B. der tatsächliche URL wird erst im Regex ermittelt).
;; #>
on $*:TEXT:$(/https? $+ $chr(58) $+ \/{2}(w{3}\.)?(youtu\.?be(\.com)?|yu2.be)/Si):*: {
  ; Überprüfen, ob überhaupt parsing erlaubt ist
  if ( $chan != $null && !$yta_is_parsing_active(chan) ) {
    return $false
  }
  elseif ( $chan == $null && !$yta_is_parsing_active(priv) ) {
    return $false
  }

  ; Wenn das bearbeiten erlaubt ist, überprüfen dass auch kein Ziel (Server, Chan, Nick) ingoriert werden soll
  if ( !$yta_is_in_ignorelist($network, $iif($chan != $null, $chan, $nick), $iif($chan != $null, $nick)) ) {
    ; Folgendes regex soll die Video-ID suchen und das 1. Ergebnis speichern
    ; Den Regex kann man bestimmt schöner machen, aber er hat in meinen Tests funktioniert
    var %re = https?:\/{2}(?:w{3}\.)?((?:youtu\.?be(?:\.com)?|yu2.be))\/(?=watch\?v\=([a-zA-Z0-9_-]+)|([a-zA-Z0-9_-]+))
    if ( $regex(yta_re_match, $1-, / $+ %re $+ /Si) > 0 ) {
      var %vid = $regml(yta_re_match, 2), %host = $regml(yta_re_match, 1)
      ; Host/URL kann erst ab hier geprüft werden
      ; Ist die URL nicht Aktiv (Checkbox im UI) dann wird das Event hier beendet
      if ( !$yta_is_active_url(%host) ) {
        return $false
      }
      ; Ticks sind ms seit systemstart
      var %tick $ticks

      ; Um Spam zu verhindern, nur alle 30 Sekunden ein Video für Chan/Nick abfragen
      if ( $calc(%tick -  [ % $+ yta/spamprot/ $+ [ $network ]  $+  [ $iif($chan != $null, $chan, $nick) ] $+ /tick ] ) >= 30000 ) {
        set %yta/spamprot/ $+ $network $+ $iif($chan != $null, $chan, $nick) $+ /tick %tick

        ; Spamprot und request Variablen nach 30 Sekunden entfernen
        .timer $+ yta/timers/ $+ $network $+ $iif($chan != $null, $chan, $nick) 1 30  yta_request_cleanup $network $+ $iif($chan != $null, $chan, $nick)

        ; Socket öffnen und Informationen als mark speichern
        sockopen -e yta/sockets/ $+ %tick googleapis.com 443
        sockmark yta/sockets/ $+ %tick $network $+ , $+ $iif($chan != $null, $chan, $nick) $+ , $+ %vid

      }
    } 
  }
}

;; <# Socket Logik
; Im folgendem Abschnitt befindet sich die Logik für den Umgang mit den geöffneten Sockets.
; Dabei gibt es zwei Hauptevents die bearbeitet werden.
; Beim öffnen wird eine HTTP Anfrage an den googleapis Server geschickt und die Markierung vom Socket in die Request-Variable geschrieben.
; Im Lesevorgang werden die erhaltenen Daten verarbeitet, in die Request-Variable geschrieben und die Ticknummer an die Funktion yta_send_message übergeben
;; #>
on *:SOCKOPEN:yta/sockets/*: {
  ; Daten für das GET  Request zusammen tragen
  var %apikey %yta/settings/General/apikey
  var %vid $token($sock($sockname, 1).mark, 3, 44)

  var %tick $token($sockname, $numtok($sockname, 47), 47)

  ; Wenn eines von beiden nicht abgerufen werden kann, socket schließen
  if ( %apikey == $null || %vid == $null) {
    unset %yta/ytrequests/ $+ %tick $+ /*
    sockclose $sockname
    return $false
  }

  ; GET Request zusammensetzen
  var %get /youtube/v3/videos?part=snippet%2CcontentDetails%2Cstatistics $+ &id= $+ %vid $+ &key= $+ %apikey

  ; HTTP Anfrage senden
  sockwrite -n $sockname GET %get HTTP/1.1
  sockwrite -n $sockname Host: www.googleapis.com
  sockwrite -n $sockname User-Agent: mSL YouTube Announcer
  sockwrite -n $sockname Accept: application/json
  sockwrite -n $sockname

  set %yta/ytrequests/ $+ %tick $+ / $+ network $token($sock($sockname, 1).mark, 1, 44)
  set %yta/ytrequests/ $+ %tick $+ / $+ dest $token($sock($sockname, 1).mark, 2, 44)
  set %yta/ytrequests/ $+ %tick $+ / $+ vid  $token($sock($sockname, 1).mark, 3, 44)

}

; TODO Eventlogik umschreiben, so das Hashtables verwendet werde
; Durch filtern von Elementen die ersetzt werden, ensteht ein Chaos aus IF/ELSIF Verzweigungen.
; Deswegen wäre ein Rewrite mit Hashtables vielleicht sinnvoll, um alle Elemente vom JSON zu speichern.
on *:SOCKREAD:yta/sockets/*: {
  var %tick $token($sockname, $numtok($sockname, 47), 47)
  var %line

  sockread %line

  ; HTTP Status-Code abfragen und entsprechend fortfahren oder abbrechen  
  if ( HTTP/1.1 isin %line ) {
    if ( $token(%line, 2, 32) != 200 ) {
      unset %yta/ytrequests/ $+ %tick $+ /*
      sockclose $sockname
      return $false
    }

  }
  elseif ( "publishedAt" isin %line ) {
    var %val $token($yta_json_keyval_token(%line), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ publishedat %val

  } 
  elseif ( "title" isin %line && %yta/ytrequests/ [ $+ [ %tick ] $+ /title ] == $null ) {
    var %val $token($yta_json_keyval_token(%line), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ title %val

  } 
  elseif ( "channeltitle" isin %line ) {
    var %val $token($yta_json_keyval_token(%line), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ channeltitle %val

  } 
  elseif ( "duration" isin %line ) {
    var %val $token($yta_json_keyval_token(%line), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ duration %val    

  } 
  elseif ( "viewcount" isin %line ) {
    var %val $token($yta_json_keyval_token(%line), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ viewcount %val    

  } 
  elseif ( "likecount" isin %line ) {
    var %val $token($yta_json_keyval_token(%line), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ likecount %val    

  } 
  elseif ( "dislikecount" isin %line ) {
    var %val $token($yta_json_keyval_token(%line), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ dislikecount %val    

  } 
  elseif ( "favoritecount" isin %line ) {
    var %val $token($yta_json_keyval_token(%line), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ favoritecount %val

  } 
  elseif ( "commentCount" isin %line ) {
    ; Quick and Dirty: Einfach ein Komma am Ende hinzufügen, weil sonst das Regex nicht greift
    var %val $token($yta_json_keyval_token(%line $+ $chr(44)), 2, 7)
    set %yta/ytrequests/ $+ %tick $+ / $+ commentcount %val    

    ; Comment Count ist das letzte Element das interessant ist für dieses Script
    sockclose $sockname
    yta_send_msg %tick
  } 
}

; Wird ausgeführt, wenn die Gegenseite ein Socket beendet
; Entsprechend, damit sich nicht zu viele globale Variablen ansammeln, ein unset versuchen
on *:SOCKCLOSE:yta/sockets/*: {
  var %tick $token($sockname, $numtok($sockname, 47), 47)
  unset %yta/ytrequests/ $+ %tick $+ /*
}

;; <#
;; Helfer Funktionen und Events
;; #>

; Parst die Zeichenfolge und teilt diese in Key:Val auf (Token, Trennzeichen 7) (Quick and Dirty Version)
; Argument $1: Zeichenfolge im Format \s+"<Key>":\s"<Val>",
; Rückgabe: Key und Val als Token oder nichts bei Fehler
; TODO Regex umschreiben, so das es auch greift, wenn kein Komma am Ende ist (letzte Element in einer Liste in JSON)
alias yta_json_keyval_token {
  if ( $isid ) {
    if ( $regex(yta_test, $1, /^\s+"(.*?)": "(.*?)" $+ $chr(44)$/) == 1 ) {
      var %key $regml(yta_test,1)
      var %val $regml(yta_test,2)
      return %key $+ $chr(7) $+ %val
    }

    return $null
  }
}

; Wraper, um einfacher auf die Request-Variable zugreifen zu können
; Argument $1: Tick Nummer vom Request
; Rückgabe: Inhalt der Request-Variable oder $null
; Beispiel: echo -ga Title: $yta_request_result(<tick>).title
alias yta_request_result {
  if ( $isid ) {
    if ( $var(%yta/ytrequests/ [ $+ [ $1 ] $+ ] /*) > 0 ) {
      return %yta/ytrequests/ [ $+ [ $1 ] $+ / $+ [ $prop ] ]
    }
    return $null
  }
}

; Gibt die eingestellte Nachricht am Abfrageort aus oder per Echo im aktiven Fenster
; Argument $1: yta request Tick Nummer
; Die Funktion erwartet als 1. Argument den Namen der globalen Variable 
; für den Request der ausgegeben werden soll
alias yta_send_msg {
  var %placeholders publishedAt $+ $chr(7) $+ title $+ $chr(7) $+ channelTitle $+ $chr(7) $+ duration $+ $chr(7) $+ favoritecount
  var %placeholders %placeholders $+ $chr(7) $+ viewcount $+ $chr(7) $+ likecount $+ $chr(7) $+ dislikecount  $+ $chr(7) $+ commentcount

  ; Replace mit dem Wraper befüllen
  var %replace $yta_request_result($1).publishedat $+ $chr(7) $+ $yta_request_result($1).title $+ $chr(7) $+ $yta_request_result($1).channeltitle 
  var %replace %replace $+ $chr(7) $+ $yta_request_result($1).duration $+ $chr(7) $+ $yta_request_result($1).favoritecount $+ $chr(7) $+ $yta_request_result($1).viewcount
  var %replace %replace $+ $chr(7) $+ $yta_request_result($1).likecount $+ $chr(7) $+ $yta_request_result($1).dislikecount $+ $chr(7) $+ $yta_request_result($1).commentcount

  var %dst $yta_request_result($1).dest
  var %net $yta_request_result($1).network
  if ( %yta/settings/General/echo == 1 ) {
    echo -gf %dst $yta_replace_placeholder(%yta/settings/Message/msg, %placeholders, %replace)
  } 
  else {
    .msg %dst $yta_replace_placeholder(%yta/settings/Message/msg, %placeholders, %replace)
  }
}

; Entfernt die Spamprotect Variable und Request Variable
; Spamprotect ist fest auf 30 Sekunden einprogrammiert und wenn in der Zeit keine Rückmeldung gekommen ist, 
; kann auch die requests Variable verworfen werden
; Argument $1: Spamprotect Variable Identifikation
alias yta_request_cleanup {
  var %tick %yta/spamprot/ [ $+ [ $1 ]  $+ /tick ]

  unset %yta/spamprot/ [ $+ [ $1 ] $+ /* ]
  unset %yta/ytrequests/ [ $+ [ %tick ] $+ /* ]
}

; Settings in die INI schreiben, Timer und Sockets anhalten und globale Variables löschen
alias yta_uninstall {
  yta_save_config
  sockclose yta/sockets/*

  var %i 1

  while ( %i <= $timer(0) ) {
    var %tname $timer(%i)

    if ( yta/timers/ isin %tname ) {
      .timer $+ %tname off
    }

    inc %i
  }

  unset %yta/*

  echo -ag - YouTube Announcer - Das Script ist nun deaktiviert und sollte auf keine YouTube Links mehr reagieren.
}

; Wenn das Script entladen wird, uninstall ausführen
on *:UNLOAD: {
  yta_uninstall
}

Expand


Read More