Skip to content

Instantly share code, notes, and snippets.

@juntalis
Created October 5, 2012 23:23
Show Gist options
  • Save juntalis/3843036 to your computer and use it in GitHub Desktop.
Save juntalis/3843036 to your computer and use it in GitHub Desktop.
Toggl API Extractor
// Run this on the Toggl API page (https://www.toggl.com/public/api) from your javascript console. (In a modern browser)
// Dirty as hell, but I didn't expect to actually add a UI.
function OnLoad() {
var rgxp = /(?:-d ("|)(.*?)\1)? -X (POST|GET|PUT|DELETE) (https:\/\/www\.toggl\.com\/api\/v\d\/[^ \r\n\t]+)\s*$/ig,
typof = function(x) { var s, t = typeof(x); return t === 'object' ? (s = Object.prototype.toString.call(x)).substring(8, s.length - 1).toLowerCase() : t; },
resultWrap = $('<div />').css({
position: 'fixed',
left: Math.floor(($(window).innerWidth() * 0.2) / 2) + 'px',
top: Math.floor(($(window).innerHeight() * 0.2) / 2) + 'px',
width: '80%',
height: '80%',
clip: 'auto',
backgroundColor: '#fff',
border: '1px solid #ccc',
padding: '5px',
display: 'block',
visibility: 'hidden'
}).css('border-radius', '5px')
.css('z-index', '1000')
.css('overflow', 'hidden')
.css('box-shadow', '0 2px 3px #999'),
toolBarBox = $('<div />')
.css('border-bottom', '1px dashed #e8e8e8')
.css('padding', '3px')
.css('text-align', 'right')
.appendTo(resultWrap),
selectAll = $('<a />')
.attr('href', '#')
.html('Select All')
.css('font-weight','strong')
.appendTo(toolBarBox),
resultBox = $('<pre />')
.css('font-family', 'Consolas')
.css('border', '0px none')
.attr('class', 'prettyprint lang-js')
.appendTo(resultWrap)
.wrap('<div style="overflow:auto;width:100%;height:100%;" />'),
requests = $('pre.req').filter(function(i, el) {
if(i > 1) {
var header = $(this).prev();
while((header = $(header).prev()).length > 0 && (header.get(0).tagName !== 'H3'));
if(header.children().length > 0) {
header = header.children('a');
}
$(this)
.data('response', $(this).next().next().html())
.data('comment', header.html());
return true;
}
return false;
}),
results = {
"requests" : [],
"version" : 6
},
addResult = function(result) {
results.requests.push(result);
},
recurse,
recurseArray,
check = function(obj) {
var t = typof(obj);
switch(t) {
case 'boolean':
return 'bool';
case 'string':
if (/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2})$/i.test(obj)) {
return 'datetime';
}
case 'number':
return t;
case 'object':
return recurse(obj);
case 'array':
return recurseArray(obj);
default:
if(obj == null) return 'null';
return false;
}
},
completeResult,
serialize = function(s) {
try {
var a = s.split(/ -d /),
results = [],
fields = {};
for(var i = 0; i < a.length; i++) {
var parts = a[i].split('='),
field = parts[0].toLowerCase(),
value = parts[1];
if (field in fields) {
results[fields[field]][1] = 'array';
} else if (/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2})$/i.test(value)) {
results.push([field, 'datetime']);
} else if (/^\d+$/.test(value)) {
results.push([field, 'number']);
} else if (/^(?:true|false)$/.test(value)) {
results.push([field, 'bool']);
} else {
results.push([field, 'string']);
}
fields[field] = i;
}
return results;
} catch(e) {
return s
}
};
recurseArray = function(arr) {
var result = [];
for(var i = 0; i < arr.length; i++) {
var r = check(arr[i]);
if(r) result.push(r);
}
return result;
};
recurse = function(obj) {
var result = {};
for(var p in obj) {
var r = check(obj[p]);
if(r) result[p] = r;
}
return result;
};
completeResult = function() {
for(var i = 0; i < results.requests.length; i++) {
results.requests[i].url = results.requests[i].url.replace(/\/\d+\.json/g, "/[id].json");
if(results.requests[i].url.indexOf('?') !== -1) {
var urlparts = results.requests[i].url.split('?');
results.requests[i].url = urlparts[0];
results.requests[i].query = serialize(urlparts[1]);
}
if(typeof(results.requests[i].data) !== 'undefined') {
results.requests[i].data = typeof(results.requests[i].data) === 'object' ? check(results.requests[i].data) : serialize(results.requests[i].data);
if(!results.requests[i].data || results.requests[i].data == 'null') delete results.requests[i].data;
}
results.requests[i].response = check(results.requests[i].response);
}
results = JSON.stringify(results, undefined, " ");
resultBox.html(
results
.replace(/ /g, "&nbsp;")
.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;")
.replace(/\r?\n/g, "<br />")
)
.data('results', results);
resultWrap.appendTo('body');
var resultBoxP = resultBox.parent();
resultBoxP
.width(resultBoxP.width() - 5)
.height(resultBoxP.height() - 36);
resultWrap
.css('display', 'none')
.css('visibility', 'visible')
.fadeIn('fast');
prettyPrint();
resultBox.find('span.str + span.pun + span.pln + span.str').each(function() {
var typ = $(this).html().substring(1);
typ = typ.substring(0,typ.length - 1);
switch(typ) {
case 'number':
$(this).attr('class', 'lit');
break;
case 'string':
$(this).attr('class', 'kwd');
break;
case 'bool':
$(this).attr('class', 'typ');
break;
case 'datetime':
$(this).attr('class', 'tag');
break;
case 'null':
$(this).attr('class', 'com').html(typ);
break;
default:
break;
}
});
var clicked = false;
selectAll.click(function(ev) {
ev.preventDefault();
if(clicked) return false;
clicked = true;
toolBarBox.fadeOut('fast');
resultBoxP.fadeOut('fast', function() {
var sres = resultBox.data('results');
resultBoxP.add(toolBarBox).remove();
var txtres = $('<textarea />')
.css('width', '100%')
.css('height', '100%')
.css('font-family', 'Consolas')
.css('display', 'block')
.css('visibility', 'hidden')
.val(sres)
.appendTo(resultWrap);
txtres
.width(txtres.width() - 5)
.height(txtres.height() - 5)
.css('display', 'none')
.css('visibility', 'visible')
.fadeIn('fast', function(){
$(this).select();
});
});
return false;
});
};
requests.each(function(i) {
var html = $(this).html(), match = rgxp.exec(html);
if (match != null) {
var sResponse, response,
fields = (function(data) {
if(typeof data === 'undefined' || data.length === 0) return null;
if(data.indexOf('"') !== -1) {
data = 'return ' + data.replace(/\\\\/g, '\\').replace(/\\"/g, '"');
if(data.indexOf('project_user') !== -1) data += '}';
data += ';';
return new Function(data)();
}
return data;
})(match[2]), method = match[3], url = match[4];
try {
sResponse = $(this).data('response');
if(typeof(sResponse) !== 'undefined' && url.indexOf('api/v6/tasks') !== -1) {
sResponse = sResponse.replace(/"estimated_workhours": (\d+)([\t \r\n]*[^,])/ig, '"estimated_workhours": $1,$2');
}
response = JSON.parse(sResponse);
} catch(e) {
console.log(this);
console.dir(e);
console.log(sResponse);
response = e;
}
addResult({
"title" : $(this).data('comment'),
"url" : url,
"method" : method,
"data" : fields,
"response" : response
});
}
});
completeResult();
}
$('head').append('<link href="https://junt-crossxhr.appspot.com/css/prettify.css" rel="stylesheet" type="text/css" />');
$.getScript("https://junt-crossxhr.appspot.com/js/lib/prettify.js", OnLoad);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment