Browse Source

Telecom voice v1

pull/135/head
Andrei 6 years ago
parent
commit
0f89d687c8
No known key found for this signature in database GPG Key ID: 4D2A02C7D500E9D9
  1. 95
      disco/voice.py
  2. 64
      examples/music.py
  3. 2
      setup.py

95
disco/voice.py

@ -0,0 +1,95 @@
from disco.gateway.packets import OPCode
from disco.types.channel import Channel
from telecom import TelecomConnection, AvConvPlayable
class VoiceConnection(object):
def __init__(self, client, guild_id):
self.client = client
self.guild_id = guild_id
self.channel_id = None
self._conn = None
self._voice_server_update_listener = self.client.events.on(
'VoiceServerUpdate',
self._on_voice_server_update,
)
self._mute = False
self._deaf = False
@property
def mute(self):
return self._mute
@property
def deaf(self):
return self._deaf
@mute.setter
def mute(self, value):
if value is self._mute:
return
self._mute = value
self._send_voice_state_update()
@deaf.setter
def deaf(self, value):
if value is self._deaf:
return
self._deaf = value
self._send_voice_state_update()
@classmethod
def from_channel(self, channel):
assert channel.is_voice, 'Cannot connect to a non voice channel'
conn = VoiceConnection(channel.client, channel.guild_id)
conn.connect(channel.id)
return conn
def set_channel(self, channel_or_id):
if channel_or_id and isinstance(channel_or_id, Channel):
channel_or_id = channel_or_id.id
self.channel_id = channel_or_id
self._send_voice_state_update()
def connect(self, channel_id):
assert self._conn is None, 'Already connected'
self.set_channel(channel_id)
self._conn = TelecomConnection(
self.client.state.me.id,
self.guild_id,
self.client.gw.session_id,
)
def disconnect(self):
assert self._conn is not None, 'Not connected'
# Send disconnection
self.set_channel(None)
# Delete our connection so it will get GC'd
del self._conn
self._conn = None
def play_file(self, url):
self._conn.play(AvConvPlayable(url))
def _on_voice_server_update(self, event):
if not self._conn or event.guild_id != self.guild_id:
return
self._conn.update_server_info(event.endpoint, event.token)
def _send_voice_state_update(self):
self.client.gw.send(OPCode.VOICE_STATE_UPDATE, {
'self_mute': self._mute,
'self_deaf': self._deaf,
'self_video': False,
'guild_id': self.guild_id,
'channel_id': self.channel_id,
})

64
examples/music.py

@ -1,56 +1,30 @@
from disco.bot import Plugin
from disco.bot.command import CommandError
from disco.voice.player import Player
from disco.voice.playable import YoutubeDLInput, BufferedOpusEncoderPlayable
from disco.voice.client import VoiceException
from disco.voice import VoiceConnection
class MusicPlugin(Plugin):
def load(self, ctx):
super(MusicPlugin, self).load(ctx)
self.guilds = {}
def load(self, data):
super(MusicPlugin, self).load(data)
self._connections = {}
@Plugin.command('join')
def on_join(self, event):
if event.guild.id in self.guilds:
return event.msg.reply("I'm already playing music here.")
vs = event.guild.get_member(event.author).get_voice_state()
if not vs:
return event.msg.reply('you are not in a voice channel')
state = event.guild.get_member(event.author).get_voice_state()
if not state:
return event.msg.reply('You must be connected to voice to use that command.')
if event.guild.id in self._connections:
if self._connections[event.guild.id].channel_id == vs.channel_id:
return event.msg.reply('already in that channel')
else:
self._connections[event.guild.id].set_channel(vs.channel)
return
try:
client = state.channel.connect()
except VoiceException as e:
return event.msg.reply('Failed to connect to voice: `{}`'.format(e))
self._connections[event.guild.id] = VoiceConnection.from_channel(vs.channel)
self.guilds[event.guild.id] = Player(client)
self.guilds[event.guild.id].complete.wait()
del self.guilds[event.guild.id]
@Plugin.command('play', '<song:str>')
def on_play(self, event, song=None):
if event.guild.id not in self._connections:
return event.msg.reply('not in voice here')
def get_player(self, guild_id):
if guild_id not in self.guilds:
raise CommandError("I'm not currently playing music here.")
return self.guilds.get(guild_id)
@Plugin.command('leave')
def on_leave(self, event):
player = self.get_player(event.guild.id)
player.disconnect()
@Plugin.command('play', '<url:str>')
def on_play(self, event, url):
item = YoutubeDLInput(url).pipe(BufferedOpusEncoderPlayable)
self.get_player(event.guild.id).queue.append(item)
@Plugin.command('pause')
def on_pause(self, event):
self.get_player(event.guild.id).pause()
@Plugin.command('resume')
def on_resume(self, event):
self.get_player(event.guild.id).resume()
@Plugin.command('kill')
def on_kill(self, event):
self.get_player(event.guild.id).client.ws.sock.shutdown()
self._connections[event.guild.id].play_file(song)

2
setup.py

@ -10,7 +10,7 @@ with open('README.md') as f:
readme = f.read()
extras_require = {
'voice': ['pynacl==1.2.1'],
'voice': ['telecom==0.0.2'],
'http': ['flask==0.12.2'],
'yaml': ['pyyaml==3.12'],
'music': ['youtube_dl>=2018.1.21'],

Loading…
Cancel
Save