X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Frhynodge%2Fstates%2FEpisodeState.java;h=abb387d38e5574705202aee491fd687e69dfc6f1;hb=8aeef90590095a455e2323d70ba8ccae032f4276;hp=d7d90b2a60554269ba1ae1c8ed9e8b2de453c391;hpb=6f69aff66ba5617d0bb27874014b4274bc551ab8;p=rhynodge.git diff --git a/src/main/java/net/pterodactylus/rhynodge/states/EpisodeState.java b/src/main/java/net/pterodactylus/rhynodge/states/EpisodeState.java index d7d90b2..abb387d 100644 --- a/src/main/java/net/pterodactylus/rhynodge/states/EpisodeState.java +++ b/src/main/java/net/pterodactylus/rhynodge/states/EpisodeState.java @@ -20,15 +20,26 @@ package net.pterodactylus.rhynodge.states; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.pterodactylus.rhynodge.Reaction; import net.pterodactylus.rhynodge.State; import net.pterodactylus.rhynodge.filters.EpisodeFilter; import net.pterodactylus.rhynodge.states.EpisodeState.Episode; import net.pterodactylus.rhynodge.states.TorrentState.TorrentFile; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Ordering; +import org.apache.commons.lang3.StringEscapeUtils; /** * {@link State} implementation that stores episodes of TV shows, parsed via @@ -38,32 +49,52 @@ import com.fasterxml.jackson.annotation.JsonProperty; */ public class EpisodeState extends AbstractState implements Iterable { - /** The episodes found in the current request. */ + /** + * The episodes found in the current request. + */ @JsonProperty - private final List episodes = new ArrayList(); + private final List episodes = new ArrayList<>(); + private final Set newEpisodes = new HashSet<>(); + private final Set changedEpisodes = new HashSet<>(); + private final Set newTorrentFiles = new HashSet<>(); /** * No-arg constructor for deserialization. */ @SuppressWarnings("unused") private EpisodeState() { - this(Collections. emptySet()); } /** * Creates a new episode state. * - * @param episodes - * The episodes of the request + * @param episodes The episodes of the request */ public EpisodeState(Collection episodes) { this.episodes.addAll(episodes); } + public EpisodeState(Collection episodes, Collection newEpisodes, Collection changedEpisodes, Collection newTorreFiles) { + this(episodes); + this.newEpisodes.addAll(newEpisodes); + this.changedEpisodes.addAll(changedEpisodes); + this.newTorrentFiles.addAll(newTorreFiles); + } + // // ACCESSORS // + @Override + public boolean isEmpty() { + return episodes.isEmpty(); + } + + @Override + public boolean triggered() { + return !newEpisodes.isEmpty() || !changedEpisodes.isEmpty() || !newTorrentFiles.isEmpty(); + } + /** * Returns all episodes contained in this state. * @@ -73,6 +104,124 @@ public class EpisodeState extends AbstractState implements Iterable { return Collections.unmodifiableCollection(episodes); } + @Nonnull + @Override + protected String summary(Reaction reaction) { + if (!newEpisodes.isEmpty()) { + if (!changedEpisodes.isEmpty()) { + return String.format("%d new and %d changed Torrent(s) for “%s!”", newEpisodes.size(), changedEpisodes.size(), reaction.name()); + } + return String.format("%d new Torrent(s) for “%s!”", newEpisodes.size(), reaction.name()); + } + return String.format("%d changed Torrent(s) for “%s!”", changedEpisodes.size(), reaction.name()); + } + + @Nonnull + @Override + protected String plainText() { + StringBuilder stringBuilder = new StringBuilder(); + if (!newEpisodes.isEmpty()) { + stringBuilder.append("New Episodes\n\n"); + for (Episode episode : newEpisodes) { + stringBuilder.append("- ").append(episode.identifier()).append("\n"); + for (TorrentFile torrentFile : episode) { + stringBuilder.append(" - ").append(torrentFile.name()).append(", ").append(torrentFile.size()).append("\n"); + if ((torrentFile.magnetUri() != null) && (torrentFile.magnetUri().length() > 0)) { + stringBuilder.append(" Magnet: ").append(torrentFile.magnetUri()).append("\n"); + } + if ((torrentFile.downloadUri() != null) && (torrentFile.downloadUri().length() > 0)) { + stringBuilder.append(" Download: ").append(torrentFile.downloadUri()).append("\n"); + } + } + } + } + if (!changedEpisodes.isEmpty()) { + stringBuilder.append("Changed Episodes\n\n"); + for (Episode episode : changedEpisodes) { + stringBuilder.append("- ").append(episode.identifier()).append("\n"); + for (TorrentFile torrentFile : episode) { + stringBuilder.append(" - ").append(torrentFile.name()).append(", ").append(torrentFile.size()).append("\n"); + if ((torrentFile.magnetUri() != null) && (torrentFile.magnetUri().length() > 0)) { + stringBuilder.append(" Magnet: ").append(torrentFile.magnetUri()).append("\n"); + } + if ((torrentFile.downloadUri() != null) && (torrentFile.downloadUri().length() > 0)) { + stringBuilder.append(" Download: ").append(torrentFile.downloadUri()).append("\n"); + } + } + } + } + /* list all known episodes. */ + stringBuilder.append("All Known Episodes\n\n"); + ImmutableMap> episodesBySeason = FluentIterable.from(episodes).index(Episode::season).asMap(); + for (Map.Entry> seasonEntry : episodesBySeason.entrySet()) { + stringBuilder.append(" Season ").append(seasonEntry.getKey()).append("\n\n"); + for (Episode episode : Ordering.natural().sortedCopy(seasonEntry.getValue())) { + stringBuilder.append(" Episode ").append(episode.episode()).append("\n"); + for (TorrentFile torrentFile : episode) { + stringBuilder.append(" Size: ").append(torrentFile.size()); + stringBuilder.append(" in ").append(torrentFile.fileCount()).append(" file(s): "); + stringBuilder.append(torrentFile.magnetUri()); + } + } + } + return stringBuilder.toString(); + } + + @Nullable + @Override + protected String htmlText() { + StringBuilder htmlBuilder = new StringBuilder(); + htmlBuilder.append("\n"); + /* show all known episodes. */ + htmlBuilder.append("\n\n"); + htmlBuilder.append("\n"); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append("\n"); + htmlBuilder.append("\n"); + htmlBuilder.append("\n"); + Episode lastEpisode = null; + for (Map.Entry> seasonEntry : FluentIterable.from(Ordering.natural().reverse().sortedCopy(episodes)).index(Episode.BY_SEASON).asMap().entrySet()) { + for (Episode episode : seasonEntry.getValue()) { + for (TorrentFile torrentFile : episode) { + if (newEpisodes.contains(episode)) { + htmlBuilder.append(""); + } else if (newTorrentFiles.contains(torrentFile)) { + htmlBuilder.append(""); + } else { + htmlBuilder.append(""); + } + if ((lastEpisode == null) || !lastEpisode.equals(episode)) { + htmlBuilder.append(""); + } else { + htmlBuilder.append(""); + } + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append(""); + htmlBuilder.append("\n"); + lastEpisode = episode; + } + } + } + htmlBuilder.append("\n"); + htmlBuilder.append("
All Known Episodes
SeasonEpisodeFilenameSizeFile(s)SeedsLeechersMagnetDownload
").append(episode.season()).append("").append(episode.episode()).append("").append(StringEscapeUtils.escapeHtml4(torrentFile.name())).append("").append(StringEscapeUtils.escapeHtml4(torrentFile.size())).append("").append(torrentFile.fileCount()).append("").append(torrentFile.seedCount()).append("").append(torrentFile.leechCount()).append("LinkLink
\n"); + htmlBuilder.append("\n"); + return htmlBuilder.toString(); + } + // // ITERABLE INTERFACE // @@ -98,7 +247,16 @@ public class EpisodeState extends AbstractState implements Iterable { * * @author David ‘Bombe’ Roden */ - public static class Episode implements Iterable { + public static class Episode implements Comparable, Iterable { + + /** Function to extract the season of an episode. */ + public static final Function BY_SEASON = new Function() { + + @Override + public Integer apply(Episode episode) { + return (episode != null ) ? episode.season() : -1; + } + }; /** The season of the episode. */ @JsonProperty @@ -184,7 +342,9 @@ public class EpisodeState extends AbstractState implements Iterable { * The torrent file to add */ public void addTorrentFile(TorrentFile torrentFile) { - torrentFiles.add(torrentFile); + if (!torrentFiles.contains(torrentFile)) { + torrentFiles.add(torrentFile); + } } // @@ -199,6 +359,26 @@ public class EpisodeState extends AbstractState implements Iterable { return torrentFiles.iterator(); } + /** + * {@inheritDoc} + */ + @Override + public int compareTo(Episode episode) { + if (season() < episode.season()) { + return -1; + } + if (season() > episode.season()) { + return 1; + } + if (episode() < episode.episode()) { + return -1; + } + if (episode() > episode.episode()) { + return 1; + } + return 0; + } + // // OBJECT METHODS //