whatsapp: v2.2024.25

This commit is contained in:
Mark Joshwel 2024-06-18 18:57:56 +08:00
parent 93e868845a
commit 44907e3462
7 changed files with 165 additions and 93 deletions

View file

@ -1,6 +1,7 @@
spow-whatsapp-bridge
mdtest.db
dist
dist/
test/
# nix
.devbox

View file

@ -0,0 +1,5 @@
# surplus on wheels: WhatsApp Bridge
see <https://surplus.joshwel.co/onwheels/whatsapp-bridge>
or [/docs/onwheels/whatsapp-bridge.md](../../docs/onwheels/whatsapp-bridge.md)
for more information and documentation

View file

@ -1,10 +1,12 @@
// Copyright (c) 2021 Tulir Asokan
// Copyright (c) 2023 Mark Joshwel
// Copyright (c) 2024 Mark Joshwel
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// from https://github.com/tulir/whatsmeow/commit/792d96fbe610bfbf1039ec3b8d3f37f630025aea
package main
import (
@ -17,7 +19,6 @@ import (
"mime"
"os"
"os/signal"
"path"
"strings"
"sync/atomic"
@ -28,8 +29,6 @@ import (
"github.com/mdp/qrterminal/v3"
"google.golang.org/protobuf/proto"
// "go.mau.fi/libsignal/groups"
// "go.mau.fi/libsignal/keys/message"
"go.mau.fi/whatsmeow"
"go.mau.fi/whatsmeow/appstate"
waBinary "go.mau.fi/whatsmeow/binary"
@ -51,33 +50,37 @@ var dbAddress = flag.String("db-address", "file:mdtest.db?_foreign_keys=on", "Da
var requestFullSync = flag.Bool("request-full-sync", false, "Request full (1 year) history sync when logging in?")
var pairRejectChan = make(chan bool, 1)
var data_dir = path.Join(os.Getenv("HOME"), ".local", "share", "s+ow-whatsapp-bridge")
var sharetext_path = path.Join(os.Getenv("HOME"), ".cache", "s+ow", "message")
// s+ow-whatsapp-bridge: define important paths
var dataDir = path.Join(os.Getenv("HOME"), ".local", "share", "s+ow-whatsapp-bridge")
var sharetextPath = path.Join(os.Getenv("HOME"), ".cache", "s+ow", "message")
func main() {
if *debugLogs {
logLevel = "DEBUG"
}
log = waLog.Stdout("Main", logLevel, true)
// make and change dir
err := os.MkdirAll(data_dir, os.ModePerm)
if err != nil {
log.Errorf("s+ow-whatsapp-bridge: Failed to create directory: %v", err)
return
}
err = os.Chdir(data_dir)
if err != nil {
log.Errorf("s+ow-whatsapp-bridge: Failed to change directory: %v", err)
return
}
// mdtest code
waBinary.IndentXML = true
flag.Parse()
if *debugLogs {
logLevel = "DEBUG"
}
if *requestFullSync {
store.DeviceProps.RequireFullSync = proto.Bool(true)
store.DeviceProps.HistorySyncConfig = &waProto.DeviceProps_HistorySyncConfig{
FullSyncDaysLimit: proto.Uint32(3650),
FullSyncSizeMbLimit: proto.Uint32(102400),
StorageQuotaMb: proto.Uint32(102400),
}
}
log = waLog.Stdout("Main", logLevel, true)
// s+ow-whatsapp-bridge: make and change dir
err := os.MkdirAll(dataDir, os.ModePerm)
if err != nil {
log.Errorf("s+ow-whatsapp-bridge: s+ow-whatsapp-bridge: Failed to create directory: %v", err)
return
}
err = os.Chdir(dataDir)
if err != nil {
log.Errorf("s+ow-whatsapp-bridge: s+ow-whatsapp-bridge: Failed to change directory: %v", err)
return
}
dbLog := waLog.Stdout("Database", logLevel, true)
@ -135,10 +138,9 @@ func main() {
return
}
c := make(chan os.Signal)
c := make(chan os.Signal, 1)
input := make(chan string)
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
defer close(input)
scan := bufio.NewScanner(os.Stdin)
@ -150,7 +152,8 @@ func main() {
}
}()
// if 'login' in os.Args, we exit here
// s+ow-whatsapp-bridge
// - if 'login' in os.Args, we exit here
for _, arg := range os.Args {
if arg == "login" {
for {
@ -170,21 +173,23 @@ func main() {
}
}
// if using as cli
// - if using as cli
args := os.Args[1:]
if len(args) > 0 {
handleCmd(strings.ToLower(args[0]), args[1:])
return
}
// read file ~/.cache/s+ow/message
sharetext, err := os.ReadFile(sharetext_path)
// - else, "normal" operation:
// - - read file ~/.cache/s+ow/message
sharetext, err := os.ReadFile(sharetextPath)
if err != nil {
log.Errorf("s+ow-whatsapp-bridge: Failed to open file: %v", err)
return
}
// "normal" operation; read JID targets from stdin
// - - read JID targets from stdin
targets := <-input
split := strings.Split(targets, ",")
for _, target := range split {
@ -198,6 +203,8 @@ func main() {
if !ok {
return
}
// reference the "send" case in handleCmd as a single source of truth
msg := &waProto.Message{Conversation: proto.String(strings.TrimSpace(string(sharetext)))}
resp, err := cli.SendMessage(context.Background(), recipient, msg)
if err != nil {
@ -233,7 +240,26 @@ func parseJID(arg string) (types.JID, bool) {
}
func handleCmd(cmd string, args []string) {
// s+ow-whatsapp-bridge: we only need the bare minimum:
// - account-related: pair-phone, logout, reconnect
// - chat-related: list, send
switch cmd {
case "pair-phone":
if len(args) < 1 {
log.Errorf("s+ow-whatsapp-bridge: Usage: pair-phone <number>")
return
}
linkingCode, err := cli.PairPhone(args[0], true, whatsmeow.PairClientChrome, "Chrome (Linux)")
if err != nil {
panic(err)
}
fmt.Println("Linking code:", linkingCode)
case "reconnect":
cli.Disconnect()
err := cli.Connect()
if err != nil {
log.Errorf("s+ow-whatsapp-bridge: Failed to connect: %v", err)
}
case "logout":
err := cli.Logout()
if err != nil {
@ -245,11 +271,11 @@ func handleCmd(cmd string, args []string) {
groups, err := cli.GetJoinedGroups()
if err != nil {
log.Errorf("s+ow-whatsapp-bridge: Failed to get group list: %v", err)
return
}
} else {
for _, group := range groups {
fmt.Printf("%s\t\t%s\n", group.JID, group.Name)
}
}
case "send":
if len(args) < 2 {
log.Errorf("s+ow-whatsapp-bridge: Usage: send <jid> <text>")
@ -278,7 +304,7 @@ func handler(rawEvt interface{}) {
if len(cli.Store.PushName) > 0 && evt.Name == appstate.WAPatchCriticalBlock {
err := cli.SendPresence(types.PresenceAvailable)
if err != nil {
log.Warnf("s+ow-whatsapp-bridge: Failed to send available presence: %v", err)
log.Warnf("Failed to send available presence: %v", err)
} else {
log.Infof("s+ow-whatsapp-bridge: Marked self as available")
}
@ -291,7 +317,7 @@ func handler(rawEvt interface{}) {
// This makes sure that outgoing messages always have the right pushname.
err := cli.SendPresence(types.PresenceAvailable)
if err != nil {
log.Warnf("s+ow-whatsapp-bridge: Failed to send available presence: %v", err)
log.Warnf("Failed to send available presence: %v", err)
} else {
log.Infof("s+ow-whatsapp-bridge: Marked self as available")
}
@ -350,13 +376,29 @@ func handler(rawEvt interface{}) {
return
}
exts, _ := mime.ExtensionsByType(img.GetMimetype())
path := fmt.Sprintf("%s%s", evt.Info.ID, exts[0])
err = os.WriteFile(path, data, 0600)
savePath := fmt.Sprintf("%s%s", evt.Info.ID, exts[0])
err = os.WriteFile(savePath, data, 0600)
if err != nil {
log.Errorf("s+ow-whatsapp-bridge: Failed to save image: %v", err)
return
}
log.Infof("s+ow-whatsapp-bridge: Saved image in message to %s", path)
log.Infof("s+ow-whatsapp-bridge: Saved image in message to %s", savePath)
}
case *events.Receipt:
if evt.Type == types.ReceiptTypeRead || evt.Type == types.ReceiptTypeReadSelf {
log.Infof("s+ow-whatsapp-bridge: %v was read by %s at %s", evt.MessageIDs, evt.SourceString(), evt.Timestamp)
} else if evt.Type == types.ReceiptTypeDelivered {
log.Infof("s+ow-whatsapp-bridge: %s was delivered to %s at %s", evt.MessageIDs[0], evt.SourceString(), evt.Timestamp)
}
case *events.Presence:
if evt.Unavailable {
if evt.LastSeen.IsZero() {
log.Infof("s+ow-whatsapp-bridge: %s is now offline", evt.From)
} else {
log.Infof("s+ow-whatsapp-bridge: %s is now offline (last seen: %s)", evt.From, evt.LastSeen)
}
} else {
log.Infof("s+ow-whatsapp-bridge: %s is now online", evt.From)
}
case *events.HistorySync:
id := atomic.AddInt32(&historySyncID, 1)
@ -376,10 +418,12 @@ func handler(rawEvt interface{}) {
log.Infof("s+ow-whatsapp-bridge: Wrote history sync to %s", fileName)
_ = file.Close()
case *events.AppState:
log.Debugf("App state event: %+v / %+v", evt.Index, evt.SyncActionValue)
log.Debugf("s+ow-whatsapp-bridge: App state event: %+v / %+v", evt.Index, evt.SyncActionValue)
case *events.KeepAliveTimeout:
log.Debugf("Keepalive timeout event: %+v", evt)
log.Debugf("s+ow-whatsapp-bridge: Keepalive timeout event: %+v", evt)
case *events.KeepAliveRestored:
log.Debugf("Keepalive restored")
log.Debugf("s+ow-whatsapp-bridge: Keepalive restored")
case *events.Blocklist:
log.Infof("s+ow-whatsapp-bridge: Blocklist event: %+v", evt)
}
}

View file

@ -1,4 +1,4 @@
mkdir -p "$HOME/.local/bin"
pkg install golang
go build
mkdir -p $HOME/.local/bin
mv spow-whatsapp-bridge $HOME/.local/bin/s+ow-whatsapp-bridge
mv spow_whatsapp_bridge "$HOME/.local/bin/s+ow-whatsapp-bridge"

View file

@ -1,22 +1,26 @@
module spow-whatsapp-bridge
module forge.joshwel.co/mark/surplus/src/spow-whatsapp-bridge
go 1.21.3
go 1.22.3
require (
github.com/mattn/go-sqlite3 v1.14.18
github.com/mattn/go-sqlite3 v1.14.22
github.com/mdp/qrterminal/v3 v3.2.0
go.mau.fi/whatsmeow v0.0.0-20231104103606-23bd57d939ca
google.golang.org/protobuf v1.31.0
go.mau.fi/whatsmeow v0.0.0-20240603101645-64bc969fbe78
google.golang.org/protobuf v1.34.2
)
require (
filippo.io/edwards25519 v1.0.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/rs/zerolog v1.33.0 // indirect
go.mau.fi/libsignal v0.1.0 // indirect
go.mau.fi/util v0.2.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/term v0.13.0 // indirect
go.mau.fi/util v0.4.2 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/term v0.21.0 // indirect
rsc.io/qr v0.2.0 // indirect
)

View file

@ -1,42 +1,55 @@
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mdp/qrterminal v1.0.1/go.mod h1:Z33WhxQe9B6CdW37HaVqcRKzP+kByF3q/qLxOGe12xQ=
github.com/mdp/qrterminal/v3 v3.0.0 h1:ywQqLRBXWTktytQNDKFjhAvoGkLVN3J2tAFZ0kMd9xQ=
github.com/mdp/qrterminal/v3 v3.0.0/go.mod h1:NJpfAs7OAm77Dy8EkWrtE4aq+cE6McoLXlBqXQEwvE0=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
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-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mdp/qrterminal/v3 v3.2.0 h1:qteQMXO3oyTK4IHwj2mWsKYYRBOp1Pj2WRYFYYNTCdk=
github.com/mdp/qrterminal/v3 v3.2.0/go.mod h1:XGGuua4Lefrl7TLEsSONiD+UEjQXJZ4mPzF+gWYIJkk=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.mau.fi/libsignal v0.1.0 h1:vAKI/nJ5tMhdzke4cTK1fb0idJzz1JuEIpmjprueC+c=
go.mau.fi/libsignal v0.1.0/go.mod h1:R8ovrTezxtUNzCQE5PH30StOQWWeBskBsWE55vMfY9I=
go.mau.fi/util v0.2.0 h1:AMGBEdg9Ya/smb/09dljo9wBwKr432EpfjDWF7aFQg0=
go.mau.fi/util v0.2.0/go.mod h1:AxuJUMCxpzgJ5eV9JbPWKRH8aAJJidxetNdUj7qcb84=
go.mau.fi/whatsmeow v0.0.0-20230805111647-405414b9b5c0 h1:6kAOyrp8E9p99X1I3uj7BtEFspdcVjnYzUZpqcHo/mE=
go.mau.fi/whatsmeow v0.0.0-20230805111647-405414b9b5c0/go.mod h1:+ObGpFE6cbbY4hKc1FmQH9MVfqaemmlXGXSnwDvCOyE=
go.mau.fi/whatsmeow v0.0.0-20231104103606-23bd57d939ca h1:r1/XGlSlYUFR4WTDKURPf8bTuPncrADZfOGPNrfr1oI=
go.mau.fi/whatsmeow v0.0.0-20231104103606-23bd57d939ca/go.mod h1:u557d2vph8xcLrk3CKTBknUHoB6icUpqazA4w+binRU=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
go.mau.fi/util v0.4.2 h1:RR3TOcRHmCF9Bx/3YG4S65MYfa+nV6/rn8qBWW4Mi30=
go.mau.fi/util v0.4.2/go.mod h1:PlAVfUUcPyHPrwnvjkJM9UFcPE7qGPDJqk+Oufa1Gtw=
go.mau.fi/whatsmeow v0.0.0-20240603101645-64bc969fbe78 h1:zST/E2cOjQEjXuis0miwSd20Uf+ffdJna6QefQyxEcc=
go.mau.fi/whatsmeow v0.0.0-20240603101645-64bc969fbe78/go.mod h1:0+65CYaE6r4dWzr0dN8i+UZKy0gIfJ79VuSqIl0nKRM=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=

View file

@ -0,0 +1,5 @@
#!/bin/sh
# surplus on wheels: WhatsApp Bridge: installation and updater script
set -e
echo TODO