mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-27 21:05:53 +00:00
4.67.0
* Fixed: Bug displaying rich content errors when no data is returned from the link information service. * API Changed: The `site.chat.addNotice()` method now supports rich content and localization.
This commit is contained in:
parent
44e30e985d
commit
8688d1a41b
4 changed files with 143 additions and 52 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"author": "Dan Salvato LLC",
|
"author": "Dan Salvato LLC",
|
||||||
"version": "4.66.0",
|
"version": "4.67.0",
|
||||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
|
|
@ -2644,58 +2644,59 @@ export default class Chat extends Module {
|
||||||
|
|
||||||
|
|
||||||
handleLinkToS(data) {
|
handleLinkToS(data) {
|
||||||
|
if ( ! Array.isArray(data?.urls) )
|
||||||
|
return data;
|
||||||
|
|
||||||
// Check for YouTube
|
// Check for YouTube
|
||||||
const agreed = this.settings.provider.get('agreed-tos', []),
|
const agreed = this.settings.provider.get('agreed-tos', []),
|
||||||
rejected = this.settings.provider.get('declined-tos', []);
|
rejected = this.settings.provider.get('declined-tos', []);
|
||||||
|
|
||||||
const resolvers = data.urls ? new Set(data.urls.map(x => x.resolver).filter(x => x)) : null;
|
const resolvers = new Set(data.urls.map(x => x.resolver).filter(x => x));
|
||||||
if ( resolvers ) {
|
for(const [key, info] of Object.entries(RESOLVERS_REQUIRE_TOS)) {
|
||||||
for(const [key, info] of Object.entries(RESOLVERS_REQUIRE_TOS)) {
|
if ( resolvers.has(key) && ! agreed.includes(key) ) {
|
||||||
if ( resolvers.has(key) && ! agreed.includes(key) ) {
|
const declined = rejected.includes(key);
|
||||||
const declined = rejected.includes(key);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
url: null,
|
url: null,
|
||||||
short: [
|
short: [
|
||||||
{
|
{
|
||||||
type: 'box',
|
type: 'box',
|
||||||
content: [
|
content: [
|
||||||
info.i18n_key
|
info.i18n_key
|
||||||
? {type: 'i18n', key: info.i18n_key, phrase: info.label}
|
? {type: 'i18n', key: info.i18n_key, phrase: info.label}
|
||||||
: info.label,
|
: info.label,
|
||||||
declined ? null : ' ',
|
declined ? null : ' ',
|
||||||
declined ? null : {
|
declined ? null : {
|
||||||
type: 'conditional',
|
type: 'conditional',
|
||||||
tooltip: false,
|
tooltip: false,
|
||||||
|
content: {
|
||||||
|
type: 'i18n',
|
||||||
|
key: 'embed.tos-open-settings',
|
||||||
|
phrase: '{link} to open your settings.',
|
||||||
content: {
|
content: {
|
||||||
type: 'i18n',
|
link: {
|
||||||
key: 'embed.tos-open-settings',
|
type: 'open_settings',
|
||||||
phrase: '{link} to open your settings.',
|
item: 'chat.tooltips',
|
||||||
content: {
|
content: {
|
||||||
link: {
|
type: 'i18n',
|
||||||
type: 'open_settings',
|
key: 'embed.tos-open-settings.click',
|
||||||
item: 'chat.tooltips',
|
phrase: 'Click here'
|
||||||
content: {
|
|
||||||
type: 'i18n',
|
|
||||||
key: 'embed.tos-open-settings.click',
|
|
||||||
phrase: 'Click here'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
alternative: {
|
|
||||||
type: 'i18n',
|
|
||||||
key: 'embed.tos-settings',
|
|
||||||
phrase: 'Open the FFZ Control Center and navigate to Chat > Tooltips to agree.'
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
alternative: {
|
||||||
|
type: 'i18n',
|
||||||
|
key: 'embed.tos-settings',
|
||||||
|
phrase: 'Open the FFZ Control Center and navigate to Chat > Tooltips to agree.'
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
]
|
||||||
],
|
},
|
||||||
mid: null,
|
],
|
||||||
full: null
|
mid: null,
|
||||||
}
|
full: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import {Color, ColorAdjuster} from 'utilities/color';
|
import {Color, ColorAdjuster} from 'utilities/color';
|
||||||
import {get, has, make_enum, shallow_object_equals, set_equals, deep_equals, glob_to_regex, escape_regex} from 'utilities/object';
|
import {get, has, make_enum, shallow_object_equals, set_equals, deep_equals, glob_to_regex, escape_regex, generateUUID} from 'utilities/object';
|
||||||
import {WEBKIT_CSS as WEBKIT} from 'utilities/constants';
|
import {WEBKIT_CSS as WEBKIT} from 'utilities/constants';
|
||||||
|
|
||||||
import {useFont} from 'utilities/fonts';
|
import {useFont} from 'utilities/fonts';
|
||||||
|
import awaitMD, { getMD } from 'utilities/markdown';
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
|
||||||
import Twilight from 'site';
|
import Twilight from 'site';
|
||||||
|
@ -2389,10 +2389,40 @@ export default class ChatHook extends Module {
|
||||||
|
|
||||||
for(const inst of this.ChatService.instances) {
|
for(const inst of this.ChatService.instances) {
|
||||||
if ( room === '*' || inst.props.channelLogin.toLowerCase() === room ) {
|
if ( room === '*' || inst.props.channelLogin.toLowerCase() === room ) {
|
||||||
inst.addMessage({
|
if ( typeof message === 'string' )
|
||||||
type: this.chat_types.Notice,
|
inst.addMessage({
|
||||||
message
|
type: this.chat_types.Notice,
|
||||||
});
|
message
|
||||||
|
});
|
||||||
|
else {
|
||||||
|
const props = inst.props,
|
||||||
|
login = props.channelLogin,
|
||||||
|
id = props.channelID;
|
||||||
|
|
||||||
|
if ( message.markdown ) {
|
||||||
|
const md = getMD();
|
||||||
|
if ( ! md )
|
||||||
|
awaitMD();
|
||||||
|
}
|
||||||
|
|
||||||
|
inst.addMessage({
|
||||||
|
type: this.chat_types.Message,
|
||||||
|
channel: `#${login}`,
|
||||||
|
roomID: id,
|
||||||
|
roomLogin: login,
|
||||||
|
id: `ffz_notice_${generateUUID()}`,
|
||||||
|
ffz_type: 'notice',
|
||||||
|
ffz_no_actions: true,
|
||||||
|
ffz_data: message,
|
||||||
|
message: null,
|
||||||
|
messageParts: [],
|
||||||
|
timestamp: Date.now(),
|
||||||
|
user: {
|
||||||
|
userID: id,
|
||||||
|
userLogin: login
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { KEYS, RERENDER_SETTINGS, UPDATE_BADGE_SETTINGS, UPDATE_TOKEN_SETTINGS }
|
||||||
import { print_duration } from 'utilities/time';
|
import { print_duration } from 'utilities/time';
|
||||||
|
|
||||||
import { getRewardTitle, getRewardCost } from './points';
|
import { getRewardTitle, getRewardCost } from './points';
|
||||||
|
import awaitMD, {getMD} from 'utilities/markdown';
|
||||||
|
|
||||||
const SUB_TIERS = {
|
const SUB_TIERS = {
|
||||||
1000: 1,
|
1000: 1,
|
||||||
|
@ -45,6 +46,65 @@ export default class ChatLine extends Module {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.line_types.notice = {
|
||||||
|
renderNotice: (msg, current_user, room, inst, e) => {
|
||||||
|
const data = msg.ffz_data;
|
||||||
|
let content = this.line_types.notice.renderContent(msg, current_user, room, inst, e);
|
||||||
|
|
||||||
|
if ( ! data.icon )
|
||||||
|
return content;
|
||||||
|
|
||||||
|
if ( typeof content === 'string' )
|
||||||
|
content = e('span', {}, content);
|
||||||
|
|
||||||
|
content.ffz_icon = e('span', {
|
||||||
|
className: `${data.icon} tw-mg-r-05`
|
||||||
|
});
|
||||||
|
|
||||||
|
return content;
|
||||||
|
},
|
||||||
|
|
||||||
|
renderContent: (msg, current_user, room, inst, e) => {
|
||||||
|
const data = msg.ffz_data;
|
||||||
|
if ( data.renderer )
|
||||||
|
try {
|
||||||
|
return data.renderer(data, inst, e);
|
||||||
|
} catch(err) {
|
||||||
|
this.log.capture(err);
|
||||||
|
this.log.error('Error using custom renderer for notice:', err);
|
||||||
|
return `Error rendering notice.`
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = data.i18n ? this.i18n.t(data.i18n, data.messgae, data) : data.message;
|
||||||
|
|
||||||
|
if ( data.markdown ) {
|
||||||
|
const md = getMD();
|
||||||
|
if ( ! md ) {
|
||||||
|
awaitMD().then(() => inst.forceUpdate());
|
||||||
|
return 'Loading...';
|
||||||
|
}
|
||||||
|
|
||||||
|
return e('span', {
|
||||||
|
dangerouslySetInnerHTML: {
|
||||||
|
__html: getMD().renderInline(text)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( data.tokenize ) {
|
||||||
|
const tokens = data.ffz_tokens = data.ffz_tokens || this.chat.tokenizeMessage({
|
||||||
|
message: text,
|
||||||
|
id: msg.id,
|
||||||
|
user: msg.user
|
||||||
|
}, current_user);
|
||||||
|
|
||||||
|
return this.chat.renderTokens(tokens, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.line_types.hype = {
|
this.line_types.hype = {
|
||||||
renderNotice: (msg, current_user, room, inst, e) => {
|
renderNotice: (msg, current_user, room, inst, e) => {
|
||||||
const setting = this.chat.context.get('chat.hype.message-style');
|
const setting = this.chat.context.get('chat.hype.message-style');
|
||||||
|
@ -1058,7 +1118,7 @@ other {# messages were deleted by a moderator.}
|
||||||
|
|
||||||
// The preamble
|
// The preamble
|
||||||
timestamp,
|
timestamp,
|
||||||
t.actions.renderInline(msg, this.props.showModerationIcons, current_user, current_room, e, this),
|
msg.ffz_no_actions ? null : t.actions.renderInline(msg, this.props.showModerationIcons, current_user, current_room, e, this),
|
||||||
this.renderInlineHighlight ? this.renderInlineHighlight() : null,
|
this.renderInlineHighlight ? this.renderInlineHighlight() : null,
|
||||||
hl_position === 2 ? highlight_tags : null,
|
hl_position === 2 ? highlight_tags : null,
|
||||||
|
|
||||||
|
@ -1121,7 +1181,7 @@ other {# messages were deleted by a moderator.}
|
||||||
? e('span', { className: 'chat-line__timestamp' }, t.chat.formatTime(msg.timestamp))
|
? e('span', { className: 'chat-line__timestamp' }, t.chat.formatTime(msg.timestamp))
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const actions = t.actions.renderInline(msg, this.props.showModerationIcons, current_user, current_room, e, this);
|
const actions = msg.ffz_no_actions ? null : t.actions.renderInline(msg, this.props.showModerationIcons, current_user, current_room, e, this);
|
||||||
|
|
||||||
if ( is_raw ) {
|
if ( is_raw ) {
|
||||||
notice.ffz_target.unshift(
|
notice.ffz_target.unshift(
|
||||||
|
@ -1187,7 +1247,7 @@ other {# messages were deleted by a moderator.}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for hover actions, as those require we wrap the output in a few extra elements.
|
// Check for hover actions, as those require we wrap the output in a few extra elements.
|
||||||
const hover_actions = (user && msg.id)
|
const hover_actions = (user && msg.id && ! msg.ffz_no_actions)
|
||||||
? t.actions.renderHover(msg, this.props.showModerationIcons, current_user, current_room, e, this)
|
? t.actions.renderHover(msg, this.props.showModerationIcons, current_user, current_room, e, this)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue