mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-05 18:48:31 +00:00
Start using SourcedSet for emoticon sets so that, in the future, special events, featured channels, etc. can add and remove emote sets without worrying about reference counting or anything like that. Also implement the method to get your Twitch Inventory emote sets.
This commit is contained in:
parent
bd518aea01
commit
3607159929
5 changed files with 172 additions and 33 deletions
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import {ManagedStyle} from 'utilities/dom';
|
import {ManagedStyle} from 'utilities/dom';
|
||||||
import {has, timeout} from 'utilities/object';
|
import {has, timeout, SourcedSet} from 'utilities/object';
|
||||||
import {API_SERVER} from 'utilities/constants';
|
import {CLIENT_ID, API_SERVER} from 'utilities/constants';
|
||||||
|
|
||||||
|
|
||||||
const MODIFIERS = {
|
const MODIFIERS = {
|
||||||
|
@ -61,13 +61,16 @@ export default class Emotes extends Module {
|
||||||
this.__twitch_emote_to_set = new Map;
|
this.__twitch_emote_to_set = new Map;
|
||||||
this.__twitch_set_to_channel = new Map;
|
this.__twitch_set_to_channel = new Map;
|
||||||
|
|
||||||
this.default_sets = new Set;
|
this.default_sets = new SourcedSet;
|
||||||
this.global_sets = new Set;
|
this.global_sets = new SourcedSet;
|
||||||
|
|
||||||
this.emote_sets = {};
|
this.emote_sets = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnable() {
|
onEnable() {
|
||||||
|
// Just in case there's a weird load order going on.
|
||||||
|
this.on('site:enabled', this.refresh_twitch_inventory);
|
||||||
|
|
||||||
this.style = new ManagedStyle('emotes');
|
this.style = new ManagedStyle('emotes');
|
||||||
|
|
||||||
if ( Object.keys(this.emote_sets).length ) {
|
if ( Object.keys(this.emote_sets).length ) {
|
||||||
|
@ -96,9 +99,9 @@ export default class Emotes extends Module {
|
||||||
const room = this.parent.getRoom(room_id, room_login, true),
|
const room = this.parent.getRoom(room_id, room_login, true),
|
||||||
user = this.parent.getUser(user_id, user_login, true);
|
user = this.parent.getUser(user_id, user_login, true);
|
||||||
|
|
||||||
return (user ? user.emote_sets : []).concat(
|
return (user ? user.emote_sets._cache : []).concat(
|
||||||
room ? room.emote_sets : [],
|
room ? room.emote_sets._cache : [],
|
||||||
Array.from(this.default_sets)
|
this.default_sets._cache
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,12 +139,11 @@ export default class Emotes extends Module {
|
||||||
|
|
||||||
const sets = data.sets || {};
|
const sets = data.sets || {};
|
||||||
|
|
||||||
for(const set_id of data.default_sets)
|
this.default_sets.extend('ffz-global', ...data.default_sets);
|
||||||
this.default_sets.add(set_id);
|
|
||||||
|
|
||||||
for(const set_id in sets)
|
for(const set_id in sets)
|
||||||
if ( has(sets, set_id) ) {
|
if ( has(sets, set_id) ) {
|
||||||
this.global_sets.add(set_id);
|
this.global_sets.push('ffz-global', set_id);
|
||||||
this.load_set_data(set_id, sets[set_id]);
|
this.load_set_data(set_id, sets[set_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,8 +162,7 @@ export default class Emotes extends Module {
|
||||||
const user = this.parent.getUser(undefined, login),
|
const user = this.parent.getUser(undefined, login),
|
||||||
sets = user.emote_sets;
|
sets = user.emote_sets;
|
||||||
|
|
||||||
if ( sets.indexOf(set_id) === -1 )
|
sets.push('ffz-global', set_id);
|
||||||
sets.push(set_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log.info(`Added "${emote_set ? emote_set.title : set_id}" emote set to ${users.length} users.`);
|
this.log.info(`Added "${emote_set ? emote_set.title : set_id}" emote set to ${users.length} users.`);
|
||||||
|
@ -279,8 +280,27 @@ export default class Emotes extends Module {
|
||||||
// Twitch Data Lookup
|
// Twitch Data Lookup
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
refresh_twitch_inventory() {
|
async refresh_twitch_inventory() {
|
||||||
this.log.debug('Unimplemented: refresh_twitch_inventory');
|
const user = this.resolve('site').getUser();
|
||||||
|
if ( ! user )
|
||||||
|
return;
|
||||||
|
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = await fetch('https://api.twitch.tv/v5/inventory/emoticons', {
|
||||||
|
headers: {
|
||||||
|
'Client-ID': CLIENT_ID,
|
||||||
|
'Authorization': `OAuth ${user.authToken}`
|
||||||
|
}
|
||||||
|
}).then(r => r.json());
|
||||||
|
|
||||||
|
} catch(err) {
|
||||||
|
this.log.error('Error loading Twitch inventory.', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.twitch_inventory_sets = data.emoticon_sets ? Object.keys(data.emoticon_sets) : [];
|
||||||
|
this.log.info('Twitch Inventory Sets:', this.twitch_inventory_sets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ const WEBKIT = IS_WEBKIT ? '-webkit-' : '';
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import {createElement, ManagedStyle} from 'utilities/dom';
|
import {createElement, ManagedStyle} from 'utilities/dom';
|
||||||
import {timeout, has} from 'utilities/object';
|
import {timeout, has, SourcedSet} from 'utilities/object';
|
||||||
|
|
||||||
import Badges from './badges';
|
import Badges from './badges';
|
||||||
import Emotes from './emotes';
|
import Emotes from './emotes';
|
||||||
|
@ -283,7 +283,7 @@ export default class Chat extends Module {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
else
|
else
|
||||||
user = {id, login, badges: [], emote_sets: []};
|
user = {id, login, badges: [], emote_sets: new SourcedSet};
|
||||||
|
|
||||||
if ( id && id !== user.id ) {
|
if ( id && id !== user.id ) {
|
||||||
// If the ID isn't what we expected, something is very wrong here.
|
// If the ID isn't what we expected, something is very wrong here.
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {API_SERVER, IS_WEBKIT} from 'utilities/constants';
|
||||||
|
|
||||||
import {EventEmitter} from 'utilities/events';
|
import {EventEmitter} from 'utilities/events';
|
||||||
import {createElement as e, ManagedStyle} from 'utilities/dom';
|
import {createElement as e, ManagedStyle} from 'utilities/dom';
|
||||||
import {has} from 'utilities/object';
|
import {has, SourcedSet} from 'utilities/object';
|
||||||
|
|
||||||
const WEBKIT = IS_WEBKIT ? '-webkit-' : '';
|
const WEBKIT = IS_WEBKIT ? '-webkit-' : '';
|
||||||
|
|
||||||
|
@ -20,42 +20,71 @@ export default class Room extends EventEmitter {
|
||||||
this._destroy_timer = null;
|
this._destroy_timer = null;
|
||||||
|
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.id = id;
|
this._id = id;
|
||||||
this.login = login;
|
this.login = login;
|
||||||
|
|
||||||
if ( login )
|
|
||||||
this.manager.rooms[login] = this;
|
|
||||||
|
|
||||||
if ( id )
|
if ( id )
|
||||||
this.manager.room_ids[id] = this;
|
this.manager.room_ids[id] = this;
|
||||||
|
|
||||||
this.refs = new Set;
|
this.refs = new Set;
|
||||||
this.style = new ManagedStyle(`room--${login}`);
|
this.style = new ManagedStyle(`room--${login}`);
|
||||||
|
|
||||||
this.emote_sets = [];
|
this.emote_sets = new SourcedSet;
|
||||||
this.users = [];
|
this.users = [];
|
||||||
this.user_ids = [];
|
this.user_ids = [];
|
||||||
|
|
||||||
if ( this.login ) {
|
this.manager.emit(':room-add', this);
|
||||||
this.manager.socket.subscribe(`room.${login}`);
|
|
||||||
this.load_data();
|
this.load_data();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
clearTimeout(this._destroy_timer);
|
clearTimeout(this._destroy_timer);
|
||||||
this._destroy_timer = null;
|
this._destroy_timer = null;
|
||||||
|
|
||||||
this.destroyed = true;
|
this.destroyed = true;
|
||||||
|
|
||||||
this.manager.socket.unsubscribe(`room.${this.login}`);
|
this.manager.emit(':room-remove', this);
|
||||||
|
|
||||||
this.style.destroy();
|
this.style.destroy();
|
||||||
|
|
||||||
|
if ( this._login ) {
|
||||||
|
if ( this.manager.rooms[this._login] === this )
|
||||||
|
this.manager.rooms[this._login] = null;
|
||||||
|
|
||||||
|
this.manager.socket.unsubscribe(`room.${this.login}`);
|
||||||
|
}
|
||||||
|
|
||||||
if ( this.manager.room_ids[this.id] === this )
|
if ( this.manager.room_ids[this.id] === this )
|
||||||
this.manager.room_ids[this.id] = null;
|
this.manager.room_ids[this.id] = null;
|
||||||
|
}
|
||||||
|
|
||||||
if ( this.manager.rooms[this.login] === this )
|
|
||||||
this.manager.rooms[this.login] = null;
|
get id() {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
get login() {
|
||||||
|
return this._login;
|
||||||
|
}
|
||||||
|
|
||||||
|
set login(val) {
|
||||||
|
if ( this._login === val )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( this._login ) {
|
||||||
|
if ( this.manager.rooms[this._login] === this )
|
||||||
|
this.manager.rooms[this._login] = null;
|
||||||
|
|
||||||
|
this.manager.socket.unsubscribe(`room.${this.login}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._login = val;
|
||||||
|
if ( ! val )
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.manager.socket.subscribe(`room.${val}`);
|
||||||
|
this.manager.emit(':room-update-login', this, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +98,7 @@ export default class Room extends EventEmitter {
|
||||||
|
|
||||||
let response, data;
|
let response, data;
|
||||||
try {
|
try {
|
||||||
response = await fetch(`${API_SERVER}/v1/room/${this.login}`);
|
response = await fetch(`${API_SERVER}/v1/room/${this.id ? `id/${this.id}` : this.login}`);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
tries++;
|
tries++;
|
||||||
if ( tries < 10 )
|
if ( tries < 10 )
|
||||||
|
@ -89,9 +118,26 @@ export default class Room extends EventEmitter {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const d = this.data = data.room;
|
const d = data.room,
|
||||||
if ( d.set && this.emote_sets.indexOf(d) === -1 )
|
id = '' + d.twitch_id;
|
||||||
this.emote_sets.push(d.set);
|
|
||||||
|
if ( ! this._id ) {
|
||||||
|
this._id = id;
|
||||||
|
this.manager.room_ids[id] = this;
|
||||||
|
|
||||||
|
} else if ( this._id !== id ) {
|
||||||
|
this.manager.log.warn(`Received data for ${this.id}:${this.login} with the wrong ID: ${id}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.login = d.id;
|
||||||
|
this.data = d;
|
||||||
|
|
||||||
|
if ( d.set )
|
||||||
|
this.emote_sets.set('main', d.set);
|
||||||
|
else
|
||||||
|
this.emote_sets.delete('main');
|
||||||
|
|
||||||
|
|
||||||
if ( data.sets )
|
if ( data.sets )
|
||||||
for(const set_id in data.sets)
|
for(const set_id in data.sets)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
export const DEBUG = localStorage.ffzDebugMode === 'true' && document.body.classList.contains('ffz-dev');
|
export const DEBUG = localStorage.ffzDebugMode === 'true' && document.body.classList.contains('ffz-dev');
|
||||||
export const SERVER = DEBUG ? '//localhost:8000' : 'https://cdn.frankerfacez.com';
|
export const SERVER = DEBUG ? '//localhost:8000' : 'https://cdn.frankerfacez.com';
|
||||||
|
|
||||||
|
export const CLIENT_ID = 'a3bc9znoz6vi8ozsoca0inlcr4fcvkl';
|
||||||
export const API_SERVER = '//api.frankerfacez.com';
|
export const API_SERVER = '//api.frankerfacez.com';
|
||||||
|
|
||||||
export const WS_CLUSTERS = {
|
export const WS_CLUSTERS = {
|
||||||
|
|
|
@ -165,3 +165,75 @@ export function maybe_call(fn, ctx, ...args) {
|
||||||
|
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class SourcedSet {
|
||||||
|
constructor() {
|
||||||
|
this._cache = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
_rebuild() {
|
||||||
|
if ( ! this._sources )
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._cache = [];
|
||||||
|
for(const items of this._sources.values())
|
||||||
|
for(const i of items)
|
||||||
|
if ( ! this._cache.includes(i) )
|
||||||
|
this._cache.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key) { return this._sources && this._sources.get(key) }
|
||||||
|
has(key) { return this._sources ? this._sources.has(key) : false }
|
||||||
|
|
||||||
|
delete(key) {
|
||||||
|
if ( this._sources && this._sources.has(key) ) {
|
||||||
|
this._sources.delete(key);
|
||||||
|
this._rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extend(key, ...items) {
|
||||||
|
if ( ! this._sources )
|
||||||
|
this._sources = new Map;
|
||||||
|
|
||||||
|
const had = this.has(key);
|
||||||
|
this._sources.set(key, [false, items]);
|
||||||
|
if ( had )
|
||||||
|
this._rebuild();
|
||||||
|
else
|
||||||
|
for(const i of items)
|
||||||
|
if ( ! this._cache.includes(i) )
|
||||||
|
this._cache.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key, val) {
|
||||||
|
if ( ! this._sources )
|
||||||
|
this._sources = new Map;
|
||||||
|
|
||||||
|
const had = this.has(key);
|
||||||
|
this._sources.set(key, [val]);
|
||||||
|
|
||||||
|
if ( had )
|
||||||
|
this._rebuild();
|
||||||
|
|
||||||
|
else if ( ! this._cache.includes(val) )
|
||||||
|
this._cache.push(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
push(key, val) {
|
||||||
|
if ( ! this._sources )
|
||||||
|
return this.set(key, val);
|
||||||
|
|
||||||
|
const old_val = this._sources.get(key);
|
||||||
|
if ( old_val === undefined )
|
||||||
|
return this.set(key, val);
|
||||||
|
|
||||||
|
else if ( old_val.includes(val) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
old_val.push(val);
|
||||||
|
if ( ! this._cache.includes(val) )
|
||||||
|
this._cache.push(val);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue