A powerful Lavalink library for Discord.py.

Overview

logo.png?raw=true

https://api.codacy.com/project/badge/Grade/d020ed97fd2a46fcb1f42bd3bc397e63

A robust and powerful Lavalink wrapper for Discord.py!

Documentation

Official Documentation.

Support

For support using WaveLink, please join the official support server on Discord.

Discord

Installation

The following commands are currently the valid ways of installing WaveLink.

WaveLink requires Python 3.7+

Windows

py -3.7 -m pip install Wavelink

Linux

python3.7 -m pip install Wavelink

Getting Started

A quick and easy bot example:

import discord
import wavelink
from discord.ext import commands


class Bot(commands.Bot):

    def __init__(self):
        super(Bot, self).__init__(command_prefix=['audio ', 'wave ','aw '])

        self.add_cog(Music(self))

    async def on_ready(self):
        print(f'Logged in as {self.user.name} | {self.user.id}')


class Music(commands.Cog):

    def __init__(self, bot):
        self.bot = bot

        if not hasattr(bot, 'wavelink'):
            self.bot.wavelink = wavelink.Client(bot=self.bot)

        self.bot.loop.create_task(self.start_nodes())

    async def start_nodes(self):
        await self.bot.wait_until_ready()

        # Initiate our nodes. For this example we will use one server.
        # Region should be a discord.py guild.region e.g sydney or us_central (Though this is not technically required)
        await self.bot.wavelink.initiate_node(host='127.0.0.1',
                                              port=2333,
                                              rest_uri='http://127.0.0.1:2333',
                                              password='youshallnotpass',
                                              identifier='TEST',
                                              region='us_central')

    @commands.command(name='connect')
    async def connect_(self, ctx, *, channel: discord.VoiceChannel=None):
        if not channel:
            try:
                channel = ctx.author.voice.channel
            except AttributeError:
                raise discord.DiscordException('No channel to join. Please either specify a valid channel or join one.')

        player = self.bot.wavelink.get_player(ctx.guild.id)
        await ctx.send(f'Connecting to **`{channel.name}`**')
        await player.connect(channel.id)

    @commands.command()
    async def play(self, ctx, *, query: str):
        tracks = await self.bot.wavelink.get_tracks(f'ytsearch:{query}')

        if not tracks:
            return await ctx.send('Could not find any songs with that query.')

        player = self.bot.wavelink.get_player(ctx.guild.id)
        if not player.is_connected:
            await ctx.invoke(self.connect_)

        await ctx.send(f'Added {str(tracks[0])} to the queue.')
        await player.play(tracks[0])


