Exemple #1
0
 def __init__(self):
     self.listOfQ = []
     self.listOfC = []
     self.listOfF = []
     self.USERS = UserList()
     self.TrumpObjects = {}
     self.resetList = []
Exemple #2
0
    def __init__(self,
                 nick,
                 realname,
                 channels,
                 admins,
                 _ssl=False,
                 reconnect=False,
                 password=False,
                 oper_user=False,
                 oper_pass=False):
        self.users = UserList()
        self.user = User(nick=nick, real=realname)
        self.users.append(self.user)
        self.channels = ChannelList(self.users)

        self._nick = nick
        self._real = realname

        self.logger = logging.getLogger('teslabot.irc')
        self._init_channels = channels
        self._ssl = _ssl
        self._reconnect = reconnect
        self._reconnect_time = 0
        self._password = password
        self._buffer = ''
        self._ipaddr = None

        self._oper = False
        self._oper_user = oper_user
        self._oper_pass = oper_pass

        self._msg_time = []
        self._msg_last_id = 0
        self._max_mps = 5
        self._throttle = False

        self._ping = 0
        self._stimeout_count = 0
        self._SOCKET_TIMEOUT = 5
        self._PING_TIMEOUT = 5
        self._PING_FREQUENCY = 12

        self._last_msg = 0

        self.alive = 1

        # Define users with administrator privileges
        for admin in admins:
            user = User(src=admin, admin=True)
            self.users.append(user)
Exemple #3
0
def create_app():
    app = Flask(__name__)
    app.user = User()
    app.userList = UserList()
    app.usermap = UserLocationStore()
    app.friendStore = FriendStore()
    app.messageStore = MessageStore()
    app.userlocation = UserLocation()
    app.register_blueprint(site)
    app.register_blueprint(myMap)
    app.register_blueprint(register)
    app.register_blueprint(adminTable)
    app.register_blueprint(add)
    app.register_blueprint(add_doc)
    app.register_blueprint(image)
    app.register_blueprint(event)
    app.register_blueprint(notifications)
    app.store = Store()
    app.commentStore = CommentStore()
    app.requestStore = RequestStore()
    app.store_images = Store_Image()
    app.store_documents = Store_Document()
    app.register_blueprint(friends)
    app.register_blueprint(messages)
    app.register_blueprint(new)
    app.time = Timesql()
    app.init_db = init_db()
    app.savelocation = SaveLocation()
    app.notificationStore = NotificationStore()
    #    app.store.add_event(Event('World War II', date='15/12/1942', place='Turkey',content= 'Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit'))
    #    app.store.add_event(Event('Train Accident', date='01/02/1985', place='California', content = 'Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit'))
    return app
Exemple #4
0
 def __init__(self, name: str, lang: str, diff: str = '') -> None:
     super().__init__(name)
     self.users: UserList = UserList()
     self.chatroom: PrivateChatroom = PrivateChatroom(name)
     self.current_img = ""
     self.mongo_manager = MongoManager()
     self.lang = lang
     self.diff = diff
     self.current_word = self._get_word()
     self.word = self.current_word['word']
     self.tries = 0
     self.round_counter = 0
     self.is_full = (self.users.length() == self.MAX_USERS)
     self.creator = None
     self.is_started = False
Exemple #5
0
    def __init__(self, nick, realname, channels, admins, _ssl = False, reconnect = False,
                  password = False, oper_user = False, oper_pass = False):
        self.users = UserList()
        self.user = User(nick=nick, real=realname)
        self.users.append(self.user)
        self.channels = ChannelList(self.users)

        self._nick = nick
        self._real = realname
        
        self.logger = logging.getLogger('teslabot.irc')
        self._init_channels = channels
        self._ssl = _ssl
        self._reconnect = reconnect
        self._reconnect_time = 0
        self._password = password
        self._buffer = ''
        self._ipaddr = None
        
        self._oper = False
        self._oper_user = oper_user
        self._oper_pass = oper_pass
        
        self._msg_time = []
        self._msg_last_id = 0
        self._max_mps = 5
        self._throttle = False

        self._ping = 0
        self._stimeout_count = 0
        self._SOCKET_TIMEOUT = 5
        self._PING_TIMEOUT = 5
        self._PING_FREQUENCY = 12
        
        self._last_msg = 0

        self.alive = 1
        
        # Define users with administrator privileges
        for admin in admins:
            user = User(src=admin, admin=True)
            self.users.append(user)
