From 2cd148c792a47fea18d760b723d23569ae52d390 Mon Sep 17 00:00:00 2001
From: Aaron Parecki <aaron@parecki.com>
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
---
 controllers/controllers.php | 172 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 149 insertions(+), 23 deletions(-)

(limited to 'controllers/controllers.php')

diff --git a/controllers/controllers.php b/controllers/controllers.php
index 0de366b..18da149 100644
--- a/controllers/controllers.php
+++ b/controllers/controllers.php
@@ -1,6 +1,6 @@
 <?php
 
-function require_login(&$app) {
+function require_login(&$app, $redirect=true) {
   $params = $app->request()->params();
   if(array_key_exists('token', $params)) {
     try {
@@ -8,16 +8,25 @@ function require_login(&$app) {
       $_SESSION['user_id'] = $data->user_id;
       $_SESSION['me'] = $data->me;
     } catch(DomainException $e) {
-      header('X-Error: DomainException');
-      $app->redirect('/', 301);
+      if($redirect) {
+        header('X-Error: DomainException');
+        $app->redirect('/', 301);
+      } else {
+        return false;
+      }
     } catch(UnexpectedValueException $e) {
-      header('X-Error: UnexpectedValueException');
-      $app->redirect('/', 301);
+      if($redirect) {
+        header('X-Error: UnexpectedValueException');
+        $app->redirect('/', 301);
+      } else {
+        return false;
+      }
     }
   }
 
   if(!array_key_exists('user_id', $_SESSION)) {
-    $app->redirect('/');
+    if($redirect)
+      $app->redirect('/');
     return false;
   } else {
     return ORM::for_table('users')->find_one($_SESSION['user_id']);
@@ -160,6 +169,42 @@ $app->get('/add-to-home', function() use($app) {
   }
 });
 
+$app->get('/settings', function() use($app) {
+  if($user=require_login($app)) {
+    $html = render('settings', array('title' => 'Settings', 'include_facebook' => true));
+    $app->response()->body($html);
+  }
+});
+
+$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];
+    } else {
+      $facebook_id = false;
+    }
+
+    $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");');
+  }
+});
+
 $app->get('/micropub/syndications', function() use($app) {
   if($user=require_login($app)) {
     $data = get_syndication_targets($user);
@@ -179,31 +224,112 @@ $app->post('/micropub/post', function() use($app) {
       return $v !== '';
     });
 
-    // Now send to the micropub endpoint
-    $r = micropub_post($user->micropub_endpoint, $params, $user->micropub_access_token);
-    $request = $r['request'];
-    $response = $r['response'];
+    $r = micropub_post_for_user($user, $params);
+
+    $app->response()->body(json_encode(array(
+      'request' => htmlspecialchars($r['request']),
+      'response' => htmlspecialchars($r['response']),
+      'location' => $r['location'],
+      'error' => $r['error'],
+      'curlinfo' => $r['curlinfo']
+    )));
+  }
+});
+
+$app->post('/auth/facebook', function() use($app) {
+  if($user=require_login($app, false)) {
+    $params = $app->request()->params();
+    // User just auth'd with facebook, store the access token
+    $user->facebook_access_token = $params['fb_token'];
+    $user->save();
+
+    $app->response()->body(json_encode(array(
+      'result' => 'ok'
+    )));
+  } else {
+    $app->response()->body(json_encode(array(
+      'result' => 'error'
+    )));
+  }
+});
+
+$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->twitter_access_token = $params['twitter_token'];
+    $user->twitter_token_secret = $params['twitter_secret'];
+    $user->save();
+
+    $app->response()->body(json_encode(array(
+      'result' => 'ok'
+    )));
+  } else {
+    $app->response()->body(json_encode(array(
+      'result' => 'error'
+    )));
+  }
+});
+
+function getTwitterLoginURL(&$twitter) {
+  $request_token = $twitter->getRequestToken(Config::$base_url . 'auth/twitter/callback');
+  $_SESSION['twitter_auth'] = $request_token;
+  return $twitter->getAuthorizeURL($request_token['oauth_token']);
+}
+
+$app->get('/auth/twitter', function() use($app) {
+  $params = $app->request()->params();
+  if($user=require_login($app, false)) {
 
-    $user->last_micropub_response = json_encode($r);
-    $user->last_micropub_response_date = date('Y-m-d H:i:s');
+    // If there is an existing Twitter token, check if it is valid
+    // Otherwise, generate a Twitter login link
+    $twitter_login_url = false;
+    $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, 
+      $user->twitter_access_token, $user->twitter_token_secret);
 
-    // Check the response and look for a "Location" header containing the URL
-    if($response && preg_match('/Location: (.+)/', $response, $match)) {
-      $location = $match[1];
-      $user->micropub_success = 1;
+    if(array_key_exists('login', $params)) {
+      $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret);
+      $twitter_login_url = getTwitterLoginURL($twitter);
     } else {
-      $location = false;
+      if($user->twitter_access_token) {
+        if ($twitter->get('account/verify_credentials')) {
+          $app->response()->body(json_encode(array(
+            'result' => 'ok'
+          )));
+          return;
+        } else {
+          // If the existing twitter token is not valid, generate a login link
+          $twitter_login_url = getTwitterLoginURL($twitter);
+        }
+      } else {
+        $twitter_login_url = getTwitterLoginURL($twitter);
+      }
     }
 
-    $user->save();
+    $app->response()->body(json_encode(array(
+      'url' => $twitter_login_url
+    )));
 
+  } else {
     $app->response()->body(json_encode(array(
-      'request' => htmlspecialchars($request),
-      'response' => htmlspecialchars($response),
-      'location' => $location,
-      'error' => $r['error'],
-      'curlinfo' => $r['curlinfo']
+      'result' => 'error'
     )));
   }
 });
 
+$app->get('/auth/twitter/callback', function() use($app) {
+  if($user=require_login($app)) {
+    $params = $app->request()->params();
+
+    $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, 
+      $_SESSION['twitter_auth']['oauth_token'], $_SESSION['twitter_auth']['oauth_token_secret']);
+    $credentials = $twitter->getAccessToken($params['oauth_verifier']);
+
+    $user->twitter_access_token = $credentials['oauth_token'];
+    $user->twitter_token_secret = $credentials['oauth_token_secret'];
+    $user->twitter_username = $credentials['screen_name'];
+    $user->save();
+
+    $app->redirect('/settings');
+  }
+});
-- 
cgit v1.2.3


From 430609b9005bb93ce2c6b21405cea0ede2b17a9d Mon Sep 17 00:00:00 2001
From: Aaron Parecki <aaron@parecki.com>
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 'controllers/controllers.php')

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 @@
   <h3>Twitter</h3>
   <input type="button" id="twitter-button" value="Checking" class="btn">
 
-
-  <!--
   <h3>Instagram</h3>
-
-  -->
+  <input type="button" id="instagram-button" value="Checking" class="btn">
 
 </div>
 <script>
@@ -60,6 +57,10 @@ function save_facebook_token(token) {
 }
 
 $(function(){
+  $("#facebook-button").click(function(){
+    FB.login(window.quillHandleFbLogin, {scope:'publish_actions'});
+  });
+
   $.getJSON("/auth/twitter", function(data){
     // Check if we're already authorized with twitter
     if(data && data.result == 'ok') {
@@ -81,8 +82,26 @@ $(function(){
     }
   });
 
-  $("#facebook-button").click(function(){
-    FB.login(window.quillHandleFbLogin, {scope:'publish_actions'});
+  $.getJSON("/auth/instagram", function(data){
+    // Check if we're already authorized with Instagram
+    if(data && data.result == 'ok') {
+      $("#instagram-button").val("Connected").addClass("btn-success");
+    } else if(data && data.url) {
+      $("#instagram-button").val("Sign In").data("url", data.url).addClass("btn-warning");
+    } else {
+      $("#instagram-button").val("Error").addClass("btn-danger");
+    }
+  });
+
+  $("#instagram-button").click(function(){
+    if($(this).data('url')) {
+      window.location = $(this).data('url');
+    } else {
+      $.getJSON("/auth/instagram", {login: 1}, function(data){
+        window.location = data.url;
+      });
+    }
   });
+
 });
 </script>
-- 
cgit v1.2.3


From 8be498a324954f9d5792ca921b7364f53ff4085f Mon Sep 17 00:00:00 2001
From: Aaron Parecki <aaron@parecki.com>
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 'controllers/controllers.php')

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: <?= $this->url ?>");
+
+var css = document.createElement('link');
+css.rel="stylesheet";
+css.type="text/css";
+css.href="<?= Config::$base_url ?>css/favorite.css";
+document.body.appendChild(css);
+
+function show_star() {
+  var star = document.createElement('img');
+  star.id="quill-star";
+  star.src="<?= Config::$base_url ?>images/<?= $this->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 = "<?= $this->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 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <title>Favoriting</title>
+  </head>
+  <body>
+    <script>
+    function favorite_finished() {
+      self.close();
+    }
+    </script>
+    <script src="/favorite.js?url=<?= urlencode($this->url) ?>&amp;token=<?= $this->token ?>"></script>
+
+    <?php /*
+    <script>
+    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("/<?= $this->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");
+        }
+      });
+    };
+    </script>
+    <?= partial('partials/fb-script') ?>
+    */ ?>
+
+
+  </body>
+</html>
\ 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 @@
 <body role="document">
 <?php 
 if(property_exists($this, 'include_facebook')) {
-  echo partial('partials/fb-script');
+  # echo partial('partials/fb-script');
 }
 ?>
 
@@ -64,13 +64,13 @@ if(property_exists($this, 'include_facebook')) {
         <? if(session('me')) { ?>
           <li><a href="/new">New Post</a></li>
           <li><a href="/bookmark">Bookmark</a></li>
+          <li><a href="/favorite">Favorite</a></li>
         <? } ?>
 
         <li><a href="/docs">Docs</a></li>
       </ul>
       <ul class="nav navbar-nav navbar-right">
         <? if(session('me')) { ?>
-          <li><a href="/add-to-home?start">Add to Home Screen</a></li>
           <li><a href="/settings"><?= preg_replace(array('/https?:\/\//','/\/$/'),'',session('me')) ?></a></li>
           <li><a href="/signout">Sign Out</a></li>
         <? } else if(property_exists($this, 'authorizing')) { ?>
diff --git a/views/liked-js.php b/views/liked-js.php
deleted file mode 100644
index 80b62ac..0000000
--- a/views/liked-js.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?= $this->facebook_id ? partial('partials/fb-script') : '' ?>
-
-console.log("Favoriting URL: <?= $this->url ?>");
-
-var star = document.createElement('img');
-star.id="quill-star";
-star.src="http://quill.dev/images/<?= $this->like_url ? 'star' : 'red-x' ?>.svg";
-document.body.appendChild(star);
-
-var css = document.createElement('link');
-css.rel="stylesheet";
-css.type="text/css";
-css.href="http://quill.dev/css/favorite.css";
-document.body.appendChild(css);
-
-setTimeout(function(){
-  
-  document.getElementById('quill-star').classList.add('hidden');
-  var el = document.getElementById('quill-star');
-  el.parentNode.removeChild(el);
-
-}, 1200);
diff --git a/views/new-bookmark.php b/views/new-bookmark.php
index d4100ba..fac2c95 100644
--- a/views/new-bookmark.php
+++ b/views/new-bookmark.php
@@ -87,9 +87,9 @@ $(function(){
 
       if(response.location != false) {
 
-        // $("#test_success").removeClass('hidden');
+        $("#test_success").removeClass('hidden');
         $("#test_error").addClass('hidden');
-        // $("#post_href").attr("href", response.location);
+        $("#post_href").attr("href", response.location);
 
         // $("#note_bookmark").val("");
         // $("#note_content").val("");
diff --git a/views/new-favorite.php b/views/new-favorite.php
new file mode 100644
index 0000000..7b19350
--- /dev/null
+++ b/views/new-favorite.php
@@ -0,0 +1,74 @@
+  <div class="narrow">
+    <?= partial('partials/header') ?>
+
+      <div style="clear: both;">
+        <div class="alert alert-success hidden" id="test_success"><strong>Success! We found a Location header in the response!</strong><br>Your post should be on your website now!<br><a href="" id="post_href">View your post</a></div>
+        <div class="alert alert-danger hidden" id="test_error"><strong>Your endpoint did not return a Location header.</strong><br>See <a href="/creating-a-micropub-endpoint">Creating a Micropub Endpoint</a> for more information.</div>
+      </div>
+
+      <form role="form" style="margin-top: 20px;" id="note_form">
+
+        <div class="form-group">
+          <label for="note_url">URL to Favorite (<code>like-of</code>)</label>
+          <input type="text" id="note_url" value="<?= $this->url ?>" class="form-control">
+        </div>
+
+        <div style="float: right; margin-top: 6px;">
+          <button class="btn btn-success" id="btn_post">Post</button>
+        </div>
+
+      </form>
+
+      <div style="clear: both;"></div>
+
+      <hr>
+      <div style="text-align: right;">
+        Bookmarklet: <a href="javascript:<?= js_bookmarklet('partials/favorite-bookmarklet', $this) ?>" class="btn btn-default btn-xs">favorite</a>
+      </div>
+
+  </div>
+
+<script>
+$(function(){
+
+  // ctrl-s to save
+  $(window).on('keydown', function(e){ 
+    if(e.keyCode == 83 && e.ctrlKey){
+      $("#btn_post").click();
+    } 
+  });
+
+  $("#btn_post").click(function(){
+
+    var syndications = [];
+    $("#syndication-container button.btn-info").each(function(i,btn){
+      syndications.push($(btn).data('syndication'));
+    });
+
+    $.post("/favorite", {
+      url: $("#note_url").val()
+    }, function(data){
+      var response = JSON.parse(data);
+
+      if(response.location != false) {
+
+        $("#test_success").removeClass('hidden');
+        $("#test_error").addClass('hidden');
+        $("#post_href").attr("href", response.location);
+
+        window.location = response.location;
+      } else {
+        $("#test_success").addClass('hidden');
+        $("#test_error").removeClass('hidden');
+      }
+
+    });
+    return false;
+  });
+
+  bind_syndication_buttons();
+});
+
+<?= partial('partials/syndication-js') ?>
+
+</script>
diff --git a/views/new-post.php b/views/new-post.php
index fa7b9bc..12c01f9 100644
--- a/views/new-post.php
+++ b/views/new-post.php
@@ -97,6 +97,10 @@
         </table>
       </div>
 
+      <hr>
+      <div style="text-align: right;">
+        <a href="/add-to-home?start">Add to Home Screen</a>
+      </div>
   </div>
 
 <script>
diff --git a/views/partials/bookmark-bookmarklet.php b/views/partials/bookmark-bookmarklet.php
index d47a728..0dfd916 100644
--- a/views/partials/bookmark-bookmarklet.php
+++ b/views/partials/bookmark-bookmarklet.php
@@ -1,4 +1,4 @@
-javascript:(function(){
+(function(){
   var t;try{t=((window.getSelection&&window.getSelection())||(document.getSelection&&document.getSelection())||(document.selection&&document.selection.createRange&&document.selection.createRange().text));}catch(e){t="";};
   window.location="<?= Config::$base_url ?>bookmark?url="+encodeURIComponent(window.location.href)+"&content="+encodeURIComponent((t == '' ? '' : '"'+t+'"'))+"&name="+encodeURIComponent(document.title)+"&token=<?= $this->token ?>";
 })();
diff --git a/views/partials/favorite-bookmarklet.php b/views/partials/favorite-bookmarklet.php
new file mode 100644
index 0000000..e4d27bd
--- /dev/null
+++ b/views/partials/favorite-bookmarklet.php
@@ -0,0 +1,10 @@
+var quill_popup=function(){ 
+  window.open(document.getElementById('quill-script').src.replace('favorite.js?','favorite-popup?'),'quill-like', 'status=no,directories=no,location=no,resizable=no,menubar=no,width=300,height=200,toolbar=no'); 
+}; 
+(function(){ 
+  var quill=document.createElement('script'); 
+  quill.src='<?= Config::$base_url ?>favorite.js?url='+encodeURIComponent(window.location)+'&token=<?= $this->token ?>'; 
+  quill.setAttribute('id','quill-script'); 
+  quill.setAttribute('onerror', 'quill_popup()'); 
+  document.body.appendChild(quill); 
+})();
\ No newline at end of file
diff --git a/views/settings.php b/views/settings.php
index 9860a91..831528d 100644
--- a/views/settings.php
+++ b/views/settings.php
@@ -4,8 +4,10 @@
   <h2>Signed In As</h2>
   <code><?= session('me') ?></code>
 
+  <!-- 
   <h3>Facebook</h3>
   <input type="button" id="facebook-button" value="Checking" class="btn">
+  -->
 
   <h3>Twitter</h3>
   <input type="button" id="twitter-button" value="Checking" class="btn">
@@ -15,6 +17,7 @@
 
 </div>
 <script>
+/*
 window.quillFbInit = function() {
   FB.getLoginStatus(function(response) {
     if (response.status === 'connected') {
@@ -55,11 +58,14 @@ function save_facebook_token(token) {
     $("#facebook-button").val("Connected").addClass("btn-success");
   });
 }
+*/
 
 $(function(){
+  /*
   $("#facebook-button").click(function(){
-    FB.login(window.quillHandleFbLogin, {scope:'publish_actions'});
+    FB.login(window.quillHandleFbLogin, {scope:'publish_actions,user_likes'});
   });
+  */
 
   $.getJSON("/auth/twitter", function(data){
     // Check if we're already authorized with twitter
-- 
cgit v1.2.3


From 875a9fd90944eef8bf94f24594c80b9433ec824d Mon Sep 17 00:00:00 2001
From: Aaron Parecki <aaron@parecki.com>
Date: Fri, 26 Dec 2014 15:02:54 -0800
Subject: actually post likes from the form

---
 controllers/controllers.php | 13 +++++++++++++
 1 file changed, 13 insertions(+)

(limited to 'controllers/controllers.php')

diff --git a/controllers/controllers.php b/controllers/controllers.php
index 05b6c06..b983675 100644
--- a/controllers/controllers.php
+++ b/controllers/controllers.php
@@ -277,6 +277,19 @@ $app->get('/favorite.js', function() use($app) {
   }
 });
 
+$app->post('/favorite', function() use($app) {
+  if($user=require_login($app)) {
+    $params = $app->request()->params();
+
+    $r = create_favorite($user, $params['url']);
+
+    $app->response()->body(json_encode(array(
+      'location' => $r['location'],
+      'error' => $r['error']
+    )));
+  }
+});
+
 $app->get('/micropub/syndications', function() use($app) {
   if($user=require_login($app)) {
     $data = get_syndication_targets($user);
-- 
cgit v1.2.3