bot = Bot()
bot.run('TOKEN')
Comments
  • TypeError: 'coroutine' object is not callable

    TypeError: 'coroutine' object is not callable

    I'm getting this error when I try and play music on using my discord bot.

    Task exception was never retrieved future: <Task finished name='Task-32' coro=<Websocket.process_data() done, defined at C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py:137> exception=TypeError("'coroutine' object is not callable")> Traceback (most recent call last): File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py", line 156, in process_data event, payload = await self._get_event_payload(data['type'], data) File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py", line 184, in get_event_payload track = await self.node.build_track(cls=wavelink.Track, identifier=base64) File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\pool.py", line 294, in build_track return cls(identifier, data) TypeError: 'coroutine' object is not callable Task exception was never retrieved future: <Task finished name='Task-39' coro=<Websocket.process_data() done, defined at C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py:137> exception=TypeError("'coroutine' object is not callable")> Traceback (most recent call last): File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py", line 156, in process_data event, payload = await self._get_event_payload(data['type'], data) File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\websocket.py", line 184, in get_event_payload track = await self.node.build_track(cls=wavelink.Track, identifier=base64) File "C:\Users\icep2\AppData\Local\Programs\Python\Python39\lib\site-packages\wavelink\pool.py", line 294, in build_track return cls(identifier, data) TypeError: 'coroutine' object is not callable

    Not a Bug 
    opened by Kaz213 15
  • Player.is_playing always returns False after track replace

    Player.is_playing always returns False after track replace

    Was broken in this commit: https://github.com/PythonistaGuild/Wavelink/commit/f126755662cdf17199b7814dbe4abcb5f038966b After first track has been replaced with Player.play(track), track_end event triggered after Player.play done. So, after first track replaced, Player._source is always None and Player.is_playing() always returns False.

    Consider changing code from commit above to something like this:

    if event == 'track_end' and payload.get('reason') == 'FINISHED':
        player._source = None
    
    opened by wladbelsky 7
  • Add support for

    Add support for "Session resuming" & "session data queueing".

    This PR is Implemented in #66

    Added New attributes

    • resume_session: bool
    • resume_timeout: float
    • resume_key: str (Best left None)
    • payload_timeout: float This is basically how recent requests shall be sent to the server
    • Websocket.reset() method.

    What are the new features?

    Websocket queueing.

    • Websocket._send() method now queues any data that is requested to be sent while the WS is disconnected.
    • New method Websocket.send_queue() which is called when connecting, and sends queue only when a session is resumed and Websocket is connected.
    • New exception NodeSessionClosedError raised when node closes a session or doesn't resume the old session. Handled within _connect method.

    Resuming

    • example of use of new features
    import string
    import secret
    class key:
        def __init__(self, len, first_key="NoSnoopingOnMyLava"):
            self.len = len
            self.persistent = first_key
    
        def __str__(self):
            return self.persistent
    
        def __repr__(self):
            """This should generate a key and shall make it persistent """
            self.persistent = SomeSecurePasswordGenerator(self.len)
            return self.persistent
    
    ---------------
    
     async def start_nodes(self) -> None:
        """Connect and intiate nodes."""
        nodes = {'MAIN': {'host': 'lavaserver.badhost.com',
                          'port': 80,
                          'rest_uri': 'http://lavaserver.badhost.com',
                          'password': "verytrivialpassword",
                          'identifier': 'MAIN',
                          'region': 'us_central',
                          'heartbeat': 40.0, # ping the server every 40s
                          'resume_session': True,
                          'resume_timeout': 90.0,
                          'resume_key': key(10) # or "Astring"
                          'payload_timeout': 40.0
                          }}
    
        for n in nodes.values():
            await self.bot.wavelink.initiate_node(**n)
    
    • or simply by setting 'resume_session': True
     async def start_nodes(self) -> None:
        """Connect and intiate nodes."""
        nodes = {'MAIN': {'host': 'lavaserver.badhost.com',
                          'port': 80,
                          'rest_uri': 'http://lavaserver.badhost.com',
                          'password': "verytrivialpassword",
                          'identifier': 'MAIN',
                          'region': 'us_central',
                          'resume_session': True
                          }}
    
        for n in nodes.values():
            await self.bot.wavelink.initiate_node(**n)
    

    Though the former has more use cases by using a Key Object we can:

    • Make the key persistent across Clusters
    • log the events, since __str__ is called when configuring the server, while __repr__ is called when the Node's session is closed to generate a new key.
    • To Generate a more secure password
    • Increase length of the password (The default is 32 characters)
    • Use

    How does resuming work?

    When the bot disconnects from the node (eg: 1006) then the lavalink server keeps on playing the music until session timeout, this allows the bot to reconnect and take control of the session. This PR implements this lavalink feature. The changes are not breaking, assuming no-one initializes Node instances directly.

    How does Queueing work?

    After the Node disconnects, we try to reconnect twice before timeout. during this time the requests to the node are queued in an asyncio.Queue subclass whose payload expires after some time. This could be useful when you have an higher timeout but want to only send recent requests

    opened by WizzyGeek 7
  • Add /decodetracks endpoint support

    Add /decodetracks endpoint support

    In addition to the Client/Node.build_track method, this adds the corresponding POST to /decodetracks to batch decode track identifiers. Useful if there are a large number of tracks that need to be decoded.

    The definition of the endpoint can be found here: https://github.com/Frederikam/Lavalink/blob/18ee6778674b7f9a817893b676a91a9b96e642f3/LavalinkServer/src/main/java/lavalink/server/player/AudioLoaderRestHandler.java#L140

    opened by james7132 6
  • AttributeError: '_MissingSentinel' object has no attribute 'guild'

    AttributeError: '_MissingSentinel' object has no attribute 'guild'

    Hi I am trying to make a setvolume command but I keep getting this error: AttributeError: '_MissingSentinel' object has no attribute 'guild'

    Code:

    @bot.command()
    async def setVolume(ctx, *, volume: float):
        vc = ctx.voice_client
        custom_player = CustomPlayer()
    
        if not vc:
            await ctx.send("I ain't in a vc bro")
        else:
            await custom_player.set_volume(volume=volume)
    opened by Necrosis000 5
  • Is there a better way to play a local file?

    Is there a better way to play a local file?

    I've finally got playing a local file (to lavalink) from the bot. (No more ffmpeg)

    I'm Just throwing this out here as a general question:

    is there a better way to search for a Local Track? I see SearchableTrack, having a return_first=true. Just trying to get my head around the API. Any help is apperciated?

    @slash_command(name="lplay", description="Play some local music or SFX") async def lplay(self, inter: Interaction, search): path = "/media/" + search
        search = wavelink.PartialTrack(query=path, cls=wavelink.LocalTrack)
    
        if inter.user.voice is None:
            return await inter.send(f'You are not connected to any voice channel!')
    
        # If the bot isn't in a voice channel
        if not inter.guild.voice_client:
            vc: wavelink.Player = await inter.user.voice.channel.connect(cls=wavelink.Player)
        else:
          #See if the bot is in another channel
          if inter.guild.voice_client.channel != inter.user.voice.channel:
            await inter.guild.voice_client.move_to(inter.user.voice.channel) 
            await inter.send(f'Connected to {inter.user.voice.channel}.')
            
        vc: wavelink.Player = inter.guild.voice_client
       
        try: 
           await vc.play(search)
           await inter.send(f'Playing {search.title}')
        except:
           await inter.send(f'{path} Not found!') 
    
    opened by Mudpuppy12 4
  • queue error please help

    queue error please help

    @bot.event async def on_wavelink_track_end(player: wavelink.Player, track: wavelink.Track, reason): ctx = player.ctx vc: player = ctx.voice_client if vc.loop: return await vc.play(track) next_song = vc.queue.get() await vc.play(next_song) await ctx.send(f"Now playing {next_song.title}")

    • File "/home/container/discord-bot/main.py", line 118, in on_wavelink_track_end next_song = vc.queue.get() File "/home/container/.local/lib/python3.10/site-packages/wavelink/queue.py", line 212, in get raise QueueEmpty("No items in the queue.") wavelink.errors.QueueEmpty: No items in the queue.
    opened by slefgameRz 4
  • wavelink.Player.connect incompatibility with Discord.py 2.0

    wavelink.Player.connect incompatibility with Discord.py 2.0

    Discord.py 2.0 introduced a new self_deaf and self_mute parameter to the connect method. This causes TypeError: Player.connect() got an unexpected keyword argument 'self_deaf'

    opened by Luc1412 4
  • module 'wavelink' has no attribute 'client'

    module 'wavelink' has no attribute 'client'

    Traceback (most recent call last): File "/Users/admin/Desktop/Cogs/music1.py", line 272, in bot = Bot() File "/Users/admin/Desktop/Cogs/music1.py", line 22, in init self.add_cog(Music(self)) File "/Users/admin/Desktop/Cogs/music1.py", line 69, in init self.bot.wavelink = wavelink.Client(bot=self.bot) AttributeError: module 'wavelink' has no attribute 'Client'

    opened by sanjaysanooj22 4
  • v1.2.0 No Longer Supports Python Version 3.8

    v1.2.0 No Longer Supports Python Version 3.8

    In the newest version (v1.2.0), the implementation of the YouTube Playlist searching has removed support for Python Version 3.8. The use of the method .removeprefix() is a python 3.9+ feature.

    The line in question: https://github.com/PythonistaGuild/Wavelink/blob/8a4fb12404a5e908bd7a22ecba1ace7dc950d73f/wavelink/tracks.py#L187

    PEP 616: String methods to remove prefixes and suffixes https://www.python.org/dev/peps/pep-0616/

    If this is intentional to remove Python 3.8 version, then please can the documentation be updated. Otherwise, an implementation to get around this could be:

    def removePrefix(url, prefix):
        if string.startswith(prefix):
            return string[len(prefix):]
        else:
            return string
    
    opened by TwoSails 4
  • [Suggestion] Advanced exmple

    [Suggestion] Advanced exmple

    Hello, Wavelink is working good but in my opinion there a a few missing things:

    • loop song & queue
    • lyrics command
    • pitch (1.00 standard 5.00 max)
    • option to keep the bot into the voicechannel even if nothing is playing.
    opened by FeelsBadMan1 4
  • Add payload_args optional argument to the play method in player.py

    Add payload_args optional argument to the play method in player.py

    This argument allows the user to pass arguments which will be directly sent to Lavalink in the play method. This gives the ability to interact with Lavalink plugins

    opened by Rajdave69 0
  • getting this error on 2.0

    getting this error on 2.0

    File "/home/subrata/Wavelink/wavelink/node.py", line 106, in <genexpr>
        version_tuple = tuple(int(v) for v in version.split('.'))
    ValueError: invalid literal for int() with base 10: 'c597fb10d9d323a174b69efa66fcebd616fb3f1e-SNAPSHOT_Unofficial'
    
    bug 2.0 
    opened by Subrata2402 0
  • Update pool.py

    Update pool.py

    Fixed bug with 'wavelink.NodePool.get_node(region="rotterdam")' raise ZeroConnectedNodes(f "No Nodes for region <{region}> exist on this pool."), although there is at least one node with this region.

    opened by Marco12223 1
  • Player running endless (without sound)

    Player running endless (without sound)

    I currently play an MP3 on the lavalink server in a loop. The loop has been accomplished by following code.

    @commands.Cog.listener(name="on_wavelink_track_end")
        async def _on_track_end(self, player: RadioPlayer, track: wavelink.Track, reason: str):
            if reason != 'FINISHED':
                return
            await player.play(track)
    

    This transition works fine so far. I also added on_wavelink_track_exception and on_wavelink_track_stuck for debug reasons, but both won't get triggered.

    I experience that the player randomly stops playing. The client is still connected. The player got is_connected() and is_playing() set to True. But when checking the position it got an inappropriate high number set.

    My track is about an hour long, but postion is set to 21h in seconds.

    Pausing and resuming resumes the playback.

    opened by Luc1412 0
  • cant search for youtube playlist

    cant search for youtube playlist

    I try to use wavelink.YouTubePlaylist to search for youtubeplaylist and I get error

    code @commands.command(aliases=['P', 'PLAY', 'Play','p']) async def play(self,ctx: commands.Context, *, search:wavelink.YouTubePlaylist): print(search)

    error Ignoring exception in on_message Traceback (most recent call last): File "C:\Python3.10\lib\site-packages\discord\ext\commands\core.py", line 456, in _actual_conversion ret = await method(ctx, argument) File "C:\Python3.10\lib\site-packages\wavelink\tracks.py", line 218, in convert return results[0] TypeError: 'YouTubePlaylist' object is not subscriptable

    Did i miss something?

    and also sorry for my bad English

    opened by tunwit 2