Exemple #6
0
class rocky(object):
    def __init__(self):
        self.listOfQ = []
        self.listOfC = []
        self.listOfF = []
        self.USERS = UserList()
        self.TrumpObjects = {}
        self.resetList = []

    def register(self, websocket, key, room, seatNo):

        gamerObject = self.USERS.checkForkey(key)
        if (self.USERS.canEnterTheRoom(
                room, seatNo)):  ## Need to replace with sqllite logic
            print("Will add in room " + str(room))
        else:
            print("Room is full or invalid seat no ")
            return False

        if gamerObject:
            # print (user)
            print("user already in table")
            if websocket in self.USERS.ws:
                print("ok ")
            else:
                print("we will re assign the socket with new one ")
                gamerObject.websocket = websocket
                gamerObject.seatNo = seatNo
                gamerObject.room = room  ## Need this for swaping seat and Room
                self.USERS.addGameroRomm(room, seatNo, gamerObject)
                self.USERS.ws.append(websocket)
                return True

        else:
            #username = ("P" + "___" + key)  ##  This will change to sqllite Actitivy in USerList Object  ## str( random.randint(9,7568)
            print(str(room) + "<-->" + str(seatNo))
            gamerObject = Gamer(
                key, key, websocket, room, seatNo
            )  ## Will imporve the secuirty later , by checking for key and get email
            self.USERS.addtoList(gamerObject)
            self.USERS.addGameroRomm(room, seatNo, gamerObject)
            return True

    def unregister(self, websocket, room, seat):
        print("Before ")
        if self.USERS.removeFromRoom(websocket):
            if room in self.TrumpObjects:
                th = self.TrumpObjects[room]
                if th.P1 is not None and th.P1.seatNo == seat:
                    th.P1 = None
                elif th.P2 is not None and th.P2.seatNo == seat:
                    th.P2 = None
                elif th.P3 is not None and th.P3.seatNo == seat:
                    th.P3 = None
                elif th.P4 is not None and th.P4.seatNo == seat:
                    th.P4 = None
                elif th.P5 is not None and th.P5.seatNo == seat:
                    th.P5 = None
                elif th.P6 is not None and th.P6.seatNo == seat:
                    th.P6 = None
            Room = self.USERS.listOfRooms[room]
            PV.roomInfo(Room, False, th.tt.listOfKunugu,
                        self.TrumpObjects[room].watchlist)
            print(str(room) + "::" + str(seat) + "  free")
            print("free from list  " + str(websocket))
            return True

    def IsthereTrumpSession(self, websocket, room, seat):
        try:
            print("IsthereTrumpSession??   " + str(websocket))
            #roomUsers = (self.USERS.getRoomDetails(websocket))
            Room = self.USERS.listOfRooms[room]
            if not Room:
                return False
            r = room
            if r in self.TrumpObjects:
                gamer = self.USERS.getUserBywebSocket(websocket)
                if gamer:
                    playerHand = []
                    P0 = self.TrumpObjects[r]
                    playerInRoom = P0.getPlayerBySeat(gamer.userID, websocket,
                                                      seat)
                    if playerInRoom == "Not vacant":
                        print("Still it is NOT vacant  " + str(seat))
                        return False
                    playerHand = playerInRoom.showHand()
                    print("Reconnected  fine  " +
                          str(playerInRoom.__dict__['name']) + " " +
                          str(playerInRoom.__dict__['seatNo']))
                    PV.roomInfo(Room, gamer, P0.tt.listOfKunugu, P0.watchlist)
                    RR = self.TrumpObjects[r].rules
                    d = {}
                    for we in range(1, 7):
                        P = P0.tt.getPlayerName("P" + str(we))
                        d["SN" + str(we)] = P

                    if RR.TrumpSet:
                        reconnectMessage = {
                            "villi": str(RR.villi),
                            'trump': RR.trump,
                            'dude': RR.dude,
                            'dudeTeam': RR.Dudeteam,
                            'hand': playerHand,
                            'VSF': [],
                            "playsofar": P0.thisPlayForSunu,
                            "names": d,
                            "base0": P0.tt.t0base,
                            "base1": P0.tt.t1base,
                            "Mc": P0.tt.gameCount,
                            "KunuguSeat": P0.tt.listOfKunugu
                        }
                    else:
                        reconnectMessage = {
                            "villi": str(RR.villi),
                            'trump': RR.trump,
                            'dude': RR.dude,
                            "TrumpIsnotSet": 1,
                            'dudeTeam': RR.Dudeteam,
                            'hand': playerHand,
                            'VSF': RR.VSF,
                            "playsofar": P0.thisPlayForSunu,
                            "names": d,
                            "base0": P0.tt.t0base,
                            "base1": P0.tt.t1base,
                            "Mc": P0.tt.gameCount,
                            "KunuguSeat": P0.tt.listOfKunugu
                        }

                    for kk in (self.listOfQ):
                        if kk['SN'] == gamer.seatNo + 1:
                            message = {
                                "event": "question",
                                "usr": kk["usr"],
                                "t": kk["t"],
                                "quNo": kk["quNo"],
                                "c": kk["c"],
                                "r": kk["r"],
                                "SN": kk["SN"],
                                "VSF": kk["VSF"],
                                "loopStart": kk["loopStart"]
                            }
                            self.listOfQ.remove(kk)
                            message.update(reconnectMessage)
                            self.askQustion(message, gamer)
                            return True

                    for kk in (self.listOfC):
                        if kk['SN'] == gamer.seatNo + 1:
                            message = {
                                "event": "play",
                                "hand": playerHand,
                                "usr": kk["usr"],
                                "pid": kk["pid"],
                                "t": kk["t"],
                                "playsofar": kk["playsofar"],
                                "c": kk["c"],
                                "r": kk["r"],
                                "SN": kk["SN"]
                            }
                            self.listOfC.remove(kk)
                            message.update(reconnectMessage)
                            self.askCard(message, gamer)
                            return True
                    for kk in (self.listOfF):
                        if kk['SN'] == gamer.seatNo + 1:
                            message = {
                                "event": "fold",
                                "hand": playerHand,
                                "usr": kk["usr"],
                                "fid": kk["fid"],
                                "r": kk["r"],
                                "SN": kk["SN"]
                            }
                            self.listOfF.remove(kk)
                            message.update(reconnectMessage)
                            self.askFold(message, gamer)
                            return True

                    reconnectMessage.update({
                        "event":
                        "Reconnect",
                        "spinner": (P0.spinner + 6 - playerInRoom.seatNo) % 6
                    })
                    payload = json.dumps(reconnectMessage).encode('utf8')
                    PV.mySendMessage(websocket, payload)

                else:
                    print("Gamer is not found .Not registered ")
                return True
            else:
                False
        except Exception as ex:
            print(ex)
            print("Reconect Exception  ")

    def askQustion(self, message, client):
        payload = json.dumps(message).encode('utf8')
        PV.mySendMessage(client.websocket, payload)
        self.listOfQ.append({
            "quNo": message["quNo"],
            "status": "Asked",
            "ans": "",
            "usr": message["usr"],
            "t": message["t"],
            "c": message["c"],
            "r": message["r"],
            "SN": message["SN"],
            "VSF": message["VSF"],
            "loopStart": message["loopStart"]
        })
        print("Question1 Asked  " + message["usr"])

    def askCard(self, message, client):
        payload = json.dumps(message).encode('utf8')
        PV.mySendMessage(client.websocket, payload)
        self.listOfC.append({
            "pid": message["pid"],
            'playsofar': message['playsofar'],
            "status": "Asked",
            "card": "",
            "usr": message["usr"],
            "t": message["t"],
            "c": message["c"],
            "r": message["r"],
            "SN": message["SN"]
        })
        print("Card  Asked  " + message["usr"])

    def askFold(self, message, client):
        payload = json.dumps(message).encode('utf8')
        PV.mySendMessage(client.websocket, payload)
        self.listOfF.append({
            "fid": message["fid"],
            "status": "Asked",
            "usr": message["usr"],
            "r": message["r"],
            "SN": message["SN"]
        })
        print("Fold  Asked " + message["usr"])

    def canWeStart(self, websocket, roomNo, seatNo):
        Room = self.USERS.listOfRooms[roomNo]

        PV.roomInfo(Room, False, [], [])
        if not Room:
            print("ERROR:2002 Issue while registring room and users__")
            websocket.sendMessage(
                "{'message':'Can't find room '}".encode('utf8'), False)
            return False

        if not None in Room:  ## Need to change to Room logic .
            if roomNo in self.TrumpObjects:
                print("Game started already wont restart this time ")
                return "Game already"
            th = TrumpHandler.TrumpHandler(Room)
            self.TrumpObjects[roomNo] = th
            th.doTheDeal()
            th.tt.getOrderOfPlayers()

            PV.MatchIsDone(
                {
                    "won": "",
                    "base0": 5,
                    "base1": 5,
                    "dialoge": "let's start Maggi",
                    "Mc": 0,
                    "KunuguSeat": []
                }, Room, [])
            PV.sendCard(th)
            quNO = "R" + str(roomNo) + str(0)
            P0 = th.tt.orderofPlay[0]
            villiSoFar = [{"S" + str(P0.seatNo): ""}]
            message = {
                "event": "question",
                "usr": P0.name,
                "SN": P0.seatNo,
                "t": "Team0",
                "quNo": quNO,
                "c": 0,
                "r": roomNo,
                "VSF": villiSoFar,
                "loopStart": 28
            }
            self.askQustion(message, P0)
            PV.whoIsSpinner(th.tt.orderofPlay, P0, th.watchlist)
            th.spinner = P0.seatNo

        else:

            PV.boradCast(
                "Room: " + str(roomNo) + " need " + str(Room.count(None)),
                Room)

    def getAnswerOfOldquestion(self, AnsNo):
        obj = ""
        for kk in self.listOfQ:
            if kk['status'] == "DONE" and kk["quNo"] == AnsNo:
                obj = kk
                break
        self.listOfQ.remove(obj)
        return (kk)

    def getCardOfRequest(self, pid):
        obj = ""
        for kk in self.listOfC:
            if kk['status'] == "DONE" and kk["pid"] == pid:
                obj = kk
                break
        self.listOfC.remove(obj)
        return (kk)

    def managePlay(self, pid):
        lastCard = self.getCardOfRequest(pid)
        print(lastCard)
        r = lastCard["r"]
        seat = "S" + str(lastCard["SN"])
        RR = self.TrumpObjects[r].rules
        TT = self.TrumpObjects[r].tt
        self.TrumpObjects[r].thisPlayForSunu.append({seat: lastCard["card"]})
        self.TrumpObjects[r].thisPlay.append(lastCard["card"])
        PlaySoFar = self.TrumpObjects[r].thisPlay
        c = lastCard["c"]  ## --> Order of Index
        TT.orderofPlay[c].removeCard(lastCard["card"])
        PV.playSoFar({"playsofar": self.TrumpObjects[r].thisPlayForSunu},
                     self.TrumpObjects[r], self.TrumpObjects[r].watchlist)
        if len(PlaySoFar) == 6:
            print("Will check who got it ")
            print(PlaySoFar)
            if RR.IsTrumpInPlay(PlaySoFar):
                print("Trump Round")
                newC = RR.trumpInAction(PlaySoFar)

            else:
                newC = RR.whoIsLeader(PlaySoFar)
            team = TT.orderofPlay[newC].team
            print(newC)
            print(team)
            self.TrumpObjects[r].thisPlay = []
            self.TrumpObjects[r].thisPlayForSunu = []
            if team == "Team0":
                RR.t0Pidi.append(PlaySoFar)
            else:
                RR.t1Pidi.append(PlaySoFar)
            TT.opener = newC
            TT.getOrderOfPlayers()
            PV.heGotPidi(
                TT.orderofPlay, TT.orderofPlay[(c + 1) % 6],
                self.TrumpObjects[r].watchlist
            )  ## Need to send my seat also & dummy one . it should sending after win or not

            PlaySoFar = []  ### To prevent 6 cards in second play
            TTO = TT.orderofPlay[(c + 1) % 6]
            if self.didHeWon(RR, TT, self.TrumpObjects[r].watchlist):
                print("match is over ")
                TTO = TT.orderofPlay[(c + 1) % 6]
                # {"fid":message["fid"],"status":"Asked","usr":message["usr"],"r":message["r"],"SN":message["SN"]}
                message = {
                    "event": "fold",
                    "usr": TTO.name,
                    "fid": lastCard["pid"][:2],
                    "t": TTO.team,
                    "r": r,
                    "SN": TTO.seatNo
                }
                self.askFold(message, TTO)
                self.startNextMatch(r, False, message)
                return True

        TTO = TT.orderofPlay[(c + 1) % 6]
        pid = lastCard["pid"][:2] + str(int(lastCard["pid"][2:]) + 1)
        message = {
            "event": "play",
            "hand": TTO.showHand(),
            "usr": TTO.name,
            "pid": pid,
            "t": TTO.team,
            "playsofar": self.TrumpObjects[r].thisPlayForSunu,
            "c": (c + 1) % 6,
            "r": r,
            "SN": TTO.seatNo
        }
        self.askCard(message, TTO)
        PV.whoIsSpinner(TT.orderofPlay, TTO, self.TrumpObjects[r].watchlist)
        self.TrumpObjects[r].spinner = TTO.seatNo

    def startNextMatch(self, r, okFromUI, fobject):
        if okFromUI:
            ## Need to add condition to check all 6 players are in table , then only it sends cards and call SetNextGame , getOrder functions
            th = self.TrumpObjects[r]
            resendAgain = th.emptySeat(fobject['SN'])
            if resendAgain:
                self.askFold(fobject, resendAgain)
                PV.chatSend(
                    {
                        "event": "chatSend",
                        "r": r,
                        "usr": "******",
                        "role": "CPU",
                        "text":
                        "One of the seat is Empty ,can't start the game"
                    }, th.tt.orderofPlay, th.watchlist)
                return False
            RR = th.rules
            TT = th.tt
            TT.VSF = [{}]
            RR.TrumpSet = False
            TT.setNextGame()
            TT.getOrderOfPlayers()
            th.doTheDeal()
            PV.sendCard(th)
            quNO = "R" + str(r) + str(0)
            P0 = TT.orderofPlay[0]
            message = {
                "event": "question",
                "usr": P0.name,
                "t": P0.team,
                "SN": P0.seatNo,
                "quNo": quNO,
                "c": 0,
                "r": r,
                "VSF": [],
                "loopStart": 28
            }
            self.askQustion(message, self.TrumpObjects[r].tt.orderofPlay[0])
            PV.whoIsSpinner(TT.orderofPlay, TT.orderofPlay[0], th.watchlist)
            th.spinner = P0.seatNo
            for kk in self.listOfF:
                if (kk['r'] == r):
                    self.listOfF.remove(
                        kk
                    )  ## This will make sure that no fold is pending , to prevent client issue and unexpected restart
        else:
            print("Need to wait for ok from UI ")

    def didHeWon(self, rules, tt, watchlist):
        t0P = rules.getPoints(rules.t0Pidi)
        t1P = rules.getPoints(rules.t1Pidi)
        print('Team0  ' + str(t0P))
        print('Team1  ' + str(t1P))
        if rules.t1GetPoint:
            if rules.villi <= t1P:
                dialoge = str(t0P) + "/" + str(t1P) + (
                    " Red won with one base")
                tt.t1VillichuWon(rules.villi, rules.dudeSeatNo)
                message = {
                    "won": "Team1",
                    "base0": tt.t0base,
                    "base1": tt.t1base,
                    "dialoge": dialoge,
                    "Mc": tt.gameCount,
                    "KunuguSeat": tt.listOfKunugu
                }
                PV.MatchIsDone(message, tt.orderofPlay, watchlist)

                return True
            if (56 - rules.villi) < t0P:
                dialoge = str(t0P) + "/" + str(t1P) + (
                    " Black won with two base")
                tt.t1VillichuLoss(rules.villi)
                message = {
                    "won": "Team0",
                    "base0": tt.t0base,
                    "base1": tt.t1base,
                    "dialoge": dialoge,
                    "Mc": tt.gameCount,
                    "KunuguSeat": tt.listOfKunugu
                }
                PV.MatchIsDone(message, tt.orderofPlay, watchlist)
                return True
        else:
            if rules.villi <= t0P:
                dialoge = str(t0P) + "/" + str(t1P) + (
                    " Black won with one base ")
                tt.t0VillichuWon(rules.villi, rules.dudeSeatNo)
                message = {
                    "won": "Team0",
                    "base0": tt.t0base,
                    "base1": tt.t1base,
                    "dialoge": dialoge,
                    "Mc": tt.gameCount,
                    "KunuguSeat": tt.listOfKunugu
                }
                PV.MatchIsDone(message, tt.orderofPlay, watchlist)
                return True
            if (56 - rules.villi) < t1P:
                dialoge = str(t0P) + "/" + str(t1P) + (
                    " Red won with two base")
                tt.t0VillichuLoss(rules.villi)
                message = {
                    "won": "Team1",
                    "base0": tt.t0base,
                    "base1": tt.t1base,
                    "dialoge": dialoge,
                    "Mc": tt.gameCount,
                    "KunuguSeat": tt.listOfKunugu
                }
                PV.MatchIsDone(message, tt.orderofPlay, watchlist)
                return True
        return False

    def manageVilli(self, AnsNo):
        lastVilli = self.getAnswerOfOldquestion(AnsNo)
        r = lastVilli["r"]
        gamers = self.USERS.listOfRooms[r]
        RR = self.TrumpObjects[r].rules
        TT = self.TrumpObjects[r].tt
        c = lastVilli["c"]
        seat = "S" + str(lastVilli["SN"])
        RR.VSF.append({seat: lastVilli["ans"]})
        print(RR.VSF)
        if lastVilli["ans"] == "P":
            RR.skipped.add(lastVilli["usr"])
            if (
                    len(RR.skipped) == 6
            ):  ## Need to change for 6  and RR.dudeSeatNo == lastVilli["SN"]
                print(RR.villi)
                RR.TrumpSet = True
                PV.TrumpIsSet(
                    {
                        "villi": str(RR.villi),
                        "trump": RR.trump,
                        "dude": RR.dude,
                        "dudeTeam": RR.Dudeteam
                    }, TT.orderofPlay, self.TrumpObjects[r].watchlist)
                if RR.Dudeteam == "Team1":
                    RR.t1GetPoint = True
                else:
                    RR.t1GetPoint = False
                pid = "R" + str(r) + str(1)
                ##self.sendCard(self.TrumpObjects[r])   ## Not need
                message = {
                    "event": "play",
                    "hand": TT.orderofPlay[0].showHand(),
                    "usr": TT.orderofPlay[0].name,
                    "pid": pid,
                    "t": "Team0",
                    "playsofar": [],
                    "c": 0,
                    "r": r,
                    "SN": TT.orderofPlay[0].seatNo
                }
                self.askCard(message, TT.orderofPlay[0])
                PV.whoIsSpinner(TT.orderofPlay, TT.orderofPlay[0],
                                self.TrumpObjects[r].watchlist)
                self.TrumpObjects[r].spinner = TT.orderofPlay[0].seatNo
                return True
        else:
            RR.villi = int(
                lastVilli["ans"]
                [1:3])  ## Fixed for thirikail  marakail  , +1 +2 etc
            RR.trump = lastVilli["ans"][0]
            RR.dude = lastVilli["usr"]
            RR.dudeSeatNo = lastVilli["SN"]
            RR.Dudeteam = lastVilli["t"]
            if lastVilli["usr"] in RR.skipped:
                RR.skipped.remove(lastVilli["usr"])
        message = {
            "seat": seat,
            "Villi": lastVilli["ans"],
            "VSF": RR.VSF,
            "dude": RR.dude,
            "dudeTeam": RR.Dudeteam
        }
        PV.heCalled(message, gamers, self.TrumpObjects[r].watchlist)
        quNo = lastVilli["quNo"][:2] + str(int(lastVilli["quNo"][2:]) + 1)
        TTO = TT.orderofPlay[(c + 1) % 6]
        message = {
            "event": "question",
            "usr": TTO.name,
            "t": TTO.team,
            "quNo": quNo,
            "c": (c + 1) % 6,
            "r": r,
            "SN": TTO.seatNo,
            "VSF": RR.VSF,
            "loopStart": RR.villi + 1
        }
        self.askQustion(message, TTO)
        PV.whoIsSpinner(TT.orderofPlay, TTO, self.TrumpObjects[r].watchlist)
        self.TrumpObjects[r].spinner = TTO.seatNo

    def resetBase(self, usr, room, seatNo):
        Room = self.USERS.listOfRooms[room]
        if not (Room[seatNo].userID == usr):
            print("Invalid player request to reset the game ")
            return False
        for kk in self.resetList:
            if room in kk:
                if (kk[room] + seatNo) % 2 == 1:
                    print("going to reset for " + str(room + 1))
                    TT = self.TrumpObjects[room].tt
                    TT.t0base = 5
                    TT.t1base = 5
                    TT.gameCount = 0
                    TT.listOfKunugu = []
                    TT.KunugSetAt = -1
                    TT.lastKunugTeam = ""
                    for yo in self.listOfQ:
                        if int(yo['r']) == room:
                            print("Removing # QUESTION:  due to Reset")
                            self.listOfQ.remove(yo)
                    for yo in self.listOfC:
                        if int(yo['r']) == room:
                            print("Removing # card list  due to Reset")
                            self.listOfC.remove(yo)
                    PV.MatchIsDone(
                        {
                            "won":
                            "",
                            "base0":
                            5,
                            "base1":
                            5,
                            "dialoge":
                            "Reset by " + str(kk[room] + 1) + "_" +
                            str(seatNo + 1),
                            "Mc":
                            0,
                            "KunuguSeat": []
                        }, Room, self.TrumpObjects[room].watchlist)
                    self.startNextMatch(
                        room, True, {
                            "event": "fold",
                            "usr": TT.orderofPlay[0].name,
                            "fid": -1,
                            "t": TT.orderofPlay[0].team,
                            "r": room,
                            "SN": TT.orderofPlay[0].seatNo
                        })
                    self.resetList = []
                    return True
        print(" Reset request for " + str(room) + "  " + str(seatNo))
        d = {}
        d[room] = seatNo
        self.resetList.append(d)

    def gotoLobby(self, usr, room, seatNo):
        Room = self.USERS.listOfRooms[room]
        if not (Room[seatNo].userID == usr):
            print("Invalid player request to reset the game ")
            return False
        if room in self.TrumpObjects:
            th = self.TrumpObjects[room]
            if th.P1.seatNo == seatNo + 1:
                th.P1 = None
            elif th.P2.seatNo == seatNo + 1:
                print(th.P2.name)
                th.P2 = None
            elif th.P3.seatNo == seatNo + 1:
                th.P3 = None
            elif th.P4.seatNo == seatNo + 1:
                th.P4 = None
            elif th.P5.seatNo == seatNo + 1:
                th.P5 = None
            elif th.P6.seatNo == seatNo + 1:
                th.P6 = None
        self.USERS.listOfRooms[room][seatNo] = None
        print("send to lobby")

    def addToWatchlist(self, websocket, room):
        if room in self.TrumpObjects:
            print("Will add in watch list")
            self.TrumpObjects[room].watchlist.append(websocket)
            th = self.TrumpObjects[room]
            Room = self.USERS.listOfRooms[room]
            PV.roomInfo(Room, False, th.tt.listOfKunugu, th.watchlist)
        else:
            print("invalid room")

    def removeToWatchlist(self, websocket, room):
        if room in self.TrumpObjects:
            if websocket in self.TrumpObjects[room].watchlist:
                self.TrumpObjects[room].watchlist.remove(websocket)
        else:
            print("Not able to remove")
