Refactor QueryResults
I don't think I've really accomplished anything lol, and I think I'll rename MBQ again. I also don't need a lessThan function for both Release and Recording, I'll just pull that out and have it compare u8 slices agnostic of the underlying type. It feels nicer having all the ID getting functions under one umbrella, but it definitely could be better. Need to look into inlining I think
This commit is contained in:
parent
5e5abc7bf3
commit
fa46f68fd0
5 changed files with 405 additions and 149 deletions
|
|
@ -40,6 +40,10 @@
|
|||
.url = "https://github.com/rockorager/zeit/archive/refs/tags/v0.6.0.tar.gz",
|
||||
.hash = "zeit-0.0.0-5I6bk_pZAgB03N1p1GmVOZ--gOFwwQSRKj1UXb5tnaKS",
|
||||
},
|
||||
//.zg = .{
|
||||
// .url = "https://codeberg.org/atman/zg/archive/v0.13.4.tar.gz",
|
||||
// .hash = "zg-0.13.4-AAAAAAiZ7QL-QuOf0UHIT9fVz2mUUwm7RyUwM-aHiPmb",
|
||||
//},
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
|
|
|
|||
|
|
@ -81,6 +81,31 @@ pub const Release = struct {
|
|||
@"release-events": ?[]ReleaseEvent = null,
|
||||
//release_events: ?[]ReleaseEvent = null,
|
||||
disambiguation: ?[]const u8 = null,
|
||||
|
||||
pub fn lessThan(context: void, a: Release, b: Release) bool {
|
||||
_ = context; // Idk what this is but it's in the Zig docs
|
||||
if (a.date) |adtstr| {
|
||||
if (b.date) |bdtstr| {
|
||||
const adtyr = std.fmt.parseInt(u32, adtstr[0..4], 10) catch 0; // Each `catch 0` is to avoid returning an error
|
||||
const bdtyr = std.fmt.parseInt(u32, bdtstr[0..4], 10) catch 0;
|
||||
if (adtyr != bdtyr) {
|
||||
return adtyr < bdtyr;
|
||||
} else if (adtstr.len > 7) {
|
||||
if (bdtstr.len < 7) return true; // a provides more information
|
||||
const adtmn = std.fmt.parseInt(u32, adtstr[5..7], 10) catch 0;
|
||||
const bdtmn = std.fmt.parseInt(u32, bdtstr[5..7], 10) catch 0;
|
||||
if (adtmn != bdtmn) {
|
||||
return adtmn < bdtmn;
|
||||
} else if (adtstr.len == 10) {
|
||||
if (bdtstr.len < 10) return true; // a provides more information
|
||||
const adtdy = std.fmt.parseInt(u32, adtstr[8..10], 10) catch 0;
|
||||
const bdtdy = std.fmt.parseInt(u32, bdtstr[8..10], 10) catch 0;
|
||||
return adtdy < bdtdy;
|
||||
} else return false; // Either b provides more information, or they're the same date
|
||||
} else return false; // Either b provides more information, or they're the same date
|
||||
} else return true; // b provides no information
|
||||
} else return false; // a provides no information
|
||||
}
|
||||
};
|
||||
pub const Medium = struct {
|
||||
position: ?u32 = null,
|
||||
|
|
|
|||
298
src/MusicBrainzQuery.zig
Normal file
298
src/MusicBrainzQuery.zig
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
|
||||
const Entities = @import("Entities.zig");
|
||||
const Artist = Entities.Artist;
|
||||
const Recording = Entities.Recording;
|
||||
const Release = Entities.Release;
|
||||
|
||||
pub const parseOption = union(enum) {
|
||||
song,
|
||||
album,
|
||||
artist,
|
||||
all,
|
||||
};
|
||||
|
||||
pub const parseByOptions = struct { parse: parseOption = .song, specifyBy: parseOption = .song };
|
||||
|
||||
pub const Result = struct {
|
||||
created: ?[]const u8 = null,
|
||||
count: ?u32 = null,
|
||||
offset: ?u32 = null,
|
||||
artists: ?[]Artist = null,
|
||||
recordings: ?[]Recording = null,
|
||||
@"error": ?[]const u8 = null,
|
||||
help: ?[]const u8 = null,
|
||||
|
||||
pub fn getIDs(self: *const Result, smd: searchMetadata, pbo: parseByOptions) ?searchIDs {
|
||||
if (self.count) |count| {
|
||||
if (count == 0) return null;
|
||||
const sorted_recordings = self.recordings.?;
|
||||
std.mem.sort(Recording, sorted_recordings, {}, Recording.lessThan);
|
||||
rc_loop: for (sorted_recordings) |rc| {
|
||||
switch (pbo.parse) {
|
||||
.song => {
|
||||
var output = searchIDs{ .id = "" };
|
||||
switch (pbo.specifyBy) {
|
||||
.song => {
|
||||
if (std.mem.eql(u8, rc.title, smd.tn)) {
|
||||
output.id = rc.id;
|
||||
break :rc_loop;
|
||||
}
|
||||
},
|
||||
.album => {
|
||||
if (rc.releases) |rls| {
|
||||
for (rls) |rl| {
|
||||
if (std.mem.eql(u8, rl.title, smd.rgn)) {
|
||||
output.id = rc.id;
|
||||
break :rc_loop;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std.log.err("Could not find any releases", .{});
|
||||
}
|
||||
},
|
||||
.artist => {
|
||||
if (rc.@"artist-credit") |acs| {
|
||||
for (acs) |ac| {
|
||||
if (std.mem.eql(u8, ac.name, smd.an)) {
|
||||
output.id = rc.id;
|
||||
break :rc_loop;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std.log.err("Could not find any artists", .{});
|
||||
}
|
||||
},
|
||||
.all => unreachable, // I'll do this later
|
||||
}
|
||||
return output;
|
||||
},
|
||||
.album => {
|
||||
const output = searchIDs{ .id = blk: {
|
||||
if (rc.releases) |rls| {
|
||||
const sorted_releases = rls;
|
||||
std.mem.sort(Release, sorted_releases, {}, Release.lessThan);
|
||||
for (sorted_releases) |rl| {
|
||||
switch (pbo.specifyBy) {
|
||||
.song, .album => {
|
||||
if (std.mem.eql(u8, rl.title, smd.rgn)) break :blk rl.id;
|
||||
},
|
||||
.artist => {
|
||||
if (rl.@"artist-credit") |acs| {
|
||||
for (acs) |ac| {
|
||||
if (std.mem.eql(u8, ac.name, smd.an)) break :blk rl.id;
|
||||
}
|
||||
}
|
||||
},
|
||||
.all => unreachable,
|
||||
}
|
||||
}
|
||||
break :blk "";
|
||||
} else break :blk "";
|
||||
} };
|
||||
return output;
|
||||
},
|
||||
.artist => {
|
||||
const output = searchIDs{ .id = switch (pbo.specifyBy) {
|
||||
.song, .artist => blk: {
|
||||
if (rc.@"artist-credit") |acs| {
|
||||
for (acs) |ac| {
|
||||
if (std.mem.eql(u8, ac.name, smd.an)) break :blk ac.artist.id;
|
||||
}
|
||||
}
|
||||
break :blk "";
|
||||
},
|
||||
.album => blk: {
|
||||
if (rc.releases) |rls| {
|
||||
for (rls) |rl| {
|
||||
if (rl.@"artist-credit") |acs| {
|
||||
for (acs) |ac| {
|
||||
if (std.mem.eql(u8, ac.name, smd.an)) break :blk ac.artist.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break :blk "";
|
||||
},
|
||||
.all => unreachable,
|
||||
} };
|
||||
return output;
|
||||
},
|
||||
.all => {
|
||||
var output = searchIDs{ .ids = undefined };
|
||||
if (self.getIDs(smd, .{ .parse = .song })) |ids| output.ids.song_id = ids.id;
|
||||
if (self.getIDs(smd, .{ .parse = .album })) |ids| output.ids.album_id = ids.id;
|
||||
if (self.getIDs(smd, .{ .parse = .artist })) |ids| output.ids.artist_id = ids.id;
|
||||
return output;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//pub fn getArtistID(self: *const Result, smd: searchMetadata, parseByOption: ?parseByOptions) ?[]const u8 {
|
||||
// _ = parseByOption; //
|
||||
// if (self.count) |count| { // Otherwise there was an error
|
||||
// switch (count) {
|
||||
// 0 => return null, // No results
|
||||
// 1 => {
|
||||
// if (self.recordings.?[0].@"artist-credit") |acs| {
|
||||
// for (acs) |ac| {
|
||||
// if (std.mem.eql(u8, ac.name, smd.an)) return ac.artist.id; // Make this case/diacritic insensitive
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
// else => {
|
||||
// for (self.recordings.?) |rc| {
|
||||
// if (std.mem.eql(u8, rc.title, smd.tn)) { // Make this case/diacritic insensitive
|
||||
// for (rc.@"artist-credit".?) |ac| {
|
||||
// if (std.mem.eql(u8, ac.name, smd.an)) return ac.artist.id;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
// return null; // Maybe return error here instead
|
||||
//}
|
||||
|
||||
//// Not sure if I want to get a ReleaseGroup or Release yet. Start with ReleaseGroup
|
||||
//pub fn getReleaseGroupID(self: *const Result, smd: searchMetadata) ?[]const u8 {
|
||||
// if (self.count) |count| {
|
||||
// switch (count) {
|
||||
// 0 => return null,
|
||||
// 1 => {
|
||||
// switch (self.recordings.?[0].releases.?.len) {
|
||||
// 0 => unreachable,
|
||||
// 1 => return self.recordings.?[0].releases.?[0].id,
|
||||
// else => {
|
||||
// for (self.recordings.?[0].releases.?) |re| {
|
||||
// if (std.mem.eql(u8, re.title, smd.rgn)) return re.id;
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// },
|
||||
// else => { // This is not ideal, limit the number of results
|
||||
// for (self.recordings.?) |rc| {
|
||||
// if (std.mem.eql(u8, rc.title, smd.tn)) {
|
||||
// for (rc.releases.?) |re| {
|
||||
// if (std.mem.eql(u8, re.@"release-group".?.title, smd.rgn)) return re.@"release-group".?.id;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//pub fn getRecordingID(self: *const Result, smd: searchMetadata) ?[]const u8 {
|
||||
// if (self.count) |count| {
|
||||
// switch (count) {
|
||||
// 0 => return null,
|
||||
// 1 => return self.recordings.?[0].id,
|
||||
// else => {
|
||||
// const rcs: []Recording = self.recordings.?;
|
||||
// //for (rcs, 0..) |rc, i| {
|
||||
// // rcs[i].dt = (try zeit.instant(.{ .source = .{ .iso8601 = rc.@"first-release-date".? } })).unixTimestamp();
|
||||
// //}
|
||||
// std.mem.sort(Recording, rcs, {}, Recording.lessThan);
|
||||
// for (rcs) |rc| {
|
||||
// if (std.mem.eql(u8, smd.tn, rc.title)) {
|
||||
// for (rc.@"artist-credit".?) |ac| {
|
||||
// if (std.mem.eql(u8, smd.an, ac.name)) {
|
||||
// for (rc.releases.?) |re| {
|
||||
// if (std.mem.eql(u8, smd.rgn, re.@"release-group".?.title)) {
|
||||
// //std.log.err("{s}", .{rc.id});
|
||||
// return rc.id;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
};
|
||||
|
||||
pub const searchMetadata = struct {
|
||||
tn: []const u8,
|
||||
rgn: []const u8,
|
||||
an: []const u8,
|
||||
};
|
||||
|
||||
// I don't think I need a second type, but I'd like to hold on to the original, unencoded metadata as well, so maybe this is fine
|
||||
// Maybe make fields for encoded data?
|
||||
pub const searchMetadataEncoded = struct {
|
||||
alloc: std.mem.Allocator,
|
||||
tn: []const u8,
|
||||
rgn: []const u8,
|
||||
an: []const u8,
|
||||
|
||||
pub fn deinit(self: *const searchMetadataEncoded) void {
|
||||
self.alloc.free(self.an);
|
||||
self.alloc.free(self.rgn);
|
||||
self.alloc.free(self.tn);
|
||||
}
|
||||
};
|
||||
|
||||
pub const searchIDs = union {
|
||||
id: []const u8,
|
||||
ids: struct {
|
||||
artist_id: ?[]const u8,
|
||||
album_id: ?[]const u8,
|
||||
song_id: ?[]const u8,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn percentEncode(alloc: std.mem.Allocator, smd: searchMetadata) !searchMetadataEncoded {
|
||||
var output = searchMetadataEncoded{ .alloc = alloc, .tn = undefined, .rgn = undefined, .an = undefined };
|
||||
inline for (std.meta.fields(searchMetadata)) |k| {
|
||||
var encoded = std.ArrayList(u8).init(alloc);
|
||||
errdefer encoded.deinit();
|
||||
for (@field(smd, k.name)) |v| {
|
||||
if ((v >= 'A' and v <= 'Z') or (v >= 'a' and v <= 'z') or (v >= '0' and v <= '9') or v == '-' or v == '_' or v == '.' or v == '~') {
|
||||
try encoded.append(v);
|
||||
} else if (v == ' ') {
|
||||
try encoded.append('+');
|
||||
} else {
|
||||
const hex = try std.fmt.allocPrint(alloc, "%{x}", .{v});
|
||||
defer alloc.free(hex);
|
||||
try encoded.appendSlice(hex);
|
||||
}
|
||||
}
|
||||
@field(output, k.name) = try encoded.toOwnedSlice();
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
test "pe_jethro_tull" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
const jt = searchMetadata{ .tn = "Aqualung", .rgn = "Aqualung", .an = "Jethro Tull" };
|
||||
const encoded = try percentEncode(test_alloc, jt);
|
||||
defer encoded.deinit();
|
||||
try testing.expect(std.mem.eql(u8, encoded.an, "Jethro+Tull"));
|
||||
}
|
||||
|
||||
test "pe_aphex_twin" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
const at = searchMetadata{ .tn = "#3", .rgn = "Selected Ambient Works Volume II", .an = "Aphex Twin" };
|
||||
const encoded = try percentEncode(test_alloc, at);
|
||||
defer encoded.deinit();
|
||||
try testing.expect(std.mem.eql(u8, encoded.tn, "%233"));
|
||||
}
|
||||
|
||||
test "pe_bon_iver" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
const bi = searchMetadata{ .tn = "21 M♢♢N WATER", .rgn = "22, a Million", .an = "Bon Iver" };
|
||||
const encoded = try percentEncode(test_alloc, bi);
|
||||
defer encoded.deinit();
|
||||
try testing.expect(std.mem.eql(u8, encoded.tn, "21+M%e2%99%a2%e2%99%a2N+WATER"));
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
const std = @import("std");
|
||||
//const zeit = @import("zeit");
|
||||
|
||||
const Entities = @import("Entities.zig");
|
||||
const Artist = Entities.Artist;
|
||||
const Recording = Entities.Recording;
|
||||
|
||||
pub const Result = struct {
|
||||
created: ?[]const u8 = null,
|
||||
//created: ?zeit.Instant.Source.iso8601 = null,
|
||||
count: ?u32 = null,
|
||||
offset: ?u32 = null,
|
||||
artists: ?[]Artist = null,
|
||||
recordings: ?[]Recording = null,
|
||||
@"error": ?[]const u8 = null,
|
||||
help: ?[]const u8 = null,
|
||||
|
||||
pub fn getSpecifiedARID(self: *const Result, an: []const u8, tn: []const u8) ?[]const u8 {
|
||||
if (self.count) |count| { // Otherwise there was an error
|
||||
switch (count) {
|
||||
0 => return null, // No results
|
||||
1 => {
|
||||
switch (self.recordings.?[0].@"artist-credit".?.len) {
|
||||
0 => unreachable, // All recordings have at least one ArtistCredit
|
||||
1 => return self.recordings.?[0].@"artist-credit".?[0].artist.id,
|
||||
else => {
|
||||
for (self.recordings.?[0].@"artist-credit".?) |ac| {
|
||||
if (std.mem.eql(u8, ac.name, an)) return ac.artist.id;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
else => {
|
||||
for (self.recordings.?) |rc| {
|
||||
if (std.mem.eql(u8, rc.title, tn)) { // I'd really prefer not including track name, but for complete accuracy
|
||||
for (rc.@"artist-credit".?) |ac| {
|
||||
if (std.mem.eql(u8, ac.name, an)) return ac.artist.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
return null; // Maybe return error here instead
|
||||
}
|
||||
|
||||
// Not sure if I want to get a ReleaseGroup or Release yet. Start with ReleaseGroup
|
||||
pub fn getSpecifiedRGID(self: *const Result, tn: []const u8, rgn: []const u8) ?[]const u8 {
|
||||
if (self.count) |count| {
|
||||
switch (count) {
|
||||
0 => return null,
|
||||
1 => {
|
||||
switch (self.recordings.?[0].releases.?.len) {
|
||||
0 => unreachable,
|
||||
1 => return self.recordings.?[0].releases.?[0].id,
|
||||
else => {
|
||||
for (self.recordings.?[0].releases.?) |re| {
|
||||
if (std.mem.eql(u8, re.title, rgn)) return re.id;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
else => { // This is not ideal, limit the number of results
|
||||
for (self.recordings.?) |rc| {
|
||||
if (std.mem.eql(u8, rc.title, tn)) {
|
||||
for (rc.releases.?) |re| {
|
||||
if (std.mem.eql(u8, re.@"release-group".?.title, rgn)) return re.@"release-group".?.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn getSpecifiedRID(self: *const Result, tn: []const u8, rgn: []const u8, an: []const u8) !?[]const u8 {
|
||||
if (self.count) |count| {
|
||||
switch (count) {
|
||||
0 => return null,
|
||||
1 => return self.recordings.?[0].id,
|
||||
else => {
|
||||
const rcs: []Recording = self.recordings.?;
|
||||
//for (rcs, 0..) |rc, i| {
|
||||
// rcs[i].dt = (try zeit.instant(.{ .source = .{ .iso8601 = rc.@"first-release-date".? } })).unixTimestamp();
|
||||
//}
|
||||
std.mem.sort(Recording, rcs, {}, Recording.lessThan);
|
||||
for (rcs) |rc| {
|
||||
if (std.mem.eql(u8, tn, rc.title)) {
|
||||
for (rc.@"artist-credit".?) |ac| {
|
||||
if (std.mem.eql(u8, an, ac.name)) {
|
||||
for (rc.releases.?) |re| {
|
||||
if (std.mem.eql(u8, rgn, re.@"release-group".?.title)) {
|
||||
//std.log.err("{s}", .{rc.id});
|
||||
return rc.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
120
src/root.zig
120
src/root.zig
|
|
@ -1,18 +1,20 @@
|
|||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const zeit = @import("zeit");
|
||||
//const zeit = @import("zeit");
|
||||
const Entities = @import("Entities.zig");
|
||||
const Alias = @import("Alias.zig");
|
||||
const QR = @import("QueryResults.zig");
|
||||
const MBQ = @import("MusicBrainzQuery.zig");
|
||||
const Client = std.http.Client;
|
||||
|
||||
pub const user_agent: []const u8 = "ZuletztMBClient/0.0.1 (swebbguy@gmail.com)";
|
||||
|
||||
pub fn mbSearch(allocator: std.mem.Allocator, ar: *std.ArrayList(u8), track_name: []const u8, album_name: []const u8, artist_name: []const u8) !?[]const u8 {
|
||||
pub fn mbSearch(allocator: std.mem.Allocator, ar: *std.ArrayList(u8), smd: MBQ.searchMetadata) !?[]const u8 {
|
||||
const encoded = try MBQ.percentEncode(allocator, smd);
|
||||
defer encoded.deinit();
|
||||
var client = Client{ .allocator = allocator };
|
||||
defer client.deinit();
|
||||
|
||||
const query: []const u8 = try std.fmt.allocPrint(allocator, "https://musicbrainz.org/ws/2/recording/?query=\"{s}\"%20AND%20artist:\"{s}\"%20AND%20release:\"{s}\"&fmt=json", .{ track_name, artist_name, album_name });
|
||||
const query: []const u8 = try std.fmt.allocPrint(allocator, "https://musicbrainz.org/ws/2/recording/?query=\"{s}\"%20AND%20artist:\"{s}\"%20AND%20release:\"{s}\"&fmt=json", .{ encoded.tn, encoded.an, encoded.rgn });
|
||||
defer allocator.free(query);
|
||||
|
||||
const response: Client.FetchResult = try client.fetch(.{ .response_storage = .{ .dynamic = ar }, .location = .{ .url = query }, .method = .GET, .headers = .{ .user_agent = .{ .override = user_agent } } });
|
||||
|
|
@ -42,95 +44,104 @@ pub fn mbSearch(allocator: std.mem.Allocator, ar: *std.ArrayList(u8), track_name
|
|||
// it shouldn't need changing too often
|
||||
test "arid_via_recording" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
const track: []const u8 = "Veni%20Veni%20Emmanuel";
|
||||
const album: []const u8 = "Counting%20the%20Ghosts";
|
||||
const artist: []const u8 = "Iamthemorning";
|
||||
|
||||
const metadata = MBQ.searchMetadata{ .tn = "Veni veni Emmanuel", .an = "iamthemorning", .rgn = "Counting the Ghosts" };
|
||||
const iatm_id: []const u8 = "5854a6de-af8f-4b99-8710-cb47d6436a19";
|
||||
|
||||
var mb_result = std.ArrayList(u8).init(test_alloc);
|
||||
defer mb_result.deinit();
|
||||
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, track, album, artist);
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, metadata);
|
||||
|
||||
if (search_result) |sr| {
|
||||
const json = try std.json.parseFromSlice(QR.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
const json = try std.json.parseFromSlice(MBQ.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
defer json.deinit();
|
||||
|
||||
const result: QR.Result = json.value;
|
||||
const result: MBQ.Result = json.value;
|
||||
const id = result.getIDs(metadata, .{ .parse = .artist, .specifyBy = .song });
|
||||
|
||||
std.Thread.sleep(1000000000);
|
||||
|
||||
try testing.expect(std.mem.eql(u8, result.getSpecifiedARID(artist, "Veni veni Emmanuel").?, iatm_id));
|
||||
if (id) |out| {
|
||||
try testing.expect(std.mem.eql(u8, out.id, iatm_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test "arid_via_recording_multiple_artists_1" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
const track: []const u8 = "Roll%20Me%20Up%20And%20Smoke%20Me%20When%20I%20Die";
|
||||
const album: []const u8 = "Willie%20Nelson%20American%20Outlaw";
|
||||
const artist: []const u8 = "Lyle%20Lovett";
|
||||
|
||||
const metadata = MBQ.searchMetadata{ .tn = "Roll Me Up And Smoke Me When I Die", .an = "Lyle Lovett", .rgn = "Willie Nelson American Outlaw" };
|
||||
const ll_id: []const u8 = "7241e3ed-5ad4-4849-94df-6858ea833472";
|
||||
|
||||
var mb_result = std.ArrayList(u8).init(test_alloc);
|
||||
defer mb_result.deinit();
|
||||
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, track, album, artist);
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, metadata);
|
||||
|
||||
if (search_result) |sr| {
|
||||
const json = try std.json.parseFromSlice(QR.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
const json = try std.json.parseFromSlice(MBQ.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
defer json.deinit();
|
||||
|
||||
const result: QR.Result = json.value;
|
||||
const result: MBQ.Result = json.value;
|
||||
const id = result.getIDs(metadata, .{ .parse = .artist, .specifyBy = .song });
|
||||
|
||||
std.Thread.sleep(1000000000);
|
||||
try testing.expect(std.mem.eql(u8, result.getSpecifiedARID("Lyle Lovett", "Roll Me Up and Smoke Me When I Die").?, ll_id));
|
||||
|
||||
if (id) |out| {
|
||||
try testing.expect(std.mem.eql(u8, out.id, ll_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test "rgid_via_recording" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
const track: []const u8 = "I%20Of%20The%20Storm";
|
||||
const album: []const u8 = "Beneath%20The%20Skin";
|
||||
const artist: []const u8 = "Of%20Monsters%20and%20Men";
|
||||
|
||||
const bts_id: []const u8 = "2e1e605d-5090-420d-beae-e7ff73791082";
|
||||
const metadata = MBQ.searchMetadata{ .tn = "I Of The Storm", .rgn = "Beneath the Skin", .an = "Of Monsters and Men" };
|
||||
const bts_id: []const u8 = "4f4f5b98-45ac-4b47-addb-66b501473bd8";
|
||||
|
||||
var mb_result = std.ArrayList(u8).init(test_alloc);
|
||||
defer mb_result.deinit();
|
||||
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, track, album, artist);
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, metadata);
|
||||
|
||||
if (search_result) |sr| {
|
||||
const json = try std.json.parseFromSlice(QR.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
const json = try std.json.parseFromSlice(MBQ.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
defer json.deinit();
|
||||
|
||||
const result: QR.Result = json.value;
|
||||
const result: MBQ.Result = json.value;
|
||||
const id = result.getIDs(metadata, .{ .parse = .album, .specifyBy = .song });
|
||||
|
||||
std.Thread.sleep(1000000000);
|
||||
try testing.expect(std.mem.eql(u8, result.getSpecifiedRGID("I of the Storm", "Beneath the Skin").?, bts_id));
|
||||
|
||||
if (id) |out| {
|
||||
try testing.expect(std.mem.eql(u8, out.id, bts_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test "rgid_via_recording_multiple_artists_2" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
const track: []const u8 = "Hesitating%20Beauty";
|
||||
const album: []const u8 = "Mermaid%20Avenue";
|
||||
const artist: []const u8 = "Wilco";
|
||||
|
||||
const wilco_id: []const u8 = "9e53f84d-ef44-4c16-9677-5fd4d78cbd7d";
|
||||
const metadata = MBQ.searchMetadata{ .tn = "Hesitating Beauty", .rgn = "Mermaid Avenue", .an = "Wilco" };
|
||||
const wilco_id: []const u8 = "9ba73bf8-6c15-4bd2-8da1-e2292538f617";
|
||||
|
||||
var mb_result = std.ArrayList(u8).init(test_alloc);
|
||||
defer mb_result.deinit();
|
||||
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, track, album, artist);
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, metadata);
|
||||
|
||||
if (search_result) |sr| {
|
||||
const json = try std.json.parseFromSlice(QR.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
const json = try std.json.parseFromSlice(MBQ.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
defer json.deinit();
|
||||
|
||||
const result: QR.Result = json.value;
|
||||
const result: MBQ.Result = json.value;
|
||||
const id = result.getIDs(metadata, .{ .parse = .album, .specifyBy = .song });
|
||||
|
||||
std.Thread.sleep(1000000000);
|
||||
try testing.expect(std.mem.eql(u8, result.getSpecifiedARID("Wilco", "Hesitating Beauty").?, wilco_id));
|
||||
if (id) |out| {
|
||||
try testing.expect(std.mem.eql(u8, out.id, wilco_id));
|
||||
}
|
||||
}
|
||||
|
||||
//try testing.expect(false);
|
||||
|
|
@ -138,23 +149,48 @@ test "rgid_via_recording_multiple_artists_2" {
|
|||
|
||||
test "rid_aqualung" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
const track: []const u8 = "Aqualung";
|
||||
const album: []const u8 = "Aqualung";
|
||||
const artist: []const u8 = "Jethro%20Tull";
|
||||
|
||||
const battery_id: []const u8 = "2621d113-3a9f-41f9-a0f2-b9459f86e8e9";
|
||||
const metadata = MBQ.searchMetadata{ .tn = "Aqualung", .rgn = "Aqualung", .an = "Jethro Tull" };
|
||||
const aqualung_id: []const u8 = "2621d113-3a9f-41f9-a0f2-b9459f86e8e9";
|
||||
|
||||
var mb_result = std.ArrayList(u8).init(test_alloc);
|
||||
defer mb_result.deinit();
|
||||
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, track, album, artist);
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, metadata);
|
||||
|
||||
if (search_result) |sr| {
|
||||
const json = try std.json.parseFromSlice(QR.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
const json = try std.json.parseFromSlice(MBQ.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
defer json.deinit();
|
||||
|
||||
const result: QR.Result = json.value;
|
||||
const result: MBQ.Result = json.value;
|
||||
const id = result.getIDs(metadata, .{ .parse = .song, .specifyBy = .song });
|
||||
|
||||
try testing.expect(std.mem.eql(u8, (try result.getSpecifiedRID("Aqualung", "Aqualung", "Jethro Tull")).?, battery_id));
|
||||
if (id) |out| {
|
||||
try testing.expect(std.mem.eql(u8, out.id, aqualung_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test "rid_battery" {
|
||||
const test_alloc = std.testing.allocator;
|
||||
|
||||
const metadata = MBQ.searchMetadata{ .tn = "Battery", .rgn = "Master of Puppets", .an = "Metallica" };
|
||||
const battery_id: []const u8 = "3bfda26a-49fa-4bc4-a4d6-8bbfa0767ab7";
|
||||
|
||||
var mb_result = std.ArrayList(u8).init(test_alloc);
|
||||
defer mb_result.deinit();
|
||||
|
||||
const search_result = try mbSearch(test_alloc, &mb_result, metadata);
|
||||
|
||||
if (search_result) |sr| {
|
||||
const json = try std.json.parseFromSlice(MBQ.Result, test_alloc, sr, .{ .ignore_unknown_fields = true });
|
||||
defer json.deinit();
|
||||
|
||||
const result: MBQ.Result = json.value;
|
||||
const id = result.getIDs(metadata, .{ .parse = .song, .specifyBy = .song });
|
||||
|
||||
if (id) |out| {
|
||||
try testing.expect(std.mem.eql(u8, out.id, battery_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue