From: David ‘Bombe’ Roden Date: Mon, 25 Oct 2021 19:28:11 +0000 (+0200) Subject: 🐛 Fix broken change detection X-Git-Tag: v2~59 X-Git-Url: https://git.pterodactylus.net/?p=rhynodge.git;a=commitdiff_plain;h=00e49489dcbb093895a9a7bfb252b7392b341138 🐛 Fix broken change detection Wow, this was a mess. Two days after the last deploy with a working change detection I changed some code around the triggers and broke the detection. I didn’t realize until over a year later because I have never deployed the broken version until I made some unrelated changes. I never liked the particular solution around the triggers keeping state and not being pure functions. So now there are no more triggers; instead, the merging of the states (which was done by the triggers — great misnomer there) is now done by a merger, and the state is responsible for exposing whether it contains a noteworthy change. The Merger and the State for a particular thing (like a comic, or a torrent file) have to work together hand in hand here but they also needed to do that before and it’s not really like you would use an X-Merger with a Y-State. The resulting changes touch pretty much everything but due to the Watcher “shortcut” of chain creation, all .json files that only reference a Watcher do not need to be touched which should make transition rather seamless. --- diff --git a/README.md b/README.md index 32ebc3c..460f783 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Rhynodge also periodically scans the chains directory to find changed or new cha ## Internal Concepts -The core of Rhynodge comprises ``Reaction``s which in turn consist of ``Query``s, ``Filter``s, ``Trigger``s, and ``Action``s. +The core of Rhynodge comprises ``Reaction``s which in turn consist of ``Query``s, ``Filter``s, ``Merger``s, and ``Action``s. ### Query @@ -44,18 +44,18 @@ A filter is an optional component that turns a ``State`` into a different ``Stat The result of a ``Filter`` is a ``State``, again. -### Trigger +### Merger -A trigger decides if, given the current state and the previous state, a noteworthy change has occured. It could calculate the difference between two file lists, or of two Facebook post lists. +A merger merges two states into a new state; the new state is responsible for detecting whether a noteworthy change has occured. -The result of a ``Trigger`` is an ``Output``. +The result of a ``Merger`` is — once again — a ``State``. ### Watcher -A watcher combines a query, a list of filters, and a trigger into a single unit which can be configured a lot easier than the separate components. For example, you could have a “Twitter” that finds new status updates for a username and that only needs to be configured with that username; the rest of the configuration is contained in the watcher. +A watcher combines a query, a list of filters, and a merger into a single unit which can be configured a lot easier than the separate components. For example, you could have a “Twitter” that finds new status updates for a username and that only needs to be configured with that username; the rest of the configuration is contained in the watcher. -A ``Watcher`` does not do any processing but instead offers a ``Query``, a list of ``Filter``s, and a ``Trigger``. +A ``Watcher`` does not do any processing but instead offers a ``Query``, a list of ``Filter``s, and a ``Merger``. ### Action -If a trigger found a change, the action is then executed. Again, an action can be almost anything: it can send an email, it can execute programs, print documents, initiate phone calls, take a picture from a webcam — anything you can program can be used an an action. +If a noteworthy change has been detected, the action is then executed. Again, an action can be almost anything: it can send an email, it can execute programs, print documents, initiate phone calls, take a picture from a webcam — anything you can program can be used an an action. diff --git a/src/main/java/net/pterodactylus/rhynodge/Action.java b/src/main/java/net/pterodactylus/rhynodge/Action.java index 4a7ed56..157f555 100644 --- a/src/main/java/net/pterodactylus/rhynodge/Action.java +++ b/src/main/java/net/pterodactylus/rhynodge/Action.java @@ -20,8 +20,8 @@ package net.pterodactylus.rhynodge; import net.pterodactylus.rhynodge.output.Output; /** - * An action is performed when a {@link Trigger} determines that two given - * {@link State}s of a {@link Query} signify a change. + * An action is performed when a {@link State} has {@link State#triggered()} + * a noteworthy change. * * @author David ‘Bombe’ Roden */ diff --git a/src/main/java/net/pterodactylus/rhynodge/Filter.java b/src/main/java/net/pterodactylus/rhynodge/Filter.java index 1906afa..3095623 100644 --- a/src/main/java/net/pterodactylus/rhynodge/Filter.java +++ b/src/main/java/net/pterodactylus/rhynodge/Filter.java @@ -20,7 +20,7 @@ package net.pterodactylus.rhynodge; import org.jetbrains.annotations.NotNull; /** - * Defines a filter that runs between {@link Query}s and {@link Trigger}s and + * 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 * be used to extract further information from a state. *

