diff --git a/src/app/jobs/process_scrobbles.zig b/src/app/jobs/process_scrobbles.zig index d8537a6..95ebc52 100644 --- a/src/app/jobs/process_scrobbles.zig +++ b/src/app/jobs/process_scrobbles.zig @@ -1,7 +1,7 @@ const std = @import("std"); const jetzig = @import("jetzig"); const jetquery = @import("jetzig").jetquery; -const Scrobble = @import("../../types.zig").SafeLastFMScrobble; +const Scrobble = @import("../../types.zig").LastFMScrobble; const lastfm = @import("../../types.zig").LastFM; // The `run` function for a job is invoked every time the job is processed by a queue worker diff --git a/src/app/views/upload.zig b/src/app/views/upload.zig index ba924d0..b0d2ccd 100644 --- a/src/app/views/upload.zig +++ b/src/app/views/upload.zig @@ -1,8 +1,10 @@ const std = @import("std"); const jetzig = @import("jetzig"); const jetquery = @import("jetzig").jetquery; -const Scrobble = @import("../../types.zig").LastFMScrobble; -const lastfm = @import("../../types.zig").LastFM; +//const Scrobble = @import("../../types.zig").LastFMScrobble; +//const lastfm = @import("../../types.zig").LastFM; +//const UploadData = @import("../../types").UploadData; +const ScrobbleTypes = @import("../../types.zig"); const zeit = @import("zeit"); pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View { @@ -20,26 +22,36 @@ pub fn post(request: *jetzig.Request) !jetzig.View { var root = try request.data(.object); if (try request.file("upload")) |file| { - //std.debug.print("{s}", .{file.content}); - const content = try std.json.parseFromSliceLeaky(lastfm, request.allocator, file.content, .{ .ignore_unknown_fields = true }); + const params = try request.params(); + + var content: ScrobbleTypes.UploadData = undefined; + + const source = std.fmt.parseInt(u8, params.get("t").string.value, 10).?; + //if (params.get("t")) |param| { + // const source = std.fmt.parseInt(u8, param.string.value, 10); + switch (source) { + 0 => content = try std.json.parseFromSliceLeaky(ScrobbleTypes.LastFM, request.allocator, file.content, .{}), + 1 => content = try std.json.parseFromSliceLeaky(ScrobbleTypes.Spotify, request.allocator, file.content, .{}), + else => unreachable, + } + + //const content = try std.json.parseFromSliceLeaky(lastfm, request.allocator, file.content, .{ .ignore_unknown_fields = true }); var scrobbles_view = try root.put("scrobbles", .array); var job = try request.job("process_scrobbles"); var scrobbles_data = try job.params.put("scrobbles", .array); - const params = try request.params(); - const limiting_date_string: ?[]const u8 = if (params.get("l")) |param| param.string.value else null; - const limiting_date_instant: ?zeit.Instant = if (limiting_date_string) |str| try zeit.instant(.{ .source = .{ .iso8601 = str } }) else null; // This is seconds from Unix epoch - const limiting_date_epoch = if (limiting_date_instant) |time| time.unixTimestamp() else 9_223_372_036_854_775_807; + const limiting_date = if (params.get("l")) |param| (try zeit.instant(.{ .source = .{ .iso8601 = param.string.value } })).unixTimestamp() else 9_223_372_036_854_775_807; appends: for (content.scrobbles) |scrobble| { + if (std.mem.eql(u8, @typeName(scrobble), "SpotifyScrobble")) scrobble = scrobble.scrobblize(); // Scrobble.date is in milliseconds from Unix epoch - if (scrobble.date < limiting_date_epoch * 1000) continue :appends; + if (scrobble.date < limiting_date * 1000) continue :appends; var value = try scrobbles_data.append(.object); // This is so unnecessary, probably useful once I start doing Spotify integration though - inline for (std.meta.fields(Scrobble)) |f| { + inline for (std.meta.fields(ScrobbleTypes.Scrobble)) |f| { try value.put(f.name, @as(f.type, @field(scrobble, f.name))); } // Note sure why this works for ZMPL, but not for jobs. diff --git a/src/app/views/upload/index.zmpl b/src/app/views/upload/index.zmpl index b219da3..b8000b0 100644 --- a/src/app/views/upload/index.zmpl +++ b/src/app/views/upload/index.zmpl @@ -14,8 +14,8 @@
diff --git a/src/types.zig b/src/types.zig index e10fb05..82aef54 100644 --- a/src/types.zig +++ b/src/types.zig @@ -1,17 +1,12 @@ +const zeit = @import("zeit"); + pub const LastFMScrobble = struct { track: []const u8, artist: []const u8, - album: ?[]const u8 = "", + album: []const u8 = "", date: i128, }; -pub const SafeLastFMScrobble = struct { - track: []const u8, - artist: []const u8, - album: []const u8, - date: u64, -}; - // From lastfmstats.com pub const LastFM = struct { username: []const u8, scrobbles: []LastFMScrobble }; @@ -35,6 +30,14 @@ pub const SpotifyScrobble = struct { offline: bool, offline_timestamp: u64, incognito_mode: bool, + + pub fn scrobblize(self: *SpotifyScrobble) LastFMScrobble { + return LastFMScrobble{ .track = self.master_metadata_track_name, .artist = self.master_metadata_artist_name, .album = self.master_metadata_album_name, .date = try zeit.instant(.{ .source = .{ .iso8601 = self.ts } }).unixTimestamp() }; + } }; pub const Spotify = struct { scrobbles: []SpotifyScrobble }; + +const UploadDataTag = enum { spotify, lastfm }; + +pub const UploadData = union(UploadDataTag) { spotify: Spotify, lastfm: LastFM };