package org.limewire.facebook.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.limewire.facebook.service.settings.FacebookReportBugs;
import org.limewire.facebook.service.settings.FacebookURLs;
import org.limewire.friend.api.Friend;
import org.limewire.friend.api.FriendException;
import org.limewire.logging.Log;
import org.limewire.logging.LogFactory;
import org.limewire.util.ExceptionUtils;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
public class PresenceListener implements Runnable {
private static final Log LOG = LogFactory.getLog(PresenceListener.class);
private final FacebookFriendConnection connection;
private final BuddyListResponseDeserializer deserializer = new BuddyListResponseDeserializer();
private Set<String> lastOnlineFriends = new HashSet<String>();
private final Provider<Boolean> reportBugs;
private final Provider<Map<String, Provider<String>>> facebookURLs;
@Inject
PresenceListener(@Assisted FacebookFriendConnection connection,
@FacebookReportBugs Provider<Boolean> reportBugs,
@FacebookURLs Provider<Map<String, Provider<String>>> facebookURLs) {
this.connection = connection;
this.reportBugs = reportBugs;
this.facebookURLs = facebookURLs;
}
public void run() {
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("buddy_list", "1"));
nvps.add(new BasicNameValuePair("notifications", "1"));
nvps.add(new BasicNameValuePair("force_render", "true"));
nvps.add(new BasicNameValuePair("user", connection.getUID()));
nvps.add(new BasicNameValuePair("popped_out", "true"));
try{
LOG.debugf("posting buddy list request: {0}", nvps);
String responseStr = connection.httpPOST(facebookURLs.get().get(FacebookURLs.UPDATE_PRESENCES_URL).get(), nvps);
if (responseStr == null) {
LOG.debug("no response for buddy list post");
throw new IOException("no buddy list response");
}
LOG.debugf("buddy list response: {0}", responseStr);
Set<String> onlineFriendIds = deserializer.parseOnlineFriendIds(responseStr);
for (Friend friend : connection.getFriends()) {
if (onlineFriendIds.contains(friend.getId())) {
connection.addPresence(friend.getId());
} else if (lastOnlineFriends.contains(friend.getId())) {
try {
// the check implicitly removes the friend if he's offline
boolean online = connection.sendFriendIsOnline(friend.getId());
if (online) {
LOG.debugf("friend still online, overriding buddy list: {0}", friend);
// re-add friend to the set of online friends, so a recheck
// happens the next time he's reported offline
onlineFriendIds.add(friend.getId());
} else {
LOG.debugf("buddy list was right, friend offline: {0}", friend);
}
} catch (FriendException e) {
LOG.debug("error checking online state", e);
}
} else {
LOG.debugf("friend not online yet or buddy list out of date: {0}", friend);
}
}
lastOnlineFriends = onlineFriendIds;
} catch (JSONException e) {
LOG.debug("error deserializing JSON response", e);
if (reportBugs.get()) {
ExceptionUtils.reportOrReturn(e);
}
} catch (IOException e) {
LOG.debug("POST error", e);
try {
connection.reconnect();
} catch (IOException e1) {
LOG.debug("error reconnecting", e1);
connection.logout();
}
}
}
}