Trouble with twitter4j and processing - java

I'm trying to get processing to display the most recent tweet containing my keyword. I'm stuck. I'm not sure how I would check to see if it's updating. I know that it's able to pull the most recent tweet, but as of now, the only way I can view the most recent tweet is by restarting my program. Sorry it's messy.
import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
import java.util.*;
Twitter twitter; // creating the twitter object
String searchString = "newborn"; // twitter search query
List<Status> tweets;// List of Status object to hold tweets
List<Status> tweets2;
int currentTweet;//
int nextTweet;
void setup ()
{
size(800,600);
ConfigurationBuilder cb = new ConfigurationBuilder(); // New config obj, auth.
cb.setOAuthConsumerKey("");
cb.setOAuthConsumerSecret("");
cb.setOAuthAccessToken("");
cb.setOAuthAccessTokenSecret("");
TwitterFactory tf = new TwitterFactory(cb.build()); // init. twit obj by retr inst from twit fact
twitter = tf.getInstance(); //here, twit gets isnt is the inst
getTweets2();
getNewTweets(); // func to get the tweets
currentTweet = 0;
nextTweet = 1;
//Status status = tweets.get(currentTweet);
thread("refreshTweets");
}
void draw()
{
background(0);
//currentTweet = currentTweet + 1;
//nextTweet = nextTweet + 1;
if (currentTweet >= tweets.size())
{
currentTweet = 0;
}
if (nextTweet >= tweets.size())
{
nextTweet = 1;
}
Status status = tweets.get(currentTweet); // retrieve current tweet from list of tweets
Status status2 = tweets.get(nextTweet);
Status status3 = tweets2.get(0);
Status status4 = status;
fill(200);
if(tweets.get(0).getCreatedAt() != tweets2.get(0).getCreatedAt()) {
//text(status.getText(),random(width),random(height), 300, 200);
text("current tweet:" + status.getCreatedAt() + ".....if" ,250,250, 300, 200);
//text("next tweet:" + status2.getCreatedAt(),250,350, 300, 200);
//text("10th tweet:" + status3.getCreatedAt(),250,450, 300, 200);
}else {
text("current tweet:" + status2.getCreatedAt() + ".....else",250,250, 300, 200);
}
delay(2500);
getNewTweets();
//System.out.println(status2.getText());
}
void getNewTweets()
{
try
{
//we try to get the tweetuses!
Query query = new Query(searchString);
QueryResult result = twitter.search(query);
tweets = result.getTweets();
}
catch (TwitterException te)
{
//tweetus aborted?
System.out.println("failed to search tweets: " + te.getMessage());
System.exit(-1);
}
}
void getTweets2() //this neat thing gets those tweets
{
try
{
//we try to get the tweetuses!
Query query = new Query(searchString);
QueryResult result = twitter.search(query);
tweets2 = result.getTweets();
}
catch (TwitterException te)
{
//tweetus aborted?
System.out.println("failed to search tweets: " + te.getMessage());
System.exit(-1);
}
}
void refreshTweets()
{
while(true)
{
getNewTweets();
println("Updated Tweets");
delay(5000);
}
}

Note: You've posted your secret tokens publicly to the internet, so you should change them as soon as possible! Just editing your question to not include them won't be enough, since they'll still be in the revision history.
You've got a lot of extra stuff going on in this program. You can simplify this a great deal. All you need to do is this:
Step 1: Write a function that gets a tweet (or an ArrayList of tweets). Keep track of that tweet in a sketch-level variable. You've already done this with the getNewTweets() function, but you can get rid of the other functions.
Step 2: Call that function at the beginning of the sketch. This is so you have something to show. Alternatively, you could just show some dummy text like "waiting to fetch tweets" until the next step.
Step 3: Every X seconds, call that function. You can do this by using the frameCount variable from the draw() function. Make sure you limit this so you don't go over twitter's rate limit.
Step 4: Use the sketch-level tweet variable to draw the current tweet however you want.
Putting it all together, it looks like this:
import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
Twitter twitter;
String searchString = "cat";
Status currentTweet;
void setup ()
{
size(800, 600);
ConfigurationBuilder cb = new ConfigurationBuilder(); // New config obj, auth.
cb.setOAuthConsumerKey("");
cb.setOAuthConsumerSecret("");
cb.setOAuthAccessToken("");
cb.setOAuthAccessTokenSecret("");
TwitterFactory tf = new TwitterFactory(cb.build());
twitter = tf.getInstance();
getNewTweets();
}
void draw()
{
//get new tweet once every 10 seconds
if (frameCount % (60*10) == 0) {
getNewTweets();
}
background(0);
fill(200);
text("current tweet:" + currentTweet.getText(), 250, 250, 300, 200);
}
void getNewTweets()
{
println("Getting new tweet...");
try
{
Query query = new Query(searchString);
QueryResult result = twitter.search(query);
currentTweet = result.getTweets().get(0);
}
catch (TwitterException te)
{
te.printStackTrace();
}
}

Related

How can I fetch more than 2000 tweets using twitter4j?

I am making a project which requires me to fetch tweets from a user's twitter handle and collect the tweets related to a particular hashtag ,eg-#IphoneX .
But I need a larger number of tweets ,(close to 2000 would be enough) and I am able to fetch a little more than a 100. I have used twitter4j .Can someone let me know how do I do this? This is the code that I used:-
public class TwitterScrapper {
/**
* #param args the command line arguments
* #throws twitter4j.TwitterException
*/
public static void main(String[] args) throws TwitterException {
ConfigurationBuilder cf = new ConfigurationBuilder();
cf.setDebugEnabled(true)
.setOAuthConsumerKey("-------------------")
.setOAuthConsumerSecret("----------------------")
.setOAuthAccessToken("------------------------")
.setOAuthAccessTokenSecret("-------------------");
TwitterFactory tf = new TwitterFactory(cf.build());
twitter4j.Twitter twitter = tf.getInstance();
try {
Query query = new Query("Iphone");
QueryResult result;
result = twitter.search(query);
List<Status> tweets = result.getTweets();
tweets.forEach((tweet) -> {
System.out.println("#" + tweet.getUser().getScreenName() + " - " + tweet.getText());
});
System.exit(0);
} catch (TwitterException te) {
System.out.println("Failed to search tweets: " + te.getMessage());
System.exit(-1);
}
}
}

Creating a new object

At the moment my program has a Jpanel with about 15 different inputs. These inputs are created to one long string called "searchInput".
"searchInput" is then put into a query named which then gets metadata about the tweet result one at a time, such as createdAt, user and text. These results are printed to a textArea named tweetsResult.
createdAt, user and text are only some of the metadata behind each tweet, more being favouriteCount and retweetCount.
Because Twitter has a maximum amount of Tweets it can deliver to you using the API, I feel it would be best if I created a new class which uses searchInput, and then get the desired amount of Tweets with all of the metadata into an object. And then from the main class, I would only call the results with the specific meta data that I would like.
Is this the right way to do it? If so how would I create this new object, presumably using getters and setters?
I hope this is clear to you, and many thanks for the help!
List<Status> tweets = new ArrayList<Status>();
//Standard Twitter and Twitter4j authentication
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(consumerKey);
builder.setOAuthConsumerSecret(consumerSecret);
Configuration configuration = builder.build();
TwitterFactory twitterFactory = new TwitterFactory(configuration);
Twitter twitter = twitterFactory.getInstance();
twitter.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
//The query is split up into 5 sections
//All the text boxes are read in the seperate methods
String searchWordInput = getWordSearchQuery();
String searchPeopleInput = getPeopleSearchQuery();
String filtersSearchInput = getFiltersSearchQuery();
String dateAndLocationSearchInput = getDateAndLocationSearchQuery();
String radiusAndLocationSearchInput = getRadiusAndLocationSearchQuery();
String searchInput = searchWordInput + searchPeopleInput + filtersSearchInput + dateAndLocationSearchInput + radiusAndLocationSearchInput;
//One big search String called "searchInput" is taken to be sent to Twitter
//Increases maximum amount of tweets in one search
int wantedTweets = 100; //CHANGE THIS FOR DIFFERENT AMOUNT OF TWEETS
long lastSearchID = Long.MAX_VALUE;
int remainingTweets = wantedTweets;
Query query = new Query(searchInput);
tweetsResultInput.append(searchInput);
try {
while (remainingTweets > 0) {
remainingTweets = wantedTweets - tweets.size();
if (remainingTweets > 100) {
query.count(100);
} else {
query.count(remainingTweets);
}
QueryResult result = twitter.search(query);
tweets.addAll(result.getTweets());
Status s = tweets.get(tweets.size() - 1);
lastSearchID = s.getId();
query.setMaxId(lastSearchID);
remainingTweets = wantedTweets - tweets.size();
}
//Increases maximum amount of tweets in ones search
tweetsResult.append(searchInput);
tweetsResult.append("\n");
//For the query tweets, using "searchInput", get every tweet in the format; when Tweet was sent, who it was sent by, and the Tweets text and write to tweetsResults
for (Status tweet : tweets) {
tweetsResult.append(tweet.getCreatedAt() + ":\t#" + tweet.getUser().getScreenName() + " - " + tweet.getText());
tweetsResult.append("\n");
}
} catch (TwitterException te) {
System.out.println("Failed to search tweets: " + te.getMessage());
System.exit(-1);
}

How to get followers and following list screen names (Twitter4J)?

I am trying to get my followers and following list via Twitter 4J.
I pass the configuration builder from the main method as a parameter to the method.
Here is the code:
try {
Twitter twitter = new TwitterFactory().getInstance();
long cursor = -1;
IDs ids;
System.out.println("Listing following ids.");
do {
if (0 < args.length) {
ids = twitter.getFriendsIDs(args[0], cursor);
} else {
ids = twitter.getFriendsIDs(cursor);
}
for (long id : ids.getIDs()) {
System.out.println(id);
}
} while ((cursor = ids.getNextCursor()) != 0);
System.exit(0);
} catch (TwitterException te) {
te.printStackTrace();
System.out.println("Failed to get friends' ids: " + te.getMessage());
System.exit(-1);
}
So far this only returns IDS but it does not return the screen name of the followers. Does anyone have any idea? I am working in Java and printing to the terminal.
Thanks.
String twitterScreenName = twitter.getScreenName();
PagableResponseList<User> statuse = twitter.getFollowersList(twitterScreenName, -1);
for (User follower : statuse) {
System.out.println(follower.getName());
}

read IRC data correctly in Processing

I am trying to read IRC and pull data from individual IRC messages in Processing. You can see the code (also with twitter library, ignore that) and I need some pointers on how I can pull the data out in the format of Nick:Message so it can be displayed in a visualization.
//Twitter
import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
import java.util.*;
// Import the net libraries
import processing.net.*;
// Declare a client
Client client;
Twitter twitter;
String searchString = "god";
List<Status> tweets;
String server = "irc.twitch.tv";
String nick = "NugShow";
//String user = "simple_bot";
int port = 6667;
String channel = "#nugshow";
String password = "xx";
String in = "butt";
String checkFor;
//bools
Boolean isLive = false;
int privMsgIndex;
int atIndex;
String playerSubstring;
// The channel which the bot will joString channel = "#irchacks";
int currentTweet;
void setup()
{
size(800,600);
frameRate(60);
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey("xx");
cb.setOAuthConsumerSecret("xx");
cb.setOAuthAccessToken("xx");
cb.setOAuthAccessTokenSecret("xx");
TwitterFactory tf = new TwitterFactory(cb.build());
twitter = tf.getInstance();
getNewTweets();
currentTweet = 0;
thread("refreshTweets");
thread("loopChat");
connectToServer();
//IRC
}
void draw()
{
if (client.available() > 0) {
String in = client.readString();
println(in);
}
if (isLive == false){
if (client.available() > 0) {
}
} else {
}
/*
fill(0, 40);
rect(0, 0, width, height);
currentTweet = currentTweet + 1;
if (currentTweet >= tweets.size())
{
currentTweet = 0;
}
Status status = tweets.get(currentTweet);
fill(200);
text(status.getText(), random(width), random(height), 300, 200);
delay(100);
*/
}
void joinChannel() {
String in = client.readString();
client.write( "JOIN " + channel + "\n\r" );
client.clear();
in = client.readString();
println(in);
if (in != null){
//println("Recieved data");
println(in);
//String inString = myClient.readStringUntil("");
isLive = true;
println(isLive);
}
}
void connectToServer()
{
client = new Client(this, server , 6667);
client.write( "PASS " + password + "\n\r" );
println(password + " sent!");
client.write( "NICK " + nick + "\n\r" );
println(nick + " sent!");
joinChannel();
}
void getNewTweets()
{
try
{
Query query = new Query(searchString);
QueryResult result = twitter.search(query);
tweets = result.getTweets();
}
catch (TwitterException te)
{
System.out.println("Failed to search tweets: " + te.getMessage());
System.exit(-1);
}
}
void refreshTweets()
{
while (true)
{
getNewTweets();
println("Updated Tweets");
delay(30000);
}
}
void loopChat()
{
while (true)
{
if (privMsgIndex != 0){
println(privMsgIndex);
//privMsgIndex = privMsgIndex - 15;
atIndex = in.indexOf("#");
println(atIndex);
//atIndex = atIndex + 1;
playerSubstring = in.substring(atIndex, privMsgIndex);
println(playerSubstring);
} else {
println("looped");
}
delay(300);
client.clear();
in = null;
}
}
void keyPressed()
{
}
void tweet()
{
try
{
Status status = twitter.updateStatus("This is a tweet sent from Processing!");
System.out.println("Status updated to [" + status.getText() + "].");
}
catch (TwitterException te)
{
System.out.println("Error: "+ te.getMessage());
}
}
The chat commands look like this: :nugshow!nugshow#nugshow.testserver.local PRIVMSG #nugshow :dddd where nugshow is the username, #nugshow is the channel, and dddd is the message. I need to get it into the format of nugshow: dddd.
there is a lot of header information that I'm not sure how to strip out of client.recieved buffer as well, it looks like this:
:testserver.local 001 nugshow :Welcome, GLHF!
:testserver.local 002 nugshow :Your host is testserver.local
:testserver.local 003 nugshow :This server is rather new
:testserver.local 004 nugshow :-
:testserver.local 375 nugshow :-
:testserver.local 372 nugshow :You are in a maze of twisty passages, all alike.
:testserver.local 376 nugshow :>
:nugshow!nugshow#nugshow.testserver.local JOIN #nugshow
:nugshow.testserver.local 353 nugshow = #nugshow :nugshow
:nugshow.testserver.local 366 nugshow #nugshow :End of /NAMES list
:jtv!jtv#jtv.testserver.local PRIVMSG nugshow :HISTORYEND nugshow
I would not recommend regex here. At least not if you want to be able to catch all types of IRC messages. The key is to look at the message code to know what you can actually get out of the message. As I'm also writing an IRC-client (just for giggles) I have some notes for you.
Be sure to answer any PINGs that the server sends you so you don't get kicked off. As the PING is sent with an identifier, you need to catch that and send it back. A simple way to do this is to check the last line that was sent from the server and substring it.
String line = inputStream.readLine();
if(line.substring(0,4).equals("PING")){
send("PONG " + line.substring(5)); // Assume you have some send-function.
}
This will make sure you don't get kicked off and can proceed to actually stay on a server.
As I mentioned, I do not recommend using regex for this as it would become a RegEx-of-doom. So, what I have done is to just split the line you get and put all the results in a String array.
String[] arr = line.split(" ");
As you know by your own message line you have posted, the IRC protocol separates things with spaces. So splitting at spaces in not all that shabby (we'll get how to deal with actual text in a bit).
The basic structure that is always the same (as far as I can tell) in messages is PREFIX COMMAND PARAM PARAM/TRAILING. So what does this mean? The PREFIX is where the message was sent from. Example ":user!user#host.com". The COMMAND is what the line actually is. You are looking for PRIVMSG here, but there are many, many, others that you might want to take care of. Like JOIN, PART, QUIT, 332 (current topic), 353 (nicks in channel, 404 (unable to send to channel), etc. etc. The PARAM and PARAM/TRAILING will all depend on the COMMAND.
So, what do we gain from splitting at spaces? This:
arr[0] = :user!user#host.com
arr[1] = COMMAND
arr[2] = PARAM
arr[3 onwards] = rest
We can now easily manage every command in it's own needed way.
Without further delay, lets get to your actual question, the PRIVMSG.
I will use this string: ":Chewtoy!chewtoy#stackoverflow.com PRIVMSG #stackoverflow :Ty: I saw your question and thought I should give you an answer."
After doing a split at the spaces, we get the array
arr[0] = :Chewtoy!chewtoy#stackoverflow.com
arr[1] = PRIVMSG
arr[2] = #stackoverflow
arr[3] = :Ty:
arr[4] = I
arr[5] = saw
...
As you can see, everything from 3 and onwards is the message you want. 0-2 is stuff that you need to be able to know who sent what where. My code for getting all this looks like this:
String[] arr = receivedLine.split(" ");
if(arr[1].equals("PRIVMSG")){
String[] usr = arr[0].split(!"); // Get the user, which is in usr[0]. Host in usr[1]
StringBuilder msg = new StringBuilder();
for(int i=3; i<arr.length; i++){ // We know the message starts at arr[3], so start counting from that.
msg.append(arr[i] + " ");
}
String chan = "";
if(arr[2].substring(0,1).equals("#")){ // We need to differentiate between sending to channel and sending a PM. The only difference in this is where the text is sent.
chan = arr[2];
} else{
chan = usr[0].substring(1); // substring(1) because we want Chewtoy, not :Chewtoy
}
// The result here will be:
// <#stackoverflow> Chewtoy: Ty: I saw your question and thought I should give you an answer.
sendItAllToWhereYouWantIt("<" + chan +"> " + usr[0].substring(1) + ": " + msg.substring(1));
}
Hope that helps.

Twitter4J: Get more than 1 tweet from a user

I'm trying to get a list of recent statuses from each user on a persons list of followers. I've got the following to get the users...
IDs list = twitter.getFriendsIDs(0);
for(long ID : list.getIDs()){
twitter4j.User TW_user = twitter.showUser(ID);
}
All I can get from this is getStatus() which is their most recent status. getHomeTimeline() is also insufficient as I need a list of recent tweets from each user. Is there anyway I can achieve this using Twitter4J?
I was just trying to find this answer myself. I had decent success using the getUserTimeline method. Looks like you're trying to look up a list of friend IDs, so this method below should take the long[] and spit out all the user statuses. lookupUsers also accepts a String[] of screen names if you want to look users up that way instead.
public static void lookupUsers(long[] usersList) {
try {
Twitter twitter = new TwitterFactory().getInstance();
ResponseList<User> users = twitter.lookupUsers(usersList);
Paging paging = new Paging(1, 100);
List<Status> statuses;
for (User user : users) {
statuses = twitter.getUserTimeline(user.getScreenName(), paging);
System.out.println("\nUser: #" + user.getScreenName());
for (Status s : statuses) {
System.out.println(s.getText());
}
}
} catch (TwitterException e) {
e.printStackTrace();
}
}
Alex's answer is close, but will only get you 100 tweets per user. The following will get you all (or at least the API's max limit):
IDs list = twitter.getFriendsIDs(0);
for(long ID : list.getIDs()) {
Status[] tweets = getAllTweets(twitter, ID);
System.out.println(ID + ": " + tweets.length);
}
Status[] getAllTweets(Twitter twitter, long userId)
{
int pageno = 1;
List statuses = new ArrayList();
while (true)
{
try
{
int size = statuses.size();
Paging page = new Paging(pageno++, 100);
statuses.addAll(twitter.getUserTimeline(userId, page));
if (statuses.size() == size)
break;
}
catch (TwitterException e)
{
e.printStackTrace();
}
}
return (Status[]) statuses.toArray(new Status[0]);
}

Categories

Resources