18 Commits

Author SHA1 Message Date
github-actions[bot]
93064a8957 chore: auto-update Go modules 2026-04-13 00:10:46 +00:00
github-actions[bot]
334ec01dfc chore: auto-update Go modules 2026-04-06 00:08:47 +00:00
github-actions[bot]
0bc2ecdf35 chore: auto-update Go modules 2026-03-30 00:08:38 +00:00
377991eeca add pre-commit config 2026-03-21 14:02:51 +00:00
github-actions[bot]
b60e006369 chore: auto-update Go modules 2026-03-16 00:07:38 +00:00
github-actions[bot]
2ce055c198 chore: auto-update Go modules 2026-03-09 00:05:20 +00:00
be2715816b move versionFromBuild() 2026-03-07 12:40:58 +00:00
55d14b0d07 upd tested against
add macOS badge
2026-03-07 01:07:37 +00:00
b7cd658d7c add vbanTxtUtf8 to give the magic value meaning
OR the bpsIndex with the mask value.
2026-03-07 00:53:35 +00:00
b506265e37 make the ratelimiting more accurate. 2026-03-07 00:52:58 +00:00
github-actions[bot]
843f7c5e0d chore: auto-update Go modules 2026-02-23 00:05:50 +00:00
754369668b rewrite versionFromBuild() 2026-02-16 01:19:54 +00:00
5485927311 return nil, nil if --version of --help flags passed 2026-02-16 00:55:08 +00:00
a0a8159557 return nil explicitly if no error 2026-02-16 00:10:00 +00:00
github-actions[bot]
87c2afbf03 chore: auto-update Go modules 2026-02-16 00:06:01 +00:00
5d9924ff58 replace exitOnError with a deferred exit function.
this ensures the closer() cleanup function is always called.
2026-02-15 11:08:25 +00:00
00acafa290 fix docstring 2026-02-15 10:51:59 +00:00
f97d241f64 add linter exclusion for test files
set thresholds for issues
2026-02-15 09:54:12 +00:00
8 changed files with 127 additions and 86 deletions

View File

@@ -67,6 +67,7 @@ linters:
- name: unused-parameter
- name: var-declaration
- name: blank-imports
- name: range
# Disabled rules (can be enabled if needed)
# - name: line-length-limit
@@ -81,6 +82,17 @@ linters:
- G104 # Duplicated errcheck checks
- G115 # integer overflow conversion int -> uint32
exclusions:
warn-unused: false
rules:
# Exclude some linters from running on tests files.
- path: _test\.go
linters:
- gocyclo
- errcheck
- dupl
- gosec
# Formatters configuration
formatters:
# Enable specific formatters
@@ -106,5 +118,8 @@ formatters:
extra-rules: true # Enable additional formatting rules
issues:
max-same-issues: 0
max-issues-per-linter: 0
# Limit the number of same issues reported to avoid spam
max-same-issues: 50
# Limit the number of issues per linter to keep output manageable
max-issues-per-linter: 100

5
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,5 @@
repos:
- repo: https://github.com/tekwizely/pre-commit-golang
rev: v1.0.0-rc.4
hooks:
- id: go-mod-tidy

View File

@@ -1,5 +1,6 @@
![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white)
![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)
![macOS](https://img.shields.io/badge/mac%20os-000000?style=for-the-badge&logo=macos&logoColor=F0F0F0)
# VBAN Sendtext
@@ -23,10 +24,10 @@ For an outline of past/future changes refer to: [CHANGELOG](CHANGELOG.md)
## Tested against
- Basic 1.1.1.9
- Banana 2.1.1.9
- Potato 3.1.1.9
- Matrix 1.0.1.2
- Basic 1.1.2.2
- Banana 2.1.2.2
- Potato 3.1.2.2
- Matrix 1.0.2.6
---

View File

@@ -20,6 +20,19 @@ import (
var version string // Version will be set at build time
// versionFromBuild retrieves the version information from the build metadata.
func versionFromBuild() string {
if version != "" {
return version
}
info, ok := debug.ReadBuildInfo()
if !ok {
return "(unable to read version)"
}
return strings.Split(info.Main.Version, "-")[0]
}
// Flags holds the command-line flags for the VBANTXT client.
type Flags struct {
Host string
@@ -47,12 +60,31 @@ func (f *Flags) String() string {
)
}
func exitOnError(err error) {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
// main is the entry point of the application.
// It sets up a deferred function to handle exiting with the appropriate exit code
// and calls the run function to execute the main logic.
func main() {
var exitCode int
// Defer exit with the final exit code
defer func() {
if exitCode != 0 {
os.Exit(exitCode)
}
}()
closer, err := run()
if closer != nil {
defer closer()
}
if err != nil {
log.Error(err)
exitCode = 1
}
}
func main() {
// run contains the main application logic and returns a closer function and any error.
func run() (func(), error) {
var flags Flags
// VBAN specific flags
@@ -66,7 +98,7 @@ func main() {
configDir, err := os.UserConfigDir()
if err != nil {
exitOnError(fmt.Errorf("failed to get user config directory: %w", err))
return nil, fmt.Errorf("failed to get user config directory: %w", err)
}
defaultConfigPath := filepath.Join(configDir, "vbantxt", "config.toml")
@@ -96,19 +128,19 @@ func main() {
switch {
case errors.Is(err, ff.ErrHelp):
fmt.Fprintf(os.Stderr, "%s\n", ffhelp.Flags(fs, "vbantxt [flags] <vban commands>"))
os.Exit(0)
return nil, nil
case err != nil:
exitOnError(fmt.Errorf("failed to parse flags: %w", err))
return nil, fmt.Errorf("failed to parse flags: %w", err)
}
if flags.Version {
fmt.Printf("vbantxt version: %s\n", versionFromBuild())
os.Exit(0)
return nil, nil
}
level, err := log.ParseLevel(flags.Loglevel)
if err != nil {
exitOnError(fmt.Errorf("invalid log level: %s", flags.Loglevel))
return nil, fmt.Errorf("invalid log level %q", flags.Loglevel)
}
log.SetLevel(level)
@@ -116,28 +148,18 @@ func main() {
client, closer, err := createClient(&flags)
if err != nil {
exitOnError(err)
return nil, fmt.Errorf("failed to create VBAN client: %w", err)
}
defer closer()
commands := fs.GetArgs()
if len(commands) == 0 {
exitOnError(errors.New("no VBAN commands provided"))
return closer, errors.New(
"no VBAN commands provided; please provide at least one command as an argument",
)
}
sendCommands(client, commands)
}
// versionFromBuild retrieves the version information from the build metadata.
func versionFromBuild() string {
if version == "" {
info, ok := debug.ReadBuildInfo()
if !ok {
exitOnError(errors.New("failed to read build info"))
}
version = strings.Split(info.Main.Version, "-")[0]
}
return version
return closer, nil
}
// createClient creates a new vban client with the provided options.
@@ -159,16 +181,14 @@ func createClient(flags *Flags) (*vbantxt.VbanTxt, func(), error) {
}
}
return client, closer, err
return client, closer, nil
}
// sendCommands sends a list of commands to the VBAN client.
// sendCommands sends the provided VBAN commands using the client and logs any errors that occur.
func sendCommands(client *vbantxt.VbanTxt, commands []string) {
for _, cmd := range commands {
err := client.Send(cmd)
if err != nil {
if err := client.Send(cmd); err != nil {
log.Errorf("Failed to send command '%s': %v", cmd, err)
continue
}
}
}

25
go.mod
View File

@@ -1,36 +1,35 @@
module github.com/onyx-and-iris/vbantxt
go 1.24.2
go 1.25.0
require (
github.com/charmbracelet/log v0.4.2
github.com/charmbracelet/log v1.0.0
github.com/peterbourgon/ff/v4 v4.0.0-beta.1
github.com/stretchr/testify v1.10.0
github.com/stretchr/testify v1.11.1
)
require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/colorprofile v0.4.1 // indirect
github.com/charmbracelet/colorprofile v0.4.3 // indirect
github.com/charmbracelet/lipgloss v1.1.0 // indirect
github.com/charmbracelet/x/ansi v0.11.6 // indirect
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect
github.com/clipperhouse/displaywidth v0.9.0 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.6.0 // indirect
github.com/clipperhouse/displaywidth v0.11.0 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logfmt/logfmt v0.6.1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.21 // indirect
github.com/mattn/go-runewidth v0.0.23 // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
github.com/pelletier/go-toml/v2 v2.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/sys v0.43.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

55
go.sum
View File

@@ -1,24 +1,21 @@
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
github.com/charmbracelet/log v1.0.0 h1:HVVVMmfOorfj3BA9i8X8UL69Hoz9lI0PYwXfJvOdRc4=
github.com/charmbracelet/log v1.0.0/go.mod h1:uYgY3SmLpwJWxmlrPwXvzVYujxis1vAKRV/0VQB7yWA=
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.6.0 h1:z0cDbUV+aPASdFb2/ndFnS9ts/WNXgTNNGFoKXuhpos=
github.com/clipperhouse/uax29/v2 v2.6.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
@@ -30,42 +27,34 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM=
github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/peterbourgon/ff/v4 v4.0.0-beta.1 h1:hV8qRu3V7YfiSMsBSfPfdcznAvPQd3jI5zDddSrDoUc=
github.com/peterbourgon/ff/v4 v4.0.0-beta.1/go.mod h1:onQJUKipvCyFmZ1rIYwFAh1BhPOvftb1uhvSI7krNLc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -10,6 +10,7 @@ import (
const (
vbanProtocolTxt = 0x40
vbanTxtUtf8 = 0x10
streamNameSz = 16
headerSz = 4 + 1 + 1 + 1 + 1 + 16 + 4
)
@@ -59,7 +60,7 @@ func newPacket(streamname string) (packet, error) {
// sr defines the samplerate for the request.
func (p *packet) sr() byte {
return byte(vbanProtocolTxt + p.bpsIndex)
return byte(p.bpsIndex | vbanProtocolTxt)
}
// nbc defines the channel of the request.
@@ -74,7 +75,7 @@ func (p *packet) header() []byte {
p.hbuf.WriteByte(p.sr())
p.hbuf.WriteByte(byte(0))
p.hbuf.WriteByte(p.nbc())
p.hbuf.WriteByte(byte(0x10))
p.hbuf.WriteByte(byte(vbanTxtUtf8))
p.hbuf.Write(p.streamname[:])
var frameBytes [4]byte

View File

@@ -4,6 +4,8 @@ import (
"fmt"
"io"
"time"
"github.com/charmbracelet/log"
)
// VbanTxt is used to send VBAN-TXT requests to a distant Voicemeeter/Matrix.
@@ -11,6 +13,7 @@ type VbanTxt struct {
conn io.WriteCloser
packet packet
ratelimit time.Duration
lastSend time.Time
}
// New constructs a fully formed VbanTxt instance. This is the package's entry point.
@@ -40,8 +43,18 @@ func New(host string, port int, streamname string, options ...Option) (*VbanTxt,
}
// Send is responsible for firing each VBAN-TXT request.
// It waits for {vt.ratelimit} time before returning.
// It enforces rate limiting by waiting only when necessary.
func (vt *VbanTxt) Send(cmd string) error {
if elapsed := time.Since(vt.lastSend); elapsed < vt.ratelimit {
log.Debugf(
"Rate limit in effect. Waiting for %v before sending next command.",
vt.ratelimit-elapsed,
)
time.Sleep(vt.ratelimit - elapsed)
}
vt.lastSend = time.Now()
_, err := vt.conn.Write(append(vt.packet.header(), cmd...))
if err != nil {
return fmt.Errorf("error sending command (%s): %w", cmd, err)
@@ -49,8 +62,6 @@ func (vt *VbanTxt) Send(cmd string) error {
vt.packet.bumpFrameCounter()
time.Sleep(vt.ratelimit)
return nil
}