Implement mbSearch()
Getting a segfault, not sure why
This commit is contained in:
parent
1d4f79206a
commit
454505335c
4 changed files with 120 additions and 173 deletions
|
|
@ -1,13 +1,14 @@
|
||||||
const MBID = @import("MBID.zig");
|
|
||||||
|
|
||||||
pub const Alias = struct {
|
pub const Alias = struct {
|
||||||
|
@"sort-name": []const u8,
|
||||||
|
//sort_name: []const u8,
|
||||||
|
@"type-id": []const u8,
|
||||||
|
//type_id: []const u8,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
sort_name: []const u8,
|
|
||||||
type_id: ?MBID,
|
|
||||||
type: ?[]const u8, // Could be an enum
|
|
||||||
locale: ?[]const u8,
|
locale: ?[]const u8,
|
||||||
primary: ?bool,
|
type: []const u8,
|
||||||
begin: ?i64,
|
primary: ?[]const u8,
|
||||||
end: ?i64,
|
@"begin-date": ?[]const u8,
|
||||||
ended: bool,
|
//begin_date: []const u8,
|
||||||
|
@"end-date": ?[]const u8,
|
||||||
|
//end_date: []const u8,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
214
src/Entities.zig
214
src/Entities.zig
|
|
@ -1,173 +1,85 @@
|
||||||
//! Types of MusicBrainz Entities described here: https://musicbrainz.org/doc/MusicBrainz_Entity
|
//! Types of MusicBrainz Entities described here: https://musicbrainz.org/doc/MusicBrainz_Entity
|
||||||
//! Fields based on JSON response fields
|
//! Fields based on JSON response fields
|
||||||
|
|
||||||
const MBID = @import("MBID.zig");
|
const Alias = @import("Alias.zig").Alias;
|
||||||
const Alias = @import("Alias.zig");
|
|
||||||
//const zeit = @import("zeit");
|
|
||||||
|
|
||||||
pub const Artist = struct {
|
pub const Artist = struct {
|
||||||
id: MBID,
|
id: []const u8,
|
||||||
type: enum([]const u8) { Person, Group, Orchestra, Choir, Character, Other },
|
|
||||||
type_id: MBID,
|
|
||||||
score: u8,
|
|
||||||
gender_id: ?MBID,
|
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
sort_name: []const u8,
|
@"sort-name": []const u8,
|
||||||
gender: ?enum([]const u8) { male, female, other },
|
//sort_name: []const u8,
|
||||||
country: ?[]const u8,
|
aliases: ?[]Alias = null,
|
||||||
area: ?Area,
|
|
||||||
begin_area: ?Area,
|
|
||||||
end_area: ?Area,
|
|
||||||
disambiguation: ?[]const u8,
|
|
||||||
ipis: ?[][]const u8,
|
|
||||||
isnis: ?[][]const u8,
|
|
||||||
life_span: struct { ended: ?bool, begin: []const u8, end: ?[]const u8 },
|
|
||||||
aliases: ?[]Alias,
|
|
||||||
tags: ?[]struct { count: i32, name: []const u8 },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ArtistCredit = struct { artists: []Artist, artists_names: ?[][]const u8, artists_join_phrase: ?[]const u8, mbid: MBID, name: []const u8 };
|
pub const ArtistCredit = struct {
|
||||||
|
|
||||||
pub const Event = struct {
|
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
type: enum { concert, festival, stage_performance, award_ceremony, launch_event, convention_expo, masterclass_clinic },
|
artist: Artist,
|
||||||
cancelled: bool,
|
|
||||||
dates: struct { begin: i64, end: i64 },
|
|
||||||
selist: []const u8, //Will need to write a parser for this
|
|
||||||
time: []const u8,
|
|
||||||
aliases: ?[]Alias,
|
|
||||||
disambiguation: []const u8,
|
|
||||||
annotation: []const u8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Label = struct {
|
|
||||||
name: []const u8,
|
|
||||||
disambiguation: []const u8,
|
|
||||||
type: []enum {
|
|
||||||
imprint,
|
|
||||||
original_production,
|
|
||||||
bootleg_production,
|
|
||||||
reissue_production,
|
|
||||||
distributor,
|
|
||||||
holding,
|
|
||||||
rights_society,
|
|
||||||
},
|
|
||||||
area: []const u8, // This in ISO-3166 format, and is referred to as "Country" on a different page
|
|
||||||
label_code: []const u8,
|
|
||||||
ipi_codes: [][]const u8, // There could be multiple for artists, unsure about albums
|
|
||||||
isni_codes: [][]const u8, // See above
|
|
||||||
date_period: struct { begin_date: i64, end_date: i64 },
|
|
||||||
aliases: ?[]Alias,
|
|
||||||
annotation: []const u8,
|
|
||||||
mbid: MBID,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Place = struct { name: []const u8, type: enum([]const u8) { studio, venue = enum { ampitheatre, club, concert_hall_theatre, festival_stage }, stadium, indoor_arena, educational_institution, park, religious_building, pressing_plant, other }, address: []const u8, coordinates: struct { lat: i32, lon: i32 }, area: ?Area, dates: struct { begin: i64, end: i64 }, aliases: ?[]Alias, mbid: MBID, disambiguation: []const u8, annotation: []const u8 };
|
|
||||||
|
|
||||||
pub const Recording = struct {
|
pub const Recording = struct {
|
||||||
|
id: []const u8,
|
||||||
|
score: u8,
|
||||||
title: []const u8,
|
title: []const u8,
|
||||||
artists: []Artist,
|
length: u64,
|
||||||
length: f64, // I don't know what this looks like yet
|
video: ?bool,
|
||||||
isrc: []const u8,
|
@"artist-credit": []ArtistCredit,
|
||||||
mbid: MBID,
|
//artist_credit: []ArtistCredit,
|
||||||
disambiguation: []const u8,
|
@"first-release-date": []const u8,
|
||||||
annotation: []const u8,
|
//first_release_date: []const u8,
|
||||||
|
releases: []Release,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Release = struct {
|
pub const Release = struct {
|
||||||
|
id: []const u8,
|
||||||
|
@"status-id": ?[]const u8 = null,
|
||||||
|
//status_id: ?[]const u8 = null,
|
||||||
|
count: i32,
|
||||||
title: []const u8,
|
title: []const u8,
|
||||||
artists: []Artist,
|
@"artist-credit": []ArtistCredit,
|
||||||
date: i64,
|
//artist_credit: []ArtistCredit,
|
||||||
country: []const u8, // Consider making a file that exhaustievly lists ISO-3166 codes
|
@"release-group": ReleaseGroup,
|
||||||
catalogue_number: []const u8,
|
//release_group: ReleaseGroup,
|
||||||
barcode: u64,
|
@"track-count": u8,
|
||||||
status: enum { official, promotion, bootleg, pseudo_release, withdrawn, expunged, cancelled },
|
//track_count: u8,
|
||||||
packaging: enum { book, box, cardboard_paper_sleeve, cassette_case, clamshell_case, digibook, digifile, digipak, discbox_slider, fatbox, gatefold_cover, jewel_case, keep_case, longbox, metal_tin, plastic_sleeve, slidepack, slim_jewel, snap_case, super_jewel_box, other, none },
|
|
||||||
language: []const u8, // ISO-639-3
|
|
||||||
script: []const u8, // ISO-15924
|
|
||||||
mbid: MBID,
|
|
||||||
disambiguation: []const u8,
|
|
||||||
annotation: []const u8,
|
|
||||||
data_quality: enum {
|
|
||||||
high,
|
|
||||||
default,
|
|
||||||
low,
|
|
||||||
},
|
|
||||||
media: []Medium,
|
media: []Medium,
|
||||||
|
status: ?[]const u8 = null,
|
||||||
|
date: ?[]const u8 = null,
|
||||||
|
country: ?[]const u8 = null,
|
||||||
|
@"release-events": ?[]ReleaseEvent = null,
|
||||||
|
//release_events: ?[]ReleaseEvent = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Medium = struct {
|
pub const Medium = struct {
|
||||||
title: []const u8,
|
position: u8,
|
||||||
format: enum([]const u8) {
|
format: []const u8,
|
||||||
compact_disc = enum([]const u8) {
|
track: []Track,
|
||||||
compact_disc,
|
@"track-count": u8,
|
||||||
copy_control_cd,
|
//track_count: u8,
|
||||||
data_cd,
|
@"track-offset": u8,
|
||||||
dts_cd,
|
//track_offset: u8,
|
||||||
enhanced_cd,
|
};
|
||||||
hdcd,
|
pub const Track = struct {
|
||||||
mixed_mode_cd,
|
id: []const u8,
|
||||||
cd_r,
|
number: []const u8,
|
||||||
eight_cm_cd,
|
title: []const u8,
|
||||||
blu_spec_cd,
|
length: u64,
|
||||||
minimax_cd,
|
};
|
||||||
shm_cd,
|
pub const Area = struct {
|
||||||
hqcd,
|
id: []const u8,
|
||||||
cd_plus_g = enum { cd_plug_g, eight_cm_cd_plus_g },
|
name: []const u8,
|
||||||
},
|
@"sort-name": []const u8,
|
||||||
vinyl = enum([]const u8) { seven_inch_vinyl, ten_inch_vinyl, twelve_inch_vinyl, flexi_disc = enum { flexi_disc, seven_inch_flexi_disc } },
|
//sort_name: []const u8,
|
||||||
digital_media,
|
@"iso-3166-1-codes": [][]const u8,
|
||||||
cassette = enum { cassette, microcassette },
|
//iso_3166_1_codes: [][]const u8,
|
||||||
dvd = enum { dvd, dvd_audio, dvd_video },
|
};
|
||||||
sacd = enum([]const u8) { hybrid_sacd = enum { hybrid_sacd, hybrid_sacd_cd_layer, hybrig_sacd_sacd_layer }, shm_sacd },
|
pub const ReleaseEvent = struct {
|
||||||
dualdisc = enum {
|
date: []const u8,
|
||||||
dualdisc,
|
area: Area,
|
||||||
dualdisc_cd_side,
|
|
||||||
dualdisc_dvd_video_side,
|
|
||||||
dualdisc_dvd_audio_side,
|
|
||||||
},
|
|
||||||
minidisc,
|
|
||||||
blu_ray = enum { blu_ray, blu_ray_r },
|
|
||||||
hd_dvd,
|
|
||||||
vcd = enum { vcd, svcd },
|
|
||||||
cdv,
|
|
||||||
umd,
|
|
||||||
shellac = enum {
|
|
||||||
shellac,
|
|
||||||
seven_inch_shellac,
|
|
||||||
ten_inch_shellac,
|
|
||||||
twelve_inch_shellac,
|
|
||||||
},
|
|
||||||
acetate = enum {
|
|
||||||
acetate,
|
|
||||||
seven_inch_acetate,
|
|
||||||
ten_inch_acetate,
|
|
||||||
twelve_inch_acetate,
|
|
||||||
},
|
|
||||||
sd_card = enum { sd_card, slotmusic },
|
|
||||||
other = enum([]const u8) { betamax, cartridge = enum { cartridge, hipac, playtape }, ced, dat, dcc, dvdplus = enum { dvdplus_cd_side, dvd_plus_dvd_video_side, dvd_plus_dvd_audio_side }, edison_diamond_disc, floppy_disk = enum { floppy_disk, three_half_inch_floppy_disk, five_quarter_inch_floppy_disk, zip_disk }, laserdisc = enum { laserdisc, eight_inch_laserdisc, twelve_inch_laserdisc }, music_card, pathe_disc, piano_roll, playbutton, reel_to_reel, tefifon, usb_flash_drive, vhd, vhs, vinyldisc, wax_cylinder },
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//pub const Track
|
|
||||||
|
|
||||||
pub const ReleaseGroup = struct {
|
pub const ReleaseGroup = struct {
|
||||||
|
id: []const u8,
|
||||||
|
@"type-id": []const u8,
|
||||||
|
//type_id: []const u8,
|
||||||
|
@"primary-type-id": []const u8,
|
||||||
|
//primary_type_id: []const u8,
|
||||||
title: []const u8,
|
title: []const u8,
|
||||||
artists: []Artist, // Mentions using ArtistCredits for multiple artists. Will need to see a JSOn response to know what to do here
|
@"primary-type": []const u8,
|
||||||
types: struct { primary: enum([]const u8) { single = enum { us, uk, japan }, ep, broadcast, other }, secondary: ?[]enum([]const u8) { compilation, soundtrack, spokenword, interview, audiobook, audio_drama, live, remix, dj_mix, mixtape_street, demo, field_recording } },
|
//primary_type: []const u8,
|
||||||
mbid: MBID,
|
|
||||||
disambiguation: []const u8,
|
|
||||||
annotation: []const u8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Series = struct { name: []const u8, type: enum([]const u8) { release_group_series = enum { release_group_series, release_group_award, podcast }, release_series, recording_series = enum { recording_series, recording_award }, work_series = enum { work_series, catalogue, work_award }, artist_series = enum { artist_series, artist_award }, event_series = enum { even_series, tour, festival, run, residency, award_ceremony } }, ordering_type: []const u8, aliases: []Alias, mbid: MBID, disambiguation: []const u8, annotation: []const u8 };
|
|
||||||
|
|
||||||
pub const URL = []const u8;
|
|
||||||
|
|
||||||
pub const Work = struct { name: []const u8, type: enum { discrete, aggregate }, aliases: []Alias, lyrics_languages: [][]const u8, iswc: []const u8, mbid: MBID, disambiguation: []const u8, annotation: []const u8 };
|
|
||||||
|
|
||||||
pub const Area = struct { name: []const u8, type: enum { country, subdivision, county, municipality, city, district, island }, dates: struct { begin: i64, end: i64 }, iso_3166_codes: [][]const u8, aliases: []Alias, mbid: MBID, annotation: []const u8 };
|
|
||||||
|
|
||||||
pub const Genre = [][]const u8;
|
|
||||||
|
|
||||||
pub const Instrument = struct { name: []const u8, type: enum { wind, string, percussion, electronic, family, ensemble, other }, description: []const u8, aliases: []Alias, mbid: MBID, disambiguation: []const u8, annotation: []const u8 };
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
const Entities = @import("Entities.zig");
|
const Entities = @import("Entities.zig");
|
||||||
|
const Recording = Entities.Recording;
|
||||||
|
|
||||||
const Artist = Entities.Artist;
|
pub const Result = struct {
|
||||||
const Release = Entities.Release;
|
created: ?[]const u8 = null,
|
||||||
|
count: ?u32 = null,
|
||||||
pub const Result = struct { created: []const u8, count: i32, offset: i32, artists: ?[]Artist };
|
offset: ?u32 = null,
|
||||||
|
recordings: ?[]Recording = null,
|
||||||
|
@"error": ?[]const u8 = null,
|
||||||
|
help: ?[]const u8 = null,
|
||||||
|
};
|
||||||
|
|
|
||||||
47
src/root.zig
47
src/root.zig
|
|
@ -3,27 +3,33 @@ const testing = std.testing;
|
||||||
const zeit = @import("zeit");
|
const zeit = @import("zeit");
|
||||||
const Entities = @import("Entities.zig");
|
const Entities = @import("Entities.zig");
|
||||||
const Alias = @import("Alias.zig");
|
const Alias = @import("Alias.zig");
|
||||||
const MBID = @import("MBID.zig");
|
|
||||||
const QR = @import("QueryResults.zig");
|
const QR = @import("QueryResults.zig");
|
||||||
const Client = std.http.Client;
|
const Client = std.http.Client;
|
||||||
|
|
||||||
pub const user_agent: []const u8 = u8{"ZuletztMBClient/0.0.1 (https://swebbguy@gmail.com)"};
|
pub const user_agent: []const u8 = "ZuletztMBClient/0.0.1 (swebbguy@gmail.com)";
|
||||||
|
|
||||||
pub fn mbSearch(allocator: std.mem.Allocator, track_name: []const u8, album_name: []const u8, artist_name: []const u8) !?QR.Result {
|
pub fn mbSearch(allocator: std.mem.Allocator, track_name: []const u8, album_name: []const u8, artist_name: []const u8) !?QR.Result {
|
||||||
var client = Client{ .allocator = allocator };
|
var client = Client{ .allocator = allocator };
|
||||||
defer client.deinit();
|
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}", .{ 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", .{ track_name, artist_name, album_name });
|
||||||
|
defer allocator.free(query);
|
||||||
|
|
||||||
var mb_result = std.ArrayList(u8).init(allocator);
|
var mb_result = std.ArrayList(u8).init(allocator);
|
||||||
defer mb_result.deinit();
|
errdefer mb_result.deinit();
|
||||||
const response: std.http.Status = try client.fetch(.{ .response_storage = mb_result, .location = .{ .url = query }, .method = .GET, .headers = .{ .user_agent = user_agent } });
|
|
||||||
switch (response) {
|
const response: Client.FetchResult = try client.fetch(.{ .response_storage = .{ .dynamic = &mb_result }, .location = .{ .url = query }, .method = .GET, .headers = .{ .user_agent = .{ .override = user_agent } } });
|
||||||
|
|
||||||
|
switch (@intFromEnum(response.status)) {
|
||||||
0...299 => std.log.debug("Success", .{}),
|
0...299 => std.log.debug("Success", .{}),
|
||||||
300...399 => {
|
300...399 => {
|
||||||
std.log.debug("Redirected", .{});
|
std.log.debug("Redirected", .{});
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
400...511 => return Client.RequestError.ConnectionRefused,
|
400...511 => {
|
||||||
|
std.log.err("Get rekt\n{s}", .{mb_result.items});
|
||||||
|
return Client.ConnectError.ConnectionRefused;
|
||||||
|
},
|
||||||
512 => {
|
512 => {
|
||||||
std.log.debug("Need to login", .{});
|
std.log.debug("Need to login", .{});
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -31,9 +37,14 @@ pub fn mbSearch(allocator: std.mem.Allocator, track_name: []const u8, album_name
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: QR.Result = try std.json.parseFromSlice(QR.Result, allocator, mb_result.items, .{});
|
//std.log.err("{s}", .{mb_result_slice});
|
||||||
|
|
||||||
return result;
|
const result = try std.json.parseFromSlice(QR.Result, allocator, mb_result.items, .{ .ignore_unknown_fields = true });
|
||||||
|
defer result.deinit();
|
||||||
|
|
||||||
|
const query_result = result.value;
|
||||||
|
|
||||||
|
return query_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub fn getAlbumMBID(query: QR.Result)
|
//pub fn getAlbumMBID(query: QR.Result)
|
||||||
|
|
@ -43,3 +54,21 @@ pub fn mbSearch(allocator: std.mem.Allocator, track_name: []const u8, album_name
|
||||||
//test "basic add functionality" {
|
//test "basic add functionality" {
|
||||||
// try testing.expect(add(3, 7) == 10);
|
// try testing.expect(add(3, 7) == 10);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
// This test is very volatile, but I think
|
||||||
|
// these params are specific enough that
|
||||||
|
// it shouldn't need changing too often
|
||||||
|
test "iamthemorning" {
|
||||||
|
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 iatm_id: []const u8 = "5854a6de-af8f-4b99-8710-cb47d6436a19";
|
||||||
|
|
||||||
|
const search_result: ?QR.Result = try mbSearch(test_alloc, track, album, artist);
|
||||||
|
if (search_result) |sr| {
|
||||||
|
const recording = sr.recordings.?[0];
|
||||||
|
try testing.expect(std.mem.eql(u8, recording.id, iatm_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue