diff --git a/app/event.php b/app/event.php
index ec74f1a..774b390 100644
--- a/app/event.php
+++ b/app/event.php
@@ -36,6 +36,12 @@ public static function getEvent($id)
$all['results'] = result::getResultsForEvent($id);
$all['routes'] = route::getRoutesForEvent($id);
$all['API version'] = RG2VERSION;
+ if (defined('STRAVA_SECRET')){
+ $all['strava'] = 'true';
+ } else {
+ $all['strava'] = 'false';
+ }
+
$output = json_encode($all);
@file_put_contents(CACHE_DIRECTORY."all_".$id.".json", $output);
}
diff --git a/app/strava.php b/app/strava.php
new file mode 100644
index 0000000..b15a7d8
--- /dev/null
+++ b/app/strava.php
@@ -0,0 +1,84 @@
+access_token;
+
+ // just echo the token, don't get activities
+ //echo "{\"access_token\":" .$access_token. "}";
+
+ //get latest strava activities
+ $activities = strava::getActivities($access_token);
+
+ echo $activities;
+
+ }
+
+ public static function getToken($code)
+ {
+ $url = 'https://www.strava.com/api/v3/oauth/token';
+ $data = array('client_id' => STRAVA_CLIENT, 'client_secret' => STRAVA_SECRET,
+ 'code' => $code, 'grant_type' => 'authorization_code');
+
+ // use key 'http' even if you send the request to https://...
+ $options = array(
+ 'http' => array(
+ 'header' => "Content-type: application/x-www-form-urlencoded\r\n",
+ 'method' => 'POST',
+ 'content' => http_build_query($data)
+ )
+ );
+ $context = stream_context_create($options);
+ $result = file_get_contents($url, false, $context);
+ if ($result === FALSE) { /* Handle error */ }
+ return $result;
+ }
+
+ public static function getActivities($token)
+ {
+ $url = 'https://www.strava.com/api/v3/athlete/activities';
+
+ // use key 'http' even if you send the request to https://...
+ $options = array(
+ 'http' => array(
+ 'header' => "Authorization: Bearer " . $token,
+ 'method' => 'GET'
+ )
+ );
+ $context = stream_context_create($options);
+ $activities = file_get_contents($url, false, $context);
+ if ($activities === FALSE) { /* Handle error */ };
+
+ $result = "{\"access_token\":\"" .$token. "\", \"activities\":" .$activities."}";
+
+ return $result;
+ }
+
+ public static function getActivityStream($data){
+
+ list($activity, $token) = explode('|', $data);
+
+ $url = 'https://www.strava.com/api/v3/activities/'. $activity . '/streams?keys=latlng,time';
+
+ // use key 'http' even if you send the request to https://...
+ $options = array(
+ 'http' => array(
+ 'header' => "Authorization: Bearer " . $token,
+ 'method' => 'GET'
+ )
+ );
+ $context = stream_context_create($options);
+ $stream = file_get_contents($url, false, $context);
+ if ($stream === FALSE) { /* Handle error */ };
+
+ return $stream;
+ }
+
+}
\ No newline at end of file
diff --git a/html/infopanel.html b/html/infopanel.html
index 66996f1..1e25d82 100644
--- a/html/infopanel.html
+++ b/html/infopanel.html
@@ -75,6 +75,10 @@
diff --git a/js/draw.js b/js/draw.js
index ff0f24b..62da373 100644
--- a/js/draw.js
+++ b/js/draw.js
@@ -28,6 +28,10 @@
this.gpstrack.uploadGPS(evt);
},
+ uploadStrava : function (evt) {
+ this.gpstrack.uploadStrava(evt);
+ },
+
getControlXY : function () {
return {x: this.controlx, y: this.controly};
},
@@ -341,6 +345,7 @@
$("#btn-three-seconds").button('enable');
// setting value to null allows you to open the same file again if needed
$("#rg2-load-gps-file").val(null).button('enable');
+ $("#btn-get-strava").button('enable');
rg2.redraw(false);
},
diff --git a/js/gpstrack.js b/js/gpstrack.js
index 12db5fd..7ba54aa 100644
--- a/js/gpstrack.js
+++ b/js/gpstrack.js
@@ -119,6 +119,31 @@
}
}
},
+
+ uploadStrava : function(json){
+ for (i=0; i < json.data.length; i++){
+
+ const d = json.data[i];
+
+ if (d.type === 'latlng'){
+
+ for (l=0; l < d.data.length; l++){
+ const lat = d.data[l][0];
+ const lon = d.data[l][1];
+ this.lat.push(lat);
+ this.lon.push(lon);
+ };
+
+ } else if (d.type === 'time'){
+
+ for (t=0; t < d.data.length; t++){
+ const tm = d.data[t]
+ this.routeData.time.push(tm)
+ };
+ }
+ };
+ this.processGPSTrack();
+ },
getStartOffset : function (timestring) {
var secs;
diff --git a/js/rg2getjson.js b/js/rg2getjson.js
index 9b0c70e..9c0f4ec 100644
--- a/js/rg2getjson.js
+++ b/js/rg2getjson.js
@@ -127,6 +127,9 @@
rg2.courses.generateControlList(rg2.controls);
$("#btn-toggle-controls").show();
$("#btn-toggle-names").show();
+ if (json.data.strava ==='false'){
+ $("#btn-get-strava").hide();
+ }
processResults(json);
processGPSTracks(json);
rg2.eventLoaded();
diff --git a/js/rg2ui.js b/js/rg2ui.js
index 45975cc..48af2e9 100644
--- a/js/rg2ui.js
+++ b/js/rg2ui.js
@@ -145,6 +145,7 @@
$("#btn-reset-drawing").button().button("disable").click(function () {
rg2.drawing.resetDrawing();
});
+ $("#btn-get-strava").button().button("disable");
$("#btn-save-gps-route").button().button("disable").click(function () {
rg2.drawing.saveGPSRoute();
});
@@ -663,6 +664,34 @@
$("#rg2-load-gps-file").change(function (evt) {
rg2.drawing.uploadGPS(evt);
});
+
+ $("#btn-get-strava").click(function(){
+ //open oauth popup. return list of latest activities.
+ rg2.utils.oauthpopup({
+ path: 'https://www.strava.com/oauth/authorize?client_id=65468&response_type=code&redirect_uri='+window.location.protocol+'//'+window.location.hostname+'/rg2/rg2api.php&approval_prompt=force&scope=activity:read_all',
+ callback: function(activities){
+
+ //parse the returned json
+ var activ = JSON.parse(activities);
+ var act = activ.activities;
+ var token = activ.access_token;
+
+ //reset div to empty
+ document.getElementById('strava-activities').innerHTML = '';
+ //disable load button
+ $("#btn-get-strava").button("disable");
+
+ //add current activities to div so user can select one
+ //limit to 10
+ for (var i=0; i<10; i++){
+ var a = act[i];
+ var activityId = a.id.toString()
+ rg2.utils.addStravaActivitySelector('strava-activities', activityId, a.name, token, a.type, a.start_date_local);
+ }
+ }
+ });
+ });
+
},
configureUI: function () {
diff --git a/js/utils.js b/js/utils.js
index 5e3f252..39d0fde 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -2,6 +2,101 @@
/*global rg2Config:false */
(function () {
var utils = {
+
+ oauthpopup : function (options){
+ // Open another window for oauth authorisation. Pass token back to main window when successful.
+ options.windowName = options.windowName || 'ConnectWithOAuth'; // should not include space for IE
+ options.windowOptions = options.windowOptions || 'location=0,status=0,width=800,height=400';
+ options.callback = options.callback || function(){ window.location.reload(); };
+ var that = this;
+ console.log(options.path);
+ that._oauthWindow = window.open(options.path, options.windowName, options.windowOptions);
+ that._oauthInterval = window.setInterval(function(){
+
+ var activities = '';
+
+ if (that._oauthWindow.document.body.innerHTML.startsWith('{"access_token":')){
+ activities = that._oauthWindow.document.body.innerHTML;
+ that._oauthWindow.close();
+ }
+
+ if (that._oauthWindow.closed) {
+ window.clearInterval(that._oauthInterval);
+ options.callback(activities);
+ }
+ }, 1000);
+ },
+
+ addStravaActivitySelector: function (elementId, activityId, name, token, type, dt){
+
+ //Reformat string as date
+ dat = dt.substring(0,10)+ " "+ dt.substring(11,16)
+
+ //create button elements
+ tr = document.getElementById(elementId).insertRow();
+
+ var td = tr.insertCell();
+
+ var actTitle = document.createElement("span");
+ actTitle.setAttribute("id", "act-title");
+ actTitle.innerText = name;
+ td.appendChild(actTitle);
+
+ var td = tr.insertCell();
+
+ var actType = document.createElement("span");
+ actType.setAttribute("id", "act-type");
+ actType.innerText = type;
+ td.appendChild(actType);
+
+ var td = tr.insertCell();
+
+ var actDate = document.createElement("span");
+ actDate.setAttribute("id", "act-date");
+ actDate.innerText = dat;
+ td.appendChild(actDate);
+
+ var td = tr.insertCell();
+
+ var btn = document.createElement("button");
+ btn.setAttribute("id", "act-btn");
+ btn.className = "act-btn";
+ btn.innerText = 'Add';
+ td.appendChild(btn);
+
+ //request activity stream onclick and load to interface.
+ btn.onclick = function() {
+ btn.innerText = "Added";
+
+ //disable other buttons
+ var cusid_ele = document.getElementsByClassName('act-btn');
+ for (var i = 0; i < cusid_ele.length; ++i) {
+ var item = cusid_ele[i];
+ if (item.innerText === 'Add'){
+ //hide other buttons. Not strictly necessary as clicking different add will override
+ //but probably more obvious to the user if we don't allow it?
+ item.style.visibility = 'hidden';
+ } else {
+ //disable Added button
+ item.style.pointerEvents = 'none';
+ }
+ }
+
+ // get activity stream
+ $.getJSON(rg2Config.json_url, {
+ type : "stravaActivityStream",
+ id : activityId+'|'+token,
+ cache : false
+ }).done(function (json) {
+ rg2.drawing.uploadStrava(json);
+ }).fail(function (jqxhr, textStatus, error) {
+ /*jslint unparam:true*/
+ reportJSONFail("Activities request failed: " + error);
+ });
+ }
+
+ },
+
rotatePoint : function (x, y, angle) {
// rotation matrix: see http://en.wikipedia.org/wiki/Rotation_matrix
var pt = {};
diff --git a/rg2-config .txt b/rg2-config .txt
index a3dc7e0..e1e4804 100644
--- a/rg2-config .txt
+++ b/rg2-config .txt
@@ -55,4 +55,8 @@
//
// or
//define('EPSG_CODE', "EPSG:12345|EPSG:67890");
- //define('EPSG_PARAMS', "+proj=x +ellps=WGS84 +datum=WGS84 +units=m +no_defs|+proj=y +ellps=WGS84 +datum=WGS84 +units=m +no_defs");
\ No newline at end of file
+ //define('EPSG_PARAMS', "+proj=x +ellps=WGS84 +datum=WGS84 +units=m +no_defs|+proj=y +ellps=WGS84 +datum=WGS84 +units=m +no_defs");
+
+ // If using strava, add the application oauth client and secret
+ //define('STRAVA_CLIENT', '')
+ //define('STRAVA_SECRET', '')
\ No newline at end of file
diff --git a/rg2api.php b/rg2api.php
index f190766..3141f14 100644
--- a/rg2api.php
+++ b/rg2api.php
@@ -11,6 +11,7 @@
require(dirname(__FILE__) . '/app/splitsbrowser.php');
require(dirname(__FILE__) . '/app/user.php');
require(dirname(__FILE__) . '/app/utils.php');
+ require(dirname(__FILE__) . '/app/strava.php');
require_once(dirname(__FILE__) . '/rg2-config.php');
@@ -55,18 +56,25 @@
} else {
$id = 0;
}
+ if (isset($_GET['code'])) {
+ $code = $_GET['code'];
+ } else {
+ $code = 'unknown';
+ }
- if ($_SERVER['REQUEST_METHOD'] == 'GET') {
- handleGetRequest($type, $id);
+ if ($_SERVER['REQUEST_METHOD'] == 'GET' && $code == 'unknown') {
+ handleGetRequest($type, $id);
+ } elseif ($_SERVER['REQUEST_METHOD'] == 'GET' && $code !== 'unknown') {
+ strava::getStravaActivities($code);
} elseif ($_SERVER['REQUEST_METHOD'] == 'POST') {
- if ($type == 'uploadmapfile') {
- map::uploadMapFile();
- } else {
- handlePostRequest($type, $id);
- }
+ if ($type == 'uploadmapfile') {
+ map::uploadMapFile();
+ } else {
+ handlePostRequest($type, $id);
+ }
} else {
- header('HTTP/1.1 405 Method Not Allowed');
- header('Allow: GET, POST');
+ header('HTTP/1.1 405 Method Not Allowed');
+ header('Allow: GET, POST');
}
function handlePostRequest($type, $eventid)
@@ -186,6 +194,9 @@ function handleGetRequest($type, $id)
event::fixResults($id);
$output = json_encode("Results fixed for event ".$id);
break;
+ case 'stravaActivityStream':
+ $output = strava::getActivityStream($id);
+ break;
default:
utils::rg2log("Get request not recognised: ".$type.", ".$id);
$output = json_encode("Request not recognised.");