@lordbex/thelounge 4.4.4-blowfish → 4.5.0-blowfish-pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +2 -2
  2. package/dist/defaults/config.js +31 -2
  3. package/dist/package.json +93 -91
  4. package/dist/server/client.js +188 -194
  5. package/dist/server/clientManager.js +65 -63
  6. package/dist/server/command-line/index.js +44 -43
  7. package/dist/server/command-line/install.js +37 -70
  8. package/dist/server/command-line/outdated.js +12 -17
  9. package/dist/server/command-line/start.js +25 -26
  10. package/dist/server/command-line/storage.js +26 -31
  11. package/dist/server/command-line/uninstall.js +16 -23
  12. package/dist/server/command-line/upgrade.js +20 -26
  13. package/dist/server/command-line/users/add.js +33 -40
  14. package/dist/server/command-line/users/edit.js +18 -24
  15. package/dist/server/command-line/users/index.js +12 -16
  16. package/dist/server/command-line/users/list.js +11 -39
  17. package/dist/server/command-line/users/remove.js +16 -22
  18. package/dist/server/command-line/users/reset.js +34 -35
  19. package/dist/server/command-line/utils.js +231 -87
  20. package/dist/server/config.js +61 -52
  21. package/dist/server/helper.js +29 -28
  22. package/dist/server/identification.js +39 -34
  23. package/dist/server/index.js +1 -3
  24. package/dist/server/log.js +19 -16
  25. package/dist/server/models/chan.js +36 -33
  26. package/dist/server/models/msg.js +15 -19
  27. package/dist/server/models/network.js +88 -86
  28. package/dist/server/models/prefix.js +4 -7
  29. package/dist/server/models/user.js +5 -10
  30. package/dist/server/path-helper.js +8 -0
  31. package/dist/server/plugins/auth/ldap.js +177 -112
  32. package/dist/server/plugins/auth/local.js +10 -15
  33. package/dist/server/plugins/auth.js +6 -35
  34. package/dist/server/plugins/changelog.js +30 -27
  35. package/dist/server/plugins/clientCertificate.js +33 -37
  36. package/dist/server/plugins/dev-server.js +15 -21
  37. package/dist/server/plugins/inputs/action.js +9 -14
  38. package/dist/server/plugins/inputs/away.js +1 -3
  39. package/dist/server/plugins/inputs/ban.js +9 -14
  40. package/dist/server/plugins/inputs/blow.js +9 -14
  41. package/dist/server/plugins/inputs/connect.js +5 -10
  42. package/dist/server/plugins/inputs/ctcp.js +7 -12
  43. package/dist/server/plugins/inputs/disconnect.js +1 -3
  44. package/dist/server/plugins/inputs/ignore.js +23 -29
  45. package/dist/server/plugins/inputs/ignorelist.js +12 -18
  46. package/dist/server/plugins/inputs/index.js +8 -34
  47. package/dist/server/plugins/inputs/invite.js +7 -12
  48. package/dist/server/plugins/inputs/kick.js +7 -12
  49. package/dist/server/plugins/inputs/kill.js +1 -3
  50. package/dist/server/plugins/inputs/list.js +1 -3
  51. package/dist/server/plugins/inputs/mode.js +10 -15
  52. package/dist/server/plugins/inputs/msg.js +13 -18
  53. package/dist/server/plugins/inputs/mute.js +9 -15
  54. package/dist/server/plugins/inputs/nick.js +9 -14
  55. package/dist/server/plugins/inputs/notice.js +5 -7
  56. package/dist/server/plugins/inputs/part.js +11 -16
  57. package/dist/server/plugins/inputs/quit.js +7 -13
  58. package/dist/server/plugins/inputs/rainbow.js +55 -0
  59. package/dist/server/plugins/inputs/raw.js +1 -3
  60. package/dist/server/plugins/inputs/rejoin.js +7 -12
  61. package/dist/server/plugins/inputs/topic.js +7 -12
  62. package/dist/server/plugins/inputs/whois.js +1 -3
  63. package/dist/server/plugins/irc-events/away.js +14 -20
  64. package/dist/server/plugins/irc-events/cap.js +16 -22
  65. package/dist/server/plugins/irc-events/chghost.js +14 -13
  66. package/dist/server/plugins/irc-events/connection.js +61 -63
  67. package/dist/server/plugins/irc-events/ctcp.js +22 -28
  68. package/dist/server/plugins/irc-events/error.js +20 -26
  69. package/dist/server/plugins/irc-events/help.js +7 -13
  70. package/dist/server/plugins/irc-events/info.js +7 -13
  71. package/dist/server/plugins/irc-events/invite.js +7 -13
  72. package/dist/server/plugins/irc-events/join.js +30 -27
  73. package/dist/server/plugins/irc-events/kick.js +21 -17
  74. package/dist/server/plugins/irc-events/link.js +75 -96
  75. package/dist/server/plugins/irc-events/list.js +23 -26
  76. package/dist/server/plugins/irc-events/message.js +46 -52
  77. package/dist/server/plugins/irc-events/mode.js +66 -63
  78. package/dist/server/plugins/irc-events/modelist.js +29 -35
  79. package/dist/server/plugins/irc-events/motd.js +10 -16
  80. package/dist/server/plugins/irc-events/names.js +3 -6
  81. package/dist/server/plugins/irc-events/nick.js +26 -23
  82. package/dist/server/plugins/irc-events/part.js +19 -15
  83. package/dist/server/plugins/irc-events/quit.js +17 -14
  84. package/dist/server/plugins/irc-events/sasl.js +9 -15
  85. package/dist/server/plugins/irc-events/spgroups.js +38 -0
  86. package/dist/server/plugins/irc-events/spjoin.js +52 -0
  87. package/dist/server/plugins/irc-events/topic.js +12 -18
  88. package/dist/server/plugins/irc-events/unhandled.js +12 -12
  89. package/dist/server/plugins/irc-events/welcome.js +7 -13
  90. package/dist/server/plugins/irc-events/whois.js +20 -24
  91. package/dist/server/plugins/massEventAggregator.js +214 -0
  92. package/dist/server/plugins/messageStorage/sqlite.js +322 -141
  93. package/dist/server/plugins/messageStorage/text.js +21 -26
  94. package/dist/server/plugins/packages/index.js +105 -74
  95. package/dist/server/plugins/packages/publicClient.js +7 -16
  96. package/dist/server/plugins/packages/themes.js +11 -16
  97. package/dist/server/plugins/storage.js +28 -33
  98. package/dist/server/plugins/sts.js +12 -17
  99. package/dist/server/plugins/uploader.js +40 -43
  100. package/dist/server/plugins/webpush.js +23 -51
  101. package/dist/server/server.js +318 -271
  102. package/dist/server/storageCleaner.js +29 -37
  103. package/dist/server/utils/fish.js +7 -14
  104. package/dist/shared/irc.js +3 -6
  105. package/dist/shared/linkify.js +7 -14
  106. package/dist/shared/types/chan.js +6 -9
  107. package/dist/shared/types/changelog.js +1 -2
  108. package/dist/shared/types/config.js +1 -2
  109. package/dist/shared/types/mention.js +1 -2
  110. package/dist/shared/types/msg.js +3 -5
  111. package/dist/shared/types/network.js +1 -2
  112. package/dist/shared/types/storage.js +1 -2
  113. package/dist/shared/types/user.js +1 -2
  114. package/index.js +14 -10
  115. package/package.json +93 -91
  116. package/public/css/style.css +9 -6
  117. package/public/css/style.css.map +1 -1
  118. package/public/fonts/font-awesome/fa-brands-400.ttf +0 -0
  119. package/public/fonts/font-awesome/fa-brands-400.woff2 +0 -0
  120. package/public/fonts/font-awesome/fa-duotone-900.ttf +0 -0
  121. package/public/fonts/font-awesome/fa-duotone-900.woff2 +0 -0
  122. package/public/fonts/font-awesome/fa-light-300.ttf +0 -0
  123. package/public/fonts/font-awesome/fa-light-300.woff2 +0 -0
  124. package/public/fonts/font-awesome/fa-regular-400.ttf +0 -0
  125. package/public/fonts/font-awesome/fa-regular-400.woff2 +0 -0
  126. package/public/fonts/font-awesome/fa-solid-900.ttf +0 -0
  127. package/public/fonts/font-awesome/fa-solid-900.woff2 +0 -0
  128. package/public/fonts/font-awesome/fa-thin-100.ttf +0 -0
  129. package/public/fonts/font-awesome/fa-thin-100.woff2 +0 -0
  130. package/public/fonts/font-awesome/fa-v4compatibility.ttf +0 -0
  131. package/public/fonts/font-awesome/fa-v4compatibility.woff2 +0 -0
  132. package/public/js/bundle.js +1 -1
  133. package/public/js/bundle.js.map +1 -1
  134. package/public/js/bundle.vendor.js +1 -1
  135. package/public/js/bundle.vendor.js.LICENSE.txt +24 -6
  136. package/public/js/bundle.vendor.js.map +1 -1
  137. package/public/service-worker.js +1 -1
  138. package/public/themes/default.css +1 -1
  139. package/public/themes/morning.css +1 -1
  140. package/dist/webpack.config.js +0 -224
@@ -1,20 +1,14 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const msg_1 = __importDefault(require("../../models/msg"));
7
- const msg_2 = require("../../../shared/types/msg");
8
- exports.default = (function (irc, network) {
9
- const client = this;
10
- irc.on("invite", function (data) {
1
+ import Msg from "../../models/msg.js";
2
+ import { MessageType } from "../../../shared/types/msg.js";
3
+ export default (function (irc, network) {
4
+ irc.on("invite", (data) => {
11
5
  let chan = network.getChannel(data.channel);
12
6
  if (typeof chan === "undefined") {
13
7
  chan = network.getLobby();
14
8
  }
15
9
  const invitedYou = data.invited === irc.user.nick;
16
- const msg = new msg_1.default({
17
- type: msg_2.MessageType.INVITE,
10
+ const msg = new Msg({
11
+ type: MessageType.INVITE,
18
12
  time: data.time,
19
13
  from: chan.getUser(data.nick),
20
14
  target: chan.getUser(data.invited),
@@ -22,6 +16,6 @@ exports.default = (function (irc, network) {
22
16
  highlight: invitedYou,
23
17
  invitedYou: invitedYou,
24
18
  });
25
- chan.pushMessage(client, msg);
19
+ chan.pushMessage(this, msg);
26
20
  });
27
21
  });
@@ -1,53 +1,56 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const msg_1 = __importDefault(require("../../models/msg"));
7
- const user_1 = __importDefault(require("../../models/user"));
8
- const msg_2 = require("../../../shared/types/msg");
9
- const chan_1 = require("../../../shared/types/chan");
10
- exports.default = (function (irc, network) {
11
- const client = this;
12
- irc.on("join", function (data) {
1
+ import Msg from "../../models/msg.js";
2
+ import User from "../../models/user.js";
3
+ import { MessageType } from "../../../shared/types/msg.js";
4
+ import { ChanState } from "../../../shared/types/chan.js";
5
+ export default (function (irc, network) {
6
+ irc.on("join", (data) => {
13
7
  let chan = network.getChannel(data.channel);
14
8
  if (typeof chan === "undefined") {
15
- chan = client.createChannel({
9
+ chan = this.createChannel({
16
10
  name: data.channel,
17
- state: chan_1.ChanState.JOINED,
11
+ state: ChanState.JOINED,
18
12
  });
19
- client.emit("join", {
13
+ this.emit("join", {
20
14
  network: network.uuid,
21
15
  chan: chan.getFilteredClone(true),
22
16
  shouldOpen: false,
23
17
  index: network.addChannel(chan),
24
18
  });
25
- client.save();
26
- chan.loadMessages(client, network);
19
+ this.save();
20
+ chan.loadMessages(this, network);
27
21
  // Request channels' modes
28
22
  network.irc.raw("MODE", chan.name);
29
23
  }
30
24
  else if (data.nick === irc.user.nick) {
31
- chan.state = chan_1.ChanState.JOINED;
32
- client.emit("channel:state", {
25
+ chan.state = ChanState.JOINED;
26
+ this.emit("channel:state", {
33
27
  chan: chan.id,
34
28
  state: chan.state,
35
29
  });
36
30
  }
37
- const user = new user_1.default({ nick: data.nick });
38
- const msg = new msg_1.default({
31
+ const user = new User({ nick: data.nick });
32
+ const msg = new Msg({
39
33
  time: data.time,
40
34
  from: user,
41
35
  hostmask: data.ident + "@" + data.hostname,
42
36
  gecos: data.gecos,
43
37
  account: data.account,
44
- type: msg_2.MessageType.JOIN,
38
+ type: MessageType.JOIN,
45
39
  self: data.nick === irc.user.nick,
46
40
  });
47
- chan.pushMessage(client, msg);
48
- chan.setUser(new user_1.default({ nick: data.nick }));
49
- client.emit("users", {
50
- chan: chan.id,
51
- });
41
+ // User list update callback - executed regardless of buffering
42
+ const updateUserList = () => {
43
+ chan.setUser(new User({ nick: data.nick }));
44
+ this.emit("users", {
45
+ chan: chan.id,
46
+ });
47
+ };
48
+ // Try to process through mass event aggregator
49
+ const wasBuffered = this.massEventAggregator.processMessage(network, chan, msg, updateUserList);
50
+ if (!wasBuffered) {
51
+ // Not in mass event mode - process normally
52
+ chan.pushMessage(this, msg);
53
+ updateUserList();
54
+ }
52
55
  });
53
56
  });
@@ -1,21 +1,15 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const msg_1 = __importDefault(require("../../models/msg"));
7
- const msg_2 = require("../../../shared/types/msg");
8
- const chan_1 = require("../../../shared/types/chan");
9
- exports.default = (function (irc, network) {
10
- const client = this;
11
- irc.on("kick", function (data) {
1
+ import Msg from "../../models/msg.js";
2
+ import { MessageType } from "../../../shared/types/msg.js";
3
+ import { ChanState } from "../../../shared/types/chan.js";
4
+ export default (function (irc, network) {
5
+ irc.on("kick", (data) => {
12
6
  const chan = network.getChannel(data.channel);
13
7
  if (typeof chan === "undefined") {
14
8
  return;
15
9
  }
16
10
  const user = chan.getUser(data.kicked);
17
- const msg = new msg_1.default({
18
- type: msg_2.MessageType.KICK,
11
+ const msg = new Msg({
12
+ type: MessageType.KICK,
19
13
  time: data.time,
20
14
  from: chan.getUser(data.nick),
21
15
  target: user,
@@ -23,17 +17,27 @@ exports.default = (function (irc, network) {
23
17
  highlight: data.kicked === irc.user.nick,
24
18
  self: data.nick === irc.user.nick,
25
19
  });
26
- chan.pushMessage(client, msg);
20
+ // Self kicks should not be buffered and need special handling
27
21
  if (data.kicked === irc.user.nick) {
22
+ chan.pushMessage(this, msg);
28
23
  chan.users = new Map();
29
- chan.state = chan_1.ChanState.PARTED;
30
- client.emit("channel:state", {
24
+ chan.state = ChanState.PARTED;
25
+ this.emit("channel:state", {
31
26
  chan: chan.id,
32
27
  state: chan.state,
33
28
  });
29
+ return;
34
30
  }
35
- else {
31
+ // User list update callback - executed regardless of buffering
32
+ const updateUserList = () => {
36
33
  chan.removeUser(user);
34
+ };
35
+ // Try to process through mass event aggregator
36
+ const wasBuffered = this.massEventAggregator.processMessage(network, chan, msg, updateUserList);
37
+ if (!wasBuffered) {
38
+ // Not in mass event mode - process normally
39
+ chan.pushMessage(this, msg);
40
+ updateUserList();
37
41
  }
38
42
  });
39
43
  });
@@ -1,47 +1,18 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- const cheerio = __importStar(require("cheerio"));
30
- const got_1 = __importDefault(require("got"));
31
- const url_1 = require("url");
32
- const mime_types_1 = __importDefault(require("mime-types"));
33
- const log_1 = __importDefault(require("../../log"));
34
- const config_1 = __importDefault(require("../../config"));
35
- const linkify_1 = require("../../../shared/linkify");
36
- const storage_1 = __importDefault(require("../storage"));
1
+ import * as cheerio from "cheerio";
2
+ import { URL } from "url";
3
+ import mime from "mime-types";
4
+ import log from "../../log.js";
5
+ import Config from "../../config.js";
6
+ import { findLinksWithSchema } from "../../../shared/linkify.js";
7
+ import storage from "../storage.js";
37
8
  const currentFetchPromises = new Map();
38
9
  const imageTypeRegex = /^image\/.+/;
39
10
  const mediaTypeRegex = /^(audio|video)\/.+/;
40
- function default_1(client, chan, msg, cleanText) {
41
- if (!config_1.default.values.prefetch) {
11
+ export default function (client, chan, msg, cleanText) {
12
+ if (!Config.values.prefetch) {
42
13
  return;
43
14
  }
44
- msg.previews = (0, linkify_1.findLinksWithSchema)(cleanText).reduce((cleanLinks, link) => {
15
+ msg.previews = findLinksWithSchema(cleanText).reduce((cleanLinks, link) => {
45
16
  const url = normalizeURL(link.link);
46
17
  // If the URL is invalid and cannot be normalized, don't fetch it
47
18
  if (!url) {
@@ -65,7 +36,7 @@ function default_1(client, chan, msg, cleanText) {
65
36
  shown: null,
66
37
  };
67
38
  cleanLinks.push(preview);
68
- const urlObj = new url_1.URL(url);
39
+ const urlObj = new URL(url);
69
40
  if ((urlObj.hostname.endsWith("youtube.com") && urlObj.pathname.includes("watch")) ||
70
41
  urlObj.hostname.endsWith("youtu.be")) {
71
42
  fetchYoutube(url, msg, chan, preview, client);
@@ -76,7 +47,6 @@ function default_1(client, chan, msg, cleanText) {
76
47
  return cleanLinks;
77
48
  }, []);
78
49
  }
79
- exports.default = default_1;
80
50
  function fetchUrl(url, msg, chan, preview, client) {
81
51
  fetch(url, {
82
52
  accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
@@ -139,7 +109,7 @@ function parseHtml(preview, res, client) {
139
109
  if (preview.body.length) {
140
110
  preview.body = preview.body.substr(0, 300);
141
111
  }
142
- if (!config_1.default.values.prefetchStorage && config_1.default.values.disableMediaPreview) {
112
+ if (!Config.values.prefetchStorage && Config.values.disableMediaPreview) {
143
113
  resolve(res);
144
114
  return;
145
115
  }
@@ -157,7 +127,7 @@ function parseHtml(preview, res, client) {
157
127
  .then((resThumb) => {
158
128
  if (resThumb !== null &&
159
129
  imageTypeRegex.test(resThumb.type) &&
160
- resThumb.size <= config_1.default.values.prefetchMaxImageSize * 1024) {
130
+ resThumb.size <= Config.values.prefetchMaxImageSize * 1024) {
161
131
  preview.thumbActualUrl = thumb;
162
132
  }
163
133
  resolve(resThumb);
@@ -170,11 +140,10 @@ function parseHtml(preview, res, client) {
170
140
  });
171
141
  });
172
142
  }
173
- // TODO: type $
174
143
  function parseHtmlMedia($, preview, client) {
175
144
  return new Promise((resolve, reject) => {
176
- if (config_1.default.values.disableMediaPreview) {
177
- reject();
145
+ if (Config.values.disableMediaPreview) {
146
+ reject(new Error("Media preview is disabled"));
178
147
  return;
179
148
  }
180
149
  let foundMedia = false;
@@ -185,7 +154,7 @@ function parseHtmlMedia($, preview, client) {
185
154
  if (openGraphType &&
186
155
  !openGraphType.startsWith("video") &&
187
156
  !openGraphType.startsWith("music")) {
188
- reject();
157
+ reject(new Error("Open Graph type is not video or music"));
189
158
  return;
190
159
  }
191
160
  ["video", "audio"].forEach((type) => {
@@ -218,7 +187,7 @@ function parseHtmlMedia($, preview, client) {
218
187
  })
219
188
  .then((resMedia) => {
220
189
  if (resMedia === null || !mediaTypeRegex.test(resMedia.type)) {
221
- return reject();
190
+ return reject(new Error("Invalid media type"));
222
191
  }
223
192
  preview.type = type;
224
193
  preview.media = mediaUrl;
@@ -231,7 +200,7 @@ function parseHtmlMedia($, preview, client) {
231
200
  });
232
201
  });
233
202
  if (!foundMedia) {
234
- reject();
203
+ reject(new Error("No media found"));
235
204
  }
236
205
  });
237
206
  }
@@ -254,13 +223,13 @@ function parse(msg, chan, preview, res, client) {
254
223
  case "image/jxl":
255
224
  case "image/webp":
256
225
  case "image/avif":
257
- if (!config_1.default.values.prefetchStorage && config_1.default.values.disableMediaPreview) {
226
+ if (!Config.values.prefetchStorage && Config.values.disableMediaPreview) {
258
227
  return removePreview(msg, preview);
259
228
  }
260
- if (res.size > config_1.default.values.prefetchMaxImageSize * 1024) {
229
+ if (res.size > Config.values.prefetchMaxImageSize * 1024) {
261
230
  preview.type = "error";
262
231
  preview.error = "image-too-big";
263
- preview.maxSize = config_1.default.values.prefetchMaxImageSize * 1024;
232
+ preview.maxSize = Config.values.prefetchMaxImageSize * 1024;
264
233
  }
265
234
  else {
266
235
  preview.type = "image";
@@ -284,7 +253,7 @@ function parse(msg, chan, preview, res, client) {
284
253
  if (!preview.link.startsWith("https://")) {
285
254
  break;
286
255
  }
287
- if (config_1.default.values.disableMediaPreview) {
256
+ if (Config.values.disableMediaPreview) {
288
257
  return removePreview(msg, preview);
289
258
  }
290
259
  preview.type = "audio";
@@ -297,7 +266,7 @@ function parse(msg, chan, preview, res, client) {
297
266
  if (!preview.link.startsWith("https://")) {
298
267
  break;
299
268
  }
300
- if (config_1.default.values.disableMediaPreview) {
269
+ if (Config.values.disableMediaPreview) {
301
270
  return removePreview(msg, preview);
302
271
  }
303
272
  preview.type = "video";
@@ -315,13 +284,16 @@ function parse(msg, chan, preview, res, client) {
315
284
  function handlePreview(client, chan, msg, preview, res) {
316
285
  const thumb = preview.thumbActualUrl || "";
317
286
  delete preview.thumbActualUrl;
318
- if (!thumb.length || !config_1.default.values.prefetchStorage) {
287
+ if (!thumb.length || !Config.values.prefetchStorage) {
319
288
  preview.thumb = thumb;
320
289
  return emitPreview(client, chan, msg, preview);
321
290
  }
291
+ if (!res) {
292
+ return emitPreview(client, chan, msg, preview);
293
+ }
322
294
  // Get the correct file extension for the provided content-type
323
295
  // This is done to prevent user-input being stored in the file name (extension)
324
- const extension = mime_types_1.default.extension(res.type);
296
+ const extension = mime.extension(res.type);
325
297
  if (!extension) {
326
298
  // For link previews, drop the thumbnail
327
299
  // For other types, do not display preview at all
@@ -330,7 +302,7 @@ function handlePreview(client, chan, msg, preview, res) {
330
302
  }
331
303
  return emitPreview(client, chan, msg, preview);
332
304
  }
333
- storage_1.default.store(res.data, extension, (uri) => {
305
+ storage.store(res.data, extension, (uri) => {
334
306
  preview.thumb = uri;
335
307
  emitPreview(client, chan, msg, preview);
336
308
  });
@@ -381,69 +353,76 @@ function fetch(uri, headers) {
381
353
  if (promise) {
382
354
  return promise;
383
355
  }
384
- const prefetchTimeout = config_1.default.values.prefetchTimeout;
356
+ const prefetchTimeout = Config.values.prefetchTimeout;
385
357
  if (!prefetchTimeout) {
386
- log_1.default.warn("prefetchTimeout is missing from your The Lounge configuration, defaulting to 5000 ms");
358
+ log.warn("prefetchTimeout is missing from your The Lounge configuration, defaulting to 5000 ms");
387
359
  }
388
360
  promise = new Promise((resolve, reject) => {
389
361
  let buffer = Buffer.from("");
390
362
  let contentLength = 0;
391
363
  let contentType;
392
- let limit = config_1.default.values.prefetchMaxImageSize * 1024;
364
+ let limit = Config.values.prefetchMaxImageSize * 1024;
393
365
  try {
394
- const gotStream = got_1.default.stream(uri, {
395
- retry: 0,
396
- timeout: prefetchTimeout || 5000, // milliseconds
366
+ const requestOptions = {
367
+ method: "GET",
397
368
  headers: getRequestHeaders(headers),
398
- localAddress: config_1.default.values.bind,
399
- });
400
- gotStream
401
- .on("response", function (res) {
402
- contentLength = parseInt(res.headers["content-length"], 10) || 0;
403
- contentType = res.headers["content-type"];
369
+ signal: AbortSignal.timeout(prefetchTimeout || 5000),
370
+ };
371
+ globalThis
372
+ .fetch(uri, requestOptions)
373
+ .then(async (response) => {
374
+ contentLength = parseInt(response.headers.get("content-length") || "0", 10);
375
+ contentType = response.headers.get("content-type") || undefined;
404
376
  if (contentType && imageTypeRegex.test(contentType)) {
405
377
  // response is an image
406
- // if Content-Length header reports a size exceeding the prefetch limit, abort fetch
407
- // and if file is not to be stored we don't need to download further either
408
- if (contentLength > limit || !config_1.default.values.prefetchStorage) {
409
- gotStream.destroy();
378
+ if (contentLength > limit || !Config.values.prefetchStorage) {
379
+ resolve({
380
+ data: Buffer.alloc(0),
381
+ type: contentType,
382
+ size: contentLength,
383
+ });
384
+ return;
410
385
  }
411
386
  }
412
387
  else if (contentType && mediaTypeRegex.test(contentType)) {
413
- // We don't need to download the file any further after we received content-type header
414
- gotStream.destroy();
388
+ // We don't need to download the file any further
389
+ resolve({ data: Buffer.alloc(0), type: contentType, size: contentLength });
390
+ return;
415
391
  }
416
392
  else {
417
- // if not image, limit download to the max search size, since we need only meta tags
418
- // twitter.com sends opengraph meta tags within ~20kb of data for individual tweets, the default is set to 50.
419
- // for sites like Youtube the og tags are in the first 300K and hence this is configurable by the admin
393
+ // if not image, limit download to the max search size
420
394
  limit =
421
- "prefetchMaxSearchSize" in config_1.default.values
422
- ? config_1.default.values.prefetchMaxSearchSize * 1024
423
- : // set to the previous size if config option is unset
424
- 50 * 1024;
395
+ "prefetchMaxSearchSize" in Config.values
396
+ ? Config.values.prefetchMaxSearchSize * 1024
397
+ : 50 * 1024;
425
398
  }
426
- })
427
- .on("error", (e) => reject(e))
428
- .on("data", (data) => {
429
- buffer = Buffer.concat([buffer, data], buffer.length + data.length);
430
- if (buffer.length >= limit) {
431
- gotStream.destroy();
399
+ if (!response.body) {
400
+ throw new Error("Response body is null");
401
+ }
402
+ const reader = response.body.getReader();
403
+ while (true) {
404
+ const { done, value } = await reader.read();
405
+ if (done) {
406
+ break;
407
+ }
408
+ const chunkBuffer = Buffer.from(value);
409
+ buffer = Buffer.concat([buffer, chunkBuffer]);
410
+ if (buffer.length >= limit) {
411
+ await reader.cancel();
412
+ break;
413
+ }
432
414
  }
433
- })
434
- .on("end", () => gotStream.destroy())
435
- .on("close", () => {
436
415
  let type = "";
437
- // If we downloaded more data then specified in Content-Length, use real data size
438
416
  const size = contentLength > buffer.length ? contentLength : buffer.length;
439
417
  if (contentType) {
440
418
  type = contentType.split(/ *; */).shift() || "";
441
419
  }
442
420
  resolve({ data: buffer, type, size });
443
- });
421
+ })
422
+ .catch((e) => reject(e instanceof Error ? e : new Error(String(e))));
444
423
  }
445
424
  catch (e) {
446
- return reject(e);
425
+ return reject(e instanceof Error ? e : new Error(String(e)));
447
426
  }
448
427
  });
449
428
  const removeCache = () => currentFetchPromises.delete(cacheKey);
@@ -453,7 +432,7 @@ function fetch(uri, headers) {
453
432
  }
454
433
  function normalizeURL(link, baseLink, disallowHttp = false) {
455
434
  try {
456
- const url = new url_1.URL(link, baseLink);
435
+ const url = new URL(link, baseLink);
457
436
  // Only fetch http and https links
458
437
  if (url.protocol !== "http:" && url.protocol !== "https:") {
459
438
  return undefined;
@@ -469,7 +448,7 @@ function normalizeURL(link, baseLink, disallowHttp = false) {
469
448
  url.hash = "";
470
449
  return url.toString();
471
450
  }
472
- catch (e) {
451
+ catch {
473
452
  // if an exception was thrown, the url is not valid
474
453
  }
475
454
  return undefined;
@@ -1,35 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const chan_1 = require("../../../shared/types/chan");
4
- exports.default = (function (irc, network) {
5
- const client = this;
1
+ import { ChanType, SpecialChanType } from "../../../shared/types/chan.js";
2
+ export default (function (irc, network) {
6
3
  const MAX_CHANS = 500;
7
- irc.on("channel list start", function () {
8
- network.chanCache = [];
9
- updateListStatus({
10
- text: "Loading channel list, this can take a moment...",
11
- });
12
- });
13
- irc.on("channel list", function (channels) {
14
- Array.prototype.push.apply(network.chanCache, channels);
15
- updateListStatus({
16
- text: `Loaded ${network.chanCache.length} channels...`,
17
- });
18
- });
19
- irc.on("channel list end", function () {
20
- updateListStatus(network.chanCache.sort((a, b) => b.num_users - a.num_users).slice(0, MAX_CHANS));
21
- network.chanCache = [];
22
- });
23
4
  function updateListStatus(msg) {
24
5
  let chan = network.getChannel("Channel List");
25
6
  if (typeof chan === "undefined") {
26
- chan = client.createChannel({
27
- type: chan_1.ChanType.SPECIAL,
28
- special: chan_1.SpecialChanType.CHANNELLIST,
7
+ chan = this.createChannel({
8
+ type: ChanType.SPECIAL,
9
+ special: SpecialChanType.CHANNELLIST,
29
10
  name: "Channel List",
30
11
  data: msg,
31
12
  });
32
- client.emit("join", {
13
+ this.emit("join", {
33
14
  network: network.uuid,
34
15
  chan: chan.getFilteredClone(true),
35
16
  shouldOpen: false,
@@ -38,10 +19,26 @@ exports.default = (function (irc, network) {
38
19
  }
39
20
  else {
40
21
  chan.data = msg;
41
- client.emit("msg:special", {
22
+ this.emit("msg:special", {
42
23
  chan: chan.id,
43
24
  data: msg,
44
25
  });
45
26
  }
46
27
  }
28
+ irc.on("channel list start", () => {
29
+ network.chanCache = [];
30
+ updateListStatus.call(this, {
31
+ text: "Loading channel list, this can take a moment...",
32
+ });
33
+ });
34
+ irc.on("channel list", (channels) => {
35
+ Array.prototype.push.apply(network.chanCache, channels);
36
+ updateListStatus.call(this, {
37
+ text: `Loaded ${network.chanCache.length} channels...`,
38
+ });
39
+ });
40
+ irc.on("channel list end", () => {
41
+ updateListStatus.call(this, network.chanCache.sort((a, b) => b.num_users - a.num_users).slice(0, MAX_CHANS));
42
+ network.chanCache = [];
43
+ });
47
44
  });