Releases(v1.3.4)
  • v1.3.4(Dec 22, 2022)

  • v1.3.3(Oct 4, 2022)

  • v1.3.2(Jul 10, 2022)

  • v1.3.1(Jun 6, 2022)

  • v1.3.0(Jun 6, 2022)

    Implemented Lavalink Filters, some documentation can be found here: https://wavelink.readthedocs.io/en/latest/wavelink.html#filters This is still a WIP.

    Fixed an issue with YouTubePlaylist converter failing. Bumped aiohttp inline with discord.py

    Source code(tar.gz)
    Source code(zip)
  • v1.2.5(Apr 22, 2022)

  • v1.2.4(Mar 21, 2022)

  • v1.2.3(Mar 21, 2022)

  • v1.2.2(Mar 13, 2022)

  • v1.2.1(Mar 10, 2022)

  • v1.2.0(Mar 7, 2022)

  • v1.1.1(Feb 8, 2022)

  • v1.1.0(Feb 4, 2022)

  • v1.0.2(Jan 24, 2022)

  • v1.0.1(Jan 24, 2022)

  • v1.0.0(Jan 24, 2022)

    Wavelink 1.0.0

    This release is a whole rewrite of the library. It supports discord.py 2.0 and some derivatives.

    See the documentaion for more info and examples. Documentation

    If the documentation is still displaying as the old version, please clear your cache.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.10(Jul 13, 2021)

  • v0.9.9(Mar 8, 2021)

  • v0.9.8(Feb 25, 2021)

    Add force keyword argument to Node.destroy() and Player.destroy()/disconnect(). This prevents a bug from occuring when a player is being destroyed, and the bot is no longer apart of the Guild the player was associated with.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.7(Feb 23, 2021)

  • v0.9.6(Sep 9, 2020)

    Fix a bug in player setting current track to None on TrackStuck and TrackException.

    Since Lavalink sends two events on Exceptions, an End and Exception event this causes a possible race condition in the player, setting the current Track to None when one is actually playing.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.5(Sep 5, 2020)

    Added Exponential Backoff attempts to get_tracks. Retrieving tracks will now by default retry on failure up to a maximum of 5 attempts with an Exponential Backoff. You can set this to False with the kwarg retry_on_failure=False, which will only attempt to retrieve tracks once.

    Added support for custom JSON Encoders.

    Changed YouTube's Track Image to hqdefault, in place of maxresdefault.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.4(Aug 5, 2020)

    Changes to Equalizer which allow for construction without the build() classmethod.

    Added name parameters to the build() classmethod and Equalizer constructor to allow setting a custom name.

    Added a name property to Equalizer. Setting the name should be done by constrcutor or the build() classmethod

    Added __str__ and __repr__ to Equalizer.

    Fixed a bug where set_eq was setting a blank Equalizer class on the player.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.3(Jul 30, 2020)

  • v0.9.2(Jun 20, 2020)

    Add heartbeat to node and websocket.

    This stabilizes connection to Nodes hosted on a VPS with a router or any such intermediate process that closes the connection if it remains idle. Which puts the bot in a "reconnection" loop.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.1(Jun 20, 2020)

  • v0.9.0(Jun 8, 2020)

    Added wavelink.WavelinkMixin to be used in conjunction with a discord.py commands.Cog. This class allows for the registration of the new wavelink listeners:

    on_node_ready on_track_start on_track_end on_track_stuck on_track_exception on_websocket_closed

    All listeners must be decorated with the wavelink.WavelinkMixin.listener() decorator. All listeners must be in a wavelink.WavelinkMixin class. Listeners can be stacked.

    Docs

    Event Payloads WavelinkMixin

    Example

    class Music(commands.Cog, wavelink.WavelinkMixin):
        
        @wavelink.WavelinkMixin.listener()
        async def on_node_ready(self, node):
            print(f'Node {node.identifier} is ready!')
    
    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(May 18, 2020)

  • v0.7.2(May 16, 2020)

  • v0.7.1(May 2, 2020)

Owner
Pythonista
Organisation for the Pythonista Guild
Pythonista
A fork of lavalink.py built for nextcord

nextcord-ext-lava is a wrapper for Lavalink which abstracts away most of the code necessary to use Lavalink, allowing for easier integration into your projects, while still promising full API coverage and powerful tools to get the most out of it.

nextcord-ext 4 Feb 27, 2022
A simple and easy to use musicbot in python and it uses lavalink.

Lavalink-MusicBot A simple and easy to use musicbot in python and it uses lavalink. ✨ Features plays music in your discord server well thats it i gues

Afnan 1 Nov 29, 2021
Represents a Lavalink client used to manage nodes and connections.

lavaplayer Represents a Lavalink client used to manage nodes and connections. setup pip install lavaplayer setup lavalink you need to java 11* LTS or

HazemMeqdad 37 Nov 21, 2022
A Advanced Powerful, Smart And Intelligent Group Management Bot With New And Powerful Features

Vegeta Robot A Advanced Powerful, Smart And Intelligent Group Management Bot With New And Powerful Features ... Written with Pyrogram and Telethon...

⚡ CT_PRO ⚡ 9 Nov 16, 2022
⚡ A really fast and powerful Discord Token Checker

discord-token-checker ⚡ A really fast and powerful Discord Token Checker How To Use? Do pip install -r requirements.txt in your command prompt Make to

