You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2013/04/17 03:47:25 UTC
svn commit: r1468708 - in /tomee/sandbox/tools/src:
main/java/org/apache/openejb/tools/twitter/ main/resources/
test/java/org/apache/openejb/tools/
Author: dblevins
Date: Wed Apr 17 01:47:25 2013
New Revision: 1468708
URL: http://svn.apache.org/r1468708
Log:
Revamped retweet tool:
- logs less : we were getting several gigs a month
- now considers the people being followed by the accounts, not just those in the contributor list
- now considers retweets of people in the approved list
- no longer just approves when hashtag is used, if specific words match (case-sensitive) the tweet will be retweeted
Added:
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Json.java (with props)
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Key.java (with props)
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/ObjectMap.java
- copied, changed from r1457180, tomee/sandbox/release-tools/src/main/java/org/apache/openejb/tools/release/util/ObjectMap.java
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Tweet.java (with props)
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterApi.java (with props)
Removed:
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Filters.java
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/JsonResponseParser.java
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/ScreenNamesRetriever.java
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/UserStatusRetriever.java
tomee/sandbox/tools/src/test/java/org/apache/openejb/tools/RetweetITest.java
Modified:
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Config.java
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Retweet.java
tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterAccount.java
tomee/sandbox/tools/src/main/resources/RetweetTool.properties
Modified: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Config.java
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Config.java?rev=1468708&r1=1468707&r2=1468708&view=diff
==============================================================================
--- tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Config.java (original)
+++ tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Config.java Wed Apr 17 01:47:25 2013
@@ -94,6 +94,10 @@ public class Config {
return properties.getProperty(account + ".supported.hashtags", "#" + account);
}
+ public static String getWords(String account) {
+ return properties.getProperty(account + ".supported.words", account);
+ }
+
public static String asString() {
return properties.toString();
}
Added: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Json.java
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Json.java?rev=1468708&view=auto
==============================================================================
--- tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Json.java (added)
+++ tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Json.java Wed Apr 17 01:47:25 2013
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.tools.twitter;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @version $Rev$ $Date$
+*/
+public class Json {
+
+ public static List<Map> asList(String responseBody) {
+ try {
+ final ObjectMapper mapper = new ObjectMapper();
+ return mapper.readValue(new StringReader(responseBody), new TypeReference<ArrayList<Map>>() {
+ });
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public static Map asMap(String responseBody) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ return mapper.readValue(new StringReader(responseBody), new TypeReference<Map>() {
+ });
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+}
Propchange: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Json.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Key.java
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Key.java?rev=1468708&view=auto
==============================================================================
--- tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Key.java (added)
+++ tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Key.java Wed Apr 17 01:47:25 2013
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.tools.twitter;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @version $Rev$ $Date$
+ */
+@Target({ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Key {
+
+ String value();
+
+}
Propchange: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Key.java
------------------------------------------------------------------------------
svn:eol-style = native
Copied: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/ObjectMap.java (from r1457180, tomee/sandbox/release-tools/src/main/java/org/apache/openejb/tools/release/util/ObjectMap.java)
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/ObjectMap.java?p2=tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/ObjectMap.java&p1=tomee/sandbox/release-tools/src/main/java/org/apache/openejb/tools/release/util/ObjectMap.java&r1=1457180&r2=1468708&rev=1468708&view=diff
==============================================================================
--- tomee/sandbox/release-tools/src/main/java/org/apache/openejb/tools/release/util/ObjectMap.java (original)
+++ tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/ObjectMap.java Wed Apr 17 01:47:25 2013
@@ -14,26 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.openejb.tools.release.util;
+package org.apache.openejb.tools.twitter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.AbstractMap;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
-* @version $Rev$ $Date$
-*/
+ * @version $Rev$ $Date$
+ */
public class ObjectMap extends AbstractMap<String, Object> {
private final Object object;
- private Map<String,Entry<String,Object>> attributes;
- private Set<Entry<String,Object>> entries;
+ private Map<String, Entry<String, Object>> attributes;
+ private Set<Entry<String, Object>> entries;
+ private static final SimpleDateFormat FORMAT = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
public ObjectMap(Object object) {
this(object.getClass(), object);
@@ -55,7 +59,7 @@ public class ObjectMap extends AbstractM
for (Method getter : clazz.getMethods()) {
try {
- if (getter.getName().startsWith("get")) continue;
+ if (!getter.getName().startsWith("get")) continue;
if (getter.getParameterTypes().length != 0) continue;
@@ -101,23 +105,97 @@ public class ObjectMap extends AbstractM
return entries;
}
- public class FieldEntry implements Entry<String, Object> {
+ private Object convert(Object value, Class<?> targetType, final String name) {
+ if (value == null) return value;
+
+ final Class<? extends Object> actualType = value.getClass();
+
+ // Return boxed primitive
+ if (targetType.isPrimitive()) {
+ targetType = boxPrimitive(targetType);
+ }
+
+ // Return if doesn't need converting
+ if (targetType.isAssignableFrom(actualType)){
+ return value;
+ }
+
+ // Return number
+ if (Number.class.isAssignableFrom(actualType) && Number.class.isAssignableFrom(targetType)) {
+ return value;
+ }
+
+ if (Tweet.class.equals(targetType) && Map.class.isAssignableFrom(actualType)) {
+ final Tweet tweet = TwitterApi.asTweet((Map) value);
+ return tweet;
+ }
+
+ // No non-strings beyond this point!!
+ if (!(value instanceof String)) {
+ final String message = String.format("Expected type '%s' for '%s'. Found '%s'", targetType.getName(), name, actualType.getName());
+ throw new IllegalArgumentException(message);
+ }
+
+ final String stringValue = (String) value;
+
+ // Return parsed Enum
+ if (Enum.class.isAssignableFrom(targetType)) {
+ Class<? extends Enum> enumType = (Class<? extends Enum>) targetType;
+ return Enum.valueOf(enumType, stringValue.toUpperCase());
+ }
+
+ // Return parsed Date
+ if (Date.class.equals(targetType)) {
+ // Tue Apr 16 16:01:09 +0000 2013
+ try {
+ return FORMAT.parse(stringValue);
+ } catch (ParseException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ // FAIL - not convertable
+ final String message = String.format("Cannot convert to '%s' for '%s'. No PropertyEditor", targetType.getName(), name);
+ throw new IllegalArgumentException(message);
+ }
+
+ private Class<?> boxPrimitive(Class<?> targetType) {
+ if (targetType == byte.class) return Byte.class;
+ if (targetType == char.class) return Character.class;
+ if (targetType == short.class) return Short.class;
+ if (targetType == int.class) return Integer.class;
+ if (targetType == long.class) return Long.class;
+ if (targetType == float.class) return Float.class;
+ if (targetType == double.class) return Double.class;
+ if (targetType == boolean.class) return Boolean.class;
+ return targetType;
+ }
+
+ public class FieldEntry implements Entry<String, Object> {
private final Field field;
+ private final String key;
public FieldEntry(Field field) {
this.field = field;
+
+ final Key keyAnnotation = field.getAnnotation(Key.class);
+ if (keyAnnotation != null) {
+ this.key = keyAnnotation.value();
+ } else {
+ this.key = field.getName();
+ }
}
@Override
public String getKey() {
- return field.getName();
+ return key;
}
@Override
- public String getValue() {
+ public Object getValue() {
try {
- return (String) field.get(object);
+ return field.get(object);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
@@ -127,6 +205,7 @@ public class ObjectMap extends AbstractM
public Object setValue(Object value) {
try {
final Object replaced = getValue();
+ value = convert(value, field.getType(), getKey());
field.set(object, value);
return replaced;
} catch (IllegalAccessException e) {
@@ -141,15 +220,22 @@ public class ObjectMap extends AbstractM
private final Method setter;
public MethodEntry(Method getter, Method setter) {
- StringBuilder name = new StringBuilder(getter.getName());
- // remove 'set' or 'get'
- name.delete(0, 3);
+ final Key keyAnnotation = getter.getAnnotation(Key.class);
+ if (keyAnnotation != null) {
+ this.key = keyAnnotation.value();
+ } else {
+ StringBuilder name = new StringBuilder(getter.getName());
+
+ // remove 'set' or 'get'
+ name.delete(0, 3);
- // lowercase first char
- name.setCharAt(0, Character.toLowerCase(name.charAt(0)));
+ // lowercase first char
+ name.setCharAt(0, Character.toLowerCase(name.charAt(0)));
+
+ this.key = name.toString();
+ }
- this.key = name.toString();
this.getter = getter;
this.setter = setter;
}
@@ -177,6 +263,7 @@ public class ObjectMap extends AbstractM
@Override
public Object setValue(Object value) {
final Object original = getValue();
+ value = convert(value, setter.getParameterTypes()[0], getKey());
invoke(setter, value);
return original;
}
Modified: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Retweet.java
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Retweet.java?rev=1468708&r1=1468707&r2=1468708&view=diff
==============================================================================
--- tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Retweet.java (original)
+++ tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Retweet.java Wed Apr 17 01:47:25 2013
@@ -16,21 +16,13 @@
*/
package org.apache.openejb.tools.twitter;
-import oauth.signpost.exception.OAuthCommunicationException;
-import oauth.signpost.exception.OAuthExpectationFailedException;
-import oauth.signpost.exception.OAuthMessageSignerException;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
-import java.io.IOException;
-import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
-
-import static org.apache.openejb.tools.twitter.TwitterAccount.OPENEJB;
+import java.util.concurrent.TimeUnit;
/**
* We should monitor this feed http://twitter.com/#!/OpenEJB/contributors
@@ -57,73 +49,88 @@ import static org.apache.openejb.tools.t
public class Retweet {
private static final Logger logger = Logger.getLogger(Retweet.class);
- public static final String RETWEET_URL = "http://api.twitter.com/1/statuses/retweet/";
public static void main(String[] args) {
+ // Everyone in this list will have their tweets considered for retweeting
+ final Set<String> contributorsNames = new HashSet<String>();
+
+ // Add all the OpenEJB contributor list
+ contributorsNames.addAll(TwitterApi.getListMembers("OpenEJB", "contributors"));
+
+ // Add all the people being followed by any of the accounts
for (TwitterAccount account : TwitterAccount.values()) {
- final Set<String> validTweetIds = UserStatusRetriever.getAllContributorsStatuses(account);
- retweetIfNotEmpty(validTweetIds, account);
+ contributorsNames.addAll(TwitterApi.getFriends(account.getScreenName()));
}
- }
- private static void retweetIfNotEmpty(Collection<String> tweetIDs, TwitterAccount twitterAccount) {
+ final Set<Tweet> contributorTweets = new HashSet<Tweet>();
- if (!tweetIDs.isEmpty()) {
- logger.info("About to retweet " + tweetIDs + " at " + twitterAccount.toString() + " twitter account");
- retweetThisCollectionOfStatuses(tweetIDs, twitterAccount);
- } else {
- logger.info("No message to retweet at " + twitterAccount.toString() + " twitter account");
- }
- }
+ for (String screenName : contributorsNames) {
+
+ final Set<Tweet> tweets = TwitterApi.getStatuses(screenName);
- private static void retweetThisCollectionOfStatuses(Collection<String> nonRetweetedOpenEJBStatusIDs, TwitterAccount twitterAccount) {
+ contributorTweets.addAll(tweets);
+ }
- for (String statusIDToRetweet : nonRetweetedOpenEJBStatusIDs) {
- try {
- retweet(statusIDToRetweet, twitterAccount);
- pauseBeforeTheNextRetweet();
- } catch (OAuthMessageSignerException e) {
- e.printStackTrace();
- } catch (OAuthExpectationFailedException e) {
- e.printStackTrace();
- } catch (OAuthCommunicationException e) {
- e.printStackTrace();
+ { // Filter out old tweets
+ final Date current = new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(4));
+ final Iterator<Tweet> iterator = contributorTweets.iterator();
+ while (iterator.hasNext()) {
+ final Tweet tweet = iterator.next();
+ if (!tweet.getCreated().after(current)) {
+ logger.debug("Too old : " + tweet);
+ iterator.remove();
+ }
}
}
- }
+ // Unwrap retweets
+ unwrapRetweets(contributorTweets);
- public static HttpResponse retweet(String statusIDToRetweet, TwitterAccount twitterAccount) throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
- HttpPost httpPost = new HttpPost(RETWEET_URL + statusIDToRetweet + ".json");
+ for (TwitterAccount account : TwitterAccount.values()) {
- twitterAccount.sign(httpPost);
+ final Set<Tweet> tweeted = TwitterApi.getStatuses(account.getScreenName());
- HttpResponse response = null;
- try {
- response = getHttpClient().execute(httpPost);
- logger.debug(response.getStatusLine());
-
- logger.info("Retweeted " + statusIDToRetweet + " at " + twitterAccount.toString() + " twitter account");
- } catch (ClientProtocolException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
+ // Unwrap retweets
+ unwrapRetweets(tweeted);
+
+ for (Tweet tweet : contributorTweets) {
+ if (tweeted.contains(tweet)) {
+ logger.debug("Already tweeted : " + tweet);
+ continue;
+ }
+
+ if (!account.shouldRetweet(tweet.getText())) {
+ logger.debug("Doesn't match : " + tweet);
+ continue;
+ }
+
+ logger.info("Valid : " + tweet);
+ account.queueTweet(tweet);
+
+ }
+
+ // Trigger the retweet thread for this account
+ account.retweet();
}
- return response;
+ // Retweet threads are non-daemon threads
+ // the system will not exit till they are complete
}
- public static HttpClient getHttpClient() {
- return new DefaultHttpClient();
- }
+ private static void unwrapRetweets(Set<Tweet> tweets) {
+ final Set<Tweet> originalTweets = new HashSet<Tweet>();
- private static void pauseBeforeTheNextRetweet() {
- try { //So it doesn't look like spamming
- Thread.sleep(1000 * 60 * 5);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ final Iterator<Tweet> iterator = tweets.iterator();
+ while (iterator.hasNext()) {
+ final Tweet tweet = iterator.next();
+ if (tweet.getRetweeted() != null) {
+ logger.debug("Unroll : " + tweet);
+ iterator.remove();
+ originalTweets.add(tweet.getRetweeted());
+ }
}
- }
+ tweets.addAll(originalTweets);
+ }
}
Added: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Tweet.java
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Tweet.java?rev=1468708&view=auto
==============================================================================
--- tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Tweet.java (added)
+++ tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Tweet.java Wed Apr 17 01:47:25 2013
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.tools.twitter;
+
+import java.util.Date;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class Tweet {
+
+ private long id;
+ private String text;
+ private Date created;
+ private Tweet retweeted;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ @Key("created_at")
+ public Date getCreated() {
+ return created;
+ }
+
+ public void setCreated(Date created) {
+ this.created = created;
+ }
+
+
+ @Key("retweeted_status")
+ public Tweet getRetweeted() {
+ return retweeted;
+ }
+
+ public void setRetweeted(Tweet retweeted) {
+ this.retweeted = retweeted;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Tweet tweet = (Tweet) o;
+
+ if (id != tweet.id) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (id ^ (id >>> 32));
+ }
+
+ @Override
+ public String toString() {
+ return "Tweet{" +
+ "id=" + id +
+ ", text='" + text + '\'' +
+ '}';
+ }
+}
Propchange: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/Tweet.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterAccount.java
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterAccount.java?rev=1468708&r1=1468707&r2=1468708&view=diff
==============================================================================
--- tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterAccount.java (original)
+++ tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterAccount.java Wed Apr 17 01:47:25 2013
@@ -18,21 +18,27 @@ package org.apache.openejb.tools.twitter
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
-import oauth.signpost.exception.OAuthCommunicationException;
-import oauth.signpost.exception.OAuthExpectationFailedException;
-import oauth.signpost.exception.OAuthMessageSignerException;
-import org.apache.http.HttpRequest;
+import org.apache.log4j.Logger;
-import java.util.regex.Matcher;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
public enum TwitterAccount {
- OPENEJB, TOMEE;
+ OPENEJB("OpenEJB"), TOMEE("ApacheTomEE");
+ private static final Logger logger = Logger.getLogger(TwitterAccount.class);
+
+ private final String screenName;
private final OAuthConsumer consumer;
- private final Pattern approvedTweets;
+ private final Pattern hashtags;
+ private final Pattern words;
+ private final List<Tweet> queue = new ArrayList<Tweet>();
+
+ private TwitterAccount(String screenName) {
+ this.screenName = screenName;
- private TwitterAccount() {
final String account = name().toLowerCase();
// Create the consumer once per account
@@ -41,15 +47,59 @@ public enum TwitterAccount {
// Compile the Pattern once per account
final String hashTagsSupported = Config.getHashTags(account);
- approvedTweets = Pattern.compile(".*(#|@)(" + hashTagsSupported + ").*", Pattern.CASE_INSENSITIVE);
+ hashtags = Pattern.compile(".*(#|@)(" + hashTagsSupported + ").*", Pattern.CASE_INSENSITIVE);
+
+ final String wordsSupported = Config.getHashTags(account);
+ words = Pattern.compile(".*(" + wordsSupported + ").*");
+ }
+
+ public String getScreenName() {
+ return screenName;
}
public boolean shouldRetweet(String tweet) {
- final Matcher matcher = approvedTweets.matcher(tweet);
- return matcher.matches();
+ return words.matcher(tweet).matches() || hashtags.matcher(tweet).matches();
}
- public void sign(HttpRequest request) throws OAuthExpectationFailedException, OAuthMessageSignerException, OAuthCommunicationException {
- consumer.sign(request);
+ public synchronized void queueTweet(Tweet tweet) {
+ queue.add(tweet);
}
+
+ public synchronized void retweet() {
+ // copy then clear the original list
+ final List<Tweet> retweet = new ArrayList<Tweet>(this.queue);
+ this.queue.clear();
+
+ // Non-daemon thread prevents vm exit till all tweets are completed
+ new Thread() {
+ @Override
+ public void run() {
+ for (Tweet tweet : retweet) {
+ try {
+
+ final long tweetId = tweet.getId();
+
+ TwitterApi.retweet(consumer, tweetId);
+
+ logger.info(TwitterAccount.this.getScreenName() + " Retweeted " + tweet);
+
+ pauseBeforeTheNextRetweet();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }.start();
+ }
+
+ private static void pauseBeforeTheNextRetweet() {
+ try { //So it doesn't look like spamming
+ Thread.sleep(TimeUnit.MINUTES.toMillis(5));
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ }
+ }
+
}
Added: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterApi.java
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterApi.java?rev=1468708&view=auto
==============================================================================
--- tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterApi.java (added)
+++ tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterApi.java Wed Apr 17 01:47:25 2013
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.tools.twitter;
+
+import oauth.signpost.OAuthConsumer;
+import oauth.signpost.exception.OAuthCommunicationException;
+import oauth.signpost.exception.OAuthExpectationFailedException;
+import oauth.signpost.exception.OAuthMessageSignerException;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TwitterApi {
+
+ public static void retweet(OAuthConsumer account, long tweetId) throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException, IOException {
+
+ final String uri = "http://api.twitter.com/1/statuses/retweet/" + tweetId + ".json";
+ final HttpUriRequest httpPost = new HttpPost(uri);
+
+ account.sign(httpPost);
+ execute(httpPost);
+ }
+
+ public static List<String> getListMembers(final String screenName, final String listName) {
+ final String uri = "http://api.twitter.com/1/lists/members.json?slug=" + listName + "&owner_screen_name=" + screenName;
+ return getScreenNames(uri);
+ }
+
+ public static List<String> getFriends(final String screenName) {
+ final String uri = "http://api.twitter.com/1/friends.json?screen_name=" + screenName;
+ return getScreenNames(uri);
+ }
+
+ private static List<String> getScreenNames(String uri) {
+ try {
+ final String responseBody = get(uri);
+ final Map response = Json.asMap(responseBody);
+
+ final List<Map> users = (List<Map>) response.get("users");
+ final List<String> contributorsScreenNames = new ArrayList<String>();
+
+ for (Map map : users) {
+ contributorsScreenNames.add((String) map.get("screen_name"));
+ }
+
+ return contributorsScreenNames;
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public static Set<Tweet> getStatuses(String screenName) {
+ try {
+ final String uri = "http://api.twitter.com/1/statuses/user_timeline.json?include_rts=true&count=20&screen_name=" + screenName;
+ final String responseBody = get(uri);
+ final List<Map> result = Json.asList(responseBody);
+
+ return asTweets(result);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to get statuses for screenName: " + screenName, e);
+ }
+ }
+
+ private static String get(String uri) throws IOException {
+ final HttpUriRequest httpGet = new HttpGet(uri);
+ return execute(httpGet);
+ }
+
+ private static String execute(HttpUriRequest request) throws IOException {
+ final DefaultHttpClient client = new DefaultHttpClient();
+ final HttpResponse response = client.execute(request);
+
+ final ResponseHandler<String> responseHander = new BasicResponseHandler();
+ return responseHander.handleResponse(response);
+ }
+
+ private static Set<Tweet> asTweets(List<Map> listFromJson) {
+ final Set<Tweet> tweets = new HashSet<Tweet>();
+ for (Map from : listFromJson) {
+
+ final Tweet tweet = asTweet(from);
+
+ tweets.add(tweet);
+ }
+ return tweets;
+ }
+
+ public static Tweet asTweet(Map from) {
+ final Tweet tweet = new Tweet();
+
+ final ObjectMap to = new ObjectMap(tweet);
+ for (String key : to.keySet()) {
+ if (from.containsKey(key)) {
+ to.put(key, from.get(key));
+ }
+ }
+ return tweet;
+ }
+}
Propchange: tomee/sandbox/tools/src/main/java/org/apache/openejb/tools/twitter/TwitterApi.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tomee/sandbox/tools/src/main/resources/RetweetTool.properties
URL: http://svn.apache.org/viewvc/tomee/sandbox/tools/src/main/resources/RetweetTool.properties?rev=1468708&r1=1468707&r2=1468708&view=diff
==============================================================================
--- tomee/sandbox/tools/src/main/resources/RetweetTool.properties (original)
+++ tomee/sandbox/tools/src/main/resources/RetweetTool.properties Wed Apr 17 01:47:25 2013
@@ -15,4 +15,6 @@ retweetApp.tomee.authorizedUser.consumer
# pipe separated list of hashtags
openejb.supported.hashtags=openejb|tomee
+openejb.supported.words=OpenEJB|TomEE
tomee.supported.hashtags=apachetomee|tomee|openjpa|myfaces|openwebbeans|owb|tomcat|openejb
+tomee.supported.words=OpenEJB|TomEE