From 3d3a630a700279edaf3c8094d6d9fa13113078ff Mon Sep 17 00:00:00 2001 From: Jakeyzerk Date: Sat, 20 Jun 2026 11:49:47 +0700 Subject: [PATCH 1/2] feat(whatsapp): rewrite service using tulir/whatsmeow Replaces abandoned Rhymen/go-whatsapp with tulir/whatsmeow. Closes #274 --- go.mod | 31 ++++++-- go.sum | 96 +++++++++++++++++++--- service/whatsapp/README.md | 33 ++++++-- service/whatsapp/doc.go | 14 ++-- service/whatsapp/whatsapp.go | 149 ++++++++++++++++++++++++++++++++--- whatsmeow.db | Bin 0 -> 163840 bytes 6 files changed, 276 insertions(+), 47 deletions(-) create mode 100644 whatsmeow.db diff --git a/go.mod b/go.mod index c873561ce..ce628cbd6 100644 --- a/go.mod +++ b/go.mod @@ -41,8 +41,11 @@ require ( github.com/caarlos0/go-reddit/v3 v3.0.1 github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible github.com/mailgun/mailgun-go/v5 v5.16.0 + github.com/mdp/qrterminal/v3 v3.2.1 github.com/textmagic/textmagic-rest-go-v2/v3 v3.0.50044 + go.mau.fi/whatsmeow v0.0.0-20260616120636-eaa388b4e537 google.golang.org/api v0.284.0 + modernc.org/sqlite v1.52.0 ) require ( @@ -64,7 +67,11 @@ require ( github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.2.0 // indirect + github.com/beeper/argo-go v1.1.2 // indirect github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect + github.com/coder/websocket v1.8.15 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -81,12 +88,17 @@ require ( github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/ncruces/go-strftime v1.0.0 // indirect github.com/oapi-codegen/runtime v1.4.1 // indirect + github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/zerolog v1.35.1 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect - go.mau.fi/util v0.9.9 // indirect + github.com/vektah/gqlparser/v2 v2.5.27 // indirect + go.mau.fi/libsignal v0.2.2 // indirect + go.mau.fi/util v0.9.10 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 // indirect @@ -96,7 +108,8 @@ require ( go.opentelemetry.io/otel/sdk v1.44.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.44.0 // indirect go.opentelemetry.io/otel/trace v1.44.0 // indirect - golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a // indirect + golang.org/x/exp v0.0.0-20260611194520-c48552f49976 // indirect + golang.org/x/term v0.44.0 // indirect golang.org/x/time v0.15.0 // indirect google.golang.org/appengine/v2 v2.0.6 // indirect google.golang.org/genproto v0.0.0-20260526163538-3dc84a4a5aaa // indirect @@ -104,6 +117,10 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect google.golang.org/grpc v1.81.1 // indirect gopkg.in/go-playground/validator.v9 v9.31.0 // indirect + modernc.org/libc v1.72.3 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect + rsc.io/qr v0.2.0 // indirect ) require ( @@ -144,11 +161,11 @@ require ( github.com/tidwall/sjson v1.2.5 // indirect github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect github.com/ttacon/libphonenumber v1.2.1 // indirect - golang.org/x/crypto v0.52.0 // indirect - golang.org/x/net v0.55.0 // indirect + golang.org/x/crypto v0.53.0 // indirect + golang.org/x/net v0.56.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sys v0.45.0 // indirect - golang.org/x/text v0.37.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/text v0.38.0 // indirect + google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index b9f1542cc..f4e8107c6 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= firebase.google.com/go/v4 v4.20.0 h1:ighpjeAC45rY/95cUQ+ojIKlKcTnz2YC0ldam56z2YU= firebase.google.com/go/v4 v4.20.0/go.mod h1:hqhkQtZkThGH42TnaYi7A8EFR1E0FEuB5oHvJ1Q57t8= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 h1:O2sXMyJh8b7devAGdE+163xtRurt0RVpB6DIzX5vGfg= @@ -44,10 +46,14 @@ github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20250718055228-285ecf400b48 h1:I github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20250718055228-285ecf400b48/go.mod h1:rjP7sIipbZcagro/6TCk6X0ZeFT2eyudH5+fve/cbBA= github.com/SherClockHolmes/webpush-go v1.4.0 h1:ocnzNKWN23T9nvHi6IfyrQjkIc0oJWv1B1pULsf9i3s= github.com/SherClockHolmes/webpush-go v1.4.0/go.mod h1:XSq8pKX11vNV8MJEMwjrlTkxhAj1zKfxmyhdV7Pd6UA= +github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= +github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.30.0 h1:uA3uhDbCxfO9+DI/DuGeAMr9qI+noVWwGPNTFuKID5M= github.com/alicebob/miniredis/v2 v2.30.0/go.mod h1:84TWKZlxYkfgMucPBf5SOQBYJceZeQRFIaQgNMiCX6Q= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/appleboy/go-fcm v1.2.10 h1:vOFLreJF4QmbV8VwtlczdBNm0Vzaw/4WNOBMYfw4CCQ= github.com/appleboy/go-fcm v1.2.10/go.mod h1:TVKSknWBz2N63uZjigxi/dudL+jZ7KQ9tfQwF3dkyyU= github.com/atc0005/go-teams-notify/v2 v2.14.0 h1:7N+xw+COnYANLREaAveQ65rsNQ12nIZJED9nMLyscCo= @@ -84,6 +90,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.43.3 h1:VrIhKRCSK1umelSgB9RghvA9RTUY github.com/aws/aws-sdk-go-v2/service/sts v1.43.3/go.mod h1:r8wkDOuLaaMFqFiYAb8dGY2A3gJCOujMc6CFOVC4Zhc= github.com/aws/smithy-go v1.27.1 h1:4T340VFndXtADGF52gYa1POyL7s9E4Z1OeZ1hCscIw8= github.com/aws/smithy-go v1.27.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/beeper/argo-go v1.1.2 h1:UQI2G8F+NLfGTOmTUI0254pGKx/HUU/etbUGTJv91Fs= +github.com/beeper/argo-go v1.1.2/go.mod h1:M+LJAnyowKVQ6Rdj6XYGEn+qcVFkb3R/MUpqkGR0hM4= github.com/blinkbean/dingtalk v1.1.3 h1:MbidFZYom7DTFHD/YIs+eaI7kRy52kmWE/sy0xjo6E4= github.com/blinkbean/dingtalk v1.1.3/go.mod h1:9BaLuGSBqY3vT5hstValh48DbsKO7vaHaJnG9pXwbto= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= @@ -103,6 +111,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= +github.com/coder/websocket v1.8.15 h1:6B2JPeOGlpff2Uz6vOEH1Vzpi0iUz20A+lPVhPHtNUA= +github.com/coder/websocket v1.8.15/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= github.com/cschomburg/go-pushbullet v0.0.0-20171206132031-67759df45fbb h1:7X9nrm+LNWdxzQOiCjy0G51rNUxbH35IDHCjAMvogyM= github.com/cschomburg/go-pushbullet v0.0.0-20171206132031-67759df45fbb/go.mod h1:RfQ9wji3fjcSEsQ+uFCtIh3+BXgcZum8Kt3JxvzYzlk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -118,6 +128,10 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/drswork/go-twitter v0.0.0-20221107160839-dea1b6ed53d7 h1:uh1GSejOhVPRQmoXZxY82TiewZB8QXiaP1skL7Nun3Y= github.com/drswork/go-twitter v0.0.0-20221107160839-dea1b6ed53d7/go.mod h1:ncTaGuXc5v7AuiVekeJ0Nwh8Bf4cudukoj0qM/15UZE= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg= +github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= @@ -192,6 +206,8 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17 github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/uuid v0.0.0-20171113160352-8c31c18f31ed/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -210,6 +226,8 @@ github.com/gregdel/pushover v1.4.0 h1:P77WAJ2zPG+b0mEsmMjWGrPMuvhkh9k3v7Oviwsove github.com/gregdel/pushover v1.4.0/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER1PthX7to= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= @@ -237,9 +255,15 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= 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.45 h1:6KA/spDguL3KV8rnybG7ezSaE4SeMR3KC9VbUoAQaIk= +github.com/mattn/go-sqlite3 v1.14.45/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ= +github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4= +github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU= github.com/mileusna/viber v1.0.1 h1:gWB6/lKoWYVxkH0Jb8jRnGIRZ/9DEM7RBZRJHRfdYWs= github.com/mileusna/viber v1.0.1/go.mod h1:Pxu/iPMnYjnHgu+bEp3SiKWHWmlf/kDp/yOX8XUdYrQ= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -259,6 +283,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 h1:WDsQxOJDy0N1VRAjXLpi8sCEZRSGarLWQevDxpTBRrM= +github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pkg/errors v0.8.1-0.20161029093637-248dadf4e906/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -269,6 +295,8 @@ github.com/plivo/plivo-go/v7 v7.60.2/go.mod h1:ceCFoYEzQrtrJjLcU7HR/r6Vz2kAVSayl github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/zerolog v1.35.1 h1:m7xQeoiLIiV0BCEY4Hs+j2NG4Gp2o2KPKmhnnLiazKI= @@ -277,6 +305,8 @@ github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekuei github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= github.com/sendgrid/sendgrid-go v3.16.1+incompatible h1:zWhTmB0Y8XCDzeWIm2/BIt1GjJohAA0p6hVEaDtHWWs= github.com/sendgrid/sendgrid-go v3.16.1+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/silenceper/wechat/v2 v2.1.13 h1:4JCnQKFtw7t5DNTZPa/ITralevehQnl6BapjBp3W3Ns= github.com/silenceper/wechat/v2 v2.1.13/go.mod h1:7Iu3EhQYVtDUJAj+ZVRy8yom75ga7aDWv8RurLkVm0s= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -330,12 +360,18 @@ github.com/ttacon/libphonenumber v1.2.1 h1:fzOfY5zUADkCkbIafAed11gL1sW+bJ26p6zWL github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M= github.com/utahta/go-linenotify v0.5.0 h1:E1tJaB/XhqRY/iz203FD0MaHm10DjQPOq5/Mem2A3Gs= github.com/utahta/go-linenotify v0.5.0/go.mod h1:KsvBXil2wx+ByaCR0e+IZKTbp4pDesc7yjzRigLf6pE= +github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s= +github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ= github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= -go.mau.fi/util v0.9.9 h1:ujDeXCo07HBor5oQLyO1tHklupmqVmPgasc53d7q/NE= -go.mau.fi/util v0.9.9/go.mod h1:pqt4Vcrt+5gcH/CgrHZg11qSx+b34o6mknGzOEA6waY= +go.mau.fi/libsignal v0.2.2 h1:QV+XdzQkm3x3aSG7FcqfGSZuFXz83pRZPBFaPygHbOU= +go.mau.fi/libsignal v0.2.2/go.mod h1:CRlIQg2J8uYTfDFvNoO8/KcZjs5cey0vbc6oj/bssY0= +go.mau.fi/util v0.9.10 h1:wzvz5iDHyqDXB8vgisD4d3SzucLXNM3iNY+1O1RoHtg= +go.mau.fi/util v0.9.10/go.mod h1:YQOxySn+ZE3qSYqNxvyX7Yi3suA8YK17PS6QqBREW7A= +go.mau.fi/whatsmeow v0.0.0-20260616120636-eaa388b4e537 h1:LhxtFShA1NXJWz4yNygwtl3Eycp9XsfMqJeDdcLyKmk= +go.mau.fi/whatsmeow v0.0.0-20260616120636-eaa388b4e537/go.mod h1:9dmNTYZ/1pHjPw/bz+azBsGjAkcrZbqzMrKcvG5bJ8U= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/detectors/gcp v1.44.0 h1:NmLfL734pJhM0JKaYd2Y28+nY9dPRWYAAbxhRCrKXPw= @@ -368,16 +404,18 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= -golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= -golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a h1:+3jdDGGB8NGb1Zktc737jlt3/A5f6UlwSzmvqUuufxw= -golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= +golang.org/x/exp v0.0.0-20260611194520-c48552f49976 h1:X8Hz2ImujgbmetVuW+w2YkyZChE3cBpZi2P158rTG9M= +golang.org/x/exp v0.0.0-20260611194520-c48552f49976/go.mod h1:vnf4pv9iKZXY58sQE1L86zmNWJ4159e1RkcWiLCkeEY= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.0.0-20171115151908-9dfe39835686/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -394,8 +432,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20171101214715-fd80eb99c8f6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -436,8 +474,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= -golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -447,6 +485,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -460,8 +500,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -471,6 +511,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk= +golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -523,3 +565,33 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mautrix v0.28.0 h1:vBakLzf8MAdfED3NzAKiMeKQbc3AQ4EAS03NC+TVMXQ= maunium.net/go/mautrix v0.28.0/go.mod h1:/a9A7LGaqb9B3nho4tLd28n0EPcCdwpm2dxkxkLLgh0= +modernc.org/cc/v4 v4.28.2 h1:3tQ0lf2ADtoby2EtSP+J7IE2SHwEJdP8ioR59wx7XpY= +modernc.org/cc/v4 v4.28.2/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI= +modernc.org/ccgo/v4 v4.34.0 h1:yRLPFZieg532OT4rp4JFNIVcquwalMX26G95WQDqwCQ= +modernc.org/ccgo/v4 v4.34.0/go.mod h1:AS5WYMyBakQ+fhsHhtP8mWB82KTGPkNNJDGfGQCe0/A= +modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= +modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo= +modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= +modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= +modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= +modernc.org/libc v1.72.3 h1:ZnDF4tXn4NBXFutMMQC4vtbTFSXhhKzR73fv0beZEAU= +modernc.org/libc v1.72.3/go.mod h1:dn0dZNnnn1clLyvRxLxYExxiKRZIRENOfqQ8XEeg4Qs= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg= +modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= +modernc.org/sqlite v1.52.0 h1:p4dhYh2tXZCiyaqHwRVJDjIGKWyXayiQpThxgDzJaxo= +modernc.org/sqlite v1.52.0/go.mod h1:tcNzv5p84E0skkmJn038y+hWJbLQXQqEnQfeh5r2JLM= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY= +rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs= diff --git a/service/whatsapp/README.md b/service/whatsapp/README.md index ef35c649b..77bd5ffd3 100644 --- a/service/whatsapp/README.md +++ b/service/whatsapp/README.md @@ -1,14 +1,31 @@ # WhatsApp -## IMPORTANT +WhatsApp notification service using [tulir/whatsmeow](https://github.com/tulir/whatsmeow). -### Broken state; see [#274](https://github.com/nikoksr/notify/issues/274) +## Usage -Since our previous WhatsApp client library was abandoned, we had to switch to a new one. Unfortunately, the new library -is not yet ready for production use. We are working on a solution, but it will take some time. +```go +wa := whatsapp.New() +wa.AddReceivers("628123456789@s.whatsapp.net") -The broken client library caused our CI pipeline to break and for that reason we decided to turn the WhatsApp service -into a no-op service. This means that the WhatsApp service will not send any notifications, but it will not return any -errors either. This is a temporary solution until we have a working client library. We chose no-op over a hard error to -prevent breaking existing applications. +ctx := context.Background() +// Login via QR code (scan with WhatsApp mobile app) +if err := wa.LoginWithQRCode(ctx, "whatsapp.db"); err != nil { + log.Fatal(err) +} +defer wa.Disconnect() + +// Or login via 8-digit pairing code +// if err := wa.LoginWithPairingCode(ctx, "628123456789", "whatsapp.db"); err != nil { +// log.Fatal(err) +// } + +notifier := notify.New() +notifier.UseServices(wa) +notifier.Send(ctx, "Subject", "Message body") +JID Format +Personal chat: 628123456789@s.whatsapp.net +Group chat: 1234567890-1234567890@g.us +Session +Session data is stored in a SQLite database file. Re-authentication is only needed once per device. diff --git a/service/whatsapp/doc.go b/service/whatsapp/doc.go index 38f0a9d64..01653755c 100644 --- a/service/whatsapp/doc.go +++ b/service/whatsapp/doc.go @@ -1,8 +1,8 @@ -/* -Package whatsapp is currently a [ NO-OP ] service! We're sorry for the inconveniences. We're already working on a fix. - -Please read this [1] for more. Thanks! - -[1]:https://github.com/nikoksr/notify/issues/274 -*/ +// Package whatsapp provides a WhatsApp notification service for the notify library. +// +// This implementation uses tulir/whatsmeow, the actively maintained Go WhatsApp +// Web Multi-Device library, replacing the previous Rhymen/go-whatsapp which is +// no longer maintained and incompatible with WhatsApp's current multi-device protocol. +// +// See https://github.com/nikoksr/notify/issues/274 for background. package whatsapp diff --git a/service/whatsapp/whatsapp.go b/service/whatsapp/whatsapp.go index 47c5bde16..ddfb390fc 100644 --- a/service/whatsapp/whatsapp.go +++ b/service/whatsapp/whatsapp.go @@ -2,24 +2,147 @@ package whatsapp import ( "context" + "errors" + "fmt" + "os" + + "github.com/mdp/qrterminal/v3" + "go.mau.fi/whatsmeow" + "go.mau.fi/whatsmeow/proto/waE2E" + "go.mau.fi/whatsmeow/store/sqlstore" + "go.mau.fi/whatsmeow/types" + waLog "go.mau.fi/whatsmeow/util/log" + "google.golang.org/protobuf/proto" + _ "modernc.org/sqlite" // SQLite driver required by whatsmeow store; imported for side-effects only. ) -// Service encapsulates the WhatsApp client along with internal state for storing contacts. -type Service struct{} +// ErrMissingRecipient is returned when Send is called with no recipients configured. +var ErrMissingRecipient = errors.New("whatsapp: missing recipient JID") + +// Service implements notify.Notifier for WhatsApp using whatsmeow. +type Service struct { + client *whatsmeow.Client + recipients []types.JID +} // New returns a new instance of a WhatsApp notification service. -func New() (*Service, error) { return &Service{}, nil } +func New() *Service { + return &Service{} +} + +// AddReceivers takes WhatsApp JID strings and appends them to the internal recipient list. +// The expected format is: 6281234567890@s.whatsapp.net. +func (s *Service) AddReceivers(receivers ...string) { + for _, r := range receivers { + jid, err := types.ParseJID(r) + if err != nil { + continue + } + + s.recipients = append(s.recipients, jid) + } +} + +func (s *Service) initClient(ctx context.Context, dbPath string) error { + container, err := sqlstore.New(ctx, "sqlite", "file:"+dbPath+"?_foreign_keys=on", waLog.Noop) + if err != nil { + return fmt.Errorf("whatsapp: failed to init store: %w", err) + } + + deviceStore, err := container.GetFirstDevice(ctx) + if err != nil { + return fmt.Errorf("whatsapp: failed to get device: %w", err) + } + + s.client = whatsmeow.NewClient(deviceStore, waLog.Noop) + + return nil +} + +// LoginWithQRCode authenticates via QR code printed to the terminal. +// It blocks until the QR code is scanned or the context is cancelled. +func (s *Service) LoginWithQRCode(ctx context.Context, dbPath string) error { + if err := s.initClient(ctx, dbPath); err != nil { + return err + } + + if s.client.Store.ID != nil { + return s.client.Connect() + } + + qrChan, _ := s.client.GetQRChannel(ctx) + if err := s.client.Connect(); err != nil { + return err + } + + for evt := range qrChan { + if evt.Event == "code" { + qrterminal.GenerateHalfBlock(evt.Code, qrterminal.L, os.Stdout) + } + } + + return nil +} + +// LoginWithPairingCode authenticates using an 8-digit pairing code sent to phoneNumber. +// It blocks until the pairing code is generated; completion is signalled via WhatsApp events. +func (s *Service) LoginWithPairingCode(ctx context.Context, phoneNumber, dbPath string) (string, error) { + if err := s.initClient(ctx, dbPath); err != nil { + return "", err + } + + if s.client.Store.ID != nil { + return "", s.client.Connect() + } + + if err := s.client.Connect(); err != nil { + return "", err + } + + code, err := s.client.PairPhone(ctx, phoneNumber, true, whatsmeow.PairClientChrome, "Chrome (Linux)") + if err != nil { + return "", fmt.Errorf("whatsapp: failed to get pairing code: %w", err) + } + + return code, nil +} + +// IsConnected reports whether the client is currently connected to WhatsApp. +func (s *Service) IsConnected() bool { + return s.client != nil && s.client.IsConnected() +} + +// Disconnect closes the connection to the WhatsApp servers. +func (s *Service) Disconnect() { + if s.client != nil { + s.client.Disconnect() + } +} + +// Send delivers subject and message to all configured recipients. +// The subject is rendered as bold text followed by a blank line before the message body. +func (s *Service) Send(ctx context.Context, subject, message string) error { + if !s.IsConnected() { + return errors.New("whatsapp: client not connected, call LoginWithQRCode or LoginWithPairingCode first") + } -// LoginWithSessionCredentials provides helper for authentication using whatsapp.Session credentials. -func (s *Service) LoginWithSessionCredentials(_, _, _, _ string, _, _ []byte) error { return nil } + if len(s.recipients) == 0 { + return ErrMissingRecipient + } -// LoginWithQRCode provides helper for authentication using QR code on terminal. -// Refer: https://github.com/Rhymen/go-whatsapp#login for more information. -func (s *Service) LoginWithQRCode() error { return nil } + body := message + if subject != "" { + body = fmt.Sprintf("*%s*\n\n%s", subject, message) + } -// AddReceivers takes WhatsApp contacts and adds them to the internal contacts list. The Send method will send -// a given message to all those contacts. -func (s *Service) AddReceivers(_ ...string) {} + for _, recipient := range s.recipients { + _, err := s.client.SendMessage(ctx, recipient, &waE2E.Message{ + Conversation: proto.String(body), + }) + if err != nil { + return fmt.Errorf("whatsapp: failed to send to %s: %w", recipient, err) + } + } -// Send takes a message subject and a message body and sends them to all previously set contacts. -func (s *Service) Send(_ context.Context, _, _ string) error { return nil } + return nil +} diff --git a/whatsmeow.db b/whatsmeow.db new file mode 100644 index 0000000000000000000000000000000000000000..1fdd11b385a10d0ea73ce3aaab15e2b3e0b6159c GIT binary patch literal 163840 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 Date: Sat, 20 Jun 2026 12:59:25 +0700 Subject: [PATCH 2/2] chore: add *.db to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 046c23f60..a2ea97ac1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ tmp/ .env coverage.out cover.html +*.db +whatsmeow.db