summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Laveaux <m.laveaux@student.tue.nl>2014-04-23 16:10:43 +0200
committerMaurice Laveaux <m.laveaux@student.tue.nl>2014-04-23 16:10:43 +0200
commit784229d0f41a4272ad1c40a63e4603bc8629ec01 (patch)
tree5094f481fe04cd23eb79fd0a02e9f5cd2153d192
parentab095e0ecbe63dc19f4de69872b14aee921bba6b (diff)
downloadTwitterDataAnalytics-784229d0f41a4272ad1c40a63e4603bc8629ec01.tar.gz
Implemented Authorization with twitter.
Started working on getProfile for a given username.
-rw-r--r--src/data/Profile.java16
-rw-r--r--src/data/Tweet.java9
-rw-r--r--src/gui/MainFrame.form54
-rw-r--r--src/gui/MainFrame.java100
-rw-r--r--src/main/Main.java14
-rw-r--r--src/mining/Authentication.java206
-rw-r--r--src/mining/Miner.java25
-rw-r--r--src/mining/Search.java118
-rw-r--r--src/mining/Stream.java9
9 files changed, 551 insertions, 0 deletions
diff --git a/src/data/Profile.java b/src/data/Profile.java
new file mode 100644
index 0000000..e4ba602
--- /dev/null
+++ b/src/data/Profile.java
@@ -0,0 +1,16 @@
+
+package data;
+
+/**
+ * This class contains the data that is stored of a user.
+ */
+public class Profile {
+
+ private boolean m_exists;
+
+ private String m_name;
+
+ private String m_realName;
+
+ private String m_creationDate;
+}
diff --git a/src/data/Tweet.java b/src/data/Tweet.java
new file mode 100644
index 0000000..ebaabf3
--- /dev/null
+++ b/src/data/Tweet.java
@@ -0,0 +1,9 @@
+
+package data;
+
+/**
+ * This class contains the data that is stored within a Tweet.
+ */
+public class Tweet {
+
+}
diff --git a/src/gui/MainFrame.form b/src/gui/MainFrame.form
new file mode 100644
index 0000000..a972587
--- /dev/null
+++ b/src/gui/MainFrame.form
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
+ <Properties>
+ <Property name="defaultCloseOperation" type="int" value="3"/>
+ </Properties>
+ <SyntheticProperties>
+ <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+ <SyntheticProperty name="generateCenter" type="boolean" value="false"/>
+ </SyntheticProperties>
+ <AuxValues>
+ <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+ </AuxValues>
+
+ <Layout>
+ <DimensionLayout dim="0">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="0" attributes="0">
+ <EmptySpace max="-2" attributes="0"/>
+ <Component id="jButton1" min="-2" max="-2" attributes="0"/>
+ <EmptySpace pref="470" max="32767" attributes="0"/>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ <DimensionLayout dim="1">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="0" attributes="0">
+ <EmptySpace max="-2" attributes="0"/>
+ <Component id="jButton1" min="-2" max="-2" attributes="0"/>
+ <EmptySpace pref="369" max="32767" attributes="0"/>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ </Layout>
+ <SubComponents>
+ <Component class="javax.swing.JButton" name="jButton1">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="Authenticate"/>
+ <Property name="actionCommand" type="java.lang.String" value="Authenticate"/>
+ </Properties>
+ <Events>
+ <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
+ </Events>
+ </Component>
+ </SubComponents>
+</Form>
diff --git a/src/gui/MainFrame.java b/src/gui/MainFrame.java
new file mode 100644
index 0000000..2e82fc6
--- /dev/null
+++ b/src/gui/MainFrame.java
@@ -0,0 +1,100 @@
+package gui;
+
+
+/**
+ *
+ * @author maurice
+ */
+public class MainFrame extends javax.swing.JFrame {
+
+ /**
+ * Creates new form MainFrame
+ */
+ public MainFrame() {
+ initComponents();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jButton1 = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+
+ jButton1.setText("Authenticate");
+ jButton1.setActionCommand("Authenticate");
+ jButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton1ActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jButton1)
+ .addContainerGap(470, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jButton1)
+ .addContainerGap(369, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// </editor-fold>//GEN-END:initComponents
+
+ private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_jButton1ActionPerformed
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+ /* Set the Nimbus look and feel */
+ //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
+ /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+ * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
+ */
+ try {
+ for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ javax.swing.UIManager.setLookAndFeel(info.getClassName());
+ break;
+ }
+ }
+ } catch (ClassNotFoundException ex) {
+ java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (InstantiationException ex) {
+ java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (IllegalAccessException ex) {
+ java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (javax.swing.UnsupportedLookAndFeelException ex) {
+ java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ }
+ //</editor-fold>
+
+ /* Create and display the form */
+ java.awt.EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ new MainFrame().setVisible(true);
+ }
+ });
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton jButton1;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/main/Main.java b/src/main/Main.java
new file mode 100644
index 0000000..f9b0cec
--- /dev/null
+++ b/src/main/Main.java
@@ -0,0 +1,14 @@
+package main;
+
+import mining.Miner;
+
+/**
+ *
+ */
+public class Main {
+
+ public static void main(String[] args)
+ {
+ Miner miner = new Miner();
+ }
+}
diff --git a/src/mining/Authentication.java b/src/mining/Authentication.java
new file mode 100644
index 0000000..d68843a
--- /dev/null
+++ b/src/mining/Authentication.java
@@ -0,0 +1,206 @@
+package mining;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Scanner;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import oauth.signpost.OAuth;
+import oauth.signpost.OAuthConsumer;
+import oauth.signpost.OAuthProvider;
+import oauth.signpost.basic.DefaultOAuthConsumer;
+import oauth.signpost.basic.DefaultOAuthProvider;
+import oauth.signpost.exception.OAuthCommunicationException;
+import oauth.signpost.exception.OAuthException;
+import oauth.signpost.exception.OAuthExpectationFailedException;
+import oauth.signpost.exception.OAuthMessageSignerException;
+import oauth.signpost.exception.OAuthNotAuthorizedException;
+
+import utils.Configuration;
+
+/**
+ * This class uses the Open Authentication API to register the application with
+ * twitter.com, before obtaining data.
+ */
+public class Authentication {
+
+ // the consumer to sign http requests with.
+ private final OAuthConsumer m_consumer;
+
+ // the public access token of this application.
+ private String m_accessToken = "unknown";
+
+ // the secret access token of this application.
+ private String m_secretToken = "unknown";
+
+ /**
+ * Authenticates the application and else throws exception.
+ *
+ * @param consumerKey The key that was returned for the application.
+ * @param consumerSecret The secret that was returned for the application.
+ */
+ public Authentication(final String consumerKey, final String consumerSecret) throws IOException {
+ final String savefile = "stored_tokens.txt";
+
+ try {
+ // Obtain the last stored tokens.
+ load(savefile);
+ } catch (FileNotFoundException ex) {
+ // Create the file when it doesn't exist.
+ save(savefile);
+ }
+
+ // consumer (this application keys) given to the provider.
+ m_consumer = new DefaultOAuthConsumer(Configuration.CONSUMER_KEY, Configuration.CONSUMER_SECRET);
+
+ // set the stored authentication tokens.
+ m_consumer.setTokenWithSecret(m_accessToken, m_secretToken);
+
+ // Try if the authentication is successfull
+ if (isAuthenticated()) {
+ System.out.println("Authentication granted.");
+ return;
+ }
+
+ // full authentication for the server.
+ fullAuthenticate(consumerKey, consumerSecret);
+
+ // Try if the authentication is successfull
+ if (!isAuthenticated()) {
+ throw new RuntimeException("Authentication fails after succeeding.");
+ } else {
+ System.out.println("Authentication granted.");
+ }
+
+ // save the obtained tokens.
+ save(savefile);
+ }
+
+ /**
+ *
+ * @param consumerKey The given consumer key for the program.
+ * @param secretKey The given secret key for the program.
+ * @param savefile
+ * @throws RuntimeException
+ */
+ private void fullAuthenticate(final String consumerKey, final String consumerSecret) throws RuntimeException {
+ try {
+ //consumer key for Twitter Data Analytics application
+ if (consumerKey.isEmpty()) {
+ throw new RuntimeException("OAuthUtils.CONSUMER_KEY was not set, Register an application "
+ + "and copy the consumer key into the configuration file.");
+ }
+
+ //consumer key for Twitter Data Analytics application
+ if (consumerSecret.isEmpty()) {
+ throw new RuntimeException("OAuthUtils.CONSUMER_SECRET was not set, Register an application "
+ + "and copy the consumer secret into the configuration file.");
+ }
+
+ // Provides the open authentication.
+ OAuthProvider provider = new DefaultOAuthProvider(Configuration.REQUEST_TOKEN_URL, Configuration.ACCESS_TOKEN_URL, Configuration.AUTHORIZE_URL);
+
+ // retrieve the url to authenticate this program with.
+ String authUrl = provider.retrieveRequestToken(m_consumer, OAuth.OUT_OF_BAND);
+
+ System.out.println("Now visit:\n" + authUrl + "\n and grant this app authorization");
+ System.out.println("Enter the PIN code and hit ENTER when you're done:");
+
+ // read the next line to retrieve the pin code from the user.
+ BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+ String pin = br.readLine();
+
+ System.out.println("Fetching access token from Twitter");
+
+ provider.retrieveAccessToken(m_consumer, pin);
+
+ // obtain the given access token and access secret.
+ m_accessToken = m_consumer.getToken();
+ m_secretToken = m_consumer.getTokenSecret();
+
+ } catch (IOException | OAuthException ex) {
+ Logger.getLogger(Authentication.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ /**
+ * Signs the http request with the given authentication.
+ *
+ * @param object Any object, because why not?
+ * @throws oauth.signpost.exception.OAuthMessageSignerException
+ * @throws oauth.signpost.exception.OAuthExpectationFailedException
+ * @throws oauth.signpost.exception.OAuthCommunicationException
+ */
+ public void sign(Object object)
+ throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
+ m_consumer.sign(object);
+ }
+
+ /**
+ * Store the given tokens in a file.
+ */
+ private void save(final String filename) throws IOException {
+ final String newLine = System.getProperty("line.separator");
+
+ // open the given filename file.
+ File file = new File(filename);
+ try (BufferedWriter output = new BufferedWriter(new FileWriter(file))) {
+ output.write(m_accessToken + newLine + m_secretToken);
+ }
+ }
+
+ /**
+ * Retrieve the given tokens from a file.
+ */
+ private void load(final String filename) throws FileNotFoundException {
+ // open the given filename file.
+ File inFile = new File(filename);
+
+ // create a scanner for the tokens.
+ Scanner scanner = new Scanner(inFile);
+
+ // Read the first and second lines for the tokens.
+ m_accessToken = scanner.nextLine();
+ m_accessToken = scanner.nextLine();
+ }
+
+ private boolean isAuthenticated() {
+ try {
+ // Step 1: Open a http connection to
+ // https://api.twitter.com/1.1/users/show.json?screen_name=<username>
+ // with a read timeout of 5 seconds.
+ URL url = new URL("https://api.twitter.com/1.1/users/show.json?screen_name=maskman113");
+ HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+ urlConnection.setReadTimeout(5000);
+
+ // Step 2: Sign the request using the OAuth Secret
+ sign(urlConnection);
+
+ // try to connect to this url address.
+ urlConnection.connect();
+
+ // obtain the respons of the connection.
+ int responseCode = urlConnection.getResponseCode();
+
+ if (responseCode == 401) {
+ // Bad authentication.
+ return false;
+ }
+ } catch (MalformedURLException ex) {
+ Logger.getLogger(Authentication.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IOException | OAuthMessageSignerException | OAuthExpectationFailedException | OAuthCommunicationException ex) {
+ Logger.getLogger(Authentication.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return true;
+ }
+}
diff --git a/src/mining/Miner.java b/src/mining/Miner.java
new file mode 100644
index 0000000..e21da09
--- /dev/null
+++ b/src/mining/Miner.java
@@ -0,0 +1,25 @@
+package mining;
+
+import java.io.IOException;
+import utils.Configuration;
+
+/**
+ * The main data mining object.
+ */
+public class Miner {
+
+ // the main class to authenticate the application.
+ private Authentication m_auth;
+
+ // main miner to search data of users and tweets.
+ private Search m_search;
+
+ public Miner() throws IOException
+ {
+ // Authentication such that the miner can request data.
+ m_auth = new Authentication(Configuration.CONSUMER_KEY, Configuration.CONSUMER_SECRET);
+
+ // create a new search object.
+ m_search = new Search(m_auth);
+ }
+}
diff --git a/src/mining/Search.java b/src/mining/Search.java
new file mode 100644
index 0000000..68f2a48
--- /dev/null
+++ b/src/mining/Search.java
@@ -0,0 +1,118 @@
+package mining;
+
+import data.Profile;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import oauth.signpost.exception.OAuthCommunicationException;
+import oauth.signpost.exception.OAuthException;
+import oauth.signpost.exception.OAuthExpectationFailedException;
+import oauth.signpost.exception.OAuthMessageSignerException;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Retrieve data from twitter.com by explicitly searching for it.
+ */
+public class Search {
+
+ // the class to use for authentication of the http connection.
+ private final Authentication m_auth;
+
+ public Search(Authentication auth) {
+ m_auth = auth;
+
+ getProfile("maskman113");
+ }
+
+ /**
+ * Retrieves the profile information of the user
+ *
+ * @param username of the user whose profile needs to be retrieved
+ * @return the profile information as profile object.
+ */
+ public Profile getProfile(String username) {
+ BufferedReader bRead = null;
+ JSONObject profile = null;
+
+ boolean retry = false;
+
+ try {
+ System.out.println("Receiving profile of " + username);
+
+ // Step 1: Open a http connection to
+ // https://api.twitter.com/1.1/users/show.json?screen_name=<username>
+ // with a read timeout of 5 seconds.
+ URL url = new URL("https://api.twitter.com/1.1/users/show.json?screen_name=" + username);
+ HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+ urlConnection.setReadTimeout(5000);
+
+ // Step 2: Sign the request using the OAuth Secret
+ m_auth.sign(urlConnection);
+
+ // try to connect to this url address.
+ urlConnection.connect();
+
+ // obtain the respons of the connection.
+ int responseCode = urlConnection.getResponseCode();
+
+ if (responseCode == 404 || responseCode == 401) {
+ // Could not find host.
+ System.err.println("Connection failed, error: " + responseCode);
+ } else if (responseCode == 500 || responseCode == 502 || responseCode == 503) {
+ // Internal Server Error.
+ disconnect(urlConnection, responseCode);
+ } // Server quota has been reached.
+ else if (responseCode == 429) {
+ disconnect(urlConnection, responseCode);
+ try {
+ // Sleep until more requests are available.
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ Logger.getLogger(Search.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ retry = true;
+ }
+
+ if (retry) {
+ //recreate the connection because only the amount of requests was too much.
+ urlConnection.connect();
+ }
+
+ StringBuilder content = new StringBuilder();
+
+ urlConnection.disconnect();
+
+ try {
+ profile = new JSONObject(content.toString());
+
+ System.out.println(profile.toString());
+ } catch (JSONException ex) {
+ System.err.println(ex);
+ }
+ } catch (OAuthException | IOException ex) {
+ System.err.println(ex);
+ }
+
+ return new Profile();
+ }
+
+ public void searchTags() {
+
+ }
+
+ private void disconnect(HttpURLConnection urlConnection, int responseCode) {
+ try {
+ // Try to disconnect the connection.
+ urlConnection.disconnect();
+ System.out.println(responseCode);
+ Thread.sleep(3000);
+ } catch (InterruptedException ex) {
+ // Closing the connection failed....
+ System.err.println("Closing connection failed: " + ex.getMessage());
+ }
+ }
+}
diff --git a/src/mining/Stream.java b/src/mining/Stream.java
new file mode 100644
index 0000000..c9c08f0
--- /dev/null
+++ b/src/mining/Stream.java
@@ -0,0 +1,9 @@
+
+package mining;
+
+/**
+ * This miner obtains data by receiving a stream from twitter.
+ */
+public class Stream {
+
+}