1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-10-19 09:22:00 +00:00

I'm literally a terrible person. Just LOOK at this commit. I did some stuff. A lot of stuff. Too much stuff.

This commit is contained in:
SirStendec 2015-05-17 19:02:57 -04:00
parent e1cfb17081
commit 576c9569b2
22 changed files with 1977 additions and 454 deletions

171
src/ember/channel.js Normal file
View file

@ -0,0 +1,171 @@
var FFZ = window.FrankerFaceZ,
utils = require('../utils'),
constants = require('../constants');
// --------------------
// Initialization
// --------------------
FFZ.prototype.setup_channel = function() {
this.channels = {};
this.log("Creating channel style element.");
var s = this._channel_style = document.createElement('style');
s.id = "ffz-channel-css";
document.head.appendChild(s);
this.log("Hooking the Ember Channel view.");
var Channel = App.__container__.lookup('controller:channel'),
f = this;
if ( ! Channel )
return;
Channel.reopen({
ffzUpdateUptime: function() {
f.update_uptime();
}.observes("isLive", "content.id").on("init")
/*ffzUpdateInfo: function() {
f.log("Updated! ID: " + this.get("content.id"));
f.update_stream_info(true);
}.observes("content.id").on("init")*/
});
// Do uptime the first time.
this.update_uptime();
//this.update_stream_info(true);
}
// ---------------
// Settings
// ---------------
FFZ.settings_info.stream_uptime = {
type: "boolean",
value: false,
category: "Channel Metadata",
name: "Stream Uptime",
help: 'Display the stream uptime under a channel by the viewer count.',
on_update: function(val) {
this.update_uptime();
}
};
// --------------------
// Stream Data Update
// --------------------
/*FFZ.prototype.update_stream_info = function(just_schedule) {
if ( this._stream_info_update ) {
clearTimeout(this._stream_info_update);
delete this._stream_info_update;
}
this._stream_info_update = setTimeout(this.update_stream_info.bind(this), 90000);
if ( just_schedule )
return;
var Channel = App.__container__.lookup('controller:channel'),
channel_id = Channel ? Channel.get('content.id') : undefined,
f = this;
if ( ! channel_id )
return;
Twitch.api.get("streams/" + channel_id, {}, {version: 3})
.done(function(data) {
var channel_id = Channel.get('content.id'), d = data.stream;
if ( ! data.stream || d.channel.name != channel_id )
return;
// Override the data in Twitch. We can't just .load() the stream
// because that resets the whole channel layout, resetting the
// video player. Twitch pls fix
var old_created = Channel.get('content.stream.created_at');
Channel.set('content.stream.created_at', d.created_at);
Channel.set('content.stream.average_fps', d.average_fps);
Channel.set('content.stream.viewers', d.viewers);
Channel.set('content.stream.video_height', d.video_height);
Channel.set('content.stream.csGoSkill', Twitch.uri.csGoSkillImg(("0" + d.skill).slice(-2)));
Channel.set('content.stream.game', d.game);
Channel.set('content.stream.gameUrl', Twitch.uri.game(d.game));
Channel.set('content.stream.gameBoxart', Twitch.uri.gameBoxArtJpg(d.game));
// Update the uptime display.
if ( f.settings.stream_uptime && old_created != d.created_at )
f.update_uptime(true) && f.update_uptime();
});
}*/
// --------------------
// Uptime Display
// --------------------
FFZ.prototype.update_uptime = function(destroy) {
if ( this._uptime_update ) {
clearTimeout(this._uptime_update);
delete this._uptime_update;
}
var Channel = App.__container__.lookup('controller:channel');
if ( destroy || ! this.settings.stream_uptime || ! Channel || ! Channel.get('isLiveAccordingToKraken') ) {
var el = document.querySelector("#ffz-uptime-display");
if ( el )
el.parentElement.removeChild(el);
return;
}
// Schedule an update.
this._update_uptime = setTimeout(this.update_uptime.bind(this), 1000);
// Determine when the channel last went live.
var online = Channel.get('content.stream.created_at');
if ( ! online ) return;
online = utils.parse_date(online);
if ( ! online ) return;
var uptime = Math.floor((Date.now() - online.getTime()) / 1000);
if ( uptime < 0 ) return;
var el = document.querySelector("#ffz-uptime-display span");
if ( ! el ) {
var cont = document.querySelector("#channel .stats-and-actions .channel-stats");
if ( ! cont ) return;
var stat = document.createElement("span");
stat.className = "ffz stat";
stat.id = "ffz-uptime-display";
stat.title = "Stream Uptime <nobr>(since " + online.toLocaleString() + ")</nobr>";
stat.innerHTML = constants.CLOCK + " ";
el = document.createElement("span");
stat.appendChild(el);
var viewers = cont.querySelector(".live-count");
if ( viewers )
cont.insertBefore(stat, viewers.nextSibling);
else {
try {
viewers = cont.querySelector("script:nth-child(0n+2)");
cont.insertBefore(stat, viewers.nextSibling);
} catch(err) {
cont.insertBefore(stat, cont.childNodes[0]);
}
}
jQuery(stat).tipsy({html:true});
}
el.innerHTML = utils.time_to_string(uptime);
}

