refactored everything and moved the project into a Maven project, that can be built easily, and removed a json call that was deprecated

This commit is contained in:
Louis Vallat 2020-03-22 20:03:01 +01:00
parent b0e6f33b87
commit a3f4c5688a
32 changed files with 1975 additions and 3595 deletions

30
.gitignore vendored
View File

@ -1,27 +1,3 @@
# Compiled class file *.iml
*.class .idea/
target/
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
/twitter_techsupportgore_bot/nbproject/private/
/twitter_techsupportgore_bot/build/
/twitter_techsupportgore_bot/dist/
*.sqlite

View File

@ -1,23 +1,25 @@
################################################################################ ################################################################################
# REDDIT SETTINGS # # REDDIT SETTINGS #
################################################################################ ################################################################################
subreddit=techsupportgore # What comes after /r/ (ex: softwaregore)
delay=30 subreddit=
sqlite_db_name=techsupportgore_twitterbot # delay (in seconds) between two scans. (ex: 60)
clear_database=N delay=
reddit_posts_limit=1 sqlite_db_name=
reddit_posts_sorting_order=new clear_database=
reddit_posts_limit=
################################################################################ reddit_posts_sorting_order=
# MISCELLANEOUS SETTINGS #
################################################################################ ################################################################################
working_directory=data # MISCELLANEOUS SETTINGS #
max_text_length=280 ################################################################################
working_directory=
################################################################################ max_text_length=
# TWITTER API SETTINGS #
################################################################################ ################################################################################
twitterAPI_consumerKey= # TWITTER API SETTINGS #
twitterAPI_consumerSecret= ################################################################################
twitterAPI_accessToken= twitterAPI_consumerKey=
twitterAPI_accessSecret= twitterAPI_consumerSecret=
twitterAPI_accessToken=
twitterAPI_accessSecret=

68
pom.xml Normal file
View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>RedditReposterBot</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>xyz.vallat.louis.RedditReposterBot</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.twitter4j</groupId>
<artifactId>twitter4j-core</artifactId>
<version>4.0.7</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.30.1</version>
</dependency>
</dependencies>
</project>

View File

@ -1,73 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="RedditReposterBot" default="default" basedir=".">
<description>Builds, tests, and runs the project RedditReposterBot.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="RedditReposterBot-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@ -1,4 +0,0 @@
#Tue, 06 Aug 2019 11:12:49 +0200
C\:\\Users\\louis\\Documents\\GitHub\\twitter_techsupportgore_bot\\reddit_reposter_bot=

View File

@ -1,32 +0,0 @@
========================
BUILD OUTPUT DESCRIPTION
========================
When you build an Java application project that has a main class, the IDE
automatically copies all of the JAR
files on the projects classpath to your projects dist/lib folder. The IDE
also adds each of the JAR files to the Class-Path element in the application
JAR files manifest file (MANIFEST.MF).
To run the project from the command line, go to the dist folder and
type the following:
java -jar "RedditReposterBot.jar"
To distribute this project, zip up the dist folder (including the lib folder)
and distribute the ZIP file.
Notes:
* If two JAR files on the project classpath have the same name, only the first
JAR file is copied to the lib folder.
* Only JAR files are copied to the lib folder.
If the classpath contains other types of files or folders, these files (folders)
are not copied.
* If a library on the projects classpath also has a Class-Path element
specified in the manifest,the content of the Class-Path element has to be on
the projects runtime path.
* To set a main class in a standard Java project, right-click the project node
in the Projects window and choose Properties. Then click Run and enter the
class name in the Main Class field. Alternatively, you can manually type the
class name in the manifest Main-Class element.

View File

@ -1,3 +0,0 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
build.xml.data.CRC32=9dc9f11e
build.xml.script.CRC32=293f3476
build.xml.stylesheet.CRC32=8064a381@1.80.1.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=9dc9f11e
nbproject/build-impl.xml.script.CRC32=69003ede
nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48

View File

@ -1,9 +0,0 @@
application.args=helo
#
#Mon Apr 22 18:09:19 CEST 2019
javac.debug=true
javadoc.preview=true
do.depend=false
do.jar=true
compile.on.save=false
user.properties.file=C\:\\Users\\louis\\AppData\\Roaming\\NetBeans\\8.2\\build.properties

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group/>
</open-files>
</project-private>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment/>
<entry key="ACTIVATED_FEATURES">#org.netbeans.modules.profiler.v2.features.MonitorFeature@#org.netbeans.modules.profiler.v2.features.ThreadsFeature@#org.netbeans.modules.profiler.v2.features.SQLFeature@</entry>
<entry key="SINGLE_FEATURE">false</entry>
</properties>

View File

@ -1,85 +0,0 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=RedditReposterBot
application.vendor=louis
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/RedditReposterBot.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
file.reference.gson-2.8.5.jar=C:\\Users\\louis\\Documents\\libraries\\Java\\gson-2.8.5.jar
file.reference.kotlin-runtime.jar=nulllib\\kotlin-runtime.jar
file.reference.sqlite-jdbc-3.23.1.jar=C:\\Users\\louis\\Documents\\libraries\\Java\\sqlite-jdbc-3.23.1.jar
file.reference.twitter4j-core-4.0.7.jar=C:\\Users\\louis\\Documents\\libraries\\Java\\twitter4j-core-4.0.7.jar
includes=**
jar.compress=false
javac.classpath=\
${file.reference.gson-2.8.5.jar}:\
${file.reference.twitter4j-core-4.0.7.jar}:\
${file.reference.sqlite-jdbc-3.23.1.jar}
# Space-separated list of extra javac options
javac.compilerargs=-Xlint:unchecked
javac.deprecation=false
javac.external.vm=true
javac.processorpath=\
${javac.classpath}
javac.source=1.8
javac.target=1.8
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
kotlinc.classpath=${file.reference.kotlin-runtime.jar}
main.class=RedditReposterBot.RedditReposterBot
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
project.license=gpl30
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>RedditReposterBot</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@ -1,106 +1,106 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot; package xyz.vallat.louis;
import RedditReposterBot.exceptions.NoSuchFile; import xyz.vallat.louis.exceptions.NoSuchFile;
import RedditReposterBot.exceptions.NotSufficientRights; import xyz.vallat.louis.exceptions.NotSufficientRights;
import RedditReposterBot.exceptions.NoSuchProperty; import xyz.vallat.louis.exceptions.NoSuchProperty;
import java.io.File; import java.io.File;
import java.util.Properties; import java.util.Properties;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
/** /**
* A config file reader. * A config file reader.
* *
* @author louis * @author louis
*/ */
public final class ConfigFileReader { public final class ConfigFileReader {
/** /**
* The config file name. * The config file name.
*/ */
private static String CONFIGFILE = "settings.conf"; private static String CONFIGFILE = "data/settings.conf";
/** /**
* The properties object. * The properties object.
*/ */
private final Properties prop = new Properties(); private final Properties prop = new Properties();
/** /**
* Create a new config file reader that automatically reads the config file. * Create a new config file reader that automatically reads the config file.
* *
* @throws NoSuchFile * @throws NoSuchFile
* @throws NotSufficientRights * @throws NotSufficientRights
*/ */
public ConfigFileReader() throws NoSuchFile, NotSufficientRights { public ConfigFileReader() throws NoSuchFile, NotSufficientRights {
readConfigFile(); readConfigFile();
} }
/** /**
* Create a new config file reader that automatically reads the config file, * Create a new config file reader that automatically reads the config file,
* precising the config file name. * precising the config file name.
* *
* @param conf the cnfig file path name. * @param conf the cnfig file path name.
* @throws NoSuchFile * @throws NoSuchFile
* @throws NotSufficientRights * @throws NotSufficientRights
*/ */
public ConfigFileReader(String conf) throws NoSuchFile, NotSufficientRights { public ConfigFileReader(String conf) throws NoSuchFile, NotSufficientRights {
CONFIGFILE = conf; CONFIGFILE = conf;
readConfigFile(); readConfigFile();
} }
/** /**
* Read the config file. * Read the config file.
* *
* @throws RedditReposterBot.exceptions.NoSuchFile * @throws RedditReposterBot.exceptions.NoSuchFile
* @throws RedditReposterBot.exceptions.NotSufficientRights * @throws RedditReposterBot.exceptions.NotSufficientRights
*/ */
public void readConfigFile() throws NoSuchFile, NotSufficientRights { public void readConfigFile() throws NoSuchFile, NotSufficientRights {
if (!new File(CONFIGFILE).exists()) { if (!new File(CONFIGFILE).exists()) {
throw new NoSuchFile( throw new NoSuchFile(
"[!] The config file " + CONFIGFILE + " doesn't exists."); "[!] The config file " + CONFIGFILE + " doesn't exists.");
} else if (!new File(CONFIGFILE).canRead()) { } else if (!new File(CONFIGFILE).canRead()) {
throw new NotSufficientRights( throw new NotSufficientRights(
"[!] Can't read the config file " + CONFIGFILE + "."); "[!] Can't read the config file " + CONFIGFILE + ".");
} }
try { try {
prop.load(new FileInputStream(new File(CONFIGFILE))); prop.load(new FileInputStream(new File(CONFIGFILE)));
} catch (IOException ex) { } catch (IOException ex) {
System.out.println( System.out.println(
"[!] Error on loading the config file."); "[!] Error on loading the config file.");
System.out.println("[!] " + ex.getMessage()); System.out.println("[!] " + ex.getMessage());
} }
} }
/** /**
* Get the property for an id. * Get the property for an id.
* *
* @param id the property id. * @param id the property id.
* @return the properties. * @return the properties.
* @throws RedditReposterBot.exceptions.NoSuchProperty * @throws RedditReposterBot.exceptions.NoSuchProperty
*/ */
public String getProperties(String id) throws NoSuchProperty { public String getProperties(String id) throws NoSuchProperty {
if (!this.prop.containsKey(id)) { if (!this.prop.containsKey(id)) {
throw new NoSuchProperty( throw new NoSuchProperty(
"[!] The property " + id + " is not defined in the config " "[!] The property " + id + " is not defined in the config "
+ "file. Define it in " + CONFIGFILE + " and try again."); + "file. Define it in " + CONFIGFILE + " and try again.");
} }
return this.prop.getProperty(id); return this.prop.getProperty(id);
} }
} }

View File

@ -1,441 +1,441 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot; package xyz.vallat.louis;
import RedditReposterBot.socialMediaHandler.SocialMediaPoster; import xyz.vallat.louis.socialMediaHandler.SocialMediaPoster;
import RedditReposterBot.redditHandler.RedditExtractor; import xyz.vallat.louis.redditHandler.RedditExtractor;
import RedditReposterBot.exceptions.NoSuchFile; import xyz.vallat.louis.exceptions.NoSuchFile;
import RedditReposterBot.exceptions.NoSuchOrder; import xyz.vallat.louis.exceptions.NoSuchOrder;
import RedditReposterBot.exceptions.NotSufficientRights; import xyz.vallat.louis.exceptions.NotSufficientRights;
import RedditReposterBot.exceptions.NoSuchProperty; import xyz.vallat.louis.exceptions.NoSuchProperty;
import RedditReposterBot.redditHandler.RedditPost; import xyz.vallat.louis.redditHandler.RedditPost;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
/** /**
* Singleton Hypervisor. This is the object that does everything. So we want it * Singleton Hypervisor. This is the object that does everything. So we want it
* to be unique. That's why it's a singleton. * to be unique. That's why it's a singleton.
* *
* @author louis * @author louis
*/ */
public class Hypervisor { public class Hypervisor {
/** /**
* Working folder. * Working folder.
*/ */
private String workingDirectory; private String workingDirectory;
/** /**
* SQLITE database for saving the already parsed posts. * SQLITE database for saving the already parsed posts.
*/ */
private final String sqliteDatabase; private final String sqliteDatabase;
/** /**
* SQLITE table name. * SQLITE table name.
*/ */
private final String tableName; private final String tableName;
/** /**
* Delay between two scans, in seconds. * Delay between two scans, in seconds.
*/ */
private final int delay; private final int delay;
/** /**
* Minimum of all the social medias text size. * Minimum of all the social medias text size.
*/ */
private final int maxLength; private final int maxLength;
/** /**
* Subreddit to extract info from. * Subreddit to extract info from.
*/ */
private final String subreddit; private final String subreddit;
/** /**
* The singleton. * The singleton.
*/ */
private static Hypervisor SINGLETON = null; private static Hypervisor SINGLETON = null;
/** /**
* All the social medias to post our reddit content. * All the social medias to post our reddit content.
*/ */
private final ArrayList<SocialMediaPoster> socialMedias; private final ArrayList<SocialMediaPoster> socialMedias;
/** /**
* Connection to the SQLITE database. * Connection to the SQLITE database.
*/ */
private Connection connexion; private Connection connexion;
/** /**
* RedditExtractor. * RedditExtractor.
*/ */
private final RedditExtractor myRedditExtractor; private final RedditExtractor myRedditExtractor;
/** /**
* Private constructor so nobody except this obect can build this object. * Private constructor so nobody except this obect can build this object.
*/ */
private Hypervisor() private Hypervisor()
throws NotSufficientRights, ClassNotFoundException, throws NotSufficientRights, ClassNotFoundException,
SQLException, IOException, NoSuchFile, NoSuchProperty, NoSuchOrder { SQLException, IOException, NoSuchFile, NoSuchProperty, NoSuchOrder {
Class.forName("org.sqlite.JDBC"); Class.forName("org.sqlite.JDBC");
System.out.println("[+] Creating Hypervisor."); System.out.println("[+] Creating Hypervisor.");
ConfigFileReader reader = new ConfigFileReader(); ConfigFileReader reader = new ConfigFileReader();
this.subreddit = reader.getProperties("subreddit"); this.subreddit = reader.getProperties("subreddit");
this.tableName = reader.getProperties("subreddit"); this.tableName = reader.getProperties("subreddit");
this.delay = Integer.valueOf(reader.getProperties("delay")); this.delay = Integer.valueOf(reader.getProperties("delay"));
this.sqliteDatabase = reader.getProperties("sqlite_db_name"); this.sqliteDatabase = reader.getProperties("sqlite_db_name");
this.socialMedias = new ArrayList<>(); this.socialMedias = new ArrayList<>();
this.workingDirectory = reader.getProperties("working_directory"); this.workingDirectory = reader.getProperties("working_directory");
setupTheBotDirectory(); setupTheBotDirectory();
this.connexion = DriverManager.getConnection("jdbc:sqlite:" this.connexion = DriverManager.getConnection("jdbc:sqlite:"
+ this.workingDirectory + File.separator + this.workingDirectory + File.separator
+ this.sqliteDatabase); + this.sqliteDatabase);
this.myRedditExtractor = new RedditExtractor(subreddit); this.myRedditExtractor = new RedditExtractor(subreddit);
if ("Y".equals(reader.getProperties("clear_database"))) { if ("Y".equals(reader.getProperties("clear_database"))) {
clearDatabase(); clearDatabase();
} }
this.maxLength = Integer.valueOf(reader.getProperties("max_text_length")); this.maxLength = Integer.valueOf(reader.getProperties("max_text_length"));
load(); load();
this.connexion.close(); this.connexion.close();
System.out.println("[+] Hypervisor created successfully."); System.out.println("[+] Hypervisor created successfully.");
} }
/** /**
* Get the Singleton Hypervisor instance. * Get the Singleton Hypervisor instance.
* *
* @return the instance. * @return the instance.
* *
* @throws java.lang.ClassNotFoundException * @throws ClassNotFoundException
* @throws RedditReposterBot.exceptions.NotSufficientRights * @throws NotSufficientRights
* @throws java.sql.SQLException * @throws SQLException
* @throws java.io.IOException * @throws IOException
* @throws RedditReposterBot.exceptions.NoSuchFile * @throws NoSuchFile
* @throws RedditReposterBot.exceptions.NoSuchProperty * @throws NoSuchProperty
* @throws RedditReposterBot.exceptions.NoSuchOrder * @throws NoSuchOrder
*/ */
public static Hypervisor getSingleton() public static Hypervisor getSingleton()
throws ClassNotFoundException, NotSufficientRights, throws ClassNotFoundException, NotSufficientRights,
SQLException, IOException, NoSuchFile, NoSuchProperty, NoSuchOrder { SQLException, IOException, NoSuchFile, NoSuchProperty, NoSuchOrder {
if (SINGLETON == null) { if (SINGLETON == null) {
SINGLETON = new Hypervisor(); SINGLETON = new Hypervisor();
} }
return SINGLETON; return SINGLETON;
} }
/** /**
* Main loop for the program. This is where everything happens. * Main loop for the program. This is where everything happens.
* *
* @throws java.lang.ClassNotFoundException * @throws ClassNotFoundException
* @throws java.sql.SQLException * @throws SQLException
* @throws java.lang.InterruptedException * @throws InterruptedException
*/ */
public void run() public void run()
throws ClassNotFoundException, SQLException, throws ClassNotFoundException, SQLException,
InterruptedException { InterruptedException {
System.out.println("[+] Hypervisor is now running."); System.out.println("[+] Hypervisor is now running.");
for (;;) { for (;;) {
this.connexion = DriverManager.getConnection("jdbc:sqlite:" this.connexion = DriverManager.getConnection("jdbc:sqlite:"
+ this.workingDirectory + File.separator + this.workingDirectory + File.separator
+ this.sqliteDatabase); + this.sqliteDatabase);
for (RedditPost post : myRedditExtractor.getRedditPosts()) { for (RedditPost post : myRedditExtractor.getRedditPosts()) {
computeRedditPost(post); computeRedditPost(post);
} }
this.connexion.close(); this.connexion.close();
System.out.println( System.out.println(
"[*] Hypervisor is waiting for " "[*] Hypervisor is waiting for "
+ this.delay + " seconds."); + this.delay + " seconds.");
Thread.sleep(this.delay * 1000); Thread.sleep(this.delay * 1000);
} }
} }
/** /**
* Load all the reddit posts from the database. * Load all the reddit posts from the database.
* *
* @throws ClassNotFoundException * @throws ClassNotFoundException
* @throws SQLException * @throws SQLException
*/ */
private void load() throws ClassNotFoundException, SQLException { private void load() throws ClassNotFoundException, SQLException {
createTable(); createTable();
PreparedStatement recherche = this.connexion.prepareStatement( PreparedStatement recherche = this.connexion.prepareStatement(
"SELECT COUNT(id) AS cpt FROM " + this.tableName + ";"); "SELECT COUNT(id) AS cpt FROM " + this.tableName + ";");
try (ResultSet res = recherche.executeQuery()) { try (ResultSet res = recherche.executeQuery()) {
res.next(); res.next();
System.out.println("[*] " + res.getInt("cpt") + " posts in database."); System.out.println("[*] " + res.getInt("cpt") + " posts in database.");
} }
} }
/** /**
* Clear the database by dropping it. * Clear the database by dropping it.
* *
* @throws ClassNotFoundException * @throws ClassNotFoundException
* @throws SQLException * @throws SQLException
*/ */
private void clearDatabase() throws ClassNotFoundException, SQLException { private void clearDatabase() throws ClassNotFoundException, SQLException {
System.out.println("[*] Clearing the database."); System.out.println("[*] Clearing the database.");
PreparedStatement stmt = connexion.prepareStatement("" PreparedStatement stmt = connexion.prepareStatement(""
+ "DROP TABLE IF EXISTS " + this.tableName + ";" + "DROP TABLE IF EXISTS " + this.tableName + ";"
); );
stmt.execute(); stmt.execute();
createTable(); createTable();
System.out.println("[*] The database has been cleared successfully."); System.out.println("[*] The database has been cleared successfully.");
} }
/** /**
* Add a given reddit post to the database. * Add a given reddit post to the database.
* *
* @param current a given reddit post to add to the database * @param current a given reddit post to add to the database
* *
* @throws ClassNotFoundException * @throws ClassNotFoundException
* @throws SQLException * @throws SQLException
*/ */
private void addRedditPostToDatabase(RedditPost current) private void addRedditPostToDatabase(RedditPost current)
throws ClassNotFoundException, SQLException { throws ClassNotFoundException, SQLException {
createTable(); createTable();
if (!isInDatabase(current.getPostId())) { if (!isInDatabase(current.getPostId())) {
PreparedStatement ajout = this.connexion.prepareStatement( PreparedStatement ajout = this.connexion.prepareStatement(
"INSERT INTO " + this.tableName "INSERT INTO " + this.tableName
+ "(" + "("
+ "postType, " + "postType, "
+ "postId, " + "postId, "
+ "title, " + "title, "
+ "quarantine, " + "quarantine, "
+ "score, " + "score, "
+ "postHint, " + "postHint, "
+ "crosspostable, " + "crosspostable, "
+ "over18, " + "over18, "
+ "author, " + "author, "
+ "permalink, " + "permalink, "
+ "spoiler, " + "spoiler, "
+ "url, " + "url, "
+ "shared" + "shared"
+ ") " + ") "
+ "VALUES " + "VALUES "
+ "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);" + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
); );
ajout.setString(1, ajout.setString(1,
current.isImage() ? "image" current.isImage() ? "image"
: current.isLink() ? "link" : current.isLink() ? "link"
: current.isText() ? "text" : current.isText() ? "text"
: "video"); : "video");
ajout.setString(2, current.getPostId()); ajout.setString(2, current.getPostId());
ajout.setString(3, current.getTitle()); ajout.setString(3, current.getTitle());
ajout.setBoolean(4, current.isQuarantine()); ajout.setBoolean(4, current.isQuarantine());
ajout.setDouble(5, current.getScore()); ajout.setDouble(5, current.getScore());
ajout.setString(6, current.getPostHint()); ajout.setString(6, current.getPostHint());
ajout.setBoolean(7, current.isCrosspostable()); ajout.setBoolean(7, current.isCrosspostable());
ajout.setBoolean(8, current.isOver18()); ajout.setBoolean(8, current.isOver18());
ajout.setString(9, current.getAuthor()); ajout.setString(9, current.getAuthor());
ajout.setString(10, current.getPermalink()); ajout.setString(10, current.getPermalink());
ajout.setBoolean(11, current.isSpoiler()); ajout.setBoolean(11, current.isSpoiler());
ajout.setString(12, current.getUrl()); ajout.setString(12, current.getUrl());
ajout.setBoolean(13, true); ajout.setBoolean(13, true);
ajout.execute(); ajout.execute();
} }
} }
/** /**
* Check if a post is in database. * Check if a post is in database.
* *
* @param postId the post id * @param postId the post id
* @return if the post is in the database * @return if the post is in the database
* *
* @throws SQLException * @throws SQLException
* @throws ClassNotFoundException * @throws ClassNotFoundException
*/ */
private boolean isInDatabase(String postId) private boolean isInDatabase(String postId)
throws SQLException, ClassNotFoundException { throws SQLException, ClassNotFoundException {
PreparedStatement recherche = this.connexion.prepareStatement( PreparedStatement recherche = this.connexion.prepareStatement(
"SELECT * FROM " + this.tableName + " " "SELECT * FROM " + this.tableName + " "
+ "WHERE postId = '" + postId + "'"); + "WHERE postId = '" + postId + "'");
try (ResultSet resultats = recherche.executeQuery()) { try (ResultSet resultats = recherche.executeQuery()) {
return resultats.next(); return resultats.next();
} }
} }
/** /**
* Create our working table if it doesn't exists yet. * Create our working table if it doesn't exists yet.
* *
* @throws SQLException * @throws SQLException
* @throws ClassNotFoundException * @throws ClassNotFoundException
*/ */
private void createTable() throws SQLException, ClassNotFoundException { private void createTable() throws SQLException, ClassNotFoundException {
PreparedStatement stmt = connexion.prepareStatement("" PreparedStatement stmt = connexion.prepareStatement(""
+ "CREATE TABLE IF NOT EXISTS " + this.tableName + " " + "CREATE TABLE IF NOT EXISTS " + this.tableName + " "
+ "(" + "("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT," + "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "postType TEXT, " + "postType TEXT, "
+ "postId TEXT UNIQUE, " + "postId TEXT UNIQUE, "
+ "title TEXT, " + "title TEXT, "
+ "quarantine BOOLEAN, " + "quarantine BOOLEAN, "
+ "score DOUBLE, " + "score DOUBLE, "
+ "postHint TEXT, " + "postHint TEXT, "
+ "crosspostable BOOLEAN, " + "crosspostable BOOLEAN, "
+ "over18 BOOLEAN, " + "over18 BOOLEAN, "
+ "author TEXT, " + "author TEXT, "
+ "permalink TEXT, " + "permalink TEXT, "
+ "spoiler BOOLEAN, " + "spoiler BOOLEAN, "
+ "url TEXT, " + "url TEXT, "
+ "shared BOOLEAN" + "shared BOOLEAN"
+ ");" + ");"
); );
stmt.execute(); stmt.execute();
} }
/** /**
* Compute a given reddit post. * Compute a given reddit post.
* *
* @param r the reddit post to compute. * @param r the reddit post to compute.
* *
* @throws ClassNotFoundException * @throws ClassNotFoundException
* @throws SQLException * @throws SQLException
*/ */
private void computeRedditPost(RedditPost r) private void computeRedditPost(RedditPost r)
throws SQLException, ClassNotFoundException { throws SQLException, ClassNotFoundException {
if (!isInDatabase(r.getPostId()) && !r.isQuarantine() && r.hasMediaUrl()) { if (!isInDatabase(r.getPostId()) && !r.isQuarantine() && r.hasMediaUrl()) {
System.out.println( System.out.println(
"[*] Computing the post \"" + r.getTitle() + "\""); "[*] Computing the post \"" + r.getTitle() + "\"");
addRedditPostToDatabase(r); addRedditPostToDatabase(r);
String fileName = saveImage(r.getUrl()); String fileName = saveImage(r.getUrl());
socialMedias.forEach((s) -> { socialMedias.forEach((s) -> {
long postRef = s.postImage( long postRef = s.postImage(
formatPost(r.getTitle()), fileName); formatPost(r.getTitle()), fileName);
if (postRef != 0 && postRef != -1) { if (postRef != 0 && postRef != -1) {
s.replyText(formatPost("from /u/" + r.getAuthor() + " " s.replyText(formatPost("from /u/" + r.getAuthor() + " "
+ "on /r/" + this.subreddit + " " + "on /r/" + this.subreddit + " "
+ "at link : https://www.reddit.com" + "at link : https://www.reddit.com"
+ r.getPermalink()), postRef); + r.getPermalink()), postRef);
} }
}); });
deleteFile(fileName); deleteFile(fileName);
System.out.println("[+] Post \"" System.out.println("[+] Post \""
+ r.getTitle() + r.getTitle()
+ "\" has been shared successfully."); + "\" has been shared successfully.");
} }
} }
/** /**
* Format a given text for being posted on the different social networks. * Format a given text for being posted on the different social networks.
* *
* @param text the text to format * @param text the text to format
* @return the formatted text * @return the formatted text
*/ */
private String formatPost(String text) { private String formatPost(String text) {
return text.length() >= this.maxLength return text.length() >= this.maxLength
? text.substring(0, this.maxLength - 4) + "..." ? text.substring(0, this.maxLength - 4) + "..."
: text; : text;
} }
/** /**
* Save Image from URL. Modified version of the code that can be found at * Save Image from URL. Modified version of the code that can be found at
* https://www.programcreek.com/2012/12/download-image-from-url-in-java/ * https://www.programcreek.com/2012/12/download-image-from-url-in-java/
* *
* @param imageUrl the image URL. * @param imageUrl the image URL.
*/ */
private String saveImage(String imageUrl) { private String saveImage(String imageUrl) {
System.out.println("[+] Dowloading image " + imageUrl + "."); System.out.println("[+] Dowloading image " + imageUrl + ".");
try { try {
URL url = new URL(imageUrl); URL url = new URL(imageUrl);
String fileName = url.getFile(); String fileName = url.getFile();
String destName = workingDirectory + fileName.substring( String destName = workingDirectory + fileName.substring(
fileName.lastIndexOf("/"), fileName.lastIndexOf("?")); fileName.lastIndexOf("/"), fileName.lastIndexOf("?"));
InputStream is = url.openStream(); InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destName); OutputStream os = new FileOutputStream(destName);
byte[] b = new byte[2048]; byte[] b = new byte[2048];
int length; int length;
while ((length = is.read(b)) != -1) { while ((length = is.read(b)) != -1) {
os.write(b, 0, length); os.write(b, 0, length);
} }
is.close(); is.close();
os.close(); os.close();
System.out.println( System.out.println(
"[+] Image " + destName + " dowloaded successfully."); "[+] Image " + destName + " dowloaded successfully.");
return destName; return destName;
} catch (IOException ex) { } catch (IOException ex) {
System.err.println("[!] IOException : " + ex.getMessage()); System.err.println("[!] IOException : " + ex.getMessage());
System.exit(1); System.exit(1);
} }
return null; return null;
} }
/** /**
* Delete a file. * Delete a file.
* *
* @param filePath the path to the file we want to delete. * @param filePath the path to the file we want to delete.
*/ */
private void deleteFile(String filePath) { private void deleteFile(String filePath) {
File f = new File(filePath); File f = new File(filePath);
f.delete(); f.delete();
System.out.println("[*] File " + filePath + " deleted."); System.out.println("[*] File " + filePath + " deleted.");
} }
/** /**
* Set working directory. * Set working directory.
* *
* @param tempDir the path to the working directory. * @param tempDir the path to the working directory.
* @throws RedditReposterBot.exceptions.NotSufficientRights * @throws NotSufficientRights
*/ */
public void setWorkDir(String tempDir) throws NotSufficientRights { public void setWorkDir(String tempDir) throws NotSufficientRights {
this.workingDirectory = tempDir; this.workingDirectory = tempDir;
setupTheBotDirectory(); setupTheBotDirectory();
} }
/** /**
* Get the working directory. * Get the working directory.
* *
* @return the working directory path. * @return the working directory path.
*/ */
public String getWorkDir() { public String getWorkDir() {
return workingDirectory; return workingDirectory;
} }
/** /**
* Setup the bot. * Setup the bot.
* *
* @throws NotSufficientRights * @throws NotSufficientRights
*/ */
private void setupTheBotDirectory() throws NotSufficientRights { private void setupTheBotDirectory() throws NotSufficientRights {
File f = new File(workingDirectory); File f = new File(workingDirectory);
f.mkdir(); f.mkdir();
if (!f.canRead() || !f.canWrite()) { if (!f.canRead() || !f.canWrite()) {
throw new NotSufficientRights( throw new NotSufficientRights(
"[!] This program does not have the sufficient " "[!] This program does not have the sufficient "
+ "rights on the folder \"" + workingDirectory + "\"."); + "rights on the folder \"" + workingDirectory + "\".");
} }
} }
/** /**
* Add a social media to post content to. * Add a social media to post content to.
* *
* @param s the social media * @param s the social media
*/ */
public void addSocialMedia(SocialMediaPoster s) { public void addSocialMedia(SocialMediaPoster s) {
this.socialMedias.add(s); this.socialMedias.add(s);
} }
} }

View File

@ -1,68 +1,68 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot; package xyz.vallat.louis;
import RedditReposterBot.socialMediaHandler.TwitterBot; import xyz.vallat.louis.socialMediaHandler.TwitterBot;
import RedditReposterBot.exceptions.NoSuchFile; import xyz.vallat.louis.exceptions.NoSuchFile;
import RedditReposterBot.exceptions.NoSuchOrder; import xyz.vallat.louis.exceptions.NoSuchOrder;
import RedditReposterBot.exceptions.NoSuchProperty; import xyz.vallat.louis.exceptions.NoSuchProperty;
import RedditReposterBot.exceptions.NotSufficientRights; import xyz.vallat.louis.exceptions.NotSufficientRights;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
/** /**
* This is where everything begins. * This is where everything begins.
* *
* @author louis * @author louis
*/ */
public class RedditReposterBot { public class RedditReposterBot {
/** /**
* Version of the application. * Version of the application.
*/ */
private static final String VERSION = "1.0.1"; private static final String VERSION = "1.0.1";
/** /**
* Launch the Hypervisor. * Launch the Hypervisor.
* *
* @param args command line arguments * @param args command line arguments
* *
* @throws ClassNotFoundException * @throws ClassNotFoundException
* @throws NotSufficientRights * @throws NotSufficientRights
* @throws SQLException * @throws SQLException
* @throws IOException * @throws IOException
* @throws InterruptedException * @throws InterruptedException
* @throws NoSuchFile * @throws NoSuchFile
* @throws NoSuchProperty * @throws NoSuchProperty
* @throws NoSuchOrder * @throws NoSuchOrder
*/ */
public static void main(String[] args) throws public static void main(String[] args) throws
ClassNotFoundException, ClassNotFoundException,
NotSufficientRights, NotSufficientRights,
SQLException, SQLException,
IOException, IOException,
InterruptedException, InterruptedException,
NoSuchFile, NoSuchFile,
NoSuchProperty, NoSuchProperty,
NoSuchOrder { NoSuchOrder {
System.out.println("[*] App version " + VERSION); System.out.println("[*] App version " + VERSION);
Hypervisor master = Hypervisor.getSingleton(); Hypervisor master = Hypervisor.getSingleton();
master.addSocialMedia(new TwitterBot()); master.addSocialMedia(new TwitterBot());
master.run(); master.run();
} }
} }