vida 25 Feb 26, 2022
A Powerful Discord Webhook spammer

RocketHook | The discord spammer Some links: Telegram | Github FEATURES ?? Hide your ass and be a good robot ! Full proxies support HTTP/S, SOCKS4/5 S

Or 2 Feb 27, 2022
A powerful discord bot for forming team.

Discord_SquadBot A powerful discord bot for forming team. Pre-requirement Python 3.7 and latest Discord.py module is required. Installation guideline

Jacky Yu 2 Jan 29, 2022
It's a Discord bot to control your PC using your Discord Channel or using Reco: Discord PC Remote Controller App.

Reco PC Server Reco PC Server is a cross platform PC Controller Discord Bot which is a modified and improved version of Chimera for Reco-Discord PC Re

Arvinth Krishna 12 Aug 31, 2022
A small and fun Discord Bot that is written in Python and discord-interactions (with discord.py)

Articuno (discord-interactions) A small and fun Discord Bot that is written in Python and discord-interactions (with discord.py) Get started If you wa

Blue 8 Dec 26, 2022
Satoshi is a discord bot template in python using discord.py that allow you to track some live crypto prices with your own discord bot.

Satoshi ~ DiscordCryptoBot Satoshi is a simple python discord bot using discord.py that allow you to track your favorites cryptos prices with your own

