diff --git a/.gitignore b/.gitignore index 03ad15e9..0b52a157 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ coverage.* .idea/ .vscode/ .DS_Store +.superpowers/ diff --git a/cmd/evolution-go/main.go b/cmd/evolution-go/main.go index 5234583f..9b27f475 100644 --- a/cmd/evolution-go/main.go +++ b/cmd/evolution-go/main.go @@ -22,7 +22,9 @@ import ( _ "modernc.org/sqlite" call_handler "github.com/evolution-foundation/evolution-go/pkg/call/handler" + call_registry "github.com/evolution-foundation/evolution-go/pkg/call/registry" call_service "github.com/evolution-foundation/evolution-go/pkg/call/service" + call_stream "github.com/evolution-foundation/evolution-go/pkg/call/stream" chat_handler "github.com/evolution-foundation/evolution-go/pkg/chat/handler" chat_service "github.com/evolution-foundation/evolution-go/pkg/chat/service" community_handler "github.com/evolution-foundation/evolution-go/pkg/community/handler" @@ -85,6 +87,7 @@ func init() { func setupRouter(db *gorm.DB, authDB *sql.DB, sqliteDB *sql.DB, config *config.Config, conn *amqp.Connection, exPath string, runtimeCtx *core.RuntimeContext) *gin.Engine { killChannel := make(map[string](chan bool)) clientPointer := make(map[string]*whatsmeow.Client) + callRegistry := call_registry.NewCallRegistry() loggerWrapper := logger_wrapper.NewLoggerManager(config) @@ -177,6 +180,7 @@ func setupRouter(db *gorm.DB, authDB *sql.DB, sqliteDB *sql.DB, config *config.C exPath, mediaStorage, natsProducer, + callRegistry, loggerWrapper, ) instanceService := instance_service.NewInstanceService( @@ -192,7 +196,7 @@ func setupRouter(db *gorm.DB, authDB *sql.DB, sqliteDB *sql.DB, config *config.C messageService := message_service.NewMessageService(clientPointer, messageRepository, whatsmeowService, loggerWrapper) chatService := chat_service.NewChatService(clientPointer, whatsmeowService, loggerWrapper) groupService := group_service.NewGroupService(clientPointer, whatsmeowService, loggerWrapper) - callService := call_service.NewCallService(clientPointer, whatsmeowService, loggerWrapper) + callService := call_service.NewCallService(clientPointer, whatsmeowService, callRegistry, loggerWrapper) communityService := community_service.NewCommunityService(clientPointer, whatsmeowService, loggerWrapper) labelService := label_service.NewLabelService(clientPointer, whatsmeowService, labelRepository, loggerWrapper) newsletterService := newsletter_service.NewNewsletterService(clientPointer, whatsmeowService, loggerWrapper) @@ -224,6 +228,7 @@ func setupRouter(db *gorm.DB, authDB *sql.DB, sqliteDB *sql.DB, config *config.C // Passkey ceremony routes — PUBLIC (called by the browser extension from the // web.whatsapp.com origin, gated only by an opaque ephemeral token). passkey_handler.RegisterRoutes(r, whatsmeowService) + call_stream.RegisterRoutes(r, callService, instanceService) routes.NewRouter( auth_middleware.NewMiddleware(config, instanceService), diff --git a/docs/docs.go b/docs/docs.go index 094912c0..1ca78fb8 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -15,6 +15,246 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/call/answer": { + "post": { + "description": "Answer an incoming call and (if it's a video call) accept its video", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Answer call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.AnswerCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/dial": { + "post": { + "description": "Spike/experimental: places an outbound call, not part of the reviewed answer-call plan", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Place an outbound call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.DialCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/handraise": { + "post": { + "description": "Spike/experimental: toggles this client's hand-raised state", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Raise or lower hand in a call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.HandRaiseStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/hangup": { + "post": { + "description": "Hangup an active call", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Hangup call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.HangupCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/participant/add": { + "post": { + "description": "Spike/experimental: adds a participant, upgrading a 1:1 call into a group call", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Add a participant to an active call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.AddParticipantStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/react": { + "post": { + "description": "Spike/experimental: sends an emoji reaction into an active call", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Send a call reaction", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.ReactCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, "/call/reject": { "post": { "description": "Reject call", @@ -35,7 +275,167 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_call_service.RejectCallStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.RejectCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/screenshare": { + "post": { + "description": "Spike/experimental: toggles this client's screen share state", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Start or stop screen sharing in a call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.ScreenShareStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/video/enabled": { + "post": { + "description": "Spike/experimental: wraps Call.SetVideoEnabled", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Mute or unmute outbound video without renegotiating the upgrade", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoEnabledStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/video/orientation": { + "post": { + "description": "Spike/experimental: wraps Call.SetVideoOrientation (0-3 quarter turns clockwise)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Announce this client's camera orientation", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoOrientationStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/video/upgrade": { + "post": { + "description": "Spike/experimental: requests an audio\u003c-\u003evideo upgrade (Call.StartVideo/StopVideo)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Start or stop sending outbound video mid-call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoUpgradeStruct" } } ], @@ -75,7 +475,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -121,7 +521,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.HistorySyncRequestStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.HistorySyncRequestStruct" } } ], @@ -167,7 +567,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -213,7 +613,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -259,7 +659,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -305,7 +705,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -351,7 +751,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -397,7 +797,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct" } } ], @@ -443,7 +843,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.CreateCommunityStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.CreateCommunityStruct" } } ], @@ -489,7 +889,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct" } } ], @@ -535,7 +935,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.CreateGroupStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.CreateGroupStruct" } } ], @@ -581,7 +981,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupDescriptionStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupDescriptionStruct" } } ], @@ -627,7 +1027,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInfoStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInfoStruct" } } ], @@ -673,7 +1073,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInviteLinkStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInviteLinkStruct" } } ], @@ -719,7 +1119,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.JoinGroupStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.JoinGroupStruct" } } ], @@ -765,7 +1165,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.LeaveGroupStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.LeaveGroupStruct" } } ], @@ -869,7 +1269,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupNameStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupNameStruct" } } ], @@ -915,7 +1315,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.AddParticipantStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.AddParticipantStruct" } } ], @@ -961,7 +1361,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupPhotoStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupPhotoStruct" } } ], @@ -1007,7 +1407,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.UpdateGroupSettingsStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.UpdateGroupSettingsStruct" } } ], @@ -1082,7 +1482,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ConnectStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ConnectStruct" } } ], @@ -1128,7 +1528,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.CreateStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.CreateStruct" } } ], @@ -1254,7 +1654,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ForceReconnectStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ForceReconnectStruct" } } ], @@ -1438,7 +1838,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.PairStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.PairStruct" } } ], @@ -1491,7 +1891,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.SetProxyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.SetProxyStruct" } } ], @@ -1669,7 +2069,7 @@ const docTemplate = `{ "200": { "description": "Advanced settings retrieved successfully", "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings" } }, "400": { @@ -1718,7 +2118,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings" } } ], @@ -1770,7 +2170,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct" } } ], @@ -1816,7 +2216,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.EditLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.EditLabelStruct" } } ], @@ -1891,7 +2291,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct" } } ], @@ -1917,89 +2317,6 @@ const docTemplate = `{ } } }, - "/license/activate": { - "get": { - "description": "Exchanges an authorization code (from the registration callback) for an api_key and persists it. Provide the code via the query string.", - "produces": [ - "application/json" - ], - "tags": [ - "License" - ], - "summary": "Activate license", - "parameters": [ - { - "type": "string", - "description": "Authorization code from the registration callback", - "name": "code", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "Activation result", - "schema": { - "$ref": "#/definitions/gin.H" - } - }, - "400": { - "description": "Missing code parameter", - "schema": { - "$ref": "#/definitions/gin.H" - } - } - } - } - }, - "/license/register": { - "get": { - "description": "Checks the GLOBAL_API_KEY with the licensing server. If not yet registered, initiates registration and returns a register_url. Accepts an optional redirect_uri for the post-registration redirect.", - "produces": [ - "application/json" - ], - "tags": [ - "License" - ], - "summary": "Register / get registration URL", - "parameters": [ - { - "type": "string", - "description": "Post-registration redirect URI", - "name": "redirect_uri", - "in": "query" - } - ], - "responses": { - "200": { - "description": "Registration state (status/message or register_url)", - "schema": { - "$ref": "#/definitions/gin.H" - } - } - } - } - }, - "/license/status": { - "get": { - "description": "Returns whether the instance license is active, along with the instance id and a masked api key.", - "produces": [ - "application/json" - ], - "tags": [ - "License" - ], - "summary": "Get license status", - "responses": { - "200": { - "description": "License status ({status, instance_id, api_key?})", - "schema": { - "$ref": "#/definitions/gin.H" - } - } - } - } - }, "/message/delete": { "post": { "description": "Delete a message for everyone", @@ -2020,7 +2337,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStruct" } } ], @@ -2066,7 +2383,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.DownloadMediaStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.DownloadMediaStruct" } } ], @@ -2112,7 +2429,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.EditMessageStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.EditMessageStruct" } } ], @@ -2158,7 +2475,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MarkPlayedStruct" } } ], @@ -2204,7 +2521,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MarkReadStruct" } } ], @@ -2250,7 +2567,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.ChatPresenceStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.ChatPresenceStruct" } } ], @@ -2296,7 +2613,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.ReactStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.ReactStruct" } } ], @@ -2342,7 +2659,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStatusStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStatusStruct" } } ], @@ -2388,7 +2705,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.CreateNewsletterStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.CreateNewsletterStruct" } } ], @@ -2434,7 +2751,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct" } } ], @@ -2480,7 +2797,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct" } } ], @@ -2555,7 +2872,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct" } } ], @@ -2601,7 +2918,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct" } } ], @@ -2818,7 +3135,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollResults" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.PollResults" } }, "400": { @@ -2862,7 +3179,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ButtonStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ButtonStruct" } } ], @@ -2908,7 +3225,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselStruct" } } ], @@ -2954,7 +3271,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ContactStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ContactStruct" } } ], @@ -3000,7 +3317,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LinkStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LinkStruct" } } ], @@ -3046,7 +3363,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ListStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ListStruct" } } ], @@ -3092,7 +3409,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LocationStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LocationStruct" } } ], @@ -3138,7 +3455,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.MediaStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.MediaStruct" } } ], @@ -3184,7 +3501,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.PollStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.PollStruct" } } ], @@ -3299,7 +3616,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StatusTextStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StatusTextStruct" } } ], @@ -3345,7 +3662,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StickerStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StickerStruct" } } ], @@ -3391,7 +3708,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.TextStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.TextStruct" } } ], @@ -3437,7 +3754,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct" } } ], @@ -3483,7 +3800,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct" } } ], @@ -3529,7 +3846,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.GetAvatarStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.GetAvatarStruct" } } ], @@ -3575,7 +3892,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct" } } ], @@ -3650,7 +3967,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct" } } ], @@ -3725,7 +4042,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct" } } ], @@ -3798,7 +4115,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.PrivacyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.PrivacyStruct" } } ], @@ -3838,7 +4155,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct" } } ], @@ -3884,7 +4201,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct" } } ], @@ -3930,7 +4247,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct" } } ], @@ -3976,7 +4293,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct" } } ], @@ -4001,25 +4318,132 @@ const docTemplate = `{ } } } - } - }, - "definitions": { - "gin.H": { + } + }, + "definitions": { + "gin.H": { + "type": "object", + "additionalProperties": {} + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.AddParticipantStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "number": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.AnswerCallStruct": { + "type": "object", + "properties": { + "callCreator": { + "$ref": "#/definitions/types.JID" + }, + "callId": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.DialCallStruct": { + "type": "object", + "properties": { + "number": { + "type": "string" + }, + "video": { + "type": "boolean" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.HandRaiseStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "raised": { + "type": "boolean" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.HangupCallStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.ReactCallStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "emoji": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.RejectCallStruct": { + "type": "object", + "properties": { + "callCreator": { + "$ref": "#/definitions/types.JID" + }, + "callId": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.ScreenShareStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "start": { + "type": "boolean" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.VideoEnabledStruct": { "type": "object", - "additionalProperties": {} + "properties": { + "callId": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } }, - "github_com_EvolutionAPI_evolution-go_pkg_call_service.RejectCallStruct": { + "github_com_evolution-foundation_evolution-go_pkg_call_service.VideoOrientationStruct": { "type": "object", "properties": { - "callCreator": { - "$ref": "#/definitions/types.JID" + "callId": { + "type": "string" }, + "orientation": { + "type": "integer" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.VideoUpgradeStruct": { + "type": "object", + "properties": { "callId": { "type": "string" + }, + "start": { + "type": "boolean" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct": { + "github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct": { "type": "object", "properties": { "chat": { @@ -4027,7 +4451,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_chat_service.HistorySyncRequestStruct": { + "github_com_evolution-foundation_evolution-go_pkg_chat_service.HistorySyncRequestStruct": { "type": "object", "properties": { "count": { @@ -4038,7 +4462,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct": { + "github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct": { "type": "object", "properties": { "communityJid": { @@ -4052,7 +4476,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_community_service.CreateCommunityStruct": { + "github_com_evolution-foundation_evolution-go_pkg_community_service.CreateCommunityStruct": { "type": "object", "properties": { "communityName": { @@ -4060,7 +4484,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.AddParticipantStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.AddParticipantStruct": { "type": "object", "properties": { "action": { @@ -4077,7 +4501,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.CreateGroupStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.CreateGroupStruct": { "type": "object", "properties": { "groupName": { @@ -4091,7 +4515,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInfoStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInfoStruct": { "type": "object", "properties": { "groupJid": { @@ -4099,7 +4523,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInviteLinkStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInviteLinkStruct": { "type": "object", "properties": { "groupJid": { @@ -4110,7 +4534,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.JoinGroupStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.JoinGroupStruct": { "type": "object", "properties": { "code": { @@ -4118,7 +4542,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.LeaveGroupStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.LeaveGroupStruct": { "type": "object", "properties": { "groupJid": { @@ -4126,7 +4550,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupDescriptionStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupDescriptionStruct": { "type": "object", "properties": { "description": { @@ -4137,7 +4561,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupNameStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupNameStruct": { "type": "object", "properties": { "groupJid": { @@ -4148,7 +4572,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupPhotoStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupPhotoStruct": { "type": "object", "properties": { "groupJid": { @@ -4159,7 +4583,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.UpdateGroupSettingsStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.UpdateGroupSettingsStruct": { "type": "object", "properties": { "action": { @@ -4171,7 +4595,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings": { + "github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings": { "type": "object", "properties": { "alwaysOnline": { @@ -4194,7 +4618,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.ConnectStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.ConnectStruct": { "type": "object", "properties": { "immediate": { @@ -4223,11 +4647,11 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.CreateStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.CreateStruct": { "type": "object", "properties": { "advancedSettings": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings" }, "instanceId": { "type": "string" @@ -4236,14 +4660,14 @@ const docTemplate = `{ "type": "string" }, "proxy": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ProxyConfig" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ProxyConfig" }, "token": { "type": "string" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.ForceReconnectStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.ForceReconnectStruct": { "type": "object", "properties": { "number": { @@ -4251,7 +4675,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.PairStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.PairStruct": { "type": "object", "properties": { "phone": { @@ -4265,7 +4689,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.ProxyConfig": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.ProxyConfig": { "type": "object", "properties": { "host": { @@ -4285,7 +4709,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.SetProxyStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.SetProxyStruct": { "type": "object", "required": [ "host", @@ -4309,7 +4733,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct": { + "github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct": { "type": "object", "properties": { "jid": { @@ -4320,7 +4744,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_label_service.EditLabelStruct": { + "github_com_evolution-foundation_evolution-go_pkg_label_service.EditLabelStruct": { "type": "object", "properties": { "color": { @@ -4337,7 +4761,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct": { + "github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct": { "type": "object", "properties": { "jid": { @@ -4351,7 +4775,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.ChatPresenceStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.ChatPresenceStruct": { "type": "object", "properties": { "delay": { @@ -4369,7 +4793,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.DownloadMediaStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.DownloadMediaStruct": { "type": "object", "properties": { "message": { @@ -4377,7 +4801,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.EditMessageStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.EditMessageStruct": { "type": "object", "properties": { "chat": { @@ -4391,7 +4815,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.MarkPlayedStruct": { "type": "object", "properties": { "id": { @@ -4405,7 +4829,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.MarkReadStruct": { "type": "object", "properties": { "id": { @@ -4419,7 +4843,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStatusStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStatusStruct": { "type": "object", "properties": { "id": { @@ -4427,7 +4851,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStruct": { "type": "object", "properties": { "chat": { @@ -4438,7 +4862,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.ReactStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.ReactStruct": { "type": "object", "properties": { "fromMe": { @@ -4458,7 +4882,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.CreateNewsletterStruct": { + "github_com_evolution-foundation_evolution-go_pkg_newsletter_service.CreateNewsletterStruct": { "type": "object", "properties": { "description": { @@ -4469,7 +4893,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct": { + "github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct": { "type": "object", "properties": { "key": { @@ -4477,7 +4901,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct": { + "github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct": { "type": "object", "properties": { "before_id": { @@ -4491,7 +4915,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct": { + "github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct": { "type": "object", "properties": { "jid": { @@ -4499,7 +4923,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollResults": { + "github_com_evolution-foundation_evolution-go_pkg_poll_model.PollResults": { "type": "object", "properties": { "optionCounts": { @@ -4521,18 +4945,18 @@ const docTemplate = `{ "voters": { "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.VoterInfo" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.VoterInfo" } }, "votes": { "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollVote" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.PollVote" } } } }, - "github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollVote": { + "github_com_evolution-foundation_evolution-go_pkg_poll_model.PollVote": { "type": "object", "properties": { "companyId": { @@ -4577,7 +5001,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_poll_model.VoterInfo": { + "github_com_evolution-foundation_evolution-go_pkg_poll_model.VoterInfo": { "type": "object", "properties": { "jid": { @@ -4600,7 +5024,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Button": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Button": { "type": "object", "properties": { "copyCode": { @@ -4669,14 +5093,14 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ButtonStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ButtonStruct": { "type": "object", "properties": { "buttons": { "description": "Buttons array. See combination rules on the parent type description.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Button" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Button" } }, "delay": { @@ -4722,7 +5146,7 @@ const docTemplate = `{ "description": "Quoted (reply-to) context.", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } ] }, @@ -4737,7 +5161,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselButtonStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselButtonStruct": { "type": "object", "properties": { "copyCode": { @@ -4772,7 +5196,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct": { "type": "object", "properties": { "text": { @@ -4782,7 +5206,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct": { "type": "object", "properties": { "imageUrl": { @@ -4806,14 +5230,14 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardStruct": { "type": "object", "properties": { "body": { "description": "Card body text (required).", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct" } ] }, @@ -4821,7 +5245,7 @@ const docTemplate = `{ "description": "Buttons shown on the card. See CarouselButtonStruct for combination rules.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselButtonStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselButtonStruct" } }, "footer": { @@ -4833,13 +5257,13 @@ const docTemplate = `{ "description": "Card header (media + title/subtitle).", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct" } ] } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselStruct": { "type": "object", "properties": { "body": { @@ -4851,7 +5275,7 @@ const docTemplate = `{ "description": "Cards displayed in order. At least one card is required.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardStruct" } }, "delay": { @@ -4877,13 +5301,13 @@ const docTemplate = `{ "description": "Quoted (reply-to) context.", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } ] } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ContactStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ContactStruct": { "type": "object", "properties": { "delay": { @@ -4908,14 +5332,14 @@ const docTemplate = `{ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "vcard": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_utils.VCardStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_utils.VCardStruct" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LinkStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LinkStruct": { "type": "object", "properties": { "delay": { @@ -4946,7 +5370,7 @@ const docTemplate = `{ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "text": { "type": "string" @@ -4959,7 +5383,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ListStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ListStruct": { "type": "object", "properties": { "buttonText": { @@ -5006,7 +5430,7 @@ const docTemplate = `{ "description": "Quoted (reply-to) context.", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } ] }, @@ -5014,7 +5438,7 @@ const docTemplate = `{ "description": "Sections with rows. At least one section with one row is required.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Section" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Section" } }, "title": { @@ -5024,7 +5448,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LocationStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LocationStruct": { "type": "object", "properties": { "address": { @@ -5061,11 +5485,11 @@ const docTemplate = `{ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.MediaStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.MediaStruct": { "type": "object", "properties": { "caption": { @@ -5099,7 +5523,7 @@ const docTemplate = `{ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "type": { "type": "string" @@ -5109,7 +5533,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.PollStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.PollStruct": { "type": "object", "properties": { "delay": { @@ -5146,11 +5570,11 @@ const docTemplate = `{ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct": { "type": "object", "properties": { "messageId": { @@ -5161,7 +5585,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Row": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Row": { "type": "object", "properties": { "description": { @@ -5181,14 +5605,14 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Section": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Section": { "type": "object", "properties": { "rows": { "description": "Rows inside this section.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Row" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Row" } }, "title": { @@ -5198,7 +5622,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StatusTextStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StatusTextStruct": { "type": "object", "properties": { "id": { @@ -5209,7 +5633,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StickerStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StickerStruct": { "type": "object", "properties": { "delay": { @@ -5234,14 +5658,14 @@ const docTemplate = `{ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "sticker": { "type": "string" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.TextStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.TextStruct": { "type": "object", "properties": { "delay": { @@ -5269,14 +5693,14 @@ const docTemplate = `{ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "text": { "type": "string" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct": { "type": "object", "properties": { "number": { @@ -5284,7 +5708,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct": { "type": "object", "properties": { "formatJid": { @@ -5298,7 +5722,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.GetAvatarStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.GetAvatarStruct": { "type": "object", "properties": { "number": { @@ -5309,7 +5733,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.PrivacyStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.PrivacyStruct": { "type": "object", "properties": { "callAdd": { @@ -5335,7 +5759,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct": { "type": "object", "properties": { "image": { @@ -5343,7 +5767,7 @@ const docTemplate = `{ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_utils.VCardStruct": { + "github_com_evolution-foundation_evolution-go_pkg_utils.VCardStruct": { "type": "object", "properties": { "fullName": { @@ -5515,6 +5939,9 @@ const docTemplate = `{ "description": "Whether the chat is a group chat or broadcast list.", "type": "boolean" }, + "isNewsletterStatus": { + "type": "boolean" + }, "mediaType": { "type": "string" }, @@ -5636,11 +6063,26 @@ const docTemplate = `{ "types.VerifiedName": { "type": "object", "properties": { + "actualActors": { + "type": "integer" + }, "certificate": { "$ref": "#/definitions/waVnameCert.VerifiedNameCertificate" }, "details": { "$ref": "#/definitions/waVnameCert.VerifiedNameCertificate_Details" + }, + "hostStorage": { + "type": "integer" + }, + "privacyModeTS": { + "type": "string" + }, + "verifiedLevel": { + "type": "string" + }, + "version": { + "type": "integer" } } }, @@ -5726,6 +6168,28 @@ const docTemplate = `{ } } }, + "waAICommon.AIProvenance": { + "type": "object", + "properties": { + "c2PaMetadata": { + "$ref": "#/definitions/waAICommon.AIProvenance_Metadata" + }, + "iptcMetadata": { + "$ref": "#/definitions/waAICommon.AIProvenance_Metadata" + } + } + }, + "waAICommon.AIProvenance_Metadata": { + "type": "object", + "properties": { + "createdWithGenAi": { + "type": "boolean" + }, + "editedWithGenAi": { + "type": "boolean" + } + } + }, "waAICommon.AIRegenerateMetadata": { "type": "object", "properties": { @@ -5847,6 +6311,12 @@ const docTemplate = `{ "waAICommon.BotAgentDeepLinkMetadata": { "type": "object", "properties": { + "clientPublicKey": { + "type": "array", + "items": { + "type": "integer" + } + }, "token": { "type": "string" } @@ -5940,7 +6410,11 @@ const docTemplate = `{ 62, 63, 64, - 65 + 65, + 66, + 67, + 68, + 69 ], "x-enum-varnames": [ "BotCapabilityMetadata_UNKNOWN", @@ -6008,7 +6482,11 @@ const docTemplate = `{ "BotCapabilityMetadata_UNIFIED_RESPONSE_AI_CONTENT_SEARCH_ENABLED", "BotCapabilityMetadata_UNIFIED_RESPONSE_MARKDOWN_LINKS_ENABLED", "BotCapabilityMetadata_AI_RICH_RESPONSE_MAPS_V2_ENABLED", - "BotCapabilityMetadata_AI_SUBSCRIPTION_METERING_ENABLED" + "BotCapabilityMetadata_AI_SUBSCRIPTION_METERING_ENABLED", + "BotCapabilityMetadata_RICH_RESPONSE_SPORTS_WIDGET_ENABLED", + "BotCapabilityMetadata_AI_RICH_RESPONSE_ARTIFACTS_ENABLED", + "BotCapabilityMetadata_AI_RICH_RESPONSE_EMAIL_CALENDAR_ENABLED", + "BotCapabilityMetadata_AI_RICH_RESPONSE_REMINDERS_ENABLED" ] }, "waAICommon.BotCommandMetadata": { @@ -6259,6 +6737,17 @@ const docTemplate = `{ } } }, + "waAICommon.BotHistoryShareMetadata": { + "type": "object", + "properties": { + "participantsMetadata": { + "type": "array", + "items": { + "$ref": "#/definitions/waAICommon.BotGroupParticipantMetadata" + } + } + } + }, "waAICommon.BotImagineMetadata": { "type": "object", "properties": { @@ -6498,6 +6987,9 @@ const docTemplate = `{ "botGroupMetadata": { "$ref": "#/definitions/waAICommon.BotGroupMetadata" }, + "botHistoryShareMetadata": { + "$ref": "#/definitions/waAICommon.BotHistoryShareMetadata" + }, "botInfrastructureDiagnostics": { "$ref": "#/definitions/waAICommon.BotInfrastructureDiagnostics" }, @@ -6665,7 +7157,8 @@ const docTemplate = `{ 47, 54, 55, - 56 + 56, + 57 ], "x-enum-varnames": [ "BotMetricsEntryPoint_UNDEFINED_ENTRY_POINT", @@ -6715,7 +7208,8 @@ const docTemplate = `{ "BotMetricsEntryPoint_WEB_NAVIGATION_BAR", "BotMetricsEntryPoint_GROUP_MEMBER", "BotMetricsEntryPoint_CHATLIST_SEARCH", - "BotMetricsEntryPoint_NEW_CHAT_LIST" + "BotMetricsEntryPoint_NEW_CHAT_LIST", + "BotMetricsEntryPoint_CONTACTS_TAB" ] }, "waAICommon.BotMetricsMetadata": { @@ -7973,6 +8467,28 @@ const docTemplate = `{ "ADVEncryptionType_HOSTED" ] }, + "waAea.NonE2EEAttestation": { + "type": "object", + "properties": { + "accountType": { + "$ref": "#/definitions/waAea.NonE2EEAttestation_AccountType" + } + } + }, + "waAea.NonE2EEAttestation_AccountType": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2 + ], + "x-enum-varnames": [ + "NonE2EEAttestation_E2EE", + "NonE2EEAttestation_HYBRID_E2EE", + "NonE2EEAttestation_NON_E2EE" + ] + }, "waCommon.LimitSharing": { "type": "object", "properties": { @@ -8356,6 +8872,23 @@ const docTemplate = `{ "BCallMessage_VIDEO" ] }, + "waE2E.BotHistoryShareSyncMetadata": { + "type": "object", + "properties": { + "botJID": { + "type": "string" + }, + "historyShareCutoffTimestamp": { + "type": "integer" + }, + "historyShareMessages": { + "type": "array", + "items": { + "$ref": "#/definitions/waE2E.HistoryShareMessageEntry" + } + } + } + }, "waE2E.ButtonsMessage": { "type": "object", "properties": { @@ -8495,6 +9028,9 @@ const docTemplate = `{ "type": "integer" } }, + "callReason": { + "type": "string" + }, "contextInfo": { "$ref": "#/definitions/waE2E.ContextInfo" }, @@ -8777,6 +9313,9 @@ const docTemplate = `{ "afterReadDuration": { "type": "integer" }, + "aiProvenance": { + "$ref": "#/definitions/waAICommon.AIProvenance" + }, "alwaysShowAdAttribution": { "type": "boolean" }, @@ -8873,6 +9412,9 @@ const docTemplate = `{ "groupSubject": { "type": "string" }, + "instagramThreadLink": { + "$ref": "#/definitions/waE2E.ContextInfo_InstagramThreadLink" + }, "isForwarded": { "type": "boolean" }, @@ -9034,6 +9576,9 @@ const docTemplate = `{ "items": { "type": "integer" } + }, + "unauthenticatedBusinessMetadata": { + "$ref": "#/definitions/waE2E.ContextInfo_BusinessInteractionPills_UnauthenticatedBusinessMetadata" } } }, @@ -9102,6 +9647,23 @@ const docTemplate = `{ "ContextInfo_BusinessInteractionPills_ORDER" ] }, + "waE2E.ContextInfo_BusinessInteractionPills_UnauthenticatedBusinessMetadata": { + "type": "object", + "properties": { + "businessCategory": { + "type": "string" + }, + "businessIsOpen": { + "type": "boolean" + }, + "businessIsOpenSnapshotMS": { + "type": "integer" + }, + "businessName": { + "type": "string" + } + } + }, "waE2E.ContextInfo_BusinessMessageForwardInfo": { "type": "object", "properties": { @@ -9371,6 +9933,14 @@ const docTemplate = `{ "ContextInfo_ForwardedNewsletterMessageInfo_LINK_CARD" ] }, + "waE2E.ContextInfo_InstagramThreadLink": { + "type": "object", + "properties": { + "URL": { + "type": "string" + } + } + }, "waE2E.ContextInfo_PairedMediaType": { "type": "integer", "format": "int32", @@ -9938,7 +10508,7 @@ const docTemplate = `{ "$ref": "#/definitions/waE2E.VideoEndCard" } }, - "faviconMMSMetadata": { + "faviconMmsMetadata": { "$ref": "#/definitions/waE2E.MMSThumbnailMetadata" }, "font": { @@ -10261,6 +10831,20 @@ const docTemplate = `{ } } }, + "waE2E.HistoryShareMessageEntry": { + "type": "object", + "properties": { + "messageSecretProof": { + "type": "array", + "items": { + "type": "integer" + } + }, + "stanzaID": { + "type": "string" + } + } + }, "waE2E.HistorySyncMessageAccessStatus": { "type": "object", "properties": { @@ -11137,6 +11721,26 @@ const docTemplate = `{ } } }, + "waE2E.MarkAsVerifiedAction": { + "type": "object", + "properties": { + "actionSeq": { + "type": "integer" + }, + "userJIDString": { + "type": "string" + }, + "verified": { + "type": "boolean" + }, + "verifiedIdentityKey": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, "waE2E.MediaDomainInfo": { "type": "object", "properties": { @@ -11469,6 +12073,9 @@ const docTemplate = `{ "splitPaymentMessage": { "$ref": "#/definitions/waE2E.SplitPaymentMessage" }, + "splitPaymentUpdateMessage": { + "$ref": "#/definitions/waE2E.SplitPaymentUpdateMessage" + }, "spoilerMessage": { "$ref": "#/definitions/waE2E.FutureProofMessage" }, @@ -11586,6 +12193,15 @@ const docTemplate = `{ "waE2E.MessageContextInfo": { "type": "object", "properties": { + "accountEncryptionAttestation": { + "$ref": "#/definitions/waAea.NonE2EEAttestation" + }, + "associatedPrimaryIdentityKey": { + "type": "array", + "items": { + "type": "integer" + } + }, "botMessageSecret": { "type": "array", "items": { @@ -11733,6 +12349,9 @@ const docTemplate = `{ "waE2E.MessageHistoryNotice": { "type": "object", "properties": { + "botHistoryShareSyncMetadata": { + "$ref": "#/definitions/waE2E.BotHistoryShareSyncMetadata" + }, "contextInfo": { "$ref": "#/definitions/waE2E.ContextInfo" }, @@ -11960,6 +12579,9 @@ const docTemplate = `{ "waE2E.PaymentExtendedMetadata": { "type": "object", "properties": { + "messageParamsJSON": { + "type": "string" + }, "platform": { "type": "string" }, @@ -12698,7 +13320,8 @@ const docTemplate = `{ 10, 11, 12, - 13 + 13, + 14 ], "x-enum-varnames": [ "PeerDataOperationRequestType_UPLOAD_STICKER", @@ -12714,7 +13337,8 @@ const docTemplate = `{ "PeerDataOperationRequestType_HISTORY_SYNC_CHUNK_RETRY", "PeerDataOperationRequestType_GALAXY_FLOW_ACTION", "PeerDataOperationRequestType_BUSINESS_BROADCAST_INSIGHTS_DELIVERED_TO", - "PeerDataOperationRequestType_BUSINESS_BROADCAST_INSIGHTS_REFRESH" + "PeerDataOperationRequestType_BUSINESS_BROADCAST_INSIGHTS_REFRESH", + "PeerDataOperationRequestType_CONTACT_REFRESH_REQUEST" ] }, "waE2E.PinInChatMessage": { @@ -13122,6 +13746,9 @@ const docTemplate = `{ "cloudApiThreadControlNotification": { "$ref": "#/definitions/waE2E.CloudAPIThreadControlNotification" }, + "coexStateSync": { + "$ref": "#/definitions/waServerSync.CoexStateSync" + }, "disappearingMode": { "$ref": "#/definitions/waE2E.DisappearingMode" }, @@ -13152,6 +13779,9 @@ const docTemplate = `{ "limitSharing": { "$ref": "#/definitions/waCommon.LimitSharing" }, + "markAsVerifiedAction": { + "$ref": "#/definitions/waE2E.MarkAsVerifiedAction" + }, "mediaNotifyMessage": { "$ref": "#/definitions/waE2E.MediaNotifyMessage" }, @@ -13167,6 +13797,9 @@ const docTemplate = `{ "requestWelcomeMessageMetadata": { "$ref": "#/definitions/waE2E.RequestWelcomeMessageMetadata" }, + "syncRequestMutationRetry": { + "$ref": "#/definitions/waE2E.SyncRequestMutationRetry" + }, "timestampMS": { "type": "integer" }, @@ -13208,7 +13841,10 @@ const docTemplate = `{ 31, 32, 34, - 35 + 35, + 36, + 37, + 38 ], "x-enum-varnames": [ "ProtocolMessage_REVOKE", @@ -13240,7 +13876,10 @@ const docTemplate = `{ "ProtocolMessage_AI_MEDIA_COLLECTION_MESSAGE", "ProtocolMessage_MESSAGE_UNSCHEDULE", "ProtocolMessage_CHAT_THEME_SETTING", - "ProtocolMessage_AI_METADATA_OPERATION" + "ProtocolMessage_AI_METADATA_OPERATION", + "ProtocolMessage_MARK_AS_VERIFIED_ACTION", + "ProtocolMessage_COEX_STATE_SYNC", + "ProtocolMessage_SYNC_REQUEST_MUTATION_RETRY" ] }, "waE2E.QuestionResponseMessage": { @@ -13534,6 +14173,17 @@ const docTemplate = `{ "SplitPaymentParticipant_PAID" ] }, + "waE2E.SplitPaymentUpdateMessage": { + "type": "object", + "properties": { + "participantJID": { + "type": "string" + }, + "splitID": { + "type": "string" + } + } + }, "waE2E.StatusNotificationMessage": { "type": "object", "properties": { @@ -13866,6 +14516,31 @@ const docTemplate = `{ } } }, + "waE2E.SyncRequestMutationRetry": { + "type": "object", + "properties": { + "collections": { + "type": "array", + "items": { + "$ref": "#/definitions/waE2E.SyncRequestMutationRetry_Collection" + } + }, + "count": { + "type": "integer" + } + } + }, + "waE2E.SyncRequestMutationRetry_Collection": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "storedSyncdVersion": { + "type": "integer" + } + } + }, "waE2E.TemplateButtonReplyMessage": { "type": "object", "properties": { @@ -14188,6 +14863,82 @@ const docTemplate = `{ "MediaRetryNotification_DECRYPTION_ERROR" ] }, + "waServerSync.CoexStateSync": { + "type": "object", + "properties": { + "collectionMutations": { + "type": "array", + "items": { + "$ref": "#/definitions/waServerSync.CoexStateSync_CollectionMutations" + } + } + } + }, + "waServerSync.CoexStateSync_CollectionMutations": { + "type": "object", + "properties": { + "collection": { + "type": "string" + }, + "mutations": { + "type": "array", + "items": { + "$ref": "#/definitions/waServerSync.CoexStateSync_Mutation" + } + } + } + }, + "waServerSync.CoexStateSync_Mutation": { + "type": "object", + "properties": { + "dirtyVersion": { + "type": "integer" + }, + "index": { + "$ref": "#/definitions/waServerSync.SyncdIndex" + }, + "operation": { + "$ref": "#/definitions/waServerSync.SyncdMutation_SyncdOperation" + }, + "value": { + "$ref": "#/definitions/waServerSync.SyncdValue" + } + } + }, + "waServerSync.SyncdIndex": { + "type": "object", + "properties": { + "blob": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "waServerSync.SyncdMutation_SyncdOperation": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1 + ], + "x-enum-varnames": [ + "SyncdMutation_SET", + "SyncdMutation_REMOVE" + ] + }, + "waServerSync.SyncdValue": { + "type": "object", + "properties": { + "blob": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, "waStatusAttributions.StatusAttribution": { "type": "object", "properties": { diff --git a/docs/superpowers/plans/2026-07-29-call-answer-stream.md b/docs/superpowers/plans/2026-07-29-call-answer-stream.md new file mode 100644 index 00000000..8bf7503c --- /dev/null +++ b/docs/superpowers/plans/2026-07-29-call-answer-stream.md @@ -0,0 +1,1268 @@ +# Call Answer + Media Stream Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add `POST /call/answer`, `POST /call/hangup`, and a dedicated WebSocket bridge (`GET /call/stream/:callId`) to Evolution Go so an accepted WhatsApp call's audio/video can be piped to any external consumer (AI voice pipeline, recorder, human console). + +**Architecture:** `github.com/purpshell/meowcaller` wraps each instance's `*whatsmeow.Client` and is constructed the moment that client is created (before `.Connect()`), exactly like `pkg/whatsmeow/service` already tracks a `map[string]*whatsmeow.Client`. Incoming `*meowcaller.Call` handles are captured via `OnIncomingCall` into a small shared registry (`pkg/call/registry`), keyed by call ID and instance ID. `pkg/call/service` answers/hangs up calls by looking them up in that registry. A new `pkg/call/stream` package bridges a `*meowcaller.Call`'s audio/video sinks and source to a per-call WebSocket connection, using a Twilio-Media-Streams-style JSON envelope. + +**Tech Stack:** Go 1.25, gin, gorilla/websocket (already a dependency via `pkg/events/websocket`), `go.mau.fi/whatsmeow`, `github.com/purpshell/meowcaller` (new, MIT-licensed). + +## Global Constraints + +- `meowcaller.NewClient(wa)` MUST be called before `wa.Connect()` — this is a hard requirement from the library's own doc comment, not a style choice. +- No AI/STT/LLM/TTS logic in this repo — this PR ships transport/plumbing only (per approved design spec `docs/superpowers/specs/2026-07-29-call-answer-stream-design.md`). +- Video is inbound-only (record/forward the peer's video); outbound synthetic video is out of scope. +- Follow the existing Handler → Service → Repository convention and package-alias-as-name-with-underscore style already used throughout (`call_service`, `call_handler`, etc.) — see `docs/wiki/desenvolvimento/contributing.md`. +- Audio wire format: 16 kHz mono, 960-sample (60 ms) frames, `float32` inside the process (`meowcaller.SampleRate`, `meowcaller.FrameSamples`), PCM16LE + base64 on the wire. +- Run `make fmt` and `make lint` before every commit that touches Go files (repo convention). + +--- + +### Task 1: Add the `meowcaller` dependency and verify the build + +**Files:** +- Modify: `go.mod`, `go.sum` + +**Interfaces:** +- Produces: `github.com/purpshell/meowcaller` importable at `v0.0.0-...` (pseudo-version, no tagged releases yet), and `go.mau.fi/whatsmeow` bumped to at least `v0.0.0-20260722203353-e9a033b24933` (meowcaller's floor; Go's minimal version selection will pick the higher of the two requirements automatically). + +- [ ] **Step 1: Add the dependency** + +```bash +cd /home/rarosh/projetos/evolution-go +go get github.com/purpshell/meowcaller@latest +``` + +- [ ] **Step 2: Verify the whatsmeow bump didn't break anything** + +**Do NOT run `go mod tidy` in this task.** No `.go` file imports `meowcaller` yet — that +starts in Task 3 — and `go mod tidy` removes `require` entries for modules nothing in +the module actually imports. Run it now and it will silently delete the line `go get` +just added, and `go build ./...` will still pass (nothing references the module, so its +absence doesn't break compilation) — meaning a clean build here is not proof the +dependency is actually present. Confirm it explicitly instead: + +```bash +grep meowcaller go.mod +``` + +Expected: one line, `github.com/purpshell/meowcaller v0.0.0-...`. If it's not there, the +`go get` in Step 1 didn't take — re-run it and check again before moving on. + +```bash +go build ./... +``` + +Expected: exits 0. If it fails, the failures will be in `pkg/whatsmeow/service/whatsmeow.go` from whatsmeow API drift between the pinned versions (2026-06-30 → 2026-07-22) — read the compiler errors, they'll name the exact symbols that moved; fix those call sites before continuing (do not downgrade whatsmeow back down, meowcaller requires the newer floor). + +(Task 8 Step 6-7, once `meowcaller` is actually imported by real code, is the right time to run `go mod tidy` — it will no longer have anything unused to strip.) + +- [ ] **Step 3: Commit** + +```bash +git add go.mod go.sum +git commit -m "feat: add meowcaller dependency for WhatsApp call media" +``` + +--- + +### Task 2: Call registry (shared between whatsmeow_service and call_service) + +**Files:** +- Create: `pkg/call/registry/call_registry.go` +- Test: `pkg/call/registry/call_registry_test.go` + +**Interfaces:** +- Produces: + - `type CallRegistry struct` (opaque, all fields unexported) + - `func NewCallRegistry() *CallRegistry` + - `func (r *CallRegistry) Store(instanceID string, call *meowcaller.Call)` + - `func (r *CallRegistry) Get(instanceID, callID string) (*meowcaller.Call, bool)` — returns `false` if the call isn't registered *or* belongs to a different instance (this is the security boundary that keeps one instance's apikey from reaching into another instance's call) + - `func (r *CallRegistry) Delete(callID string)` + +This is its own leaf package (not inside `pkg/call/service`) specifically to avoid an import cycle: `pkg/call/service` already imports `pkg/whatsmeow/service`, and `pkg/whatsmeow/service` needs to write into this registry too — if the registry lived inside `pkg/call/service`, that would make `pkg/whatsmeow/service` import `pkg/call/service` while `pkg/call/service` imports `pkg/whatsmeow/service`, which Go rejects. + +- [ ] **Step 1: Write the failing test** + +```go +// pkg/call/registry/call_registry_test.go +package call_registry + +import ( + "testing" + + "github.com/purpshell/meowcaller" +) + +func TestStoreAndGet(t *testing.T) { + r := NewCallRegistry() + call := &meowcaller.Call{} + + r.Store("instance-a", call) + + got, ok := r.Get("instance-a", callIDOf(call)) + if !ok { + t.Fatal("expected call to be found") + } + if got != call { + t.Fatal("expected the same call pointer back") + } +} + +func TestGetWrongInstanceFails(t *testing.T) { + r := NewCallRegistry() + call := &meowcaller.Call{} + r.Store("instance-a", call) + + _, ok := r.Get("instance-b", callIDOf(call)) + if ok { + t.Fatal("expected lookup from a different instance to fail") + } +} + +func TestDeleteRemovesEntry(t *testing.T) { + r := NewCallRegistry() + call := &meowcaller.Call{} + r.Store("instance-a", call) + r.Delete(callIDOf(call)) + + _, ok := r.Get("instance-a", callIDOf(call)) + if ok { + t.Fatal("expected entry to be gone after Delete") + } +} + +// callIDOf mirrors what CallRegistry.Store keys entries by: meowcaller.Call.ID(). +// A zero-value *meowcaller.Call has an empty string ID, which is a perfectly valid +// (if degenerate) key for exercising Store/Get/Delete without a live call. +func callIDOf(call *meowcaller.Call) string { + return call.ID() +} +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `go test ./pkg/call/registry/... -v` +Expected: FAIL — `call_registry.go` doesn't exist yet, compile error `undefined: NewCallRegistry`. + +- [ ] **Step 3: Write the implementation** + +```go +// pkg/call/registry/call_registry.go +package call_registry + +import ( + "sync" + + "github.com/purpshell/meowcaller" +) + +// entry pairs a live call with the instance it belongs to, so Get can refuse to hand +// back a call to a caller authenticated as a different instance. +type entry struct { + instanceID string + call *meowcaller.Call +} + +// CallRegistry tracks in-progress meowcaller calls by call ID, scoped by instance. +// It is written from the whatsmeow event-handling goroutine (on incoming call) and +// read/written from HTTP handler goroutines (answer/hangup/stream), so all access is +// mutex-guarded. +type CallRegistry struct { + mu sync.RWMutex + entries map[string]entry +} + +// NewCallRegistry returns an empty registry. +func NewCallRegistry() *CallRegistry { + return &CallRegistry{entries: make(map[string]entry)} +} + +// Store records call under its own ID (meowcaller.Call.ID()), tagged with instanceID. +func (r *CallRegistry) Store(instanceID string, call *meowcaller.Call) { + r.mu.Lock() + defer r.mu.Unlock() + r.entries[call.ID()] = entry{instanceID: instanceID, call: call} +} + +// Get returns the call for callID, but only if it was stored under instanceID. +func (r *CallRegistry) Get(instanceID, callID string) (*meowcaller.Call, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + e, ok := r.entries[callID] + if !ok || e.instanceID != instanceID { + return nil, false + } + return e.call, true +} + +// Delete removes callID regardless of which instance it belongs to. +func (r *CallRegistry) Delete(callID string) { + r.mu.Lock() + defer r.mu.Unlock() + delete(r.entries, callID) +} +``` + +- [ ] **Step 4: Run test to verify it passes** + +Run: `go test ./pkg/call/registry/... -v` +Expected: PASS (3 tests) + +- [ ] **Step 5: Commit** + +```bash +git add pkg/call/registry +git commit -m "feat: add call registry for tracking answerable meowcaller calls" +``` + +--- + +### Task 3: Wire meowcaller into `pkg/whatsmeow/service` + +**Files:** +- Modify: `pkg/whatsmeow/service/whatsmeow.go` + +**Interfaces:** +- Consumes: `call_registry.CallRegistry` from Task 2 (`Store`, `Delete`) +- Produces: `whatsmeowService.meowcallerPointer map[string]*meowcaller.Client` (internal, not part of the `WhatsmeowService` interface — nothing outside this file needs to reach into it), and `NewWhatsmeowService` gains one new parameter. + +No automated test for this task: it's wiring inside a 2800-line file that drives a live WhatsApp connection, already untested elsewhere in the repo for the same reason (`ClientData`/`MyClient` flow has zero existing test coverage). Verified by `go build` here and by the manual end-to-end test in Task 9. + +- [ ] **Step 1: Add the import** + +In `pkg/whatsmeow/service/whatsmeow.go`, add to the import block (alongside the other `github.com/evolution-foundation/evolution-go/...` and third-party imports): + +```go + call_registry "github.com/evolution-foundation/evolution-go/pkg/call/registry" + "github.com/purpshell/meowcaller" +``` + +- [ ] **Step 2: Add the two new struct fields** + +Find the `whatsmeowService` struct (currently starts `type whatsmeowService struct {` around line 78). Add two fields, right after `clientPointer map[string]*whatsmeow.Client`: + +```go + clientPointer map[string]*whatsmeow.Client + meowcallerPointer map[string]*meowcaller.Client + callRegistry *call_registry.CallRegistry +``` + +- [ ] **Step 3: Add the new constructor parameter** + +Find `func NewWhatsmeowService(` (around line 2793). Add `callRegistry *call_registry.CallRegistry` as a new parameter right before `loggerWrapper *logger_wrapper.LoggerManager`: + +```go +func NewWhatsmeowService( + instanceRepository instance_repository.InstanceRepository, + authDB *sql.DB, + messageRepository message_repository.MessageRepository, + labelRepository label_repository.LabelRepository, + config *config.Config, + killChannel map[string](chan bool), + clientPointer map[string]*whatsmeow.Client, + rabbitmqProducer producer_interfaces.Producer, + webhookProducer producer_interfaces.Producer, + websocketProducer producer_interfaces.Producer, + sqliteDB *sql.DB, + exPath string, + mediaStorage storage_interfaces.MediaStorage, + natsProducer producer_interfaces.Producer, + callRegistry *call_registry.CallRegistry, + loggerWrapper *logger_wrapper.LoggerManager, +) WhatsmeowService { +``` + +And in the returned `&whatsmeowService{...}` literal in the same function, add two lines (right after `clientPointer: clientPointer,`): + +```go + clientPointer: clientPointer, + meowcallerPointer: make(map[string]*meowcaller.Client), + callRegistry: callRegistry, +``` + +- [ ] **Step 4: Construct the meowcaller client at the exact point whatsmeow's client is created** + +In `func (w whatsmeowService) StartClient(cd *ClientData)`, find this existing line (around line 413-415): + +```go + client := whatsmeow.NewClient(deviceStore, clientLog) + + w.clientPointer[cd.Instance.Id] = client +``` + +Change it to: + +```go + client := whatsmeow.NewClient(deviceStore, clientLog) + + w.clientPointer[cd.Instance.Id] = client + + // meowcaller.NewClient must run before client.Connect() — it installs the raw + // stanza adapter, and doing so after Connect() is a documented race. + meowcallerClient := meowcaller.NewClient(client) + w.meowcallerPointer[cd.Instance.Id] = meowcallerClient + instanceID := cd.Instance.Id + meowcallerClient.OnIncomingCall(func(call *meowcaller.Call) { + w.loggerWrapper.GetLogger(instanceID).LogInfo("[%s] meowcaller captured incoming call %s from %s", instanceID, call.ID(), call.Peer().String()) + w.callRegistry.Store(instanceID, call) + }) +``` + +(`instanceID` is captured into a local variable before the closure so the closure doesn't capture the loop-mutated `cd` — `cd` itself isn't reused in a loop here, but this keeps the closure's captured value explicit and independent of whatever happens to `cd` later in this same function.) + +- [ ] **Step 5: Clean up the registry when whatsmeow itself reports the call ended** + +Find the existing `case *events.CallTerminate:` block (around line 1939): + +```go + case *events.CallTerminate: + doWebhook = true + postMap["event"] = "CallTerminate" + mycli.loggerWrapper.GetLogger(mycli.userID).LogInfo("[%s] Got call terminate %+v", mycli.userID, evt) +``` + +Add one line so a call that's never answered (or whose stream socket never connects) doesn't leak in the registry forever: + +```go + case *events.CallTerminate: + doWebhook = true + postMap["event"] = "CallTerminate" + mycli.loggerWrapper.GetLogger(mycli.userID).LogInfo("[%s] Got call terminate %+v", mycli.userID, evt) + mycli.service.(*whatsmeowService).callRegistry.Delete(evt.CallID) +``` + +Note the `mycli.service.(*whatsmeowService)` type assertion: `mycli.service` is typed as the `WhatsmeowService` interface (see the `MyClient` struct's `service WhatsmeowService` field), which doesn't expose `callRegistry` — and it shouldn't, nothing outside this file needs to touch the registry directly. The type assertion is safe here because `mycli.service` is always set to `&w` (a `*whatsmeowService`) at construction (see the existing `service: &w,` in the `&MyClient{...}` literal a few dozen lines above `StartClient`'s call-event switch) and this code lives in the same package. + +- [ ] **Step 6: Build just this package** + +```bash +go build ./pkg/whatsmeow/service/... +``` + +Expected: exits 0. (Don't run `go build ./...` yet — `cmd/evolution-go/main.go` still calls the old-arity `NewWhatsmeowService` and won't compile until Task 8 fixes that call site.) + +- [ ] **Step 7: Commit** + +```bash +git add pkg/whatsmeow/service/whatsmeow.go +git commit -m "feat: capture incoming meowcaller calls into the call registry" +``` + +--- + +### Task 4: `AnswerCall` / `HangupCall` / `GetActiveCall` in `pkg/call/service` + +**Files:** +- Modify: `pkg/call/service/call_service.go` + +**Interfaces:** +- Consumes: `call_registry.CallRegistry.Get`/`Delete` (Task 2); `whatsmeow_service.NewWhatsmeowService`'s new `callRegistry` param (Task 3, for the constructor wiring done in Task 8) +- Produces: + - `type AnswerCallStruct struct { CallCreator types.JID; CallID string }` (JSON: `callCreator`, `callId`) + - `type HangupCallStruct struct { CallID string }` (JSON: `callId`) + - `CallService.AnswerCall(data *AnswerCallStruct, instance *instance_model.Instance) (*meowcaller.Call, error)` + - `CallService.HangupCall(data *HangupCallStruct, instance *instance_model.Instance) error` + - `CallService.GetActiveCall(instanceId, callId string) (*meowcaller.Call, error)` — used by `pkg/call/stream` (Task 7) + +No automated test here: `*meowcaller.Call`'s exported methods (`Answer`, `Hangup`, `AcceptVideo`) all dereference an unexported, unset-from-outside-the-package `eng *engine` field — calling them on a zero-value `&meowcaller.Call{}` (the only kind of `Call` this package can construct in a test) panics with a nil pointer dereference. There is no seam to inject a fake without forking meowcaller. This is exactly the kind of external, un-mockable dependency the design spec's Testing section already called out — verified instead by the manual real-call test in Task 9. + +- [ ] **Step 1: Add imports** + +In `pkg/call/service/call_service.go`, add to the import block: + +```go + call_registry "github.com/evolution-foundation/evolution-go/pkg/call/registry" + "github.com/purpshell/meowcaller" +``` + +- [ ] **Step 2: Add the new struct types** + +Right after the existing `RejectCallStruct` definition: + +```go +type RejectCallStruct struct { + CallCreator types.JID `json:"callCreator"` + CallID string `json:"callId"` +} + +type AnswerCallStruct struct { + CallCreator types.JID `json:"callCreator"` + CallID string `json:"callId"` +} + +type HangupCallStruct struct { + CallID string `json:"callId"` +} +``` + +- [ ] **Step 3: Add `callRegistry` to the service struct and constructor** + +```go +type callService struct { + clientPointer map[string]*whatsmeow.Client + whatsmeowService whatsmeow_service.WhatsmeowService + callRegistry *call_registry.CallRegistry + loggerWrapper *logger_wrapper.LoggerManager +} +``` + +```go +func NewCallService( + clientPointer map[string]*whatsmeow.Client, + whatsmeowService whatsmeow_service.WhatsmeowService, + callRegistry *call_registry.CallRegistry, + loggerWrapper *logger_wrapper.LoggerManager, +) CallService { + return &callService{ + clientPointer: clientPointer, + whatsmeowService: whatsmeowService, + callRegistry: callRegistry, + loggerWrapper: loggerWrapper, + } +} +``` + +- [ ] **Step 4: Extend the `CallService` interface** + +```go +type CallService interface { + RejectCall(data *RejectCallStruct, instance *instance_model.Instance) error + AnswerCall(data *AnswerCallStruct, instance *instance_model.Instance) (*meowcaller.Call, error) + HangupCall(data *HangupCallStruct, instance *instance_model.Instance) error + GetActiveCall(instanceId, callId string) (*meowcaller.Call, error) +} +``` + +- [ ] **Step 5: Implement the three methods** + +Add after the existing `RejectCall` method: + +```go +func (c *callService) AnswerCall(data *AnswerCallStruct, instance *instance_model.Instance) (*meowcaller.Call, error) { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return nil, errors.New("no pending call with that id") + } + + if err := call.Answer(); err != nil { + logger.LogError("[%s] error answering call: %v", instance.Id, err) + return nil, err + } + + if call.IsVideo() { + if err := call.AcceptVideo(); err != nil { + c.loggerWrapper.GetLogger(instance.Id).LogError("[%s] answered call but failed to accept video: %v", instance.Id, err) + } + } + + return call, nil +} + +func (c *callService) HangupCall(data *HangupCallStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + + err := call.Hangup() + c.callRegistry.Delete(data.CallID) + if err != nil { + logger.LogError("[%s] error hanging up call: %v", instance.Id, err) + return err + } + return nil +} + +func (c *callService) GetActiveCall(instanceId, callId string) (*meowcaller.Call, error) { + call, ok := c.callRegistry.Get(instanceId, callId) + if !ok { + return nil, errors.New("no active call with that id") + } + return call, nil +} +``` + +- [ ] **Step 6: Build just this package** + +```bash +go build ./pkg/call/service/... +``` + +Expected: exits 0. (Don't run `go build ./...` yet — `cmd/evolution-go/main.go` still calls the old 3-argument `NewCallService` and won't compile until Task 8 fixes that call site; building only this package sidesteps that known, temporary gap.) + +- [ ] **Step 7: Commit** + +```bash +git add pkg/call/service/call_service.go +git commit -m "feat: add AnswerCall, HangupCall, GetActiveCall to call service" +``` + +--- + +### Task 5: `AnswerCall` / `HangupCall` handlers in `pkg/call/handler` + +**Files:** +- Modify: `pkg/call/handler/call_handler.go` + +**Interfaces:** +- Consumes: `call_service.CallService.AnswerCall`, `.HangupCall` (Task 4) +- Produces: `CallHandler.AnswerCall(ctx *gin.Context)`, `CallHandler.HangupCall(ctx *gin.Context)` + +- [ ] **Step 1: Extend the `CallHandler` interface** + +```go +type CallHandler interface { + RejectCall(ctx *gin.Context) + AnswerCall(ctx *gin.Context) + HangupCall(ctx *gin.Context) +} +``` + +- [ ] **Step 2: Implement `AnswerCall`** + +Add after the existing `RejectCall` method, following its exact shape: + +```go +// Answer call +// @Summary Answer call +// @Description Answer an incoming call and (if it's a video call) accept its video +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.AnswerCallStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/answer [post] +func (g *callHandler) AnswerCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.AnswerCallStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + _, err = g.callService.AnswerCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} +``` + +- [ ] **Step 3: Implement `HangupCall`** + +```go +// Hangup call +// @Summary Hangup call +// @Description Hangup an active call +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.HangupCallStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/hangup [post] +func (g *callHandler) HangupCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.HangupCallStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.HangupCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} +``` + +- [ ] **Step 4: Build just this package** + +```bash +go build ./pkg/call/handler/... +``` + +Expected: exits 0. + +- [ ] **Step 5: Commit** + +```bash +git add pkg/call/handler/call_handler.go +git commit -m "feat: add answer and hangup call HTTP handlers" +``` + +--- + +### Task 6: Register the new routes + +**Files:** +- Modify: `pkg/routes/routes.go` + +**Interfaces:** +- Consumes: `call_handler.CallHandler.AnswerCall`, `.HangupCall` (Task 5) + +- [ ] **Step 1: Add the two routes to the existing `/call` group** + +Find (around line 192-198): + +```go + routes = eng.Group("/call") + { + routes.Use(r.authMiddleware.Auth) + { + routes.POST("/reject", r.jidValidationMiddleware.ValidateNumberField(), r.callHandler.RejectCall) + } + } +``` + +Change to: + +```go + routes = eng.Group("/call") + { + routes.Use(r.authMiddleware.Auth) + { + routes.POST("/reject", r.jidValidationMiddleware.ValidateNumberField(), r.callHandler.RejectCall) + routes.POST("/answer", r.jidValidationMiddleware.ValidateNumberField(), r.callHandler.AnswerCall) + routes.POST("/hangup", r.callHandler.HangupCall) + } + } +``` + +(`/answer`'s body has a `callCreator` field, same shape as `/reject`, so it gets the same `ValidateNumberField()` call for consistency with its sibling route — note this middleware validates a field literally named `number`, which neither `/reject` nor `/answer` actually send, so in practice it's a no-op passthrough for both; that's pre-existing behavior in this file, not something this task changes. `/hangup`'s body has no JID-shaped field, so it gets no JID middleware, matching how routes without JID fields elsewhere in this file skip it too.) + +`GET /call/stream/:callId` is intentionally **not** added here — it needs query-string apikey auth (WebSocket clients can't always set custom headers), which doesn't fit `authMiddleware.Auth`'s header-only check. Task 7 registers it directly on the `*gin.Engine`, the same way `pkg/passkey/handler` already registers its own public routes outside this file (see `passkey_handler.RegisterRoutes(r, whatsmeowService)` in `cmd/evolution-go/main.go`). + +- [ ] **Step 2: Build just this package** + +```bash +go build ./pkg/routes/... +``` + +Expected: exits 0. + +- [ ] **Step 3: Commit** + +```bash +git add pkg/routes/routes.go +git commit -m "feat: register call answer and hangup routes" +``` + +--- + +### Task 7: `pkg/call/stream` — the WebSocket media bridge + +**Files:** +- Create: `pkg/call/stream/codec.go` +- Test: `pkg/call/stream/codec_test.go` +- Create: `pkg/call/stream/bridge.go` +- Create: `pkg/call/stream/handler.go` + +**Interfaces:** +- Consumes: `call_service.CallService.GetActiveCall` (Task 4); `instance_service.InstanceService.GetInstanceByToken` (existing); `meowcaller.SampleRate`, `meowcaller.AudioSink`, `meowcaller.AudioSource`, `meowcaller.VideoSink`, `meowcaller.Call.{Receive,ReceiveVideo,Play,OnEnd,Hangup,IsVideo,ID}` (external library) +- Produces: `call_stream.RegisterRoutes(r *gin.Engine, callService call_service.CallService, instanceService instance_service.InstanceService)` + +#### Part A: pure PCM16LE ⇄ float32 conversion (TDD, no I/O) + +- [ ] **Step 1: Write the failing test** + +```go +// pkg/call/stream/codec_test.go +package call_stream + +import "testing" + +func TestPCM16RoundTrip(t *testing.T) { + frame := []float32{0, 0.5, -0.5, 1, -1, 0.25} + + pcm := pcm16FromFloat32(frame) + if len(pcm) != len(frame)*2 { + t.Fatalf("expected %d bytes, got %d", len(frame)*2, len(pcm)) + } + + back := float32FromPCM16(pcm) + if len(back) != len(frame) { + t.Fatalf("expected %d samples back, got %d", len(frame), len(back)) + } + + for i, want := range frame { + got := back[i] + diff := got - want + if diff < 0 { + diff = -diff + } + if diff > 0.001 { + t.Errorf("sample %d: want %v, got %v (diff %v)", i, want, got, diff) + } + } +} + +func TestPCM16ClampsOutOfRange(t *testing.T) { + frame := []float32{2.0, -2.0} // out of [-1, 1] range + pcm := pcm16FromFloat32(frame) + back := float32FromPCM16(pcm) + + if back[0] < 0.99 { + t.Errorf("expected clamp to max positive, got %v", back[0]) + } + if back[1] > -0.99 { + t.Errorf("expected clamp to max negative, got %v", back[1]) + } +} +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `go test ./pkg/call/stream/... -v` +Expected: FAIL — `pcm16FromFloat32`/`float32FromPCM16` undefined. + +- [ ] **Step 3: Write the implementation** + +```go +// pkg/call/stream/codec.go +package call_stream + +import "encoding/binary" + +// pcm16FromFloat32 converts one mono PCM frame (as meowcaller delivers it: float32 +// samples in [-1, 1]) into little-endian 16-bit PCM bytes, clamping out-of-range +// samples the same way meowcaller's own WAVRecorder does. +func pcm16FromFloat32(frame []float32) []byte { + out := make([]byte, len(frame)*2) + for i, s := range frame { + v := s * 32768.0 + if v > 32767 { + v = 32767 + } else if v < -32768 { + v = -32768 + } + binary.LittleEndian.PutUint16(out[2*i:], uint16(int16(v))) + } + return out +} + +// float32FromPCM16 converts little-endian 16-bit PCM bytes (as sent by a stream +// consumer) back into mono float32 samples in [-1, 1] for meowcaller.Call.Play. +func float32FromPCM16(b []byte) []float32 { + n := len(b) / 2 + out := make([]float32, n) + for i := 0; i < n; i++ { + v := int16(binary.LittleEndian.Uint16(b[2*i:])) + out[i] = float32(v) / 32768.0 + } + return out +} +``` + +- [ ] **Step 4: Run test to verify it passes** + +Run: `go test ./pkg/call/stream/... -v` +Expected: PASS (2 tests) + +- [ ] **Step 5: Commit** + +```bash +git add pkg/call/stream/codec.go pkg/call/stream/codec_test.go +git commit -m "feat: add PCM16LE/float32 conversion for call media stream" +``` + +#### Part B: the bridge (implements AudioSink + VideoSink + AudioSource) + +- [ ] **Step 1: Write the bridge** + +```go +// pkg/call/stream/bridge.go +package call_stream + +import ( + "encoding/base64" + "io" + "sync" + + "github.com/gorilla/websocket" + "github.com/purpshell/meowcaller" +) + +// wsMessage is the JSON envelope carried over the stream socket, modeled on Twilio +// Media Streams so existing AI-voice integrations need minimal adapting. +type wsMessage struct { + Event string `json:"event"` + CallID string `json:"callId,omitempty"` + SampleRate int `json:"sampleRate,omitempty"` + Video bool `json:"video,omitempty"` + Track string `json:"track,omitempty"` + Payload string `json:"payload,omitempty"` + Reason string `json:"reason,omitempty"` +} + +// bridge adapts one WebSocket connection to meowcaller's AudioSink (Call.Receive), +// VideoSink (Call.ReceiveVideo), and AudioSource (Call.Play) interfaces, so a single +// object plugs a call's media straight into the socket in both directions. +type bridge struct { + conn *websocket.Conn + writeMu sync.Mutex + incoming chan []float32 + closed chan struct{} + closeOnce sync.Once +} + +func newBridge(conn *websocket.Conn) *bridge { + return &bridge{ + conn: conn, + // ~3 seconds of buffering at one 60ms frame per slot before frames start + // getting dropped — enough slack for scheduling jitter without unbounded growth. + incoming: make(chan []float32, 50), + closed: make(chan struct{}), + } +} + +func (b *bridge) writeJSON(msg wsMessage) error { + b.writeMu.Lock() + defer b.writeMu.Unlock() + return b.conn.WriteJSON(msg) +} + +// writeStart sends the initial handshake message once the socket is up. +func (b *bridge) writeStart(callID string, video bool) { + _ = b.writeJSON(wsMessage{ + Event: "start", + CallID: callID, + SampleRate: meowcaller.SampleRate, + Video: video, + }) +} + +// WriteFrame implements meowcaller.AudioSink: one decoded mono frame from the peer. +func (b *bridge) WriteFrame(frame []float32) error { + payload := base64.StdEncoding.EncodeToString(pcm16FromFloat32(frame)) + return b.writeJSON(wsMessage{Event: "media", Track: "inbound", Payload: payload}) +} + +// WriteVideo implements meowcaller.VideoSink: one Annex-B H.264 access unit. +func (b *bridge) WriteVideo(accessUnit []byte) error { + payload := base64.StdEncoding.EncodeToString(accessUnit) + return b.writeJSON(wsMessage{Event: "video", Track: "inbound", Payload: payload}) +} + +// ReadFrame implements meowcaller.AudioSource: frames the consumer sent back over the +// socket, decoded by readLoop and handed here on demand. +func (b *bridge) ReadFrame() ([]float32, error) { + select { + case frame, ok := <-b.incoming: + if !ok { + return nil, io.EOF + } + return frame, nil + case <-b.closed: + return nil, io.EOF + } +} + +// Close satisfies AudioSink/VideoSink/AudioSource's shared Close() error method. Safe +// to call more than once (from the call's OnEnd callback and from readLoop exiting). +func (b *bridge) Close() error { + b.closeOnce.Do(func() { + _ = b.writeJSON(wsMessage{Event: "stop", Reason: "hangup"}) + close(b.closed) + _ = b.conn.Close() + }) + return nil +} + +// readLoop blocks reading consumer-sent media messages until the connection closes +// (by either side) or send Close(). Every non-media message is ignored rather than +// erroring, so the wire format can grow new event types without breaking old clients. +func (b *bridge) readLoop() { + for { + var msg wsMessage + if err := b.conn.ReadJSON(&msg); err != nil { + b.Close() + return + } + if msg.Event != "media" || msg.Track != "outbound" { + continue + } + raw, err := base64.StdEncoding.DecodeString(msg.Payload) + if err != nil { + continue + } + frame := float32FromPCM16(raw) + select { + case b.incoming <- frame: + case <-b.closed: + return + default: + // Consumer is sending audio faster than the call can play it out; drop + // the frame rather than block the socket read loop. + } + } +} +``` + +- [ ] **Step 2: Build** + +```bash +go build ./pkg/call/stream/... +``` + +Expected: exits 0. + +- [ ] **Step 3: Commit** + +```bash +git add pkg/call/stream/bridge.go +git commit -m "feat: add WebSocket bridge implementing meowcaller media interfaces" +``` + +#### Part C: the HTTP/WS handler + +- [ ] **Step 1: Write the handler** + +```go +// pkg/call/stream/handler.go +package call_stream + +import ( + "net/http" + + call_service "github.com/evolution-foundation/evolution-go/pkg/call/service" + instance_service "github.com/evolution-foundation/evolution-go/pkg/instance/service" + "github.com/gin-gonic/gin" + "github.com/gorilla/websocket" +) + +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: func(r *http.Request) bool { return true }, +} + +// RegisterRoutes mounts GET /call/stream/:callId directly on the engine, bypassing the +// header-based authMiddleware chain used by pkg/routes: WebSocket clients (especially +// browser-based ones) can't always set a custom apikey header on the upgrade request, +// so auth here is a query parameter instead, resolved the same way authMiddleware.Auth +// resolves it. This mirrors how pkg/passkey/handler.RegisterRoutes already registers +// its own routes directly on *gin.Engine for the same "doesn't fit the standard +// middleware chain" reason. +func RegisterRoutes(r *gin.Engine, callService call_service.CallService, instanceService instance_service.InstanceService) { + r.GET("/call/stream/:callId", serveStream(callService, instanceService)) +} + +func serveStream(callService call_service.CallService, instanceService instance_service.InstanceService) gin.HandlerFunc { + return func(ctx *gin.Context) { + instance, err := instanceService.GetInstanceByToken(ctx.Query("apikey")) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "not authorized"}) + return + } + + callID := ctx.Param("callId") + call, err := callService.GetActiveCall(instance.Id, callID) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": err.Error()}) + return + } + + conn, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil) + if err != nil { + return + } + + b := newBridge(conn) + call.OnEnd(func(reason string) { b.Close() }) + call.Receive(b) + call.ReceiveVideo(b) + call.Play(b) + + b.writeStart(callID, call.IsVideo()) + b.readLoop() // blocks until the socket closes, from either end + + _ = call.Hangup() + } +} +``` + +- [ ] **Step 2: Build just this package** + +```bash +go build ./pkg/call/stream/... +``` + +Expected: exits 0. + +- [ ] **Step 3: Commit** + +```bash +git add pkg/call/stream/handler.go +git commit -m "feat: add call stream HTTP/WebSocket handler" +``` + +--- + +### Task 8: Wire everything together in `main.go` + +**Files:** +- Modify: `cmd/evolution-go/main.go` + +**Interfaces:** +- Consumes: `call_registry.NewCallRegistry` (Task 2), `whatsmeow_service.NewWhatsmeowService`'s new param (Task 3), `call_service.NewCallService`'s new param (Task 4), `call_stream.RegisterRoutes` (Task 7) + +- [ ] **Step 1: Add imports** + +```go + call_registry "github.com/evolution-foundation/evolution-go/pkg/call/registry" + call_stream "github.com/evolution-foundation/evolution-go/pkg/call/stream" +``` + +- [ ] **Step 2: Create the shared registry alongside `clientPointer`** + +Find (around line 87): + +```go + killChannel := make(map[string](chan bool)) + clientPointer := make(map[string]*whatsmeow.Client) +``` + +Change to: + +```go + killChannel := make(map[string](chan bool)) + clientPointer := make(map[string]*whatsmeow.Client) + callRegistry := call_registry.NewCallRegistry() +``` + +- [ ] **Step 3: Pass it into `NewWhatsmeowService`** + +Find the `whatsmeowService := whatsmeow_service.NewWhatsmeowService(...)` call (around line 165) and add `callRegistry,` as the new second-to-last argument (matching the parameter position added in Task 3 Step 3): + +```go + whatsmeowService := whatsmeow_service.NewWhatsmeowService( + instanceRepository, + authDB, + message_repository.NewMessageRepository(db), + labelRepository, + config, + killChannel, + clientPointer, + rabbitmqProducer, + webhookProducer, + websocketProducer, + sqliteDB, + exPath, + mediaStorage, + natsProducer, + callRegistry, + loggerWrapper, + ) +``` + +- [ ] **Step 4: Pass it into `NewCallService`** + +Find (around line 195): + +```go + callService := call_service.NewCallService(clientPointer, whatsmeowService, loggerWrapper) +``` + +Change to: + +```go + callService := call_service.NewCallService(clientPointer, whatsmeowService, callRegistry, loggerWrapper) +``` + +- [ ] **Step 5: Register the stream route** + +Find the existing: + +```go + passkey_handler.RegisterRoutes(r, whatsmeowService) +``` + +Add right after it: + +```go + call_stream.RegisterRoutes(r, callService, instanceService) +``` + +(`instanceService` is already constructed a few lines above this point in the same function.) + +- [ ] **Step 6: Tidy modules now that `meowcaller` is actually imported, then build** + +This is the first point in the plan where real code imports `meowcaller` (Tasks 3, 4, +and 7 all added imports of it), so `go mod tidy` is now safe to run — it has something +to keep. Task 1 deliberately skipped this step for exactly that reason. + +```bash +go mod tidy +grep meowcaller go.mod +``` + +Expected: the `grep` still shows the `github.com/purpshell/meowcaller` line (confirming +`tidy` kept it now that it's actually used). + +```bash +go build ./... +``` + +Expected: exits 0 — this is the point where every wiring gap from Tasks 4-7 gets closed. + +- [ ] **Step 7: Run the full test suite** + +```bash +go test ./... +``` + +Expected: PASS across the repo (including the pre-existing 4 test files and the new tests from Tasks 2 and 7). + +- [ ] **Step 8: Format and lint** + +```bash +make fmt +make lint +``` + +Expected: both exit 0. If `make fmt` rewrites anything, re-run `go build ./...` and `go test ./...` once more before committing. + +- [ ] **Step 9: Commit** + +```bash +git add cmd/evolution-go/main.go +git commit -m "feat: wire call registry and stream route into main" +``` + +--- + +### Task 9: Manual end-to-end validation and PR prep + +**Files:** +- Modify: `docs/superpowers/plans/2026-07-29-call-answer-stream.md` (check off as validated) + +This is the step that actually proves the feature works — everything up to here only proves it compiles and the pure-logic pieces are correct. Do not open the PR before this passes. + +- [ ] **Step 1: Run the server locally against a real test instance** + +Follow the repo's existing local-run instructions (`README.md` / `docker/`) to start Evolution Go pointed at a WhatsApp test number you control, and confirm the instance shows `connected: true`. + +- [ ] **Step 2: Trigger an incoming call** + +From a second phone, place a WhatsApp voice call to the test number. Confirm (via logs) the line added in Task 3 Step 4 fires: + +``` +[] meowcaller captured incoming call from +``` + +- [ ] **Step 3: Answer it via the API** + +```bash +curl -X POST http://localhost:/call/answer \ + -H "apikey: " \ + -H "Content-Type: application/json" \ + -d '{"callCreator": "", "callId": ""}' +``` + +Expected: `{"message":"success"}`, and the call actually connects on the calling phone (no more "Connecting…"). + +- [ ] **Step 4: Connect a throwaway WS client and confirm audio** + +Use any small script (Python `websockets`, `wscat`, etc.) to connect to `ws://localhost:/call/stream/?apikey=`, write every `{"event":"media","track":"inbound",...}` message's decoded, base64-decoded, PCM16LE payload to a raw file, then convert that raw file to WAV (16-bit, mono, 16000 Hz) with any audio tool. Speak into the calling phone during the call. Confirm the resulting WAV is intelligible speech. + +- [ ] **Step 5: Confirm hangup behavior both ways** + +- Call `POST /call/hangup` with the same `callId` — confirm the call actually ends on the calling phone, and the WS connection receives `{"event":"stop","reason":"hangup"}` and closes. +- On a second test call, hang up from the *calling phone* instead — confirm the WS connection closes on its own (via `Call.OnEnd` → `bridge.Close()`) without needing `/call/hangup`. + +- [ ] **Step 6: Update Swagger** + +```bash +make swagger +git add docs/ +git commit -m "docs: regenerate swagger for call answer/hangup endpoints" +``` + +- [ ] **Step 7: Push the branch and open the PR** + +```bash +git push -u origin feature/call-answer-stream +gh pr create \ + --repo evolution-foundation/evolution-go \ + --title "feat: answer WhatsApp calls and stream their media over WebSocket" \ + --body "$(cat <<'EOF' +## Summary + +- Adds `POST /call/answer` and `POST /call/hangup`, alongside the existing `POST /call/reject`. +- Adds `GET /call/stream/:callId`, a dedicated per-call WebSocket that carries the + call's audio (and inbound video) as base64 PCM16LE/H.264 frames, in a JSON envelope + modeled on Twilio Media Streams. Sending `{"event":"media","track":"outbound",...}` + back over the same socket plays audio into the call (e.g. TTS output). +- This PR ships transport/plumbing only — no AI/STT/LLM/TTS logic lives here. What's on + the other end of the WebSocket (an AI voice pipeline, a recorder, a human console) is + entirely up to the consumer. + +## Why + +`go.mau.fi/whatsmeow` (this project's WhatsApp protocol library) has never implemented +accepting a call or handling its media — only rejecting. Building that from scratch is a +multi-year reverse-engineering effort (see `tulir/whatsmeow#555`). +[`purpshell/meowcaller`](https://github.com/purpshell/meowcaller) (MIT-licensed, pure Go, +actively maintained) already did that work as an independent interoperability research +project — see its [DISCLAIMER.md](https://github.com/purpshell/meowcaller/blob/main/DISCLAIMER.md) +for its scope and ground rules. This PR wires it into Evolution Go's existing per-instance +client lifecycle. + +## How it's wired + +`meowcaller.NewClient` is constructed the moment each instance's `*whatsmeow.Client` is +created, before `.Connect()` (required by the library). Incoming calls are captured via +`OnIncomingCall` into a small new `pkg/call/registry` package, scoped by instance so one +instance's apikey can't reach another instance's call. `pkg/call/service` answers/hangs +up by looking calls up in that registry. `pkg/call/stream` bridges a call's audio/video +sinks and source to the WebSocket. + +## Test plan + +- [x] Unit tests for the call registry (`pkg/call/registry`) and PCM16LE/float32 + conversion (`pkg/call/stream`) +- [x] `go build ./...` and `go test ./...` pass +- [x] `make fmt` / `make lint` clean +- [x] Manually verified against a real WhatsApp call: answered via the API, recorded + intelligible audio from the stream socket, confirmed hangup both via the API and + via the remote end hanging up first +EOF +)" +``` + +- [ ] **Step 8: Check off validation in this plan** + +Edit this file's Task 9 checkboxes to `[x]` once every step above has actually been run and passed, and commit that update too. + +--- + +## Self-Review Notes + +- **Spec coverage:** every section of `docs/superpowers/specs/2026-07-29-call-answer-stream-design.md` maps to a task — architecture/constraint (Task 3), components (Tasks 2, 4, 5, 6, 7), wire format (Task 7 Part B), auth (Task 7 Part C), lifecycle/error handling (Tasks 3 Step 5, 4 Step 5, 7 Part B `Close`/`OnEnd`), testing (Tasks 2, 7 Part A automated; Task 9 manual), PR plan (Task 9 Steps 6-7). +- **Type consistency checked:** `AnswerCallStruct`/`HangupCallStruct` (Task 4) match what Task 5's handlers bind into; `CallService` interface additions (Task 4 Step 4) match the concrete methods implemented in the same task and the calls made from Task 7's handler; `call_registry.CallRegistry`'s `Store(instanceID string, call *meowcaller.Call)`/`Get(instanceID, callID string)`/`Delete(callID string)` signatures are identical everywhere they're called (Tasks 3, 4). +- **No placeholders:** every step has complete, real code — the only two forward references (`NewCallService`'s call site in `main.go`, fixed in Task 8; the intermediate `go build` failures in Tasks 4-7) are explicitly called out as expected and temporary, with the exact fixing task named. diff --git a/docs/superpowers/specs/2026-07-29-call-answer-stream-design.md b/docs/superpowers/specs/2026-07-29-call-answer-stream-design.md new file mode 100644 index 00000000..11c76756 --- /dev/null +++ b/docs/superpowers/specs/2026-07-29-call-answer-stream-design.md @@ -0,0 +1,135 @@ +# Design: Answer WhatsApp Calls + Bidirectional Media Stream + +Date: 2026-07-29 +Status: Approved for planning + +## Problem + +Evolution Go exposes `POST /call/reject` (see `pkg/call/handler/call_handler.go` and +`pkg/call/service/call_service.go`) but has no way to accept an incoming call or access +its audio/video. This is not a gap specific to Evolution Go: the underlying +`go.mau.fi/whatsmeow` client only parses call signaling (offer/accept/preaccept/ +transport/terminate) and can reject — it never implemented accepting a call or handling +the actual encrypted media stream. Building that from scratch means reverse-engineering +WhatsApp's proprietary call media protocol, which is a multi-year, multi-attempt effort +documented in `tulir/whatsmeow#555`. + +`github.com/purpshell/meowcaller` (MIT, actively maintained, pure Go, no CGO) already +did this work as an interoperability research project. It wraps a `*whatsmeow.Client` +and exposes: `OnIncomingCall`, `Call.Answer()`, `Call.Reject()`, `Call.Hangup()`, +`Call.AcceptVideo()`/`StartVideo()`, `Call.Play(AudioSource)`, `Call.Receive(AudioSink)`, +`Call.ReceiveVideo(VideoSink)`. Audio is delivered as 16 kHz mono `float32` PCM in +960-sample (60 ms) frames (`FrameSamples = 960`, `SampleRate = 16000` in `audio.go`); +video is H.264 Annex B access units (`VideoSink.WriteVideo([]byte)`). + +Goal: add generic infrastructure to Evolution Go so an incoming call can be answered and +its audio/video piped to an external system (an AI voice pipeline, a human operator +console, a recorder — Evolution Go stays agnostic to what's on the other end). This +mirrors how Evolution already lets Chatwoot/Typebot/OpenAI plug into messaging via +webhook/websocket/RabbitMQ/NATS — except the existing event producers are unidirectional, +fire-and-forget JSON events, unsuited to a sustained, low-latency, two-way audio/video +stream. This feature therefore needs its own dedicated channel, not a new event type +bolted onto the existing producers. + +Explicitly out of scope: no AI/STT/LLM/TTS logic lives in Evolution Go. This PR only +ships the plumbing; whatever consumes the stream is the caller's problem. + +## Constraint that shapes the architecture + +`meowcaller.NewClient(wa)` must be called **before** `wa.Connect()` — the doc comment on +`NewClient` is explicit: "Construct it before connecting whatsmeow so the raw call +adapter can be installed safely." In `pkg/whatsmeow/service/whatsmeow.go`, the +whatsmeow client is created and stored at lines 413–415 +(`client := whatsmeow.NewClient(...)`; `w.clientPointer[cd.Instance.Id] = client`), and +`.Connect()` is called later in several branches (lines ~507–559 and ~2061). This means +the meowcaller client cannot be lazily created inside `pkg/call/service` the way +`ensureClientConnected` currently lazily starts instances — it must be created in +`whatsmeow.go` at client-creation time, alongside `clientPointer`. + +## Components + +Following the existing Handler → Service → Repository convention +(`docs/wiki/desenvolvimento/contributing.md`): + +- **`pkg/whatsmeow/service`**: add `meowcallerPointer map[string]*meowcaller.Client` + alongside the existing `clientPointer`. Populated at the same point `clientPointer` is + populated, before `Connect()`. Exposes a getter so `pkg/call/service` can look up the + meowcaller client for an instance. +- **`pkg/call/service`**: add a call registry (`map[callID]*meowcaller.Call`, mutex- + guarded, matching the style of `CallRegistry` internal to meowcaller but scoped to + what Evolution Go needs: lookup by callID for answer/hangup/stream-attach). New + interface methods: + - `AnswerCall(data *AnswerCallStruct, instance *Instance) (*meowcaller.Call, error)` + - `HangupCall(data *HangupCallStruct, instance *Instance) error` + - `GetActiveCall(instanceId, callId string) (*meowcaller.Call, error)` — used by the + stream bridge. +- **`pkg/call/handler`**: new REST endpoints, same shape as the existing `RejectCall`: + - `POST /call/answer` — body `{callCreator, callId}`. Calls `AnswerCall`; if the + incoming call's `IsVideo()` is true, also calls `Call.AcceptVideo()`. + - `POST /call/hangup` — body `{callId}`. +- **`pkg/call/stream`** (new package): the WebSocket bridge. One connection per call. + Implements `meowcaller.AudioSink`/`VideoSink` (writes frames out to the socket) and + `meowcaller.AudioSource` (reads frames the remote client sends back, feeds + `Call.Play`). +- **`pkg/routes/routes.go`**: register `POST /call/answer`, `POST /call/hangup` in the + existing `/call` group (auth middleware applies, same as `/call/reject`), and + `GET /call/stream/:callId` as its own route (WS upgrade, can't sit behind the same + auth middleware chain — needs upgrade-compatible auth, see below). + +## Wire format (`GET /call/stream/:callId?apikey=...`) + +Modeled on Twilio Media Streams, since AI voice vendors' existing WhatsApp/Twilio +bridges already speak a message shape like this — minimizes adapter work for whoever +consumes it: + +```json +{"event": "start", "callId": "...", "sampleRate": 16000, "video": true} +{"event": "media", "track": "inbound", "payload": ""} +{"event": "media", "track": "outbound", "payload": ""} +{"event": "video", "track": "inbound", "payload": ""} +{"event": "stop", "reason": "hangup"} +``` + +The bridge converts `meowcaller`'s `[]float32` frames to PCM16LE for the `inbound` +track, and decodes base64 PCM16LE from `outbound` messages back to `[]float32` for +`Call.Play`. Video is inbound-only in this PR (receiving/recording the peer's video); +sending synthetic video back is not implemented (no known driver for it here — call +audio is the primary use case, video send can be a follow-up if someone needs it). + +## Auth + +WebSocket upgrades can't rely on custom headers from every possible client, so this +follows the existing pattern in `pkg/events/websocket/websocket_producer.go`: apikey as +a query parameter, validated against the instance before the upgrade completes. + +## Lifecycle / error handling + +- Remote hangs up → meowcaller's engine dispatches `CallTerminate` → bridge sends + `{"event":"stop","reason":"hangup"}` and closes the socket. +- Consumer's WebSocket closes (crash, disconnect) → bridge calls `Call.Hangup()` so the + WhatsApp call doesn't hang open with no one listening. +- `POST /call/answer` for an unknown/expired callId → `404`, same convention as + `RejectCall`'s error handling. +- `GET /call/stream/:callId` for a call not yet answered, or already terminated → + reject the upgrade with `4004`-equivalent close code. + +## Testing + +- Unit tests in `pkg/call/service` and `pkg/call/stream` against a small interface + wrapping the `meowcaller.Client`/`Call` types (mockable), covering answer/hangup/ + registry lookup and the PCM16LE ⇄ float32 conversion in the bridge. +- Manual validation (real WhatsApp test number, since this can't be meaningfully faked): + place a call to the number connected to a test instance, `POST /call/answer`, connect + a throwaway WS client that dumps the `inbound` track to a WAV file, confirm the + recording is intelligible speech. + +## PR plan + +Branch `feature/call-answer-stream` off `main` in the fork +(`RamonBritoDev/evolution-go`), Conventional Commits (`feat: ...`), PR against +`evolution-foundation/evolution-go` per `docs/wiki/desenvolvimento/contributing.md`. +The PR description calls out the new `meowcaller` dependency (MIT-licensed, compatible +with Evolution Go's Apache-2.0 license), links `meowcaller`'s `DISCLAIMER.md` (framed as +independent interoperability research, not affiliated with Meta, with explicit misuse +ground rules), and states clearly that this PR ships transport/plumbing only — no AI +logic — so reviewers aren't evaluating an opinionated AI stack. diff --git a/docs/swagger.json b/docs/swagger.json index 7cfe913e..d1a2f65c 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -7,6 +7,246 @@ "version": "1.0" }, "paths": { + "/call/answer": { + "post": { + "description": "Answer an incoming call and (if it's a video call) accept its video", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Answer call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.AnswerCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/dial": { + "post": { + "description": "Spike/experimental: places an outbound call, not part of the reviewed answer-call plan", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Place an outbound call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.DialCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/handraise": { + "post": { + "description": "Spike/experimental: toggles this client's hand-raised state", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Raise or lower hand in a call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.HandRaiseStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/hangup": { + "post": { + "description": "Hangup an active call", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Hangup call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.HangupCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/participant/add": { + "post": { + "description": "Spike/experimental: adds a participant, upgrading a 1:1 call into a group call", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Add a participant to an active call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.AddParticipantStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/react": { + "post": { + "description": "Spike/experimental: sends an emoji reaction into an active call", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Send a call reaction", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.ReactCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, "/call/reject": { "post": { "description": "Reject call", @@ -27,7 +267,167 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_call_service.RejectCallStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.RejectCallStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/screenshare": { + "post": { + "description": "Spike/experimental: toggles this client's screen share state", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Start or stop screen sharing in a call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.ScreenShareStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/video/enabled": { + "post": { + "description": "Spike/experimental: wraps Call.SetVideoEnabled", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Mute or unmute outbound video without renegotiating the upgrade", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoEnabledStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/video/orientation": { + "post": { + "description": "Spike/experimental: wraps Call.SetVideoOrientation (0-3 quarter turns clockwise)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Announce this client's camera orientation", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoOrientationStruct" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/gin.H" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/gin.H" + } + } + } + } + }, + "/call/video/upgrade": { + "post": { + "description": "Spike/experimental: requests an audio\u003c-\u003evideo upgrade (Call.StartVideo/StopVideo)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Call" + ], + "summary": "Start or stop sending outbound video mid-call", + "parameters": [ + { + "description": "Call data", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoUpgradeStruct" } } ], @@ -67,7 +467,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -113,7 +513,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.HistorySyncRequestStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.HistorySyncRequestStruct" } } ], @@ -159,7 +559,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -205,7 +605,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -251,7 +651,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -297,7 +697,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -343,7 +743,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct" } } ], @@ -389,7 +789,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct" } } ], @@ -435,7 +835,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.CreateCommunityStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.CreateCommunityStruct" } } ], @@ -481,7 +881,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct" } } ], @@ -527,7 +927,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.CreateGroupStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.CreateGroupStruct" } } ], @@ -573,7 +973,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupDescriptionStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupDescriptionStruct" } } ], @@ -619,7 +1019,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInfoStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInfoStruct" } } ], @@ -665,7 +1065,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInviteLinkStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInviteLinkStruct" } } ], @@ -711,7 +1111,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.JoinGroupStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.JoinGroupStruct" } } ], @@ -757,7 +1157,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.LeaveGroupStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.LeaveGroupStruct" } } ], @@ -861,7 +1261,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupNameStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupNameStruct" } } ], @@ -907,7 +1307,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.AddParticipantStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.AddParticipantStruct" } } ], @@ -953,7 +1353,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupPhotoStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupPhotoStruct" } } ], @@ -999,7 +1399,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.UpdateGroupSettingsStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.UpdateGroupSettingsStruct" } } ], @@ -1074,7 +1474,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ConnectStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ConnectStruct" } } ], @@ -1120,7 +1520,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.CreateStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.CreateStruct" } } ], @@ -1246,7 +1646,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ForceReconnectStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ForceReconnectStruct" } } ], @@ -1430,7 +1830,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.PairStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.PairStruct" } } ], @@ -1483,7 +1883,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.SetProxyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.SetProxyStruct" } } ], @@ -1661,7 +2061,7 @@ "200": { "description": "Advanced settings retrieved successfully", "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings" } }, "400": { @@ -1710,7 +2110,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings" } } ], @@ -1762,7 +2162,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct" } } ], @@ -1808,7 +2208,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.EditLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.EditLabelStruct" } } ], @@ -1883,7 +2283,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct" } } ], @@ -1909,89 +2309,6 @@ } } }, - "/license/activate": { - "get": { - "description": "Exchanges an authorization code (from the registration callback) for an api_key and persists it. Provide the code via the query string.", - "produces": [ - "application/json" - ], - "tags": [ - "License" - ], - "summary": "Activate license", - "parameters": [ - { - "type": "string", - "description": "Authorization code from the registration callback", - "name": "code", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "Activation result", - "schema": { - "$ref": "#/definitions/gin.H" - } - }, - "400": { - "description": "Missing code parameter", - "schema": { - "$ref": "#/definitions/gin.H" - } - } - } - } - }, - "/license/register": { - "get": { - "description": "Checks the GLOBAL_API_KEY with the licensing server. If not yet registered, initiates registration and returns a register_url. Accepts an optional redirect_uri for the post-registration redirect.", - "produces": [ - "application/json" - ], - "tags": [ - "License" - ], - "summary": "Register / get registration URL", - "parameters": [ - { - "type": "string", - "description": "Post-registration redirect URI", - "name": "redirect_uri", - "in": "query" - } - ], - "responses": { - "200": { - "description": "Registration state (status/message or register_url)", - "schema": { - "$ref": "#/definitions/gin.H" - } - } - } - } - }, - "/license/status": { - "get": { - "description": "Returns whether the instance license is active, along with the instance id and a masked api key.", - "produces": [ - "application/json" - ], - "tags": [ - "License" - ], - "summary": "Get license status", - "responses": { - "200": { - "description": "License status ({status, instance_id, api_key?})", - "schema": { - "$ref": "#/definitions/gin.H" - } - } - } - } - }, "/message/delete": { "post": { "description": "Delete a message for everyone", @@ -2012,7 +2329,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStruct" } } ], @@ -2058,7 +2375,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.DownloadMediaStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.DownloadMediaStruct" } } ], @@ -2104,7 +2421,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.EditMessageStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.EditMessageStruct" } } ], @@ -2150,7 +2467,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MarkPlayedStruct" } } ], @@ -2196,7 +2513,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MarkReadStruct" } } ], @@ -2242,7 +2559,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.ChatPresenceStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.ChatPresenceStruct" } } ], @@ -2288,7 +2605,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.ReactStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.ReactStruct" } } ], @@ -2334,7 +2651,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStatusStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStatusStruct" } } ], @@ -2380,7 +2697,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.CreateNewsletterStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.CreateNewsletterStruct" } } ], @@ -2426,7 +2743,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct" } } ], @@ -2472,7 +2789,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct" } } ], @@ -2547,7 +2864,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct" } } ], @@ -2593,7 +2910,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct" } } ], @@ -2810,7 +3127,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollResults" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.PollResults" } }, "400": { @@ -2854,7 +3171,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ButtonStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ButtonStruct" } } ], @@ -2900,7 +3217,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselStruct" } } ], @@ -2946,7 +3263,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ContactStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ContactStruct" } } ], @@ -2992,7 +3309,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LinkStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LinkStruct" } } ], @@ -3038,7 +3355,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ListStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ListStruct" } } ], @@ -3084,7 +3401,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LocationStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LocationStruct" } } ], @@ -3130,7 +3447,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.MediaStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.MediaStruct" } } ], @@ -3176,7 +3493,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.PollStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.PollStruct" } } ], @@ -3291,7 +3608,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StatusTextStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StatusTextStruct" } } ], @@ -3337,7 +3654,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StickerStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StickerStruct" } } ], @@ -3383,7 +3700,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.TextStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.TextStruct" } } ], @@ -3429,7 +3746,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct" } } ], @@ -3475,7 +3792,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct" } } ], @@ -3521,7 +3838,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.GetAvatarStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.GetAvatarStruct" } } ], @@ -3567,7 +3884,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct" } } ], @@ -3642,7 +3959,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct" } } ], @@ -3717,7 +4034,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct" } } ], @@ -3790,7 +4107,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.PrivacyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.PrivacyStruct" } } ], @@ -3830,7 +4147,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct" } } ], @@ -3876,7 +4193,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct" } } ], @@ -3922,7 +4239,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct" } } ], @@ -3968,7 +4285,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct" } } ], @@ -3993,25 +4310,132 @@ } } } - } - }, - "definitions": { - "gin.H": { + } + }, + "definitions": { + "gin.H": { + "type": "object", + "additionalProperties": {} + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.AddParticipantStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "number": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.AnswerCallStruct": { + "type": "object", + "properties": { + "callCreator": { + "$ref": "#/definitions/types.JID" + }, + "callId": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.DialCallStruct": { + "type": "object", + "properties": { + "number": { + "type": "string" + }, + "video": { + "type": "boolean" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.HandRaiseStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "raised": { + "type": "boolean" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.HangupCallStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.ReactCallStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "emoji": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.RejectCallStruct": { + "type": "object", + "properties": { + "callCreator": { + "$ref": "#/definitions/types.JID" + }, + "callId": { + "type": "string" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.ScreenShareStruct": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "start": { + "type": "boolean" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.VideoEnabledStruct": { "type": "object", - "additionalProperties": {} + "properties": { + "callId": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } }, - "github_com_EvolutionAPI_evolution-go_pkg_call_service.RejectCallStruct": { + "github_com_evolution-foundation_evolution-go_pkg_call_service.VideoOrientationStruct": { "type": "object", "properties": { - "callCreator": { - "$ref": "#/definitions/types.JID" + "callId": { + "type": "string" }, + "orientation": { + "type": "integer" + } + } + }, + "github_com_evolution-foundation_evolution-go_pkg_call_service.VideoUpgradeStruct": { + "type": "object", + "properties": { "callId": { "type": "string" + }, + "start": { + "type": "boolean" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct": { + "github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct": { "type": "object", "properties": { "chat": { @@ -4019,7 +4443,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_chat_service.HistorySyncRequestStruct": { + "github_com_evolution-foundation_evolution-go_pkg_chat_service.HistorySyncRequestStruct": { "type": "object", "properties": { "count": { @@ -4030,7 +4454,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct": { + "github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct": { "type": "object", "properties": { "communityJid": { @@ -4044,7 +4468,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_community_service.CreateCommunityStruct": { + "github_com_evolution-foundation_evolution-go_pkg_community_service.CreateCommunityStruct": { "type": "object", "properties": { "communityName": { @@ -4052,7 +4476,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.AddParticipantStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.AddParticipantStruct": { "type": "object", "properties": { "action": { @@ -4069,7 +4493,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.CreateGroupStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.CreateGroupStruct": { "type": "object", "properties": { "groupName": { @@ -4083,7 +4507,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInfoStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInfoStruct": { "type": "object", "properties": { "groupJid": { @@ -4091,7 +4515,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInviteLinkStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInviteLinkStruct": { "type": "object", "properties": { "groupJid": { @@ -4102,7 +4526,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.JoinGroupStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.JoinGroupStruct": { "type": "object", "properties": { "code": { @@ -4110,7 +4534,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.LeaveGroupStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.LeaveGroupStruct": { "type": "object", "properties": { "groupJid": { @@ -4118,7 +4542,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupDescriptionStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupDescriptionStruct": { "type": "object", "properties": { "description": { @@ -4129,7 +4553,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupNameStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupNameStruct": { "type": "object", "properties": { "groupJid": { @@ -4140,7 +4564,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupPhotoStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupPhotoStruct": { "type": "object", "properties": { "groupJid": { @@ -4151,7 +4575,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_group_service.UpdateGroupSettingsStruct": { + "github_com_evolution-foundation_evolution-go_pkg_group_service.UpdateGroupSettingsStruct": { "type": "object", "properties": { "action": { @@ -4163,7 +4587,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings": { + "github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings": { "type": "object", "properties": { "alwaysOnline": { @@ -4186,7 +4610,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.ConnectStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.ConnectStruct": { "type": "object", "properties": { "immediate": { @@ -4215,11 +4639,11 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.CreateStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.CreateStruct": { "type": "object", "properties": { "advancedSettings": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings" }, "instanceId": { "type": "string" @@ -4228,14 +4652,14 @@ "type": "string" }, "proxy": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ProxyConfig" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ProxyConfig" }, "token": { "type": "string" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.ForceReconnectStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.ForceReconnectStruct": { "type": "object", "properties": { "number": { @@ -4243,7 +4667,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.PairStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.PairStruct": { "type": "object", "properties": { "phone": { @@ -4257,7 +4681,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.ProxyConfig": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.ProxyConfig": { "type": "object", "properties": { "host": { @@ -4277,7 +4701,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_instance_service.SetProxyStruct": { + "github_com_evolution-foundation_evolution-go_pkg_instance_service.SetProxyStruct": { "type": "object", "required": [ "host", @@ -4301,7 +4725,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct": { + "github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct": { "type": "object", "properties": { "jid": { @@ -4312,7 +4736,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_label_service.EditLabelStruct": { + "github_com_evolution-foundation_evolution-go_pkg_label_service.EditLabelStruct": { "type": "object", "properties": { "color": { @@ -4329,7 +4753,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct": { + "github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct": { "type": "object", "properties": { "jid": { @@ -4343,7 +4767,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.ChatPresenceStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.ChatPresenceStruct": { "type": "object", "properties": { "delay": { @@ -4361,7 +4785,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.DownloadMediaStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.DownloadMediaStruct": { "type": "object", "properties": { "message": { @@ -4369,7 +4793,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.EditMessageStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.EditMessageStruct": { "type": "object", "properties": { "chat": { @@ -4383,7 +4807,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.MarkPlayedStruct": { "type": "object", "properties": { "id": { @@ -4397,7 +4821,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.MarkReadStruct": { "type": "object", "properties": { "id": { @@ -4411,7 +4835,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStatusStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStatusStruct": { "type": "object", "properties": { "id": { @@ -4419,7 +4843,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStruct": { "type": "object", "properties": { "chat": { @@ -4430,7 +4854,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_message_service.ReactStruct": { + "github_com_evolution-foundation_evolution-go_pkg_message_service.ReactStruct": { "type": "object", "properties": { "fromMe": { @@ -4450,7 +4874,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.CreateNewsletterStruct": { + "github_com_evolution-foundation_evolution-go_pkg_newsletter_service.CreateNewsletterStruct": { "type": "object", "properties": { "description": { @@ -4461,7 +4885,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct": { + "github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct": { "type": "object", "properties": { "key": { @@ -4469,7 +4893,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct": { + "github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct": { "type": "object", "properties": { "before_id": { @@ -4483,7 +4907,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct": { + "github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct": { "type": "object", "properties": { "jid": { @@ -4491,7 +4915,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollResults": { + "github_com_evolution-foundation_evolution-go_pkg_poll_model.PollResults": { "type": "object", "properties": { "optionCounts": { @@ -4513,18 +4937,18 @@ "voters": { "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.VoterInfo" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.VoterInfo" } }, "votes": { "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollVote" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.PollVote" } } } }, - "github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollVote": { + "github_com_evolution-foundation_evolution-go_pkg_poll_model.PollVote": { "type": "object", "properties": { "companyId": { @@ -4569,7 +4993,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_poll_model.VoterInfo": { + "github_com_evolution-foundation_evolution-go_pkg_poll_model.VoterInfo": { "type": "object", "properties": { "jid": { @@ -4592,7 +5016,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Button": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Button": { "type": "object", "properties": { "copyCode": { @@ -4661,14 +5085,14 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ButtonStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ButtonStruct": { "type": "object", "properties": { "buttons": { "description": "Buttons array. See combination rules on the parent type description.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Button" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Button" } }, "delay": { @@ -4714,7 +5138,7 @@ "description": "Quoted (reply-to) context.", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } ] }, @@ -4729,7 +5153,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselButtonStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselButtonStruct": { "type": "object", "properties": { "copyCode": { @@ -4764,7 +5188,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct": { "type": "object", "properties": { "text": { @@ -4774,7 +5198,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct": { "type": "object", "properties": { "imageUrl": { @@ -4798,14 +5222,14 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardStruct": { "type": "object", "properties": { "body": { "description": "Card body text (required).", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct" } ] }, @@ -4813,7 +5237,7 @@ "description": "Buttons shown on the card. See CarouselButtonStruct for combination rules.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselButtonStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselButtonStruct" } }, "footer": { @@ -4825,13 +5249,13 @@ "description": "Card header (media + title/subtitle).", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct" } ] } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselStruct": { "type": "object", "properties": { "body": { @@ -4843,7 +5267,7 @@ "description": "Cards displayed in order. At least one card is required.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardStruct" } }, "delay": { @@ -4869,13 +5293,13 @@ "description": "Quoted (reply-to) context.", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } ] } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ContactStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ContactStruct": { "type": "object", "properties": { "delay": { @@ -4900,14 +5324,14 @@ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "vcard": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_utils.VCardStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_utils.VCardStruct" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LinkStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LinkStruct": { "type": "object", "properties": { "delay": { @@ -4938,7 +5362,7 @@ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "text": { "type": "string" @@ -4951,7 +5375,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ListStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ListStruct": { "type": "object", "properties": { "buttonText": { @@ -4998,7 +5422,7 @@ "description": "Quoted (reply-to) context.", "allOf": [ { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } ] }, @@ -5006,7 +5430,7 @@ "description": "Sections with rows. At least one section with one row is required.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Section" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Section" } }, "title": { @@ -5016,7 +5440,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LocationStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LocationStruct": { "type": "object", "properties": { "address": { @@ -5053,11 +5477,11 @@ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.MediaStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.MediaStruct": { "type": "object", "properties": { "caption": { @@ -5091,7 +5515,7 @@ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "type": { "type": "string" @@ -5101,7 +5525,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.PollStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.PollStruct": { "type": "object", "properties": { "delay": { @@ -5138,11 +5562,11 @@ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct": { "type": "object", "properties": { "messageId": { @@ -5153,7 +5577,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Row": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Row": { "type": "object", "properties": { "description": { @@ -5173,14 +5597,14 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Section": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Section": { "type": "object", "properties": { "rows": { "description": "Rows inside this section.", "type": "array", "items": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Row" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Row" } }, "title": { @@ -5190,7 +5614,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StatusTextStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StatusTextStruct": { "type": "object", "properties": { "id": { @@ -5201,7 +5625,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StickerStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StickerStruct": { "type": "object", "properties": { "delay": { @@ -5226,14 +5650,14 @@ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "sticker": { "type": "string" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.TextStruct": { + "github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.TextStruct": { "type": "object", "properties": { "delay": { @@ -5261,14 +5685,14 @@ "type": "string" }, "quoted": { - "$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct" + "$ref": "#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct" }, "text": { "type": "string" } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct": { "type": "object", "properties": { "number": { @@ -5276,7 +5700,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct": { "type": "object", "properties": { "formatJid": { @@ -5290,7 +5714,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.GetAvatarStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.GetAvatarStruct": { "type": "object", "properties": { "number": { @@ -5301,7 +5725,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.PrivacyStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.PrivacyStruct": { "type": "object", "properties": { "callAdd": { @@ -5327,7 +5751,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct": { + "github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct": { "type": "object", "properties": { "image": { @@ -5335,7 +5759,7 @@ } } }, - "github_com_EvolutionAPI_evolution-go_pkg_utils.VCardStruct": { + "github_com_evolution-foundation_evolution-go_pkg_utils.VCardStruct": { "type": "object", "properties": { "fullName": { @@ -5507,6 +5931,9 @@ "description": "Whether the chat is a group chat or broadcast list.", "type": "boolean" }, + "isNewsletterStatus": { + "type": "boolean" + }, "mediaType": { "type": "string" }, @@ -5628,11 +6055,26 @@ "types.VerifiedName": { "type": "object", "properties": { + "actualActors": { + "type": "integer" + }, "certificate": { "$ref": "#/definitions/waVnameCert.VerifiedNameCertificate" }, "details": { "$ref": "#/definitions/waVnameCert.VerifiedNameCertificate_Details" + }, + "hostStorage": { + "type": "integer" + }, + "privacyModeTS": { + "type": "string" + }, + "verifiedLevel": { + "type": "string" + }, + "version": { + "type": "integer" } } }, @@ -5718,6 +6160,28 @@ } } }, + "waAICommon.AIProvenance": { + "type": "object", + "properties": { + "c2PaMetadata": { + "$ref": "#/definitions/waAICommon.AIProvenance_Metadata" + }, + "iptcMetadata": { + "$ref": "#/definitions/waAICommon.AIProvenance_Metadata" + } + } + }, + "waAICommon.AIProvenance_Metadata": { + "type": "object", + "properties": { + "createdWithGenAi": { + "type": "boolean" + }, + "editedWithGenAi": { + "type": "boolean" + } + } + }, "waAICommon.AIRegenerateMetadata": { "type": "object", "properties": { @@ -5839,6 +6303,12 @@ "waAICommon.BotAgentDeepLinkMetadata": { "type": "object", "properties": { + "clientPublicKey": { + "type": "array", + "items": { + "type": "integer" + } + }, "token": { "type": "string" } @@ -5932,7 +6402,11 @@ 62, 63, 64, - 65 + 65, + 66, + 67, + 68, + 69 ], "x-enum-varnames": [ "BotCapabilityMetadata_UNKNOWN", @@ -6000,7 +6474,11 @@ "BotCapabilityMetadata_UNIFIED_RESPONSE_AI_CONTENT_SEARCH_ENABLED", "BotCapabilityMetadata_UNIFIED_RESPONSE_MARKDOWN_LINKS_ENABLED", "BotCapabilityMetadata_AI_RICH_RESPONSE_MAPS_V2_ENABLED", - "BotCapabilityMetadata_AI_SUBSCRIPTION_METERING_ENABLED" + "BotCapabilityMetadata_AI_SUBSCRIPTION_METERING_ENABLED", + "BotCapabilityMetadata_RICH_RESPONSE_SPORTS_WIDGET_ENABLED", + "BotCapabilityMetadata_AI_RICH_RESPONSE_ARTIFACTS_ENABLED", + "BotCapabilityMetadata_AI_RICH_RESPONSE_EMAIL_CALENDAR_ENABLED", + "BotCapabilityMetadata_AI_RICH_RESPONSE_REMINDERS_ENABLED" ] }, "waAICommon.BotCommandMetadata": { @@ -6251,6 +6729,17 @@ } } }, + "waAICommon.BotHistoryShareMetadata": { + "type": "object", + "properties": { + "participantsMetadata": { + "type": "array", + "items": { + "$ref": "#/definitions/waAICommon.BotGroupParticipantMetadata" + } + } + } + }, "waAICommon.BotImagineMetadata": { "type": "object", "properties": { @@ -6490,6 +6979,9 @@ "botGroupMetadata": { "$ref": "#/definitions/waAICommon.BotGroupMetadata" }, + "botHistoryShareMetadata": { + "$ref": "#/definitions/waAICommon.BotHistoryShareMetadata" + }, "botInfrastructureDiagnostics": { "$ref": "#/definitions/waAICommon.BotInfrastructureDiagnostics" }, @@ -6657,7 +7149,8 @@ 47, 54, 55, - 56 + 56, + 57 ], "x-enum-varnames": [ "BotMetricsEntryPoint_UNDEFINED_ENTRY_POINT", @@ -6707,7 +7200,8 @@ "BotMetricsEntryPoint_WEB_NAVIGATION_BAR", "BotMetricsEntryPoint_GROUP_MEMBER", "BotMetricsEntryPoint_CHATLIST_SEARCH", - "BotMetricsEntryPoint_NEW_CHAT_LIST" + "BotMetricsEntryPoint_NEW_CHAT_LIST", + "BotMetricsEntryPoint_CONTACTS_TAB" ] }, "waAICommon.BotMetricsMetadata": { @@ -7965,6 +8459,28 @@ "ADVEncryptionType_HOSTED" ] }, + "waAea.NonE2EEAttestation": { + "type": "object", + "properties": { + "accountType": { + "$ref": "#/definitions/waAea.NonE2EEAttestation_AccountType" + } + } + }, + "waAea.NonE2EEAttestation_AccountType": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2 + ], + "x-enum-varnames": [ + "NonE2EEAttestation_E2EE", + "NonE2EEAttestation_HYBRID_E2EE", + "NonE2EEAttestation_NON_E2EE" + ] + }, "waCommon.LimitSharing": { "type": "object", "properties": { @@ -8348,6 +8864,23 @@ "BCallMessage_VIDEO" ] }, + "waE2E.BotHistoryShareSyncMetadata": { + "type": "object", + "properties": { + "botJID": { + "type": "string" + }, + "historyShareCutoffTimestamp": { + "type": "integer" + }, + "historyShareMessages": { + "type": "array", + "items": { + "$ref": "#/definitions/waE2E.HistoryShareMessageEntry" + } + } + } + }, "waE2E.ButtonsMessage": { "type": "object", "properties": { @@ -8487,6 +9020,9 @@ "type": "integer" } }, + "callReason": { + "type": "string" + }, "contextInfo": { "$ref": "#/definitions/waE2E.ContextInfo" }, @@ -8769,6 +9305,9 @@ "afterReadDuration": { "type": "integer" }, + "aiProvenance": { + "$ref": "#/definitions/waAICommon.AIProvenance" + }, "alwaysShowAdAttribution": { "type": "boolean" }, @@ -8865,6 +9404,9 @@ "groupSubject": { "type": "string" }, + "instagramThreadLink": { + "$ref": "#/definitions/waE2E.ContextInfo_InstagramThreadLink" + }, "isForwarded": { "type": "boolean" }, @@ -9026,6 +9568,9 @@ "items": { "type": "integer" } + }, + "unauthenticatedBusinessMetadata": { + "$ref": "#/definitions/waE2E.ContextInfo_BusinessInteractionPills_UnauthenticatedBusinessMetadata" } } }, @@ -9094,6 +9639,23 @@ "ContextInfo_BusinessInteractionPills_ORDER" ] }, + "waE2E.ContextInfo_BusinessInteractionPills_UnauthenticatedBusinessMetadata": { + "type": "object", + "properties": { + "businessCategory": { + "type": "string" + }, + "businessIsOpen": { + "type": "boolean" + }, + "businessIsOpenSnapshotMS": { + "type": "integer" + }, + "businessName": { + "type": "string" + } + } + }, "waE2E.ContextInfo_BusinessMessageForwardInfo": { "type": "object", "properties": { @@ -9363,6 +9925,14 @@ "ContextInfo_ForwardedNewsletterMessageInfo_LINK_CARD" ] }, + "waE2E.ContextInfo_InstagramThreadLink": { + "type": "object", + "properties": { + "URL": { + "type": "string" + } + } + }, "waE2E.ContextInfo_PairedMediaType": { "type": "integer", "format": "int32", @@ -9930,7 +10500,7 @@ "$ref": "#/definitions/waE2E.VideoEndCard" } }, - "faviconMMSMetadata": { + "faviconMmsMetadata": { "$ref": "#/definitions/waE2E.MMSThumbnailMetadata" }, "font": { @@ -10253,6 +10823,20 @@ } } }, + "waE2E.HistoryShareMessageEntry": { + "type": "object", + "properties": { + "messageSecretProof": { + "type": "array", + "items": { + "type": "integer" + } + }, + "stanzaID": { + "type": "string" + } + } + }, "waE2E.HistorySyncMessageAccessStatus": { "type": "object", "properties": { @@ -11129,6 +11713,26 @@ } } }, + "waE2E.MarkAsVerifiedAction": { + "type": "object", + "properties": { + "actionSeq": { + "type": "integer" + }, + "userJIDString": { + "type": "string" + }, + "verified": { + "type": "boolean" + }, + "verifiedIdentityKey": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, "waE2E.MediaDomainInfo": { "type": "object", "properties": { @@ -11461,6 +12065,9 @@ "splitPaymentMessage": { "$ref": "#/definitions/waE2E.SplitPaymentMessage" }, + "splitPaymentUpdateMessage": { + "$ref": "#/definitions/waE2E.SplitPaymentUpdateMessage" + }, "spoilerMessage": { "$ref": "#/definitions/waE2E.FutureProofMessage" }, @@ -11578,6 +12185,15 @@ "waE2E.MessageContextInfo": { "type": "object", "properties": { + "accountEncryptionAttestation": { + "$ref": "#/definitions/waAea.NonE2EEAttestation" + }, + "associatedPrimaryIdentityKey": { + "type": "array", + "items": { + "type": "integer" + } + }, "botMessageSecret": { "type": "array", "items": { @@ -11725,6 +12341,9 @@ "waE2E.MessageHistoryNotice": { "type": "object", "properties": { + "botHistoryShareSyncMetadata": { + "$ref": "#/definitions/waE2E.BotHistoryShareSyncMetadata" + }, "contextInfo": { "$ref": "#/definitions/waE2E.ContextInfo" }, @@ -11952,6 +12571,9 @@ "waE2E.PaymentExtendedMetadata": { "type": "object", "properties": { + "messageParamsJSON": { + "type": "string" + }, "platform": { "type": "string" }, @@ -12690,7 +13312,8 @@ 10, 11, 12, - 13 + 13, + 14 ], "x-enum-varnames": [ "PeerDataOperationRequestType_UPLOAD_STICKER", @@ -12706,7 +13329,8 @@ "PeerDataOperationRequestType_HISTORY_SYNC_CHUNK_RETRY", "PeerDataOperationRequestType_GALAXY_FLOW_ACTION", "PeerDataOperationRequestType_BUSINESS_BROADCAST_INSIGHTS_DELIVERED_TO", - "PeerDataOperationRequestType_BUSINESS_BROADCAST_INSIGHTS_REFRESH" + "PeerDataOperationRequestType_BUSINESS_BROADCAST_INSIGHTS_REFRESH", + "PeerDataOperationRequestType_CONTACT_REFRESH_REQUEST" ] }, "waE2E.PinInChatMessage": { @@ -13114,6 +13738,9 @@ "cloudApiThreadControlNotification": { "$ref": "#/definitions/waE2E.CloudAPIThreadControlNotification" }, + "coexStateSync": { + "$ref": "#/definitions/waServerSync.CoexStateSync" + }, "disappearingMode": { "$ref": "#/definitions/waE2E.DisappearingMode" }, @@ -13144,6 +13771,9 @@ "limitSharing": { "$ref": "#/definitions/waCommon.LimitSharing" }, + "markAsVerifiedAction": { + "$ref": "#/definitions/waE2E.MarkAsVerifiedAction" + }, "mediaNotifyMessage": { "$ref": "#/definitions/waE2E.MediaNotifyMessage" }, @@ -13159,6 +13789,9 @@ "requestWelcomeMessageMetadata": { "$ref": "#/definitions/waE2E.RequestWelcomeMessageMetadata" }, + "syncRequestMutationRetry": { + "$ref": "#/definitions/waE2E.SyncRequestMutationRetry" + }, "timestampMS": { "type": "integer" }, @@ -13200,7 +13833,10 @@ 31, 32, 34, - 35 + 35, + 36, + 37, + 38 ], "x-enum-varnames": [ "ProtocolMessage_REVOKE", @@ -13232,7 +13868,10 @@ "ProtocolMessage_AI_MEDIA_COLLECTION_MESSAGE", "ProtocolMessage_MESSAGE_UNSCHEDULE", "ProtocolMessage_CHAT_THEME_SETTING", - "ProtocolMessage_AI_METADATA_OPERATION" + "ProtocolMessage_AI_METADATA_OPERATION", + "ProtocolMessage_MARK_AS_VERIFIED_ACTION", + "ProtocolMessage_COEX_STATE_SYNC", + "ProtocolMessage_SYNC_REQUEST_MUTATION_RETRY" ] }, "waE2E.QuestionResponseMessage": { @@ -13526,6 +14165,17 @@ "SplitPaymentParticipant_PAID" ] }, + "waE2E.SplitPaymentUpdateMessage": { + "type": "object", + "properties": { + "participantJID": { + "type": "string" + }, + "splitID": { + "type": "string" + } + } + }, "waE2E.StatusNotificationMessage": { "type": "object", "properties": { @@ -13858,6 +14508,31 @@ } } }, + "waE2E.SyncRequestMutationRetry": { + "type": "object", + "properties": { + "collections": { + "type": "array", + "items": { + "$ref": "#/definitions/waE2E.SyncRequestMutationRetry_Collection" + } + }, + "count": { + "type": "integer" + } + } + }, + "waE2E.SyncRequestMutationRetry_Collection": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "storedSyncdVersion": { + "type": "integer" + } + } + }, "waE2E.TemplateButtonReplyMessage": { "type": "object", "properties": { @@ -14180,6 +14855,82 @@ "MediaRetryNotification_DECRYPTION_ERROR" ] }, + "waServerSync.CoexStateSync": { + "type": "object", + "properties": { + "collectionMutations": { + "type": "array", + "items": { + "$ref": "#/definitions/waServerSync.CoexStateSync_CollectionMutations" + } + } + } + }, + "waServerSync.CoexStateSync_CollectionMutations": { + "type": "object", + "properties": { + "collection": { + "type": "string" + }, + "mutations": { + "type": "array", + "items": { + "$ref": "#/definitions/waServerSync.CoexStateSync_Mutation" + } + } + } + }, + "waServerSync.CoexStateSync_Mutation": { + "type": "object", + "properties": { + "dirtyVersion": { + "type": "integer" + }, + "index": { + "$ref": "#/definitions/waServerSync.SyncdIndex" + }, + "operation": { + "$ref": "#/definitions/waServerSync.SyncdMutation_SyncdOperation" + }, + "value": { + "$ref": "#/definitions/waServerSync.SyncdValue" + } + } + }, + "waServerSync.SyncdIndex": { + "type": "object", + "properties": { + "blob": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "waServerSync.SyncdMutation_SyncdOperation": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1 + ], + "x-enum-varnames": [ + "SyncdMutation_SET", + "SyncdMutation_REMOVE" + ] + }, + "waServerSync.SyncdValue": { + "type": "object", + "properties": { + "blob": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, "waStatusAttributions.StatusAttribution": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 5c6fe8bb..3f6e7337 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -2,26 +2,94 @@ definitions: gin.H: additionalProperties: {} type: object - github_com_EvolutionAPI_evolution-go_pkg_call_service.RejectCallStruct: + github_com_evolution-foundation_evolution-go_pkg_call_service.AddParticipantStruct: + properties: + callId: + type: string + number: + type: string + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.AnswerCallStruct: properties: callCreator: $ref: '#/definitions/types.JID' callId: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct: + github_com_evolution-foundation_evolution-go_pkg_call_service.DialCallStruct: + properties: + number: + type: string + video: + type: boolean + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.HandRaiseStruct: + properties: + callId: + type: string + raised: + type: boolean + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.HangupCallStruct: + properties: + callId: + type: string + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.ReactCallStruct: + properties: + callId: + type: string + emoji: + type: string + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.RejectCallStruct: + properties: + callCreator: + $ref: '#/definitions/types.JID' + callId: + type: string + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.ScreenShareStruct: + properties: + callId: + type: string + start: + type: boolean + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.VideoEnabledStruct: + properties: + callId: + type: string + enabled: + type: boolean + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.VideoOrientationStruct: + properties: + callId: + type: string + orientation: + type: integer + type: object + github_com_evolution-foundation_evolution-go_pkg_call_service.VideoUpgradeStruct: + properties: + callId: + type: string + start: + type: boolean + type: object + github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct: properties: chat: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_chat_service.HistorySyncRequestStruct: + github_com_evolution-foundation_evolution-go_pkg_chat_service.HistorySyncRequestStruct: properties: count: type: integer messageInfo: $ref: '#/definitions/types.MessageInfo' type: object - github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct: + github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct: properties: communityJid: type: string @@ -30,12 +98,12 @@ definitions: type: string type: array type: object - github_com_EvolutionAPI_evolution-go_pkg_community_service.CreateCommunityStruct: + github_com_evolution-foundation_evolution-go_pkg_community_service.CreateCommunityStruct: properties: communityName: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.AddParticipantStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.AddParticipantStruct: properties: action: $ref: '#/definitions/whatsmeow.ParticipantChange' @@ -46,7 +114,7 @@ definitions: type: string type: array type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.CreateGroupStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.CreateGroupStruct: properties: groupName: type: string @@ -55,50 +123,50 @@ definitions: type: string type: array type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInfoStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInfoStruct: properties: groupJid: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInviteLinkStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInviteLinkStruct: properties: groupJid: type: string reset: type: boolean type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.JoinGroupStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.JoinGroupStruct: properties: code: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.LeaveGroupStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.LeaveGroupStruct: properties: groupJid: $ref: '#/definitions/types.JID' type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupDescriptionStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupDescriptionStruct: properties: description: type: string groupJid: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupNameStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupNameStruct: properties: groupJid: type: string name: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupPhotoStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupPhotoStruct: properties: groupJid: type: string image: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_group_service.UpdateGroupSettingsStruct: + github_com_evolution-foundation_evolution-go_pkg_group_service.UpdateGroupSettingsStruct: properties: action: description: announcement, not_announcement, locked, unlocked @@ -106,7 +174,7 @@ definitions: groupJid: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings: + github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings: properties: alwaysOnline: type: boolean @@ -121,7 +189,7 @@ definitions: rejectCall: type: boolean type: object - github_com_EvolutionAPI_evolution-go_pkg_instance_service.ConnectStruct: + github_com_evolution-foundation_evolution-go_pkg_instance_service.ConnectStruct: properties: immediate: type: boolean @@ -140,25 +208,25 @@ definitions: websocketEnable: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_instance_service.CreateStruct: + github_com_evolution-foundation_evolution-go_pkg_instance_service.CreateStruct: properties: advancedSettings: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings' instanceId: type: string name: type: string proxy: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ProxyConfig' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ProxyConfig' token: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_instance_service.ForceReconnectStruct: + github_com_evolution-foundation_evolution-go_pkg_instance_service.ForceReconnectStruct: properties: number: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_instance_service.PairStruct: + github_com_evolution-foundation_evolution-go_pkg_instance_service.PairStruct: properties: phone: type: string @@ -167,7 +235,7 @@ definitions: type: string type: array type: object - github_com_EvolutionAPI_evolution-go_pkg_instance_service.ProxyConfig: + github_com_evolution-foundation_evolution-go_pkg_instance_service.ProxyConfig: properties: host: type: string @@ -180,7 +248,7 @@ definitions: username: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_instance_service.SetProxyStruct: + github_com_evolution-foundation_evolution-go_pkg_instance_service.SetProxyStruct: properties: host: type: string @@ -196,14 +264,14 @@ definitions: - host - port type: object - github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct: + github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct: properties: jid: type: string labelId: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_label_service.EditLabelStruct: + github_com_evolution-foundation_evolution-go_pkg_label_service.EditLabelStruct: properties: color: type: integer @@ -214,7 +282,7 @@ definitions: name: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct: + github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct: properties: jid: type: string @@ -223,7 +291,7 @@ definitions: messageId: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_message_service.ChatPresenceStruct: + github_com_evolution-foundation_evolution-go_pkg_message_service.ChatPresenceStruct: properties: delay: description: |- @@ -238,12 +306,12 @@ definitions: state: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_message_service.DownloadMediaStruct: + github_com_evolution-foundation_evolution-go_pkg_message_service.DownloadMediaStruct: properties: message: $ref: '#/definitions/waE2E.Message' type: object - github_com_EvolutionAPI_evolution-go_pkg_message_service.EditMessageStruct: + github_com_evolution-foundation_evolution-go_pkg_message_service.EditMessageStruct: properties: chat: type: string @@ -252,7 +320,7 @@ definitions: messageId: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct: + github_com_evolution-foundation_evolution-go_pkg_message_service.MarkPlayedStruct: properties: id: items: @@ -261,7 +329,7 @@ definitions: number: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct: + github_com_evolution-foundation_evolution-go_pkg_message_service.MarkReadStruct: properties: id: items: @@ -270,19 +338,19 @@ definitions: number: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStatusStruct: + github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStatusStruct: properties: id: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStruct: + github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStruct: properties: chat: type: string messageId: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_message_service.ReactStruct: + github_com_evolution-foundation_evolution-go_pkg_message_service.ReactStruct: properties: fromMe: type: boolean @@ -295,19 +363,19 @@ definitions: reaction: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.CreateNewsletterStruct: + github_com_evolution-foundation_evolution-go_pkg_newsletter_service.CreateNewsletterStruct: properties: description: type: string name: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct: + github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct: properties: key: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct: + github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct: properties: before_id: type: integer @@ -316,12 +384,12 @@ definitions: jid: $ref: '#/definitions/types.JID' type: object - github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct: + github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct: properties: jid: $ref: '#/definitions/types.JID' type: object - github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollResults: + github_com_evolution-foundation_evolution-go_pkg_poll_model.PollResults: properties: optionCounts: additionalProperties: @@ -336,14 +404,14 @@ definitions: type: integer voters: items: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.VoterInfo' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.VoterInfo' type: array votes: items: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollVote' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.PollVote' type: array type: object - github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollVote: + github_com_evolution-foundation_evolution-go_pkg_poll_model.PollVote: properties: companyId: type: string @@ -373,7 +441,7 @@ definitions: voterPhone: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_poll_model.VoterInfo: + github_com_evolution-foundation_evolution-go_pkg_poll_model.VoterInfo: properties: jid: type: string @@ -388,7 +456,7 @@ definitions: votedAt: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Button: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Button: properties: copyCode: description: Code placed in the clipboard when type=copy. @@ -445,12 +513,12 @@ definitions: example: https://evolutionapi.com type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ButtonStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ButtonStruct: properties: buttons: description: Buttons array. See combination rules on the parent type description. items: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Button' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Button' type: array delay: description: Typing delay (milliseconds) applied before sending the message. @@ -485,7 +553,7 @@ definitions: type: string quoted: allOf: - - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + - $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' description: Quoted (reply-to) context. title: description: Header title (required). @@ -495,7 +563,7 @@ definitions: description: Optional video URL used as header for reply-only buttons. type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselButtonStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselButtonStruct: properties: copyCode: description: Code placed in the clipboard when type=COPY. @@ -525,14 +593,14 @@ definitions: example: REPLY type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct: properties: text: description: Main text of the card. example: Card 1 - Oferta especial type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct: properties: imageUrl: description: Public URL to an image. Downloaded, uploaded to WhatsApp servers @@ -551,17 +619,17 @@ definitions: description: Public URL to a video. Used only when `imageUrl` is empty. type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardStruct: properties: body: allOf: - - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct' + - $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardBodyStruct' description: Card body text (required). buttons: description: Buttons shown on the card. See CarouselButtonStruct for combination rules. items: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselButtonStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselButtonStruct' type: array footer: description: Optional footer rendered under the body. @@ -569,10 +637,10 @@ definitions: type: string header: allOf: - - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct' + - $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardHeaderStruct' description: Card header (media + title/subtitle). type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselStruct: properties: body: description: Optional message body shown above the cards. @@ -581,7 +649,7 @@ definitions: cards: description: Cards displayed in order. At least one card is required. items: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselCardStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselCardStruct' type: array delay: description: Typing delay (milliseconds) applied before sending the message. @@ -601,10 +669,10 @@ definitions: type: string quoted: allOf: - - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + - $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' description: Quoted (reply-to) context. type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ContactStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ContactStruct: properties: delay: type: integer @@ -621,11 +689,11 @@ definitions: number: type: string quoted: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' vcard: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_utils.VCardStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_utils.VCardStruct' type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LinkStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LinkStruct: properties: delay: type: integer @@ -646,7 +714,7 @@ definitions: number: type: string quoted: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' text: type: string title: @@ -654,7 +722,7 @@ definitions: url: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ListStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ListStruct: properties: buttonText: description: Label of the button that opens the list. Defaults to "Ver Menu" @@ -691,19 +759,19 @@ definitions: type: string quoted: allOf: - - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + - $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' description: Quoted (reply-to) context. sections: description: Sections with rows. At least one section with one row is required. items: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Section' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Section' type: array title: description: Header title (required). example: Nossos planos type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LocationStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LocationStruct: properties: address: type: string @@ -728,9 +796,9 @@ definitions: number: type: string quoted: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.MediaStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.MediaStruct: properties: caption: type: string @@ -753,13 +821,13 @@ definitions: number: type: string quoted: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' type: type: string url: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.PollStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.PollStruct: properties: delay: type: integer @@ -784,16 +852,16 @@ definitions: question: type: string quoted: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct: properties: messageId: type: string participant: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Row: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Row: properties: description: description: Optional secondary line below the title. @@ -809,26 +877,26 @@ definitions: example: Plano Basico type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Section: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Section: properties: rows: description: Rows inside this section. items: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.Row' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.Row' type: array title: description: Section heading (optional; rendered as a group separator). example: Planos type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StatusTextStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StatusTextStruct: properties: id: type: string text: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StickerStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StickerStruct: properties: delay: type: integer @@ -845,11 +913,11 @@ definitions: number: type: string quoted: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' sticker: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.TextStruct: + github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.TextStruct: properties: delay: type: integer @@ -868,16 +936,16 @@ definitions: number: type: string quoted: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.QuotedStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.QuotedStruct' text: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct: + github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct: properties: number: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct: + github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct: properties: formatJid: type: boolean @@ -886,14 +954,14 @@ definitions: type: string type: array type: object - github_com_EvolutionAPI_evolution-go_pkg_user_service.GetAvatarStruct: + github_com_evolution-foundation_evolution-go_pkg_user_service.GetAvatarStruct: properties: number: type: string preview: type: boolean type: object - github_com_EvolutionAPI_evolution-go_pkg_user_service.PrivacyStruct: + github_com_evolution-foundation_evolution-go_pkg_user_service.PrivacyStruct: properties: callAdd: $ref: '#/definitions/types.PrivacySetting' @@ -910,12 +978,12 @@ definitions: status: $ref: '#/definitions/types.PrivacySetting' type: object - github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct: + github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct: properties: image: type: string type: object - github_com_EvolutionAPI_evolution-go_pkg_utils.VCardStruct: + github_com_evolution-foundation_evolution-go_pkg_utils.VCardStruct: properties: fullName: type: string @@ -1037,6 +1105,8 @@ definitions: isGroup: description: Whether the chat is a group chat or broadcast list. type: boolean + isNewsletterStatus: + type: boolean mediaType: type: string msgBotInfo: @@ -1119,10 +1189,20 @@ definitions: - PrivacySettingOff types.VerifiedName: properties: + actualActors: + type: integer certificate: $ref: '#/definitions/waVnameCert.VerifiedNameCertificate' details: $ref: '#/definitions/waVnameCert.VerifiedNameCertificate_Details' + hostStorage: + type: integer + privacyModeTS: + type: string + verifiedLevel: + type: string + version: + type: integer type: object types.WebAuthnResponse: properties: @@ -1177,6 +1257,20 @@ definitions: hatchMetadataSync: $ref: '#/definitions/waAICommon.HatchMetadataSync' type: object + waAICommon.AIProvenance: + properties: + c2PaMetadata: + $ref: '#/definitions/waAICommon.AIProvenance_Metadata' + iptcMetadata: + $ref: '#/definitions/waAICommon.AIProvenance_Metadata' + type: object + waAICommon.AIProvenance_Metadata: + properties: + createdWithGenAi: + type: boolean + editedWithGenAi: + type: boolean + type: object waAICommon.AIRegenerateMetadata: properties: messageKey: @@ -1261,6 +1355,10 @@ definitions: - BotAgeCollectionMetadata_WAFFLE waAICommon.BotAgentDeepLinkMetadata: properties: + clientPublicKey: + items: + type: integer + type: array token: type: string type: object @@ -1344,6 +1442,10 @@ definitions: - 63 - 64 - 65 + - 66 + - 67 + - 68 + - 69 format: int32 type: integer x-enum-varnames: @@ -1413,6 +1515,10 @@ definitions: - BotCapabilityMetadata_UNIFIED_RESPONSE_MARKDOWN_LINKS_ENABLED - BotCapabilityMetadata_AI_RICH_RESPONSE_MAPS_V2_ENABLED - BotCapabilityMetadata_AI_SUBSCRIPTION_METERING_ENABLED + - BotCapabilityMetadata_RICH_RESPONSE_SPORTS_WIDGET_ENABLED + - BotCapabilityMetadata_AI_RICH_RESPONSE_ARTIFACTS_ENABLED + - BotCapabilityMetadata_AI_RICH_RESPONSE_EMAIL_CALENDAR_ENABLED + - BotCapabilityMetadata_AI_RICH_RESPONSE_REMINDERS_ENABLED waAICommon.BotCommandMetadata: properties: commandDescription: @@ -1586,6 +1692,13 @@ definitions: botFbid: type: string type: object + waAICommon.BotHistoryShareMetadata: + properties: + participantsMetadata: + items: + $ref: '#/definitions/waAICommon.BotGroupParticipantMetadata' + type: array + type: object waAICommon.BotImagineMetadata: properties: imagineType: @@ -1748,6 +1861,8 @@ definitions: $ref: '#/definitions/waAICommon.BotDocumentMessageMetadata' botGroupMetadata: $ref: '#/definitions/waAICommon.BotGroupMetadata' + botHistoryShareMetadata: + $ref: '#/definitions/waAICommon.BotHistoryShareMetadata' botInfrastructureDiagnostics: $ref: '#/definitions/waAICommon.BotInfrastructureDiagnostics' botLinkedAccountsMetadata: @@ -1875,6 +1990,7 @@ definitions: - 54 - 55 - 56 + - 57 format: int32 type: integer x-enum-varnames: @@ -1926,6 +2042,7 @@ definitions: - BotMetricsEntryPoint_GROUP_MEMBER - BotMetricsEntryPoint_CHATLIST_SEARCH - BotMetricsEntryPoint_NEW_CHAT_LIST + - BotMetricsEntryPoint_CONTACTS_TAB waAICommon.BotMetricsMetadata: properties: destinationEntryPoint: @@ -2800,6 +2917,22 @@ definitions: x-enum-varnames: - ADVEncryptionType_E2EE - ADVEncryptionType_HOSTED + waAea.NonE2EEAttestation: + properties: + accountType: + $ref: '#/definitions/waAea.NonE2EEAttestation_AccountType' + type: object + waAea.NonE2EEAttestation_AccountType: + enum: + - 0 + - 1 + - 2 + format: int32 + type: integer + x-enum-varnames: + - NonE2EEAttestation_E2EE + - NonE2EEAttestation_HYBRID_E2EE + - NonE2EEAttestation_NON_E2EE waCommon.LimitSharing: properties: initiatedByMe: @@ -3054,6 +3187,17 @@ definitions: - BCallMessage_UNKNOWN - BCallMessage_AUDIO - BCallMessage_VIDEO + waE2E.BotHistoryShareSyncMetadata: + properties: + botJID: + type: string + historyShareCutoffTimestamp: + type: integer + historyShareMessages: + items: + $ref: '#/definitions/waE2E.HistoryShareMessageEntry' + type: array + type: object waE2E.ButtonsMessage: properties: buttons: @@ -3152,6 +3296,8 @@ definitions: items: type: integer type: array + callReason: + type: string contextInfo: $ref: '#/definitions/waE2E.ContextInfo' conversionData: @@ -3346,6 +3492,8 @@ definitions: $ref: '#/definitions/waE2E.ActionLink' afterReadDuration: type: integer + aiProvenance: + $ref: '#/definitions/waAICommon.AIProvenance' alwaysShowAdAttribution: type: boolean botMessageSharingInfo: @@ -3410,6 +3558,8 @@ definitions: type: array groupSubject: type: string + instagramThreadLink: + $ref: '#/definitions/waE2E.ContextInfo_InstagramThreadLink' isForwarded: type: boolean isGroupStatus: @@ -3519,6 +3669,8 @@ definitions: items: type: integer type: array + unauthenticatedBusinessMetadata: + $ref: '#/definitions/waE2E.ContextInfo_BusinessInteractionPills_UnauthenticatedBusinessMetadata' type: object waE2E.ContextInfo_BusinessInteractionPills_EntryPoint: enum: @@ -3575,6 +3727,17 @@ definitions: - ContextInfo_BusinessInteractionPills_ABOUT - ContextInfo_BusinessInteractionPills_SHOP - ContextInfo_BusinessInteractionPills_ORDER + waE2E.ContextInfo_BusinessInteractionPills_UnauthenticatedBusinessMetadata: + properties: + businessCategory: + type: string + businessIsOpen: + type: boolean + businessIsOpenSnapshotMS: + type: integer + businessName: + type: string + type: object waE2E.ContextInfo_BusinessMessageForwardInfo: properties: businessOwnerJID: @@ -3762,6 +3925,11 @@ definitions: - ContextInfo_ForwardedNewsletterMessageInfo_UPDATE - ContextInfo_ForwardedNewsletterMessageInfo_UPDATE_CARD - ContextInfo_ForwardedNewsletterMessageInfo_LINK_CARD + waE2E.ContextInfo_InstagramThreadLink: + properties: + URL: + type: string + type: object waE2E.ContextInfo_PairedMediaType: enum: - 0 @@ -4155,7 +4323,7 @@ definitions: items: $ref: '#/definitions/waE2E.VideoEndCard' type: array - faviconMMSMetadata: + faviconMmsMetadata: $ref: '#/definitions/waE2E.MMSThumbnailMetadata' font: $ref: '#/definitions/waE2E.ExtendedTextMessage_FontType' @@ -4379,6 +4547,15 @@ definitions: paramOneof: description: "Types that are valid to be assigned to ParamOneof:\n\n\t*HighlyStructuredMessage_HSMLocalizableParameter_Currency\n\t*HighlyStructuredMessage_HSMLocalizableParameter_DateTime" type: object + waE2E.HistoryShareMessageEntry: + properties: + messageSecretProof: + items: + type: integer + type: array + stanzaID: + type: string + type: object waE2E.HistorySyncMessageAccessStatus: properties: completeAccessGranted: @@ -4976,6 +5153,19 @@ definitions: thumbnailWidth: type: integer type: object + waE2E.MarkAsVerifiedAction: + properties: + actionSeq: + type: integer + userJIDString: + type: string + verified: + type: boolean + verifiedIdentityKey: + items: + type: integer + type: array + type: object waE2E.MediaDomainInfo: properties: e2EeMediaKey: @@ -5198,6 +5388,8 @@ definitions: $ref: '#/definitions/waE2E.SenderKeyDistributionMessage' splitPaymentMessage: $ref: '#/definitions/waE2E.SplitPaymentMessage' + splitPaymentUpdateMessage: + $ref: '#/definitions/waE2E.SplitPaymentUpdateMessage' spoilerMessage: $ref: '#/definitions/waE2E.FutureProofMessage' statusAddYours: @@ -5289,6 +5481,12 @@ definitions: - MessageAssociation_POLL_ADD_OPTION waE2E.MessageContextInfo: properties: + accountEncryptionAttestation: + $ref: '#/definitions/waAea.NonE2EEAttestation' + associatedPrimaryIdentityKey: + items: + type: integer + type: array botMessageSecret: items: type: integer @@ -5387,6 +5585,8 @@ definitions: type: object waE2E.MessageHistoryNotice: properties: + botHistoryShareSyncMetadata: + $ref: '#/definitions/waE2E.BotHistoryShareSyncMetadata' contextInfo: $ref: '#/definitions/waE2E.ContextInfo' messageHistoryMetadata: @@ -5539,6 +5739,8 @@ definitions: - PaymentBackground_DEFAULT waE2E.PaymentExtendedMetadata: properties: + messageParamsJSON: + type: string platform: type: string type: @@ -6045,6 +6247,7 @@ definitions: - 11 - 12 - 13 + - 14 format: int32 type: integer x-enum-varnames: @@ -6062,6 +6265,7 @@ definitions: - PeerDataOperationRequestType_GALAXY_FLOW_ACTION - PeerDataOperationRequestType_BUSINESS_BROADCAST_INSIGHTS_DELIVERED_TO - PeerDataOperationRequestType_BUSINESS_BROADCAST_INSIGHTS_REFRESH + - PeerDataOperationRequestType_CONTACT_REFRESH_REQUEST waE2E.PinInChatMessage: properties: key: @@ -6334,6 +6538,8 @@ definitions: $ref: '#/definitions/waE2E.ChatThemeSetting' cloudApiThreadControlNotification: $ref: '#/definitions/waE2E.CloudAPIThreadControlNotification' + coexStateSync: + $ref: '#/definitions/waServerSync.CoexStateSync' disappearingMode: $ref: '#/definitions/waE2E.DisappearingMode' editedMessage: @@ -6354,6 +6560,8 @@ definitions: $ref: '#/definitions/waE2E.LIDMigrationMappingSyncMessage' limitSharing: $ref: '#/definitions/waCommon.LimitSharing' + markAsVerifiedAction: + $ref: '#/definitions/waE2E.MarkAsVerifiedAction' mediaNotifyMessage: $ref: '#/definitions/waE2E.MediaNotifyMessage' memberLabel: @@ -6364,6 +6572,8 @@ definitions: $ref: '#/definitions/waE2E.PeerDataOperationRequestResponseMessage' requestWelcomeMessageMetadata: $ref: '#/definitions/waE2E.RequestWelcomeMessageMetadata' + syncRequestMutationRetry: + $ref: '#/definitions/waE2E.SyncRequestMutationRetry' timestampMS: type: integer type: @@ -6401,6 +6611,9 @@ definitions: - 32 - 34 - 35 + - 36 + - 37 + - 38 format: int32 type: integer x-enum-varnames: @@ -6434,6 +6647,9 @@ definitions: - ProtocolMessage_MESSAGE_UNSCHEDULE - ProtocolMessage_CHAT_THEME_SETTING - ProtocolMessage_AI_METADATA_OPERATION + - ProtocolMessage_MARK_AS_VERIFIED_ACTION + - ProtocolMessage_COEX_STATE_SYNC + - ProtocolMessage_SYNC_REQUEST_MUTATION_RETRY waE2E.QuestionResponseMessage: properties: key: @@ -6633,6 +6849,13 @@ definitions: x-enum-varnames: - SplitPaymentParticipant_PENDING - SplitPaymentParticipant_PAID + waE2E.SplitPaymentUpdateMessage: + properties: + participantJID: + type: string + splitID: + type: string + type: object waE2E.StatusNotificationMessage: properties: originalMessageKey: @@ -6857,6 +7080,22 @@ definitions: rmrSource: type: string type: object + waE2E.SyncRequestMutationRetry: + properties: + collections: + items: + $ref: '#/definitions/waE2E.SyncRequestMutationRetry_Collection' + type: array + count: + type: integer + type: object + waE2E.SyncRequestMutationRetry_Collection: + properties: + name: + type: string + storedSyncdVersion: + type: integer + type: object waE2E.TemplateButtonReplyMessage: properties: contextInfo: @@ -7077,6 +7316,56 @@ definitions: - MediaRetryNotification_SUCCESS - MediaRetryNotification_NOT_FOUND - MediaRetryNotification_DECRYPTION_ERROR + waServerSync.CoexStateSync: + properties: + collectionMutations: + items: + $ref: '#/definitions/waServerSync.CoexStateSync_CollectionMutations' + type: array + type: object + waServerSync.CoexStateSync_CollectionMutations: + properties: + collection: + type: string + mutations: + items: + $ref: '#/definitions/waServerSync.CoexStateSync_Mutation' + type: array + type: object + waServerSync.CoexStateSync_Mutation: + properties: + dirtyVersion: + type: integer + index: + $ref: '#/definitions/waServerSync.SyncdIndex' + operation: + $ref: '#/definitions/waServerSync.SyncdMutation_SyncdOperation' + value: + $ref: '#/definitions/waServerSync.SyncdValue' + type: object + waServerSync.SyncdIndex: + properties: + blob: + items: + type: integer + type: array + type: object + waServerSync.SyncdMutation_SyncdOperation: + enum: + - 0 + - 1 + format: int32 + type: integer + x-enum-varnames: + - SyncdMutation_SET + - SyncdMutation_REMOVE + waServerSync.SyncdValue: + properties: + blob: + items: + type: integer + type: array + type: object waStatusAttributions.StatusAttribution: properties: actionURL: @@ -7170,6 +7459,164 @@ info: title: Evolution GO version: "1.0" paths: + /call/answer: + post: + consumes: + - application/json + description: Answer an incoming call and (if it's a video call) accept its video + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.AnswerCallStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Answer call + tags: + - Call + /call/dial: + post: + consumes: + - application/json + description: 'Spike/experimental: places an outbound call, not part of the reviewed + answer-call plan' + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.DialCallStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Place an outbound call + tags: + - Call + /call/handraise: + post: + consumes: + - application/json + description: 'Spike/experimental: toggles this client''s hand-raised state' + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.HandRaiseStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Raise or lower hand in a call + tags: + - Call + /call/hangup: + post: + consumes: + - application/json + description: Hangup an active call + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.HangupCallStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Hangup call + tags: + - Call + /call/participant/add: + post: + consumes: + - application/json + description: 'Spike/experimental: adds a participant, upgrading a 1:1 call into + a group call' + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.AddParticipantStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Add a participant to an active call + tags: + - Call + /call/react: + post: + consumes: + - application/json + description: 'Spike/experimental: sends an emoji reaction into an active call' + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.ReactCallStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Send a call reaction + tags: + - Call /call/reject: post: consumes: @@ -7181,7 +7628,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_call_service.RejectCallStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.RejectCallStruct' produces: - application/json responses: @@ -7196,6 +7643,111 @@ paths: summary: Reject call tags: - Call + /call/screenshare: + post: + consumes: + - application/json + description: 'Spike/experimental: toggles this client''s screen share state' + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.ScreenShareStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Start or stop screen sharing in a call + tags: + - Call + /call/video/enabled: + post: + consumes: + - application/json + description: 'Spike/experimental: wraps Call.SetVideoEnabled' + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoEnabledStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Mute or unmute outbound video without renegotiating the upgrade + tags: + - Call + /call/video/orientation: + post: + consumes: + - application/json + description: 'Spike/experimental: wraps Call.SetVideoOrientation (0-3 quarter + turns clockwise)' + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoOrientationStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Announce this client's camera orientation + tags: + - Call + /call/video/upgrade: + post: + consumes: + - application/json + description: 'Spike/experimental: requests an audio<->video upgrade (Call.StartVideo/StopVideo)' + parameters: + - description: Call data + in: body + name: message + required: true + schema: + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_call_service.VideoUpgradeStruct' + produces: + - application/json + responses: + "200": + description: success + schema: + $ref: '#/definitions/gin.H' + "500": + description: Internal server error + schema: + $ref: '#/definitions/gin.H' + summary: Start or stop sending outbound video mid-call + tags: + - Call /chat/archive: post: consumes: @@ -7207,7 +7759,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct' produces: - application/json responses: @@ -7237,7 +7789,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.HistorySyncRequestStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.HistorySyncRequestStruct' produces: - application/json responses: @@ -7267,7 +7819,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct' produces: - application/json responses: @@ -7297,7 +7849,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct' produces: - application/json responses: @@ -7327,7 +7879,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct' produces: - application/json responses: @@ -7357,7 +7909,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct' produces: - application/json responses: @@ -7387,7 +7939,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_chat_service.BodyStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_chat_service.BodyStruct' produces: - application/json responses: @@ -7417,7 +7969,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct' produces: - application/json responses: @@ -7447,7 +7999,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.CreateCommunityStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.CreateCommunityStruct' produces: - application/json responses: @@ -7477,7 +8029,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_community_service.AddParticipantStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_community_service.AddParticipantStruct' produces: - application/json responses: @@ -7507,7 +8059,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.CreateGroupStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.CreateGroupStruct' produces: - application/json responses: @@ -7537,7 +8089,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupDescriptionStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupDescriptionStruct' produces: - application/json responses: @@ -7567,7 +8119,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInfoStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInfoStruct' produces: - application/json responses: @@ -7597,7 +8149,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.GetGroupInviteLinkStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.GetGroupInviteLinkStruct' produces: - application/json responses: @@ -7627,7 +8179,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.JoinGroupStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.JoinGroupStruct' produces: - application/json responses: @@ -7657,7 +8209,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.LeaveGroupStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.LeaveGroupStruct' produces: - application/json responses: @@ -7725,7 +8277,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupNameStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupNameStruct' produces: - application/json responses: @@ -7755,7 +8307,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.AddParticipantStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.AddParticipantStruct' produces: - application/json responses: @@ -7785,7 +8337,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.SetGroupPhotoStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.SetGroupPhotoStruct' produces: - application/json responses: @@ -7816,7 +8368,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_group_service.UpdateGroupSettingsStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_group_service.UpdateGroupSettingsStruct' produces: - application/json responses: @@ -7850,7 +8402,7 @@ paths: "200": description: Advanced settings retrieved successfully schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings' "400": description: Invalid instance ID schema: @@ -7881,7 +8433,7 @@ paths: name: settings required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_model.AdvancedSettings' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_model.AdvancedSettings' produces: - application/json responses: @@ -7934,7 +8486,7 @@ paths: name: instance required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ConnectStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ConnectStruct' produces: - application/json responses: @@ -7965,7 +8517,7 @@ paths: name: instance required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.CreateStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.CreateStruct' produces: - application/json responses: @@ -8048,7 +8600,7 @@ paths: name: instance required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.ForceReconnectStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.ForceReconnectStruct' produces: - application/json responses: @@ -8170,7 +8722,7 @@ paths: name: instance required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.PairStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.PairStruct' produces: - application/json responses: @@ -8233,7 +8785,7 @@ paths: name: proxy required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_instance_service.SetProxyStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_instance_service.SetProxyStruct' produces: - application/json responses: @@ -8320,7 +8872,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct' produces: - application/json responses: @@ -8350,7 +8902,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.EditLabelStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.EditLabelStruct' produces: - application/json responses: @@ -8399,7 +8951,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct' produces: - application/json responses: @@ -8418,64 +8970,6 @@ paths: summary: Add label to message tags: - Label - /license/activate: - get: - description: Exchanges an authorization code (from the registration callback) - for an api_key and persists it. Provide the code via the query string. - parameters: - - description: Authorization code from the registration callback - in: query - name: code - required: true - type: string - produces: - - application/json - responses: - "200": - description: Activation result - schema: - $ref: '#/definitions/gin.H' - "400": - description: Missing code parameter - schema: - $ref: '#/definitions/gin.H' - summary: Activate license - tags: - - License - /license/register: - get: - description: Checks the GLOBAL_API_KEY with the licensing server. If not yet - registered, initiates registration and returns a register_url. Accepts an - optional redirect_uri for the post-registration redirect. - parameters: - - description: Post-registration redirect URI - in: query - name: redirect_uri - type: string - produces: - - application/json - responses: - "200": - description: Registration state (status/message or register_url) - schema: - $ref: '#/definitions/gin.H' - summary: Register / get registration URL - tags: - - License - /license/status: - get: - description: Returns whether the instance license is active, along with the - instance id and a masked api key. - produces: - - application/json - responses: - "200": - description: License status ({status, instance_id, api_key?}) - schema: - $ref: '#/definitions/gin.H' - summary: Get license status - tags: - - License /message/delete: post: consumes: @@ -8487,7 +8981,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStruct' produces: - application/json responses: @@ -8518,7 +9012,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.DownloadMediaStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.DownloadMediaStruct' produces: - application/json responses: @@ -8548,7 +9042,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.EditMessageStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.EditMessageStruct' produces: - application/json responses: @@ -8578,7 +9072,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MarkPlayedStruct' produces: - application/json responses: @@ -8608,7 +9102,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MarkReadStruct' produces: - application/json responses: @@ -8638,7 +9132,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.ChatPresenceStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.ChatPresenceStruct' produces: - application/json responses: @@ -8669,7 +9163,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.ReactStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.ReactStruct' produces: - application/json responses: @@ -8699,7 +9193,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MessageStatusStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_message_service.MessageStatusStruct' produces: - application/json responses: @@ -8729,7 +9223,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.CreateNewsletterStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.CreateNewsletterStruct' produces: - application/json responses: @@ -8759,7 +9253,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct' produces: - application/json responses: @@ -8789,7 +9283,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterInviteStruct' produces: - application/json responses: @@ -8838,7 +9332,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterMessagesStruct' produces: - application/json responses: @@ -8868,7 +9362,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_newsletter_service.GetNewsletterStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_newsletter_service.GetNewsletterStruct' produces: - application/json responses: @@ -9019,7 +9513,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_poll_model.PollResults' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_poll_model.PollResults' "400": description: Bad Request schema: @@ -9058,7 +9552,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ButtonStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ButtonStruct' produces: - application/json responses: @@ -9104,7 +9598,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.CarouselStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.CarouselStruct' produces: - application/json responses: @@ -9134,7 +9628,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ContactStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ContactStruct' produces: - application/json responses: @@ -9164,7 +9658,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LinkStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LinkStruct' produces: - application/json responses: @@ -9201,7 +9695,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.ListStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.ListStruct' produces: - application/json responses: @@ -9231,7 +9725,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.LocationStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.LocationStruct' produces: - application/json responses: @@ -9261,7 +9755,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.MediaStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.MediaStruct' produces: - application/json responses: @@ -9291,7 +9785,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.PollStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.PollStruct' produces: - application/json responses: @@ -9368,7 +9862,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StatusTextStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StatusTextStruct' produces: - application/json responses: @@ -9398,7 +9892,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.StickerStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.StickerStruct' produces: - application/json responses: @@ -9428,7 +9922,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_sendMessage_service.TextStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_sendMessage_service.TextStruct' produces: - application/json responses: @@ -9458,7 +9952,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.ChatLabelStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.ChatLabelStruct' produces: - application/json responses: @@ -9488,7 +9982,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_label_service.MessageLabelStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_label_service.MessageLabelStruct' produces: - application/json responses: @@ -9518,7 +10012,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.GetAvatarStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.GetAvatarStruct' produces: - application/json responses: @@ -9548,7 +10042,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct' produces: - application/json responses: @@ -9597,7 +10091,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct' produces: - application/json responses: @@ -9646,7 +10140,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.CheckUserStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.CheckUserStruct' produces: - application/json responses: @@ -9694,7 +10188,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.PrivacyStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.PrivacyStruct' produces: - application/json responses: @@ -9720,7 +10214,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct' produces: - application/json responses: @@ -9750,7 +10244,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct' produces: - application/json responses: @@ -9780,7 +10274,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.SetProfilePictureStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.SetProfilePictureStruct' produces: - application/json responses: @@ -9810,7 +10304,7 @@ paths: name: message required: true schema: - $ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_user_service.BlockStruct' + $ref: '#/definitions/github_com_evolution-foundation_evolution-go_pkg_user_service.BlockStruct' produces: - application/json responses: diff --git a/go.mod b/go.mod index c1c97f6a..f22e9703 100644 --- a/go.mod +++ b/go.mod @@ -15,16 +15,17 @@ require ( github.com/minio/minio-go/v7 v7.0.80 github.com/nats-io/nats.go v1.39.0 github.com/patrickmn/go-cache v2.1.0+incompatible + github.com/purpshell/meowcaller v0.0.0-20260726180203-6d9b7b2c1807 github.com/rabbitmq/amqp091-go v1.10.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.3 github.com/vincent-petithory/dataurl v1.0.0 - go.mau.fi/whatsmeow v0.0.0-20260630180629-b572e5bcb92b - golang.org/x/exp v0.0.0-20260611194520-c48552f49976 + go.mau.fi/whatsmeow v0.0.0-20260722203353-e9a033b24933 + golang.org/x/exp v0.0.0-20260709172345-9ea1abe57597 golang.org/x/image v0.0.0-20211028202545-6944b10bf410 - golang.org/x/net v0.56.0 + golang.org/x/net v0.57.0 google.golang.org/protobuf v1.36.11 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gorm.io/driver/postgres v1.5.9 @@ -53,6 +54,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/goccy/go-json v0.10.3 // indirect + github.com/hajimehoshi/go-mp3 v0.3.4 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect @@ -75,7 +77,14 @@ require ( github.com/nats-io/nuid v1.0.1 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect - github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect + github.com/petermattis/goid v0.0.0-20260713124913-97594f28f5ca // indirect + github.com/pion/datachannel v1.6.0 // indirect + github.com/pion/dtls/v3 v3.1.2 // indirect + github.com/pion/logging v0.2.4 // indirect + github.com/pion/opus v0.1.0 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/sctp v1.9.4 // indirect + github.com/pion/transport/v4 v4.0.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/xid v1.6.0 // indirect @@ -84,13 +93,13 @@ require ( github.com/ugorji/go/codec v1.2.12 // 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.mau.fi/util v0.9.12-0.20260717235539-f9ffa7eca58d // indirect golang.org/x/arch v0.10.0 // indirect - golang.org/x/crypto v0.53.0 // indirect - golang.org/x/sync v0.21.0 // indirect - golang.org/x/sys v0.46.0 // indirect - golang.org/x/text v0.38.0 // indirect - golang.org/x/tools v0.46.0 // indirect + golang.org/x/crypto v0.54.0 // indirect + golang.org/x/sync v0.22.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.40.0 // indirect + golang.org/x/tools v0.48.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect modernc.org/libc v1.55.3 // indirect diff --git a/go.sum b/go.sum index c8e3eefc..d235cd31 100644 --- a/go.sum +++ b/go.sum @@ -69,6 +69,9 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68= +github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo= +github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo= 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/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -111,8 +114,8 @@ 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/mattn/go-sqlite3 v1.14.48 h1:7XHIgl0a8HwOaiK4E47ozLkST78rR9+OtNGx27D/TFs= +github.com/mattn/go-sqlite3 v1.14.48/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.80 h1:2mdUHXEykRdY/BigLt3Iuu1otL0JTogT0Nmltg0wujk= @@ -134,10 +137,26 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= -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/petermattis/goid v0.0.0-20260713124913-97594f28f5ca h1:GHSUVE4yOgX4E7kTRzpxCPbCOYkd3Kj8Dgdod30OI1E= +github.com/petermattis/goid v0.0.0-20260713124913-97594f28f5ca/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pion/datachannel v1.6.0 h1:XecBlj+cvsxhAMZWFfFcPyUaDZtd7IJvrXqlXD/53i0= +github.com/pion/datachannel v1.6.0/go.mod h1:ur+wzYF8mWdC+Mkis5Thosk+u/VOL287apDNEbFpsIk= +github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc= +github.com/pion/dtls/v3 v3.1.2/go.mod h1:Hw/igcX4pdY69z1Hgv5x7wJFrUkdgHwAn/Q/uo7YHRo= +github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= +github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= +github.com/pion/opus v0.1.0 h1:GgK/a3DNDrffKjUFsK39rZKqfv7bQ2S2eqRKt0BnqAE= +github.com/pion/opus v0.1.0/go.mod h1:t5Xog2n682JnawoykACE6nKVmupFvmJvkpM7x6bTv6g= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/sctp v1.9.4 h1:cMxEu0F5tbP4qH07bKf1Zjf4rUih9LIo0qQt424e258= +github.com/pion/sctp v1.9.4/go.mod h1:N20Dq6LY+JvJDAh9VVh1JELngb2rQ8dPgds5yBWiPgw= +github.com/pion/transport/v4 v4.0.1 h1:sdROELU6BZ63Ab7FrOLn13M6YdJLY20wldXW2Cu2k8o= +github.com/pion/transport/v4 v4.0.1/go.mod h1:nEuEA4AD5lPdcIegQDpVLgNoDGreqM/YqmEx3ovP4jM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/purpshell/meowcaller v0.0.0-20260726180203-6d9b7b2c1807 h1:SnLX76CnagumooXRm63BK9Rn2/e/Th6aWWJJKTqOk2k= +github.com/purpshell/meowcaller v0.0.0-20260726180203-6d9b7b2c1807/go.mod h1:kSME01MaSkwul6tSmExmgBWUOmfkw3DNpfnozsn01eE= github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw= github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -179,44 +198,45 @@ github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 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-20260630180629-b572e5bcb92b h1:ZUk1ErarDNpnbosXR/MeOz2gkqA4S1bh8zjaSRj7N+Y= -go.mau.fi/whatsmeow v0.0.0-20260630180629-b572e5bcb92b/go.mod h1:9dmNTYZ/1pHjPw/bz+azBsGjAkcrZbqzMrKcvG5bJ8U= +go.mau.fi/util v0.9.12-0.20260717235539-f9ffa7eca58d h1:bUGRidYrauEwLoBvGLLPPQ0lgQUecT0z/ND+vHz07jM= +go.mau.fi/util v0.9.12-0.20260717235539-f9ffa7eca58d/go.mod h1:xunp/oIQfFD68HHcNHfG0pOiHkvEtDhTweeIwKJ//+Q= +go.mau.fi/whatsmeow v0.0.0-20260722203353-e9a033b24933 h1:7skZGs9q+rWKqYHok4ZufzhKpf6GmTKZnTjSm0aDtus= +go.mau.fi/whatsmeow v0.0.0-20260722203353-e9a033b24933/go.mod h1:Iy/xVSuVU2payR26MB1hv0UZUWRraEn4qKZ7+VRHulg= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8= golang.org/x/arch v0.10.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.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/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= +golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= +golang.org/x/exp v0.0.0-20260709172345-9ea1abe57597 h1:qLvzZeaANDgyVOA8pyHCOStGlXn0rseXma+GQjeuv2g= +golang.org/x/exp v0.0.0-20260709172345-9ea1abe57597/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q= golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -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/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= +golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= 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.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= -golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= +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.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= -golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= 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= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= -golang.org/x/sys v0.46.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/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= @@ -225,13 +245,15 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/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.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= -golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= +golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= +golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 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.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk= -golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys= +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/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/pkg/call/handler/call_handler.go b/pkg/call/handler/call_handler.go index 550c3390..fbfa436f 100644 --- a/pkg/call/handler/call_handler.go +++ b/pkg/call/handler/call_handler.go @@ -10,6 +10,16 @@ import ( type CallHandler interface { RejectCall(ctx *gin.Context) + AnswerCall(ctx *gin.Context) + HangupCall(ctx *gin.Context) + DialCall(ctx *gin.Context) + ReactCall(ctx *gin.Context) + AddParticipant(ctx *gin.Context) + ScreenShareCall(ctx *gin.Context) + HandRaiseCall(ctx *gin.Context) + VideoUpgradeCall(ctx *gin.Context) + VideoEnabledCall(ctx *gin.Context) + VideoOrientationCall(ctx *gin.Context) } type callHandler struct { @@ -51,6 +61,356 @@ func (g *callHandler) RejectCall(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{"message": "success"}) } +// Answer call +// @Summary Answer call +// @Description Answer an incoming call and (if it's a video call) accept its video +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.AnswerCallStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/answer [post] +func (g *callHandler) AnswerCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.AnswerCallStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + _, err = g.callService.AnswerCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + +// Hangup call +// @Summary Hangup call +// @Description Hangup an active call +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.HangupCallStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/hangup [post] +func (g *callHandler) HangupCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.HangupCallStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.HangupCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + +// Dial call +// @Summary Place an outbound call +// @Description Spike/experimental: places an outbound call, not part of the reviewed answer-call plan +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.DialCallStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/dial [post] +func (g *callHandler) DialCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.DialCallStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + call, err := g.callService.DialCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success", "callId": call.ID()}) +} + +// React to a call +// @Summary Send a call reaction +// @Description Spike/experimental: sends an emoji reaction into an active call +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.ReactCallStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/react [post] +func (g *callHandler) ReactCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.ReactCallStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.ReactCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + +// Add participant to a call +// @Summary Add a participant to an active call +// @Description Spike/experimental: adds a participant, upgrading a 1:1 call into a group call +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.AddParticipantStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/participant/add [post] +func (g *callHandler) AddParticipant(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.AddParticipantStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.AddParticipant(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + +// Toggle screen share +// @Summary Start or stop screen sharing in a call +// @Description Spike/experimental: toggles this client's screen share state +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.ScreenShareStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/screenshare [post] +func (g *callHandler) ScreenShareCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.ScreenShareStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.ScreenShareCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + +// Toggle hand raise +// @Summary Raise or lower hand in a call +// @Description Spike/experimental: toggles this client's hand-raised state +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.HandRaiseStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/handraise [post] +func (g *callHandler) HandRaiseCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.HandRaiseStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.HandRaiseCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + +// Toggle video upgrade +// @Summary Start or stop sending outbound video mid-call +// @Description Spike/experimental: requests an audio<->video upgrade (Call.StartVideo/StopVideo) +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.VideoUpgradeStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/video/upgrade [post] +func (g *callHandler) VideoUpgradeCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.VideoUpgradeStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.VideoUpgradeCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + +// Toggle video enabled +// @Summary Mute or unmute outbound video without renegotiating the upgrade +// @Description Spike/experimental: wraps Call.SetVideoEnabled +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.VideoEnabledStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/video/enabled [post] +func (g *callHandler) VideoEnabledCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.VideoEnabledStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.VideoEnabledCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + +// Set video orientation +// @Summary Announce this client's camera orientation +// @Description Spike/experimental: wraps Call.SetVideoOrientation (0-3 quarter turns clockwise) +// @Tags Call +// @Accept json +// @Produce json +// @Param message body call_service.VideoOrientationStruct true "Call data" +// @Success 200 {object} gin.H "success" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /call/video/orientation [post] +func (g *callHandler) VideoOrientationCall(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *call_service.VideoOrientationStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = g.callService.VideoOrientationCall(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success"}) +} + func NewCallHandler( callService call_service.CallService, ) CallHandler { diff --git a/pkg/call/registry/call_registry.go b/pkg/call/registry/call_registry.go new file mode 100644 index 00000000..16a35f38 --- /dev/null +++ b/pkg/call/registry/call_registry.go @@ -0,0 +1,53 @@ +package call_registry + +import ( + "sync" + + "github.com/purpshell/meowcaller" +) + +// entry pairs a live call with the instance it belongs to, so Get can refuse to hand +// back a call to a caller authenticated as a different instance. +type entry struct { + instanceID string + call *meowcaller.Call +} + +// CallRegistry tracks in-progress meowcaller calls by call ID, scoped by instance. +// It is written from the whatsmeow event-handling goroutine (on incoming call) and +// read/written from HTTP handler goroutines (answer/hangup/stream), so all access is +// mutex-guarded. +type CallRegistry struct { + mu sync.RWMutex + entries map[string]entry +} + +// NewCallRegistry returns an empty registry. +func NewCallRegistry() *CallRegistry { + return &CallRegistry{entries: make(map[string]entry)} +} + +// Store records call under its own ID (meowcaller.Call.ID()), tagged with instanceID. +func (r *CallRegistry) Store(instanceID string, call *meowcaller.Call) { + r.mu.Lock() + defer r.mu.Unlock() + r.entries[call.ID()] = entry{instanceID: instanceID, call: call} +} + +// Get returns the call for callID, but only if it was stored under instanceID. +func (r *CallRegistry) Get(instanceID, callID string) (*meowcaller.Call, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + e, ok := r.entries[callID] + if !ok || e.instanceID != instanceID { + return nil, false + } + return e.call, true +} + +// Delete removes callID regardless of which instance it belongs to. +func (r *CallRegistry) Delete(callID string) { + r.mu.Lock() + defer r.mu.Unlock() + delete(r.entries, callID) +} diff --git a/pkg/call/registry/call_registry_test.go b/pkg/call/registry/call_registry_test.go new file mode 100644 index 00000000..339a20ce --- /dev/null +++ b/pkg/call/registry/call_registry_test.go @@ -0,0 +1,52 @@ +package call_registry + +import ( + "testing" + + "github.com/purpshell/meowcaller" +) + +func TestStoreAndGet(t *testing.T) { + r := NewCallRegistry() + call := &meowcaller.Call{} + + r.Store("instance-a", call) + + got, ok := r.Get("instance-a", callIDOf(call)) + if !ok { + t.Fatal("expected call to be found") + } + if got != call { + t.Fatal("expected the same call pointer back") + } +} + +func TestGetWrongInstanceFails(t *testing.T) { + r := NewCallRegistry() + call := &meowcaller.Call{} + r.Store("instance-a", call) + + _, ok := r.Get("instance-b", callIDOf(call)) + if ok { + t.Fatal("expected lookup from a different instance to fail") + } +} + +func TestDeleteRemovesEntry(t *testing.T) { + r := NewCallRegistry() + call := &meowcaller.Call{} + r.Store("instance-a", call) + r.Delete(callIDOf(call)) + + _, ok := r.Get("instance-a", callIDOf(call)) + if ok { + t.Fatal("expected entry to be gone after Delete") + } +} + +// callIDOf mirrors what CallRegistry.Store keys entries by: meowcaller.Call.ID(). +// A zero-value *meowcaller.Call has an empty string ID, which is a perfectly valid +// (if degenerate) key for exercising Store/Get/Delete without a live call. +func callIDOf(call *meowcaller.Call) string { + return call.ID() +} diff --git a/pkg/call/service/call_service.go b/pkg/call/service/call_service.go index 3c14a948..0594760e 100644 --- a/pkg/call/service/call_service.go +++ b/pkg/call/service/call_service.go @@ -5,21 +5,35 @@ import ( "errors" "time" + call_registry "github.com/evolution-foundation/evolution-go/pkg/call/registry" instance_model "github.com/evolution-foundation/evolution-go/pkg/instance/model" logger_wrapper "github.com/evolution-foundation/evolution-go/pkg/logger" whatsmeow_service "github.com/evolution-foundation/evolution-go/pkg/whatsmeow/service" "github.com/gomessguii/logger" + "github.com/purpshell/meowcaller" "go.mau.fi/whatsmeow" "go.mau.fi/whatsmeow/types" ) type CallService interface { RejectCall(data *RejectCallStruct, instance *instance_model.Instance) error + AnswerCall(data *AnswerCallStruct, instance *instance_model.Instance) (*meowcaller.Call, error) + HangupCall(data *HangupCallStruct, instance *instance_model.Instance) error + GetActiveCall(instanceId, callId string) (*meowcaller.Call, error) + DialCall(data *DialCallStruct, instance *instance_model.Instance) (*meowcaller.Call, error) + ReactCall(data *ReactCallStruct, instance *instance_model.Instance) error + AddParticipant(data *AddParticipantStruct, instance *instance_model.Instance) error + ScreenShareCall(data *ScreenShareStruct, instance *instance_model.Instance) error + HandRaiseCall(data *HandRaiseStruct, instance *instance_model.Instance) error + VideoUpgradeCall(data *VideoUpgradeStruct, instance *instance_model.Instance) error + VideoEnabledCall(data *VideoEnabledStruct, instance *instance_model.Instance) error + VideoOrientationCall(data *VideoOrientationStruct, instance *instance_model.Instance) error } type callService struct { clientPointer map[string]*whatsmeow.Client whatsmeowService whatsmeow_service.WhatsmeowService + callRegistry *call_registry.CallRegistry loggerWrapper *logger_wrapper.LoggerManager } @@ -28,68 +42,261 @@ type RejectCallStruct struct { CallID string `json:"callId"` } -func (c *callService) ensureClientConnected(instanceId string) (*whatsmeow.Client, error) { - client := c.clientPointer[instanceId] - c.loggerWrapper.GetLogger(instanceId).LogInfo("[%s] Checking client connection status - Client exists: %v", instanceId, client != nil) +type AnswerCallStruct struct { + CallCreator types.JID `json:"callCreator"` + CallID string `json:"callId"` +} - if client == nil { - c.loggerWrapper.GetLogger(instanceId).LogInfo("[%s] No client found, attempting to start new instance", instanceId) - err := c.whatsmeowService.StartInstance(instanceId) - if err != nil { - c.loggerWrapper.GetLogger(instanceId).LogError("[%s] Failed to start instance: %v", instanceId, err) - return nil, errors.New("no active session found") - } +type HangupCallStruct struct { + CallID string `json:"callId"` +} - c.loggerWrapper.GetLogger(instanceId).LogInfo("[%s] Instance started, waiting 2 seconds...", instanceId) - time.Sleep(2 * time.Second) - - client = c.clientPointer[instanceId] - c.loggerWrapper.GetLogger(instanceId).LogInfo("[%s] Checking new client - Exists: %v, Connected: %v", - instanceId, - client != nil, - client != nil && client.IsConnected()) - - if client == nil || !client.IsConnected() { - c.loggerWrapper.GetLogger(instanceId).LogError("[%s] New client validation failed - Exists: %v, Connected: %v", - instanceId, - client != nil, - client != nil && client.IsConnected()) - return nil, errors.New("no active session found") - } - } else if !client.IsConnected() { - c.loggerWrapper.GetLogger(instanceId).LogError("[%s] Existing client is disconnected - Connected status: %v", - instanceId, - client.IsConnected()) - return nil, errors.New("client disconnected") - } +// DialCallStruct is a spike/experimental addition, outside the reviewed +// answer-call plan: it places an OUTBOUND call rather than answering an +// inbound one. Number accepts anything meowcaller.Client.Call accepts (a +// phone number, a phone JID, or an @lid JID). +type DialCallStruct struct { + Number string `json:"number"` + Video bool `json:"video"` +} + +// The following structs are all spike/experimental additions, outside the reviewed +// answer-call plan, for call-control features requested during live manual testing. + +type ReactCallStruct struct { + CallID string `json:"callId"` + Emoji string `json:"emoji"` +} + +type AddParticipantStruct struct { + CallID string `json:"callId"` + Number string `json:"number"` +} + +type ScreenShareStruct struct { + CallID string `json:"callId"` + Start bool `json:"start"` +} + +type HandRaiseStruct struct { + CallID string `json:"callId"` + Raised bool `json:"raised"` +} + +// VideoUpgradeStruct requests turning this client's camera on or off mid-call. +// Start=true calls Call.StartVideo (audio->video upgrade, gated until the peer +// acknowledges); Start=false calls Call.StopVideo (drop outbound video, keep audio). +type VideoUpgradeStruct struct { + CallID string `json:"callId"` + Start bool `json:"start"` +} + +type VideoEnabledStruct struct { + CallID string `json:"callId"` + Enabled bool `json:"enabled"` +} - c.loggerWrapper.GetLogger(instanceId).LogInfo("[%s] Client successfully validated - Connected: %v", instanceId, client.IsConnected()) - return client, nil +type VideoOrientationStruct struct { + CallID string `json:"callId"` + Orientation int `json:"orientation"` } func (c *callService) RejectCall(data *RejectCallStruct, instance *instance_model.Instance) error { - client, err := c.ensureClientConnected(instance.Id) + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no pending call with that id") + } + + err := call.Reject() + c.callRegistry.Delete(data.CallID) if err != nil { + logger.LogError("[%s] error reject call: %v", instance.Id, err) return err } - err = client.RejectCall(context.Background(), data.CallCreator, data.CallID) + return nil +} + +func (c *callService) AnswerCall(data *AnswerCallStruct, instance *instance_model.Instance) (*meowcaller.Call, error) { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return nil, errors.New("no pending call with that id") + } + + // Answer negotiates media for whatever the offer already declared (audio, or + // audio+video if the call started as a video call) — no separate step needed. + // AcceptVideo is for a different case entirely: accepting a peer's request to + // upgrade an in-progress audio call to video (Call.StartVideo on their side), + // which isn't wired up here. + if err := call.Answer(); err != nil { + logger.LogError("[%s] error answering call: %v", instance.Id, err) + return nil, err + } + + return call, nil +} + +func (c *callService) HangupCall(data *HangupCallStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + + err := call.Hangup() + c.callRegistry.Delete(data.CallID) if err != nil { - logger.LogError("[%s] error reject call: %v", instance.Id, err) + logger.LogError("[%s] error hanging up call: %v", instance.Id, err) return err } + return nil +} + +func (c *callService) GetActiveCall(instanceId, callId string) (*meowcaller.Call, error) { + call, ok := c.callRegistry.Get(instanceId, callId) + if !ok { + return nil, errors.New("no active call with that id") + } + return call, nil +} + +// DialCall places an outbound call and registers it so /call/stream and +// /call/hangup can act on it just like an answered inbound call. +func (c *callService) DialCall(data *DialCallStruct, instance *instance_model.Instance) (*meowcaller.Call, error) { + meowcallerClient, err := c.whatsmeowService.GetMeowcallerClient(instance.Id) + if err != nil { + return nil, err + } + + call, err := meowcallerClient.CallWithOptions(context.Background(), data.Number, meowcaller.CallOptions{Video: data.Video}) + if err != nil { + logger.LogError("[%s] error dialing call: %v", instance.Id, err) + return nil, err + } + c.callRegistry.Store(instance.Id, call) + + return call, nil +} + +func (c *callService) ReactCall(data *ReactCallStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + if err := call.SendReaction(data.Emoji); err != nil { + logger.LogError("[%s] error sending call reaction: %v", instance.Id, err) + return err + } + return nil +} + +func (c *callService) AddParticipant(data *AddParticipantStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + // Spike/experimental: live testing showed the usync lookup AddParticipant does + // internally reliably times out while a call is already active (it works fine + // with no call in progress), even for numbers resolved moments earlier in the + // same session. Retrying with a short backoff to see whether it's transient + // network contention rather than a hard block. + var err error + for attempt := 1; attempt <= 3; attempt++ { + err = call.AddParticipant(context.Background(), data.Number) + if err == nil { + return nil + } + c.loggerWrapper.GetLogger(instance.Id).LogError("[%s] add participant attempt %d/3 failed: %v", instance.Id, attempt, err) + if attempt < 3 { + time.Sleep(2 * time.Second) + } + } + logger.LogError("[%s] error adding call participant after 3 attempts: %v", instance.Id, err) + return err +} + +func (c *callService) ScreenShareCall(data *ScreenShareStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + var err error + if data.Start { + err = call.StartScreenShare(nil) + } else { + err = call.StopScreenShare() + } + if err != nil { + logger.LogError("[%s] error toggling call screen share: %v", instance.Id, err) + return err + } + return nil +} + +func (c *callService) HandRaiseCall(data *HandRaiseStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + if err := call.SetHandRaised(data.Raised); err != nil { + logger.LogError("[%s] error setting call hand-raise state: %v", instance.Id, err) + return err + } + return nil +} + +func (c *callService) VideoUpgradeCall(data *VideoUpgradeStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + var err error + if data.Start { + err = call.StartVideo() + } else { + err = call.StopVideo() + } + if err != nil { + logger.LogError("[%s] error toggling call video upgrade: %v", instance.Id, err) + return err + } + return nil +} + +func (c *callService) VideoEnabledCall(data *VideoEnabledStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + if err := call.SetVideoEnabled(data.Enabled); err != nil { + logger.LogError("[%s] error setting call video enabled state: %v", instance.Id, err) + return err + } + return nil +} + +func (c *callService) VideoOrientationCall(data *VideoOrientationStruct, instance *instance_model.Instance) error { + call, ok := c.callRegistry.Get(instance.Id, data.CallID) + if !ok { + return errors.New("no active call with that id") + } + if err := call.SetVideoOrientation(data.Orientation); err != nil { + logger.LogError("[%s] error setting call video orientation: %v", instance.Id, err) + return err + } return nil } func NewCallService( clientPointer map[string]*whatsmeow.Client, whatsmeowService whatsmeow_service.WhatsmeowService, + callRegistry *call_registry.CallRegistry, loggerWrapper *logger_wrapper.LoggerManager, ) CallService { return &callService{ clientPointer: clientPointer, whatsmeowService: whatsmeowService, + callRegistry: callRegistry, loggerWrapper: loggerWrapper, } } diff --git a/pkg/call/stream/bridge.go b/pkg/call/stream/bridge.go new file mode 100644 index 00000000..92693c11 --- /dev/null +++ b/pkg/call/stream/bridge.go @@ -0,0 +1,153 @@ +// pkg/call/stream/bridge.go +package call_stream + +import ( + "encoding/base64" + "io" + "sync" + + "github.com/gorilla/websocket" + "github.com/purpshell/meowcaller" +) + +// wsMessage is the JSON envelope carried over the stream socket, modeled on Twilio +// Media Streams so existing AI-voice integrations need minimal adapting. +type wsMessage struct { + Event string `json:"event"` + CallID string `json:"callId,omitempty"` + SampleRate int `json:"sampleRate,omitempty"` + Video bool `json:"video,omitempty"` + Track string `json:"track,omitempty"` + Payload string `json:"payload,omitempty"` + Reason string `json:"reason,omitempty"` +} + +// bridge adapts one WebSocket connection to meowcaller's AudioSink (Call.Receive), +// VideoSink (Call.ReceiveVideo), and AudioSource (Call.Play) interfaces, so a single +// object plugs a call's media straight into the socket in both directions. +type bridge struct { + conn *websocket.Conn + writeMu sync.Mutex + incoming chan []float32 + closed chan struct{} + closeOnce sync.Once + sendVideo func([]byte) error + startVideo func() error + startVideoOnce sync.Once +} + +func newBridge(conn *websocket.Conn) *bridge { + return &bridge{ + conn: conn, + // ~3 seconds of buffering at one 60ms frame per slot before frames start + // getting dropped — enough slack for scheduling jitter without unbounded growth. + incoming: make(chan []float32, 50), + closed: make(chan struct{}), + } +} + +func (b *bridge) writeJSON(msg wsMessage) error { + b.writeMu.Lock() + defer b.writeMu.Unlock() + return b.conn.WriteJSON(msg) +} + +// writeStart sends the initial handshake message once the socket is up. +func (b *bridge) writeStart(callID string, video bool) { + _ = b.writeJSON(wsMessage{ + Event: "start", + CallID: callID, + SampleRate: meowcaller.SampleRate, + Video: video, + }) +} + +// WriteFrame implements meowcaller.AudioSink: one decoded mono frame from the peer. +func (b *bridge) WriteFrame(frame []float32) error { + payload := base64.StdEncoding.EncodeToString(pcm16FromFloat32(frame)) + return b.writeJSON(wsMessage{Event: "media", Track: "inbound", Payload: payload}) +} + +// WriteVideo implements meowcaller.VideoSink: one Annex-B H.264 access unit. +func (b *bridge) WriteVideo(accessUnit []byte) error { + payload := base64.StdEncoding.EncodeToString(accessUnit) + return b.writeJSON(wsMessage{Event: "video", Track: "inbound", Payload: payload}) +} + +// ReadFrame implements meowcaller.AudioSource: frames the consumer sent back over the +// socket, decoded by readLoop and handed here on demand. +func (b *bridge) ReadFrame() ([]float32, error) { + select { + case frame, ok := <-b.incoming: + if !ok { + return nil, io.EOF + } + return frame, nil + case <-b.closed: + return nil, io.EOF + } +} + +// Close satisfies AudioSink/VideoSink/AudioSource's shared Close() error method. Safe +// to call more than once (from the call's OnEnd callback and from readLoop exiting). +func (b *bridge) Close() error { + b.closeOnce.Do(func() { + _ = b.writeJSON(wsMessage{Event: "stop", Reason: "hangup"}) + close(b.closed) + _ = b.conn.Close() + }) + return nil +} + +// readLoop blocks reading consumer-sent media messages until the connection closes +// (by either side) or send Close(). Every non-media message is ignored rather than +// erroring, so the wire format can grow new event types without breaking old clients. +func (b *bridge) readLoop() { + for { + var msg wsMessage + if err := b.conn.ReadJSON(&msg); err != nil { + b.Close() + return + } + if msg.Event == "video" && msg.Track == "outbound" { + raw, err := base64.StdEncoding.DecodeString(msg.Payload) + if err != nil || b.sendVideo == nil { + continue + } + // Spike/experimental: outbound video was explicitly out of scope in the + // reviewed plan (video is inbound-only there). Added here to test + // screen-share/camera content actually reaching the peer. + // + // meowcaller's StartVideo doc comment: "Outbound video remains gated + // until the peer acknowledges the transition" -- so the upgrade must be + // requested before any SendVideo call has an effect. Lazily triggered on + // the first outbound video message so callers don't need a separate + // endpoint/step to remember. + b.startVideoOnce.Do(func() { + if b.startVideo != nil { + _ = b.startVideo() + } + }) + if err := b.sendVideo(raw); err != nil { + continue + } + continue + } + if msg.Event != "media" || msg.Track != "outbound" { + continue + } + raw, err := base64.StdEncoding.DecodeString(msg.Payload) + if err != nil { + continue + } + frame := float32FromPCM16(raw) + select { + case b.incoming <- frame: + case <-b.closed: + return + default: + // Consumer is sending audio faster than the call can play it out; drop + // the frame rather than block the socket read loop. + } + } +} diff --git a/pkg/call/stream/codec.go b/pkg/call/stream/codec.go new file mode 100644 index 00000000..52328e75 --- /dev/null +++ b/pkg/call/stream/codec.go @@ -0,0 +1,33 @@ +// pkg/call/stream/codec.go +package call_stream + +import "encoding/binary" + +// pcm16FromFloat32 converts one mono PCM frame (as meowcaller delivers it: float32 +// samples in [-1, 1]) into little-endian 16-bit PCM bytes, clamping out-of-range +// samples the same way meowcaller's own WAVRecorder does. +func pcm16FromFloat32(frame []float32) []byte { + out := make([]byte, len(frame)*2) + for i, s := range frame { + v := s * 32768.0 + if v > 32767 { + v = 32767 + } else if v < -32768 { + v = -32768 + } + binary.LittleEndian.PutUint16(out[2*i:], uint16(int16(v))) + } + return out +} + +// float32FromPCM16 converts little-endian 16-bit PCM bytes (as sent by a stream +// consumer) back into mono float32 samples in [-1, 1] for meowcaller.Call.Play. +func float32FromPCM16(b []byte) []float32 { + n := len(b) / 2 + out := make([]float32, n) + for i := 0; i < n; i++ { + v := int16(binary.LittleEndian.Uint16(b[2*i:])) + out[i] = float32(v) / 32768.0 + } + return out +} diff --git a/pkg/call/stream/codec_test.go b/pkg/call/stream/codec_test.go new file mode 100644 index 00000000..6806b1b8 --- /dev/null +++ b/pkg/call/stream/codec_test.go @@ -0,0 +1,42 @@ +// pkg/call/stream/codec_test.go +package call_stream + +import "testing" + +func TestPCM16RoundTrip(t *testing.T) { + frame := []float32{0, 0.5, -0.5, 1, -1, 0.25} + + pcm := pcm16FromFloat32(frame) + if len(pcm) != len(frame)*2 { + t.Fatalf("expected %d bytes, got %d", len(frame)*2, len(pcm)) + } + + back := float32FromPCM16(pcm) + if len(back) != len(frame) { + t.Fatalf("expected %d samples back, got %d", len(frame), len(back)) + } + + for i, want := range frame { + got := back[i] + diff := got - want + if diff < 0 { + diff = -diff + } + if diff > 0.001 { + t.Errorf("sample %d: want %v, got %v (diff %v)", i, want, got, diff) + } + } +} + +func TestPCM16ClampsOutOfRange(t *testing.T) { + frame := []float32{2.0, -2.0} // out of [-1, 1] range + pcm := pcm16FromFloat32(frame) + back := float32FromPCM16(pcm) + + if back[0] < 0.99 { + t.Errorf("expected clamp to max positive, got %v", back[0]) + } + if back[1] > -0.99 { + t.Errorf("expected clamp to max negative, got %v", back[1]) + } +} diff --git a/pkg/call/stream/handler.go b/pkg/call/stream/handler.go new file mode 100644 index 00000000..957a6efd --- /dev/null +++ b/pkg/call/stream/handler.go @@ -0,0 +1,69 @@ +// pkg/call/stream/handler.go +package call_stream + +import ( + "net/http" + + call_service "github.com/evolution-foundation/evolution-go/pkg/call/service" + instance_service "github.com/evolution-foundation/evolution-go/pkg/instance/service" + "github.com/gin-gonic/gin" + "github.com/gorilla/websocket" +) + +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: func(r *http.Request) bool { return true }, +} + +// RegisterRoutes mounts GET /call/stream/:callId directly on the engine, bypassing the +// header-based authMiddleware chain used by pkg/routes: WebSocket clients (especially +// browser-based ones) can't always set a custom apikey header on the upgrade request, +// so auth here is a query parameter instead, resolved the same way authMiddleware.Auth +// resolves it. This mirrors how pkg/passkey/handler.RegisterRoutes already registers +// its own routes directly on *gin.Engine for the same "doesn't fit the standard +// middleware chain" reason. +func RegisterRoutes(r *gin.Engine, callService call_service.CallService, instanceService instance_service.InstanceService) { + r.GET("/call/stream/:callId", serveStream(callService, instanceService)) +} + +func serveStream(callService call_service.CallService, instanceService instance_service.InstanceService) gin.HandlerFunc { + return func(ctx *gin.Context) { + instance, err := instanceService.GetInstanceByToken(ctx.Query("apikey")) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "not authorized"}) + return + } + + callID := ctx.Param("callId") + call, err := callService.GetActiveCall(instance.Id, callID) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": err.Error()}) + return + } + + conn, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil) + if err != nil { + return + } + + b := newBridge(conn) + b.sendVideo = call.SendVideo + // StartVideo requests an audio->video upgrade. Calling it on a call that + // already has video (declared in the original offer) doesn't just no-op -- + // live testing showed it can drop the call entirely. Only wire it up when + // there's an actual upgrade to request. + if !call.IsVideo() { + b.startVideo = call.StartVideo + } + call.OnEnd(func(reason string) { b.Close() }) + call.Receive(b) + call.ReceiveVideo(b) + call.Play(b) + + b.writeStart(callID, call.IsVideo()) + b.readLoop() // blocks until the socket closes, from either end + + _ = call.Hangup() + } +} diff --git a/pkg/routes/routes.go b/pkg/routes/routes.go index 8e026a87..13a855f1 100644 --- a/pkg/routes/routes.go +++ b/pkg/routes/routes.go @@ -194,6 +194,16 @@ func (r *Routes) AssignRoutes(eng *gin.Engine) { routes.Use(r.authMiddleware.Auth) { routes.POST("/reject", r.jidValidationMiddleware.ValidateNumberField(), r.callHandler.RejectCall) + routes.POST("/answer", r.jidValidationMiddleware.ValidateNumberField(), r.callHandler.AnswerCall) + routes.POST("/hangup", r.callHandler.HangupCall) + routes.POST("/dial", r.callHandler.DialCall) + routes.POST("/react", r.callHandler.ReactCall) + routes.POST("/participant/add", r.jidValidationMiddleware.ValidateNumberField(), r.callHandler.AddParticipant) + routes.POST("/screenshare", r.callHandler.ScreenShareCall) + routes.POST("/handraise", r.callHandler.HandRaiseCall) + routes.POST("/video/upgrade", r.callHandler.VideoUpgradeCall) + routes.POST("/video/enabled", r.callHandler.VideoEnabledCall) + routes.POST("/video/orientation", r.callHandler.VideoOrientationCall) } } routes = eng.Group("/community") diff --git a/pkg/whatsmeow/service/whatsmeow.go b/pkg/whatsmeow/service/whatsmeow.go index 366f0edb..80a1a1b0 100644 --- a/pkg/whatsmeow/service/whatsmeow.go +++ b/pkg/whatsmeow/service/whatsmeow.go @@ -23,6 +23,7 @@ import ( _ "github.com/lib/pq" "github.com/patrickmn/go-cache" + "github.com/purpshell/meowcaller" "github.com/skip2/go-qrcode" "go.mau.fi/whatsmeow" "go.mau.fi/whatsmeow/appstate" @@ -34,6 +35,7 @@ import ( "go.mau.fi/whatsmeow/types/events" waLog "go.mau.fi/whatsmeow/util/log" + call_registry "github.com/evolution-foundation/evolution-go/pkg/call/registry" "github.com/evolution-foundation/evolution-go/pkg/config" producer_interfaces "github.com/evolution-foundation/evolution-go/pkg/events/interfaces" instance_model "github.com/evolution-foundation/evolution-go/pkg/instance/model" @@ -63,6 +65,11 @@ type WhatsmeowService interface { UpdateInstanceAdvancedSettings(instanceId string) error GetPollService() poll_service.PollService // NOVO: Acesso ao serviço de polls + // GetMeowcallerClient returns the per-instance meowcaller client used to place + // and answer WhatsApp calls. Returns an error if the instance has no active + // meowcaller client (i.e. its whatsmeow client was never started). + GetMeowcallerClient(instanceId string) (*meowcaller.Client, error) + // Passkey (WebAuthn) pairing bridge — read by the public ceremony endpoint, // written by the whatsmeow event goroutine. PasskeyCeremonyStore() *ceremony.Store @@ -86,6 +93,8 @@ type whatsmeowService struct { killChannel map[string](chan bool) userInfoCache *cache.Cache clientPointer map[string]*whatsmeow.Client + meowcallerPointer map[string]*meowcaller.Client + callRegistry *call_registry.CallRegistry myClientPointer map[string]*MyClient rabbitmqProducer producer_interfaces.Producer webhookProducer producer_interfaces.Producer @@ -414,6 +423,16 @@ func (w whatsmeowService) StartClient(cd *ClientData) { w.clientPointer[cd.Instance.Id] = client + // meowcaller.NewClient must run before client.Connect() — it installs the raw + // stanza adapter, and doing so after Connect() is a documented race. + meowcallerClient := meowcaller.NewClient(client) + w.meowcallerPointer[cd.Instance.Id] = meowcallerClient + instanceID := cd.Instance.Id + meowcallerClient.OnIncomingCall(func(call *meowcaller.Call) { + w.loggerWrapper.GetLogger(instanceID).LogInfo("[%s] meowcaller captured incoming call %s from %s", instanceID, call.ID(), call.Peer().String()) + w.callRegistry.Store(instanceID, call) + }) + if cd.IsProxy { var proxyConfig ProxyConfig err := json.Unmarshal([]byte(cd.Instance.Proxy), &proxyConfig) @@ -1940,6 +1959,7 @@ func (mycli *MyClient) myEventHandler(rawEvt interface{}) { doWebhook = true postMap["event"] = "CallTerminate" mycli.loggerWrapper.GetLogger(mycli.userID).LogInfo("[%s] Got call terminate %+v", mycli.userID, evt) + mycli.service.(*whatsmeowService).callRegistry.Delete(evt.CallID) case *events.CallOfferNotice: doWebhook = true postMap["event"] = "CallOfferNotice" @@ -2805,6 +2825,7 @@ func NewWhatsmeowService( exPath string, mediaStorage storage_interfaces.MediaStorage, natsProducer producer_interfaces.Producer, + callRegistry *call_registry.CallRegistry, loggerWrapper *logger_wrapper.LoggerManager, ) WhatsmeowService { // Inicializar PollService de forma segura @@ -2820,6 +2841,8 @@ func NewWhatsmeowService( killChannel: killChannel, userInfoCache: cache.New(5*time.Minute, 10*time.Minute), clientPointer: clientPointer, + meowcallerPointer: make(map[string]*meowcaller.Client), + callRegistry: callRegistry, myClientPointer: make(map[string]*MyClient), rabbitmqProducer: rabbitmqProducer, webhookProducer: webhookProducer, @@ -2839,6 +2862,16 @@ func (w *whatsmeowService) GetPollService() poll_service.PollService { return w.pollService } +// GetMeowcallerClient returns the meowcaller client for instanceId, if its +// whatsmeow client has been started. +func (w *whatsmeowService) GetMeowcallerClient(instanceId string) (*meowcaller.Client, error) { + client, ok := w.meowcallerPointer[instanceId] + if !ok || client == nil { + return nil, fmt.Errorf("no active meowcaller client for instance %s", instanceId) + } + return client, nil +} + // PasskeyCeremonyStore exposes the shared ceremony store so the public HTTP // polling endpoint can read the current stage for a given ceremony token. func (w *whatsmeowService) PasskeyCeremonyStore() *ceremony.Store {