mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-27 21:05:53 +00:00
3.5.41 to 3.5.50. Viewer list sorting is now optional. CSS is now embedded in the script to prevent loading issues. Started testing new socket server. Added chat batching option to display new messages in batches for performance reasons. Changed socket server rotation logic. Added error checks for Stream Latency. Socket protocol now uses ok instead of True. Added deploy and clear_cache commands to gulp for convenience.
This commit is contained in:
parent
05db9ea5eb
commit
10da2b4fd5
13 changed files with 371 additions and 85 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,5 +6,6 @@ Extension Building
|
|||
*.iml
|
||||
script.js
|
||||
script.min.js
|
||||
credentials.json
|
||||
|
||||
/socketserver/cmd/socketserver/socketserver
|
||||
|
|
101
gulpfile.js
101
gulpfile.js
|
@ -13,7 +13,13 @@ var fs = require('fs'),
|
|||
// Templates
|
||||
var jsEscape = require('gulp-js-escape'),
|
||||
wrap = require('gulp-wrap'),
|
||||
declare = require('gulp-declare');
|
||||
declare = require('gulp-declare'),
|
||||
minifyCss = require('gulp-minify-css');
|
||||
|
||||
|
||||
// Deploy Dependencies
|
||||
var ftp = require('vinyl-ftp'),
|
||||
request = require('request');
|
||||
|
||||
|
||||
// Server Dependencies
|
||||
|
@ -56,7 +62,25 @@ gulp.task('templates', ['prepare'], function() {
|
|||
});
|
||||
|
||||
|
||||
gulp.task('scripts', ['prepare', 'templates'], function() {
|
||||
gulp.task('styles', ['prepare'], function() {
|
||||
gulp.src(['build/styles/**/*.css'])
|
||||
.pipe(minifyCss())
|
||||
.pipe(jsEscape())
|
||||
.pipe(declare({
|
||||
root: 'exports',
|
||||
noRedeclare: true,
|
||||
processName: function(filePath) {
|
||||
var match = filePath.match(/build[\\\/]styles[\\\/](.*)\.css$/);
|
||||
return declare.processNameByPath((match && match.length > 1) ? match[1] : filePath);
|
||||
}
|
||||
}))
|
||||
.pipe(concat('styles.js'))
|
||||
.pipe(gulp.dest('build/'))
|
||||
.on('error', util.log)
|
||||
});
|
||||
|
||||
|
||||
gulp.task('scripts', ['prepare', 'templates', 'styles'], function() {
|
||||
gulp.src(['build/main.js'])
|
||||
.pipe(browserify())
|
||||
.pipe(concat('script.js'))
|
||||
|
@ -76,6 +100,79 @@ gulp.task('watch', ['default', 'server'], function() {
|
|||
gulp.task('default', ['scripts']);
|
||||
|
||||
|
||||
// Deploy
|
||||
|
||||
gulp.task('upload', ['default'], function() {
|
||||
// Load credentials from an external file.
|
||||
var contents = fs.readFileSync('credentials.json', 'utf8'),
|
||||
cred = JSON.parse(contents);
|
||||
|
||||
cred.log = util.log;
|
||||
|
||||
// Create the connection.
|
||||
var conn = ftp.create(cred);
|
||||
|
||||
// What we're transfering.
|
||||
var ftp_path = cred.remote_path,
|
||||
|
||||
globs = [
|
||||
"script.min.js",
|
||||
"style.css",
|
||||
"dark.css",
|
||||
"changelog.html"
|
||||
];
|
||||
|
||||
util.log(cred.remote_path);
|
||||
|
||||
return gulp.src(globs, {base: '.', buffer: false})
|
||||
.pipe(conn.newerOrDifferentSize(ftp_path))
|
||||
.pipe(conn.dest(ftp_path))
|
||||
.on('error', util.log);
|
||||
});
|
||||
|
||||
gulp.task('clear_cache', ['upload'], function() {
|
||||
// Load credentials from an external file.
|
||||
var contents = fs.readFileSync('credentials.json', 'utf8'),
|
||||
cred = JSON.parse(contents);
|
||||
|
||||
// Build the URLs.
|
||||
var base = "://cdn.frankerfacez.com/script/",
|
||||
files = [],
|
||||
globs = [
|
||||
"script.min.js",
|
||||
"style.css",
|
||||
"dark.css",
|
||||
"changelog.html"
|
||||
];
|
||||
|
||||
for(var i=0; i < globs.length; i++) {
|
||||
files.push("http" + base + globs[i]);
|
||||
files.push("https" + base + globs[i]);
|
||||
}
|
||||
|
||||
request({
|
||||
method: 'DELETE',
|
||||
uri: "https://api.cloudflare.com/client/v4/zones/" + cred.cloudflare_zone + "/purge_cache",
|
||||
headers: {
|
||||
"X-Auth-Email": cred.cloudflare_email,
|
||||
"X-Auth-Key": cred.cloudflare_key
|
||||
},
|
||||
json: {
|
||||
"files": files
|
||||
}
|
||||
}, function(error, request, body) {
|
||||
if ( error )
|
||||
return util.log("[FAIL] Error: " + error);
|
||||
else if ( request.statusCode !== 200 )
|
||||
return util.log("[FAIL] Non-200 Status: " + request.statusCode);
|
||||
|
||||
util.log("[SUCCESS] Cache cleared.");
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('deploy', ['upload', 'clear_cache']);
|
||||
|
||||
|
||||
// Server
|
||||
|
||||
gulp.task('server', function() {
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
"gulp-footer": "^1.0.5",
|
||||
"gulp-header": "^1.2.2",
|
||||
"gulp-js-escape": "^1.0.1",
|
||||
"gulp-minify-css": "^1.2.1",
|
||||
"gulp-rename": "^1.2.0",
|
||||
"gulp-uglify": "^1.0.2",
|
||||
"gulp-util": "^3.0.2",
|
||||
"gulp-wrap": "^0.11.0",
|
||||
"request": "^2.51.0"
|
||||
"request": "^2.65.0",
|
||||
"vinyl-ftp": "^0.4.5"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
var SVGPATH = '<path d="m120.95 1.74c4.08-0.09 8.33-0.84 12.21 0.82 3.61 1.8 7 4.16 11.01 5.05 2.08 3.61 6.12 5.46 8.19 9.07 3.6 5.67 7.09 11.66 8.28 18.36 1.61 9.51 7.07 17.72 12.69 25.35 3.43 7.74 1.97 16.49 3.6 24.62 2.23 5.11 4.09 10.39 6.76 15.31 1.16 2 4.38 0.63 4.77-1.32 1.2-7.1-2.39-13.94-1.97-21.03 0.38-3.64-0.91-7.48 0.25-10.99 2.74-3.74 4.57-8.05 7.47-11.67 3.55-5.47 10.31-8.34 16.73-7.64 2.26 2.89 5.13 5.21 7.58 7.92 2.88 4.3 6.52 8.01 9.83 11.97 1.89 2.61 3.06 5.64 4.48 8.52 2.81 4.9 4 10.5 6.63 15.49 2.16 6.04 5.56 11.92 5.37 18.5 0.65 1.95 0.78 4 0.98 6.03 1.01 3.95 2.84 8.55 0.63 12.42-2.4 5.23-7.03 8.97-11.55 12.33-6.06 4.66-11.62 10.05-18.37 13.75-4.06 2.65-8.24 5.17-12.71 7.08-3.59 1.57-6.06 4.94-9.85 6.09-2.29 1.71-3.98 4.51-6.97 5.02-4.56 1.35-8.98-3.72-13.5-1.25-2.99 1.83-6.19 3.21-9.39 4.6-8.5 5.61-18.13 9.48-28.06 11.62-8.36-0.2-16.69 0.62-25.05 0.47-3.5-1.87-7.67-1.08-11.22-2.83-6.19-1.52-10.93-6.01-16.62-8.61-2.87-1.39-5.53-3.16-8.11-4.99-2.58-1.88-4.17-4.85-6.98-6.44-3.83-0.11-6.54 3.42-10.24 3.92-2.31 0.28-4.64 0.32-6.96 0.31-3.5-3.65-5.69-8.74-10.59-10.77-5.01-3.68-10.57-6.67-14.84-11.25-2.52-2.55-5.22-4.87-8.24-6.8-4.73-4.07-7.93-9.51-11.41-14.62-3.08-4.41-5.22-9.73-4.6-15.19 0.65-8.01 0.62-16.18 2.55-24.02 4.06-10.46 11.15-19.34 18.05-28.06 3.71-5.31 9.91-10.21 16.8-8.39 3.25 1.61 5.74 4.56 7.14 7.89 1.19 2.7 3.49 4.93 3.87 7.96 0.97 5.85 1.6 11.86 0.74 17.77-1.7 6.12-2.98 12.53-2.32 18.9 0.01 2.92 2.9 5.36 5.78 4.57 3.06-0.68 3.99-4.07 5.32-6.48 1.67-4.06 4.18-7.66 6.69-11.23 3.61-5.28 5.09-11.57 7.63-17.37 2.07-4.56 1.7-9.64 2.56-14.46 0.78-7.65-0.62-15.44 0.7-23.04 1.32-3.78 1.79-7.89 3.8-11.4 3.01-3.66 6.78-6.63 9.85-10.26 1.72-2.12 4.21-3.32 6.55-4.6 7.89-2.71 15.56-6.75 24.06-7z"/>',
|
||||
|
||||
DEBUG = localStorage.ffzDebugMode == "true" && document.body.classList.contains('ffz-dev'),
|
||||
WS_SERVERS = DEBUG ? ["localhost:8001", "catbag.frankerfacez.com"] : ["catbag.frankerfacez.com"],
|
||||
SERVER = DEBUG ? "//localhost:8000/" : "//cdn.frankerfacez.com/";
|
||||
|
||||
module.exports = {
|
||||
DEBUG: DEBUG,
|
||||
SERVER: SERVER,
|
||||
WS_SERVERS: WS_SERVERS,
|
||||
API_SERVER: "//api.frankerfacez.com/",
|
||||
API_SERVER_2: "//direct-api.frankerfacez.com/",
|
||||
|
||||
WS_SERVER_POOLS: {
|
||||
1: ["ws://catbag.frankerfacez.com/", "ws://andknuckles.frankerfacez.com/"],
|
||||
2: ["ws://localhost:8001/"]
|
||||
},
|
||||
|
||||
KNOWN_CODES: {
|
||||
"#-?[\\\\/]": "#-/",
|
||||
":-?(?:7|L)": ":-7",
|
||||
|
|
|
@ -456,8 +456,14 @@ FFZ.prototype._modify_cindex = function(view) {
|
|||
el = stat_el && stat_el.querySelector('span'),
|
||||
|
||||
player_cont = f.players && f.players[channel_id],
|
||||
player = player_cont && player_cont.ffz_player,
|
||||
player = undefined, stats = undefined;
|
||||
|
||||
try {
|
||||
player = player_cont && player_cont.ffz_player;
|
||||
stats = player && player.stats;
|
||||
} catch(err) {
|
||||
f.error("Channel ffzUpdatePlayerStats: player.stats: " + err);
|
||||
}
|
||||
|
||||
if ( ! container || ! f.settings.player_stats || ! stats || stats.hlsLatencyBroadcaster === 'NaN' || stats.hlsLatencyBroadcaster === NaN ) {
|
||||
if ( stat_el )
|
||||
|
@ -508,8 +514,14 @@ FFZ.prototype._modify_cindex = function(view) {
|
|||
el = stat_el && stat_el.querySelector('span'),
|
||||
|
||||
player_cont = f.players && f.players[hosted_id],
|
||||
player = player_cont && player_cont.ffz_player,
|
||||
player = undefined, stats = undefined;
|
||||
|
||||
try {
|
||||
player = player_cont && player_cont.ffz_player;
|
||||
stats = player && player.stats;
|
||||
} catch(err) {
|
||||
f.error("Channel ffzUpdatePlayerStats: player.stats: " + err);
|
||||
}
|
||||
|
||||
|
||||
if ( ! container || ! f.settings.player_stats || ! stats || stats.hlsLatencyBroadcaster === 'NaN' || stats.hlsLatencyBroadcaster === NaN ) {
|
||||
|
|
|
@ -98,6 +98,36 @@ FFZ.settings_info.minimal_chat = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.chat_batching = {
|
||||
type: "select",
|
||||
options: {
|
||||
0: "No Batching",
|
||||
250: "Minor (0.25s)",
|
||||
500: "Normal (0.5s)",
|
||||
750: "Large (0.75s)",
|
||||
1000: "Extreme (1s)"
|
||||
},
|
||||
value: 0,
|
||||
|
||||
category: "Chat Appearance",
|
||||
no_bttv: true,
|
||||
|
||||
name: "Chat Message Batching",
|
||||
help: "Display chat messages in batches to improve performance in <em>extremely</em> fast chats.",
|
||||
|
||||
process_value: function(val) {
|
||||
if ( typeof val === "string" )
|
||||
return parseInt(val) || 0;
|
||||
return val;
|
||||
},
|
||||
|
||||
on_update: function(val) {
|
||||
if ( this._roomv )
|
||||
this._roomv.ffzUpdateStatus();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FFZ.settings_info.chat_delay = {
|
||||
type: "select",
|
||||
options: {
|
||||
|
|
|
@ -159,14 +159,23 @@ FFZ.prototype._modify_player = function(player) {
|
|||
return;
|
||||
|
||||
player = tp2.getPlayer();
|
||||
if ( ! player )
|
||||
if ( ! player || ! player.getVideo )
|
||||
// We can't get a valid player. :-(
|
||||
return;
|
||||
}
|
||||
|
||||
this.set('ffz_player', player);
|
||||
|
||||
// Only set up the stats hooks if we need stats.
|
||||
if ( ! player.getVideo() )
|
||||
var has_video;
|
||||
|
||||
try {
|
||||
has_video = player.getVideo();
|
||||
} catch(err) {
|
||||
f.error("Player2 ffzPostPlayer: getVideo: " + err);
|
||||
}
|
||||
|
||||
if ( ! has_video )
|
||||
this.ffzInitStats();
|
||||
},
|
||||
|
||||
|
@ -186,7 +195,7 @@ FFZ.prototype._modify_player = function(player) {
|
|||
player.ffz_stats = player.getStatsEnabled();
|
||||
} catch(err) {
|
||||
// Assume stats are off.
|
||||
f.log("player ffzInitStats: getStatsEnabled still doesn't work: " + err);
|
||||
f.error("Player2 ffzInitStats: getStatsEnabled still doesn't work: " + err);
|
||||
player.ffz_stats = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ FFZ.prototype._modify_rview = function(view) {
|
|||
slow_badge = cont.querySelector('#ffz-stat-slow'),
|
||||
banned_badge = cont.querySelector('#ffz-stat-banned'),
|
||||
delay_badge = cont.querySelector('#ffz-stat-delay'),
|
||||
batch_badge = cont.querySelector('#ffz-stat-batch'),
|
||||
btn = cont.querySelector('button');
|
||||
|
||||
if ( f.has_bttv || ! f.settings.room_status ) {
|
||||
|
@ -199,6 +200,10 @@ FFZ.prototype._modify_rview = function(view) {
|
|||
sub_badge.parentElement.removeChild(sub_badge);
|
||||
if ( slow_badge )
|
||||
slow_badge.parentElement.removeChild(slow_badge);
|
||||
if ( delay_badge )
|
||||
delay_badge.parentElement.removeChild(delay_badge);
|
||||
if ( batch_badge )
|
||||
batch_badge.parentElement.removeChild(batch_badge);
|
||||
|
||||
if ( btn )
|
||||
btn.classList.remove('ffz-waiting');
|
||||
|
@ -209,7 +214,7 @@ FFZ.prototype._modify_rview = function(view) {
|
|||
r9k_badge = document.createElement('span');
|
||||
r9k_badge.className = 'ffz room-state stat float-right';
|
||||
r9k_badge.id = 'ffz-stat-r9k';
|
||||
r9k_badge.innerHTML = 'R9K';
|
||||
r9k_badge.innerHTML = 'R<span>9K</span>';
|
||||
r9k_badge.title = "This room is in R9K-mode.";
|
||||
cont.appendChild(r9k_badge);
|
||||
jQuery(r9k_badge).tipsy({gravity:"s", offset:15});
|
||||
|
@ -219,7 +224,7 @@ FFZ.prototype._modify_rview = function(view) {
|
|||
sub_badge = document.createElement('span');
|
||||
sub_badge.className = 'ffz room-state stat float-right';
|
||||
sub_badge.id = 'ffz-stat-sub';
|
||||
sub_badge.innerHTML = 'SUB';
|
||||
sub_badge.innerHTML = 'S<span>UB</span>';
|
||||
sub_badge.title = "This room is in subscribers-only mode.";
|
||||
cont.appendChild(sub_badge);
|
||||
jQuery(sub_badge).tipsy({gravity:"s", offset:15});
|
||||
|
@ -229,8 +234,7 @@ FFZ.prototype._modify_rview = function(view) {
|
|||
slow_badge = document.createElement('span');
|
||||
slow_badge.className = 'ffz room-state stat float-right';
|
||||
slow_badge.id = 'ffz-stat-slow';
|
||||
slow_badge.innerHTML = 'SLOW';
|
||||
slow_badge.title = "This room is in slow mode. You may send messages every 120 seconds.";
|
||||
slow_badge.innerHTML = 'S<span>LOW</span>';
|
||||
cont.appendChild(slow_badge);
|
||||
jQuery(slow_badge).tipsy({gravity:"s", offset:15});
|
||||
}
|
||||
|
@ -239,7 +243,7 @@ FFZ.prototype._modify_rview = function(view) {
|
|||
banned_badge = document.createElement('span');
|
||||
banned_badge.className = 'ffz room-state stat float-right';
|
||||
banned_badge.id = 'ffz-stat-banned';
|
||||
banned_badge.innerHTML = 'BAN';
|
||||
banned_badge.innerHTML = 'B<span>AN</span>';
|
||||
banned_badge.title = "You have been banned from talking in this room.";
|
||||
cont.appendChild(banned_badge);
|
||||
jQuery(banned_badge).tipsy({gravity:"s", offset:15});
|
||||
|
@ -249,21 +253,54 @@ FFZ.prototype._modify_rview = function(view) {
|
|||
delay_badge = document.createElement('span');
|
||||
delay_badge.className = 'ffz room-state stat float-right';
|
||||
delay_badge.id = 'ffz-stat-delay';
|
||||
delay_badge.innerHTML = 'DELAY';
|
||||
delay_badge.title = "You have enabled artificial chat delay. Messages are displayed after 0.3 seconds.";
|
||||
delay_badge.innerHTML = 'D<span>ELAY</span>';
|
||||
cont.appendChild(delay_badge);
|
||||
jQuery(delay_badge).tipsy({gravity:"s", offset:15});
|
||||
}
|
||||
|
||||
r9k_badge.classList.toggle('hidden', !(room && room.get('r9k')));
|
||||
sub_badge.classList.toggle('hidden', !(room && room.get('subsOnly')));
|
||||
banned_badge.classList.toggle('hidden', !(room && room.get('ffz_banned')));
|
||||
if ( ! batch_badge ) {
|
||||
batch_badge = document.createElement('span');
|
||||
batch_badge.className = 'ffz room-state stat float-right';
|
||||
batch_badge.id = 'ffz-stat-batch';
|
||||
batch_badge.innerHTML = 'B<span>ATCH</span>';
|
||||
cont.appendChild(batch_badge);
|
||||
jQuery(batch_badge).tipsy({gravity:"s", offset:15});
|
||||
}
|
||||
|
||||
slow_badge.classList.toggle('hidden', !(room && room.get('slowMode')));
|
||||
var vis_count = 0,
|
||||
r9k_vis = room && room.get('r9k'),
|
||||
sub_vis = room && room.get('subsOnly'),
|
||||
ban_vis = room && room.get('ffz_banned'),
|
||||
slow_vis = room && room.get('slowMode'),
|
||||
delay_vis = f.settings.chat_delay !== 0,
|
||||
batch_vis = f.settings.chat_batching !== 0;
|
||||
|
||||
if ( r9k_vis ) vis_count += 1;
|
||||
if ( sub_vis ) vis_count += 1;
|
||||
if ( ban_vis ) vis_count += 1;
|
||||
if ( slow_vis ) vis_count += 1;
|
||||
if ( delay_vis ) vis_count += 1;
|
||||
if ( batch_vis ) vis_count += 1;
|
||||
|
||||
r9k_badge.classList.toggle('truncated', vis_count > 3);
|
||||
sub_badge.classList.toggle('truncated', vis_count > 3);
|
||||
banned_badge.classList.toggle('truncated', vis_count > 3);
|
||||
slow_badge.classList.toggle('truncated', vis_count > 3);
|
||||
delay_badge.classList.toggle('truncated', vis_count > 3);
|
||||
batch_badge.classList.toggle('truncated', vis_count > 3);
|
||||
|
||||
r9k_badge.classList.toggle('hidden', ! r9k_vis);
|
||||
sub_badge.classList.toggle('hidden', ! sub_vis);
|
||||
banned_badge.classList.toggle('hidden', ! ban_vis);
|
||||
|
||||
slow_badge.classList.toggle('hidden', ! slow_vis);
|
||||
slow_badge.title = "This room is in slow mode. You may send messages every " + utils.number_commas(room && room.get('slow')||120) + " seconds.";
|
||||
|
||||
delay_badge.title = "You have enabled artificial chat delay. Messages are displayed after " + (f.settings.chat_delay/1000) + " seconds.";
|
||||
delay_badge.classList.toggle('hidden', f.settings.chat_delay === 0);
|
||||
delay_badge.classList.toggle('hidden', ! delay_vis);
|
||||
|
||||
batch_badge.title = "You have enabled chat message batching. Messages are displayed in " + (f.settings.chat_batching/1000) + " second increments.";
|
||||
batch_badge.classList.toggle('hidden', ! batch_vis);
|
||||
|
||||
if ( btn ) {
|
||||
btn.classList.toggle('ffz-waiting', (room && room.get('slowWait') || 0));
|
||||
|
@ -1022,7 +1059,7 @@ FFZ.prototype._modify_room = function(room) {
|
|||
|
||||
// Artificial chat delay
|
||||
pushMessage: function(msg) {
|
||||
if ( f.settings.chat_delay !== 0 || (this.ffzPending && this.ffzPending.length) ) {
|
||||
if ( f.settings.chat_batching !== 0 || f.settings.chat_delay !== 0 || (this.ffzPending && this.ffzPending.length) ) {
|
||||
if ( ! this.ffzPending )
|
||||
this.ffzPending = [];
|
||||
|
||||
|
@ -1056,11 +1093,21 @@ FFZ.prototype._modify_room = function(room) {
|
|||
// Instead of just blindly looping every x seconds, we want to calculate the time until
|
||||
// the next message should be displayed, and then set the timeout for that. We'll
|
||||
// end up looping a bit more frequently, but it'll make chat feel more responsive.
|
||||
|
||||
// If we have a pending flush, don't reschedule. It wouldn't change.
|
||||
if ( this._ffz_pending_flush )
|
||||
clearTimeout(this._ffz_pending_flush);
|
||||
return;
|
||||
|
||||
/*if ( this._ffz_pending_flush )
|
||||
clearTimeout(this._ffz_pending_flush);*/
|
||||
|
||||
if ( this.ffzPending && this.ffzPending.length ) {
|
||||
var delay = 50 + Math.max(0, (f.settings.chat_delay + (this.ffzPending[0].time||0)) - (now || Date.now()));
|
||||
// We need either the amount of chat delay past the first message, if chat_delay is on, or the
|
||||
// amount of time from the last batch.
|
||||
var delay = Math.max(
|
||||
(f.settings.chat_delay !== 0 ? 50 + Math.max(0, (f.settings.chat_delay + (this.ffzPending[0].time||0)) - (now || Date.now())) : 0),
|
||||
(f.settings.chat_batching !== 0 ? Math.max(0, f.settings.chat_batching - ((now || Date.now()) - (this._ffz_last_batch||0))) : 0));
|
||||
|
||||
this._ffz_pending_flush = setTimeout(this.ffzPendingFlush.bind(this), delay);
|
||||
}
|
||||
},
|
||||
|
@ -1068,13 +1115,14 @@ FFZ.prototype._modify_room = function(room) {
|
|||
ffzPendingFlush: function() {
|
||||
this._ffz_pending_flush = null;
|
||||
|
||||
var now = Date.now();
|
||||
var now = this._ffz_last_batch = Date.now();
|
||||
|
||||
for (var i = 0, l = this.ffzPending.length; i < l; i++) {
|
||||
var msg = this.ffzPending[i];
|
||||
if ( msg.removed )
|
||||
continue;
|
||||
|
||||
if ( f.settings.chat_delay + msg.time > now )
|
||||
if ( f.settings.chat_delay !== 0 && (f.settings.chat_delay + msg.time > now) )
|
||||
break;
|
||||
|
||||
this.ffzActualPushMessage(msg);
|
||||
|
|
|
@ -22,7 +22,7 @@ FFZ.get = function() { return FFZ.instance; }
|
|||
|
||||
// Version
|
||||
var VER = FFZ.version_info = {
|
||||
major: 3, minor: 5, revision: 42,
|
||||
major: 3, minor: 5, revision: 50,
|
||||
toString: function() {
|
||||
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
|
||||
}
|
||||
|
|
170
src/socket.js
170
src/socket.js
|
@ -3,50 +3,106 @@ var FFZ = window.FrankerFaceZ,
|
|||
|
||||
FFZ.prototype._ws_open = false;
|
||||
FFZ.prototype._ws_delay = 0;
|
||||
FFZ.prototype._ws_last_iframe = 0;
|
||||
FFZ.prototype._ws_host_idx = Math.floor(Math.random() * constants.WS_SERVERS.length) + 1;
|
||||
if (constants.DEBUG) {
|
||||
FFZ.prototype._ws_host_idx = 0;
|
||||
}
|
||||
FFZ.prototype._ws_host_idx = -1;
|
||||
FFZ.prototype._ws_current_pool = -1;
|
||||
|
||||
|
||||
FFZ.ws_commands = {};
|
||||
FFZ.ws_on_close = [];
|
||||
|
||||
|
||||
// ----------------
|
||||
// Socket Creation
|
||||
// Settings
|
||||
// ----------------
|
||||
|
||||
// Attempt to authenticate to the socket server as a real browser by loading the root page.
|
||||
// e.g. cloudflare ddos check
|
||||
FFZ.prototype.ws_iframe = function() {
|
||||
this._ws_last_iframe = Date.now();
|
||||
var ifr = document.createElement('iframe'),
|
||||
f = this;
|
||||
var ffz_socket_seed;
|
||||
|
||||
ifr.src = 'http://catbag.frankerfacez.com';
|
||||
ifr.style.visibility = 'hidden';
|
||||
document.body.appendChild(ifr);
|
||||
setTimeout(function() {
|
||||
document.body.removeChild(ifr);
|
||||
if ( ! f._ws_open )
|
||||
f.ws_create();
|
||||
}, 2000);
|
||||
try {
|
||||
ffz_socket_seed = JSON.parse(localStorage.ffz_socket_seed);
|
||||
} catch(err) { }
|
||||
|
||||
if ( ! ffz_socket_seed ) {
|
||||
ffz_socket_seed = Math.random();
|
||||
localStorage.ffz_socket_seed = JSON.stringify(ffz_socket_seed);
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype.ws_create = function() {
|
||||
// Disable sockets for now.
|
||||
return;
|
||||
FFZ.settings_info.socket_server_pool = {
|
||||
type: "select",
|
||||
options: {
|
||||
0: "Disabled",
|
||||
1: "Production",
|
||||
2: "Development"
|
||||
},
|
||||
|
||||
value: ffz_socket_seed > 0.65 ? 1 : 0,
|
||||
|
||||
process_value: function(val) {
|
||||
if ( typeof val === "string" )
|
||||
return parseInt(val) || 0;
|
||||
return val;
|
||||
},
|
||||
|
||||
visible: function() { return (localStorage.hasOwnProperty('ffz_socket_server_pool') && this.settings.socket_server_pool !== 1) || this.settings.developer_mode || (Date.now() - parseInt(localStorage.ffzLastDevMode || "0")) < 604800000; },
|
||||
|
||||
category: "Debugging",
|
||||
name: "Socket Server Cluster",
|
||||
help: "Select which cluster of socket servers to connect to.",
|
||||
|
||||
on_update: function(val) {
|
||||
if ( val === this._ws_current_pool )
|
||||
return;
|
||||
|
||||
try {
|
||||
this._ws_sock.close();
|
||||
} catch(err) { }
|
||||
|
||||
this._ws_open = false;
|
||||
this._ws_delay = 0;
|
||||
this._ws_host_idx = -1;
|
||||
|
||||
if ( this._ws_recreate_timer ) {
|
||||
clearTimeout(this._ws_recreate_timer);
|
||||
this._ws_recreate_timer = null;
|
||||
}
|
||||
|
||||
if ( val === 0 )
|
||||
return;
|
||||
|
||||
this.ws_create();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ----------------
|
||||
// Socket Creation
|
||||
// ----------------
|
||||
|
||||
FFZ.prototype.ws_create = function() {
|
||||
var f = this, ws;
|
||||
|
||||
this._ws_last_req = 0;
|
||||
this._ws_callbacks = {};
|
||||
this._ws_last_req = 1;
|
||||
this._ws_callbacks = {1: f._ws_on_hello.bind(f)};
|
||||
this._ws_pending = this._ws_pending || [];
|
||||
this._ws_recreate_timer = null;
|
||||
|
||||
var pool_id = this.settings.socket_server_pool,
|
||||
pool = constants.WS_SERVER_POOLS[pool_id];
|
||||
|
||||
this._ws_current_pool = pool_id;
|
||||
|
||||
if ( ! pool )
|
||||
return;
|
||||
|
||||
if ( this._ws_host_idx < 0 )
|
||||
this._ws_host_idx = Math.floor(Math.random() * pool.length);
|
||||
|
||||
var server = pool[this._ws_host_idx];
|
||||
|
||||
this.log("Using Socket Server: " + server + " [" + pool_id + ":" + this._ws_host_idx + "]");
|
||||
|
||||
try {
|
||||
ws = this._ws_sock = new WebSocket("ws://" + constants.WS_SERVERS[this._ws_host_idx] + "/");
|
||||
ws = this._ws_sock = new WebSocket(pool[this._ws_host_idx]);
|
||||
} catch(err) {
|
||||
this._ws_exists = false;
|
||||
return this.log("Error Creating WebSocket: " + err);
|
||||
|
@ -57,10 +113,10 @@ FFZ.prototype.ws_create = function() {
|
|||
ws.onopen = function(e) {
|
||||
f._ws_open = true;
|
||||
f._ws_delay = 0;
|
||||
f._ws_last_iframe = Date.now();
|
||||
f.log("Socket connected.");
|
||||
f.log("Socket Connected.");
|
||||
|
||||
f.ws_send("hello", ["ffz_" + FFZ.version_info, localStorage.ffzClientId], f._ws_on_hello.bind(f));
|
||||
// Hard-code the first command.
|
||||
ws.send("1 hello " + JSON.stringify(["ffz_" + FFZ.version_info, localStorage.ffzClientId]));
|
||||
|
||||
var user = f.get_user();
|
||||
if ( user )
|
||||
|
@ -70,7 +126,6 @@ FFZ.prototype.ws_create = function() {
|
|||
if ( f.is_dashboard ) {
|
||||
var match = location.pathname.match(/\/([^\/]+)/);
|
||||
if ( match ) {
|
||||
f.ws_send("sub", "room." + match[1]);
|
||||
f.ws_send("sub", "channel." + match[1]);
|
||||
}
|
||||
}
|
||||
|
@ -124,13 +179,16 @@ FFZ.prototype.ws_create = function() {
|
|||
if ( ! f._ws_offline_time ) {
|
||||
f._ws_offline_time = new Date().getTime();
|
||||
}
|
||||
|
||||
// Cycle selected server
|
||||
f._ws_host_idx = (f._ws_host_idx + 1) % constants.WS_SERVERS.length;
|
||||
}
|
||||
|
||||
ws.onclose = function(e) {
|
||||
var was_open = f._ws_open;
|
||||
f.log("Socket closed. (Code: " + e.code + ", Reason: " + e.reason + ")");
|
||||
|
||||
// If a recreate is already scheduled, this is expected.
|
||||
if ( f._ws_recreate_timer )
|
||||
return;
|
||||
|
||||
f._ws_open = false;
|
||||
if ( ! f._ws_offline_time ) {
|
||||
f._ws_offline_time = new Date().getTime();
|
||||
|
@ -145,14 +203,11 @@ FFZ.prototype.ws_create = function() {
|
|||
}
|
||||
}
|
||||
|
||||
// Cycle selected server
|
||||
f._ws_host_idx = (f._ws_host_idx + 1) % constants.WS_SERVERS.length;
|
||||
|
||||
if ( f._ws_delay > 10000 ) {
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
if ( Date.now() - f._ws_last_iframe > 1800000 && !(ua.indexOf('chrome') === -1 && ua.indexOf('safari') !== -1) )
|
||||
return f.ws_iframe();
|
||||
}
|
||||
// Cycle selected server if our last attempt to connect didn't
|
||||
// actually connect.
|
||||
if ( ! was_open )
|
||||
// Actually, let's get a random new server instead.
|
||||
f._ws_host_idx = -1; //(f._ws_host_idx + 1) % pool.length;
|
||||
|
||||
// We never ever want to not have a socket.
|
||||
if ( f._ws_delay < 60000 )
|
||||
|
@ -161,7 +216,7 @@ FFZ.prototype.ws_create = function() {
|
|||
// Randomize delay.
|
||||
f._ws_delay = (Math.floor(Math.random()*60)+30)*1000;
|
||||
|
||||
setTimeout(f.ws_create.bind(f), f._ws_delay);
|
||||
f._ws_recreate_timer = setTimeout(f.ws_create.bind(f), f._ws_delay);
|
||||
}
|
||||
|
||||
ws.onmessage = function(e) {
|
||||
|
@ -193,7 +248,7 @@ FFZ.prototype.ws_create = function() {
|
|||
delete f._ws_callbacks[request];
|
||||
|
||||
} else {
|
||||
var success = cmd === 'True',
|
||||
var success = cmd === 'ok',
|
||||
has_callback = typeof f._ws_callbacks[request] === "function";
|
||||
|
||||
if ( ! has_callback )
|
||||
|
@ -251,7 +306,7 @@ FFZ.prototype._ws_on_hello = function(success, data) {
|
|||
localStorage.ffzClientId = data;
|
||||
this.log("Client ID: " + data);
|
||||
|
||||
var survey = {},
|
||||
/*var survey = {},
|
||||
set = survey['settings'] = {};
|
||||
|
||||
for(var key in FFZ.settings_info)
|
||||
|
@ -271,10 +326,35 @@ FFZ.prototype._ws_on_hello = function(success, data) {
|
|||
survey['language'] = navigator.language;
|
||||
survey['platform'] = navigator.platform;
|
||||
|
||||
this.ws_send("survey", [survey]);
|
||||
this.ws_send("survey", [survey]);*/
|
||||
}
|
||||
|
||||
|
||||
// ----------------
|
||||
// Reconnect Logic
|
||||
// ----------------
|
||||
|
||||
FFZ.ws_commands.reconnect = function() {
|
||||
this.log("Socket Reconnect Command Received");
|
||||
|
||||
// Set the socket as closed and close it.
|
||||
this._ws_open = false;
|
||||
this._ws_sock.close();
|
||||
|
||||
// Socket Close Callbacks
|
||||
for(var i=0; i < FFZ.ws_on_close.length; i++) {
|
||||
try {
|
||||
FFZ.ws_on_close[i].bind(this)();
|
||||
} catch(err) {
|
||||
this.log("Error on Socket Close Callback: " + err);
|
||||
}
|
||||
}
|
||||
|
||||
// Randomize the reconnect delay to avoid a complete hammering.
|
||||
this._ws_delay = Math.floor(Math.random() * 5) * 1000;
|
||||
this._ws_recreate_timer = setTimeout(this.ws_create.bind(this), this._ws_delay);
|
||||
}
|
||||
|
||||
|
||||
// ----------------
|
||||
// Authorization
|
||||
|
|
|
@ -850,6 +850,7 @@ span.ffz-handle:after { left: 8px }
|
|||
|
||||
|
||||
/* Chat Mentions */
|
||||
|
||||
.ember-chat .mentioned:empty,
|
||||
.ember-chat .mentioning:empty {
|
||||
display: none;
|
||||
|
@ -1155,7 +1156,7 @@ body:not(.ffz-chat-purge-icon) .ember-chat .mod-icons .purge { display: none; }
|
|||
.ffz-chat-background .ember-chat-container.dark .ember-chat .chat-messages .chat-line.ffz-mentioned.ffz-alternate:before {
|
||||
background-color: rgba(255,0,0, 0.3);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/* The New Whispers */
|
||||
|
||||
|
@ -1643,6 +1644,8 @@ body.ffz-minimal-chat-input .ember-chat .chat-interface .textarea-contain textar
|
|||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.ffz.room-state.truncated span { font-size: 8px; }
|
||||
|
||||
.button.primary.ffz-waiting:not(:hover) {
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
color: #32323e;
|
||||
|
@ -1932,28 +1935,28 @@ li[data-name="following"] a {
|
|||
.ffz-legacy-mod-badges .ember-chat .badges .moderator,
|
||||
.ffz-legacy-badges .ember-chat .badges .moderator {
|
||||
background-color: #068c10;
|
||||
background-image: url('legacy-mod.png');
|
||||
background-image: url('//cdn.frankerfacez.com/script/legacy-mod.png');
|
||||
}
|
||||
|
||||
.ffz-legacy-badges .ember-chat .badges .staff {
|
||||
background-color: #6441a5;
|
||||
background-image: url('legacy-staff.png');
|
||||
background-image: url('//cdn.frankerfacez.com/script/legacy-staff.png');
|
||||
}
|
||||
|
||||
.ffz-legacy-badges .ember-chat .badges .broadcaster {
|
||||
background-color: #000;
|
||||
background-image: url('legacy-broadcaster.png');
|
||||
background-image: url('//cdn.frankerfacez.com/script/legacy-broadcaster.png');
|
||||
}
|
||||
|
||||
.ffz-legacy-badges .ember-chat .badges .admin {
|
||||
background-color: #ff0303;
|
||||
background-image: url('legacy-admin.png');
|
||||
background-image: url('//cdn.frankerfacez.com/script/legacy-admin.png');
|
||||
}
|
||||
|
||||
.ffz-legacy-turbo-badges .ember-chat .badges .turbo,
|
||||
.ffz-legacy-badges .ember-chat .badges .turbo {
|
||||
background-color: #6441a3;
|
||||
background-image: url('legacy-turbo.png');
|
||||
background-image: url('//cdn.frankerfacez.com/script/legacy-turbo.png');
|
||||
}
|
||||
|
||||
/* High Contrast Chat */
|
|
@ -1,5 +1,6 @@
|
|||
var FFZ = window.FrankerFaceZ,
|
||||
constants = require("../constants");
|
||||
constants = require("../constants"),
|
||||
styles = require("../styles");
|
||||
|
||||
|
||||
// ---------------------
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
var FFZ = window.FrankerFaceZ,
|
||||
constants = require('../constants');
|
||||
constants = require('../constants'),
|
||||
styles = require('../styles');
|
||||
|
||||
FFZ.prototype.setup_css = function() {
|
||||
document.body.classList.toggle('ffz-flip-dashboard', this.settings.flip_dashboard);
|
||||
|
||||
this.log("Injecting main FrankerFaceZ CSS.");
|
||||
|
||||
var s = this._main_style = document.createElement('link');
|
||||
var s = this._main_style = document.createElement('style');
|
||||
|
||||
s.textContent = styles.style;
|
||||
s.id = "ffz-ui-css";
|
||||
s.setAttribute('rel', 'stylesheet');
|
||||
s.setAttribute('href', constants.SERVER + "script/style.css?_=" + (constants.DEBUG ? Date.now() : FFZ.version_info));
|
||||
s.onerror = "this.href = this.href + '_';"
|
||||
|
||||
document.head.appendChild(s);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue