Skip to content

Commit

Permalink
Fix: Send more data to MinuteWatched to make drops progress & Unrecog…
Browse files Browse the repository at this point in the history
…nized field "count_by_md" (#622)

* Fix: send more data to minute watched event

See: rdavydov/Twitch-Channel-Points-Miner-v2#378

* tests

* Refactor

* Fix for #623
  • Loading branch information
Rakambda committed Oct 23, 2023
1 parent 084552e commit a2366d8
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,26 @@
@Builder
@EqualsAndHashCode
public class MinuteWatchedProperties{
@JsonProperty("channel_id")
@NotNull
private String channelId;
@JsonProperty("broadcast_id")
@NotNull
private String broadcastId;
@JsonProperty("channel")
@NotNull
private String channel;
@JsonProperty("channel_id")
@NotNull
private String channelId;
@JsonProperty("game")
@Nullable
private String game;
@JsonProperty("game_id")
@Nullable
private String gameId;
@JsonProperty("live")
private boolean live;
@JsonProperty("player")
@NotNull
private String player;
@JsonProperty("user_id")
private int userId;
@JsonProperty("game")
@Nullable
private String game;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import fr.rakambda.channelpointsminer.miner.util.json.ISO8601ZonedDateTimeDeserializer;
import fr.rakambda.channelpointsminer.miner.util.json.UnknownDeserializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
Expand All @@ -29,4 +30,8 @@ public class Summary{
@JsonDeserialize(using = ISO8601ZonedDateTimeDeserializer.class)
@Nullable
private ZonedDateTime lastSeen;
@JsonProperty("count_by_md")
@Nullable
@JsonDeserialize(using = UnknownDeserializer.class)
private Object countByMd;
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,10 @@ public void start(){
scheduledExecutor.schedule(streamerConfigurationReload, 0, MINUTES);
}

listenTopic(COMMUNITY_POINTS_USER_V1, getTwitchLogin().fetchUserId(gqlApi));
listenTopic(USER_DROP_EVENTS, getTwitchLogin().fetchUserId(gqlApi));
listenTopic(ONSITE_NOTIFICATIONS, getTwitchLogin().fetchUserId(gqlApi));
var connectedUserId = getTwitchLogin().fetchUserId(gqlApi);
listenTopic(COMMUNITY_POINTS_USER_V1, connectedUserId);
listenTopic(USER_DROP_EVENTS, connectedUserId);
listenTopic(ONSITE_NOTIFICATIONS, connectedUserId);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,13 @@ private boolean send(Streamer streamer){
var request = MinuteWatchedEvent.builder()
.properties(MinuteWatchedProperties.builder()
.channelId(streamer.getId())
.channel(streamer.getUsername())
.broadcastId(streamId.get())
.player(SITE_PLAYER)
.userId(miner.getTwitchLogin().getUserIdAsInt(miner.getGqlApi()))
.gameId(streamer.getGame().map(Game::getId).orElse(null))
.game(streamer.getGame().map(Game::getName).orElse(null))
.live(true)
.build())
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public String deserialize(@NotNull JsonParser jsonParser, @NotNull Deserializati
var currentLocation = jsonParser.getCurrentLocation();
var treeNode = jsonParser.readValueAsTree();
var treeNodeStr = treeNode == null ? null : treeNode.toString();
log.warn("Got actual value for field {} (l:{},c:{}) : {}", jsonParser.getCurrentName(), currentLocation.getLineNr(), currentLocation.getColumnNr(), treeNodeStr);
log.warn("Got actual value for unknown field {} (l:{},c:{}) : {}", jsonParser.getCurrentName(), currentLocation.getLineNr(), currentLocation.getColumnNr(), treeNodeStr);
return treeNodeStr;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ class TwitchApiTest{
private static final int USER_ID = 123456789;
private static final String BROADCAST_ID = "broadcast-id";
private static final String CHANNEL_ID = "channel-id";
private static final String CHANNEL_NAME = "channel-name";
private static final String PLAYER = "player";
private static final String GAME = "game";
private static final String GAME_ID = "game-id";
private static final String STREAMER_URL = "https://google.com/streamer";
private static final String CONFIG_URL = "https://static.twitchcdn.net/config/settings.sq5d4q6s54ds854c84qs.js";
private static final String CONFIG_BODY = "<script src=\"%s\" crossorigin=\"anonymous\"></script>".formatted(CONFIG_URL);
Expand All @@ -56,8 +58,8 @@ void setUp(UnirestMock unirestMock) throws MalformedURLException{

@Test
void sendMinutesWatched(UnirestMock unirest){
var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel_id\":\"%s\",\"player\":\"%s\",\"user_id\":%d}}]"
.formatted(BROADCAST_ID, CHANNEL_ID, PLAYER, USER_ID);
var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel\":\"%s\",\"channel_id\":\"%s\",\"live\":true,\"player\":\"%s\",\"user_id\":%d}}]"
.formatted(BROADCAST_ID, CHANNEL_NAME, CHANNEL_ID, PLAYER, USER_ID);
var expectedData = new String(Base64.getEncoder().encode(json.getBytes(UTF_8)));

unirest.expect(POST, SPADE_URL)
Expand All @@ -70,7 +72,9 @@ void sendMinutesWatched(UnirestMock unirest){
.userId(USER_ID)
.broadcastId(BROADCAST_ID)
.channelId(CHANNEL_ID)
.channel(CHANNEL_NAME)
.player(PLAYER)
.live(true)
.build())
.build();
assertThat(tested.sendPlayerEvents(spadeUrl, request)).isTrue();
Expand All @@ -80,8 +84,8 @@ void sendMinutesWatched(UnirestMock unirest){

@Test
void sendMinutesWatchedWithGame(UnirestMock unirest){
var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel_id\":\"%s\",\"game\":\"%s\",\"player\":\"%s\",\"user_id\":%d}}]"
.formatted(BROADCAST_ID, CHANNEL_ID, GAME, PLAYER, USER_ID);
var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel\":\"%s\",\"channel_id\":\"%s\",\"game\":\"%s\",\"game_id\":\"%s\",\"live\":true,\"player\":\"%s\",\"user_id\":%d}}]"
.formatted(BROADCAST_ID, CHANNEL_NAME, CHANNEL_ID, GAME, GAME_ID, PLAYER, USER_ID);
var expectedData = new String(Base64.getEncoder().encode(json.getBytes(UTF_8)));

unirest.expect(POST, SPADE_URL)
Expand All @@ -93,9 +97,12 @@ void sendMinutesWatchedWithGame(UnirestMock unirest){
.properties(MinuteWatchedProperties.builder()
.userId(USER_ID)
.broadcastId(BROADCAST_ID)
.channelId(CHANNEL_ID)
.player(PLAYER)
.channelId(CHANNEL_ID)
.channel(CHANNEL_NAME)
.player(PLAYER)
.game(GAME)
.gameId(GAME_ID)
.live(true)
.build())
.build();
assertThat(tested.sendPlayerEvents(spadeUrl, request)).isTrue();
Expand All @@ -105,8 +112,8 @@ void sendMinutesWatchedWithGame(UnirestMock unirest){

@Test
void sendMinutesWatchedNotSuccess(UnirestMock unirest){
var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel_id\":\"%s\",\"player\":\"%s\",\"user_id\":%d}}]"
.formatted(BROADCAST_ID, CHANNEL_ID, PLAYER, USER_ID);
var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel\":\"%s\",\"channel_id\":\"%s\",\"live\":true,\"player\":\"%s\",\"user_id\":%d}}]"
.formatted(BROADCAST_ID, CHANNEL_NAME, CHANNEL_ID, PLAYER, USER_ID);
var expectedData = new String(Base64.getEncoder().encode(json.getBytes(UTF_8)));

unirest.expect(POST, SPADE_URL)
Expand All @@ -119,7 +126,9 @@ void sendMinutesWatchedNotSuccess(UnirestMock unirest){
.userId(USER_ID)
.broadcastId(BROADCAST_ID)
.channelId(CHANNEL_ID)
.channel(CHANNEL_NAME)
.player(PLAYER)
.live(true)
.build())
.build();
assertThat(tested.sendPlayerEvents(spadeUrl, request)).isFalse();
Expand All @@ -139,7 +148,9 @@ void sendMinutesWatchedJsonError(){
.userId(USER_ID)
.broadcastId(BROADCAST_ID)
.channelId(CHANNEL_ID)
.channel(CHANNEL_NAME)
.player(PLAYER)
.live(true)
.build())
.build();
assertThat(tested.sendPlayerEvents(spadeUrl, request)).isFalse();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@
@ExtendWith(MockitoExtension.class)
class SendMinutesWatchedTest{
private static final String STREAMER_ID = "streamer-id";
private static final String STREAMER_NAME = "streamer-name";
private static final String STREAM_ID = "stream-id";
private static final String SITE_PLAYER = "site";
private static final int USER_ID = 123456789;
private static final String GAME_NAME = "game-name";
private static final String GAME_ID = "game-id";
private static final Instant NOW = Instant.parse("2021-03-25T18:12:36Z");
private static final int INDEX = 5;

Expand Down Expand Up @@ -75,24 +77,30 @@ void setUp() throws MalformedURLException{
lenient().when(twitchLogin.getUserIdAsInt(gqlApi)).thenReturn(USER_ID);

lenient().when(streamer.getId()).thenReturn(STREAMER_ID);
lenient().when(streamer.getUsername()).thenReturn(STREAMER_NAME);
lenient().when(streamer.getSpadeUrl()).thenReturn(spadeUrl);
lenient().when(streamer.getStreamId()).thenReturn(Optional.of(STREAM_ID));
lenient().when(streamer.isStreaming()).thenReturn(true);
lenient().when(streamer.getIndex()).thenReturn(INDEX);

lenient().when(game.getName()).thenReturn(GAME_NAME);
lenient().when(game.getId()).thenReturn(GAME_ID);
}

@Test
void sendingMinutesWatched(){
when(streamer.getGame()).thenReturn(Optional.of(game));
when(game.getName()).thenReturn(GAME_NAME);

var expected = MinuteWatchedEvent.builder()
.properties(MinuteWatchedProperties.builder()
.channelId(STREAMER_ID)
.channel(STREAMER_NAME)
.broadcastId(STREAM_ID)
.player(SITE_PLAYER)
.userId(USER_ID)
.gameId(GAME_ID)
.game(GAME_NAME)
.live(true)
.build())
.build();

Expand All @@ -109,15 +117,17 @@ void sendingMinutesWatchedUpdatesMinutesWatched(){
timeFactory.when(TimeFactory::now).thenReturn(NOW);

when(streamer.getGame()).thenReturn(Optional.of(game));
when(game.getName()).thenReturn(GAME_NAME);

var expected = MinuteWatchedEvent.builder()
.properties(MinuteWatchedProperties.builder()
.channelId(STREAMER_ID)
.channel(STREAMER_NAME)
.broadcastId(STREAM_ID)
.player(SITE_PLAYER)
.userId(USER_ID)
.game(GAME_NAME)
.gameId(GAME_ID)
.live(true)
.build())
.build();

Expand All @@ -139,15 +149,17 @@ void sendingMinutesWatchedUpdatesMinutesWatchedResetIfNotPresentOnARound(){
timeFactory.when(TimeFactory::now).thenReturn(NOW);

when(streamer.getGame()).thenReturn(Optional.of(game));
when(game.getName()).thenReturn(GAME_NAME);

var expected = MinuteWatchedEvent.builder()
.properties(MinuteWatchedProperties.builder()
.channelId(STREAMER_ID)
.channel(STREAMER_NAME)
.broadcastId(STREAM_ID)
.player(SITE_PLAYER)
.userId(USER_ID)
.game(GAME_NAME)
.gameId(GAME_ID)
.live(true)
.build())
.build();

Expand Down Expand Up @@ -187,15 +199,17 @@ void sendingMinutesWatchedDoesNotUpdateMinutesWatchedIfCallFailed(){
timeFactory.when(TimeFactory::now).thenReturn(NOW);

when(streamer.getGame()).thenReturn(Optional.of(game));
when(game.getName()).thenReturn(GAME_NAME);

var expected = MinuteWatchedEvent.builder()
.properties(MinuteWatchedProperties.builder()
.channelId(STREAMER_ID)
.channel(STREAMER_NAME)
.broadcastId(STREAM_ID)
.player(SITE_PLAYER)
.userId(USER_ID)
.game(GAME_NAME)
.gameId(GAME_ID)
.live(true)
.build())
.build();

Expand All @@ -216,13 +230,17 @@ void sendingMinutesWatchedDoesNotUpdateMinutesWatchedIfCallFailed(){
@Test
void sendingMinutesWatchedNoGameName(){
when(streamer.getGame()).thenReturn(Optional.of(game));
when(game.getName()).thenReturn(null);
when(game.getId()).thenReturn(null);

var expected = MinuteWatchedEvent.builder()
.properties(MinuteWatchedProperties.builder()
.channelId(STREAMER_ID)
.channel(STREAMER_NAME)
.broadcastId(STREAM_ID)
.player(SITE_PLAYER)
.userId(USER_ID)
.live(true)
.build())
.build();

Expand All @@ -238,9 +256,11 @@ void sendingMinutesWatchedNoGame(){
var expected = MinuteWatchedEvent.builder()
.properties(MinuteWatchedProperties.builder()
.channelId(STREAMER_ID)
.channel(STREAMER_NAME)
.broadcastId(STREAM_ID)
.player(SITE_PLAYER)
.userId(USER_ID)
.live(true)
.build())
.build();

Expand Down Expand Up @@ -293,11 +313,11 @@ void sendingMinutesWatchedChatBanned(){

@Test
void sendingMinutesWatchedSeveralStreamers() throws MalformedURLException{
var streamerId2 = "streamer-id-2";
var spadeUrl2 = new URL("https://google.com/2");

var streamer2 = mock(Streamer.class);
when(streamer2.getId()).thenReturn(streamerId2);
when(streamer2.getId()).thenReturn("s2");
when(streamer2.getUsername()).thenReturn("sn2");
when(streamer2.getSpadeUrl()).thenReturn(spadeUrl2);
when(streamer2.getStreamId()).thenReturn(Optional.of(STREAM_ID));
when(streamer2.isStreaming()).thenReturn(true);
Expand Down Expand Up @@ -341,6 +361,7 @@ void sendingMinutesWatchedBestScores() throws MalformedURLException{
var spade2 = new URL("https://spade2");
var s2 = mock(Streamer.class);
when(s2.getId()).thenReturn("s2");
when(s2.getUsername()).thenReturn("sn2");
when(s2.getSpadeUrl()).thenReturn(spade2);
when(s2.getStreamId()).thenReturn(Optional.of("sid2"));
when(s2.isStreaming()).thenReturn(true);
Expand All @@ -354,6 +375,7 @@ void sendingMinutesWatchedBestScores() throws MalformedURLException{
var spade4 = new URL("https://spade4");
var s4 = mock(Streamer.class);
when(s4.getId()).thenReturn("s4");
when(s4.getUsername()).thenReturn("sn4");
when(s4.getSpadeUrl()).thenReturn(spade4);
when(s4.getStreamId()).thenReturn(Optional.of("sid4"));
when(s4.isStreaming()).thenReturn(true);
Expand All @@ -379,6 +401,7 @@ void sendingMinutesWatchedBestScoresEqualsPicksIndex() throws MalformedURLExcept
var spade2 = new URL("https://spade2");
var s2 = mock(Streamer.class);
when(s2.getId()).thenReturn("s2");
when(s2.getUsername()).thenReturn("sn2");
when(s2.getSpadeUrl()).thenReturn(spade2);
when(s2.getStreamId()).thenReturn(Optional.of("sid2"));
when(s2.isStreaming()).thenReturn(true);
Expand All @@ -394,6 +417,7 @@ void sendingMinutesWatchedBestScoresEqualsPicksIndex() throws MalformedURLExcept
var spade4 = new URL("https://spade4");
var s4 = mock(Streamer.class);
when(s4.getId()).thenReturn("s4");
when(s4.getUsername()).thenReturn("sn4");
when(s4.getSpadeUrl()).thenReturn(spade4);
when(s4.getStreamId()).thenReturn(Optional.of("sid4"));
when(s4.isStreaming()).thenReturn(true);
Expand Down

0 comments on commit a2366d8

Please sign in to comment.