├── src ├── test │ ├── java │ │ └── .gitkeep │ └── resources │ │ └── .gitkeep └── main │ ├── resources │ └── .gitkeep │ └── java │ └── com │ └── podio │ └── sample │ └── twitter │ ├── TweetPrinter.java │ ├── TwitterReader.java │ ├── BaseTwitterReader.java │ ├── MarkdownTweetPrinter.java │ ├── HTMLTweetPrinter.java │ ├── DebugTwitterWriter.java │ ├── TwitterWriter.java │ ├── SearchTwitterReader.java │ ├── StreamTwitterReader.java │ ├── Importer.java │ └── PodioTwitterWriter.java ├── .gitignore ├── .settings ├── org.eclipse.m2e.core.prefs ├── org.maven.ide.eclipse.prefs └── org.eclipse.jdt.core.prefs ├── README.markdown ├── example.config.properties ├── .project ├── .classpath └── pom.xml /src/test/java/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /target 3 | 4 | config.properties -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Podio API Example - Twitter 2 | --------------------------- 3 | 4 | This is an example use of the Podio API to search for tweets and add them to an app in Podio. -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/TweetPrinter.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | public interface TweetPrinter { 4 | 5 | public String getLink(String text, String url); 6 | } 7 | -------------------------------------------------------------------------------- /example.config.properties: -------------------------------------------------------------------------------- 1 | twitter.token=token 2 | twitter.secret=secret 3 | twitter.access_token=token 4 | twitter.access_token_secret=secret 5 | podio.client.mail=client@example.com 6 | podio.client.secret=secret 7 | podio.user.mail=user@example.com 8 | podio.user.password=password -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/TwitterReader.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | public interface TwitterReader { 4 | 5 | /** 6 | * Reads from Twitter and posts to the Twitter app 7 | */ 8 | public void process(TwitterWriter writer) throws Exception; 9 | 10 | } -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/BaseTwitterReader.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | 4 | public abstract class BaseTwitterReader implements TwitterReader { 5 | 6 | protected static final String[] TERMS = new String[] { "@podio", "#podio", 7 | "@podiosupport", "podio.com" }; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/MarkdownTweetPrinter.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | public class MarkdownTweetPrinter implements TweetPrinter { 4 | 5 | @Override 6 | public String getLink(String text, String url) { 7 | return "[" + text + "](" + url + ")"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/HTMLTweetPrinter.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | public class HTMLTweetPrinter implements TweetPrinter { 4 | 5 | @Override 6 | public String getLink(String text, String url) { 7 | return "" + text + ""; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.settings/org.maven.ide.eclipse.prefs: -------------------------------------------------------------------------------- 1 | #Sat Nov 20 14:34:16 CET 2010 2 | activeProfiles= 3 | eclipse.preferences.version=1 4 | fullBuildGoals=process-test-resources 5 | includeModules=false 6 | resolveWorkspaceProjects=true 7 | resourceFilterGoals=process-resources resources\:testResources 8 | skipCompilerPlugin=true 9 | version=1 10 | -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/DebugTwitterWriter.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | import twitter4j.Status; 4 | 5 | public class DebugTwitterWriter implements TwitterWriter { 6 | 7 | @Override 8 | public boolean write(Status status) throws Exception { 9 | System.out.println(status.getText()); 10 | return false; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/TwitterWriter.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | import twitter4j.Status; 4 | 5 | public interface TwitterWriter { 6 | 7 | /** 8 | * Publishes the tweet to Podio 9 | * 10 | * @param tweet 11 | * The tweet to publish 12 | * @return true if the tweet was added, false 13 | */ 14 | boolean write(Status status) throws Exception; 15 | 16 | } -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | twitter 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.m2e.core.maven2Nature 21 | org.eclipse.jdt.core.javanature 22 | org.maven.ide.eclipse.maven2Nature 23 | 24 | 25 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Sun Nov 21 11:53:30 CET 2010 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.6 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 13 | org.eclipse.jdt.core.compiler.source=1.6 14 | -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/SearchTwitterReader.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | import java.io.IOException; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import org.apache.commons.lang3.StringUtils; 8 | 9 | import twitter4j.Query; 10 | import twitter4j.QueryResult; 11 | import twitter4j.Status; 12 | import twitter4j.Twitter; 13 | import twitter4j.TwitterException; 14 | import twitter4j.TwitterFactory; 15 | import twitter4j.auth.OAuth2Authorization; 16 | import twitter4j.conf.Configuration; 17 | 18 | public class SearchTwitterReader extends BaseTwitterReader { 19 | 20 | private Twitter twitter; 21 | 22 | public SearchTwitterReader(Configuration configuration) throws IOException, 23 | TwitterException { 24 | OAuth2Authorization authorization = new OAuth2Authorization( 25 | configuration); 26 | authorization.getOAuth2Token(); 27 | 28 | this.twitter = new TwitterFactory(configuration) 29 | .getInstance(authorization); 30 | } 31 | 32 | @Override 33 | public void process(TwitterWriter writer) throws Exception { 34 | String query = StringUtils.join(TERMS, " OR "); 35 | 36 | QueryResult result = twitter.search(new Query(query)); 37 | 38 | List statuses = result.getTweets(); 39 | Collections.reverse(statuses); 40 | for (Status status : statuses) { 41 | writer.write(status); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/StreamTwitterReader.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | import java.io.IOException; 4 | 5 | import twitter4j.FilterQuery; 6 | import twitter4j.Status; 7 | import twitter4j.StatusListener; 8 | import twitter4j.TwitterException; 9 | import twitter4j.TwitterStream; 10 | import twitter4j.TwitterStreamFactory; 11 | import twitter4j.UserStreamAdapter; 12 | import twitter4j.auth.OAuthAuthorization; 13 | import twitter4j.conf.Configuration; 14 | 15 | public class StreamTwitterReader extends BaseTwitterReader { 16 | 17 | private TwitterStream twitter; 18 | 19 | public StreamTwitterReader(Configuration configuration) throws IOException, 20 | TwitterException { 21 | this.twitter = new TwitterStreamFactory(configuration) 22 | .getInstance(new OAuthAuthorization(configuration)); 23 | } 24 | 25 | @Override 26 | public void process(final TwitterWriter writer) throws TwitterException { 27 | StatusListener listener = new UserStreamAdapter() { 28 | @Override 29 | public void onStatus(Status status) { 30 | try { 31 | writer.write(status); 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | } 35 | } 36 | 37 | @Override 38 | public void onException(Exception ex) { 39 | ex.printStackTrace(); 40 | } 41 | }; 42 | twitter.addListener(listener); 43 | 44 | FilterQuery query = new FilterQuery(); 45 | query.track(TERMS); 46 | twitter.filter(query); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/Importer.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | import java.io.FileInputStream; 4 | import java.util.Properties; 5 | 6 | import twitter4j.conf.Configuration; 7 | import twitter4j.conf.ConfigurationBuilder; 8 | 9 | /** 10 | * Imports tweets 11 | * 12 | */ 13 | public class Importer { 14 | 15 | /** 16 | * Runs the importer 17 | * 18 | * @param args 19 | * The first argument is mandatory and must specify the 20 | * configuration file to use 21 | */ 22 | public static void main(String[] args) throws Exception { 23 | Properties properties = new Properties(); 24 | properties.load(new FileInputStream(args[0])); 25 | 26 | ConfigurationBuilder cb = new ConfigurationBuilder(); 27 | cb.setDebugEnabled(true) 28 | .setOAuthConsumerKey(properties.getProperty("twitter.token")) 29 | .setOAuthConsumerSecret( 30 | properties.getProperty("twitter.secret")) 31 | .setOAuthAccessToken( 32 | properties.getProperty("twitter.access_token")) 33 | .setOAuthAccessTokenSecret( 34 | properties.getProperty("twitter.access_token_secret")) 35 | .setUseSSL(true); 36 | Configuration configuration = cb.build(); 37 | 38 | TwitterReader searchReader = new SearchTwitterReader(configuration); 39 | TwitterReader streamReader = new StreamTwitterReader(configuration); 40 | 41 | TwitterWriter writer = new PodioTwitterWriter(properties); 42 | 43 | try { 44 | System.out.println("Starting search"); 45 | 46 | searchReader.process(writer); 47 | 48 | System.out.println("Starting stream"); 49 | 50 | streamReader.process(writer); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.podio.sample 5 | twitter 6 | 0.2.0 7 | Twitter 8 | 9 | 10 | 11 | 12 | maven-compiler-plugin 13 | 2.3.2 14 | 15 | 1.6 16 | 1.6 17 | 18 | 19 | 20 | org.apache.maven.plugins 21 | maven-shade-plugin 22 | 1.4 23 | 24 | 25 | package 26 | 27 | shade 28 | 29 | 30 | 31 | 33 | 34 | com.podio.sample.twitter.Importer 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | MIT 49 | http://creativecommons.org/licenses/MIT/ 50 | 51 | 52 | 53 | 54 | 55 | twitter4j.org 56 | twitter4j.org Repository 57 | http://twitter4j.org/maven2 58 | 59 | true 60 | 61 | 62 | true 63 | 64 | 65 | 66 | 67 | 68 | com.podio 69 | api 70 | 0.7.3 71 | jar 72 | compile 73 | 74 | 75 | org.twitter4j 76 | twitter4j-stream 77 | 3.0.4-SNAPSHOT 78 | 79 | 80 | org.twitter4j 81 | twitter4j-core 82 | 3.0.4-SNAPSHOT 83 | 84 | 85 | org.apache.commons 86 | commons-lang3 87 | 3.1 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/main/java/com/podio/sample/twitter/PodioTwitterWriter.java: -------------------------------------------------------------------------------- 1 | package com.podio.sample.twitter; 2 | 3 | import java.io.IOException; 4 | import java.io.UnsupportedEncodingException; 5 | import java.net.MalformedURLException; 6 | import java.net.URL; 7 | import java.net.URLEncoder; 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.List; 11 | import java.util.Properties; 12 | 13 | import twitter4j.HashtagEntity; 14 | import twitter4j.Status; 15 | import twitter4j.URLEntity; 16 | import twitter4j.UserMentionEntity; 17 | 18 | import com.podio.APIFactory; 19 | import com.podio.ResourceFactory; 20 | import com.podio.comment.Comment; 21 | import com.podio.comment.CommentAPI; 22 | import com.podio.comment.CommentCreate; 23 | import com.podio.common.Reference; 24 | import com.podio.common.ReferenceType; 25 | import com.podio.file.FileAPI; 26 | import com.podio.item.FieldValuesUpdate; 27 | import com.podio.item.ItemAPI; 28 | import com.podio.item.ItemCreate; 29 | import com.podio.item.ItemsResponse; 30 | import com.podio.oauth.OAuthClientCredentials; 31 | import com.podio.oauth.OAuthUsernameCredentials; 32 | 33 | public class PodioTwitterWriter implements TwitterWriter { 34 | 35 | /** 36 | * The id of the app in Podio 37 | */ 38 | private static final int APP_ID = 29350; 39 | 40 | /** 41 | * The external ids of the fields in Podio 42 | */ 43 | private static final String TEXT = "title"; 44 | private static final String TWEET = "tweet"; 45 | private static final String FROM = "user"; 46 | private static final String AVATAR = "avatar"; 47 | private static final String FOLLOWERS = "followers"; 48 | private static final String LOCATION = "location"; 49 | private static final String SOURCE = "source"; 50 | private static final String LINK = "link"; 51 | private static final String REPLY_TO = "reply-to"; 52 | 53 | /** 54 | * The interface to Podio 55 | */ 56 | private final APIFactory apiFactory; 57 | 58 | public PodioTwitterWriter(Properties properties) { 59 | ResourceFactory resourceFactory = new ResourceFactory( 60 | new OAuthClientCredentials( 61 | properties.getProperty("podio.client.mail"), 62 | properties.getProperty("podio.client.secret")), 63 | new OAuthUsernameCredentials(properties 64 | .getProperty("podio.user.mail"), properties 65 | .getProperty("podio.user.password"))); 66 | this.apiFactory = new APIFactory(resourceFactory); 67 | } 68 | 69 | /** 70 | * Returns the full text for for a Tweet 71 | * 72 | * @param tweet 73 | * The tweet to get the full text for 74 | * @param status 75 | * The status of the tweet 76 | * @return The full text of the tweet in HTML code 77 | */ 78 | private String getFullText(Status status, TweetPrinter printer) { 79 | String text = status.getText(); 80 | 81 | HashtagEntity[] hashtags = status.getHashtagEntities(); 82 | if (hashtags != null) { 83 | for (HashtagEntity hashtag : hashtags) { 84 | try { 85 | String url = "http://twitter.com/#search?q=" 86 | + URLEncoder.encode(hashtag.getText(), "UTF-8"); 87 | String tag = "#" + hashtag.getText(); 88 | 89 | text = text.replace(tag, printer.getLink(tag, url)); 90 | } catch (UnsupportedEncodingException e) { 91 | e.printStackTrace(); 92 | } 93 | } 94 | } 95 | 96 | UserMentionEntity[] users = status.getUserMentionEntities(); 97 | if (users != null) { 98 | for (UserMentionEntity user : users) { 99 | String url = "http://twitter.com/" + user.getScreenName(); 100 | String tag = "@" + user.getScreenName(); 101 | 102 | text = text.replace(tag, printer.getLink(tag, url)); 103 | } 104 | } 105 | 106 | String url = "http://twitter.com/" + status.getUser().getScreenName(); 107 | String tag = "@" + status.getUser().getScreenName(); 108 | 109 | text = text.replace(tag, printer.getLink(tag, url)); 110 | 111 | return text; 112 | } 113 | 114 | private boolean include(Status status) { 115 | UserMentionEntity[] users = status.getUserMentionEntities(); 116 | if (users != null) { 117 | for (UserMentionEntity user : users) { 118 | if (user.getScreenName().equals("podio") 119 | || user.getScreenName().equals("podiosupport")) { 120 | return true; 121 | } 122 | } 123 | } 124 | 125 | if (status.getText().contains("pódio") 126 | || status.getText().contains("pòdio")) { 127 | return false; 128 | } 129 | 130 | return true; 131 | } 132 | 133 | /* 134 | * (non-Javadoc) 135 | * 136 | * @see com.podio.sample.twitter.TwitterWriter#tweet(twitter4j.Status) 137 | */ 138 | @Override 139 | public boolean write(Status status) throws Exception { 140 | if (!include(status)) { 141 | System.out.println("Skipping"); 142 | return false; 143 | } 144 | 145 | if (getItemId(status.getId()) != null) { 146 | System.out.println("Already added"); 147 | return false; 148 | } 149 | 150 | if (status.isRetweet()) { 151 | Integer retweetItemId = getItemId(status.getRetweetedStatus() 152 | .getId()); 153 | if (retweetItemId == null) { 154 | System.out.println("Unable to find original tweet"); 155 | return false; 156 | } 157 | 158 | CommentAPI commentAPI = apiFactory.getAPI(CommentAPI.class); 159 | List comments = commentAPI.getComments(new Reference( 160 | ReferenceType.ITEM, retweetItemId)); 161 | for (Comment comment : comments) { 162 | if (comment.getExternalId() != null 163 | && comment.getExternalId().equals( 164 | Long.toString(status.getId()))) { 165 | System.out.println("Already added as comment"); 166 | return false; 167 | } 168 | } 169 | 170 | Integer profileImageId = uploadProfile(status); 171 | List fileIds = new ArrayList(); 172 | if (profileImageId != null) { 173 | fileIds.add(profileImageId); 174 | } 175 | 176 | fileIds.addAll(uploadURLs(status)); 177 | 178 | TweetPrinter printer = new MarkdownTweetPrinter(); 179 | 180 | String text = getFullText(status, printer); 181 | text += "\n"; 182 | text += "\n"; 183 | text += getAuthorLink(status, printer); 184 | text += "\n"; 185 | text += "\n"; 186 | text += printer.getLink("twitter.com", getTweetLink(status)); 187 | 188 | commentAPI.addComment(new Reference(ReferenceType.ITEM, 189 | retweetItemId), 190 | new CommentCreate(text, Long.toString(status.getId()), 191 | Collections. emptyList(), fileIds), false); 192 | 193 | System.out.println("Added retweet " + status.getText()); 194 | 195 | return true; 196 | } else { 197 | Integer imageId = uploadProfile(status); 198 | 199 | TweetPrinter printer = new HTMLTweetPrinter(); 200 | 201 | List fields = new ArrayList(); 202 | fields.add(new FieldValuesUpdate(TEXT, "value", status.getText())); 203 | fields.add(new FieldValuesUpdate(TWEET, "value", getFullText( 204 | status, printer))); 205 | fields.add(new FieldValuesUpdate(FROM, "value", getAuthorLink( 206 | status, printer))); 207 | if (imageId != null) { 208 | fields.add(new FieldValuesUpdate(AVATAR, "value", imageId)); 209 | } 210 | fields.add(new FieldValuesUpdate(FOLLOWERS, "value", status 211 | .getUser().getFollowersCount())); 212 | if (status.getPlace() != null) { 213 | fields.add(new FieldValuesUpdate(LOCATION, "value", status 214 | .getPlace().getName())); 215 | } 216 | if (status.getSource() != null) { 217 | fields.add(new FieldValuesUpdate(SOURCE, "value", status 218 | .getSource())); 219 | } 220 | fields.add(new FieldValuesUpdate(LINK, "value", 221 | getTweetLink(status))); 222 | if (status.getInReplyToStatusId() > 0) { 223 | Integer replyToItemId = getItemId(status.getInReplyToStatusId()); 224 | if (replyToItemId != null) { 225 | fields.add(new FieldValuesUpdate(REPLY_TO, "value", 226 | replyToItemId)); 227 | } 228 | } 229 | 230 | List tags = new ArrayList(); 231 | if (status.getHashtagEntities() != null) { 232 | for (HashtagEntity tag : status.getHashtagEntities()) { 233 | tags.add(tag.getText()); 234 | } 235 | } 236 | 237 | List fileIds = uploadURLs(status); 238 | 239 | apiFactory.getAPI(ItemAPI.class).addItem( 240 | APP_ID, 241 | new ItemCreate(Long.toString(status.getId()), fields, 242 | fileIds, tags), false); 243 | 244 | System.out.println("Added tweet " + status.getText()); 245 | 246 | return true; 247 | } 248 | } 249 | 250 | /** 251 | * Returns the link to the tweet 252 | * 253 | * @param tweet 254 | * The tweet to link to 255 | * @return The link 256 | */ 257 | private String getTweetLink(Status status) { 258 | return "http://twitter.com/" + status.getUser().getScreenName() 259 | + "/status/" + status.getId(); 260 | } 261 | 262 | /** 263 | * Returns the link to the author of the tweet 264 | * 265 | * @param tweet 266 | * The tweet in question 267 | * @param status 268 | * The status of the tweet 269 | * @return The link 270 | */ 271 | private String getAuthorLink(Status status, TweetPrinter printer) { 272 | String url = "http://twitter.com/" + status.getUser().getScreenName(); 273 | return printer.getLink(status.getUser().getName(), url); 274 | } 275 | 276 | /** 277 | * Uploads the profile picture to Podio 278 | * 279 | * @param status 280 | * The status to upload the photo from 281 | * @return The file id of the uploaded file 282 | */ 283 | private Integer uploadProfile(Status status) { 284 | try { 285 | return uploadURL(new URL(status.getUser().getProfileImageURL())); 286 | } catch (MalformedURLException e) { 287 | return null; 288 | } 289 | } 290 | 291 | private List uploadURLs(Status status) { 292 | List fileIds = new ArrayList(); 293 | 294 | URLEntity[] urls = status.getURLEntities(); 295 | if (urls != null) { 296 | for (URLEntity url : urls) { 297 | String expandedUrl = url.getExpandedURL() != null ? url 298 | .getExpandedURL() : url.getURL(); 299 | if (expandedUrl == null) { 300 | continue; 301 | } 302 | 303 | URL resolvedUrl; 304 | try { 305 | resolvedUrl = new URL(expandedUrl); 306 | } catch (MalformedURLException e) { 307 | continue; 308 | } 309 | 310 | resolvedUrl = resolveURL(resolvedUrl); 311 | if (resolvedUrl == null) { 312 | continue; 313 | } 314 | 315 | Integer fileId = uploadURL(resolvedUrl); 316 | if (fileId == null) { 317 | continue; 318 | } 319 | 320 | fileIds.add(fileId); 321 | } 322 | } 323 | 324 | return fileIds; 325 | } 326 | 327 | /** 328 | * Uploads a single URL to the given reference if the URL is a link to an 329 | * image. Currently only images from twitpic and yfrog is supported. 330 | * 331 | * @param url 332 | * The URL to the image 333 | * @param reference 334 | * The reference to attach the image to 335 | */ 336 | private Integer uploadURL(URL url) { 337 | try { 338 | String contentType = url.openConnection().getContentType(); 339 | if (contentType == null || !contentType.startsWith("image/")) { 340 | return null; 341 | } 342 | 343 | String name = url.getPath().substring(1); 344 | if (contentType.contains("png")) { 345 | name += ".png"; 346 | } else if (contentType.contains("jpg") 347 | || contentType.contains("jpeg")) { 348 | name += ".jpg"; 349 | } else if (contentType.contains("gif")) { 350 | name += ".gif"; 351 | } 352 | 353 | return apiFactory.getAPI(FileAPI.class).uploadImage(url, name); 354 | } catch (IOException e) { 355 | e.printStackTrace(); 356 | 357 | return null; 358 | } 359 | } 360 | 361 | private URL resolveURL(URL url) { 362 | try { 363 | if (url.getHost().equals("twitpic.com")) { 364 | return new URL("http://twitpic.com/show/large" + url.getPath()); 365 | } else if (url.getHost().equals("yfrog.com")) { 366 | return new URL(url.toString() + ":medium"); 367 | } else { 368 | return null; 369 | } 370 | } catch (MalformedURLException e) { 371 | e.printStackTrace(); 372 | 373 | return null; 374 | } 375 | } 376 | 377 | /** 378 | * Returns the item id for a given tweet id. 379 | * 380 | * @param id 381 | * The id of the tweet 382 | * @return The item id if the tweet exists in Podio already, 383 | * null otherwise 384 | */ 385 | private Integer getItemId(long id) { 386 | ItemsResponse response = apiFactory.getAPI(ItemAPI.class) 387 | .getItemsByExternalId(APP_ID, Long.toString(id)); 388 | 389 | if (response.getFiltered() == 0) { 390 | return null; 391 | } 392 | 393 | return response.getItems().get(0).getId(); 394 | } 395 | } 396 | --------------------------------------------------------------------------------