diff --git a/assets/chat/js/chat.js b/assets/chat/js/chat.js
index 196e40eb..4cfb32de 100644
--- a/assets/chat/js/chat.js
+++ b/assets/chat/js/chat.js
@@ -112,7 +112,6 @@ class Chat {
// The websocket connection, emits events from the chat server
this.source = new ChatSource();
- this.source.on('REFRESH', () => window.location.reload(false));
this.source.on('PING', (data) => this.source.send('PONG', data));
this.source.on('CONNECTING', (data) => this.onCONNECTING(data));
this.source.on('ME', (data) => this.onME(data));
@@ -140,6 +139,7 @@ class Chat {
this.source.on('GIFTSUB', (data) => this.onGIFTSUB(data));
this.source.on('MASSGIFT', (data) => this.onMASSGIFT(data));
this.source.on('DONATION', (data) => this.onDONATION(data));
+ this.source.on('UPDATEUSER', (data) => this.onUPDATEUSER(data));
this.source.on('ADDPHRASE', (data) => this.onADDPHRASE(data));
this.source.on('REMOVEPHRASE', (data) => this.onREMOVEPHRASE(data));
@@ -973,13 +973,19 @@ class Chat {
onDISPATCH({ data }) {
if (data && typeof data === 'object') {
let users = [];
- const now = Date.now();
- if (Object.hasOwn(data, 'nick')) users.push(this.addUser(data));
- if (Object.hasOwn(data, 'users'))
- users = users.concat(
- Array.from(data.users).map((d) => this.addUser(d))
- );
- users.forEach((u) => this.autocomplete.add(u.nick, false, now));
+ if (data.users) {
+ users = users.concat(data.users.map((d) => this.addUser(d)));
+ }
+ if (data.user) {
+ users.push(this.addUser(data.user));
+ } else if (data.nick) {
+ users.push(this.addUser(data));
+ }
+ // For sub recipients in `GIFTSUB` events.
+ if (data.recipient) {
+ users.push(this.addUser(data.recipient));
+ }
+ users.forEach((u) => this.autocomplete.add(u.nick, false, Date.now()));
}
}
@@ -1241,46 +1247,19 @@ class Chat {
}
onSUBSCRIPTION(data) {
- const user = this.users.get(data.nick) ?? new ChatUser(data.nick);
- MessageBuilder.subscription(
- data.data,
- user,
- data.tier,
- data.tierlabel,
- data.streak,
- data.timestamp
- ).into(this);
+ MessageBuilder.subscription(data).into(this);
}
onGIFTSUB(data) {
- const user = this.users.get(data.nick) ?? new ChatUser(data.nick);
- MessageBuilder.gift(
- data.data,
- user,
- data.tier,
- data.tierlabel,
- data.giftee,
- data.timestamp
- ).into(this);
+ MessageBuilder.gift(data).into(this);
}
onMASSGIFT(data) {
- const user = this.users.get(data.nick) ?? new ChatUser(data.nick);
- MessageBuilder.massgift(
- data.data,
- user,
- data.tier,
- data.tierlabel,
- data.quantity,
- data.timestamp
- ).into(this);
+ MessageBuilder.massgift(data).into(this);
}
onDONATION(data) {
- const user = this.users.get(data.nick) ?? new ChatUser(data.nick);
- MessageBuilder.donation(data.data, user, data.amount, data.timestamp).into(
- this
- );
+ MessageBuilder.donation(data).into(this);
}
onADDPHRASE(data) {
@@ -1440,6 +1419,12 @@ class Chat {
}
}
+ onUPDATEUSER(data) {
+ if (this.user?.id === data.id) {
+ this.setUser(data);
+ }
+ }
+
cmdSHOWPOLL() {
if (this.chatpoll.poll) {
this.chatpoll.show();
diff --git a/assets/chat/js/formatters.test.js b/assets/chat/js/formatters/AmazonAssociatesTagInjector.test.js
similarity index 97%
rename from assets/chat/js/formatters.test.js
rename to assets/chat/js/formatters/AmazonAssociatesTagInjector.test.js
index ef7abaa1..1ab908df 100644
--- a/assets/chat/js/formatters.test.js
+++ b/assets/chat/js/formatters/AmazonAssociatesTagInjector.test.js
@@ -1,4 +1,4 @@
-import { AmazonAssociatesTagInjector } from './formatters';
+import AmazonAssociatesTagInjector from './AmazonAssociatesTagInjector';
const chatStub = {
config: {
diff --git a/assets/chat/js/formatters/UrlFormatter.js b/assets/chat/js/formatters/UrlFormatter.js
index 4809a5c9..b897f972 100644
--- a/assets/chat/js/formatters/UrlFormatter.js
+++ b/assets/chat/js/formatters/UrlFormatter.js
@@ -71,16 +71,31 @@ export default class UrlFormatter {
const m = decodedUrl.match(self.linkregex);
if (m) {
const encodedUrl = self.encodeUrl(m[0]);
+ const normalizedUrl = this.normalizeUrl(encodedUrl);
const maxUrlLength = 90;
- let urlText = encodedUrl;
+ let urlText = normalizedUrl;
if (urlText.length > maxUrlLength) {
urlText = `${urlText.slice(0, 40)}...${urlText.slice(-40)}`;
}
const extra = self.encodeUrl(decodedUrl.substring(m[0].length));
- const href = `${scheme ? '' : 'http://'}${encodedUrl}`;
+ const href = `${scheme ? '' : 'http://'}${normalizedUrl}`;
return `${extra}`;
}
return url;
});
}
+
+ /**
+ * @param {string} url
+ * @return {string} The normalized URL.
+ */
+ normalizeUrl(url) {
+ if (/(x|twitter)\.com\/\w{1,15}\/status\/\d{2,19}\?/i.test(url)) {
+ // Remove the query string from xeet URLs to protect users from clicking
+ // on a link to a xeet they've already seen.
+ return url.split('?')[0];
+ }
+
+ return url;
+ }
}
diff --git a/assets/chat/js/formatters/UrlFormatter.test.js b/assets/chat/js/formatters/UrlFormatter.test.js
new file mode 100644
index 00000000..de1bdfea
--- /dev/null
+++ b/assets/chat/js/formatters/UrlFormatter.test.js
@@ -0,0 +1,29 @@
+import UrlFormatter from './UrlFormatter';
+
+const urlFormatter = new UrlFormatter();
+
+describe('Normalizing URLs', () => {
+ test('Remove the query string from a tweet URL', () => {
+ expect(
+ urlFormatter.normalizeUrl('https://twitter.com/jack/status/20?lang=en')
+ ).toBe('https://twitter.com/jack/status/20');
+ });
+
+ test('Remove the query string from a xeet URL', () => {
+ expect(
+ urlFormatter.normalizeUrl('https://x.com/jack/status/20?lang=en')
+ ).toBe('https://x.com/jack/status/20');
+ });
+
+ test("Don't modify a URL to a tweet that doesn't contain a query string", () => {
+ expect(urlFormatter.normalizeUrl('https://x.com/jack/status/20')).toBe(
+ 'https://x.com/jack/status/20'
+ );
+ });
+
+ test("Don't modify a URL that isn't Twitter or X", () => {
+ expect(
+ urlFormatter.normalizeUrl('https://www.twitch.tv/search?term=vtuber')
+ ).toBe('https://www.twitch.tv/search?term=vtuber');
+ });
+});
diff --git a/assets/chat/js/menus/ChatUserInfoMenu.js b/assets/chat/js/menus/ChatUserInfoMenu.js
index e1ac2137..48b23986 100644
--- a/assets/chat/js/menus/ChatUserInfoMenu.js
+++ b/assets/chat/js/menus/ChatUserInfoMenu.js
@@ -38,7 +38,10 @@ export default class ChatUserInfoMenu extends ChatMenuFloating {
this.configureButtons();
this.chat.output.on('contextmenu', '.msg-chat .user', (e) => {
+ // If the target has this class, it's a sub tier label styled to match the
+ // username color of the sub (which requires the `user` class).
if (e.currentTarget.classList.contains('tier')) return false;
+
const message = $(e.currentTarget).closest('.msg-chat');
this.showUser(e, message);
@@ -219,6 +222,8 @@ export default class ChatUserInfoMenu extends ChatMenuFloating {
}
addContent(message) {
+ // Don't display messages if the giftee was clicked in a gift sub event
+ // because the message belongs to the gifter.
this.messageArray =
message[0].querySelector('.text') &&
this.clickedNick !== message.data('giftee')
@@ -326,6 +331,8 @@ export default class ChatUserInfoMenu extends ChatMenuFloating {
this.messageArray.forEach((element) => {
const text = element.find('.text')[0].innerText;
const nick = element.data('username');
+
+ // Create a new `ChatUser` to remove username styles for a cleaner look.
const msg = MessageBuilder.message(text, new ChatUser(nick));
displayedMessages.push(msg.html(this.chat));
});
diff --git a/assets/chat/js/menus/ChatUserMenu.js b/assets/chat/js/menus/ChatUserMenu.js
index 6a588546..a6e94f30 100644
--- a/assets/chat/js/menus/ChatUserMenu.js
+++ b/assets/chat/js/menus/ChatUserMenu.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import { debounce } from 'throttle-debounce';
import ChatMenu from './ChatMenu';
+import ChatUser from '../user';
// sections in order.
const UserMenuSections = [
@@ -20,12 +21,8 @@ const UserMenuSections = [
];
function userComparator(a, b) {
- const u1 = this.chat.users.get(a.getAttribute('data-username').toLowerCase());
- const u2 = this.chat.users.get(b.getAttribute('data-username').toLowerCase());
- if (!u1 || !u2) return 0;
-
- const u1Nick = u1.nick.toLowerCase();
- const u2Nick = u2.nick.toLowerCase();
+ const u1Nick = a.getAttribute('data-username').toLowerCase();
+ const u2Nick = b.getAttribute('data-username').toLowerCase();
if (u1Nick < u2Nick) return -1;
if (u1Nick > u2Nick) return 1;
return 0;
@@ -76,9 +73,10 @@ export default class ChatUserMenu extends ChatMenu {
}
return true;
});
- this.chat.source.on('JOIN', (data) => this.addAndRedraw(data.nick));
- this.chat.source.on('QUIT', (data) => this.removeAndRedraw(data.nick));
- this.chat.source.on('NAMES', () => this.addAll());
+ this.chat.source.on('JOIN', (data) => this.addAndRedraw(data));
+ this.chat.source.on('QUIT', (data) => this.removeAndRedraw(data));
+ this.chat.source.on('NAMES', (data) => this.addAll(data.users));
+ this.chat.source.on('UPDATEUSER', (data) => this.replaceAndRedraw(data));
this.searchinput.on(
'keyup',
debounce(
@@ -146,7 +144,7 @@ export default class ChatUserMenu extends ChatMenu {
return features !== '' ? `${features}` : '';
}
- addAll() {
+ addAll(users) {
this.totalcount = 0;
this.container.empty();
this.sections = new Map();
@@ -157,25 +155,32 @@ export default class ChatUserMenu extends ChatMenu {
this.flairSection.set(flair, data.name)
);
});
- [...this.chat.users.keys()].forEach((username) =>
- this.addElement(username)
- );
+ users.forEach((u) => this.addElement(u));
this.sort();
this.filter();
this.redraw();
}
- addAndRedraw(username) {
- if (!this.hasElement(username)) {
- this.addElement(username, true);
+ addAndRedraw(user) {
+ if (!this.hasElement(user)) {
+ this.addElement(user, true);
this.filter();
this.redraw();
}
}
- removeAndRedraw(username) {
- if (this.hasElement(username)) {
- this.removeElement(username);
+ removeAndRedraw(user) {
+ if (this.hasElement(user)) {
+ this.removeElement(user);
+ this.redraw();
+ }
+ }
+
+ replaceAndRedraw(user) {
+ if (this.hasElement(user)) {
+ this.removeElement(user);
+ this.addElement(user, true);
+ this.filter();
this.redraw();
}
}
@@ -219,19 +224,19 @@ export default class ChatUserMenu extends ChatMenu {
this.container.append(section);
}
- removeElement(username) {
- this.container.find(`.user-entry[data-username="${username}"]`).remove();
+ removeElement(user) {
+ this.container.find(`.user-entry[data-user-id="${user.id}"]`).remove();
this.totalcount -= 1;
}
- addElement(username, sort = false) {
- const user = this.chat.users.get(username.toLowerCase());
+ addElement(messageUser, sort = false) {
+ const user = new ChatUser(messageUser);
const label =
!user.username || user.username === '' ? 'Anonymous' : user.username;
const features =
user.features.length === 0 ? 'nofeature' : user.features.join(' ');
const usr = $(
- `
`
+ ``
);
const section = this.sections.get(this.highestSection(user));
@@ -254,9 +259,9 @@ export default class ChatUserMenu extends ChatMenu {
this.totalcount += 1;
}
- hasElement(username) {
+ hasElement(user) {
return (
- this.container.find(`.user-entry[data-username="${username}"]`).length > 0
+ this.container.find(`.user-entry[data-user-id="${user.id}"]`).length > 0
);
}
diff --git a/assets/chat/js/messages/MessageBuilder.js b/assets/chat/js/messages/MessageBuilder.js
index 888c660f..91c54485 100644
--- a/assets/chat/js/messages/MessageBuilder.js
+++ b/assets/chat/js/messages/MessageBuilder.js
@@ -1,6 +1,7 @@
import MessageTypes from './MessageTypes';
import ChatUIMessage from './ChatUIMessage';
import ChatMessage from './ChatMessage';
+import ChatUser from '../user';
import ChatUserMessage from './ChatUserMessage';
import ChatEmoteMessage from './ChatEmoteMessage';
import PinnedMessage from './PinnedMessage';
@@ -59,47 +60,49 @@ export default class MessageBuilder {
return new PinnedMessage(message, user, timestamp, uuid);
}
- static subscription(
- message,
- user,
- tier,
- tierLabel,
- streak,
- timestamp = null
- ) {
+ static subscription(data) {
return new ChatRegularSubscriptionMessage(
- message,
- user,
- tier,
- tierLabel,
- streak,
- timestamp
+ data.data,
+ new ChatUser(data.user),
+ data.tier,
+ data.tierLabel,
+ data.streak,
+ data.timestamp,
+ data.uuid
);
}
- static gift(message, user, tier, tierLabel, giftee, timestamp = null) {
+ static gift(data) {
return new ChatGiftedSubscriptionMessage(
- message,
- user,
- tier,
- tierLabel,
- giftee,
- timestamp
+ data.data,
+ new ChatUser(data.user),
+ data.tier,
+ data.tierLabel,
+ new ChatUser(data.recipient),
+ data.timestamp,
+ data.uuid
);
}
- static massgift(message, user, tier, tierLabel, quantity, timestamp = null) {
+ static massgift(data) {
return new ChatMassSubscriptionMessage(
- message,
- user,
- tier,
- tierLabel,
- quantity,
- timestamp
+ data.data,
+ new ChatUser(data.user),
+ data.tier,
+ data.tierLabel,
+ data.quantity,
+ data.timestamp,
+ data.uuid
);
}
- static donation(message, user, currency, timestamp = null) {
- return new ChatDonationMessage(message, user, currency, timestamp);
+ static donation(data) {
+ return new ChatDonationMessage(
+ data.data,
+ new ChatUser(data.user),
+ data.amount,
+ data.timestamp,
+ data.uuid
+ );
}
}
diff --git a/assets/chat/js/messages/subscriptions/ChatGiftedSubscriptionMessage.js b/assets/chat/js/messages/subscriptions/ChatGiftedSubscriptionMessage.js
index 565f7764..07be0899 100644
--- a/assets/chat/js/messages/subscriptions/ChatGiftedSubscriptionMessage.js
+++ b/assets/chat/js/messages/subscriptions/ChatGiftedSubscriptionMessage.js
@@ -1,5 +1,4 @@
import { usernameColorFlair } from '../ChatUserMessage';
-import ChatUser from '../../user';
import ChatSubscriptionMessage from './ChatSubscriptionMessage';
import MessageTypes from '../MessageTypes';
@@ -23,7 +22,7 @@ export default class ChatGiftedSubscriptionMessage extends ChatSubscriptionMessa
};
}, {});
- attributes['data-giftee'] = this.giftee.toLowerCase();
+ attributes['data-giftee'] = this.giftee.username.toLowerCase();
message.querySelector('.subscription-icon').classList.add('gift');
@@ -32,11 +31,9 @@ export default class ChatGiftedSubscriptionMessage extends ChatSubscriptionMessa
.querySelector('#user-template')
?.content.cloneNode(true).firstElementChild;
- const gifteeUser =
- chat.users.get(this.giftee.toLowerCase()) ?? new ChatUser(this.giftee);
- const gifteeColorFlair = usernameColorFlair(chat.flairs, gifteeUser);
+ const gifteeColorFlair = usernameColorFlair(chat.flairs, this.giftee);
giftee.classList.add(gifteeColorFlair?.name);
- giftee.innerText = gifteeUser.username;
+ giftee.innerText = this.giftee.username;
const subscriptionInfo = message.querySelector('.event-info');
const user = message.querySelector('.user');
diff --git a/assets/chat/js/user.js b/assets/chat/js/user.js
index 85b8c115..fcec85f0 100644
--- a/assets/chat/js/user.js
+++ b/assets/chat/js/user.js
@@ -3,11 +3,13 @@ import UserFeature from './features';
class ChatUser {
constructor(args = {}) {
if (typeof args === 'string') {
+ this.id = null;
this.nick = args;
this.username = args;
this.createdDate = args;
this.features = [];
} else {
+ this.id = args.id || null;
this.nick = args.nick || '';
this.username = args.nick || '';
this.createdDate = args.createdDate || '';
diff --git a/package-lock.json b/package-lock.json
index 629deafc..b2426ef0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "dgg-chat-gui",
- "version": "2.33.0",
+ "version": "2.35.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "dgg-chat-gui",
- "version": "2.32.0",
+ "version": "2.33.0",
"license": "SEE LICENSE IN ",
"dependencies": {
"dotenv": "^16.0.3",
@@ -5268,11 +5268,14 @@
}
},
"node_modules/dotenv": {
- "version": "16.0.3",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
- "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
+ "version": "16.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+ "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"engines": {
"node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/motdotla/dotenv?sponsor=1"
}
},
"node_modules/eastasianwidth": {
@@ -5330,9 +5333,9 @@
}
},
"node_modules/enhanced-resolve": {
- "version": "5.14.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz",
- "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==",
+ "version": "5.15.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
+ "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@@ -5679,9 +5682,9 @@
}
},
"node_modules/eslint-plugin-jest": {
- "version": "27.2.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz",
- "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==",
+ "version": "27.2.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz",
+ "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/utils": "^5.10.0"
@@ -5690,8 +5693,9 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
"peerDependencies": {
- "@typescript-eslint/eslint-plugin": "^5.0.0",
- "eslint": "^7.0.0 || ^8.0.0"
+ "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0",
+ "eslint": "^7.0.0 || ^8.0.0",
+ "jest": "*"
},
"peerDependenciesMeta": {
"@typescript-eslint/eslint-plugin": {
@@ -7078,9 +7082,9 @@
}
},
"node_modules/html-webpack-plugin": {
- "version": "5.5.1",
- "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.1.tgz",
- "integrity": "sha512-cTUzZ1+NqjGEKjmVgZKLMdiFg3m9MdRXkZW2OEe69WYVi5ONLMmlnSZdXzGGMOq0C8jGDrL6EWyEDDUioHO/pA==",
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz",
+ "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==",
"dev": true,
"dependencies": {
"@types/html-minifier-terser": "^6.0.0",
@@ -9744,15 +9748,6 @@
"node": ">=6"
}
},
- "node_modules/klona": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
- "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/launch-editor": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz",
@@ -10740,9 +10735,9 @@
}
},
"node_modules/overlayscrollbars": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.1.1.tgz",
- "integrity": "sha512-xvs2g8Tcq9+CZDpLEUchN3YUzjJhnTWw9kwqT/qcC53FIkOyP9mqnRMot5sW16tcsPT1KaMyzF0AMXw/7E4a8g=="
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.2.1.tgz",
+ "integrity": "sha512-5oMxq4UCiEVLiOSvovbX8p+P2NtPosjHC0KkIcaobnYuxGwMyTOwBCtBdqO1tXrrA02VVrNzuIjGMLisO2mIwg=="
},
"node_modules/p-limit": {
"version": "2.3.0",
@@ -13268,9 +13263,9 @@
}
},
"node_modules/webpack": {
- "version": "5.86.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.86.0.tgz",
- "integrity": "sha512-3BOvworZ8SO/D4GVP+GoRC3fVeg5MO4vzmq8TJJEkdmopxyazGDxN8ClqN12uzrZW9Tv8EED8v5VSb6Sqyi0pg==",
+ "version": "5.88.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
+ "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
@@ -13281,7 +13276,7 @@
"acorn-import-assertions": "^1.9.0",
"browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^5.14.1",
+ "enhanced-resolve": "^5.15.0",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
@@ -13291,7 +13286,7 @@
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
- "schema-utils": "^3.1.2",
+ "schema-utils": "^3.2.0",
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.7",
"watchpack": "^2.4.0",
@@ -13489,9 +13484,9 @@
}
},
"node_modules/webpack/node_modules/schema-utils": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz",
- "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
@@ -17755,9 +17750,9 @@
}
},
"dotenv": {
- "version": "16.0.3",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
- "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ=="
+ "version": "16.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+ "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ=="
},
"eastasianwidth": {
"version": "0.2.0",
@@ -17805,9 +17800,9 @@
"dev": true
},
"enhanced-resolve": {
- "version": "5.14.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz",
- "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==",
+ "version": "5.15.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
+ "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
"requires": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@@ -18270,9 +18265,9 @@
}
},
"eslint-plugin-jest": {
- "version": "27.2.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz",
- "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==",
+ "version": "27.2.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz",
+ "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==",
"dev": true,
"requires": {
"@typescript-eslint/utils": "^5.10.0"
@@ -19104,9 +19099,9 @@
}
},
"html-webpack-plugin": {
- "version": "5.5.1",
- "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.1.tgz",
- "integrity": "sha512-cTUzZ1+NqjGEKjmVgZKLMdiFg3m9MdRXkZW2OEe69WYVi5ONLMmlnSZdXzGGMOq0C8jGDrL6EWyEDDUioHO/pA==",
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz",
+ "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==",
"dev": true,
"requires": {
"@types/html-minifier-terser": "^6.0.0",
@@ -21062,12 +21057,6 @@
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
"dev": true
},
- "klona": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
- "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
- "dev": true
- },
"launch-editor": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz",
@@ -21796,9 +21785,9 @@
}
},
"overlayscrollbars": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.1.1.tgz",
- "integrity": "sha512-xvs2g8Tcq9+CZDpLEUchN3YUzjJhnTWw9kwqT/qcC53FIkOyP9mqnRMot5sW16tcsPT1KaMyzF0AMXw/7E4a8g=="
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.2.1.tgz",
+ "integrity": "sha512-5oMxq4UCiEVLiOSvovbX8p+P2NtPosjHC0KkIcaobnYuxGwMyTOwBCtBdqO1tXrrA02VVrNzuIjGMLisO2mIwg=="
},
"p-limit": {
"version": "2.3.0",
@@ -23670,9 +23659,9 @@
"dev": true
},
"webpack": {
- "version": "5.86.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.86.0.tgz",
- "integrity": "sha512-3BOvworZ8SO/D4GVP+GoRC3fVeg5MO4vzmq8TJJEkdmopxyazGDxN8ClqN12uzrZW9Tv8EED8v5VSb6Sqyi0pg==",
+ "version": "5.88.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
+ "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"requires": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
@@ -23683,7 +23672,7 @@
"acorn-import-assertions": "^1.9.0",
"browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^5.14.1",
+ "enhanced-resolve": "^5.15.0",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
@@ -23693,7 +23682,7 @@
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
- "schema-utils": "^3.1.2",
+ "schema-utils": "^3.2.0",
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.7",
"watchpack": "^2.4.0",
@@ -23701,9 +23690,9 @@
},
"dependencies": {
"schema-utils": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz",
- "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
"requires": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
diff --git a/package.json b/package.json
index 04d07295..f5abb564 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "dgg-chat-gui",
- "version": "2.33.0",
+ "version": "2.35.0",
"description": "Destiny.gg chat client front-end",
"main": "destiny",
"scripts": {