diff --git a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackEndEvent.java b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackEndEvent.java index 60e32e7..e39823e 100644 --- a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackEndEvent.java +++ b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackEndEvent.java @@ -4,12 +4,15 @@ import net.pixaurora.kit_tunes.api.music.ListeningProgress; import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kit_tunes.api.resource.ResourcePath; public interface TrackEndEvent { - public Optional track(); + public Optional track(); - public ResourcePath searchPath(); + public Optional record(); - public ListeningProgress progress(); + public ResourcePath searchPath(); + + public ListeningProgress progress(); } diff --git a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackMiddleEvent.java b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackMiddleEvent.java index d21ac9f..d6e9583 100644 --- a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackMiddleEvent.java +++ b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackMiddleEvent.java @@ -4,11 +4,14 @@ import net.pixaurora.kit_tunes.api.music.ListeningProgress; import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kit_tunes.api.resource.ResourcePath; public interface TrackMiddleEvent { public Optional track(); + public Optional record(); + public ResourcePath searchPath(); public ListeningProgress progress(); diff --git a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackStartEvent.java b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackStartEvent.java index 40a5a78..2b7d96d 100644 --- a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackStartEvent.java +++ b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackStartEvent.java @@ -4,12 +4,15 @@ import net.pixaurora.kit_tunes.api.music.ListeningProgress; import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kit_tunes.api.resource.ResourcePath; public interface TrackStartEvent { - public Optional track(); + public Optional track(); - public ResourcePath searchPath(); + public Optional record(); - public ListeningProgress progress(); + public ResourcePath searchPath(); + + public ListeningProgress progress(); } diff --git a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/music/history/ListenDurations.java b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/music/history/ListenDurations.java new file mode 100644 index 0000000..4b2bbd4 --- /dev/null +++ b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/music/history/ListenDurations.java @@ -0,0 +1,9 @@ +package net.pixaurora.kit_tunes.api.music.history; + +import java.time.Duration; + +public interface ListenDurations { + public Duration progress(); + + public Duration full(); +} diff --git a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/music/history/ListenRecord.java b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/music/history/ListenRecord.java new file mode 100644 index 0000000..a5d9af2 --- /dev/null +++ b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/music/history/ListenRecord.java @@ -0,0 +1,52 @@ +package net.pixaurora.kit_tunes.api.music.history; + +import java.time.Instant; +import java.util.List; +import java.util.Optional; + +import net.pixaurora.kit_tunes.api.music.Album; +import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.scrobble.ScrobblerId; + +public class ListenRecord { + private final Track track; + private final Optional album; + private final Instant timestamp; + + private final ListenDurations durations; + + private final List succeededScrobblers; + + public ListenRecord(Track track, Optional album, Instant timestamp, ListenDurations durations, + List succeededScrobblers) { + this.track = track; + this.album = album; + this.timestamp = timestamp; + this.durations = durations; + this.succeededScrobblers = succeededScrobblers; + } + + public Track track() { + return this.track; + } + + public Optional album() { + return this.album; + } + + public Instant timestamp() { + return this.timestamp; + } + + public ListenDurations durations() { + return this.durations; + } + + public List succeededScrobblers() { + return this.succeededScrobblers; + } + + public void succeededFor(ScrobblerId scrobbler) { + this.succeededScrobblers.add(scrobbler); + } +} diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/ScrobblerId.java b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/scrobble/ScrobblerId.java similarity index 95% rename from projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/ScrobblerId.java rename to projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/scrobble/ScrobblerId.java index 09827eb..66ea2b3 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/ScrobblerId.java +++ b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/scrobble/ScrobblerId.java @@ -1,4 +1,4 @@ -package net.pixaurora.kitten_heart.impl.scrobble; +package net.pixaurora.kit_tunes.api.scrobble; public class ScrobblerId { private final String username; diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/EventHandling.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/EventHandling.java index b5e578b..7af29af 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/EventHandling.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/EventHandling.java @@ -50,7 +50,7 @@ public static void handleTrackEnd(ListeningProgress progress) { } private static void handleTrackEnd(PlayingSong song) { - TrackEndEvent event = new TrackEventImpl(song.path(), song.track(), song.progress()); + TrackEndEvent event = new TrackEventImpl(song); processEvent(listener -> listener.onTrackEnd(event)); } @@ -75,7 +75,7 @@ public static void tick() { if (song.canSendMiddleEvent()) { processEvent(listener -> listener - .onTrackMiddleReached(new TrackEventImpl(song.path(), song.track(), song.progress()))); + .onTrackMiddleReached(new TrackEventImpl(song))); } } } @@ -123,11 +123,13 @@ private static TrackStartEvent createStartEvent(ResourcePath path, ListeningProg MusicMetadata.asMutable().giveDuration(track.get(), songDuration); } + PlayingSong song = new PlayingSong(path, track, progress, controls); + synchronized (PLAYING_TRACKS) { - PLAYING_TRACKS.put(progress, new PlayingSong(path, track, progress, controls)); + PLAYING_TRACKS.put(progress, song); } - return new TrackEventImpl(path, track, progress); + return new TrackEventImpl(song); } private static Duration songDuration(ResourcePath path) throws IOException { diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/config/ScrobblerCache.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/config/ScrobblerCache.java index 6199f61..2a58940 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/config/ScrobblerCache.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/config/ScrobblerCache.java @@ -12,9 +12,9 @@ import com.google.gson.JsonSerializationContext; import net.pixaurora.catculator.api.http.Client; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kitten_heart.impl.KitTunes; import net.pixaurora.kitten_heart.impl.error.KitTunesException; -import net.pixaurora.kitten_heart.impl.music.history.ListenRecord; import net.pixaurora.kitten_heart.impl.scrobble.SimpleScrobbler; import net.pixaurora.kitten_heart.impl.scrobble.scrobbler.Scrobbler; @@ -46,7 +46,7 @@ public void startScrobbling(Client client, ListenRecord track) { public void completeScrobbling(Client client, ListenRecord track) { this.handleScrobbling(scrobbler -> { scrobbler.completeScrobbling(client, track); - track.succeededFor(scrobbler); + track.succeededFor(scrobbler.id()); }); } diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/config/Serialization.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/config/Serialization.java index d065a08..2cc6a90 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/config/Serialization.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/config/Serialization.java @@ -12,12 +12,15 @@ import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kit_tunes.api.resource.ResourcePath; +import net.pixaurora.kit_tunes.api.scrobble.ScrobblerId; import net.pixaurora.kitten_heart.impl.music.AlbumImpl; import net.pixaurora.kitten_heart.impl.music.ArtistImpl; import net.pixaurora.kitten_heart.impl.music.TrackImpl; -import net.pixaurora.kitten_heart.impl.music.history.ListenRecord; +import net.pixaurora.kitten_heart.impl.music.history.ListenRecordSerializer; import net.pixaurora.kitten_heart.impl.resource.ResourcePathImpl; +import net.pixaurora.kitten_heart.impl.scrobble.ScrobblerIdSerializer; import net.pixaurora.kitten_heart.impl.scrobble.scrobbler.Scrobbler; public class Serialization { @@ -33,7 +36,8 @@ private static final Gson createSerializer() { .registerTypeAdapter(TrackImpl.TransformsToTrack.class, new TrackImpl.TransformsToTrack.Serializer()) .registerTypeAdapter(TrackImpl.FromData.class, new TrackImpl.FromData.Serializer()) .registerTypeAdapter(TrackImpl.FromPath.class, TrackImpl.FromPath.SERIALIZER) - .registerTypeAdapter(ListenRecord.class, new ListenRecord.Serializer()) + .registerTypeAdapter(ListenRecord.class, new ListenRecordSerializer()) + .registerTypeAdapter(ScrobblerId.class, new ScrobblerIdSerializer()) .registerTypeAdapter(Duration.class, new DurationSerializer()) .registerTypeAdapter(Instant.class, new InstantSerializer()) .create(); diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/event/TrackEventImpl.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/event/TrackEventImpl.java index 934c380..7059aa0 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/event/TrackEventImpl.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/event/TrackEventImpl.java @@ -7,17 +7,26 @@ import net.pixaurora.kit_tunes.api.event.TrackStartEvent; import net.pixaurora.kit_tunes.api.music.ListeningProgress; import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kit_tunes.api.resource.ResourcePath; +import net.pixaurora.kitten_heart.impl.music.progress.PlayingSong; public class TrackEventImpl implements TrackStartEvent, TrackMiddleEvent, TrackEndEvent { private final ResourcePath path; private final Optional track; + private final Optional record; private final ListeningProgress progress; - public TrackEventImpl(ResourcePath path, Optional track, ListeningProgress progress) { + public TrackEventImpl(ResourcePath path, Optional track, Optional record, + ListeningProgress progress) { this.path = path; this.track = track; this.progress = progress; + this.record = record; + } + + public TrackEventImpl(PlayingSong song) { + this(song.path(), song.track(), song.record(), song.progress()); } @Override @@ -34,4 +43,9 @@ public ResourcePath searchPath() { public ListeningProgress progress() { return this.progress; } + + @Override + public Optional record() { + return this.record; + } } diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/listener/ScrobblingMusicListener.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/listener/ScrobblingMusicListener.java index f0d13a2..8787787 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/listener/ScrobblingMusicListener.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/listener/ScrobblingMusicListener.java @@ -6,22 +6,17 @@ import net.pixaurora.kit_tunes.api.event.TrackMiddleEvent; import net.pixaurora.kit_tunes.api.event.TrackStartEvent; import net.pixaurora.kit_tunes.api.listener.MusicEventListener; -import net.pixaurora.kit_tunes.api.music.ListeningProgress; -import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kitten_heart.impl.KitTunes; -import net.pixaurora.kitten_heart.impl.music.history.ListenRecord; public class ScrobblingMusicListener implements MusicEventListener { @Override public void onTrackStart(TrackStartEvent event) { - if (!event.track().isPresent()) { + if (!event.record().isPresent()) { return; } - Track track = event.track().get(); - ListeningProgress progress = event.progress(); - - ListenRecord record = new ListenRecord(track, progress); + ListenRecord record = event.record().get(); KitTunes.SCROBBLER_CACHE.execute( scrobblers -> scrobblers.startScrobbling(KitTunes.CLIENT, record)); @@ -29,11 +24,11 @@ public void onTrackStart(TrackStartEvent event) { @Override public void onTrackMiddleReached(TrackMiddleEvent event) { - if (!event.track().isPresent()) { + if (!event.record().isPresent()) { return; } - ListenRecord record = new ListenRecord(event.track().get(), event.progress()); + ListenRecord record = event.record().get(); KitTunes.SCROBBLER_CACHE .execute(scrobblers -> scrobblers.completeScrobbling(KitTunes.CLIENT, record)); @@ -41,11 +36,11 @@ public void onTrackMiddleReached(TrackMiddleEvent event) { @Override public void onTrackEnd(TrackEndEvent event) { - if (!event.track().isPresent()) { + if (!event.record().isPresent()) { return; } - ListenRecord record = new ListenRecord(event.track().get(), event.progress()); + ListenRecord record = event.record().get(); KitTunes.LISTEN_HISTORY.execute(history -> history.record(record)); try { diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ImmutableListenDurations.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ImmutableListenDurations.java new file mode 100644 index 0000000..45927f1 --- /dev/null +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ImmutableListenDurations.java @@ -0,0 +1,25 @@ +package net.pixaurora.kitten_heart.impl.music.history; + +import java.time.Duration; + +import net.pixaurora.kit_tunes.api.music.history.ListenDurations; + +public class ImmutableListenDurations implements ListenDurations { + private final Duration progress; + private final Duration full; + + public ImmutableListenDurations(Duration progress, Duration full) { + this.progress = progress; + this.full = full; + } + + @Override + public Duration progress() { + return this.progress; + } + + @Override + public Duration full() { + return this.full; + } +} diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenHistory.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenHistory.java index 4aaceb3..37f6ee0 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenHistory.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenHistory.java @@ -6,12 +6,17 @@ import java.util.List; import java.util.function.Predicate; +import com.google.gson.annotations.SerializedName; + +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; + public class ListenHistory { private final List history; - private Duration timespanStored; + @SerializedName("max_retention") + private Duration maxRetention; - public ListenHistory(Duration timespanStored, List history) { - this.timespanStored = timespanStored; + public ListenHistory(Duration maxRetention, List history) { + this.maxRetention = maxRetention; this.history = history; } @@ -23,12 +28,12 @@ public List getHistory() { return history; } - public Duration timespanStored() { - return timespanStored; + public Duration maxRetention() { + return this.maxRetention; } public void timespanStored(Duration newValue) { - this.timespanStored = newValue; + this.maxRetention = newValue; this.clearOldHistory(); } @@ -40,7 +45,7 @@ public void record(ListenRecord record) { private void clearOldHistory() { Predicate isTooOld = record -> Duration .between(record.timestamp(), Instant.now()) - .compareTo(this.timespanStored) > 0; + .compareTo(this.maxRetention) > 0; this.history.removeIf(isTooOld); } diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenRecord.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenRecord.java deleted file mode 100644 index 1b9ee6e..0000000 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenRecord.java +++ /dev/null @@ -1,127 +0,0 @@ -package net.pixaurora.kitten_heart.impl.music.history; - -import java.lang.reflect.Type; -import java.time.Duration; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSerializationContext; - -import net.pixaurora.kit_tunes.api.music.Album; -import net.pixaurora.kit_tunes.api.music.ListeningProgress; -import net.pixaurora.kit_tunes.api.music.Track; -import net.pixaurora.kit_tunes.api.resource.ResourcePath; -import net.pixaurora.kitten_heart.impl.config.DualSerializer; -import net.pixaurora.kitten_heart.impl.music.AlbumImpl; -import net.pixaurora.kitten_heart.impl.music.TrackImpl; -import net.pixaurora.kitten_heart.impl.scrobble.ScrobblerId; -import net.pixaurora.kitten_heart.impl.scrobble.scrobbler.Scrobbler; - -public class ListenRecord { - private final Track track; - private final Optional album; - private final Instant timestamp; - - private final Duration listenedDuration; - private final Duration fullDuration; - - private final List succeededScrobblers; - - public ListenRecord(Track track, Optional album, Instant timestamp, Duration listenedDuration, - Duration fullDuration, List succeededScrobblers) { - this.track = track; - this.album = album; - this.timestamp = timestamp; - this.listenedDuration = listenedDuration; - this.fullDuration = fullDuration; - this.succeededScrobblers = succeededScrobblers; - } - - public ListenRecord(Track track, ListeningProgress progress) { - this(track, track.album(), progress.startTime(), progress.amountPlayed(), track.duration(), new ArrayList<>()); - } - - public Track track() { - return this.track; - } - - public Optional album() { - return this.album; - } - - public Instant timestamp() { - return this.timestamp; - } - - public Duration listenedDuration() { - return this.listenedDuration; - } - - public Duration fullDuration() { - return this.fullDuration; - } - - public List succeededScrobblers() { - return this.succeededScrobblers; - } - - public void succeededFor(Scrobbler scrobbler) { - this.succeededScrobblers.add(scrobbler.id()); - } - - public static class Serializer implements DualSerializer { - @Override - public JsonElement serialize(ListenRecord record, Type typeOfSrc, JsonSerializationContext context) { - JsonObject json = new JsonObject(); - - json.add("track", context.serialize(record.track.path(), ResourcePath.class)); - - if (record.album.isPresent()) { - json.add("album", context.serialize(record.album.get().path(), ResourcePath.class)); - } - - json.add("timestamp", context.serialize(record.timestamp)); - - json.add("listened_for", context.serialize(record.listenedDuration)); - - json.add("full_time", context.serialize(record.fullDuration)); - - json.add("succeeded", context.serialize(record.succeededScrobblers)); - - return json; - } - - @Override - public ListenRecord deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - JsonObject object = json.getAsJsonObject(); - - TrackImpl.FromPath trackFromPath = context.deserialize(object.get("track"), TrackImpl.FromPath.class); - Track track = trackFromPath.transform(); - - Optional albumFromPath = Optional.ofNullable(object.get("album")) - .map(album0 -> context.deserialize(album0, AlbumImpl.FromPath.class)); - Optional album = albumFromPath.map(AlbumImpl.FromPath::transform); - - Instant timestamp = context.deserialize(object.get("timestamp"), Instant.class); - - Duration listenedDuration = context.deserialize(object.get("listened_for"), Duration.class); - - Duration fullDuration = context.deserialize(object.get("full_time"), Duration.class); - - List succeededScrobblers = new ArrayList<>(); - for (JsonElement scrobblerId : object.get("succeeded").getAsJsonArray()) { - succeededScrobblers.add(context.deserialize(scrobblerId, ScrobblerId.class)); - } - - return new ListenRecord(track, album, timestamp, listenedDuration, fullDuration, - succeededScrobblers); - } - } -} diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenRecordSerializer.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenRecordSerializer.java new file mode 100644 index 0000000..59b7b43 --- /dev/null +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/ListenRecordSerializer.java @@ -0,0 +1,71 @@ +package net.pixaurora.kitten_heart.impl.music.history; + +import java.lang.reflect.Type; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; + +import net.pixaurora.kit_tunes.api.music.Album; +import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; +import net.pixaurora.kit_tunes.api.resource.ResourcePath; +import net.pixaurora.kit_tunes.api.scrobble.ScrobblerId; +import net.pixaurora.kitten_heart.impl.config.DualSerializer; +import net.pixaurora.kitten_heart.impl.music.AlbumImpl; +import net.pixaurora.kitten_heart.impl.music.TrackImpl; + +public class ListenRecordSerializer implements DualSerializer { + @Override + public JsonElement serialize(ListenRecord record, Type typeOfSrc, JsonSerializationContext context) { + JsonObject json = new JsonObject(); + + json.add("track", context.serialize(record.track().path(), ResourcePath.class)); + + if (record.album().isPresent()) { + json.add("album", context.serialize(record.album().get().path(), ResourcePath.class)); + } + + json.add("timestamp", context.serialize(record.timestamp())); + + json.add("progress", context.serialize(record.durations().progress())); + json.add("duration", context.serialize(record.durations().full())); + + json.add("succeeded", context.serialize(record.succeededScrobblers())); + + return json; + } + + @Override + public ListenRecord deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject object = json.getAsJsonObject(); + + TrackImpl.FromPath trackFromPath = context.deserialize(object.get("track"), TrackImpl.FromPath.class); + Track track = trackFromPath.transform(); + + Optional albumFromPath = Optional.ofNullable(object.get("album")) + .map(album0 -> context.deserialize(album0, AlbumImpl.FromPath.class)); + Optional album = albumFromPath.map(AlbumImpl.FromPath::transform); + + Instant timestamp = context.deserialize(object.get("timestamp"), Instant.class); + + Duration progress = context.deserialize(object.get("duration"), Duration.class); + Duration duration = context.deserialize(object.get("progress"), Duration.class); + + List succeededScrobblers = new ArrayList<>(); + for (JsonElement scrobblerId : object.get("succeeded").getAsJsonArray()) { + succeededScrobblers.add(context.deserialize(scrobblerId, ScrobblerId.class)); + } + + return new ListenRecord(track, album, timestamp, new ImmutableListenDurations(progress, duration), + succeededScrobblers); + } +} diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/MutableListenDurations.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/MutableListenDurations.java new file mode 100644 index 0000000..452941d --- /dev/null +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/history/MutableListenDurations.java @@ -0,0 +1,26 @@ +package net.pixaurora.kitten_heart.impl.music.history; + +import java.time.Duration; + +import net.pixaurora.kit_tunes.api.music.ListeningProgress; +import net.pixaurora.kit_tunes.api.music.history.ListenDurations; + +public class MutableListenDurations implements ListenDurations { + private final ListeningProgress progress; + private final Duration full; + + public MutableListenDurations(ListeningProgress progress, Duration full) { + this.progress = progress; + this.full = full; + } + + @Override + public Duration progress() { + return this.progress.amountPlayed(); + } + + @Override + public Duration full() { + return this.full; + } +} diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java index 54fb5c0..9f2ba00 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java @@ -1,18 +1,22 @@ package net.pixaurora.kitten_heart.impl.music.progress; import java.time.Duration; +import java.util.ArrayList; import java.util.Optional; import net.pixaurora.kit_tunes.api.music.ListeningProgress; import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kit_tunes.api.resource.ResourcePath; import net.pixaurora.kitten_heart.impl.Constants; import net.pixaurora.kitten_heart.impl.music.control.MusicControls; +import net.pixaurora.kitten_heart.impl.music.history.MutableListenDurations; import net.pixaurora.kitten_heart.impl.ui.widget.progress.ProgressProvider; public class PlayingSong implements ProgressProvider { private final ResourcePath path; private final Optional track; + private final Optional record; private final ListeningProgress progress; private final MusicControls controls; @@ -27,6 +31,19 @@ public PlayingSong(ResourcePath path, Optional track, ListeningProgress p this.controls = controls; this.middleEventMillis = track.map(Track::duration).map(duration -> duration.toMillis() * 6 / 10) .orElse(Constants.MINIMUM_TIME_TO_SCROBBLE.toMillis()); + + if (this.track.isPresent()) { + Track track0 = track.get(); + + this.record = Optional.of(new ListenRecord( + track0, + track0.album(), + progress.startTime(), + new MutableListenDurations(progress, track0.duration()), + new ArrayList<>())); + } else { + this.record = Optional.empty(); + } } public ResourcePath path() { @@ -37,6 +54,10 @@ public Optional track() { return this.track; } + public Optional record() { + return this.record; + } + public ListeningProgress progress() { return this.progress; } diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/ScrobblerIdSerializer.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/ScrobblerIdSerializer.java new file mode 100644 index 0000000..ee3a8ff --- /dev/null +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/ScrobblerIdSerializer.java @@ -0,0 +1,35 @@ +package net.pixaurora.kitten_heart.impl.scrobble; + +import java.lang.reflect.Type; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; + +import net.pixaurora.kit_tunes.api.scrobble.ScrobblerId; +import net.pixaurora.kitten_heart.impl.config.DualSerializer; + +public class ScrobblerIdSerializer implements DualSerializer { + @Override + public JsonElement serialize(ScrobblerId src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject json = new JsonObject(); + + json.addProperty("username", src.username()); + json.addProperty("scrobbler_type", src.scrobblerType()); + + return json; + } + + @Override + public ScrobblerId deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject object = json.getAsJsonObject(); + + String username = object.getAsJsonPrimitive("username").getAsString(); + String scrobblerType = object.getAsJsonPrimitive("scrobbler_type").getAsString(); + + return new ScrobblerId(username, scrobblerType); + } +} diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/SimpleScrobbler.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/SimpleScrobbler.java index 174fd9c..6d1296e 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/SimpleScrobbler.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/SimpleScrobbler.java @@ -1,8 +1,8 @@ package net.pixaurora.kitten_heart.impl.scrobble; import net.pixaurora.catculator.api.http.Client; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kitten_heart.impl.error.KitTunesException; -import net.pixaurora.kitten_heart.impl.music.history.ListenRecord; public interface SimpleScrobbler { public void startScrobbling(Client client, ListenRecord track) throws KitTunesException; diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/scrobbler/LastFMScrobbler.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/scrobbler/LastFMScrobbler.java index 5af1e12..fd65b68 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/scrobbler/LastFMScrobbler.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/scrobbler/LastFMScrobbler.java @@ -13,9 +13,9 @@ import net.pixaurora.catculator.api.http.Client; import net.pixaurora.catculator.api.http.RequestBuilder; import net.pixaurora.catculator.api.http.Response; +import net.pixaurora.kit_tunes.api.music.history.ListenRecord; import net.pixaurora.kitten_heart.impl.KitTunes; import net.pixaurora.kitten_heart.impl.error.UnhandledKitTunesException; -import net.pixaurora.kitten_heart.impl.music.history.ListenRecord; import org.w3c.dom.Document; import org.w3c.dom.Node; diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/scrobbler/Scrobbler.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/scrobbler/Scrobbler.java index be29780..6e870d9 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/scrobbler/Scrobbler.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/scrobble/scrobbler/Scrobbler.java @@ -2,9 +2,9 @@ import java.util.Arrays; +import net.pixaurora.kit_tunes.api.scrobble.ScrobblerId; import net.pixaurora.kitten_heart.impl.config.dispatch.DispatchGroup; import net.pixaurora.kitten_heart.impl.config.dispatch.SpecifiesType; -import net.pixaurora.kitten_heart.impl.scrobble.ScrobblerId; import net.pixaurora.kitten_heart.impl.scrobble.ScrobblerType; import net.pixaurora.kitten_heart.impl.scrobble.SimpleScrobbler;