View File

@ -1,41 +1,41 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.exceptions; package xyz.vallat.louis.exceptions;
/** /**
* Exception throwable when there are no file at a given path. * Exception throwable when there are no file at a given path.
* *
* @author louis * @author louis
*/ */
public class NoSuchFile extends Exception { public class NoSuchFile extends Exception {
/** /**
* Creates a new instance of <code>NoSuchFile</code> without detail message. * Creates a new instance of <code>NoSuchFile</code> without detail message.
*/ */
public NoSuchFile() { public NoSuchFile() {
} }
/** /**
* Constructs an instance of <code>NoSuchFile</code> with the specified * Constructs an instance of <code>NoSuchFile</code> with the specified
* detail message. * detail message.
* *
* @param msg the detail message. * @param msg the detail message.
*/ */
public NoSuchFile(String msg) { public NoSuchFile(String msg) {
super(msg); super(msg);
} }
} }

View File

@ -1,42 +1,42 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.exceptions; package xyz.vallat.louis.exceptions;
/** /**
* Exception throwable when a sort order isn't a correct one. * Exception throwable when a sort order isn't a correct one.
* *
* @author louis * @author louis
*/ */
public class NoSuchOrder extends Exception { public class NoSuchOrder extends Exception {
/** /**
* Creates a new instance of <code>NoSuchOrder</code> without detail * Creates a new instance of <code>NoSuchOrder</code> without detail
* message. * message.
*/ */
public NoSuchOrder() { public NoSuchOrder() {
} }
/** /**
* Constructs an instance of <code>NoSuchOrder</code> with the specified * Constructs an instance of <code>NoSuchOrder</code> with the specified
* detail message. * detail message.
* *
* @param msg the detail message. * @param msg the detail message.
*/ */
public NoSuchOrder(String msg) { public NoSuchOrder(String msg) {
super(msg); super(msg);
} }
} }

View File

@ -1,43 +1,43 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.exceptions; package xyz.vallat.louis.exceptions;
/** /**
* Exception throwable when there are no property in the config file for a given * Exception throwable when there are no property in the config file for a given
* setting name/id. * setting name/id.
* *
* @author louis * @author louis
*/ */
public class NoSuchProperty extends Exception { public class NoSuchProperty extends Exception {
/** /**
* Creates a new instance of <code>NoSuchProperty</code> without detail * Creates a new instance of <code>NoSuchProperty</code> without detail
* message. * message.
*/ */
public NoSuchProperty() { public NoSuchProperty() {
} }
/** /**
* Constructs an instance of <code>NoSuchProperty</code> with the specified * Constructs an instance of <code>NoSuchProperty</code> with the specified
* detail message. * detail message.
* *
* @param msg the detail message. * @param msg the detail message.
*/ */
public NoSuchProperty(String msg) { public NoSuchProperty(String msg) {
super(msg); super(msg);
} }
} }

View File

@ -1,42 +1,42 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.exceptions; package xyz.vallat.louis.exceptions;
/** /**
* Exception throwable when the rights on a folder or a file aren't sufficient. * Exception throwable when the rights on a folder or a file aren't sufficient.
* *
* @author louis * @author louis
*/ */
public class NotSufficientRights extends Exception { public class NotSufficientRights extends Exception {
/** /**
* Creates a new instance of <code>NotSufficientRights</code> without detail * Creates a new instance of <code>NotSufficientRights</code> without detail
* message. * message.
*/ */
public NotSufficientRights() { public NotSufficientRights() {
} }
/** /**
* Constructs an instance of <code>NotSufficientRights</code> with the * Constructs an instance of <code>NotSufficientRights</code> with the
* specified detail message. * specified detail message.
* *
* @param msg the detail message. * @param msg the detail message.
*/ */
public NotSufficientRights(String msg) { public NotSufficientRights(String msg) {
super(msg); super(msg);
} }
} }

View File

