From 2cd148c792a47fea18d760b723d23569ae52d390 Mon Sep 17 00:00:00 2001 From: Aaron Parecki Date: Wed, 24 Dec 2014 16:44:44 -0800 Subject: Support for "likes" and adding "settings" page * Supports a bookmarklet to create "like" posts. * Beginning a "settings" page to connect silo profiles for POSSEing likes to twitter, facebook and instagram --- lib/config.template.php | 7 +++++++ lib/helpers.php | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'lib') diff --git a/lib/config.template.php b/lib/config.template.php index df80efa..dae8968 100644 --- a/lib/config.template.php +++ b/lib/config.template.php @@ -10,5 +10,12 @@ class Config { public static $dbPassword = ''; public static $jwtSecret = 'xxx'; + + public static $fbClientID = ''; + public static $fbClientSecret = ''; + public static $twitterClientID = ''; + public static $twitterClientSecret = ''; + public static $instagramClientID = ''; + public static $instagramClientSecret = ''; } diff --git a/lib/helpers.php b/lib/helpers.php index cf751c6..010bd91 100644 --- a/lib/helpers.php +++ b/lib/helpers.php @@ -70,6 +70,26 @@ function get_timezone($lat, $lng) { return null; } +function micropub_post_for_user(&$user, $params) { + // Now send to the micropub endpoint + $r = micropub_post($user->micropub_endpoint, $params, $user->micropub_access_token); + + $user->last_micropub_response = json_encode($r); + $user->last_micropub_response_date = date('Y-m-d H:i:s'); + + // Check the response and look for a "Location" header containing the URL + if($r['response'] && preg_match('/Location: (.+)/', $r['response'], $match)) { + $r['location'] = $match[1]; + $user->micropub_success = 1; + } else { + $r['location'] = false; + } + + $user->save(); + + return $r; +} + function micropub_post($endpoint, $params, $access_token) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $endpoint); -- cgit v1.2.3 From 430609b9005bb93ce2c6b21405cea0ede2b17a9d Mon Sep 17 00:00:00 2001 From: Aaron Parecki Date: Thu, 25 Dec 2014 18:50:34 -0800 Subject: adds instagram auth --- composer.json | 3 ++- composer.lock | 45 ++++++++++++++++++++++++++++++++++++++++++++- controllers/controllers.php | 40 ++++++++++++++++++++++++++++++++++++++++ lib/helpers.php | 11 +++++++++++ views/settings.php | 31 +++++++++++++++++++++++++------ 5 files changed, 122 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/composer.json b/composer.json index a7dbea7..cf2f57e 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,8 @@ "indieauth/client": "0.1.3", "mpratt/relativetime": ">=1.0", "firebase/php-jwt": "dev-master", - "ruudk/twitter-oauth": "dev-master" + "ruudk/twitter-oauth": "dev-master", + "andreyco/instagram": "3.*" }, "autoload": { "files": [ diff --git a/composer.lock b/composer.lock index 0bdac28..eb3dfc1 100644 --- a/composer.lock +++ b/composer.lock @@ -3,8 +3,51 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "502847c033f5a54c69a6a1a51d26e894", + "hash": "f2f8fdb671b52ce22dc0a5e133f9a13d", "packages": [ + { + "name": "andreyco/instagram", + "version": "v3.2", + "source": { + "type": "git", + "url": "https://github.com/Andreyco/Instagram-for-PHP.git", + "reference": "726e724c51301410873d9bae9c659a0597ca47e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Andreyco/Instagram-for-PHP/zipball/726e724c51301410873d9bae9c659a0597ca47e4", + "reference": "726e724c51301410873d9bae9c659a0597ca47e4", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Andreyco\\Instagram\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-4-Clause" + ], + "authors": [ + { + "name": "Andrej Badin", + "email": "contact@andrejbadin.com", + "homepage": "http://andrejbadin.com" + } + ], + "description": "An easy-to-use PHP Class for accessing Instagram's API.", + "homepage": "https://github.com/Andreyco/Instagram", + "keywords": [ + "api", + "instagram" + ], + "time": "2014-07-14 19:53:19" + }, { "name": "firebase/php-jwt", "version": "dev-master", diff --git a/controllers/controllers.php b/controllers/controllers.php index 18da149..47fd614 100644 --- a/controllers/controllers.php +++ b/controllers/controllers.php @@ -333,3 +333,43 @@ $app->get('/auth/twitter/callback', function() use($app) { $app->redirect('/settings'); } }); + +$app->get('/auth/instagram', function() use($app) { + if($user=require_login($app, false)) { + + $instagram = instagram_client(); + + // If there is an existing Instagram auth token, check if it's valid + if($user->instagram_access_token) { + $instagram->setAccessToken($user->instagram_access_token); + $igUser = $instagram->getUser(); + + if($igUser && $igUser->meta->code == 200) { + $app->response()->body(json_encode(array( + 'result' => 'ok', + 'username' => $igUser->data->username + ))); + return; + } + } + + $app->response()->body(json_encode(array( + 'result' => 'error', + 'url' => $instagram->getLoginUrl(array('basic','likes')) + ))); + } +}); + +$app->get('/auth/instagram/callback', function() use($app) { + if($user=require_login($app)) { + $params = $app->request()->params(); + + $instagram = instagram_client(); + $data = $instagram->getOAuthToken($params['code']); + $user->instagram_access_token = $data->access_token; + $user->save(); + + $app->redirect('/settings'); + } +}); + diff --git a/lib/helpers.php b/lib/helpers.php index 010bd91..456fcfd 100644 --- a/lib/helpers.php +++ b/lib/helpers.php @@ -195,3 +195,14 @@ function relative_time($date) { } return $rel->timeAgo($date); } + +function instagram_client() { + return new Andreyco\Instagram\Client(array( + 'apiKey' => Config::$instagramClientID, + 'apiSecret' => Config::$instagramClientSecret, + 'apiCallback' => Config::$base_url . 'auth/instagram/callback', + 'scope' => array('basic','likes'), + )); +} + + diff --git a/views/settings.php b/views/settings.php index 61feefc..9860a91 100644 --- a/views/settings.php +++ b/views/settings.php @@ -10,11 +10,8 @@

Twitter

- - + -- cgit v1.2.3 From 8be498a324954f9d5792ca921b7364f53ff4085f Mon Sep 17 00:00:00 2001 From: Aaron Parecki Date: Fri, 26 Dec 2014 14:57:31 -0800 Subject: new "favorite" form with bookmarklet * disable facebook liking for now since it was getting complicated * new page for creating a favorite, can pass in a URL parameter too * bookmarklet code added to the "favorite" page --- controllers/controllers.php | 109 +++++++++++++++++++++++++++----- lib/helpers.php | 2 +- public/css/favorite.css | 2 +- views/favorite-js.php | 33 ++++++++++ views/favorite-popup.php | 50 +++++++++++++++ views/layout.php | 4 +- views/liked-js.php | 22 ------- views/new-bookmark.php | 4 +- views/new-favorite.php | 74 ++++++++++++++++++++++ views/new-post.php | 4 ++ views/partials/bookmark-bookmarklet.php | 2 +- views/partials/favorite-bookmarklet.php | 10 +++ views/settings.php | 8 ++- 13 files changed, 277 insertions(+), 47 deletions(-) create mode 100644 views/favorite-js.php create mode 100644 views/favorite-popup.php delete mode 100644 views/liked-js.php create mode 100644 views/new-favorite.php create mode 100644 views/partials/favorite-bookmarklet.php (limited to 'lib') diff --git a/controllers/controllers.php b/controllers/controllers.php index 47fd614..05b6c06 100644 --- a/controllers/controllers.php +++ b/controllers/controllers.php @@ -104,6 +104,24 @@ $app->get('/bookmark', function() use($app) { } }); +$app->get('/favorite', function() use($app) { + if($user=require_login($app)) { + $params = $app->request()->params(); + + $url = ''; + + if(array_key_exists('url', $params)) + $url = $params['url']; + + $html = render('new-favorite', array( + 'title' => 'New Favorite', + 'url' => $url, + 'token' => generate_login_token() + )); + $app->response()->body($html); + } +}); + $app->post('/prefs', function() use($app) { if($user=require_login($app)) { $params = $app->request()->params(); @@ -176,30 +194,84 @@ $app->get('/settings', function() use($app) { } }); +$app->get('/favorite-popup', function() use($app) { + if($user=require_login($app)) { + $params = $app->request()->params(); + + $html = $app->render('favorite-popup.php', array( + 'url' => $params['url'], + 'token' => $params['token'] + )); + $app->response()->body($html); + } +}); + +function create_favorite(&$user, $url) { + $micropub_request = array( + 'like-of' => $url + ); + $r = micropub_post_for_user($user, $micropub_request); + + $facebook_id = false; + $instagram_id = false; + $tweet_id = false; + + /* + // Facebook likes are posted via Javascript, so pass the FB ID to the javascript code + if(preg_match('/https?:\/\/(?:www\.)?facebook\.com\/(?:[^\/]+)\/posts\/(\d+)/', $url, $match)) { + $facebook_id = $match[1]; + } + + if(preg_match('/https?:\/\/(?:www\.)?facebook\.com\/photo\.php\?fbid=(\d+)/', $url, $match)) { + $facebook_id = $match[1]; + } + */ + + if(preg_match('/https?:\/\/(?:www\.)?instagram\.com\/p\/([^\/]+)/', $url, $match)) { + $instagram_id = $match[1]; + if($user->instagram_access_token) { + $instagram = instagram_client(); + $instagram->setAccessToken($user->instagram_access_token); + $ch = curl_init('https://api.instagram.com/v1/media/shortcode/' . $instagram_id . '?access_token=' . $user->instagram_access_token); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $result = json_decode(curl_exec($ch)); + + $result = $instagram->likeMedia($result->data->id); + } else { + // TODO: indicate that the instagram post couldn't be liked because no access token was available + } + } + + if(preg_match('/https?:\/\/(?:www\.)?twitter\.com\/[^\/]+\/status(?:es)?\/(\d+)/', $url, $match)) { + $tweet_id = $match[1]; + $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, + $user->twitter_access_token, $user->twitter_token_secret); + $result = $twitter->post('favorites/create', array( + 'id' => $tweet_id + )); + } + + return $r; +} + $app->get('/favorite.js', function() use($app) { $app->response()->header("Content-type", "text/javascript"); if($user=require_login($app, false)) { $params = $app->request()->params(); if(array_key_exists('url', $params)) { - $micropub_request = array( - 'like-of' => $params['url'] - ); - $r = micropub_post_for_user($user, $micropub_request); - } - - if(preg_match('/https?:\/\/(?:www\.)?facebook\.com\/(?:[^\/]+)\/posts\/(\d+)/', $params['url'], $match)) { - $facebook_id = $match[1]; + $r = create_favorite($user, $params['url']); + + $app->response()->body($app->render('favorite-js.php', array( + 'url' => $params['url'], + 'like_url' => $r['location'], + 'error' => $r['error'], + // 'facebook_id' => $facebook_id + ))); } else { - $facebook_id = false; + $app->response()->body('alert("no url");'); } - $app->response()->body($app->render('liked-js.php', array( - 'url' => $params['url'], - 'like_url' => $r['location'], - 'error' => $r['error'], - 'facebook_id' => $facebook_id - ))); } else { $app->response()->body('alert("invalid token");'); } @@ -236,6 +308,7 @@ $app->post('/micropub/post', function() use($app) { } }); +/* $app->post('/auth/facebook', function() use($app) { if($user=require_login($app, false)) { $params = $app->request()->params(); @@ -252,11 +325,12 @@ $app->post('/auth/facebook', function() use($app) { ))); } }); +*/ $app->post('/auth/twitter', function() use($app) { if($user=require_login($app, false)) { $params = $app->request()->params(); - // User just auth'd with facebook, store the access token + // User just auth'd with twitter, store the access token $user->twitter_access_token = $params['twitter_token']; $user->twitter_token_secret = $params['twitter_secret']; $user->save(); @@ -347,7 +421,8 @@ $app->get('/auth/instagram', function() use($app) { if($igUser && $igUser->meta->code == 200) { $app->response()->body(json_encode(array( 'result' => 'ok', - 'username' => $igUser->data->username + 'username' => $igUser->data->username, + 'url' => $instagram->getLoginUrl(array('basic','likes')) ))); return; } diff --git a/lib/helpers.php b/lib/helpers.php index 456fcfd..9993231 100644 --- a/lib/helpers.php +++ b/lib/helpers.php @@ -79,7 +79,7 @@ function micropub_post_for_user(&$user, $params) { // Check the response and look for a "Location" header containing the URL if($r['response'] && preg_match('/Location: (.+)/', $r['response'], $match)) { - $r['location'] = $match[1]; + $r['location'] = trim($match[1]); $user->micropub_success = 1; } else { $r['location'] = false; diff --git a/public/css/favorite.css b/public/css/favorite.css index a80bc3a..70a8677 100644 --- a/public/css/favorite.css +++ b/public/css/favorite.css @@ -1,6 +1,6 @@ #quill-star { - position: absolute; + position: fixed; top: 50%; left: 50%; diff --git a/views/favorite-js.php b/views/favorite-js.php new file mode 100644 index 0000000..4ce6dba --- /dev/null +++ b/views/favorite-js.php @@ -0,0 +1,33 @@ + +console.log("Favoriting URL: url ?>"); + +var css = document.createElement('link'); +css.rel="stylesheet"; +css.type="text/css"; +css.href="css/favorite.css"; +document.body.appendChild(css); + +function show_star() { + var star = document.createElement('img'); + star.id="quill-star"; + star.src="images/like_url ? 'star' : 'red-x' ?>.svg"; + star.onload=function() { + setTimeout(function(){ + + document.getElementById('quill-star').classList.add('hidden'); + var el = document.getElementById('quill-star'); + el.parentNode.removeChild(el); + if(typeof favorite_finished == "function") { + favorite_finished(); + } else { + // For now, redirect the user to the URL of their favorite so they can see it posted. + // Might want to change this later. + window.location = "like_url ?>"; + } + + }, 1200); + } + document.body.appendChild(star); +} + +show_star(); diff --git a/views/favorite-popup.php b/views/favorite-popup.php new file mode 100644 index 0000000..fecc780 --- /dev/null +++ b/views/favorite-popup.php @@ -0,0 +1,50 @@ + + + + Favoriting + + + + + + + window.quillFbInit = function() { + FB.getLoginStatus(function(response) { + + if (response.status === 'connected') { + // the user is logged in and has authenticated your + // app, and response.authResponse supplies + // the user's ID, a valid access token, a signed + // request, and the time the access token + // and signed request each expire + var uid = response.authResponse.userID; + var accessToken = response.authResponse.accessToken; + console.log(accessToken); + + FB.api("/facebook_id ?>/likes", "post", function(response){ + console.log(response); + show_star(); + }); + + } else if (response.status === 'not_authorized') { + // the user is logged in to Facebook, + // but has not authenticated your app + console.log("Logged in but not authorized"); + } else { + // the user isn't logged in to Facebook. + console.log("User isn't logged in"); + } + }); + }; + + + */ ?> + + + + \ No newline at end of file diff --git a/views/layout.php b/views/layout.php index 0c78aa7..8d7607d 100644 --- a/views/layout.php +++ b/views/layout.php @@ -33,7 +33,7 @@ @@ -64,13 +64,13 @@ if(property_exists($this, 'include_facebook')) {
  • New Post
  • Bookmark
  • +
  • Favorite
  • Docs