From ff7138931a3370f514c63cdcc823db38a973023e Mon Sep 17 00:00:00 2001 From: Redouane Bali Date: Mon, 3 Apr 2023 18:26:26 +0100 Subject: [PATCH] v2.22 (#429) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added @Jacksonized to all @Builder classes. (#428) * Updated README.md (#431) Updated README.md with the correct print statements for the user example. * Empty predicate (#434) * Fix formatting * Handle empty predicates This commit improves FilteredStreamRulePredicate so that an empty predicate is handled properly when associated with an operator. * Bump jackson-databind from 2.13.4.1 to 2.13.4.2 (#441) Bumps [jackson-databind](https://github.com/FasterXML/jackson) from 2.13.4.1 to 2.13.4.2. - [Release notes](https://github.com/FasterXML/jackson/releases) - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix for issue #440 and improved rate limit handling (#442) * update version --------- Signed-off-by: dependabot[bot] Co-authored-by: takeshitakenji <47hasbegun@gmail.com> Co-authored-by: suomi35 Co-authored-by: Stéphane Nicoll Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Swiss Dev <92470138+swisstechguy@users.noreply.github.com> --- README.md | 24 +- pom.xml | 4 +- .../twitter/dto/dm/DmParameters.java | 3 + .../dto/endpoints/AdditionalParameters.java | 2 + .../twitter/dto/list/TwitterListMember.java | 2 + .../rules/FilteredStreamRulePredicate.java | 152 +++++------ .../redouane59/twitter/dto/space/Space.java | 3 + .../twitter/dto/space/SpaceList.java | 5 +- .../twitter/dto/tweet/Attachments.java | 2 + .../redouane59/twitter/dto/tweet/Geo.java | 3 + .../twitter/dto/tweet/LikeResponse.java | 3 + .../twitter/dto/tweet/RetweetResponse.java | 3 + .../twitter/dto/tweet/TweetCountsList.java | 4 + .../twitter/dto/tweet/TweetList.java | 2 + .../twitter/dto/tweet/TweetParameters.java | 5 + .../redouane59/twitter/dto/tweet/TweetV1.java | 2 + .../redouane59/twitter/dto/tweet/TweetV2.java | 4 + .../twitter/dto/user/UserActionResponse.java | 3 + .../redouane59/twitter/dto/user/UserList.java | 3 + .../redouane59/twitter/dto/user/UserV1.java | 2 + .../redouane59/twitter/dto/user/UserV2.java | 4 + .../helpers/AbstractRequestHelper.java | 33 ++- .../twitter/signature/TwitterCredentials.java | 2 + .../FilteredStreamRulePredicateTest.java | 235 +++++------------- 24 files changed, 241 insertions(+), 264 deletions(-) diff --git a/README.md b/README.md index dc9d5f4f..53e20c07 100644 --- a/README.md +++ b/README.md @@ -139,18 +139,18 @@ System.out.println(tweet.getUser().getName()); ```java User user = twitterClient.getUserFromUserName("RedouaneBali"); -System.out.println(tweet.getUser().getName()); -System.out.println(tweet.getUser().getDisplayedName()); -System.out.println(tweet.getUser().getDateOfCreation()); -System.out.println(tweet.getUser().getDescription()); -System.out.println(tweet.getUser().getTweetCount()); -System.out.println(tweet.getUser().getFollowersCount()); -System.out.println(tweet.getUser().getFollowingCount()); -System.out.println(tweet.getUser().getPinnedTweet()); -System.out.println(tweet.getUser().getPinnedTweet()); -System.out.println(tweet.getUser().getLocation()); -System.out.println(tweet.getUser().getId()); -System.out.println(tweet.getUser().getUrl()); +System.out.println(user.getName()); +System.out.println(user.getDisplayedName()); +System.out.println(user.getDateOfCreation()); +System.out.println(user.getDescription()); +System.out.println(user.getTweetCount()); +System.out.println(user.getFollowersCount()); +System.out.println(user.getFollowingCount()); +System.out.println(user.getPinnedTweet()); +System.out.println(user.getPinnedTweet()); +System.out.println(user.getLocation()); +System.out.println(user.getId()); +System.out.println(user.getUrl()); ``` ### Contribution diff --git a/pom.xml b/pom.xml index 1f791e6d..5241126c 100644 --- a/pom.xml +++ b/pom.xml @@ -83,7 +83,7 @@ jackson-databind com.fasterxml.jackson.core - 2.13.4.1 + 2.13.4.2 jackson-datatype-jsr310 @@ -195,5 +195,5 @@ https://github.com/Redouane59/twittered - 2.21 + 2.22 \ No newline at end of file diff --git a/src/main/java/io/github/redouane59/twitter/dto/dm/DmParameters.java b/src/main/java/io/github/redouane59/twitter/dto/dm/DmParameters.java index abf15579..04a0c756 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/dm/DmParameters.java +++ b/src/main/java/io/github/redouane59/twitter/dto/dm/DmParameters.java @@ -4,8 +4,10 @@ import java.util.List; import lombok.Builder; import lombok.Getter; +import lombok.extern.jackson.Jacksonized; @Builder +@Jacksonized public class DmParameters { @JsonProperty("conversation_type") @@ -18,6 +20,7 @@ public class DmParameters { @Builder @Getter + @Jacksonized public static class DmMessage { private String text; diff --git a/src/main/java/io/github/redouane59/twitter/dto/endpoints/AdditionalParameters.java b/src/main/java/io/github/redouane59/twitter/dto/endpoints/AdditionalParameters.java index 25fa03ed..d8d6581b 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/endpoints/AdditionalParameters.java +++ b/src/main/java/io/github/redouane59/twitter/dto/endpoints/AdditionalParameters.java @@ -8,10 +8,12 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; @Builder @Getter @Setter +@Jacksonized public class AdditionalParameters { public static final String SINCE_ID = "since_id"; diff --git a/src/main/java/io/github/redouane59/twitter/dto/list/TwitterListMember.java b/src/main/java/io/github/redouane59/twitter/dto/list/TwitterListMember.java index 5f968981..2e60ca08 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/list/TwitterListMember.java +++ b/src/main/java/io/github/redouane59/twitter/dto/list/TwitterListMember.java @@ -7,11 +7,13 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.extern.jackson.Jacksonized; @NoArgsConstructor @AllArgsConstructor @Builder @Getter +@Jacksonized public class TwitterListMember { private TwitterListMemberData data; diff --git a/src/main/java/io/github/redouane59/twitter/dto/rules/FilteredStreamRulePredicate.java b/src/main/java/io/github/redouane59/twitter/dto/rules/FilteredStreamRulePredicate.java index b94daaf5..11187f91 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/rules/FilteredStreamRulePredicate.java +++ b/src/main/java/io/github/redouane59/twitter/dto/rules/FilteredStreamRulePredicate.java @@ -12,6 +12,10 @@ public class FilteredStreamRulePredicate { FilteredStreamRulePredicate() { } + private FilteredStreamRulePredicate(String predicate) { + this.predicate = predicate; + } + private static FilteredStreamRulePredicate build(String one, String two, String operator) { FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); if (one == null || one.isEmpty()) { @@ -27,194 +31,196 @@ public static FilteredStreamRulePredicate withKeyword(String keyword) { } public static FilteredStreamRulePredicate withEmoji(String emoji) { - return build("", emoji, ""); + return new FilteredStreamRulePredicate(emoji); } public static FilteredStreamRulePredicate withExactPhrase(String phrase) { - return build("", "\"" + phrase + "\"", ""); + return new FilteredStreamRulePredicate(quote(phrase)); } public static FilteredStreamRulePredicate withHashtag(String hashtag) { - return build("", hashtag.startsWith("#") ? hashtag : "#" + hashtag, ""); + String predicate = hashtag.startsWith("#") ? hashtag : "#" + hashtag; + return new FilteredStreamRulePredicate(predicate); } public static FilteredStreamRulePredicate withMention(String mention) { - return build("", mention.startsWith("@") ? mention : "@" + mention, ""); + String predicate = mention.startsWith("@") ? mention : "@" + mention; + return new FilteredStreamRulePredicate(predicate); } public static FilteredStreamRulePredicate withCashtag(String cashtag) { - return build("", cashtag.startsWith("$") ? cashtag : "$" + cashtag, ""); + String predicate = cashtag.startsWith("$") ? cashtag : "$" + cashtag; + return new FilteredStreamRulePredicate(predicate); } public static FilteredStreamRulePredicate withUser(String user) { - return build("", user, "from:"); + return new FilteredStreamRulePredicate("from:" + user); } public static FilteredStreamRulePredicate withReplyTo(String user) { - return build("", user, "to:"); + return new FilteredStreamRulePredicate("to:" + user); } public static FilteredStreamRulePredicate withUrl(String url) { - return build("", withExactPhrase(url).toString(), "url:"); + return new FilteredStreamRulePredicate("url:" + quote(url)); } public static FilteredStreamRulePredicate withRetweetsOf(String user) { - return build("", user, "retweets_of:"); + return new FilteredStreamRulePredicate("retweets_of:" + user); } public static FilteredStreamRulePredicate withContext(String context) { - return build("", context, "context:"); + return new FilteredStreamRulePredicate("context:" + context); } public static FilteredStreamRulePredicate withEntity(String entity) { - return build("", withExactPhrase(entity).toString(), "entity:"); + return new FilteredStreamRulePredicate("entity:" + quote(entity)); } public static FilteredStreamRulePredicate withConversationId(String conversationId) { - return build("", conversationId, "conversation_id:"); + return new FilteredStreamRulePredicate("conversation_id:" + conversationId); } public static FilteredStreamRulePredicate withBio(String bio) { - return build("", bio, "bio:"); + return new FilteredStreamRulePredicate("bio:" + bio); } public static FilteredStreamRulePredicate withBioName(String bioName) { - return build("", bioName, "bio_name:"); + return new FilteredStreamRulePredicate("bio_name:" + bioName); } public static FilteredStreamRulePredicate withBioLocation(String bioLocation) { - return build("", bioLocation, "bio_location:"); + return new FilteredStreamRulePredicate("bio_location:" + bioLocation); } public static FilteredStreamRulePredicate withPlace(String place) { - return build("", place, "place:"); + return new FilteredStreamRulePredicate("place:" + place); } public static FilteredStreamRulePredicate withPlaceCountry(String alpha2IsoCode) { - return build("", alpha2IsoCode, "place_country:"); + return new FilteredStreamRulePredicate("place_country:" + alpha2IsoCode); } public static FilteredStreamRulePredicate withPointRadius(double longitude, double latitude, String radius) { //mi or km - return build("", "[" + longitude + " " + latitude + " " + radius + "]", "point_radius:"); + String pointRadius = "[" + longitude + " " + latitude + " " + radius + "]"; + return new FilteredStreamRulePredicate("point_radius:" + pointRadius); } public static FilteredStreamRulePredicate withBoundingBox(double westLongitude, double southLatitude, double eastLongitude, double northLatitude) { //mi or km - return build("", "[" + westLongitude + " " + southLatitude + " " + eastLongitude + " " + northLatitude + "]", "bounding_box:"); + String boundingBox = "[" + westLongitude + " " + southLatitude + " " + eastLongitude + " " + northLatitude + "]"; + return new FilteredStreamRulePredicate("bounding_box:" + boundingBox); } public static FilteredStreamRulePredicate withLanguage(String language) { - return build("", language, "lang:"); - } - - public static FilteredStreamRulePredicate isRetweet(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "is:retweet"); + return new FilteredStreamRulePredicate("lang:" + language); } - public static FilteredStreamRulePredicate isReply(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "is:reply"); + public static FilteredStreamRulePredicate isRetweet() { + return new FilteredStreamRulePredicate("is:retweet"); } - public static FilteredStreamRulePredicate isQuote(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "is:quote"); + public static FilteredStreamRulePredicate isReply() { + return new FilteredStreamRulePredicate("is:reply"); } - public static FilteredStreamRulePredicate isVerified(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "is:verified"); + public static FilteredStreamRulePredicate isQuote() { + return new FilteredStreamRulePredicate("is:quote"); } - public static FilteredStreamRulePredicate isNullcast(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "-is:nullcast"); + public static FilteredStreamRulePredicate isVerified() { + return new FilteredStreamRulePredicate("is:verified"); } - public static FilteredStreamRulePredicate hasHashtags(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "has:hashtags"); + public static FilteredStreamRulePredicate isNullcast() { + return new FilteredStreamRulePredicate("-is:nullcast"); } - public static FilteredStreamRulePredicate hasCashtags(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "has:cashtags"); + public static FilteredStreamRulePredicate hasHashtags() { + return new FilteredStreamRulePredicate("has:hashtags"); } - public static FilteredStreamRulePredicate hasLinks(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "has:links"); + public static FilteredStreamRulePredicate hasCashtags() { + return new FilteredStreamRulePredicate("has:cashtags"); } - public static FilteredStreamRulePredicate hasMentions(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "has:mentions"); + public static FilteredStreamRulePredicate hasLinks() { + return new FilteredStreamRulePredicate("has:links"); } - public static FilteredStreamRulePredicate hasMedia(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "has:media"); + public static FilteredStreamRulePredicate hasMentions() { + return new FilteredStreamRulePredicate("has:mentions"); } - public static FilteredStreamRulePredicate hasImages(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "has:images"); + public static FilteredStreamRulePredicate hasMedia() { + return new FilteredStreamRulePredicate("has:media"); } - public static FilteredStreamRulePredicate hasVideos(FilteredStreamRulePredicate predicate) { - checkConjunction(predicate); - return build(predicate.toString(), "", "has:videos"); + public static FilteredStreamRulePredicate hasImages() { + return new FilteredStreamRulePredicate("has:images"); } - public static FilteredStreamRulePredicate hasGeo(FilteredStreamRulePredicate predicate, String geo) { - checkConjunction(predicate); - return build(predicate.toString(), " " + geo, "has:geo"); + public static FilteredStreamRulePredicate hasVideos() { + return new FilteredStreamRulePredicate("has:videos"); } - public static FilteredStreamRulePredicate doSampling(FilteredStreamRulePredicate predicate, int sampleSize) { - checkConjunction(predicate); - return build(predicate.toString(), Integer.toString(sampleSize), "sample:"); + public static FilteredStreamRulePredicate hasGeo(String geo) { + return new FilteredStreamRulePredicate("has:geo " + geo); } - private static void checkConjunction(FilteredStreamRulePredicate predicate) { - if (predicate == null || predicate.isEmpty()) { - throw new RuleBuilderException("Given operator can only be used in an conjunction"); - } + public static FilteredStreamRulePredicate doSampling(int sampleSize) { + return new FilteredStreamRulePredicate("sample:" + sampleSize); } public FilteredStreamRulePredicate negate() { + if (predicate == null) { + throw new RuleBuilderException("Cannot negate empty predicate"); + } predicate = "-" + capsule(); return this; } public FilteredStreamRulePredicate capsule() { - predicate = "(" + predicate + ")"; + if (predicate != null) { + predicate = "(" + predicate + ")"; + } return this; } public FilteredStreamRulePredicate or(FilteredStreamRulePredicate other) { - predicate += " OR " + other.predicate; + applyOperator(" OR ", other); return this; } public FilteredStreamRulePredicate and(FilteredStreamRulePredicate other) { - predicate += " " + other.predicate; + applyOperator(" ", other); return this; } public static FilteredStreamRulePredicate empty() { - return build("","",""); + return new FilteredStreamRulePredicate(null); } public boolean isEmpty() { return predicate == null; } + private void applyOperator(String operator, FilteredStreamRulePredicate right) { + if (this.predicate == null) { + this.predicate = right.predicate; + } else if (right != null && !right.isEmpty()) { + this.predicate = this.predicate + operator + right.predicate; + } + } + + private static String quote(String phrase) { + return "\"" + phrase + "\""; + } + @Override public String toString() { - return predicate; + return (predicate != null ? predicate : ""); } public static class RuleBuilderException extends RuntimeException { diff --git a/src/main/java/io/github/redouane59/twitter/dto/space/Space.java b/src/main/java/io/github/redouane59/twitter/dto/space/Space.java index 580dc28a..dce604ed 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/space/Space.java +++ b/src/main/java/io/github/redouane59/twitter/dto/space/Space.java @@ -7,11 +7,13 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.extern.jackson.Jacksonized; @NoArgsConstructor @AllArgsConstructor @Builder @Getter +@Jacksonized public class Space { private SpaceData data; @@ -22,6 +24,7 @@ public class Space { @AllArgsConstructor @Builder @Getter + @Jacksonized public static class SpaceData { private String id; diff --git a/src/main/java/io/github/redouane59/twitter/dto/space/SpaceList.java b/src/main/java/io/github/redouane59/twitter/dto/space/SpaceList.java index 38cd59d2..f1b175af 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/space/SpaceList.java +++ b/src/main/java/io/github/redouane59/twitter/dto/space/SpaceList.java @@ -7,11 +7,13 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.extern.jackson.Jacksonized; @NoArgsConstructor @AllArgsConstructor @Builder @Getter +@Jacksonized public class SpaceList { List data; @@ -22,10 +24,11 @@ public class SpaceList { @AllArgsConstructor @Builder @Getter + @Jacksonized public static class SpaceMeta { @JsonProperty("result_count") private int resultCount; } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/Attachments.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/Attachments.java index f1e332b4..7cefb6ae 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/Attachments.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/Attachments.java @@ -6,12 +6,14 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder +@Jacksonized public class Attachments { @JsonProperty("media_keys") diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/Geo.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/Geo.java index eacd0695..0ac58144 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/Geo.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/Geo.java @@ -6,12 +6,14 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder +@Jacksonized public class Geo { @JsonProperty("place_id") @@ -20,6 +22,7 @@ public class Geo { @Getter @Setter + @Jacksonized public static class Coordinates { private String type; diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/LikeResponse.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/LikeResponse.java index b2b35bc8..055cfcc6 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/LikeResponse.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/LikeResponse.java @@ -5,12 +5,14 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder @AllArgsConstructor @NoArgsConstructor +@Jacksonized public class LikeResponse { DataLikeResponse data; @@ -20,6 +22,7 @@ public class LikeResponse { @Builder @AllArgsConstructor @NoArgsConstructor + @Jacksonized public static class DataLikeResponse { private boolean liked; diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/RetweetResponse.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/RetweetResponse.java index 34e6b415..d170cf37 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/RetweetResponse.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/RetweetResponse.java @@ -4,11 +4,13 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.extern.jackson.Jacksonized; @NoArgsConstructor @AllArgsConstructor @Builder @Getter +@Jacksonized public class RetweetResponse { private RetweetData data; @@ -17,6 +19,7 @@ public class RetweetResponse { @AllArgsConstructor @Builder @Getter + @Jacksonized public static class RetweetData { private boolean retweeted; diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetCountsList.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetCountsList.java index d0e23263..a0964150 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetCountsList.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetCountsList.java @@ -13,11 +13,13 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.extern.jackson.Jacksonized; @AllArgsConstructor @NoArgsConstructor @Builder @Getter +@Jacksonized public class TweetCountsList { private List data; @@ -27,6 +29,7 @@ public class TweetCountsList { @NoArgsConstructor @Builder @Getter + @Jacksonized public static class TweetCountData { @JsonProperty("tweet_count") @@ -57,6 +60,7 @@ public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) @NoArgsConstructor @Builder @Getter + @Jacksonized public static class TweetCountMeta { @JsonProperty("total_tweet_count") diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetList.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetList.java index 135d5ce8..a2f925a4 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetList.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetList.java @@ -9,6 +9,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; @Getter @Setter @@ -27,6 +28,7 @@ public class TweetList { @Builder @NoArgsConstructor @AllArgsConstructor + @Jacksonized public static class TweetMeta { @JsonProperty("newest_id") diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetParameters.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetParameters.java index c94ea741..32adf7d6 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetParameters.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetParameters.java @@ -7,11 +7,13 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; @Builder @Getter @Setter @JsonInclude(Include.NON_NULL) +@Jacksonized public class TweetParameters { private String text; @@ -33,6 +35,7 @@ public class TweetParameters { @Builder @Getter + @Jacksonized public static class Reply { @JsonProperty("exclude_reply_user_ids") @@ -44,6 +47,7 @@ public static class Reply { @Builder @Getter + @Jacksonized public static class Poll { @JsonProperty("duration_minutes") @@ -53,6 +57,7 @@ public static class Poll { @Builder @Getter + @Jacksonized public static class Media { @JsonProperty("media_ids") diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetV1.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetV1.java index 3b438d18..baab6d20 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetV1.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetV1.java @@ -26,6 +26,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import lombok.extern.jackson.Jacksonized; /** * @version current @@ -38,6 +39,7 @@ @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) @Slf4j +@Jacksonized public class TweetV1 implements Tweet { private static final String NOT_IMPLEMENTED_EXCEPTION = "not implemented"; diff --git a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetV2.java b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetV2.java index d69b6b19..79d96421 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetV2.java +++ b/src/main/java/io/github/redouane59/twitter/dto/tweet/TweetV2.java @@ -28,6 +28,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; import lombok.extern.slf4j.Slf4j; /** @@ -39,6 +40,7 @@ @NoArgsConstructor @Builder @Slf4j +@Jacksonized public class TweetV2 implements Tweet { private static final String NOT_IMPLEMENTED_EXCEPTION = "not implemented"; @@ -245,6 +247,7 @@ public TweetType getTweetType() { @Builder @NoArgsConstructor @AllArgsConstructor + @Jacksonized public static class TweetData implements Tweet { private String id; @@ -377,6 +380,7 @@ public static class ReferencedTweetDTO { @Builder @NoArgsConstructor @AllArgsConstructor + @Jacksonized public static class Includes { private List users; diff --git a/src/main/java/io/github/redouane59/twitter/dto/user/UserActionResponse.java b/src/main/java/io/github/redouane59/twitter/dto/user/UserActionResponse.java index ac90becc..0cffe5d2 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/user/UserActionResponse.java +++ b/src/main/java/io/github/redouane59/twitter/dto/user/UserActionResponse.java @@ -5,11 +5,13 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.extern.jackson.Jacksonized; @Builder @AllArgsConstructor @NoArgsConstructor @Getter +@Jacksonized public class UserActionResponse { private FollowData data; @@ -18,6 +20,7 @@ public class UserActionResponse { @AllArgsConstructor @NoArgsConstructor @Getter + @Jacksonized public static class FollowData { boolean muting; diff --git a/src/main/java/io/github/redouane59/twitter/dto/user/UserList.java b/src/main/java/io/github/redouane59/twitter/dto/user/UserList.java index 95f9c2df..a4a50c88 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/user/UserList.java +++ b/src/main/java/io/github/redouane59/twitter/dto/user/UserList.java @@ -9,12 +9,14 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor +@Jacksonized public class UserList { @Builder.Default @@ -26,6 +28,7 @@ public class UserList { @Builder @NoArgsConstructor @AllArgsConstructor + @Jacksonized public static class UserMeta { @JsonProperty("result_count") diff --git a/src/main/java/io/github/redouane59/twitter/dto/user/UserV1.java b/src/main/java/io/github/redouane59/twitter/dto/user/UserV1.java index 00774306..95ea3fe0 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/user/UserV1.java +++ b/src/main/java/io/github/redouane59/twitter/dto/user/UserV1.java @@ -12,6 +12,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; import lombok.extern.slf4j.Slf4j; /** @@ -24,6 +25,7 @@ @NoArgsConstructor @Builder @Slf4j +@Jacksonized public class UserV1 implements User { private String id; diff --git a/src/main/java/io/github/redouane59/twitter/dto/user/UserV2.java b/src/main/java/io/github/redouane59/twitter/dto/user/UserV2.java index 902d4276..dd579666 100644 --- a/src/main/java/io/github/redouane59/twitter/dto/user/UserV2.java +++ b/src/main/java/io/github/redouane59/twitter/dto/user/UserV2.java @@ -14,6 +14,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; import lombok.extern.slf4j.Slf4j; /** @@ -25,6 +26,7 @@ @AllArgsConstructor @NoArgsConstructor @Slf4j +@Jacksonized public class UserV2 implements User { private UserData data; @@ -143,6 +145,7 @@ public int hashCode() { @NoArgsConstructor @AllArgsConstructor @Builder + @Jacksonized public static class UserData implements User { private String id; @@ -201,6 +204,7 @@ public Tweet getPinnedTweet() { @NoArgsConstructor @AllArgsConstructor @Builder + @Jacksonized public static class Includes { private TweetData[] tweets; diff --git a/src/main/java/io/github/redouane59/twitter/helpers/AbstractRequestHelper.java b/src/main/java/io/github/redouane59/twitter/helpers/AbstractRequestHelper.java index 6cf3123b..84f5862e 100644 --- a/src/main/java/io/github/redouane59/twitter/helpers/AbstractRequestHelper.java +++ b/src/main/java/io/github/redouane59/twitter/helpers/AbstractRequestHelper.java @@ -31,6 +31,8 @@ public abstract class AbstractRequestHelper { private final OAuth10aService service; @Setter private boolean automaticRetry = true; + + private long lastCallTs; protected AbstractRequestHelper(TwitterCredentials twitterCredentials) { this(twitterCredentials, new ServiceBuilder(twitterCredentials.getApiKey()) @@ -82,19 +84,42 @@ public Optional makeRequest(OAuthRequest request, boolean signRequired, C if (signRequired) { signRequest(request); } + // endpoint /2/tweets/search/all has a one request per second rate limit, see https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all + if(request.getUrl().contains("/2/tweets/search/all")) { + long now = System.currentTimeMillis(); + if(now < (lastCallTs+1000)) { + int sleepTime= 1000-Math.toIntExact(now-lastCallTs); + LOGGER.trace("sleep {}ms between two calls on /search/all", sleepTime); + Thread.sleep(sleepTime); + lastCallTs = now+sleepTime; + } else { + lastCallTs = now; + } + + } try (Response response = getService().execute(request)) { String stringResponse = response.getBody(); + LOGGER.debug("Response code: {} to url: '{}' headers: x-rate-limit-reset: {} x-rate-limit-remaining: {}", response.getCode(), request.getUrl(), response.getHeader("x-rate-limit-reset"), response.getHeader("x-rate-limit-remaining")); + if (response.getCode() == 429) { if (!automaticRetry) { throw new LimitExceededException(response.getHeader("x-rate-limit-reset")); } int retryAfter = DEFAULT_RETRY_AFTER_SEC; String retryAfterStr = response.getHeader("x-rate-limit-reset"); - if (retryAfterStr != null) { + String rateRemainingStr = response.getHeader("x-rate-limit-remaining"); + LOGGER.trace("Rate limit exceeded, x-rate-limit-reset: {} x-rate-limit-remaining: {}, x-rate-limit-limit: {}", retryAfterStr, response.getHeader("x-rate-limit-remaining"), response.getHeader("x-rate-limit-limit")); + if (retryAfterStr != null && rateRemainingStr != null) { try { - long resetTime = Long.parseLong(retryAfterStr); - long currentTime = (new Date().getTime()) / 1000; - retryAfter = Math.toIntExact(resetTime - currentTime); + int remaining = Integer.parseInt(rateRemainingStr); + if(remaining>0) { //if we have remaining requests in this slot, the rate limit has been raised due to more calls than one per second. e.g. /search/all endpoint + retryAfter=1; //wait one second + } else { + long resetTime = Long.parseLong(retryAfterStr); + long currentTime = (new Date().getTime()) / 1000; + retryAfter = Math.toIntExact(resetTime - currentTime); + if(retryAfter<0) retryAfter=1; //issue #440 ( negative sleep time) + } } catch (NumberFormatException e) { LOGGER.error("Using default retry after because header format is invalid: {}", retryAfterStr, e); } diff --git a/src/main/java/io/github/redouane59/twitter/signature/TwitterCredentials.java b/src/main/java/io/github/redouane59/twitter/signature/TwitterCredentials.java index 426ba34c..9e1f1a29 100644 --- a/src/main/java/io/github/redouane59/twitter/signature/TwitterCredentials.java +++ b/src/main/java/io/github/redouane59/twitter/signature/TwitterCredentials.java @@ -8,12 +8,14 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder +@Jacksonized public class TwitterCredentials { private String apiKey; diff --git a/src/test/java/io/github/redouane59/twitter/dto/rules/FilteredStreamRulePredicateTest.java b/src/test/java/io/github/redouane59/twitter/dto/rules/FilteredStreamRulePredicateTest.java index eda58e49..22862db4 100644 --- a/src/test/java/io/github/redouane59/twitter/dto/rules/FilteredStreamRulePredicateTest.java +++ b/src/test/java/io/github/redouane59/twitter/dto/rules/FilteredStreamRulePredicateTest.java @@ -1,12 +1,21 @@ package io.github.redouane59.twitter.dto.rules; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Assertions; +import io.github.redouane59.twitter.dto.rules.FilteredStreamRulePredicate.RuleBuilderException; import org.junit.jupiter.api.Test; class FilteredStreamRulePredicateTest { + @Test + void testEmpty() { + final FilteredStreamRulePredicate p = FilteredStreamRulePredicate.empty(); + assertEquals("", p.toString()); + assertTrue(p.isEmpty()); + } + @Test void testExactPhrase() { assertEquals("\"test\"", FilteredStreamRulePredicate.withExactPhrase("test").toString()); @@ -151,80 +160,110 @@ void testNegateRule() { FilteredStreamRulePredicate.withPointRadius(2.355128, 48.861118, "16km").negate().toString()); } + @Test + void testNegateOnEmptyPredicate() { + final FilteredStreamRulePredicate p = FilteredStreamRulePredicate.empty(); + assertThrows(RuleBuilderException.class, p::negate); + } + @Test void testCapsule() { assertEquals("(point_radius:[2.355128 48.861118 16km])", FilteredStreamRulePredicate.withPointRadius(2.355128, 48.861118, "16km").capsule().toString()); } + @Test + void testCapsuleOnEmptyPredicate() { + final FilteredStreamRulePredicate p = FilteredStreamRulePredicate.empty().capsule(); + assertTrue(p.isEmpty()); + } + @Test void testIsRetweet() { - assertEquals("test is:retweet", FilteredStreamRulePredicate.isRetweet(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test is:retweet", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.isRetweet()).toString()); } @Test void testIsReply() { - assertEquals("test is:reply", FilteredStreamRulePredicate.isReply(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test is:reply", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.isReply()).toString()); } @Test void testIsQuote() { - assertEquals("test is:quote", FilteredStreamRulePredicate.isQuote(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test is:quote", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.isQuote()).toString()); } @Test void testIsVerified() { - assertEquals("test is:verified", FilteredStreamRulePredicate.isVerified(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test is:verified", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.isVerified()).toString()); } @Test void testIsNullcast() { - assertEquals("test -is:nullcast", FilteredStreamRulePredicate.isNullcast(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test -is:nullcast", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.isNullcast()).toString()); } @Test void testHasHashtags() { - assertEquals("test has:hashtags", FilteredStreamRulePredicate.hasHashtags(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test has:hashtags", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.hasHashtags()).toString()); } @Test void testHasCashtags() { - assertEquals("test has:cashtags", FilteredStreamRulePredicate.hasCashtags(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test has:cashtags", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.hasCashtags()).toString()); } @Test void testHasLinks() { - assertEquals("test has:links", FilteredStreamRulePredicate.hasLinks(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test has:links", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.hasLinks()).toString()); } @Test void testHasMentions() { - assertEquals("test has:mentions", FilteredStreamRulePredicate.hasMentions(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test has:mentions", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.hasMentions()).toString()); } @Test void testHasMedia() { - assertEquals("test has:media", FilteredStreamRulePredicate.hasMedia(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test has:media", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.hasMedia()).toString()); } @Test void testHasImages() { - assertEquals("test has:images", FilteredStreamRulePredicate.hasImages(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test has:images", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.hasImages()).toString()); } @Test void testHasVideos() { - assertEquals("test has:videos", FilteredStreamRulePredicate.hasVideos(FilteredStreamRulePredicate.withKeyword("test")).toString()); + assertEquals("test has:videos", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.hasVideos()).toString()); } @Test void testHasGeo() { - assertEquals("test has:geo bakery", FilteredStreamRulePredicate.hasGeo(FilteredStreamRulePredicate.withKeyword("test"), "bakery").toString()); + assertEquals("test has:geo bakery", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.hasGeo("bakery")).toString()); } @Test void testSample() { - assertEquals("test sample:15", FilteredStreamRulePredicate.doSampling(FilteredStreamRulePredicate.withKeyword("test"), 15).toString()); + assertEquals("test sample:15", FilteredStreamRulePredicate.withKeyword("test").and(FilteredStreamRulePredicate.doSampling(15)).toString()); + } + + @Test + void testOrWithLeftEmptyPredicate() { + final FilteredStreamRulePredicate p = FilteredStreamRulePredicate.empty(); + assertEquals("lang:de", p.or(FilteredStreamRulePredicate.withLanguage("de")).toString()); + } + + @Test + void testOrWithRightEmptyPredicate() { + final FilteredStreamRulePredicate p = FilteredStreamRulePredicate.withLanguage("de"); + assertEquals("lang:de", p.or(FilteredStreamRulePredicate.empty()).toString()); + } + + @Test + void testAndWithLeftEmptyPredicate() { + final FilteredStreamRulePredicate p = FilteredStreamRulePredicate.withLanguage("de"); + assertEquals("lang:de", p.and(FilteredStreamRulePredicate.empty()).toString()); } @Test @@ -243,7 +282,7 @@ void testComplexQueries2() { FilteredStreamRulePredicate p3 = FilteredStreamRulePredicate.withLanguage("de"); FilteredStreamRulePredicate p4 = FilteredStreamRulePredicate.withLanguage("en").negate(); assertEquals("((\"test\" bio_name:test) OR lang:de) OR -(lang:en) sample:15", - FilteredStreamRulePredicate.doSampling(p.and(p2).capsule().or(p3).capsule().or(p4), 15).toString()); + p.and(p2).capsule().or(p3).capsule().or(p4).and(FilteredStreamRulePredicate.doSampling(15)).toString()); } @Test @@ -253,162 +292,14 @@ void testComplexQueries3() { FilteredStreamRulePredicate p3 = FilteredStreamRulePredicate.withLanguage("de"); FilteredStreamRulePredicate p4 = FilteredStreamRulePredicate.withLanguage("en").negate(); assertEquals("(((\"test\" bio_name:test) OR lang:de) OR -(lang:en)) -(is:retweet)", - p.and(p2).capsule().or(p3).capsule().or(p4).capsule().and(FilteredStreamRulePredicate.isRetweet(FilteredStreamRulePredicate.empty()).negate()).toString()); - } - - - @Test - void testConjunctionOperatorsInvalid1() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isReply(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isReply(p); - }); - + p.and(p2) + .capsule() + .or(p3) + .capsule() + .or(p4) + .capsule() + .and(FilteredStreamRulePredicate.isRetweet().negate()) + .toString()); } - @Test - void testConjunctionOperatorsInvalid2() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isRetweet(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isRetweet(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid3() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isQuote(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isQuote(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid4() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isVerified(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isVerified(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid5() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isNullcast(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.isNullcast(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid6() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasHashtags(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasHashtags(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid7() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasCashtags(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasCashtags(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid8() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasLinks(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasLinks(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid9() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasMentions(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasMentions(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid10() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasMedia(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasMedia(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid11() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasImages(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasImages(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid12() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasVideos(null); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasVideos(p); - }); - } - - @Test - void testConjunctionOperatorsInvalid13() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasGeo(null, "test"); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.hasGeo(p, "test"); - }); - } - - @Test - void testConjunctionOperatorsInvalid14() { - FilteredStreamRulePredicate p = new FilteredStreamRulePredicate(); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.doSampling(null, 15); - }); - Assertions.assertThrows(FilteredStreamRulePredicate.RuleBuilderException.class, () -> { - FilteredStreamRulePredicate.doSampling(p, 15); - }); - } } \ No newline at end of file