Skip to content

Commit ac73ce4

Browse files
author
Meyn
committed
Update T2Tunes (TripleTrple) indexer
1 parent 4eb2694 commit ac73ce4

3 files changed

Lines changed: 88 additions & 88 deletions

File tree

Tubifarry/Indexers/TripleTriple/TripleTripleParser.cs

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -32,35 +32,30 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
3232
indexerResponse.Content,
3333
IndexerParserHelper.StandardJsonOptions);
3434

35-
if (response?.Results == null)
35+
if (response?.Data == null)
3636
{
3737
logger.Trace("No results found in response");
3838
return releases;
3939
}
4040

41-
foreach (TripleTripleResult result in response.Results)
41+
foreach (TripleTripleSearchEdge edge in response.Data.SearchAlbums?.Edges ?? [])
4242
{
43-
if (result.Hits == null)
43+
if (edge.Node == null)
4444
continue;
45+
AlbumData albumData = CreateAlbumRelease(edge.Node, codec);
46+
albumData.ParseReleaseDate();
47+
releases.Add(albumData.ToReleaseInfo());
48+
}
4549

46-
foreach (TripleTripleSearchHit hit in result.Hits)
50+
if (isSingle)
51+
{
52+
foreach (TripleTripleSearchEdge edge in response.Data.SearchTracks?.Edges ?? [])
4753
{
48-
TripleTripleDocument? document = hit.Document;
49-
if (document == null)
54+
if (edge.Node == null)
5055
continue;
51-
52-
if (document.IsAlbum)
53-
{
54-
AlbumData albumData = CreateAlbumRelease(document, codec);
55-
albumData.ParseReleaseDate();
56-
releases.Add(albumData.ToReleaseInfo());
57-
}
58-
else if (document.IsTrack && isSingle)
59-
{
60-
AlbumData trackData = CreateTrackRelease(document, codec);
61-
trackData.ParseReleaseDate();
62-
releases.Add(trackData.ToReleaseInfo());
63-
}
56+
AlbumData trackData = CreateTrackRelease(edge.Node, codec);
57+
trackData.ParseReleaseDate();
58+
releases.Add(trackData.ToReleaseInfo());
6459
}
6560
}
6661
}
@@ -72,49 +67,48 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
7267
return releases;
7368
}
7469

75-
private AlbumData CreateAlbumRelease(TripleTripleDocument album, TripleTripleCodec codec)
70+
private AlbumData CreateAlbumRelease(TripleTripleSearchNode album, TripleTripleCodec codec)
7671
{
7772
(AudioFormat format, int bitrate, int bitDepth) = GetQualityForCodec(codec);
78-
int trackCount = album.TrackNum > 0 ? album.TrackNum : 10;
79-
long estimatedSize = IndexerParserHelper.EstimateSize(0, 0, bitrate, trackCount);
73+
int trackCount = album.TrackCount > 0 ? album.TrackCount : 10;
74+
long estimatedSize = IndexerParserHelper.EstimateSize(0, album.Duration, bitrate, trackCount);
75+
bool hasDate = DateTime.TryParse(album.ReleaseDate, out DateTime releaseDate);
8076

8177
return new("TripleTriple", nameof(AmazonMusicDownloadProtocol))
8278
{
83-
AlbumId = $"album/{album.Asin}",
79+
AlbumId = $"album/{album.Id}",
8480
AlbumName = album.Title,
8581
ArtistName = album.ArtistName,
86-
InfoUrl = $"https://music.amazon.com/albums/{album.Asin}",
82+
InfoUrl = $"https://music.amazon.com/albums/{album.Id}",
8783
TotalTracks = trackCount,
88-
ReleaseDate = album.OriginalReleaseDate.HasValue && album.OriginalReleaseDate.Value > 0
89-
? DateTimeOffset.FromUnixTimeSeconds(album.OriginalReleaseDate.Value).ToString("yyyy-MM-dd")
90-
: DateTime.Now.Year.ToString(),
91-
ReleaseDatePrecision = album.OriginalReleaseDate.HasValue && album.OriginalReleaseDate.Value > 0 ? "day" : "year",
92-
CustomString = album.ArtOriginal?.Url ?? album.ArtOriginal?.ArtUrl ?? string.Empty,
84+
ReleaseDate = hasDate ? releaseDate.ToString("yyyy-MM-dd") : DateTime.Now.Year.ToString(),
85+
ReleaseDatePrecision = hasDate ? "day" : "year",
86+
Duration = album.Duration,
87+
CustomString = album.CoverUrl ?? string.Empty,
9388
Codec = format,
9489
Bitrate = bitrate,
9590
BitDepth = bitDepth,
9691
Size = estimatedSize
9792
};
9893
}
9994