Exemple #7
0
from gameroom.free_gameroom import FreeGameroom
from gameroom.gameroom import Gameroom, GameroomList
from gameroom.solo_gameroom import SoloGameroom
from gameroom.tuto_gameroom import TutoGameroom
from message import UserMessage
from mongo_manager import AbsentEntryError, MissingParameterError, MongoManager
from user import User, UserList

Payload.max_decode_packets = 1000

app = Flask(__name__)
app.config['SECRET_KEY'] = random.randbytes(16)
socketio = SocketIO(app, cors_allowed_origins="*", ping_timeout=12000)

connectedUsers = {}
connected_users_list = UserList()
db = MongoManager()
chatrooms = ChatroomList()
gamerooms = GameroomList()


#########
# UTILS #
#########
def verify_session(event):
    def verify_session_decor(fn):
        def wrapper(*args, **kwargs):
            user = connected_users_list.get_instance_by_sid(request.sid)
            if user is None:
                print(f'Unauthorized user event: {event}')
                resp = get_resp(0, 'Unauthorized: user not connected', {})
Exemple #8
0
class IRC(object):
    """
    IRC protocol interface.
    
    Attributes:
        user: A User object to store the bot's user details
        logger: A Logger object
        channels: A ChannelList object
        admins: A list of User objects
        ssl: A boolean to enable or disable SSL wrapper
        
        _init_channels: A list of channels that is joined when the client is connected
        _reconnect: Whether or not to reconnect when socket connection is lost
        _password: The connection password (if any)
        _buffer: A socket buffer string
        
        _oper: Boolean indicating whether or not the server accepts the client as an IRCOP
        _oper_user: A username string argument for the OPER command
        _oper_pass: A password string argument for the OPER command
        
        _ping: UNIX time of last ping request
        _stimeout_count: A counter to keep track of the number of timeouts
        _SOCKET_TIMEOUT: The number of seconds before the socket times out
        _PING_TIMEOUT: The number of seconds after which a PING message is considered timed out
        _PING_FREQUENCY: The number of seconds (in multiples of _SOCKET_TIMEOUT) that must elapse
            before a PING message is sent to the server.
        
        _last_msg: UNIX time of latest received message
    """
    def __init__(self, nick, realname, channels, admins, _ssl = False, reconnect = False,
                  password = False, oper_user = False, oper_pass = False):
        self.users = UserList()
        self.user = User(nick=nick, real=realname)
        self.users.append(self.user)
        self.channels = ChannelList(self.users)

        self._nick = nick
        self._real = realname
        
        self.logger = logging.getLogger('teslabot.irc')
        self._init_channels = channels
        self._ssl = _ssl
        self._reconnect = reconnect
        self._reconnect_time = 0
        self._password = password
        self._buffer = ''
        self._ipaddr = None
        
        self._oper = False
        self._oper_user = oper_user
        self._oper_pass = oper_pass
        
        self._msg_time = []
        self._msg_last_id = 0
        self._max_mps = 5
        self._throttle = False

        self._ping = 0
        self._stimeout_count = 0
        self._SOCKET_TIMEOUT = 5
        self._PING_TIMEOUT = 5
        self._PING_FREQUENCY = 12
        
        self._last_msg = 0

        self.alive = 1
        
        # Define users with administrator privileges
        for admin in admins:
            user = User(src=admin, admin=True)
            self.users.append(user)

    def run(self):
        """
        Keeps the the connection alive by continuously calling _recv().
        It will attempt to reconnect if connection is lost and reconnect is enabled.
        """
        while self.alive:
            try:
                self._recv()
            except socket.error as e:
                self.reconnect()

    def _get_headers(self):
        return ':' + self.user.nick + '!' + self.user.real + '@' + self.user.host

    def join(self, chan):
        """Accepts channel name string."""
        self.send('JOIN :{0}'.format(chan))
        
    @property
    def nick(self):
        return self.user.nick

    @nick.setter
    def nick(self, value):
        self.send('NICK {0}'.format(value))
        self.user.nick = value
        
    def notice(self, msg, nick):
        """Accepts a string or a list of messages."""
        if type(msg) == list:
            for line in msg:
                if len(line) > 0:
                    self.send(u'NOTICE {0} :{1}'.format(nick, line))
                    self.logger.info('>{0}< {1}'.format(nick, line))
        else:
            msg = msg.split('\r\n')
            for line in msg:
                maxlen = 512 - len(self._get_headers()) - len(nick) - 12
                
                if len(line) < maxlen:
                    self.send('NOTICE {0} :{1}'.format(nick, line))
                    self.logger.info('>{0}< {1}'.format(nick, line))
                else:
                    self.send('NOTICE {0} :{1}'.format(nick, line[:maxlen-1]))
                    self.logger.info('>{0}< {1}'.format(nick, line[:maxlen-1]))
                    self.notice(line, line[maxlen-1:])
            
    def mode(self, target, modes = False, args = False):
        """Sends a MODE command.
        Args:
            target: A channel or nick string
            modes: A string of flags
            args: An argument string
        """
        if not modes:
            self.send('MODE {0}'.format(target))
        elif modes and not args:
            self.send('MODE {0} {1}'.format(target, modes))
        elif modes and args:
            self.send('MODE {0} {1} {2}'.format(target, modes, args))
            
    def kick(self, nick, chan, reason = ''):
        self.send(u'KICK {0} {1} :{2}'.format(chan, nick, reason))
            
    def _get_avg_mps(self):
        """Returns the average rate of sent messages per second."""
        x1 = self._msg_last_id - self._max_mps
        t1 = self._msg_time[self._msg_last_id - self._max_mps]
        x2 = self._msg_last_id
        t2 = self._msg_time[self._msg_last_id]
        
        avg_mps = (x2 - x1) / (t2 - t1)
        
        return avg_mps
            
    def _is_throttling(self):
        """Returns true if the rate of messages per second has exceeded the limit.
        
        Formula:
            (x2 - x1)/(t2 - t1) = mps (average messages per second)
            where (x1, t1) and (x2, t2) represent amount of x messages covered in y seconds.
            
            The distance between (x1, t1) and (x2, t2) is determined by _max_mps (5 by default).
            
            If the average mps exceeds _max_mps, throttling occurs. When throttling, messages are
            sent every 1 second. When the average mps is equal to or less than 1, throttling stops.
            
        Data structure:
            _msg_time: a list of UNIX time values, whose index represents the number of messages.
            Although in practice, the difference between each index is the only relevant fact.
            As a result, we "pop" values from the beginning of the list that are no longer needed.
        """
        self._msg_time.append(time.time())
        throttle = False
        
        if self._throttle:    
            avg_mps = self._get_avg_mps()
            
            if self._msg_last_id % self._max_mps == 0:
                # In order to prevent the list from growing big, we drop values we no longer need.
                self._msg_time.pop(0)
                self._msg_last_id -= 1
            
            if avg_mps <= 1:
                self.logger.warning('Throttling disabled.')
                self._throttle = False
            else:
                self.logger.warning('Throttling.')
                throttle = True
        
        elif len(self._msg_time) > self._max_mps:
            avg_mps = self._get_avg_mps()
            
            # In order to prevent the list from growing large, we drop values we no longer need.
            if self._msg_last_id % self._max_mps == 0:
                self._msg_time.pop(0)
                self._msg_last_id -= 1
            
            if avg_mps >= self._max_mps:
                self.logger.warning('Throttling enabled.')
                self._throttle = throttle = True
            else:
                throttle = False
                
        self._msg_last_id += 1
        return throttle

    def send(self, msg, silent = False):
        """msg should be 512 bytes or less"""
        
        if self._is_throttling():
            time.sleep(1)
            
        # Encode to bytes -- assuming it's a utf-8 string
        msg = msg.encode('utf-8')
        
        self.sock.send(msg + '\r\n')
        if not silent:
            self.logger.debug('{0}'.format(msg))

    def leave(self, chan, reason = 'Leaving'):
        self.send('PART {0} :{1}'.format(chan, reason))

    def say(self, msg, dst):
        msg = msg.split('\r\n')

        for line in msg:
            maxlen = 512 - len(self._get_headers()) - len(dst) - 12
            
            if len(line) < maxlen:
                self.send(u'PRIVMSG {0} :{1}'.format(dst, line))
                self.logger.info(u'[{0}] <{1}> {2}'.format(dst, self.user.nick, line))
            else:
                self.send(u'PRIVMSG ' + dst + ' :' + line[:maxlen-1])
                self.logger.info(u'[{0}] <{1}> {2}'.format(dst, self.user.nick, line[:maxlen-1]))
                self.say(line[maxlen-1:], dst)
                
    def names(self, chan):
        self.send('NAMES {0}'.format(chan))

    def action(self, msg, dst):
        self.send('PRIVMSG ' + dst + ' :\x01ACTION ' + msg + '\x01')

    def whois(self, nick):
        self.send('WHOIS {0}'.format(nick))
        
    def oper(self, username = False, password = False):
        if not username:
            username = self._oper_user
        if not password:
            password = self._oper_pass
        self.send('OPER {0} {1}'.format(username, password), True)

    def is_chan(self, chan):
        """Returns true if a given string is a valid channel name."""
        if chan[:1] in ('&', '#', '+', '!'):
            return True
        return False

    def _on_privmsg(self, user, args):
        """Calls the appropriate handler for a given PRIVMSG type.
        Either channel, private, or CTCP message.
        
        Args:
            user: A User class instance
            args: A string of arguments
        """
        dst, msg  = args.split(' ', 1)
        
        # CTCP query/reply
        if msg[1] == '\x01' and msg[-1] == '\x01':
            ctcp_msg = msg[2:-1]
            if len(ctcp_msg.split()) > 1:
                cmd, subargs = ctcp_msg.split(' ', 1)
            else:
                cmd = ctcp_msg
                subargs = None

            self.on_ctcp(user, cmd, subargs)
        
        # Channel message
        if self.is_chan(dst[:1]):
            self.on_channel_message(user, self.channels.get(dst), msg[1:])

        # Private query
        elif dst.lower() == self.user.nick.lower():
            self.on_private_message(user, msg[1:])

        else:
            self.logger.warning("Unrecognized PRIVMSG format.")

    def quit(self, msg = 'Quitting', force = None):
        try:
            if force:
                sys.exit()
            
            self.send('QUIT :{0}'.format(msg))
            self.sock.close()
            self.alive = 0
        finally:
            self.logger.info('Disconnected from [{0}].'.format(self.user.host))

    def ping(self):
        self.send('PING {0}'.format(self._host))
        self._ping = time.time()

    def _set_hostname(self, hostname):
        self.user.host = hostname
        
    def _recv_timeout(self):
        self._stimeout_count += 1
        if self._stimeout_count >= self._PING_FREQUENCY and not self._ping:
            self._stimeout_count = 0
            self.ping()
        elif self._ping:
            diff = time.time() - self._ping
            if diff >= self._PING_TIMEOUT:
                self.logger.info('Disconnected due to timeout.')
                self.reconnect()
                
    def _recv(self, timeout = False):
        """Processes messages received from the IRC server and calls the
        appropriate handlers."""
        buffer = ''
        self._last_msg = time.time()
        
        try:
            buffer = self._buffer + self.sock.recv(512)
        except (socket.error, ssl.SSLError) as e:
            if e.message == 'The read operation timed out'\
                    or e.message == 'timed out':
               self._recv_timeout()
               return
        except socket.timeout:
            self._recv_timeout()
            return
        
        self._buffer = ''

        # Server has closed the socket connection
        if len(buffer) == 0:
            self.logger.debug('Server has closed socket connection.')
            raise socket.error
        
        data = buffer.split('\r\n')
        
        # If not empty, this is part of a new message. Add it to the buffer.
        self._buffer += data.pop()

        # Server didn't send CRLF
        if not len(data):
            return

        # Remove empty strings due to an \r\n in the beginning 
        if data[0] == '':
            data.pop(0)

        for msg in data:
            self.logger.debug('{0}'.format(msg))
            # Assuming it's UTF-8 encoded. If not, ignore errors.
            self._parse_message(msg.decode('utf-8', 'ignore'))

    def _parse_message(self, msg):
        """Parses a given IRC message."""
        if msg[:4] == 'PING':
            self.send('PONG {0}'.format(msg[5:]))
            return

        elif msg[:5] == 'ERROR':
            self.quit(force=True)
        
        src, cmd, args = msg.split(' ', 2)
        user = self.users.get(src[1:])
        
        if cmd == 'PONG' and self._ping:
            diff = time.time() - self._ping
            self._ping = 0
            self.logger.debug('PONG acknowledged ({0}s).'.format(diff))

        elif cmd == 'PRIVMSG':
            self._on_privmsg(user, args)

        elif cmd == 'MODE':
            args = args.split(' ', 2)
            subargs = False

            if self.is_chan(args[0]):
                if len(args) == 3:
                    subargs = args.pop().split()

                chan, modes = args
                channel = self.channels.get(chan)
                self.on_channel_mode(user, channel, modes, subargs)
            
        elif cmd == 'NOTICE':
            self.on_notice(user, args)

        elif cmd == 'TOPIC':
            chan = args.split(' ', 1)[0]
            topic = args.split(' ', 1)[1][1:]

            self.on_channel_topic(user, self.channels[chan], topic)

        elif cmd == 'JOIN':
            if args[0] != ':':
                chan = args
            else:
                chan = args[1:]
            channel = self.channels.add(chan)
            self.on_channel_join(user, channel)
            
        elif cmd == 'KICK':
            chan, target, reason = args.split(' ', 2)
            channel = self.channels[chan]
            target = self.users.get(target)
            
            self.on_channel_kick(user, channel, target, reason[1:])
            
        elif cmd == 'NICK':
            self.users.get(user=user).nick = args

        elif cmd == 'PART':
            subargs = args.split()
            
            if len(subargs) == 2:
                chan, reason = subargs
                self.on_channel_part(user, self.channels[chan], reason[1:])
            else:
                chan = args.split()[0]
                self.on_channel_part(user, self.channels[chan])

        elif cmd == RPL_WELCOME:
            self.on_connect()
            
        elif cmd == RPL_YOUREOPER:
            self._oper = True

        elif cmd == RPL_HOSTHIDDEN:
            self._set_hostname(args)

        elif cmd in (RPL_WHOISUSER, RPL_WHOISIDLE, RPL_WHOISACTUALLY,
            RPL_WHOISHOST):
            self._on_whois(cmd, args)

        elif cmd == ERR_NICKNAMEINUSE:
            self.on_nickinuse()
        
        elif cmd in (RPL_TOPIC, RPL_TOPICWHOTIME, RPL_NAMREPLY):
            self.channels.on_reply(cmd, args)
            
        elif cmd in (RPL_MOTDSTART, RPL_MOTD, RPL_ENDOFMOTD):
            self.on_motd(args)
            
    def on_motd(self, msg):
        if not __debug__:
            self.logger.info(msg.split(':', 1)[1])
            
    def _on_whois(self, cmd, args):
        if cmd == RPL_WHOISUSER:
            if args.split(' ')[1] == self.user.nick:   # Self-WHOIS
                self._set_hostname(args.split(' ')[3])    # Get the hostname
                self.logger.debug('Setting hostname to [{0}].'.format(self.user.host))
            else:
                pass
        elif cmd == RPL_WHOISIDLE:
            args = args.split()
            
            user = self.users.get(args[1])
            user.idle = int(args[2])
            user.signon = int(args[3])

        elif cmd == RPL_WHOISACTUALLY:
            self._ipaddr = args.split()[-1][1:-1]

        elif cmd == RPL_WHOISHOST:
            self._ipaddr = args.split()[-1]

    def ipaddr(self):
        return self._ipaddr

    def connect(self, host, port):
        """Attempts to establish a socket connection with a given IRC server."""
        self._host = host
        self._port = port
        
        try:
            self.logger.info('Connecting to {0}:{1}.'.format(host, port))
            
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            if self._ssl:
                self.sock = ssl.wrap_socket(self.sock, cert_reqs=ssl.CERT_NONE)
            self.sock.settimeout(self._SOCKET_TIMEOUT)
            self.sock.connect((host, port))
            self.alive = 1
            
            if self._password:
                self.send('PASS {0}'.format(self._password))
        
            self.send('NICK {0}'.format(self._nick))
            self.send('USER {0} 0 * :{0}'.format(self._real))

        except socket.error as e:
            self.logger.critical('Failed to connect to {0}:{1}.'.format(host, port))
            
    def reconnect(self):
        if self._reconnect:
            # Wait 15 seconds before reconnecting again
            tdiff = time.time() - self._reconnect_time
            if self._reconnect_time and tdiff < 15:
                self.logger.info('Attempting to reconnect in 15 seconds...')
                time.sleep(15)
                
            self.logger.debug('Reconnecting.')
            self.connect(self._host, self._port)
            self._reconnect_time = time.time()
        else:
            self.logger.info('Reconnection disabled.')
            
    def on_connect(self):
        self.whois(self.user.nick)
        if self._oper_user and self._oper_pass:
            self.oper()
            
        for channel in self._init_channels:
            self.join(channel)

    def on_channel_mode(self, user, channel, modes, args = False):
        """Called when a channel mode is changed.

        TODO: Recognize channel modes that aren't specific to users.

        Args:
            args: A list of arguments
        """
        for i, mode in enumerate(modes[1:]):
            if mode in ('a', 'q', 'o', 'h', 'v'):
                target = self.users.get(args[i])
                if modes[0] == '+':
                    target.modes.add(channel.name, mode)
                else:
                    target.modes.remove(channel.name, mode)

    def on_channel_message(self, user, channel, msg):
        raise NotImplementedError

    def on_channel_join(self, user, channel):
        """on_channel_join is called when a user (including the bot) joins a channel.
        
        Args:
            channel: A Channel instance
            user: A user instance
        """
        # Requests channel modes
        self.mode(channel.name)

    def on_channel_part(self, user, channel, reason):
        """on_channel_part is called when a user (including the bot) leaves the channel."""
        user.modes.remove(channel.name, -1)
        if user.nick == self.user.nick:
            self.channels.remove(channel)
        else:
            channel.remove(user)
            
    def on_channel_kick(self, user, channel, target, reason):
        raise NotImplementedError

    def on_channel_topic(self, user, channel, topic):
        raise NotImplementedError

    def on_private_message(self, user, msg):
        raise NotImplementedError
    
    def on_notice(self, user, msg):
        if not __debug__:
            self.logger.info('-{0}- {1}'.format(user.nick, msg))

    def on_nickinuse(self):
        raise NotImplementedError

    def ctcp(self, msg, nick):
        self.send(u'PRIVMSG {2} :{0}{1}{0}'.format('\x01', msg, nick))

    def on_ctcp(self, user, cmd, args):
        global __version__

        if cmd == 'VERSION':
            self.notice('VERSION Teslabot {0}'.format(__version__), user.nick)
