überarbeitung Code und hinzufügen Auto Favo für neue Storys
This commit is contained in:
@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
application.mainClass = "de.ocame.ffdiscordbot.Main"
|
||||
group 'de.ocame'
|
||||
version '1.1-SNAPSHOT'
|
||||
version '1.2-SNAPSHOT'
|
||||
|
||||
|
||||
repositories {
|
||||
|
||||
@ -29,4 +29,12 @@ public class ConfigLoader {
|
||||
return properties.getProperty("ff.password");
|
||||
}
|
||||
|
||||
public String getFfFavList() {
|
||||
return properties.getProperty("ff.favList");
|
||||
}
|
||||
|
||||
public Long getDebugChannel() {
|
||||
return Long.parseLong(properties.getProperty("debug.Channel"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
5
src/main/java/de/ocame/ffdiscordbot/DataChapter.java
Normal file
5
src/main/java/de/ocame/ffdiscordbot/DataChapter.java
Normal file
@ -0,0 +1,5 @@
|
||||
package de.ocame.ffdiscordbot;
|
||||
|
||||
public record DataChapter(String name, String link, String storyId, long date, long number) {
|
||||
|
||||
}
|
||||
5
src/main/java/de/ocame/ffdiscordbot/DataStory.java
Normal file
5
src/main/java/de/ocame/ffdiscordbot/DataStory.java
Normal file
@ -0,0 +1,5 @@
|
||||
package de.ocame.ffdiscordbot;
|
||||
|
||||
public record DataStory(String name, String link, String ffid, long date, String author, Integer tagId) {
|
||||
|
||||
}
|
||||
@ -1,242 +0,0 @@
|
||||
package de.ocame.ffdiscordbot;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
|
||||
import java.awt.*;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
public class DiscordOutput {
|
||||
|
||||
private final List<StoryOutputText> chapterText;
|
||||
public DiscordOutput() {
|
||||
|
||||
chapterText = new ArrayList<>();
|
||||
chapterText.add(new StoryOutputText(
|
||||
"Oh, wie mein Herz singt! **%autor%** hat ein neues Kapitel unserer Geschichte \"**%storyName%**\" geschrieben, " +
|
||||
"und es heißt \"**%chapterName%**\". \n\nIch spüre die Aufregung in der Luft, als ob jeder Flügelschlag mich höher trägt. " +
|
||||
"Die Welt leuchtet in neuen Farben, und jeder Sonnenstrahl erzählt von Abenteuern, die uns erwarten. Dieses Kapitel " +
|
||||
"verspricht so viel – ich kann es kaum erwarten, in die Worte zu tauchen und die Geschichten, die sie verbergen, " +
|
||||
"zu entdecken!"
|
||||
, "https://media.discordapp.net/stickers/1219043798101786624.webp?size=160"));
|
||||
chapterText.add(new StoryOutputText(
|
||||
"Aye, Text in Sicht, ihr Seeratten! **%autor%** hat ein neues Kapitel in der Geschichte \"**%storyName%**\" aufgetan, und " +
|
||||
"es trägt den Namen \"**%chapterName%**\". Macht die Fässer klar, holt die besten Getränke, und besetzt die Bildschirme! \n" +
|
||||
"Keiner rührt sich, bis wir jedes Wort gelesen haben, verstanden? Und hört gut hin: Wer es wagt, auch nur ein Wort " +
|
||||
"zu spoilern, wird schneller gekielholt, als er \"Piratenkodex\" sagen kann! Jetzt aber volle Fahrt voraus – das " +
|
||||
"Abenteuer ruft!", "https://cdn.discordapp.com/attachments/542202034330271759/1272999183673987133/image.png?ex=66bd0460&is=66bbb2e0&hm=708f10708d0616ed212d0c288cfde503fb27785ddd68c1ba30bb4d3f7698acee&"));
|
||||
chapterText.add(new StoryOutputText(
|
||||
"Mesdames et Messieurs, heute habe ich die Ehre, Ihnen ein exquisites Gericht zu präsentieren: " +
|
||||
"das \"**%chapterName%**\" à la \"**%storyName%**\", nach der feinen Art unseres geschätzten Chef-Autors \"**%autor%**\". \n" +
|
||||
"Es ist ein Meisterwerk der literarischen Küche, perfekt gewürzt mit Spannung und serviert mit einer Prise Abenteuer. " +
|
||||
"Lassen Sie sich von den Aromen dieser neuen Geschichte verführen und genießen Sie jeden Bissen – bon appétit!",
|
||||
"https://cdn.discordapp.com/attachments/542202034330271759/1272999507587629188/image.png?ex=66bd04ad&is=66bbb32d&hm=d4d7325f233c27a75305ee9622c9f87b03e1aa507acb534c2fd6c3de62d435d1&",
|
||||
new Color(255, 0, 229)));
|
||||
|
||||
chapterText.add(new StoryOutputText(
|
||||
"........................\n " +
|
||||
"........................\n " +
|
||||
"........................\n " +
|
||||
"........................\n " +
|
||||
"Na los, Grünschnabel, hör auf zu trödeln und lies endlich das neue Kapitel \"**%chapterName%**\" aus der Geschichte \"**%storyName%**\" " +
|
||||
"vom \"**%autor%**\" vor! Meine Zeit ist nicht unendlich, und ich hab keine Lust, hier ewig zu warten. Also mach schon, bevor ich " +
|
||||
"noch selbst anfangen muss, die Seiten zu ertasten!"
|
||||
));
|
||||
chapterText.add(new StoryOutputText(
|
||||
"Das neue Kapitel \"**%chapterName%**\" aus der Geschichte \"**%storyName%**\" vom \"**%autor%**\" ist erschienen, und ich werde es als Erster lesen. " +
|
||||
"Während die Piraten noch ihren Rum genießen, verschaffe ich mir den Wissensvorsprung. Mit jedem Satz, den ich lese, " +
|
||||
"wird meine Strategie schärfer, und bald werde ich ihnen einen Schritt voraus sein. Ein kluger Kopf gewinnt schließlich immer " +
|
||||
"das Spiel.",
|
||||
"https://cdn.discordapp.com/attachments/542202034330271759/1273002039923965952/image.png?ex=66bd0709&is=66bbb589&hm=77130cbe420a9e941e58e68010c12cc2e53c54c288b8563fd6a1a856ffebd0df&"
|
||||
));
|
||||
|
||||
chapterText.add(new StoryOutputText(
|
||||
"hcilrütan ebah hci sad etseuen Letipak nohcs neseleg \n\n" +
|
||||
"Erika Rückwerts die Worte auszuprechen ist kein Reptiloidisch!\n\n" +
|
||||
"Menschen! Natürlich habe ich das neueste Kapitel schon gelesen. Kein Zweifel, es ist genauso grandios, " +
|
||||
"wie ich es erwartet habe. Jede Wendung, jeder Dialog – einfach meisterhaft. Und falls du es wissen willst: Es handelt sich " +
|
||||
"um \"**%chapterName%**\" aus der Geschichte \"**%storyName%**\" vom Autor \"**%autor%**\". Wenn du wirklich etwas Gutes lesen willst, dann ist das genau das " +
|
||||
"Richtige für dich. Aber hey, das hab ich ja gleich gewusst.",
|
||||
"https://cdn.discordapp.com/attachments/542202034330271759/1273005878974349313/image.png?ex=66bd0a9c&is=66bbb91c&hm=8e7701f259b7bd84ea3b91b5c8fb63c4b8807dd297a05fc9289aead8c1978fac&",
|
||||
new Color(40, 145, 6)
|
||||
));
|
||||
chapterText.add(new StoryOutputText(
|
||||
"Ah, wie wunderbar! Endlich halte ich das neue Kapitel \"**%chapterName%**\" aus der Geschichte \"**%storyName%**\" " +
|
||||
"vom \"**%autor%**\" in den Händen. Ein wahres Vergnügen für den Geist! Und bitte, meine Lieben, lasst den Kronleuchter in Ruhe. " +
|
||||
"Er spendet gerade das perfekte Licht zum Lesen – eine solch erhabene Lektüre verdient schließlich die besten Bedingungen."
|
||||
));
|
||||
chapterText.add(new StoryOutputText("Ich habe die Zukunft gesehen, und glaub mir, das neue Kapitel von \"**%chapterName%**\" aus der Geschichte " +
|
||||
"\"**%storyName%**\" vom \"**%autor%**\" ist etwas ganz Besonderes. Es ist, als ob die Worte selbst eine Melodie singen, die so sanft und " +
|
||||
"doch so kraftvoll ist, dass sie dich mitreißt, egal wohin sie dich führt. Jedes Wort, jede Zeile – sie fließen wie ein ruhiger " +
|
||||
"Fluss, der dich in eine Welt entführt, die so fesselnd und lebendig ist, dass du alles um dich herum vergisst.\n" +
|
||||
"\n" +
|
||||
"Es ist wie der erste Schluck eines perfekt gebrühten Tees, dieser Moment, in dem sich die Wärme in deinem Körper ausbreitet " +
|
||||
"und du spürst, wie jeder Tropfen dich beruhigt und gleichzeitig belebt. Ach, Tee... Was für ein wunderbares Getränk, nicht wahr? " +
|
||||
"So viel Sorgfalt und Liebe steckt in jeder Tasse, genau wie in diesen Worten, die ich gerade gelesen habe. Die Teeblätter, " +
|
||||
"die mit so viel Bedacht und Geduld gepflückt werden, erinnern mich an die frischen Pflanzen im Frühling, wenn alles grünt und blüht. " +
|
||||
"Sie sind voller Leben, voller Möglichkeiten, genau wie die Geschichten, die uns erzählen, wohin unser Weg führen könnte.\n" +
|
||||
"\n" +
|
||||
"Wie wunderschön es doch ist, in solchen einfachen Freuden Trost zu finden – sei es in einem guten Buch, einer heißen Tasse Tee oder dem " +
|
||||
"Anblick von Pflanzen, die in ihrer vollen Pracht stehen. Manchmal sind es gerade diese kleinen, stillen Momente, die das Leben wirklich " +
|
||||
"lebenswert machen."));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void newChapter(JDA jda, DataChapter chapter, DataStory story) {
|
||||
newChapter(jda, chapter, story, null, null);
|
||||
}
|
||||
public void newChapter(JDA jda, DataChapter chapter, DataStory story, Integer version, Long tagetChannel) {
|
||||
try {
|
||||
String message;
|
||||
EmbedBuilder outputBox = new EmbedBuilder();
|
||||
|
||||
outputBox.setTitle("Neues Kapitel:", chapter.link());
|
||||
|
||||
List<StoryOutputText> chapterTexte;
|
||||
if(version != null) {
|
||||
chapterTexte = SQLiteStorage.getChapterTexte(version);
|
||||
}
|
||||
else {
|
||||
chapterTexte = SQLiteStorage.getChapterTexte(story);
|
||||
}
|
||||
|
||||
|
||||
StoryOutputText versionText = null;
|
||||
if(chapterTexte.size() == 0)
|
||||
return;
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
versionText = chapterTexte.get(random.nextInt(chapterTexte.size()));
|
||||
|
||||
message = versionText.getMessage();
|
||||
|
||||
message = message.replace("%chapterName%", "**" + chapter.name() + "**")
|
||||
.replace("%storyName%", "**" + story.name() + "**")
|
||||
.replace("%autor%", "**" + story.author() + "**");
|
||||
|
||||
|
||||
outputBox.setDescription(message);
|
||||
|
||||
outputBox.setColor(versionText.getColor());
|
||||
|
||||
Instant instant = Instant.ofEpochSecond(chapter.date());
|
||||
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.of("Europe/Berlin"));
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy HH:mm 'Uhr'");
|
||||
|
||||
|
||||
outputBox.setFooter("Veröffentlicht am " + dateTime.format(formatter));
|
||||
if(versionText.getImage() != null && !Objects.equals(versionText.getImage(), ""))
|
||||
outputBox.setThumbnail(versionText.getImage());
|
||||
|
||||
Long[] channelIds = SQLiteStorage.getChannelIds();
|
||||
if(tagetChannel != null) {
|
||||
Objects.requireNonNull(jda.getTextChannelById(tagetChannel))
|
||||
.sendMessage("Hier ist ein Text vor dem Embed <@&423156046115242005> :")
|
||||
.setEmbeds(outputBox.build())
|
||||
.queue();
|
||||
}
|
||||
else if(Objects.requireNonNull(channelIds).length == 0) {
|
||||
Objects.requireNonNull(jda.getTextChannelById(542202034330271759L)).sendMessageEmbeds(outputBox.build()).queue();
|
||||
}
|
||||
else {
|
||||
for (Long channelId : channelIds ) {
|
||||
try {
|
||||
if (Objects.requireNonNull(jda.getTextChannelById(channelId)).canTalk())
|
||||
Objects.requireNonNull(jda.getTextChannelById(channelId)).sendMessageEmbeds(outputBox.build()).queue();
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
//jda.getTextChannelById(channelId).sendMessage("Nope").queue();
|
||||
System.out.println("problem: " + e.getMessage());
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println("problem: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void newStory(JDA jda, DataStory story) {
|
||||
newStory(jda, story, null);
|
||||
}
|
||||
public void newStory(JDA jda, DataStory story, Integer version) {
|
||||
try {
|
||||
String message;
|
||||
EmbedBuilder outputBox = new EmbedBuilder();
|
||||
|
||||
|
||||
outputBox.setTitle("Neue Gesichte:", story.link());
|
||||
|
||||
List<StoryOutputText> storyTexte = SQLiteStorage.getStoryTexte();
|
||||
StoryOutputText versionText = null;
|
||||
if(storyTexte.size() == 0)
|
||||
return;
|
||||
|
||||
if(version != null) {
|
||||
versionText = storyTexte.get(version);
|
||||
}
|
||||
if(version == null || versionText == null) {
|
||||
Random random = new Random();
|
||||
versionText = storyTexte.get(random.nextInt(storyTexte.size()));
|
||||
}
|
||||
|
||||
message = versionText.getMessage();
|
||||
|
||||
message = message.replace("%storyName%", "**" + story.name() + "**")
|
||||
.replace("%autor%", "**" + story.author() + "**");
|
||||
|
||||
|
||||
outputBox.setDescription(message);
|
||||
|
||||
outputBox.setColor(versionText.getColor());
|
||||
|
||||
Instant instant = Instant.ofEpochSecond(story.date());
|
||||
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.of("Europe/Berlin"));
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy HH:mm 'Uhr'");
|
||||
|
||||
|
||||
outputBox.setFooter("Veröffentlicht am " + dateTime.format(formatter));
|
||||
if(versionText.getImage() != null && !Objects.equals(versionText.getImage(), ""))
|
||||
outputBox.setThumbnail(versionText.getImage());
|
||||
|
||||
Long[] channelIds = SQLiteStorage.getChannelIds();
|
||||
if(channelIds.length == 0) {
|
||||
jda.getTextChannelById(542202034330271759L).sendMessageEmbeds(outputBox.build()).queue();
|
||||
}
|
||||
else {
|
||||
for (Long channelId : channelIds ) {
|
||||
try {
|
||||
if (jda.getTextChannelById(channelId).canTalk())
|
||||
jda.getTextChannelById(channelId).sendMessageEmbeds(outputBox.build())
|
||||
.queue();
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
//jda.getTextChannelById(channelId).sendMessage("Nope").queue();
|
||||
}
|
||||
catch (NullPointerException e ) {
|
||||
//
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println("problem: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,69 +1,60 @@
|
||||
package de.ocame.ffdiscordbot;
|
||||
|
||||
import de.ocame.ffdiscordbot.fetcher.DefaultHtmlFetcher;
|
||||
import de.ocame.ffdiscordbot.output.ChapterNotifier;
|
||||
import de.ocame.ffdiscordbot.output.InfoNotifier;
|
||||
import de.ocame.ffdiscordbot.output.StoryNotifier;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.Instant;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
|
||||
public class FanFiktionReader {
|
||||
|
||||
private final HtmlFetcher fetcher;
|
||||
|
||||
private final DiscordOutput dco;
|
||||
private final DefaultHtmlFetcher fetcher; // Use the HtmlFetcher interface
|
||||
|
||||
private final JDA jda;
|
||||
|
||||
private long time = 30*60;
|
||||
private long time = 30 * 60;
|
||||
|
||||
private final String URL = "https://www.fanfiktion.de";
|
||||
|
||||
|
||||
public FanFiktionReader(JDA jda) {
|
||||
|
||||
fetcher = new HtmlFetcher();
|
||||
this.fetcher = new DefaultHtmlFetcher();
|
||||
SQLiteStorage.createTable();
|
||||
dco = new DiscordOutput();
|
||||
this.jda = jda;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Liest neue Ereignse von der Alert Seite aus
|
||||
* Liest neue Ereignse von der Alert-Seite aus
|
||||
*/
|
||||
public void checkAlerts() {
|
||||
|
||||
try {
|
||||
String alertURL = "https://www.fanfiktion.de/?a=i";
|
||||
|
||||
Document alertPage = fetcher.fetchURL(alertURL);
|
||||
|
||||
// Login Check
|
||||
Elements title = alertPage.getElementsByTag("title");
|
||||
if(title.first().text().contains("keine Berechtigung!") || title.first().text().contains("Session-Error") || title.first().text().contains("Login")) {
|
||||
login();
|
||||
alertPage = fetcher.fetchURL(alertURL);
|
||||
title = alertPage.getElementsByTag("title");
|
||||
if(title.first().text().contains("keine Berechtigung!") || title.first().text().contains("Session-Error") || title.first().text().contains("Login")) {
|
||||
// Fehler
|
||||
Document alertPage = fetchHTMLWithAuthentication(URL + "/?a=i");
|
||||
if (alertPage == null)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Story Check
|
||||
Element authorBox = alertPage.getElementById("ffcbox-alerts_author-box");
|
||||
if(authorBox != null) {
|
||||
if (authorBox != null) {
|
||||
Elements rows = authorBox.select("table tbody tr");
|
||||
for (Element row : rows) {
|
||||
checkNewStoryFromAlert(row);
|
||||
@ -72,7 +63,7 @@ public class FanFiktionReader {
|
||||
|
||||
// Kapitel Check
|
||||
Element StoryBox = alertPage.getElementById("ffcbox-alerts_story-box");
|
||||
if(StoryBox != null) {
|
||||
if (StoryBox != null) {
|
||||
Elements rows = StoryBox.select("table tbody tr");
|
||||
|
||||
for (Element row : rows) {
|
||||
@ -80,20 +71,19 @@ public class FanFiktionReader {
|
||||
if (cols.size() >= 2) {
|
||||
Element link = cols.get(1).selectFirst("a");
|
||||
String linkHref = (link != null) ? link.attr("href") : "No link";
|
||||
String chaptertime = cols.get(6).text();
|
||||
String chaptertime = cols.get(5).text();
|
||||
long chapterUnixtime = DateToTimestamp(chaptertime);
|
||||
|
||||
Element delLink = cols.last().selectFirst("a");
|
||||
String delLinkHref = (delLink != null) ? delLink.attr("href") : "No link";
|
||||
|
||||
checkNewChapter("https://www.fanfiktion.de" + linkHref, chapterUnixtime);
|
||||
checkNewChapter(URL + linkHref, chapterUnixtime);
|
||||
|
||||
// Ausführung des Links, um Inhalt aus Alert zu entfernen
|
||||
try {
|
||||
if(!delLinkHref.equals("No link"))
|
||||
fetcher.fetchURL("https://www.fanfiktion.de" + delLinkHref);
|
||||
}
|
||||
catch (IOException | InterruptedException | URISyntaxException e) {
|
||||
if (!delLinkHref.equals("No link"))
|
||||
fetcher.fetchHtml(URL + delLinkHref);
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@ -101,16 +91,15 @@ public class FanFiktionReader {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException | InterruptedException | URISyntaxException e) {
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Random random = new Random();
|
||||
this.time = random.nextLong(24*60,34*60);
|
||||
this.time = random.nextLong(24 * 60, 34 * 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liest neue Storys von der Alarm Seite aus
|
||||
* Liest neue Storys von der Alarm-Seite aus
|
||||
*
|
||||
* @param row
|
||||
*/
|
||||
@ -125,24 +114,22 @@ public class FanFiktionReader {
|
||||
|
||||
Element link = cols.get(1).selectFirst("a");
|
||||
String linkHref = (link != null) ? link.attr("href") : "No link";
|
||||
String[] hrefElements = linkHref.split("/s/",2);
|
||||
String[] hrefElements = linkHref.split("/s/", 2);
|
||||
String storyId = hrefElements[1];
|
||||
if(!SQLiteStorage.checkStory(storyId)) {
|
||||
/* todo: neue Story gefunden Ausgabe */
|
||||
DataStory newStory = new DataStory(storyName, "https://www.fanfiktion.de/s/" + storyId, storyId,storyUnixtime,storyAutor, 0);
|
||||
if (SQLiteStorage.isStoryInvalid(storyId)) {
|
||||
DataStory newStory = new DataStory(storyName, URL + "/s/" + storyId, storyId, storyUnixtime, storyAutor, 0);
|
||||
SQLiteStorage.insertStorys(newStory);
|
||||
dco.newStory(jda, newStory);
|
||||
|
||||
new StoryNotifier(jda, newStory).sendOutput();
|
||||
addStoryToFavorit(storyId);
|
||||
}
|
||||
Element delLink = cols.last().selectFirst("a");
|
||||
String delLinkHref = (delLink != null) ? delLink.attr("href") : "No link";
|
||||
|
||||
// Ausführung des Links, um Inhalt aus Alert zu entfernen
|
||||
try {
|
||||
if(!delLinkHref.equals("No link"))
|
||||
fetcher.fetchURL("https://www.fanfiktion.de" + delLinkHref);
|
||||
}
|
||||
catch (IOException | InterruptedException | URISyntaxException e) {
|
||||
if (!delLinkHref.equals("No link"))
|
||||
fetcher.fetchHtml(URL + delLinkHref);
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -157,29 +144,21 @@ public class FanFiktionReader {
|
||||
public void checkNewChapter(String url, long chapterDate) {
|
||||
try {
|
||||
|
||||
// Login Check
|
||||
Document storyPage = fetcher.fetchURL(url);
|
||||
Elements title = storyPage.getElementsByTag("title");
|
||||
if(title.first().text().contains("keine Berechtigung!") || title.first().text().contains("Session-Error") || title.first().text().contains("Login")) {
|
||||
login();
|
||||
storyPage = fetcher.fetchURL(url);
|
||||
title = storyPage.getElementsByTag("title");
|
||||
if(title.first().text().contains("keine Berechtigung!") || title.first().text().contains("Session-Error") || title.first().text().contains("Login")) {
|
||||
// Fehler
|
||||
Document storyPage = fetchHTMLWithAuthentication(url);
|
||||
if (storyPage == null)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Auswahl Select für Kapitel Auswahl
|
||||
Element chapterSelect = storyPage.getElementById("kA");
|
||||
if(chapterSelect != null) {
|
||||
if (chapterSelect != null) {
|
||||
Elements options = storyPage.select("option");
|
||||
String chapterName = options.last().text();
|
||||
String chapterNumer = options.last().attr("value");
|
||||
String onChange = chapterSelect.attributes().get("onchange")
|
||||
.replace("location.href = '" , "")
|
||||
.replace("' + this.value + '" , chapterNumer)
|
||||
.replace("'" , "");
|
||||
.replace("location.href = '", "")
|
||||
.replace("' + this.value + '", chapterNumer)
|
||||
.replace("'", "");
|
||||
|
||||
// Regulärer Ausdruck für die ffid nach /s/
|
||||
String regex = "/s/([a-zA-Z0-9]+)/";
|
||||
@ -193,26 +172,26 @@ public class FanFiktionReader {
|
||||
// todo: fehler behandlung
|
||||
}
|
||||
|
||||
if(SQLiteStorage.checkChapter(ffid, Long.parseLong(chapterNumer))) {
|
||||
if (!SQLiteStorage.checkChapter(ffid, Long.parseLong(chapterNumer))) {
|
||||
/* todo: neue Chapter gefunden Ausgabe */
|
||||
if(!SQLiteStorage.checkStory(ffid)) {
|
||||
if (SQLiteStorage.isStoryInvalid(ffid)) {
|
||||
readandSaveStory(storyPage);
|
||||
}
|
||||
DataStory ds = SQLiteStorage.getStory(ffid);
|
||||
DataChapter newChapter = new DataChapter(chapterName, "https://www.fanfiktion.de" + onChange, ffid, chapterDate, Long.parseLong(chapterNumer));
|
||||
DataChapter newChapter = new DataChapter(chapterName, URL + onChange, ffid, chapterDate, Long.parseLong(chapterNumer));
|
||||
SQLiteStorage.insertChapter(newChapter);
|
||||
//clearChapter();
|
||||
dco.newChapter(jda, newChapter, ds);
|
||||
new ChapterNotifier(jda, newChapter, ds).sendOutput();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException | InterruptedException | URISyntaxException e) {
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List alle Infos aus einer Story Seite aus, um das relevante zu speichern
|
||||
*
|
||||
* @param storyPage
|
||||
*/
|
||||
public void readandSaveStory(Document storyPage) {
|
||||
@ -231,22 +210,24 @@ public class FanFiktionReader {
|
||||
if (matcher.find()) {
|
||||
// Die gefundene Nummernfolge ausgeben
|
||||
ffid = matcher.group(1);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// todo: fehler behandlung
|
||||
return;
|
||||
}
|
||||
|
||||
if(!SQLiteStorage.checkStory(ffid)) {
|
||||
DataStory newStory = new DataStory(storyName, "https://www.fanfiktion.de/s/" + ffid, ffid, storyUnixtime, storyAutor, 0);
|
||||
if (SQLiteStorage.isStoryInvalid(ffid)) {
|
||||
DataStory newStory = new DataStory(storyName, URL + "/s/" + ffid, ffid, storyUnixtime, storyAutor, 0);
|
||||
SQLiteStorage.insertStorys(newStory);
|
||||
addStoryToFavorit(ffid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void outputCheapterTester(int chapterId, String chapterTextTitle, String storyTitle, String autor, Long tagetChannel) {
|
||||
DataStory ds = new DataStory(storyTitle, "https://www.fanfiktion.de", "", LocalDateTime.now().toEpochSecond(ZoneOffset.UTC), autor, 0);
|
||||
DataChapter dc = new DataChapter(chapterTextTitle, "https://www.fanfiktion.de", "", LocalDateTime.now().toEpochSecond(ZoneOffset.UTC), 1);
|
||||
|
||||
dco.newChapter(jda, dc, ds, chapterId, tagetChannel);
|
||||
DataStory ds = new DataStory(storyTitle, URL, "", Instant.now().getEpochSecond(), autor, 0);
|
||||
DataChapter dc = new DataChapter(chapterTextTitle, URL, "", Instant.now().getEpochSecond(), 1);
|
||||
new ChapterNotifier(jda, dc, ds).setVersion(chapterId).sendOutput(tagetChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,13 +244,17 @@ public class FanFiktionReader {
|
||||
//DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy | HH:mm 'Uhr'").withResolverStyle(ResolverStyle.STRICT);
|
||||
//DateTimeFormatter formatteralternativ = DateTimeFormatter.ofPattern("dd.MM.yyyy'");
|
||||
|
||||
String[] patterns = {"dd.MM.yyyy | HH:mm 'Uhr'" , "dd.MM.yyyy'", "dd.MM.yyyy HH:mm'"};
|
||||
String[] patterns = {"dd.MM.yyyy | HH:mm 'Uhr'", "dd.MM.yyyy'", "dd.MM.yyyy HH:mm'"};
|
||||
LocalDateTime dateTime = parseDateTimeWithMultiplePatterns(dateString, patterns);
|
||||
if(dateTime == null || dateTime.toEpochSecond(ZoneOffset.UTC) == 0) {
|
||||
if (dateTime == null || dateTime.toEpochSecond(ZoneOffset.UTC) == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
ZoneId zoneId = ZoneId.of("Europe/Berlin");
|
||||
ZonedDateTime zonedDateTime = dateTime.atZone(zoneId);
|
||||
Instant instant = zonedDateTime.toInstant();
|
||||
|
||||
return instant.getEpochSecond();
|
||||
}
|
||||
else
|
||||
return dateTime.toEpochSecond(ZoneOffset.UTC);
|
||||
|
||||
|
||||
}
|
||||
@ -290,24 +275,25 @@ public class FanFiktionReader {
|
||||
* Führt den Login aus
|
||||
*/
|
||||
public void login() {
|
||||
|
||||
System.out.print("Login muss ausgeführt werden");
|
||||
try {
|
||||
ConfigLoader configLoader = new ConfigLoader();
|
||||
|
||||
String loginURL = "https://www.fanfiktion.de/?a=l";
|
||||
Document logintPage = fetcher.fetchURL(loginURL);
|
||||
String loginURL = URL + "/?a=l";
|
||||
Document logintPage = fetcher.fetchHtml(loginURL);
|
||||
|
||||
Elements nameBox = logintPage.select ("input[name='nickname']");
|
||||
Elements pwBox = logintPage.select ("input[name='passwd']");
|
||||
Elements nameBox = logintPage.select("input[name='nickname']");
|
||||
Elements pwBox = logintPage.select("input[name='passwd']");
|
||||
|
||||
if(nameBox.isEmpty()) {
|
||||
// todo: Fehler wenn Login nicht geht
|
||||
if (nameBox.isEmpty()) {
|
||||
time += 2 * 60 * 60; // Zeit um 2h erhöhen
|
||||
new InfoNotifier(jda).setMessagetext("Login Fehlgeschlagen").sendOutput();
|
||||
}
|
||||
|
||||
Elements aBox = logintPage.select ("input[name='a']");
|
||||
Elements uBox = logintPage.select ("input[name='u']");
|
||||
Elements aBox = logintPage.select("input[name='a']");
|
||||
Elements uBox = logintPage.select("input[name='u']");
|
||||
|
||||
String uValue = fetcher.getCookieValue("https://www.fanfiktion.de/", "u");
|
||||
String uValue = fetcher.getCookieValue(URL, "u");
|
||||
uValue = java.net.URLDecoder.decode(uValue, StandardCharsets.UTF_8);
|
||||
|
||||
String ffNickname = configLoader.getUsername();
|
||||
@ -319,16 +305,15 @@ public class FanFiktionReader {
|
||||
+ "&savelogindata=" + java.net.URLEncoder.encode("1", StandardCharsets.UTF_8);
|
||||
|
||||
|
||||
Document loginRequest = fetcher.fetchHtml(URL, postData);
|
||||
nameBox = loginRequest.select("input[name='nickname']");
|
||||
|
||||
Document loginRequest = fetcher.fetchURL("https://www.fanfiktion.de/", postData);
|
||||
nameBox = loginRequest.select ("input[name='nickname']");
|
||||
|
||||
if(!nameBox.isEmpty()) {
|
||||
// todo: Fehler wenn Login nicht geht
|
||||
if (!nameBox.isEmpty()) {
|
||||
time += 2 * 60 * 60; // Zeit um 2h erhöhen
|
||||
new InfoNotifier(jda).setMessagetext("Login Fehlgeschlagen").sendOutput();
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException | InterruptedException | URISyntaxException e) {
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@ -339,23 +324,45 @@ public class FanFiktionReader {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void clearChapter(String url) {
|
||||
try {
|
||||
Document storyPage = fetcher.fetchURL(url);
|
||||
Elements title = storyPage.getElementsByTag("title");
|
||||
if (title.first().text().contains("keine Berechtigung!")) {
|
||||
public Document fetchHTMLWithAuthentication(String alertURL) throws IOException, InterruptedException {
|
||||
|
||||
Document alertPage = fetcher.fetchHtml(alertURL);
|
||||
|
||||
// Login Check
|
||||
Elements title = alertPage.getElementsByTag("title");
|
||||
if (title.first().text().contains("keine Berechtigung!") || title.first().text().contains("Session-Error") || title.first().text().contains("Login")) {
|
||||
login();
|
||||
storyPage = fetcher.fetchURL(url);
|
||||
title = storyPage.getElementsByTag("title");
|
||||
if (title.first().text().contains("keine Berechtigung!")) {
|
||||
alertPage = fetcher.fetchHtml(alertURL);
|
||||
title = alertPage.getElementsByTag("title");
|
||||
if (title.first().text().contains("keine Berechtigung!") || title.first().text().contains("Session-Error") || title.first().text().contains("Login")) {
|
||||
// Fehler
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException | InterruptedException | URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return alertPage;
|
||||
}
|
||||
|
||||
public void addStoryToFavorit(String ffid) {
|
||||
|
||||
ConfigLoader configLoader = new ConfigLoader();
|
||||
String ffFavList = configLoader.getFfFavList();
|
||||
String postData = "storyid=" + java.net.URLEncoder.encode(ffid, StandardCharsets.UTF_8)
|
||||
+ "&favlist=" + java.net.URLEncoder.encode(ffFavList, StandardCharsets.UTF_8)
|
||||
+ "&alert=1";
|
||||
try {
|
||||
Document sendToFav = fetcher.fetchHtml(URL + "/?a=q&a1=v&t=addstory&lbi=popup-addtofav-body&ar=1&action=i", postData);
|
||||
if(sendToFav.getElementsByClass("successbox").isEmpty()) {
|
||||
System.out.print("Story konnte nicht hinzugefügt werden");
|
||||
new InfoNotifier(jda).setMessagetext("Story " + ffid + "konnte nicht hinzugefügt werden. \n" + sendToFav.toString()).sendOutput();
|
||||
}
|
||||
}
|
||||
catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.OnlineStatus;
|
||||
import net.dv8tion.jda.api.entities.Activity;
|
||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
@ -19,9 +18,6 @@ public class Main {
|
||||
|
||||
ConfigLoader configLoader = new ConfigLoader();
|
||||
|
||||
// Insert your bot's token here
|
||||
//String token = "MTI3NzcxNTQ1NTI1MDkyMzU4MA.GUuRyh.07mjVRcI7MhLHo-Wdnytvxlb3Pts-hfRaNMaPA";
|
||||
// iro
|
||||
String token = configLoader.getToken();
|
||||
/**/
|
||||
JDA jda = JDABuilder.createDefault(token)
|
||||
@ -33,7 +29,8 @@ public class Main {
|
||||
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
|
||||
}
|
||||
FanFiktionReader ffr = new FanFiktionReader(jda);
|
||||
@ -43,7 +40,7 @@ public class Main {
|
||||
socketThread.start();
|
||||
|
||||
|
||||
//ffr.checkAlerts();
|
||||
ffr.checkAlerts();
|
||||
|
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
final long[] delay = {30 * 60};
|
||||
@ -52,7 +49,7 @@ public class Main {
|
||||
Runnable task = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//ffr.checkAlerts();
|
||||
ffr.checkAlerts();
|
||||
// Berechne das neue Intervall basierend auf ffr.getTime()
|
||||
delay[0] = ffr.getTime();
|
||||
|
||||
@ -64,8 +61,6 @@ public class Main {
|
||||
|
||||
// Plane die erste Ausführung der Aufgabe
|
||||
scheduledFuture.set(scheduler.schedule(task, delay[0], TimeUnit.SECONDS));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,23 +2,23 @@ package de.ocame.ffdiscordbot;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class StoryOutputText {
|
||||
public class OutputContentElement {
|
||||
|
||||
private final String message;
|
||||
private final String image;
|
||||
private final Color color;
|
||||
|
||||
public StoryOutputText(String message) {
|
||||
public OutputContentElement(String message) {
|
||||
this.message = message;
|
||||
this.image = null;
|
||||
this.color = new Color(36, 153, 245);
|
||||
}
|
||||
public StoryOutputText(String message, String image) {
|
||||
public OutputContentElement(String message, String image) {
|
||||
this.message = message;
|
||||
this.image = image;
|
||||
this.color = new Color(36, 153, 245);
|
||||
}
|
||||
public StoryOutputText(String message, String image, Color color) {
|
||||
public OutputContentElement(String message, String image, Color color) {
|
||||
this.message = message;
|
||||
this.image = image;
|
||||
this.color = color;
|
||||
@ -123,7 +123,7 @@ public class SQLiteStorage {
|
||||
}
|
||||
|
||||
|
||||
public static boolean checkStory(String ffid) {
|
||||
public static boolean isStoryInvalid(String ffid) {
|
||||
|
||||
String sql = "SELECT COUNT(*) FROM Storys WHERE ffid = ?";
|
||||
|
||||
@ -132,13 +132,13 @@ public class SQLiteStorage {
|
||||
|
||||
if (rs.next()) {
|
||||
int count = rs.getInt(1);
|
||||
return count > 0; // Gibt true zurück, wenn die ID existiert, sonst false
|
||||
return count <= 0; // Gibt true zurück, wenn die ID existiert, sonst false
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean checkChapter(String ffid, long number) {
|
||||
@ -215,25 +215,6 @@ public class SQLiteStorage {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
createTable();
|
||||
|
||||
/* DataStory record1 = new DataStory("Text 1", "https://link1.com", "Text 2");
|
||||
DataStory record2 = new DataStory("Text 3", "https://link2.com", "Text 4");
|
||||
|
||||
// Insert data into SQLite
|
||||
insertData(record1);
|
||||
insertData(record2);
|
||||
|
||||
// Load data from SQLite
|
||||
List<DataStory> loadedData = loadData();
|
||||
for (DataStory record : loadedData) {
|
||||
System.out.println(record);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private static int executeUpdateWithRetry(Connection conn, String sql, Object... params) throws SQLException {
|
||||
int attempt = 0;
|
||||
boolean success = false;
|
||||
@ -291,11 +272,13 @@ public class SQLiteStorage {
|
||||
System.out.println("Datenbank gesperrt, versuche erneut... (Versuch " + attempt + " von " + MAX_RETRIES + ")");
|
||||
try {
|
||||
Thread.sleep(RETRY_WAIT_TIME_MS);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new SQLException("Der Thread wurde unterbrochen.", ie);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw e; // Andere SQL-Fehler weiterwerfen
|
||||
}
|
||||
}
|
||||
@ -328,13 +311,14 @@ public class SQLiteStorage {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<StoryOutputText> getChapterTexte(DataStory ds) {
|
||||
public static List<OutputContentElement> getChapterTexte(DataStory ds) {
|
||||
String sql = """
|
||||
SELECT\s
|
||||
CT.id,
|
||||
@ -359,10 +343,10 @@ public class SQLiteStorage {
|
||||
try (Connection conn = DriverManager.getConnection(DB_URL)) {
|
||||
ResultSet rs = executeQueryWithRetry(conn, sql, ds.tagId());
|
||||
|
||||
List<StoryOutputText> outputList = new ArrayList<>();
|
||||
List<OutputContentElement> outputList = new ArrayList<>();
|
||||
|
||||
if (rs.next()) {
|
||||
outputList.add(new StoryOutputText(
|
||||
while (rs.next()) {
|
||||
outputList.add(new OutputContentElement(
|
||||
rs.getString("chapterText"),
|
||||
rs.getString("imageUrl"),
|
||||
Color.decode(rs.getString("color")))
|
||||
@ -370,14 +354,15 @@ public class SQLiteStorage {
|
||||
}
|
||||
return outputList;
|
||||
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<StoryOutputText> getChapterTexte(int ctId) {
|
||||
public static List<OutputContentElement> getChapterTexte(int ctId) {
|
||||
String sql = """
|
||||
SELECT\s
|
||||
CT.id,
|
||||
@ -394,10 +379,10 @@ public class SQLiteStorage {
|
||||
try (Connection conn = DriverManager.getConnection(DB_URL)) {
|
||||
ResultSet rs = executeQueryWithRetry(conn, sql, ctId);
|
||||
|
||||
List<StoryOutputText> outputList = new ArrayList<>();
|
||||
List<OutputContentElement> outputList = new ArrayList<>();
|
||||
|
||||
if (rs.next()) {
|
||||
outputList.add(new StoryOutputText(
|
||||
while (rs.next()) {
|
||||
outputList.add(new OutputContentElement(
|
||||
rs.getString("chapterText"),
|
||||
rs.getString("imageUrl"),
|
||||
Color.decode(rs.getString("color")))
|
||||
@ -405,14 +390,15 @@ public class SQLiteStorage {
|
||||
}
|
||||
return outputList;
|
||||
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<StoryOutputText> getStoryTexte() {
|
||||
public static List<OutputContentElement> getStoryTexte() {
|
||||
String sql = """
|
||||
SELECT\s
|
||||
CT.id,
|
||||
@ -428,10 +414,10 @@ public class SQLiteStorage {
|
||||
try (Connection conn = DriverManager.getConnection(DB_URL)) {
|
||||
ResultSet rs = executeQueryWithRetry(conn, sql);
|
||||
|
||||
List<StoryOutputText> outputList = new ArrayList<>();
|
||||
List<OutputContentElement> outputList = new ArrayList<>();
|
||||
|
||||
if (rs.next()) {
|
||||
outputList.add(new StoryOutputText(
|
||||
while (rs.next()) {
|
||||
outputList.add(new OutputContentElement(
|
||||
rs.getString("storyText"),
|
||||
rs.getString("imageUrl"),
|
||||
Color.decode(rs.getString("color")))
|
||||
@ -439,7 +425,8 @@ public class SQLiteStorage {
|
||||
}
|
||||
return outputList;
|
||||
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
@ -447,11 +434,4 @@ public class SQLiteStorage {
|
||||
}
|
||||
}
|
||||
|
||||
record DataStory(String name, String link, String ffid, long date, String author, Integer tagId) {
|
||||
|
||||
}
|
||||
record DataChapter(String name, String link, String storyId, long date, long number) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -37,24 +37,47 @@ class SocketServerRunnable implements Runnable {
|
||||
JSONObject jsonData = new JSONObject(jsonMessageFromClient);
|
||||
String action = jsonData.getString("action");
|
||||
|
||||
switch (action) {
|
||||
case "channelCheck" -> {
|
||||
if (channelCheckAction(jsonData, out))
|
||||
continue;
|
||||
}
|
||||
case "check" -> checkAction(out);
|
||||
case "chapterTest" -> chapterTest(jsonData, out);
|
||||
case "addFavo" -> addFavo(jsonData);
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException | NullPointerException e) {
|
||||
System.out.println("Fehler bei der Kommunikation mit dem Client: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("Server konnte nicht gestartet werden: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
private Boolean channelCheckAction(JSONObject jsonData, PrintWriter out) {
|
||||
JSONObject jsonResponse= new JSONObject();
|
||||
Long channelId = null;
|
||||
|
||||
if(action.equals("channelCheck")) {
|
||||
Object channelIdObj = jsonData.get("channelId");
|
||||
if(channelIdObj.equals("")) {
|
||||
jsonResponse.put("status", "fail");
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (channelIdObj instanceof Number) {
|
||||
channelId = ((Number) channelIdObj).longValue();
|
||||
} else if (channelIdObj instanceof String) {
|
||||
}
|
||||
else if (channelIdObj instanceof String) {
|
||||
String channelIdStr = (String) channelIdObj;
|
||||
channelId = Long.parseLong(channelIdStr);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
jsonResponse.put("status", "fail");
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
String response = "";
|
||||
@ -69,36 +92,30 @@ class SocketServerRunnable implements Runnable {
|
||||
else {
|
||||
jsonResponse.put("status", "fail");
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
jsonResponse.put("status", "error");
|
||||
}
|
||||
|
||||
out.println(jsonResponse);
|
||||
return false;
|
||||
}
|
||||
else if(action.equals("check")) {
|
||||
private void checkAction(PrintWriter out) {
|
||||
ffr.checkAlerts();
|
||||
jsonResponse.put("status", "success");
|
||||
out.println(jsonResponse);
|
||||
out.println( new JSONObject().put("status", "success"));
|
||||
}
|
||||
else if(action.equals("chapterTest")) {
|
||||
private void chapterTest(JSONObject jsonData, PrintWriter out) {
|
||||
String storyName = jsonData.getString("storyName");
|
||||
String chapterName = jsonData.getString("chapterName");
|
||||
String author = jsonData.getString("author");
|
||||
Integer id = jsonData.getInt("id");
|
||||
int id = jsonData.getInt("id");
|
||||
Long target = jsonData.getLong("target");
|
||||
|
||||
|
||||
ffr.outputCheapterTester(id, chapterName, storyName, author, target);
|
||||
jsonResponse.put("status", "success");
|
||||
out.println(jsonResponse);
|
||||
out.println( new JSONObject().put("status", "success"));
|
||||
}
|
||||
|
||||
} catch (IOException | NullPointerException e) {
|
||||
System.out.println("Fehler bei der Kommunikation mit dem Client: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("Server konnte nicht gestartet werden: " + e.getMessage());
|
||||
}
|
||||
private void addFavo(JSONObject jsonData) {
|
||||
String ffId = jsonData.getString("ffId");
|
||||
ffr.addStoryToFavorit(ffId);
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,12 @@
|
||||
package de.ocame.ffdiscordbot;
|
||||
package de.ocame.ffdiscordbot.fetcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.net.URI;
|
||||
import java.net.*;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
import java.net.CookieStore;
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -21,16 +16,13 @@ import com.google.gson.reflect.TypeToken;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
|
||||
|
||||
public class HtmlFetcher {
|
||||
public class DefaultHtmlFetcher implements HtmlFetcher {
|
||||
|
||||
private final HttpClient client;
|
||||
private final CookieManager cookieManager;
|
||||
private static final String COOKIE_FILE = "cookies.json";
|
||||
|
||||
public HtmlFetcher() {
|
||||
public DefaultHtmlFetcher() {
|
||||
cookieManager = new CookieManager();
|
||||
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
|
||||
client = HttpClient.newBuilder()
|
||||
@ -42,10 +34,12 @@ public class HtmlFetcher {
|
||||
loadCookies();
|
||||
}
|
||||
|
||||
public Document fetchURL(String url) throws IOException, InterruptedException, URISyntaxException {
|
||||
return fetchURL(url, "");
|
||||
@Override
|
||||
public Document fetchHtml(String url) throws IOException, InterruptedException {
|
||||
return fetchHtml(url, null);
|
||||
}
|
||||
public Document fetchURL(String url, String postData) throws IOException, InterruptedException, URISyntaxException {
|
||||
|
||||
public Document fetchHtml(String url, String postData) throws IOException, InterruptedException {
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url))
|
||||
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0")
|
||||
@ -60,19 +54,12 @@ public class HtmlFetcher {
|
||||
// Wenn postData nicht leer ist, füge die POST-Daten hinzu
|
||||
requestBuilder
|
||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||
.POST(BodyPublishers.ofString(postData));
|
||||
.POST(HttpRequest.BodyPublishers.ofString(postData));
|
||||
}
|
||||
|
||||
HttpRequest request = requestBuilder.build();
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
// Print cookies if any
|
||||
CookieStore cookieStore = cookieManager.getCookieStore();
|
||||
List<HttpCookie> cookies = cookieStore.getCookies();
|
||||
/*for (HttpCookie cookie : cookies) {
|
||||
System.out.println("Cookie: " + cookie);
|
||||
}*/
|
||||
|
||||
// Save cookies
|
||||
saveCookies();
|
||||
|
||||
@ -108,6 +95,17 @@ public class HtmlFetcher {
|
||||
}
|
||||
}
|
||||
|
||||
public String getCookieValue(String uri, String cookieName) {
|
||||
CookieStore cookieStore = cookieManager.getCookieStore();
|
||||
List<HttpCookie> cookies = cookieStore.get(URI.create(uri));
|
||||
for (HttpCookie cookie : cookies) {
|
||||
if (cookie.getName().equals(cookieName)) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
return null; // Cookie wurde nicht gefunden
|
||||
}
|
||||
|
||||
private static class SerializableCookie {
|
||||
private String uri;
|
||||
private String name;
|
||||
@ -139,19 +137,4 @@ public class HtmlFetcher {
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
|
||||
public CookieManager getCookieManager() {
|
||||
return cookieManager;
|
||||
}
|
||||
|
||||
public String getCookieValue(String uri, String cookieName) {
|
||||
CookieStore cookieStore = cookieManager.getCookieStore();
|
||||
List<HttpCookie> cookies = cookieStore.get(URI.create(uri));
|
||||
for (HttpCookie cookie : cookies) {
|
||||
if (cookie.getName().equals(cookieName)) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
return null; // Cookie wurde nicht gefunden
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package de.ocame.ffdiscordbot.fetcher;
|
||||
|
||||
import org.jsoup.nodes.Document;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
public interface HtmlFetcher {
|
||||
Document fetchHtml(String url) throws IOException, InterruptedException;
|
||||
}
|
||||
132
src/main/java/de/ocame/ffdiscordbot/output/BaseNotifier.java
Normal file
132
src/main/java/de/ocame/ffdiscordbot/output/BaseNotifier.java
Normal file
@ -0,0 +1,132 @@
|
||||
package de.ocame.ffdiscordbot.output;
|
||||
|
||||
import de.ocame.ffdiscordbot.DataStory;
|
||||
import de.ocame.ffdiscordbot.OutputContentElement;
|
||||
import de.ocame.ffdiscordbot.SQLiteStorage;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
// Basisklasse für Benachrichtigungen
|
||||
public abstract class BaseNotifier <T extends BaseNotifier<T>> {
|
||||
protected final JDA jda;
|
||||
private Integer version;
|
||||
|
||||
public void setStory(DataStory story) {
|
||||
this.story = story;
|
||||
}
|
||||
|
||||
private DataStory story;
|
||||
private Long targetChannel;
|
||||
|
||||
public BaseNotifier(JDA jda) {
|
||||
this.jda = jda;
|
||||
}
|
||||
|
||||
// Allgemeine Benachrichtigungsmethode
|
||||
public void sendOutput(Long targetChannel) {
|
||||
this.targetChannel = targetChannel;
|
||||
sendOutput();
|
||||
}
|
||||
|
||||
public void sendOutput() {
|
||||
EmbedBuilder outputBox = createEmbed();
|
||||
Long[] channelIds = SQLiteStorage.getChannelIds();
|
||||
if(targetChannel != null) {
|
||||
Objects.requireNonNull(jda.getTextChannelById(targetChannel))
|
||||
// .sendMessage("Hier ist ein Text vor dem Embed <@&423156046115242005> :")
|
||||
// .setEmbeds(outputBox.build())
|
||||
.sendMessageEmbeds(outputBox.build())
|
||||
.queue();
|
||||
}
|
||||
else if(Objects.requireNonNull(channelIds).length == 0) {
|
||||
Objects.requireNonNull(jda.getTextChannelById(542202034330271759L)).sendMessageEmbeds(outputBox.build()).queue();
|
||||
}
|
||||
else {
|
||||
for (Long channelId : channelIds ) {
|
||||
try {
|
||||
if (Objects.requireNonNull(jda.getTextChannelById(channelId)).canTalk())
|
||||
Objects.requireNonNull(jda.getTextChannelById(channelId)).sendMessageEmbeds(outputBox.build()).queue();
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Abstrakte Methode, um den spezifischen Titel zu liefern
|
||||
protected abstract String getEmbedTitle();
|
||||
|
||||
// Abstrakte Methode zur Lieferung der Platzhalter und deren Ersetzungen
|
||||
protected abstract Map<String, String> getMessagePlaceholders();
|
||||
|
||||
// Abstrakte Methode zur Lieferung des Links (falls erforderlich)
|
||||
protected abstract String getLink();
|
||||
|
||||
// Methode zum Erstellen des Embeds, die Platzhalter verwendet
|
||||
protected EmbedBuilder createEmbed() {
|
||||
EmbedBuilder outputBox = new EmbedBuilder();
|
||||
OutputContentElement outputContentElement = getOCE();
|
||||
|
||||
// Titel und Link von der spezifischen Implementierung holen
|
||||
outputBox.setTitle(getEmbedTitle(), getLink())
|
||||
.setColor(outputContentElement.getColor());
|
||||
|
||||
// Nachricht holen und Platzhalter ersetzen
|
||||
String message = outputContentElement.getMessage();
|
||||
for (Map.Entry<String, String> entry : getMessagePlaceholders().entrySet()) {
|
||||
message = message.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
outputBox.setDescription(message);
|
||||
|
||||
// Zeitformatierung und Footer
|
||||
Instant instant = Instant.ofEpochSecond(getDate());
|
||||
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.of("Europe/Berlin"));
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy HH:mm 'Uhr'");
|
||||
outputBox.setFooter("Veröffentlicht am " + dateTime.format(formatter));
|
||||
|
||||
// Thumbnail setzen, falls vorhanden
|
||||
if (outputContentElement.getImage() != null && !Objects.equals(outputContentElement.getImage(), "")) {
|
||||
outputBox.setThumbnail(outputContentElement.getImage());
|
||||
}
|
||||
|
||||
return outputBox;
|
||||
}
|
||||
|
||||
// Methode zur Auswahl eines OutputContentElement, kann auch einheitlich gehalten werden
|
||||
protected OutputContentElement getOCE() {
|
||||
List<OutputContentElement> chapterTexte;
|
||||
if(version != null) {
|
||||
chapterTexte = SQLiteStorage.getChapterTexte(version);
|
||||
}
|
||||
else {
|
||||
chapterTexte = SQLiteStorage.getChapterTexte(story);
|
||||
}
|
||||
|
||||
assert chapterTexte != null;
|
||||
if(chapterTexte.isEmpty())
|
||||
return null;
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
return chapterTexte.get(random.nextInt(chapterTexte.size()));
|
||||
}
|
||||
|
||||
// Abstrakte Methode zur Rückgabe des Zeitstempels
|
||||
protected abstract long getDate();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T setVersion(Integer version) {
|
||||
this.version = version;
|
||||
return (T) this;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package de.ocame.ffdiscordbot.output;
|
||||
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import de.ocame.ffdiscordbot.DataChapter;
|
||||
import de.ocame.ffdiscordbot.DataStory;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
// Handles notifications about new chapters
|
||||
public class ChapterNotifier extends BaseNotifier<ChapterNotifier> {
|
||||
|
||||
private DataChapter chapter;
|
||||
private DataStory story;
|
||||
|
||||
public ChapterNotifier(JDA jda, DataChapter chapter, DataStory story) {
|
||||
super(jda);
|
||||
this.chapter = chapter;
|
||||
this.story = story;
|
||||
super.setStory(story);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getEmbedTitle() {
|
||||
return "Neues Kapitel:";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getMessagePlaceholders() {
|
||||
return Map.of(
|
||||
"%chapterName%", "**" + chapter.name() + "**",
|
||||
"%storyName%", "**" + story.name() + "**",
|
||||
"%autor%", "**" + story.author() + "**"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLink() {
|
||||
return chapter.link();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getDate() {
|
||||
return chapter.date();
|
||||
}
|
||||
|
||||
}
|
||||
54
src/main/java/de/ocame/ffdiscordbot/output/InfoNotifier.java
Normal file
54
src/main/java/de/ocame/ffdiscordbot/output/InfoNotifier.java
Normal file
@ -0,0 +1,54 @@
|
||||
package de.ocame.ffdiscordbot.output;
|
||||
|
||||
import de.ocame.ffdiscordbot.ConfigLoader;
|
||||
import de.ocame.ffdiscordbot.OutputContentElement;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
public class InfoNotifier extends BaseNotifier<InfoNotifier> {
|
||||
|
||||
private String messagetext;
|
||||
|
||||
public InfoNotifier(JDA jda) {
|
||||
super(jda);
|
||||
this.sendOutput(new ConfigLoader().getDebugChannel() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected String getEmbedTitle() {
|
||||
return "Problem:";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getMessagePlaceholders() {
|
||||
return Map.of(
|
||||
"%storyName%", ""
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLink() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getDate() {
|
||||
return Instant.now().getEpochSecond();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputContentElement getOCE() {
|
||||
return new OutputContentElement("Fehler " + messagetext);
|
||||
}
|
||||
|
||||
public InfoNotifier setMessagetext(String messagetext) {
|
||||
this.messagetext = messagetext;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package de.ocame.ffdiscordbot.output;
|
||||
|
||||
import de.ocame.ffdiscordbot.OutputContentElement;
|
||||
import de.ocame.ffdiscordbot.SQLiteStorage;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import de.ocame.ffdiscordbot.DataStory;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
// Handles notifications about new stories
|
||||
public class StoryNotifier extends BaseNotifier<StoryNotifier> {
|
||||
|
||||
private final DataStory story;
|
||||
|
||||
public StoryNotifier(JDA jda, DataStory story) {
|
||||
super(jda);
|
||||
this.story = story;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getEmbedTitle() {
|
||||
return "Neue Geschichte:";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getMessagePlaceholders() {
|
||||
return Map.of(
|
||||
"%storyName%", "**" + story.name() + "**",
|
||||
"%autor%", "**" + story.author() + "**"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLink() {
|
||||
return story.link();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getDate() {
|
||||
return story.date();
|
||||
}
|
||||
|
||||
// Methode zur Auswahl eines OutputContentElement, kann auch einheitlich gehalten werden
|
||||
@Override
|
||||
protected OutputContentElement getOCE() {
|
||||
List<OutputContentElement> storyTexte;
|
||||
storyTexte = SQLiteStorage.getStoryTexte();
|
||||
|
||||
assert storyTexte != null;
|
||||
if(storyTexte.isEmpty())
|
||||
return null;
|
||||
|
||||
Random random = new Random();
|
||||
return storyTexte.get(random.nextInt(storyTexte.size()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user