Пример #1
0
    def __init__(self):
        if not hasattr(botconfig, "igdbAuthKey"):
            ptf("igdbAuthKey not found in botconfig")
        if not hasattr(botconfig, "steamAuthKey"):
            ptf("steamAuthKey not found in botconfig")

        self.igdbHeader = { "user-key" : botconfig.igdbAuthKey,
                            "Accept" : "application/json" }

        params = { "key" : botconfig.steamAuthKey }

        response = requests.get("https://api.steampowered.com/ISteamApps/GetAppList/v2/", params=params)
        data = response.json()

        self.steamApps = {}
        if response.ok:
            self.steamApps = { app["name"] : app["appid"] for app in data["applist"]["apps"] }

        self.activeCommands = {
            # snippet start
            # findgame (TEXT)
            # findgame
            # findgame Silent Hill
            # Remarks
            # findgame on its own will search for the currently played game.
            "findgame" : self.ExecuteFindGame,
        }

        self.findGameRegex = re.compile(f"^findgame {groups.text}$")
Пример #2
0
    def CheckGetAccessToken(self):
        response = requests.get(
            f"https://api.spotify.com/v1/tracks/11dFghVXANMlKmJXsNCbNl",
            headers=self.spotifyHeader)

        if not response.ok:
            response = requests.post("https://accounts.spotify.com/api/token",
                                     headers=self.authHeader,
                                     data=self.authBody)
            data = response.json()
            ptf(data)
            self.spotifyHeader[
                "Authorization"] = f"Bearer {data['access_token']}"
Пример #3
0
    def add_capability(self, capability):
        assert type(capability) in [list, str]

        self.capability = capability

        if type(capability) == list:
            for cap in capability:
                self.send_req(cap.lower())
        else:
            self.send_req(capability.lower())

        ptf("")
        ptf("Connected to Twitch IRC\n", time=True)

        self.send_message("Hi chat. I'm back! :)")
        self.conn.settimeout(330)
Пример #4
0
    def _send(self, command, message):
        if (sent := self.conn.send(bytes("{}{}\r\n".format(command, message), 'UTF-8'))) == 0:
            ptf("Socket connection broken, sent is 0. Reconnecting", time=True)

            self.conn.shutdown(socket.SHUT_WR)

            self._initialize_websocket()

            if len(self.nick) > 0:
                self.login(self.nick, self.auth)

            if len(self.chan) > 1:
                self.join_channel(self.chan)

            if self.capability is not None:
                self.add_capability(self.capability)
Пример #5
0
    def __init__(self):
        self.header = {"Accept": "application/json"}

        if not hasattr(botconfig, "spoonacularAuthKey"):
            ptf("spoonacularAuthKey not found in botconfig")

        self.params = {"apiKey": botconfig.spoonacularAuthKey}

        self.activeCommands = {
            # snippet start
            # findfood TEXT
            # findfood burger
            # findfood chicken alfredo
            "findfood": self.ExecuteFindFood,
        }

        self.findFoodRegex = re.compile(f"^findfood {groups.text}$")
Пример #6
0
    def CheckPingAsync(self):
        while not self.stopped():
            time.sleep(10)

            if (datetime.datetime.now() - self.lastPingTime).total_seconds() > 330:
                ptf("No PING. Reconnecting", time=True)
                self.conn.shutdown(socket.SHUT_WR)

                self._initialize_websocket()

                if len(self.nick) > 0:
                    self.login(self.nick, self.auth)

                if len(self.chan) > 1:
                    self.join_channel(self.chan)

                if self.capability is not None:
                    self.add_capability(self.capability)
Пример #7
0
    def _initialize_websocket(self):
        while True:
            try:
                self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                # We set the timeout to 330 seconds, as the PING from the Twitch server indicating
                # That the connection is still live is sent roughly every 5 minutes it seems.
                # the extra 30 seconds prevents us from checking the connection when it's not
                # needed.

                #TODO Error handle socket.gaierror: [Errno 11001] getaddrinfo failed and other errors
                self.conn.settimeout(10)

                self.conn.connect( (self.host, self.port) )
                self.lastPingTime = datetime.datetime.now()

                return
            except socket.gaierror:
                # Sleep and retry if not successful
                ptf("Failed to connect socket. Sleeping and retrying...", time=True)
                time.sleep(5)
