function weather_google_conditions($lat, $lon) { $enc_lat = geo_utils_prepare_coordinate($lat); $enc_lon = geo_utils_prepare_coordinate($lon); $query = array('weather' => ",,,{$enc_lat},{$enc_lon}"); $url = $GLOBALS['weather_google_endpoint'] . "?" . http_build_query($query); $rsp = http_get($url); if (!$rsp['ok']) { return $rsp; } libxml_use_internal_errors(true); $doc = new DOMDocument(); $doc->loadXML($rsp['body']); $xpath = new DOMXpath($doc); $cond = $xpath->query("*/current_conditions"); $current = array(); foreach ($cond as $c) { foreach ($c->childNodes as $node) { $k = $node->nodeName; $v = $node->getAttribute("data"); if ($k == 'icon') { continue; } $current[$k] = $v; } break; } if (!count($current)) { return not_okay("failed to parse conditions"); } $rsp = array('latitude' => $lat, 'longitude' => $lon, 'timestamp' => time(), 'source' => 'google', 'conditions' => $current); return okay($rsp); }
function flickr_photos_exif_read(&$photo) { $map = flickr_photos_media_map(); if ($map[$photo['media']] == 'video') { return not_okay("video does not contain EXIF data"); } $fname = "{$photo['id']}_{$photo['originalsecret']}_o.{$photo['originalformat']}"; $froot = $GLOBALS['cfg']['flickr_static_path'] . flickr_photos_id_to_path($photo['id']); $path = "{$froot}/{$fname}"; if (!preg_match("/\\.jpe?g\$/i", $path)) { return not_okay("not a JPEG photo"); } if (!file_exists($path)) { return not_okay("original photo not found"); } if (!filesize($path)) { return not_okay("original photo is empty"); } # TO DO: cache me? $exif = exif_read_data($path); if (!$exif) { return not_okay("failed to read EXIF data"); } # TO DO: expand EXIF tag values $to_simplejoin = array('SubjectLocation', 'GPSLatitude', 'GPSLongitude', 'GPSTimeStamp'); foreach ($to_simplejoin as $tag) { if (is_array($exif[$tag])) { $exif[$tag] = implode(",", $exif[$tag]); } } # TO DO: work out how/where individual EXIF tags get # "prettified" ... ksort($exif); return okay(array("rows" => $exif)); }
function api_spec_utils_example_for_method($method) { $path = FLAMEWORK_INCLUDE_DIR . "config.api.examples/{$method}.json"; if (!file_exists($path)) { return not_okay("no example defined for {$method} method"); } return okay(array('example' => file_get_contents($path))); }
function flickr_geobookmarks_import_for_nsid($nsid, $more = array()) { $flickr_user = flickr_users_get_by_nsid($nsid); $user = users_get_by_id($flickr_user['user_id']); if (!$user) { return not_okay("Not a valid user"); } $flickr_user = flickr_users_get_by_user_id($user['id']); $method = 'flickr.people.geoBookmarks.getList'; $args = array('auth_token' => $flickr_user['auth_token']); $rsp = flickr_api_call($method, $args); if (!$rsp['ok']) { return $rsp; } if (!$rsp['rsp']['bookmarks']['count']) { return okay(); } $bookmarks = array(); # mark everything as private for now since none of that stuff # got turned on before I left, sad face... (20120217/straup) $geo_perms = flickr_geo_permissions_map("string keys"); $geo_private = $geo_perms['private']; foreach ($rsp['rsp']['bookmarks']['bookmark'] as $bm) { $bm['user_id'] = $user['id']; $bm['name'] = $bm['label']; $bm['geocontext'] = $bm['context']; $bm['geoperms'] = $geo_private; $bm['woeid'] = 0; unset($bm['label']); unset($bm['pretty_name']); unset($bm['context']); $geo_method = 'flickr.places.findByLatLon'; $geo_args = array('lat' => $bm['latitude'], 'lon' => $bm['longitude'], 'accuracy' => $bm['accuracy']); $geo_rsp = flickr_api_call($geo_method, $geo_args); if ($geo_rsp['ok']) { # I still miss xpath... $bm['woeid'] = $geo_rsp['rsp']['places']['place'][0]['woeid']; } $bookmarks[] = $bm; } $rsp = flickr_geobookmarks_purge_for_user($user); if (!$rsp['ok']) { return $rsp; } $count = 0; foreach ($bookmarks as $bm) { $rsp = flickr_geobookmarks_add($bm); $count += $rsp['ok']; } return okay(array('count_imported' => $count)); }
function foursquare_api_get_auth_token($code) { $callback = $GLOBALS['cfg']['abs_root_url'] . $GLOBALS['cfg']['foursquare_oauth_callback']; $args = array('client_id' => $GLOBALS['cfg']['foursquare_oauth_key'], 'client_secret' => $GLOBALS['cfg']['foursquare_oauth_secret'], 'grant_type' => 'authorization_code', 'redirect_uri' => $callback, 'code' => $code); $query = http_build_query($args); $url = "{$GLOBALS['foursquare_oauth_endpoint']}access_token?{$query}"; $rsp = http_get($url); if (!$rsp['ok']) { return $rsp; } $data = json_decode($rsp['body'], 'as hash'); if (!$data || !$data['access_token']) { return not_okay("failed to parse response"); } return okay(array('oauth_token' => $data['access_token'])); }
function flickr_photos_geo_corrections_create($correction) { $user = users_get_by_id($correction['user_id']); if (!$user['id']) { return not_okay("Invalid user ID"); } $cluster_id = $user['cluster_id']; $correction['created'] = time(); $insert = array(); foreach ($correction as $k => $v) { $insert[$k] = AddSlashes($v); } $rsp = db_insert_users($cluster_id, 'FlickrPhotosGeoCorrections', $insert); if ($rsp['ok']) { $rsp['correction'] = $correction; } return $rsp; }
function _reverse_geoplanet_remote($lat, $lon, $remote_endpoint) { $cache_key = _reverse_geoplanet_cache_key($lat, $lon); $cache = cache_get($cache_key); if ($cache['ok']) { return okay($cache); } # $query = http_build_query(array('lat' => $lat, 'lon' => $lon)); $url = "{$remote_endpoint}?{$query}"; $rsp = http_get($url); if (!$rsp['ok']) { return $rsp; } $data = json_decode($rsp['body'], 'as hash'); if (!$data) { return not_okay("failed to parse response"); } # cache_set($cache_key, $data, "cache locally"); return okay(array('data' => $data, 'source' => $remote_endpoint)); }
function reverse_geoplanet_get_by_woeid($woeid, $placetype = 'woeid') { $cache_key = "reverse_geoplanet_woe_{$woeid}"; $cache = cache_get($cache_key); if ($cache['ok']) { return $cache['data']; } $valid_placetypes = array('woeid', 'locality'); if (!in_array($placetype, $valid_placetypes)) { return not_okay("invalid placetype"); } $enc_id = AddSlashes($woeid); $sql = "SELECT * FROM reverse_geoplanet WHERE `{$placetype}`='{$enc_id}'"; $rsp = db_fetch($sql); $row = db_single($rsp); if (!$row) { return; } if ($row['placetype'] == 22) { # This is a combination of my shitty code while I was # at Flickr (sorry) and the part where reverse_geoplanet # records the neighbourhood name even if it's only storing # cities (because names were never critical and a bit of # an afterthought... (20120229/straup) $parts = explode(", ", $row['name']); $country = array_pop($parts); array_pop($parts); array_shift($parts); # argh... if ($woeid == 2459115 && $parts[0] != 'New York') { array_unshift($parts, "New York"); } $parts[] = $country; $row['name'] = implode(", ", $parts); } cache_set($cache_key, $row, "cache locally"); return $row; }
function flickr_photos_places_contexts_for_user_and_place(&$user, &$place, $more = array()) { $defaults = array('viewer_id' => 0); $more = array_merge($defaults, $more); $more['enforce_geoperms'] = 1; if (!flickr_places_is_valid_placetype($place['place_type'])) { return not_okay("not a valid placetype"); } $query = array("user_id" => $user['id'], $place['place_type'] => $place['woeid']); $map = flickr_photos_geo_context_map(); $contexts = array(); foreach ($map as $ctx => $ignore) { $contexts[$ctx] = 0; } $rsp = flickr_photos_search_facet($query, 'geocontext', $more); if (!$rsp['ok']) { return $rsp; } foreach ($rsp['facets'] as $ctx => $count) { $contexts[$ctx] = $count; } return okay(array('contexts' => $contexts)); }
function flickr_photos_search_index_photo(&$photo, $meta = array()) { if (!$GLOBALS['cfg']['enable_feature_solr']) { return not_okay('search indexing is disabled'); } if (!$meta) { $meta = flickr_photos_metadata_load($photo); } # really exit or just ignore all the $meta stuff below? if (!$meta['ok']) { return not_okay('failed to load photo metadata'); } $meta = $meta['data']['photo']; $doc = array('id' => $photo['id'], 'user_id' => $photo['user_id'], 'title' => $photo['title'], 'perms' => $photo['perms'], 'datetaken' => solr_dates_prep_mysql_datetime($photo['datetaken']), 'dateupload' => solr_dates_prep_mysql_datetime($photo['dateupload'])); $tags = array(); $machinetags = array(); if (isset($meta['tags']['tag'])) { foreach ($meta['tags']['tag'] as $tag) { $tags[] = $tag['raw']; if ($tag['machinetag']) { $machinetags = array_merge($machinetags, solr_machinetags_explode($tag['raw'])); } } } if (count($tags)) { $doc['tags'] = $tags; } if (count($machinetags)) { $doc['machinetags'] = $machinetags; } if ($photo['hasgeo']) { $doc['location'] = "{$photo['latitude']},{$photo['longitude']}"; $doc['accuracy'] = $photo['accuracy']; $doc['geoperms'] = $photo['geoperms']; $doc['geocontext'] = $photo['geocontext']; foreach (array('neighbourhood', 'locality', 'county', 'region', 'country', 'continent') as $place) { if (isset($meta['location'][$place])) { $doc[$place] = $meta['location'][$place]['woeid']; } } if ($place = flickr_places_get_by_woeid($photo['woeid'])) { $doc['timezone'] = $place['timezone']; $doc['place'] = $place['place_url']; } } # pull in some EXIF data (if present) $rsp = flickr_photos_exif_read($photo); if ($rsp['ok']) { $exif = $rsp['rows']; if (isset($exif['Make'])) { if ($make = exif_tools_scrub_string($exif['Make'])) { $doc['camera_make'] = ucwords($make); } } if (isset($exif['Model'])) { if ($model = exif_tools_scrub_string($exif['Model'])) { $doc['camera_model'] = $model; } } # EXIF: what else? if (isset($exif['FocalLength'])) { $doc['focal_length'] = exif_tools_rational2float($exif['FocalLength']); } if (isset($exif['ApetureValue'])) { $doc['apeture'] = exif_tools_rational2float($exif['ApetureValue']); } if (isset($exif['ShutterSpeedValue'])) { $doc['shutter_speed'] = exif_tools_rational2float($exif['ShutterSpeedValue']); } if (isset($exif['ISOSpeedRatings'])) { $doc['iso_speed'] = intval($exif['ISOSpeedRatings']); } # http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/GPS.html if (isset($exif['GPSAltitude'])) { $altitude = exif_tools_explode_gps_altitude($exif['GPSAltitude'], $exif['GPSAltitudeRef']); $doc['altitude'] = $altitude; } if (isset($exif['GPSImgDirection'])) { $direction = exif_tools_explode_gps_img_direction($exif['GPSImgDirection'], $exif['GPSImgDirectionRef']); $doc['direction'] = $direction; } } # go! $docs = array($doc); $rsp = solr_add($docs); return $rsp; }
function flickr_photos_import_get_recent($nsid, $more = array()) { $flickr_user = flickr_users_get_by_nsid($nsid); $user = users_get_by_id($flickr_user['user_id']); if (!$user) { return array('ok' => 0, 'error' => 'not a valid user'); } $method = 'flickr.photos.recentlyUpdated'; if (!isset($more['min_date'])) { $offset_days = 1; $offset = intval(60 * 60 * 24 * $offset_days); $min_date = time() - $offset; } else { $min_date = intval($more['min_date']); } $args = array('auth_token' => $flickr_user['auth_token'], 'min_date' => $min_date, 'extras' => 'original_format,tags,media,date_upload,date_taken,geo', 'per_page' => 100, 'page' => 1); $pages = null; $imported = 0; # TO DO: capture dateupdate for each photo and return that # if there's a fatal error so that the FlickrBackups database # can be set with something other than 0 (20111206/straup) while (!isset($pages) || $pages >= $args['page']) { # because the Flickr API has an annoying habit of # timing out and this causes an initial import of # photos to fail and be repeated in-toto over and # over again (20111206/straup) $tries = 1; $max_tries = 5; $ok = 0; while (!$ok && $tries < $max_tries) { $rsp = flickr_api_call($method, $args); $ok = $rsp['ok']; $tries++; if ($ok) { $photos = $rsp['rsp']['photos']['photo']; if (!is_array($photos)) { $rsp = not_okay("no photos"); $ok = 0; } } } if (!$ok) { return $rsp; } if (!isset($pages)) { $pages = $rsp['rsp']['photos']['pages']; } # TO DO: date update stuff (see above) foreach ($photos as $photo) { flickr_photos_import_photo($photo, $more); $imported++; } $args['page'] += 1; } return okay(array('count_imported' => $imported)); }
function flickr_backups_get_contacts(&$user) { $backups = flickr_backups_for_user($user); if (!isset($backups['contacts'])) { return not_okay("backups not registered"); } $backup = $backups['contacts']; $update = array(); $start_time = time(); $flickr_user = flickr_users_get_by_user_id($user['id']); $more = array('purge_existing_contacts' => 1); $rsp = flickr_contacts_import_for_nsid($flickr_user['nsid'], $more); if ($rsp['ok']) { $update['date_lastupdate'] = $start_time; $update['details'] = "count: {$rsp['count_imported']}"; if (!$backup['date_firstupdate']) { $update['date_firstupdate'] = $update['date_lastupdate']; } } else { $update['details'] = "update failed ({$start_time}) : {$rsp['error']}"; } flickr_backups_update($backup, $update); return $rsp; }
function flickr_contacts_import_for_nsid($nsid, $more = array()) { $flickr_user = flickr_users_get_by_nsid($nsid); $user = users_get_by_id($flickr_user['user_id']); if (!$user) { return array('ok' => 0, 'error' => 'not a valid user'); } $method = 'flickr.contacts.getList'; $all_contacts = array(); $count_contacts = 0; $args = array('auth_token' => $flickr_user['auth_token'], 'per_page' => 100, 'page' => 1); $pages = null; while (!isset($pages) || $pages >= $args['page']) { $api_ok = 0; $api_error = ''; # Can I just say this is so profoundly annoying. Why why why # are API calls to a federated database table failing? Anyway. # (20120201/straup) $retries = 0; $max_retries = 10; while (!$api_ok) { $retries += 1; $rsp = flickr_api_call($method, $args); $api_ok = $rsp['ok']; if (!$api_ok) { $api_error = "The Flickr API is wigging out: {$rsp['error']}"; } else { $contacts = $rsp['rsp']['contacts']['contact']; if (!is_array($contacts)) { $api_error = "The Flickr API did not return any contacts"; $api_ok = 0; } } echo "page: {$args['page']}/{$pages} tries: {$retries}/{$max_retries} ok: {$api_ok}\n"; if (!$api_ok) { if ($retries == $max_retries) { return not_okay("Unable to fetch contacts: {$api_error}"); } } } if (!isset($pages)) { $pages = $rsp['rsp']['contacts']['pages']; } foreach ($contacts as $contact) { $contact_nsid = $contact['nsid']; $contact_username = $contact['username']; $flickr_contact = flickr_users_get_by_nsid($contact_nsid); if (!$flickr_contact) { $password = random_string(32); $user_contact = users_create_user(array("username" => $contact_username, "email" => "{$contact_username}@donotsend-flickr.com", "password" => $password)); # $method = 'flickr.people.getInfo'; $args = array('user_id' => $contact_nsid); $rsp = flickr_api_call($method, $args); $path_alias = $rsp['ok'] ? $rsp['rsp']['person']['path_alias'] : ''; # $flickr_contact = flickr_users_create_user(array('user_id' => $user_contact['id'], 'nsid' => $contact_nsid, 'path_alias' => $path_alias)); } $rel = flickr_contacts_calculate_relationship($contact); # echo "{$contact_username} : {$rel} ({$contact['friend']} {$contact['family']})\n"; $insert = array('user_id' => $user['id'], 'contact_id' => $flickr_contact['user_id'], 'rel' => $rel); $all_contacts[] = $insert; } $args['page'] += 1; } if (isset($more['purge_existing_contacts'])) { $rsp = flickr_contacts_purge_contacts($user); if (!$rsp['ok']) { return not_okay("failed to purge existing contacts: {$rsp['error']}"); } } # echo "import " . count($all_contacts) . " contacts\n"; foreach ($all_contacts as $insert) { if (flickr_contacts_add_contact($insert)) { $count_contacts++; } } return array('ok' => 1, 'count_imported' => $count_contacts); }
function flickr_photos_get_bookends_for_user(&$user, $more = array()) { $defaults = array('viewer_id' => 0, 'context' => 'datetaken'); $more = array_merge($defaults, $more); if (!in_array($more['context'], array('datetaken', 'dateupload'))) { return not_okay("invalid date context"); } $cluster_id = $user['cluster_id']; $enc_user = AddSlashes($user['id']); if ($perms = flickr_photos_permissions_photos_where($user['id'], $more['viewer_id'])) { $str_perms = implode(",", $perms); $extra = " AND perms IN ({$str_perms})"; } # TO DO: INDEXES $sql = "SELECT MIN(`{$more['context']}`) AS start, MAX(`{$more['context']}`) AS end FROM FlickrPhotos WHERE user_id = '{$enc_user}' {$extra}"; $rsp = db_fetch_users($cluster_id, $sql); if (!$rsp['ok']) { return $rsp; } $row = db_single($rsp); if (!$row) { return not_okay("no photos to bookend!"); } return okay($row); }