Exemple #9
0
class IRC(object):
    """
    IRC protocol interface.
    
    Attributes:
        user: A User object to store the bot's user details
        logger: A Logger object
        channels: A ChannelList object
        admins: A list of User objects
        ssl: A boolean to enable or disable SSL wrapper
        
        _init_channels: A list of channels that is joined when the client is connected
        _reconnect: Whether or not to reconnect when socket connection is lost
        _password: The connection password (if any)
        _buffer: A socket buffer string
        
        _oper: Boolean indicating whether or not the server accepts the client as an IRCOP
        _oper_user: A username string argument for the OPER command
        _oper_pass: A password string argument for the OPER command
        
        _ping: UNIX time of last ping request
        _stimeout_count: A counter to keep track of the number of timeouts
        _SOCKET_TIMEOUT: The number of seconds before the socket times out
        _PING_TIMEOUT: The number of seconds after which a PING message is considered timed out
        _PING_FREQUENCY: The number of seconds (in multiples of _SOCKET_TIMEOUT) that must elapse
            before a PING message is sent to the server.
        
        _last_msg: UNIX time of latest received message
    """
    def __init__(self,
                 nick,
                 realname,
                 channels,
                 admins,
                 _ssl=False,
                 reconnect=False,
                 password=False,
                 oper_user=False,
                 oper_pass=False):
        self.users = UserList()
        self.user = User(nick=nick, real=realname)
        self.users.append(self.user)
        self.channels = ChannelList(self.users)

        self._nick = nick
        self._real = realname

        self.logger = logging.getLogger('teslabot.irc')
        self._init_channels = channels
        self._ssl = _ssl
        self._reconnect = reconnect
        self._reconnect_time = 0
        self._password = password
        self._buffer = ''
        self._ipaddr = None

        self._oper = False
        self._oper_user = oper_user
        self._oper_pass = oper_pass

        self._msg_time = []
        self._msg_last_id = 0
        self._max_mps = 5
        self._throttle = False

        self._ping = 0
        self._stimeout_count = 0
        self._SOCKET_TIMEOUT = 5
        self._PING_TIMEOUT = 5
        self._PING_FREQUENCY = 12

        self._last_msg = 0

        self.alive = 1

        # Define users with administrator privileges
        for admin in admins:
            user = User(src=admin, admin=True)
            self.users.append(user)

    def run(self):
        """
        Keeps the the connection alive by continuously calling _recv().
        It will attempt to reconnect if connection is lost and reconnect is enabled.
        """
        while self.alive:
            try:
                self._recv()
            except socket.error as e:
                self.reconnect()

    def _get_headers(self):
        return ':' + self.user.nick + '!' + self.user.real + '@' + self.user.host

    def join(self, chan):
        """Accepts channel name string."""
        self.send('JOIN :{0}'.format(chan))

    @property
    def nick(self):
        return self.user.nick

    @nick.setter
    def nick(self, value):
        self.send('NICK {0}'.format(value))
        self.user.nick = value

    def notice(self, msg, nick):
        """Accepts a string or a list of messages."""
        if type(msg) == list:
            for line in msg:
                if len(line) > 0:
                    self.send(u'NOTICE {0} :{1}'.format(nick, line))
                    self.logger.info('>{0}< {1}'.format(nick, line))
        else:
            msg = msg.split('\r\n')
            for line in msg:
                maxlen = 512 - len(self._get_headers()) - len(nick) - 12

                if len(line) < maxlen:
                    self.send('NOTICE {0} :{1}'.format(nick, line))
                    self.logger.info('>{0}< {1}'.format(nick, line))
                else:
                    self.send('NOTICE {0} :{1}'.format(nick,
                                                       line[:maxlen - 1]))
                    self.logger.info('>{0}< {1}'.format(
                        nick, line[:maxlen - 1]))
                    self.notice(line, line[maxlen - 1:])

    def mode(self, target, modes=False, args=False):
        """Sends a MODE command.
        Args:
            target: A channel or nick string
            modes: A string of flags
            args: An argument string
        """
        if not modes:
            self.send('MODE {0}'.format(target))
        elif modes and not args:
            self.send('MODE {0} {1}'.format(target, modes))
        elif modes and args:
            self.send('MODE {0} {1} {2}'.format(target, modes, args))

    def kick(self, nick, chan, reason=''):
        self.send(u'KICK {0} {1} :{2}'.format(chan, nick, reason))

    def _get_avg_mps(self):
        """Returns the average rate of sent messages per second."""
        x1 = self._msg_last_id - self._max_mps
        t1 = self._msg_time[self._msg_last_id - self._max_mps]
        x2 = self._msg_last_id
        t2 = self._msg_time[self._msg_last_id]

        avg_mps = (x2 - x1) / (t2 - t1)

        return avg_mps

    def _is_throttling(self):
        """Returns true if the rate of messages per second has exceeded the limit.
        
        Formula:
            (x2 - x1)/(t2 - t1) = mps (average messages per second)
            where (x1, t1) and (x2, t2) represent amount of x messages covered in y seconds.
            
            The distance between (x1, t1) and (x2, t2) is determined by _max_mps (5 by default).
            
            If the average mps exceeds _max_mps, throttling occurs. When throttling, messages are
            sent every 1 second. When the average mps is equal to or less than 1, throttling stops.
            
        Data structure:
            _msg_time: a list of UNIX time values, whose index represents the number of messages.
            Although in practice, the difference between each index is the only relevant fact.
            As a result, we "pop" values from the beginning of the list that are no longer needed.
        """
        self._msg_time.append(time.time())
        throttle = False

        if self._throttle:
            avg_mps = self._get_avg_mps()

            if self._msg_last_id % self._max_mps == 0:
                # In order to prevent the list from growing big, we drop values we no longer need.
                self._msg_time.pop(0)
                self._msg_last_id -= 1

            if avg_mps <= 1:
                self.logger.warning('Throttling disabled.')
                self._throttle = False
            else:
                self.logger.warning('Throttling.')
                throttle = True

        elif len(self._msg_time) > self._max_mps:
            avg_mps = self._get_avg_mps()

            # In order to prevent the list from growing large, we drop values we no longer need.
            if self._msg_last_id % self._max_mps == 0:
                self._msg_time.pop(0)
                self._msg_last_id -= 1

            if avg_mps >= self._max_mps:
                self.logger.warning('Throttling enabled.')
                self._throttle = throttle = True
            else:
                throttle = False

        self._msg_last_id += 1
        return throttle

    def send(self, msg, silent=False):
        """msg should be 512 bytes or less"""

        if self._is_throttling():
            time.sleep(1)

        # Encode to bytes -- assuming it's a utf-8 string
        msg = msg.encode('utf-8')

        self.sock.send(msg + '\r\n')
        if not silent:
            self.logger.debug('{0}'.format(msg))

    def leave(self, chan, reason='Leaving'):
        self.send('PART {0} :{1}'.format(chan, reason))

    def say(self, msg, dst):
        msg = msg.split('\r\n')

        for line in msg:
            maxlen = 512 - len(self._get_headers()) - len(dst) - 12

            if len(line) < maxlen:
                self.send(u'PRIVMSG {0} :{1}'.format(dst, line))
                self.logger.info(u'[{0}] <{1}> {2}'.format(
                    dst, self.user.nick, line))
            else:
                self.send(u'PRIVMSG ' + dst + ' :' + line[:maxlen - 1])
                self.logger.info(u'[{0}] <{1}> {2}'.format(
                    dst, self.user.nick, line[:maxlen - 1]))
                self.say(line[maxlen - 1:], dst)

    def names(self, chan):
        self.send('NAMES {0}'.format(chan))

    def action(self, msg, dst):
        self.send('PRIVMSG ' + dst + ' :\x01ACTION ' + msg + '\x01')

    def whois(self, nick):
        self.send('WHOIS {0}'.format(nick))

    def oper(self, username=False, password=False):
        if not username:
            username = self._oper_user
        if not password:
            password = self._oper_pass
        self.send('OPER {0} {1}'.format(username, password), True)

    def is_chan(self, chan):
        """Returns true if a given string is a valid channel name."""
        if chan[:1] in ('&', '#', '+', '!'):
            return True
        return False

    def _on_privmsg(self, user, args):
        """Calls the appropriate handler for a given PRIVMSG type.
        Either channel, private, or CTCP message.
        
        Args:
            user: A User class instance
            args: A string of arguments
        """
        dst, msg = args.split(' ', 1)

        # CTCP query/reply
        if msg[1] == '\x01' and msg[-1] == '\x01':
            ctcp_msg = msg[2:-1]
            if len(ctcp_msg.split()) > 1:
                cmd, subargs = ctcp_msg.split(' ', 1)
            else:
                cmd = ctcp_msg
                subargs = None

            self.on_ctcp(user, cmd, subargs)

        # Channel message
        if self.is_chan(dst[:1]):
            self.on_channel_message(user, self.channels.get(dst), msg[1:])

        # Private query
        elif dst.lower() == self.user.nick.lower():
            self.on_private_message(user, msg[1:])

        else:
            self.logger.warning("Unrecognized PRIVMSG format.")

    def quit(self, msg='Quitting', force=None):
        try:
            if force:
                sys.exit()

            self.send('QUIT :{0}'.format(msg))
            self.sock.close()
            self.alive = 0
        finally:
            self.logger.info('Disconnected from [{0}].'.format(self.user.host))

    def ping(self):
        self.send('PING {0}'.format(self._host))
        self._ping = time.time()

    def _set_hostname(self, hostname):
        self.user.host = hostname

    def _recv_timeout(self):
        self._stimeout_count += 1
        if self._stimeout_count >= self._PING_FREQUENCY and not self._ping:
            self._stimeout_count = 0
            self.ping()
        elif self._ping:
            diff = time.time() - self._ping
            if diff >= self._PING_TIMEOUT:
                self.logger.info('Disconnected due to timeout.')
                self.reconnect()

    def _recv(self, timeout=False):
        """Processes messages received from the IRC server and calls the
        appropriate handlers."""
        buffer = ''
        self._last_msg = time.time()

        try:
            buffer = self._buffer + self.sock.recv(512)
        except (socket.error, ssl.SSLError) as e:
            if e.message == 'The read operation timed out'\
                    or e.message == 'timed out':
                self._recv_timeout()
                return
        except socket.timeout:
            self._recv_timeout()
            return

        self._buffer = ''

        # Server has closed the socket connection
        if len(buffer) == 0:
            self.logger.debug('Server has closed socket connection.')
            raise socket.error

        data = buffer.split('\r\n')

        # If not empty, this is part of a new message. Add it to the buffer.
        self._buffer += data.pop()

        # Server didn't send CRLF
        if not len(data):
            return

        # Remove empty strings due to an \r\n in the beginning
        if data[0] == '':
            data.pop(0)

        for msg in data:
            self.logger.debug('{0}'.format(msg))
            # Assuming it's UTF-8 encoded. If not, ignore errors.
            self._parse_message(msg.decode('utf-8', 'ignore'))

    def _parse_message(self, msg):
        """Parses a given IRC message."""
        if msg[:4] == 'PING':
            self.send('PONG {0}'.format(msg[5:]))
            return

        elif msg[:5] == 'ERROR':
            self.quit(force=True)

        src, cmd, args = msg.split(' ', 2)
        user = self.users.get(src[1:])

        if cmd == 'PONG' and self._ping:
            diff = time.time() - self._ping
            self._ping = 0
            self.logger.debug('PONG acknowledged ({0}s).'.format(diff))

        elif cmd == 'PRIVMSG':
            self._on_privmsg(user, args)

        elif cmd == 'MODE':
            args = args.split(' ', 2)
            subargs = False

            if self.is_chan(args[0]):
                if len(args) == 3:
                    subargs = args.pop().split()

                chan, modes = args
                channel = self.channels.get(chan)
                self.on_channel_mode(user, channel, modes, subargs)

        elif cmd == 'NOTICE':
            self.on_notice(user, args)

        elif cmd == 'TOPIC':
            chan = args.split(' ', 1)[0]
            topic = args.split(' ', 1)[1][1:]

            self.on_channel_topic(user, self.channels[chan], topic)

        elif cmd == 'JOIN':
            if args[0] != ':':
                chan = args
            else:
                chan = args[1:]
            channel = self.channels.add(chan)
            self.on_channel_join(user, channel)

        elif cmd == 'KICK':
            chan, target, reason = args.split(' ', 2)
            channel = self.channels[chan]
            target = self.users.get(target)

            self.on_channel_kick(user, channel, target, reason[1:])

        elif cmd == 'NICK':
            self.users.get(user=user).nick = args

        elif cmd == 'PART':
            subargs = args.split()

            if len(subargs) == 2:
                chan, reason = subargs
                self.on_channel_part(user, self.channels[chan], reason[1:])
            else:
                chan = args.split()[0]
                self.on_channel_part(user, self.channels[chan])

        elif cmd == RPL_WELCOME:
            self.on_connect()

        elif cmd == RPL_YOUREOPER:
            self._oper = True

        elif cmd == RPL_HOSTHIDDEN:
            self._set_hostname(args)

        elif cmd in (RPL_WHOISUSER, RPL_WHOISIDLE, RPL_WHOISACTUALLY,
                     RPL_WHOISHOST):
            self._on_whois(cmd, args)

        elif cmd == ERR_NICKNAMEINUSE:
            self.on_nickinuse()

        elif cmd in (RPL_TOPIC, RPL_TOPICWHOTIME, RPL_NAMREPLY):
            self.channels.on_reply(cmd, args)

        elif cmd in (RPL_MOTDSTART, RPL_MOTD, RPL_ENDOFMOTD):
            self.on_motd(args)

    def on_motd(self, msg):
        if not __debug__:
            self.logger.info(msg.split(':', 1)[1])

    def _on_whois(self, cmd, args):
        if cmd == RPL_WHOISUSER:
            if args.split(' ')[1] == self.user.nick:  # Self-WHOIS
                self._set_hostname(args.split(' ')[3])  # Get the hostname
                self.logger.debug('Setting hostname to [{0}].'.format(
                    self.user.host))
            else:
                pass
        elif cmd == RPL_WHOISIDLE:
            args = args.split()

            user = self.users.get(args[1])
            user.idle = int(args[2])
            user.signon = int(args[3])

        elif cmd == RPL_WHOISACTUALLY:
            self._ipaddr = args.split()[-1][1:-1]

        elif cmd == RPL_WHOISHOST:
            self._ipaddr = args.split()[-1]

    def ipaddr(self):
        return self._ipaddr

    def connect(self, host, port):
        """Attempts to establish a socket connection with a given IRC server."""
        self._host = host
        self._port = port

        try:
            self.logger.info('Connecting to {0}:{1}.'.format(host, port))

            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            if self._ssl:
                self.sock = ssl.wrap_socket(self.sock, cert_reqs=ssl.CERT_NONE)
            self.sock.settimeout(self._SOCKET_TIMEOUT)
            self.sock.connect((host, port))
            self.alive = 1

            if self._password:
                self.send('PASS {0}'.format(self._password))

            self.send('NICK {0}'.format(self._nick))
            self.send('USER {0} 0 * :{0}'.format(self._real))

        except socket.error as e:
            self.logger.critical('Failed to connect to {0}:{1}.'.format(
                host, port))

    def reconnect(self):
        if self._reconnect:
            # Wait 15 seconds before reconnecting again
            tdiff = time.time() - self._reconnect_time
            if self._reconnect_time and tdiff < 15:
                self.logger.info('Attempting to reconnect in 15 seconds...')
                time.sleep(15)

            self.logger.debug('Reconnecting.')
            self.connect(self._host, self._port)
            self._reconnect_time = time.time()
        else:
            self.logger.info('Reconnection disabled.')

    def on_connect(self):
        self.whois(self.user.nick)
        if self._oper_user and self._oper_pass:
            self.oper()

        for channel in self._init_channels:
            self.join(channel)

    def on_channel_mode(self, user, channel, modes, args=False):
        """Called when a channel mode is changed.

        TODO: Recognize channel modes that aren't specific to users.

        Args:
            args: A list of arguments
        """
        for i, mode in enumerate(modes[1:]):
            if mode in ('a', 'q', 'o', 'h', 'v'):
                target = self.users.get(args[i])
                if modes[0] == '+':
                    target.modes.add(channel.name, mode)
                else:
                    target.modes.remove(channel.name, mode)

    def on_channel_message(self, user, channel, msg):
        raise NotImplementedError

    def on_channel_join(self, user, channel):
        """on_channel_join is called when a user (including the bot) joins a channel.
        
        Args:
            channel: A Channel instance
            user: A user instance
        """
        # Requests channel modes
        self.mode(channel.name)

    def on_channel_part(self, user, channel, reason):
        """on_channel_part is called when a user (including the bot) leaves the channel."""
        user.modes.remove(channel.name, -1)
        if user.nick == self.user.nick:
            self.channels.remove(channel)
        else:
            channel.remove(user)

    def on_channel_kick(self, user, channel, target, reason):
        raise NotImplementedError

    def on_channel_topic(self, user, channel, topic):
        raise NotImplementedError

    def on_private_message(self, user, msg):
        raise NotImplementedError

    def on_notice(self, user, msg):
        if not __debug__:
            self.logger.info('-{0}- {1}'.format(user.nick, msg))

    def on_nickinuse(self):
        raise NotImplementedError

    def ctcp(self, msg, nick):
        self.send(u'PRIVMSG {2} :{0}{1}{0}'.format('\x01', msg, nick))

    def on_ctcp(self, user, cmd, args):
        global __version__

        if cmd == 'VERSION':
            self.notice('VERSION Teslabot {0}'.format(__version__), user.nick)
Exemple #10
0
def init_flask_openid(app):
    return OpenID(app)


def init_flask(name):
    app = Flask(name)
    app.config.update(SECRET_KEY='development key', DEBUG=True)
    return app


app = init_flask(__name__)
oid = init_flask_openid(app)

from user import UserList
user_list = UserList()


def render_time(fn):
    @wraps(fn)
    def inner(*args, **kwargs):
        start = time.time()
        result = fn(*args, **kwargs)
        end = time.time()
        try:
            return result.replace("TTTTIME", "%.4f" % (end - start))
        except AttributeError:
            return result

    return inner
Exemple #11
0
class Server:
    group_id = 191177272
    access_token = 'access_token=f068c796542cba0f4dbdd0f6e39ba656a489731d36cfdcbdf7cee30de822ae000aa9e1aa8293bc61d77c7'
    v = 'v=5.103'  # Текущая версия VkAPI
    body = 'https://api.vk.com/method/'  # Тело запроса
    data = UserList()
    closest_time = 'z'  # to make it bigger than numbers
    closest_events = dict()

    def __init__(self):
        Server.getLongPollServer(self)
        self.find_closest_events()

    def find_closest_events(self):
        self.closest_events, self.closest_time = dict(), 'z'
        for key, value in self.data.get_dict().items():
            for sub_key, sub_value in value.items():
                if sub_key <= self.closest_time:
                    self.closest_time = sub_key
                    self.closest_events[key] = sub_value

    def send_notifications(self):
        for key, value in self.closest_events.items():
            message, user_id, random_id = value, key, random.randint(0, 100)
            method = 'messages.send?' + 'user_id=' + str(user_id) + '&random_id=' + str(random_id) \
                     + '&message=' + message
            r = requests.get("&".join([Server.body + method, Server.v, Server.access_token]))
            self.data.delete_event(key, self.closest_time)
        self.data.update_file()
        self.find_closest_events()

    def getLongPollServer(self):
        method = 'groups.getLongPollServer?group_id=191177272'
        reply = requests.get("&".join([Server.body + method, Server.v, Server.access_token]))
        data = json.loads(reply.text)
        self.server = data['response']['server']
        self.key = data['response']['key']
        self.ts = data['response']['ts']
        # print(self.server, self.key, self.ts)

    def simple_request(self):
        method = self.server + '?act=a_check&key=' + self.key + '&ts=' + self.ts + "&wait=25"
        return requests.get(method)

    def simple_loop(self):
        reply = json.loads(self.simple_request().text)
        self.ts = reply['ts']
        if self.closest_time != '' and self.check_date():
            self.send_notifications()
        if reply['updates']:
            message = reply['updates'][0]['object']['message']['text']
            user_id = reply['updates'][0]['object']['message']['from_id']
            self.data.add_rec(str(user_id), {datetime.datetime.now().strftime('%Y-%m-%d:%H.%M'): message})
            random_id = random.randint(0, 100)
            method = 'messages.send?' + 'user_id=' + str(user_id) + '&random_id=' + str(random_id) \
                     + '&message=' + message
            r = requests.get("&".join([Server.body + method, Server.v, Server.access_token]))
            print("&".join([Server.body + method, Server.v, Server.access_token]))
        self.simple_loop()

    def check_date(self):
        if datetime.datetime.now().strftime('%Y-%m-%d:%H.%M') == self.closest_time:
            return True
        return False