Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save saitamanodoruji/2944470 to your computer and use it in GitHub Desktop.
Save saitamanodoruji/2944470 to your computer and use it in GitHub Desktop.
Endless Summer on Tumblr Dashboard with Logger
// ==UserScript==
// @name Endless Summer on dsbd with Logger
// @namespace http://www.tumblr.com/
// @description random next link on tumblr dashboard
// @include http://www.tumblr.com/dashboard/1*
// @include http://www.tumblr.com/show/*/1*
// @require https://raw.github.com/gist/3242
// @require https://raw.github.com/gist/198443
// @require https://raw.github.com/gist/34615
// @version 0.0.4.0.17
// @update 2013-09-06
// ==/UserScript==
// shuffles dashboard with Exponential Endless Summer method
// http://tumblr.g.hatena.ne.jp/saitamanodoruji/20130831/1377961157
// scrapes dashboard and logs data to Firefox preference
// under the name "log" as JSON array
// [{"drawnNo": 1234567899, "utime": 1234567890000, "postNo": 1234567890, "type": 1}, ...]
// requires sharedObject fix to Greaesemonkey (or Scriptish)
// http://exe.tyo.ro/2011/11/greasemonkey0912minibufferldrize.html by tyoro
// requires AutoPagerize http://userscripts.org/scripts/show/8551 by swdyh
// requires fix of AutoPagerize http://d.hatena.ne.jp/t_f_m/20111121/1321886246a by t_f_m
// using $X() https://gist.github.com/3242 by os0x
// using createDocumentFromString https://gist.github.com/198443 by os0x
// using wedata utility for GM https://gist.github.com/34615 by youpy
(function(){
var dsbd = 'http://www.tumblr.com/dashboard';
var DATABASE_URL = 'http://wedata.net/items/54652.json';
var database = new Wedata.Database(DATABASE_URL);
var data = JSON.parse(GM_getValue('log', '[{"drawnNo": 1}]'));
var data_ = [];
data.forEach(function(d){
if (d.utime && d.postNo < d.drawnNo) data_.push(d);
});
data = data_;
GM_log('logged data loaded from Firefox preference.\nN = ' + data.length);
var getId = function(info){
var opt = {
method: 'GET',
url: dsbd,
headers : {
},
onload: function(res) {
var i = $X(info.nextLink, createDocumentFromString(res.responseText));
if(i.length){
i = i[0];
}else{
return;
}
var cacheInfo = {
postNo : i.href.match(/.*\/\d+\/(\d+)/)[1],
nextLink : info.nextLink
};
GM_setValue('cacheInfo', JSON.stringify(cacheInfo));
}
};
GM_xmlhttpRequest(opt);
};
var endlessSummer = function(doc, url, info){
var cacheInfo = JSON.parse(GM_getValue('cacheInfo'));
if (!cacheInfo){
return;
}
var a = $X(cacheInfo.nextLink, doc);
if (a.length) {
a = a[0];
}else{
return;
}
var range = {min: 72997, max: cacheInfo.postNo};
var drawnNo = draw(range.min, range.max);
a.href = location.pathname.replace(/(\/[^\/]+\/\d+)(\/\d+)/,'$1') + '?offset=' + drawnNo;
a.textContent = 'Searching for The Endless Summer \u2192 ';
a.style.background='none repeat scroll 0 0 #4AADF0';
// log
if (data.length) {
var d = data[data.length - 1];
if (d.drawnNo && !d.postNo && !d.utime && !d.type) {
var dData = {}; // data scraped from dashboard
var anchor = $X('//a[contains(concat(" ", @class, " "), " post_permalink ")]', doc)[0];
dData.postNo = anchor.href.replace(/^http:\/\/[^\/]+\/(?:post\/)?(\d+)\/?[^\/]*$/, '$1');
if (dData.postNo > d.drawnNo) {
// when AutoPagerize.filter didn't work before loading next page
data.pop();
GM_log('AutoPagerize.filter didn\'t work before loading this page.\n'
+ 'drawnNo = ' + d.drawnNo + '\n'
+ 'postNo = ' + dData.postNo + '\n'
+ 'discarded the data.\n'
+ 'N = ' + data.length);
} else {
dData.mesTime = new Date().getTime();
dData.utime = getUnixTimeFromDsbdDateString(anchor.title, dData.postNo);
dData.type = anchor.title.replace('View post - ', '').split(' ').length;
dData.minPID = range.min;
dData.maxPID = range.max;
d = update(d, dData);
GM_log('got data. N = ' + data.length + '\n' + [
dData.type,
(new Date(dData.utime)).toLocaleFormat('%Y-%m-%dT%H:%M:%S+09:00'),
dData.utime,
(new Date(dData.mesTime)).toLocaleFormat('%Y-%m-%dT%H:%M:%S+09:00'),
dData.mesTime,
dData.postNo,
d.drawnNo,
dData.minPID,
dData.maxPID].join(','))
}
}
}
data.push({drawnNo: drawnNo});
GM_setValue('log', JSON.stringify(data));
};
// Exponential Endless Summer 2013.08
var draw = function(oldestID, newestID) {
var oldestUTime = getUnixTimeFromPostID(oldestID);
var newestUTime = getUnixTimeFromPostID(newestID);
var drawnUTime = oldestUTime + Math.floor((newestUTime - oldestUTime) * Math.random());
return getPostIDFromUnixTime(drawnUTime);
}
var getPostIDFromUnixTime = function(utime) {
if (utime < 1149465600000) {
return;
} else if (utime === Number.POSITIVE_INFINITY) {
return Number.POSITIVE_INFINITY;
}
for (var i = 0; i < params.length; i++) {
if (utime <= params[i].upperBound) {
return Math.ceil(params[i].coefAlpha * Math.exp(params[i].coefBeta * (utime - 1136073600000)));
}
}
}
var getUnixTimeFromPostID = function(postID) {
if (postID < 1) { return; }
for (var i = 0; i < params.length; i++) {
if (postID <= getPostIDFromUnixTime(params[i].upperBound)) {
return Math.floor(Math.log(postID/params[i].coefAlpha)/params[i].coefBeta) + 1136073600000;
}
}
}
var params = [
// f_i(t) = Alpha_i * exp[Beta_i * (t - t_0)]
// t: Unix time [msec]
// t_0 = 1136073600000 [msec] (2006-01-01T00:00:00+09:00)
{coefAlpha: 1.211 * Math.pow(10, -1), coefBeta: 1.571 * Math.pow(10, -10), upperBound: 1160012789359},
{coefAlpha: 3.619 * Math.pow(10, -13), coefBeta: 1.266 * Math.pow(10, -9), upperBound: 1163269541924},
{coefAlpha: 2.120 * Math.pow(10, 0), coefBeta: 1.846 * Math.pow(10, -10), upperBound: 1172120791893},
{coefAlpha: 1.179 * Math.pow(10, -49), coefBeta: 3.331 * Math.pow(10, -9), upperBound: 1173392561265},
{coefAlpha: 4.702 * Math.pow(10, -7), coefBeta: 7.024 * Math.pow(10, -10), upperBound: 1176405323219},
{coefAlpha: 5.338 * Math.pow(10, 1), coefBeta: 2.425 * Math.pow(10, -10), upperBound: 1182930300850},
{coefAlpha: 8.255 * Math.pow(10, 3), coefBeta: 1.349 * Math.pow(10, -10), upperBound: 1193299359828},
{coefAlpha: 2.496 * Math.pow(10, 6), coefBeta: 3.509 * Math.pow(10, -11), upperBound: 1241622616806},
{coefAlpha: 2.907 * Math.pow(10, 5), coefBeta: 5.546 * Math.pow(10, -11), upperBound: 1283088065116},
{coefAlpha: 5.206 * Math.pow(10, 4), coefBeta: 6.716 * Math.pow(10, -11), upperBound: 1291075200000},
{coefAlpha: 8.329 * Math.pow(10, 4), coefBeta: 6.521 * Math.pow(10, -11), upperBound: 1292241600000},
{coefAlpha: 8.396 * Math.pow(10, 4), coefBeta: 6.541 * Math.pow(10, -11), upperBound: 1307576237376},
{coefAlpha: 7.746 * Math.pow(10, 4), coefBeta: 6.588 * Math.pow(10, -11), upperBound: 1313586050187},
{coefAlpha: 8.798 * Math.pow(10, 6), coefBeta: 3.922 * Math.pow(10, -11), upperBound: 1340572542928},
{coefAlpha: 2.693 * Math.pow(10, 8), coefBeta: 2.249 * Math.pow(10, -11), upperBound: Number.POSITIVE_INFINITY},
]
// utilities for date correction
// a.post_permalink の title に入っている日付文字列と Post ID を元に
// ポストが作られた Unix time を求める
var getUnixTimeFromDsbdDateString = function(dsbdDateStr, dsbdPostNo) {
var utime;
var dateArr = dsbdDateStr.replace('View post - ', '').split(' ');
var type = dateArr.length;
var curDate = new Date();
if (type == 1) {
// View post - 5:17am
var formattedTime = getFormattedTime(dsbdDateStr.replace('View post - ', ''));
var timestamp = curDate.toString().replace(/\d\d:\d\d:\d\d/, formattedTime);
utime = new Date(timestamp).getTime();
} else if (type == 2) {
// View post - Thursday, 11:53pm
var diffInWeek;
var day = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
day.forEach(function(e, i) {
if( e == dateArr[0].replace(',', '') ) {
diffInWeek = curDate.getDay() - i > 0 ?
curDate.getDay() - i :
curDate.getDay() - i + 7;
}
});
var formattedTime = getFormattedTime(dsbdDateStr.replace(/^[^,]+, /, ''));
var timestamp = curDate.toString().replace(/\d\d:\d\d:\d\d/, formattedTime);
utime = new Date(timestamp).getTime() - diffInWeek * 86400000;
} else if (type == 3) {
// View post - June 8th, 8:46pm
var formattedDateStr = [
curDate.getFullYear(),
dateArr[0],
dateArr[1].replace(/(?:st|nd|rd|th)/, ''),
getFormattedTime(dateArr[2])
].join(' ');
utime = new Date(formattedDateStr).getTime();
} else if (type == 4) {
// View post - March 29th 2007, 8:38pm
var formattedDateStr = [
dateArr[0],
dateArr[1].replace(/(?:st|nd|rd|th)/, ''),
dateArr[2],
getFormattedTime(dateArr[3])
].join(' ');
utime = new Date(formattedDateStr).getTime();
}
return correctDsbdUTime(utime, type, dsbdPostNo);
}
// いくつかの日付で日付文字列が間違っているので校正する
var correctDsbdUTime = function(utime, type, dsbdPostNo) {
var cUTime; //corrected Unix time
var timestamp = new Date(utime).toLocaleFormat('%Y-%m-%dT%H:%M:%S+09:00');
if (1230649200000 <= utime && utime < 1230735600000
&& dsbdPostNo < 31818629) {
// 2007-12-31 is displayed as 2008 by mistake
cUTime = new Date(timestamp.replace(/^2008/, '2007')).getTime();
} else if (1262012400000 <= utime && utime < 1262271600000
&& dsbdPostNo < 175958681) {
// 2008-12-29, 2008-12-30, 2008-12-31 are displayed as 2009 by mistake
cUTime = new Date(timestamp.replace(/^2009/, '2008')).getTime();
} else if (1230735600000 <= utime && utime < 1230994800000
&& dsbdPostNo > 175958681) {
// 2010-01-01, 2010-01-02, 2010-01-03 are displayed as 2009 by mistake
cUTime = new Date(timestamp.replace(/^2009/, '2010')).getTime();
} else if (1262271600000 <= utime && utime < 1262444400000
&& dsbdPostNo > 973060715) {
// 2011-01-01, 2011-01-02 are displayed as 2010 by mistake
cUTime = new Date(timestamp.replace(/^2010/, '2011')).getTime();
} else if (1293807600000 <= utime && utime < 1293894000000
&& dsbdPostNo > 5381076679) {
// 2012-01-01 is displayed as 2011 by mistake
cUTime = new Date(timestamp.replace(/^2011/, '2012')).getTime();
}
// same day of previous years displayed as current year
if (type == 1) {
var currentYear = new Date().getFullYear();
if (dsbdPostNo < 22717143) {
// to 2007
cUTime = rewindYear(utime, currentYear - 2007);
} else if (dsbdPostNo < 67667869) {
// to 2008
cUTime = rewindYear(utime, currentYear - 2008);
} else if (dsbdPostNo < 309781747) {
// to 2009
cUTime = rewindYear(utime, currentYear - 2009);
} else if (dsbdPostNo < 2542286951) {
// to 2010
cUTime = rewindYear(utime, currentYear - 2010);
} else if (dsbdPostNo < 15082228675) {
// to 2011
cUTime = rewindYear(utime, currentYear - 2011);
} else if (dsbdPostNo < 39306789337) {
// to 2012
cUTime = rewindYear(utime, currentYear - 2012);
}
}
// for 2012-12-31
if (type == 2 && 39217020996 < dsbdPostNo && dsbdPostNo < 39306789337) {
cUTime = new Date(timestamp.replace(/\d{4}-\d{2}-\d{2}/, '2012-12-31')).getTime();
}
return cUTime || utime;
}
// n 年前の同日の Unix time を求める
var rewindYear = function(utime, n) {
var utimeDateStr = new Date(utime).toISOString();
var utimeYear = Number(utimeDateStr.match(/^\d{4}/)[0]);
var rewindedYear = utimeYear - n;
var rewindedDateStr = utimeDateStr.replace(/^\d{4}/, rewindedYear);
var rewindedUTime = new Date(rewindedDateStr).getTime();
return rewindedUTime;
}
// 時刻文字列を 24 h 形式にする
// ex. 1) '9:17am' -> '09:17'
// ex. 2) '5:36pm' -> '17:36'
var getFormattedTime = function(timeStr) {
var timeArr = timeStr.split(':');
timeArr[0] = Number(timeArr[0]);
if (/pm/.test(timeArr[1])) {
timeArr[0] = (timeArr[0] + 12).toString();
} else if (timeArr[0].toString().length == 1) {
timeArr[0] = '0' + timeArr[0];
} else {
timeArr[0] = timeArr[0].toString().replace('12', '00');
}
timeArr[1] = timeArr[1].replace(/(?:am|pm)/, '');
return timeArr.join(':');
}
function update(t, s){
for(var p in s)
t[p] = s[p]
return t
}
// end of utilities for date correction
GM_registerMenuCommand('endless summer - clear cache', function() {
GM_setValue('cacheInfo', '');
database.clearCache();
});
GM_registerMenuCommand('endless summer - dump log', function() {
var data = JSON.parse(GM_getValue('log', '[]'));
if (data.length) {
data.pop();
} else {
GM_log('no log');
return;
}
var labels = [
'dsbdDateStringType',
'dsbdDate',
'dsbdUnixtime',
'mesDate',
'mesUnixTime',
'calcDate',
'calcUnixTime',
'postNo',
'drawnNo',
'residual[day]',
'minPID',
'maxPID'
].join(',');
var msg = data.map(function(e){
var calcUTime = getUnixTimeFromPostNo(e.drawnNo);
var ret = [
e.type,
(new Date(e.utime)).toLocaleFormat('%Y-%m-%dT%H:%M:%S+09:00'),
e.utime,
(new Date(e.mesTime)).toLocaleFormat('%Y-%m-%dT%H:%M:%S+09:00'),
e.mesTime,
(new Date(calcUTime)).toLocaleFormat('%Y-%m-%dT%H:%M:%S+09:00'),
calcUTime,
e.postNo,
e.drawnNo,
((e.utime - calcUTime) / (1000 * 60 * 60 * 24)).toFixed(1),
e.minPID,
e.maxPID
].join(',');
return ret;
}).join('\n');
GM_log(['','N = ' + data.length, labels, msg].join('\n'));
});
GM_registerMenuCommand('endless summer - clear log', function() {
if(confirm('Endless Summer: Are you sure you want to clear log?')) {
GM_deleteValue('log');
data = [];
}
});
database.get(function(items) {
getId(items.data);
});
endlessSummer(document, '', '');
setTimeout(function(){
if (sharedObject.AutoPagerize && sharedObject.AutoPagerize.addDocumentFilter){
sharedObject.AutoPagerize.addDocumentFilter(endlessSummer);
}
},0);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment