Skip to content

Commit d80c79c

Browse files
authored
Merge pull request #1667 from nextcloud/feat/predefine-account-cli
feat: add CLI command to set accounts prefilling server url and user
2 parents 3f25ca9 + cc0894f commit d80c79c

File tree

5 files changed

+122
-8
lines changed

5 files changed

+122
-8
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,36 @@ However, using portable `zip` distribution, you can have several Nextcloud Talk
6868
└── ...
6969
```
7070

71+
## ⌨️ CLI usage
72+
73+
### Application flags
74+
75+
Adjust how the application runs when launching.
76+
77+
| Flag | Description |
78+
|----------------|-------------------------------------------------------------------------------|
79+
| `--background` | Start minimized to the system tray without a window (used for run at startup) |
80+
81+
### CLI commands
82+
83+
Run a command in the app and quit without launching the entire app.
84+
85+
#### `config`
86+
87+
Set application configuration.
88+
89+
| Option | Description |
90+
|----------------------------|--------------------------------------------|
91+
| `--accounts=[user@]server` | Comma-separated list of prefilled accounts |
92+
93+
Examples:
94+
95+
```sh
96+
./Nextcloud\ Talk config --accounts=cloud.company.tld
97+
./Nextcloud\ Talk config --accounts='Name Surname@cloud.company.tld'
98+
./Nextcloud\ Talk config --accounts=name@email.tld@company.tld/nextcloud
99+
```
100+
71101
## 🛠️ Development Setup
72102

73103
1. Install dependencies

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"core-js": "^3.47.0",
6363
"electron-squirrel-startup": "^1.0.1",
6464
"howler": "^2.2.4",
65+
"mri": "^1.2.0",
6566
"pinia": "^3.0.4",
6667
"semver": "^7.7.3",
6768
"unzip-crx-3": "^0.2.0",

src/app/cli.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*!
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import type { Argv } from 'mri'
7+
8+
import { app } from 'electron'
9+
import { setAppConfig } from './AppConfig.ts'
10+
11+
/**
12+
* Handle CLI usage
13+
*
14+
* @param argv - Parsed by mri CLI arguments
15+
*/
16+
export async function cli(argv: Argv) {
17+
// TODO: Add --help command
18+
19+
if (!argv._.length) {
20+
return
21+
}
22+
23+
if (argv._[0] === 'config' && argv._.length === 1) {
24+
await handleConfigCommand(argv)
25+
} else {
26+
console.log('Unknown command:', argv._.join(' '))
27+
app.exit(1)
28+
}
29+
30+
app.exit(0)
31+
}
32+
33+
/**
34+
* Handle "config" CLI command
35+
*
36+
* @param argv - Parsed by mri CLI arguments
37+
*/
38+
async function handleConfigCommand(argv: Argv) {
39+
if (!argv.accounts) {
40+
console.log('No config to set')
41+
app.exit(1)
42+
}
43+
44+
// --accounts=user@email.tld@server.tld/nextcloud,nextcloud.local
45+
const accounts = argv.accounts.split(',')
46+
47+
// Validate
48+
for (const account of accounts) {
49+
const atIndex = account.lastIndexOf('@')
50+
const [server, user] = atIndex === -1
51+
? [account, '']
52+
: [account.slice(atIndex + 1), account.slice(0, atIndex)]
53+
try {
54+
new URL(`https://${server}`)
55+
} catch {
56+
console.error(`Invalid server: ${server}`)
57+
app.exit(1)
58+
}
59+
if (user && (!/^[a-zA-Z0-9 _.@\-']{1,64}$/.test(user) || user !== user.trim())) {
60+
console.error(`Invalid user: ${user}`)
61+
app.exit(1)
62+
}
63+
}
64+
65+
// Set
66+
await setAppConfig('accounts', accounts)
67+
68+
console.log('Accounts configuration updated')
69+
}

src/main.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
*/
55

66
const { app, ipcMain, desktopCapturer, systemPreferences, shell, session } = require('electron')
7+
const { default: mri } = require('mri')
78
const { spawn } = require('node:child_process')
89
const path = require('node:path')
910
const { setupMenu } = require('./app/app.menu.js')
1011
const { loadAppConfig, getAppConfig, setAppConfig } = require('./app/AppConfig.ts')
1112
const { appData } = require('./app/AppData.js')
1213
const { registerAppProtocolHandler } = require('./app/appProtocol.ts')
1314
const { verifyCertificate, promptCertificateTrust } = require('./app/certificate.service.ts')
15+
const { cli } = require('./app/cli.ts')
1416
const { openChromeWebRtcInternals } = require('./app/dev.utils.ts')
1517
const { triggerDownloadUrl } = require('./app/downloads.ts')
1618
const { setupReleaseNotificationScheduler, checkForUpdate } = require('./app/githubRelease.service.ts')
@@ -30,13 +32,7 @@ const { createTalkWindow } = require('./talk/talk.window.js')
3032
const { createUpgradeWindow } = require('./upgrade/upgrade.window.ts')
3133
const { createWelcomeWindow } = require('./welcome/welcome.window.js')
3234

33-
/**
34-
* Parse command line arguments
35-
*/
36-
const ARGUMENTS = {
37-
// Open Talk window in the background, minimized to the system tray
38-
openInBackground: process.argv.includes('--background'),
39-
}
35+
const argv = mri(process.argv.slice(app.isPackaged ? 1 : 2))
4036

4137
// Electron 36 with Chromium 136 is not compatible with GNOME due to GTK3 with GTK4 mixing
4238
// Workaround: force GTK3
@@ -74,6 +70,7 @@ if (require('electron-squirrel-startup')) {
7470
* Only one instance is allowed at the same time
7571
*/
7672
if (!app.requestSingleInstanceLock()) {
73+
console.log('Another instance of the app is already running')
7774
app.quit()
7875
}
7976

@@ -137,6 +134,8 @@ app.whenReady().then(async () => {
137134
await loadAppConfig()
138135
await runMigrations()
139136

137+
await cli(argv)
138+
140139
applyTheme()
141140
initLaunchAtStartupListener()
142141
registerAppProtocolHandler()
@@ -149,7 +148,7 @@ app.whenReady().then(async () => {
149148
}
150149

151150
// Open in the background if it is explicitly set, or the app was open at login on macOS
152-
const openInBackground = ARGUMENTS.openInBackground || app.getLoginItemSettings().wasOpenedAtLogin
151+
const openInBackground = argv.background || app.getLoginItemSettings().wasOpenedAtLogin
153152

154153
try {
155154
await installVueDevtools()

0 commit comments

Comments
 (0)