buildscript {
- ext.kotlinVersion = '1.9.20'
+ ext.kotlinVersion = '2.2.21'
repositories {
mavenCentral()
plugins {
id 'java'
- id('org.jetbrains.kotlin.jvm') version '1.9.20'
+ id('org.jetbrains.kotlin.jvm') version "$kotlinVersion"
}
apply plugin: "jacoco"
package net.pterodactylus.rhynodge;
-import org.jspecify.annotations.NonNull;
-import org.jspecify.annotations.Nullable;
-
/**
* Defines a filter that runs between {@link Query}s and {@link Merger}s and
* can be used to convert a {@link State} into another {@link State}. This can
* The state to convert
* @return The new state
*/
- @NonNull
- State filter(@Nullable State state);
+ State filter(State state);
}
package net.pterodactylus.rhynodge;
import net.pterodactylus.rhynodge.output.Output;
-import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
/**
* Defines the current state of a system.
* @return An exception that occured, may be {@code null} in case an
* exception can not be meaningfully returned
*/
+ @Nullable
Throwable exception();
- @NonNull
Output output(Reaction reaction);
}
--- /dev/null
+@NullMarked
+package net.pterodactylus.rhynodge.actions;
+
+import org.jspecify.annotations.NullMarked;
import net.pterodactylus.rhynodge.states.TorrentState;
import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile;
-import org.jspecify.annotations.NonNull;
-
/**
* Filter for {@link TorrentState}s that removes all {@link TorrentFile}s whose
* names match a list of bad words.
this.filterWords = filterWords;
}
- @NonNull
@Override
- public State filter(@NonNull State state) {
+ public State filter(State state) {
if (!state.success()) {
return FailedState.from(state);
}
import net.pterodactylus.rhynodge.states.HtmlState;
import org.jsoup.nodes.Document;
-import org.jspecify.annotations.NonNull;
import static net.pterodactylus.rhynodge.utils.Preconditions.checkArgument;
*/
public abstract class ComicSiteFilter implements Filter {
- @NonNull
@Override
- public State filter(@NonNull State state) {
+ public State filter(State state) {
checkArgument(state instanceof HtmlState, "state must be an HTML state");
/* initialize states: */
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.jspecify.annotations.NonNull;
import static net.pterodactylus.rhynodge.utils.Preconditions.checkState;
/**
* {@inheritDoc}
*/
- @NonNull
@Override
- public State filter(@NonNull State state) {
+ public State filter(State state) {
if (!state.success()) {
return FailedState.from(state);
}
import net.pterodactylus.rhynodge.states.StringState;
import org.jsoup.nodes.Document;
-import org.jspecify.annotations.NonNull;
import static net.pterodactylus.rhynodge.utils.Preconditions.checkArgument;
*/
public abstract class ExtractUrlFilter implements Filter {
- @NonNull
@Override
- public State filter(@NonNull State state) {
+ public State filter(State state) {
checkArgument(state instanceof HtmlState, "state must be an HTML state");
HtmlState htmlState = (HtmlState) state;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
-import org.jspecify.annotations.NonNull;
import static net.pterodactylus.rhynodge.utils.Preconditions.checkState;
/**
* {@inheritDoc}
*/
- @NonNull
@Override
- public State filter(@NonNull State state) {
+ public State filter(State state) {
if (!state.success()) {
return FailedState.from(state);
}
import net.pterodactylus.rhynodge.states.HttpState;
import net.pterodactylus.rhynodge.states.StringState;
-import org.jspecify.annotations.NonNull;
-
import static net.pterodactylus.rhynodge.utils.Preconditions.checkArgument;
/**
*/
public class HttpQueryFilter implements Filter {
- @NonNull
@Override
- public State filter(@NonNull State state) {
+ public State filter(State state) {
checkArgument(state instanceof StringState, "state must be a String state");
StringState stringState = (StringState) state;
package net.pterodactylus.rhynodge.filters;
-import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
-import org.jspecify.annotations.NonNull;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.utils.Preconditions.checkState;
/**
/**
* {@inheritDoc}
*/
- @NonNull
@Override
- public State filter(@NonNull State state) {
+ public State filter(State state) {
if (!state.success()) {
return FailedState.from(state);
}
int leechCount = extractLeechCount(dataRow);
try {
if ((downloadUri != null) && (downloadUri.length() > 0)) {
- downloadUri = new URI(((HtmlState) state).uri()).resolve(URLEncoder.encode(downloadUri, "UTF-8").replace("%2F", "/")).toString();
+ downloadUri = new URI(((HtmlState) state).uri()).resolve(URLEncoder.encode(downloadUri, UTF_8).replace("%2F", "/")).toString();
} else {
downloadUri = null;
}
torrentState.addTorrentFile(torrentFile);
} catch (URISyntaxException use1) {
/* ignore; if uri was wrong, we wouldn’t be here. */
- } catch (UnsupportedEncodingException uee1) {
- /* ignore, all JVMs can do UTF-8. */
}
}
--- /dev/null
+@NullMarked
+package net.pterodactylus.rhynodge.filters.comics;
+
+import org.jspecify.annotations.NullMarked;
--- /dev/null
+@NullMarked
+package net.pterodactylus.rhynodge.filters;
+
+import org.jspecify.annotations.NullMarked;
@Override
protected String extractMagnetUri(Element dataRow) {
- return null;
+ return "";
}
@Override
protected String extractDownloadUri(Element dataRow) {
- return null;
+ return "";
}
@Override
--- /dev/null
+@NullMarked
+package net.pterodactylus.rhynodge.filters.torrents;
+
+import org.jspecify.annotations.NullMarked;
* previous state to define that action.
*/
+@NullMarked
package net.pterodactylus.rhynodge;
+import org.jspecify.annotations.NullMarked;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.util.EntityUtils;
+import org.jspecify.annotations.Nullable;
/**
* {@link Query} that performs an HTTP GET request to a fixed uri.
public class HttpQuery implements Query {
private final String uri;
- private final String proxyHost;
+ private final @Nullable String proxyHost;
private final int proxyPort;
public HttpQuery(String uri) {
this(uri, null, -1);
}
- public HttpQuery(String uri, String proxyHost, int proxyPort) {
+ public HttpQuery(String uri, @Nullable String proxyHost, int proxyPort) {
this.uri = uri;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
--- /dev/null
+@NullMarked
+package net.pterodactylus.rhynodge.queries;
+
+import org.jspecify.annotations.NullMarked;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import static java.util.Collections.emptyMap;
private boolean triggered = false;
/** The optional exception that occured while retrieving the state. */
- private final Throwable exception;
+ private final @Nullable Throwable exception;
/** The number of consecutive failures. */
@JsonProperty
* @param exception
* The exception that occured while retrieving the state
*/
- protected AbstractState(Throwable exception) {
+ protected AbstractState(@Nullable Throwable exception) {
this(Clock.systemUTC(), exception);
}
* @param clock The clock for generating {@link #time}
* @param exception The exception that occured while retrieving the state
*/
- protected AbstractState(Clock clock, Throwable exception) {
+ protected AbstractState(Clock clock, @Nullable Throwable exception) {
this(clock, false, true, exception);
}
* @param exception
* The exception that occured while retrieving the state
*/
- protected AbstractState(boolean success, boolean empty, Throwable exception) {
+ protected AbstractState(boolean success, boolean empty, @Nullable Throwable exception) {
this(Clock.systemUTC(), success, empty, exception);
}
* otherwise
* @param exception The exception that occured while retrieving the state
*/
- protected AbstractState(Clock clock, boolean success, boolean empty, Throwable exception) {
+ protected AbstractState(Clock clock, boolean success, boolean empty, @Nullable Throwable exception) {
this.time = clock.millis();
this.success = success;
this.empty = empty;
/**
* {@inheritDoc}
*/
+ @Nullable
@Override
public Throwable exception() {
return exception;
}
- @NonNull
@Override
public Output output(Reaction reaction) {
return new DefaultOutput(summary(reaction))
.addText("text/html", htmlText());
}
- @NonNull
protected String summary(Reaction reaction) {
return reaction.name();
}
- @NonNull
protected abstract String plainText();
- @Nullable
protected String htmlText() {
var tagConsumer = createHTML(false, false);
var div = new DIV(emptyMap(), tagConsumer);
import kotlinx.html.FlowContent;
import net.pterodactylus.rhynodge.Reaction;
import net.pterodactylus.rhynodge.states.ComicState.Comic;
-import org.jspecify.annotations.NonNull;
-import org.jspecify.annotations.Nullable;
import static java.lang.String.format;
import static kotlinx.html.Gen_consumer_tagsKt.html;
return format("ComicState[comics=%s]", comics());
}
- @NonNull
@Override
protected String summary(Reaction reaction) {
return format("New Comic found for “%s!”", reaction.name());
}
- @NonNull
@Override
protected String plainText() {
StringBuilder text = new StringBuilder();
return text.toString();
}
- @Nullable
@Override
protected String htmlText() {
List<Comic> latestComics = new ArrayList<>(comics());
import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile;
import com.fasterxml.jackson.annotation.JsonProperty;
-import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
return Collections.unmodifiableCollection(episodes);
}
- @NonNull
@Override
protected String summary(Reaction reaction) {
if (!newEpisodes.isEmpty()) {
return String.format("%d changed Torrent(s) for “%s!”", changedEpisodes.size(), reaction.name());
}
- @NonNull
@Override
protected String plainText() {
StringBuilder stringBuilder = new StringBuilder();
return stringBuilder.toString();
}
- @NonNull
@Override
protected String htmlText() {
var tagConsumer = createHTML(false, false);
th(row, null, null, wrapper(th -> th.text("Download")));
}))));
tbody(table, null, wrapper(tableBody -> {
- var lastEpisode = new AtomicReference<Episode>();
+ var lastEpisode = new AtomicReference<@Nullable Episode>();
for (Map.Entry<Integer, List<Episode>> seasonEntry : episodes.stream().sorted(Comparator.<Episode>naturalOrder().reversed()).collect(groupingBy(Episode::season, LinkedHashMap::new, toList())).entrySet()) {
for (Episode episode : seasonEntry.getValue()) {
for (TorrentFile torrentFile : episode) {
import java.io.Writer;
import net.pterodactylus.rhynodge.State;
-import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
/**
* {@link State} implementation that signals failure.
* @param exception
* The exception of the state
*/
- public FailedState(Throwable exception) {
+ public FailedState(@Nullable Throwable exception) {
super(exception);
}
return true;
}
- @NonNull
@Override
protected String plainText() {
if (exception() == null) {
package net.pterodactylus.rhynodge.states;
import net.pterodactylus.rhynodge.State;
-import org.jspecify.annotations.NonNull;
/**
* A {@link State} that contains information about a file.
return modificationTime;
}
- @NonNull
@Override
protected String plainText() {
return toString();
import net.pterodactylus.rhynodge.State;
import org.jsoup.nodes.Document;
-import org.jspecify.annotations.NonNull;
-import org.jspecify.annotations.Nullable;
/**
* {@link State} implementation that contains a parsed HTML {@link Document}.
return document;
}
- @NonNull
@Override
protected String plainText() {
//noinspection ConstantConditions
return htmlText();
}
- @Nullable
@Override
protected String htmlText() {
return document.toString();
import org.apache.http.HeaderElement;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicHeaderValueParser;
-import org.jspecify.annotations.NonNull;
/**
* {@link State} that contains the results of an {@link HttpQuery}.
}
}
- @NonNull
@Override
protected String plainText() {
return content();
import java.util.Optional;
import net.pterodactylus.rhynodge.State;
-import org.jspecify.annotations.NonNull;
-import org.jspecify.annotations.Nullable;
/**
* {@link State} implementation that can expose itself as plain text and/or
return !plainTextOutput.isPresent() && !htmlOutput.isPresent();
}
- @NonNull
@Override
protected String plainText() {
return plainTextOutput.orElse("");
}
- @Nullable
@Override
protected String htmlText() {
- return htmlOutput.orElse(null);
+ return htmlOutput.orElse("");
}
}
package net.pterodactylus.rhynodge.states;
-import org.jspecify.annotations.NonNull;
-
/**
* A {@link net.pterodactylus.rhynodge.State} that stores a single {@link
* String} value.
return value.isEmpty();
}
- @NonNull
@Override
protected String plainText() {
return value;
import net.pterodactylus.rhynodge.Reaction;
import net.pterodactylus.rhynodge.State;
-import net.pterodactylus.rhynodge.output.DefaultOutput;
-import net.pterodactylus.rhynodge.output.Output;
import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
-import org.jspecify.annotations.NonNull;
-import org.jspecify.annotations.Nullable;
import static java.lang.String.format;
return this;
}
- @NonNull
@Override
protected String summary(Reaction reaction) {
return format("Found %d new Torrent(s) for “%s!”", newTorrentFiles.size(), reaction.name());
}
- @NonNull
@Override
protected String plainText() {
StringBuilder plainText = new StringBuilder();
return plainText.toString();
}
- @Nullable
@Override
protected String htmlText() {
StringBuilder htmlBuilder = new StringBuilder();
*/
@SuppressWarnings("unused")
private TorrentFile() {
- this(null, null, null, null, 0, 0, 0);
+ this("", "", "", "", 0, 0, 0);
}
/**
--- /dev/null
+@NullMarked
+package net.pterodactylus.rhynodge.states;
+
+import org.jspecify.annotations.NullMarked;
package net.pterodactylus.rhynodge.watchers;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.filters.BlacklistFilter.createDefaultBlacklistFilter;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
* @return The query of the watcher
*/
private static Query createHttpQuery(String searchTerms) {
- try {
- return new HttpQuery("https://kat.cr/usearch/" + URLEncoder.encode(searchTerms, "UTF-8") + "/?field=time_add&sorder=desc");
- } catch (UnsupportedEncodingException uee1) {
- /* will not happen. */
- return null;
- }
+ return new HttpQuery("https://kat.cr/usearch/" + URLEncoder.encode(searchTerms, UTF_8) + "/?field=time_add&sorder=desc");
}
/**
package net.pterodactylus.rhynodge.watchers;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.filters.BlacklistFilter.createDefaultBlacklistFilter;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
* @return The query of the watcher
*/
private static Query createHttpQuery(String searchTerms) {
- try {
- return new HttpQuery("https://kat.cr/usearch/" + URLEncoder.encode(searchTerms, "UTF-8") + "/?field=time_add&sorder=desc");
- } catch (UnsupportedEncodingException uee1) {
- /* will not happen. */
- return null;
- }
+ return new HttpQuery("https://kat.cr/usearch/" + URLEncoder.encode(searchTerms, UTF_8) + "/?field=time_add&sorder=desc");
}
/**
package net.pterodactylus.rhynodge.watchers;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.filters.BlacklistFilter.createDefaultBlacklistFilter;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
//
private static Query createHttpQuery(String searchTerms, String proxyHost, int proxyPort) {
- try {
- HttpQuery hiddenServiceQuery = new HttpQuery("http://uj3wazyk5u4hnvtk.onion/search/" + URLEncoder.encode(searchTerms, "UTF-8") + "/0/3/0", proxyHost, proxyPort);
- HttpQuery torQuery = new HttpQuery("http://thepiratebay.org/search/" + URLEncoder.encode(searchTerms, "UTF-8") + "/0/3/0", proxyHost, proxyPort);
- HttpQuery plainInternetQuery = new HttpQuery("http://thepiratebay.org/search/" + URLEncoder.encode(searchTerms, "UTF-8") + "/0/3/0");
- return new FallbackQuery(hiddenServiceQuery, torQuery, plainInternetQuery);
- } catch (UnsupportedEncodingException uee1) {
- /* will not happen. */
- return null;
- }
+ HttpQuery hiddenServiceQuery = new HttpQuery("http://uj3wazyk5u4hnvtk.onion/search/" + URLEncoder.encode(searchTerms, UTF_8) + "/0/3/0", proxyHost, proxyPort);
+ HttpQuery torQuery = new HttpQuery("http://thepiratebay.org/search/" + URLEncoder.encode(searchTerms, UTF_8) + "/0/3/0", proxyHost, proxyPort);
+ HttpQuery plainInternetQuery = new HttpQuery("http://thepiratebay.org/search/" + URLEncoder.encode(searchTerms, UTF_8) + "/0/3/0");
+ return new FallbackQuery(hiddenServiceQuery, torQuery, plainInternetQuery);
}
/**
package net.pterodactylus.rhynodge.watchers;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.filters.BlacklistFilter.createDefaultBlacklistFilter;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
* @return The query of the watcher
*/
private static Query createHttpQuery(String searchTerms, String proxyHost, int proxyPort) {
- try {
- HttpQuery hiddenServiceQuery = new HttpQuery("http://uj3wazyk5u4hnvtk.onion/search/" + URLEncoder.encode(searchTerms, "UTF-8") + "/0/3/0", proxyHost, proxyPort);
- HttpQuery torQuery = new HttpQuery("http://thepiratebay.org/search/" + URLEncoder.encode(searchTerms, "UTF-8") + "/0/3/0", proxyHost, proxyPort);
- HttpQuery plainInternetQuery = new HttpQuery("http://thepiratebay.org/search/" + URLEncoder.encode(searchTerms, "UTF-8") + "/0/3/0");
- return new FallbackQuery(hiddenServiceQuery, torQuery, plainInternetQuery);
- } catch (UnsupportedEncodingException uee1) {
- /* will not happen. */
- return null;
- }
+ HttpQuery hiddenServiceQuery = new HttpQuery("http://uj3wazyk5u4hnvtk.onion/search/" + URLEncoder.encode(searchTerms, UTF_8) + "/0/3/0", proxyHost, proxyPort);
+ HttpQuery torQuery = new HttpQuery("http://thepiratebay.org/search/" + URLEncoder.encode(searchTerms, UTF_8) + "/0/3/0", proxyHost, proxyPort);
+ HttpQuery plainInternetQuery = new HttpQuery("http://thepiratebay.org/search/" + URLEncoder.encode(searchTerms, UTF_8) + "/0/3/0");
+ return new FallbackQuery(hiddenServiceQuery, torQuery, plainInternetQuery);
}
/**
package net.pterodactylus.rhynodge.watchers;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.filters.BlacklistFilter.createDefaultBlacklistFilter;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
* @return The query of the watcher
*/
private static Query createHttpQuery(String searchTerms) {
- try {
- return new HttpQuery("http://www.torrenthound.com/search/1/" + URLEncoder.encode(searchTerms, "UTF-8") + "/added:desc");
- } catch (UnsupportedEncodingException uee1) {
- /* will not happen. */
- return null;
- }
+ return new HttpQuery("http://www.torrenthound.com/search/1/" + URLEncoder.encode(searchTerms, UTF_8) + "/added:desc");
}
/**
package net.pterodactylus.rhynodge.watchers;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.filters.BlacklistFilter.createDefaultBlacklistFilter;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
* @return The query of the watcher
*/
private static Query createHttpQuery(String searchTerms) {
- try {
- return new HttpQuery("http://www.torrenthound.com/search/1/" + URLEncoder.encode(searchTerms, "UTF-8") + "/added:desc");
- } catch (UnsupportedEncodingException uee1) {
- /* will not happen. */
- return null;
- }
+ return new HttpQuery("http://www.torrenthound.com/search/1/" + URLEncoder.encode(searchTerms, UTF_8) + "/added:desc");
}
/**
package net.pterodactylus.rhynodge.watchers;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.filters.BlacklistFilter.createDefaultBlacklistFilter;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
* @return The query of the watcher
*/
private static Query createHttpQuery(String searchTerms) {
- try {
- return new HttpQuery("http://torrentz.eu/searchA?q=" + URLEncoder.encode(searchTerms, "UTF-8"));
- } catch (UnsupportedEncodingException uee1) {
- /* will not happen. */
- return null;
- }
+ return new HttpQuery("http://torrentz.eu/searchA?q=" + URLEncoder.encode(searchTerms, UTF_8));
}
/**
package net.pterodactylus.rhynodge.watchers;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static net.pterodactylus.rhynodge.filters.BlacklistFilter.createDefaultBlacklistFilter;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
* @return The query of the watcher
*/
private static Query createHttpQuery(String searchTerms) {
- try {
- return new HttpQuery("http://torrentz.eu/searchA?q=" + URLEncoder.encode(searchTerms, "UTF-8"));
- } catch (UnsupportedEncodingException uee1) {
- /* will not happen. */
- return null;
- }
+ return new HttpQuery("http://torrentz.eu/searchA?q=" + URLEncoder.encode(searchTerms, UTF_8));
}
/**
--- /dev/null
+@NullMarked
+package net.pterodactylus.rhynodge.watchers;
+
+import org.jspecify.annotations.NullMarked;
private fun parseMovies(jsonNode: JsonNode) =
jsonNode.get("movies").map { movieNode ->
- MovieJson(movieNode.get("id").asText(), movieNode.get("translations").get(0).get("name").asText().split("|").first().strip(), movieNode.get("slug").asText(), movieNode.get("poster").get("src").asText().fixImageUrl(), movieNode.get("translations").get(0).get("descLong").asText())
+ MovieJson(movieNode.get("id").asText(), movieNode.get("translations").get(0).get("name").asText().split("|").first().trim(), movieNode.get("slug").asText(), movieNode.get("poster").get("src").asText().fixImageUrl(), movieNode.get("translations").get(0).get("descLong").asText())
}
private data class MovieJson(val id: String, val name: String, val slug: String, val poster: String, val description: String)
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
import java.util.Collections;
import java.util.List;
@Test
public void comicSiteFilterRequiresHtmlState() {
State state = new FailedState();
- ComicSiteFilter comicSiteFilter = new TestComicSiteFilter(null, null, null);
+ ComicSiteFilter comicSiteFilter = new TestComicSiteFilter("", mock(), mock());
assertThrows(IllegalArgumentException.class, () -> comicSiteFilter.filter(state));
}
@Test
public void htmlWithoutImagesIsNotRecognizedAsComic() {
- State state = new HtmlState("http://foo/", null);
- ComicSiteFilter comicSiteFilter = new TestComicSiteFilter("Title", Collections.<String>emptyList(), null);
+ State state = new HtmlState("http://foo/", mock());
+ ComicSiteFilter comicSiteFilter = new TestComicSiteFilter("Title", Collections.<String>emptyList(), mock());
State newState = comicSiteFilter.filter(state);
assertThat(newState.success(), is(false));
}
@Test
public void everyUrlGetAStrip() {
- State state = new HtmlState("http://foo/", null);
+ State state = new HtmlState("http://foo/", mock());
ComicSiteFilter comicSiteFilter = new TestComicSiteFilter("Title", asList("url1.gif", "url2.gif", "url3.gif"), asList("Comment 1", "Comment 2"));
State newState = comicSiteFilter.filter(state);
assertThat(newState instanceof ComicState, is(true));
@Test
public void illegalUrlThrowsException() {
- State state = new HtmlState("http://foo/^", null);
+ State state = new HtmlState("http://foo/^", mock());
ComicSiteFilter comicSiteFilter = new TestComicSiteFilter("Title", asList("url1.gif"), Collections.<String>emptyList());
assertThrows(IllegalStateException.class, () -> comicSiteFilter.filter(state));
}
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
import net.pterodactylus.rhynodge.State;
import net.pterodactylus.rhynodge.states.EpisodeState;
@Test
public void episodeFilterRequiresATorrentState() {
- State state = new HtmlState("http://foo/", null);
+ State state = new HtmlState("http://foo/", mock());
assertThrows(IllegalStateException.class, () -> episodeFilter.filter(state));
}
--- /dev/null
+@NullMarked
+package net.pterodactylus.rhynodge.filters;
+
+import org.jspecify.annotations.NullMarked;
import java.util.Optional.of
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
+import org.mockito.Mockito.mock
/**
* Unit test for [ReactionRunner].
}, "Test Reaction")
private fun createEmailAction(action: () -> Unit = {}) = object : EmailAction("test.test", "sender@test.test", "recipient@test.test") {
- override fun execute(output: Output?) = action()
+ override fun execute(output: Output) = action()
}
private val reactionState = createReactionState()
- private val failingReaction = object : Reaction("Test", null, null, null) {
+ private val failingReaction = object : Reaction("Test", mock(), mock(), mock()) {
override fun query() = Query { FailedState() }
}
private val nullEmailAction = createEmailAction { }
import org.junit.jupiter.api.Test
import java.time.Instant
import java.time.ZoneOffset
+import org.mockito.Mockito.mock
class FreeGamesStateTest {
@Test
fun `state lists all games in text output`() {
- val output = state.output(Reaction("", null, null, null)).text("text/plain")
+ val output = state.output(Reaction("", mock(), mock(), mock())).text("text/plain")
assertThat(
output, equalTo(
listOf(
@Test
fun `state lists all games in HTML output`() {
- val output = state.output(Reaction("", null, null, null)).text("text/html")
+ val output = state.output(Reaction("", mock(), mock(), mock())).text("text/html")
val parsedOutput = Jsoup.parse(output)
assertThat(
parsedOutput.select(".game").map {
import org.jsoup.nodes.TextNode
import org.junit.jupiter.api.Test
import java.time.LocalDateTime
+import org.mockito.Mockito.mock
class MovieStateTest {
Movie("3", "", "", listOf(Performance(LocalDateTime.of(2024, 2, 11, 21, 15), "", "")))
), emptySet()
)
- assertThat(movieState.output(Reaction("", null, null, null)).summary(), containsString("2024-02-11"))
+ assertThat(movieState.output(Reaction("", mock(), mock(), mock())).summary(), containsString("2024-02-11"))
}
@Test
@Test
fun `html output does not contain a section for new movies if there are no new movies`() {
val movieState = MovieState(emptySet(), emptySet())
- val output = movieState.output(Reaction("", null, null, null))
+ val output = movieState.output(Reaction("", mock(), mock(), mock()))
val document = Jsoup.parse(output.text("text/html"))
assertThat(document.select("section.new-movies"), empty())
}
@Test
fun `html output does contain a section for new movie if there are new movies`() {
val movieState = MovieState(emptySet(), setOf(Movie("1", "", ""), Movie("2", "", "")))
- val output = movieState.output(Reaction("", null, null, null))
+ val output = movieState.output(Reaction("", mock(), mock(), mock()))
val document = Jsoup.parse(output.text("text/html"))
assertThat(document.select("section.new-movies"), not(empty()))
}
@Test
fun `new movies section contains description of movies`() {
val movieState = MovieState(emptySet(), setOf(Movie("1", "", "Movie 1 is cool."), Movie("2", "", "Movie 2 is bad.")))
- val output = movieState.output(Reaction("", null, null, null))
+ val output = movieState.output(Reaction("", mock(), mock(), mock()))
val document = Jsoup.parse(output.text("text/html"))
assertThat(document.select("section.new-movies .description").map(Element::text), contains("Movie 1 is cool.", "Movie 2 is bad."))
}
@Test
fun `new movies section contains the titles of all new movies`() {
val movieState = MovieState(emptySet(), setOf(Movie("New Movie", "", ""), Movie("Even Newer Movie", "", "")))
- val output = movieState.output(Reaction("", null, null, null))
+ val output = movieState.output(Reaction("", mock(), mock(), mock()))
val document = Jsoup.parse(output.text("text/html"))
assertThat(document.select("section.new-movies li.movie .name").textNodes().map(TextNode::text), containsInAnyOrder("New Movie", "Even Newer Movie"))
}
@Test
fun `html output contains section for the daily programme`() {
val movieState = MovieState(emptySet(), emptySet())
- val output = movieState.output(Reaction("", null, null, null))
+ val output = movieState.output(Reaction("", mock(), mock(), mock()))
val document = Jsoup.parse(output.text("text/html"))
assertThat(document.select("section.daily-programmes"), not(empty()))
}
movie("Movie 4", "", "", "20240216-1000"),
), emptySet()
)
- val output = movieState.output(Reaction("", null, null, null))
+ val output = movieState.output(Reaction("", mock(), mock(), mock()))
val html = output.text("text/html")
val document = Jsoup.parse(html)
assertThat(document.select("section.daily-programmes li.day").map { it.attr("data-date") }, contains("2024-02-12", "2024-02-13", "2024-02-14", "2024-02-16"))
movie("Movie 2", "https://cdn.premiumkino.de/movie/1066/aba09af737677ff6a15676ae588098b1_w300.jpg", "", "20240212-1845", "20240213-1330", "20240214-1815")
)
)
- val output = movieState.output(Reaction("", null, null, null))
+ val output = movieState.output(Reaction("", mock(), mock(), mock()))
val html = output.text("text/html")
val document = Jsoup.parse(html)
assertThat(
movie("Movie 1", "https://cdn.premiumkino.de/movie/3047/81c49774d7828a898ae1d525ffd135af_w300.jpg", "", "20240212-1845" to "2D OV", "20240213-1330" to "2D", "20240214-1815" to "2D OmeU"),
), setOf()
)
- val output = movieState.output(Reaction("", null, null, null))
+ val output = movieState.output(Reaction("", mock(), mock(), mock()))
val html = output.text("text/html")
val document = Jsoup.parse(html)
assertThat(
import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.not
import org.junit.jupiter.api.Test
+import org.mockito.Mockito.mock
import org.xml.sax.InputSource
class ComicStateTest {
}
-private val reaction = Reaction("foo", null, null, null)
+private val reaction = Reaction("foo", mock(), mock(), mock())