summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--composer.json4
-rw-r--r--composer.lock110
-rw-r--r--controllers/controllers.php298
-rw-r--r--lib/config.template.php7
-rw-r--r--lib/helpers.php31
-rw-r--r--public/css/favorite.css17
-rw-r--r--public/images/quill-logo-1024.pngbin0 -> 38419 bytes
-rw-r--r--public/images/red-x.svg8
-rw-r--r--public/images/star.svg8
-rw-r--r--public/js/fav.js23
-rw-r--r--views/favorite-js.php33
-rw-r--r--views/favorite-popup.php50
-rw-r--r--views/layout.php10
-rw-r--r--views/new-bookmark.php4
-rw-r--r--views/new-favorite.php74
-rw-r--r--views/new-post.php4
-rw-r--r--views/partials/bookmark-bookmarklet.php2
-rw-r--r--views/partials/favorite-bookmarklet.php10
-rw-r--r--views/partials/fb-script.php20
-rw-r--r--views/settings.php113
20 files changed, 779 insertions, 47 deletions
diff --git a/composer.json b/composer.json
index 196f5a9..cf2f57e 100644
--- a/composer.json
+++ b/composer.json
@@ -8,7 +8,9 @@
"indieweb/date-formatter": "0.1.*",
"indieauth/client": "0.1.3",
"mpratt/relativetime": ">=1.0",
- "firebase/php-jwt": "dev-master"
+ "firebase/php-jwt": "dev-master",
+ "ruudk/twitter-oauth": "dev-master",
+ "andreyco/instagram": "3.*"
},
"autoload": {
"files": [
diff --git a/composer.lock b/composer.lock
index a4e4ad6..eb3dfc1 100644
--- a/composer.lock
+++ b/composer.lock
@@ -3,21 +3,64 @@
"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": "3e034e0a6a692d5bbfecfdc95ee69db2",
+ "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",
"target-dir": "Firebase/PHP-JWT",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
- "reference": "53669d621149e49c2a428722a62acfef3342c260"
+ "reference": "83b8899cb73d85d648af93f37ec0ac89f4a5bbae"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/firebase/php-jwt/zipball/53669d621149e49c2a428722a62acfef3342c260",
- "reference": "53669d621149e49c2a428722a62acfef3342c260",
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b8899cb73d85d648af93f37ec0ac89f4a5bbae",
+ "reference": "83b8899cb73d85d648af93f37ec0ac89f4a5bbae",
"shasum": ""
},
"require": {
@@ -26,7 +69,8 @@
"type": "library",
"autoload": {
"classmap": [
- "Authentication/"
+ "Authentication/",
+ "Exceptions/"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -47,7 +91,7 @@
],
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
"homepage": "https://github.com/firebase/php-jwt",
- "time": "2013-09-03 20:55:18"
+ "time": "2014-11-18 17:58:25"
},
{
"name": "indieauth/client",
@@ -368,6 +412,41 @@
"time": "2013-09-23 22:51:48"
},
{
+ "name": "ruudk/twitter-oauth",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ruudk/twitteroauth.git",
+ "reference": "7f5a94eaa1572ddbc7f0a32ba3b865b8ac23712a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ruudk/twitteroauth/zipball/7f5a94eaa1572ddbc7f0a32ba3b865b8ac23712a",
+ "reference": "7f5a94eaa1572ddbc7f0a32ba3b865b8ac23712a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "authors": [
+ {
+ "name": "Ruud Kamphuis",
+ "email": "ruud@1plus1media.nl",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP 5.3 version of abraham/twitteroauth",
+ "homepage": "http://github.com/ruudk/twitteroauth",
+ "time": "2014-06-10 18:17:38"
+ },
+ {
"name": "saltybeagle/savant3",
"version": "dev-master",
"source": {
@@ -446,21 +525,14 @@
"time": "2012-12-13 02:15:50"
}
],
- "packages-dev": [
-
- ],
- "aliases": [
-
- ],
+ "packages-dev": [],
+ "aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"saltybeagle/savant3": 20,
- "firebase/php-jwt": 20
+ "firebase/php-jwt": 20,
+ "ruudk/twitter-oauth": 20
},
- "platform": [
-
- ],
- "platform-dev": [
-
- ]
+ "platform": [],
+ "platform-dev": []
}
diff --git a/controllers/controllers.php b/controllers/controllers.php
index b6bb30a..0fef6df 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']);
@@ -95,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();
@@ -165,6 +192,109 @@ $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-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)) {
+ $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 {
+ $app->response()->body('alert("no url");');
+ }
+
+ } else {
+ $app->response()->body('alert("invalid token");');
+ }
+});
+
+$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);
@@ -184,31 +314,155 @@ $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);
- $user->last_micropub_response = json_encode($r);
- $user->last_micropub_response_date = date('Y-m-d H:i:s');
+ $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 twitter, store the access token
+ $user->twitter_access_token = $params['twitter_token'];
+ $user->twitter_token_secret = $params['twitter_secret'];
+ $user->save();
- // 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;
+ $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)) {
+
+ // 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);
+
+ 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);
+ }
}
+ $app->response()->body(json_encode(array(
+ 'url' => $twitter_login_url
+ )));
+
+ } else {
+ $app->response()->body(json_encode(array(
+ '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');
+ }
+});
+
+$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,
+ 'url' => $instagram->getLoginUrl(array('basic','likes'))
+ )));
+ return;
+ }
+ }
+
$app->response()->body(json_encode(array(
- 'request' => htmlspecialchars($request),
- 'response' => htmlspecialchars($response),
- 'location' => $location,
- 'error' => $r['error'],
- 'curlinfo' => $r['curlinfo']
+ '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/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..9993231 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'] = trim($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);
@@ -175,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/public/css/favorite.css b/public/css/favorite.css
new file mode 100644
index 0000000..70a8677
--- /dev/null
+++ b/public/css/favorite.css
@@ -0,0 +1,17 @@
+
+#quill-star {
+ position: fixed;
+
+ top: 50%;
+ left: 50%;
+ margin-top: -100px;
+ margin-left: -100px;
+
+ width: 200px;
+ height: 200px;
+
+}
+
+#quill-star.hidden {
+ display: none;
+}
diff --git a/public/images/quill-logo-1024.png b/public/images/quill-logo-1024.png
new file mode 100644
index 0000000..b6bc513
--- /dev/null
+++ b/public/images/quill-logo-1024.png
Binary files differ
diff --git a/public/images/red-x.svg b/public/images/red-x.svg
new file mode 100644
index 0000000..041364d
--- /dev/null
+++ b/public/images/red-x.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="108px" height="108px" viewBox="0 0 108 108" enable-background="new 0 0 108 108" xml:space="preserve">
+<line fill="none" stroke="#972D2C" stroke-width="20" stroke-miterlimit="10" x1="8.788" y1="8.308" x2="99.81" y2="99.329"/>
+<line fill="none" stroke="#972D2C" stroke-width="20" stroke-miterlimit="10" x1="99.81" y1="8.308" x2="8.788" y2="99.329"/>
+</svg>
diff --git a/public/images/star.svg b/public/images/star.svg
new file mode 100644
index 0000000..5970e33
--- /dev/null
+++ b/public/images/star.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="108px" height="108px" viewBox="0 0 108 108" enable-background="new 0 0 108 108" xml:space="preserve">
+<polygon fill="#FCB117" points="54.306,4.549 70.476,37.312 106.633,42.566 80.47,68.069 86.646,104.079 54.306,87.077
+ 21.967,104.079 28.143,68.069 1.98,42.566 38.136,37.312 "/>
+</svg>
diff --git a/public/js/fav.js b/public/js/fav.js
new file mode 100644
index 0000000..4288329
--- /dev/null
+++ b/public/js/fav.js
@@ -0,0 +1,23 @@
+console.log("Favoriting with token: " + quill_token);
+
+var http = new XMLHttpRequest();
+var params = "like-of=" + encodeURIComponent(window.location) + "&token=" + quill_token;
+
+http.open("POST", "http://quill.dev/favorite", true);
+http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+http.onreadystatechange = function() {//Call a function when the state changes.
+ console.log(http);
+ if(http.readyState == 4 && http.status == 200) {
+ alert(http.responseText);
+ }
+}
+http.send(params);
+
+/*
+
+(function(){var el=document.createElement('input'); el.type="hidden"; el.id="quill_token"; el.value="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjciLCJtZSI6Imh0dHA6XC9cL2Fhcm9ucGFyZWNraS5jb20iLCJjcmVhdGVkX2F0IjoxNDEwMTE3NTM5fQ.ifp1VIgCTz9NPtMTlTLPBXAGSxHwpGS5tLPhXGxrjNk"; document.body.appendChild(el); document.body.appendChild(document.createElement('script')).src='http://quill.dev/js/fav.js';})();
+
+(function(){document.body.appendChild(document.createElement('script')).src='http://quill.dev/favorite.js?url='+encodeURIComponent(window.location)+'&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMSIsIm1lIjoiaHR0cDpcL1wvcGsuZGV2XC8iLCJjcmVhdGVkX2F0IjoxNDE5MDM2NzAzfQ.AgJ5xyviiBzWOvQO0je0Bdi3BUpKJ4CLJnx8GIm-0OI';})();
+
+*/ \ No newline at end of file
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 531dec9..8d7607d 100644
--- a/views/layout.php
+++ b/views/layout.php
@@ -31,6 +31,12 @@
</head>
<body role="document">
+<?php
+if(property_exists($this, 'include_facebook')) {
+ # echo partial('partials/fb-script');
+}
+?>
+
<script type="text/javascript">
var _gaq = _gaq || [];
@@ -58,14 +64,14 @@
<? 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><span class="navbar-text"><?= preg_replace('/https?:\/\//','',session('me')) ?></span></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')) { ?>
<li class="navbar-text"><?= $this->authorizing ?></li>
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/partials/fb-script.php b/views/partials/fb-script.php
new file mode 100644
index 0000000..ce5b96a
--- /dev/null
+++ b/views/partials/fb-script.php
@@ -0,0 +1,20 @@
+<script>
+ window.fbAsyncInit = function() {
+ FB.init({
+ appId : '<?= Config::$fbClientID ?>',
+ xfbml : true,
+ version : 'v2.2'
+ });
+ if(window.quillFbInit) {
+ window.quillFbInit();
+ }
+ };
+
+ (function(d, s, id){
+ var js, fjs = d.getElementsByTagName(s)[0];
+ if (d.getElementById(id)) {return;}
+ js = d.createElement(s); js.id = id;
+ js.src = "//connect.facebook.net/en_US/sdk.js";
+ fjs.parentNode.insertBefore(js, fjs);
+ }(document, 'script', 'facebook-jssdk'));
+</script> \ No newline at end of file
diff --git a/views/settings.php b/views/settings.php
new file mode 100644
index 0000000..831528d
--- /dev/null
+++ b/views/settings.php
@@ -0,0 +1,113 @@
+<div class="narrow">
+ <?= partial('partials/header') ?>
+
+ <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">
+
+ <h3>Instagram</h3>
+ <input type="button" id="instagram-button" value="Checking" class="btn">
+
+</div>
+<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;
+
+ save_facebook_token(response.authResponse.accessToken);
+
+ } 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");
+
+ $("#facebook-button").val("Sign In").addClass("btn-warning");
+
+ } else {
+ // the user isn't logged in to Facebook.
+ console.log("User isn't logged in");
+
+ $("#facebook-button").val("Sign In").addClass("btn-warning");
+ }
+ });
+};
+window.quillHandleFbLogin = function(response) {
+ save_facebook_token(response.authResponse.accessToken);
+};
+
+function save_facebook_token(token) {
+ console.log("Authed with token: " + token);
+ $.post('/auth/facebook', {
+ fb_token: token
+ }, function(data){
+ $("#facebook-button").val("Connected").addClass("btn-success");
+ });
+}
+*/
+
+$(function(){
+ /*
+ $("#facebook-button").click(function(){
+ FB.login(window.quillHandleFbLogin, {scope:'publish_actions,user_likes'});
+ });
+ */
+
+ $.getJSON("/auth/twitter", function(data){
+ // Check if we're already authorized with twitter
+ if(data && data.result == 'ok') {
+ $("#twitter-button").val("Connected").addClass("btn-success");
+ } else if(data && data.url) {
+ $("#twitter-button").val("Sign In").data("url", data.url).addClass("btn-warning");
+ } else {
+ $("#twitter-button").val("Error").addClass("btn-danger");
+ }
+ });
+
+ $("#twitter-button").click(function(){
+ if($(this).data('url')) {
+ window.location = $(this).data('url');
+ } else {
+ $.getJSON("/auth/twitter", {login: 1}, function(data){
+ window.location = data.url;
+ });
+ }
+ });
+
+ $.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>