Skip to content
This repository has been archived by the owner on Dec 10, 2023. It is now read-only.

Commit

Permalink
Add resuming support from PythonistaGuild#59
Browse files Browse the repository at this point in the history
  • Loading branch information
WizzyGeek committed Aug 13, 2020
1 parent 0a5a844 commit 5baa310
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 38 deletions.
33 changes: 24 additions & 9 deletions wavelink/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
import aiohttp
import asyncio
import logging
from discord.ext import commands
from functools import partial
from typing import Optional, Union

import aiohttp
from discord.ext import commands

from .errors import *
from .player import Player
from .node import Node

from .player import Player

__log__ = logging.getLogger(__name__)

Expand Down Expand Up @@ -68,7 +68,6 @@ def __init__(self, bot: Union[commands.Bot, commands.AutoShardedBot]):
self.session = aiohttp.ClientSession(loop=self.loop)

self.nodes = {}

bot.add_listener(self.update_handler, 'on_socket_response')

@property
Expand Down Expand Up @@ -361,7 +360,9 @@ def get_player(self, guild_id: int, *, cls=None, node_id=None, **kwargs) -> Play
return player

async def initiate_node(self, host: str, port: int, *, rest_uri: str, password: str, region: str, identifier: str,
shard_id: int = None, secure: bool = False, heartbeat: float = None) -> Node:
shard_id: int = None, secure: bool = False, heartbeat: float = None,
resume_session: bool = False, resume_timeout: float = 60.0, resume_key: str = None,
payload_timeout: float = 35.02) -> Node:
"""|coro|
Initiate a Node and connect to the provided server.
Expand All @@ -386,7 +387,17 @@ async def initiate_node(self, host: str, port: int, *, rest_uri: str, password:
Whether the websocket should be started with the secure wss protocol.
heartbeat: Optional[float]
Send ping message every heartbeat seconds and wait pong response, if pong response is not received then close connection.
resume_session: Optional[bool]
If True then Lavalink server will continue to play music until bot reconnects or
till `resume_timeout` and then shuts-down all Players. Defaults to False.
resume_timeout: Optional[float]
Has no effect unless resume_session is True. Defaults to 60.0 seconds.
resume_key: Optional[str]
Has no effect unless resume_session is True. Defaults to a secret AlphaNumeric key that is 32 characters long
payload_timeout: float
The amount of time a payload should be queued, logically should be greater than (resume_timeout/2 - 1) or 30.0.
Defaults to 35.02 seconds.
Returns
---------
:class:`wavelink.node.Node`
Expand All @@ -412,8 +423,12 @@ async def initiate_node(self, host: str, port: int, *, rest_uri: str, password:
session=self.session,
client=self,
secure=secure,
heartbeat=heartbeat)

heartbeat=heartbeat,
resume_session=resume_session,
resume_timeout=resume_timeout,
resume_key=resume_key,
payload_timeout=payload_timeout)

await node.connect(bot=self.bot)

node.available = True
Expand Down
3 changes: 3 additions & 0 deletions wavelink/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ class AuthorizationFailure(WavelinkException):

class BuildTrackError(WavelinkException):
"""Exception raised when a track is failed to be decoded and re-built."""

class NodeSessionClosedError(WavelinkException):
"""Exception raised when a Node's session can't be or is not resumed."""
56 changes: 50 additions & 6 deletions wavelink/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
"""
import inspect
import logging
from discord.ext import commands
from typing import Optional, Union
from urllib.parse import quote

from discord.ext import commands

from .errors import *
from .player import Player, Track, TrackPlaylist
from .websocket import WebSocket


__log__ = logging.getLogger(__name__)


Expand All @@ -46,12 +46,43 @@ class Node:
The host address the node is connected to.
port: int
The port the node is connected to.
shards: int
The number of Shards.
rest_uri: str
The rest server address the node is connecte to.
uid: int
The user id.
password: str
The Node's password
region: str
The region provided to the node on connection.
identifier: str
The unique indentifier associated with the node.
secure: bool
Wether the web-sockect connection is secure.
shard_id: Optional[int]
The shard id, defuault value is None.
heartbeat: float
Duration between pings, helps keep WS stable. Defaults to None to disable.
resume_session: bool
If True then Lavalink server will continue to play music until bot reconnects or
till `resume_timeout` and then shuts-down all Players. Defaults to False.
resume_timeout: float
Has no effect unless resume_session is True.
resume_key: str
Has no effect unless resume_session is True. Defaults to a secret AlphaNumeric key that is 32 characters long
payload_timeout: float
Has no effect unless resume_session is True. Amount of time a send request should be queued.
players: Dict[int, Player]
A dictionary with guild id as key and the respective guild's Player as value. Please use :func:`Node.get_player` instead.
session: aiohttp.ClientSession
The aiohttp session.
hook: Callable
A callable object. use :func:`Node.set_hook`
available: bool
Wether the Node is in use or not. Use is_available instead.
stats: Optional[:class:`Stats`]
The Node's stats, sent by the server. Could be None.
"""

def __init__(self, host: str,
Expand All @@ -67,7 +98,11 @@ def __init__(self, host: str,
identifier: str,
shard_id: int = None,
secure: bool = False,
heartbeat: float = None
heartbeat: float,
resume_session: bool,
resume_timeout: float,
resume_key: str,
payload_timeout: float
):

self.host = host
Expand All @@ -80,7 +115,10 @@ def __init__(self, host: str,
self.identifier = identifier
self.secure = secure
self.heartbeat = heartbeat

self.resume_session = resume_session
self.resume_timeout = resume_timeout
self.resume_key = resume_key
self.payload_timeout = payload_timeout
self.shard_id = shard_id

self.players = {}
Expand Down Expand Up @@ -125,7 +163,11 @@ async def connect(self, bot: Union[commands.Bot, commands.AutoShardedBot]) -> No
password=self.password,
shard_count=self.shards,
user_id=self.uid,
secure=self.secure)
secure=self.secure,
resume_session=self.resume_session,
resume_timeout=self.resume_timeout,
resume_key=self.resume_key,
payload_timeout=self.payload_timeout)
await self._websocket._connect()

__log__.info(f'NODE | {self.identifier} connected:: {self.__repr__()}')
Expand Down Expand Up @@ -252,8 +294,10 @@ async def destroy(self) -> None:
self._websocket._task.cancel()
except Exception:
pass

await self._websocket.close()
__log__.info(f"{self} | Destroyed and disconnected")
del self._client.nodes[self.identifier]
return

async def _send(self, **data) -> None:
__log__.debug(f'NODE | Sending payload:: <{data}> ({self.__repr__()})')
Expand Down

0 comments on commit 5baa310

Please sign in to comment.