diff --git a/src/app/views/upload.zig b/src/app/views/upload.zig index b21fa17..0beaf95 100644 --- a/src/app/views/upload.zig +++ b/src/app/views/upload.zig @@ -15,7 +15,17 @@ pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View { pub fn post(request: *jetzig.Request) !jetzig.View { var root = try request.data(.object); - const params = try request.params(); + //const params = try request.params(); + + const UploadParams = struct { + source: enum { LFMW, LFMS, Spotify }, + earliest_date: ?[]const u8, + latest_date: ?[]const u8, + username: ?[]const u8, + }; + + const params = (try request.expectParams(UploadParams)).?; + const rule_file = try (std.fs.cwd().openFile("rules.json", .{ .mode = .read_only }) catch |err| switch (err) { error.FileNotFound => std.fs.cwd().createFile("rules.json", .{ .read = true }), else => err, @@ -26,43 +36,39 @@ pub fn post(request: *jetzig.Request) !jetzig.View { const rule_list = std.json.parseFromSliceLeaky([]Data.Rule, request.allocator, rule_file_content, .{}) catch null; //var job = try request.job("process_scrobbles"); var job = try request.job("process_scrobbles2"); - const source = params.getT(.integer, "t").?; // This param is required in HTML - const latest_date = if (params.getT(.boolean, "adv-opt")) |_| blk: { - const date = params.getT(.string, "latest-date").?; - break :blk try zeit.Time.fromISO8601(date); - } else (try zeit.instant(.{ .source = .now })).time(); + // We can parse the dates better + const latest_ts = if (params.latest_date) |ld| + (try zeit.instant(.{ .source = .{ .iso8601 = ld } })).timestamp + else + (try zeit.instant(.{ .source = .now })).timestamp; - const earliest_date = if (params.getT(.boolean, "adv-opt")) |_| blk: { - const date = params.getT(.string, "earliest-date").?; - break :blk try zeit.Time.fromISO8601(date); - } else (try zeit.instant(.{ .source = .{ .unix_timestamp = 0 } })).time(); - - const earliest_timestamp = earliest_date.instant().unixTimestamp(); - const latest_timestamp = latest_date.instant().unixTimestamp(); + const earliest_ts = if (params.earliest_date) |ed| + (try zeit.instant(.{ .source = .{ .iso8601 = ed } })).timestamp + else + (try zeit.instant(.{ .source = .{ .unix_timestamp = 0 } })).timestamp; var view_params = try root.put("scrobbles", .array); - //var job_params = try job.params.put("scrobbles", .array); var skipped_tracks: u64 = 0; var limited_tracks: u64 = 0; - const imported_scrobbles: []Data.UnifiedScrobble = switch (source) { - 0, 1 => try Utils.scrobbleIngest(request.allocator, if (try request.file("upload")) |file| file.content else unreachable), - 2 => blk: { + const imported_scrobbles: []Data.UnifiedScrobble = switch (params.source) { + .LFMS, .Spotify => try Utils.scrobbleIngest(request.allocator, if (try request.file("upload")) |file| file.content else unreachable), + .LFMW => blk: { const user_agent: []const u8 = "Zuletzt/0.0.1"; var client = Client{ .allocator = request.allocator }; var lastfm_response_buffer = std.ArrayList(u8).init(request.allocator); var scrobble_buffer = std.ArrayList(Data.UnifiedScrobble).init(request.allocator); - const username = if (params.getT(.string, "username")) |un| un else "VAOTM"; + const username = if (params.username) |un| un else "VAOTM"; var page: usize = 1; //var max_pages: ?usize = null; while (true) : (page += 1) { if (page > 91) break; - const query: []const u8 = try std.fmt.allocPrint(request.allocator, "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user={s}&api_key=b0c410a48a6078a651e0832699e3cd41&from={}&to={}&page={}&limit=1000&format=json", .{ username, earliest_timestamp, latest_timestamp, page }); + const query: []const u8 = try std.fmt.allocPrint(request.allocator, "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user={s}&api_key=b0c410a48a6078a651e0832699e3cd41&from={}&to={}&page={}&limit=1000&format=json", .{ username, @divFloor(earliest_ts, std.time.ns_per_s), @divFloor(latest_ts, std.time.ns_per_s), page }); const r = try client.fetch(.{ .response_storage = .{ .dynamic = &lastfm_response_buffer }, .location = .{ .url = query }, .method = .GET, .headers = .{ .user_agent = .{ .override = user_agent } } }); std.log.debug("{}: {}", .{ page, r }); if (@intFromEnum(r.status) == 500) { @@ -79,7 +85,6 @@ pub fn post(request: *jetzig.Request) !jetzig.View { break :blk try scrobble_buffer.toOwnedSlice(); }, - else => unreachable, }; var artists = try job.params.put("artists", .object); @@ -92,7 +97,7 @@ pub fn post(request: *jetzig.Request) !jetzig.View { var hash_buffer = [_]u8{undefined} ** 20; // A minimum i64 needs 19 digits + 1 negative sign appends: for (imported_scrobbles) |scrobble| { - if (scrobble.date > latest_timestamp * std.time.ns_per_s or scrobble.date < earliest_timestamp * std.time.ns_per_s) { + if (scrobble.date > latest_ts or scrobble.date < earliest_ts) { limited_tracks += 1; continue :appends; } diff --git a/src/app/views/upload/index.zmpl b/src/app/views/upload/index.zmpl index 420e08c..bdeaacb 100644 --- a/src/app/views/upload/index.zmpl +++ b/src/app/views/upload/index.zmpl @@ -14,14 +14,29 @@
- Last.fm - Spotify - Last.fm (WebAuth) + Last.fm + Spotify + Last.fm (WebAuth) - Advanced Options - Limit to Scrobbles before: - Limit to Scrobbles after: + Advanced Options +
+ +