#!/usr/bin/env python
# -*- coding: utf8 -*-

# Das Schwarze Auge IRC Wuerfelbot
# Version 0.1
# Author: Danny "duke" Funkat
# Webseite: http://botnetz.com
# Lizenz: GPLv3

## Importieren der Module ##
import sys, time, socket, random, string

## Optionen ##
_network = "irc.netzwerk.de"
_port = 6667
_nick = "DSA-Wuerfler"
_channel = "#Channel"
_channelpass = None
_owner = "Admin!User@netzwerk.de"

## IRC Klasse ##
class aIRC(object):
    def __init__(self):
        self.aConnection = False
        self.SockConnect()
    def SockConnect(self):
        try:
            self.aBuffer = ''
            self.aSocket = socket.socket()
            self.aSocket.connect((_network, _port))
            self.SockSend("NICK %s" % (_nick))
            self.SockSend("USER dsa dsa dsa :DSA Wuerfelbot 0.1")
            print "[DSA - Info] Verbunden: %s:%s (%s)" % (_network, repr(_port), _nick)
            self.aConnection = True
            self.aLastPong = time.mktime(time.localtime(time.time()))
        except socket.error:
            print "[DSA - Warnung] Socket Error: %s" % (socket.error)
    def SockSend(self, raw):
        self.aSocket.send("%s\r\n" % (raw))
    def SockMsg(self, target, message):
        self.aSocket.send("PRIVMSG %s :%s\r\n" % (target, message))
    def SockJoin(self, target, password):
        self.aSocket.send("JOIN %s %s\r\n" % (target, password))
    def SockQuit(self):
        self.aSocket.send("QUIT :http://dsa.botnetz.com/\r\n")
        time.sleep(1)
        self.aSocket.close()
        sys.exit("[DSA - Info] Wuerfelbot erfolgreich beendet.")
    def SockReconnect(self):
        print "[DSA - Info] Verbindung verloren... Neu verbinden."
        self.aSocket.close()
        time.sleep(5)
        self.SockConnect()
    def SockProcess(self):
        while self.aConnection == True:
            try:
                if time.mktime(time.localtime(time.time())) - self.aLastPong >= 240:
                    self.SockReconnect()
                    
                ## Socket Data aufbereiten > Liste
                self.aBuffer = self.aBuffer + self.aSocket.recv(1024)
                self.aTemp = string.split(self.aBuffer, '\n')
                self.aBuffer = self.aTemp.pop()
                for self.aCurrent in self.aTemp:
                        self.aCurrent = string.rstrip(self.aCurrent)
                        self.aCurrent = string.split(self.aCurrent)

                        #print 'DEBUG: %s - %s' % (time.ctime(time.time()), self.aCurrent)
                        self.aLastPong = time.mktime(time.localtime(time.time()))
                        
                        ## Server Anfragen ##
                        if self.aCurrent[0] == 'PING':
                            self.SockSend("PONG %s" % (self.aCurrent[1].strip(':')))
                            print "[DSA - Info] Ping? Pong!"
                        
                        ## RAW Nummer 001: Verbindung zum Server erfolgreich
                        if self.aCurrent[1] == '001':
                            self.SockJoin(_channel, _channelpass)
                            time.sleep(1)
                            print "[DSA - Info] Betrete Channel... (%s)" % (_channel)
                            self.SockMsg(_channel, '\x033\x02[DSA - Info] Erfolgreich verbunden.')
                            
                        ## RAW Nummer 433: Nickname bereits in Verwendung, Nickame + Zufallszahl
                        if self.aCurrent[1] == '433':
                            self.SockSend("NICK %s" % (_nick+repr(random.randint(0,1000))))
                            print "[DSA - Warnung] Nick in Benutzung, Nutze Alternative..."
                            
                        ## RAW Nummer 442: Wenn nicht im Channel, JOIN
                        if self.aCurrent[1] == '442':
                            self.SockJoin(_channel, _channelpass)
                            print "[DSA - Info] Betrete Channel erneut... (%s)" % (_channel)
                            
                        ## RAW Nummer 473, 474, 475: Channelmodus +b, +k oder +i, Quit
                        if self.aCurrent[1] == '473' or self.aCurrent[1] == '474' or self.aCurrent[1] == '475':
                            print "[DSA - Fehler] Kann den angegebenen Channel nicht betreten. Beende."
                            self.SockQuit()
                        
                        ## Mehr als 4 Records in der Liste?
                        if len(self.aCurrent) >= 4:
                            if len(self.aCurrent[3]) >= 5:
                                try:
                                    # aWuerfel = Command ":.2w6" [':', '.', '2', 'w', '6']
                                    self.aWuerfel = []
                                    self.xWuerfel = ''
                                    # aPerson = Host "test!test@testhost.de" > "['test', 'test@testhost.de']"
                                    self.aPerson = self.aCurrent[0].split("!")
                                    
                                    # aWuerfel String in einzelne Buchstaben zerteilen
                                    for x in self.aCurrent[3]:
                                        self.aWuerfel.append(x)
                                    # "w/W" befindet sich im 3. Listeintrag?
                                    if self.aWuerfel[3] == "w" or self.aWuerfel[3] == "W":
                                        # Listeintrag 4 = 6, dann W6 
                                        if self.aWuerfel[4] == "6":
                                            # n Zufallszahlen generieren
                                            for x in range(0, int(self.aWuerfel[2])):
                                                random.seed(time.mktime(time.localtime())+random.randint(1000,5000))
                                                self.xWuerfel = self.xWuerfel+"[%s] " % (repr(random.randint(1,6)))
                                            # Ausgeben    
                                            self.SockMsg(_channel, "\x02[DSA - %sW6 - %s] %s" % (self.aWuerfel[2], self.aPerson[0].strip(":"), self.xWuerfel))
                                        if len(self.aWuerfel) >= 6:
                                            if self.aWuerfel[4] == "2" and self.aWuerfel[5] == "0":
                                                for x in range(0, int(self.aWuerfel[2])):
                                                    random.seed(time.mktime(time.localtime())+random.randint(1000,5000))
                                                    self.xWuerfel = self.xWuerfel+"[%s] " % (random.randint(1,20))
                                                self.SockMsg(_channel, "\x02[DSA - %sW20 - %s] %s" % (self.aWuerfel[2], self.aPerson[0].strip(":"), self.xWuerfel))
                                        if self.aWuerfel[4] == "2" and len(self.aWuerfel) <= 5:
                                            for x in range(0, int(self.aWuerfel[2])):
                                                random.seed(time.mktime(time.localtime())+random.randint(1000,5000))
                                                self.xWuerfel = self.xWuerfel+"[%s] " % (random.randint(1,2))
                                            self.SockMsg(_channel, "\x02[DSA - %sW2 - %s] %s" % (self.aWuerfel[2], self.aPerson[0].strip(":"), self.xWuerfel))
                                            
                                except ValueError:
                                    # Commanderror? z.B. .bW6
                                    self.SockMsg(_channel, "\x035\x02[DSA - Warnung] Kein Gueltiger Wuerfel.")
                                if self.aCurrent[3] == ":.help":
                                    self.SockMsg(_channel, "Befehle: .*W2 (2-seitiger Wuerfel) .*W6 (6-seitiger Wuerfel) .*W20 (20-seitiger Wuerfel) - Ersetze * mit beliebiger Zahl zwischen 1 und 9")
                            if self.aCurrent[0].strip(":") == _owner:
                                if self.aCurrent[3] == ":.DEBUG":
                                    self.SockMsg(_channel, "Current time: %s - Last Activity: %s - Diff: %ss" % (time.ctime(time.time()), time.ctime(self.aLastPong), time.mktime(time.localtime(time.time())) - self.aLastPong))
                                if self.aCurrent[3] == ":.QUIT":
                                    self.SockQuit()
                                if self.aCurrent[3] == ":.RECONNECT":
                                    self.SockMsg(_channel, "Neuverbinden...")
                                    self.SockReconnect()
            except socket.error, EBADF:
                raise

def main():
    try:
        IRC = aIRC()
        IRC.SockProcess()
    except KeyboardInterrupt:
        IRC.SockQuit()
        
if "__main__":    
    main()
