More message handling updates.

This commit is contained in:
flash 2024-05-09 18:22:36 +00:00
parent c379c4bd0e
commit 5cbe5e98f2
12 changed files with 332 additions and 351 deletions

View file

@ -88,11 +88,7 @@ window.Umi = { UI: {} };
settings.define('autoScroll').default(true).create(); settings.define('autoScroll').default(true).create();
settings.define('closeTabConfirm').default(false).create(); settings.define('closeTabConfirm').default(false).create();
settings.define('showChannelList').default(false).create(); settings.define('showChannelList').default(false).create();
settings.define('fancyInfo').default(true).create();
settings.define('autoCloseUserContext').default(true).create(); settings.define('autoCloseUserContext').default(true).create();
settings.define('enableParser').default(true).create();
settings.define('enableEmoticons').default(true).create();
settings.define('autoParseUrls').default(true).create();
settings.define('preventOverflow').default(false).create(); settings.define('preventOverflow').default(false).create();
settings.define('expandTextBox').default(false).create(); settings.define('expandTextBox').default(false).create();
settings.define('eepromAutoInsert').default(true).create(); settings.define('eepromAutoInsert').default(true).create();
@ -113,7 +109,6 @@ window.Umi = { UI: {} };
settings.define('windowsLiveMessenger').default(false).create(); settings.define('windowsLiveMessenger').default(false).create();
settings.define('seinfeld').default(false).create(); settings.define('seinfeld').default(false).create();
settings.define('flashTitle').default(true).create(); settings.define('flashTitle').default(true).create();
settings.define('showServerMsgInTitle').default(true).create();
settings.define('onlyConnectWhenVisible').default(true).create(); settings.define('onlyConnectWhenVisible').default(true).create();
settings.define('playJokeSounds').default(true).create(); settings.define('playJokeSounds').default(true).create();
settings.define('weeaboo').default(false).create(); settings.define('weeaboo').default(false).create();

View file

@ -1,40 +1,74 @@
#include channels.js
#include users.js #include users.js
#include ui/messages.jsx
// messages should probably also be an "event" like how it is on the server const MamiMessageAuthorInfo = function(self = false, user = null, id = null, name = null, colour = null, rank = null, avatar = null) {
if(typeof self !== 'boolean')
throw 'self must be a boolean';
Umi.Message = (() => { if(user === null) {
const chatBot = new MamiUserInfo('-1', 'Server'); id ??= '';
name ??= '';
colour ??= 'inherit';
rank ??= 0;
avatar ??= new MamiUserAvatarInfo(id);
} else {
if(typeof user !== 'object')
throw 'user must be an object or null';
return function(msgId, time, user, text, channel, highlight, botInfo, isAction, isLog) { id ??= user.id;
msgId = (msgId || '').toString(); name ??= user.name;
time = time === null ? new Date() : (typeof time === 'object' ? time : new Date(parseInt(time || 0) * 1000)); colour ??= user.colour;
user = user !== null && typeof user === 'object' ? user : chatBot; rank ??= user.perms.rank;
text = (text || '').toString(); avatar ??= user.avatar;
channel = (channel || '').toString(); }
highlight = !!highlight;
isAction = !!isAction;
isLog = !!isLog;
hasSeen = isLog;
return { if(typeof id !== 'string')
getId: () => msgId, throw 'id must be a string';
getIdInt: () => { if(typeof name !== 'string')
const num = parseInt(msgId); throw 'name must be a string';
return isNaN(num) ? (Math.round(Number.MIN_SAFE_INTEGER * Math.random())) : num; if(typeof colour !== 'string')
}, throw 'colour must be a string';
getTime: () => time, if(typeof rank !== 'number')
getUser: () => MamiConvertUserInfoToUmi(user), throw 'rank must be a number';
getUserV2: () => user, if(typeof avatar !== 'object')
getText: () => text, throw 'avatar must be an object';
getChannel: () => channel,
shouldHighlight: () => highlight, return {
getBotInfo: () => botInfo, get self() { return self; },
isAction: () => isAction,
isLog: () => isLog, get user() { return user; },
hasSeen: () => hasSeen, get hasUser() { return user !== null; },
markSeen: () => hasSeen = true,
}; get id() { return id; },
get name() { return name; },
get colour() { return colour; },
get rank() { return rank; },
get avatar() { return avatar; },
}; };
})(); };
const MamiMessageInfo = function(type, created = null, detail = null, id = '', author = null, channel = '', silent = false) {
if(typeof type !== 'string')
throw 'type must be a string';
if(created === null)
created = new Date;
else if(!(created instanceof Date))
throw 'created must be an instance of window.Date or null';
if(typeof id !== 'string')
throw 'id must be a string';
if(typeof author !== 'object')
throw 'author must be an object';
if(typeof channel !== 'string')
throw 'channel must be a string';
if(typeof silent !== 'boolean')
throw 'silent must be a boolean';
return {
get type() { return type; },
get created() { return created; },
get detail() { return detail; },
get id() { return id; },
get author() { return author; },
get channel() { return channel; },
get silent() { return silent; },
};
};

