zuletzt/src/app/jobs/process_scrobbles.zig
mitteneer 18d4df0a5c Fix albums not being hashed correctly
Also provides more actions for rules, but they don't seem to work...
2025-04-27 15:48:47 -04:00

130 lines
6.8 KiB
Zig

const std = @import("std");
const jetzig = @import("jetzig");
const jetquery = @import("jetzig").jetquery;
const lastfm = @import("../../types.zig").LastFM;
const Data = @import("../../types.zig");
const rules = @import("../../apply_rule.zig");
// The `run` function for a job is invoked every time the job is processed by a queue worker
// (or by the Jetzig server if the job is processed in-line).
//
// Arguments:
// * allocator: Arena allocator for use during the job execution process.
// * params: Params assigned to a job (from a request, values added to response data).
// * env: Provides the following fields:
// - logger: Logger attached to the same stream as the Jetzig server.
// - environment: Enum of `{ production, development }`.
pub fn run(allocator: std.mem.Allocator, params: *jetzig.data.Value, env: jetzig.jobs.JobEnv) !void {
//_ = env;
if (params.getT(.array, "scrobbles")) |scrobbles| {
for (scrobbles.items()) |item| {
// Probably want to include artist name here, but not sure how to yet
const track_artist_count = item.getT(.array, "artists_track").?.count();
const album_artist_count = item.getT(.array, "artists_album").?.count();
var track_artist_name_buffer = try allocator.alloc([]const u8, track_artist_count);
var album_artist_name_buffer = try allocator.alloc([]const u8, album_artist_count);
var track_artist_id_buffer = try allocator.alloc(i32, track_artist_count);
var album_artist_id_buffer = try allocator.alloc(i32, album_artist_count);
const scrobble: Data.Scrobble = .{
.track = item.getT(.string, "track").?,
.artists_track = track_artist_name_buffer,
.album = item.getT(.string, "album") orelse "",
.artists_album = album_artist_name_buffer,
.date = @as(u64, @bitCast(@as(i64, @truncate(item.getT(.integer, "date").? * 1000)))),
};
var id_prehash = std.ArrayList(u8).init(allocator);
for (item.getT(.array, "artists_track").?.items(), 0..track_artist_count) |artist, i| {
const artist_name = try artist.coerce([]const u8);
track_artist_name_buffer[i] = artist_name;
track_artist_id_buffer[i] = @as(i32, @bitCast(std.hash.Fnv1a_32.hash(artist_name)));
}
for (item.getT(.array, "artists_album").?.items(), 0..album_artist_count) |artist, i| {
const artist_name = try artist.coerce([]const u8);
album_artist_name_buffer[i] = artist_name;
album_artist_id_buffer[i] = @as(i32, @bitCast(std.hash.Fnv1a_32.hash(artist_name)));
try id_prehash.appendSlice(artist_name);
}
try id_prehash.appendSlice(scrobble.album);
const album_id = @as(i32, @bitCast(std.hash.Fnv1a_32.hash(id_prehash.items)));
try id_prehash.appendSlice(scrobble.track);
const song_id = @as(i32, @bitCast(std.hash.Fnv1a_32.hash(id_prehash.items)));
var albumsong = try jetzig.database.Query(.Albumsong)
.findBy(.{ .album_id = album_id, .song_id = song_id })
.select(.{.id}).execute(env.repo);
var ins_album = try jetzig.database.Query(.Album)
.find(album_id)
.select(.{.id}).execute(env.repo);
for (track_artist_name_buffer, track_artist_id_buffer) |artist_name, artist_id| {
var ins_artist = try jetzig.database.Query(.Artist)
.find(artist_id)
.select(.{.id}).execute(env.repo);
if (ins_artist == null)
ins_artist = try jetzig.database.Query(.Artist)
.insert(.{ .id = artist_id, .name = artist_name, .disambiguation = null })
.returning(.{.id}).execute(env.repo);
if (albumsong == null) {
var ins_song = try jetzig.database.Query(.Song)
.find(song_id)
.select(.{.id}).execute(env.repo);
if (ins_song == null)
ins_song = try jetzig.database.Query(.Song)
.insert(.{ .id = song_id, .name = scrobble.track, .length = null, .hidden = false })
.returning(.{.id}).execute(env.repo);
if (ins_album == null)
ins_album = try jetzig.database.Query(.Album)
.insert(.{ .id = album_id, .name = scrobble.album, .length = null })
.returning(.{.id}).execute(env.repo);
albumsong = try jetzig.database.Query(.Albumsong)
.insert(.{ .song_id = ins_song.?.id, .album_id = ins_album.?.id })
.returning(.{.id}).execute(env.repo);
try jetzig.database.Query(.Albumsongsartist)
.insert(.{ .albumsong_id = albumsong.?.id, .artist_id = ins_artist.?.id }).execute(env.repo);
} else {
const ins_albumsongartist = try jetzig.database.Query(.Albumsongsartist)
.findBy(.{ .albumsong_id = albumsong.?.id, .artist_id = ins_artist.?.id })
.select(.{.id}).execute(env.repo);
if (ins_albumsongartist == null)
try jetzig.database.Query(.Albumsongsartist)
.insert(.{ .albumsong_id = albumsong.?.id, .artist_id = ins_artist.?.id }).execute(env.repo);
}
}
for (album_artist_name_buffer, album_artist_id_buffer) |artist_name, artist_id| {
const ins_artistalbum = try jetzig.database.Query(.Artistalbum)
.findBy(.{ .album_id = ins_album.?.id, .artist_id = artist_id })
.select(.{.id}).execute(env.repo);
if (ins_artistalbum == null) {
var ins_artist = try jetzig.database.Query(.Artist)
.find(artist_id)
.select(.{.id}).execute(env.repo);
if (ins_artist == null)
ins_artist = try jetzig.database.Query(.Artist)
.insert(.{ .id = artist_id, .name = artist_name, .disambiguation = null })
.returning(.{.id}).execute(env.repo);
try jetzig.database.Query(.Artistalbum)
.insert(.{ .album_id = ins_album.?.id, .artist_id = ins_artist.?.id }).execute(env.repo);
}
}
try jetzig.database.Query(.Scrobble)
.insert(.{ .albumsong = albumsong.?.id, .datetime = scrobble.date }).execute(env.repo);
}
}
}