View file

@ -1,4 +1,4 @@
var FFZ = window.FrankerFaceZ,
var FFZ = window.FrankerFaceZ,
utils = require("../utils"),
reg_escape = function(str) {
@ -71,6 +71,106 @@ var FFZ = window.FrankerFaceZ,
var images = document.querySelectorAll('img[emote-id="' + id + '"]');
for(var x=0; x < images.length; x++)
images[x].title = tooltip;
},
build_link_tooltip = function(href) {
var link_data = this._link_data[href],
tooltip;
if ( ! link_data )
return "";
if ( link_data.tooltip )
return link_data.tooltip;
if ( link_data.type == "youtube" ) {
tooltip = "<b>YouTube: " + utils.sanitize(link_data.title) + "</b><hr>";
tooltip += "Channel: " + utils.sanitize(link_data.channel) + " | " + utils.time_to_string(link_data.duration) + "<br>";
tooltip += utils.number_commas(link_data.views||0) + " Views | &#128077; " + utils.number_commas(link_data.likes||0) + " &#128078; " + utils.number_commas(link_data.dislikes||0);
} else if ( link_data.type == "strawpoll" ) {
tooltip = "<b>Strawpoll: " + utils.sanitize(link_data.title) + "</b><hr><table><tbody>";
for(var key in link_data.items) {
var votes = link_data.items[key],
percentage = Math.floor((votes / link_data.total) * 100);
tooltip += '<tr><td style="text-align:left">' + utils.sanitize(key) + '</td><td style="text-align:right">' + utils.number_commas(votes) + "</td></tr>";
}
tooltip += "</tbody></table><hr>Total: " + utils.number_commas(link_data.total);
var fetched = utils.parse_date(link_data.fetched);
if ( fetched ) {
var age = Math.floor((fetched.getTime() - Date.now()) / 1000);
if ( age > 60 )
tooltip += "<br><small>Data was cached " + utils.time_to_string(age) + " ago.</small>";
}
} else if ( link_data.type == "twitch" ) {
tooltip = "<b>Twitch: " + utils.sanitize(link_data.display_name) + "</b><hr>";
var since = utils.parse_date(link_data.since);
if ( since )
tooltip += "Member Since: " + utils.date_string(since) + "<br>";
tooltip += "<nobr>Views: " + utils.number_commas(link_data.views) + "</nobr> | <nobr>Followers: " + utils.number_commas(link_data.followers) + "</nobr>";
} else if ( link_data.type == "twitter" ) {
tooltip = "<b>Tweet By: " + utils.sanitize(link_data.user) + "</b><hr>";
tooltip += utils.sanitize(link_data.tweet);
} else if ( link_data.type == "reputation" ) {
tooltip = '<span style="word-wrap: break-word">' + utils.sanitize(link_data.full.toLowerCase()) + '</span>';
if ( link_data.trust < 50 || link_data.safety < 50 || (link_data.tags && link_data.tags.length > 0) ) {
tooltip += "<hr>";
var had_extra = false;
if ( link_data.trust < 50 || link_data.safety < 50 ) {
link_data.unsafe = true;
tooltip += "<b>Potentially Unsafe Link</b><br>";
tooltip += "Trust: " + link_data.trust + "% | Child Safety: " + link_data.safety + "%";
had_extra = true;
}
if ( link_data.tags && link_data.tags.length > 0 )
tooltip += (had_extra ? "<br>" : "") + "Tags: " + link_data.tags.join(", ");
tooltip += "<br>Data Source: WOT";
}
} else if ( link_data.full )
tooltip = '<span style="word-wrap: break-word">' + utils.sanitize(link_data.full.toLowerCase()) + '</span>';
if ( ! tooltip )
tooltip = '<span style="word-wrap: break-word">' + utils.sanitize(href.toLowerCase()) + '</span>';
link_data.tooltip = tooltip;
return tooltip;
},
load_link_data = function(href, success, data) {
if ( ! success )
return;
this._link_data[href] = data;
data.unsafe = false;
var tooltip = build_link_tooltip.bind(this)(href), links,
no_trail = href.charAt(href.length-1) == "/" ? href.substr(0, href.length-1) : null;
if ( no_trail )
links = document.querySelectorAll('span.message a[href="' + href + '"], span.message a[href="' + no_trail + '"], span.message a[data-url="' + href + '"], span.message a[data-url="' + no_trail + '"]');
else
links = document.querySelectorAll('span.message a[href="' + href + '"], span.message a[data-url="' + href + '"]');
if ( ! this.settings.link_info )
return;
for(var x=0; x < links.length; x++) {
if ( data.unsafe )
links[x].classList.add('unsafe-link');
if ( ! links[x].classList.contains('deleted-link') )
links[x].title = tooltip;
}
};
@ -78,24 +178,13 @@ var FFZ = window.FrankerFaceZ,
// Settings
// ---------------------
FFZ.settings_info.capitalize = {
type: "boolean",
value: true,
category: "Chat",
visible: function() { return ! this.has_bttv },
name: "Username Capitalization",
help: "Display names in chat with proper capitalization."
};
FFZ.settings_info.banned_words = {
type: "button",
value: [],
category: "Chat",
visible: function() { return ! this.has_bttv },
no_bttv: true,
//visible: function() { return ! this.has_bttv },
name: "Banned Words",
help: "Set a list of words that will be locally removed from chat messages.",
@ -126,7 +215,8 @@ FFZ.settings_info.keywords = {
value: [],
category: "Chat",
visible: function() { return ! this.has_bttv },
no_bttv: true,
//visible: function() { return ! this.has_bttv },
name: "Highlight Keywords",
help: "Set additional keywords that will be highlighted in chat.",
@ -158,7 +248,8 @@ FFZ.settings_info.fix_color = {
value: true,
category: "Chat",
visible: function() { return ! this.has_bttv },
no_bttv: true,
//visible: function() { return ! this.has_bttv },
name: "Adjust Username Colors",
help: "Ensure that username colors contrast with the background enough to be readable.",
@ -172,12 +263,26 @@ FFZ.settings_info.fix_color = {
};
FFZ.settings_info.link_info = {
type: "boolean",
value: true,
category: "Chat",
no_bttv: true,
//visible: function() { return ! this.has_bttv },
name: "Link Tooltips <span>Beta</span>",
help: "Check links against known bad websites, unshorten URLs, and show YouTube info."
};
FFZ.settings_info.chat_rows = {
type: "boolean",
value: false,
category: "Chat",
visible: function() { return ! this.has_bttv },
no_bttv: true,
//visible: function() { return ! this.has_bttv },
name: "Chat Line Backgrounds",
help: "Display alternating background colors for lines in chat.",
@ -211,6 +316,7 @@ FFZ.prototype.setup_line = function() {
// Emoticon Data
this._twitch_emotes = {};
this._link_data = {};
this.log("Hooking the Ember Line controller.");
@ -232,6 +338,11 @@ FFZ.prototype.setup_line = function() {
if ( ! user || this.get("model.from") != user.login )
tokens = f._mentionize(this, tokens);
// Store the capitalization.
var display = this.get("model.tags.display-name");
if ( display && display.length )
FFZ.capitalization[this.get("model.from")] = [display.trim(), Date.now()];
var end = performance.now();
if ( end - start > 5 )
f.log("Tokenizing Message Took Too Long - " + (end-start) + "ms", tokens, false, true);
@ -265,7 +376,6 @@ FFZ.prototype.setup_line = function() {
row_type = controller.get('model.ffz_alternate');
// Color Processing
if ( color )
f._handle_color(color);
@ -290,11 +400,6 @@ FFZ.prototype.setup_line = function() {
f.render_badge(this);
// Capitalization
if ( f.settings.capitalize )
f.capitalize(this, user);
// Mention Highlighting
var mentioned = el.querySelector('span.mentioned');
if ( mentioned ) {
@ -357,12 +462,52 @@ FFZ.prototype.setup_line = function() {
this.target = "_new";
this.textContent = link;
// Now, check for a tooltip.
var link_data = f._link_data[link];
if ( link_data && typeof link_data != "boolean" ) {
this.title = link_data.tooltip;
if ( link_data.unsafe )
this.classList.add('unsafe-link');
}
// Stop from Navigating
e.preventDefault();
});
// Also add a nice tooltip.
jQuery(link).tipsy();
jQuery(link).tipsy({html:true});
}
// Link Tooltips
if ( f.settings.link_info ) {
var links = el.querySelectorAll("span.message a");
for(var i=0; i < links.length; i++) {
var link = links[i],
href = link.href,
deleted = false;
if ( link.classList.contains("deleted-link") ) {
href = link.getAttribute("data-url");
deleted = true;
}
// Check the cache.
var link_data = f._link_data[href];
if ( link_data ) {
if ( !deleted && typeof link_data != "boolean" )
link.title = link_data.tooltip;
if ( link_data.unsafe )
link.classList.add('unsafe-link');
} else if ( ! /^mailto:/.test(href) ) {
f._link_data[href] = true;
f.ws_send("get_link", href, load_link_data.bind(f, href));
}
}
jQuery(links).tipsy({html:true});
}
@ -536,16 +681,6 @@ FFZ.get_capitalization = function(name, callback) {
}
FFZ.prototype.capitalize = function(view, user) {
var name = FFZ.get_capitalization(user, this.capitalize.bind(this, view));
if ( !name || !view )
return;
var from = view.$('.from');
from && from.text(name);
}
// ---------------------
// Extra Mentions
// ---------------------

View file

@ -5,7 +5,8 @@ var FFZ = window.FrankerFaceZ,
ESC: 27,
P: 80,
B: 66,
T: 84
T: 84,
U: 85
},
btns = [
@ -27,7 +28,8 @@ FFZ.settings_info.enhanced_moderation = {
type: "boolean",
value: false,
visible: function() { return ! this.has_bttv },
no_bttv: true,
//visible: function() { return ! this.has_bttv },
category: "Chat",
name: "Enhanced Moderation",
@ -41,32 +43,33 @@ FFZ.settings_info.enhanced_moderation = {
FFZ.prototype.setup_mod_card = function() {
this.log("Hooking the Ember Moderation Card view.");
var Card = App.__container__.resolve('view:moderation-card'),
var Card = App.__container__.resolve('component:moderation-card'),
f = this;
Card.reopen({
didInsertElement: function() {
this._super();
window._card = this;
try {
if ( f.has_bttv || ! f.settings.enhanced_moderation )
return;
var el = this.get('element'),
controller = this.get('context');
controller = this.get('controller');
// Style it!
el.classList.add('ffz-moderation-card');
// Only do the big stuff if we're mod.
if ( controller.get('parentController.model.isModeratorOrHigher') ) {
if ( controller.get('cardInfo.isModeratorOrHigher') ) {
el.classList.add('ffz-is-mod');
el.setAttribute('tabindex', 1);
// Key Handling
el.addEventListener('keyup', function(e) {
var key = e.keyCode || e.which,
user_id = controller.get('model.user.id'),
room = controller.get('parentController.model');
user_id = controller.get('cardInfo.user.id'),
room = App.__container__.lookup('controller:chat').get('currentRoom');
if ( key == keycodes.P )
room.send("/timeout " + user_id + " 1");
@ -77,6 +80,9 @@ FFZ.prototype.setup_mod_card = function() {
else if ( key == keycodes.T )
room.send("/timeout " + user_id + " 600");
else if ( key == keycodes.U )
room.send("/unban " + user_id);
else if ( key != keycodes.ESC )
return;
@ -89,8 +95,8 @@ FFZ.prototype.setup_mod_card = function() {
line.className = 'interface clearfix';
var btn_click = function(timeout) {
var user_id = controller.get('model.user.id'),
room = controller.get('parentController.model');
var user_id = controller.get('cardInfo.user.id'),
room = App.__container__.lookup('controller:chat').get('currentRoom');
if ( timeout === -1 )
room.send("/unban " + user_id);
@ -151,8 +157,9 @@ FFZ.prototype.setup_mod_card = function() {
// More Fixing Other Buttons
var op_btn = el.querySelector('button.mod');
if ( op_btn ) {
var model = controller.get('parentController.model'),
can_op = model.get('isBroadcaster') || model.get('isStaff') || model.get('isAdmin');
var is_owner = controller.get('cardInfo.isChannelOwner'),
user = ffz.get_user();
can_op = is_owner || (user && user.is_admin) || (user && user.is_staff);
if ( ! can_op )
op_btn.parentElement.removeChild(op_btn);
@ -160,7 +167,7 @@ FFZ.prototype.setup_mod_card = function() {
var msg_btn = el.querySelector(".interface > button");
if ( msg_btn && msg_btn.className == "button" ) {
if ( msg_btn && msg_btn.classList.contains("message-button") ) {
msg_btn.innerHTML = MESSAGE;
msg_btn.classList.add('glyph-only');
msg_btn.classList.add('message');

View file

@ -28,6 +28,16 @@ FFZ.prototype.setup_room = function() {
this.log("Hooking the Ember Room model.");
// Responsive ban button.
var RC = App.__container__.lookup('controller:room');
if ( RC ) {
var orig_action = RC._actions.banUser;
RC._actions.banUser = function(e) {
orig_action.bind(this)(e);
this.get("model").clearMessages(e.user);
}
}
var Room = App.__container__.resolve('model:room');
this._modify_room(Room);
@ -287,8 +297,7 @@ FFZ.prototype._modify_room = function(room) {
var suggestions = this._super();
try {
if ( f.settings.capitalize )
suggestions = _.map(suggestions, FFZ.get_capitalization);
suggestions = _.map(suggestions, FFZ.get_capitalization);
} catch(err) {
f.error("get_suggestions: " + err);
}