示例#1
0
文件: bot.py 项目: f0ur0ne/vicky
class Vicky(irc.bot.SingleServerIRCBot):
    def __init__(self, channel, nickname, server, port=6667, enabled=[]):
        self.bot = irc.bot.SingleServerIRCBot.__init__(self, [(server, port)],
                                                       nickname, nickname)
        self.channel = Channel(users=[], name=channel)
        self.cm = CogManager()

    def run(self):
        # TODO pull default modules from config
        enabled_modules = ['kodictrl']
        self.cm.load_all(enabled_modules, bot=self)
        self.start()

    def sendmsg(self, msg: str, channel=None):
        # TODO split and send for long messages
        self.connection.privmsg(self.channel.name, msg)

    def on_nicknameinuse(self, client, event):
        client.nick(client.get_nickname() + "_")

    def on_welcome(self, client, event):
        client.join(self.channel.name)

    def on_join(self, c, event):
        print(event)
        # self.connection.privmsg(self.channel, "I have joined!")

    def on_namreply(self, c, event):
        self.gen_userlist()

    def on_nick(self, c, event):
        self.channel.setnick(event.source.nick, event.target)
        print(self.channel)

    def on_part(self, c, event):
        self.channel.remove(event.source.nick)

    def on_quit(self, c, event):
        self.channel.remove(event.source.nick)

    def on_privmsg(self, c, event):
        print(event)

    def on_pubmsg(self, c, event):
        # TODO pull prefixes from config
        prefix = ";"
        msg = Message(message=event.arguments[0],
                      user=self.channel.getuser(event.source.nick))
        # TEMP stick in a module after events are wired
        #        if "http" in msg.message:
        #            try:
        #                urlexpression = "http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"
        #                possible = re.findall(urlexpression, msg.message)
        #                req = get(possible[0])
        #                if req.status == 200:
        #                    soup = bs4(req.data, "html.parser")
        #                    if soup is not None:
        #                        try:
        #                            title = soup.title.string
        #                        except AttributeError as error:
        #                            pass
        #                        else:
        #                            self.sendmsg(title.strip())
        #            except:
        #                pass

        if msg.message.startswith(prefix):
            command = Command(prefix=prefix, data=msg)
            # TODO move these
            if command.name == "reload" or command.name == "load":
                if m := self.cm.import_module(command.message, self):
                    self.cm.add_cog(m, command.message, self)
                    self.sendmsg(f"{command.name}ed {command.message}")
                else:
                    self.sendmsg(f"failed to {command.name} {command.message}")
            elif command.name == "unload":
                if self.cm.unload(command.message):
                    self.sendmsg(f"unloaded {command.message}")
                else:
                    self.sendmsg(f"Could not unload {command.message}")
            elif command.name == "loaded":
                available = ", ".join(list(self.cm.modules.keys()))
                loaded = ", ".join(list(self.cm.cogs.keys()))

                self.sendmsg(f"Loaded: {loaded}")
                self.sendmsg(f"Available: {available}")
            else:
                self.cm.do_command(command)
        return
示例#2
0
class QuantumJumpBot:
    def __init__(self, settings):
        self._ws = None
        self.state = BotState(BotState.INITIALIZED)
        self.start_time = time.time()
        self.api = Http()
        self.cm = CogManager()
        self.settings = settings
        self.botconfig = self.settings.Bot
        self.ul = UserList()
        self.room = self.botconfig.roomname
        if self.settings.Bot.debug:
            self.log = QuantumLogger('QuantumJump', 10)
        else:
            self.log = QuantumLogger('QuantumJump', 19)

    async def wsend(self, data):
        if type(data) is list:
            data = f"42{json.dumps(data)}"
        elif type(data) is str:
            type_exemptions = ["2probe", "5", "2"]
            if not data.startswith("42") and data not in type_exemptions:
                data = f"42{data}"
        await self._ws.send(data)
        self.log.ws_send(data)

    async def run(self):
        enabled_modules = self.settings.Modules["enabled"]
        self.cm.load_all(enabled_modules, bot=self)
        await self.connect()

    async def disconnect(self):
        self.state = BotState.DISCONNECT
        await self._ws.close()

    async def connect(self):
        logged_in = await self.api.login(self.botconfig.username,
                                         self.botconfig.password)
        self.log.info(f"Logged in: {logged_in}")

        async with websockets.connect(
                uri=await self.api.get_wss(),
                timeout=600,
                origin="https://jumpin.chat") as self._ws:
            self.log.info("Connected to websocket.")
            self.state = BotState.RUNNING
            await self.wsend("2probe")
            async for message in self._ws:
                await self._recv(message=message)

    async def _recv(self, message: str):

        if message.isdigit():
            return
        self.log.ws_event(message)

        if message == "3probe":
            await self.wsend("5")
            roommsg = ["room::join", {"room": self.botconfig.roomname}]
            await self.wsend(roommsg)
            asyncio.create_task(self.pacemaker())
            return

        data = json.loads(message[2:])

        if data[0] == "room::status":
            msg = data[1].get("message")
            if "added a video to the playlist" in msg:

                ytid = re.search("(?:v=|\.be\/)(.{11})", msg)[1]
                myid = msg.split(' ')[0]
                title = msg.split('added a video to the playlist: ')[1]
                title = title.split('(https://')[0]

                #data = await self.endpoint(f"https://www.googleapis.com/youtube/v3/videos/?part=snippet%2CcontentDetails%2Cstatistics&id={ytid}",ytid)

                mydb = mysql.connector.connect(
                    host=
                    "gk90usy5ik2otcvi.cbetxkdyhwsb.us-east-1.rds.amazonaws.com",
                    user="******",
                    passwd="n9rgtn2meyhthi9t",
                    database="ppyh9hbf089e36w6")
                cursor = mydb.cursor()

                ids = ((ytid))
                myv = f"SELECT COUNT(*) as count FROM videos WHERE ytid LIKE '{ytid}'"
                add = f"""INSERT INTO videos (ytid, title) VALUES ('{ytid}', '{title}')"""
                our = "SELECT COUNT(*) as count FROM videos"

                cursor.execute(myv)
                myvideos = cursor.fetchone()[0]

                if myvideos == 0:
                    try:
                        cursor.execute(add, ids)
                        mydb.commit()
                        print(f"Added {title} to video.coder.ml/watch/{ytid}.")
                    except:
                        mydb.rollback()

                cursor.execute(our)
                allvids = cursor.fetchone()[0]
                print(f"{allvids} videos in cache.")

                mydb.close()

        if data[0] == "room::updateUserList":
            for user in data[1].get("users", []):
                if user:
                    self.ul.add(User(**user))
            if user := data[1].get("user", None):
                if user:
                    self.ul.add(User(**user))
        if data[0] == "room::updateUser":
            self.ul.update(User(**data[1].get("user", None)))

        if data[0] == "room::updateUsers":
            for user in data[1].get("users", []):
                self.ul.update(User(**user))

        #todo  update userlist when a name changes.
        if data[0] == "room::handleChange":
            # ["room::handleChange",{"userId":"5e22c017be8a4900076d3e21","handle":"Tech"}]
            pass
        if data[0] == "room::disconnect":
            self.ul.remove(User(**data[1].get("user", None)))

        if data[0] == "self::join":
            nickmsg = [
                "room::handleChange", {
                    "userId": self.api.login_data.user.get("userId"),
                    "handle": self.botconfig.nickname
                }
            ]
            await self.wsend(nickmsg)
            await self.wsend('42["room::users", {}]')

            # deprecated
            # user_list_data = await self.api.getroominfo(room=str(self.room))
            # self.ul = UserList(**user_list_data)
        if data[0] == "client::error":
            if error := data[1].get("error", False):
                if error == 'ERR_ACCOUNT_REQUIRED':
                    await self.disconnect()
                    raise Exception(
                        "Account must be signed in to join this room.")
                if error == 'ENOSESSION':
                    await self.disconnect()
                    raise Exception("Session was invalidated.")
示例#3
0
class QuantumJumpBot:
    def __init__(self, settings):
        self._ws = None
        self.state = BotState(BotState.INITIALIZED)
        self.start_time = time.time()
        self.api = Http()

        self.cm = CogManager()
        self.settings = settings
        self.botconfig = self.settings.Bot
        self.ul = UserList()
        self.room = self.botconfig.roomname
        if self.settings.Bot.debug:
            self.log = QuantumLogger('QuantumJump', self.room, 10)
        else:
            self.log = QuantumLogger('QuantumJump', self.room, 19)

    async def wsend(self, data):
        if type(data) is list:
            data = f"42{json.dumps(data)}"
        elif type(data) is str:
            type_exemptions = ["2probe", "5", "2"]
            if not data.startswith("42") and data not in type_exemptions:
                data = f"42{data}"
        self.log.ws_send(data)

        await self._ws.send(data)

    async def run(self):
        enabled_modules = self.settings.Modules["enabled"]
        self.cm.load_all(enabled_modules, bot=self)
        await self.connect()

    async def disconnect(self):
        self.state = BotState.DISCONNECT
        await self._ws.close()


    async def connect(self):
        logged_in = await self.api.login(self.botconfig.username,
                                          self.botconfig.password)
        async with websockets.connect(
                uri=await self.api.get_wss(),
                timeout=600,
                origin="https://jumpin.chat"
        ) as self._ws:
            self.log.info("Connected to websocket.")
            self.state = BotState.RUNNING
            await self.wsend("2probe")
            async for message in self._ws:
                await self._recv(message=message)

    async def _recv(self, message: str):
        if not message:
            return
        self.log.ws_event(message)

        if message.isdigit():
            return

        if message == "3probe":
            await self.wsend("5")
            roommsg = [
                "room::join",
                {"room": self.botconfig.roomname}
            ]
            await self.wsend(roommsg)
            asyncio.create_task(self.pacemaker())
            # await self.api.enroll()
            return

        data = json.loads(message[2:])

        if data[0] == "room::updateUserList":
            for user in data[1].get("users", []):
                if user:
                    self.ul.add(User(**user))
            if user := data[1].get("user", None):
                if user:
                    self.ul.add(User(**user))
        if data[0] == "room::updateUser":
            self.ul.update(User(**data[1].get("user", None)))

        if data[0] == "room::updateUsers":
            for user in data[1].get("users", []):
                self.ul.update(User(**user))

        # todo  update userlist when a name changes.
        if data[0] == "room::handleChange":
            # ["room::handleChange",{"userId":"5e22c017be8a4900076d3e21","handle":"Tech"}]
            pass
        if data[0] == "room::disconnect":
            self.ul.remove(User(**data[1].get("user", None)))

        if data[0] == "self::join":
            nickmsg = [
                "room::handleChange", {
                    "userId": self.api.login_data.user.get("userId"),
                    "handle": self.botconfig.nickname
                }
            ]
            await self.wsend(nickmsg)
            await self.wsend('42["room::users", {}]')

            # deprecated
            # user_list_data = await self.api.getroominfo(room=str(self.room))
            # self.ul = UserList(**user_list_data)
        if data[0] == "client::error":
            if error := data[1].get("error", False):
                if error == 'ERR_ACCOUNT_REQUIRED':
                    await self.disconnect()
                    raise Exception("Account must be signed in to join this room.")
                if error == 'ENOSESSION':
                    await self.disconnect()
                    raise Exception("Session was invalidated.")
示例#4
0
class QuantumJumpBot:
    def __init__(self, settings):
        self._ws = None
        self.state = BotState(BotState.INITIALIZED)
        self.start_time = time.time()
        self.api = Http()
        self.cm = CogManager()
        self.settings = settings
        self.botconfig = self.settings.Bot
        self.ul: UserList
        self.room = self.botconfig.roomname

    async def wsend(self, data):
        if type(data) is list:
            data = "42{}".format(json.dumps(data))
        elif type(data) is str:
            type_exemptions = ["2probe", "5", "2"]
            if not data.startswith("42") and data not in type_exemptions:
                data = f"42{data}"
        else:
            print("invalid data type for wsend")
        await self._ws.send(data)
        print(f"SEND {data}")

    async def run(self):
        enabled_modules = self.settings.Modules["enabled"]
        self.cm.load_all(enabled_modules, bot=self)
        await self.connect()

    async def disconnect(self):
        self.state = BotState.DISCONNECT
        await self._ws.close()

    async def connect(self):
        await self.api.login(self.botconfig.username,
                             self.botconfig.password)

        async with websockets.connect(
                uri=await self.api.get_wss(),
                timeout=600,
                origin="https://jumpin.chat"
        ) as self._ws:
            print("Socket started")
            self.state = BotState.RUNNING
            await self.wsend("2probe")
            async for message in self._ws:
                await self._recv(message=message)

    async def _recv(self, message: str):
        print(f"RECV {message}")
        if message.isdigit():
            return
        if message == "3probe":
            await self.wsend("5")
            roommsg = [
                "room::join",
                {"room": self.botconfig.roomname}
            ]
            await self.wsend(roommsg)
            asyncio.create_task(self.pacemaker())
            return

        data = json.loads(message[2:])
        await self.cm.do_event(data=data)
        if data[0] == "self::join":
            nickmsg = [
                "room::handleChange", {
                    "userId": self.api.login_data.user.get("user_id"),
                    "handle": self.botconfig.nickname
                }
            ]
            await self.wsend(nickmsg)
            user_list_data = await self.api.getroominfo(room=str(self.room))

            self.ul = UserList(**user_list_data)
        if data[0] == "client::error":
            if error := data[1].get("error", False):
                # todo logger
                # todo create an enum for different error codes.

                if error == 'ERR_ACCOUNT_REQUIRED':
                    # if we do not disconnect, spy mode becomes possible.
                    await self.disconnect()
                    raise Exception("Account must be signed in to join this room.")
                if error == 'ENOSESSION':
                    # if we do not disconnect, spy mode becomes possible.
                    await self.disconnect()
                    raise Exception("Session was invalidated.")

        if data[0] == "room::message":
            prefix = self.botconfig.prefix
            if data[1].get("message").startswith(prefix):
                data[1].update({"sender": self.ul.get(handle=data[1].get("handle"))})
                c = Command(prefix=prefix, data=Message(**data[1]))
                if c.name == "reload" or c.name == "load":
                    if m := self.cm.import_module(c.message, self):
                        self.cm.add_cog(m, c.message, self)
                        await self.wsend(
                            Message.makeMsg(message=f"{c.name}ed {c.message}",
                                            room=self.room))
                    else:
                        await self.wsend(
                            Message.makeMsg(message=f"failed to {c.name} {c.message}",
                                            room=self.room))
                if c.name == "unload":
                    if self.cm.unload(c.message):
                        await self.wsend(
                            Message.makeMsg(message=f"unloaded {c.message}",
                                            room=self.room))
                    else:
                        await self.wsend(
                            Message.makeMsg(message=f"Could not unload {c.message}",
                                            room=self.room))
                if c.name == "loaded":
                    await self.wsend(
                        Message.makeMsg(message=f"modules: {self.cm.modules}, cogs:{self.cm.cogs}",
                                        room=self.room))
                await self.cm.do_command(c)