Théo 2 Sep 15, 2022
Discord bot script for sending multiple media files to a discord channel according to discord limitations.

Discord Bulk Image Sending Bot Send bulk images to Discord channel. This is a bot script that will allow you to send multiple images to Discord channe

Nikola Arbov 1 Jan 13, 2022
DeKrypt 24 Sep 21, 2022
MusicBot is the original Discord music bot written for Python 3.5+, using the discord.py library

The original MusicBot for Discord (formerly SexualRhinoceros/MusicBot)

Just Some Bots 2.9k Jan 2, 2023
This is a tutorial on how to make a Discord Bot using the discord.py library

HowToMakeADiscordBot This Github repository is here to help you code a Discord Bot using the discord.py library! 1 - Setup: Download the code inside t

Baz 1 Oct 31, 2021
Discord bot ( discord.py ), uses pandas library from python for data-management.

Discord_bot A Best and the most easy-to-use Discord bot !! Some simple basic auto moderations, Chat functions. It includes a game similar to Casino, g

Jaitej 4 Aug 30, 2022
Some random bot for Discord which was created just for fun (Made with Discord.py library)

Ghosty Previously known as 'secondthunder-py-bot' This is repository of some random bot for Discord which was created just for fun and for some educat

Владислав 8 Oct 2, 2022
Kevin L. 3 Jul 14, 2022
Powerful Telegram Members Scraping and Adding Toolkit

?? Genisys V2.1 Powerful Telegram Members Scraping and Adding Toolkit ?? Features ?? ADDS IN BULK[by user id, not by username] Scrapes and adds to pub

The Cryptonian 16 Mar 1, 2022
Advanced and powerful Userbot written with telethon. ♥

Daisy-X-UB ☣️ The Most Super Powerfull UserBot ☣️ ⚡ †hê ∂αιѕу χ ⚡ Legendary AF Ꭰαιѕу χ This is a userbot made for telegram. I made this userbot with h

TeamDaisyX 31 Jul 30, 2021