mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-12 10:18:27 -04:00
Restructured the project structure back to the way it was, there's no reasonable way to split the modules
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
namespace NadekoBot.Modules.Searches.Youtube;
|
||||
|
||||
public interface IYoutubeSearchService
|
||||
{
|
||||
Task<VideoInfo?> SearchAsync(string query);
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NadekoBot.Modules.Searches;
|
||||
|
||||
public sealed class InvidiousSearchResponse
|
||||
{
|
||||
[JsonPropertyName("videoId")]
|
||||
public string VideoId { get; set; } = null!;
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
using NadekoBot.Modules.Searches.Youtube;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace NadekoBot.Modules.Searches;
|
||||
|
||||
public sealed class InvidiousYtSearchService : IYoutubeSearchService, INService
|
||||
{
|
||||
private readonly IHttpClientFactory _http;
|
||||
private readonly SearchesConfigService _scs;
|
||||
private readonly NadekoRandom _rng;
|
||||
|
||||
public InvidiousYtSearchService(
|
||||
IHttpClientFactory http,
|
||||
SearchesConfigService scs)
|
||||
{
|
||||
_http = http;
|
||||
_scs = scs;
|
||||
_rng = new();
|
||||
}
|
||||
|
||||
public async Task<VideoInfo?> SearchAsync(string query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var instances = _scs.Data.InvidiousInstances;
|
||||
if (instances is null or { Count: 0 })
|
||||
{
|
||||
Log.Warning("Attempted to use Invidious as the .youtube provider but there are no 'invidiousInstances' "
|
||||
+ "specified in `data/searches.yml`");
|
||||
return null;
|
||||
}
|
||||
|
||||
var instance = instances[_rng.Next(0, instances.Count)];
|
||||
|
||||
using var http = _http.CreateClient();
|
||||
var res = await http.GetFromJsonAsync<List<InvidiousSearchResponse>>(
|
||||
$"{instance}/api/v1/search"
|
||||
+ $"?q={query}"
|
||||
+ $"&type=video");
|
||||
|
||||
if (res is null or {Count: 0})
|
||||
return null;
|
||||
|
||||
return new VideoInfo(res[0].VideoId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
namespace NadekoBot.Modules.Searches.Youtube;
|
||||
|
||||
public readonly struct VideoInfo
|
||||
{
|
||||
public VideoInfo(string videoId)
|
||||
=> Url = $"https://youtube.com/watch?v={videoId}";
|
||||
|
||||
public string Url { get; init; }
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
namespace NadekoBot.Modules.Searches.Youtube;
|
||||
|
||||
public sealed class YoutubeDataApiSearchService : IYoutubeSearchService, INService
|
||||
{
|
||||
private readonly IGoogleApiService _gapi;
|
||||
|
||||
public YoutubeDataApiSearchService(IGoogleApiService gapi)
|
||||
{
|
||||
_gapi = gapi;
|
||||
}
|
||||
|
||||
public async Task<VideoInfo?> SearchAsync(string query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var results = await _gapi.GetVideoLinksByKeywordAsync(query);
|
||||
var first = results.FirstOrDefault();
|
||||
if (first is null)
|
||||
return null;
|
||||
|
||||
return new()
|
||||
{
|
||||
Url = first
|
||||
};
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
namespace NadekoBot.Modules.Searches.Youtube;
|
||||
|
||||
public sealed class YtdlYoutubeSearchService : YoutubedlxServiceBase, INService
|
||||
{
|
||||
public override async Task<VideoInfo?> SearchAsync(string query)
|
||||
=> await InternalGetInfoAsync(query, false);
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
namespace NadekoBot.Modules.Searches.Youtube;
|
||||
|
||||
public sealed class YtdlpYoutubeSearchService : YoutubedlxServiceBase, INService
|
||||
{
|
||||
public override async Task<VideoInfo?> SearchAsync(string query)
|
||||
=> await InternalGetInfoAsync(query, true);
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
namespace NadekoBot.Modules.Searches.Youtube;
|
||||
|
||||
public abstract class YoutubedlxServiceBase : IYoutubeSearchService
|
||||
{
|
||||
private YtdlOperation CreateYtdlOp(bool isYtDlp)
|
||||
=> new YtdlOperation("-4 "
|
||||
+ "--geo-bypass "
|
||||
+ "--encoding UTF8 "
|
||||
+ "--get-id "
|
||||
+ "--no-check-certificate "
|
||||
+ "--default-search "
|
||||
+ "\"ytsearch:\" -- \"{0}\"",
|
||||
isYtDlp: isYtDlp);
|
||||
|
||||
protected async Task<VideoInfo?> InternalGetInfoAsync(string query, bool isYtDlp)
|
||||
{
|
||||
var op = CreateYtdlOp(isYtDlp);
|
||||
var data = await op.GetDataAsync(query);
|
||||
var items = data?.Split('\n');
|
||||
if (items is null or { Length: 0 })
|
||||
return null;
|
||||
|
||||
var id = items.FirstOrDefault(x => x.Length is > 5 and < 15);
|
||||
if (id is null)
|
||||
return null;
|
||||
|
||||
return new VideoInfo()
|
||||
{
|
||||
Url = $"https://youtube.com/watch?v={id}"
|
||||
};
|
||||
}
|
||||
|
||||
public abstract Task<VideoInfo?> SearchAsync(string query);
|
||||
}
|
Reference in New Issue
Block a user