View file

@ -378,8 +378,6 @@ Umi.Parsing = (function() {
} }
} }
} }
return element;
}, },
}; };
})(); })();

View file

@ -3,7 +3,7 @@ const MamiRNG = function(seed) {
const MBIG = 0x7FFFFFFF; const MBIG = 0x7FFFFFFF;
const MSEED = 161803398; const MSEED = 161803398;
if((typeof seed).toLowerCase() !== 'number') if(isNaN(seed))
seed = Math.round(Date.now() / 1000); seed = Math.round(Date.now() / 1000);
const seedArray = new Int32Array(56); const seedArray = new Int32Array(56);

View file

@ -142,14 +142,13 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe
Umi.Users.Add(userInfo); Umi.Users.Add(userInfo);
if(ev.detail.msg !== undefined) if(ev.detail.msg !== undefined)
Umi.UI.Messages.Add(new Umi.Message( Umi.UI.Messages.Add(new MamiMessageInfo(
ev.detail.msg.id, ev.detail.msg.time, undefined, '', ev.detail.msg.channel, false, 'user:join',
{ ev.detail.msg.time,
isError: false, null,
type: ev.detail.msg.botInfo.type, ev.detail.msg.id,
args: ev.detail.msg.botInfo.args, new MamiMessageAuthorInfo(ev.detail.user.self, userInfo),
target: userInfo, ev.detail.msg.channel
}
)); ));
}; };
handlers['user:remove'] = ev => { handlers['user:remove'] = ev => {
@ -160,19 +159,13 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe
return; return;
if(ev.detail.msg !== undefined) if(ev.detail.msg !== undefined)
Umi.UI.Messages.Add(new Umi.Message( Umi.UI.Messages.Add(new MamiMessageInfo(
ev.detail.msg.id, 'user:leave',
ev.detail.msg.time, ev.detail.msg.time,
undefined, { reason: ev.detail.leave.type },
'', ev.detail.msg.id,
ev.detail.msg.channel, new MamiMessageAuthorInfo(ev.detail.user.self, userInfo),
false, ev.detail.msg.channel
{
isError: false,
type: ev.detail.msg.botInfo.type,
args: ev.detail.msg.botInfo.args,
target: userInfo,
},
)); ));
Umi.Users.Remove(userInfo); Umi.Users.Remove(userInfo);
@ -183,7 +176,7 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe
const userInfo = Umi.Users.Get(ev.detail.user.id); const userInfo = Umi.Users.Get(ev.detail.user.id);
userInfo.name = ev.detail.user.name; userInfo.name = ev.detail.user.name;
userInfo.colour = ev.detail.user.colour; userInfo.colour = ev.detail.user.colour;
userInfo.avatarChangeTime = Date.now(); userInfo.avatar = new MamiUserAvatarInfo(ev.detail.user.id);
userInfo.status = new MamiUserStatusInfo(ev.detail.user.status.isAway, ev.detail.user.status.message); userInfo.status = new MamiUserStatusInfo(ev.detail.user.status.isAway, ev.detail.user.status.message);
userInfo.perms = new MamiUserPermsInfo( userInfo.perms = new MamiUserPermsInfo(
ev.detail.user.perms.rank, ev.detail.user.perms.kick, ev.detail.user.perms.rank, ev.detail.user.perms.kick,
@ -250,14 +243,12 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe
Umi.Users.Add(userInfo); Umi.Users.Add(userInfo);
if(ev.detail.msg !== undefined) if(ev.detail.msg !== undefined)
Umi.UI.Messages.Add(new Umi.Message( Umi.UI.Messages.Add(new MamiMessageInfo(
ev.detail.msg.id, null, undefined, '', ev.detail.msg.channel, false, 'channel:join',
{ null, null,
isError: false, ev.detail.msg.id,
type: ev.detail.msg.botInfo.type, new MamiMessageAuthorInfo(ev.detail.user.self, userInfo),
args: [ userInfo.name ], ev.detail.msg.channel
target: userInfo,
},
)); ));
}; };
handlers['chan:leave'] = ev => { handlers['chan:leave'] = ev => {
@ -271,14 +262,12 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe
return; return;
if(ev.detail.msg !== undefined) if(ev.detail.msg !== undefined)
Umi.UI.Messages.Add(new Umi.Message( Umi.UI.Messages.Add(new MamiMessageInfo(
ev.detail.msg.id, null, undefined, '', ev.detail.msg.channel, false, 'channel:leave',
{ null, null,
isError: false, ev.detail.msg.id,
type: ev.detail.msg.botInfo.type, new MamiMessageAuthorInfo(ev.detail.user.self, userInfo),
args: [ userInfo.name ], ev.detail.msg.channel
target: userInfo,
},
)); ));
Umi.Users.Remove(userInfo); Umi.Users.Remove(userInfo);
@ -289,8 +278,9 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe
if(dumpEvents) console.log('msg:add', ev.detail); if(dumpEvents) console.log('msg:add', ev.detail);
const senderInfo = ev.detail.msg.sender; const senderInfo = ev.detail.msg.sender;
const rawUserInfo = Umi.Users.Get(senderInfo.id);
const userInfo = senderInfo.name === undefined const userInfo = senderInfo.name === undefined
? Umi.Users.Get(senderInfo.id) ? rawUserInfo
: new MamiUserInfo( : new MamiUserInfo(
senderInfo.id, senderInfo.id,
senderInfo.name, senderInfo.name,
@ -319,15 +309,71 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe
Umi.UI.Menus.Attention('channels'); Umi.UI.Menus.Attention('channels');
} }
Umi.UI.Messages.Add(new Umi.Message( let type, detail, author;
ev.detail.msg.id, if(ev.detail.msg.isBot) {
const botInfo = ev.detail.msg.botInfo;
let authorMethod;
if(botInfo.type === 'join') {
type = 'user:join';
authorMethod = 'nameArg';
} else if(['leave', 'kick', 'flood', 'timeout'].includes(botInfo.type)) {
type = 'user:leave';
authorMethod = 'nameArg';
detail = { reason: botInfo.type };
} else if(botInfo.type === 'jchan') {
type = 'channel:join';
authorMethod = 'nameArg';
} else if(botInfo.type === 'lchan') {
type = 'channel:leave';
authorMethod = 'nameArg';
}
if(authorMethod === 'nameArg') {
author = botInfo.args[0];
authorMethod = 'name';
}
if(authorMethod === 'name') {
// the concat below should be done by the server, remove when fixed
const botUserInfo = Umi.Users.FindExact(author) ?? Umi.Users.FindExact(`~${author}`);
author = new MamiMessageAuthorInfo(
Umi.User.isCurrentUser(botUserInfo),
botUserInfo,
null,
author
);
}
if(typeof type !== 'string') {
type = `legacy:${botInfo.type}`;
detail = {
error: botInfo.isError,
args: botInfo.args,
};
}
} else {
author = new MamiMessageAuthorInfo(
senderInfo.self,
rawUserInfo,
senderInfo.id ?? rawUserInfo.id,
senderInfo.name ?? rawUserInfo.name,
senderInfo.colour ?? rawUserInfo.colour,
senderInfo.perms?.rank ?? rawUserInfo.perms?.rank ?? 0,
new MamiUserAvatarInfo(senderInfo.id ?? rawUserInfo.id ?? '0'),
);
type = `message:${ev.detail.msg.flags.isAction ? 'action' : 'text'}`;
detail = { body: ev.detail.msg.text };
}
Umi.UI.Messages.Add(new MamiMessageInfo(
type,
ev.detail.msg.time, ev.detail.msg.time,
userInfo, detail,
ev.detail.msg.text, ev.detail.msg.id,
channelName, author,
false, ev.detail.msg.channel,
ev.detail.msg.botInfo,
ev.detail.msg.flags.isAction,
ev.detail.msg.silent, ev.detail.msg.silent,
)); ));
}; };

View file

@ -33,12 +33,9 @@ Umi.UI.Emoticons = (function() {
}); });
}, },
Parse: function(element, message) { Parse: function(element, message) {
if(!mami.settings.get('enableEmoticons'))
return element;
let inner = element.innerHTML; let inner = element.innerHTML;
MamiEmotes.forEach(message.getUserV2().perms.rank, function(emote) { MamiEmotes.forEach(message?.author?.perms?.rank ?? 0, function(emote) {
const image = $e({ const image = $e({
tag: 'img', tag: 'img',
attrs: { attrs: {
@ -56,8 +53,6 @@ Umi.UI.Emoticons = (function() {
}); });
element.innerHTML = inner; element.innerHTML = inner;
return element;
}, },
Insert: function(sender) { Insert: function(sender) {
const emoticon = sender.getAttribute('data-umi-emoticon'); const emoticon = sender.getAttribute('data-umi-emoticon');

View file

@ -122,103 +122,44 @@ Umi.UI.Messages = (function() {
return { return {
Add: function(msg) { Add: function(msg) {
mami.globalEvents.dispatch('umi:message_add', msg); const elementId = `message-${msg.id}`;
const msgId = msg.getId(); if(msg.id !== '' && $i(elementId))
const elementId = `message-${msgId}`;
if(msgId !== '' && $i(elementId))
return; return;
const channelName = msg.getChannel();
const sender = msg.getUserV2();
const isBot = sender.id === '-1';
const isOutgoing = Umi.User.isCurrentUser(sender);
const hasSeen = msg.hasSeen();
const displayMessage = focusChannelName === '' || channelName === '' || channelName === focusChannelName;
const notifyPM = !displayMessage && !isOutgoing && !hasSeen && channelName.startsWith('@');
let isTiny = false; let isTiny = false;
let skipTextParsing = false; let skipTextParsing = false;
let msgText = msg.getText(); let msgText = '';
let msgTextLong = msgText; let msgTextLong = '';
let msgAuthor = msg.author;
let eBase;
let eAvatar;
let eText;
let eMeta;
let eUser;
let avatarUser = sender;
let avatarSize = '80';
let soundIsLegacy = true; let soundIsLegacy = true;
let soundName = isOutgoing ? 'outgoing' : 'incoming'; let soundName;
let soundVolume; let soundVolume;
let soundRate; let soundRate;
const userClass = `message--user-${sender.id}`; const eText = <div/>;
const eAvatar = <div class="message__avatar"/>;
const eUser = <div class="message__user"/>;
const eMeta = <div class="message__meta">{eUser}</div>;
const eTime = <div class="message__time">
{msg.created.getHours().toString().padStart(2, '0')}
:{msg.created.getMinutes().toString().padStart(2, '0')}
:{msg.created.getSeconds().toString().padStart(2, '0')}
</div>;
const eContainer = <div class="message__container">{eMeta}</div>;
const eBase = <div class="message">
{eAvatar}
{eContainer}
</div>;
const classes = ['message', userClass]; if(msg.type.startsWith('message:')) {
const styles = {}; msgText = msgTextLong = msg.detail.body;
soundName = msg.author?.self === true ? 'outgoing' : 'incoming';
const avatarClasses = ['message__avatar']; if(msg.type === 'message:action')
isTiny = true;
if(msg.isAction()) {
isTiny = true;
classes.push('message-action');
}
if(!displayMessage)
classes.push('hidden');
if(sender.id === "136")
styles.transform = 'scaleY(' + (0.76 + (0.01 * Math.max(0, Math.ceil(Date.now() / (7 * 24 * 60 * 60000)) - 2813))).toString() + ')';
const msgCreated = msg.getTime();
const msgDateTime = msgCreated.getHours().toString().padStart(2, '0')
+ ':' + msgCreated.getMinutes().toString().padStart(2, '0')
+ ':' + msgCreated.getSeconds().toString().padStart(2, '0');
if(isBot) {
const botInfo = msg.getBotInfo();
soundName = botInfo.isError ? 'error' : 'server';
if(botMsgs.hasOwnProperty(botInfo.type)) {
const bmInfo = botMsgs[botInfo.type];
let bArgs = botInfo.args;
if(typeof bmInfo.filter === 'function')
bArgs = bmInfo.filter(bArgs);
if(typeof bmInfo.sound === 'string')
soundName = bmInfo.sound;
let actionSuccess = false;
if(typeof bmInfo.action === 'string' && mami.settings.get('fancyInfo')) {
const target = botInfo.target ?? Umi.Users.FindExact(bArgs[0]) ?? Umi.Users.FindExact('~' + bArgs[0]); // shitty fix for server sending invalid data
if(target) {
actionSuccess = true;
isTiny = true;
skipTextParsing = true;
avatarUser = target;
$ari(classes, userClass);
msgText = formatTemplate(bmInfo.action, bArgs);
if(typeof bmInfo.avatar === 'string')
avatarClasses.push(`avatar-filter-${bmInfo.avatar}`);
}
}
msgTextLong = formatTemplate(bmInfo.text, bArgs);
if(!actionSuccess)
msgText = msgTextLong;
} else
msgText = msgTextLong = `!!! Received unsupported message type: ${botInfo.type} !!!`;
} else {
if(mami.settings.get('playJokeSounds')) if(mami.settings.get('playJokeSounds'))
try { try {
const trigger = mami.textTriggers.getTrigger(msgText); const trigger = mami.textTriggers.getTrigger(msgText);
@ -229,103 +170,135 @@ Umi.UI.Messages = (function() {
soundRate = trigger.getRate(); soundRate = trigger.getRate();
} }
} catch(ex) {} } catch(ex) {}
} else {
let bIsError = false;
let bType;
let bArgs;
if(msg.type === 'user:join') {
bType = 'join';
bArgs = [msgAuthor.name];
} else if(msg.type === 'user:leave') {
bType = msg.detail.reason;
bArgs = [msgAuthor.name];
} else if(msg.type === 'channel:join') {
bType = 'jchan';
bArgs = [msgAuthor.name];
} else if(msg.type === 'channel:leave') {
bType = 'lchan';
bArgs = [msgAuthor.name];
} else if(msg.type.startsWith('legacy:')) {
bType = msg.type.substring(7);
bIsError = msg.detail.error;
bArgs = msg.detail.args;
msgAuthor = Umi.Users.FindExact(bArgs[0]) ?? Umi.Users.FindExact('~' + bArgs[0]);
}
soundName = bIsError ? 'error' : 'server';
if(botMsgs.hasOwnProperty(bType)) {
const bmInfo = botMsgs[bType];
if(typeof bmInfo.filter === 'function')
bArgs = bmInfo.filter(bArgs);
if(typeof bmInfo.sound === 'string')
soundName = bmInfo.sound;
let actionSuccess = false;
if(typeof bmInfo.action === 'string')
if(msgAuthor) {
actionSuccess = true;
isTiny = true;
skipTextParsing = true;
msgText = formatTemplate(bmInfo.action, bArgs);
if(typeof bmInfo.avatar === 'string')
eAvatar.classList.add(`avatar-filter-${bmInfo.avatar}`);
}
msgTextLong = formatTemplate(bmInfo.text, bArgs);
if(!actionSuccess)
msgText = msgTextLong;
} else
msgText = msgTextLong = `!!! Received unsupported message type: ${msg.type} !!!`;
} }
let avatarUrl = futami.get('avatar'); if(msgAuthor !== null) {
if(typeof avatarUrl !== 'string' || avatarUrl.length < 1) eUser.style.color = msgAuthor.colour;
avatarUrl = undefined; eUser.textContent = msgAuthor.name;
else }
avatarUrl = avatarUrl.replace('{user:id}', avatarUser.id)
.replace('{resolution}', avatarSize)
.replace('{user:avatar_change}', avatarUser.avatarChangeTime);
eAvatar = <div class={avatarClasses}/>;
eUser = <div class="message__user" style={{ color: avatarUser.colour }}>{avatarUser.name}</div>;
if(isTiny) { if(isTiny) {
classes.push('message-tiny'); eText.classList.add('message-tiny-text');
eBase.classList.add('message-tiny');
avatarSize = '40';
if(msgText.indexOf("'") !== 0 || (msgText.match(/\'/g).length % 2) === 0) if(msgText.indexOf("'") !== 0 || (msgText.match(/\'/g).length % 2) === 0)
msgText = "\xA0" + msgText; msgText = "\xA0" + msgText;
eBase = <div class={classes} style={styles}> eMeta.append(eText, eTime);
{eAvatar}
<div class="message__container">
{eMeta = <div class="message__meta">
{eUser}
{eText = <div class="message-tiny-text"/>}
<div class="message__time">{msgDateTime}</div>
</div>}
</div>
</div>;
} else { } else {
eBase = <div class={classes} style={styles}> eText.classList.add('message__text');
{eAvatar} eMeta.append(eTime);
<div class="message__container"> eContainer.append(eText);
{eMeta = <div class="message__meta">
{eUser} if(msgAuthor?.id === '136')
<div class="message__time">{msgDateTime}</div> eBase.style.transform = 'scaleY(' + (0.76 + (0.01 * Math.max(0, Math.ceil(Date.now() / (7 * 24 * 60 * 60000)) - 2813))).toString() + ')';
</div>}
{eText = <div class="message__text"/>}
</div>
</div>;
} }
if(msgId !== '') { eBase.classList.add(`message--user-${msgAuthor?.id ?? '-1'}`);
if(focusChannelName !== '' && msg.channel !== '' && msg.channel !== focusChannelName)
eBase.classList.add('hidden');
if(msg.id !== '') {
eBase.id = elementId; eBase.id = elementId;
eBase.dataset.id = msgId; eBase.dataset.id = msg.id;
} }
if(!isBot) if(msgAuthor)
eBase.dataset.author = sender.id; eBase.dataset.author = msgAuthor.id;
if(channelName !== '') if(msg.channel !== '')
eBase.dataset.channel = channelName; eBase.dataset.channel = msg.channel;
if(isTiny) if(isTiny)
eBase.dataset.tiny = '1'; eBase.dataset.tiny = '1';
eBase.dataset.created = msgCreated.toISOString(); eBase.dataset.created = msg.created.toISOString();
eBase.dataset.body = msgText; eBase.dataset.body = msgText;
eText.innerText = msgText; eText.innerText = msgText;
if(!skipTextParsing) { if(!skipTextParsing) {
eText = Umi.UI.Emoticons.Parse(eText, msg); Umi.UI.Emoticons.Parse(eText, msg);
eText = Umi.Parsing.Parse(eText, msg); Umi.Parsing.Parse(eText, msg);
const urls = []; const urls = [];
const textSplit = eText.innerText.split(' ');
for(const textPart of textSplit) {
const uri = Umi.URI.Parse(textPart);
if(mami.settings.get('autoParseUrls')) { if(uri !== null && uri.Slashes !== null) {
const textSplit = eText.innerText.split(' '); urls.push(textPart);
for(const textPart of textSplit) {
const uri = Umi.URI.Parse(textPart);
if(uri !== null && uri.Slashes !== null) { const anchorElem = <a class="markup__link" href={textPart} target="_blank" rel="nofollow noreferrer noopener">{textPart}</a>;
urls.push(textPart); eText.innerHTML = eText.innerHTML.replace(textPart.replace(/&/g, '&amp;'), anchorElem.outerHTML);
const anchorElem = <a class="markup__link" href={textPart} target="_blank" rel="nofollow noreferrer noopener">{textPart}</a>;
eText.innerHTML = eText.innerHTML.replace(textPart.replace(/&/g, '&amp;'), anchorElem.outerHTML);
}
} }
} }
if(mami.settings.get('weeaboo')) { if(mami.settings.get('weeaboo')) {
eText.appendChild($t(Weeaboo.getTextSuffix(sender))); eUser.appendChild($t(Weeaboo.getNameSuffix(msgAuthor)));
eText.appendChild($t(Weeaboo.getTextSuffix(msgAuthor)));
const kaomoji = Weeaboo.getRandomKaomoji(true, msg); const kaomoji = Weeaboo.getRandomKaomoji(true, msg);
if(kaomoji) { if(kaomoji)
eText.appendChild($t(' ')); eText.append(` ${kaomoji}`);
eText.appendChild($t(kaomoji));
}
} }
if(mami.settings.get('weeaboo'))
eUser.appendChild($t(Weeaboo.getNameSuffix(sender)));
} }
if(avatarUrl === undefined) const avatarUrl = msgAuthor?.avatar?.[isTiny ? 'x40' : 'x80'] ?? '';
eAvatar.classList.add('message__avatar--disabled'); if(avatarUrl.length > 0)
eAvatar.style.backgroundImage = `url('${avatarUrl}')`;
else else
eAvatar.style.backgroundImage = `url(${avatarUrl})`; eAvatar.classList.add('message__avatar--disabled');
const msgsList = $i('umi-messages'); const msgsList = $i('umi-messages');
@ -353,7 +326,7 @@ Umi.UI.Messages = (function() {
msgsList.append(eBase); msgsList.append(eBase);
} }
if(displayMessage) { if(!eBase.classList.contains('hidden')) {
if(mami.settings.get('autoEmbedV1')) { if(mami.settings.get('autoEmbedV1')) {
const callEmbedOn = eBase.querySelectorAll('a[onclick^="Umi.Parser.SockChatBBcode.Embed"]'); const callEmbedOn = eBase.querySelectorAll('a[onclick^="Umi.Parser.SockChatBBcode.Embed"]');
for(const embedElem of callEmbedOn) for(const embedElem of callEmbedOn)
@ -387,12 +360,9 @@ Umi.UI.Messages = (function() {
if(document.hidden) { if(document.hidden) {
if(mami.settings.get('flashTitle')) { if(mami.settings.get('flashTitle')) {
let titleText = isBot && mami.settings.get('showServerMsgInTitle') let titleText = msgAuthor?.name ?? msgTextLong;
? ` ${msgTextLong}` if(focusChannelName !== '' && focusChannelName !== msg.channel)
: ` ${sender.name}`; titleText += ` @ ${msg.channel}`;
if(focusChannelName !== '' && focusChannelName !== channelName)
titleText += ` @ ${channelName}`;
title.strobe([ title.strobe([
`[ @] ${titleText}`, `[ @] ${titleText}`,
@ -400,8 +370,8 @@ Umi.UI.Messages = (function() {
]); ]);
} }
if(!hasSeen) { if(!msg.silent) {
Umi.UI.Channels.Unread(channelName); Umi.UI.Channels.Unread(msg.channel);
if(mami.settings.get('enableNotifications') && isMentioned) { if(mami.settings.get('enableNotifications') && isMentioned) {
const options = {}; const options = {};
@ -410,10 +380,10 @@ Umi.UI.Messages = (function() {
if(mami.settings.get('notificationShowMessage')) if(mami.settings.get('notificationShowMessage'))
options.body += "\n" + msgTextLong; options.body += "\n" + msgTextLong;
if(avatarUrl !== undefined) if(avatarUrl.length > 0)
options.icon = avatarUrl; options.icon = avatarUrl;
const notif = new Notification(`${sender.name} mentioned you!`, options); const notif = new Notification(`${msgAuthor.name} mentioned you!`, options);
notif.addEventListener('click', () => { notif.addEventListener('click', () => {
window.focus(); window.focus();
}); });
@ -425,19 +395,14 @@ Umi.UI.Messages = (function() {
} }
} }
if(soundName !== undefined && !hasSeen) { if(!msg.silent && soundName !== undefined) {
if(soundIsLegacy) if(soundIsLegacy)
soundName = Umi.Sound.Convert(soundName); soundName = Umi.Sound.Convert(soundName);
mami.sound.library.play(soundName, soundVolume, soundRate); mami.sound.library.play(soundName, soundVolume, soundRate);
} }
mami.globalEvents.dispatch('umi:ui:message_add', { mami.globalEvents.dispatch('umi:ui:message_add', { element: eBase });
element: eBase,
message: msg,
});
msg.markSeen();
}, },
SwitchChannel: channel => { SwitchChannel: channel => {
if(typeof channel === 'object' && channel !== null && 'name' in channel) if(typeof channel === 'object' && channel !== null && 'name' in channel)

View file

@ -43,11 +43,6 @@ Umi.UI.Settings = (function() {
title: 'Show channel list', title: 'Show channel list',
type: 'checkbox', type: 'checkbox',
}, },
{
name: 'fancyInfo',
title: 'Fancy server messages',
type: 'checkbox',
},
{ {
name: 'autoCloseUserContext', name: 'autoCloseUserContext',
title: 'Auto-close user menus', title: 'Auto-close user menus',
@ -59,21 +54,6 @@ Umi.UI.Settings = (function() {
name: 'text', name: 'text',
title: 'Text', title: 'Text',
items: [ items: [
{
name: 'enableParser',
title: 'Parse markup',
type: 'checkbox',
},
{
name: 'enableEmoticons',
title: 'Parse emoticons',
type: 'checkbox',
},
{
name: 'autoParseUrls',
title: 'Auto detect links',
type: 'checkbox',
},
{ {
name: 'preventOverflow', name: 'preventOverflow',
title: 'Prevent overflow', title: 'Prevent overflow',
@ -105,11 +85,6 @@ Umi.UI.Settings = (function() {
title: 'Strobe title on new message', title: 'Strobe title on new message',
type: 'checkbox', type: 'checkbox',
}, },
{
name: 'showServerMsgInTitle',
title: 'Show server message in title',
type: 'checkbox',
},
{ {
name: 'enableNotifications', name: 'enableNotifications',
title: 'Show notifications', title: 'Show notifications',

View file

@ -165,9 +165,9 @@ Umi.UI.Users = (function() {
uName.appendChild($t(user.name)); uName.appendChild($t(user.name));
} }
const avatarUrl = futami.get('avatar'); const avatarUrl = user.avatar.x60;
if(avatarUrl !== null && avatarUrl.length > 1) { if(avatarUrl !== '') {
uAvatar.style.backgroundImage = 'url({0})'.replace('{0}', avatarUrl.replace('{user:id}', user.id).replace('{resolution}', '80').replace('{user:avatar_change}', user.avatarChangeTime)); uAvatar.style.backgroundImage = `url('${avatarUrl}')`;
uDetails.appendChild(uAvatar); uDetails.appendChild(uAvatar);
} }
@ -184,9 +184,9 @@ Umi.UI.Users = (function() {
uBase.style.backgroundColor = user.colour === 'inherit' ? '#fff' : user.colour; uBase.style.backgroundColor = user.colour === 'inherit' ? '#fff' : user.colour;
uName.textContent = ''; uName.textContent = '';
const avatarUrl = futami.get('avatar'); const avatarUrl = user.avatar.x60;
if(avatarUrl !== null && avatarUrl.length > 1) if(uAvatar instanceof Element && avatarUrl !== '')
uAvatar.style.backgroundImage = 'url({0})'.replace('{0}', avatarUrl.replace('{user:id}', user.id).replace('{resolution}', '80').replace('{user:avatar_change}', user.avatarChangeTime)); uAvatar.style.backgroundImage = `url('${avatarUrl}')`;
if(user.status.isAway) if(user.status.isAway)
uName.appendChild($e({ attrs: { 'class': 'user-sidebar-afk' }, child: user.status.message })); uName.appendChild($e({ attrs: { 'class': 'user-sidebar-afk' }, child: user.status.message }));

View file

@ -28,7 +28,27 @@ const MamiUserStatusInfo = function(isAway = false, message = '') {
}; };
}; };
const MamiUserInfo = function(id, name, colour = 'inherit', status = null, perms = null) { const MamiUserAvatarInfo = function(userId) {
userId ??= '';
const template = futami.get('avatar') ?? '';
const changeTime = Date.now();
const getAvatar = res => {
return template.replace('{user:id}', userId)
.replace('{resolution}', res)
.replace('{user:avatar_change}', changeTime);
};
return {
get original() { return getAvatar('0'); },
get x80() { return getAvatar('80'); },
get x60() { return getAvatar('60'); },
get x40() { return getAvatar('40'); },
};
};
const MamiUserInfo = function(id, name, colour = 'inherit', status = null, perms = null, avatar = null) {
if(typeof id !== 'string') if(typeof id !== 'string')
throw 'id must be a string'; throw 'id must be a string';
if(typeof name !== 'string') if(typeof name !== 'string')
@ -43,8 +63,10 @@ const MamiUserInfo = function(id, name, colour = 'inherit', status = null, perms
perms = new MamiUserPermsInfo; perms = new MamiUserPermsInfo;
else if(typeof perms !== 'object') else if(typeof perms !== 'object')
throw 'perms must be an object'; throw 'perms must be an object';
if(avatar === null)
let avatarChangeTime = Date.now(); avatar = new MamiUserAvatarInfo(id);
else if(typeof avatar !== 'object')
throw 'avatar must be an object';
return { return {
get id() { return id; }, get id() { return id; },
@ -77,48 +99,15 @@ const MamiUserInfo = function(id, name, colour = 'inherit', status = null, perms
perms = value; perms = value;
}, },
get avatarChangeTime() { return avatarChangeTime; }, get avatar() { return avatar; },
set avatarChangeTime(value) { set avatar(value) {
if(typeof value !== 'number') if(typeof value !== 'object' || value === null)
throw 'value must be a number'; throw 'value must be an object';
avatarChangeTime = value; avatar = value;
}, },
}; };
}; };
const MamiConvertUserInfoToUmi = info => {
return {
getId: () => info.id,
getIdInt: () => parseInt(info.id),
getName: () => {
let name = info.name;
if(info.status.isAway)
name = `<${info.status.message.substring(0, 5).toUpperCase()}>_${name}`;
return name;
},
setName: () => {},
getColour: () => info.colour,
setColour: () => {},
setPermissions: () => {},
getRank: () => info.perms.rank,
canBan: () => info.perms.canKick,
canSilence: () => false,
canCreateChannel: () => info.perms.canCreateChannels,
canSetNickName: () => info.perms.canSetNick,
getAvatarTime: () => info.avatarChangeTime,
bumpAvatarTime: () => {
info.avatarChangeTime = Date.now();
},
isBot: () => info.id === '-1',
};
};
Umi.User = (() => { Umi.User = (() => {
let userInfo; let userInfo;

View file

@ -27,7 +27,7 @@ const Weeaboo = (function() {
if((typeof allowEmpty).toLowerCase() !== 'boolean') if((typeof allowEmpty).toLowerCase() !== 'boolean')
allowEmpty = true; allowEmpty = true;
const rng = new MamiRNG(message.getIdInt() || undefined); const rng = new MamiRNG(parseInt(message.id));
if(allowEmpty && rng.next(0, 10000) <= 9000) if(allowEmpty && rng.next(0, 10000) <= 9000)
return ''; return '';
@ -39,9 +39,9 @@ const Weeaboo = (function() {
if(typeof user !== 'object' || user === null) if(typeof user !== 'object' || user === null)
return ''; return '';
if(user.perms.rank >= 10) if(user.rank >= 10)
return '-sama'; return '-sama';
if(user.perms.rank >= 5) if(user.rank >= 5)
return '-sensei'; return '-sensei';
if(user.colour.toLowerCase() === '#f02d7d') if(user.colour.toLowerCase() === '#f02d7d')
return '-san'; return '-san';

View file

@ -123,10 +123,6 @@ const SockChatS2CUserAdd = (ctx, timeStamp, userId, userName, userColour, userPe
id: msgId, id: msgId,
time: new Date(parseInt(timeStamp) * 1000), time: new Date(parseInt(timeStamp) * 1000),
channel: ctx.channelName, channel: ctx.channelName,
botInfo: {
type: 'join',
args: [statusInfo.name],
},
}, },
user: { user: {
id: userId, id: userId,
@ -163,10 +159,6 @@ const SockChatS2CUserRemove = (ctx, userId, userName, reason, timeStamp, msgId)
id: msgId, id: msgId,
time: new Date(parseInt(timeStamp) * 1000), time: new Date(parseInt(timeStamp) * 1000),
channel: ctx.channelName, channel: ctx.channelName,
botInfo: {
type: reason,
args: [statusInfo.name],
},
}, },
user: { user: {
id: userId, id: userId,
@ -192,10 +184,6 @@ const SockChatS2CUserChannelJoin = (ctx, userId, userName, userColour, userPerms
msg: { msg: {
id: msgId, id: msgId,
channel: ctx.channelName, channel: ctx.channelName,
botInfo: {
type: 'jchan',
args: [statusInfo.name],
},
}, },
}); });
}; };
@ -209,10 +197,6 @@ const SockChatS2CUserChannelLeave = (ctx, userId, msgId) => {
msg: { msg: {
id: msgId, id: msgId,
channel: ctx.channelName, channel: ctx.channelName,
botInfo: {
type: 'lchan',
args: [userId],
},
}, },
}); });
}; };
@ -238,7 +222,7 @@ const SockChatS2CMessagePopulate = (ctx, timeStamp, userId, userName, userColour
name: statusInfo.name, name: statusInfo.name,
status: statusInfo.status, status: statusInfo.status,
colour: SockChatParseUserColour(userColour), colour: SockChatParseUserColour(userColour),
perms: SockChatParseUserColour(userPerms), perms: SockChatParseUserPerms(userPerms),
}, },
isBot: userId === '-1', isBot: userId === '-1',
silent: msgNotify === '0', silent: msgNotify === '0',