diff --git a/src/main/java/net/pterodactylus/rhynodge/Reaction.java b/src/main/java/net/pterodactylus/rhynodge/Reaction.java index 69e2592..4b390ef 100644 --- a/src/main/java/net/pterodactylus/rhynodge/Reaction.java +++ b/src/main/java/net/pterodactylus/rhynodge/Reaction.java @@ -23,7 +23,7 @@ import java.util.List; import com.google.common.collect.Lists; /** - * A {@code Reaction} binds together {@link Query}s, {@link Trigger}s, and + * A {@code Reaction} binds together {@link Query}s, {@link Merger}s, and * {@link Action}s, and it stores the intermediary {@link State}s. * * @author David ‘Bombe’ Roden @@ -39,8 +39,8 @@ public class Reaction { /** The filters to run. */ private final List filters = Lists.newArrayList(); - /** The trigger to detect changes. */ - private final Trigger trigger; + /** The merger merges old and new states. */ + private final Merger merger; /** The action to perform. */ private final Action action; @@ -55,13 +55,13 @@ public class Reaction { * The name of the reaction * @param query * The query to run - * @param trigger - * The trigger to detect changes + * @param merger + * The merger to merge states * @param action * The action to perform */ - public Reaction(String name, Query query, Trigger trigger, Action action) { - this(name, query, Collections. emptyList(), trigger, action); + public Reaction(String name, Query query, Merger merger, Action action) { + this(name, query, Collections. emptyList(), merger, action); } /** @@ -73,16 +73,16 @@ public class Reaction { * The query to run * @param filters * The filters to run - * @param trigger - * The trigger to detect changes + * @param merger + * The merger to merge states * @param action * The action to perform */ - public Reaction(String name, Query query, List filters, Trigger trigger, Action action) { + public Reaction(String name, Query query, List filters, Merger merger, Action action) { this.name = name; this.query = query; this.filters.addAll(filters); - this.trigger = trigger; + this.merger = merger; this.action = action; } @@ -119,12 +119,12 @@ public class Reaction { } /** - * Returns the trigger to detect changes. + * Returns the merger to merge states. * - * @return The trigger to detect changes + * @return The merger to merge states */ - public Trigger trigger() { - return trigger; + public Merger merger() { + return merger; } /** diff --git a/src/main/java/net/pterodactylus/rhynodge/State.java b/src/main/java/net/pterodactylus/rhynodge/State.java index bda5bf5..2a8ba1c 100644 --- a/src/main/java/net/pterodactylus/rhynodge/State.java +++ b/src/main/java/net/pterodactylus/rhynodge/State.java @@ -47,6 +47,18 @@ public interface State { */ boolean success(); + /** + * Returns whether this state triggers a change notification. This can + * only return {@code true} if this state is the result of a + * {@link Merger} merging two states. + * + * @return {@code true} if this state triggers a change notification, + * {@code false} otherwise + */ + default boolean triggered() { + return false; + } + boolean isEmpty(); /** diff --git a/src/main/java/net/pterodactylus/rhynodge/Trigger.java b/src/main/java/net/pterodactylus/rhynodge/Trigger.java deleted file mode 100644 index 9f43a46..0000000 --- a/src/main/java/net/pterodactylus/rhynodge/Trigger.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Rhynodge - Trigger.java - Copyright © 2013 David Roden - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.pterodactylus.rhynodge; - -import net.pterodactylus.rhynodge.states.FileState; - -/** - * A trigger determines whether two different states actually warrant a change - * trigger. For example, two {@link FileState}s might contain different file - * sizes but a trigger might only care about whether the file appeared or - * disappeared since the last check. - * - * @author David ‘Bombe’ Roden - */ -public interface Trigger { - - /** - * Merges the current state into the previous state, returning the merged - * state. - * - * @param previousState - * The previous state of the system - * @param currentState - * The current state of a system - * @return The new state, containing a meaningful merge between the previous - * and the current state - */ - State mergeStates(State previousState, State currentState); - - /** - * Checks whether the states given to {@link #mergeStates(State, State)} - * warrant a change trigger. - * - * @return {@code true} if the states given to - * {@link #mergeStates(State, State)} warrant a change trigger, - * {@code false} otherwise - */ - boolean triggers(); - -} diff --git a/src/main/java/net/pterodactylus/rhynodge/Watcher.java b/src/main/java/net/pterodactylus/rhynodge/Watcher.java index 2ded28f..4e63846 100644 --- a/src/main/java/net/pterodactylus/rhynodge/Watcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/Watcher.java @@ -21,7 +21,7 @@ import java.util.List; /** * A {@code Watcher} combines a {@link Query}, a number of {@link Filter}s, and - * a {@link Trigger}, as these parts are closely related after all. + * a {@link Merger}, as these parts are closely related after all. * * @author David ‘Bombe’ Roden */ @@ -42,10 +42,10 @@ public interface Watcher { public List filters(); /** - * Returns the trigger of the watcher. + * Returns the merger of the watcher. * - * @return The trigger of the watcher + * @return The merger of the watcher */ - public Trigger trigger(); + public Merger merger(); } diff --git a/src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java b/src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java index a4006d8..0538a0f 100644 --- a/src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java +++ b/src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java @@ -15,8 +15,8 @@ import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; import net.pterodactylus.rhynodge.Reaction; import net.pterodactylus.rhynodge.State; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.actions.EmailAction; +import net.pterodactylus.rhynodge.Merger; import net.pterodactylus.rhynodge.output.DefaultOutput; import net.pterodactylus.rhynodge.output.Output; import net.pterodactylus.rhynodge.states.FailedState; @@ -25,7 +25,7 @@ import org.apache.log4j.Logger; /** * Runs a {@link Reaction}, starting with its {@link Query}, running the {@link - * State} through its {@link Filter}s, and finally checking the {@link Trigger} + * State} through its {@link Filter}s, and finally checking the {@link Merger} * for whether an {@link Action} needs to be executed. * * @author David ‘Bombe’ Roden @@ -59,10 +59,10 @@ public class ReactionRunner implements Runnable { reactionState.saveState(state); return; } - Trigger trigger = reaction.trigger(); - State newState = trigger.mergeStates(lastSuccessfulState.get(), state); + Merger merger = reaction.merger(); + State newState = merger.mergeStates(lastSuccessfulState.get(), state); reactionState.saveState(newState); - if (trigger.triggers()) { + if (newState.triggered()) { logger.info(format("Trigger was hit for %s, executing action...", reaction.name())); reaction.action().execute(newState.output(reaction)); } diff --git a/src/main/java/net/pterodactylus/rhynodge/loader/Chain.java b/src/main/java/net/pterodactylus/rhynodge/loader/Chain.java index ab81754..c4eba26 100644 --- a/src/main/java/net/pterodactylus/rhynodge/loader/Chain.java +++ b/src/main/java/net/pterodactylus/rhynodge/loader/Chain.java @@ -177,11 +177,11 @@ public class Chain { @JsonProperty private List filters = new ArrayList(); - /** The trigger of the chain. */ + /** The merger of the chain. */ @JsonProperty - private Part trigger; + private Part merger; - /** A combination of query, filters, and a trigger. */ + /** A combination of query, filters, and a merger. */ @JsonProperty private Part watcher; @@ -230,12 +230,12 @@ public class Chain { } /** - * Returns the trigger of this chain. + * Returns the merger of this chain. * - * @return The trigger of this chain + * @return The merger of this chain */ - public Part trigger() { - return trigger; + public Part merger() { + return merger; } /** @@ -283,7 +283,7 @@ public class Chain { for (Part filter : filters) { hashCode ^= filter.hashCode(); } - hashCode ^= trigger.hashCode(); + hashCode ^= merger.hashCode(); } hashCode ^= action.hashCode(); hashCode ^= updateInterval; @@ -318,7 +318,7 @@ public class Chain { return false; } } - if (!trigger.equals(chain.trigger)) { + if (!merger.equals(chain.merger)) { return false; } } diff --git a/src/main/java/net/pterodactylus/rhynodge/loader/ChainWatcher.java b/src/main/java/net/pterodactylus/rhynodge/loader/ChainWatcher.java index 69faf8b..f0b1215 100644 --- a/src/main/java/net/pterodactylus/rhynodge/loader/ChainWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/loader/ChainWatcher.java @@ -143,8 +143,8 @@ public class ChainWatcher extends AbstractExecutionThreadService { logger.debug(String.format(" Parameter: %s=%s", parameter.name(), parameter.value())); } } - logger.debug(String.format(" Trigger: %s", chain.trigger().name())); - for (Parameter parameter : chain.trigger().parameters()) { + logger.debug(String.format(" Trigger: %s", chain.merger().name())); + for (Parameter parameter : chain.merger().parameters()) { logger.debug(String.format(" Parameter: %s=%s", parameter.name(), parameter.value())); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/loader/ReactionLoader.java b/src/main/java/net/pterodactylus/rhynodge/loader/ReactionLoader.java index 10608d9..94009af 100644 --- a/src/main/java/net/pterodactylus/rhynodge/loader/ReactionLoader.java +++ b/src/main/java/net/pterodactylus/rhynodge/loader/ReactionLoader.java @@ -27,10 +27,10 @@ import net.pterodactylus.rhynodge.Action; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; import net.pterodactylus.rhynodge.Reaction; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.loader.Chain.Parameter; import net.pterodactylus.rhynodge.loader.Chain.Part; +import net.pterodactylus.rhynodge.Merger; /** * Creates {@link Reaction}s from {@link Chain}s. @@ -68,7 +68,7 @@ public class ReactionLoader { Watcher watcher = createObject(chain.watcher().name(), "net.pterodactylus.rhynodge.watchers", extractParameters(chain.watcher().parameters())); /* create reaction. */ - reaction = new Reaction(chain.name(), watcher.query(), watcher.filters(), watcher.trigger(), action); + reaction = new Reaction(chain.name(), watcher.query(), watcher.filters(), watcher.merger(), action); } else { @@ -81,11 +81,11 @@ public class ReactionLoader { filters.add(ReactionLoader. createObject(filterPart.name(), "net.pterodactylus.rhynodge.filters", extractParameters(filterPart.parameters()))); } - /* create trigger. */ - Trigger trigger = createObject(chain.trigger().name(), "net.pterodactylus.rhynodge.triggers", extractParameters(chain.trigger().parameters())); + /* create merger. */ + Merger merger = createObject(chain.merger().name(), "net.pterodactylus.rhynodge.mergers", extractParameters(chain.merger().parameters())); /* create reaction. */ - reaction = new Reaction(chain.name(), query, filters, trigger, action); + reaction = new Reaction(chain.name(), query, filters, merger, action); } reaction.setUpdateInterval(TimeUnit.SECONDS.toMillis(chain.updateInterval())); diff --git a/src/main/java/net/pterodactylus/rhynodge/mergers/ComicMerger.java b/src/main/java/net/pterodactylus/rhynodge/mergers/ComicMerger.java new file mode 100644 index 0000000..5b8f8df --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/mergers/ComicMerger.java @@ -0,0 +1,62 @@ +/* + * rhynodge - ComicMerger.java - Copyright © 2013–2021 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.pterodactylus.rhynodge.mergers; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.annotation.Nonnull; + +import net.pterodactylus.rhynodge.Merger; +import net.pterodactylus.rhynodge.State; +import net.pterodactylus.rhynodge.states.ComicState; +import net.pterodactylus.rhynodge.states.ComicState.Comic; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * {@link Merger} implementation that merger two {@link ComicState}s. + * + * @author David ‘Bombe’ Roden + */ +public class ComicMerger implements Merger { + + @Nonnull + @Override + public State mergeStates(@Nonnull State previousState, @Nonnull State currentState) { + checkArgument(previousState instanceof ComicState, "previous state must be a comic state"); + checkArgument(currentState instanceof ComicState, "current state must be a comic state"); + + ComicState previousComicState = (ComicState) previousState; + ComicState currentComicState = (ComicState) currentState; + + List allComics = new ArrayList<>(previousComicState.comics()); + Set newComics = new HashSet<>(); + + for (Comic comic : currentComicState) { + if (!allComics.contains(comic)) { + allComics.add(comic); + newComics.add(comic); + } + } + + return new ComicState(allComics, newComics); + } + +} diff --git a/src/main/java/net/pterodactylus/rhynodge/mergers/EpisodeMerger.java b/src/main/java/net/pterodactylus/rhynodge/mergers/EpisodeMerger.java new file mode 100644 index 0000000..9101c36 --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/mergers/EpisodeMerger.java @@ -0,0 +1,78 @@ +/* + * Rhynodge - EpisodeMerger.java - Copyright © 2013–2021 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.pterodactylus.rhynodge.mergers; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; + +import javax.annotation.Nonnull; + +import net.pterodactylus.rhynodge.Merger; +import net.pterodactylus.rhynodge.State; +import net.pterodactylus.rhynodge.states.EpisodeState; +import net.pterodactylus.rhynodge.states.EpisodeState.Episode; +import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile; + +import static com.google.common.base.Preconditions.checkState; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; + +/** + * {@link Merger} implementation that merges two {@link EpisodeState}s. + * + * @author David ‘Bombe’ Roden + */ +public class EpisodeMerger implements Merger { + + /** + * {@inheritDoc} + */ + @Nonnull + @Override + public State mergeStates(@Nonnull State previousState, @Nonnull State currentState) { + checkState(currentState instanceof EpisodeState, "currentState is not a EpisodeState but a %s", currentState.getClass().getName()); + checkState(previousState instanceof EpisodeState, "previousState is not a EpisodeState but a %s", currentState.getClass().getName()); + + Collection newEpisodes = new HashSet<>(); + Collection changedEpisodes = new HashSet<>(); + Collection newTorrentFiles = new HashSet<>(); + Map allEpisodes = ((EpisodeState) previousState).episodes().stream().collect(toMap(identity(), identity())); + for (Episode episode : ((EpisodeState) currentState).episodes()) { + if (!allEpisodes.containsKey(episode)) { + allEpisodes.put(episode, episode); + newEpisodes.add(episode); + } + Episode existingEpisode = allEpisodes.get(episode); + for (TorrentFile torrentFile : new ArrayList<>(episode.torrentFiles())) { + int oldSize = existingEpisode.torrentFiles().size(); + existingEpisode.addTorrentFile(torrentFile); + int newSize = existingEpisode.torrentFiles().size(); + if (oldSize != newSize) { + newTorrentFiles.add(torrentFile); + } + if (!newEpisodes.contains(existingEpisode) && (oldSize != newSize)) { + changedEpisodes.add(existingEpisode); + } + } + } + return new EpisodeState(allEpisodes.values(), newEpisodes, changedEpisodes, newTorrentFiles); + } + +} diff --git a/src/main/java/net/pterodactylus/rhynodge/mergers/TorrentMerger.java b/src/main/java/net/pterodactylus/rhynodge/mergers/TorrentMerger.java new file mode 100644 index 0000000..f6a75a8 --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/mergers/TorrentMerger.java @@ -0,0 +1,60 @@ +/* + * Rhynodge - TorrentMerger.java - Copyright © 2013–2021 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.pterodactylus.rhynodge.mergers; + +import java.util.HashSet; +import java.util.Set; +import javax.annotation.Nonnull; + +import net.pterodactylus.rhynodge.Merger; +import net.pterodactylus.rhynodge.State; +import net.pterodactylus.rhynodge.states.TorrentState; +import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile; + +import static com.google.common.base.Preconditions.checkState; + +/** + * {@link Merger} implementation that merges two {@link TorrentState}s, taking + * careful note of which {@link TorrentFile}s appear in the current + * {@link TorrentState} but not in the previous one. + * + * @author David ‘Bombe’ Roden + */ +public class TorrentMerger implements Merger { + + /** + * {@inheritDoc} + */ + @Nonnull + @Override + public State mergeStates(@Nonnull State previousState, @Nonnull State currentState) { + checkState(currentState instanceof TorrentState, "currentState is not a TorrentState but a %s", currentState.getClass().getName()); + checkState(previousState instanceof TorrentState, "previousState is not a TorrentState but a %s", currentState.getClass().getName()); + + Set allTorrentFiles = new HashSet<>(((TorrentState) previousState).torrentFiles()); + Set newTorrentFiles = new HashSet<>(); + for (TorrentFile torrentFile : (TorrentState) currentState) { + if (allTorrentFiles.add(torrentFile)) { + newTorrentFiles.add(torrentFile); + } + } + + return new TorrentState(allTorrentFiles, newTorrentFiles); + } + +} diff --git a/src/main/java/net/pterodactylus/rhynodge/output/Output.java b/src/main/java/net/pterodactylus/rhynodge/output/Output.java index 853c9ce..3e9d904 100644 --- a/src/main/java/net/pterodactylus/rhynodge/output/Output.java +++ b/src/main/java/net/pterodactylus/rhynodge/output/Output.java @@ -17,10 +17,10 @@ package net.pterodactylus.rhynodge.output; -import net.pterodactylus.rhynodge.Trigger; +import net.pterodactylus.rhynodge.State; /** - * Defines the output of a {@link Trigger}. As different output has to be + * Defines the output of a {@link State}. As different output has to be * generated for different media, the {@link #text(String)} method takes as * an argument the MIME type of the desired output. * @@ -44,7 +44,7 @@ public interface Output { * * @param mimeType * The MIME type of the text (“text/plain” and “text/html” should - * be supported by all {@link Trigger}s) + * be supported by all {@link State}s) * @return The text for the given MIME type, or {@code null} if there is no * text defined for the given MIME type */ diff --git a/src/main/java/net/pterodactylus/rhynodge/package-info.java b/src/main/java/net/pterodactylus/rhynodge/package-info.java index 2e7d9df..a58164d 100644 --- a/src/main/java/net/pterodactylus/rhynodge/package-info.java +++ b/src/main/java/net/pterodactylus/rhynodge/package-info.java @@ -3,7 +3,7 @@ *

* A {@link net.pterodactylus.rhynodge.Reaction} consists of three different * elements: a {@link net.pterodactylus.rhynodge.Query}, a - * {@link net.pterodactylus.rhynodge.Trigger}, and an + * {@link net.pterodactylus.rhynodge.Merger}, and an * {@link net.pterodactylus.rhynodge.Action}. *

* A {@code Query} retrieves the current state of a system; this can simply be @@ -13,8 +13,10 @@ *

* After a {@code Query} retrieved the current * {@link net.pterodactylus.rhynodge.State} of a system, this state and the - * previously retrieved state are handed in to a {@code Trigger}. The trigger - * then decides whether the state of the system can be considered a change. + * previously retrieved state are handed in to a {@code Merger}. The merger + * takes care of merging the two states in a way that the new state can + * {@link net.pterodactylus.rhynodge.State#triggered() decide} whether a + * noteworthy change has occured. *

* If a system has been found to trigger, an {@code Action} is executed. It * performs arbitrary actions and can use both the current state and the diff --git a/src/main/java/net/pterodactylus/rhynodge/states/ComicState.java b/src/main/java/net/pterodactylus/rhynodge/states/ComicState.java index e1eff9a..0e661bc 100644 --- a/src/main/java/net/pterodactylus/rhynodge/states/ComicState.java +++ b/src/main/java/net/pterodactylus/rhynodge/states/ComicState.java @@ -68,6 +68,11 @@ public class ComicState extends AbstractState implements Iterable { return comics.isEmpty(); } + @Override + public boolean triggered() { + return !newComics.isEmpty(); + } + public List comics() { return comics; } diff --git a/src/main/java/net/pterodactylus/rhynodge/states/EpisodeState.java b/src/main/java/net/pterodactylus/rhynodge/states/EpisodeState.java index e022541..abb387d 100644 --- a/src/main/java/net/pterodactylus/rhynodge/states/EpisodeState.java +++ b/src/main/java/net/pterodactylus/rhynodge/states/EpisodeState.java @@ -90,6 +90,11 @@ public class EpisodeState extends AbstractState implements Iterable { return episodes.isEmpty(); } + @Override + public boolean triggered() { + return !newEpisodes.isEmpty() || !changedEpisodes.isEmpty() || !newTorrentFiles.isEmpty(); + } + /** * Returns all episodes contained in this state. * diff --git a/src/main/java/net/pterodactylus/rhynodge/states/TorrentState.java b/src/main/java/net/pterodactylus/rhynodge/states/TorrentState.java index f2e9ae2..99cb9d1 100644 --- a/src/main/java/net/pterodactylus/rhynodge/states/TorrentState.java +++ b/src/main/java/net/pterodactylus/rhynodge/states/TorrentState.java @@ -91,6 +91,11 @@ public class TorrentState extends AbstractState implements Iterable return files.isEmpty(); } + @Override + public boolean triggered() { + return !newTorrentFiles.isEmpty(); + } + /** * Returns all torrent files of this state. * diff --git a/src/main/java/net/pterodactylus/rhynodge/triggers/AlwaysTrigger.java b/src/main/java/net/pterodactylus/rhynodge/triggers/AlwaysTrigger.java deleted file mode 100644 index 0018f50..0000000 --- a/src/main/java/net/pterodactylus/rhynodge/triggers/AlwaysTrigger.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Rhynodge - AlwaysTrigger.java - Copyright © 2013 David Roden - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.pterodactylus.rhynodge.triggers; - -import net.pterodactylus.rhynodge.State; -import net.pterodactylus.rhynodge.Trigger; - -/** - * {@link Trigger} implementation that always triggers. - * - * @author David ‘Bombe’ Roden - */ -public class AlwaysTrigger implements Trigger { - - private State currentState; - - /** - * {@inheritDoc} - *

- * This implementation returns the current state. - */ - @Override - public State mergeStates(State previousState, State currentState) { - this.currentState = currentState; - return currentState; - } - - /** - * {@inheritDoc} - *

- * This implementation always returns {@code true}. - */ - @Override - public boolean triggers() { - return true; - } - -} diff --git a/src/main/java/net/pterodactylus/rhynodge/triggers/NewComicTrigger.java b/src/main/java/net/pterodactylus/rhynodge/triggers/NewComicTrigger.java deleted file mode 100644 index 16560e2..0000000 --- a/src/main/java/net/pterodactylus/rhynodge/triggers/NewComicTrigger.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * rhynodge - NewComicTrigger.java - Copyright © 2013 David Roden - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.pterodactylus.rhynodge.triggers; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import net.pterodactylus.rhynodge.State; -import net.pterodactylus.rhynodge.Trigger; -import net.pterodactylus.rhynodge.states.ComicState; -import net.pterodactylus.rhynodge.states.ComicState.Comic; - -import static com.google.common.base.Preconditions.checkArgument; - -/** - * {@link Trigger} implementation that detects the presence of new {@link - * Comic}s in a {@link ComicState}. - * - * @author David ‘Bombe’ Roden - */ -public class NewComicTrigger implements Trigger { - - private boolean triggered = false; - - @Override - public State mergeStates(State previousState, State currentState) { - checkArgument(previousState instanceof ComicState, "previous state must be a comic state"); - checkArgument(currentState instanceof ComicState, "current state must be a comic state"); - - ComicState previousComicState = (ComicState) previousState; - ComicState currentComicState = (ComicState) currentState; - - List allComics = new ArrayList<>(previousComicState.comics()); - Set newComics = new HashSet<>(); - - for (Comic comic : currentComicState) { - if (!allComics.contains(comic)) { - allComics.add(comic); - newComics.add(comic); - triggered = true; - } - } - - return new ComicState(allComics, newComics); - } - - @Override - public boolean triggers() { - return triggered; - } - -} diff --git a/src/main/java/net/pterodactylus/rhynodge/triggers/NewEpisodeTrigger.java b/src/main/java/net/pterodactylus/rhynodge/triggers/NewEpisodeTrigger.java deleted file mode 100644 index 4b1d209..0000000 --- a/src/main/java/net/pterodactylus/rhynodge/triggers/NewEpisodeTrigger.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Rhynodge - NewEpisodeTrigger.java - Copyright © 2013 David Roden - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.pterodactylus.rhynodge.triggers; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; - -import net.pterodactylus.rhynodge.State; -import net.pterodactylus.rhynodge.Trigger; -import net.pterodactylus.rhynodge.states.EpisodeState; -import net.pterodactylus.rhynodge.states.EpisodeState.Episode; -import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile; - -import static com.google.common.base.Preconditions.checkState; -import static java.util.function.Function.identity; -import static java.util.stream.Collectors.toMap; - -/** - * {@link Trigger} implementation that compares two {@link EpisodeState}s for - * new and changed {@link Episode}s. - * - * @author David ‘Bombe’ Roden - */ -public class NewEpisodeTrigger implements Trigger { - - private boolean triggered = false; - - /** - * {@inheritDoc} - */ - @Override - public State mergeStates(State previousState, State currentState) { - checkState(currentState instanceof EpisodeState, "currentState is not a EpisodeState but a %s", currentState.getClass().getName()); - checkState(previousState instanceof EpisodeState, "previousState is not a EpisodeState but a %s", currentState.getClass().getName()); - - Collection newEpisodes = new HashSet<>(); - Collection changedEpisodes = new HashSet<>(); - Collection newTorrentFiles = new HashSet<>(); - Map allEpisodes = ((EpisodeState) previousState).episodes().stream().collect(toMap(identity(), identity())); - for (Episode episode : ((EpisodeState) currentState).episodes()) { - if (!allEpisodes.containsKey(episode)) { - allEpisodes.put(episode, episode); - newEpisodes.add(episode); - triggered = true; - } - Episode existingEpisode = allEpisodes.get(episode); - for (TorrentFile torrentFile : new ArrayList<>(episode.torrentFiles())) { - int oldSize = existingEpisode.torrentFiles().size(); - existingEpisode.addTorrentFile(torrentFile); - int newSize = existingEpisode.torrentFiles().size(); - if (oldSize != newSize) { - newTorrentFiles.add(torrentFile); - } - if (!newEpisodes.contains(existingEpisode) && (oldSize != newSize)) { - changedEpisodes.add(existingEpisode); - } - } - } - return new EpisodeState(allEpisodes.values(), newEpisodes, changedEpisodes, newTorrentFiles); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean triggers() { - return triggered; - } - -} diff --git a/src/main/java/net/pterodactylus/rhynodge/triggers/NewTorrentTrigger.java b/src/main/java/net/pterodactylus/rhynodge/triggers/NewTorrentTrigger.java deleted file mode 100644 index 0ff193c..0000000 --- a/src/main/java/net/pterodactylus/rhynodge/triggers/NewTorrentTrigger.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Rhynodge - NewTorrentTrigger.java - Copyright © 2013 David Roden - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.pterodactylus.rhynodge.triggers; - -import java.util.HashSet; -import java.util.Set; - -import net.pterodactylus.rhynodge.State; -import net.pterodactylus.rhynodge.Trigger; -import net.pterodactylus.rhynodge.states.TorrentState; -import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile; - -import static com.google.common.base.Preconditions.checkState; - -/** - * {@link Trigger} implementation that is triggered by {@link TorrentFile}s that - * appear in the current {@link TorrentState} but not in the previous one. - * - * @author David ‘Bombe’ Roden - */ -public class NewTorrentTrigger implements Trigger { - - private boolean triggered = false; - - // - // TRIGGER METHODS - // - - /** - * {@inheritDoc} - */ - @Override - public State mergeStates(State previousState, State currentState) { - checkState(currentState instanceof TorrentState, "currentState is not a TorrentState but a %s", currentState.getClass().getName()); - checkState(previousState instanceof TorrentState, "previousState is not a TorrentState but a %s", currentState.getClass().getName()); - - Set allTorrentFiles = new HashSet<>(((TorrentState) previousState).torrentFiles()); - Set newTorrentFiles = new HashSet<>(); - for (TorrentFile torrentFile : (TorrentState) currentState) { - if (allTorrentFiles.add(torrentFile)) { - newTorrentFiles.add(torrentFile); - triggered = true; - } - } - - return new TorrentState(allTorrentFiles, newTorrentFiles); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean triggers() { - return triggered; - } - -} diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/AbstruseGooseWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/AbstruseGooseWatcher.java index 1355408..0fd1105 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/AbstruseGooseWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/AbstruseGooseWatcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.AbstruseGooseComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new Abstruse Goose comics. @@ -33,7 +33,7 @@ import net.pterodactylus.rhynodge.triggers.NewComicTrigger; public class AbstruseGooseWatcher extends DefaultWatcher { public AbstruseGooseWatcher() { - super(new HttpQuery("http://abstrusegoose.com/"), Arrays.asList(new HtmlFilter(), new AbstruseGooseComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://abstrusegoose.com/"), Arrays.asList(new HtmlFilter(), new AbstruseGooseComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/Collar6Watcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/Collar6Watcher.java index fedcc7f..804160b 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/Collar6Watcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/Collar6Watcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.Collar6ComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new Collar 6 comics. @@ -34,7 +34,7 @@ public class Collar6Watcher extends DefaultWatcher { /** Creates a new watcher for Cyanide and Happiness comics. */ public Collar6Watcher() { - super(new HttpQuery("http://collar6.com/"), Arrays.asList(new HtmlFilter(), new Collar6ComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://collar6.com/"), Arrays.asList(new HtmlFilter(), new Collar6ComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/CtrlAltDelWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/CtrlAltDelWatcher.java index ff5db70..ad93e1f 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/CtrlAltDelWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/CtrlAltDelWatcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.CtrlAltDelComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new Ctrl Alt Del comics. @@ -34,7 +34,7 @@ public class CtrlAltDelWatcher extends DefaultWatcher { /** Creates a new watcher for Cyanide and Happiness comics. */ public CtrlAltDelWatcher() { - super(new HttpQuery("http://www.cad-comic.com/cad/"), Arrays.asList(new HtmlFilter(), new CtrlAltDelComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://www.cad-comic.com/cad/"), Arrays.asList(new HtmlFilter(), new CtrlAltDelComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/CyanideAndHappinessWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/CyanideAndHappinessWatcher.java index 11971f6..331ec4b 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/CyanideAndHappinessWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/CyanideAndHappinessWatcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.CyanideAndHappinessComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new Cyanide and Happiness @@ -35,7 +35,7 @@ public class CyanideAndHappinessWatcher extends DefaultWatcher { /** Creates a new watcher for Cyanide and Happiness comics. */ public CyanideAndHappinessWatcher() { - super(new HttpQuery("http://www.explosm.net/comics/new/"), Arrays.asList(new HtmlFilter(), new CyanideAndHappinessComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://www.explosm.net/comics/new/"), Arrays.asList(new HtmlFilter(), new CyanideAndHappinessComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/DefaultWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/DefaultWatcher.java index fb6b218..9dc2930 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/DefaultWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/DefaultWatcher.java @@ -22,8 +22,8 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.Watcher; +import net.pterodactylus.rhynodge.Merger; /** * Abstract base implementation of a {@link Watcher}. @@ -38,8 +38,8 @@ public class DefaultWatcher implements Watcher { /** The filters of the watcher. */ private final List filters = new ArrayList(); - /** The trigger of the watcher. */ - private final Trigger trigger; + /** The merger of the watcher. */ + private final Merger merger; /** * Creates a new default watcher. @@ -48,13 +48,13 @@ public class DefaultWatcher implements Watcher { * The query of the watcher * @param filters * The filters of the watcher - * @param trigger - * The trigger of the watcher + * @param merger + * The merger of the watcher */ - protected DefaultWatcher(Query query, List filters, Trigger trigger) { + protected DefaultWatcher(Query query, List filters, Merger merger) { this.query = query; this.filters.addAll(filters); - this.trigger = trigger; + this.merger = merger; } // @@ -77,12 +77,8 @@ public class DefaultWatcher implements Watcher { return filters; } - /** - * {@inheritDoc} - */ - @Override - public Trigger trigger() { - return trigger; + public Merger merger() { + return merger; } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/DrugsAndWiresWatcher.kt b/src/main/java/net/pterodactylus/rhynodge/watchers/DrugsAndWiresWatcher.kt index 98f5c5c..08d7d8f 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/DrugsAndWiresWatcher.kt +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/DrugsAndWiresWatcher.kt @@ -2,11 +2,11 @@ package net.pterodactylus.rhynodge.watchers import net.pterodactylus.rhynodge.filters.HtmlFilter import net.pterodactylus.rhynodge.filters.comics.DrugsAndWiresComicFilter +import net.pterodactylus.rhynodge.mergers.ComicMerger import net.pterodactylus.rhynodge.queries.HttpQuery -import net.pterodactylus.rhynodge.triggers.NewComicTrigger -class DrugsAndWiresWatcher: DefaultWatcher(query, filters, trigger) +class DrugsAndWiresWatcher: DefaultWatcher(query, filters, merger) private val query = HttpQuery("https://www.drugsandwires.fail/") private val filters = listOf(HtmlFilter(), DrugsAndWiresComicFilter()) -private val trigger = NewComicTrigger() +private val merger = ComicMerger() diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/GeneralProtectionFaultWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/GeneralProtectionFaultWatcher.java index 1bb999c..f57762c 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/GeneralProtectionFaultWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/GeneralProtectionFaultWatcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.GeneralProtectionFaultComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new General Protection Fault @@ -35,7 +35,7 @@ public class GeneralProtectionFaultWatcher extends DefaultWatcher { /** Creates a new watcher for Cyanide and Happiness comics. */ public GeneralProtectionFaultWatcher() { - super(new HttpQuery("http://www.gpf-comics.com/"), Arrays.asList(new HtmlFilter(), new GeneralProtectionFaultComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://www.gpf-comics.com/"), Arrays.asList(new HtmlFilter(), new GeneralProtectionFaultComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/GirlGeniusWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/GirlGeniusWatcher.java index dd9703f..e1aa4a2 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/GirlGeniusWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/GirlGeniusWatcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.GirlGeniusComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new Genius Girl comics. @@ -34,7 +34,7 @@ public class GirlGeniusWatcher extends DefaultWatcher { /** Creates a new watcher for Cyanide and Happiness comics. */ public GirlGeniusWatcher() { - super(new HttpQuery("http://www.girlgeniusonline.com/comic.php"), Arrays.asList(new HtmlFilter(), new GirlGeniusComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://www.girlgeniusonline.com/comic.php"), Arrays.asList(new HtmlFilter(), new GirlGeniusComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/HeldentageWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/HeldentageWatcher.java index 19a8513..593f8ff 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/HeldentageWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/HeldentageWatcher.java @@ -5,8 +5,8 @@ import static java.util.Arrays.asList; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.HeldentageFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new “Heldentage” comics. @@ -16,7 +16,7 @@ import net.pterodactylus.rhynodge.triggers.NewComicTrigger; public class HeldentageWatcher extends DefaultWatcher { public HeldentageWatcher() { - super(new HttpQuery("http://www.der-flix.de/"), asList(new HtmlFilter(), new HeldentageFilter()), new NewComicTrigger()); + super(new HttpQuery("http://www.der-flix.de/"), asList(new HtmlFilter(), new HeldentageFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/KevinAndKellWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/KevinAndKellWatcher.java index f96f940..6826e25 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/KevinAndKellWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/KevinAndKellWatcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.KevinAndKellComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new Kevin and Kell comics. @@ -34,7 +34,7 @@ public class KevinAndKellWatcher extends DefaultWatcher { /** Creates a new watcher for Cyanide and Happiness comics. */ public KevinAndKellWatcher() { - super(new HttpQuery("http://www.kevinandkell.com/"), Arrays.asList(new HtmlFilter(), new KevinAndKellComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://www.kevinandkell.com/"), Arrays.asList(new HtmlFilter(), new KevinAndKellComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/KickAssTorrentsEpisodeWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/KickAssTorrentsEpisodeWatcher.java index ee8c1f3..0fec686 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/KickAssTorrentsEpisodeWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/KickAssTorrentsEpisodeWatcher.java @@ -25,14 +25,13 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.EpisodeFilter; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.SizeBlacklistFilter; import net.pterodactylus.rhynodge.filters.torrents.KickAssTorrentsFilter; +import net.pterodactylus.rhynodge.mergers.EpisodeMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewEpisodeTrigger; import com.google.common.collect.ImmutableList; @@ -51,7 +50,7 @@ public class KickAssTorrentsEpisodeWatcher extends DefaultWatcher { * The terms to search for */ public KickAssTorrentsEpisodeWatcher(String searchTerms) { - super(createHttpQuery(searchTerms), createFilters(), createTrigger()); + super(createHttpQuery(searchTerms), createFilters(), new EpisodeMerger()); } // @@ -83,13 +82,4 @@ public class KickAssTorrentsEpisodeWatcher extends DefaultWatcher { return ImmutableList.of(new HtmlFilter(), new KickAssTorrentsFilter(), createDefaultBlacklistFilter(), new SizeBlacklistFilter(), new EpisodeFilter()); } - /** - * Creates the trigger of the watcher. - * - * @return The trigger of the watcher - */ - private static Trigger createTrigger() { - return new NewEpisodeTrigger(); - } - } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/KickAssTorrentsWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/KickAssTorrentsWatcher.java index 6fa449d..231c086 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/KickAssTorrentsWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/KickAssTorrentsWatcher.java @@ -25,13 +25,12 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.SizeBlacklistFilter; import net.pterodactylus.rhynodge.filters.torrents.KickAssTorrentsFilter; +import net.pterodactylus.rhynodge.mergers.TorrentMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewTorrentTrigger; import com.google.common.collect.ImmutableList; @@ -49,7 +48,7 @@ public class KickAssTorrentsWatcher extends DefaultWatcher { * The terms to search for */ public KickAssTorrentsWatcher(String searchTerms) { - super(createHttpQuery(searchTerms), createFilters(), createTrigger()); + super(createHttpQuery(searchTerms), createFilters(), new TorrentMerger()); } // @@ -81,13 +80,4 @@ public class KickAssTorrentsWatcher extends DefaultWatcher { return ImmutableList.of(new HtmlFilter(), new KickAssTorrentsFilter(), createDefaultBlacklistFilter(), new SizeBlacklistFilter()); } - /** - * Creates the trigger of the watcher. - * - * @return The trigger of the watcher - */ - private static Trigger createTrigger() { - return new NewTorrentTrigger(); - } - } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/LeastICouldDoWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/LeastICouldDoWatcher.java index d88f574..13d48c9 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/LeastICouldDoWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/LeastICouldDoWatcher.java @@ -25,8 +25,8 @@ import net.pterodactylus.rhynodge.filters.ExtractUrlFilter; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.HttpQueryFilter; import net.pterodactylus.rhynodge.filters.comics.LeastICouldDoComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; @@ -43,7 +43,7 @@ public class LeastICouldDoWatcher extends DefaultWatcher { /** Creates a new “Least I Could Do” watcher. */ public LeastICouldDoWatcher() { - super(new HttpQuery("http://www.leasticoulddo.com/"), createFilters(), new NewComicTrigger()); + super(new HttpQuery("http://www.leasticoulddo.com/"), createFilters(), new ComicMerger()); } // diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/PirateBayEpisodeWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/PirateBayEpisodeWatcher.java index 4fec730..eed6c90 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/PirateBayEpisodeWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/PirateBayEpisodeWatcher.java @@ -25,15 +25,14 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.EpisodeFilter; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.SizeBlacklistFilter; import net.pterodactylus.rhynodge.filters.torrents.PirateBayFilter; +import net.pterodactylus.rhynodge.mergers.EpisodeMerger; import net.pterodactylus.rhynodge.queries.FallbackQuery; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewEpisodeTrigger; import com.google.common.collect.ImmutableList; @@ -51,7 +50,7 @@ public class PirateBayEpisodeWatcher extends DefaultWatcher { * The terms to search for */ public PirateBayEpisodeWatcher(String searchTerms, String proxy) { - super(createHttpQuery(searchTerms, extractProxyHost(proxy), extractProxyPort(proxy)), createFilters(), createTrigger()); + super(createHttpQuery(searchTerms, extractProxyHost(proxy), extractProxyPort(proxy)), createFilters(), new EpisodeMerger()); } private static String extractProxyHost(String proxy) { @@ -87,13 +86,4 @@ public class PirateBayEpisodeWatcher extends DefaultWatcher { return ImmutableList.of(new HtmlFilter(), new PirateBayFilter(), createDefaultBlacklistFilter(), new SizeBlacklistFilter(), new EpisodeFilter()); } - /** - * Creates the trigger of the watcher. - * - * @return The trigger of the watcher - */ - private static Trigger createTrigger() { - return new NewEpisodeTrigger(); - } - } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/PirateBayWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/PirateBayWatcher.java index 1a62e80..2254fba 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/PirateBayWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/PirateBayWatcher.java @@ -25,14 +25,13 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.SizeBlacklistFilter; import net.pterodactylus.rhynodge.filters.torrents.PirateBayFilter; +import net.pterodactylus.rhynodge.mergers.TorrentMerger; import net.pterodactylus.rhynodge.queries.FallbackQuery; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewTorrentTrigger; import com.google.common.collect.ImmutableList; @@ -50,7 +49,7 @@ public class PirateBayWatcher extends DefaultWatcher { * The terms to search for */ public PirateBayWatcher(String searchTerms, String proxy) { - super(createHttpQuery(searchTerms, extractProxyHost(proxy), extractProxyPort(proxy)), createFilters(), createTrigger()); + super(createHttpQuery(searchTerms, extractProxyHost(proxy), extractProxyPort(proxy)), createFilters(), new TorrentMerger()); } private static String extractProxyHost(String proxy) { @@ -93,13 +92,4 @@ public class PirateBayWatcher extends DefaultWatcher { return ImmutableList.of(new HtmlFilter(), new PirateBayFilter(), createDefaultBlacklistFilter(), new SizeBlacklistFilter()); } - /** - * Creates the trigger of the watcher. - * - * @return The trigger of the watcher - */ - private static Trigger createTrigger() { - return new NewTorrentTrigger(); - } - } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/PoorlyDrawnLinesWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/PoorlyDrawnLinesWatcher.java index dc1f33c..0ea2849 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/PoorlyDrawnLinesWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/PoorlyDrawnLinesWatcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.PoorlyDrawnLinesComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new Poorly Drawn Lines @@ -35,7 +35,7 @@ public class PoorlyDrawnLinesWatcher extends DefaultWatcher { /** Creates a new watcher for Cyanide and Happiness comics. */ public PoorlyDrawnLinesWatcher() { - super(new HttpQuery("http://poorlydrawnlines.com/"), Arrays.asList(new HtmlFilter(), new PoorlyDrawnLinesComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://poorlydrawnlines.com/"), Arrays.asList(new HtmlFilter(), new PoorlyDrawnLinesComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/SaturdayMorningBreakfastCerealWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/SaturdayMorningBreakfastCerealWatcher.java index 769d1dd..3e90a00 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/SaturdayMorningBreakfastCerealWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/SaturdayMorningBreakfastCerealWatcher.java @@ -22,8 +22,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.SaturdayMorningBreakfastCerealComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link Watcher} implementation that watches for new Saturday Morning @@ -35,7 +35,7 @@ public class SaturdayMorningBreakfastCerealWatcher extends DefaultWatcher { /** Creates a new watcher for Cyanide and Happiness comics. */ public SaturdayMorningBreakfastCerealWatcher() { - super(new HttpQuery("http://www.smbc-comics.com/"), Arrays.asList(new HtmlFilter(), new SaturdayMorningBreakfastCerealComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://www.smbc-comics.com/"), Arrays.asList(new HtmlFilter(), new SaturdayMorningBreakfastCerealComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/SavoyTicketWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/SavoyTicketWatcher.java index 0a67f6f..e797d18 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/SavoyTicketWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/SavoyTicketWatcher.java @@ -5,8 +5,8 @@ import static java.util.Arrays.asList; import net.pterodactylus.rhynodge.Watcher; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.webpages.savoy.SavoyTicketsFilter; +import net.pterodactylus.rhynodge.mergers.LastStateMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.AlwaysTrigger; /** * {@link Watcher} implementation that shows tickets sold in the Savoy theatre. @@ -22,7 +22,7 @@ public class SavoyTicketWatcher extends DefaultWatcher { new HtmlFilter(), new SavoyTicketsFilter() ), - new AlwaysTrigger() + new LastStateMerger() ); } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/ScandinaviaAndTheWorldWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/ScandinaviaAndTheWorldWatcher.java index fdcae7d..cb7775f 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/ScandinaviaAndTheWorldWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/ScandinaviaAndTheWorldWatcher.java @@ -24,8 +24,8 @@ import net.pterodactylus.rhynodge.filters.ExtractUrlFilter; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.HttpQueryFilter; import net.pterodactylus.rhynodge.filters.comics.ScandinaviaAndTheWorldComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; @@ -40,7 +40,7 @@ import org.jsoup.select.Elements; public class ScandinaviaAndTheWorldWatcher extends DefaultWatcher { public ScandinaviaAndTheWorldWatcher() { - super(new HttpQuery("http://satwcomic.com/"), createFilters(), new NewComicTrigger()); + super(new HttpQuery("http://satwcomic.com/"), createFilters(), new ComicMerger()); } private static List createFilters() { diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/SinfestWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/SinfestWatcher.java index b273004..914f614 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/SinfestWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/SinfestWatcher.java @@ -21,8 +21,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.SinfestComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link net.pterodactylus.rhynodge.Watcher} implementation that watches @@ -33,7 +33,7 @@ import net.pterodactylus.rhynodge.triggers.NewComicTrigger; public class SinfestWatcher extends DefaultWatcher { public SinfestWatcher() { - super(new HttpQuery("http://www.sinfest.net/"), Arrays.asList(new HtmlFilter(), new SinfestComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://www.sinfest.net/"), Arrays.asList(new HtmlFilter(), new SinfestComicFilter()), new ComicMerger()); } } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentHoundEpisodeWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentHoundEpisodeWatcher.java index bc22f92..1a47ffa 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentHoundEpisodeWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentHoundEpisodeWatcher.java @@ -25,13 +25,12 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.filters.EpisodeFilter; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.SizeBlacklistFilter; import net.pterodactylus.rhynodge.filters.torrents.TorrentHoundFilter; +import net.pterodactylus.rhynodge.mergers.EpisodeMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewEpisodeTrigger; import com.google.common.collect.ImmutableList; @@ -50,7 +49,7 @@ public class TorrentHoundEpisodeWatcher extends DefaultWatcher { * The terms to search for */ public TorrentHoundEpisodeWatcher(String searchTerms) { - super(createHttpQuery(searchTerms), createFilters(), createTrigger()); + super(createHttpQuery(searchTerms), createFilters(), new EpisodeMerger()); } // @@ -82,13 +81,4 @@ public class TorrentHoundEpisodeWatcher extends DefaultWatcher { return ImmutableList.of(new HtmlFilter(), new TorrentHoundFilter(), createDefaultBlacklistFilter(), new SizeBlacklistFilter(), new EpisodeFilter()); } - /** - * Creates the trigger of the watcher. - * - * @return The trigger of the watcher - */ - private static Trigger createTrigger() { - return new NewEpisodeTrigger(); - } - } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentHoundWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentHoundWatcher.java index 4a9fba5..4df53a6 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentHoundWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentHoundWatcher.java @@ -25,12 +25,11 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.SizeBlacklistFilter; import net.pterodactylus.rhynodge.filters.torrents.TorrentHoundFilter; +import net.pterodactylus.rhynodge.mergers.TorrentMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewTorrentTrigger; import com.google.common.collect.ImmutableList; @@ -49,7 +48,7 @@ public class TorrentHoundWatcher extends DefaultWatcher { * The terms to search for */ public TorrentHoundWatcher(String searchTerms) { - super(createHttpQuery(searchTerms), createFilters(), createTrigger()); + super(createHttpQuery(searchTerms), createFilters(), new TorrentMerger()); } // @@ -81,13 +80,4 @@ public class TorrentHoundWatcher extends DefaultWatcher { return ImmutableList.of(new HtmlFilter(), new TorrentHoundFilter(), createDefaultBlacklistFilter(), new SizeBlacklistFilter()); } - /** - * Creates the trigger of the watcher. - * - * @return The trigger of the watcher - */ - private static Trigger createTrigger() { - return new NewTorrentTrigger(); - } - } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentzEuEpisodeWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentzEuEpisodeWatcher.java index 920d3bc..a212359 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentzEuEpisodeWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentzEuEpisodeWatcher.java @@ -25,13 +25,12 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; import net.pterodactylus.rhynodge.filters.EpisodeFilter; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.SizeBlacklistFilter; import net.pterodactylus.rhynodge.filters.torrents.TorrentzEuFilter; +import net.pterodactylus.rhynodge.mergers.EpisodeMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewEpisodeTrigger; import com.google.common.collect.ImmutableList; @@ -50,7 +49,7 @@ public class TorrentzEuEpisodeWatcher extends DefaultWatcher { * The terms to search for */ public TorrentzEuEpisodeWatcher(String searchTerms) { - super(createHttpQuery(searchTerms), createFilters(), createTrigger()); + super(createHttpQuery(searchTerms), createFilters(), new EpisodeMerger()); } // @@ -82,13 +81,4 @@ public class TorrentzEuEpisodeWatcher extends DefaultWatcher { return ImmutableList.of(new HtmlFilter(), new TorrentzEuFilter(), createDefaultBlacklistFilter(), new SizeBlacklistFilter(), new EpisodeFilter()); } - /** - * Creates the trigger of the watcher. - * - * @return The trigger of the watcher - */ - private static Trigger createTrigger() { - return new NewEpisodeTrigger(); - } - } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentzEuWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentzEuWatcher.java index a5192a3..a709d0d 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentzEuWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/TorrentzEuWatcher.java @@ -25,13 +25,11 @@ import java.util.List; import net.pterodactylus.rhynodge.Filter; import net.pterodactylus.rhynodge.Query; -import net.pterodactylus.rhynodge.Trigger; -import net.pterodactylus.rhynodge.filters.EpisodeFilter; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.SizeBlacklistFilter; import net.pterodactylus.rhynodge.filters.torrents.TorrentzEuFilter; +import net.pterodactylus.rhynodge.mergers.TorrentMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewEpisodeTrigger; import com.google.common.collect.ImmutableList; @@ -50,7 +48,7 @@ public class TorrentzEuWatcher extends DefaultWatcher { * The terms to search for */ public TorrentzEuWatcher(String searchTerms) { - super(createHttpQuery(searchTerms), createFilters(), createTrigger()); + super(createHttpQuery(searchTerms), createFilters(), new TorrentMerger()); } // @@ -82,13 +80,4 @@ public class TorrentzEuWatcher extends DefaultWatcher { return ImmutableList.of(new HtmlFilter(), new TorrentzEuFilter(), createDefaultBlacklistFilter(), new SizeBlacklistFilter()); } - /** - * Creates the trigger of the watcher. - * - * @return The trigger of the watcher - */ - private static Trigger createTrigger() { - return new NewEpisodeTrigger(); - } - } diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/XkcdWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/XkcdWatcher.java index 360652a..9829d82 100644 --- a/src/main/java/net/pterodactylus/rhynodge/watchers/XkcdWatcher.java +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/XkcdWatcher.java @@ -21,8 +21,8 @@ import java.util.Arrays; import net.pterodactylus.rhynodge.filters.HtmlFilter; import net.pterodactylus.rhynodge.filters.comics.XkcdComicFilter; +import net.pterodactylus.rhynodge.mergers.ComicMerger; import net.pterodactylus.rhynodge.queries.HttpQuery; -import net.pterodactylus.rhynodge.triggers.NewComicTrigger; /** * {@link net.pterodactylus.rhynodge.Watcher} implementation that watches XKCD @@ -34,7 +34,7 @@ public class XkcdWatcher extends DefaultWatcher { /** Creates a new XKCD watcher. */ public XkcdWatcher() { - super(new HttpQuery("http://xkcd.com/"), Arrays.asList(new HtmlFilter(), new XkcdComicFilter()), new NewComicTrigger()); + super(new HttpQuery("http://xkcd.com/"), Arrays.asList(new HtmlFilter(), new XkcdComicFilter()), new ComicMerger()); } } diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/Merger.kt b/src/main/kotlin/net/pterodactylus/rhynodge/Merger.kt new file mode 100644 index 0000000..a9807bf --- /dev/null +++ b/src/main/kotlin/net/pterodactylus/rhynodge/Merger.kt @@ -0,0 +1,7 @@ +package net.pterodactylus.rhynodge + +interface Merger { + + fun mergeStates(previousState: State, currentState: State): State + +} diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/mergers/LastStateMerger.kt b/src/main/kotlin/net/pterodactylus/rhynodge/mergers/LastStateMerger.kt new file mode 100644 index 0000000..fe1fb37 --- /dev/null +++ b/src/main/kotlin/net/pterodactylus/rhynodge/mergers/LastStateMerger.kt @@ -0,0 +1,13 @@ +package net.pterodactylus.rhynodge.mergers + +import net.pterodactylus.rhynodge.Merger +import net.pterodactylus.rhynodge.State + +/** + * [Merger] implementation that always returns the current state. + */ +class LastStateMerger : Merger { + + override fun mergeStates(previousState: State, currentState: State) = currentState + +} diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/watchers/BusinessCatWatcher.kt b/src/main/kotlin/net/pterodactylus/rhynodge/watchers/BusinessCatWatcher.kt index 94fe96d..e6d288a 100644 --- a/src/main/kotlin/net/pterodactylus/rhynodge/watchers/BusinessCatWatcher.kt +++ b/src/main/kotlin/net/pterodactylus/rhynodge/watchers/BusinessCatWatcher.kt @@ -2,11 +2,11 @@ package net.pterodactylus.rhynodge.watchers import net.pterodactylus.rhynodge.filters.HtmlFilter import net.pterodactylus.rhynodge.filters.comics.BusinessCatComicFilter +import net.pterodactylus.rhynodge.mergers.ComicMerger import net.pterodactylus.rhynodge.queries.HttpQuery -import net.pterodactylus.rhynodge.triggers.NewComicTrigger -class BusinessCatWatcher : DefaultWatcher(query, filters, trigger) +class BusinessCatWatcher : DefaultWatcher(query, filters, merger) private val query = HttpQuery("https://www.businesscatcomic.com/") private val filters = listOf(HtmlFilter(), BusinessCatComicFilter()) -private val trigger = NewComicTrigger() +private val merger = ComicMerger() diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/watchers/QuestionableContentWatcher.kt b/src/main/kotlin/net/pterodactylus/rhynodge/watchers/QuestionableContentWatcher.kt index 417e2c2..dfa5cb0 100644 --- a/src/main/kotlin/net/pterodactylus/rhynodge/watchers/QuestionableContentWatcher.kt +++ b/src/main/kotlin/net/pterodactylus/rhynodge/watchers/QuestionableContentWatcher.kt @@ -18,11 +18,11 @@ package net.pterodactylus.rhynodge.watchers import net.pterodactylus.rhynodge.filters.HtmlFilter import net.pterodactylus.rhynodge.filters.comics.QuestionableContentComicFilter +import net.pterodactylus.rhynodge.mergers.ComicMerger import net.pterodactylus.rhynodge.queries.HttpQuery -import net.pterodactylus.rhynodge.triggers.NewComicTrigger -class QuestionableContentWatcher : DefaultWatcher(query, filters, trigger) +class QuestionableContentWatcher : DefaultWatcher(query, filters, merger) private val query = HttpQuery("https://www.questionablecontent.net/") private val filters = listOf(HtmlFilter(), QuestionableContentComicFilter()) -private val trigger = NewComicTrigger() +private val merger = ComicMerger() diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/watchers/SoggyCardboardWatcher.kt b/src/main/kotlin/net/pterodactylus/rhynodge/watchers/SoggyCardboardWatcher.kt index e68e218..80edc4b 100644 --- a/src/main/kotlin/net/pterodactylus/rhynodge/watchers/SoggyCardboardWatcher.kt +++ b/src/main/kotlin/net/pterodactylus/rhynodge/watchers/SoggyCardboardWatcher.kt @@ -2,11 +2,11 @@ package net.pterodactylus.rhynodge.watchers import net.pterodactylus.rhynodge.filters.HtmlFilter import net.pterodactylus.rhynodge.filters.comics.SoggyCardboardComicFilter +import net.pterodactylus.rhynodge.mergers.ComicMerger import net.pterodactylus.rhynodge.queries.HttpQuery -import net.pterodactylus.rhynodge.triggers.NewComicTrigger -class SoggyCardboardWatcher : DefaultWatcher(query, filters, trigger) +class SoggyCardboardWatcher : DefaultWatcher(query, filters, merger) private val query = HttpQuery("http://www.soggycardboard.com/") private val filters = listOf(HtmlFilter(), SoggyCardboardComicFilter()) -private val trigger = NewComicTrigger() +private val merger = ComicMerger() diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/watchers/TheMonsterUnderTheBedWatcher.kt b/src/main/kotlin/net/pterodactylus/rhynodge/watchers/TheMonsterUnderTheBedWatcher.kt index 214bfb9..a596d12 100644 --- a/src/main/kotlin/net/pterodactylus/rhynodge/watchers/TheMonsterUnderTheBedWatcher.kt +++ b/src/main/kotlin/net/pterodactylus/rhynodge/watchers/TheMonsterUnderTheBedWatcher.kt @@ -2,11 +2,11 @@ package net.pterodactylus.rhynodge.watchers import net.pterodactylus.rhynodge.filters.* import net.pterodactylus.rhynodge.filters.comics.* +import net.pterodactylus.rhynodge.mergers.ComicMerger import net.pterodactylus.rhynodge.queries.* -import net.pterodactylus.rhynodge.triggers.* -class TheMonsterUnderTheBedWatcher : DefaultWatcher(query, filters, trigger) +class TheMonsterUnderTheBedWatcher : DefaultWatcher(query, filters, merger) private val query = HttpQuery("http://themonsterunderthebed.net/") private val filters = listOf(HtmlFilter(), TheMonsterUnderTheBedFilter()) -private val trigger = NewComicTrigger() +private val merger = ComicMerger() diff --git a/src/main/resources/chains/kickasstorrents-example.json b/src/main/resources/chains/kickasstorrents-example.json index 32bc1a2..febdfa5 100644 --- a/src/main/resources/chains/kickasstorrents-example.json +++ b/src/main/resources/chains/kickasstorrents-example.json @@ -25,9 +25,9 @@ } ], - "trigger": + "merger": { - "class": "NewEpisodeTrigger" + "class": "EpisodeMerger" }, "action": diff --git a/src/main/resources/chains/thepiratebay-example.json b/src/main/resources/chains/thepiratebay-example.json index 09e07e1..78a892f 100644 --- a/src/main/resources/chains/thepiratebay-example.json +++ b/src/main/resources/chains/thepiratebay-example.json @@ -22,9 +22,9 @@ } ], - "trigger": + "merger": { - "class": "NewTorrentTrigger" + "class": "TorrentMerger" }, "action": diff --git a/src/test/java/net/pterodactylus/rhynodge/ReactionTest.java b/src/test/java/net/pterodactylus/rhynodge/ReactionTest.java index 4ddf3ae..c30013f 100644 --- a/src/test/java/net/pterodactylus/rhynodge/ReactionTest.java +++ b/src/test/java/net/pterodactylus/rhynodge/ReactionTest.java @@ -18,10 +18,10 @@ public class ReactionTest { private final Query query = mock(Query.class); private final Filter filter = mock(Filter.class); - private final Trigger trigger = mock(Trigger.class); + private final Merger merger = mock(Merger.class); private final Action action = mock(Action.class); - private final Reaction reactionWithoutFilters = new Reaction("without", query, trigger, action); - private final Reaction reactionWithFilters = new Reaction("with", query, asList(filter), trigger, action); + private final Reaction reactionWithoutFilters = new Reaction("without", query, merger, action); + private final Reaction reactionWithFilters = new Reaction("with", query, asList(filter), merger, action); @Test public void reactionStoresNameCorrectly() { @@ -42,9 +42,9 @@ public class ReactionTest { } @Test - public void reactionStoresTriggerCorrectly() { - assertThat(reactionWithoutFilters.trigger(), is(trigger)); - assertThat(reactionWithFilters.trigger(), is(trigger)); + public void reactionStoresMergerCorrectly() { + assertThat(reactionWithoutFilters.merger(), is(merger)); + assertThat(reactionWithFilters.merger(), is(merger)); } @Test diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/mergers/ComicMergerTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/mergers/ComicMergerTest.kt new file mode 100644 index 0000000..3f07181 --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/rhynodge/mergers/ComicMergerTest.kt @@ -0,0 +1,23 @@ +package net.pterodactylus.rhynodge.mergers + +import net.pterodactylus.rhynodge.states.ComicState +import net.pterodactylus.rhynodge.states.ComicState.Comic +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.contains +import org.junit.Test + +class ComicMergerTest { + + private val comicMerger = ComicMerger() + + @Test + fun `comic merger does not reorder comics`() { + val oldComicState = ComicState(generateListOfComics()) + val newComicState = ComicState(generateListOfComics().plusElement(Comic("new 1"))) + val mergedComicState = comicMerger.mergeStates(oldComicState, newComicState) as ComicState + assertThat(mergedComicState.comics(), contains(*generateListOfComics().plusElement(Comic("new 1")).toTypedArray())) + } + +} + +private fun generateListOfComics(): List = (1..40).map { Comic("comic $it") } diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/mergers/LastStateMergerTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/mergers/LastStateMergerTest.kt new file mode 100644 index 0000000..6046bb3 --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/rhynodge/mergers/LastStateMergerTest.kt @@ -0,0 +1,20 @@ +package net.pterodactylus.rhynodge.mergers + +import net.pterodactylus.rhynodge.State +import net.pterodactylus.rhynodge.states.StateManagerTest.TestState +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.sameInstance +import org.junit.Test + +class LastStateMergerTest { + + @Test + fun `merging states returns the current state`() { + assertThat(merger.mergeStates(previousState, successfulState), sameInstance(successfulState)) + } + + private val merger = LastStateMerger() + private val previousState = TestState() + private val successfulState: State = TestState() + +} diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/triggers/AlwaysTriggerTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/triggers/AlwaysTriggerTest.kt deleted file mode 100644 index 6945a0e..0000000 --- a/src/test/kotlin/net/pterodactylus/rhynodge/triggers/AlwaysTriggerTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.pterodactylus.rhynodge.triggers - -import net.pterodactylus.rhynodge.State -import net.pterodactylus.rhynodge.states.FailedState -import net.pterodactylus.rhynodge.states.StateManagerTest.TestState -import org.hamcrest.MatcherAssert.assertThat -import org.hamcrest.Matchers.equalTo -import org.hamcrest.Matchers.sameInstance -import org.junit.Test - -class AlwaysTriggerTest { - - @Test - fun `merging states returns the current state`() { - assertThat(trigger.mergeStates(previousState, successfulState), sameInstance(successfulState)) - } - - @Test - fun `successful state triggers`() { - trigger.mergeStates(previousState, successfulState) - assertThat(trigger.triggers(), equalTo(true)) - } - - @Test - fun `failed state also triggers`() { - trigger.mergeStates(previousState, failedState) - assertThat(trigger.triggers(), equalTo(true)) - } - - private val trigger = AlwaysTrigger() - private val previousState = TestState() - private val successfulState: State = TestState() - private val failedState: State = FailedState() - -} diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/triggers/NewComicTriggerTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/triggers/NewComicTriggerTest.kt deleted file mode 100644 index 967a890..0000000 --- a/src/test/kotlin/net/pterodactylus/rhynodge/triggers/NewComicTriggerTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -package net.pterodactylus.rhynodge.triggers - -import net.pterodactylus.rhynodge.states.ComicState -import net.pterodactylus.rhynodge.states.ComicState.Comic -import org.hamcrest.MatcherAssert.assertThat -import org.hamcrest.Matchers.contains -import org.hamcrest.Matchers.equalTo -import org.junit.Test - -class NewComicTriggerTest { - - private val newComicTrigger = NewComicTrigger() - - @Test - fun `comic trigger recognizes there are no new comic`() { - val oldComicState = ComicState(generateListOfComics()) - val newComicState = ComicState(generateListOfComics()) - newComicTrigger.mergeStates(oldComicState, newComicState) - assertThat(newComicTrigger.triggers(), equalTo(false)) - } - - @Test - fun `comic trigger recognizes new comics`() { - val oldComicState = ComicState(generateListOfComics()) - val newComicState = ComicState(generateListOfComics().plusElement(Comic("new 1"))) - newComicTrigger.mergeStates(oldComicState, newComicState) - assertThat(newComicTrigger.triggers(), equalTo(true)) - } - - @Test - fun `comic trigger does not reorder comics`() { - val oldComicState = ComicState(generateListOfComics()) - val newComicState = ComicState(generateListOfComics().plusElement(Comic("new 1"))) - val mergedComicState = newComicTrigger.mergeStates(oldComicState, newComicState) as ComicState - assertThat(mergedComicState.comics(), contains(*generateListOfComics().plusElement(Comic("new 1")).toTypedArray())) - } - -} - -private fun generateListOfComics(): List = (1..40).map { Comic("comic $it") }