@ -1,232 +1,229 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.redditHandler; package xyz.vallat.louis.redditHandler;
import RedditReposterBot.exceptions.NoSuchFile; import com.google.gson.*;
import RedditReposterBot.exceptions.NoSuchOrder; import xyz.vallat.louis.exceptions.NoSuchFile;
import RedditReposterBot.exceptions.NoSuchProperty; import xyz.vallat.louis.exceptions.NoSuchOrder;
import RedditReposterBot.exceptions.NotSufficientRights; import xyz.vallat.louis.exceptions.NoSuchProperty;
import com.google.gson.JsonArray; import xyz.vallat.louis.exceptions.NotSufficientRights;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import java.io.BufferedReader;
import com.google.gson.JsonSyntaxException; import java.io.IOException;
import java.io.BufferedReader; import java.io.InputStreamReader;
import java.io.IOException; import java.net.HttpURLConnection;
import java.io.InputStreamReader; import java.net.MalformedURLException;
import java.net.HttpURLConnection; import java.net.URL;
import java.net.MalformedURLException; import java.util.HashSet;
import java.net.URL;
import java.util.HashSet; /**
* Reddit extractor object.
/** *
* Reddit extractor object. * @author louis
* */
* @author louis public final class RedditExtractor {
*/
public final class RedditExtractor { /**
* Subreddit to extract infos from.
/** */
* Subreddit to extract infos from. private final SubReddit sub;
*/
private final SubReddit sub; /**
* Main Constructor.
/** *
* Main Constructor. * @param subreddit Subreddit name. Just after /r/
* *
* @param subreddit Subreddit name. Just after /r/ * @throws IOException
* * @throws NoSuchProperty
* @throws IOException * @throws NoSuchFile
* @throws RedditReposterBot.exceptions.NoSuchProperty * @throws NotSufficientRights
* @throws RedditReposterBot.exceptions.NoSuchFile * @throws NoSuchOrder
* @throws RedditReposterBot.exceptions.NotSufficientRights */
* @throws NoSuchOrder public RedditExtractor(String subreddit)
*/ throws IOException, NoSuchProperty, NoSuchFile,
public RedditExtractor(String subreddit) NotSufficientRights, NoSuchOrder {
throws IOException, NoSuchProperty, NoSuchFile, if (!doesSubredditExists(subreddit)) {
NotSufficientRights, NoSuchOrder { throw new MalformedURLException("This subreddit ("
if (!doesSubredditExists(subreddit)) { + subreddit + ") does not exist.");
throw new MalformedURLException("This subreddit (" } else {
+ subreddit + ") does not exist."); this.sub = new SubReddit(subreddit);
} else { }
this.sub = new SubReddit(subreddit); }
}
} /**
* Check if a subreddit exists.
/** *
* Check if a subreddit exists. * @param subredditName
* * @return if a subreddit exists
* @param subredditName */
* @return if a subreddit exists public boolean doesSubredditExists(String subredditName) {
*/ System.out.println("[*] Checking if subreddit /r/" + subredditName
public boolean doesSubredditExists(String subredditName) { + " exists.");
System.out.println("[*] Checking if subreddit /r/" + subredditName return ((JsonParser.parseString(getJsonFromURL(""
+ " exists."); + "https://www.reddit.com/api/search_reddit_names.json"
return ((new JsonParser() + "?query=" + subredditName + "&exact=true")).getAsJsonObject()
.parse(getJsonFromURL("" .get("names").getAsJsonArray()
+ "https://www.reddit.com/api/search_reddit_names.json" .size()) >= 1);
+ "?query=" + subredditName + "&exact=true")) }
.getAsJsonObject().get("names").getAsJsonArray()
.size()) >= 1); /**
} * Obtain the subreddit JSON response.
*
/** * @return the JSON from the REDDIT API.
* Obtain the subreddit JSON response. */
* public String getSubredditJson() {
* @return the JSON from the REDDIT API. return getJsonFromURL(this.sub.getJsonURL());
*/ }
public String getSubredditJson() {
return getJsonFromURL(this.sub.getJsonURL()); /**
} * Get JSON from URL.
*
/** * @param URL the JSON url.
* Get JSON from URL. * @return the JSON data as a String from the given URL.
* */
* @param URL the JSON url. public String getJsonFromURL(String URL) {
* @return the JSON data as a String from the given URL. try {
*/ System.out.println("[+] Obtaining JSON from URL " + URL + ".");
public String getJsonFromURL(String URL) { HttpURLConnection con;
try { URL myurl = new URL(URL);
System.out.println("[+] Obtaining JSON from URL " + URL + "."); con = (HttpURLConnection) myurl.openConnection();
HttpURLConnection con; try {
URL myurl = new URL(URL); con.setRequestMethod("GET");
con = (HttpURLConnection) myurl.openConnection(); con.setRequestProperty("User-Agent", "Mozilla 5.0 (Windows; U; "
try { + "Windows NT 5.1; en-US; rv:1.8.0.11) ");
con.setRequestMethod("GET"); StringBuilder response;
con.setRequestProperty("User-Agent", "Mozilla 5.0 (Windows; U; " try (BufferedReader in = new BufferedReader(
+ "Windows NT 5.1; en-US; rv:1.8.0.11) "); new InputStreamReader(con.getInputStream()))) {
StringBuilder response; String line;
try (BufferedReader in = new BufferedReader( response = new StringBuilder();
new InputStreamReader(con.getInputStream()))) { while ((line = in.readLine()) != null) {
String line; response.append(line);
response = new StringBuilder(); response.append(System.lineSeparator());
while ((line = in.readLine()) != null) { }
response.append(line); return response.toString();
response.append(System.lineSeparator()); }
} } finally {
return response.toString(); con.disconnect();
} }
} finally { } catch (IOException e) {
con.disconnect(); System.err.println("[!] IOException: " + e.getMessage());
} System.out.println("[!] Retrying...");
} catch (IOException e) { return getJsonFromURL(URL);
System.err.println("[!] IOException: " + e.getMessage()); }
System.out.println("[!] Retrying..."); }
return getJsonFromURL(URL);
} /**
} * Get Reddit's subreddit posts.
*
/** * @return a treeset of all the reddit posts parsed.
* Get Reddit's subreddit posts. */
* public HashSet<RedditPost> getRedditPosts() {
* @return a treeset of all the reddit posts parsed. try {
*/ HashSet<RedditPost> set = new HashSet<>();
public HashSet<RedditPost> getRedditPosts() { String jsonResponse = getSubredditJson();
try { JsonObject objet = JsonParser.parseString(jsonResponse)
HashSet<RedditPost> set = new HashSet<>(); .getAsJsonObject();
String jsonResponse = getSubredditJson(); JsonObject data = JsonParser.parseString(objet.get("data")
JsonObject objet = new JsonParser().parse(jsonResponse) .toString()).getAsJsonObject();
.getAsJsonObject(); JsonArray children = JsonParser.parseString(data.get("children")
JsonObject data = new JsonParser().parse(objet.get("data") .toString()).getAsJsonArray();
.toString()).getAsJsonObject(); for (int i = 0; i < children.size(); i++) {
JsonArray children = new JsonParser().parse(data.get("children") try {
.toString()).getAsJsonArray(); JsonObject child = JsonParser.parseString(children.get(i)
for (int i = 0; i < children.size(); i++) { .toString()).getAsJsonObject();
try { JsonObject childData = JsonParser.parseString(child.get("data")
JsonObject child = new JsonParser().parse(children.get(i) .toString()).getAsJsonObject();
.toString()).getAsJsonObject(); if (childData.get("id").toString() != null
JsonObject childData = new JsonParser().parse(child.get("data") && !childData.get("quarantine").getAsBoolean()
.toString()).getAsJsonObject(); && childData.get("url").getAsString() != null) {
if (childData.get("id").toString() != null String id = childData.get("id").toString();
&& !childData.get("quarantine").getAsBoolean() String title = childData.get("title") != null
&& childData.get("url").getAsString() != null) { ? childData.get("title").toString()
String id = childData.get("id").toString(); : this.sub.getName();
String title = childData.get("title") != null title = title
? childData.get("title").toString() .replace("\"", "")
: this.sub.getName(); .replace("\\", "\"")
title = title .replace("&lt;", "<")
.replace("\"", "") .replace("&gt;", ">")
.replace("\\", "\"") .replace("&amp;", "&");
.replace("&lt;", "<") String author = childData.get("author") != null
.replace("&gt;", ">") ? childData.get("author").toString()
.replace("&amp;", "&"); .replace("&lt;", "<")
String author = childData.get("author") != null .replace("&gt;", ">")
? childData.get("author").toString() .replace("&amp;", "&") : "anonymous";
.replace("&lt;", "<") author = author.replace("\"", "");
.replace("&gt;", ">") boolean quarantine = childData.get("quarantine")
.replace("&amp;", "&") : "anonymous"; .getAsBoolean();
author = author.replace("\"", ""); double score = childData.get("score").getAsDouble();
boolean quarantine = childData.get("quarantine") String postHint = childData.get("post_hint").getAsString();
.getAsBoolean(); boolean crosspostable = !childData.get("is_crosspostable")
double score = childData.get("score").getAsDouble(); .getAsBoolean();
String postHint = childData.get("post_hint").getAsString(); boolean over18 = childData.get("over_18").getAsBoolean();
boolean crosspostable = !childData.get("is_crosspostable") String url;
.getAsBoolean(); try {
boolean over18 = childData.get("over_18").getAsBoolean(); JsonObject preview = JsonParser.parseString(childData
String url; .get("preview").toString()).getAsJsonObject();
try { JsonArray previewImages = JsonParser.parseString(preview
JsonObject preview = new JsonParser().parse(childData .get("images").toString()).getAsJsonArray();
.get("preview").toString()).getAsJsonObject(); JsonObject source = JsonParser.parseString(previewImages
JsonArray previewImages = new JsonParser().parse(preview .get(0).toString()).getAsJsonObject();
.get("images").toString()).getAsJsonArray(); JsonObject urlSrc = JsonParser.parseString(source
JsonObject source = new JsonParser().parse(previewImages .get("source").toString()).getAsJsonObject();
.get(0).toString()).getAsJsonObject(); url = urlSrc.get("url").toString().replace("&amp;", "&")
JsonObject urlSrc = new JsonParser().parse(source .replace("\"", "");
.get("source").toString()).getAsJsonObject(); } catch (NullPointerException n) {
url = urlSrc.get("url").toString().replace("&amp;", "&") url = childData.get("url").getAsString();
.replace("\"", ""); }
} catch (NullPointerException n) { String permalink = childData.get("permalink").getAsString();
url = childData.get("url").getAsString(); boolean spoiler = childData.get("spoiler").getAsBoolean();
}
String permalink = childData.get("permalink").getAsString(); if (postHint.contains("video")) {
boolean spoiler = childData.get("spoiler").getAsBoolean(); set.add(new RedditPostVideo(
id, title, quarantine, score, postHint,
if (postHint.contains("video")) { crosspostable, over18, author,
set.add(new RedditPostVideo( permalink, spoiler, url));
id, title, quarantine, score, postHint, } else if ("link".equals(postHint)) {
crosspostable, over18, author, set.add(new RedditPostLink(
permalink, spoiler, url)); id, title, quarantine, score, postHint,
} else if ("link".equals(postHint)) { crosspostable, over18, author,
set.add(new RedditPostLink( permalink, spoiler, url));
id, title, quarantine, score, postHint, } else if ("text".equals(postHint)) {
crosspostable, over18, author, set.add(new RedditPostText(
permalink, spoiler, url)); id, title, quarantine, score, postHint,
} else if ("text".equals(postHint)) { crosspostable, over18, author,
set.add(new RedditPostText( permalink, spoiler, url));
id, title, quarantine, score, postHint, } else if ("image".equals(postHint)) {
crosspostable, over18, author, set.add(new RedditPostImage(
permalink, spoiler, url)); id, title, quarantine, score, postHint,
} else if ("image".equals(postHint)) { crosspostable, over18, author,
set.add(new RedditPostImage( permalink, spoiler, url));
id, title, quarantine, score, postHint, }
crosspostable, over18, author, }
permalink, spoiler, url)); } catch (NullPointerException e) {
} System.out.println(
} "[*] There were a problem while parsing. "
} catch (NullPointerException e) { + "Continuing");
System.out.println( }
"[*] There were a problem while parsing. " }
+ "Continuing"); return set;
} } catch (JsonSyntaxException e) {
} System.err.println("[!] JsonSyntaxException: " + e.getMessage());
return set; System.exit(1);
} catch (JsonSyntaxException e) { }
System.err.println("[!] JsonSyntaxException: " + e.getMessage()); return null;
System.exit(1); }
} }
return null;
}
}

View File

@ -1,265 +1,265 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.redditHandler; package xyz.vallat.louis.redditHandler;
/** /**
* This is an abstract class to define all RedditPosts. * This is an abstract class to define all RedditPosts.
* *
* @author louis * @author louis
*/ */
public abstract class RedditPost { public abstract class RedditPost {
/** /**
* Post's id. * Post's id.
*/ */
protected String postId; protected String postId;
/** /**
* Post's title. * Post's title.
*/ */
protected String title; protected String title;
/** /**
* Is the post in quarantine? * Is the post in quarantine?
*/ */
protected boolean quarantine; protected boolean quarantine;
/** /**
* Post's score. * Post's score.
*/ */
protected double score; protected double score;
/** /**
* Post's hint. * Post's hint.
*/ */
protected String postHint; protected String postHint;
/** /**
* Is this post crosspostable? * Is this post crosspostable?
*/ */
protected boolean crosspostable; protected boolean crosspostable;
/** /**
* Is this post NSFW? * Is this post NSFW?
*/ */
protected boolean over18; protected boolean over18;
/** /**
* Post's author. * Post's author.
*/ */
protected String author; protected String author;
/** /**
* Post's permalink. * Post's permalink.
*/ */
protected String permalink; protected String permalink;
/** /**
* Is this post a spoiler? * Is this post a spoiler?
*/ */
protected boolean spoiler; protected boolean spoiler;
/** /**
* Post's media url. * Post's media url.
*/ */
protected String url; protected String url;
/** /**
* Main constructor for a Reddit post. * Main constructor for a Reddit post.
* *
* @param id post's id * @param id post's id
* @param title post's title * @param title post's title
* @param quarantine is this post in quarantine? * @param quarantine is this post in quarantine?
* @param score post's score * @param score post's score
* @param postHint post's hint * @param postHint post's hint
* @param crosspostable is post crosspostable? * @param crosspostable is post crosspostable?
* @param over18 is post NSFW? * @param over18 is post NSFW?
* @param author post's author * @param author post's author
* @param permalink post's permalink * @param permalink post's permalink
* @param spoiler is this post a spoiler? * @param spoiler is this post a spoiler?
* @param url post's media url * @param url post's media url
*/ */
public RedditPost(String id, String title, boolean quarantine, double score, public RedditPost(String id, String title, boolean quarantine, double score,
String postHint, boolean crosspostable, boolean over18, String postHint, boolean crosspostable, boolean over18,
String author, String permalink, boolean spoiler, String url) { String author, String permalink, boolean spoiler, String url) {
this.postId = id; this.postId = id;
this.title = title; this.title = title;
this.quarantine = quarantine; this.quarantine = quarantine;
this.score = score; this.score = score;
this.postHint = postHint; this.postHint = postHint;
this.crosspostable = crosspostable; this.crosspostable = crosspostable;
this.over18 = over18; this.over18 = over18;
this.author = author; this.author = author;
this.permalink = permalink; this.permalink = permalink;
this.spoiler = spoiler; this.spoiler = spoiler;
this.url = url; this.url = url;
} }
/** /**
* Get post's URL. * Get post's URL.
* *
* @return the post's media URL. * @return the post's media URL.
*/ */
public String getUrl() { public String getUrl() {
return url; return url;
} }
/** /**
* Check if the Media URL is correct. * Check if the Media URL is correct.
* *
* @return if the URL is correct. * @return if the URL is correct.
*/ */
public boolean hasMediaUrl() { public boolean hasMediaUrl() {
return url.contains(".jpg") || url.contains(".png"); return url.contains(".jpg") || url.contains(".png");
} }
/** /**
* Get post's title. * Get post's title.
* *
* @return post's title. * @return post's title.
*/ */
public String getTitle() { public String getTitle() {
return title; return title;
} }
/** /**
* Is this post in quarantine? * Is this post in quarantine?
* *
* @return if the post is in quarantine. * @return if the post is in quarantine.
*/ */
public boolean isQuarantine() { public boolean isQuarantine() {
return quarantine; return quarantine;
} }
/** /**
* Set quarantine state for the post. * Set quarantine state for the post.
* *
* @param state the state to apply. * @param state the state to apply.
*/ */
public void setQuarantineState(boolean state) { public void setQuarantineState(boolean state) {
this.quarantine = state; this.quarantine = state;
} }
/** /**
* Get post's score. * Get post's score.
* *
* @return last known post's score. * @return last known post's score.
*/ */
public double getScore() { public double getScore() {
return score; return score;
} }
/** /**
* Update post's score. * Update post's score.
* *
* @param newScore the new score. * @param newScore the new score.
*/ */
public void updateScore(double newScore) { public void updateScore(double newScore) {
this.score = newScore; this.score = newScore;
} }
/** /**
* Get post's hint. * Get post's hint.
* *
* @return post's hint. * @return post's hint.
*/ */
public String getPostHint() { public String getPostHint() {
return postHint; return postHint;
} }
/** /**
* Is this post crosspostable? * Is this post crosspostable?
* *
* @return if the post is crosspostable. * @return if the post is crosspostable.
*/ */
public boolean isCrosspostable() { public boolean isCrosspostable() {
return crosspostable; return crosspostable;
} }
/** /**
* Is this post NSFW? * Is this post NSFW?
* *
* @return if the post is Not Safe For Work. * @return if the post is Not Safe For Work.
*/ */
public boolean isOver18() { public boolean isOver18() {
return over18; return over18;
} }
/** /**
* Get post's author. * Get post's author.
* *
* @return post's author. * @return post's author.
*/ */
public String getAuthor() { public String getAuthor() {
return author; return author;
} }
/** /**
* Get post's permalink. * Get post's permalink.
* *
* @return the post's permalink. * @return the post's permalink.
*/ */
public String getPermalink() { public String getPermalink() {
return permalink; return permalink;
} }
/** /**
* Is this post a spoiler? * Is this post a spoiler?
* *
* @return if the post is a spoiler. * @return if the post is a spoiler.
*/ */
public boolean isSpoiler() { public boolean isSpoiler() {
return spoiler; return spoiler;
} }
/** /**
* Get post's id. * Get post's id.
* *
* @return post's id. * @return post's id.
*/ */
public String getPostId() { public String getPostId() {
return postId; return postId;
} }
/** /**
* Is this post an image? * Is this post an image?
* *
* @return if the post is an image. * @return if the post is an image.
*/ */
public abstract boolean isImage(); public abstract boolean isImage();
/** /**
* Is this post a text? * Is this post a text?
* *
* @return if the post is a text. * @return if the post is a text.
*/ */
public abstract boolean isText(); public abstract boolean isText();
/** /**
* Is this post a video? * Is this post a video?
* *
* @return if the post is a video. * @return if the post is a video.
*/ */
public abstract boolean isVideo(); public abstract boolean isVideo();
/** /**
* Is this post a link? * Is this post a link?
* *
* @return if the post is a link. * @return if the post is a link.
*/ */
public abstract boolean isLink(); public abstract boolean isLink();
} }

View File

@ -1,53 +1,53 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.redditHandler; package xyz.vallat.louis.redditHandler;
/** /**
* Reddit image post object representation. * Reddit image post object representation.
* *
* @author louis * @author louis
*/ */
public class RedditPostImage extends RedditPost { public class RedditPostImage extends RedditPost {
public RedditPostImage(String id, String title, boolean quarantine, public RedditPostImage(String id, String title, boolean quarantine,
double score, String postHint, boolean crosspostable, double score, String postHint, boolean crosspostable,
boolean over18, String author, String permalink, boolean over18, String author, String permalink,
boolean spoiler, String url) { boolean spoiler, String url) {
super(id, title, quarantine, score, postHint, super(id, title, quarantine, score, postHint,
crosspostable, over18, author, permalink, spoiler, url); crosspostable, over18, author, permalink, spoiler, url);
} }
@Override @Override
public boolean isImage() { public boolean isImage() {
return true; return true;
} }
@Override @Override
public boolean isText() { public boolean isText() {
return false; return false;
} }
@Override @Override
public boolean isVideo() { public boolean isVideo() {
return false; return false;
} }
@Override @Override
public boolean isLink() { public boolean isLink() {
return false; return false;
} }
} }

View File

@ -1,54 +1,54 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.redditHandler; package xyz.vallat.louis.redditHandler;
/** /**
* Reddit link post object representation. * Reddit link post object representation.
* *
* @author louis * @author louis
*/ */
public class RedditPostLink extends RedditPost { public class RedditPostLink extends RedditPost {
public RedditPostLink(String id, String title, boolean quarantine, public RedditPostLink(String id, String title, boolean quarantine,
double score, String postHint, boolean crosspostable, double score, String postHint, boolean crosspostable,
boolean over18, String author, String permalink, boolean over18, String author, String permalink,
boolean spoiler, String url) { boolean spoiler, String url) {
super(id, title, quarantine, score, postHint, super(id, title, quarantine, score, postHint,
crosspostable, over18, author, permalink, spoiler, url); crosspostable, over18, author, permalink, spoiler, url);
} }
@Override @Override
public boolean isImage() { public boolean isImage() {
return false; return false;
} }
@Override @Override
public boolean isText() { public boolean isText() {
return false; return false;
} }
@Override @Override
public boolean isVideo() { public boolean isVideo() {
return false; return false;
} }
@Override @Override
public boolean isLink() { public boolean isLink() {
return true; return true;
} }
} }

View File

@ -1,53 +1,53 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.redditHandler; package xyz.vallat.louis.redditHandler;
/** /**
* Reddit text post object representation. * Reddit text post object representation.
* *
* @author louis * @author louis
*/ */
public class RedditPostText extends RedditPost { public class RedditPostText extends RedditPost {
public RedditPostText(String id, String title, boolean quarantine, public RedditPostText(String id, String title, boolean quarantine,
double score, String postHint, boolean crosspostable, double score, String postHint, boolean crosspostable,
boolean over18, String author, String permalink, boolean over18, String author, String permalink,
boolean spoiler, String url) { boolean spoiler, String url) {
super(id, title, quarantine, score, postHint, super(id, title, quarantine, score, postHint,
crosspostable, over18, author, permalink, spoiler, url); crosspostable, over18, author, permalink, spoiler, url);
} }
@Override @Override
public boolean isImage() { public boolean isImage() {
return false; return false;
} }
@Override @Override
public boolean isText() { public boolean isText() {
return true; return true;
} }
@Override @Override
public boolean isVideo() { public boolean isVideo() {
return false; return false;
} }
@Override @Override
public boolean isLink() { public boolean isLink() {
return false; return false;
} }
} }

View File

@ -1,54 +1,54 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.redditHandler; package xyz.vallat.louis.redditHandler;
/** /**
* Reddit video post object representation. * Reddit video post object representation.
* *
* @author louis * @author louis
*/ */
public class RedditPostVideo extends RedditPost { public class RedditPostVideo extends RedditPost {
public RedditPostVideo(String id, String title, boolean quarantine, public RedditPostVideo(String id, String title, boolean quarantine,
double score, String postHint, boolean crosspostable, double score, String postHint, boolean crosspostable,
boolean over18, String author, String permalink, boolean over18, String author, String permalink,
boolean spoiler, String url) { boolean spoiler, String url) {
super(id, title, quarantine, score, postHint, super(id, title, quarantine, score, postHint,
crosspostable, over18, author, permalink, spoiler, url); crosspostable, over18, author, permalink, spoiler, url);
} }
@Override @Override
public boolean isImage() { public boolean isImage() {
return false; return false;
} }
@Override @Override
public boolean isText() { public boolean isText() {
return false; return false;
} }
@Override @Override
public boolean isVideo() { public boolean isVideo() {
return true; return true;
} }
@Override @Override
public boolean isLink() { public boolean isLink() {
return false; return false;
} }
} }

View File

@ -1,148 +1,148 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.redditHandler; package xyz.vallat.louis.redditHandler;
import RedditReposterBot.ConfigFileReader; import xyz.vallat.louis.ConfigFileReader;
import RedditReposterBot.exceptions.NoSuchFile; import xyz.vallat.louis.exceptions.NoSuchFile;
import RedditReposterBot.exceptions.NoSuchOrder; import xyz.vallat.louis.exceptions.NoSuchOrder;
import RedditReposterBot.exceptions.NoSuchProperty; import xyz.vallat.louis.exceptions.NoSuchProperty;
import RedditReposterBot.exceptions.NotSufficientRights; import xyz.vallat.louis.exceptions.NotSufficientRights;
import java.util.Arrays; import java.util.Arrays;
/** /**
* A subreddit. * A subreddit.
* *
* @author louis * @author louis
*/ */
public final class SubReddit { public final class SubReddit {
/** /**
* Subreddit's name. * Subreddit's name.
*/ */
private final String name; private final String name;
/** /**
* Subreddit's URL. * Subreddit's URL.
*/ */
private final String url; private final String url;
/** /**
* Subreddit's JSON URL. * Subreddit's JSON URL.
*/ */
private final String jsonURL; private final String jsonURL;
/** /**
* Dist limit for the JSON api call. * Dist limit for the JSON api call.
*/ */
private int limit; private int limit;
/** /**
* Order for the JSON (by default, new). * Order for the JSON (by default, new).
*/ */
private String order; private String order;
/** /**
* Main constructor. * Main constructor.
* *
* @param name subreddit's name * @param name subreddit's name
* *
* @throws RedditReposterBot.exceptions.NoSuchProperty * @throws NoSuchProperty
* @throws RedditReposterBot.exceptions.NoSuchFile * @throws NoSuchFile
* @throws RedditReposterBot.exceptions.NotSufficientRights * @throws NotSufficientRights
* @throws RedditReposterBot.exceptions.NoSuchOrder * @throws NoSuchOrder
*/ */
public SubReddit(String name) throws NoSuchProperty, NoSuchFile, public SubReddit(String name) throws NoSuchProperty, NoSuchFile,
NotSufficientRights, NoSuchOrder { NotSufficientRights, NoSuchOrder {
this.name = name; this.name = name;
ConfigFileReader reader = new ConfigFileReader(); ConfigFileReader reader = new ConfigFileReader();
setLimit(Integer.valueOf(reader.getProperties("reddit_posts_limit"))); setLimit(Integer.valueOf(reader.getProperties("reddit_posts_limit")));
setOrder(reader.getProperties("reddit_posts_sorting_order")); setOrder(reader.getProperties("reddit_posts_sorting_order"));
this.url = "https://www.reddit.com/r/" + name + "/"; this.url = "https://www.reddit.com/r/" + name + "/";
this.jsonURL this.jsonURL
= this.url.substring(0, this.url.length()) + order + ".json"; = this.url.substring(0, this.url.length()) + order + ".json";
} }
/** /**
* Set subreddit dist limit for parsing JSON file. * Set subreddit dist limit for parsing JSON file.
* *
* @param limit the limit between 1 and 100. * @param limit the limit between 1 and 100.
*/ */
public void setLimit(int limit) { public void setLimit(int limit) {
if (limit < 1 || limit > 100) { if (limit < 1 || limit > 100) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Limit should be between 1 and 100, and it was" "Limit should be between 1 and 100, and it was"
+ limit + "."); + limit + ".");
} else { } else {
this.limit = limit; this.limit = limit;
} }
} }
/** /**
* Set order for the subreddit. * Set order for the subreddit.
* *
* @param order an order to set * @param order an order to set
* *
* @throws NoSuchOrder * @throws NoSuchOrder
*/ */
public void setOrder(String order) throws NoSuchOrder { public void setOrder(String order) throws NoSuchOrder {
String[] availableOrders String[] availableOrders
= {"new", "hot", "best", "controversial", "top", "rising"}; = {"new", "hot", "best", "controversial", "top", "rising"};
if (!Arrays.asList(availableOrders).contains(order)) { if (!Arrays.asList(availableOrders).contains(order)) {
throw new NoSuchOrder("This order " + order throw new NoSuchOrder("This order " + order
+ "isn't allowed. Orders allowed are: " + "isn't allowed. Orders allowed are: "
+ Arrays.toString(availableOrders)); + Arrays.toString(availableOrders));
} else { } else {
this.order = order; this.order = order;
} }
} }
/** /**
* Get subreddit dist limit. * Get subreddit dist limit.
* *
* @return the limit. * @return the limit.
*/ */
public int getLimit() { public int getLimit() {
return limit; return limit;
} }
/** /**
* Get name. * Get name.
* *
* @return the name. * @return the name.
*/ */
public String getName() { public String getName() {
return name; return name;
} }
/** /**
* Get the url. * Get the url.
* *
* @return the subreddit's url. * @return the subreddit's url.
*/ */
public String getUrl() { public String getUrl() {
return url; return url;
} }
/** /**
* Get the JSON URL. * Get the JSON URL.
* *
* @return the subreddit's JSON URL. * @return the subreddit's JSON URL.
*/ */
public String getJsonURL() { public String getJsonURL() {
return jsonURL + "?limit=" + limit; return jsonURL + "?limit=" + limit;
} }
} }

