A 100% pure Java library for the Twitter API with no extra dependency
Managing tweet favorites (likes) and retrieving favorite lists.
Add and remove favorites (likes) on tweets.
interface FavoritesResources {
/**
* Like a tweet (add to favorites)
* @param id Tweet ID to like
* @return Liked tweet status
*/
Status createFavorite(long id) throws TwitterException;
/**
* Unlike a tweet (remove from favorites)
* @param id Tweet ID to unlike
* @return Unliked tweet status
*/
Status destroyFavorite(long id) throws TwitterException;
}Usage Examples:
TwitterV1 v1 = twitter.v1();
// Like a tweet
Status likedTweet = v1.favorites().createFavorite(1234567890L);
System.out.println("Liked tweet: " + likedTweet.getText());
System.out.println("Total likes: " + likedTweet.getFavoriteCount());
// Unlike a tweet
Status unlikedTweet = v1.favorites().destroyFavorite(1234567890L);
System.out.println("Unliked tweet: " + unlikedTweet.getText());Get lists of liked tweets for any user.
interface FavoritesResources {
/**
* Get authenticated user's favorite tweets
* @return List of favorited tweets (20 most recent)
*/
ResponseList<Status> getFavorites() throws TwitterException;
/**
* Get authenticated user's favorites with pagination
* @param paging Pagination parameters
* @return List of favorited tweets
*/
ResponseList<Status> getFavorites(Paging paging) throws TwitterException;
/**
* Get specific user's favorite tweets by user ID
* @param userId User ID
* @return List of user's favorited tweets
*/
ResponseList<Status> getFavorites(long userId) throws TwitterException;
/**
* Get specific user's favorites with pagination by user ID
* @param userId User ID
* @param paging Pagination parameters
* @return List of user's favorited tweets
*/
ResponseList<Status> getFavorites(long userId, Paging paging) throws TwitterException;
/**
* Get specific user's favorite tweets by screen name
* @param screenName User's screen name (without @)
* @return List of user's favorited tweets
*/
ResponseList<Status> getFavorites(String screenName) throws TwitterException;
/**
* Get specific user's favorites with pagination by screen name
* @param screenName User's screen name (without @)
* @param paging Pagination parameters
* @return List of user's favorited tweets
*/
ResponseList<Status> getFavorites(String screenName, Paging paging) throws TwitterException;
}Usage Examples:
// Get your own favorites
ResponseList<Status> myFavorites = v1.favorites().getFavorites();
for (Status favorite : myFavorites) {
System.out.println("Liked: " + favorite.getText());
System.out.println("By: @" + favorite.getUser().getScreenName());
}
// Get specific user's favorites
ResponseList<Status> userFavorites = v1.favorites().getFavorites("twitterapi");
for (Status tweet : userFavorites) {
System.out.println("@twitterapi liked: " + tweet.getText());
}
// Get favorites with pagination
Paging paging = Paging.ofCount(200).maxId(9876543210L);
ResponseList<Status> paginatedFavorites = v1.favorites().getFavorites("twitterapi", paging);
// Get all favorites for a user (with pagination)
List<Status> allFavorites = new ArrayList<>();
Paging currentPaging = Paging.ofCount(200);
while (true) {
ResponseList<Status> batch = v1.favorites().getFavorites("username", currentPaging);
if (batch.isEmpty()) break;
allFavorites.addAll(batch);
// Set up next page
long oldestId = batch.get(batch.size() - 1).getId();
currentPaging = Paging.ofCount(200).maxId(oldestId - 1);
// Rate limiting
RateLimitStatus rateLimit = batch.getRateLimitStatus();
if (rateLimit.getRemaining() <= 1) {
Thread.sleep(rateLimit.getSecondsUntilReset() * 1000L);
}
}Analyze favorited content patterns.
public class FavoritesAnalyzer {
private final TwitterV1 v1;
public FavoritesStats analyzeFavorites(String screenName) throws TwitterException {
List<Status> allFavorites = getAllFavorites(screenName);
FavoritesStats stats = new FavoritesStats();
stats.totalFavorites = allFavorites.size();
// Analyze by content type
stats.originalTweets = (int) allFavorites.stream()
.filter(s -> s.getRetweetedStatus() == null)
.count();
stats.retweets = stats.totalFavorites - stats.originalTweets;
// Analyze by media content
stats.tweetsWithMedia = (int) allFavorites.stream()
.filter(s -> s.getMediaEntities().length > 0)
.count();
stats.tweetsWithImages = (int) allFavorites.stream()
.filter(s -> Arrays.stream(s.getMediaEntities())
.anyMatch(media -> "photo".equals(media.getType())))
.count();
stats.tweetsWithVideo = (int) allFavorites.stream()
.filter(s -> Arrays.stream(s.getMediaEntities())
.anyMatch(media -> "video".equals(media.getType()) ||
"animated_gif".equals(media.getType())))
.count();
// Most favorited authors
stats.topFavoritedAuthors = allFavorites.stream()
.collect(Collectors.groupingBy(
s -> s.getUser().getScreenName(),
Collectors.counting()
))
.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(10)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new
));
// Most common hashtags in favorites
stats.topHashtags = allFavorites.stream()
.flatMap(s -> Arrays.stream(s.getHashtagEntities()))
.collect(Collectors.groupingBy(
HashtagEntity::getText,
Collectors.counting()
))
.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(10)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new
));
// Engagement analysis
stats.averageRetweetCount = allFavorites.stream()
.mapToInt(Status::getRetweetCount)
.average().orElse(0.0);
stats.averageFavoriteCount = allFavorites.stream()
.mapToInt(Status::getFavoriteCount)
.average().orElse(0.0);
return stats;
}
private List<Status> getAllFavorites(String screenName) throws TwitterException {
List<Status> allFavorites = new ArrayList<>();
Paging paging = Paging.ofCount(200);
while (allFavorites.size() < 3200) { // Twitter limit for favorites
ResponseList<Status> batch = v1.favorites().getFavorites(screenName, paging);
if (batch.isEmpty()) break;
allFavorites.addAll(batch);
// Set up next page
long oldestId = batch.get(batch.size() - 1).getId();
paging = Paging.ofCount(200).maxId(oldestId - 1);
// Rate limiting
RateLimitStatus rateLimit = batch.getRateLimitStatus();
if (rateLimit.getRemaining() <= 1) {
try {
Thread.sleep(rateLimit.getSecondsUntilReset() * 1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
return allFavorites;
}
public static class FavoritesStats {
public int totalFavorites;
public int originalTweets;
public int retweets;
public int tweetsWithMedia;
public int tweetsWithImages;
public int tweetsWithVideo;
public Map<String, Long> topFavoritedAuthors;
public Map<String, Long> topHashtags;
public double averageRetweetCount;
public double averageFavoriteCount;
}
}Tools for managing large numbers of favorites.
public class FavoritesManager {
private final TwitterV1 v1;
public void cleanupOldFavorites(int daysOld) throws TwitterException {
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(daysOld);
ResponseList<Status> favorites = v1.favorites().getFavorites(Paging.ofCount(200));
for (Status favorite : favorites) {
if (favorite.getCreatedAt().isBefore(cutoffDate)) {
try {
v1.favorites().destroyFavorite(favorite.getId());
System.out.println("Unliked old tweet: " + favorite.getId());
Thread.sleep(1000); // Rate limiting - be conservative
} catch (TwitterException e) {
if (e.getStatusCode() == 144) {
// Tweet no longer exists
System.out.println("Tweet " + favorite.getId() + " no longer exists");
} else {
System.err.println("Error unliking tweet " + favorite.getId() + ": " + e.getMessage());
}
}
}
}
}
public void bulkFavoriteFromSearch(String searchQuery, int maxFavorites) throws TwitterException {
Query query = Query.of(searchQuery)
.count(100)
.resultType(Query.ResultType.popular);
QueryResult result = v1.search().search(query);
int favoritedCount = 0;
for (Status tweet : result.getTweets()) {
if (favoritedCount >= maxFavorites) break;
try {
// Don't favorite your own tweets or already favorited tweets
if (!tweet.isFavorited() && !tweet.getUser().getScreenName().equals(getMyScreenName())) {
v1.favorites().createFavorite(tweet.getId());
favoritedCount++;
System.out.println("Favorited: " + tweet.getText().substring(0, 50) + "...");
Thread.sleep(2000); // Conservative rate limiting
}
} catch (TwitterException e) {
if (e.getStatusCode() == 144) {
System.out.println("Tweet no longer exists");
} else if (e.getStatusCode() == 139) {
System.out.println("Already favorited this tweet");
} else {
System.err.println("Error favoriting tweet: " + e.getMessage());
}
}
}
}
public void exportFavorites(String screenName, String filename) throws TwitterException, IOException {
List<Status> favorites = getAllUserFavorites(screenName);
try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
writer.println("Date,Author,Tweet,URL");
for (Status favorite : favorites) {
String date = favorite.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE);
String author = favorite.getUser().getScreenName();
String text = favorite.getText().replace(",", ";").replace("\n", " ");
String url = "https://twitter.com/" + author + "/status/" + favorite.getId();
writer.println(String.join(",",
date, author, "\"" + text + "\"", url));
}
}
System.out.println("Exported " + favorites.size() + " favorites to " + filename);
}
private List<Status> getAllUserFavorites(String screenName) throws TwitterException {
// Implementation similar to FavoritesAnalyzer.getAllFavorites()
// Return all favorites for the user
return new ArrayList<>(); // Placeholder
}
private String getMyScreenName() {
// Cache and return authenticated user's screen name
return "myusername"; // Placeholder
}
}Find tweets similar to your existing favorites.
public class FavoritesRecommendation {
private final TwitterV1 v1;
public List<Status> recommendSimilarTweets(int limit) throws TwitterException {
// Get recent favorites to understand preferences
ResponseList<Status> recentFavorites = v1.favorites().getFavorites(Paging.ofCount(100));
// Extract common hashtags and keywords from favorites
Set<String> favoriteHashtags = recentFavorites.stream()
.flatMap(s -> Arrays.stream(s.getHashtagEntities()))
.map(HashtagEntity::getText)
.collect(Collectors.toSet());
// Find authors you frequently favorite
Map<String, Long> favoriteAuthors = recentFavorites.stream()
.collect(Collectors.groupingBy(
s -> s.getUser().getScreenName(),
Collectors.counting()
));
List<Status> recommendations = new ArrayList<>();
// Search for tweets with similar hashtags
for (String hashtag : favoriteHashtags.stream().limit(5).collect(Collectors.toList())) {
Query query = Query.of("#" + hashtag)
.count(20)
.resultType(Query.ResultType.popular);
QueryResult result = v1.search().search(query);
// Filter out tweets you've already favorited
List<Status> newTweets = result.getTweets().stream()
.filter(tweet -> !tweet.isFavorited())
.filter(tweet -> !tweet.getUser().getScreenName().equals(getMyScreenName()))
.collect(Collectors.toList());
recommendations.addAll(newTweets);
if (recommendations.size() >= limit) break;
Thread.sleep(1000); // Rate limiting
}
// Search for recent tweets from frequently favorited authors
for (Map.Entry<String, Long> entry : favoriteAuthors.entrySet()) {
if (entry.getValue() >= 3) { // Authors you've favorited at least 3 times
try {
ResponseList<Status> authorTweets = v1.timelines()
.getUserTimeline(entry.getKey(), Paging.ofCount(10));
List<Status> unfavoritedTweets = authorTweets.stream()
.filter(tweet -> !tweet.isFavorited())
.collect(Collectors.toList());
recommendations.addAll(unfavoritedTweets);
if (recommendations.size() >= limit) break;
Thread.sleep(500);
} catch (TwitterException e) {
// Handle protected accounts or other errors
continue;
}
}
}
// Remove duplicates and return top recommendations
return recommendations.stream()
.distinct()
.limit(limit)
.collect(Collectors.toList());
}
private String getMyScreenName() {
return "myusername"; // Placeholder
}
}Common favorites operations errors and handling:
try {
Status favorite = v1.favorites().createFavorite(tweetId);
System.out.println("Successfully liked tweet");
} catch (TwitterException e) {
switch (e.getStatusCode()) {
case 139:
System.out.println("Tweet already favorited");
break;
case 144:
System.out.println("Tweet not found or deleted");
break;
case 403:
if (e.getErrorCode() == 261) {
System.out.println("Cannot favorite: application write access required");
} else {
System.out.println("Forbidden: " + e.getMessage());
}
break;
case 429:
System.out.println("Rate limit exceeded");
int retryAfter = e.getRetryAfter();
System.out.println("Retry after " + retryAfter + " seconds");
break;
default:
System.out.println("Error: " + e.getMessage());
}
}
try {
ResponseList<Status> favorites = v1.favorites().getFavorites("protecteduser");
} catch (TwitterException e) {
if (e.getStatusCode() == 401) {
System.out.println("User's favorites are protected");
} else if (e.getStatusCode() == 404) {
System.out.println("User not found");
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-twitter4j--twitter4j-core