Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/event.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
84 changes: 84 additions & 0 deletions app/strava.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

class strava
{

public static function getStravaActivities($code)
{
//request token
$token = strava::getToken($code);
//decode and get access token
$t = json_decode($token);
$access_token = $t->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;
}

}
4 changes: 4 additions & 0 deletions html/infopanel.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ <h3 id='rg2-load-gps-title'>Load GPS file (GPX or TCX)</h3>
<div id="rg2-select-gps-file">
<input type='file' accept='.gpx, .tcx' id='rg2-load-gps-file'>
</div>
<div id="strava" class="singlerow">
<button type="button" id="btn-get-strava">Get 10 most recent activities from Strava</button>
<table id="strava-activities"></table>
</div>
<div class="singlerow">
<button class = "singlerowitem" id="btn-autofit-gps">Autofit</button>
<div id="rg2-offset-spinner" class="singlerowitem">
Expand Down
5 changes: 5 additions & 0 deletions js/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
this.gpstrack.uploadGPS(evt);
},

uploadStrava : function (evt) {
this.gpstrack.uploadStrava(evt);
},

getControlXY : function () {
return {x: this.controlx, y: this.controly};
},
Expand Down Expand Up @@ -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);
},

Expand Down
25 changes: 25 additions & 0 deletions js/gpstrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions js/rg2getjson.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
29 changes: 29 additions & 0 deletions js/rg2ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
Expand Down Expand Up @@ -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 () {
Expand Down
95 changes: 95 additions & 0 deletions js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};
Expand Down
6 changes: 5 additions & 1 deletion rg2-config .txt
Original file line number Diff line number Diff line change
Expand Up @@ -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");
//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', '')
29 changes: 20 additions & 9 deletions rg2api.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.");
Expand Down