generated from ricardo/MVCLogin
228 lines
8.6 KiB
C#
228 lines
8.6 KiB
C#
using Google.Apis.Services;
|
|
using Google.Apis.YouTube.v3;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Postall.Domain.Services.Contracts;
|
|
using Postall.Infra.Dtos;
|
|
using System.Security.Claims;
|
|
|
|
namespace Postall.Infra.Services
|
|
{
|
|
public class YouTubeServiceChannel: IYouTubeServiceChannel
|
|
{
|
|
private readonly IConfiguration _configuration;
|
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
private readonly string _apiKey;
|
|
private readonly string _clientId;
|
|
private readonly string _clientSecret;
|
|
|
|
public YouTubeServiceChannel(IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
|
|
{
|
|
_configuration = configuration;
|
|
_httpContextAccessor = httpContextAccessor;
|
|
|
|
_apiKey = _configuration["YouTube:ApiKey"];
|
|
_clientId = _configuration["Authentication:Google:ClientId"];
|
|
_clientSecret = _configuration["Authentication:Google:ClientSecret"];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Obtém o ID do usuário atual a partir das claims
|
|
/// </summary>
|
|
private string GetCurrentUserId()
|
|
{
|
|
var user = _httpContextAccessor.HttpContext.User;
|
|
|
|
// Primeiro tentar obter o NameIdentifier (que foi adicionado no ExternalLoginCallback)
|
|
var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
|
|
// Se não encontrou, tenta usar o email como identificador
|
|
if (string.IsNullOrEmpty(userId))
|
|
{
|
|
var email = user.FindFirst(ClaimTypes.Email)?.Value;
|
|
if (!string.IsNullOrEmpty(email))
|
|
{
|
|
// Gerar ID baseado no email (mesmo método usado no ExternalLoginCallback)
|
|
userId = Convert.ToBase64String(
|
|
System.Text.Encoding.UTF8.GetBytes(email)
|
|
).Replace("/", "_").Replace("+", "-").Replace("=", "");
|
|
}
|
|
}
|
|
|
|
return userId;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Obtém os vídeos dos canais que o usuário tem acesso, ordenados por data
|
|
/// </summary>
|
|
public async Task<List<VideoItemResponse>> GetUserChannelVideosAsync(int maxResults = 10)
|
|
{
|
|
// Obter o ID do usuário das claims
|
|
var userId = GetCurrentUserId();
|
|
|
|
if (string.IsNullOrEmpty(userId))
|
|
return new List<VideoItemResponse>();
|
|
|
|
// Obter os canais do usuário do banco de dados
|
|
var userChannels = await GetUserChannelsAsync(userId);
|
|
|
|
if (!userChannels.Any())
|
|
return new List<VideoItemResponse>();
|
|
|
|
var videos = new List<VideoItemResponse>();
|
|
|
|
// Para cada canal, buscar os vídeos recentes
|
|
foreach (var channelId in userChannels)
|
|
{
|
|
var channelVideos = await GetChannelVideosAsync(channelId, maxResults);
|
|
videos.AddRange(channelVideos);
|
|
}
|
|
|
|
// Ordenar por data de publicação e pegar os mais recentes
|
|
return videos
|
|
.OrderByDescending(v => v.PublishedAt)
|
|
.Take(maxResults)
|
|
.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Obtém os vídeos de um canal específico
|
|
/// </summary>
|
|
public async Task<List<VideoItemResponse>> GetChannelVideosAsync(string channelId, int maxResults = 10)
|
|
{
|
|
try
|
|
{
|
|
var youtubeService = new YouTubeBaseServiceWrapper(_apiKey);
|
|
|
|
// Primeiro, buscar os IDs dos últimos vídeos do canal
|
|
var searchRequest = youtubeService.Search.List("snippet");
|
|
searchRequest.ChannelId = channelId;
|
|
searchRequest.Order = SearchResource.ListRequest.OrderEnum.Date;
|
|
searchRequest.MaxResults = maxResults;
|
|
searchRequest.Type = "video";
|
|
|
|
var searchResponse = await searchRequest.ExecuteAsync();
|
|
|
|
if (searchResponse.Items == null || searchResponse.Items.Count == 0)
|
|
return new List<VideoItemResponse>();
|
|
|
|
// Obter os IDs dos vídeos
|
|
var videoIds = searchResponse.Items.Select(i => i.Id.VideoId).ToList();
|
|
|
|
// Buscar detalhes dos vídeos
|
|
var videosRequest = youtubeService.Videos.List("snippet,contentDetails,statistics");
|
|
videosRequest.Id = string.Join(",", videoIds);
|
|
var videosResponse = await videosRequest.ExecuteAsync();
|
|
|
|
// Converter para o modelo
|
|
var videos = new List<VideoItemResponse>();
|
|
foreach (var videoItem in videosResponse.Items)
|
|
{
|
|
var searchItem = searchResponse.Items.FirstOrDefault(i => i.Id.VideoId == videoItem.Id);
|
|
|
|
videos.Add(new VideoItemResponse
|
|
{
|
|
Id = videoItem.Id,
|
|
Title = videoItem.Snippet.Title,
|
|
Description = videoItem.Snippet.Description,
|
|
ThumbnailUrl = videoItem.Snippet.Thumbnails.High.Url,
|
|
PublishedAt = videoItem.Snippet.PublishedAt.Value,
|
|
ChannelId = videoItem.Snippet.ChannelId,
|
|
ChannelTitle = videoItem.Snippet.ChannelTitle
|
|
});
|
|
}
|
|
|
|
return videos;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Em produção, use um logger adequado
|
|
Console.WriteLine($"Erro ao obter vídeos do canal {channelId}: {ex.Message}");
|
|
return new List<VideoItemResponse>();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Método para buscar os canais que o usuário gerencia ou tem acesso
|
|
/// Em um cenário real, isso viria do banco de dados
|
|
/// </summary>
|
|
private async Task<List<string>> GetUserChannelsAsync(string userId)
|
|
{
|
|
// TODO: Substituir isso por uma consulta real ao banco de dados
|
|
|
|
// Em produção, você deve implementar uma tabela que relacione
|
|
// os usuários com seus canais do YouTube
|
|
|
|
// Para teste, aqui estão alguns canais populares
|
|
// Na implementação real, você deve armazenar os canais que o usuário tem permissão
|
|
return new List<string>
|
|
{
|
|
"UC_x5XG1OV2P6uZZ5FSM9Ttw", // Google Developers
|
|
"UCt84aUC9OG6di8kSdKzEHTQ", // Outro canal de exemplo
|
|
"UCkw4JCwteGrDHIsyIIKo4tQ" // Google
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salva um vídeo para o usuário atual
|
|
/// Em produção, isso salvaria no banco de dados
|
|
/// </summary>
|
|
public async Task SaveVideoForUserAsync(string videoId)
|
|
{
|
|
var userId = GetCurrentUserId();
|
|
|
|
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(videoId))
|
|
return;
|
|
|
|
// TODO: Salvar no banco de dados a relação entre o usuário e o vídeo
|
|
|
|
// Código de exemplo:
|
|
// await _dbContext.UserVideos.AddAsync(new UserVideo
|
|
// {
|
|
// UserId = userId,
|
|
// VideoId = videoId,
|
|
// DateAdded = DateTime.UtcNow
|
|
// });
|
|
// await _dbContext.SaveChangesAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove um vídeo do usuário atual
|
|
/// Em produção, isso removeria do banco de dados
|
|
/// </summary>
|
|
public async Task RemoveVideoForUserAsync(string videoId)
|
|
{
|
|
var userId = GetCurrentUserId();
|
|
|
|
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(videoId))
|
|
return;
|
|
|
|
// TODO: Remover do banco de dados a relação entre o usuário e o vídeo
|
|
|
|
// Código de exemplo:
|
|
// var userVideo = await _dbContext.UserVideos
|
|
// .FirstOrDefaultAsync(uv => uv.UserId == userId && uv.VideoId == videoId);
|
|
// if (userVideo != null)
|
|
// {
|
|
// _dbContext.UserVideos.Remove(userVideo);
|
|
// await _dbContext.SaveChangesAsync();
|
|
// }
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Wrapper para o serviço base do YouTube
|
|
/// </summary>
|
|
public class YouTubeBaseServiceWrapper : YouTubeService
|
|
{
|
|
public YouTubeBaseServiceWrapper(string apiKey)
|
|
: base(new BaseClientService.Initializer()
|
|
{
|
|
ApiKey = apiKey,
|
|
ApplicationName = "PostAll"
|
|
})
|
|
{
|
|
}
|
|
}
|
|
}
|