From 6e1698e8200a2ffdc41f59b9e7bb16caa7ad60c4 Mon Sep 17 00:00:00 2001 From: Gara Dorta Date: Wed, 6 May 2026 11:57:16 +0100 Subject: [PATCH 01/17] feat: deploy pages with CI Co-authored-by: Copilot --- .github/workflows/deploy-pages.yml | 37 ++++++++++++++++++++++++++++++ src/docs/build-static-bundle.sh | 24 +++++++++++++++++++ index.html => src/docs/index.html | 2 +- 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/deploy-pages.yml create mode 100755 src/docs/build-static-bundle.sh rename index.html => src/docs/index.html (92%) diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml new file mode 100644 index 0000000..e4fd14a --- /dev/null +++ b/.github/workflows/deploy-pages.yml @@ -0,0 +1,37 @@ +name: Deploy API Docs to GitHub Pages + +on: + release: + types: + - published + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build-and-deploy: + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup Pages + uses: actions/configure-pages@v6 + + - name: Build static documentation bundle + run: src/docs/build-static-bundle.sh site "${{ github.event.release.tag_name }}" + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v5 + with: + path: site + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/src/docs/build-static-bundle.sh b/src/docs/build-static-bundle.sh new file mode 100755 index 0000000..f1d279b --- /dev/null +++ b/src/docs/build-static-bundle.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +DOCS_DIR="$ROOT_DIR/src/docs" +INDEX_FILE="$DOCS_DIR/index.html" +OUT_DIR="${1:?output directory argument is required}" +DOCS_VERSION="${2:?docs version argument is required}" +NORMALIZED_DOCS_VERSION="${DOCS_VERSION#v}" + +echo "Normalized docs version: $NORMALIZED_DOCS_VERSION" + +rm -rf "$OUT_DIR" +mkdir -p "$OUT_DIR" + +cp "$DOCS_DIR/swagger.json" "$OUT_DIR/swagger.json" +cp "$INDEX_FILE" "$OUT_DIR/index.html" +touch "$OUT_DIR/.nojekyll" + +jq --arg version "$NORMALIZED_DOCS_VERSION" '.info.version = $version' "$OUT_DIR/swagger.json" > "$OUT_DIR/swagger.json.tmp" +mv "$OUT_DIR/swagger.json.tmp" "$OUT_DIR/swagger.json" + +echo "Static bundle created at: $OUT_DIR" diff --git a/index.html b/src/docs/index.html similarity index 92% rename from index.html rename to src/docs/index.html index f747d1c..6346d99 100644 --- a/index.html +++ b/src/docs/index.html @@ -11,7 +11,7 @@ window.onload = function () { // Begin Swagger UI call region const ui = SwaggerUIBundle({ - url: "src/docs/swagger.json", //Location of Open API spec in the repo + url: "swagger.json", dom_id: '#swagger-ui', deepLinking: true, presets: [ From ede08b64d8b95f3c2a10f6e76cdd6a37ed2303c2 Mon Sep 17 00:00:00 2001 From: PINKU <241377225+pinkustar@users.noreply.github.com> Date: Fri, 5 Jun 2026 10:05:41 +0200 Subject: [PATCH 02/17] expose group membership isMember via the REST API --- src/client/client.go | 40 ++++++++++------- src/client/groups_test.go | 93 +++++++++++++++++++++++++++++++++++++++ src/docs/docs.go | 4 ++ src/docs/swagger.json | 4 ++ 4 files changed, 124 insertions(+), 17 deletions(-) create mode 100644 src/client/groups_test.go diff --git a/src/client/client.go b/src/client/client.go index 5dc5985..92008db 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -119,6 +119,7 @@ type GroupEntry struct { InternalId string `json:"internal_id"` Members []string `json:"members"` Blocked bool `json:"blocked"` + Member bool `json:"member"` PendingInvites []string `json:"pending_invites"` PendingRequests []string `json:"pending_requests"` InviteLink string `json:"invite_link"` @@ -143,6 +144,7 @@ type ExpandedGroupEntry struct { InternalId string `json:"internal_id"` Members []GroupMember `json:"members"` Blocked bool `json:"blocked"` + Member bool `json:"member"` PendingInvites []GroupMember `json:"pending_invites"` PendingRequests []GroupMember `json:"pending_requests"` InviteLink string `json:"invite_link"` @@ -1330,6 +1332,25 @@ func (s *SignalClient) RemoveAdminsFromGroup(number string, groupId string, admi return s.updateGroupAdmins(number, groupId, admins, false) } +func signalCliGroupEntryToExpandedGroupEntry(signalCliGroupEntry SignalCliGroupEntry) ExpandedGroupEntry { + var groupEntry ExpandedGroupEntry + groupEntry.InternalId = signalCliGroupEntry.Id + groupEntry.Name = signalCliGroupEntry.Name + groupEntry.Id = convertInternalGroupIdToGroupId(signalCliGroupEntry.Id) + groupEntry.Blocked = signalCliGroupEntry.IsBlocked + groupEntry.Member = signalCliGroupEntry.IsMember + groupEntry.Description = signalCliGroupEntry.Description + groupEntry.Permissions.SendMessages = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionSendMessage) + groupEntry.Permissions.EditGroup = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionSendMessage) + groupEntry.Permissions.AddMembers = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionAddMember) + groupEntry.Members = signalCliGroupEntry.Members + groupEntry.PendingInvites = signalCliGroupEntry.PendingMembers + groupEntry.PendingRequests = signalCliGroupEntry.RequestingMembers + groupEntry.Admins = signalCliGroupEntry.Admins + groupEntry.InviteLink = signalCliGroupEntry.GroupInviteLink + return groupEntry +} + func (s *SignalClient) GetGroupsExpanded(number string) ([]ExpandedGroupEntry, error) { groupEntries := []ExpandedGroupEntry{} @@ -1360,22 +1381,7 @@ func (s *SignalClient) GetGroupsExpanded(number string) ([]ExpandedGroupEntry, e } for _, signalCliGroupEntry := range signalCliGroupEntries { - var groupEntry ExpandedGroupEntry - groupEntry.InternalId = signalCliGroupEntry.Id - groupEntry.Name = signalCliGroupEntry.Name - groupEntry.Id = convertInternalGroupIdToGroupId(signalCliGroupEntry.Id) - groupEntry.Blocked = signalCliGroupEntry.IsBlocked - groupEntry.Description = signalCliGroupEntry.Description - groupEntry.Permissions.SendMessages = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionSendMessage) - groupEntry.Permissions.EditGroup = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionSendMessage) - groupEntry.Permissions.AddMembers = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionAddMember) - groupEntry.Members = signalCliGroupEntry.Members - groupEntry.PendingInvites = signalCliGroupEntry.PendingMembers - groupEntry.PendingRequests = signalCliGroupEntry.RequestingMembers - groupEntry.Admins = signalCliGroupEntry.Admins - groupEntry.InviteLink = signalCliGroupEntry.GroupInviteLink - - groupEntries = append(groupEntries, groupEntry) + groupEntries = append(groupEntries, signalCliGroupEntryToExpandedGroupEntry(signalCliGroupEntry)) } return groupEntries, nil @@ -1390,7 +1396,7 @@ func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) { groupEntries := []GroupEntry{} for _, expandedGroupEntry := range expandedGroupEntries { groupEntry := GroupEntry{InternalId: expandedGroupEntry.InternalId, Name: expandedGroupEntry.Name, - Id: expandedGroupEntry.Id, Blocked: expandedGroupEntry.Blocked, Description: expandedGroupEntry.Description, + Id: expandedGroupEntry.Id, Blocked: expandedGroupEntry.Blocked, Member: expandedGroupEntry.Member, Description: expandedGroupEntry.Description, Permissions: expandedGroupEntry.Permissions, InviteLink: expandedGroupEntry.InviteLink} members := []string{} diff --git a/src/client/groups_test.go b/src/client/groups_test.go new file mode 100644 index 0000000..af58e6d --- /dev/null +++ b/src/client/groups_test.go @@ -0,0 +1,93 @@ +package client + +import ( + "encoding/json" + "testing" +) + +// sampleListGroupsJSON mirrors the shape of signal-cli's `listGroups` JSON output +// (see signal-cli's ListGroupsCommand / the jsonrpc man page). It contains a group +// the account is still in (isMember=true), a group it has left or been removed from +// (isMember=false) — the "ghost" group that the REST API previously could not +// distinguish — and a blocked-but-still-member group to verify the two flags are +// mapped independently. +const sampleListGroupsJSON = `[ + { + "id": "Pmpi+EfPWmsxiomLe9Nx2XF9HOE483p6iKiFj65iMwI=", + "name": "Current Group", + "description": "still a member", + "isMember": true, + "isBlocked": false, + "members": [{"number": "+15551230001", "uuid": "11111111-1111-1111-1111-111111111111"}], + "pendingMembers": [], + "requestingMembers": [], + "admins": [{"number": "+15551230001", "uuid": "11111111-1111-1111-1111-111111111111"}], + "groupInviteLink": "", + "permissionAddMember": "EVERY_MEMBER", + "permissionSendMessage": "EVERY_MEMBER" + }, + { + "id": "Zm9vYmFyYmF6cXV4MTIzNDU2Nzg5MGFiY2RlZmdoaWo=", + "name": "Left Group", + "description": "removed or left", + "isMember": false, + "isBlocked": false, + "members": [], + "pendingMembers": [], + "requestingMembers": [], + "admins": [], + "groupInviteLink": "" + }, + { + "id": "YmxvY2tlZGdyb3VwaWQwMDAwMDAwMDAwMDAwMDAwMDA=", + "name": "Blocked But Member", + "description": "blocked yet still a member", + "isMember": true, + "isBlocked": true, + "members": [], + "pendingMembers": [], + "requestingMembers": [], + "admins": [], + "groupInviteLink": "" + } +]` + +// TestSignalCliGroupEntryToExpandedGroupEntry verifies that the signal-cli isMember +// flag is carried through to the REST ExpandedGroupEntry.Member field, independently +// of the isBlocked -> Blocked mapping. +func TestSignalCliGroupEntryToExpandedGroupEntry(t *testing.T) { + var entries []SignalCliGroupEntry + if err := json.Unmarshal([]byte(sampleListGroupsJSON), &entries); err != nil { + t.Fatalf("failed to unmarshal sample listGroups JSON: %v", err) + } + if len(entries) != 3 { + t.Fatalf("expected 3 group entries, got %d", len(entries)) + } + + cases := []struct { + name string + wantMember bool + wantBlocked bool + }{ + {"Current Group", true, false}, + {"Left Group", false, false}, + {"Blocked But Member", true, true}, + } + + for i, c := range cases { + got := signalCliGroupEntryToExpandedGroupEntry(entries[i]) + + if got.Name != c.name { + t.Errorf("entry %d: Name = %q, want %q", i, got.Name, c.name) + } + if got.Member != c.wantMember { + t.Errorf("%s: Member = %v, want %v (must reflect signal-cli isMember)", c.name, got.Member, c.wantMember) + } + if got.Blocked != c.wantBlocked { + t.Errorf("%s: Blocked = %v, want %v", c.name, got.Blocked, c.wantBlocked) + } + if got.InternalId != entries[i].Id { + t.Errorf("%s: InternalId = %q, want %q", c.name, got.InternalId, entries[i].Id) + } + } +} diff --git a/src/docs/docs.go b/src/docs/docs.go index 08b0e9e..7e3b62b 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -806,6 +806,9 @@ const docTemplate = `{ "invite_link": { "type": "string" }, + "member": { + "type": "boolean" + }, "members": { "items": { "type": "string" @@ -838,6 +841,7 @@ const docTemplate = `{ "id", "internal_id", "invite_link", + "member", "members", "name", "pending_invites", diff --git a/src/docs/swagger.json b/src/docs/swagger.json index fd913c7..21ffe3d 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -801,6 +801,9 @@ "invite_link": { "type": "string" }, + "member": { + "type": "boolean" + }, "members": { "items": { "type": "string" @@ -833,6 +836,7 @@ "id", "internal_id", "invite_link", + "member", "members", "name", "pending_invites", From e34cd5af876b4cfbe4c68581fa7e613455a67643 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 06:13:13 +0000 Subject: [PATCH 03/17] Bump golang.org/x/net from 0.47.0 to 0.55.0 in /src Bumps [golang.org/x/net](https://github.com/golang/net) from 0.47.0 to 0.55.0. - [Commits](https://github.com/golang/net/compare/v0.47.0...v0.55.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-version: 0.55.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src/go.mod | 12 ++++++------ src/go.sum | 32 ++++++++++++++++---------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/go.mod b/src/go.mod index 9f5a509..9dab7c4 100644 --- a/src/go.mod +++ b/src/go.mod @@ -1,6 +1,6 @@ module github.com/bbernhard/signal-cli-rest-api -go 1.24.0 +go 1.25.0 require ( github.com/bbernhard/gluasql v0.2.0 @@ -57,11 +57,11 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.14.0 // indirect - golang.org/x/crypto v0.45.0 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/text v0.31.0 // indirect - golang.org/x/tools v0.38.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/net v0.55.0 // indirect + golang.org/x/sys v0.45.0 // indirect + golang.org/x/text v0.37.0 // indirect + golang.org/x/tools v0.44.0 // indirect google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/src/go.sum b/src/go.sum index 4e60dac..7ed892b 100644 --- a/src/go.sum +++ b/src/go.sum @@ -170,21 +170,21 @@ golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +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/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -194,10 +194,10 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= -golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= +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/telemetry v0.0.0-20260409153401-be6f6cb8b1fa h1:efT73AJZfAAUV7SOip6pWGkwJDzIGiKBZGVzHYa+ve4= +golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa/go.mod h1:kHjTxDEnAu6/Nl9lDkzjWpR+bmKfxeiRuSDlsMb70gE= 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= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -205,13 +205,13 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2 h1:pl8qT5D+48655f14yDURpIZwSPvMWuuekfAP+gxtjvk= google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= From 2ee3907d9ec779d9e6791ab9e4a6f2b8846a6b84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 21:35:10 +0000 Subject: [PATCH 04/17] Bump golang.org/x/crypto from 0.51.0 to 0.52.0 in /src Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.51.0 to 0.52.0. - [Commits](https://github.com/golang/crypto/compare/v0.51.0...v0.52.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.52.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src/go.mod | 2 +- src/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/go.mod b/src/go.mod index 9dab7c4..2573564 100644 --- a/src/go.mod +++ b/src/go.mod @@ -57,7 +57,7 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.14.0 // indirect - golang.org/x/crypto v0.51.0 // indirect + golang.org/x/crypto v0.52.0 // indirect golang.org/x/net v0.55.0 // indirect golang.org/x/sys v0.45.0 // indirect golang.org/x/text v0.37.0 // indirect diff --git a/src/go.sum b/src/go.sum index 7ed892b..55bd023 100644 --- a/src/go.sum +++ b/src/go.sum @@ -170,8 +170,8 @@ golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= -golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= From b13a74f43e6b349ed2512106fa6c762a8c662079 Mon Sep 17 00:00:00 2001 From: Gara Dorta <1507774+Gara-Dorta@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:08:28 +0200 Subject: [PATCH 05/17] feat: download the json schemas from the signal-cli releases --- Dockerfile | 23 ++++++----------------- src/docs/README.md | 2 +- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index 539f4e0..77d8b20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN dpkg-reconfigure debconf --frontend=noninteractive \ && apt-get update \ && apt-get -y install --no-install-recommends \ wget git locales zip unzip \ - file build-essential libz-dev zlib1g-dev binutils openjdk-25-jdk \ + file build-essential libz-dev zlib1g-dev binutils \ && rm -rf /var/lib/apt/lists/* #COPY ext/libraries/libsignal-client/v${LIBSIGNAL_CLIENT_VERSION} /tmp/libsignal-client-libraries @@ -40,15 +40,6 @@ ENV JAVA_OPTS="-Djdk.lang.Process.launchMechanism=vfork" ENV LANG en_US.UTF-8 -# building the jsonSchemas for armv7l unfortunately doesn't work, so as a temporary fix, do not build the json schema -# for armv7. should be removed as soon as https://github.com/AsamK/signal-cli/pull/2040 is merged -RUN if [ "$(uname -m)" != "armv7l" ]; then \ - cd /tmp \ - && git clone https://github.com/AsamK/signal-cli.git --branch v${SIGNAL_CLI_VERSION} --single-branch signal-cli-source \ - && cd signal-cli-source \ - && ./gradlew jsonSchemas; \ -fi; - RUN go install github.com/swaggo/swag/cmd/swag@v${SWAG_VERSION} RUN cd /tmp/ \ @@ -112,13 +103,11 @@ RUN cd /tmp/signal-cli-rest-api-src && ${GOPATH}/bin/swag init --requiredByDefau # manually add the json schemas for the receive V1 endpoint to the docs -# (building the jsonSchemas for armv7l unfortunately doesn't work, so as a temporary fix, do not build the json schema -# for armv7. should be removed as soon as https://github.com/AsamK/signal-cli/pull/2040 is merged) -RUN if [ "$(uname -m)" != "armv7l" ]; then \ - cd /tmp/signal-cli-rest-api-src/docs \ - && cp -r /tmp/signal-cli-source/build/generated/META-INF/schemas signal-cli-schemas \ - && go run add_v1_receive_schemas.go signal-cli-schemas; \ - fi; +RUN cd /tmp/signal-cli-rest-api-src/docs \ + && wget https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-json-schemas.tar.gz \ + && mkdir signal-cli-schemas \ + && tar xf signal-cli-${SIGNAL_CLI_VERSION}-json-schemas.tar.gz -C signal-cli-schemas \ + && go run add_v1_receive_schemas.go signal-cli-schemas # build signal-cli-rest-api RUN cd /tmp/signal-cli-rest-api-src && go build -o signal-cli-rest-api main.go diff --git a/src/docs/README.md b/src/docs/README.md index 5b162a4..aab599b 100644 --- a/src/docs/README.md +++ b/src/docs/README.md @@ -45,7 +45,7 @@ Install [go](https://go.dev/). cd docs ``` 1. Add the signal-cli receive V1 schemas - * Download the `signal-cli-x.y.z-json-schemas.tar.gz` schema files from https://github.com/Gara-Dorta/signal-cli/releases + * Download the `signal-cli-x.y.z-json-schemas.tar.gz` schema files from https://github.com/AsamK/signal-cli/releases * Extract the files * Run the script to add the schemas ```bash From 2d03a6c0ce7e1b96d2003b8a7dab0bbee710a0d4 Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Sat, 18 Jul 2026 12:53:53 +0200 Subject: [PATCH 06/17] added debug output to deploy-pages.yml --- .github/workflows/deploy-pages.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index e4fd14a..21eaaac 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -27,6 +27,14 @@ jobs: - name: Build static documentation bundle run: src/docs/build-static-bundle.sh site "${{ github.event.release.tag_name }}" + - name: Debug site + run: | + echo "PWD: $(pwd)" + ls -la + ls -la site + du -sh site + find site -type f -exec ls -lh {} \; + - name: Upload Pages artifact uses: actions/upload-pages-artifact@v5 with: From bef11316e330835d2a1478d82a8be1d4e6b6050f Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Sat, 18 Jul 2026 13:03:20 +0200 Subject: [PATCH 07/17] dummy change to test github workflow --- .github/workflows/deploy-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index 21eaaac..97c56fd 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -33,7 +33,7 @@ jobs: ls -la ls -la site du -sh site - find site -type f -exec ls -lh {} \; + find site -type f -exec ls -lh {} \; - name: Upload Pages artifact uses: actions/upload-pages-artifact@v5 From 7c12204889285f9753c464731c816d700c72e72e Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Sat, 18 Jul 2026 13:05:41 +0200 Subject: [PATCH 08/17] execute deploy-pages workflow for every commit --- .github/workflows/deploy-pages.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index 97c56fd..df299ee 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -1,9 +1,7 @@ name: Deploy API Docs to GitHub Pages on: - release: - types: - - published + push: permissions: contents: read From 7138ffde7c80d16a890b9cd1c023a3a6819e4f25 Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Sat, 18 Jul 2026 13:09:22 +0200 Subject: [PATCH 09/17] fixed version in deploy-pages.yml --- .github/workflows/deploy-pages.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index df299ee..e53c257 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -23,7 +23,9 @@ jobs: uses: actions/configure-pages@v6 - name: Build static documentation bundle - run: src/docs/build-static-bundle.sh site "${{ github.event.release.tag_name }}" + run: | + VERSION=$(git describe --tags --always) + src/docs/build-static-bundle.sh site "$VERSION" - name: Debug site run: | From 0e36e15f606f1f3b38ddb87d7c223309844cfa8f Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Sat, 18 Jul 2026 22:21:40 +0200 Subject: [PATCH 10/17] remove debug logging --- .github/workflows/deploy-pages.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index e53c257..686dc20 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -27,14 +27,6 @@ jobs: VERSION=$(git describe --tags --always) src/docs/build-static-bundle.sh site "$VERSION" - - name: Debug site - run: | - echo "PWD: $(pwd)" - ls -la - ls -la site - du -sh site - find site -type f -exec ls -lh {} \; - - name: Upload Pages artifact uses: actions/upload-pages-artifact@v5 with: From 6a225e62c15f5274e24158b779769b8470374cd7 Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Thu, 23 Jul 2026 22:47:13 +0200 Subject: [PATCH 11/17] fixed bug in send endpoint * in case a message is sent to either multiple recipients or a group, it is always possible that the message couldn't be sent to some recipients (e.g because of an untrusted identity). This is now reflected in the API by returning an additional `errors` object in that case. --- src/api/api.go | 13 ++---- src/client/client.go | 83 ++++++++++++++++++++-------------- src/datastructs/datastructs.go | 16 +++++++ src/go.mod | 1 + src/go.sum | 5 ++ 5 files changed, 75 insertions(+), 43 deletions(-) diff --git a/src/api/api.go b/src/api/api.go index 3ec81a2..210660b 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -173,10 +173,6 @@ type TrustIdentityRequest struct { TrustAllKnownKeys *bool `json:"trust_all_known_keys,omitempty" example:"false"` } -type SendMessageResponse struct { - Timestamp string `json:"timestamp"` -} - type RemoteDeleteResponse struct { Timestamp string `json:"timestamp"` } @@ -476,7 +472,6 @@ func (a *Api) VerifyRegisteredNumber(c *gin.Context) { // @Router /v1/send [post] // @Deprecated func (a *Api) Send(c *gin.Context) { - var req SendMessageV1 err := c.BindJSON(&req) if err != nil { @@ -489,12 +484,12 @@ func (a *Api) Send(c *gin.Context) { base64Attachments = append(base64Attachments, req.Base64Attachment) } - timestamp, err := a.signalClient.SendV1(req.Number, req.Message, req.Recipients, base64Attachments, req.IsGroup) + resp, err := a.signalClient.SendV1(req.Number, req.Message, req.Recipients, base64Attachments, req.IsGroup) if err != nil { c.JSON(400, Error{Msg: err.Error()}) return } - c.JSON(201, SendMessageResponse{Timestamp: strconv.FormatInt(timestamp.Timestamp, 10)}) + c.JSON(201, resp) } // @Summary Send a signal message. @@ -502,7 +497,7 @@ func (a *Api) Send(c *gin.Context) { // @Description Send a signal message. Set the text_mode to 'styled' in case you want to add formatting to your text message. Styling Options: \*italic text\*, \*\*bold text\*\*, ~strikethrough text~, ||spoiler||, \`monospace\`. If you want to escape a formatting character, prefix it with two backslashes. // @Accept json // @Produce json -// @Success 201 {object} SendMessageResponse +// @Success 201 {object} ds.SendMessageResponse // @Failure 400 {object} SendMessageError // @Param data body SendMessageV2 true "Input Data" // @Router /v2/send [post] @@ -574,7 +569,7 @@ func (a *Api) SendV2(c *gin.Context) { return } - c.JSON(201, SendMessageResponse{Timestamp: strconv.FormatInt((*data)[0].Timestamp, 10)}) + c.JSON(201, data) } func (a *Api) handleSignalReceive(ws *websocket.Conn, number string, stop chan struct{}) { diff --git a/src/client/client.go b/src/client/client.go index 92008db..18d9049 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -479,8 +479,8 @@ func validateLinkPreview(message string, linkPreview *ds.LinkPreviewType) error return nil } -func (s *SignalClient) send(signalCliSendRequest ds.SignalCliSendRequest) (*SendResponse, error) { - var resp SendResponse +func (s *SignalClient) send(signalCliSendRequest ds.SignalCliSendRequest) (*ds.SendMessageResponse, error) { + var rawData string var linkPreviewAttachmentEntry *AttachmentEntry = nil if len(signalCliSendRequest.Recipients) == 0 { @@ -615,23 +615,13 @@ func (s *SignalClient) send(signalCliSendRequest ds.SignalCliSendRequest) (*Send } } - rawData, err := jsonRpc2Client.getRaw("send", &signalCliSendRequest.Number, request) + rawData, err = jsonRpc2Client.getRaw("send", &signalCliSendRequest.Number, request) if err != nil { cleanupAttachmentEntries(attachmentEntries, linkPreviewAttachmentEntry) return nil, err } - - err = json.Unmarshal([]byte(rawData), &resp) - if err != nil { - cleanupAttachmentEntries(attachmentEntries, linkPreviewAttachmentEntry) - - if strings.Contains(err.Error(), signalCliV2GroupError) { - return nil, errors.New("Cannot send message to group - please first update your profile.") - } - return nil, err - } } else { - cmd := []string{"--config", s.signalCliConfig, "-a", signalCliSendRequest.Number, "send", "--message-from-stdin"} + cmd := []string{"--output", "json", "--config", s.signalCliConfig, "-a", signalCliSendRequest.Number, "send", "--message-from-stdin"} if signalCliSendRequest.RecipientType == ds.Number { cmd = append(cmd, signalCliSendRequest.Recipients...) } else if signalCliSendRequest.RecipientType == ds.Group { @@ -719,23 +709,48 @@ func (s *SignalClient) send(signalCliSendRequest ds.SignalCliSendRequest) (*Send cmd = append(cmd, "--view-once") } - rawData, err := s.cliClient.Execute(true, cmd, signalCliSendRequest.Message) + rawData, err = s.cliClient.Execute(true, cmd, signalCliSendRequest.Message) if err != nil { cleanupAttachmentEntries(attachmentEntries, linkPreviewAttachmentEntry) - if strings.Contains(err.Error(), signalCliV2GroupError) { - return nil, errors.New("Cannot send message to group - please first update your profile.") - } return nil, err } - resp.Timestamp, err = strconv.ParseInt(strings.TrimSuffix(rawData, "\n"), 10, 64) - if err != nil { - cleanupAttachmentEntries(attachmentEntries, linkPreviewAttachmentEntry) - return nil, errors.New(strings.Replace(rawData, "\n", "", -1)) //in case we can't parse the timestamp, it means signal-cli threw an error. So instead of returning the parsing error, return the actual error from signal-cli + } + + type SignalCliSendResponse struct { + Timestamp int64 `json:"timestamp"` + Results []struct { + RecipientAddress struct { + Uuid string `json:"uuid"` + Number string `json:"number"` + Username string `json:"username"` + } `json:"recipientAddress"` + Type string `json:"type"` + } `json:"results"` + } + + var signalCliSendResponse SignalCliSendResponse + err = json.Unmarshal([]byte(rawData), &signalCliSendResponse) + if err != nil { + cleanupAttachmentEntries(attachmentEntries, linkPreviewAttachmentEntry) + + if strings.Contains(err.Error(), signalCliV2GroupError) { + return nil, errors.New("Cannot send message to group - please first update your profile.") } + return nil, err } cleanupAttachmentEntries(attachmentEntries, linkPreviewAttachmentEntry) + resp := ds.SendMessageResponse{Timestamp: strconv.FormatInt(signalCliSendResponse.Timestamp, 10)} + for _, entry := range signalCliSendResponse.Results { + if entry.Type != "SUCCESS" { + if resp.Errors == nil { + resp.Errors = &ds.SendMessageErrors{} + } + sendMessageError := ds.SendMessageError{Uuid: entry.RecipientAddress.Uuid, Number: entry.RecipientAddress.Number, Username: entry.RecipientAddress.Username, Reason: entry.Type} + resp.Errors.Recipients = append(resp.Errors.Recipients, sendMessageError) + } + } return &resp, nil } @@ -901,7 +916,7 @@ func (s *SignalClient) VerifyRegisteredNumber(number string, token string, pin s } } -func (s *SignalClient) SendV1(number string, message string, recipients []string, base64Attachments []string, isGroup bool) (*SendResponse, error) { +func (s *SignalClient) SendV1(number string, message string, recipients []string, base64Attachments []string, isGroup bool) (*ds.SendMessageResponse, error) { recipientType := ds.Number if isGroup { recipientType = ds.Group @@ -910,8 +925,8 @@ func (s *SignalClient) SendV1(number string, message string, recipients []string signalCliSendRequest := ds.SignalCliSendRequest{Number: number, Message: message, Recipients: recipients, Base64Attachments: base64Attachments, RecipientType: recipientType, Sticker: "", Mentions: nil, QuoteTimestamp: nil, QuoteAuthor: nil, QuoteMessage: nil, QuoteMentions: nil, TextMode: nil, EditTimestamp: nil, LinkPreview: nil} - timestamp, err := s.send(signalCliSendRequest) - return timestamp, err + resp, err := s.send(signalCliSendRequest) + return resp, err } func (s *SignalClient) getJsonRpc2Client() (*JsonRpc2Client, error) { @@ -931,7 +946,7 @@ func (s *SignalClient) getJsonRpc2Clients() []*JsonRpc2Client { func (s *SignalClient) SendV2(number string, message string, recps []string, base64Attachments []string, sticker string, mentions []ds.MessageMention, quoteTimestamp *int64, quoteAuthor *string, quoteMessage *string, quoteMentions []ds.MessageMention, textMode *string, editTimestamp *int64, notifySelf *bool, - linkPreview *ds.LinkPreviewType, viewOnce *bool) (*[]SendResponse, error) { + linkPreview *ds.LinkPreviewType, viewOnce *bool) (*[]ds.SendMessageResponse, error) { if len(recps) == 0 { return nil, errors.New("Please provide at least one recipient") } @@ -977,17 +992,17 @@ func (s *SignalClient) SendV2(number string, message string, recps []string, bas return nil, errors.New("A signal message cannot be sent to more than one group at once! Please use multiple REST API calls for that.") } - timestamps := []SendResponse{} + responses := []ds.SendMessageResponse{} for _, group := range groups { signalCliSendRequest := ds.SignalCliSendRequest{Number: number, Message: message, Recipients: []string{group}, Base64Attachments: base64Attachments, RecipientType: ds.Group, Sticker: sticker, Mentions: mentions, QuoteTimestamp: quoteTimestamp, QuoteAuthor: quoteAuthor, QuoteMessage: quoteMessage, QuoteMentions: quoteMentions, TextMode: textMode, EditTimestamp: editTimestamp, NotifySelf: notifySelf, LinkPreview: linkPreview, ViewOnce: viewOnce} - timestamp, err := s.send(signalCliSendRequest) + resp, err := s.send(signalCliSendRequest) if err != nil { return nil, err } - timestamps = append(timestamps, *timestamp) + responses = append(responses, *resp) } if len(numbers) > 0 { @@ -995,11 +1010,11 @@ func (s *SignalClient) SendV2(number string, message string, recps []string, bas RecipientType: ds.Number, Sticker: sticker, Mentions: mentions, QuoteTimestamp: quoteTimestamp, QuoteAuthor: quoteAuthor, QuoteMessage: quoteMessage, QuoteMentions: quoteMentions, TextMode: textMode, EditTimestamp: editTimestamp, NotifySelf: notifySelf, LinkPreview: linkPreview, ViewOnce: viewOnce} - timestamp, err := s.send(signalCliSendRequest) + resp, err := s.send(signalCliSendRequest) if err != nil { return nil, err } - timestamps = append(timestamps, *timestamp) + responses = append(responses, *resp) } if len(usernames) > 0 { @@ -1007,14 +1022,14 @@ func (s *SignalClient) SendV2(number string, message string, recps []string, bas RecipientType: ds.Username, Sticker: sticker, Mentions: mentions, QuoteTimestamp: quoteTimestamp, QuoteAuthor: quoteAuthor, QuoteMessage: quoteMessage, QuoteMentions: quoteMentions, TextMode: textMode, EditTimestamp: editTimestamp, NotifySelf: notifySelf, LinkPreview: linkPreview, ViewOnce: viewOnce} - timestamp, err := s.send(signalCliSendRequest) + resp, err := s.send(signalCliSendRequest) if err != nil { return nil, err } - timestamps = append(timestamps, *timestamp) + responses = append(responses, *resp) } - return ×tamps, nil + return &responses, nil } func (s *SignalClient) Receive(number string, timeout int64, ignoreAttachments bool, ignoreStories bool, ignoreAvatars bool, ignoreStickers bool, maxMessages int64, sendReadReceipts bool) (string, error) { diff --git a/src/datastructs/datastructs.go b/src/datastructs/datastructs.go index 4046111..9be8f47 100644 --- a/src/datastructs/datastructs.go +++ b/src/datastructs/datastructs.go @@ -58,3 +58,19 @@ type GroupPermissions struct { EditGroup string `json:"edit_group" enums:"only-admins,every-member"` SendMessages string `json:"send_messages" enums:"only-admins,every-member"` } + +type SendMessageError struct { + Username string `json:"username,omitempty"` + Number string `json:"number,omitempty"` + Uuid string `json:"uuid,omitempty"` + Reason string `json:"reason,omitempty"` +} + +type SendMessageErrors struct { + Recipients []SendMessageError `json:"recipients,omitempty"` +} + +type SendMessageResponse struct { + Timestamp string `json:"timestamp"` + Errors *SendMessageErrors `json:"errors,omitempty"` +} diff --git a/src/go.mod b/src/go.mod index 2573564..ac90042 100644 --- a/src/go.mod +++ b/src/go.mod @@ -9,6 +9,7 @@ require ( github.com/gabriel-vasile/mimetype v1.4.8 github.com/gin-gonic/gin v1.10.0 github.com/gofrs/uuid v4.4.0+incompatible + github.com/golang/protobuf v1.5.2 github.com/gorilla/websocket v1.5.0 github.com/h2non/filetype v1.1.3 github.com/robfig/cron/v3 v3.0.1 diff --git a/src/go.sum b/src/go.sum index 55bd023..3dcd083 100644 --- a/src/go.sum +++ b/src/go.sum @@ -62,10 +62,12 @@ github.com/gocraft/dbr/v2 v2.7.2 h1:ccUxMuz6RdZvD7VPhMRRMSS/ECF3gytPhPtcavjktHk= github.com/gocraft/dbr/v2 v2.7.2/go.mod h1:5bCqyIXO5fYn3jEp/L06QF4K1siFdhxChMjdNu6YJrg= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/flatbuffers v2.0.6+incompatible h1:XHFReMv7nFFusa+CEokzWbzaYocKXI6C7hdU5Kgh9Lw= github.com/google/flatbuffers v2.0.6+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -213,10 +215,13 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2 h1:pl8qT5D+48655f14yDURpIZwSPvMWuuekfAP+gxtjvk= google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 54507eba20904238dd4db8056b4529bd3199dbd2 Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Thu, 23 Jul 2026 22:51:35 +0200 Subject: [PATCH 12/17] handle status code -4 in the `getRaw` method of the JsonRpc2Client --- src/client/jsonrpc2.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client/jsonrpc2.go b/src/client/jsonrpc2.go index ef00633..94307cd 100644 --- a/src/client/jsonrpc2.go +++ b/src/client/jsonrpc2.go @@ -186,6 +186,8 @@ func (r *JsonRpc2Client) getRaw(command string, account *string, args interface{ ChallengeTokens: challengeTokens, Err: errors.New(resp.Err.Message), } + } else if resp.Err.Code == -4 { + return "", errors.New("Unable to complete request due to untrusted recipient keys") } return "", errors.New(resp.Err.Message) } From 1a2da6c79b6dce68317a714d3f4015d18e30dcad Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Sat, 1 Aug 2026 15:06:43 +0200 Subject: [PATCH 13/17] updated signal-cli to v0.14.7 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 77d8b20..9d38bf1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -ARG SIGNAL_CLI_VERSION=0.14.5 -ARG LIBSIGNAL_CLIENT_VERSION=0.94.4 +ARG SIGNAL_CLI_VERSION=0.14.7 +ARG LIBSIGNAL_CLIENT_VERSION=0.99.1 ARG SWAG_VERSION=1.16.4 From 5cc379fde09edf0753be8d8a871ca5a3003913f7 Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Sun, 9 Aug 2026 21:39:35 +0200 Subject: [PATCH 14/17] only (re-)build github pages documentation when a new release is published see #872 --- .github/workflows/deploy-pages.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index 686dc20..829cb2d 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -1,7 +1,9 @@ name: Deploy API Docs to GitHub Pages on: - push: + release: + types: + - published permissions: contents: read @@ -24,8 +26,7 @@ jobs: - name: Build static documentation bundle run: | - VERSION=$(git describe --tags --always) - src/docs/build-static-bundle.sh site "$VERSION" + src/docs/build-static-bundle.sh site "${{ github.event.release.tag_name }}" - name: Upload Pages artifact uses: actions/upload-pages-artifact@v5 From a08db23a31b5c2fb6535ebe0977a7420848019b8 Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Sun, 16 Aug 2026 22:51:31 +0200 Subject: [PATCH 15/17] fixed bug in textstyleparser * the textstyleparser now properly handles `***` and marks the text as bold and italic. see #879 --- src/utils/textstyleparser.go | 35 ++++++++++++++++++++++++------- src/utils/textstyleparser_test.go | 8 ++++++- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/utils/textstyleparser.go b/src/utils/textstyleparser.go index 9b267c9..f8b4beb 100644 --- a/src/utils/textstyleparser.go +++ b/src/utils/textstyleparser.go @@ -23,6 +23,7 @@ const ( MonoSpaceBegin = 6 StrikethroughBegin = 8 SpoilerBegin = 9 + BoldItalicBegin = 10 ) const EscapeCharacter rune = '\\' @@ -119,7 +120,14 @@ func (l *TextstyleParser) handleToken(tokenType int, signalCliStylingType string } else { if l.tokens.Peek().Token == tokenType { tokenBeginState := l.tokens.Pop() - l.signalCliFormatStrings = append(l.signalCliFormatStrings, strconv.Itoa(tokenBeginState.BeginPos)+":"+strconv.Itoa(getUtf16StringLength(l.fullString)-tokenBeginState.BeginPos)+":"+signalCliStylingType) + length := getUtf16StringLength(l.fullString) - tokenBeginState.BeginPos + + if tokenType == BoldItalicBegin { + l.signalCliFormatStrings = append(l.signalCliFormatStrings, strconv.Itoa(tokenBeginState.BeginPos)+":"+strconv.Itoa(length)+":"+Bold) + l.signalCliFormatStrings = append(l.signalCliFormatStrings, strconv.Itoa(tokenBeginState.BeginPos)+":"+strconv.Itoa(length)+":"+Italic) + } else { + l.signalCliFormatStrings = append(l.signalCliFormatStrings, strconv.Itoa(tokenBeginState.BeginPos)+":"+strconv.Itoa(length)+":"+signalCliStylingType) + } } else { l.tokens.Push(TokenState{BeginPos: getUtf16StringLength(l.fullString), Token: tokenType}) } @@ -137,14 +145,27 @@ func (l *TextstyleParser) Parse() (string, []string) { nextRune := l.peek() if c == '*' { - if nextRune == '*' { //Bold + if nextRune == '*' { l.next() - if prevChar == EscapeCharacter { - prevChar = c - l.fullString += "**" - continue + + if l.peek() == '*' { // Check for *** before treating it as ** + l.next() + + if prevChar == EscapeCharacter { + prevChar = c + l.fullString += "***" + continue + } + + l.handleToken(BoldItalicBegin, "BOLD_ITALIC") + } else { + if prevChar == EscapeCharacter { + prevChar = c + l.fullString += "**" + continue + } + l.handleToken(BoldBegin, Bold) } - l.handleToken(BoldBegin, Bold) } else { //Italic if prevChar == EscapeCharacter { prevChar = c diff --git a/src/utils/textstyleparser_test.go b/src/utils/textstyleparser_test.go index 480a1fd..0ad3237 100644 --- a/src/utils/textstyleparser_test.go +++ b/src/utils/textstyleparser_test.go @@ -155,5 +155,11 @@ func TestEscapeNew(t *testing.T) { message, signalCliFormatStrings := textstyleParser.Parse() expectMessageEqual(t, message, "Test ** * ~ Escape") expectFormatStringsEqual(t, signalCliFormatStrings, []string{}) - +} + +func TestBoldItalic(t *testing.T) { + textstyleParser := NewTextstyleParser("***Bold Italic Text***") + message, signalCliFormatStrings := textstyleParser.Parse() + expectMessageEqual(t, message, "Bold Italic Text") + expectFormatStringsEqual(t, signalCliFormatStrings, []string{"0:16:BOLD", "0:16:ITALIC"}) } From 1491a52285260e2b9fd0f64b6c770a814b88407b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 21:37:32 +0000 Subject: [PATCH 16/17] Bump github.com/gorilla/websocket from 1.5.0 to 1.5.3 in /src Bumps [github.com/gorilla/websocket](https://github.com/gorilla/websocket) from 1.5.0 to 1.5.3. - [Release notes](https://github.com/gorilla/websocket/releases) - [Commits](https://github.com/gorilla/websocket/compare/v1.5.0...v1.5.3) --- updated-dependencies: - dependency-name: github.com/gorilla/websocket dependency-version: 1.5.3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/go.mod | 3 +-- src/go.sum | 9 ++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/go.mod b/src/go.mod index ac90042..f8cd317 100644 --- a/src/go.mod +++ b/src/go.mod @@ -9,8 +9,7 @@ require ( github.com/gabriel-vasile/mimetype v1.4.8 github.com/gin-gonic/gin v1.10.0 github.com/gofrs/uuid v4.4.0+incompatible - github.com/golang/protobuf v1.5.2 - github.com/gorilla/websocket v1.5.0 + github.com/gorilla/websocket v1.5.3 github.com/h2non/filetype v1.1.3 github.com/robfig/cron/v3 v3.0.1 github.com/sirupsen/logrus v1.9.1 diff --git a/src/go.sum b/src/go.sum index 3dcd083..25ca308 100644 --- a/src/go.sum +++ b/src/go.sum @@ -62,19 +62,17 @@ github.com/gocraft/dbr/v2 v2.7.2 h1:ccUxMuz6RdZvD7VPhMRRMSS/ECF3gytPhPtcavjktHk= github.com/gocraft/dbr/v2 v2.7.2/go.mod h1:5bCqyIXO5fYn3jEp/L06QF4K1siFdhxChMjdNu6YJrg= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/flatbuffers v2.0.6+incompatible h1:XHFReMv7nFFusa+CEokzWbzaYocKXI6C7hdU5Kgh9Lw= github.com/google/flatbuffers v2.0.6+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= @@ -215,13 +213,10 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2 h1:pl8qT5D+48655f14yDURpIZwSPvMWuuekfAP+gxtjvk= google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From d4ab41ad2b7246215c0d432304732d8b2c1de4af Mon Sep 17 00:00:00 2001 From: Bernhard B Date: Thu, 3 Sep 2026 20:05:06 +0200 Subject: [PATCH 17/17] updated golang.org/x/crypto to v0.55.0 see #883 --- src/go.mod | 10 +++++----- src/go.sum | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/go.mod b/src/go.mod index f8cd317..3c9633f 100644 --- a/src/go.mod +++ b/src/go.mod @@ -57,11 +57,11 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.14.0 // indirect - golang.org/x/crypto v0.52.0 // indirect - golang.org/x/net v0.55.0 // indirect - golang.org/x/sys v0.45.0 // indirect - golang.org/x/text v0.37.0 // indirect - golang.org/x/tools v0.44.0 // indirect + golang.org/x/crypto v0.55.0 // indirect + golang.org/x/net v0.57.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.41.0 // indirect + golang.org/x/tools v0.48.0 // indirect google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/src/go.sum b/src/go.sum index 25ca308..2b95b00 100644 --- a/src/go.sum +++ b/src/go.sum @@ -172,19 +172,25 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= +golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 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.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= +golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -196,8 +202,11 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa h1:efT73AJZfAAUV7SOip6pWGkwJDzIGiKBZGVzHYa+ve4= golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa/go.mod h1:kHjTxDEnAu6/Nl9lDkzjWpR+bmKfxeiRuSDlsMb70gE= +golang.org/x/telemetry v0.0.0-20260708182218-49f421fb7959 h1:RJhm5l6Fo4rmEIcndxDllNhhf/fAx8qIm4t6A7vpm2A= 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= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -207,11 +216,15 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 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.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE= +golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2 h1:pl8qT5D+48655f14yDURpIZwSPvMWuuekfAP+gxtjvk= google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=