|
@@ -69,8 +69,8 @@ import org.xml.sax.SAXException;
|
69
|
69
|
public class TwitterAPI {
|
70
|
70
|
|
71
|
71
|
/** Characters used in b64 encoding. */
|
72
|
|
- private static final String BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"
|
73
|
|
- + "fghijklmnopqrstuvwxyz0123456789+/";
|
|
72
|
+ private static final String BASE64_CHARS
|
|
73
|
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
74
|
74
|
|
75
|
75
|
/** OAuth Consumer. */
|
76
|
76
|
private OAuthConsumer consumer;
|
|
@@ -156,19 +156,20 @@ public class TwitterAPI {
|
156
|
156
|
private String mySource = "web";
|
157
|
157
|
|
158
|
158
|
/** Should we prepend an @ to all user names? */
|
159
|
|
- private boolean autoAt;
|
|
159
|
+ private boolean prependAt;
|
160
|
160
|
|
161
|
161
|
/**
|
162
|
162
|
* Create a non-OAuth using TwitterAPI.
|
163
|
163
|
*
|
164
|
164
|
* @param username Username to use.
|
165
|
165
|
* @param password Password to use.
|
166
|
|
- * @param apiAddress
|
167
|
|
- * @param useAPIVersion
|
168
|
|
- * @param apiVersion
|
|
166
|
+ * @param apiAddress Address to send API Requests to. (No protocol, eg "api.twitter.com")
|
|
167
|
+ * @param useAPIVersion Should we use the versioned api?
|
|
168
|
+ * @param apiVersion What version of the api should we use? (0 == Unversioned, -1 == maximum version known)
|
|
169
|
+ * @param prependAt Should '@' signs be prepended to user names?
|
169
|
170
|
*/
|
170
|
|
- public TwitterAPI(final String username, final String password, final String apiAddress, final boolean useAPIVersion, final int apiVersion, final boolean autoAt) {
|
171
|
|
- this(username, password, apiAddress, "", "", "", "", "", useAPIVersion, apiVersion, autoAt);
|
|
171
|
+ public TwitterAPI(final String username, final String password, final String apiAddress, final boolean useAPIVersion, final int apiVersion, final boolean prependAt) {
|
|
172
|
+ this(username, password, apiAddress, "", "", "", "", "", useAPIVersion, apiVersion, prependAt);
|
172
|
173
|
useOAuth = false;
|
173
|
174
|
}
|
174
|
175
|
|
|
@@ -185,14 +186,14 @@ public class TwitterAPI {
|
185
|
186
|
* @param tokenSecret If using OAuth, the tokenSecret to use.
|
186
|
187
|
* @param useAPIVersion Should we use the versioned api?
|
187
|
188
|
* @param apiVersion What version of the api should we use? (0 == Unversioned, -1 == maximum version known)
|
188
|
|
- * @param autoAt Should '@' signs be prepended to user names?
|
|
189
|
+ * @param prependAt Should '@' signs be prepended to user names?
|
189
|
190
|
*/
|
190
|
|
- public TwitterAPI(final String username, final String password, final String apiAddress, final String oauthAddress, final String consumerKey, final String consumerSecret, final String token, final String tokenSecret, final boolean useAPIVersion, final int apiVersion, final boolean autoAt) {
|
|
191
|
+ public TwitterAPI(final String username, final String password, final String apiAddress, final String oauthAddress, final String consumerKey, final String consumerSecret, final String token, final String tokenSecret, final boolean useAPIVersion, final int apiVersion, final boolean prependAt) {
|
191
|
192
|
this.myLoginUsername = username;
|
192
|
193
|
this.apiAddress = apiAddress.replaceAll("/+$", "");
|
193
|
194
|
this.myPassword = password;
|
194
|
|
- this.autoAt = autoAt;
|
195
|
|
- this.myDisplayUsername = (autoAt ? "@" : "") + myLoginUsername;
|
|
195
|
+ this.prependAt = prependAt;
|
|
196
|
+ this.myDisplayUsername = (prependAt ? "@" : "") + myLoginUsername;
|
196
|
197
|
|
197
|
198
|
if (this.apiAddress.isEmpty() && myLoginUsername.isEmpty()) {
|
198
|
199
|
return;
|
|
@@ -233,7 +234,7 @@ public class TwitterAPI {
|
233
|
234
|
|
234
|
235
|
/**
|
235
|
236
|
* Get the source used in status updates when not using OAuth.
|
236
|
|
- *
|
|
237
|
+ *
|
237
|
238
|
* @return The source used in status updates when not using OAuth.
|
238
|
239
|
*/
|
239
|
240
|
public String getSource() {
|
|
@@ -267,11 +268,10 @@ public class TwitterAPI {
|
267
|
268
|
* @return URL To use!
|
268
|
269
|
*/
|
269
|
270
|
private String getURL(final String apiCall, final int version) {
|
270
|
|
- if (!useAPIVersion || version == 0) {
|
271
|
|
- return (useSSL ? "https" : "http") + "://" + apiAddress + "/" + apiCall + ".xml";
|
272
|
|
- } else {
|
273
|
|
- return (useSSL ? "https" : "http") + "://" + apiAddress + "/" + version + "/" + apiCall + ".xml";
|
274
|
|
- }
|
|
271
|
+ final String prefix = (useSSL ? "https" : "http") + "://" + apiAddress + "/";
|
|
272
|
+
|
|
273
|
+ return prefix + (!useAPIVersion || version == 0 ? "" : version + "/")
|
|
274
|
+ + apiCall + ".xml";
|
275
|
275
|
}
|
276
|
276
|
|
277
|
277
|
/**
|
|
@@ -313,7 +313,8 @@ public class TwitterAPI {
|
313
|
313
|
* @param twitterInput The input to the API that caused this error.
|
314
|
314
|
* @param twitterOutput The output from the API that caused this error.
|
315
|
315
|
*/
|
316
|
|
- private void handleError(final Throwable t, final String source, final String twitterInput, final String twitterOutput) {
|
|
316
|
+ private void handleError(final Throwable t, final String source,
|
|
317
|
+ final String twitterInput, final String twitterOutput) {
|
317
|
318
|
handleError(t, source, twitterInput, twitterOutput, "");
|
318
|
319
|
}
|
319
|
320
|
|
|
@@ -326,7 +327,8 @@ public class TwitterAPI {
|
326
|
327
|
* @param twitterOutput The output from the API that caused this error.
|
327
|
328
|
* @param message If more information should be relayed to the user, it comes here
|
328
|
329
|
*/
|
329
|
|
- private void handleError(final Throwable t, final String source, final String twitterInput, final String twitterOutput, final String message) {
|
|
330
|
+ private void handleError(final Throwable t, final String source,
|
|
331
|
+ final String twitterInput, final String twitterOutput, final String message) {
|
330
|
332
|
synchronized (errorHandlers) {
|
331
|
333
|
for (final TwitterErrorHandler eh : errorHandlers) {
|
332
|
334
|
eh.handleTwitterError(this, t, source, twitterInput, twitterOutput, message);
|
|
@@ -397,17 +399,9 @@ public class TwitterAPI {
|
397
|
399
|
* @return are we using autoAt?
|
398
|
400
|
*/
|
399
|
401
|
public boolean autoAt() {
|
400
|
|
- return autoAt;
|
|
402
|
+ return prependAt;
|
401
|
403
|
}
|
402
|
404
|
|
403
|
|
- /**
|
404
|
|
- * Set if we should use autoAt or not.
|
405
|
|
- *
|
406
|
|
- * @param autoAt Should we use autoAt?
|
407
|
|
- */
|
408
|
|
- /* public void setAutoAt(final boolean autoAt) {
|
409
|
|
- this.autoAt = autoAt;
|
410
|
|
- } */
|
411
|
405
|
/**
|
412
|
406
|
* Is debugging enabled?
|
413
|
407
|
*
|
|
@@ -544,15 +538,13 @@ public class TwitterAPI {
|
544
|
538
|
try {
|
545
|
539
|
consumer.sign(connection);
|
546
|
540
|
} catch (final OAuthMessageSignerException ex) {
|
547
|
|
- handleError(ex, "(1) signURL", apiInput, apiOutput, "Unable to sign URL, are we authorised to use this account?");
|
|
541
|
+ handleError(ex, "(1) signURL", apiInput, apiOutput,
|
|
542
|
+ "Unable to sign URL, are we authorised to use this account?");
|
548
|
543
|
} catch (final OAuthExpectationFailedException ex) {
|
549
|
|
- handleError(ex, "(2) signURL", apiInput, apiOutput, "Unable to sign URL, are we authorised to use this account?");
|
|
544
|
+ handleError(ex, "(2) signURL", apiInput, apiOutput,
|
|
545
|
+ "Unable to sign URL, are we authorised to use this account?");
|
550
|
546
|
}
|
551
|
547
|
} else {
|
552
|
|
- // final String userpassword = myUsername + ":" + myPassword;
|
553
|
|
- // sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
|
554
|
|
- // String encodedAuthorization = enc.encode(userpassword.getBytes());
|
555
|
|
-
|
556
|
548
|
connection.setRequestProperty("Authorization", "Basic "
|
557
|
549
|
+ b64encode(myLoginUsername + ":" + myPassword));
|
558
|
550
|
}
|
|
@@ -591,7 +583,8 @@ public class TwitterAPI {
|
591
|
583
|
}
|
592
|
584
|
|
593
|
585
|
// replace encoded padding nulls with "="
|
594
|
|
- return encoded.substring(0, encoded.length() - paddingCount) + "==".substring(0, paddingCount);
|
|
586
|
+ return encoded.substring(0, encoded.length() - paddingCount)
|
|
587
|
+ + "==".substring(0, paddingCount);
|
595
|
588
|
}
|
596
|
589
|
|
597
|
590
|
/**
|
|
@@ -633,7 +626,8 @@ public class TwitterAPI {
|
633
|
626
|
* @return Boolean from string
|
634
|
627
|
*/
|
635
|
628
|
public static boolean parseBoolean(final String string) {
|
636
|
|
- return string.equalsIgnoreCase("true") || string.equalsIgnoreCase("yes") || string.equalsIgnoreCase("1");
|
|
629
|
+ return string.equalsIgnoreCase("true") || string.equalsIgnoreCase("yes")
|
|
630
|
+ || string.equalsIgnoreCase("1");
|
637
|
631
|
}
|
638
|
632
|
|
639
|
633
|
/**
|
|
@@ -645,7 +639,8 @@ public class TwitterAPI {
|
645
|
639
|
* @param fallback Default on failure.
|
646
|
640
|
* @return Long from string
|
647
|
641
|
*/
|
648
|
|
- public static String getElementContents(final Element element, final String string, final String fallback) {
|
|
642
|
+ public static String getElementContents(final Element element,
|
|
643
|
+ final String string, final String fallback) {
|
649
|
644
|
if (element != null) {
|
650
|
645
|
final NodeList nl = element.getElementsByTagName(string);
|
651
|
646
|
if (nl != null && nl.getLength() > 0) {
|
|
@@ -743,7 +738,7 @@ public class TwitterAPI {
|
743
|
738
|
*
|
744
|
739
|
* If an IOException is thrown this will be sent via handleError when
|
745
|
740
|
* debugigng is enabled.
|
746
|
|
- *
|
|
741
|
+ *
|
747
|
742
|
* @return True if connecting to the api works, else false.
|
748
|
743
|
*/
|
749
|
744
|
public boolean checkConnection() {
|
|
@@ -839,9 +834,11 @@ public class TwitterAPI {
|
839
|
834
|
responseCode = request.getResponseCode();
|
840
|
835
|
if (responseCode != 200) {
|
841
|
836
|
if (isDebug()) {
|
842
|
|
- handleError(null, "* (6) getXML", apiInput, apiOutput, "(" + request.getResponseCode() + ") " + request.getResponseMessage());
|
|
837
|
+ handleError(null, "* (6) getXML", apiInput, apiOutput,
|
|
838
|
+ "(" + request.getResponseCode() + ") " + request.getResponseMessage());
|
843
|
839
|
} else if (responseCode >= 500 && responseCode < 600) {
|
844
|
|
- handleError(null, "(6) getXML", apiInput, apiOutput, "(" + request.getResponseCode() + ") " + request.getResponseMessage());
|
|
840
|
+ handleError(null, "(6) getXML", apiInput, apiOutput,
|
|
841
|
+ "(" + request.getResponseCode() + ") " + request.getResponseMessage());
|
845
|
842
|
}
|
846
|
843
|
}
|
847
|
844
|
} catch (final IOException ioe) {
|
|
@@ -1008,7 +1005,7 @@ public class TwitterAPI {
|
1008
|
1005
|
*
|
1009
|
1006
|
* @param status
|
1010
|
1007
|
*/
|
1011
|
|
- protected void updateStatus(final TwitterStatus status) {
|
|
1008
|
+ protected void cacheStatus(final TwitterStatus status) {
|
1012
|
1009
|
if (status == null) {
|
1013
|
1010
|
return;
|
1014
|
1011
|
}
|
|
@@ -1061,7 +1058,7 @@ public class TwitterAPI {
|
1061
|
1058
|
status = null;
|
1062
|
1059
|
}
|
1063
|
1060
|
|
1064
|
|
- updateStatus(status);
|
|
1061
|
+ cacheStatus(status);
|
1065
|
1062
|
}
|
1066
|
1063
|
|
1067
|
1064
|
return status;
|
|
@@ -1094,7 +1091,8 @@ public class TwitterAPI {
|
1094
|
1091
|
*/
|
1095
|
1092
|
public boolean newDirectMessage(final String target, final String message) {
|
1096
|
1093
|
try {
|
1097
|
|
- final XMLResponse doc = postXML(getURL("direct_messages/new"), "screen_name=" + target + "&text=" + URLEncoder.encode(message, "utf-8"));
|
|
1094
|
+ final XMLResponse doc = postXML(getURL("direct_messages/new"),
|
|
1095
|
+ "screen_name=" + target + "&text=" + URLEncoder.encode(message, "utf-8"));
|
1098
|
1096
|
|
1099
|
1097
|
if (doc.isGood()) {
|
1100
|
1098
|
new TwitterMessage(this, doc.getDocumentElement());
|
|
@@ -1127,12 +1125,15 @@ public class TwitterAPI {
|
1127
|
1125
|
public List<TwitterStatus> getUserTimeline(final long lastUserTimelineId) {
|
1128
|
1126
|
final List<TwitterStatus> result = new ArrayList<TwitterStatus>();
|
1129
|
1127
|
|
1130
|
|
- final XMLResponse doc = getXML(getURL("statuses/user_timeline") + "?since_id=" + lastUserTimelineId + "&count=20");
|
|
1128
|
+ final XMLResponse doc = getXML(getURL("statuses/user_timeline")
|
|
1129
|
+ + "?since_id=" + lastUserTimelineId + "&count=20");
|
1131
|
1130
|
|
1132
|
1131
|
if (doc.isGood()) {
|
1133
|
1132
|
final NodeList nodes = doc.getElementsByTagName("status");
|
1134
|
1133
|
for (int i = 0; i < nodes.getLength(); i++) {
|
1135
|
|
- result.add(new TwitterStatus(this, nodes.item(i)));
|
|
1134
|
+ final TwitterStatus status = new TwitterStatus(this, nodes.item(i));
|
|
1135
|
+ cacheStatus(status);
|
|
1136
|
+ result.add(status);
|
1136
|
1137
|
}
|
1137
|
1138
|
}
|
1138
|
1139
|
|
|
@@ -1161,19 +1162,22 @@ public class TwitterAPI {
|
1161
|
1162
|
final List<TwitterStatus> result = new ArrayList<TwitterStatus>();
|
1162
|
1163
|
|
1163
|
1164
|
try {
|
1164
|
|
- final XMLResponse doc = getXML("http://search.twitter.com/search.atom?since_id=" + lastStatusId + "&rpp=100&q=" + URLEncoder.encode(term, "utf-8"));
|
|
1165
|
+ final XMLResponse doc = getXML("http://search.twitter.com/search.atom?since_id="
|
|
1166
|
+ + lastStatusId + "&rpp=100&q=" + URLEncoder.encode(term, "utf-8"));
|
1165
|
1167
|
|
1166
|
1168
|
if (doc.isGood()) {
|
1167
|
1169
|
final NodeList nodes = doc.getElementsByTagName("entry");
|
1168
|
1170
|
for (int i = 0; i < nodes.getLength(); i++) {
|
1169
|
1171
|
final Element element = (Element) nodes.item(i);
|
1170
|
1172
|
final String message = TwitterAPI.getElementContents(element, "title", "");
|
1171
|
|
- final long id = Long.parseLong(TwitterAPI.getElementContents(element, "id", "::-1").split(":")[2]);
|
|
1173
|
+ final long id =Long.parseLong(TwitterAPI.getElementContents(element,"id", "::-1").split(":")[2]);
|
1172
|
1174
|
final String user = TwitterAPI.getElementContents((Element) element.getElementsByTagName("author").item(0), "name", "").split(" ")[0];
|
1173
|
1175
|
|
1174
|
1176
|
final long time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(TwitterAPI.getElementContents(element, "published", "")).getTime();
|
1175
|
1177
|
|
1176
|
|
- result.add(0, new TwitterStatus(this, message, -1, id, user, time));
|
|
1178
|
+ final TwitterStatus status = new TwitterStatus(this, message, -1, id, user, time);
|
|
1179
|
+ cacheStatus(status);
|
|
1180
|
+ result.add(0, status);
|
1177
|
1181
|
}
|
1178
|
1182
|
}
|
1179
|
1183
|
} catch (final UnsupportedEncodingException ex) {
|
|
@@ -1303,7 +1307,9 @@ public class TwitterAPI {
|
1303
|
1307
|
final NodeList nodes = doc.getElementsByTagName("status");
|
1304
|
1308
|
|
1305
|
1309
|
for (int i = 0; i < nodes.getLength(); i++) {
|
1306
|
|
- result.add(new TwitterStatus(this, nodes.item(i)));
|
|
1310
|
+ final TwitterStatus status = new TwitterStatus(this, nodes.item(i));
|
|
1311
|
+ cacheStatus(status);
|
|
1312
|
+ result.add(status);
|
1307
|
1313
|
}
|
1308
|
1314
|
}
|
1309
|
1315
|
|
|
@@ -1334,7 +1340,9 @@ public class TwitterAPI {
|
1334
|
1340
|
if (doc.isGood()) {
|
1335
|
1341
|
final NodeList nodes = doc.getElementsByTagName("status");
|
1336
|
1342
|
for (int i = 0; i < nodes.getLength(); i++) {
|
1337
|
|
- result.add(new TwitterStatus(this, nodes.item(i)));
|
|
1343
|
+ final TwitterStatus status = new TwitterStatus(this, nodes.item(i));
|
|
1344
|
+ cacheStatus(status);
|
|
1345
|
+ result.add(status);
|
1338
|
1346
|
}
|
1339
|
1347
|
}
|
1340
|
1348
|
|
|
@@ -1415,16 +1423,18 @@ public class TwitterAPI {
|
1415
|
1423
|
final StringBuilder params = new StringBuilder("status=");
|
1416
|
1424
|
params.append(URLEncoder.encode(status, "utf-8"));
|
1417
|
1425
|
if (id >= 0) {
|
1418
|
|
- params.append("&in_reply_to_status_id=" + Long.toString(id));
|
|
1426
|
+ params.append("&in_reply_to_status_id=");
|
|
1427
|
+ params.append(Long.toString(id));
|
1419
|
1428
|
}
|
1420
|
1429
|
if (!useOAuth) {
|
1421
|
|
- params.append("&source=" + URLEncoder.encode(mySource, "utf-8"));
|
|
1430
|
+ params.append("&source=");
|
|
1431
|
+ params.append(URLEncoder.encode(mySource, "utf-8"));
|
1422
|
1432
|
}
|
1423
|
1433
|
|
1424
|
1434
|
final XMLResponse doc = postXML(getURL("statuses/update"), params.toString());
|
1425
|
1435
|
if (doc.getResponseCode() == 200) {
|
1426
|
1436
|
if (doc.isGood()) {
|
1427
|
|
- new TwitterStatus(this, doc.getDocumentElement());
|
|
1437
|
+ cacheStatus(new TwitterStatus(this, doc.getDocumentElement()));
|
1428
|
1438
|
}
|
1429
|
1439
|
return true;
|
1430
|
1440
|
}
|
|
@@ -1451,7 +1461,7 @@ public class TwitterAPI {
|
1451
|
1461
|
final XMLResponse doc = postXML(getURL("statuses/retweet/" + status.getID()));
|
1452
|
1462
|
if (doc.getResponseCode() == 200) {
|
1453
|
1463
|
if (doc.isGood()) {
|
1454
|
|
- new TwitterStatus(this, doc.getDocumentElement());
|
|
1464
|
+ cacheStatus(new TwitterStatus(this, doc.getDocumentElement()));
|
1455
|
1465
|
}
|
1456
|
1466
|
return true;
|
1457
|
1467
|
}
|
|
@@ -1522,7 +1532,7 @@ public class TwitterAPI {
|
1522
|
1532
|
|
1523
|
1533
|
/**
|
1524
|
1534
|
* Get the URL the user must visit in order to authorize DMDirc.
|
1525
|
|
- *
|
|
1535
|
+ *
|
1526
|
1536
|
* @return the URL the user must visit in order to authorize DMDirc.
|
1527
|
1537
|
* @throws TwitterRuntimeException if there is a problem with OAuth.*
|
1528
|
1538
|
*/
|