@lordbex/thelounge 4.4.3-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.
- package/README.md +31 -7
- package/dist/defaults/config.js +31 -2
- package/dist/package.json +94 -91
- package/dist/server/client.js +188 -194
- package/dist/server/clientManager.js +75 -72
- package/dist/server/command-line/index.js +44 -43
- package/dist/server/command-line/install.js +37 -70
- package/dist/server/command-line/outdated.js +12 -17
- package/dist/server/command-line/start.js +25 -26
- package/dist/server/command-line/storage.js +26 -31
- package/dist/server/command-line/uninstall.js +16 -23
- package/dist/server/command-line/upgrade.js +20 -26
- package/dist/server/command-line/users/add.js +33 -40
- package/dist/server/command-line/users/edit.js +18 -24
- package/dist/server/command-line/users/index.js +12 -16
- package/dist/server/command-line/users/list.js +11 -39
- package/dist/server/command-line/users/remove.js +16 -22
- package/dist/server/command-line/users/reset.js +34 -35
- package/dist/server/command-line/utils.js +231 -87
- package/dist/server/config.js +61 -52
- package/dist/server/helper.js +29 -28
- package/dist/server/identification.js +39 -34
- package/dist/server/index.js +1 -3
- package/dist/server/log.js +19 -16
- package/dist/server/models/chan.js +36 -33
- package/dist/server/models/msg.js +15 -19
- package/dist/server/models/network.js +102 -104
- package/dist/server/models/prefix.js +4 -7
- package/dist/server/models/user.js +5 -10
- package/dist/server/path-helper.js +8 -0
- package/dist/server/plugins/auth/ldap.js +177 -112
- package/dist/server/plugins/auth/local.js +10 -15
- package/dist/server/plugins/auth.js +6 -35
- package/dist/server/plugins/changelog.js +30 -27
- package/dist/server/plugins/clientCertificate.js +33 -37
- package/dist/server/plugins/dev-server.js +15 -21
- package/dist/server/plugins/inputs/action.js +9 -14
- package/dist/server/plugins/inputs/away.js +1 -3
- package/dist/server/plugins/inputs/ban.js +9 -14
- package/dist/server/plugins/inputs/blow.js +9 -14
- package/dist/server/plugins/inputs/connect.js +5 -10
- package/dist/server/plugins/inputs/ctcp.js +7 -12
- package/dist/server/plugins/inputs/disconnect.js +1 -3
- package/dist/server/plugins/inputs/ignore.js +23 -29
- package/dist/server/plugins/inputs/ignorelist.js +12 -18
- package/dist/server/plugins/inputs/index.js +8 -34
- package/dist/server/plugins/inputs/invite.js +7 -12
- package/dist/server/plugins/inputs/kick.js +7 -12
- package/dist/server/plugins/inputs/kill.js +1 -3
- package/dist/server/plugins/inputs/list.js +1 -3
- package/dist/server/plugins/inputs/mode.js +10 -15
- package/dist/server/plugins/inputs/msg.js +13 -18
- package/dist/server/plugins/inputs/mute.js +9 -15
- package/dist/server/plugins/inputs/nick.js +9 -14
- package/dist/server/plugins/inputs/notice.js +5 -7
- package/dist/server/plugins/inputs/part.js +11 -16
- package/dist/server/plugins/inputs/quit.js +7 -13
- package/dist/server/plugins/inputs/rainbow.js +55 -0
- package/dist/server/plugins/inputs/raw.js +1 -3
- package/dist/server/plugins/inputs/rejoin.js +7 -12
- package/dist/server/plugins/inputs/topic.js +7 -12
- package/dist/server/plugins/inputs/whois.js +1 -3
- package/dist/server/plugins/irc-events/away.js +14 -20
- package/dist/server/plugins/irc-events/cap.js +16 -22
- package/dist/server/plugins/irc-events/chghost.js +14 -13
- package/dist/server/plugins/irc-events/connection.js +61 -63
- package/dist/server/plugins/irc-events/ctcp.js +22 -28
- package/dist/server/plugins/irc-events/error.js +20 -26
- package/dist/server/plugins/irc-events/help.js +7 -13
- package/dist/server/plugins/irc-events/info.js +7 -13
- package/dist/server/plugins/irc-events/invite.js +7 -13
- package/dist/server/plugins/irc-events/join.js +30 -27
- package/dist/server/plugins/irc-events/kick.js +21 -17
- package/dist/server/plugins/irc-events/link.js +122 -109
- package/dist/server/plugins/irc-events/list.js +23 -26
- package/dist/server/plugins/irc-events/message.js +46 -52
- package/dist/server/plugins/irc-events/mode.js +66 -63
- package/dist/server/plugins/irc-events/modelist.js +29 -35
- package/dist/server/plugins/irc-events/motd.js +10 -16
- package/dist/server/plugins/irc-events/names.js +3 -6
- package/dist/server/plugins/irc-events/nick.js +26 -23
- package/dist/server/plugins/irc-events/part.js +19 -15
- package/dist/server/plugins/irc-events/quit.js +17 -14
- package/dist/server/plugins/irc-events/sasl.js +9 -15
- package/dist/server/plugins/irc-events/spgroups.js +38 -0
- package/dist/server/plugins/irc-events/spjoin.js +52 -0
- package/dist/server/plugins/irc-events/topic.js +12 -18
- package/dist/server/plugins/irc-events/unhandled.js +12 -12
- package/dist/server/plugins/irc-events/welcome.js +7 -13
- package/dist/server/plugins/irc-events/whois.js +20 -24
- package/dist/server/plugins/massEventAggregator.js +214 -0
- package/dist/server/plugins/messageStorage/sqlite.js +322 -141
- package/dist/server/plugins/messageStorage/text.js +21 -26
- package/dist/server/plugins/packages/index.js +105 -74
- package/dist/server/plugins/packages/publicClient.js +7 -16
- package/dist/server/plugins/packages/themes.js +11 -16
- package/dist/server/plugins/storage.js +28 -33
- package/dist/server/plugins/sts.js +12 -17
- package/dist/server/plugins/uploader.js +40 -43
- package/dist/server/plugins/webpush.js +23 -51
- package/dist/server/server.js +318 -271
- package/dist/server/storageCleaner.js +29 -37
- package/dist/server/utils/fish.js +349 -389
- package/dist/shared/irc.js +3 -6
- package/dist/shared/linkify.js +7 -14
- package/dist/shared/types/chan.js +6 -9
- package/dist/shared/types/changelog.js +1 -2
- package/dist/shared/types/config.js +1 -2
- package/dist/shared/types/mention.js +1 -2
- package/dist/shared/types/msg.js +3 -5
- package/dist/shared/types/network.js +1 -2
- package/dist/shared/types/storage.js +1 -2
- package/dist/shared/types/user.js +1 -2
- package/index.js +14 -10
- package/package.json +94 -91
- package/public/css/style.css +9 -6
- package/public/css/style.css.map +1 -1
- package/public/fonts/font-awesome/fa-brands-400.ttf +0 -0
- package/public/fonts/font-awesome/fa-brands-400.woff2 +0 -0
- package/public/fonts/font-awesome/fa-duotone-900.ttf +0 -0
- package/public/fonts/font-awesome/fa-duotone-900.woff2 +0 -0
- package/public/fonts/font-awesome/fa-light-300.ttf +0 -0
- package/public/fonts/font-awesome/fa-light-300.woff2 +0 -0
- package/public/fonts/font-awesome/fa-regular-400.ttf +0 -0
- package/public/fonts/font-awesome/fa-regular-400.woff2 +0 -0
- package/public/fonts/font-awesome/fa-solid-900.ttf +0 -0
- package/public/fonts/font-awesome/fa-solid-900.woff2 +0 -0
- package/public/fonts/font-awesome/fa-thin-100.ttf +0 -0
- package/public/fonts/font-awesome/fa-thin-100.woff2 +0 -0
- package/public/fonts/font-awesome/fa-v4compatibility.ttf +0 -0
- package/public/fonts/font-awesome/fa-v4compatibility.woff2 +0 -0
- package/public/js/bundle.js +1 -1
- package/public/js/bundle.js.map +1 -1
- package/public/js/bundle.vendor.js +1 -1
- package/public/js/bundle.vendor.js.LICENSE.txt +24 -6
- package/public/js/bundle.vendor.js.map +1 -1
- package/public/js/loading-error-handlers.js +1 -1
- package/public/service-worker.js +1 -1
- package/public/themes/default.css +1 -1
- package/public/themes/morning.css +1 -1
- package/dist/webpack.config.js +0 -224
|
@@ -1,35 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const auth_1 = __importDefault(require("./plugins/auth"));
|
|
12
|
-
const client_1 = __importDefault(require("./client"));
|
|
13
|
-
const config_1 = __importDefault(require("./config"));
|
|
14
|
-
const webpush_1 = __importDefault(require("./plugins/webpush"));
|
|
15
|
-
const log_1 = __importDefault(require("./log"));
|
|
1
|
+
import _ from "lodash";
|
|
2
|
+
import colors from "chalk";
|
|
3
|
+
import crypto from "crypto";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import Auth from "./plugins/auth.js";
|
|
7
|
+
import Client from "./client.js";
|
|
8
|
+
import Config from "./config.js";
|
|
9
|
+
import WebPush from "./plugins/webpush.js";
|
|
10
|
+
import log from "./log.js";
|
|
16
11
|
class ClientManager {
|
|
17
12
|
clients;
|
|
18
13
|
sockets;
|
|
19
14
|
identHandler;
|
|
20
15
|
webPush;
|
|
16
|
+
userWatcher = null;
|
|
21
17
|
constructor() {
|
|
22
18
|
this.clients = [];
|
|
23
19
|
}
|
|
24
20
|
init(identHandler, sockets) {
|
|
25
21
|
this.sockets = sockets;
|
|
26
22
|
this.identHandler = identHandler;
|
|
27
|
-
this.webPush = new
|
|
28
|
-
if (!
|
|
23
|
+
this.webPush = new WebPush();
|
|
24
|
+
if (!Config.values.public) {
|
|
29
25
|
this.loadUsers();
|
|
30
26
|
// LDAP does not have user commands, and users are dynamically
|
|
31
27
|
// created upon logon, so we don't need to watch for new files
|
|
32
|
-
if (!
|
|
28
|
+
if (!Config.values.ldap.enable) {
|
|
33
29
|
this.autoloadUsers();
|
|
34
30
|
}
|
|
35
31
|
}
|
|
@@ -41,14 +37,14 @@ class ClientManager {
|
|
|
41
37
|
loadUsers() {
|
|
42
38
|
let users = this.getUsers();
|
|
43
39
|
if (users.length === 0) {
|
|
44
|
-
|
|
40
|
+
log.info(`There are currently no users. Create one with ${colors.bold("thelounge add <name>")}.`);
|
|
45
41
|
return;
|
|
46
42
|
}
|
|
47
43
|
const alreadySeenUsers = new Set();
|
|
48
44
|
users = users.filter((user) => {
|
|
49
45
|
user = user.toLowerCase();
|
|
50
46
|
if (alreadySeenUsers.has(user)) {
|
|
51
|
-
|
|
47
|
+
log.error(`There is more than one user named "${colors.bold(user)}". Usernames are now case insensitive, duplicate users will not load.`);
|
|
52
48
|
return false;
|
|
53
49
|
}
|
|
54
50
|
alreadySeenUsers.add(user);
|
|
@@ -58,30 +54,35 @@ class ClientManager {
|
|
|
58
54
|
const callbackLoadUser = (user) => {
|
|
59
55
|
this.loadUser(user);
|
|
60
56
|
};
|
|
61
|
-
if (!
|
|
57
|
+
if (!Auth.loadUsers(users, callbackLoadUser)) {
|
|
62
58
|
// Fallback to loading all users
|
|
63
59
|
users.forEach((name) => this.loadUser(name));
|
|
64
60
|
}
|
|
65
61
|
}
|
|
66
62
|
autoloadUsers() {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (updatedUsers.length === 0) {
|
|
71
|
-
log_1.default.info(`There are currently no users. Create one with ${chalk_1.default.bold("thelounge add <name>")}.`);
|
|
63
|
+
this.userWatcher = fs.watch(Config.getUsersPath(), { persistent: false }, (_eventType, file) => {
|
|
64
|
+
if (!file || !file.endsWith(".json")) {
|
|
65
|
+
return;
|
|
72
66
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
67
|
+
const name = file.slice(0, -5);
|
|
68
|
+
const userPath = Config.getUserConfigPath(name);
|
|
69
|
+
if (fs.existsSync(userPath)) {
|
|
70
|
+
this.loadUser(name);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const client = _.find(this.clients, { name });
|
|
74
|
+
if (client) {
|
|
75
|
+
client.quit(true);
|
|
76
|
+
this.clients = _.without(this.clients, client);
|
|
77
|
+
log.info(`User ${colors.bold(name)} disconnected and removed.`);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
stopAutoloadUsers() {
|
|
82
|
+
if (this.userWatcher) {
|
|
83
|
+
this.userWatcher.close();
|
|
84
|
+
this.userWatcher = null;
|
|
85
|
+
}
|
|
85
86
|
}
|
|
86
87
|
loadUser(name) {
|
|
87
88
|
const userConfig = this.readUserConfig(name);
|
|
@@ -99,32 +100,32 @@ class ClientManager {
|
|
|
99
100
|
* @see https://github.com/thelounge/thelounge/issues/598
|
|
100
101
|
*/
|
|
101
102
|
client.config.password = userConfig.password;
|
|
102
|
-
|
|
103
|
+
log.info(`Password for user ${colors.bold(name)} was reset.`);
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
else {
|
|
106
|
-
client = new
|
|
107
|
+
client = new Client(this, name, userConfig);
|
|
107
108
|
client.connect();
|
|
108
109
|
this.clients.push(client);
|
|
109
110
|
}
|
|
110
111
|
return client;
|
|
111
112
|
}
|
|
112
113
|
getUsers = function () {
|
|
113
|
-
if (!
|
|
114
|
+
if (!fs.existsSync(Config.getUsersPath())) {
|
|
114
115
|
return [];
|
|
115
116
|
}
|
|
116
|
-
return
|
|
117
|
-
.readdirSync(
|
|
117
|
+
return fs
|
|
118
|
+
.readdirSync(Config.getUsersPath())
|
|
118
119
|
.filter((file) => file.endsWith(".json"))
|
|
119
120
|
.map((file) => file.slice(0, -5));
|
|
120
121
|
};
|
|
121
122
|
addUser(name, password, enableLog) {
|
|
122
|
-
if (
|
|
123
|
+
if (path.basename(name) !== name) {
|
|
123
124
|
throw new Error(`${name} is an invalid username.`);
|
|
124
125
|
}
|
|
125
|
-
const userPath =
|
|
126
|
-
if (
|
|
127
|
-
|
|
126
|
+
const userPath = Config.getUserConfigPath(name);
|
|
127
|
+
if (fs.existsSync(userPath)) {
|
|
128
|
+
log.error(`User ${colors.green(name)} already exists.`);
|
|
128
129
|
return false;
|
|
129
130
|
}
|
|
130
131
|
const user = {
|
|
@@ -132,29 +133,31 @@ class ClientManager {
|
|
|
132
133
|
log: enableLog,
|
|
133
134
|
};
|
|
134
135
|
try {
|
|
135
|
-
|
|
136
|
+
const tmpPath = userPath + ".tmp";
|
|
137
|
+
fs.writeFileSync(tmpPath, JSON.stringify(user, null, "\t"), {
|
|
136
138
|
mode: 0o600,
|
|
137
139
|
});
|
|
140
|
+
fs.renameSync(tmpPath, userPath);
|
|
138
141
|
}
|
|
139
142
|
catch (e) {
|
|
140
|
-
|
|
143
|
+
log.error(`Failed to create user ${colors.green(name)} (${e instanceof Error ? e.message : String(e)})`);
|
|
141
144
|
throw e;
|
|
142
145
|
}
|
|
143
146
|
try {
|
|
144
|
-
const userFolderStat =
|
|
145
|
-
const userFileStat =
|
|
147
|
+
const userFolderStat = fs.statSync(Config.getUsersPath());
|
|
148
|
+
const userFileStat = fs.statSync(userPath);
|
|
146
149
|
if (userFolderStat &&
|
|
147
150
|
userFileStat &&
|
|
148
151
|
(userFolderStat.uid !== userFileStat.uid || userFolderStat.gid !== userFileStat.gid)) {
|
|
149
|
-
|
|
150
|
-
|
|
152
|
+
log.warn(`User ${colors.green(name)} has been created, but with a different uid (or gid) than expected.`);
|
|
153
|
+
log.warn("The file owner has been changed to the expected user. " +
|
|
151
154
|
"To prevent any issues, please run thelounge commands " +
|
|
152
155
|
"as the correct user that owns the config folder.");
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
log.warn("See https://thelounge.chat/docs/usage#using-the-correct-system-user for more information.");
|
|
157
|
+
fs.chownSync(userPath, userFolderStat.uid, userFolderStat.gid);
|
|
155
158
|
}
|
|
156
159
|
}
|
|
157
|
-
catch
|
|
160
|
+
catch {
|
|
158
161
|
// We're simply verifying file owner as a safe guard for users
|
|
159
162
|
// that run `thelounge add` as root, so we don't care if it fails
|
|
160
163
|
}
|
|
@@ -165,7 +168,7 @@ class ClientManager {
|
|
|
165
168
|
networks: client.networks.map((n) => n.export()),
|
|
166
169
|
});
|
|
167
170
|
const newUser = JSON.stringify(json, null, "\t");
|
|
168
|
-
const newHash =
|
|
171
|
+
const newHash = crypto.createHash("sha256").update(newUser).digest("hex");
|
|
169
172
|
return { newUser, newHash };
|
|
170
173
|
}
|
|
171
174
|
saveUser(client, callback) {
|
|
@@ -174,47 +177,47 @@ class ClientManager {
|
|
|
174
177
|
if (client.fileHash === newHash) {
|
|
175
178
|
return;
|
|
176
179
|
}
|
|
177
|
-
const pathReal =
|
|
180
|
+
const pathReal = Config.getUserConfigPath(client.name);
|
|
178
181
|
const pathTemp = pathReal + ".tmp";
|
|
179
182
|
try {
|
|
180
183
|
// Write to a temp file first, in case the write fails
|
|
181
184
|
// we do not lose the original file (for example when disk is full)
|
|
182
|
-
|
|
185
|
+
fs.writeFileSync(pathTemp, newUser, {
|
|
183
186
|
mode: 0o600,
|
|
184
187
|
});
|
|
185
|
-
|
|
188
|
+
fs.renameSync(pathTemp, pathReal);
|
|
186
189
|
return callback ? callback() : true;
|
|
187
190
|
}
|
|
188
191
|
catch (e) {
|
|
189
|
-
|
|
192
|
+
log.error(`Failed to update user ${colors.green(client.name)} (${e instanceof Error ? e.message : String(e)})`);
|
|
190
193
|
if (callback) {
|
|
191
|
-
callback(e);
|
|
194
|
+
callback(e instanceof Error ? e : new Error(String(e)));
|
|
192
195
|
}
|
|
193
196
|
}
|
|
194
197
|
}
|
|
195
198
|
removeUser(name) {
|
|
196
|
-
const userPath =
|
|
197
|
-
if (!
|
|
198
|
-
|
|
199
|
+
const userPath = Config.getUserConfigPath(name);
|
|
200
|
+
if (!fs.existsSync(userPath)) {
|
|
201
|
+
log.error(`Tried to remove non-existing user ${colors.green(name)}.`);
|
|
199
202
|
return false;
|
|
200
203
|
}
|
|
201
|
-
|
|
204
|
+
fs.unlinkSync(userPath);
|
|
202
205
|
return true;
|
|
203
206
|
}
|
|
204
207
|
readUserConfig(name) {
|
|
205
|
-
const userPath =
|
|
206
|
-
if (!
|
|
207
|
-
|
|
208
|
+
const userPath = Config.getUserConfigPath(name);
|
|
209
|
+
if (!fs.existsSync(userPath)) {
|
|
210
|
+
log.error(`Tried to read non-existing user ${colors.green(name)}`);
|
|
208
211
|
return false;
|
|
209
212
|
}
|
|
210
213
|
try {
|
|
211
|
-
const data =
|
|
214
|
+
const data = fs.readFileSync(userPath, "utf-8");
|
|
212
215
|
return JSON.parse(data);
|
|
213
216
|
}
|
|
214
217
|
catch (e) {
|
|
215
|
-
|
|
218
|
+
log.error(`Failed to read user ${colors.bold(name)}: ${e instanceof Error ? e.message : String(e)}`);
|
|
216
219
|
}
|
|
217
220
|
return false;
|
|
218
221
|
}
|
|
219
222
|
}
|
|
220
|
-
|
|
223
|
+
export default ClientManager;
|
|
@@ -1,48 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
-
const commander_1 = require("commander");
|
|
12
|
-
const helper_1 = __importDefault(require("../helper"));
|
|
13
|
-
const config_1 = __importDefault(require("../config"));
|
|
14
|
-
const utils_1 = __importDefault(require("./utils"));
|
|
15
|
-
const program = new commander_1.Command("thelounge");
|
|
1
|
+
import log from "../log.js";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import colors from "chalk";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import Helper from "../helper.js";
|
|
7
|
+
import Config from "../config.js";
|
|
8
|
+
import Utils from "./utils.js";
|
|
9
|
+
const program = new Command("thelounge");
|
|
16
10
|
program
|
|
17
|
-
.version(
|
|
18
|
-
.option("-c, --config <key=value>", "override entries of the configuration file, must be specified for each entry that needs to be overriden",
|
|
19
|
-
.on("--help",
|
|
11
|
+
.version(Helper.getVersion(), "-v, --version")
|
|
12
|
+
.option("-c, --config <key=value>", "override entries of the configuration file, must be specified for each entry that needs to be overriden", Utils.parseConfigOptions)
|
|
13
|
+
.on("--help", Utils.extraHelp);
|
|
20
14
|
// Parse options from `argv` returning `argv` void of these options.
|
|
21
15
|
const argvWithoutOptions = program.parseOptions(process.argv);
|
|
22
|
-
|
|
16
|
+
await Config.setHome(process.env.THELOUNGE_HOME || Utils.defaultHome());
|
|
23
17
|
// Check config file owner and warn if we're running under a different user
|
|
24
18
|
try {
|
|
25
19
|
verifyFileOwner();
|
|
26
20
|
}
|
|
27
|
-
catch
|
|
21
|
+
catch {
|
|
28
22
|
// We do not care about failures of these checks
|
|
29
23
|
// fs.statSync will throw if config.js does not exist (e.g. first run)
|
|
30
24
|
}
|
|
31
25
|
// Create packages/package.json
|
|
32
26
|
createPackagesFolder();
|
|
33
27
|
// Merge config key-values passed as CLI options into the main config
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
28
|
+
Config.merge(program.opts().config);
|
|
29
|
+
const startCmd = await import("./start.js");
|
|
30
|
+
const installCmd = await import("./install.js");
|
|
31
|
+
const uninstallCmd = await import("./uninstall.js");
|
|
32
|
+
const upgradeCmd = await import("./upgrade.js");
|
|
33
|
+
const outdatedCmd = await import("./outdated.js");
|
|
34
|
+
const storageCmd = await import("./storage.js");
|
|
35
|
+
program.addCommand(startCmd.default);
|
|
36
|
+
program.addCommand(installCmd.default);
|
|
37
|
+
program.addCommand(uninstallCmd.default);
|
|
38
|
+
program.addCommand(upgradeCmd.default);
|
|
39
|
+
program.addCommand(outdatedCmd.default);
|
|
40
|
+
program.addCommand(storageCmd.default);
|
|
41
|
+
if (!Config.values.public) {
|
|
42
|
+
const usersCmd = await import("./users/index.js");
|
|
43
|
+
usersCmd.default
|
|
44
|
+
.filter((command) => command !== undefined)
|
|
45
|
+
.forEach((command) => {
|
|
46
|
+
program.addCommand(command);
|
|
46
47
|
});
|
|
47
48
|
}
|
|
48
49
|
// `parse` expects to be passed `process.argv`, but we need to remove to give it
|
|
@@ -53,13 +54,13 @@ if (!config_1.default.values.public) {
|
|
|
53
54
|
// See https://github.com/tj/commander.js/blob/fefda77f463292/index.js#L686-L763
|
|
54
55
|
program.parse(argvWithoutOptions.operands.concat(argvWithoutOptions.unknown));
|
|
55
56
|
function createPackagesFolder() {
|
|
56
|
-
const packagesPath =
|
|
57
|
-
const packagesConfig =
|
|
57
|
+
const packagesPath = Config.getPackagesPath();
|
|
58
|
+
const packagesConfig = path.join(packagesPath, "package.json");
|
|
58
59
|
// Create node_modules folder, otherwise yarn will start walking upwards to find one
|
|
59
|
-
|
|
60
|
+
fs.mkdirSync(path.join(packagesPath, "node_modules"), { recursive: true });
|
|
60
61
|
// Create package.json with private set to true, if it doesn't exist already
|
|
61
|
-
if (!
|
|
62
|
-
|
|
62
|
+
if (!fs.existsSync(packagesConfig)) {
|
|
63
|
+
fs.writeFileSync(packagesConfig, JSON.stringify({
|
|
63
64
|
private: true,
|
|
64
65
|
description: "Packages for The Lounge. Use `thelounge install <package>` command to add a package.",
|
|
65
66
|
dependencies: {},
|
|
@@ -72,14 +73,14 @@ function verifyFileOwner() {
|
|
|
72
73
|
}
|
|
73
74
|
const uid = process.getuid();
|
|
74
75
|
if (uid === 0) {
|
|
75
|
-
|
|
76
|
+
log.warn(`You are currently running The Lounge as root. ${colors.bold.red("We highly discourage running as root!")}`);
|
|
76
77
|
}
|
|
77
|
-
const configStat =
|
|
78
|
+
const configStat = fs.statSync(path.join(Config.getHomePath(), "config.js"));
|
|
78
79
|
if (configStat && configStat.uid !== uid) {
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
log.warn("Config file owner does not match the user you are currently running The Lounge as.");
|
|
81
|
+
log.warn("To prevent any issues, please run thelounge commands " +
|
|
81
82
|
"as the correct user that owns the config folder.");
|
|
82
|
-
|
|
83
|
+
log.warn("See https://thelounge.chat/docs/usage#using-the-correct-system-user for more information.");
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
+
export default program;
|
|
@@ -1,57 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
30
|
-
const log_1 = __importDefault(require("../log"));
|
|
31
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
32
|
-
const semver_1 = __importDefault(require("semver"));
|
|
33
|
-
const helper_1 = __importDefault(require("../helper"));
|
|
34
|
-
const config_1 = __importDefault(require("../config"));
|
|
35
|
-
const utils_1 = __importDefault(require("./utils"));
|
|
36
|
-
const commander_1 = require("commander");
|
|
37
|
-
const program = new commander_1.Command("install");
|
|
1
|
+
import log from "../log.js";
|
|
2
|
+
import colors from "chalk";
|
|
3
|
+
import semver from "semver";
|
|
4
|
+
import Helper from "../helper.js";
|
|
5
|
+
import Config from "../config.js";
|
|
6
|
+
import Utils from "./utils.js";
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import packageJsonImport from "package-json";
|
|
9
|
+
import fs from "node:fs";
|
|
10
|
+
import fspromises from "node:fs/promises";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
const program = new Command("install");
|
|
38
13
|
program
|
|
39
14
|
.argument("<package>", "package to install. Use `file:$path_to_package_dir` to install a local package")
|
|
40
15
|
.description("Install a theme or a package")
|
|
41
|
-
.on("--help",
|
|
42
|
-
.action(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const path = await Promise.resolve().then(() => __importStar(require("path")));
|
|
46
|
-
const packageJson = await Promise.resolve().then(() => __importStar(require("package-json")));
|
|
47
|
-
if (!fs.existsSync(config_1.default.getConfigPath())) {
|
|
48
|
-
log_1.default.error(`${config_1.default.getConfigPath()} does not exist.`);
|
|
16
|
+
.on("--help", Utils.extraHelp)
|
|
17
|
+
.action(function (packageName) {
|
|
18
|
+
if (!fs.existsSync(Config.getConfigPath())) {
|
|
19
|
+
log.error(`${Config.getConfigPath()} does not exist.`);
|
|
49
20
|
return;
|
|
50
21
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
let readFile = null;
|
|
22
|
+
log.info("Retrieving information about the package...");
|
|
23
|
+
let readFile;
|
|
54
24
|
let isLocalFile = false;
|
|
25
|
+
let packageVersion = "latest";
|
|
55
26
|
if (packageName.startsWith("file:")) {
|
|
56
27
|
isLocalFile = true;
|
|
57
28
|
// our yarn invocation sets $HOME to the cachedir, so we must expand ~ now
|
|
@@ -64,60 +35,56 @@ program
|
|
|
64
35
|
else {
|
|
65
36
|
// properly split scoped and non-scoped npm packages
|
|
66
37
|
// into their name and version
|
|
67
|
-
let packageVersion = "latest";
|
|
68
38
|
const atIndex = packageName.indexOf("@", 1);
|
|
69
39
|
if (atIndex !== -1) {
|
|
70
40
|
packageVersion = packageName.slice(atIndex + 1);
|
|
71
41
|
packageName = packageName.slice(0, atIndex);
|
|
72
42
|
}
|
|
73
|
-
readFile =
|
|
43
|
+
readFile = packageJsonImport(packageName, {
|
|
74
44
|
fullMetadata: true,
|
|
75
45
|
version: packageVersion,
|
|
76
46
|
});
|
|
77
47
|
}
|
|
78
|
-
if (!readFile) {
|
|
79
|
-
// no-op, error should've been thrown before this point
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
48
|
readFile
|
|
83
49
|
.then((json) => {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
50
|
+
const version = json.version || packageVersion;
|
|
51
|
+
const humanVersion = isLocalFile ? packageName : `${json.name} v${version}`;
|
|
52
|
+
if (!json.thelounge) {
|
|
53
|
+
log.error(`${colors.red(humanVersion)} does not have The Lounge metadata.`);
|
|
87
54
|
process.exit(1);
|
|
88
55
|
}
|
|
89
56
|
if (json.thelounge.supports &&
|
|
90
|
-
!
|
|
57
|
+
!semver.satisfies(Helper.getVersionNumber(), json.thelounge.supports, {
|
|
91
58
|
includePrerelease: true,
|
|
92
59
|
})) {
|
|
93
|
-
|
|
60
|
+
log.error(`${colors.red(humanVersion)} does not support The Lounge v${Helper.getVersionNumber()}. Supported version(s): ${json.thelounge.supports}`);
|
|
94
61
|
process.exit(2);
|
|
95
62
|
}
|
|
96
|
-
|
|
97
|
-
const yarnVersion = isLocalFile ? packageName : `${json.name}@${
|
|
98
|
-
return
|
|
63
|
+
log.info(`Installing ${colors.green(humanVersion)}...`);
|
|
64
|
+
const yarnVersion = isLocalFile ? packageName : `${json.name}@${version}`;
|
|
65
|
+
return Utils.executeYarnCommand("add", "--exact", yarnVersion)
|
|
99
66
|
.then(() => {
|
|
100
|
-
|
|
67
|
+
log.info(`${colors.green(humanVersion)} has been successfully installed.`);
|
|
101
68
|
if (isLocalFile) {
|
|
102
69
|
// yarn v1 is buggy if a local filepath is used and doesn't update
|
|
103
70
|
// the lockfile properly. We need to run an install in that case
|
|
104
71
|
// even though that's supposed to be done by the add subcommand
|
|
105
|
-
return
|
|
106
|
-
throw `Failed to update lockfile after package install ${err}
|
|
72
|
+
return Utils.executeYarnCommand("install").catch((err) => {
|
|
73
|
+
throw new Error(`Failed to update lockfile after package install ${err}`);
|
|
107
74
|
});
|
|
108
75
|
}
|
|
109
76
|
})
|
|
110
77
|
.catch((code) => {
|
|
111
|
-
throw `Failed to install ${
|
|
78
|
+
throw new Error(`Failed to install ${colors.red(humanVersion)}. Exit code: ${code}`);
|
|
112
79
|
});
|
|
113
80
|
})
|
|
114
81
|
.catch((e) => {
|
|
115
|
-
|
|
82
|
+
log.error(`${e}`);
|
|
116
83
|
process.exit(1);
|
|
117
84
|
});
|
|
118
85
|
});
|
|
119
86
|
function expandTildeInLocalPath(packageName) {
|
|
120
|
-
const
|
|
121
|
-
return "file:" +
|
|
87
|
+
const localPath = packageName.substring("file:".length);
|
|
88
|
+
return "file:" + Helper.expandHome(localPath);
|
|
122
89
|
}
|
|
123
|
-
|
|
90
|
+
export default program;
|
|
@@ -1,30 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const commander_1 = require("commander");
|
|
7
|
-
const utils_1 = __importDefault(require("./utils"));
|
|
8
|
-
const packages_1 = __importDefault(require("../plugins/packages"));
|
|
9
|
-
const log_1 = __importDefault(require("../log"));
|
|
10
|
-
const program = new commander_1.Command("outdated");
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import Utils from "./utils.js";
|
|
3
|
+
import packageManager from "../plugins/packages/index.js";
|
|
4
|
+
import log from "../log.js";
|
|
5
|
+
const program = new Command("outdated");
|
|
11
6
|
program
|
|
12
7
|
.description("Check for any outdated packages")
|
|
13
|
-
.on("--help",
|
|
8
|
+
.on("--help", Utils.extraHelp)
|
|
14
9
|
.action(async () => {
|
|
15
|
-
|
|
16
|
-
await
|
|
10
|
+
log.info("Checking for outdated packages");
|
|
11
|
+
await packageManager
|
|
17
12
|
.outdated(0)
|
|
18
13
|
.then((outdated) => {
|
|
19
14
|
if (outdated) {
|
|
20
|
-
|
|
15
|
+
log.info("There are outdated packages");
|
|
21
16
|
}
|
|
22
17
|
else {
|
|
23
|
-
|
|
18
|
+
log.info("No outdated packages");
|
|
24
19
|
}
|
|
25
20
|
})
|
|
26
21
|
.catch(() => {
|
|
27
|
-
|
|
22
|
+
log.error("Error finding outdated packages.");
|
|
28
23
|
});
|
|
29
24
|
});
|
|
30
|
-
|
|
25
|
+
export default program;
|