Beispiel #1
0
    async def call(self, **kwargs):

        if not (hasattr(self.msg.guild, "voice_client")
                and self.msg.guild.voice_client):
            await self.respond(
                "I'm currently not in a voice channel on this server.", True)
            return

        targetChannel = self.msg.guild.voice_client.channel

        if not self.msg.author.voice.channel == targetChannel:
            await self.respond(
                "You have to be in my voice channel to play your voiceline!",
                True)
            return

        dir = os.listdir(SOUND_DIR + "voicelines")
        for i in dir:
            if os.path.isdir(SOUND_DIR + "voicelines/" + i) and i == str(
                    self.msg.author.id):  #we have a voiceline for this member
                files = os.listdir(SOUND_DIR + "voicelines/" + i)
                sound = FFMPEGSound(SOUND_DIR + "voicelines/" + i + "/" +
                                    random.choice(files))
                self.playSound(
                    sound, targetChannel, False
                )  #Don't sync member voicelines; this may be a bad idea...
                return
        await self.respond(
            "You don't have a voiceline associated with your user ID!", True)
        return
Beispiel #2
0
    async def call(self, **kwargs):

        if not (hasattr(self.msg.guild, "voice_client") and self.msg.guild.voice_client):
            await self.respond("I'm currently not in a voice channel on this server.",True)
            return

        dir = os.listdir(SOUND_DIR+"lucio")
        line = random.choice(dir)
        sound = FFMPEGSound(SOUND_DIR+"lucio/"+line)
        self.playSound(sound, self.msg.guild.voice_client.channel, False)
Beispiel #3
0
    async def on_voice_state_update(self, what, before, after):

        before_channel = before.channel
        after_channel = after.channel

        #Voice line handling
        if (after_channel and after_channel != before_channel): #if the user is connected and has changed his voice channel (this may mean he just joined)
            if what.guild.voice_client and (after_channel == what.guild.voice_client.channel): #we are in the same channel as our target

                #Use new dynamic voiceline handling (voicelines are compared by User ID / Filename instead of a dictionary lookup
                #This isn't necessarily any faster but it is more convenient and doesn't require a restart to assign voicelines
                dir = os.listdir(self.SOUND_DIR / "voicelines")
                for i in dir:
                    if os.path.isdir(self.SOUND_DIR / "voicelines" / i) and  i == str(what.id): #we have a voiceline folder for this member
                        files = os.listdir(self.SOUND_DIR / "voicelines" / i)
                        if not files: #no voicelines found, return
                            return
                        filepath = self.SOUND_DIR / "voicelines" / i / random.choice(files)
                        sound = FFMPEGSound(filepath.as_posix())
                        self.audio.playSound(sound, after_channel, sync=False)
                        return
Beispiel #4
0
    async def call(self, target, options=""):

        try:
            ch = self.msg.server.voice_client.channel
        except AttributeError:
            await self.respond("unable to play FFMPEG sound: Not connected to a voice channel on this server.", True)
            return

        try:
            snd = FFMPEGSound(target, shlex.split(options))
        except AudioError as e:
            await self.respond("unable to create FFMPEG sound instance: %s" % str(e), True)
            return

        try:
            self.playSound(snd, ch)
        except AudioError as e:
            await self.respond("unable to play FFMPEG sound on channel %s: %s" % (ch.name, str(e)), True)
            return

        await self.respond("Queued **%s**." % target)
Beispiel #5
0
    def playSound(self, sound, message):
        """
        Tries to play a sound in the server the message was sent from.
        If no sound backend is available, this method is a noop.
        """

        if not self.audioManager:
            return

        try:
            vc = message.guild.voice_client
            channel = vc.channel
        except AttributeError:
            return  #This is easier than LBYL

        if not (vc and channel):
            return

        sound = FFMPEGSound(sound)
        self.audioManager.playSound(sound, channel, True)
        return True
Beispiel #6
0
    async def call(self, query, **kwargs):

        loop = asyncio.get_event_loop()

        if not (hasattr(self.msg.guild, "voice_client")
                and self.msg.guild.voice_client):
            await self.respond(
                "I'm currently not in a voice channel on this server.", True)
            return

        targetChannel = self.msg.guild.voice_client.channel

        #LOCAL MUSIC FILES

        localquery = query.lower()  #make query string match all cases
        dir = os.listdir("tracks")
        for i in dir:
            if i.lower().rsplit(".")[0] == localquery:
                sound = FFMPEGSound("tracks/" + i)
                self.playSound(sound, targetChannel)
                await self.respond("Queued %s." % chatutils.mdItalic(i))
                return

        #YOUTUBE_DL

        if HAS_YTDL:

            #TODO: Currently, users could exploit the way the search engines work to add arbitrary query arguments to the HTTP call.
            #Fix this by escaping the query string if YTDL is to be used.

            if localquery.startswith("search "):
                q = query[7:]
                searchEngine = YouTubeSearch(
                    self.config.getElementText("google.api.token"))
                query = await self.search(q, searchEngine, 0xFF0000)
                if not query:
                    return

            elif localquery.startswith("youtube "):
                q = query[8:]
                searchEngine = YouTubeSearch(
                    self.config.getElementText("google.api.token"))
                query = await self.search(q, searchEngine, 0xFF0000)
                if not query:
                    return

            elif localquery.startswith("soundcloud "):
                q = query[11:]
                #Since SoundCloud doesn't allow new client applications right now,
                #we try to use the youtube_dl client ID (which may end up blocked or rate limited very fast)
                searchEngine = SoundCloudSearch(
                    self.config.getElementText("soundcloud.clientID",
                                               SoundcloudIE._CLIENT_ID))
                query = await self.search(q, searchEngine, 0xFF5500)
                if not query:
                    return

            #New playlist handling code
            #We need to do youtube_dl handling manually
            await self.respond("Looking for requested resource online...")
            yt = youtube_dl.YoutubeDL(YOUTUBE_DL_OPTIONS)
            try:
                self.logger.debug(
                    "Trying to extract youtube stream information...")
                func = functools.partial(yt.extract_info, query,
                                         **YOUTUBE_DL_EXTRACT_OPTIONS)
                info = await asyncio.get_event_loop().run_in_executor(
                    None, func)
            except:
                self.logger.exception("YTDL failed: ")
                await self.respond("Couldn't find a file matching your query.",
                                   True)
                return

            #consolidate single videos to pseudo playlists
            if "_type" in info and info["_type"] == "playlist":
                await self.respond(
                    "Playlist detected at source location, launching experimental playlist handling code.\nExamining source manifest..."
                )
                entries = info["entries"]
            else:
                entries = [info]

            listLength = len(entries)
            await self.respond("%i source %s found, downloading..." %
                               (listLength,
                                ("entries" if listLength > 1 else "entry")))
            i = 0
            for track in entries:
                i += 1
                self.logger.debug("Queuing entry %i of %i total: %s" %
                                  (i, listLength, track["webpage_url"]))

                url = track["url"]
                author = track["uploader"] if "uploader" in track else "Unknown"
                title = track["title"] if "title" in track else "Untitled"

                #this is necessary because the WebResourceSound downloads the target resource on instance creation.
                #Since this can take quite some time, the websocket can timeout before the sound is ready since the
                #program blocks because we can't await inside of a constructor.
                sound = await loop.run_in_executor(
                    None, lambda: WebResourceSound(
                        track["url"], author=author, title=title))
                self.playSound(sound, targetChannel)

            await self.respond("Queued %i track(s)." % i)
            return

        await self.respond("Couldn't find a file matching your query.", True)
        return
Beispiel #7
0
    async def call(self, channel, path, **kwargs):

        sound = FFMPEGSound(BASE_PATH + path)
        self.playSound(sound, channel, False)