73 lines
2.9 KiB
Zig
73 lines
2.9 KiB
Zig
const std = @import("std");
|
|
const Rules = @import("./types.zig").Rules;
|
|
const Data = @import("./types.zig");
|
|
|
|
// Wrapper for containsAtLeast to make the switch below to work
|
|
fn containsWrapper(haystack: []const u8, needle: []const u8) bool {
|
|
return std.mem.containsAtLeast(u8, haystack, 1, needle);
|
|
}
|
|
|
|
fn eqlWrapper(haystack: []const u8, needle: []const u8) bool {
|
|
return std.mem.eql(u8, haystack, needle);
|
|
}
|
|
|
|
pub fn applyScrobbleRule(allocator: std.mem.Allocator, scrobble: Data.ImportedScrobble, rules: Rules) !Data.Scrobble {
|
|
const artists = try allocator.alloc([]const u8, 1);
|
|
artists[0] = scrobble.artist;
|
|
var output_scrobble = Data.Scrobble{
|
|
.track = scrobble.track,
|
|
.artists_track = artists,
|
|
.album = scrobble.album,
|
|
.artists_album = artists,
|
|
.date = scrobble.date,
|
|
};
|
|
|
|
for (rules.rules) |rule| {
|
|
var match_found: bool = switch (rule.cond_req) {
|
|
.any => false,
|
|
.all => true,
|
|
};
|
|
for (rule.conditionals) |cond| {
|
|
const match_fn: *const fn ([]const u8, []const u8) bool = switch (cond.match_cond) {
|
|
.is => eqlWrapper,
|
|
.contains => containsWrapper,
|
|
};
|
|
switch (rule.cond_req) {
|
|
.any => switch (cond.match_on) {
|
|
inline else => |on| match_found = match_found or match_fn(@field(scrobble, @tagName(on)), cond.match_txt),
|
|
},
|
|
.all => switch (cond.match_on) {
|
|
inline else => |on| match_found = match_found and match_fn(@field(scrobble, @tagName(on)), cond.match_txt),
|
|
},
|
|
}
|
|
}
|
|
if (match_found) {
|
|
for (rule.actions) |act| {
|
|
switch (act.action) {
|
|
.add => {
|
|
var al = std.ArrayList([]const u8).init(allocator);
|
|
switch (act.action_on) {
|
|
.album, .track => unreachable,
|
|
inline else => |on| {
|
|
try al.appendSlice(@field(output_scrobble, @tagName(on)));
|
|
try al.append(act.action_txt);
|
|
const list = try al.toOwnedSlice();
|
|
@field(output_scrobble, @tagName(on)) = list;
|
|
},
|
|
}
|
|
},
|
|
.replace => switch (act.action_on) {
|
|
inline .album, .track => |on| @field(output_scrobble, @tagName(on)) = act.action_txt,
|
|
inline .artists_album, .artists_track => |on| {
|
|
const artist = try allocator.alloc([]const u8, 1);
|
|
artist[0] = act.action_txt;
|
|
@field(output_scrobble, @tagName(on)) = artist;
|
|
},
|
|
},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return output_scrobble;
|
|
}
|