Using API v2 for posting

This commit is contained in:
2025-10-29 22:01:18 +09:00
parent 8f38bc82a0
commit 9b8e79877f
2 changed files with 32 additions and 23 deletions

View File

@@ -29,7 +29,7 @@ public class TwitterService {
private final String accessTokenSecret;
private final ObjectMapper objectMapper;
private static final String MEDIA_UPLOAD_URL = "https://upload.twitter.com/1.1/media/upload.json";
private static final String TWEET_CREATE_URL = "https://api.twitter.com/1.1/statuses/update.json";
private static final String TWEET_CREATE_URL = "https://api.twitter.com/2/tweets";
public TwitterService(String apiKey, String apiSecret, String accessToken, String accessTokenSecret) {
this.apiKey = apiKey;
@@ -37,7 +37,7 @@ public class TwitterService {
this.accessToken = accessToken;
this.accessTokenSecret = accessTokenSecret;
this.objectMapper = new ObjectMapper();
logger.info("Twitter service initialized successfully with OAuth 1.0a");
logger.info("Twitter service initialized successfully with OAuth 1.0a (using API v2 for tweets)");
}
/**
@@ -59,9 +59,9 @@ public class TwitterService {
try {
logger.info("Posting tweet: {}", tweetText);
// Build query parameters
Map<String, String> params = new TreeMap<>();
params.put("status", tweetText);
// Build JSON request body for Twitter API v2
ObjectNode tweetData = objectMapper.createObjectNode();
tweetData.put("text", tweetText);
// Upload media if image path is provided
if (imagePath != null && !imagePath.isEmpty()) {
@@ -72,32 +72,35 @@ public class TwitterService {
try {
String mediaId = uploadMedia(imageFile);
logger.info("Media uploaded successfully. Media ID: {}", mediaId);
params.put("media_ids", mediaId);
// Add media to tweet (v2 format)
ObjectNode media = objectMapper.createObjectNode();
media.put("media_ids", objectMapper.createArrayNode().add(mediaId));
tweetData.set("media", media);
} catch (Exception e) {
logger.error("Failed to upload media, posting tweet without image", e);
}
}
}
// Build URL with query parameters
StringBuilder urlBuilder = new StringBuilder(TWEET_CREATE_URL);
urlBuilder.append("?");
for (Map.Entry<String, String> entry : params.entrySet()) {
if (urlBuilder.charAt(urlBuilder.length() - 1) != '?') {
urlBuilder.append("&");
}
urlBuilder.append(urlEncode(entry.getKey())).append("=").append(urlEncode(entry.getValue()));
}
String fullUrl = urlBuilder.toString();
String requestBody = objectMapper.writeValueAsString(tweetData);
logger.debug("Request body: {}", requestBody);
// Create OAuth header (include query params in signature)
String authHeader = generateOAuthHeader("POST", TWEET_CREATE_URL, params);
// Create OAuth header (no query params for v2)
String authHeader = generateOAuthHeader("POST", TWEET_CREATE_URL, new TreeMap<>());
// Make HTTP request
HttpURLConnection connection = (HttpURLConnection) new URL(fullUrl).openConnection();
HttpURLConnection connection = (HttpURLConnection) new URL(TWEET_CREATE_URL).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", authHeader);
connection.setRequestProperty("Content-Length", "0");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
// Send request body
try (OutputStream os = connection.getOutputStream()) {
byte[] input = requestBody.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
// Read response
int responseCode = connection.getResponseCode();
@@ -116,14 +119,14 @@ public class TwitterService {
}
reader.close();
if (responseCode != 200) {
if (responseCode != 200 && responseCode != 201) {
logger.error("Failed to post tweet. Status code: {}, Response: {}", responseCode, response.toString());
throw new IOException("Failed to post tweet. Status code: " + responseCode + ", Response: " + response.toString());
}
// Parse tweet ID from response (v1.1 format)
// Parse tweet ID from response (v2 format)
JsonNode responseJson = objectMapper.readTree(response.toString());
String tweetId = responseJson.get("id_str").asText();
String tweetId = responseJson.get("data").get("id").asText();
logger.info("Tweet posted successfully. Tweet ID: {}", tweetId);
logger.info("View tweet at: https://twitter.com/user/status/{}", tweetId);