示例#1
0
        public async Task PlayAsync(PlayPacket playPacket)
        {
            _cache.TryGetFromCache(playPacket.Id, out var track);
            if (track is null)
            {
                var(isEnabled, response) = await _sources
                                           .HandleRequestAsync(track.Provider, track.Url ?? track.Title)
                                           .ConfigureAwait(false);

                if (isEnabled)
                {
                    LogHandler <AudioEngine> .Log
                    .Error($"{track.Provider} is disabled in configuration.");

                    return;
                }

                track = response.Tracks
                        .FirstOrDefault(x => x.Url == track.Url || x.Title.Contains(track.Title));
            }

            if (track is null)
            {
                LogHandler <AudioEngine> .Log.Error($"Unable to play the requested track: {track.Title}");

                return;
            }

            if (playPacket.StartTime > track.Duration || playPacket.StartTime < 0 ||
                playPacket.EndTime > track.Duration)
            {
                LogHandler <AudioEngine> .Log.Error($"Client sent out-of-bounds start or end time.");

                return;
            }

            _currentTrack = track;
            var stream = await _sources.GetStreamAsync(track).ConfigureAwait(false);

            await stream.CopyToAsync(_stream)
            .ConfigureAwait(false);

            await _stream.FlushAsync()
            .ConfigureAwait(false);

            SpinWait.SpinUntil(() => IsPlaybackCompleted);

            await _socket.SendAsync(new BaseResponse
            {
                Op   = OperationType.TrackFinished,
                Data = new PlayerResponse
                {
                    GuildId = _voiceClient.GuildId,
                    Track   = _currentTrack
                }
            })
            .ConfigureAwait(false);

            _currentTrack = default;
        }
示例#2
0
        private async Task ProcessRequestAsync(HttpListenerContext context)
        {
            var localPath      = context.Request.Url.LocalPath;
            var remoteEndPoint = context.Request.RemoteEndPoint;
            var response       = new BaseResponse();

            try
            {
                switch (localPath)
                {
                case "/tracks":
                    LogHandler <WsServer> .Log.Debug($"Incoming http request from {remoteEndPoint}.");

                    if (context.Request.Headers.Get("Password") != _config.Password)
                    {
                        response.Error = "Password header doesn't match value specified in configuration";
                        return;
                    }

                    var(prov, query) = context.Request.QueryString.BuildQuery();
                    if (query is null || prov is null)
                    {
                        response.Error =
                            "Please use the `?prov={provider}&q={YOUR_QUERY} argument after /tracks";
                        return;
                    }

                    var(isEnabled, searchResponse) = await _sources.HandleRequestAsync(prov, query)
                                                     .ConfigureAwait(false);

                    if (!isEnabled)
                    {
                        response.Error = $"Requested {prov} isn't enabled in configuration";
                    }
                    else
                    {
                        response.Data = searchResponse;
                    }

                    response.Op = OperationType.Rest;
                    await context.SendResponseAsync(response)
                    .ConfigureAwait(false);

                    LogHandler <WsServer> .Log.Debug($"Replied to {remoteEndPoint} with {response.Error ?? "success"}.");

                    break;

                case "/":
                    if (!context.Request.IsWebSocketRequest)
                    {
                        response.Error =
                            "Only websocket connections are allowed at this endpoint. For rest use /tracks endpoint.";
                        await context.SendResponseAsync(response)
                        .ConfigureAwait(false);

                        return;
                    }

                    LogHandler <WsServer> .Log.Debug($"Incoming websocket request coming from {remoteEndPoint}.");

                    var wsContext = await context.AcceptWebSocketAsync(default)
                                    .ConfigureAwait(false);

                    var wsClient = new WsClient(wsContext);
                    _clients.TryAdd(remoteEndPoint, wsClient);

                    if (_clients.Count > 0 && _statsSenderTask == null)
                    {
                        _statsCancellation = new CancellationTokenSource();
                        _statsSenderTask   = CollectStatsAsync();
                    }

                    LogHandler <WsServer> .Log.Information($"Websocket connection opened from {remoteEndPoint}.");

                    break;

                default:
                    LogHandler <WsServer> .Log.Warning(
                        $"{remoteEndPoint} requested an unknown path: {context.Request.Url}.");

                    response.Error = "You are trying to access an unknown endpoint.";
                    await context.SendResponseAsync(response)
                    .ConfigureAwait(false);

                    break;
                }
            }
            catch (Exception ex)
            {
                response.Error = $"Frostbyte threw an inner exception: {ex?.InnerException?.Message ?? ex?.Message}";
                await context.SendResponseAsync(response)
                .ConfigureAwait(false);

                LogHandler <WsServer> .Log.Error(exception : ex);
            }
            finally
            {
                context.Response.Close();
            }
        }