157 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# -*- coding: utf-8 -*-
 | 
						|
 | 
						|
"""
 | 
						|
The MIT License (MIT)
 | 
						|
 | 
						|
Copyright (c) 2015-2017 Rapptz
 | 
						|
 | 
						|
Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
copy of this software and associated documentation files (the "Software"),
 | 
						|
to deal in the Software without restriction, including without limitation
 | 
						|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
Software is furnished to do so, subject to the following conditions:
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 | 
						|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
						|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
						|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
						|
DEALINGS IN THE SOFTWARE.
 | 
						|
"""
 | 
						|
 | 
						|
import datetime
 | 
						|
 | 
						|
from . import utils
 | 
						|
from .enums import VoiceRegion, try_enum
 | 
						|
from .member import VoiceState
 | 
						|
 | 
						|
class CallMessage:
 | 
						|
    """Represents a group call message from Discord.
 | 
						|
 | 
						|
    This is only received in cases where the message type is equivalent to
 | 
						|
    :attr:`MessageType.call`.
 | 
						|
 | 
						|
    Attributes
 | 
						|
    -----------
 | 
						|
    ended_timestamp: Optional[datetime.datetime]
 | 
						|
        A naive UTC datetime object that represents the time that the call has ended.
 | 
						|
    participants: List[:class:`User`]
 | 
						|
        The list of users that are participating in this call.
 | 
						|
    message: :class:`Message`
 | 
						|
        The message associated with this call message.
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self, message, **kwargs):
 | 
						|
        self.message = message
 | 
						|
        self.ended_timestamp = utils.parse_time(kwargs.get('ended_timestamp'))
 | 
						|
        self.participants = kwargs.get('participants')
 | 
						|
 | 
						|
    @property
 | 
						|
    def call_ended(self):
 | 
						|
        """:obj:`bool`: Indicates if the call has ended."""
 | 
						|
        return self.ended_timestamp is not None
 | 
						|
 | 
						|
    @property
 | 
						|
    def channel(self):
 | 
						|
        """:class:`GroupChannel`\: The private channel associated with this message."""
 | 
						|
        return self.message.channel
 | 
						|
 | 
						|
    @property
 | 
						|
    def duration(self):
 | 
						|
        """Queries the duration of the call.
 | 
						|
 | 
						|
        If the call has not ended then the current duration will
 | 
						|
        be returned.
 | 
						|
 | 
						|
        Returns
 | 
						|
        ---------
 | 
						|
        datetime.timedelta
 | 
						|
            The timedelta object representing the duration.
 | 
						|
        """
 | 
						|
        if self.ended_timestamp is None:
 | 
						|
            return datetime.datetime.utcnow() - self.message.timestamp
 | 
						|
        else:
 | 
						|
            return self.ended_timestamp - self.message.timestamp
 | 
						|
 | 
						|
class GroupCall:
 | 
						|
    """Represents the actual group call from Discord.
 | 
						|
 | 
						|
    This is accompanied with a :class:`CallMessage` denoting the information.
 | 
						|
 | 
						|
    Attributes
 | 
						|
    -----------
 | 
						|
    call: :class:`CallMessage`
 | 
						|
        The call message associated with this group call.
 | 
						|
    unavailable: :obj:`bool`
 | 
						|
        Denotes if this group call is unavailable.
 | 
						|
    ringing: List[:class:`User`]
 | 
						|
        A list of users that are currently being rung to join the call.
 | 
						|
    region: :class:`VoiceRegion`
 | 
						|
        The guild region the group call is being hosted on.
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self, **kwargs):
 | 
						|
        self.call = kwargs.get('call')
 | 
						|
        self.unavailable = kwargs.get('unavailable')
 | 
						|
        self._voice_states = {}
 | 
						|
 | 
						|
        for state in kwargs.get('voice_states', []):
 | 
						|
            self._update_voice_state(state)
 | 
						|
 | 
						|
        self._update(**kwargs)
 | 
						|
 | 
						|
    def _update(self, **kwargs):
 | 
						|
        self.region = try_enum(VoiceRegion, kwargs.get('region'))
 | 
						|
        lookup = {u.id: u for u in self.call.channel.recipients}
 | 
						|
        me = self.call.channel.me
 | 
						|
        lookup[me.id] = me
 | 
						|
        self.ringing = list(filter(None, map(lambda i: lookup.get(i), kwargs.get('ringing', []))))
 | 
						|
 | 
						|
    def _update_voice_state(self, data):
 | 
						|
        user_id = int(data['user_id'])
 | 
						|
        # left the voice channel?
 | 
						|
        if data['channel_id'] is None:
 | 
						|
            self._voice_states.pop(user_id, None)
 | 
						|
        else:
 | 
						|
            self._voice_states[user_id] = VoiceState(data=data, channel=self.channel)
 | 
						|
 | 
						|
    @property
 | 
						|
    def connected(self):
 | 
						|
        """A property that returns the :obj:`list` of :class:`User` that are currently in this call."""
 | 
						|
        ret = [u for u in self.channel.recipients if self.voice_state_for(u) is not None]
 | 
						|
        me = self.channel.me
 | 
						|
        if self.voice_state_for(me) is not None:
 | 
						|
            ret.append(me)
 | 
						|
 | 
						|
        return ret
 | 
						|
 | 
						|
    @property
 | 
						|
    def channel(self):
 | 
						|
        """:class:`GroupChannel`\: Returns the channel the group call is in."""
 | 
						|
        return self.call.channel
 | 
						|
 | 
						|
    def voice_state_for(self, user):
 | 
						|
        """Retrieves the :class:`VoiceState` for a specified :class:`User`.
 | 
						|
 | 
						|
        If the :class:`User` has no voice state then this function returns
 | 
						|
        ``None``.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ------------
 | 
						|
        user: :class:`User`
 | 
						|
            The user to retrieve the voice state for.
 | 
						|
 | 
						|
        Returns
 | 
						|
        --------
 | 
						|
        Optional[:class:`VoiceState`]
 | 
						|
            The voice state associated with this user.
 | 
						|
        """
 | 
						|
 | 
						|
        return self._voice_states.get(user.id)
 | 
						|
 |