1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-11 08:30:55 +00:00
FrankerFaceZ/src/bridge.js
SirStendec 2340992977 4.24.0
* Changed: The settings for Animated Emotes and chat user color correction now default to enabled or disabled based on your vanilla Twitch settings.
* Changed: Strip automatic error reporting from builds till it can be fixed.
* Fixed: Native viewer count and uptime not hiding correctly when a stream goes live.
* API Added: Settings can now depend on `localStorage` values by using `ls.{name}` keys for JSON or `ls.raw.{name}` for raw strings.
* Maintenance: Update dependencies.
2021-06-18 14:27:14 -04:00

222 lines
No EOL
5.3 KiB
JavaScript

'use strict';
import Logger from 'utilities/logging';
import Module from 'utilities/module';
import {DEBUG} from 'utilities/constants';
import {serializeBlob, deserializeBlob} from 'utilities/blobs';
import SettingsManager from './settings/index';
class FFZBridge extends Module {
constructor() {
super();
const start_time = performance.now(),
VER = FFZBridge.version_info;
FFZBridge.instance = this;
this.name = 'ffz_bridge';
this.__state = 0;
this.__modules.core = this;
// ========================================================================
// Logging
// ========================================================================
this.log = new Logger(null, null, null);
this.log.label = 'FFZBridge';
this.log.init = true;
this.core_log = this.log.get('core');
this.log.info(`FrankerFaceZ Settings Bridge v${VER} (build ${VER.build}${VER.commit ? ` - commit ${VER.commit}` : ''}) (initial ${location})`);
// ========================================================================
// Core Systems
// ========================================================================
this.inject('settings', SettingsManager);
// ========================================================================
// Startup
// ========================================================================
this.enable().then(() => {
const duration = performance.now() - start_time;
this.core_log.info(`Initialization complete in ${duration.toFixed(5)}ms.`);
this.log.init = false;
}).catch(err => {
this.core_log.error(`An error occurred during initialization.`, err);
this.log.init = false;
});
}
static get() {
return FFZBridge.instance;
}
async onEnable() {
window.addEventListener('message', this.onMessage.bind(this));
this.settings.provider.on('changed', this.onProviderChange, this);
this.settings.provider.on('changed-blob', this.onProviderBlobChange, this);
this.settings.provider.on('clear-blobs', this.onProviderClearBlobs, this);
await this.settings.awaitProvider();
await this.settings.provider.awaitReady();
this.send({
ffz_type: 'ready'
});
}
async onMessage(event) {
const msg = event.data;
if ( ! msg || ! msg.ffz_type )
return;
if ( msg.ffz_type === 'load' ) {
const out = {};
for(const [key, value] of this.settings.provider.entries())
out[key] = value;
this.send({
ffz_type: 'loaded',
data: out
});
return;
} else if ( msg.ffz_type === 'change' ) {
this.onChange(msg);
return;
}
if ( ! msg.id )
return this.log.warn('Received command with no reply ID');
let reply, transfer;
try {
if ( msg.ffz_type === 'init-load' ) {
reply = {
blobs: this.settings.provider.supportsBlobs,
values: {}
};
for(const [key,value] of this.settings.provider.entries())
reply.values[key] = value;
} else if ( msg.ffz_type === 'set' )
this.settings.provider.set(msg.key, msg.value);
else if ( msg.ffz_type === 'delete' )
this.settings.provider.delete(msg.key);
else if ( msg.ffz_type === 'clear' )
this.settings.provider.clear();
else if ( msg.ffz_type === 'get-blob' ) {
reply = await serializeBlob(await this.settings.provider.getBlob(msg.key));
if ( reply )
transfer = reply.buffer;
} else if ( msg.ffz_type === 'set-blob' ) {
const blob = deserializeBlob(msg.value);
await this.settings.provider.setBlob(msg.key, blob);
} else if ( msg.ffz_type === 'delete-blob' )
await this.settings.provider.deleteBlob(msg.key);
else if ( msg.ffz_type === 'has-blob' )
reply = await this.settings.provider.hasBlob(msg.key);
else if ( msg.ffz_type === 'clear-blobs' )
await this.settings.provider.clearBlobs();
else if ( msg.ffz_type === 'blob-keys' )
reply = await this.settings.provider.blobKeys();
else if ( msg.ffz_type === 'flush' )
await this.settings.provider.flush();
else
return this.send({
ffz_type: 'reply-error',
id: msg.id,
error: 'bad-command'
});
this.send({
ffz_type: 'reply',
id: msg.id,
reply
}, transfer);
} catch(err) {
this.log.error('Error handling command.', err);
this.send({
ffz_type: 'reply-error',
id: msg.id
});
}
}
send(msg, blob) { // eslint-disable-line class-methods-use-this
try {
window.parent.postMessage(msg, '*', blob ? [blob] : undefined)
} catch(err) { this.log.error('send error', err); /* no-op */ }
}
onChange(msg) {
const key = msg.key,
value = msg.value,
deleted = msg.deleted;
if ( deleted )
this.settings.provider.delete(key);
else
this.settings.provider.set(key, value);
}
onProviderChange(key, value, deleted) {
this.send({
ffz_type: 'change',
key,
value,
deleted
});
}
onProviderBlobChange(key, deleted) {
this.send({
ffz_type: 'change-blob',
key,
deleted
});
}
onProviderClearBlobs() {
this.send({
ffz_type: 'clear-blobs'
});
}
}
FFZBridge.Logger = Logger;
const VER = FFZBridge.version_info = {
major: __version_major__,
minor: __version_minor__,
revision: __version_patch__,
extra: __version_prerelease__?.length && __version_prerelease__[0],
commit: __git_commit__,
build: __webpack_hash__,
toString: () =>
`${VER.major}.${VER.minor}.${VER.revision}${VER.extra || ''}${DEBUG ? '-dev' : ''}`
}
window.FFZBridge = FFZBridge;
window.ffz_bridge = new FFZBridge();