Пример #8
0
    def run(self):
        while not self.stopped():
            try:
                try:
                    # Receive data from Twitch Websocket.
                    packet = self.conn.recv(8192).decode('UTF-8')
                except UnicodeDecodeError:
                    ptf("Received bad packet", time=True)
                    # In case of unexpected end of data.
                    continue

                self.data += packet
                data_split = self.data.split("\r\n")
                self.data = data_split.pop()

                # Iterate over seperately sent data.
                for line in data_split:
                    m = Message(line)

                    # We will do some handling depending on the message ourself,
                    # so the developer doesn't have to.
                    if m.type == "PING":
                        self.send_pong()
                        self.lastPingTime = datetime.datetime.now()

                    self.callback(m)

            except OSError as e:
                ptf(f"OSError: {e} -> {line}", time=True)

                self._initialize_websocket()

                if len(self.nick) > 0:
                    self.login(self.nick, self.auth)

                if len(self.chan) > 1:
                    self.join_channel(self.chan)

                if self.capability is not None:
                    self.add_capability(self.capability)
Пример #9
0
    def message_handler(self, m):
        # Check for proper message type
        if (m.type != "PRIVMSG" and m.type != "WHISPER"):
            return

        # Check for valid message with prefix and valid rewards
        validReward = "custom-reward-id" in m.tags
        validCommand = m.message != None and len(
            m.message) > 1 and m.message[0] in self.prefixes

        if (not validReward and not validCommand):
            return

        try:
            if validReward:
                util.LogReceived(m.type, m.user, m.message, m.tags)
                util.SendMessage(self.redeem[m.tags["custom-reward-id"]](m),
                                 m.type, m.user)

            if validCommand:
                # Retrieve first word without prefix
                m.message = m.message[1:]
                token = m.message.lower().split()[0]

                if (token in self.execute):
                    util.LogReceived(m.type, m.user, m.message, m.tags, True)
                    util.SendMessage(self.execute[token](m), m.type, m.user)
                    return

                # Simple response commands
                # Note that we don't get this far unless the message does not match other commands
                response = self.commands["CustomCommands"].Execute(m)
                if response != None:
                    util.SendMessage(response, m.type, m.user)
                    return

        except Exception as e:
            ptf(f"Error: {e}", time=True)
Пример #10
0
    def __init__(self):
        if not hasattr(botconfig, "spotifyIdAndSecret"):
            ptf("spotifyIdAndSecret not found in botconfig")

        self.authHeader = {
            "Authorization":
            f"Basic {base64.urlsafe_b64encode(botconfig.spotifyIdAndSecret.encode('utf-8')).decode('utf-8')}"
        }
        self.authBody = {"grant_type": "client_credentials"}

        self.spotifyHeader = {
            "Authorization": "Bearer [Invalid]",
            "Accept": "application/json"
        }

        self.activeCommands = {
            # snippet start
            # findsong TEXT
            # findsong Piano Man
            # findsong Killer Queen
            "findsong": self.ExecuteFindSong,
        }

        self.findSongRegex = re.compile(f"^findsong {groups.text}$")
