From 830659420afcd12d766a399e9d7287b05bdb748d Mon Sep 17 00:00:00 2001 From: iProdigy <8106344+iProdigy@users.noreply.github.com> Date: Wed, 6 Sep 2023 13:06:24 -0700 Subject: [PATCH] feat(pubsub): support unofficial ads manager topic (#847) --- .../github/twitch4j/pubsub/ITwitchPubSub.java | 5 ++++ .../github/twitch4j/pubsub/TwitchPubSub.java | 9 ++++++ .../pubsub/domain/ScheduleUpdate.java | 25 ++++++++++++++++ .../twitch4j/pubsub/domain/ScheduledAd.java | 17 +++++++++++ .../pubsub/events/AdsScheduleUpdateEvent.java | 13 +++++++++ .../pubsub/domain/ScheduleUpdateTest.java | 29 +++++++++++++++++++ 6 files changed, 98 insertions(+) create mode 100644 pubsub/src/main/java/com/github/twitch4j/pubsub/domain/ScheduleUpdate.java create mode 100644 pubsub/src/main/java/com/github/twitch4j/pubsub/domain/ScheduledAd.java create mode 100644 pubsub/src/main/java/com/github/twitch4j/pubsub/events/AdsScheduleUpdateEvent.java create mode 100644 pubsub/src/test/java/com/github/twitch4j/pubsub/domain/ScheduleUpdateTest.java diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/ITwitchPubSub.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/ITwitchPubSub.java index d9720c703..a8c681629 100644 --- a/pubsub/src/main/java/com/github/twitch4j/pubsub/ITwitchPubSub.java +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/ITwitchPubSub.java @@ -203,6 +203,11 @@ default PubSubSubscription listenForAdsEvents(OAuth2Credential credential, Strin return listenOnTopic(PubSubType.LISTEN, credential, "ads." + channelId); } + @Unofficial + default PubSubSubscription listenForAdsManagerEvents(OAuth2Credential credential, String userId, String channelId) { + return listenOnTopic(PubSubType.LISTEN, credential, "ads-manager." + userId + '.' + channelId); + } + @Unofficial @Deprecated default PubSubSubscription listenForAdPropertyRefreshEvents(OAuth2Credential credential, String channelId) { diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/TwitchPubSub.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/TwitchPubSub.java index a4485de1d..af4a2383b 100644 --- a/pubsub/src/main/java/com/github/twitch4j/pubsub/TwitchPubSub.java +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/TwitchPubSub.java @@ -60,6 +60,7 @@ import com.github.twitch4j.pubsub.domain.PubSubResponse; import com.github.twitch4j.pubsub.domain.RadioData; import com.github.twitch4j.pubsub.domain.RedemptionProgress; +import com.github.twitch4j.pubsub.domain.ScheduleUpdate; import com.github.twitch4j.pubsub.domain.ShieldModeSettings; import com.github.twitch4j.pubsub.domain.ShieldModeStatus; import com.github.twitch4j.pubsub.domain.SubGiftData; @@ -73,6 +74,7 @@ import com.github.twitch4j.pubsub.domain.VideoPlaybackData; import com.github.twitch4j.pubsub.domain.WhisperThread; import com.github.twitch4j.pubsub.enums.PubSubType; +import com.github.twitch4j.pubsub.events.AdsScheduleUpdateEvent; import com.github.twitch4j.pubsub.events.AliasRestrictionUpdateEvent; import com.github.twitch4j.pubsub.events.AutomodCaughtMessageEvent; import com.github.twitch4j.pubsub.events.AutomodLevelsModifiedEvent; @@ -472,6 +474,13 @@ protected void onTextMessage(String text) { } else { log.warn("Unparsable Message: " + message.getType() + "|" + message.getData()); } + } else if ("ads-manager".equals(topicName)) { + if ("ads-schedule-update".equals(type)) { + ScheduleUpdate data = TypeConvert.jsonToObject(rawMessage, ScheduleUpdate.class); + eventManager.publish(new AdsScheduleUpdateEvent(lastTopicIdentifier, data)); + } else { + log.warn("Unparsable Message: " + message.getType() + "|" + message.getData()); + } } else if ("community-boost-events-v1".equals(topicName)) { if ("community-boost-progression".equals(type)) { CommunityBoostProgression progression = TypeConvert.convertValue(msgData, CommunityBoostProgression.class); diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/ScheduleUpdate.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/ScheduleUpdate.java new file mode 100644 index 000000000..4cdeb7559 --- /dev/null +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/ScheduleUpdate.java @@ -0,0 +1,25 @@ +package com.github.twitch4j.pubsub.domain; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +import java.util.List; + +@Data +@Setter(AccessLevel.PRIVATE) +@JsonNaming(PropertyNamingStrategies.LowerCamelCaseStrategy.class) +public class ScheduleUpdate { + private String scheduleUpdateType; + private List adSchedule; + + public boolean isSnooze() { + return "Snooze".equalsIgnoreCase(scheduleUpdateType); + } + + public boolean isRemoval() { + return "RemoveAdTime".equalsIgnoreCase(scheduleUpdateType); + } +} diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/ScheduledAd.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/ScheduledAd.java new file mode 100644 index 000000000..1f6a5e7f1 --- /dev/null +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/ScheduledAd.java @@ -0,0 +1,17 @@ +package com.github.twitch4j.pubsub.domain; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +import java.time.Instant; + +@Data +@Setter(AccessLevel.PRIVATE) +@JsonNaming(PropertyNamingStrategies.LowerCamelCaseStrategy.class) +public class ScheduledAd { + private Instant runAtTime; + private Long durationSeconds; +} diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/events/AdsScheduleUpdateEvent.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/events/AdsScheduleUpdateEvent.java new file mode 100644 index 000000000..7bfd07af9 --- /dev/null +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/events/AdsScheduleUpdateEvent.java @@ -0,0 +1,13 @@ +package com.github.twitch4j.pubsub.events; + +import com.github.twitch4j.common.events.TwitchEvent; +import com.github.twitch4j.pubsub.domain.ScheduleUpdate; +import lombok.EqualsAndHashCode; +import lombok.Value; + +@Value +@EqualsAndHashCode(callSuper = false) +public class AdsScheduleUpdateEvent extends TwitchEvent { + String channelId; + ScheduleUpdate data; +} diff --git a/pubsub/src/test/java/com/github/twitch4j/pubsub/domain/ScheduleUpdateTest.java b/pubsub/src/test/java/com/github/twitch4j/pubsub/domain/ScheduleUpdateTest.java new file mode 100644 index 000000000..548f98a20 --- /dev/null +++ b/pubsub/src/test/java/com/github/twitch4j/pubsub/domain/ScheduleUpdateTest.java @@ -0,0 +1,29 @@ +package com.github.twitch4j.pubsub.domain; + +import com.github.twitch4j.common.util.TypeConvert; +import org.junit.jupiter.api.Test; + +import java.time.Instant; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ScheduleUpdateTest { + + @Test + void deserializeSnooze() { + String json = "{\"type\":\"ads-schedule-update\",\"scheduleUpdateType\":\"Snooze\",\"adSchedule\":[{\"runAtTime\":\"2023-07-20T16:30:45Z\",\"durationSeconds\":60}]}"; + ScheduleUpdate data = TypeConvert.jsonToObject(json, ScheduleUpdate.class); + assertNotNull(data); + assertTrue(data.isSnooze()); + assertNotNull(data.getAdSchedule()); + assertFalse(data.getAdSchedule().isEmpty()); + ScheduledAd ad = data.getAdSchedule().get(0); + assertNotNull(ad); + assertEquals(60L, ad.getDurationSeconds()); + assertEquals(Instant.parse("2023-07-20T16:30:45Z"), ad.getRunAtTime()); + } + +}