View File

@ -1,35 +1,35 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.socialMediaHandler; package xyz.vallat.louis.socialMediaHandler;
/** /**
* Interface to specify what methods should social media posters implement. * Interface to specify what methods should social media posters implement.
* *
* @author louis * @author louis
*/ */
public interface SocialMediaPoster { public interface SocialMediaPoster {
public String getSocialMediaName(); public String getSocialMediaName();
public long postText(String text); public long postText(String text);
public long postImage(String imagePath); public long postImage(String imagePath);
public long postImage(String text, String imagePath); public long postImage(String text, String imagePath);
public long replyText(String text, long tweetId); public long replyText(String text, long tweetId);
} }

View File

@ -1,205 +1,205 @@
/* /*
* Copyright (C) 2019 louis * Copyright (C) 2019 louis
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package RedditReposterBot.socialMediaHandler; package xyz.vallat.louis.socialMediaHandler;
import RedditReposterBot.exceptions.NotSufficientRights; import xyz.vallat.louis.exceptions.NotSufficientRights;
import RedditReposterBot.exceptions.NoSuchProperty; import xyz.vallat.louis.exceptions.NoSuchProperty;
import RedditReposterBot.ConfigFileReader; import xyz.vallat.louis.ConfigFileReader;
import RedditReposterBot.exceptions.NoSuchFile; import xyz.vallat.louis.exceptions.NoSuchFile;
import java.io.File; import java.io.File;
import twitter4j.StatusUpdate; import twitter4j.StatusUpdate;
import twitter4j.Twitter; import twitter4j.Twitter;
import twitter4j.TwitterException; import twitter4j.TwitterException;
import twitter4j.TwitterFactory; import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder; import twitter4j.conf.ConfigurationBuilder;
/** /**
* Twutter Bot object. * Twutter Bot object.
* *
* @author louis * @author louis
*/ */
public final class TwitterBot implements SocialMediaPoster { public final class TwitterBot implements SocialMediaPoster {
/** /**
* The twitter link. * The twitter link.
*/ */
private final Twitter twitter; private final Twitter twitter;
/** /**
* The Twitter API consumer key. * The Twitter API consumer key.
*/ */
private final String consumerKey; private final String consumerKey;
/** /**
* The Twitter API consumer secret. * The Twitter API consumer secret.
*/ */
private final String consumerSecret; private final String consumerSecret;
/** /**
* The Twitter API access token. * The Twitter API access token.
*/ */
private final String accessToken; private final String accessToken;
/** /**
* The Twitter API access secret. * The Twitter API access secret.
*/ */
private final String accessSecret; private final String accessSecret;
/** /**
* Main constructor for the Twitter Bot. * Main constructor for the Twitter Bot.
* *
* @throws RedditReposterBot.exceptions.NoSuchFile * @throws RedditReposterBot.exceptions.NoSuchFile
* @throws RedditReposterBot.exceptions.NotSufficientRights * @throws RedditReposterBot.exceptions.NotSufficientRights
* @throws RedditReposterBot.exceptions.NoSuchProperty * @throws RedditReposterBot.exceptions.NoSuchProperty
*/ */
public TwitterBot() throws NoSuchFile, NotSufficientRights, NoSuchProperty { public TwitterBot() throws NoSuchFile, NotSufficientRights, NoSuchProperty {
ConfigFileReader reader = new ConfigFileReader(); ConfigFileReader reader = new ConfigFileReader();
this.consumerKey = reader.getProperties("twitterAPI_consumerKey"); this.consumerKey = reader.getProperties("twitterAPI_consumerKey");
this.consumerSecret = reader.getProperties("twitterAPI_consumerSecret"); this.consumerSecret = reader.getProperties("twitterAPI_consumerSecret");
this.accessToken = reader.getProperties("twitterAPI_accessToken"); this.accessToken = reader.getProperties("twitterAPI_accessToken");
this.accessSecret = reader.getProperties("twitterAPI_accessSecret"); this.accessSecret = reader.getProperties("twitterAPI_accessSecret");
ConfigurationBuilder cb = new ConfigurationBuilder(); ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true) cb.setDebugEnabled(true)
.setOAuthConsumerKey(consumerKey) .setOAuthConsumerKey(consumerKey)
.setOAuthConsumerSecret(consumerSecret) .setOAuthConsumerSecret(consumerSecret)
.setOAuthAccessToken(accessToken) .setOAuthAccessToken(accessToken)
.setOAuthAccessTokenSecret(accessSecret); .setOAuthAccessTokenSecret(accessSecret);
TwitterFactory factory = new TwitterFactory(cb.build()); TwitterFactory factory = new TwitterFactory(cb.build());
this.twitter = factory.getInstance(); this.twitter = factory.getInstance();
showScreenName(); showScreenName();
} }
/** /**
* Print the bot's screen name. * Print the bot's screen name.
*/ */
public void showScreenName() { public void showScreenName() {
try { try {
System.out.println("[+] Connected as user @" System.out.println("[+] Connected as user @"
+ this.twitter.getScreenName() + this.twitter.getScreenName()
+ " on " + getSocialMediaName() + "."); + " on " + getSocialMediaName() + ".");
} catch (TwitterException te) { } catch (TwitterException te) {
System.err.println("[!] TwitterException: " + te.getMessage()); System.err.println("[!] TwitterException: " + te.getMessage());
System.exit(1); System.exit(1);
} }
} }
/** /**
* Tweet a text. * Tweet a text.
* *
* @param text the text to tweet. * @param text the text to tweet.
* @return the tweet's id. * @return the tweet's id.
*/ */
@Override @Override
public long postText(String text) { public long postText(String text) {
try { try {
System.out.println("[+] Tweeting \"" + text + "\"."); System.out.println("[+] Tweeting \"" + text + "\".");
return twitter.updateStatus(text).getId(); return twitter.updateStatus(text).getId();
} catch (TwitterException te) { } catch (TwitterException te) {
System.err.println("[!] TwitterException: " + te.getMessage()); System.err.println("[!] TwitterException: " + te.getMessage());
} }
return 0; return 0;
} }
/** /**
* Tweet an image. * Tweet an image.
* *
* @param imagePath the path to the image. * @param imagePath the path to the image.
* @return the tweet's id. * @return the tweet's id.
*/ */
@Override @Override
public long postImage(String imagePath) { public long postImage(String imagePath) {
System.out.println("[+] Tweeting image."); System.out.println("[+] Tweeting image.");
File file = new File(imagePath); File file = new File(imagePath);
StatusUpdate status = new StatusUpdate(""); StatusUpdate status = new StatusUpdate("");
status.setMedia(file); status.setMedia(file);
try { try {
return twitter.updateStatus(status).getId(); return twitter.updateStatus(status).getId();
} catch (TwitterException te) { } catch (TwitterException te) {
System.err.println("[!] TwitterException: " + te.getMessage()); System.err.println("[!] TwitterException: " + te.getMessage());
} }
return 0; return 0;
} }
/** /**
* Post an image with some text. * Post an image with some text.
* *
* @param text image's caption. * @param text image's caption.
* @param imagePath path to the image. * @param imagePath path to the image.
* @return the tweet's id. * @return the tweet's id.
*/ */
@Override @Override
public long postImage(String text, String imagePath) { public long postImage(String text, String imagePath) {
System.out.println("[+] Tweeting image with caption \"" + text + "\"."); System.out.println("[+] Tweeting image with caption \"" + text + "\".");
File file = new File(imagePath); File file = new File(imagePath);
StatusUpdate status = new StatusUpdate(text); StatusUpdate status = new StatusUpdate(text);
status.setMedia(file); status.setMedia(file);
try { try {
return twitter.updateStatus(status).getId(); return twitter.updateStatus(status).getId();
} catch (TwitterException te) { } catch (TwitterException te) {
System.err.println("[!] TwitterException: " + te.getMessage()); System.err.println("[!] TwitterException: " + te.getMessage());
} }
return 0; return 0;
} }
/** /**
* Get the social media name. * Get the social media name.
* *
* @return the social media name. * @return the social media name.
*/ */
@Override @Override
public String getSocialMediaName() { public String getSocialMediaName() {
return "Twitter"; return "Twitter";
} }
/** /**
* Get the screen name. * Get the screen name.
* *
* @return the user's screen name. * @return the user's screen name.
* *
* @throws TwitterException * @throws TwitterException
*/ */
public String getScreenName() throws TwitterException { public String getScreenName() throws TwitterException {
return this.twitter.getScreenName(); return this.twitter.getScreenName();
} }
/** /**
* Reply to a tweet. * Reply to a tweet.
* *
* @param text the text to tweet. * @param text the text to tweet.
* @param tweetId the tweet id. * @param tweetId the tweet id.
* @return the reply's id. * @return the reply's id.
*/ */
@Override @Override
public long replyText(String text, long tweetId) { public long replyText(String text, long tweetId) {
System.out.println("[+] Replying \"" + text + "\" to tweet " System.out.println("[+] Replying \"" + text + "\" to tweet "
+ tweetId + "."); + tweetId + ".");
StatusUpdate statusReply = new StatusUpdate(text); StatusUpdate statusReply = new StatusUpdate(text);
statusReply.setInReplyToStatusId(tweetId); statusReply.setInReplyToStatusId(tweetId);
try { try {
twitter.updateStatus(statusReply); twitter.updateStatus(statusReply);
} catch (TwitterException ex) { } catch (TwitterException ex) {
System.err.println("TwitterException: " + ex.getMessage()); System.err.println("TwitterException: " + ex.getMessage());
} }
return statusReply.getInReplyToStatusId(); return statusReply.getInReplyToStatusId();
} }
} }