Compare commits
4 commits
7f3778e82f
...
d638fa66c5
| Author | SHA1 | Date | |
|---|---|---|---|
| d638fa66c5 | |||
| 3ff973e193 | |||
| f59eec79a8 | |||
| aab61631a3 |
6 changed files with 188 additions and 147 deletions
|
|
@ -17,8 +17,8 @@
|
|||
// internet connectivity.
|
||||
.dependencies = .{
|
||||
.jetzig = .{
|
||||
.url = "https://github.com/jetzig-framework/jetzig/archive/7be1d137fcab5c422e05f12092f6e04a02900d6f.tar.gz",
|
||||
.hash = "jetzig-0.0.0-IpAgLURbDwB1NlywUH7lnQ3zptNvSQWVosaA1k7l1cNz",
|
||||
.url = "https://github.com/jetzig-framework/jetzig/archive/695664bc10e6e73389ee2fe7fbcaedc27fa8adc9.tar.gz",
|
||||
.hash = "jetzig-0.0.0-IpAgLSFeDwBEhfEaDBo0JqhRbvQA3ScbWjssBqhJHFmb",
|
||||
},
|
||||
.zeit = .{
|
||||
.url = "https://github.com/rockorager/zeit/archive/refs/tags/v0.6.0.tar.gz",
|
||||
|
|
|
|||
|
|
@ -1,56 +1,12 @@
|
|||
const std = @import("std");
|
||||
const jetzig = @import("jetzig");
|
||||
const zeit = @import("zeit");
|
||||
const TableRow = @import("../../types.zig").TableRow;
|
||||
const HyperlinkData = @import("../../types.zig").HyperlinkData;
|
||||
const Utils = @import("../../date_fmt.zig");
|
||||
const queries = @import("../../queries.zig");
|
||||
|
||||
pub fn index(request: *jetzig.Request) !jetzig.View {
|
||||
var root = try request.data(.object);
|
||||
var scrobbles_view = try root.put("scrobbles", .array);
|
||||
|
||||
const query =
|
||||
\\SELECT songs.name, songs.id, albums.name, albums.id, artists.name, artists.id, scrobbles.id, scrobbles.datetime
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN albums ON albums.id = albumsongs.album_id
|
||||
\\INNER JOIN scrobbles ON scrobbles.albumsong = albumsongs.id
|
||||
\\INNER JOIN albumsongsartists ON albumsongsartists.albumsong_id = albumsongs.id
|
||||
\\INNER JOIN artists ON artists.id = albumsongsartists.artist_id
|
||||
\\ORDER BY scrobbles.datetime ASC
|
||||
;
|
||||
|
||||
var scrobbles_jq_result = try request.repo.executeSql(query, .{});
|
||||
defer scrobbles_jq_result.deinit();
|
||||
|
||||
const Scrobble = struct { song_name: []const u8, song_id: i32, album_name: []const u8, album_id: i32, artist_name: []const u8, artist_id: i32, s_id: i32, date: i64 };
|
||||
|
||||
var prev_s_id: ?i32 = null;
|
||||
|
||||
var row: ?TableRow = null;
|
||||
var artistlist = std.ArrayList(HyperlinkData).init(request.allocator);
|
||||
|
||||
blk: while (try scrobbles_jq_result.postgresql.result.next()) |scrobble_row| {
|
||||
const scrobble = try scrobble_row.to(Scrobble, .{ .dupe = true, .allocator = request.allocator });
|
||||
if (scrobble.s_id == prev_s_id) {
|
||||
try artistlist.append(.{ .name = scrobble.artist_name, .id = scrobble.artist_id });
|
||||
continue :blk;
|
||||
} else {
|
||||
const date = try Utils.dateFmt(request.allocator, scrobble.date);
|
||||
|
||||
try artistlist.append(.{ .name = scrobble.artist_name, .id = scrobble.artist_id });
|
||||
|
||||
row = TableRow{
|
||||
.song = .{ .name = scrobble.song_name, .id = scrobble.song_id },
|
||||
.album = .{ .name = scrobble.album_name, .id = scrobble.album_id },
|
||||
.artistlist = try artistlist.toOwnedSlice(),
|
||||
.date = date,
|
||||
};
|
||||
|
||||
try scrobbles_view.append(row);
|
||||
}
|
||||
prev_s_id = scrobble.s_id;
|
||||
}
|
||||
const scrobbles = try queries.entityQueryResult(request, queries.generateQuery(.scrobble, .entities), .{}, .array);
|
||||
try root.put("scrobbles", scrobbles);
|
||||
|
||||
return request.render(.ok);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,21 @@ pub fn index(request: *jetzig.Request) !jetzig.View {
|
|||
}
|
||||
|
||||
pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
||||
_ = id;
|
||||
var root = try request.data(.object);
|
||||
|
||||
const song = try queries.entityQueryResult(request, queries.generateQuery(.song, .entity_info), .{id}, .object);
|
||||
try root.put("song", song.get("entity_info"));
|
||||
|
||||
const scrobbles = try queries.entityQueryResult(request, queries.generateQuery(.song, .entity_items), .{id}, .array);
|
||||
try root.put("scrobbles", scrobbles);
|
||||
|
||||
const appears = try queries.entityQueryResult(request, queries.generateQuery(.song, .appears), .{id}, .array);
|
||||
try root.put("appears", appears);
|
||||
|
||||
const firstlast = try queries.entityQueryResult(request, queries.generateQuery(.song, .firstlast), .{id}, .array);
|
||||
try root.put("firstlast", firstlast);
|
||||
|
||||
const timescale = try queries.entityQueryResult(request, queries.generateQuery(.song, .timescale), .{id}, .array);
|
||||
try root.put("yearly", timescale);
|
||||
return request.render(.ok);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,19 @@
|
|||
<div>
|
||||
<span>Content goes here</span>
|
||||
</div>
|
||||
@zig {
|
||||
const ColumnChoices = []const enum{song, album, artist, artistlist, scrobbles, date};
|
||||
const columns: ColumnChoices = &.{.song, .artistlist, .album, .date};
|
||||
}
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
@partial partials/header
|
||||
<h1>{{.song}}</h1>
|
||||
@partial partials/firstlast_listens(scrobbles: .song.scrobbles, rank: .song.rank, firstlast: .firstlast)
|
||||
<h3>Yearly Performance</h3>
|
||||
@partial partials/timescale(range: .yearly)
|
||||
<h2>Scrobbles</h2>
|
||||
@partial partials/newtable(T: ColumnChoices, table_data: .scrobbles, columns: columns)
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -81,77 +81,74 @@ pub fn post(request: *jetzig.Request) !jetzig.View {
|
|||
|
||||
// Not sure if I should be proud or feel sick
|
||||
switch (imported_scrobbles) {
|
||||
inline else => |scrobbles| {
|
||||
.LastFMStats => |scrobbles| {
|
||||
appends: for (scrobbles) |scrobble| {
|
||||
const filtered_scrobble: Data.Scrobble = blk: switch (@TypeOf(scrobble)) {
|
||||
Data.IgnorantScrobble => {
|
||||
if (scrobble.date > latest_timestamp * 1_000 or scrobble.date < earliest_timestamp * 1_000) {
|
||||
limited_tracks += 1;
|
||||
continue :appends;
|
||||
}
|
||||
break :blk Data.Scrobble{
|
||||
.album = scrobble.album,
|
||||
.artists_album = &[_][]const u8{scrobble.artist},
|
||||
.track = scrobble.track,
|
||||
.artists_track = &[_][]const u8{scrobble.artist},
|
||||
.date = scrobble.date * 1_000,
|
||||
};
|
||||
},
|
||||
Data.SpotifyScrobble => {
|
||||
if (scrobble.ms_played < 30_000 and (scrobble.reason_end == null or !std.mem.eql(u8, scrobble.reason_end.?, "trackdone"))) {
|
||||
skipped_tracks += 1;
|
||||
continue :appends;
|
||||
}
|
||||
if (scrobble.master_metadata_album_artist_name == null or scrobble.master_metadata_track_name == null) {
|
||||
skipped_tracks += 1;
|
||||
continue :appends;
|
||||
}
|
||||
|
||||
const iso_ts = try zeit.Time.fromISO8601(scrobble.ts);
|
||||
if ((iso_ts.after(latest_date) or iso_ts.before(earliest_date))) {
|
||||
limited_tracks += 1;
|
||||
continue :appends;
|
||||
}
|
||||
|
||||
break :blk Data.Scrobble{
|
||||
.album = scrobble.master_metadata_album_album_name.?,
|
||||
.artists_album = &[_][]const u8{scrobble.master_metadata_album_artist_name.?},
|
||||
.track = scrobble.master_metadata_track_name.?,
|
||||
.artists_track = &[_][]const u8{scrobble.master_metadata_album_artist_name.?},
|
||||
.date = (try zeit.instant(.{ .source = .{ .iso8601 = scrobble.ts } })).unixTimestamp() * 1_000_000,
|
||||
};
|
||||
},
|
||||
Data.LastFMWebScrobble => {
|
||||
break :blk Data.Scrobble{
|
||||
.album = if (scrobble.album) |album| album.@"#text" else "Not Provided",
|
||||
.artists_album = &[_][]const u8{scrobble.artist.@"#text"},
|
||||
.track = scrobble.name,
|
||||
.artists_track = &[_][]const u8{scrobble.artist.@"#text"},
|
||||
.date = try std.fmt.parseInt(i64, scrobble.date.?.uts, 10) * 1_000_000,
|
||||
};
|
||||
},
|
||||
else => unreachable,
|
||||
if (scrobble.date > latest_timestamp * 1_000 or scrobble.date < earliest_timestamp * 1_000) {
|
||||
limited_tracks += 1;
|
||||
continue :appends;
|
||||
}
|
||||
const filtered_scrobble = Data.Scrobble{
|
||||
.album = scrobble.album,
|
||||
.artists_album = &[_][]const u8{scrobble.artist},
|
||||
.track = scrobble.track,
|
||||
.artists_track = &[_][]const u8{scrobble.artist},
|
||||
.date = scrobble.date * 1_000,
|
||||
};
|
||||
|
||||
const complete_scrobble = if (rule_list) |rl| try rules.applyScrobbleRule(request.allocator, filtered_scrobble, rl) else filtered_scrobble;
|
||||
|
||||
const row = try Utils.scrobbleToRow(request.allocator, complete_scrobble);
|
||||
|
||||
try view_params.append(row);
|
||||
var job_param = try job_params.append(.object);
|
||||
try job_param.put("album", complete_scrobble.album);
|
||||
try job_param.put("track", complete_scrobble.track);
|
||||
try job_param.put("date", complete_scrobble.date);
|
||||
try job_params.append(complete_scrobble);
|
||||
}
|
||||
},
|
||||
.LastFMWeb => |scrobbles| {
|
||||
for (scrobbles) |scrobble| {
|
||||
const filtered_scrobble = Data.Scrobble{
|
||||
.album = if (scrobble.album) |album| album.@"#text" else "Not Provided",
|
||||
.artists_album = &[_][]const u8{scrobble.artist.@"#text"},
|
||||
.track = scrobble.name,
|
||||
.artists_track = &[_][]const u8{scrobble.artist.@"#text"},
|
||||
.date = try std.fmt.parseInt(i64, scrobble.date.?.uts, 10) * 1_000_000,
|
||||
};
|
||||
const complete_scrobble = if (rule_list) |rl| try rules.applyScrobbleRule(request.allocator, filtered_scrobble, rl) else filtered_scrobble;
|
||||
|
||||
var track_artists_array = try job_param.put("artists_track", .array);
|
||||
for (complete_scrobble.artists_track) |a| {
|
||||
try track_artists_array.append(a);
|
||||
const row = try Utils.scrobbleToRow(request.allocator, complete_scrobble);
|
||||
|
||||
try view_params.append(row);
|
||||
try job_params.append(complete_scrobble);
|
||||
}
|
||||
},
|
||||
.Spotify => |scrobbles| {
|
||||
appends: for (scrobbles) |scrobble| {
|
||||
if (scrobble.ms_played < 30_000 and (scrobble.reason_end == null or !std.mem.eql(u8, scrobble.reason_end.?, "trackdone"))) {
|
||||
skipped_tracks += 1;
|
||||
continue :appends;
|
||||
}
|
||||
if (scrobble.master_metadata_album_artist_name == null or scrobble.master_metadata_track_name == null) {
|
||||
skipped_tracks += 1;
|
||||
continue :appends;
|
||||
}
|
||||
|
||||
var album_artists_array = try job_param.put("artists_album", .array);
|
||||
for (complete_scrobble.artists_album) |a| {
|
||||
try album_artists_array.append(a);
|
||||
const iso_ts = try zeit.Time.fromISO8601(scrobble.ts);
|
||||
if ((iso_ts.after(latest_date) or iso_ts.before(earliest_date))) {
|
||||
limited_tracks += 1;
|
||||
continue :appends;
|
||||
}
|
||||
|
||||
const filtered_scrobble = Data.Scrobble{
|
||||
.album = scrobble.master_metadata_album_album_name.?,
|
||||
.artists_album = &[_][]const u8{scrobble.master_metadata_album_artist_name.?},
|
||||
.track = scrobble.master_metadata_track_name.?,
|
||||
.artists_track = &[_][]const u8{scrobble.master_metadata_album_artist_name.?},
|
||||
.date = (try zeit.instant(.{ .source = .{ .iso8601 = scrobble.ts } })).unixTimestamp() * 1_000_000,
|
||||
};
|
||||
const complete_scrobble = if (rule_list) |rl| try rules.applyScrobbleRule(request.allocator, filtered_scrobble, rl) else filtered_scrobble;
|
||||
|
||||
const row = try Utils.scrobbleToRow(request.allocator, complete_scrobble);
|
||||
|
||||
try view_params.append(row);
|
||||
try job_params.append(complete_scrobble);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
|||
125
src/queries.zig
125
src/queries.zig
|
|
@ -20,30 +20,27 @@ pub fn entityQueryResult(request: *jetzig.Request, query: GeneratedQuery, args:
|
|||
|
||||
blk: while (try result.postgresql.result.next()) |entity_row| {
|
||||
switch (query.ResultType) {
|
||||
FirstlastResult, TimescaleResult, EntitiesScrobbleResult, EntitiesSongResult, EntitiesAlbumResult, EntitiesArtistResult, EntityItemsResult, AppearsResult, EntityInfoResult => |T| {
|
||||
FirstlastResult, TimescaleResult, EntitiesScrobbleResult, EntitiesSongResult, EntitiesAlbumResult, EntitiesArtistResult, EntityItemsResult, AppearsResult, EntityInfoResult, EntityItemsSongResult => |T| {
|
||||
const entity = try entity_row.to(T, .{ .dupe = true, .allocator = request.allocator });
|
||||
const item: ?TableRow = switch (query.ResultType) {
|
||||
EntitiesScrobbleResult, EntitiesSongResult, EntitiesAlbumResult, EntitiesArtistResult => switch (query.entity) {
|
||||
.artist => TableRow{ .artist = .{ .name = entity.name, .id = entity.id }, .scrobbles = entity.scrobbles },
|
||||
.album => album_entities: {
|
||||
.scrobble, .song, .album => album_entities: {
|
||||
const last_artist = artist_list.getLastOrNull();
|
||||
try artist_list.append(.{ .name = entity.artist_name, .id = entity.artist_id });
|
||||
if (last_artist) |la| {
|
||||
if (la.id == entity.artist_id) continue :blk;
|
||||
}
|
||||
break :album_entities TableRow{ .album = .{ .name = entity.name, .id = entity.id }, .artistlist = try artist_list.toOwnedSlice(), .scrobbles = entity.scrobbles };
|
||||
break :album_entities switch (query.entity) {
|
||||
.scrobble => TableRow{ .song = .{ .name = entity.song_name, .id = entity.song_id }, .album = .{ .name = entity.album_name, .id = entity.album_id }, .artistlist = try artist_list.toOwnedSlice(), .date = entity.date },
|
||||
.song => TableRow{ .song = .{ .name = entity.name, .id = entity.id }, .artistlist = try artist_list.toOwnedSlice(), .scrobbles = entity.scrobbles },
|
||||
.album => TableRow{ .album = .{ .name = entity.name, .id = entity.id }, .artistlist = try artist_list.toOwnedSlice(), .scrobbles = entity.scrobbles },
|
||||
else => unreachable,
|
||||
};
|
||||
},
|
||||
.song => song_entities: {
|
||||
const last_artist = artist_list.getLastOrNull();
|
||||
try artist_list.append(.{ .name = entity.artist_name, .id = entity.artist_id });
|
||||
if (last_artist) |la| {
|
||||
if (la.id == entity.artist_id) continue :blk;
|
||||
}
|
||||
break :song_entities TableRow{ .song = .{ .name = entity.name, .id = entity.id }, .artistlist = try artist_list.toOwnedSlice(), .scrobbles = entity.scrobbles };
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
EntityItemsResult => switch (query.entity) {
|
||||
EntityItemsResult, EntityItemsSongResult => switch (query.entity) {
|
||||
.song => TableRow{ .song = .{ .name = entity.song_name, .id = entity.song_id }, .album = .{ .name = entity.album_name, .id = entity.album_id }, .date = entity.date },
|
||||
.artist => TableRow{ .album = .{ .name = entity.name, .id = entity.id }, .scrobbles = entity.scrobbles },
|
||||
.album => TableRow{ .song = .{ .name = entity.name, .id = entity.id }, .scrobbles = entity.scrobbles },
|
||||
else => unreachable,
|
||||
|
|
@ -92,10 +89,21 @@ const TimescaleResult = struct { year: []const u8, scrobbles: i64 };
|
|||
const EntitiesArtistResult = struct { name: []const u8, id: i32, scrobbles: i64 };
|
||||
const EntitiesAlbumResult = struct { name: []const u8, id: i32, artist_name: []const u8, artist_id: i32, scrobbles: i64 };
|
||||
const EntitiesSongResult = struct { name: []const u8, id: i32, artist_name: []const u8, artist_id: i32, scrobbles: i64 };
|
||||
const EntitiesScrobbleResult = struct { song_name: []const u8, song_id: i32, album_name: []const u8, album_id: i32, artist_name: []const u8, artist_id: i32, s_id: i32, date: i64 };
|
||||
const EntitiesScrobbleResult = struct { song_name: []const u8, song_id: i32, album_name: []const u8, album_id: i32, artist_name: []const u8, artist_id: i32, date: []const u8 };
|
||||
const EntityItemsResult = struct { name: []const u8, id: i32, scrobbles: i64 };
|
||||
const AppearsResult = struct { name: []const u8, id: i32, scrobbles: i64 };
|
||||
const EntityInfoResult = struct { name: []const u8, id: i32, scrobbles: i64, rank: []const u8 };
|
||||
const EntityItemsSongResult = struct { song_name: []const u8, song_id: i32, album_name: []const u8, album_id: i32, date: []const u8 };
|
||||
const UnifiedResult = struct {
|
||||
album_name: ?[]const u8 = null,
|
||||
album_id: ?i32 = null,
|
||||
song_name: ?[]const u8 = null,
|
||||
song_id: ?i32 = null,
|
||||
artist_names: ?[]const []const u8 = null,
|
||||
artist_ids: ?[]i32 = null,
|
||||
scrobbles: ?i64 = null,
|
||||
date: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQuery {
|
||||
return GeneratedQuery{
|
||||
|
|
@ -110,7 +118,11 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
.album => EntitiesAlbumResult,
|
||||
.artist => EntitiesArtistResult,
|
||||
},
|
||||
.entity_items => EntityItemsResult,
|
||||
.entity_items => switch (entity) {
|
||||
.scrobble => unreachable,
|
||||
.song => EntityItemsSongResult,
|
||||
else => EntityItemsResult,
|
||||
},
|
||||
.appears => AppearsResult,
|
||||
.entity_info => EntityInfoResult,
|
||||
},
|
||||
|
|
@ -120,29 +132,27 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
switch (entity) {
|
||||
.scrobble => unreachable,
|
||||
.song =>
|
||||
\\(SELECT songs.name AS name, songs.id AS id, scrobbles.datetime AS date
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime,'YYYY-MM-DD HH24:MI:SS') AS date
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN scrobbles ON albumsongs.id = scrobbles.albumsong
|
||||
\\INNER JOIN albumsongsartists ON albumsongsartists.albumsong_id = albumsongs.id
|
||||
\\WHERE albumsongsartists.artist_id = $1
|
||||
\\WHERE albumsongs.song_id = $1
|
||||
\\ORDER BY scrobbles.datetime ASC
|
||||
\\LIMIT 1)
|
||||
\\
|
||||
\\UNION ALL
|
||||
\\
|
||||
\\(SELECT songs.name AS name, songs.id AS id, scrobbles.datetime AS date
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MI:SS') AS date
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN scrobbles ON albumsongs.id = scrobbles.albumsong
|
||||
\\INNER JOIN albumsongsartists ON albumsongsartists.albumsong_id = albumsongs.id
|
||||
\\WHERE albumsongsartists.artist_id = $1
|
||||
\\WHERE albumsongs.song_id = $1
|
||||
\\ORDER BY scrobbles.datetime DESC
|
||||
\\LIMIT 1)
|
||||
,
|
||||
|
||||
.album =>
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MM:SS') AS date
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MI:SS') AS date
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN scrobbles ON albumsongs.id = scrobbles.albumsong
|
||||
|
|
@ -153,7 +163,7 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
\\
|
||||
\\UNION ALL
|
||||
\\
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MM:SS') AS date
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MI:SS') AS date
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN scrobbles ON albumsongs.id = scrobbles.albumsong
|
||||
|
|
@ -164,7 +174,7 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
,
|
||||
|
||||
.artist =>
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MM:SS') AS date
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MI:SS') AS date
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN scrobbles ON albumsongs.id = scrobbles.albumsong
|
||||
|
|
@ -175,7 +185,7 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
\\
|
||||
\\UNION ALL
|
||||
\\
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MM:SS') AS date
|
||||
\\(SELECT songs.name AS name, songs.id AS id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MI:SS') AS date
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN scrobbles ON albumsongs.id = scrobbles.albumsong
|
||||
|
|
@ -194,9 +204,8 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
\\SELECT TO_CHAR(date_trunc('year', datetime), 'YYYY') AS year, COUNT(*) as scrobbles
|
||||
\\FROM scrobbles
|
||||
\\INNER JOIN albumsongs ON albumsongs.id = scrobbles.albumsong
|
||||
\\INNER JOIN albumsongsartists ON albumsongsartists.albumsong_id = albumsongs.id
|
||||
\\INNER JOIN artists ON artists.id = albumsongsartists.artist_id
|
||||
\\WHERE artists.id = $1
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\WHERE songs.id = $1
|
||||
\\GROUP BY year
|
||||
\\ORDER BY year ASC;
|
||||
,
|
||||
|
|
@ -227,7 +236,14 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
//.ResultType = EntitiesResult,
|
||||
switch (entity) {
|
||||
.scrobble =>
|
||||
\\none
|
||||
\\SELECT songs.name AS song_name, songs.id AS song_id, albums.name AS album_name, albums.id AS album_id, artists.name AS artist_name, artists.id AS artist_id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MI:SS') AS date
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN albums ON albums.id = albumsongs.album_id
|
||||
\\INNER JOIN scrobbles ON scrobbles.albumsong = albumsongs.id
|
||||
\\INNER JOIN albumsongsartists ON albumsongsartists.albumsong_id = albumsongs.id
|
||||
\\INNER JOIN artists ON artists.id = albumsongsartists.artist_id
|
||||
\\ORDER BY scrobbles.datetime ASC
|
||||
,
|
||||
.song =>
|
||||
\\SELECT songs.name, songs.id, artists.name, artists.id, COUNT(scrobbles) AS scrobbles
|
||||
|
|
@ -265,13 +281,21 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
switch (entity) {
|
||||
.scrobble => unreachable,
|
||||
.song =>
|
||||
\\ NOTHING YET
|
||||
\\SELECT albums.name AS album_name, albums.id AS album_id, COUNT(scrobbles) AS scrobbles
|
||||
\\FROM artistalbums
|
||||
\\INNER JOIN albums ON albums.id = artistalbums.album_id
|
||||
\\INNER JOIN albumsongs ON albumsongs.album_id = albums.id
|
||||
\\INNER JOIN scrobbles ON scrobbles.albumsong = albumsongs.id
|
||||
\\INNER JOIN albumsongsartists ON albumsongsartists.albumsong_id = albumsongs.id
|
||||
\\WHERE albumsongs.song_id = $1
|
||||
\\GROUP BY albums.id
|
||||
\\ORDER BY scrobbles DESC;
|
||||
,
|
||||
.album =>
|
||||
\\nope
|
||||
,
|
||||
.artist =>
|
||||
\\SELECT albums.name AS name, albums.id AS id, COUNT(scrobbles) AS scrobbles
|
||||
\\SELECT albums.name AS album_name, albums.id AS album_id, COUNT(scrobbles) AS scrobbles
|
||||
\\FROM artistalbums
|
||||
\\INNER JOIN albums ON albums.id = artistalbums.album_id
|
||||
\\INNER JOIN albumsongs ON albumsongs.album_id = albums.id
|
||||
|
|
@ -288,7 +312,13 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
switch (entity) {
|
||||
.scrobble => unreachable,
|
||||
.song =>
|
||||
\\get all scrobbles
|
||||
\\SELECT songs.name, songs.id, albums.name, albums.id, TO_CHAR(scrobbles.datetime, 'YYYY-MM-DD HH24:MI:SS') AS date
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN albums ON albums.id = albumsongs.album_id
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\INNER JOIN scrobbles ON scrobbles.albumsong = albumsongs.id
|
||||
\\WHERE songs.id = $1
|
||||
\\ORDER BY date ASC
|
||||
,
|
||||
.album =>
|
||||
\\SELECT songs.name, songs.id, COUNT(scrobbles) AS scrobbles
|
||||
|
|
@ -314,12 +344,19 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
.entity_info => switch (entity) {
|
||||
.scrobble => unreachable,
|
||||
.song =>
|
||||
\\lol idk
|
||||
\\SELECT * FROM
|
||||
\\(SELECT *, TO_CHAR(ROW_NUMBER() OVER (ORDER BY scrobbles DESC),'FM99999th') AS rank FROM
|
||||
\\(SELECT songs.name AS name, songs.id AS id, COUNT(scrobbles) AS scrobbles
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN songs ON albumsongs.song_id = songs.id
|
||||
\\INNER JOIN scrobbles ON scrobbles.albumsong = albumsongs.id
|
||||
\\GROUP BY songs.id))
|
||||
\\WHERE id = $1
|
||||
,
|
||||
.album =>
|
||||
\\SELECT * FROM
|
||||
\\(SELECT *, TO_CHAR(ROW_NUMBER() OVER (ORDER BY scrobbles DESC),'FM9999th') AS rank FROM
|
||||
\\(SELECT albums.name, albums.id, COUNT(scrobbles) AS scrobbles
|
||||
\\(SELECT albums.name AS name, albums.id AS id, COUNT(scrobbles) AS scrobbles
|
||||
\\FROM albumsongs
|
||||
\\INNER JOIN albums ON albumsongs.album_id = albums.id
|
||||
\\INNER JOIN scrobbles ON scrobbles.albumsong = albumsongs.id
|
||||
|
|
@ -338,6 +375,26 @@ pub fn generateQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQue
|
|||
\\WHERE id = $1
|
||||
,
|
||||
},
|
||||
|
||||
.datestreak => switch (entity) {
|
||||
.song =>
|
||||
\\SELECT songs.name, albums.name, streak.maxseq, streak.ds, streak.de FROM (SELECT albumsong, MAX(numdays) AS maxseq, ds, de
|
||||
\\FROM (SELECT albumsong, grp, MIN(datetime::date) AS ds, MAX(datetime::date) AS de,
|
||||
\\COUNT(DISTINCT datetime::date) AS numdays
|
||||
\\FROM (SELECT scrobbles.*,
|
||||
\\((datetime::date - '1970-01-01'::date) - DENSE_RANK() OVER (PARTITION BY albumsong ORDER BY datetime::date)) AS grp
|
||||
\\FROM scrobbles
|
||||
\\) scrobbles
|
||||
\\GROUP BY albumsong, grp
|
||||
\\) scrobbles
|
||||
\\GROUP BY albumsong, ds, de) AS streak
|
||||
\\INNER JOIN albumsongs ON albumsongs.id = streak.albumsong
|
||||
\\INNER JOIN albums ON albums.id = albumsongs.album_id
|
||||
\\INNER JOIN songs ON songs.id = albumsongs.song_id
|
||||
\\ORDER BY streak.maxseq DESC;
|
||||
,
|
||||
else => unreachable,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue