package org.mots.haxsync.utilities;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.TimeZone;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mots.haxsync.BaseRequestListener;
import org.mots.haxsync.R;
import org.mots.haxsync.provider.*;
import org.mots.haxsync.provider.FacebookFQLFriend;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Debug;
import android.preference.PreferenceManager;
import android.provider.CalendarContract.Attendees;
import android.util.Log;
import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.Facebook;
import com.facebook.android.Facebook.ServiceListener;
import com.facebook.android.FacebookError;
public class FacebookUtil extends Application{
// public static final String fbID = "176550339110536";
public static final String fbID = "366633546716469";
public static Facebook facebook = new Facebook(fbID);
public static AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(facebook);
public static Activity mActivity;
public static String accessToken;
private static final String TAG = "Utility";
public static final int PERMISSION_LEVEL = 1;
private static JSONObject selfInfo = null;
private static final int FQL_LIMIT = 20;
private static HashMap<String, Long> birthdays = new HashMap<String, Long>();
public static boolean isExtendingToken = false;
public static final boolean RESPECT_FACEBOOK_POLICY = true;
private static JSONObject realSelfInfo = null;
public static class PicInfo{
public String url;
public long timestamp;
}
public static boolean authorize(Context context, Account account) {
if (isExtendingToken) {
return false;
}
String token;
AccountManager am = AccountManager.get(context);
try {
token = am.getPassword(account);
} catch (SecurityException e) {
Log.e(TAG, "error getting token");
return false;
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
long access_expires = prefs.getLong("access_expires", 0);
Log.i("TOKEN EXPIRES", String.valueOf(access_expires));
facebook.setAccessToken(token);
if (access_expires != 0)
facebook.setAccessExpires(access_expires);
//Log.i("Facebook valid?", String.valueOf());
DeviceUtil.showJellyBeanNotification(context);
if (!DeviceUtil.isOnline(context))
return false;
boolean shouldExtend = false;
try {
shouldExtend = !checkToken() || facebook.shouldExtendAccessToken();
} catch (IOException i) {
Log.e(TAG, "error: " + i.getMessage());
return false;
}
if (shouldExtend) {
notifyToken(context);
return false;
}
return true;
}
private static void notifyToken(Context context) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName("org.mots.haxsync", "org.mots.haxsync.activities.AuthorizationActivity");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
isExtendingToken = true;
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = context.getResources();
Notification.Builder builder = new Notification.Builder(context);
builder.setContentIntent(contentIntent)
.setSmallIcon(android.R.drawable.stat_notify_error)
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.icon))
.setTicker(res.getString(R.string.token_notification_ticker))
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle(res.getString(R.string.token_notification_title))
.setContentText(res.getString(R.string.token_notification_description));
Notification n = builder.getNotification();
nm.notify(0, n);
}
private static boolean checkToken() throws IOException {
String response = facebook.request("me");
//Log.i("response", response);
return (!response.contains("\"type\":\"OAuthException\"") && facebook.isSessionValid());
}
public static void refreshPermissions(Context c){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
int permissionLevel = prefs.getInt("permission_level", 0);
Log.i("Permission Level", String.valueOf(permissionLevel));
if (permissionLevel < FacebookUtil.PERMISSION_LEVEL){
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName("org.mots.haxsync", "org.mots.haxsync.activities.AuthorizationActivity");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.startActivity(intent);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("permission_level", FacebookUtil.PERMISSION_LEVEL);
editor.commit();
}
}
public static List<FacebookGraphFriend> getFriends(int maxsize, boolean addMeToFriends){
Bundle params = new Bundle();
params.putString("fields", "picture.width("+maxsize+").height("+maxsize+"), name, first_name, last_name, username, birthday, location, updated_time");
List<FacebookGraphFriend> friends = new ArrayList<FacebookGraphFriend>();
List<String> ids = new ArrayList<String>();
try {
Bundle idParam = new Bundle();
idParam.putString("fields", "id");
if(addMeToFriends){
JSONObject resp = new JSONObject(facebook.request("me",idParam));
Log.i(TAG, "id response " + resp);
Log.i(TAG, "add Me to friends:" + resp.getString("id"));
ids.add(resp.getString("id"));
}
JSONObject resp = new JSONObject(facebook.request("me/friends", idParam));
Log.i(TAG, "id response:" + resp);
JSONArray friendsjson = resp.getJSONArray("data");
for(int i = 0; i < friendsjson.length(); i++){
ids.add(friendsjson.getJSONObject(i).getString("id"));
}
for(String id : ids){
JSONObject response = new JSONObject(facebook.request(id,params));
FacebookGraphFriend friend = new FacebookGraphFriend(response);
friends.add(friend);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
Log.e(TAG, "Error loading friends: " + e.toString());
}
return friends;
}
public static ArrayList<FacebookFQLFriend> getFriendInfo(boolean status){
//me/friends?fields=picture.height(720).width(720),name,username,birthday,location
//old fql way
JSONArray friendarray = new JSONArray();
JSONArray timestamps = new JSONArray();
int fetched = FQL_LIMIT;
int callNo = 0;
try{
while (fetched == FQL_LIMIT){
JSONObject jsonFQL = new JSONObject();
String query1;
if (status){
query1 = "select name, username, status, uid, profile_update_time, birthday_date, pic_big, current_location from user where uid in (select uid2 from friend where uid1=me()) order by name limit " + FQL_LIMIT + " offset " + callNo * FQL_LIMIT;
} else {
query1 = "select name, username, uid, profile_update_time, birthday_date, pic_big, current_location from user where uid in (select uid2 from friend where uid1=me()) order by name limit " + FQL_LIMIT + " offset " + callNo * FQL_LIMIT;
}
//Log.i("query1", query1);
jsonFQL.put("query1", query1);
jsonFQL.put("query2", "SELECT modified, src_big, owner FROM photo WHERE pid IN (SELECT cover_pid FROM album WHERE owner IN (SELECT uid FROM #query1) AND type = 'profile')");
Bundle params = new Bundle();
params.putString("method", "fql.multiquery");
params.putString("queries", jsonFQL.toString());
String friendstring = facebook.request(params);
JSONArray friendInfo = new JSONArray(friendstring);
JSONArray newFriends = friendInfo.getJSONObject(0).getJSONArray("fql_result_set");
Log.i("friendstring", friendstring);
fetched = newFriends.length();
Log.i("no of friends fetched", String.valueOf(fetched));
friendarray = concatArray(friendarray, newFriends);
timestamps = concatArray(timestamps, friendInfo.getJSONObject(1).getJSONArray("fql_result_set"));
callNo++;
}
} catch (Exception e) {
Log.e("ERROR:", e.toString());
}
//Log.i("friendarray", friendarray.toString());
Log.i("total number of friends fetched", String.valueOf(friendarray.length()));
Log.i("timestamps", timestamps.toString());
return mergeArrays(friendarray, timestamps);
}
public static PicInfo getProfilePicInfo(String uid){
String query = "SELECT modified, src_big, owner FROM photo WHERE pid IN (SELECT cover_pid FROM album WHERE owner = "+uid+" AND type = 'profile')";
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
PicInfo pic = new PicInfo();
try {
JSONArray hires = new JSONArray(facebook.request(params));
if (hires.length() >= 1){
pic.url = hires.getJSONObject(0).getString("src_big");
pic.timestamp = hires.getJSONObject(0).getLong("modified");
}
else {
query = "select pic_big from user where uid =" +uid;
params.putString("query", query);
//Log.i("json", facebook.request(params));
pic.url = new JSONArray(facebook.request(params)).getJSONObject(0).getString("pic_big");
}
} catch (Exception e){
e.printStackTrace();
}
return pic;
}
private static JSONArray concatArray(JSONArray old, JSONArray add) throws JSONException {
for (int i = 0; i < add.length(); i++) {
old.put(add.get(i));
}
return old;
}
public static ArrayList<Status> getStatuses(String uid, boolean fullTimeline){
JSONArray statusarray = getStatusJSON(uid, fullTimeline);
ArrayList<Status> statuses = new ArrayList<Status>();
if (statusarray != null){
for (int j = statusarray.length() -1 ; j >= 0 ; j--) {
JSONObject statusjson = null;
try {
statusjson = statusarray.getJSONObject(j);
} catch (JSONException e) { }
if (statusjson != null) {
statuses.add(new FacebookStatus(statusjson));
}
}
}
return statuses;
}
private static JSONArray getStatusJSON(String uid, boolean fullTimeline){
String query = "SELECT message, post_id, type, created_time, actor_id, app_data, source_id, likes, comments, permalink FROM stream WHERE source_id="+uid+" ORDER BY created_time DESC LIMIT 50";
if (!fullTimeline){
query = "SELECT message, post_id, type, created_time, actor_id, app_data, source_id, likes, comments, permalink FROM stream WHERE source_id="+uid+" AND actor_id="+uid+" ORDER BY created_time DESC LIMIT 50";
}
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
JSONArray result = null;
try {
String response = facebook.request(params);
// Log.i("response", response);
result = new JSONArray(response);
} catch (Exception e){}
//Log.i("response", result.toString());
return result;
}
public static List<Event> getEvents(String status){
ArrayList<Event> events = new ArrayList<Event>();
try{
Bundle params = new Bundle();
params.putString("method", "fql.query");
String statusString = "";
String[] statusArray = status.split("\\|");
for (int i = 0; i < statusArray.length; i++){
statusString += "'"+statusArray[i]+"'";
if (i != statusArray.length-1)
statusString += ", ";
}
String request = "SELECT name, eid, start_time, end_time, location, description FROM event WHERE eid IN ( SELECT eid FROM event_member WHERE uid = me() AND rsvp_status in ("+statusString+"))";
Log.i("request", request);
params.putString("query", request);
JSONArray eventarray = new JSONArray(facebook.request(params));
for (int i = 0; i < eventarray.length(); i++){
events.add(new Event(eventarray.getJSONObject(i)));
}
} catch (Exception e) {
Log.e("ERROR:", e.toString());
}
return events;
}
private static void addBirthday(String name, String date){
int month = Integer.valueOf(date.split("/")[0]);
int day = Integer.valueOf(date.split("/")[1]);
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.getInstance().get(Calendar.YEAR), month-1, day, 0, 0 , 0);
long millis = cal.getTimeInMillis();
birthdays.put(name, millis);
}
public static HashMap<String, Long> getBirthdays(){
if (birthdays.size() > 0){
return birthdays;
}
String query = "select name, birthday_date from user where uid in (select uid2 from friend where uid1=me()) order by name";
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
JSONArray result = null;
try {
result = new JSONArray(facebook.request(params));
} catch (Exception e) {
return birthdays;
}for(int i = 0; i < result.length(); i++){
try{
JSONObject friend = result.getJSONObject(i);
if (friend.getString("birthday_date") != null){
addBirthday(friend.getString("name"), friend.getString("birthday_date"));
}} catch (Exception e) {}
}
return birthdays;
}
private static ArrayList<FacebookFQLFriend> mergeArrays(JSONArray friendarray, JSONArray timestamps){
ArrayList<FacebookFQLFriend> friends = new ArrayList<FacebookFQLFriend>();
try{
for(int i = 0; i < friendarray.length(); i++){
JSONObject friend = friendarray.getJSONObject(i);
String uid = friend.getString("uid");
//write birthday hashmap
String birthdayDate = friend.getString("birthday_date");
if (birthdayDate != null && !birthdayDate.equals("") && ! birthdayDate.equals("null")){
addBirthday(friend.getString("name"), friend.getString("birthday_date"));
}
long modified = 0;
for(int j = 0; j < timestamps.length(); j++){
JSONObject timestamp = timestamps.getJSONObject(j);
if (timestamp.getString("owner").equals(uid)){
modified = timestamp.getLong("modified");
String src = timestamp.getString("src_big");
if (!src.equalsIgnoreCase("")){
friend.put("pic_big", src);
}
break;
}
}
friend.put("pic_modified", modified);
friends.add(new FacebookFQLFriend(friend));
}
} catch (Exception e) {
Log.e("ERROR:", e.toString());
}
// Log.i("JSON2", merged.toString());
return friends;
}
public static JSONObject getPicInfo(long picID){
String query = "SELECT owner, src_big, pid, aid FROM photo WHERE object_id="+picID;
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
JSONObject result = null;
try {
result = new JSONArray(facebook.request(params)).getJSONObject(0);
//Log.i("PIC_ID"+picID, result);
} catch (Exception e) {
Log.e(TAG, "error getting pic for id: " + picID);
return null;
}
return result;
}
public static JSONObject getProfilePic(String uid){
String query = "SELECT modified, src_big FROM photo WHERE pid IN (SELECT cover_pid FROM album WHERE owner="+uid+" AND type = 'profile')";
Log.i("query", query);
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
JSONObject result = null;
try {
result = new JSONArray(facebook.request(params)).getJSONObject(0);
} catch (Exception e) { }
//Log.i("result", result.toString());
return result;
}
public static String getSelfID(){
FacebookGraphFriend selfInfo = getSelfInfo();
return selfInfo.getUserName();
}
public static FacebookGraphFriend getSelfInfo(){
FacebookGraphFriend friend = null;
Bundle params = new Bundle();
params.putString("fields", "picture.width(720).height(720), name, username, birthday, location, updated_time");
try {
JSONObject response = new JSONObject(facebook.request("me", params));
friend = new FacebookGraphFriend(response);
//Log.i("GRAPH FRIENDS", friendsjson.toString());
} catch (IOException e) {
Log.e(TAG, "Error loading friends: " + e.toString());
}catch (JSONException e) {
Log.e(TAG, "Error loading friends: " + e.toString());
}
return friend;
}
public static JSONObject getSelfInfoAsync(){
Bundle params = new Bundle();
params.putString("fields", "name, picture");
mAsyncRunner.request("me", params, new UserRequestListener());
while (selfInfo == null){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return selfInfo;
}
public static String getFriendName(String uid){
String name = null;
try{
String query = "select name from user where uid = " + uid;
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
name = new JSONArray(facebook.request(params)).getJSONObject(0).getString("name");
} catch (Exception e) {
Log.e("ERROR:", e.toString());
}
// Log.i("JSON1", friendInfo.toString());
return name;
}
public static JSONArray getFriendNames(){
JSONArray friendInfo = null;
try{
String query = "select name from user where uid in (select uid2 from friend where uid1=me()) order by name";
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
String friendstring = facebook.request(params);
friendInfo = new JSONArray(friendstring);
} catch (Exception e) {
Log.e("ERROR:", e.toString());
}
// Log.i("JSON1", friendInfo.toString());
return friendInfo;
}
public static int convertStatus(String statusString){
if (statusString.equals("attending")){
return Attendees.ATTENDEE_STATUS_ACCEPTED;
} else if (statusString.equals("unsure")){
return Attendees.ATTENDEE_STATUS_TENTATIVE;
} else if (statusString.equals("declined")){
return Attendees.ATTENDEE_STATUS_DECLINED;
} else {
return Attendees.ATTENDEE_STATUS_INVITED;
}
}
public static List<EventAttendee> getEventAttendees(long eid){
JSONObject jsonFQL = new JSONObject();
String query1 = "SELECT uid, rsvp_status FROM event_member WHERE eid = " +eid + " AND uid IN (select uid2 from friend where uid1=me())";
List<EventAttendee> attendees = new ArrayList<EventAttendee>();
try {
jsonFQL.put("query1", query1);
jsonFQL.put("query2", "SELECT name, username, uid FROM user WHERE uid IN (SELECT uid FROM #query1)");
Bundle params = new Bundle();
params.putString("method", "fql.multiquery");
params.putString("queries", jsonFQL.toString());
JSONArray response = new JSONArray(facebook.request(params));
attendees = mergeAttendees(response.getJSONObject(0).getJSONArray("fql_result_set"), response.getJSONObject(1).getJSONArray("fql_result_set"));
// Log.i("respnse", response.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*try{
JSONObject self = getSelfInfo();
String query = "SELECT rsvp_status FROM event_member WHERE eid = " + eid +" AND uid = me()";
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
int status = convertStatus(new JSONArray(facebook.request(params)).getJSONObject(0).getString("rsvp_status"));
EventAttendee selfAttendee = new EventAttendee(self.getString("name"), self.getString("email"), status);
Log.i("selfattendee", selfAttendee.toString());
attendees.add(selfAttendee);
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
return attendees;
}
public static String getSelfAttendance(long eid){
try{
String query = "SELECT rsvp_status FROM event_member WHERE eid = " + eid +" AND uid = me()";
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
return new JSONArray(facebook.request(params)).getJSONObject(0).getString("rsvp_status");
}catch (Exception e) {
// TODO Auto-generated catch block
Log.e(TAG, e.getMessage());
return "";
}
}
private static List<EventAttendee> mergeAttendees(JSONArray statuses, JSONArray attendees){
ArrayList<EventAttendee> attendeeList = new ArrayList<EventAttendee>();
try{
for(int i = 0; i < attendees.length(); i++){
JSONObject friend = attendees.getJSONObject(i);
String uid = friend.getString("uid");
//write birthday hashmap
long modified = 0;
for(int j = 0; j < statuses.length(); j++){
JSONObject status = statuses.getJSONObject(j);
if (status.getString("uid").equals(uid)){
friend.put("rsvp_status", status.getString("rsvp_status"));
break;
}
}
attendeeList.add(new EventAttendee(friend));
}
} catch (Exception e) {
Log.e("ERROR:", e.toString());
}
// Log.i("JSON2", merged.toString());
return attendeeList;
}
public static JSONObject getFriendNamesAsync(){
Bundle params = new Bundle();
params.putString("fields", "name, picture");
mAsyncRunner.request("me", params, new UserRequestListener());
while (selfInfo == null){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return selfInfo;
}
public static class TokenListener implements ServiceListener{
@Override
public void onComplete(Bundle values) {
//Log.i("got values", values.toString());
accessToken = values.getString(Facebook.TOKEN);
// TODO Auto-generated method stub
}
@Override
public void onFacebookError(FacebookError e) {
Log.e(TAG, e.toString());
}
@Override
public void onError(Error e) {
Log.e(TAG, e.toString());
}
}
public static class UserRequestListener extends BaseRequestListener{
public void onComplete(final String response, final Object state){
JSONObject jsonobject;
try{
jsonobject = new JSONObject(response);
selfInfo = jsonobject;
} catch (JSONException e){
e.printStackTrace();
}
}
}
}