From 72d562994ea3ee73a22abbd27f1a8e2117eb7a14 Mon Sep 17 00:00:00 2001 From: Flameish Date: Thu, 9 Jul 2020 01:52:26 +0200 Subject: [PATCH] 2.8.0 --- README.md | 2 + src/files/about.txt | 11 +- src/files/images/download_icon.png | Bin 0 -> 211 bytes src/files/images/starred_icon.png | Bin 0 -> 364 bytes src/files/images/unstarred_icon.png | Bin 0 -> 478 bytes src/grabber/Chapter.java | 10 +- src/grabber/Driver.java | 2 +- src/grabber/EPUB.java | 41 +- src/grabber/GrabberUtils.java | 8 +- src/grabber/Metadata.java | 23 +- src/grabber/Novel.java | 12 +- src/gui/GUI.form | 938 +++++++++++++++++-------- src/gui/GUI.java | 404 ++++++++++- src/library/LibrarySystem.java | 66 ++ src/scripts/ChapterLists.java | 2 +- src/scripts/ChapterListsHeadless.java | 2 +- src/scripts/Logins.java | 4 +- src/system/Accounts.java | 48 -- src/system/Config.java | 40 +- src/system/Notification.java | 104 +++ src/system/init.java | 43 +- src/system/persistent/Accounts.java | 32 + src/system/persistent/EmailConfig.java | 86 +++ src/system/persistent/Library.java | 185 +++++ src/system/persistent/Settings.java | 67 ++ 25 files changed, 1698 insertions(+), 432 deletions(-) create mode 100644 src/files/images/download_icon.png create mode 100644 src/files/images/starred_icon.png create mode 100644 src/files/images/unstarred_icon.png create mode 100644 src/library/LibrarySystem.java delete mode 100644 src/system/Accounts.java create mode 100644 src/system/Notification.java create mode 100644 src/system/persistent/Accounts.java create mode 100644 src/system/persistent/EmailConfig.java create mode 100644 src/system/persistent/Library.java create mode 100644 src/system/persistent/Settings.java diff --git a/README.md b/README.md index 5f8f328..4298c7e 100644 --- a/README.md +++ b/README.md @@ -108,3 +108,5 @@ Novel Grabber was build in java with:
* [epublib](https://github.com/psiegman/epublib) * [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) * [selenium ](https://selenium.dev/) + * [Simple Java Mail ](https://github.com/bbottema/simple-java-mail/) + diff --git a/src/files/about.txt b/src/files/about.txt index 01ec821..4b45854 100644 --- a/src/files/about.txt +++ b/src/files/about.txt @@ -24,8 +24,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CREDITS: - - json.simple https://code.google.com/archive/p/json-simple/ - - jsoup https://jsoup.org/ - - webdrivermanager https://github.com/bonigarcia/webdrivermanager - - selenium https://selenium.dev/ - - Images https://icons8.com/ \ No newline at end of file + * [jsoup](https://www.jsoup.org/) + * [json-simple](https://code.google.com/archive/p/json-simple/) + * [epublib](https://github.com/psiegman/epublib) + * [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) + * [selenium ](https://selenium.dev/) + * [Simple Java Mail ](https://github.com/bbottema/simple-java-mail/) diff --git a/src/files/images/download_icon.png b/src/files/images/download_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cb872b366676356e3381d91a4580058227a6e3da GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt@~o-U3d z9-VKeIC3>82)M@IRb2V|8f*5&(4tUjb{&%~$6BwnGrCs#hp_FN#JSFZ4e^tkEYj%B({(+_T`GUhmHWjvk5&i%wPZMBXJN!uz5X@OO$?r{elF{r G5}E*-Vp0MC literal 0 HcmV?d00001 diff --git a/src/files/images/starred_icon.png b/src/files/images/starred_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bd3c00aedcf59ee5b73804f2fda07672df44fced GIT binary patch literal 364 zcmV-y0h9iTP)7%OTXNj=YE4O5toS;ZU{bNa7v zi$}C#wsC>`uf;bRDF@|sBAPyfv!d+=;5=_(5AQ!n-o<{A`#N3*5bt24>=x^ygDWfE z#%fvd1dRZLMxIE&i?$FDrZ$MdN`OH~Eustfr2L4U3&MUwEkmS*&6ur>_1rOKp_yvz z;#lbyrt^4LkxD~rc2Q$n}>Q_)5A`PK?U>5%{8R<58?yI0g0Ex?jrvH0000< KMNUMnLSTY=i=CAK literal 0 HcmV?d00001 diff --git a/src/files/images/unstarred_icon.png b/src/files/images/unstarred_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..09c71339451c4f8a327cdf74f6daeeca7e484506 GIT binary patch literal 478 zcmV<40U`d0P)wzphygWbEq3nR<9c&40>820R$_nn!uJ9GHQ za5k(q+6@zo<61*aZM5(f?=>&17A_+TyHr=yq>}L+)_Z~jSXG?hGY;-$g3$=Ph^1JM z)DiAa)-4>3^&xqMZ5+Ww?9asWJZ|A5Hn5HF*bM)A6w$@)AY^^)7f#_Mwko(kF%?C3 zaSZ2r<48V;C6H?5vwPT;dv0Za9{sUYhe;ULh}lPefV9`l>C!qc!Gf* zyu)}HoNYY7zN+9Ut|(e_u7`gvd~3M6Q;>egf0hJZNcip2-XlD%RdNX}c^hW(8}u|@ zVjgF3E_|Pqx}`2IM1T(%!xu%Te3Sp&ckw>Fn*{e1J>3aB8" + NL + htmlFoot); novel.extraPages.add(fileName); } catch (IOException e) { - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.appendText(novel.options.window,e.getMessage()); } @@ -215,7 +236,7 @@ public void createToc() { out.print("

" + NL + htmlFoot); novel.extraPages.add(fileName); } catch (IOException e) { - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.appendText(novel.options.window,e.getMessage()); } @@ -232,7 +253,7 @@ public void createDescPage() { out.print("" + NL + htmlFoot); novel.extraPages.add(fileName); } catch (IOException e) { - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.appendText(novel.options.window,e.getMessage()); } e.printStackTrace(); diff --git a/src/grabber/GrabberUtils.java b/src/grabber/GrabberUtils.java index a006684..077d2aa 100644 --- a/src/grabber/GrabberUtils.java +++ b/src/grabber/GrabberUtils.java @@ -56,13 +56,13 @@ static void downloadImage(String src, Novel currGrab) { currGrab.imageLinks.add(src); currGrab.imageNames.add(name); - if(init.window != null) { + if(init.window != null && !currGrab.options.window.equals("checker")) { init.window.appendText(currGrab.options.window, "[INFO]" + name + " saved."); } //General catch } catch (Throwable e) { e.printStackTrace(); - if(init.window != null) { + if(init.window != null && !currGrab.options.window.equals("checker")) { init.window.appendText(currGrab.options.window, "[ERROR]Failed to save " + name); } } @@ -115,7 +115,7 @@ static BufferedImage getBufferedCover(String src, Novel novel) { //General catch } catch (Throwable e) { e.printStackTrace(); - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.appendText("auto", "[ERROR]Failed to get" + name); } } @@ -158,7 +158,7 @@ public static int ordinalIndexOf(String str, String substr, int n) { /** * Freeze thread for selected wait time. */ - static void sleep(int waitTime) { + public static void sleep(int waitTime) { try { Thread.sleep(waitTime); } catch (InterruptedException ex) { diff --git a/src/grabber/Metadata.java b/src/grabber/Metadata.java index 2e55674..4ad14e1 100644 --- a/src/grabber/Metadata.java +++ b/src/grabber/Metadata.java @@ -36,19 +36,18 @@ void getTitle() { if (!novel.host.bookTitleSelector.isEmpty()) { if (novel.tableOfContent.select(novel.host.bookTitleSelector) != null && !novel.tableOfContent.select(novel.host.bookTitleSelector).isEmpty()) { bookTitle = novel.tableOfContent.select(novel.host.bookTitleSelector).first().text().replaceAll("[\\\\/:*?\"<>|]", ""); - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoBookTitle.setText(bookTitle); } } else { bookTitle = "Unknown"; - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoBookTitle.setText("Unknown"); - } } } else { bookTitle = "Unknown"; - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoBookTitle.setText("Unknown"); } } @@ -71,18 +70,18 @@ void getAuthor() { if (!novel.host.bookAuthorSelector.isEmpty()) { if (novel.tableOfContent.select(novel.host.bookAuthorSelector) != null && !novel.tableOfContent.select(novel.host.bookAuthorSelector).isEmpty()) { bookAuthor = novel.tableOfContent.select(novel.host.bookAuthorSelector).first().text(); - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoAuthor.setText(bookAuthor); } } else { bookAuthor = "Unknown"; - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoAuthor.setText("Unknown"); } } } else { bookAuthor = "Unknown"; - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoAuthor.setText("Unknown"); } } @@ -98,7 +97,7 @@ void getTags() { // Display book subjects on GUI int maxNumberOfSubjects = 0; - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoBookSubjects.setText(""); for (String eachTag : bookSubjects) { init.window.autoBookSubjects.setText(init.window.autoBookSubjects.getText() + eachTag + ", "); @@ -116,14 +115,14 @@ void getTags() { } } else { bookSubjects.add("Unknown"); - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoBookSubjects.setText("Unknown"); } } } else { bookSubjects.add("Unknown"); - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoBookSubjects.setText("Unknown"); } } @@ -131,7 +130,7 @@ void getTags() { void getChapterNumber() { if (!novel.chapters.isEmpty()) { - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.autoChapterAmount.setText(String.valueOf(novel.chapters.size())); init.window.autoGetNumberButton.setEnabled(true); } @@ -154,7 +153,7 @@ void getCover() { } bufferedCover = GrabberUtils.getBufferedCover(coverLink, novel); if(!novel.imageNames.isEmpty()) { - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.setBufferedCover(bufferedCover); } bookCover = novel.imageNames.get(0); diff --git a/src/grabber/Novel.java b/src/grabber/Novel.java index 738318c..a512be7 100644 --- a/src/grabber/Novel.java +++ b/src/grabber/Novel.java @@ -33,7 +33,7 @@ public class Novel { List extraPages = new ArrayList<>(); List imageLinks = new ArrayList<>(); List imageNames = new ArrayList<>(); - + public String epubFilename; public Novel() { } @@ -59,7 +59,7 @@ public void getChapterList() { public void downloadChapters() throws Exception { System.out.println("[INFO]Starting download..."); - if(init.window != null) { + if(init.window != null && !options.window.equals("checker")) { init.window.setMaxProgress(options.window, options.lastChapter-options.firstChapter+1); } if(reGrab) { @@ -85,7 +85,7 @@ public void downloadChapters() throws Exception { if (Files.exists(chaptersFolder)) GrabberUtils.deleteFolderAndItsContent(chaptersFolder); } catch (IOException e) { e.printStackTrace(); - if(init.window != null) { + if(init.window != null && !options.window.equals("checker")) { init.window.appendText(options.window, e.getMessage()); } } @@ -93,7 +93,7 @@ public void downloadChapters() throws Exception { } chapters.get(i).saveChapter(this); - if(init.window != null) { + if(init.window != null && !options.window.equals("checker")) { init.window.updateProgress(options.window); } @@ -117,14 +117,14 @@ public void getMetadata() { */ public void report() { System.out.println("[INFO]Output: "+options.saveLocation + " " + metadata.bookAuthor + " - " + metadata.bookTitle + ".epub"); - if(init.window != null) { + if(init.window != null && !options.window.equals("checker")) { init.window.appendText(options.window,"[INFO]Finished."); } if(options.invertOrder) Collections.reverse(chapters); // Print failed chapters for(Chapter chapter: chapters) { if(chapter.status == 2) - if(init.window != null) { + if(init.window != null && !options.window.equals("checker")) { init.window.appendText(options.window,"[WARN]Failed to grab: " +chapter.name); } } diff --git a/src/gui/GUI.form b/src/gui/GUI.form index 8fe3718..837a305 100644 --- a/src/gui/GUI.form +++ b/src/gui/GUI.form @@ -3,7 +3,7 @@ - + @@ -88,7 +88,7 @@ - + @@ -106,29 +106,9 @@ - + - - - - - - - - - - - - - - - - - - - - @@ -205,12 +185,35 @@ - + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -220,29 +223,39 @@ - + - + + + - - + + + + - + - + + - + - + - + - + + + + + + @@ -294,7 +307,7 @@ - + @@ -488,7 +501,7 @@ - + @@ -562,7 +575,7 @@ - + @@ -588,15 +601,7 @@ - - - - - - - - - + @@ -623,14 +628,6 @@ - - - - - - - - @@ -639,7 +636,7 @@ - + @@ -674,7 +671,7 @@ - + @@ -908,7 +905,7 @@ - + @@ -1056,295 +1053,648 @@ - + - + - - + - + - - - - + + - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + - + - - - + - - - - - - - - - - + + - + - - - - - - - - - - - - - - - - - - - + + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/gui/GUI.java b/src/gui/GUI.java index 75f7770..ab3297e 100644 --- a/src/gui/GUI.java +++ b/src/gui/GUI.java @@ -1,8 +1,12 @@ package gui; import grabber.*; -import system.Accounts; import system.Config; +import system.init; +import system.persistent.Accounts; +import system.persistent.EmailConfig; +import system.persistent.Library; +import system.persistent.Settings; import updater.Updater; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; @@ -13,6 +17,7 @@ import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; +import javax.swing.text.DefaultFormatter; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; @@ -26,32 +31,36 @@ import java.util.concurrent.Executors; public class GUI extends JFrame { - public static String versionNumber = "2.7.2"; + public static String versionNumber = "2.8.0"; private static final String[] headerlessBrowserWebsites = {"FicFun", "Dreame", "WuxiaWorld.site","FoxTeller"}; private static final String[] noHeaderlessBrowserWebsites = {"WattPad", "FanFiction", "FanFiktion"}; private static final String[] loginWebsites = {"Booklat","Wuxiaworld", "WattPad"}; + private static final String[] settingsMenus = {"Accounts","General", "Email", "Update"}; public static List headerlessBrowserWebsitesList = Arrays.asList(headerlessBrowserWebsites); public static List noHeaderlessBrowserWebsitesList = Arrays.asList(noHeaderlessBrowserWebsites); public static List loginWebsitesList = Arrays.asList(loginWebsites); public static DefaultListModel manLinkListModel = new DefaultListModel<>(); public static DefaultListModel accountWebsiteListModel = new DefaultListModel<>(); + public static DefaultListModel settingsMenuModel = new DefaultListModel<>(); public static List blacklistedTags = new ArrayList<>(); public static String[] chapterToChapterArgs = new String[3]; public static TrayIcon trayIcon; public static Integer chapterToChapterNumber = 1; private static String[] browserList = {"Chrome", "Firefox", "Edge", "Opera", "IE"}; + private static String[] epubFilenameFormats = {" - ", "<title> - <author>", "<title>"}; + private static String[] sslList = {"SMTP","SMTPS","SMTP TLS",}; private static MenuItem defaultItem0; private final String NL = System.getProperty("line.separator"); public static Novel autoNovel = null; public static ManNovel manNovel = null; public JComboBox autoHostSelection; public JTextField chapterListURL; - public JTextField saveLocation; + public JTextField autoSaveLocation; public JCheckBox chapterAllCheckBox; public JSpinner firstChapter; public JSpinner lastChapter; public JCheckBox toLastChapter; - public JCheckBox getImages; + public JCheckBox autoGetImages; public JCheckBox checkInvertOrder; public JTextField waitTime; public JProgressBar progressBar; @@ -99,7 +108,6 @@ public class GUI extends JFrame { private JScrollPane updateScrollPane; private JProgressBar manProgressBar; private JLabel updateStatusLbl; - private JPanel updateTab; private JLabel updateLogLbl; private JButton manGrabChaptersButton; private JButton manBlackListedTags; @@ -136,7 +144,7 @@ public class GUI extends JFrame { public JTextField autoChapterToChapterNumberField; public JCheckBox manUseHeaderlessBrowser; public JComboBox manBrowserCombobox; - public JCheckBox autoNoStyling; + public JCheckBox autoRemoveStyling; public JCheckBox manNoStyling; private JButton manAddChapterButton; private JList accountWebsiteList; @@ -145,6 +153,34 @@ public class GUI extends JFrame { private JButton accountAddBtn; private JScrollPane accountWebsiteScrollPane; public JCheckBox useAccountCheckBox; + private JList settingsMenuList; + private JScrollPane settingsMenuScrollPane; + private JPanel settingsAccountsPanel; + private JPanel settingsHeadlessPanel; + private JPanel settingsUpdatePanel; + private JCheckBox browserGUICheckBox; + private JButton emailSaveBtn; + private JComboBox settingsOutputFormatComboBox; + private JPanel settingsGeneralPanel; + private JCheckBox settingsAlwaysGetImagesCheckBox; + private JCheckBox settingsAlwaysRemoveStylingCheckBox; + private JTextField settingsSavelocationField; + private JButton settingsBrowseSaveLocationBtn; + private JCheckBox standardSaveLocationCheckBox; + private JButton autoStarredBtn; + private JPanel settingsTab; + private JPanel libraryTab; + private JPanel libraryPanel; + private JScrollPane libraryScrollPane; + private JPanel settingsEmailPanel; + private JTextField emailHostField; + private JTextField emailPortField; + private JTextField emailUserField; + private JTextField emailPasswordField; + private JComboBox emailSLLComboBox; + private JCheckBox sendNewChapterNotificationsCheckBox; + private JTextField emailReceiver; + private JCheckBox sendEPUBAsAttachmentCheckBox; private JButton manEditChapterOrder; public JTextArea autoBookDescArea; private JScrollPane autoBookDescScrollPane; @@ -170,6 +206,7 @@ public GUI() { options.hostname = autoHostSelection.getSelectedItem().toString(); options.novelLink = chapterListURL.getText(); options.useAccount = useAccountCheckBox.isSelected(); + options.headlessGUI = browserGUICheckBox.isSelected(); autoNovel = new Novel(options); // Needed @@ -183,6 +220,15 @@ public GUI() { pagesCountLbl.setText(""); pagesCountLbl.setVisible(false); pagesLbl.setVisible(false); + if(Library.isStarred(autoNovel.novelLink)) { + autoStarredBtn.setIcon(new ImageIcon(getClass().getResource("/files/images/starred_icon.png"))); + autoStarredBtn.setEnabled(true); + autoStarredBtn.setToolTipText("Remove novel from library"); + } else { + autoStarredBtn.setIcon(new ImageIcon(getClass().getResource("/files/images/unstarred_icon.png"))); + autoStarredBtn.setEnabled(true); + autoStarredBtn.setToolTipText("Add novel to library"); + } } autoBusyLabel.setVisible(false); } @@ -196,9 +242,9 @@ public GUI() { chapterListURL.requestFocusInWindow(); return; } - if (saveLocation.getText().isEmpty()) { + if (autoSaveLocation.getText().isEmpty()) { showPopup("Save directory field is empty.", "warning"); - saveLocation.requestFocusInWindow(); + autoSaveLocation.requestFocusInWindow(); return; } if ((!chapterAllCheckBox.isSelected()) && (!toLastChapter.isSelected()) @@ -238,7 +284,7 @@ public GUI() { stopButton.setVisible(true); try { // Needed - autoNovel.options.saveLocation = saveLocation.getText(); + autoNovel.options.saveLocation = autoSaveLocation.getText(); //Optional autoNovel.options.waitTime = Integer.parseInt(waitTime.getText()); autoNovel.options.displayChapterTitle = displayChapterTitleCheckBox.isSelected(); @@ -247,6 +293,7 @@ public GUI() { autoNovel.options.headless = useHeaderlessBrowserCheckBox.isSelected(); autoNovel.options.browser = autoBrowserCombobox.getSelectedItem().toString(); autoNovel.options.useAccount = useAccountCheckBox.isSelected(); + autoNovel.options.headlessGUI = browserGUICheckBox.isSelected(); // Set chapter range if(chapterAllCheckBox.isSelected()) { autoNovel.options.firstChapter = 1; @@ -288,7 +335,7 @@ public GUI() { chooser.setAcceptAllFileFilterUsed(false); if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { - saveLocation.setText(chooser.getSelectedFile().toString()); + autoSaveLocation.setText(chooser.getSelectedFile().toString()); } }); @@ -654,14 +701,283 @@ else if (manSaveLocation.getText().isEmpty()) { } }); // Add or Edit an account entry - accountAddBtn.addActionListener(actionEvent -> Accounts.addAccount( + accountAddBtn.addActionListener(actionEvent -> Accounts.setAccount( accountWebsiteListModel.get(accountWebsiteList.getSelectedIndex()), accountUsernameField.getText(), accountPasswordField.getText() )); + settingsMenuList.addListSelectionListener(listSelectionEvent -> { + String selectedMenu = settingsMenuModel.get(settingsMenuList.getSelectedIndex()); + settingsAccountsPanel.setVisible(false); + settingsHeadlessPanel.setVisible(false); + settingsUpdatePanel.setVisible(false); + settingsGeneralPanel.setVisible(false); + if(selectedMenu.equals("Accounts")) settingsAccountsPanel.setVisible(true); + if(selectedMenu.equals("Update")) settingsUpdatePanel.setVisible(true); + if(selectedMenu.equals("Email")) settingsEmailPanel.setVisible(true); + if(selectedMenu.equals("General")) { + settingsGeneralPanel.setVisible(true); + settingsHeadlessPanel.setVisible(true); + } + }); + browserGUICheckBox.addActionListener(actionEvent -> { + Settings.setHeadlessSettings(autoBrowserCombobox.getSelectedItem().toString(), browserGUICheckBox.isSelected()); + + }); + autoBrowserCombobox.addActionListener(actionEvent -> { + Settings.setHeadlessSettings(autoBrowserCombobox.getSelectedItem().toString(), browserGUICheckBox.isSelected()); + + }); + settingsAlwaysGetImagesCheckBox.addActionListener(actionEvent -> { + Settings.setGeneralSettings( + settingsAlwaysGetImagesCheckBox.isSelected(), + settingsAlwaysRemoveStylingCheckBox.isSelected(), + settingsOutputFormatComboBox.getSelectedIndex(), + settingsSavelocationField.getText(), + standardSaveLocationCheckBox.isSelected() + ); + }); + settingsAlwaysRemoveStylingCheckBox.addActionListener(actionEvent -> { + Settings.setGeneralSettings( + settingsAlwaysGetImagesCheckBox.isSelected(), + settingsAlwaysRemoveStylingCheckBox.isSelected(), + settingsOutputFormatComboBox.getSelectedIndex(), + settingsSavelocationField.getText(), + standardSaveLocationCheckBox.isSelected() + ); + }); + settingsOutputFormatComboBox.addActionListener(actionEvent -> { + Settings.setGeneralSettings( + settingsAlwaysGetImagesCheckBox.isSelected(), + settingsAlwaysRemoveStylingCheckBox.isSelected(), + settingsOutputFormatComboBox.getSelectedIndex(), + settingsSavelocationField.getText(), + standardSaveLocationCheckBox.isSelected() + ); + }); + standardSaveLocationCheckBox.addActionListener(actionEvent -> { + Settings.setGeneralSettings( + settingsAlwaysGetImagesCheckBox.isSelected(), + settingsAlwaysRemoveStylingCheckBox.isSelected(), + settingsOutputFormatComboBox.getSelectedIndex(), + settingsSavelocationField.getText(), + standardSaveLocationCheckBox.isSelected() + ); + + }); + settingsBrowseSaveLocationBtn.addActionListener(actionEvent -> { + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new File(".")); + chooser.setDialogTitle("Choose destination directory"); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + + if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { + settingsSavelocationField.setText(chooser.getSelectedFile().toString()); + } + }); + autoStarredBtn.addActionListener(actionEvent -> { + if(Library.isStarred(autoNovel.novelLink)) { + Library.removeStarred(autoNovel.novelLink); + autoStarredBtn.setIcon(new ImageIcon(getClass().getResource("/files/images/unstarred_icon.png"))); + } else { + Library.setStarred(autoNovel); + autoStarredBtn.setIcon(new ImageIcon(getClass().getResource("/files/images/starred_icon.png"))); + } + }); + tabbedPane.addChangeListener(e -> { + if(tabbedPane.getSelectedIndex() == 2) { + buildLibrary(); + } + }); + emailSaveBtn.addActionListener(actionEvent -> { + EmailConfig.saveEmailSettings( + emailHostField.getText(), + emailUserField.getText(), + emailPasswordField.getText(), + emailReceiver.getText(), + Integer.parseInt(emailPortField.getText()), + emailSLLComboBox.getSelectedIndex() + ); + }); + sendNewChapterNotificationsCheckBox.addActionListener(actionEvent -> EmailConfig.setNotifications(sendNewChapterNotificationsCheckBox.isSelected())); + sendEPUBAsAttachmentCheckBox.addActionListener(actionEvent -> EmailConfig.setUseAttachment(sendEPUBAsAttachmentCheckBox.isSelected())); } + public void buildLibrary() { + libraryPanel.setVisible(false); + libraryPanel.removeAll(); + libraryPanel.setVisible(true); + int gridRow = 0; + int gridCol = 0; + for(String novelUrl: Library.getLibrary()) { + JPanel novelPane = new JPanel(); + novelPane.setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + + JPanel infoPanel = new JPanel(); + + infoPanel.setLayout(new GridBagLayout()); + JLabel novelTitle = new JLabel(Library.getNovelTitle(novelUrl)); + novelTitle.setFont(new Font("Calibri", Font.BOLD, 17)); + + JLabel thresholdLbl = new JLabel("Threshold:"); + JSpinner thresholdSpinner = new JSpinner(); + thresholdSpinner.setValue(Library.getThreshold(novelUrl)); + JComponent comp = thresholdSpinner.getEditor(); + JFormattedTextField field = (JFormattedTextField) comp.getComponent(0); + field.setColumns(4); + DefaultFormatter formatter = (DefaultFormatter) field.getFormatter(); + formatter.setCommitsOnValidEdit(true); + thresholdSpinner.addChangeListener(e -> Library.setThreshold(novelUrl, (Integer) thresholdSpinner.getValue())); + + JCheckBox autoGrabbingCheckbox = new JCheckBox("Grab new chapters"); + autoGrabbingCheckbox.setSelected(Library.getAutoDownload(novelUrl)); + autoGrabbingCheckbox.setToolTipText("Automatically download chapters when threshold of new releases is met"); + autoGrabbingCheckbox.addActionListener(actionEvent -> { + Library.setAutoDownload(novelUrl, autoGrabbingCheckbox.isSelected()); + }); + JLabel lastChapter = new JLabel("Last chapter: "+ Library.getLastChapter(novelUrl)); + JLabel newestChapter = new JLabel("Newest chapter: "+ Library.getNewestChapter(novelUrl)); + + JButton changeCLIBtn = new JButton(new ImageIcon(getClass().getResource("/files/images/settings_icon.png"))); + changeCLIBtn.setBorder(BorderFactory.createEmptyBorder()); + changeCLIBtn.setContentAreaFilled(false); + changeCLIBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + changeCLIBtn.setToolTipText("Change the CLI command to adjust download parameters"); + changeCLIBtn.addActionListener(actionEvent -> { + String cli = JOptionPane.showInputDialog("Change cli command:",Library.getCLICommand(novelUrl)); + if(cli != null) { + Library.setCLICommand(novelUrl, cli); + } + }); + + JButton removeFromFavBtn = new JButton(new ImageIcon(getClass().getResource("/files/images/remove_icon.png"))); + removeFromFavBtn.setBorder(BorderFactory.createEmptyBorder()); + removeFromFavBtn.setContentAreaFilled(false); + removeFromFavBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + removeFromFavBtn.setToolTipText("Remove novel from library"); + removeFromFavBtn.addActionListener(actionEvent -> { + Library.removeStarred(novelUrl); + buildLibrary(); + }); + + JButton getLatestChapterBtn = new JButton(new ImageIcon(getClass().getResource("/files/images/download_icon.png"))); + getLatestChapterBtn.setBorder(BorderFactory.createEmptyBorder()); + getLatestChapterBtn.setContentAreaFilled(false); + getLatestChapterBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + getLatestChapterBtn.setToolTipText("Download chapters from last downloaded to latest"); + getLatestChapterBtn.addActionListener(actionEvent -> { + int lastDownloadedChapter = Integer.parseInt(lastChapter.getText().substring(lastChapter.getText().lastIndexOf(" ")+1)); + int lastestChapter = Integer.parseInt(newestChapter.getText().substring(newestChapter.getText().lastIndexOf(" ")+1)); + if(lastDownloadedChapter != lastestChapter) { + String cliString = Library.getCLICommand(novelUrl)+" -window checker -chapters "+(lastDownloadedChapter+1)+" "+lastestChapter; + String[] cliParams = cliString.split(" "); + init.processParams(init.getParamsFromString(cliParams)); + Library.setLastChapter(novelUrl, lastestChapter); + buildLibrary(); + } + }); + + JPanel imagePanel = new JPanel(); + imagePanel.setLayout(new GridBagLayout()); + + JLabel novelImage; + String novelCover = Config.home_path+ "/" + Config.home_folder + + "/"+ Library.getNovelTitle(novelUrl)+"/" + + Library.getBookCover(novelUrl); + if(novelCover.isEmpty()) { + novelImage = new JLabel(new ImageIcon(getClass().getResource("/files/images/cover_placeholder.png"))); + } else { + ImageIcon imageIcon = new ImageIcon(novelCover); // load the image to a imageIcon + Image image = imageIcon.getImage(); // transform it + Image newimg = image.getScaledInstance(100, 133, java.awt.Image.SCALE_SMOOTH); // scale it the smooth way + imageIcon = new ImageIcon(newimg); // transform it back + novelImage = new JLabel(imageIcon); + } + novelImage.setBorder(BorderFactory.createEmptyBorder()); + imagePanel.add(novelImage); + + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.gridx = 0; + gbc.gridy = 0; + infoPanel.add(novelTitle, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.NORTHEAST; + gbc.gridx = 1; + gbc.gridy = 0; + infoPanel.add(getLatestChapterBtn, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.NORTHEAST; + gbc.gridx = 2; + gbc.gridy = 0; + infoPanel.add(changeCLIBtn, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.NORTHEAST; + gbc.gridx = 3; + gbc.gridy = 0; + infoPanel.add(removeFromFavBtn, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.gridx = 0; + gbc.gridy = 1; + infoPanel.add(lastChapter, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.gridx = 0; + gbc.gridy = 2; + infoPanel.add(newestChapter, gbc); + + gbc.fill = GridBagConstraints.VERTICAL; + gbc.anchor = GridBagConstraints.SOUTHWEST; + gbc.gridx = 0; + gbc.gridy = 3; + infoPanel.add(autoGrabbingCheckbox, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.SOUTHWEST; + gbc.gridx = 0; + gbc.gridy = 4; + infoPanel.add(thresholdLbl, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.SOUTHWEST; + gbc.gridx = 1; + gbc.gridy = 4; + infoPanel.add(thresholdSpinner, gbc); + + gbc.fill = GridBagConstraints.NONE; + //gbc.anchor = GridBagConstraints.WEST; + gbc.gridx = 0; + gbc.gridy = 0; + novelPane.add(imagePanel, gbc); + + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.gridx = 1; + gbc.gridy = 0; + gbc.insets = new Insets( 0, 10, 0, 0); + novelPane.add(infoPanel, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.gridx = gridCol++ % 2 == 0 ? 0 : 1; + gbc.gridy = gridRow++ % 2 == 0 ? gridRow : gridRow-1; + gbc.weightx = 1.0; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.weighty = 1; + gbc.insets = new Insets( 10, 10, 10, 10); + libraryPanel.add(novelPane, gbc); + //libraryPanel.add(novelPane); + } + } + private void initialize() { add(rootPanel); setTitle("Novel-Grabber " + versionNumber); @@ -776,8 +1092,7 @@ public void appendText(String logWindow, String logMsg) { manLogArea.setCaretPosition(manLogArea.getText().length()); break; case "checker": - checkerLogArea.append(logMsg + NL); - checkerLogArea.setCaretPosition(checkerLogArea.getText().length()); + System.out.println(logMsg); break; case "update": updateTextArea.append(" - " + logMsg + NL); @@ -883,6 +1198,15 @@ private void createUIComponents() { autoHostSelection = new JComboBox(getWebsites()); autoBrowserCombobox = new JComboBox(browserList); + autoBrowserCombobox.setSelectedItem(Settings.getBrowser()); + + autoGetImages = new JCheckBox(); + autoGetImages.setSelected(Settings.getImages()); + + autoRemoveStyling = new JCheckBox(); + autoRemoveStyling.setSelected(Settings.getRemoveStyling()); + + autoSaveLocation = new JTextField(); autoChapterToChapterNumberField = new JTextField("Number"); autoChapterToChapterNumberField.setForeground(Color.GRAY); @@ -891,6 +1215,10 @@ private void createUIComponents() { autoShowBlacklistedTagsBtn.setBorder(BorderFactory.createEmptyBorder()); autoShowBlacklistedTagsBtn.setContentAreaFilled(false); + autoStarredBtn = new JButton(new ImageIcon(getClass().getResource("/files/images/unstarred_icon.png"))); + autoStarredBtn.setBorder(BorderFactory.createEmptyBorder()); + autoStarredBtn.setContentAreaFilled(false); + autoCheckAvailability = new JButton(new ImageIcon(getClass().getResource("/files/images/check_icon.png"))); autoCheckAvailability.setBorder(BorderFactory.createEmptyBorder()); autoCheckAvailability.setContentAreaFilled(false); @@ -999,15 +1327,61 @@ void change() { manWaitTime = new JTextField("0"); manWaitTime.setHorizontalAlignment(SwingConstants.CENTER); - // Account Tab + // Settins Tab + for(String settingsMenu: settingsMenus) { + settingsMenuModel.addElement(settingsMenu); + } + settingsMenuList = new JList<>(settingsMenuModel); + settingsMenuList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + settingsMenuScrollPane = new JScrollPane(settingsMenuList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + browserGUICheckBox = new JCheckBox(); + browserGUICheckBox.setSelected(Settings.getBrowserShowGUI()); + + settingsAlwaysGetImagesCheckBox = new JCheckBox(); + settingsAlwaysGetImagesCheckBox.setSelected(Settings.getImages()); + + settingsAlwaysRemoveStylingCheckBox = new JCheckBox(); + settingsAlwaysRemoveStylingCheckBox.setSelected(Settings.getRemoveStyling()); + + standardSaveLocationCheckBox = new JCheckBox(); + standardSaveLocationCheckBox.setSelected(Settings.getUseStandardLocation()); + + if(Settings.getUseStandardLocation()) { + autoSaveLocation.setText(Settings.getSavelocation()); + } + + settingsSavelocationField = new JTextField(); + settingsSavelocationField.setText(Settings.getSavelocation()); + + settingsBrowseSaveLocationBtn = new JButton(new ImageIcon(getClass().getResource("/files/images/folder_icon.png"))); + settingsBrowseSaveLocationBtn.setBorder(BorderFactory.createEmptyBorder()); + settingsBrowseSaveLocationBtn.setContentAreaFilled(false); + + settingsOutputFormatComboBox = new JComboBox(epubFilenameFormats); + settingsOutputFormatComboBox.setSelectedIndex(Settings.getEPUBOutputFormat()); + accountPasswordField = new JPasswordField(); for(String accountDomain: loginWebsitesList) { accountWebsiteListModel.addElement(accountDomain); } accountWebsiteList = new JList<>(accountWebsiteListModel); - manLinkList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + accountWebsiteList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); accountWebsiteScrollPane = new JScrollPane(accountWebsiteList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + // Email settings + emailHostField = new JTextField(EmailConfig.getHost()); + emailUserField = new JTextField(EmailConfig.getUsername()); + emailReceiver = new JTextField(EmailConfig.getReceiverEmail()); + emailPasswordField = new JPasswordField(EmailConfig.getPassword()); + emailPortField = new JTextField(String.valueOf(EmailConfig.getPort())); + emailSLLComboBox = new JComboBox(sslList); + emailSLLComboBox.setSelectedIndex(EmailConfig.getSSL()); + sendNewChapterNotificationsCheckBox = new JCheckBox(); + sendNewChapterNotificationsCheckBox.setSelected(EmailConfig.useNotifications()); + sendEPUBAsAttachmentCheckBox = new JCheckBox(); + sendEPUBAsAttachmentCheckBox.setSelected(EmailConfig.useAttachment()); + // Update Tab updateTextArea = new JTextArea(); updateTextArea.setLineWrap(true); diff --git a/src/library/LibrarySystem.java b/src/library/LibrarySystem.java new file mode 100644 index 0000000..d4513b3 --- /dev/null +++ b/src/library/LibrarySystem.java @@ -0,0 +1,66 @@ +package library; + +import grabber.GrabberUtils; +import grabber.Novel; +import grabber.NovelOptions; +import system.Notification; +import system.init; +import system.persistent.EmailConfig; +import system.persistent.Library; + +import java.util.concurrent.Executors; + +public class LibrarySystem { + + public static void startPolling() { + // Start new thread not to block others + Executors.newSingleThreadExecutor().execute(LibrarySystem::pollLibrary); + } + + private static void pollLibrary() { + System.out.println("[INFO]Polling library..."); + for(String novelUrl: Library.getLibrary()) { + // Getting the latest chapter count + NovelOptions options = new NovelOptions(); + options.hostname = Library.getHost(novelUrl); + options.headless = Library.useHeadless(novelUrl); + options.useAccount = Library.useAccount(novelUrl); + options.window = "checker"; + options.novelLink = novelUrl; + + Novel autoNovel = new Novel(options); + autoNovel.getChapterList(); + autoNovel.getMetadata(); + Library.setNewestChapter(novelUrl, autoNovel.chapters.size()); + + if(Library.getNewestChapter(novelUrl) - Library.getLastChapter(novelUrl) >= Library.getThreshold(novelUrl)) { + // Autodownload + if(Library.getAutoDownload(novelUrl)) { + String cliString = Library.getCLICommand(novelUrl) + +" -window checker -chapters " + +(Library.getLastChapter(novelUrl)+1) + +" " + +Library.getNewestChapter(novelUrl); + String[] cliParams = cliString.split(" "); + autoNovel = init.processParams(init.getParamsFromString(cliParams)); + Library.setLastChapter(novelUrl, Library.getNewestChapter(novelUrl)); + } + if(EmailConfig.useAttachment() && Library.getAutoDownload(novelUrl)) { + Notification.sendAttachment(autoNovel); + System.out.println("[INFO]Email with attachment send."); + } + if(EmailConfig.useNotifications()) { + Notification.sendNotification(autoNovel); + System.out.println("[INFO]Notification send."); + } + } + + GrabberUtils.sleep(1000); + } + System.out.println("[INFO]Polling done."); + init.window.buildLibrary(); + // wait 20 minutes + GrabberUtils.sleep(20*60*1000); + pollLibrary(); + } +} diff --git a/src/scripts/ChapterLists.java b/src/scripts/ChapterLists.java index d636bbe..a7fc549 100644 --- a/src/scripts/ChapterLists.java +++ b/src/scripts/ChapterLists.java @@ -25,7 +25,7 @@ public class ChapterLists { public static void getList(Novel novel) { System.out.println("[INFO]Fetching chapterlist..."); - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.appendText(novel.options.window, "[INFO]Fetching novel info..."); } diff --git a/src/scripts/ChapterListsHeadless.java b/src/scripts/ChapterListsHeadless.java index bf2bdeb..24c4eb9 100644 --- a/src/scripts/ChapterListsHeadless.java +++ b/src/scripts/ChapterListsHeadless.java @@ -20,7 +20,7 @@ public class ChapterListsHeadless { public static void getList(Novel novel) { System.out.println("[INFO]Fetching chapterlist..."); - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.appendText(novel.options.window, "[INFO]Fetching novel info..."); } diff --git a/src/scripts/Logins.java b/src/scripts/Logins.java index b3ef6aa..e3878cf 100644 --- a/src/scripts/Logins.java +++ b/src/scripts/Logins.java @@ -1,10 +1,10 @@ package scripts; -import system.Accounts; import grabber.Novel; import org.jsoup.Connection; import org.jsoup.Jsoup; import system.init; +import system.persistent.Accounts; import java.io.IOException; import java.util.Map; @@ -12,7 +12,7 @@ public class Logins { public static void getLoginCookies(Novel novel) { System.out.println("[INFO]Login..."); - if(init.window != null) { + if(init.window != null && !novel.options.window.equals("checker")) { init.window.appendText("auto","[INFO]Login..."); } diff --git a/src/system/Accounts.java b/src/system/Accounts.java deleted file mode 100644 index 26a7769..0000000 --- a/src/system/Accounts.java +++ /dev/null @@ -1,48 +0,0 @@ -package system; - -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -import java.io.*; -import java.util.Base64; - -public class Accounts { - public static JSONObject accounts = new JSONObject(); - - public static void readAccounts() throws ParseException { - try(BufferedReader reader = new BufferedReader(new FileReader(Config.account_Config_Path))) { - accounts = (JSONObject) new JSONParser().parse(reader); - } catch(IOException e) { - e.printStackTrace(); - } - } - - public static void saveAccounts() { - try(BufferedWriter writer = new BufferedWriter(new FileWriter(Config.account_Config_Path))) { - writer.write(accounts.toJSONString()); - } catch(IOException e) { - e.printStackTrace(); - } - } - - public static String getUsername(String domain) { - return accounts.containsKey(domain) ? String.valueOf(((JSONObject) accounts.get(domain)).get("username")) : ""; - } - - public static String getPassword(String domain) { - String password = accounts.containsKey(domain) ? String.valueOf(((JSONObject) accounts.get(domain)).get("password")) : ""; - return new String(Base64.getDecoder().decode(password)); - } - - // Can add new and edit existing objects - public static void addAccount(String domain, String username, String password) { - JSONObject accountDetails = new JSONObject(); - accountDetails.put("username", username); - accountDetails.put("password", Base64.getEncoder().encodeToString(password.getBytes())); - - Accounts.accounts.put(domain, accountDetails); - - saveAccounts(); - } -} diff --git a/src/system/Config.java b/src/system/Config.java index 0875b60..d9ab205 100644 --- a/src/system/Config.java +++ b/src/system/Config.java @@ -6,8 +6,7 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -17,29 +16,44 @@ public class Config { public static String home_path = System.getProperty("user.home"); public static String home_folder = "Novel-Grabber"; public static String JSON_Link = "https://raw.githubusercontent.com/Flameish/Novel-Grabber/master/src/files/siteSelector.json"; - public static String account_Config_Path = home_path+ File.separator + home_folder + File.separator + "accounts.json"; + public static String config_file_path = home_path+ File.separator + home_folder + File.separator + "config.json"; + public static JSONObject data = new JSONObject(); - public static void fetchSelectors() { - try { - System.out.println("[INFO]Fetching latest selector JSON..."); - Document doc = Jsoup.connect(JSON_Link).timeout(30 * 1000).get(); - String JSONString = doc.select("body").first().text(); - Object obj = new JSONParser().parse(JSONString); - siteSelectorsJSON = (JSONObject) obj; - } catch (ParseException | IOException e) { + public static void readConfig() throws ParseException { + try(BufferedReader reader = new BufferedReader(new FileReader(Config.config_file_path))) { + data = (JSONObject) new JSONParser().parse(reader); + } catch(IOException e) { + System.out.println("[INFO]No config file found at: "+Config.config_file_path); + } + } + + public static void saveConfig() { + try(BufferedWriter writer = new BufferedWriter(new FileWriter(Config.config_file_path))) { + writer.write(data.toJSONString()); + } catch(IOException e) { e.printStackTrace(); } } public static void checkConfigFolder() throws IOException { Path path = Paths.get(home_path); - if (Files.isDirectory(path) && Files.exists(path)) { Path myFolder = path.resolve(home_folder); - if (Files.notExists(myFolder)) { Files.createDirectory(myFolder); } } } + + public static void fetchSelectors() { + try { + System.out.println("[INFO]Fetching latest selector JSON..."); + Document doc = Jsoup.connect(JSON_Link).timeout(30 * 1000).get(); + String JSONString = doc.select("body").first().text(); + Object obj = new JSONParser().parse(JSONString); + siteSelectorsJSON = (JSONObject) obj; + } catch (ParseException | IOException e) { + e.printStackTrace(); + } + } } diff --git a/src/system/Notification.java b/src/system/Notification.java new file mode 100644 index 0000000..08e1125 --- /dev/null +++ b/src/system/Notification.java @@ -0,0 +1,104 @@ +package system; + +import grabber.Novel; +import org.simplejavamail.api.email.Email; +import org.simplejavamail.api.mailer.Mailer; +import org.simplejavamail.api.mailer.config.TransportStrategy; +import org.simplejavamail.email.EmailBuilder; +import org.simplejavamail.mailer.MailerBuilder; +import system.persistent.EmailConfig; + +import javax.activation.FileDataSource; +import java.io.File; + +public class Notification { + + public static void sendNotification(Novel novel) { + StringBuilder links = new StringBuilder(); + for (int i = novel.options.firstChapter-1; i < novel.options.lastChapter; i++) { + links.append(novel.chapters.get(i).chapterURL).append("\n"); + } + Email email = EmailBuilder.startingBlank() + .to(EmailConfig.getReceiverEmail()) + .from(EmailConfig.getReceiverEmail()) + .withSubject(novel.metadata.bookTitle + " - New Chapter") + .withPlainText(links.toString()) + .buildEmail(); + + Mailer mailer; + switch (EmailConfig.getSSL()) { + case 0: + mailer = MailerBuilder + .withSMTPServer(EmailConfig.getHost(), EmailConfig.getPort(), EmailConfig.getUsername(), EmailConfig.getPassword()) + .withTransportStrategy(TransportStrategy.SMTP) + .withSessionTimeout(10 * 1000) + .buildMailer(); + break; + case 1: + mailer = MailerBuilder + .withSMTPServer(EmailConfig.getHost(), EmailConfig.getPort(), EmailConfig.getUsername(), EmailConfig.getPassword()) + .withTransportStrategy(TransportStrategy.SMTPS) + .withSessionTimeout(10 * 1000) + .buildMailer(); + break; + case 2: + mailer = MailerBuilder + .withSMTPServer(EmailConfig.getHost(), EmailConfig.getPort(), EmailConfig.getUsername(), EmailConfig.getPassword()) + .withTransportStrategy(TransportStrategy.SMTP_TLS) + .withSessionTimeout(10 * 1000) + .buildMailer(); + break; + default: + mailer = MailerBuilder + .withSMTPServer(EmailConfig.getHost(), EmailConfig.getPort(), EmailConfig.getUsername(), EmailConfig.getPassword()) + .withTransportStrategy(TransportStrategy.SMTP) + .withSessionTimeout(10 * 1000) + .buildMailer(); + break; + } + mailer.sendMail(email); + } + public static void sendAttachment(Novel novel) { + File epub = new File(novel.options.saveLocation+"/"+novel.epubFilename); + Email email = EmailBuilder.startingBlank() + .to(EmailConfig.getReceiverEmail()) + .from(EmailConfig.getReceiverEmail()) + .withSubject(novel.metadata.bookTitle+" - New Chapter") + .withPlainText("") + .withAttachment(epub.getName(), new FileDataSource(epub)) + .buildEmail(); + + Mailer mailer; + switch (EmailConfig.getSSL()) { + case 0: + mailer = MailerBuilder + .withSMTPServer(EmailConfig.getHost(), EmailConfig.getPort(), EmailConfig.getUsername(), EmailConfig.getPassword()) + .withTransportStrategy(TransportStrategy.SMTP) + .withSessionTimeout(10 * 1000) + .buildMailer(); + break; + case 1: + mailer = MailerBuilder + .withSMTPServer(EmailConfig.getHost(), EmailConfig.getPort(), EmailConfig.getUsername(), EmailConfig.getPassword()) + .withTransportStrategy(TransportStrategy.SMTPS) + .withSessionTimeout(10 * 1000) + .buildMailer(); + break; + case 2: + mailer = MailerBuilder + .withSMTPServer(EmailConfig.getHost(), EmailConfig.getPort(), EmailConfig.getUsername(), EmailConfig.getPassword()) + .withTransportStrategy(TransportStrategy.SMTP_TLS) + .withSessionTimeout(10 * 1000) + .buildMailer(); + break; + default: + mailer = MailerBuilder + .withSMTPServer(EmailConfig.getHost(), EmailConfig.getPort(), EmailConfig.getUsername(), EmailConfig.getPassword()) + .withTransportStrategy(TransportStrategy.SMTP_TLS) + .withSessionTimeout(10 * 1000) + .buildMailer(); + break; + } + mailer.sendMail(email); + } +} diff --git a/src/system/init.java b/src/system/init.java index 7715d48..9cb8bf0 100644 --- a/src/system/init.java +++ b/src/system/init.java @@ -1,7 +1,9 @@ package system; import grabber.*; import gui.GUI; +import library.LibrarySystem; import org.json.simple.parser.ParseException; +import system.persistent.Accounts; import javax.swing.*; import java.awt.*; @@ -17,13 +19,19 @@ public class init { public static GUI window; public static void main(String[] args) { + final Map<String, List<String>> params = getParamsFromString(args); + getConfigs(); + processParams(params); + } + + public static Map<String, List<String>> getParamsFromString(String[] args) { final Map<String, List<String>> params = new HashMap<>(); List<String> options = null; for (final String a : args) { if (a.charAt(0) == '-') { if (a.length() < 2) { System.err.println("Error at argument " + a); - return; + return null; } options = new ArrayList<>(); @@ -32,14 +40,13 @@ public static void main(String[] args) { options.add(a); } else { System.err.println("Illegal parameter usage"); - return; + return null; } } - processParams(params); + return params; } - private static void processParams(Map<String, List<String>> params) { - getConfigs(); + public static Novel processParams(Map<String, List<String>> params) { if(params.containsKey("gui") || params.isEmpty()) { startGUI(); } @@ -89,9 +96,12 @@ else if(params.containsKey("help")) { if(params.containsKey("wait")) { novelOptions.waitTime = Integer.parseInt(params.get("wait").get(0)); } - if(params.containsKey("getImages")) { + if(params.containsKey("autoGetImages")) { novelOptions.getImages = true; } + if(params.containsKey("window")) { + novelOptions.window = params.get("window").get(0); + } if(params.containsKey("removeStyle")) { novelOptions.removeStyling = true; } @@ -102,7 +112,7 @@ else if(params.containsKey("help")) { novelOptions.useAccount = true; } if(params.containsKey("account")) { - Accounts.addAccount(novelOptions.hostname, params.get("account").get(0), params.get("account").get(1)); + Accounts.setAccount(novelOptions.hostname, params.get("account").get(0), params.get("account").get(1)); } Novel autoNovel = new Novel(novelOptions); @@ -125,6 +135,11 @@ else if(params.containsKey("help")) { autoNovel.options.lastChapter = autoNovel.chapters.size(); } try { + if(autoNovel.options.window.equals("checker")) { + autoNovel.metadata.bookTitle = autoNovel.options.firstChapter + +"-"+ autoNovel.options.lastChapter + +"-"+ autoNovel.metadata.bookTitle; + } autoNovel.downloadChapters(); } catch (Exception e) { e.printStackTrace(); @@ -137,10 +152,12 @@ else if(params.containsKey("help")) { epub.writeEpub(); autoNovel.report(); + return autoNovel; } else { System.out.println("No novel link."); } } + return null; } @@ -153,6 +170,7 @@ private static void startGUI() { window = new GUI(); window.setLocationRelativeTo(null); window.setVisible(true); + LibrarySystem.startPolling(); } catch (Exception e) { e.printStackTrace(); } @@ -162,15 +180,10 @@ private static void startGUI() { private static void getConfigs() { try { Config.checkConfigFolder(); - } catch (IOException e) { - e.printStackTrace(); - } - try { - Accounts.readAccounts(); - } catch (ParseException e) { + Config.readConfig(); + } catch (IOException | ParseException e) { e.printStackTrace(); } - // Fetch latest selectors Config.fetchSelectors(); } @@ -192,7 +205,7 @@ private static void printHelp() { " [-displayTitle]\t\t\t\tWrite the chapter title at the top of each chapter text.\n" + " [-invertOrder]\t\t\t\tInvert the chapter order.\n" + " [-noDesc]\t\t\t\t\tDon't create a description page.\n" + - " [-getImages]\t\t\t\t\tGrab images from chapter.\n" + + " [-autoGetImages]\t\t\t\t\tGrab images from chapter.\n" + " [-removeStyle]\t\t\t\tRemove css styling from chapter.\n" + " \n" + "Examples:\n" + diff --git a/src/system/persistent/Accounts.java b/src/system/persistent/Accounts.java new file mode 100644 index 0000000..639702c --- /dev/null +++ b/src/system/persistent/Accounts.java @@ -0,0 +1,32 @@ +package system.persistent; + +import org.json.simple.JSONObject; +import system.Config; + +import java.util.Base64; + +public class Accounts { + public static String getUsername(String domain) { + JSONObject accounts = (JSONObject) Config.data.get("accounts"); + if(accounts == null || !accounts.containsKey(domain)) return ""; + return (String) ((JSONObject) accounts.get(domain)).get("username"); + } + + public static String getPassword(String domain) { + JSONObject accounts = (JSONObject) Config.data.get("accounts"); + if(accounts == null || !accounts.containsKey(domain)) return ""; + String password = (String) ((JSONObject) accounts.get(domain)).get("password"); + return new String(Base64.getDecoder().decode(password)); + } + + public static void setAccount(String domain, String username, String password) { + JSONObject accounts = (JSONObject) Config.data.get("accounts"); + if(accounts == null) accounts = new JSONObject(); + JSONObject accountDetails = new JSONObject(); + accountDetails.put("password", Base64.getEncoder().encodeToString(password.getBytes())); + accountDetails.put("username", username); + accounts.put(domain, accountDetails); + Config.data.put("accounts", accounts); + Config.saveConfig(); + } +} diff --git a/src/system/persistent/EmailConfig.java b/src/system/persistent/EmailConfig.java new file mode 100644 index 0000000..98548af --- /dev/null +++ b/src/system/persistent/EmailConfig.java @@ -0,0 +1,86 @@ +package system.persistent; + +import org.json.simple.JSONObject; +import system.Config; + +import java.util.Base64; + +public class EmailConfig { + public static String getUsername() { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null || !email.containsKey("username")) return ""; + return (String) email.get("username"); + } + + public static String getPassword() { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null || !email.containsKey("password")) return ""; + String password = (String) email.get("password"); + return new String(Base64.getDecoder().decode(password)); + } + + public static String getHost() { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null || !email.containsKey("host")) return ""; + return (String) email.get("host"); + } + + public static int getPort() { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null || !email.containsKey("port")) return 587; + return Integer.parseInt(String.valueOf(email.get("port"))); + } + + public static int getSSL() { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null || !email.containsKey("ssl")) return 0; + return Integer.parseInt(String.valueOf(email.get("ssl"))); + } + + public static boolean useNotifications() { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null || !email.containsKey("useNotifications")) return false; + return (boolean) email.get("useNotifications"); + } + + public static boolean useAttachment() { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null || !email.containsKey("useAttachment")) return false; + return (boolean) email.get("useAttachment"); + } + + public static String getReceiverEmail() { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null || !email.containsKey("receiverEmail")) return ""; + return (String) email.get("receiverEmail"); + } + + public static void setNotifications(boolean useNotifications) { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null) email = new JSONObject(); + email.put("useNotifications", useNotifications); + Config.data.put("email", email); + Config.saveConfig(); + } + + public static void setUseAttachment(boolean useAttachment) { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null) email = new JSONObject(); + email.put("useAttachment", useAttachment); + Config.data.put("email", email); + Config.saveConfig(); + } + + public static void saveEmailSettings(String host, String username, String password, String receiverEmail, int port, int SSL) { + JSONObject email = (JSONObject) Config.data.get("email"); + if(email == null) email = new JSONObject(); + email.put("password", Base64.getEncoder().encodeToString(password.getBytes())); + email.put("username", username); + email.put("receiverEmail", receiverEmail); + email.put("host", host); + email.put("port", port); + email.put("ssl", SSL); + Config.data.put("email", email); + Config.saveConfig(); + } +} diff --git a/src/system/persistent/Library.java b/src/system/persistent/Library.java new file mode 100644 index 0000000..4e11c58 --- /dev/null +++ b/src/system/persistent/Library.java @@ -0,0 +1,185 @@ +package system.persistent; + +import grabber.Novel; +import org.json.simple.JSONObject; +import system.Config; + +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class Library { + public static int getLastChapter(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if (library == null || !library.containsKey(novelUrl)) return 0; + return Integer.parseInt(String.valueOf(((JSONObject) library.get(novelUrl)).get("lastChapter"))); + } + + public static int getNewestChapter(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if (library == null || !library.containsKey(novelUrl)) return 0; + if(((JSONObject) library.get(novelUrl)).get("newestChapter") == null) return getLastChapter(novelUrl); + return Integer.parseInt(String.valueOf(((JSONObject) library.get(novelUrl)).get("newestChapter"))); + } + + public static int getThreshold(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if (library == null || !library.containsKey(novelUrl)) return 0; + if(((JSONObject) library.get(novelUrl)).get("threshold") == null) return 0; + return Integer.parseInt(String.valueOf(((JSONObject) library.get(novelUrl)).get("threshold"))); + } + + public static String getNovelTitle(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if (library == null || !library.containsKey(novelUrl)) return ""; + return (String) ((JSONObject) library.get(novelUrl)).get("title"); + + } + + public static String getHost(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if (library == null || !library.containsKey(novelUrl)) return ""; + return (String) ((JSONObject) library.get(novelUrl)).get("host"); + } + + public static boolean useHeadless(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if(library == null || ((JSONObject) library.get(novelUrl)).get("headless") == null) return false; + return (boolean) ((JSONObject) library.get(novelUrl)).get("headless"); + } + public static boolean useAccount(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if(library == null || ((JSONObject) library.get(novelUrl)).get("useAccount") == null) return false; + return (boolean) ((JSONObject) library.get(novelUrl)).get("useAccount"); + } + + public static String getBookCover(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if (library == null || !library.containsKey(novelUrl)) return ""; + return (String) ((JSONObject) library.get(novelUrl)).get("cover"); + } + + public static String getSavelocation(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if (library == null || !library.containsKey(novelUrl)) return ""; + return (String) ((JSONObject) library.get(novelUrl)).get("saveLocation"); + } + + public static String getCLICommand(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if (library == null || !library.containsKey(novelUrl)) return ""; + return (String) ((JSONObject) library.get(novelUrl)).get("cliCommand"); + } + + public static boolean isStarred(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if(library == null || !library.containsKey(novelUrl)) return false; + return true; + } + + public static boolean getAutoDownload(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if(library == null || ((JSONObject) library.get(novelUrl)).get("autoDownload") == null) return false; + return (boolean) ((JSONObject) library.get(novelUrl)).get("autoDownload"); + } + + public static List<String> getLibrary() { + JSONObject library = (JSONObject) Config.data.get("library"); + if(library == null || library.isEmpty()) return new ArrayList<>(); + Set<String> keys = library.keySet(); + return new ArrayList<>(keys); + } + + public static void removeStarred(String novelUrl) { + JSONObject library = (JSONObject) Config.data.get("library"); + if(library == null) library = new JSONObject(); + library.remove(novelUrl); + Config.data.put("library", library); + Config.saveConfig(); + } + + + public static void setNewestChapter(String novelUrl, int chapterNumber) { + JSONObject library = (JSONObject) Config.data.get("library"); + JSONObject novel = (JSONObject) library.get(novelUrl); + novel.put("newestChapter", chapterNumber); + library.put(novelUrl, novel); + Config.data.put("library", library); + Config.saveConfig(); + } + + public static void setLastChapter(String novelUrl, int chapterNumber) { + JSONObject library = (JSONObject) Config.data.get("library"); + JSONObject novel = (JSONObject) library.get(novelUrl); + novel.put("lastChapter", chapterNumber); + library.put(novelUrl, novel); + Config.data.put("library", library); + Config.saveConfig(); + } + + public static void setThreshold(String novelUrl, int amountChapters) { + JSONObject library = (JSONObject) Config.data.get("library"); + JSONObject novel = (JSONObject) library.get(novelUrl); + novel.put("threshold", amountChapters); + library.put(novelUrl, novel); + Config.data.put("library", library); + Config.saveConfig(); + } + + public static void setAutoDownload(String novelUrl, boolean useAuto) { + JSONObject library = (JSONObject) Config.data.get("library"); + JSONObject novel = (JSONObject) library.get(novelUrl); + novel.put("autoDownload", useAuto); + library.put(novelUrl, novel); + Config.data.put("library", library); + Config.saveConfig(); + } + + public static void setCLICommand(String novelUrl, String cliCommand) { + JSONObject library = (JSONObject) Config.data.get("library"); + JSONObject novel = (JSONObject) library.get(novelUrl); + novel.put("cliCommand", cliCommand); + library.put(novelUrl, novel); + Config.data.put("library", library); + Config.saveConfig(); + } + + + public static void setStarred(Novel novel) { + JSONObject library = (JSONObject) Config.data.get("library"); + if(library == null) library = new JSONObject(); + JSONObject newNovel = (JSONObject) library.get(novel.novelLink); + if(newNovel == null) newNovel = new JSONObject(); + newNovel.put("title", novel.metadata.bookTitle); + newNovel.put("author", novel.metadata.bookAuthor); + newNovel.put("cover", novel.metadata.bookCover); + newNovel.put("lastChapter", novel.chapters.size()); + newNovel.put("headless", novel.options.headless); + newNovel.put("host", novel.options.hostname); + newNovel.put("useAccount", novel.options.useAccount); + newNovel.put("saveLocation", Config.home_path+ "/" + Config.home_folder + "/"+novel.metadata.bookTitle); + String cliCommand = "-link "+novel.novelLink +" -path "+Config.home_path+ "/" + Config.home_folder + "/"+novel.metadata.bookTitle+"/"; + if(novel.options.headless) { + cliCommand = cliCommand+ " -headless " +Settings.getBrowser(); + } + if(novel.options.useAccount) { + cliCommand = cliCommand+ " -login -account " +Accounts.getUsername(novel.options.hostname) + " "+Accounts.getPassword(novel.options.hostname); + } + newNovel.put("cliCommand", cliCommand); + + library.put(novel.novelLink, newNovel); + Config.data.put("library", library); + File outputfile = new File(Config.home_path+ "/" + Config.home_folder + "/"+novel.metadata.bookTitle+"/"+novel.metadata.bookCover); + outputfile.mkdirs(); + try { + ImageIO.write(novel.metadata.bufferedCover, novel.metadata.bookCover.substring(novel.metadata.bookCover.lastIndexOf(".")+1), outputfile); + } catch (IOException e) { + e.printStackTrace(); + } + Config.saveConfig(); + } + +} diff --git a/src/system/persistent/Settings.java b/src/system/persistent/Settings.java new file mode 100644 index 0000000..805cb09 --- /dev/null +++ b/src/system/persistent/Settings.java @@ -0,0 +1,67 @@ +package system.persistent; + +import org.json.simple.JSONObject; +import system.Config; + +public class Settings { + public static String getBrowser() { + JSONObject headless = (JSONObject) Config.data.get("headless"); + if(headless == null || !headless.containsKey("browser")) return "Chrome"; + return (String) headless.get("browser"); + } + + public static boolean getBrowserShowGUI() { + JSONObject headless = (JSONObject) Config.data.get("headless"); + if(headless == null || !headless.containsKey("showBrowserGUI")) return false; + return (boolean) headless.get("showBrowserGUI"); + } + + public static int getEPUBOutputFormat() { + JSONObject generalSettings = (JSONObject) Config.data.get("generalSettings"); + if(generalSettings == null || !generalSettings.containsKey("filenameFormat")) return 0; + return Integer.parseInt(String.valueOf(generalSettings.get("filenameFormat"))); + } + + public static boolean getImages() { + JSONObject generalSettings = (JSONObject) Config.data.get("generalSettings"); + if(generalSettings == null || !generalSettings.containsKey("autoGetImages")) return false; + return (boolean) generalSettings.get("autoGetImages"); + } + + public static String getSavelocation() { + JSONObject generalSettings = (JSONObject) Config.data.get("generalSettings"); + if(generalSettings == null || !generalSettings.containsKey("saveLocation")) return ""; + return (String) generalSettings.get("saveLocation"); + } + + public static boolean getRemoveStyling() { + JSONObject generalSettings = (JSONObject) Config.data.get("generalSettings"); + if(generalSettings == null || !generalSettings.containsKey("removeStyling")) return false; + return (boolean) generalSettings.get("removeStyling"); + } + + public static boolean getUseStandardLocation() { + JSONObject generalSettings = (JSONObject) Config.data.get("generalSettings"); + if(generalSettings == null || !generalSettings.containsKey("useStandardLocation")) return false; + return (boolean) generalSettings.get("useStandardLocation"); + } + + public static void setHeadlessSettings(String newBrowser, boolean showGUI) { + JSONObject headlessDetails = new JSONObject(); + headlessDetails.put("browser", newBrowser); + headlessDetails.put("showBrowserGUI", showGUI); + Config.data.put("headless", headlessDetails); + Config.saveConfig(); + } + + public static void setGeneralSettings(boolean getImages, boolean removeStyling, int formatNumber, String saveLocation, boolean useStandardLocation) { + JSONObject generalSettings = new JSONObject(); + generalSettings.put("autoGetImages", getImages); + generalSettings.put("removeStyling", removeStyling); + generalSettings.put("filenameFormat", formatNumber); + generalSettings.put("saveLocation", saveLocation); + generalSettings.put("useStandardLocation", useStandardLocation); + Config.data.put("generalSettings", generalSettings); + Config.saveConfig(); + } +}