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
*.class
# 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
*.iml
.idea/
target/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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