mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-29 15:55:33 +00:00
Add a limited legacy API to support at least basic channel and global emotes from FFZ:AP.
This commit is contained in:
parent
21b598b92d
commit
c86895797c
5 changed files with 351 additions and 6 deletions
294
src/api.js
Normal file
294
src/api.js
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Legacy API
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
import Module from 'utilities/module';
|
||||||
|
import {has} from 'utilities/object';
|
||||||
|
import {EventEmitter} from 'utilities/events';
|
||||||
|
|
||||||
|
|
||||||
|
export default class ApiModule extends Module {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
this.inject('chat');
|
||||||
|
this.inject('chat.emotes');
|
||||||
|
|
||||||
|
this._apis = {};
|
||||||
|
|
||||||
|
if ( ! this._known_apis ) {
|
||||||
|
this._known_apis = {};
|
||||||
|
var stored_val = localStorage.getItem("ffz_known_apis");
|
||||||
|
if ( stored_val !== null )
|
||||||
|
try {
|
||||||
|
this._known_apis = JSON.parse(stored_val);
|
||||||
|
} catch(err) {
|
||||||
|
this.error("Error loading Known APIs", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create(...args) {
|
||||||
|
return new LegacyAPI(this, ...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class LegacyAPI extends EventEmitter {
|
||||||
|
constructor(instance, name, icon = null, version = null, name_key = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.ffz = instance.root;
|
||||||
|
this.parent = instance;
|
||||||
|
|
||||||
|
if ( name ) {
|
||||||
|
for(const id in this.parent._known_apis) {
|
||||||
|
if ( this.parent._known_apis[id] === name ) {
|
||||||
|
this.id = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! this.id ) {
|
||||||
|
let i = 0;
|
||||||
|
while ( ! this.id ) {
|
||||||
|
if ( ! has(this.parent._known_apis, i) ) {
|
||||||
|
this.id = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( name ) {
|
||||||
|
this.parent._known_apis[this.id] = name;
|
||||||
|
localStorage.ffz_known_apis = JSON.stringify(this.parent._known_apis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parent._apis[this.id] = this;
|
||||||
|
|
||||||
|
this.emote_sets = {};
|
||||||
|
this.global_sets = [];
|
||||||
|
this.default_sets = [];
|
||||||
|
|
||||||
|
this.badges = {};
|
||||||
|
this.users = {};
|
||||||
|
|
||||||
|
this.name = name || `Extension#${this.id}`;
|
||||||
|
this.name_key = name_key || this.name.replace(/[^A-Z0-9_\-]/g, '').toLowerCase();
|
||||||
|
|
||||||
|
if ( /^[0-9]/.test(this.name_key) )
|
||||||
|
this.name_key = `_${this.name_key}`;
|
||||||
|
|
||||||
|
this.icon = icon;
|
||||||
|
this.version = version;
|
||||||
|
|
||||||
|
this.parent.log.info(`Registered New Extension #${this.id} (${this.name_key}): ${this.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
log(msg, data) {
|
||||||
|
this.parent.log.info(`Ext #${this.id} (${this.name_key}): ${msg}`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(msg, error) {
|
||||||
|
this.parent.log.error(`Ext #${this.id} (${this.name_key}): ${msg}`, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
register_metadata(key, data) { }
|
||||||
|
unregister_metadata(key, data) { }
|
||||||
|
update_metadata(key, full_update) { }
|
||||||
|
|
||||||
|
|
||||||
|
_load_set(real_id, set_id, data) {
|
||||||
|
if ( ! data )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
const emote_set = Object.assign({
|
||||||
|
source: this.name,
|
||||||
|
icon: this.icon || null,
|
||||||
|
title: 'Global Emoticons',
|
||||||
|
_type: 0
|
||||||
|
}, data, {
|
||||||
|
source_ext: this.id,
|
||||||
|
source_id: set_id,
|
||||||
|
id: real_id,
|
||||||
|
count: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
this.emote_sets[set_id] = emote_set;
|
||||||
|
this.parent.emotes.load_set_data(real_id, emote_set);
|
||||||
|
|
||||||
|
return emote_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
load_set(set_id, emote_set) {
|
||||||
|
const real_id = `${this.id}-${set_id}`;
|
||||||
|
return this._load_set(real_id, set_id, emote_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unload_set(set_id) {
|
||||||
|
const real_id = `${this.id}-${set_id}`,
|
||||||
|
emote_set = this.emote_sets[set_id];
|
||||||
|
|
||||||
|
if ( ! emote_set )
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.unregister_global_set(set_id);
|
||||||
|
|
||||||
|
// TODO: Unload sets
|
||||||
|
|
||||||
|
return emote_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get_set(set_id) {
|
||||||
|
return this.emote_sets[set_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
register_global_set(set_id, emote_set) {
|
||||||
|
const real_id = `${this.id}-${set_id}`;
|
||||||
|
if ( emote_set )
|
||||||
|
emote_set = this.load_set(set_id, emote_set);
|
||||||
|
else
|
||||||
|
emote_set = this.emote_sets[set_id];
|
||||||
|
|
||||||
|
if ( ! emote_set )
|
||||||
|
throw new Error('Invalid set ID.');
|
||||||
|
|
||||||
|
if ( this.parent.emotes.emote_sets && ! this.parent.emotes.emote_sets[real_id] )
|
||||||
|
this.parent.emotes.emote_sets[real_id] = emote_set;
|
||||||
|
|
||||||
|
if ( this.global_sets.indexOf(set_id) === -1 )
|
||||||
|
this.global_sets.push(set_id);
|
||||||
|
|
||||||
|
if ( this.default_sets.indexOf(set_id) === -1 )
|
||||||
|
this.default_sets.push(set_id);
|
||||||
|
|
||||||
|
this.parent.emotes.global_sets.push(`api--${this.id}`, real_id);
|
||||||
|
this.parent.emotes.default_sets.push(`api--${this.id}`, real_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
unregister_global_set(set_id) {
|
||||||
|
const real_id = `${this.id}-${set_id}`,
|
||||||
|
emote_set = this.emote_sets[set_id];
|
||||||
|
|
||||||
|
if ( ! emote_set )
|
||||||
|
return;
|
||||||
|
|
||||||
|
let ind = this.global_sets.indexOf(set_id);
|
||||||
|
if ( ind !== -1 )
|
||||||
|
this.global_sets.splice(ind,1);
|
||||||
|
|
||||||
|
ind = this.default_sets.indexOf(set_id);
|
||||||
|
if ( ind !== -1 )
|
||||||
|
this.default_sets.splice(ind,1);
|
||||||
|
|
||||||
|
this.parent.emote.global_sets.remove(`api--${this.id}`, real_id);
|
||||||
|
this.parent.emote.default_sets.remove(`api--${this.id}`, real_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
register_room_set(room_login, set_id, emote_set) {
|
||||||
|
const real_id = `${this.id}-${set_id}`,
|
||||||
|
room = this.parent.chat.getRoom(null, room_login, true);
|
||||||
|
|
||||||
|
if ( ! room )
|
||||||
|
throw new Error('Room not loaded');
|
||||||
|
|
||||||
|
if ( emote_set ) {
|
||||||
|
emote_set.title = emote_set.title || `Channel: ${room.data && room.data.display_name || room_login}`;
|
||||||
|
emote_set._type = emote_set._type || 1;
|
||||||
|
|
||||||
|
emote_set = this.load_set(set_id, emote_set);
|
||||||
|
} else
|
||||||
|
emote_set = this.emote_sets[set_id];
|
||||||
|
|
||||||
|
if ( ! emote_set )
|
||||||
|
throw new Error('Invalid set ID.');
|
||||||
|
|
||||||
|
if ( this.parent.emotes.emote_sets && ! this.parent.emotes.emote_sets[real_id] )
|
||||||
|
this.parent.emotes.emote_sets[real_id] = emote_set;
|
||||||
|
|
||||||
|
room.emote_sets.push(`api--${this.id}`, real_id);
|
||||||
|
emote_set.users++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unregister_room_set(room_login, set_id) {
|
||||||
|
const real_id = `${this.id}-${set_id}`,
|
||||||
|
emote_set = this.emote_sets[set_id],
|
||||||
|
room = this.parent.chat.getRoom(null, room_login, true);
|
||||||
|
|
||||||
|
if ( ! emote_set || ! room )
|
||||||
|
return;
|
||||||
|
|
||||||
|
room.emote_sets.remove(`api--${this.id}`, real_id);
|
||||||
|
emote_set.users--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
add_badge() { }
|
||||||
|
remove_badge() { }
|
||||||
|
user_add_badge() { }
|
||||||
|
user_remove_badge() { }
|
||||||
|
room_add_user_badge() { }
|
||||||
|
room_remove_user_badge() { }
|
||||||
|
|
||||||
|
user_add_set(username, set_id) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
user_remove_set(username, set_id) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
retokenize_messages() { }
|
||||||
|
|
||||||
|
|
||||||
|
register_chat_filter(filter) {
|
||||||
|
this.on('room-message', filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
unregister_chat_filter(filter) {
|
||||||
|
this.off('room-message', filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
iterate_chat_views(func) { }
|
||||||
|
iterate_rooms(func) {
|
||||||
|
if ( func === undefined )
|
||||||
|
func = this.emit.bind(this, 'room-add');
|
||||||
|
|
||||||
|
const chat = this.parent.resolve('chat');
|
||||||
|
for(const room_id in chat.rooms)
|
||||||
|
func(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
register_on_room_callback(callback, dont_iterate) {
|
||||||
|
const thing = room_id => {
|
||||||
|
return callback(room_id, this.register_room_set.bind(this, room_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
thing.original_func = callback;
|
||||||
|
callback.__wrapped = thing;
|
||||||
|
|
||||||
|
this.on('room-add', thing);
|
||||||
|
if ( ! dont_iterate )
|
||||||
|
this.iterate_rooms(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
unregister_on_room_callback(callback) {
|
||||||
|
if ( ! callback.__wrapped )
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.off('room-add', callback.__wrapped);
|
||||||
|
callback.__wrapped = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
src/main.js
18
src/main.js
|
@ -9,6 +9,7 @@ import SettingsManager from './settings/index';
|
||||||
import {TranslationManager} from './i18n';
|
import {TranslationManager} from './i18n';
|
||||||
import SocketClient from './socket';
|
import SocketClient from './socket';
|
||||||
import Site from 'site';
|
import Site from 'site';
|
||||||
|
import LegacyAPI from './api';
|
||||||
import Vue from 'utilities/vue';
|
import Vue from 'utilities/vue';
|
||||||
|
|
||||||
class FrankerFaceZ extends Module {
|
class FrankerFaceZ extends Module {
|
||||||
|
@ -38,6 +39,8 @@ class FrankerFaceZ extends Module {
|
||||||
this.inject('socket', SocketClient);
|
this.inject('socket', SocketClient);
|
||||||
this.inject('site', Site);
|
this.inject('site', Site);
|
||||||
|
|
||||||
|
this.inject('_api', LegacyAPI);
|
||||||
|
|
||||||
this.register('vue', Vue);
|
this.register('vue', Vue);
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,8 +90,8 @@ class FrankerFaceZ extends Module {
|
||||||
|
|
||||||
|
|
||||||
/* eslint class-methods-use-this: off */
|
/* eslint class-methods-use-this: off */
|
||||||
api() {
|
api(...args) {
|
||||||
throw new Error('Not Implemented');
|
return this._api.create(...args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,4 +120,13 @@ FrankerFaceZ.utilities = {
|
||||||
|
|
||||||
|
|
||||||
window.FrankerFaceZ = FrankerFaceZ;
|
window.FrankerFaceZ = FrankerFaceZ;
|
||||||
window.ffz = new FrankerFaceZ();
|
window.ffz = new FrankerFaceZ();
|
||||||
|
|
||||||
|
// Make FFZ:AP Run
|
||||||
|
FrankerFaceZ.chat_commands = {};
|
||||||
|
FrankerFaceZ.settings_info = {};
|
||||||
|
FrankerFaceZ.utils = {
|
||||||
|
process_int(a,b,c) { return a }
|
||||||
|
}
|
||||||
|
window.App = true;
|
||||||
|
jQuery.noty = {themes: {}};
|
|
@ -73,9 +73,11 @@ export default class Room extends EventEmitter {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( this._login ) {
|
if ( this._login ) {
|
||||||
if ( this.manager.rooms[this._login] === this )
|
const old_room = this.manager.rooms[this._login];
|
||||||
this.manager.rooms[this._login] = null;
|
if ( old_room !== this )
|
||||||
|
old_room.login = null;
|
||||||
|
|
||||||
|
this.manager.rooms[this._login] = null;
|
||||||
this.manager.socket.unsubscribe(`room.${this.login}`);
|
this.manager.socket.unsubscribe(`room.${this.login}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +85,11 @@ export default class Room extends EventEmitter {
|
||||||
if ( ! val )
|
if ( ! val )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const old_room = this.manager.rooms[val];
|
||||||
|
if ( old_room && old_room !== this )
|
||||||
|
old_room.login = null;
|
||||||
|
|
||||||
|
this.manager.rooms[val] = this;
|
||||||
this.manager.socket.subscribe(`room.${val}`);
|
this.manager.socket.subscribe(`room.${val}`);
|
||||||
this.manager.emit(':room-update-login', this, val);
|
this.manager.emit(':room-update-login', this, val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,15 @@ import SettingsContext from './context';
|
||||||
import MigrationManager from './migration';
|
import MigrationManager from './migration';
|
||||||
|
|
||||||
|
|
||||||
|
const OVERRIDE_GET = {
|
||||||
|
ffz_enable_highlight_sound: false,
|
||||||
|
ffz_highlight_sound_volume: 0,
|
||||||
|
bttv_channel_emotes: true,
|
||||||
|
bttv_global_emotes: true,
|
||||||
|
bttv_gif_emotes: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// SettingsManager
|
// SettingsManager
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
@ -322,7 +331,12 @@ export default class SettingsManager extends Module {
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
context(env) { return this.main_context.context(env) }
|
context(env) { return this.main_context.context(env) }
|
||||||
get(key) { return this.main_context.get(key) }
|
get(key) {
|
||||||
|
if ( has(OVERRIDE_GET, key) )
|
||||||
|
return OVERRIDE_GET[key];
|
||||||
|
|
||||||
|
return this.main_context.get(key);
|
||||||
|
}
|
||||||
uses(key) { return this.main_context.uses(key) }
|
uses(key) { return this.main_context.uses(key) }
|
||||||
update(key) { return this.main_context.update(key) }
|
update(key) { return this.main_context.update(key) }
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,10 @@ export class SourcedSet {
|
||||||
get(key) { return this._sources && this._sources.get(key) }
|
get(key) { return this._sources && this._sources.get(key) }
|
||||||
has(key) { return this._sources ? this._sources.has(key) : false }
|
has(key) { return this._sources ? this._sources.has(key) : false }
|
||||||
|
|
||||||
|
includes(val) {
|
||||||
|
return this._cache.includes(val);
|
||||||
|
}
|
||||||
|
|
||||||
delete(key) {
|
delete(key) {
|
||||||
if ( this._sources && this._sources.has(key) ) {
|
if ( this._sources && this._sources.has(key) ) {
|
||||||
this._sources.delete(key);
|
this._sources.delete(key);
|
||||||
|
@ -236,4 +240,18 @@ export class SourcedSet {
|
||||||
if ( ! this._cache.includes(val) )
|
if ( ! this._cache.includes(val) )
|
||||||
this._cache.push(val);
|
this._cache.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove(key, val) {
|
||||||
|
if ( ! this.has(key) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const old_val = this._sources.get(key),
|
||||||
|
idx = old_val.indexOf(val);
|
||||||
|
|
||||||
|
if ( idx === -1 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
old_val.splice(idx, 1);
|
||||||
|
this._rebuild();
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue