473 lines
15 KiB
JavaScript
473 lines
15 KiB
JavaScript
|
|
/* Window state */
|
|
var textbox = null;
|
|
var busy = false;
|
|
|
|
var auto_mark = {};
|
|
var mass_mark_legit = [];
|
|
var mass_mark_btn = null;
|
|
|
|
var newest_uid = null;
|
|
var oldest_uid = null;
|
|
|
|
/* Credit: https://stackoverflow.com/a/7124052 */
|
|
var htmlEscape = function(str) {
|
|
return str
|
|
.replace(/&/g, '&')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>');
|
|
};
|
|
|
|
|
|
var scoreColour = function (score) {
|
|
var red = Math.round(((score > 0) ? (1.0 - score) : 1.0)*255);
|
|
var grn = Math.round(((score < 0) ? (score + 1.0) : 1.0)*255);
|
|
return 'rgb(' + red + ', ' + grn + ', 0)';
|
|
};
|
|
|
|
var getNextPage = function() {
|
|
var rq = new XMLHttpRequest();
|
|
busy = true;
|
|
var loading_msg = document.createElement('pre');
|
|
var spinner = '-';
|
|
var dots = '';
|
|
textbox.appendChild(loading_msg);
|
|
mass_mark_legit = Object.keys(auto_mark);
|
|
|
|
if (mass_mark_btn !== null) {
|
|
textbox.removeChild(mass_mark_btn);
|
|
}
|
|
|
|
if (mass_mark_legit.length > 0) {
|
|
mass_mark_btn = document.createElement('button');
|
|
mass_mark_btn.innerHTML = ('Mark above '
|
|
+ mass_mark_legit.length
|
|
+ ' auto_legit accounts as legit');
|
|
mass_mark_btn.onclick = function() {
|
|
mass_mark_legit.forEach(function (uid) {
|
|
auto_mark[uid](true);
|
|
});
|
|
textbox.removeChild(mass_mark_btn);
|
|
mass_mark_btn = null;
|
|
window.scrollTo(0,0);
|
|
};
|
|
textbox.appendChild(mass_mark_btn);
|
|
}
|
|
|
|
var nextSpinner = function() {
|
|
if (busy) {
|
|
window.setTimeout(nextSpinner, 250);
|
|
}
|
|
|
|
switch (spinner) {
|
|
case '-': spinner = '\\'; break;
|
|
case '\\': spinner = '|'; break;
|
|
case '|': spinner = '/'; break;
|
|
default:
|
|
spinner = '-';
|
|
dots += '.';
|
|
break;
|
|
}
|
|
|
|
loading_msg.innerHTML = 'Loading'
|
|
+ ((oldest_uid !== null)
|
|
? (' users older than #' + oldest_uid)
|
|
: (' most recent users'))
|
|
+ dots + spinner;
|
|
};
|
|
nextSpinner();
|
|
|
|
var found = 0;
|
|
var displayed = 0;
|
|
|
|
rq.onreadystatechange = function() {
|
|
try {
|
|
if (this.readyState == 4) {
|
|
// Typical action to be performed when
|
|
// the document is ready:
|
|
textbox.removeChild(loading_msg);
|
|
|
|
if (this.status === 200) {
|
|
var data = JSON.parse(rq.responseText);
|
|
found += data.users.length;
|
|
data.users.forEach(function (user) {
|
|
if ((newest_uid === null)
|
|
|| (newest_uid < user.id))
|
|
newest_uid = user.id;
|
|
|
|
if ((oldest_uid === null)
|
|
|| (oldest_uid > user.id))
|
|
oldest_uid = user.id;
|
|
|
|
/* Hide if there's nothing to inspect */
|
|
if (user.pending && (Object.keys(user.words).length === 0)) {
|
|
return
|
|
}
|
|
displayed++;
|
|
|
|
var userBox = document.createElement('div');
|
|
userBox.style.border = '1px solid black';
|
|
userBox.style.padding = '2em';
|
|
|
|
var avatarBox = document.createElement('div');
|
|
var avatar = document.createElement('img');
|
|
avatar.src = '/avatar/' + user.avatar_id
|
|
+ '?width=100&height=100';
|
|
avatarBox.appendChild(avatar);
|
|
avatarBox.style.width = '100px';
|
|
avatarBox.style.height = '100px';
|
|
userBox.appendChild(avatarBox);
|
|
|
|
var profile_link = document.createElement('a');
|
|
profile_link.href = user.url;
|
|
var profile_name = document.createElement('tt');
|
|
profile_name.innerHTML = user.screen_name;
|
|
profile_link.appendChild(profile_name);
|
|
userBox.appendChild(profile_link);
|
|
|
|
var profile_uid = document.createTextNode(' ' + user.id);
|
|
userBox.appendChild(profile_uid);
|
|
|
|
if (user.pending) {
|
|
userBox.appendChild(
|
|
document.createTextNode(' Re-inspection pending ('
|
|
+ user.next_inspection
|
|
+ '; '
|
|
+ user.inspections
|
|
+ ' inspections)')
|
|
);
|
|
}
|
|
|
|
var profile_score = document.createElement('div');
|
|
userBox.appendChild(profile_score);
|
|
|
|
var profile_score_gauge = document.createElement('div');
|
|
profile_score_gauge.style.display = 'table-row';
|
|
profile_score_gauge.style.height = '32px';
|
|
profile_score_gauge.style.width = '320px';
|
|
profile_score_gauge.style.border = '1px solid black';
|
|
var profile_score_gauge_left = document.createElement('div');
|
|
profile_score_gauge_left.style.display = 'table-cell';
|
|
profile_score_gauge_left.style.height = '32px';
|
|
profile_score_gauge_left.style.background = '#ccc';
|
|
profile_score_gauge.appendChild(profile_score_gauge_left);
|
|
var profile_score_gauge_bar = document.createElement('div');
|
|
profile_score_gauge_bar.style.display = 'table-cell';
|
|
profile_score_gauge_bar.style.height = '32px';
|
|
profile_score_gauge.appendChild(profile_score_gauge_bar);
|
|
var profile_score_gauge_right = document.createElement('div');
|
|
profile_score_gauge_right.style.display = 'table-cell';
|
|
profile_score_gauge_right.style.height = '32px';
|
|
profile_score_gauge_right.style.background = '#ccc';
|
|
profile_score_gauge.appendChild(profile_score_gauge_right);
|
|
userBox.appendChild(profile_score_gauge);
|
|
|
|
var profile_created = document.createElement('div');
|
|
profile_created.innerHTML = user.created;
|
|
userBox.appendChild(profile_created);
|
|
|
|
var profile_groups = document.createElement('div');
|
|
var group_set = {};
|
|
user.groups.forEach(function (group) {
|
|
var group_label = document.createElement('tt');
|
|
group_label.innerHTML = group;
|
|
profile_groups.appendChild(group_label);
|
|
group_set[group] = true;
|
|
});
|
|
|
|
var rm_auto = function() {
|
|
if (auto_mark[user.id] !== undefined) {
|
|
delete auto_mark[user.id];
|
|
}
|
|
};
|
|
|
|
if (!group_set.legit) {
|
|
var classify_legit = document.createElement('button');
|
|
classify_legit.innerHTML = 'Legit';
|
|
var do_classify = function(mass_update) {
|
|
var rq = new XMLHttpRequest();
|
|
rm_auto();
|
|
rq.open('POST', '/classify/' + user.id);
|
|
rq.setRequestHeader("Content-type", 'application/json');
|
|
rq.send(JSON.stringify("legit"));
|
|
rq.onreadystatechange = function() {
|
|
if ((this.readyState === 4) && (this.status === 200)) {
|
|
setTimeout(function () {
|
|
textbox.removeChild(userBox);
|
|
}, ((mass_update === true) ? 500 : 10000));
|
|
}
|
|
};
|
|
profile_groups.removeChild(classify_legit);
|
|
};
|
|
if (group_set.auto_legit && (!user.pending)) {
|
|
auto_mark[user.id] = do_classify;
|
|
}
|
|
|
|
classify_legit.onclick = do_classify;
|
|
profile_groups.appendChild(classify_legit);
|
|
}
|
|
if (!group_set.suspect) {
|
|
var classify_suspect = document.createElement('button');
|
|
classify_suspect.innerHTML = 'Suspect';
|
|
classify_suspect.onclick = function() {
|
|
var rq = new XMLHttpRequest();
|
|
rm_auto();
|
|
rq.open('POST', '/classify/' + user.id);
|
|
rq.setRequestHeader("Content-type", 'application/json');
|
|
rq.send(JSON.stringify("suspect"));
|
|
rq.onreadystatechange = function() {
|
|
if ((this.readyState === 4) && (this.status === 200)) {
|
|
setTimeout(function () {
|
|
textbox.removeChild(userBox);
|
|
}, 10000);
|
|
}
|
|
};
|
|
profile_groups.removeChild(classify_suspect);
|
|
};
|
|
profile_groups.appendChild(classify_suspect);
|
|
}
|
|
|
|
var defer_classify = document.createElement('button');
|
|
defer_classify.innerHTML = 'Defer';
|
|
defer_classify.onclick = function() {
|
|
var rq = new XMLHttpRequest();
|
|
rm_auto();
|
|
textbox.removeChild(userBox);
|
|
};
|
|
profile_groups.appendChild(defer_classify);
|
|
|
|
userBox.appendChild(profile_groups);
|
|
|
|
var profile_tags = document.createElement('div');
|
|
user.tags.forEach(function (tag) {
|
|
var tag_label = document.createElement('tt');
|
|
tag_label.innerHTML = tag;
|
|
profile_tags.appendChild(tag_label);
|
|
});
|
|
userBox.appendChild(profile_tags);
|
|
|
|
if (user.location) {
|
|
var profile_location = document.createElement('div');
|
|
profile_location.innerHTML = user.location;
|
|
userBox.appendChild(profile_location);
|
|
}
|
|
|
|
if (user.about_me) {
|
|
var profile_about_me = document.createElement('div');
|
|
profile_about_me.innerHTML = user.about_me;
|
|
userBox.appendChild(profile_about_me);
|
|
}
|
|
|
|
if (user.who_am_i) {
|
|
var profile_who_am_i = document.createElement('div');
|
|
profile_who_am_i.innerHTML = user.who_am_i;
|
|
userBox.appendChild(profile_who_am_i);
|
|
}
|
|
|
|
if (user.projects) {
|
|
var profile_projects = document.createElement('div');
|
|
profile_projects.innerHTML = user.projects + ' project(s)';
|
|
userBox.appendChild(profile_projects);
|
|
}
|
|
|
|
if (user.what_i_would_like_to_do) {
|
|
var profile_what_i_would_like_to_do = document.createElement('div');
|
|
profile_what_i_would_like_to_do.innerHTML = user.what_i_would_like_to_do;
|
|
userBox.appendChild(profile_what_i_would_like_to_do);
|
|
}
|
|
|
|
var links = document.createElement('ul');
|
|
user.links.forEach(function (link) {
|
|
var link_tag = document.createElement('a');
|
|
link_tag.href = link.url;
|
|
link_tag.appendChild(document.createTextNode(link.title + ' '));
|
|
var link_tt = document.createElement('tt');
|
|
link_tt.appendChild(document.createTextNode(
|
|
'<' + htmlEscape(link.url) + '>'));
|
|
link_tag.appendChild(link_tt);
|
|
|
|
var link_item = document.createElement('li');
|
|
link_item.appendChild(link_tag);
|
|
links.appendChild(link_item);
|
|
});
|
|
userBox.appendChild(links);
|
|
|
|
if (user.tokens && Object.keys(user.tokens).length) {
|
|
var profile_tokens = document.createElement('ul');
|
|
Object.keys(user.tokens).forEach(function (token) {
|
|
var token_li = document.createElement('li');
|
|
var token_tt = document.createElement('tt');
|
|
token_tt.innerHTML = htmlEscape(token);
|
|
token_li.appendChild(token_tt);
|
|
token_li.appendChild(document.createTextNode(' ' + user.tokens[token] + ' instances'));
|
|
profile_tokens.appendChild(token_li);
|
|
});
|
|
userBox.appendChild(profile_tokens);
|
|
}
|
|
|
|
/* Compute the user's score */
|
|
var user_score = [];
|
|
var first;
|
|
if (user.words && Object.keys(user.words).length) {
|
|
var profile_words = document.createElement('div');
|
|
first = false;
|
|
var words = Object.keys(user.words).map(function (word) {
|
|
var stat = user.words[word];
|
|
var score = 0.0;
|
|
if (stat.site_count > 0) {
|
|
score = Math.round((stat.site_score * 100)
|
|
/ stat.site_count) / 100;
|
|
user_score.push(score);
|
|
}
|
|
stat.word = word;
|
|
stat.norm_score = score;
|
|
return stat;
|
|
});
|
|
words.sort(function (a, b) {
|
|
if (a.norm_score < b.norm_score)
|
|
return -1;
|
|
else if (a.norm_score > b.norm_score)
|
|
return 1;
|
|
return 0;
|
|
});
|
|
words.forEach(function (stat) {
|
|
var word = stat.word;
|
|
var word_span = document.createElement('span');
|
|
var word_tt = document.createElement('tt');
|
|
var score = stat.norm_score;
|
|
|
|
word_tt.innerHTML = htmlEscape(word);
|
|
word_span.appendChild(word_tt);
|
|
word_span.title = stat.user_count
|
|
+ ' occurances; score: '
|
|
+ score;
|
|
word_span.style.backgroundColor = scoreColour(score);
|
|
if (first) {
|
|
profile_words.appendChild(
|
|
document.createTextNode(' ')
|
|
);
|
|
} else {
|
|
first = true;
|
|
}
|
|
profile_words.appendChild(word_span);
|
|
});
|
|
userBox.appendChild(profile_words);
|
|
}
|
|
|
|
if (user.word_adj && user.word_adj.length) {
|
|
var profile_word_adj = document.createElement('div');
|
|
first = false;
|
|
var word_adjs = user.word_adj.map(function (word_adj) {
|
|
var score = 0.0;
|
|
if (word_adj.site_count > 0) {
|
|
score = Math.round((word_adj.site_score * 100)
|
|
/ word_adj.site_count) / 100;
|
|
user_score.push(score);
|
|
}
|
|
word_adj.norm_score = score;
|
|
return word_adj;
|
|
});
|
|
word_adjs.sort(function (a, b) {
|
|
if (a.norm_score < b.norm_score)
|
|
return -1;
|
|
else if (a.norm_score > b.norm_score)
|
|
return 1;
|
|
return 0;
|
|
});
|
|
word_adjs.forEach(function (word_adj) {
|
|
var adj_span = document.createElement('span');
|
|
var adj_tt = document.createElement('tt');
|
|
var score = word_adj.norm_score;
|
|
|
|
adj_tt.innerHTML = htmlEscape(word_adj.proceeding)
|
|
+ ' → '
|
|
+ htmlEscape(word_adj.following);
|
|
adj_span.appendChild(adj_tt);
|
|
adj_span.title = word_adj.user_count
|
|
+ ' occurances; score: '
|
|
+ score;
|
|
if (first) {
|
|
profile_word_adj.appendChild(
|
|
document.createTextNode(' ')
|
|
);
|
|
} else {
|
|
first = true;
|
|
}
|
|
|
|
profile_word_adj.appendChild(adj_span);
|
|
|
|
/* Derive span colour */
|
|
adj_span.style.backgroundColor = scoreColour(score);
|
|
});
|
|
userBox.appendChild(profile_word_adj);
|
|
}
|
|
|
|
/* Compute user score */
|
|
if (user_score.length) {
|
|
user_score = Math.round(100*user_score.sort(function (a, b) {
|
|
if (a < b)
|
|
return -1;
|
|
else if (a > b)
|
|
return 1;
|
|
return 0;
|
|
}).slice(0, 5).reduce(function (a, b) {
|
|
return a + b;
|
|
})) / 100;
|
|
} else {
|
|
user_score = 0.0;
|
|
}
|
|
profile_score.innerHTML = 'Score: ' + user_score;
|
|
|
|
if (user_score < 0.0) {
|
|
profile_score_gauge_left.style.width = (16 * (10.0 + user_score)) + 'px';
|
|
profile_score_gauge_bar.style.width = (16 * (-user_score)) + 'px';
|
|
profile_score_gauge_right.style.width = '160px';
|
|
} else if (user_score > 0.0) {
|
|
profile_score_gauge_left.style.width = '160px';
|
|
profile_score_gauge_bar.style.width = (16 * (user_score)) + 'px';
|
|
profile_score_gauge_right.style.width = (16 * (10.0 - user_score)) + 'px';
|
|
} else {
|
|
profile_score_gauge_left.style.width = '155px';
|
|
profile_score_gauge_bar.style.width = '10px';
|
|
profile_score_gauge_right.style.width = '155px';
|
|
}
|
|
profile_score_gauge_bar.style.backgroundColor = scoreColour(user_score);
|
|
|
|
textbox.appendChild(userBox);
|
|
});
|
|
|
|
if (found && !displayed) {
|
|
setTimeout(getNextPage, 10);
|
|
}
|
|
}
|
|
busy = false;
|
|
}
|
|
} catch (err) {
|
|
busy = false;
|
|
throw err;
|
|
}
|
|
};
|
|
|
|
var uri = "/data/newcomers.json";
|
|
if (oldest_uid !== null)
|
|
uri += "?before_user_id=" + oldest_uid;
|
|
|
|
rq.open("GET", uri, true);
|
|
rq.send();
|
|
};
|
|
|
|
var main = function() {
|
|
window.onscroll = function(ev) {
|
|
if ((window.innerHeight + window.scrollY)
|
|
>= document.body.offsetHeight) {
|
|
if (!busy)
|
|
getNextPage();
|
|
}
|
|
};
|
|
|
|
textbox = document.getElementById('recent');
|
|
getNextPage();
|
|
};
|