Skip to content

Instantly share code, notes, and snippets.

@badp
Created October 17, 2010 18:11
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save badp/631092 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name SO Live!
// @namespace tag://badp/
// @version 1.1 (now with update feedback)
// @description Bring Live reputation updates to the StackExchange™ EgoEmpowering HumanWorth™ counter.
// @include http://stackoverflow.com/*
// @include http://meta.stackoverflow.com/*
// @include http://superuser.com/*
// @include http://meta.superuser.com/*
// @include http://serverfault.com/*
// @include http://meta.serverfault.com/*
// @include http://askubuntu.com/*
// @include http://meta.askubuntu.com/*
// @include http://answers.onstartups.com/*
// @include http://meta.answers.onstartups.com/*
// @include http://nothingtoinstall.com/*
// @include http://meta.nothingtoinstall.com/*
// @include http://seasonedadvice.com/*
// @include http://meta.seasonedadvice.com/*
// @include http://stackapps.com/*
// @include http://*.stackexchange.com/*
// @exclude http://chat.stackexchange.com/*
// @exclude http://chat.*.stackexchange.com/*
// @exclude http://api.*.stackexchange.com/*
// @exclude http://odata.stackexchange.com/*
// @exclude http://area51.stackexchange.com/*
// @exclude http://*/reputation
// ==/UserScript==
//balpha <3
function with_plugin(url, callback) {
var script = document.createElement("script");
script.setAttribute("src", url);
script.addEventListener("load", function () {
var script = document.createElement("script");
script.type = "text/javascript";
if(callback.name)
script.textContent = callback.toString() + ";" + callback.name + "(jQuery);";
else
script.textContent = "(" + callback.toString() + ")(jQuery)";
document.body.appendChild(script);
}, false);
document.body.appendChild(script);
}
with_plugin("http://soapi.info/code/js/stable/scripts/Soapi.js", SO_Live)
function SO_Live($){
var debug = 0;
var site = window.location.hostname;
if(site !== "meta.stackoverflow.com") // metas do not count
site = site.replace("meta.", ""); //get rep updates from parent instead.
var user_id = $("#hlinks-user a").first().attr("href").match(/[0-9]+/)[0];
// get the URL address of the link to the user page; the sequence of digits is the user number, right? Right?
var rep_number_obj = $("#hlinks-user .reputation-score").first();
var api = Soapi.RouteFactory("api." + site, "a4T4v6g2pESuXB5InP2CWg");
var last_update = now();
function update_reputation_since(date){
if(date === undefined)
throw new Error("Please specify a date object.");
to_date = now()
rep_number_obj.fadeTo(0, 0.4) //visual feedback
api.UsersByIdReputation(
{ id: user_id,
fromdate: date,
todate: to_date
}).getResponse( function(data)
{
last_update = now(); //only update on successful update
rep_number_obj.fadeTo(1000, 1);
if(data.items.length)
$.each(data.items, _parse_api_result);
if(debug)
window.console.debug("Updates received: " + data.items);
});
_schedule_next_update();
}
function _schedule_next_update(){
if(debug)
window.console.debug("Scheduling next update in 60 seconds, checking activity since " + last_update);
setTimeout( function(){update_reputation_since(last_update) },
60000);
}
//entry point
_schedule_next_update();
function get_current_reputation(){
return to_num(rep_number_obj.text().replace(",", ""));
}
function _change_rep_number_by(difference){
var prev_rep = get_current_reputation();
var new_rep = prev_rep + difference;
rep_number_obj.text(add_commas(new_rep));
return new_rep;
}
function lightweight_notify(show_this_message, duration){
/*
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0
|---'---'---|---'---'---|---'---'---'---'---'---'---'---|---'---'---|---'---'---|
| fade out | fade in | display message | fade out | fade in |
| #hlinks | message | | message | #hlinks |
|<---300--->|<---300--->|<-------------800------------->|<---300--->|<---300--->|
|<---300--->|<------------------------1,400------------------------>|<---300--->|
*/
if(duration === undefined){
duration = 800;
}
var fade_time = 300;
if( $(".lightweight_notify").length ) { //delay -- TODO: handle this better
throw new Error("lightweight notifies overlap");
}
$("#hlinks")
.fadeOut(fade_time)
.delay(fade_time + duration + fade_time) //give the time for the message to appaear
.fadeIn(fade_time);
$("<span />")
.css({'float': 'left',
'text-align': 'right',
'margin-right': 20,
'width': '500px', //960-340=620-20=600 on SO, let's take less space for SE sites
'overflow': 'hidden',
'text-overflow': 'ellipsis',
'-o-text-overflow': 'ellipsis',
'white-space': 'nowrap',
'font-weight': 'bold'
})
.addClass('hot transient-notification')
.insertBefore("#hsearch")
.hide()
.delay(fade_time) //give the time for #links to fade out
.fadeIn(fade_time)
.delay(duration)
.fadeOut(fade_time)
[0] //get DOM object
.innerHTML = show_this_message;
setTimeout("$(\".transient-notification\").remove()", fade_time*3 + duration);
}
//http://stackoverflow.com/q/3953746/13992
function _schedule_rep_number_change(diff, step, number){
setTimeout( function(){ _change_rep_number_by(diff) },
4200 + step*25 + number*5000);
}
function _schedule_lightweight_notify(message, number){
setTimeout( function(){ lightweight_notify(message, 3000)},
number*5000
);
}
function linkify(change){
return $("<a/>").text(change.title)
.attr("href", "http://" + site + "/questions/" + change.post_id + "/-1") //give Community some love
[0] //get dom object
.outerHTML //cringe
}
function _parse_api_result(number, change){
//lit up the envelope
$(".envelope-off").toggleClass(".envelope-on", true)
.toggleClass(".envelope-off", false)
.attr("title", "You have new replies");
var rep_net_change = change.positive_rep - change.negative_rep;
var step = 1;
var msg = rep_net_change > 0 ? "Gained " : "Spent ";
msg += Math.abs(rep_net_change);
msg += " reputation for ";
msg += linkify(change);
_schedule_lightweight_notify(msg, number);
while(rep_net_change){
if(rep_net_change > 0)
var diff = Math.ceil(rep_net_change / 10);
else
var diff = Math.floor(rep_net_change / 10);
_schedule_rep_number_change(diff, step, number);
rep_net_change -= diff;
step++;
}
} // _parse_api_result(0, debug_change)
//for the I can't believe I had to write this™ series
function now(){
return new Date();
}
function to_num(val){
var number = parseInt(val, 10);
if( isNaN(number) )
throw new Error(val + " is not a number");
return number;
}
//http://www.mredkj.com/javascript/numberFormat.html
function add_commas(nStr)
{
if(nStr > 999999) //this function breaks above one million.
throw new Error("Sorry, you are too awesome for this mere function.");
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
window._start_SO_Live_debug = function(){
lightweight_notify("Hello! Now try <code>SO_Live_demo()</code> to replay a month's worth of rep changes.", 5000)
debug = 1;
window.SO_Live = SO_Live;
window.SO_Live_demo = function(){
var one_month_ago = new Date(now() - 100*86400*30)
update_reputation_since(one_month_ago)
}
}
}
// ==UserScript==
// @name SO Live! Chat Edition 1.1
// @namespace tag://badp/
// @version 1.1
// @description Bring Live reputation updates to the StackExchange™ DismissalProne AwesomeNotifier™
// @include http://chat.stackoverflow.com/rooms/*
// @include http://chat.meta.stackoverflow.com/rooms/*
// @include http://chat.superuser.com/rooms/*
// @include http://chat.serverfault.com/rooms/*
// @include http://chat.askubuntu.com/rooms/*
// @include http://chat.answers.onstartups.com/rooms/*
// @include http://chat.nothingtoinstall.com/rooms/*
// @include http://chat.seasonedadvice.com/rooms/*
// @include http://chat.stackapps.com/rooms/*
// @include http://chat.*.stackexchange.com/rooms/*
// @include http://chat.stackexchange.com/rooms/*
// ==/UserScript==
//balpha <3
function with_plugin(url, callback) {
var script = document.createElement("script");
script.setAttribute("src", url);
script.addEventListener("load", function () {
var script = document.createElement("script");
script.type = "text/javascript";
if(callback.name)
script.textContent = callback.toString() + ";" + callback.name + "(jQuery);";
else
script.textContent = "(" + callback.toString() + ")(jQuery)";
document.body.appendChild(script);
}, false);
document.body.appendChild(script);
}
with_plugin("http://soapi.info/code/js/stable/scripts/Soapi.js", SO_Live_Chat)
function SO_Live_Chat($){
var so_live_site = $("#footer-logo a").first().attr("href").replace("http://", "")
var debug = 0;
// get user for site -- a waste on non-SE chats.
var chat_user_id = $('#active-user').data('user');
var user_id = -1;
$.get("/users/sites/" + chat_user_id, _get_real_user_id)
function _get_real_user_id(associations){
$.each(associations, function(x, association){ // MAXIMUM JQUERY
if(association.Host == so_live_site){
user_id = association.UserId
console.debug("Found user id on", so_live_site, ":", user_id)
}
})
}
var api = Soapi.RouteFactory("api." + so_live_site, "a4T4v6g2pESuXB5InP2CWg");
var last_update = now();
function update_reputation_since(date){
if(date === undefined)
throw new Error("Please specify a date object.");
api.UsersByIdReputation(
{ id: user_id,
fromdate: date
}).getResponse( function(data)
{
last_update = now(); //only update on successful update
if(data.items.length)
$.each(data.items, _parse_api_result);
if(debug)
console.debug("Updates received: " + data.items);
});
_schedule_next_update();
}
function _schedule_next_update(){
if(debug)
console.debug("Scheduling next update in 60 seconds, checking activity since " + last_update);
setTimeout( function(){update_reputation_since(last_update) },
60000);
}
//entry point
if(so_live_site !== "stackexchange.com")
_schedule_next_update();
else
console.warn("SO Live! disabled -- room not bound to a site.");
function notify(message){
window.Notifier().notify(message);
}
function linkify(change){
// see http://chat.stackoverflow.com/transcript/message/479425#479425
dummy = $("<hack></hack>")
what_I_want = $("<a></a>").text(change.title)
.attr("href", "http://" + so_live_site + "/q/" + change.post_id + "/-1") //give Community some love
dummy.append(what_I_want)
return dummy[0].innerHTML
}
function _parse_api_result(number, change){
var rep_net_change = change.positive_rep - change.negative_rep;
var message = rep_net_change > 0 ? "Gained " : "Spent ";
message += "<b>";
message += Math.abs(rep_net_change);
message += "</b>";
message += " reputation for ";
message += linkify(change);
notify(message);
} // _parse_api_result(0, debug_change)
//for the I can't believe I had to write this™ series
function now(){
return new Date();
}
window._start_SO_Live_debug = function(){
notify("Hello! Now try <code>SO_Live_demo()</code> to replay a week's worth of rep change notifications.")
debug = 1;
window.SO_Live_Chat = SO_Live_Chat;
window.SO_Live_demo = function(){
var one_week_ago = new Date(now() - 100*86400*30)
update_reputation_since(one_week_ago)
}
}
}
This file has been truncated, but you can view the full file.
@badp
Copy link
Author

badp commented Oct 17, 2010

How to try revision 6ab9d

  1. Paste it in, get error SoApi is not defined
  2. Paste it in again
  3. update_reputation_since(new Date("2010-09-01 00:00:00Z"))

Following updates are actually functional.

@badp
Copy link
Author

badp commented Oct 17, 2010

How to try revision 7c5cb

  1. Paste it in the javascript console.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment