/**
*
*/
package com.googlecode.flickr2twitter.impl.flickr;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.logging.Logger;
import org.xml.sax.SAXException;
import com.googlecode.flickr2twitter.com.aetrion.flickr.Flickr;
import com.googlecode.flickr2twitter.com.aetrion.flickr.FlickrException;
import com.googlecode.flickr2twitter.com.aetrion.flickr.REST;
import com.googlecode.flickr2twitter.com.aetrion.flickr.RequestContext;
import com.googlecode.flickr2twitter.com.aetrion.flickr.auth.Auth;
import com.googlecode.flickr2twitter.com.aetrion.flickr.auth.AuthInterface;
import com.googlecode.flickr2twitter.com.aetrion.flickr.auth.Permission;
import com.googlecode.flickr2twitter.com.aetrion.flickr.photos.Extras;
import com.googlecode.flickr2twitter.com.aetrion.flickr.photos.Photo;
import com.googlecode.flickr2twitter.com.aetrion.flickr.photos.PhotoList;
import com.googlecode.flickr2twitter.com.aetrion.flickr.photos.PhotosInterface;
import com.googlecode.flickr2twitter.com.aetrion.flickr.tags.Tag;
import com.googlecode.flickr2twitter.core.GlobalDefaultConfiguration;
import com.googlecode.flickr2twitter.datastore.MyPersistenceManagerFactory;
import com.googlecode.flickr2twitter.datastore.model.GlobalServiceConfiguration;
import com.googlecode.flickr2twitter.datastore.model.GlobalSourceApplicationService;
import com.googlecode.flickr2twitter.datastore.model.User;
import com.googlecode.flickr2twitter.datastore.model.UserSourceServiceConfig;
import com.googlecode.flickr2twitter.exceptions.TokenAlreadyRegisteredException;
import com.googlecode.flickr2twitter.intf.IServiceAuthorizer;
import com.googlecode.flickr2twitter.intf.ISourceServiceProvider;
import com.googlecode.flickr2twitter.model.IPhoto;
import com.googlecode.flickr2twitter.org.apache.commons.lang3.StringUtils;
/**
* @author Toby Yu(yuyang226@gmail.com)
*
*/
public class SourceServiceProviderFlickr implements
ISourceServiceProvider<IPhoto>, IServiceAuthorizer {
public static final String ID = "flickr";
public static final String DISPLAY_NAME = "Flickr";
public static final String KEY_FROB = "frob";
public static final String KEY_FILTER_TAGS = "filter_tags";
public static final String TAGS_DELIMITER = ",";
public static final String TIMEZONE_CST = "CST";
public static final String TIMEZONE_GMT = "GMT";
public static final String CALLBACK_URL = "flickrcallback.jsp";
private static final Logger log = Logger.getLogger(SourceServiceProviderFlickr.class.getName());
/**
*
*/
public SourceServiceProviderFlickr() {
super();
}
private List<IPhoto> showRecentPhotos(Flickr f, UserSourceServiceConfig sourceService,
long interval, long currentTime) throws IOException, SAXException, FlickrException {
String userId = sourceService.getServiceUserId();
String token = sourceService.getServiceAccessToken();
RequestContext requestContext = RequestContext.getRequestContext();
Auth auth = new Auth();
auth.setPermission(Permission.READ);
auth.setToken(token);
requestContext.setAuth(auth);
List<IPhoto> photos = new ArrayList<IPhoto>();
List<String> filterTags = new ArrayList<String>();
Map<String, String> additionalParams = sourceService.getAdditionalParameters();
if (additionalParams.containsKey(KEY_FILTER_TAGS)) {
String filterTrags = additionalParams.get(KEY_FILTER_TAGS);
if (filterTrags != null) {
filterTags.addAll(Arrays.asList(StringUtils.split(
filterTrags.trim(), TAGS_DELIMITER)));
}
}
PhotosInterface photosFace = f.getPhotosInterface();
Set<String> extras = new HashSet<String>(2);
extras.add(Extras.DATE_UPLOAD);
extras.add(Extras.LAST_UPDATE);
extras.add(Extras.GEO);
if (filterTags.isEmpty() == false) {
extras.add(Extras.TAGS);
}
Date pastTime = sourceService.getLastUpdateTime();
Calendar past = Calendar.getInstance(TimeZone.getTimeZone(TIMEZONE_GMT));
if (pastTime == null) {
Calendar cstTime = Calendar.getInstance(TimeZone.getTimeZone(TIMEZONE_GMT));
cstTime.setTimeInMillis(currentTime);
log.info("Converted current time: " + cstTime.getTime());
// Calendar past = getFromTime(globalConfig, currentTime);
long newTime = cstTime.getTime().getTime() - interval;
past.setTimeInMillis(newTime);
pastTime = past.getTime();
} else {
past.setTimeInMillis(pastTime.getTime());
pastTime = past.getTime();
}
PhotoList list = photosFace.recentlyUpdated(pastTime, extras, 100,
1);
log.info("Trying to find photos uploaded for user " + userId
+ " after " + pastTime.toString() + " from "
+ list.getTotal() + " new photos");
for (Object obj : list) {
if (obj instanceof Photo) {
Photo photo = (Photo) obj;
log.info("processing photo: " + photo.getTitle()
+ ", date uploaded: " + photo.getDatePosted());
if (photo.isPublicFlag() && photo.getDatePosted().after(pastTime)) {
if (!filterTags.isEmpty() && containsTags(filterTags, photo.getTags()) == false) {
log.warning("Photo does not contains the required tags, contained tags are: "
+ photo.getTags());
} else {
log.info(photo.getTitle() + ", URL: " + photo.getUrl()
+ ", date uploaded: " + photo.getDatePosted()
+ ", GEO: " + photo.getGeoData());
photos.add(photo);
}
} else {
log.warning("private photo will not be posted: " + photo.getTitle());
}
}
}
return photos;
}
private static boolean containsTags(List<String> filterTags, Collection<Tag> photoTags) {
if (photoTags == null)
return false;
int matchCount = 0;
for (Tag tag : photoTags) {
if (filterTags.contains(tag.getValue())) {
matchCount++;
}
if (matchCount == filterTags.size()) {
return true;
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see
* com.googlecode.flickr2twitter.intf.ISourceServiceProvider#getId
* ()
*/
@Override
public String getId() {
return ID;
}
/*
* (non-Javadoc)
*
* @see com.googlecode.flickr2twitter.intf.ISourceServiceProvider#
* getLatestItems()
*/
@Override
public List<IPhoto> getLatestItems(GlobalServiceConfiguration globalConfig,
GlobalSourceApplicationService globalSvcConfig,
UserSourceServiceConfig sourceService,
long currentTime) throws Exception {
if (globalSvcConfig == null
|| ID.equalsIgnoreCase(globalSvcConfig.getProviderId()) == false) {
throw new IllegalArgumentException(
"Invalid source service provider: " + globalSvcConfig);
}
REST transport = new REST();
Flickr f = new Flickr(globalSvcConfig.getSourceAppApiKey(),
globalSvcConfig.getSourceAppSecret(), transport);
transport.setAllowCache(false);
Flickr.debugRequest = false;
Flickr.debugStream = false;
return showRecentPhotos(f, sourceService,
globalConfig.getMinUploadTime(), currentTime);
}
/*
* (non-Javadoc)
*
* @see
* com.googlecode.flickr2twitter.intf.ISourceServiceProvider#storeToken
* (com.googlecode.flickr2twitter.intf.IDataStoreService)
*/
@Override
public String readyAuthorization(String userEmail, Map<String, Object> data)
throws Exception {
if (data == null || data.containsKey(KEY_FROB) == false) {
throw new IllegalArgumentException("Invalid data: " + data);
}
User user = MyPersistenceManagerFactory.getUser(userEmail);
if (user == null) {
throw new IllegalArgumentException(
"Can not find the specified user: " + userEmail);
}
Flickr f = new Flickr(GlobalDefaultConfiguration.getInstance()
.getFlickrApiKey(), GlobalDefaultConfiguration.getInstance()
.getFlickrSecret(), new REST());
String frob = String.valueOf(data.get(KEY_FROB));
AuthInterface authInterface = f.getAuthInterface();
Auth auth = authInterface.getToken(frob);
StringBuffer buf = new StringBuffer();
buf.append("Authentication success\n");
// This token can be used until the user revokes it.
buf.append("Token: " + auth.getToken());
buf.append("\n");
buf.append("nsid: " + auth.getUser().getId());
buf.append("\n");
buf.append("Realname: " + auth.getUser().getRealName());
buf.append("\n");
buf.append("User Site: " + auth.getUser().getPhotosurl());
buf.append("\n");
buf.append("Username: " + auth.getUser().getUsername());
buf.append("\n");
buf.append("Permission: " + auth.getPermission().getType());
String userId = auth.getUser().getId();
for (UserSourceServiceConfig service : MyPersistenceManagerFactory
.getUserSourceServices(user)) {
if (auth.getToken().equals(service.getServiceAccessToken())) {
throw new TokenAlreadyRegisteredException(auth.getToken(), auth
.getUser().getUsername());
}
}
UserSourceServiceConfig serviceConfig = new UserSourceServiceConfig();
serviceConfig.setServiceUserId(userId);
serviceConfig.setServiceUserName(auth.getUser().getUsername());
serviceConfig.setServiceAccessToken(auth.getToken());
serviceConfig.setServiceProviderId(ID);
serviceConfig.setUserEmail(userEmail);
com.googlecode.flickr2twitter.com.aetrion.flickr.people.User flickrUser =
f.getPeopleInterface().getInfo(userId);
if (flickrUser != null) {
serviceConfig.setUserSiteUrl(flickrUser.getPhotosurl());
}
serviceConfig.addAddtionalParameter(KEY_FILTER_TAGS, "");
MyPersistenceManagerFactory.addSourceServiceApp(userEmail, serviceConfig);
return buf.toString();
}
public static void setFilterTags(UserSourceServiceConfig serviceConfig, String filterTags) {
}
/*
* (non-Javadoc)
*
* @see com.googlecode.flickr2twitter.intf.ISourceServiceProvider#
* requestAuthorization()
*/
@Override
public Map<String, Object> requestAuthorization(String baseUrl) throws Exception {
GlobalSourceApplicationService globalAppConfig = MyPersistenceManagerFactory
.getGlobalSourceAppService(ID);
if (globalAppConfig == null
|| ID.equalsIgnoreCase(globalAppConfig.getProviderId()) == false) {
throw new IllegalArgumentException(
"Invalid source service provider: " + globalAppConfig);
}
Map<String, Object> result = new HashMap<String, Object>();
Flickr f = new Flickr(globalAppConfig.getSourceAppApiKey(),
globalAppConfig.getSourceAppSecret(), new REST());
AuthInterface authInterface = f.getAuthInterface();
String frob = authInterface.getFrob();
if (baseUrl.endsWith("/oauth")) {
baseUrl = StringUtils.left(baseUrl, baseUrl.length() - "/oauth".length());
}
String nextUrl = baseUrl + "/" + CALLBACK_URL;
URL url = authInterface.buildAuthenticationUrl(Permission.READ, frob, nextUrl);
log.info("frob: " + frob + ", Token URL: " + url.toExternalForm());
result.put(KEY_FROB, frob);
result.put("url", url.toExternalForm());
return result;
}
/*
* trying to use OAuth 1a
* @Override
public Map<String, Object> requestAuthorization(String baseUrl) throws Exception {
GlobalSourceApplicationService globalAppConfig = MyPersistenceManagerFactory
.getGlobalSourceAppService(ID);
if (globalAppConfig == null
|| ID.equalsIgnoreCase(globalAppConfig.getProviderId()) == false) {
throw new IllegalArgumentException(
"Invalid source service provider: " + globalAppConfig);
}
Map<String, Object> result = new HashMap<String, Object>();
if (baseUrl.endsWith("/oauth")) {
baseUrl = StringUtils.left(baseUrl, baseUrl.length() - "/oauth".length());
}
String nextUrl = baseUrl + "/" + CALLBACK_URL;
OAuthConsumer consumer = new DefaultOAuthConsumer(globalAppConfig.getSourceAppApiKey(),
globalAppConfig.getSourceAppSecret());
OAuthProvider provider = new DefaultOAuthProvider(
"http://www.flickr.com/services/oauth/request_token",
"http://www.flickr.com/services/oauth/access_token",
"http://www.flickr.com/services/oauth/authorize");
// fetches a request token from the service provider and builds
// a url based on AUTHORIZE_WEBSITE_URL and CALLBACK_URL to
// which your app must now send the user
provider.setOAuth10a(true);
String tokenUrl = provider.retrieveRequestToken(consumer, nextUrl);
log.info(", Token URL: " + tokenUrl);
result.put("url", tokenUrl);
return result;
}*/
/*
* (non-Javadoc)
*
* @see com.googlecode.flickr2twitter.intf.IServiceProvider#
* createDefaultGlobalApplicationConfig()
*/
@Override
public GlobalSourceApplicationService createDefaultGlobalApplicationConfig() {
GlobalSourceApplicationService result = new GlobalSourceApplicationService();
result.setAppName(DISPLAY_NAME);
result.setProviderId(ID);
result.setDescription("The world's leading online photo storage service");
result.setSourceAppApiKey(GlobalDefaultConfiguration.getInstance()
.getFlickrApiKey());
result.setSourceAppSecret(GlobalDefaultConfiguration.getInstance()
.getFlickrSecret());
result.setAuthPagePath(CALLBACK_URL);
result.setImagePath("/services/flickr/images/flickr_100.gif");
return result;
}
}