Пример #11
0
    def __init__(self, chan, mongoClient):
        self.colLeaderboard = mongoClient.purebotdb[chan + "Leaderboards"]
        self.colLeaderboard.create_index([("user", pymongo.ASCENDING)])
        self.colLeaderboard.create_index([("score", pymongo.ASCENDING)])

        if not hasattr(botconfig, "scoreLifespan"):
            ptf("scoreLifespan not found in botconfig")
        if not hasattr(botconfig, "clearScoreId"):
            ptf("clearScoreId not found in botconfig")
        if not hasattr(botconfig, "stealScoreId"):
            ptf("stealScoreId not found in botconfig")
        if not hasattr(botconfig, "swapScoreId"):
            ptf("swapScoreId not found in botconfig")

        # Set expiration timer on collection documents
        self.colLeaderboard.create_index(
            [("_ts", pymongo.ASCENDING)],
            expireAfterSeconds=botconfig.scoreLifespan)

        self.scoreMin = -1
        self.scoreMax = 101

        self.activeCommands = {
            # snippet start
            # purecount
            "purecount": self.ExecutePureCount,

            # snippet start
            # pureboard
            "pureboard": self.ExecutePureBoard,

            # snippet start
            # curseboard
            "curseboard": self.ExecuteCurseBoard,

            # snippet start
            # clearboard
            # remarks
            # Mod Only. Clears leaderboard.
            "clearboard": self.ExecuteClearBoard,

            # snippet start
            # stealscore USER
            # stealscore BabotzInc
            # remarks
            # Requires spending sushi rolls. Only needed when you don't provide a name in the reward message.
            "stealscore": self.ExecuteStealScore,

            # snippet start
            # swapscore USER
            # swapscore BabotzInc
            # remarks
            # Requires spending sushi rolls. Only needed when you don't provide a name in the reward message.
            "swapscore": self.ExecuteSwapScore,
        }

        self.activeRewards = {
            botconfig.clearScoreId: self.RedeemClearScore,
            botconfig.stealScoreId: self.RedeemStealScore,
            botconfig.swapScoreId: self.RedeemSwapScore,
        }

        self.rewardStealId = "stealScore"
        self.rewardSwapId = "swapScore"

        self.redeemStealSwapScoreRegex = re.compile(f"^{groups.user}")
        self.stealScoreRegex = re.compile(f"^stealscore {groups.user}")
        self.swapScoreRegex = re.compile(f"^swapscore {groups.user}")
Пример #12
0
            return f"[{msg.user}]: Only mods and subs can add a quote"

        if (regMatch := self.quoteAddRegex.match(msg.message)) is None:
            return util.GetSyntax(msg.user, "quote add TEXT")

        try:
            result = self.colCounters.find_one_and_update(
                {"name": self.counterName}, {"$inc": {
                    "value": 1
                }},
                upsert=True)
        except TimeoutError:
            return f"[{msg.user}]: Server took too long"

        if result == None:
            ptf(f"Counter not found for {self.counterName}")
            return f"[{msg.user}]: Unable to add quote"

        quoteId = result["value"]

        if (gameName := GetGame()) is None:
            gameName = "[Unknown Game]"

        quoteText = regMatch.group("text")
        quoteText.strip("\"'")

        try:
            self.colQuotes.insert_one({
                "id": quoteId,
                "user": msg.user,
                "text": quoteText,
Пример #13
0
    def __init__(self, host, port, chan, nick, auth, callback, capability = None, live = False):
        assert type(host) == str and type(port) == int and (type(callback) == types.FunctionType or type(callback) == types.MethodType)
        threading.Thread.__init__(self)
        self.pingThread = threading.Thread(target=self.CheckPingAsync)
        self.name = "TwitchWebsocket"
        self._stop_event = threading.Event()

        # Variables
        self.host = host
        self.port = port
        self.chan = chan
        self.nick = nick
        self.auth = auth
        self.live = live
        self.callback = callback
        self.capability = capability

        self.data = str()

        # Lambda Functions.
        self.send_join = lambda message,    command="JOIN ": self._send(command, message)
        self.send_pong = lambda message="", command="PONG ": self._send(command, message)
        self.send_ping = lambda message="", command="PING ": self._send(command, message)
        self.send_nick = lambda message,    command="NICK ": self._send(command, message)
        self.send_pass = lambda message,    command="PASS ": self._send(command, message)
        self.send_part = lambda message,    command="PART ": self._send(command, message)
        self.send_req  = lambda message,    command="CAP REQ :twitch.tv/": self._send(command, message)
        self.send_message = lambda message, command="PRIVMSG ": self._send("{}{} :".format(command, self.chan.lower()), message) if self.live else ptf(message)
        self.send_whisper = lambda sender,  message: self.send_message(f"/w {sender} {message}")