update config options naming, move scripts to own folder.

This commit is contained in:
Miroslav Šedivý 2025-04-05 16:53:37 +02:00
parent e3a1929f7f
commit 0e3bcedcd4
10 changed files with 96 additions and 52 deletions

View file

@ -90,12 +90,12 @@ func (Capture) Init(cmd *cobra.Command) error {
return err return err
} }
cmd.PersistentFlags().String("capture.video.pipelines", "[]", "pipelines config in JSON used for video streaming") cmd.PersistentFlags().String("capture.video.pipelines", "{}", "pipelines config used for video streaming")
if err := viper.BindPFlag("capture.video.pipelines", cmd.PersistentFlags().Lookup("capture.video.pipelines")); err != nil { if err := viper.BindPFlag("capture.video.pipelines", cmd.PersistentFlags().Lookup("capture.video.pipelines")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("capture.video.pipeline", "", "gstreamer pipeline used for video streaming; shortcut for having only a single video pipeline instead of multiple, ignored if capture.video.pipelines is set") cmd.PersistentFlags().String("capture.video.pipeline", "", "shortcut for configuring only a single gstreamer pipeline, ignored if pipelines is set")
if err := viper.BindPFlag("capture.video.pipeline", cmd.PersistentFlags().Lookup("capture.video.pipeline")); err != nil { if err := viper.BindPFlag("capture.video.pipeline", cmd.PersistentFlags().Lookup("capture.video.pipeline")); err != nil {
return err return err
} }

View file

@ -22,45 +22,45 @@ type Member struct {
} }
func (Member) Init(cmd *cobra.Command) error { func (Member) Init(cmd *cobra.Command) error {
cmd.PersistentFlags().String("member.provider", "multiuser", "choose member provider") cmd.PersistentFlags().String("member.provider", "multiuser", "selected member provider")
if err := viper.BindPFlag("member.provider", cmd.PersistentFlags().Lookup("member.provider")); err != nil { if err := viper.BindPFlag("member.provider", cmd.PersistentFlags().Lookup("member.provider")); err != nil {
return err return err
} }
// file provider // file provider
cmd.PersistentFlags().String("member.file.path", "", "member file provider: storage path") cmd.PersistentFlags().String("member.file.path", "", "member file provider: path to the file containing the users and their passwords")
if err := viper.BindPFlag("member.file.path", cmd.PersistentFlags().Lookup("member.file.path")); err != nil { if err := viper.BindPFlag("member.file.path", cmd.PersistentFlags().Lookup("member.file.path")); err != nil {
return err return err
} }
cmd.PersistentFlags().Bool("member.file.hash", true, "member file provider: whether to hash passwords using sha256 (recommended)") cmd.PersistentFlags().Bool("member.file.hash", true, "member file provider: whether the passwords are hashed using sha256 or not (recommended)")
if err := viper.BindPFlag("member.file.hash", cmd.PersistentFlags().Lookup("member.file.hash")); err != nil { if err := viper.BindPFlag("member.file.hash", cmd.PersistentFlags().Lookup("member.file.hash")); err != nil {
return err return err
} }
// object provider // object provider
cmd.PersistentFlags().String("member.object.users", "[]", "member object provider: users in JSON format") cmd.PersistentFlags().String("member.object.users", "[]", "member object provider: list of users with their passwords and profiles")
if err := viper.BindPFlag("member.object.users", cmd.PersistentFlags().Lookup("member.object.users")); err != nil { if err := viper.BindPFlag("member.object.users", cmd.PersistentFlags().Lookup("member.object.users")); err != nil {
return err return err
} }
// multiuser provider // multiuser provider
cmd.PersistentFlags().String("member.multiuser.user_password", "neko", "member multiuser provider: user password") cmd.PersistentFlags().String("member.multiuser.user_password", "neko", "member multiuser provider: password for regular users")
if err := viper.BindPFlag("member.multiuser.user_password", cmd.PersistentFlags().Lookup("member.multiuser.user_password")); err != nil { if err := viper.BindPFlag("member.multiuser.user_password", cmd.PersistentFlags().Lookup("member.multiuser.user_password")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("member.multiuser.admin_password", "admin", "member multiuser provider: admin password") cmd.PersistentFlags().String("member.multiuser.admin_password", "admin", "member multiuser provider: password for admin users")
if err := viper.BindPFlag("member.multiuser.admin_password", cmd.PersistentFlags().Lookup("member.multiuser.admin_password")); err != nil { if err := viper.BindPFlag("member.multiuser.admin_password", cmd.PersistentFlags().Lookup("member.multiuser.admin_password")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("member.multiuser.user_profile", "{}", "member multiuser provider: user profile in JSON format") cmd.PersistentFlags().String("member.multiuser.user_profile", "{}", "member multiuser provider: profile template for regular users")
if err := viper.BindPFlag("member.multiuser.user_profile", cmd.PersistentFlags().Lookup("member.multiuser.user_profile")); err != nil { if err := viper.BindPFlag("member.multiuser.user_profile", cmd.PersistentFlags().Lookup("member.multiuser.user_profile")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("member.multiuser.admin_profile", "{}", "member multiuser provider: admin profile in JSON format") cmd.PersistentFlags().String("member.multiuser.admin_profile", "{}", "member multiuser provider: profile template for admin users")
if err := viper.BindPFlag("member.multiuser.admin_profile", cmd.PersistentFlags().Lookup("member.multiuser.admin_profile")); err != nil { if err := viper.BindPFlag("member.multiuser.admin_profile", cmd.PersistentFlags().Lookup("member.multiuser.admin_profile")); err != nil {
return err return err
} }

View file

@ -67,17 +67,17 @@ func (WebRTC) Init(cmd *cobra.Command) error {
} }
// Looks like this is conflicting with the frontend and backend ICE servers since latest versions // Looks like this is conflicting with the frontend and backend ICE servers since latest versions
//cmd.PersistentFlags().String("webrtc.iceservers", "[]", "Global STUN and TURN servers in JSON format with `urls`, `username` and `credential` keys") //cmd.PersistentFlags().String("webrtc.iceservers", "[]", "STUN and TURN servers used by the ICE agent")
//if err := viper.BindPFlag("webrtc.iceservers", cmd.PersistentFlags().Lookup("webrtc.iceservers")); err != nil { //if err := viper.BindPFlag("webrtc.iceservers", cmd.PersistentFlags().Lookup("webrtc.iceservers")); err != nil {
// return err // return err
//} //}
cmd.PersistentFlags().String("webrtc.iceservers.frontend", "[]", "Frontend only STUN and TURN servers in JSON format with `urls`, `username` and `credential` keys") cmd.PersistentFlags().String("webrtc.iceservers.frontend", "[]", "STUN and TURN servers used by the frontend")
if err := viper.BindPFlag("webrtc.iceservers.frontend", cmd.PersistentFlags().Lookup("webrtc.iceservers.frontend")); err != nil { if err := viper.BindPFlag("webrtc.iceservers.frontend", cmd.PersistentFlags().Lookup("webrtc.iceservers.frontend")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("webrtc.iceservers.backend", "[]", "Backend only STUN and TURN servers in JSON format with `urls`, `username` and `credential` keys") cmd.PersistentFlags().String("webrtc.iceservers.backend", "[]", "STUN and TURN servers used by the backend")
if err := viper.BindPFlag("webrtc.iceservers.backend", cmd.PersistentFlags().Lookup("webrtc.iceservers.backend")); err != nil { if err := viper.BindPFlag("webrtc.iceservers.backend", cmd.PersistentFlags().Lookup("webrtc.iceservers.backend")); err != nil {
return err return err
} }
@ -217,14 +217,14 @@ func (s *WebRTC) Set() {
// parse frontend ice servers // parse frontend ice servers
if err := viper.UnmarshalKey("webrtc.iceservers.frontend", &s.ICEServersFrontend, viper.DecodeHook( if err := viper.UnmarshalKey("webrtc.iceservers.frontend", &s.ICEServersFrontend, viper.DecodeHook(
utils.JsonStringAutoDecode([]types.ICEServer{}), utils.JsonStringAutoDecode(s.ICEServersFrontend),
)); err != nil { )); err != nil {
log.Warn().Err(err).Msgf("unable to parse frontend ICE servers") log.Warn().Err(err).Msgf("unable to parse frontend ICE servers")
} }
// parse backend ice servers // parse backend ice servers
if err := viper.UnmarshalKey("webrtc.iceservers.backend", &s.ICEServersBackend, viper.DecodeHook( if err := viper.UnmarshalKey("webrtc.iceservers.backend", &s.ICEServersBackend, viper.DecodeHook(
utils.JsonStringAutoDecode([]types.ICEServer{}), utils.JsonStringAutoDecode(s.ICEServersBackend),
)); err != nil { )); err != nil {
log.Warn().Err(err).Msgf("unable to parse backend ICE servers") log.Warn().Err(err).Msgf("unable to parse backend ICE servers")
} }
@ -238,7 +238,7 @@ func (s *WebRTC) Set() {
// parse global ice servers // parse global ice servers
var iceServers []types.ICEServer var iceServers []types.ICEServer
if err := viper.UnmarshalKey("webrtc.iceservers", &iceServers, viper.DecodeHook( if err := viper.UnmarshalKey("webrtc.iceservers", &iceServers, viper.DecodeHook(
utils.JsonStringAutoDecode([]types.ICEServer{}), utils.JsonStringAutoDecode(iceServers),
)); err != nil { )); err != nil {
log.Warn().Err(err).Msgf("unable to parse global ICE servers") log.Warn().Err(err).Msgf("unable to parse global ICE servers")
} }

View file

@ -177,11 +177,20 @@
"key": [ "key": [
"capture", "capture",
"video", "video",
"pipelines" "pipeline"
], ],
"type": "string", "type": "string",
"defaultValue": "[]", "description": "shortcut for configuring only a single gstreamer pipeline, ignored if pipelines is set"
"description": "pipelines config in JSON used for video streaming" },
{
"key": [
"capture",
"video",
"pipelines"
],
"type": "object",
"defaultValue": {},
"description": "pipelines config used for video streaming"
}, },
{ {
"key": [ "key": [
@ -295,7 +304,7 @@
], ],
"type": "boolean", "type": "boolean",
"defaultValue": "true", "defaultValue": "true",
"description": "member file provider: whether to hash passwords using sha256 (recommended)" "description": "member file provider: whether the passwords are hashed using sha256 or not (recommended)"
}, },
{ {
"key": [ "key": [
@ -304,7 +313,7 @@
"path" "path"
], ],
"type": "string", "type": "string",
"description": "member file provider: storage path" "description": "member file provider: path to the file containing the users and their passwords"
}, },
{ {
"key": [ "key": [
@ -314,7 +323,7 @@
], ],
"type": "string", "type": "string",
"defaultValue": "admin", "defaultValue": "admin",
"description": "member multiuser provider: admin password" "description": "member multiuser provider: password for admin users"
}, },
{ {
"key": [ "key": [
@ -322,9 +331,9 @@
"multiuser", "multiuser",
"admin_profile" "admin_profile"
], ],
"type": "string", "type": "object",
"defaultValue": "{}", "defaultValue": {},
"description": "member multiuser provider: admin profile in JSON format" "description": "member multiuser provider: profile template for admin users"
}, },
{ {
"key": [ "key": [
@ -334,7 +343,7 @@
], ],
"type": "string", "type": "string",
"defaultValue": "neko", "defaultValue": "neko",
"description": "member multiuser provider: user password" "description": "member multiuser provider: password for regular users"
}, },
{ {
"key": [ "key": [
@ -342,9 +351,9 @@
"multiuser", "multiuser",
"user_profile" "user_profile"
], ],
"type": "string", "type": "object",
"defaultValue": "{}", "defaultValue": {},
"description": "member multiuser provider: user profile in JSON format" "description": "member multiuser provider: profile template for regular users"
}, },
{ {
"key": [ "key": [
@ -352,9 +361,9 @@
"object", "object",
"users" "users"
], ],
"type": "string", "type": "array",
"defaultValue": "[]", "defaultValue": [],
"description": "member object provider: users in JSON format" "description": "member object provider: list of users with their passwords and profiles"
}, },
{ {
"key": [ "key": [
@ -363,7 +372,7 @@
], ],
"type": "string", "type": "string",
"defaultValue": "multiuser", "defaultValue": "multiuser",
"description": "choose member provider" "description": "selected member provider"
}, },
{ {
"key": [ "key": [
@ -758,9 +767,9 @@
"iceservers", "iceservers",
"backend" "backend"
], ],
"type": "urls", "type": "array",
"defaultValue": "[]", "defaultValue": [],
"description": "Backend only STUN and TURN servers in JSON format with urls, `username` and `credential` keys" "description": "STUN and TURN servers used by the backend"
}, },
{ {
"key": [ "key": [
@ -768,9 +777,9 @@
"iceservers", "iceservers",
"frontend" "frontend"
], ],
"type": "urls", "type": "array",
"defaultValue": "[]", "defaultValue": [],
"description": "Frontend only STUN and TURN servers in JSON format with urls, `username` and `credential` keys" "description": "STUN and TURN servers used by the frontend"
}, },
{ {
"key": [ "key": [

View file

@ -16,7 +16,8 @@
--capture.video.codec string video codec to be used (default "vp8") --capture.video.codec string video codec to be used (default "vp8")
--capture.video.display string X display to capture --capture.video.display string X display to capture
--capture.video.ids strings ordered list of video ids --capture.video.ids strings ordered list of video ids
--capture.video.pipelines string pipelines config in JSON used for video streaming (default "[]") --capture.video.pipeline string shortcut for configuring only a single gstreamer pipeline, ignored if pipelines is set
--capture.video.pipelines string pipelines config used for video streaming (default "{}")
--capture.webcam.device string v4l2sink device used for webcam (default "/dev/video0") --capture.webcam.device string v4l2sink device used for webcam (default "/dev/video0")
--capture.webcam.enabled enable webcam stream --capture.webcam.enabled enable webcam stream
--capture.webcam.height int webcam stream height (default 720) --capture.webcam.height int webcam stream height (default 720)
@ -28,14 +29,14 @@
--desktop.screen string default screen size and framerate (default "1280x720@30") --desktop.screen string default screen size and framerate (default "1280x720@30")
--desktop.unminimize automatically unminimize window when it is minimized (default true) --desktop.unminimize automatically unminimize window when it is minimized (default true)
--desktop.upload_drop whether drop upload is enabled (default true) --desktop.upload_drop whether drop upload is enabled (default true)
--member.file.hash member file provider: whether to hash passwords using sha256 (recommended) (default true) --member.file.hash member file provider: whether the passwords are hashed using sha256 or not (recommended) (default true)
--member.file.path string member file provider: storage path --member.file.path string member file provider: path to the file containing the users and their passwords
--member.multiuser.admin_password string member multiuser provider: admin password (default "admin") --member.multiuser.admin_password string member multiuser provider: password for admin users (default "admin")
--member.multiuser.admin_profile string member multiuser provider: admin profile in JSON format (default "{}") --member.multiuser.admin_profile string member multiuser provider: profile template for admin users (default "{}")
--member.multiuser.user_password string member multiuser provider: user password (default "neko") --member.multiuser.user_password string member multiuser provider: password for regular users (default "neko")
--member.multiuser.user_profile string member multiuser provider: user profile in JSON format (default "{}") --member.multiuser.user_profile string member multiuser provider: profile template for regular users (default "{}")
--member.object.users string member object provider: users in JSON format (default "[]") --member.object.users string member object provider: list of users with their passwords and profiles (default "[]")
--member.provider string choose member provider (default "multiuser") --member.provider string selected member provider (default "multiuser")
--plugins.dir string path to neko plugins to load (default "./bin/plugins") --plugins.dir string path to neko plugins to load (default "./bin/plugins")
--plugins.enabled load plugins in runtime --plugins.enabled load plugins in runtime
--plugins.required if true, neko will exit if there is an error when loading a plugin --plugins.required if true, neko will exit if there is an error when loading a plugin
@ -78,8 +79,8 @@
--webrtc.estimator.unstable_duration duration how long to wait for stalled connection (neutral trend with low bandwidth) before downgrading (default 6s) --webrtc.estimator.unstable_duration duration how long to wait for stalled connection (neutral trend with low bandwidth) before downgrading (default 6s)
--webrtc.estimator.upgrade_backoff duration how long to wait before upgrading again after previous upgrade (default 5s) --webrtc.estimator.upgrade_backoff duration how long to wait before upgrading again after previous upgrade (default 5s)
--webrtc.icelite configures whether or not the ICE agent should be a lite agent --webrtc.icelite configures whether or not the ICE agent should be a lite agent
--webrtc.iceservers.backend urls Backend only STUN and TURN servers in JSON format with urls, `username` and `credential` keys (default "[]") --webrtc.iceservers.backend string STUN and TURN servers used by the backend (default "[]")
--webrtc.iceservers.frontend urls Frontend only STUN and TURN servers in JSON format with urls, `username` and `credential` keys (default "[]") --webrtc.iceservers.frontend string STUN and TURN servers used by the frontend (default "[]")
--webrtc.icetrickle configures whether cadidates should be sent asynchronously using Trickle ICE (default true) --webrtc.icetrickle configures whether cadidates should be sent asynchronously using Trickle ICE (default true)
--webrtc.ip_retrieval_url string URL address used for retrieval of the external IP address (default "https://checkip.amazonaws.com") --webrtc.ip_retrieval_url string URL address used for retrieval of the external IP address (default "https://checkip.amazonaws.com")
--webrtc.nat1to1 strings sets a list of external IP addresses of 1:1 (D)NAT and a candidate type for which the external IP address is used --webrtc.nat1to1 strings sets a list of external IP addresses of 1:1 (D)NAT and a candidate type for which the external IP address is used

View file

@ -36,6 +36,7 @@ This project uses a monorepo structure with the following directories:
- `webpage/`: Webpage code for neko.m1k1o.net, written in [TypeScript](https://www.typescriptlang.org/) and [Docusaurus](https://docusaurus.io/), deployed on [GitHub Pages](https://pages.github.com/). - `webpage/`: Webpage code for neko.m1k1o.net, written in [TypeScript](https://www.typescriptlang.org/) and [Docusaurus](https://docusaurus.io/), deployed on [GitHub Pages](https://pages.github.com/).
- `webpage/docs/`: Documentation for the neko project, including this README file. - `webpage/docs/`: Documentation for the neko project, including this README file.
- `webpage/scripts/`: Helper scripts for generating configuration and OpenAPI docs.
- `webpage/src/`: Source code, components, and styles for the webpage. - `webpage/src/`: Source code, components, and styles for the webpage.
- `webpage/static/`: Static files for the webpage, such as images and icons. - `webpage/static/`: Static files for the webpage, such as images and icons.
- `webpage/versioned_*`: Versioned documentation files for the neko project, generated by [Docusaurus](https://docusaurus.io/). - `webpage/versioned_*`: Versioned documentation files for the neko project, generated by [Docusaurus](https://docusaurus.io/).

View file

@ -10,8 +10,8 @@
"deploy": "docusaurus deploy", "deploy": "docusaurus deploy",
"clear": "docusaurus clear", "clear": "docusaurus clear",
"serve": "docusaurus serve", "serve": "docusaurus serve",
"gen-help": "node ./src/components/Configuration/generate.js ./docs/configuration/help.txt ./docs/configuration/help.json", "gen-config": "node ./src/components/Configuration/generate.js ./docs/configuration/help.txt ./docs/configuration/help.json",
"gen-help:v2": "node ./src/components/Configuration/generate.js ./docs/v2-migration/help.txt ./docs/v2-migration/help.json", "gen-config:v2": "node ./src/components/Configuration/generate.js ./docs/v2-migration/help.txt ./docs/v2-migration/help.json",
"write-translations": "docusaurus write-translations", "write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids", "write-heading-ids": "docusaurus write-heading-ids",
"gen-api-docs": "./gen-api-docs.sh", "gen-api-docs": "./gen-api-docs.sh",

View file

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
cd "$(dirname "$0")/.."
# Clean the API docs # Clean the API docs
docusaurus clean-api-docs all docusaurus clean-api-docs all

22
webpage/scripts/gen-config.sh Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash
cd "$(dirname "$0")/.."
HELP_FILE="$(realpath -m docs/configuration/help.txt)"
pushd ../server
go run cmd/neko/main.go serve --help > $HELP_FILE
popd
# remove all lines with " V2: "
sed -i '/ V2: /d' $HELP_FILE
# remove all lines with " V2 DEPRECATED: "
sed -i '/ V2 DEPRECATED: /d' $HELP_FILE
# remove --legacy
sed -i '/--legacy/d' $HELP_FILE
# remove evething until first "Flags:"
sed -i '1,/Flags:/d' $HELP_FILE
# remove --help
sed -i '/--help/d' $HELP_FILE
npm run gen-config

View file

@ -17,6 +17,16 @@ const parseConfigOptions = (text) => {
defaultValue = 'true'; defaultValue = 'true';
} }
} }
// this is an opaque object
if (type === 'string' && defaultValue === '{}') {
type = 'object';
defaultValue = {};
}
// this is an opaque array
if (type === 'string' && defaultValue === '[]') {
type = 'array';
defaultValue = [];
}
return { key: key.split('.'), type, defaultValue: defaultValue || undefined, description }; return { key: key.split('.'), type, defaultValue: defaultValue || undefined, description };
} }
return null; return null;