100-
private AlbumData CreateTrackRelease(TripleTripleDocument track, TripleTripleCodec codec)
95+
private AlbumData CreateTrackRelease(TripleTripleSearchNode track, TripleTripleCodec codec)
10196
{
10297
(AudioFormat format, int bitrate, int bitDepth) = GetQualityForCodec(codec);
10398
long estimatedSize = IndexerParserHelper.EstimateSize(0, track.Duration, bitrate);
99+
bool hasDate = DateTime.TryParse(track.ReleaseDate, out DateTime releaseDate);
104100

105101
return new("TripleTriple", nameof(AmazonMusicDownloadProtocol))
106102
{
107-
AlbumId = $"track/{track.Asin}",
108-
AlbumName = track.AlbumName ?? track.Title,
103+
AlbumId = $"track/{track.Id}",
104+
AlbumName = track.Album?.Title ?? track.Title,
109105
ArtistName = track.ArtistName,
110-
InfoUrl = $"https://music.amazon.com/tracks/{track.Asin}",
106+
InfoUrl = $"https://music.amazon.com/tracks/{track.Id}",
111107
TotalTracks = 1,
112-
ReleaseDate = track.OriginalReleaseDate.HasValue && track.OriginalReleaseDate.Value > 0
113-
? DateTimeOffset.FromUnixTimeSeconds(track.OriginalReleaseDate.Value).ToString("yyyy-MM-dd")
114-
: DateTime.Now.Year.ToString(),
115-
ReleaseDatePrecision = track.OriginalReleaseDate.HasValue && track.OriginalReleaseDate.Value > 0 ? "day" : "year",
108+
ReleaseDate = hasDate ? releaseDate.ToString("yyyy-MM-dd") : DateTime.Now.Year.ToString(),
109+
ReleaseDatePrecision = hasDate ? "day" : "year",
116110
Duration = track.Duration,
117-
CustomString = track.ArtOriginal?.Url ?? track.ArtOriginal?.ArtUrl ?? string.Empty,
111+
CustomString = track.CoverUrl ?? track.Album?.CoverUrl ?? string.Empty,
118112
Codec = format,
119113
Bitrate = bitrate,
120114
BitDepth = bitDepth,

Tubifarry/Indexers/TripleTriple/TripleTripleRecords.cs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,46 @@ public record TripleTripleStatusResponse(
66
[property: JsonPropertyName("amazonMusic")] string AmazonMusic);
77

88
public record TripleTripleSearchResponse(
9-
[property: JsonPropertyName("results")] List<TripleTripleResult>? Results);
9+
[property: JsonPropertyName("data")] TripleTripleSearchData? Data);
1010

11-
public record TripleTripleResult(
12-
[property: JsonPropertyName("hits")] List<TripleTripleSearchHit>? Hits);
11+
public record TripleTripleSearchData(
12+
[property: JsonPropertyName("searchAlbums")] TripleTripleSearchConnection? SearchAlbums,
13+
[property: JsonPropertyName("searchTracks")] TripleTripleSearchConnection? SearchTracks);
1314

14-
public record TripleTripleSearchHit(
15-
[property: JsonPropertyName("document")] TripleTripleDocument? Document);
15+
public record TripleTripleSearchConnection(
16+
[property: JsonPropertyName("edgeCount")] int EdgeCount,
17+
[property: JsonPropertyName("edges")] List<TripleTripleSearchEdge>? Edges);
1618

17-
public record TripleTripleDocument(
18-
[property: JsonPropertyName("__type")] string Type,
19-
[property: JsonPropertyName("asin")] string Asin,
19+
public record TripleTripleSearchEdge(
20+
[property: JsonPropertyName("node")] TripleTripleSearchNode? Node);
21+
22+
public record TripleTripleSearchNode(
23+
[property: JsonPropertyName("id")] string Id,
2024
[property: JsonPropertyName("title")] string Title,
21-
[property: JsonPropertyName("artistName")] string ArtistName,
22-
[property: JsonPropertyName("duration")] int Duration,
23-
[property: JsonPropertyName("trackNum")] int TrackNum,
24-
[property: JsonPropertyName("discNum")] int DiscNum,
25-
[property: JsonPropertyName("albumName")] string? AlbumName = null,
26-
[property: JsonPropertyName("albumAsin")] string? AlbumAsin = null,
27-
[property: JsonPropertyName("artistAsin")] string? ArtistAsin = null,
28-
[property: JsonPropertyName("artOriginal")] TripleTripleArt? ArtOriginal = null,
29-
[property: JsonPropertyName("originalReleaseDate")] long? OriginalReleaseDate = null,
30-
[property: JsonPropertyName("primaryGenre")] string? PrimaryGenre = null,
31-
[property: JsonPropertyName("isrc")] string? Isrc = null,
32-
[property: JsonPropertyName("isMusicSubscription")] bool IsMusicSubscription = false)
25+
[property: JsonPropertyName("duration")] int Duration = 0,
26+
[property: JsonPropertyName("trackCount")] int TrackCount = 0,
27+
[property: JsonPropertyName("trackNumber")] int TrackNumber = 0,
28+
[property: JsonPropertyName("releaseDate")] string? ReleaseDate = null,
29+
[property: JsonPropertyName("format")] string? Format = null,
30+
[property: JsonPropertyName("artistNames")] string? ArtistNames = null,
31+
[property: JsonPropertyName("images")] List<TripleTripleImage>? Images = null,
32+
[property: JsonPropertyName("album")] TripleTripleSearchNode? Album = null,
33+
[property: JsonPropertyName("contributingArtists")] TripleTripleContributingArtists? ContributingArtists = null)
3334
{
34-
public bool IsTrack => Type?.Contains("Track") == true;
35-
public bool IsAlbum => Type?.Contains("Album") == true;
35+
[JsonIgnore]
36+
public string ArtistName => ArtistNames ?? ContributingArtists?.ConcatenatedName ?? string.Empty;
37+
38+
[JsonIgnore]
39+
public string? CoverUrl => Images?.OrderByDescending(i => i.Width).FirstOrDefault()?.Url;
3640
}
3741

38-
public record TripleTripleArt(
39-
[property: JsonPropertyName("URL")] string Url,
40-
[property: JsonPropertyName("artUrl")] string? ArtUrl);
42+
public record TripleTripleContributingArtists(
43+
[property: JsonPropertyName("concatenatedName")] string? ConcatenatedName);
44+
45+
public record TripleTripleImage(
46+
[property: JsonPropertyName("width")] int Width,
47+
[property: JsonPropertyName("height")] int Height,
48+
[property: JsonPropertyName("url")] string Url);
4149

4250
public record TripleTripleMediaResponse(
4351
[property: JsonPropertyName("asin")] string Asin,

Tubifarry/Indexers/TripleTriple/TripleTripleRequestGenerator.cs

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,45 @@ public class TripleTripleRequestGenerator : ITripleTripleRequestGenerator
2222

2323
public IndexerPageableRequestChain GetSearchRequests(AlbumSearchCriteria searchCriteria)
2424
{
25-
string query = string.Join(' ', new[] { searchCriteria.AlbumQuery, searchCriteria.ArtistQuery }.Where(s => !string.IsNullOrWhiteSpace(s)));
2625
bool isSingle = searchCriteria.Albums?.FirstOrDefault()?.AlbumReleases?.Value?.Min(r => r.TrackCount) == 1;
27-
return Generate(query, isSingle);
26+
return Generate(searchCriteria.ArtistQuery, searchCriteria.AlbumQuery, isSingle);
2827
}
2928

30-
public IndexerPageableRequestChain GetSearchRequests(ArtistSearchCriteria searchCriteria) => Generate(searchCriteria.ArtistQuery, false);
29+
public IndexerPageableRequestChain GetSearchRequests(ArtistSearchCriteria searchCriteria) => Generate(searchCriteria.ArtistQuery, null, false);
3130

3231
public void SetSetting(TripleTripleIndexerSettings settings) => _settings = settings;
3332

34-
private IndexerPageableRequestChain Generate(string query, bool isSingle)
33+
private IndexerPageableRequestChain Generate(string? artistQuery, string? albumQuery, bool isSingle)
3534
{
3635
IndexerPageableRequestChain chain = new();
37-
if (string.IsNullOrWhiteSpace(query))
36+
string combinedQuery = string.Join(' ', new[] { albumQuery, artistQuery }.Where(s => !string.IsNullOrWhiteSpace(s)));
37+
if (string.IsNullOrWhiteSpace(combinedQuery))
3838
{
3939
_logger.Warn("Empty query, skipping search request");
4040
return chain;
4141
}
4242

43+
string type = isSingle ? "track" : "album";
44+
45+
chain.AddTier([CreateRequest(combinedQuery, type, isSingle)]);
46+
47+
string? fallbackQuery = !string.IsNullOrWhiteSpace(artistQuery) ? artistQuery : albumQuery;
48+
if (!string.IsNullOrWhiteSpace(fallbackQuery) && !string.Equals(fallbackQuery, combinedQuery, StringComparison.OrdinalIgnoreCase))
49+
chain.AddTier([CreateRequest(fallbackQuery, type, isSingle)]);
50+
51+
if (isSingle)
52+
chain.AddTier([CreateRequest(combinedQuery, "album", true)]);
53+
54+
return chain;
55+
}
56+
57+
private IndexerRequest CreateRequest(string query, string type, bool isSingle)
58+
{
4359
string baseUrl = _settings!.BaseUrl.TrimEnd('/');
4460
string country = ((TripleTripleCountry)_settings.CountryCode).ToString();
4561
string codec = ((TripleTripleCodec)_settings.Codec).ToString().ToLowerInvariant();
4662

47-
string url = $"{baseUrl}/api/amazon-music/search?query={Uri.EscapeDataString(query)}&types=track,album&country={country}";
63+
string url = $"{baseUrl}/api/amazon-music/search?query={Uri.EscapeDataString(query)}&type={type}&country={country}";
4864
_logger.Trace("Creating TripleTriple search request: {Url}", url);
4965

5066
HttpRequest req = new(url)
@@ -55,25 +71,7 @@ private IndexerPageableRequestChain Generate(string query, bool isSingle)
5571
req.Headers["User-Agent"] = Tubifarry.UserAgent;
5672
req.Headers["Referer"] = $"{baseUrl}/search/{Uri.EscapeDataString(query)}";
5773

58-
chain.AddTier([new IndexerRequest(req)]);
59-
60-
if (isSingle)
61-
{
62-
string fallbackUrl = $"{baseUrl}/api/amazon-music/search?query={Uri.EscapeDataString(query)}&types=track&country={country}";
63-
_logger.Trace("Adding fallback track-only search: {Url}", fallbackUrl);
64-
65-
HttpRequest fallbackReq = new(fallbackUrl)
66-
{
67-
RequestTimeout = TimeSpan.FromSeconds(_settings.RequestTimeout),
68-
ContentSummary = new TripleTripleRequestData(baseUrl, country, codec, true).ToJson()
69-
};
70-
fallbackReq.Headers["User-Agent"] = Tubifarry.UserAgent;
71-
fallbackReq.Headers["Referer"] = $"{baseUrl}/search/{Uri.EscapeDataString(query)}";
72-
73-
chain.AddTier([new IndexerRequest(fallbackReq)]);
74-
}
75-
76-
return chain;
74+
return new IndexerRequest(req);
7775
}
7876
}
7977
}

0 commit comments

Comments
 (0)