Skip to content

Commit

Permalink
4.0.0 (#126)
Browse files Browse the repository at this point in the history
* Fix dispatching to empty hook lists

* Bump version

* Bump aiohttp

* Update license stuff

* Fix CI badge

* Fix broken doc ref

* support new lavalink exception format (#105)

* Making a note of this issue

* Bump aiohttp upper version

* Bump Lavalink.py to 3.1.5

* Update dev to Lavalink.py 4.0 (#121)

* Rename some errors, support Union[int, str] for user_id

* Expose AuthenticationError

* Ambiguous no more

* Update get_tracks returns

* Fix dispatching to empty hook lists

* Bump aiohttp

* Fix slight mistake in example cog.

* Readme QoL change.

* Use a link reference instead

* Start on filter stuff

* Update license stuff

* Fix CI badge

* Fix broken doc ref

* Finishing up filter stuff maybe

* Specify decode_errors when decoding author too

* Exceptions -> Errors, more reliably pull WS close code, handle ConnectionResetError

* Didn't mean to push this loool

* Add utfm decoding capabilities

* Fix equalizer failing to serialize

* forgot an await, oops

* Reorder player_manager funcs

* Fix docs & expand parameter names

* Update Lavalink URL

* Fix Python 3.5 support not displayed in badge (#109)

lol

* Update example to use voice client (#116)

* Update example to use voice client

discord.py 2.0 removed the `on_socket_response` event. This resulted in
Lavalink.py not being able to forward the events. At least in the
current implementation of the example.
We now use the preferred way of using the VoiceProtocol to forward the
voice events to Lavalink.

* Set player.channel_id to None manually

* support new lavalink exception format (#105)

* Bump min aiohttp version

* Update copyright

* who did this

* Update license 2

* Making a note of this issue

* Bump aiohttp upper version

* Slight adjustments to strings

* Expose previously unused variables 'position' and 'encoder_version'

* Clarify some units in Stats.py

* Logging message consistency

* Remove superfluous log call in _node_disconnect

* Logging consistency

* Init node with empty stats object

* scheisse

* Redundant logic check as this will be zero anyway

* int() guild_id in create, add doc link to DefaultPlayer

* Doc consistency in playermanager.py

* Document player.channel_id attr

* More documentation updates

* Finalise guild_id -> int change

* Lavalink.py v4.0.0

* 0.0 is the default gain

* Add timestamp_to_millis helper function.

* Linting

* Register auto docs for new things

* Minor docs changes again

* How much other stuff is missing???

* cmon

* Fixing docs build error

* Add filter limits, allow passing str to Player.X_filter, add filter TODOs

* Fix docs formatting

* Add missing list call

* Avoid handling TrackStartEvent to prevent None being fired

* Rotation filter

* Low Pass filter

* Add channelmix + lint

* Add missing __ to init

* Add filter command to example cog.

* Lavalink appears to have exception handling for this...

* Mark set_gain(s) & reset_equalizer as deprecated, add docs for remove_filter.

* Enlarge deprecation warning

* Move deprecation warning last to ensure func summary still works as intended

* Distortion filter

* Lint

* New year new me xx

* doc stuff

* forgot to cd out of docs/

* update readme badge

* Support volume filter

* Enforce 0 < volume < 5

* Support connected in PlayerUpdateEvent

* Linting

* Small cleanups

* new codacy badge

* Implement DeferredAudioTrack

* Linting

* Imports & docs

* Custom source support

* Implement hash for source

* Implement handling for info attribute access in AudioTrack

* More docstrings, a little more consistency

* Clarify docs.

* Adjust player.add parameters, docs

* Fix an issue with track needing to be declared, improve compatibility

* Oversight

* Implement two more docstrings in Client.

* Custom Source provider example

* If check to avoid returning bogus track on every query.

* Enum documentation

* missing ,

* self._raw in AudioTrack

* slotssssssss

* lets gloss over this ok

* Copy-paste RIP

* Fix typo in custom_source.py

* Add player.destroy shortcut

* Reluctantly support passing AudioTrack to AudioTrack

* Don't overwrite requester

* Remove AudioTrack construction from example cog

* Access attributes directly in example cog

* Filter descriptions.

* an -> a

* Support position + sourceName fields

* Correctly reflect that track is Optional

* Close any existing websockets before connecting

* support volume + pause in play op

* Fix volume not having an immediate effect

* Add @lavalink.listener decorator support

* Clarify listener decorator

* forgot to cd out of docs again lol

* Add player.update_filter, improve docs

* Ensure provided filter is a class not instance

* Instances passed to issubclass will throw, catch that.

* subclass check in other x_filter commands

* Add custom source to README

* Updating readme

* Reducing duplicated code in client

* Fixing a slight oversight

* Sorting out comment lines a little lol

* Remove unused import from example/music.py

* Experimental command-line tools

* Support SSL on nodes

* Use pythonic naming

* Add clear_filters()

* Only apply endTime if > 0

* On second thoughts, move endTime check AFTER sanity check

Co-authored-by: AlexFlipnote <[email protected]>
Co-authored-by: sh0tx420 <[email protected]>
Co-authored-by: Eric Schneider <[email protected]>
Co-authored-by: Rob Wainwright <[email protected]>

* 3 attempts -> max_attempts_str

* missing await

* Attempt fix for already connected errors

* Rearrange README and document custom sources

* Link to Lavaplayer repo

* Remove use of endpoint as guild.region is deprecated

* Fixing literals

* Fixing more literals

* fix func reference

* use voice_client for channel comparison

* Make force an optional argument

* Update VoiceProtocol for latest discord.py change (#123)

* Implement TrackLoadFailedEvent for DAT errors

* Add LoadError

* Remove this

* Single track looping

* Experimental fix for double VU dispatching

* Don't pop event, compare session IDs

* Log event type received

* More typings, implement repr on some models

* Log the connection error if it's not handled

* Switch to logginb.exception to automatically attach the exc

* Refactor logging

* Remove debugging line

* VSC didn't save this one, either

* Remove module name from log msg

* Correctly label async methods as |coro|

* Add plugin support (#124)

* Add support for getting plugins

* Doc for plugins

* remove dataclass for py3.5 and return List[Plugin]

* POST is not GET

* changed the wrong line 👍👍👍

* repr for plugin

* plugin str

* cleanups

* Move node-specific functions to Node.py

* Fix typo in logging format

* Expose Plugin in init

* Support check_local in node.get_tracks

* Update docs

* Fix documentation for repeat & loop class attrs

* Document DefaultPlayer.loop attr

* Fix reconnect attempts logic

* Allow returning of connect future

* Node.destroy() + docs update

* hello vsc save?????????

* Allow enabling debug logging for specific submodules

* pushed w/o linting? fatherless behaviour

* should not be async

* fix parameter description

* Enforce minimum for lowpass

* Enforce a minimum of zero instead

* Actually, enforce no minimum to remain consistent with Lavalink server.

* Should be fine now.

* Remove async from get_filter

* Update docs

* Avoid logging non-existent player if event of specific type(s)

* didn't end up using this lol

* Improve documentation

* Implement entry point for playing tracks with custom player implementations

* Update play docstring

* Move requester into AudioTrack.extra

* Check start_time & end_time before setting self.current

* Fix: return if no_replace to prevent self.current mismatch

* Bug fixes in models.py (#125)

* Fix bugs

Corrects the requester and also fixes start_time and end_time

* oops

* Fixed bugs

Corrected requester and also fixed start_time and end_time

* Add node_unavailable() to BasePlayer, pause position clock during node unavailability

* Remove misplaced abstractmethod decorator

* (AudioTrack) avoid placing source in extra.

* Correctly extract sourceName for AudioTracks

Co-authored-by: Rob Wainwright <[email protected]>
Co-authored-by: AlexFlipnote <[email protected]>
Co-authored-by: sh0tx420 <[email protected]>
Co-authored-by: Eric Schneider <[email protected]>
Co-authored-by: Danny <[email protected]>
Co-authored-by: cdwpx <[email protected]>
  • Loading branch information
7 people authored Aug 18, 2022
1 parent 685cca2 commit 68ac818
Show file tree
Hide file tree
Showing 27 changed files with 2,726 additions and 627 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 Luke & William
Copyright (c) 2017-present Devoxin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
35 changes: 20 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
[Lavalink]: https://github.com/freyacodes/Lavalink
[Lavaplayer]: https://github.com/sedmelluq/lavaplayer
[Documentation]: https://lavalink.readthedocs.io/en/master/
[Latest Docs]: https://lavalink.readthedocs.io/en/latest/

<img align="right" src="https://serux.pro/9e83af1581.png" height="150" width="150">

# Lavalink.py
[![Python](https://img.shields.io/badge/Python-3.5%20%7C%203.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue.svg)](https://www.python.org) [![Build Status](https://travis-ci.com/devoxin/Lavalink.py.svg?branch=master)](https://travis-ci.com/Devoxin/Lavalink.py) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/428eebed5a2e467fb038eacfa1d92e62)](https://www.codacy.com/gh/Devoxin/Lavalink.py/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=Devoxin/Lavalink.py&amp;utm_campaign=Badge_Grade) [![License](https://img.shields.io/github/license/Devoxin/Lavalink.py.svg)](LICENSE) [![Documentation Status](https://readthedocs.org/projects/lavalink/badge/?version=latest)](https://lavalink.readthedocs.io/en/latest/?badge=latest)

Lavalink.py 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.

Lavalink.py is a wrapper for [Lavalink](https://github.com/freyacodes/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.
## Features
- Regions
- Multi-Node Support
- Load Balancing (this includes region-based load balancing)
- Audio Filters
- [Custom Sources](examples/custom_source.py)


# What is Lavalink?
Lavalink is standalone audio sending software capable of transmitting audio to Discord, utilising [Lavaplayer] for audio transcoding. It can be configured to work independently, or as part of a cluster depending on needs, which allows it to be highly scalable and performant. Head over to the [Lavalink] repository to find out more.


# Getting Started
First you need to run a command to install the library,
Expand All @@ -19,18 +34,9 @@ Then place an ``application.yml`` file in the same directory. The file should lo
Additionally, there is an [example cog](examples). It should be noted that the example cog is oriented towards usage with Discord.py rewrite and Lavalink v3.1+, although backwards
compatibility may be possible, it's not encouraged nor is support guaranteed.

## Features
- Regions
- Multi-Node Support
- Load Balancing (this includes region-based load balancing)
- Equalizer

## Optional Dependencies
*These are used by aiohttp.*

`aiodns` - Speed up DNS resolving.

`cchardet` - A faster alternative to `chardet`.
## Custom Sources
As of Lavalink.py 4.0, custom sources can be registered to a client instance to allow searching more audio sources. These aren't "true" sources in the sense that you can play from them (unless you support HTTP playback and are able to retrieve a playable HTTP URL).
This means you can build sources that allow retrieving track metadata from third party services, such as Spotify, whilst the underlying stream is played from elsewhere. This is a popular method for providing support for otherwise unsupported services. You can find an [example source here](examples/custom_source.py).

## Supported Platforms
While Lavalink.py supports any platform Python will run on, the same can not be said for the Lavalink server.
Expand All @@ -40,8 +46,7 @@ It is highly recommended that you invest in a dedicated server or a [VPS](https:
### Exceptions
The exception to the "unsupported platforms" rule are ARM-based machines, for example; a Raspberry Pi. While official Lavalink builds do not support the ARM architecture, there are [custom builds by Cog-Creators](https://github.com/Cog-Creators/Lavalink-Jars/releases) that offer ARM support. These are the official builds, with additional native libraries for running on otherwise unsupported platforms.


## Need Further Help?
[Discord Server](https://discord.gg/SbJXU9s)

[Documentation](https://lavalink.readthedocs.io/en/latest/)
[Documentation] or [Latest Docs]
20 changes: 19 additions & 1 deletion docs/_static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,22 @@

code {
padding: 0px !important;
}
}

div.deprecated {
margin: 20px 0;
padding: 20px;
background-color: #fff;
border-radius: 3px;
color: #333;
overflow: auto;
border-width: 0 0 0 2px;
border-color: #ff5858;
border-style: solid;
padding-right: 0;
}

span.deprecated {
display: block;
font-size: large;
}
4 changes: 3 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# -- Project information -----------------------------------------------------

project = 'Lavalink.py'
copyright = '2021, Devoxin'
copyright = '2022, Devoxin'
author = 'Devoxin'
master_doc = 'index'

Expand All @@ -41,6 +41,7 @@
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'guzzle_sphinx_theme',
'enum_tools.autoenum'
]

rst_prolog = """
Expand Down Expand Up @@ -88,6 +89,7 @@
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = ['style.css']

# html_context = {
# 'css_files': ['_static/style.css']
Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Welcome to Lavalink.py's documentation!
- Regions
- Multi-Node Support
- Load Balancing (this includes region-based load balancing)
- Equalizer
- Audio Filters

**Support:**

Expand Down
82 changes: 76 additions & 6 deletions docs/lavalink.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,23 @@ Documentation

.. autofunction:: enable_debug_logging

.. autofunction:: listener

.. autofunction:: add_event_hook

Client
------
.. autoclass:: Client
:members:

Errors
------
.. autoclass:: NodeError

.. autoclass:: AuthenticationError

.. autoclass:: InvalidTrack

Events
------
All Events are derived from :class:`Event`
Expand All @@ -22,43 +32,101 @@ All Events are derived from :class:`Event`
.. autoclass:: TrackStartEvent
:members:

.. autoclass:: TrackEndEvent
:members:

.. autoclass:: TrackStuckEvent
:members:

.. autoclass:: TrackExceptionEvent
:members:

.. autoclass:: TrackEndEvent
:members:

.. autoclass:: TrackLoadFailedEvent
:members:

.. autoclass:: QueueEndEvent
:members:

.. autoclass:: NodeConnectedEvent
.. autoclass:: PlayerUpdateEvent
:members:

.. autoclass:: NodeChangedEvent
.. autoclass:: NodeConnectedEvent
:members:

.. autoclass:: NodeDisconnectedEvent
:members:

.. autoclass:: NodeChangedEvent
:members:

.. autoclass:: WebSocketClosedEvent
:members:

Filters
-------
**All** custom filters must derive from :class:`Filter`

.. autoclass:: Filter
:members:

.. autoclass:: Equalizer
:members:

.. autoclass:: Karaoke
:members:

.. autoclass:: Timescale
:members:

.. autoclass:: Tremolo
:members:

.. autoclass:: Vibrato
:members:

.. autoclass:: Rotation
:members:

.. autoclass:: LowPass
:members:

.. autoclass:: ChannelMix
:members:

.. autoclass:: Volume
:members:

Models
------
**All** custom players must derive from :class:`BasePlayer`

.. autoclass:: AudioTrack
:members:

.. autoclass:: DeferredAudioTrack
:members:

.. autoenum:: LoadType
:members:

.. autoclass:: PlaylistInfo
:members:

.. autoclass:: LoadResult
:members:

.. autoclass:: Source
:members:

.. autoclass:: BasePlayer
:members:

.. autoclass:: DefaultPlayer
:members:

.. autoclass:: Plugin
:members:

Node
----
.. autoclass:: Node
Expand All @@ -84,8 +152,10 @@ Stats

Utilities
---------
.. autofunction:: timestamp_to_millis

.. autofunction:: format_time

.. autofunction:: parse_time

.. autofunction:: decode_track
.. autofunction:: decode_track
2 changes: 1 addition & 1 deletion docs/license.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Licensed using the `MIT license <https://opensource.org/licenses/MIT>`_.

MIT License

Copyright (c) 2021 Luke & William
Copyright (c) 2022 Devoxin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
45 changes: 45 additions & 0 deletions examples/custom_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from lavalink.models import (DeferredAudioTrack, LoadResult, LoadType,
PlaylistInfo, Source)


class LoadError(Exception): # We'll raise this if we have trouble loading our track.
pass


class CustomAudioTrack(DeferredAudioTrack):
# A DeferredAudioTrack allows us to load metadata now, and a playback URL later.
# This makes the DeferredAudioTrack highly efficient, particularly in cases
# where large playlists are loaded.

async def load(self, client): # Load our 'actual' playback track using the metadata from this one.
result: LoadResult = await client.get_tracks('ytsearch:{0.title} {0.author}'.format(self)) # Search for our track on YouTube.

if result.load_type != LoadType.SEARCH or not result.tracks: # We're expecting a 'SEARCH' due to our 'ytsearch' prefix above.
raise LoadError

first_track = result.tracks[0] # Grab the first track from the results.
base64 = first_track.track # Extract the base64 string from the track.
self.track = base64 # We'll store this for later, as it allows us to save making network requests
# if this track is re-used (e.g. repeat).

return base64


class CustomSource(Source):
def __init__(self):
super().__init__(name='custom') # Initialising our custom source with the name 'custom'.

async def load_item(self, client, query: str):
if 'keyword' in query:
# track_metadata = http.get("https://our.provider/api/{}".format(query))

track = CustomAudioTrack({ # Create an instance of our CustomAudioTrack.
'identifier': '27cgqh0VRhVeM61ugTnorD', # Fill it with metadata that we've obtained from our source's provider.
'isSeekable': True,
'author': 'DJ Seinfeld',
'length': 296000,
'isStream': False,
'title': 'These Things Will Come To Be',
'uri': 'https://open.spotify.com/track/27cgqh0VRhVeM61ugTnorD'
}, requester=0) # Init requester with a default value.
return LoadResult(LoadType.TRACK, [track], playlist_info=PlaylistInfo.none())
Loading

0 comments on commit 68ac818

Please sign in to comment.