+5
src/feed/filter.zig
+5
src/feed/filter.zig
···
64
64
"plyr.fm",
65
65
"open.spotify.com",
66
66
"spotify.link",
67
+
"music.apple.com",
67
68
};
68
69
69
70
fn includeMusicLinks(record: Record) ?bool {
···
110
111
return .spotify;
111
112
}
112
113
if (mem.indexOf(u8, uri, "plyr.fm") != null) return .plyr;
114
+
if (mem.indexOf(u8, uri, "music.apple.com") != null) return .apple;
113
115
return null;
114
116
}
115
117
···
163
165
164
166
// plyr
165
167
try testing.expectEqual(.plyr, detectPlatform("https://plyr.fm/track/123"));
168
+
169
+
// apple music
170
+
try testing.expectEqual(.apple, detectPlatform("https://music.apple.com/au/album/gooey/1440817571"));
166
171
167
172
// unknown
168
173
try testing.expectEqual(null, detectPlatform("https://youtube.com/watch?v=123"));
+2
-1
src/server/dashboard.zig
+2
-1
src/server/dashboard.zig
···
176
176
177
177
// get platform counts
178
178
const platforms = s.getPlatformCounts();
179
-
const total = platforms.soundcloud + platforms.bandcamp + platforms.spotify + platforms.plyr;
179
+
const total = platforms.soundcloud + platforms.bandcamp + platforms.spotify + platforms.plyr + platforms.apple;
180
180
181
181
if (total > 0) {
182
182
const PlatformData = struct { name: []const u8, count: u64, color: []const u8 };
···
185
185
.{ .name = "bandcamp", .count = platforms.bandcamp, .color = "#1da0c3" },
186
186
.{ .name = "spotify", .count = platforms.spotify, .color = "#1db954" },
187
187
.{ .name = "plyr.fm", .count = platforms.plyr, .color = "#7c3aed" },
188
+
.{ .name = "apple music", .count = platforms.apple, .color = "#fa243c" },
188
189
};
189
190
190
191
// sort by count descending
+16
-3
src/server/stats.zig
+16
-3
src/server/stats.zig
···
6
6
7
7
const STATS_PATH = "/data/stats.json";
8
8
9
-
pub const Platform = enum { soundcloud, bandcamp, spotify, plyr };
9
+
pub const Platform = enum { soundcloud, bandcamp, spotify, plyr, apple };
10
10
11
11
pub const Stats = struct {
12
12
started_at: i64,
···
24
24
bandcamp: Atomic(u64),
25
25
spotify: Atomic(u64),
26
26
plyr: Atomic(u64),
27
+
apple: Atomic(u64),
27
28
28
29
// for lag trend tracking
29
30
prev_lag_ms: Atomic(i64),
···
42
43
.bandcamp = Atomic(u64).init(0),
43
44
.spotify = Atomic(u64).init(0),
44
45
.plyr = Atomic(u64).init(0),
46
+
.apple = Atomic(u64).init(0),
45
47
.prev_lag_ms = Atomic(i64).init(0),
46
48
};
47
49
self.load();
···
82
84
if (root.get("plyr")) |v| if (v == .integer) {
83
85
self.plyr.store(@intCast(@max(0, v.integer)), .monotonic);
84
86
};
87
+
if (root.get("apple")) |v| if (v == .integer) {
88
+
self.apple.store(@intCast(@max(0, v.integer)), .monotonic);
89
+
};
85
90
86
91
std.debug.print("loaded stats from {s}\n", .{STATS_PATH});
87
92
}
···
96
101
97
102
var buf: [512]u8 = undefined;
98
103
const data = std.fmt.bufPrint(&buf,
99
-
\\{{"messages":{},"matches":{},"cumulative_uptime":{},"soundcloud":{},"bandcamp":{},"spotify":{},"plyr":{}}}
104
+
\\{{"messages":{},"matches":{},"cumulative_uptime":{},"soundcloud":{},"bandcamp":{},"spotify":{},"plyr":{},"apple":{}}}
100
105
, .{
101
106
self.messages.load(.monotonic),
102
107
self.matches.load(.monotonic),
···
105
110
self.bandcamp.load(.monotonic),
106
111
self.spotify.load(.monotonic),
107
112
self.plyr.load(.monotonic),
113
+
self.apple.load(.monotonic),
108
114
}) catch return;
109
115
110
116
file.writeAll(data) catch return;
···
152
158
.bandcamp => _ = self.bandcamp.fetchAdd(1, .monotonic),
153
159
.spotify => _ = self.spotify.fetchAdd(1, .monotonic),
154
160
.plyr => _ = self.plyr.fetchAdd(1, .monotonic),
161
+
.apple => _ = self.apple.fetchAdd(1, .monotonic),
155
162
}
156
163
}
157
164
158
-
pub fn getPlatformCounts(self: *const Stats) struct { soundcloud: u64, bandcamp: u64, spotify: u64, plyr: u64 } {
165
+
pub fn getPlatformCounts(self: *const Stats) struct { soundcloud: u64, bandcamp: u64, spotify: u64, plyr: u64, apple: u64 } {
159
166
return .{
160
167
.soundcloud = self.soundcloud.load(.monotonic),
161
168
.bandcamp = self.bandcamp.load(.monotonic),
162
169
.spotify = self.spotify.load(.monotonic),
163
170
.plyr = self.plyr.load(.monotonic),
171
+
.apple = self.apple.load(.monotonic),
164
172
};
165
173
}
166
174
···
238
246
.bandcamp = Atomic(u64).init(0),
239
247
.spotify = Atomic(u64).init(0),
240
248
.plyr = Atomic(u64).init(0),
249
+
.apple = Atomic(u64).init(0),
241
250
.prev_lag_ms = Atomic(i64).init(0),
242
251
};
243
252
···
262
271
.bandcamp = Atomic(u64).init(0),
263
272
.spotify = Atomic(u64).init(0),
264
273
.plyr = Atomic(u64).init(0),
274
+
.apple = Atomic(u64).init(0),
265
275
.prev_lag_ms = Atomic(i64).init(0),
266
276
};
267
277
268
278
s.recordPlatform(.soundcloud);
269
279
s.recordPlatform(.soundcloud);
270
280
s.recordPlatform(.bandcamp);
281
+
s.recordPlatform(.apple);
271
282
272
283
const counts = s.getPlatformCounts();
273
284
try std.testing.expectEqual(2, counts.soundcloud);
274
285
try std.testing.expectEqual(1, counts.bandcamp);
275
286
try std.testing.expectEqual(0, counts.spotify);
276
287
try std.testing.expectEqual(0, counts.plyr);
288
+
try std.testing.expectEqual(1, counts.apple);
277
289
}
278
290
279
291
test "Stats.getStatus returns live or catching_up" {
···
290
302
.bandcamp = Atomic(u64).init(0),
291
303
.spotify = Atomic(u64).init(0),
292
304
.plyr = Atomic(u64).init(0),
305
+
.apple = Atomic(u64).init(0),
293
306
.prev_lag_ms = Atomic(i64).init(0),
294
307
};
295
308