@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,16 +1,11 @@
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 lodash_1 = __importDefault(require("lodash"));
7
- const log_1 = __importDefault(require("../log"));
8
- const config_1 = __importDefault(require("../config"));
9
- const user_1 = __importDefault(require("./user"));
10
- const storage_1 = __importDefault(require("../plugins/storage"));
11
- const prefix_1 = __importDefault(require("./prefix"));
12
- const msg_1 = require("../../shared/types/msg");
13
- const chan_1 = require("../../shared/types/chan");
1
+ import _ from "lodash";
2
+ import log from "../log.js";
3
+ import Config from "../config.js";
4
+ import User from "./user.js";
5
+ import storage from "../plugins/storage.js";
6
+ import Prefix from "./prefix.js";
7
+ import { MessageType } from "../../shared/types/msg.js";
8
+ import { ChanType, ChanState } from "../../shared/types/chan.js";
14
9
  class Chan {
15
10
  // TODO: don't force existence, figure out how to make TS infer it.
16
11
  id;
@@ -25,6 +20,7 @@ class Chan {
25
20
  muted;
26
21
  type;
27
22
  state;
23
+ pinned;
28
24
  // mIRC FiSH Blowfish key, stored server-side only
29
25
  blowfishKey;
30
26
  userAway;
@@ -32,20 +28,22 @@ class Chan {
32
28
  data;
33
29
  closed;
34
30
  num_users;
31
+ groups;
35
32
  constructor(attr) {
36
- lodash_1.default.defaults(this, attr, {
33
+ _.defaults(this, attr, {
37
34
  id: 0,
38
35
  messages: [],
39
36
  name: "",
40
37
  key: "",
41
38
  topic: "",
42
- type: chan_1.ChanType.CHANNEL,
43
- state: chan_1.ChanState.PARTED,
39
+ type: ChanType.CHANNEL,
40
+ state: ChanState.PARTED,
44
41
  firstUnread: 0,
45
42
  unread: 0,
46
43
  highlight: 0,
47
44
  users: new Map(),
48
45
  muted: false,
46
+ pinned: false,
49
47
  });
50
48
  }
51
49
  destroy() {
@@ -55,7 +53,7 @@ class Chan {
55
53
  const chanId = this.id;
56
54
  msg.id = client.idMsg++;
57
55
  // If this channel is open in any of the clients, do not increase unread counter
58
- const isOpen = lodash_1.default.find(client.attachedClients, { openChannel: chanId }) !== undefined;
56
+ const isOpen = _.find(client.attachedClients, { openChannel: chanId }) !== undefined;
59
57
  if (msg.self) {
60
58
  // reset counters/markers when receiving self-/echo-message
61
59
  this.unread = 0;
@@ -76,7 +74,7 @@ class Chan {
76
74
  client.emit("msg", { chan: chanId, msg, unread: this.unread, highlight: this.highlight });
77
75
  // Never store messages in public mode as the session
78
76
  // is completely destroyed when the page gets closed
79
- if (config_1.default.values.public) {
77
+ if (Config.values.public) {
80
78
  return;
81
79
  }
82
80
  // showInActive is only processed on "msg", don't need it on page reload
@@ -84,24 +82,24 @@ class Chan {
84
82
  delete msg.showInActive;
85
83
  }
86
84
  this.writeUserLog(client, msg);
87
- if (config_1.default.values.maxHistory >= 0 && this.messages.length > config_1.default.values.maxHistory) {
88
- const deleted = this.messages.splice(0, this.messages.length - config_1.default.values.maxHistory);
85
+ if (Config.values.maxHistory >= 0 && this.messages.length > Config.values.maxHistory) {
86
+ const deleted = this.messages.splice(0, this.messages.length - Config.values.maxHistory);
89
87
  // If maxHistory is 0, image would be dereferenced before client had a chance to retrieve it,
90
88
  // so for now, just don't implement dereferencing for this edge case.
91
- if (config_1.default.values.maxHistory > 0) {
89
+ if (Config.values.maxHistory > 0) {
92
90
  this.dereferencePreviews(deleted);
93
91
  }
94
92
  }
95
93
  }
96
94
  dereferencePreviews(messages) {
97
- if (!config_1.default.values.prefetch || !config_1.default.values.prefetchStorage) {
95
+ if (!Config.values.prefetch || !Config.values.prefetchStorage) {
98
96
  return;
99
97
  }
100
98
  messages.forEach((message) => {
101
99
  if (message.previews) {
102
100
  message.previews.forEach((preview) => {
103
101
  if (preview.thumb) {
104
- storage_1.default.dereference(preview.thumb);
102
+ storage.dereference(preview.thumb);
105
103
  preview.thumb = "";
106
104
  }
107
105
  });
@@ -132,7 +130,7 @@ class Chan {
132
130
  return this.users.get(nick.toLowerCase());
133
131
  }
134
132
  getUser(nick) {
135
- return this.findUser(nick) || new user_1.default({ nick }, new prefix_1.default([]));
133
+ return this.findUser(nick) || new User({ nick }, new Prefix([]));
136
134
  }
137
135
  setUser(user) {
138
136
  this.users.set(user.nick.toLowerCase(), user);
@@ -176,10 +174,12 @@ class Chan {
176
174
  muted: this.muted,
177
175
  type: this.type,
178
176
  state: this.state,
177
+ pinned: this.pinned,
179
178
  special: this.special,
180
179
  data: this.data,
181
180
  closed: this.closed,
182
181
  num_users: this.num_users,
182
+ groups: this.groups,
183
183
  };
184
184
  // TODO: funny array mutation below might need to be reproduced
185
185
  // static optionalProperties = ["userAway", "special", "data", "closed", "num_users"];
@@ -196,13 +196,12 @@ class Chan {
196
196
  if (client.messageStorage.length === 0) {
197
197
  return;
198
198
  }
199
- const targetChannel = this;
200
199
  // Is this particular message or channel loggable
201
200
  if (!msg.isLoggable() || !this.isLoggable()) {
202
201
  // Because notices are nasty and can be shown in active channel on the client
203
202
  // if there is no open query, we want to always log notices in the sender's name
204
- if (msg.type === msg_1.MessageType.NOTICE && msg.showInActive) {
205
- targetChannel.name = msg.from.nick || ""; // TODO: check if || works
203
+ if (msg.type === MessageType.NOTICE && msg.showInActive) {
204
+ this.name = msg.from.nick || ""; // TODO: check if || works
206
205
  }
207
206
  else {
208
207
  return;
@@ -214,7 +213,7 @@ class Chan {
214
213
  return;
215
214
  }
216
215
  for (const messageStorage of client.messageStorage) {
217
- messageStorage.index(target.network, targetChannel, msg).catch((e) => log_1.default.error(e));
216
+ messageStorage.index(target.network, this, msg).catch((e) => log.error(e));
218
217
  }
219
218
  }
220
219
  loadMessages(client, network) {
@@ -223,7 +222,7 @@ class Chan {
223
222
  }
224
223
  if (!network.irc) {
225
224
  // Network created, but misconfigured
226
- log_1.default.warn(`Failed to load messages for ${client.name}, network ${network.name} is not initialized.`);
225
+ log.warn(`Failed to load messages for ${client.name}, network ${network.name} is not initialized.`);
227
226
  return;
228
227
  }
229
228
  if (!client.messageProvider) {
@@ -247,9 +246,13 @@ class Chan {
247
246
  if (!this.firstUnread) {
248
247
  this.firstUnread = messages[messages.length - 1].id;
249
248
  }
249
+ const enhancedSearch = Boolean(client.config.clientSettings.searchEnabled &&
250
+ client.config.clientSettings.enableEnhancedSearch);
251
+ // if enhancedSearchEnabled = true send all loaded messages to the client
252
+ // otherwise only send 100
250
253
  client.emit("more", {
251
254
  chan: this.id,
252
- messages: messages.slice(-100),
255
+ messages: enhancedSearch ? messages : messages.slice(-100),
253
256
  totalMessages: messages.length,
254
257
  });
255
258
  if (network.irc.network.cap.isEnabled("znc.in/playback")) {
@@ -257,10 +260,10 @@ class Chan {
257
260
  requestZncPlayback(this, network, from);
258
261
  }
259
262
  })
260
- .catch((err) => log_1.default.error(`Failed to load messages for ${client.name}: ${err.toString()}`));
263
+ .catch((err) => log.error(`Failed to load messages for ${client.name}: ${err.toString()}`));
261
264
  }
262
265
  isLoggable() {
263
- return this.type === chan_1.ChanType.CHANNEL || this.type === chan_1.ChanType.QUERY;
266
+ return this.type === ChanType.CHANNEL || this.type === ChanType.QUERY;
264
267
  }
265
268
  setMuteStatus(muted) {
266
269
  this.muted = !!muted;
@@ -272,4 +275,4 @@ function requestZncPlayback(channel, network, from) {
272
275
  }
273
276
  network.irc.raw("ZNC", "*playback", "PLAY", channel.name, from.toString());
274
277
  }
275
- exports.default = Chan;
278
+ export default Chan;
@@ -1,10 +1,5 @@
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 lodash_1 = __importDefault(require("lodash"));
7
- const msg_1 = require("../../shared/types/msg");
1
+ import _ from "lodash";
2
+ import { MessageType, } from "../../shared/types/msg.js";
8
3
  class Msg {
9
4
  from;
10
5
  id;
@@ -39,6 +34,7 @@ class Msg {
39
34
  users;
40
35
  statusmsgGroup;
41
36
  params;
37
+ massEventSummary;
42
38
  constructor(attr) {
43
39
  // Some properties need to be copied in the Msg object instead of referenced
44
40
  if (attr) {
@@ -51,12 +47,12 @@ class Msg {
51
47
  }
52
48
  });
53
49
  }
54
- lodash_1.default.defaults(this, attr, {
50
+ _.defaults(this, attr, {
55
51
  from: {},
56
52
  id: 0,
57
53
  previews: [],
58
54
  text: "",
59
- type: msg_1.MessageType.MESSAGE,
55
+ type: MessageType.MESSAGE,
60
56
  self: false,
61
57
  });
62
58
  if (this.time) {
@@ -70,23 +66,23 @@ class Msg {
70
66
  return this.previews.find((preview) => preview.link === link);
71
67
  }
72
68
  isLoggable() {
73
- if (this.type === msg_1.MessageType.TOPIC) {
69
+ if (this.type === MessageType.TOPIC) {
74
70
  // Do not log topic that is sent on channel join
75
71
  return !!this.from.nick;
76
72
  }
77
73
  switch (this.type) {
78
- case msg_1.MessageType.MONOSPACE_BLOCK:
79
- case msg_1.MessageType.ERROR:
80
- case msg_1.MessageType.TOPIC_SET_BY:
81
- case msg_1.MessageType.MODE_CHANNEL:
82
- case msg_1.MessageType.MODE_USER:
83
- case msg_1.MessageType.RAW:
84
- case msg_1.MessageType.WHOIS:
85
- case msg_1.MessageType.PLUGIN:
74
+ case MessageType.MONOSPACE_BLOCK:
75
+ case MessageType.ERROR:
76
+ case MessageType.TOPIC_SET_BY:
77
+ case MessageType.MODE_CHANNEL:
78
+ case MessageType.MODE_USER:
79
+ case MessageType.RAW:
80
+ case MessageType.WHOIS:
81
+ case MessageType.PLUGIN:
86
82
  return false;
87
83
  default:
88
84
  return true;
89
85
  }
90
86
  }
91
87
  }
92
- exports.default = Msg;
88
+ export default Msg;
@@ -1,20 +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 lodash_1 = __importDefault(require("lodash"));
7
- const uuid_1 = require("uuid");
8
- const irc_framework_1 = __importDefault(require("irc-framework"));
9
- const chan_1 = __importDefault(require("./chan"));
10
- const msg_1 = __importDefault(require("./msg"));
11
- const prefix_1 = __importDefault(require("./prefix"));
12
- const helper_1 = __importDefault(require("../helper"));
13
- const config_1 = __importDefault(require("../config"));
14
- const sts_1 = __importDefault(require("../plugins/sts"));
15
- const clientCertificate_1 = __importDefault(require("../plugins/clientCertificate"));
16
- const msg_2 = require("../../shared/types/msg");
17
- const chan_2 = require("../../shared/types/chan");
1
+ import _ from "lodash";
2
+ import { v4 as uuidv4 } from "uuid";
3
+ import IrcFramework from "irc-framework";
4
+ import Chan from "./chan.js";
5
+ import Msg from "./msg.js";
6
+ import Prefix from "./prefix.js";
7
+ import Helper from "../helper.js";
8
+ import Config from "../config.js";
9
+ import STSPolicies from "../plugins/sts.js";
10
+ import ClientCertificate from "../plugins/clientCertificate.js";
11
+ import { MessageType } from "../../shared/types/msg.js";
12
+ import { ChanType } from "../../shared/types/chan.js";
18
13
  class Network {
19
14
  nick;
20
15
  name;
@@ -52,7 +47,7 @@ class Network {
52
47
  // TODO: this is only available on export
53
48
  hasSTSPolicy;
54
49
  constructor(attr) {
55
- lodash_1.default.defaults(this, attr, {
50
+ _.defaults(this, attr, {
56
51
  name: "",
57
52
  nick: "",
58
53
  host: "",
@@ -73,7 +68,7 @@ class Network {
73
68
  irc: null,
74
69
  serverOptions: {
75
70
  CHANTYPES: ["#", "&"],
76
- PREFIX: new prefix_1.default([
71
+ PREFIX: new Prefix([
77
72
  { symbol: "!", mode: "Y" },
78
73
  { symbol: "@", mode: "o" },
79
74
  { symbol: "%", mode: "h" },
@@ -94,18 +89,18 @@ class Network {
94
89
  keepNick: null,
95
90
  });
96
91
  if (!this.uuid) {
97
- this.uuid = (0, uuid_1.v4)();
92
+ this.uuid = uuidv4();
98
93
  }
99
94
  if (!this.name) {
100
95
  this.name = this.host;
101
96
  }
102
- this.channels.unshift(new chan_1.default({
97
+ this.channels.unshift(new Chan({
103
98
  name: this.name,
104
- type: chan_2.ChanType.LOBBY,
99
+ type: ChanType.LOBBY,
105
100
  // The lobby only starts as muted if every channel (unless it's special) is muted.
106
101
  // This is A) easier to implement and B) stops some confusion on startup.
107
102
  muted: this.channels.length >= 1 &&
108
- this.channels.every((chan) => chan.muted || chan.type === chan_2.ChanType.SPECIAL),
103
+ this.channels.every((chan) => chan.muted || chan.type === ChanType.SPECIAL),
109
104
  }));
110
105
  // Ensure FiSH keys are applied to any pre-existing channels loaded from disk
111
106
  this.applyBlowKeysToChannels();
@@ -115,7 +110,7 @@ class Network {
115
110
  const cleanNick = (str) => str.replace(/[\x00\s:!@]/g, "_").substring(0, 100);
116
111
  // Remove new lines and limit length
117
112
  const cleanString = (str) => str.replace(/[\x00\r\n]/g, "").substring(0, 300);
118
- this.setNick(cleanNick(String(this.nick || config_1.default.getDefaultNick())));
113
+ this.setNick(cleanNick(String(this.nick || Config.getDefaultNick())));
119
114
  if (!this.username) {
120
115
  // If username is empty, make one from the provided nick
121
116
  this.username = this.nick.replace(/[^a-zA-Z0-9]/g, "");
@@ -134,8 +129,8 @@ class Network {
134
129
  this.proxyPassword = cleanString(this.proxyPassword);
135
130
  this.proxyEnabled = !!this.proxyEnabled;
136
131
  const error = function (network, text) {
137
- network.getLobby().pushMessage(client, new msg_1.default({
138
- type: msg_2.MessageType.ERROR,
132
+ network.getLobby().pushMessage(client, new Msg({
133
+ type: MessageType.ERROR,
139
134
  text: text,
140
135
  }), true);
141
136
  };
@@ -145,30 +140,30 @@ class Network {
145
140
  if (!["", "plain", "external"].includes(this.sasl)) {
146
141
  this.sasl = "";
147
142
  }
148
- if (config_1.default.values.lockNetwork) {
143
+ if (Config.values.lockNetwork) {
149
144
  // This check is needed to prevent invalid user configurations
150
- if (!config_1.default.values.public &&
145
+ if (!Config.values.public &&
151
146
  this.host &&
152
147
  this.host.length > 0 &&
153
- this.host !== config_1.default.values.defaults.host) {
148
+ this.host !== Config.values.defaults.host) {
154
149
  error(this, `The hostname you specified (${this.host}) is not allowed.`);
155
150
  return false;
156
151
  }
157
- if (config_1.default.values.public) {
158
- this.name = config_1.default.values.defaults.name;
152
+ if (Config.values.public) {
153
+ this.name = Config.values.defaults.name;
159
154
  // Sync lobby channel name
160
- this.getLobby().name = config_1.default.values.defaults.name;
155
+ this.getLobby().name = Config.values.defaults.name;
161
156
  }
162
- this.host = config_1.default.values.defaults.host;
163
- this.port = config_1.default.values.defaults.port;
164
- this.tls = config_1.default.values.defaults.tls;
165
- this.rejectUnauthorized = config_1.default.values.defaults.rejectUnauthorized;
157
+ this.host = Config.values.defaults.host;
158
+ this.port = Config.values.defaults.port;
159
+ this.tls = Config.values.defaults.tls;
160
+ this.rejectUnauthorized = Config.values.defaults.rejectUnauthorized;
166
161
  }
167
162
  if (this.host.length === 0) {
168
163
  error(this, "You must specify a hostname to connect.");
169
164
  return false;
170
165
  }
171
- const stsPolicy = sts_1.default.get(this.host);
166
+ const stsPolicy = STSPolicies.get(this.host);
172
167
  if (stsPolicy && !this.tls) {
173
168
  error(this, `${this.host} has an active strict transport security policy, will connect to port ${stsPolicy.port} over a secure connection.`);
174
169
  this.port = stsPolicy.port;
@@ -178,9 +173,9 @@ class Network {
178
173
  return true;
179
174
  }
180
175
  createIrcFramework(client) {
181
- this.irc = new irc_framework_1.default.Client({
176
+ this.irc = new IrcFramework.Client({
182
177
  version: false, // We handle it ourselves
183
- outgoing_addr: config_1.default.values.bind,
178
+ outgoing_addr: Config.values.bind,
184
179
  enable_chghost: true,
185
180
  enable_echomessage: true,
186
181
  enable_setname: true,
@@ -191,18 +186,21 @@ class Network {
191
186
  // TODO: this type should be set after setIrcFrameworkOptions
192
187
  });
193
188
  this.setIrcFrameworkOptions(client);
194
- this.irc.requestCap([
189
+ // Request custom capabilities
190
+ const customCaps = [
195
191
  "znc.in/self-message", // Legacy echo-message for ZNC
196
192
  "znc.in/playback", // See http://wiki.znc.in/Playback
197
- ]);
193
+ "seedpool/enhanced", // THC enhanced client features
194
+ ];
195
+ this.irc.requestCap(customCaps);
198
196
  }
199
197
  setIrcFrameworkOptions(client) {
200
198
  this.irc.options.host = this.host;
201
199
  this.irc.options.port = this.port;
202
200
  this.irc.options.password = this.password;
203
201
  this.irc.options.nick = this.nick;
204
- this.irc.options.username = config_1.default.values.useHexIp
205
- ? helper_1.default.ip2hex(client.config.browser.ip)
202
+ this.irc.options.username = Config.values.useHexIp
203
+ ? Helper.ip2hex(client.config.browser.ip)
206
204
  : this.username;
207
205
  this.irc.options.gecos = this.realname;
208
206
  this.irc.options.tls = this.tls;
@@ -230,7 +228,7 @@ class Network {
230
228
  else if (this.sasl === "external") {
231
229
  this.irc.options.sasl_mechanism = "EXTERNAL";
232
230
  this.irc.options.account = {};
233
- this.irc.options.client_certificate = clientCertificate_1.default.get(this.uuid);
231
+ this.irc.options.client_certificate = ClientCertificate.get(this.uuid);
234
232
  }
235
233
  else if (this.sasl === "plain") {
236
234
  delete this.irc.options.sasl_mechanism;
@@ -250,19 +248,19 @@ class Network {
250
248
  }
251
249
  applyBlowKeysToChannels() {
252
250
  for (const c of this.channels) {
253
- if (c.type !== chan_2.ChanType.CHANNEL && c.type !== chan_2.ChanType.QUERY) {
251
+ if (c.type !== ChanType.CHANNEL && c.type !== ChanType.QUERY) {
254
252
  continue;
255
253
  }
256
254
  c.blowfishKey = this.resolveBlowKeyFor(c.name);
257
255
  }
258
256
  }
259
257
  createWebIrc(client) {
260
- if (!config_1.default.values.webirc ||
261
- !Object.prototype.hasOwnProperty.call(config_1.default.values.webirc, this.host)) {
258
+ if (!Config.values.webirc ||
259
+ !Object.prototype.hasOwnProperty.call(Config.values.webirc, this.host)) {
262
260
  return null;
263
261
  }
264
262
  const webircObject = {
265
- password: config_1.default.values.webirc[this.host],
263
+ password: Config.values.webirc[this.host],
266
264
  username: "thelounge",
267
265
  address: client.config.browser?.ip,
268
266
  hostname: client.config.browser?.hostname,
@@ -274,9 +272,9 @@ class Network {
274
272
  secure: true,
275
273
  };
276
274
  }
277
- if (typeof config_1.default.values.webirc[this.host] === "function") {
275
+ if (typeof Config.values.webirc[this.host] === "function") {
278
276
  webircObject.password = null;
279
- return config_1.default.values.webirc[this.host](webircObject, this);
277
+ return Config.values.webirc[this.host](webircObject, this);
280
278
  }
281
279
  return webircObject;
282
280
  }
@@ -285,32 +283,35 @@ class Network {
285
283
  const oldNick = this.nick;
286
284
  const oldRealname = this.realname;
287
285
  this.keepNick = null;
288
- this.nick = args.nick;
289
- this.host = String(args.host || "");
290
- this.name = String(args.name || "") || this.host;
291
- this.port = parseInt(args.port, 10);
286
+ this.nick = String(args.nick ?? "");
287
+ this.host = String(args.host ?? "");
288
+ this.name = String(args.name ?? "") || this.host;
289
+ this.port = parseInt(String(args.port ?? 6667), 10);
292
290
  this.tls = !!args.tls;
293
291
  this.rejectUnauthorized = !!args.rejectUnauthorized;
294
- this.password = String(args.password || "");
295
- this.username = String(args.username || "");
296
- this.realname = String(args.realname || "");
297
- this.leaveMessage = String(args.leaveMessage || "");
298
- this.sasl = String(args.sasl || "");
299
- this.saslAccount = String(args.saslAccount || "");
300
- this.saslPassword = String(args.saslPassword || "");
301
- this.proxyHost = String(args.proxyHost || "");
302
- this.proxyPort = parseInt(args.proxyPort, 10);
303
- this.proxyUsername = String(args.proxyUsername || "");
304
- this.proxyPassword = String(args.proxyPassword || "");
292
+ this.password = String(args.password ?? "");
293
+ this.username = String(args.username ?? "");
294
+ this.realname = String(args.realname ?? "");
295
+ this.leaveMessage = String(args.leaveMessage ?? "");
296
+ this.sasl = String(args.sasl ?? "");
297
+ this.saslAccount = String(args.saslAccount ?? "");
298
+ this.saslPassword = String(args.saslPassword ?? "");
299
+ this.proxyHost = String(args.proxyHost ?? "");
300
+ this.proxyPort = parseInt(String(args.proxyPort ?? 1080), 10);
301
+ this.proxyUsername = String(args.proxyUsername ?? "");
302
+ this.proxyPassword = String(args.proxyPassword ?? "");
305
303
  this.proxyEnabled = !!args.proxyEnabled;
306
304
  // Split commands into an array
307
- this.commands = String(args.commands || "")
305
+ const commandsStr = Array.isArray(args.commands)
306
+ ? args.commands.join("\n")
307
+ : String(args.commands ?? "");
308
+ this.commands = commandsStr
308
309
  .replace(/\r\n|\r|\n/g, "\n")
309
310
  .split("\n")
310
311
  .filter((command) => command.length > 0);
311
312
  // FiSH: read global key and per-target keys (only update when provided)
312
313
  if (Object.prototype.hasOwnProperty.call(args, "fishGlobalKey")) {
313
- this.fishGlobalKey = String(args.fishGlobalKey || "").trim();
314
+ this.fishGlobalKey = Helper.toTrimmedString(args.fishGlobalKey || "");
314
315
  }
315
316
  // FiSH: read per-target keys (only update when provided)
316
317
  if (Object.prototype.hasOwnProperty.call(args, "fishKeys")) {
@@ -318,8 +319,8 @@ class Network {
318
319
  const map = {};
319
320
  if (value && typeof value === "object") {
320
321
  for (const [rawName, rawKey] of Object.entries(value)) {
321
- const name = String(rawName).trim().toLowerCase();
322
- const key = String(rawKey ?? "").trim();
322
+ const name = Helper.toTrimmedString(rawName).toLowerCase();
323
+ const key = Helper.toTrimmedString(rawKey);
323
324
  if (name && key) {
324
325
  map[name] = key;
325
326
  }
@@ -380,7 +381,7 @@ class Network {
380
381
  // Do not match characters and numbers (unless IRC color)
381
382
  "(?:^|[^a-z0-9]|\x03[0-9]{1,2})" +
382
383
  // Escape nickname, as it may contain regex stuff
383
- lodash_1.default.escapeRegExp(nick) +
384
+ _.escapeRegExp(nick) +
384
385
  // Do not match characters and numbers
385
386
  "(?:[^a-z0-9]|$)",
386
387
  // Case insensitive search
@@ -410,7 +411,7 @@ class Network {
410
411
  if (this.irc && this.irc.connection && this.irc.connection.transport) {
411
412
  const transport = this.irc.connection.transport;
412
413
  if (transport.socket) {
413
- const isLocalhost = transport.socket.remoteAddress === "127.0.0.1";
414
+ const isLocalhost = ["127.0.0.1", "::1"].includes(transport.socket.remoteAddress);
414
415
  const isAuthorized = transport.socket.encrypted && transport.socket.authorized;
415
416
  status.connected = transport.isConnected();
416
417
  status.secure = isAuthorized || isLocalhost;
@@ -420,12 +421,12 @@ class Network {
420
421
  }
421
422
  addChannel(newChan) {
422
423
  // Assign FiSH key based on network configuration when adding
423
- if (newChan && (newChan.type === chan_2.ChanType.CHANNEL || newChan.type === chan_2.ChanType.QUERY)) {
424
+ if (newChan && (newChan.type === ChanType.CHANNEL || newChan.type === ChanType.QUERY)) {
424
425
  newChan.blowfishKey = this.resolveBlowKeyFor(newChan.name);
425
426
  }
426
427
  let index = this.channels.length; // Default to putting as the last item in the array
427
428
  // Don't sort special channels in amongst channels/users.
428
- if (newChan.type === chan_2.ChanType.CHANNEL || newChan.type === chan_2.ChanType.QUERY) {
429
+ if (newChan.type === ChanType.CHANNEL || newChan.type === ChanType.QUERY) {
429
430
  // We start at 1 so we don't test against the lobby
430
431
  for (let i = 1; i < this.channels.length; i++) {
431
432
  const compareChan = this.channels[i];
@@ -433,7 +434,7 @@ class Network {
433
434
  if (newChan.name.localeCompare(compareChan.name, undefined, {
434
435
  sensitivity: "base",
435
436
  }) <= 0 ||
436
- (compareChan.type !== chan_2.ChanType.CHANNEL && compareChan.type !== chan_2.ChanType.QUERY)) {
437
+ (compareChan.type !== ChanType.CHANNEL && compareChan.type !== ChanType.QUERY)) {
437
438
  index = i;
438
439
  break;
439
440
  }
@@ -447,8 +448,8 @@ class Network {
447
448
  return;
448
449
  }
449
450
  // https://ircv3.net/specs/extensions/sts#rescheduling-expiry-on-disconnect
450
- sts_1.default.refreshExpiration(this.host);
451
- this.irc.quit(quitMessage || this.leaveMessage || config_1.default.values.leaveMessage);
451
+ STSPolicies.refreshExpiration(this.host);
452
+ this.irc.quit(quitMessage || this.leaveMessage || Config.values.leaveMessage);
452
453
  }
453
454
  exportForEdit() {
454
455
  const fieldsToReturn = [
@@ -469,21 +470,21 @@ class Network {
469
470
  "proxyUsername",
470
471
  "proxyPassword",
471
472
  ];
472
- if (!config_1.default.values.lockNetwork) {
473
+ if (!Config.values.lockNetwork) {
473
474
  fieldsToReturn.push("host");
474
475
  fieldsToReturn.push("port");
475
476
  fieldsToReturn.push("tls");
476
477
  fieldsToReturn.push("rejectUnauthorized");
477
478
  }
478
- const data = lodash_1.default.pick(this, fieldsToReturn);
479
- data.hasSTSPolicy = !!sts_1.default.get(this.host);
479
+ const data = _.pick(this, fieldsToReturn);
480
+ data.hasSTSPolicy = !!STSPolicies.get(this.host);
480
481
  // Include FiSH fields for editing UI
481
482
  data.fishGlobalKey = this.fishGlobalKey || "";
482
483
  data.fishKeys = { ...(this.fishKeys || {}) };
483
484
  return data;
484
485
  }
485
486
  export() {
486
- const network = lodash_1.default.pick(this, [
487
+ const network = _.pick(this, [
487
488
  "uuid",
488
489
  "awayMessage",
489
490
  "nick",
@@ -513,24 +514,25 @@ class Network {
513
514
  ]);
514
515
  network.channels = this.channels
515
516
  .filter(function (channel) {
516
- return channel.type === chan_2.ChanType.CHANNEL || channel.type === chan_2.ChanType.QUERY;
517
+ return channel.type === ChanType.CHANNEL || channel.type === ChanType.QUERY;
517
518
  })
518
519
  .map(function (chan) {
519
520
  const keys = ["name", "muted"];
520
- if (chan.type === chan_2.ChanType.CHANNEL) {
521
+ if (chan.type === ChanType.CHANNEL) {
521
522
  keys.push("key");
522
523
  }
523
- else if (chan.type === chan_2.ChanType.QUERY) {
524
+ else if (chan.type === ChanType.QUERY) {
524
525
  keys.push("type");
526
+ keys.push("pinned");
525
527
  }
526
- return lodash_1.default.pick(chan, keys);
528
+ return _.pick(chan, keys);
527
529
  // Override the type because we're omitting ID
528
530
  });
529
531
  return network;
530
532
  }
531
533
  getChannel(name) {
532
534
  name = name.toLowerCase();
533
- return lodash_1.default.find(this.channels, function (that, i) {
535
+ return _.find(this.channels, function (that, i) {
534
536
  // Skip network lobby (it's always unshifted into first position)
535
537
  return i > 0 && that.name.toLowerCase() === name;
536
538
  });
@@ -539,4 +541,4 @@ class Network {
539
541
  return this.channels[0];
540
542
  }
541
543
  }
542
- exports.default = Network;
544
+ export default Network;