blueticks 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/lib/blueticks/client.rb +20 -0
- data/lib/blueticks/resources/boards.rb +124 -0
- data/lib/blueticks/resources/chats.rb +6 -1
- data/lib/blueticks/resources/groups.rb +15 -0
- data/lib/blueticks/resources/identity.rb +27 -0
- data/lib/blueticks/resources/latest_chats.rb +22 -0
- data/lib/blueticks/resources/messages.rb +22 -5
- data/lib/blueticks/resources/realtime.rb +19 -0
- data/lib/blueticks/resources/scheduled_messages.rb +9 -2
- data/lib/blueticks/resources/suno.rb +4 -3
- data/lib/blueticks/types/boards.rb +110 -0
- data/lib/blueticks/types/chats.rb +3 -3
- data/lib/blueticks/types/coverage.rb +14 -0
- data/lib/blueticks/types/groups.rb +11 -0
- data/lib/blueticks/types/identity.rb +28 -0
- data/lib/blueticks/types/latest_chats.rb +32 -0
- data/lib/blueticks/types/messages.rb +9 -1
- data/lib/blueticks/types/paginated.rb +11 -6
- data/lib/blueticks/types/realtime.rb +23 -0
- data/lib/blueticks/types/webhooks.rb +4 -3
- data/lib/blueticks/version.rb +1 -1
- metadata +10 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80ac68082d0098a0ceae9ace729c7d019bbeca7f4714b5f8f11c4846af84ac04
|
|
4
|
+
data.tar.gz: f8d39230912328f38e8e9dda9034cc5d0d9192b47f7ed7857063d2a173fd32ec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fc539e01c948edc214d396f4bb8aafb09eacc7a450a370c5e4675a23021c3705b829b467332c19a1e2c5b4c3ab53d88af64930e122e205b980f1a3354ca4cfb0
|
|
7
|
+
data.tar.gz: ebe45c16ef9311b23600ca225dcaffb1924e64f1df5681966383053a8be2d50d05791abc199db390de7fc30404d87a386892b0086631ecf269187e1ddef21736
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ All notable changes to the Blueticks Ruby SDK are documented here. The format
|
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this
|
|
5
5
|
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## 2.1.1 — 2026-11-07
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Publish workflow now runs on a GitHub-hosted runner (`ubuntu-24.04`); the 2.1.0 publish failed on the self-hosted runner, so 2.1.1 is the first published release with `groups.get_picture` / `groups.remove_picture`.
|
|
11
|
+
|
|
12
|
+
## 2.1.0 — 2026-11-07
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Group picture: `groups.get_picture` (get the current picture URL) and `groups.remove_picture` (remove the picture; Gateway/Baileys engine only — Chrome-extension-only accounts get `501 unsupported_command`). `groups.set_picture` already existed.
|
|
17
|
+
|
|
7
18
|
## 1.2.0 — 2026-05-22
|
|
8
19
|
|
|
9
20
|
OpenAPI parity pass. The SDK now matches `backend/openapi.json`
|
data/lib/blueticks/client.rb
CHANGED
|
@@ -4,14 +4,18 @@ require_relative "errors"
|
|
|
4
4
|
require_relative "transport"
|
|
5
5
|
require_relative "resources/account"
|
|
6
6
|
require_relative "resources/audiences"
|
|
7
|
+
require_relative "resources/boards"
|
|
7
8
|
require_relative "resources/campaigns"
|
|
8
9
|
require_relative "resources/chats"
|
|
9
10
|
require_relative "resources/contacts"
|
|
10
11
|
require_relative "resources/engines"
|
|
11
12
|
require_relative "resources/groups"
|
|
13
|
+
require_relative "resources/identity"
|
|
14
|
+
require_relative "resources/latest_chats"
|
|
12
15
|
require_relative "resources/messages"
|
|
13
16
|
require_relative "resources/newsletters"
|
|
14
17
|
require_relative "resources/ping"
|
|
18
|
+
require_relative "resources/realtime"
|
|
15
19
|
require_relative "resources/scheduled_messages"
|
|
16
20
|
require_relative "resources/suno"
|
|
17
21
|
require_relative "resources/utils"
|
|
@@ -100,6 +104,22 @@ module Blueticks
|
|
|
100
104
|
@messages ||= Resources::MessagesResource.new(self)
|
|
101
105
|
end
|
|
102
106
|
|
|
107
|
+
def boards
|
|
108
|
+
@boards ||= Resources::BoardsResource.new(self)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def identity
|
|
112
|
+
@identity ||= Resources::IdentityResource.new(self)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def latest_chats
|
|
116
|
+
@latest_chats ||= Resources::LatestChatsResource.new(self)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def realtime
|
|
120
|
+
@realtime ||= Resources::RealtimeResource.new(self)
|
|
121
|
+
end
|
|
122
|
+
|
|
103
123
|
def suno
|
|
104
124
|
@suno ||= Resources::SunoResource.new(self)
|
|
105
125
|
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base_resource"
|
|
4
|
+
require_relative "../types/boards"
|
|
5
|
+
require_relative "../types/paginated"
|
|
6
|
+
|
|
7
|
+
module Blueticks
|
|
8
|
+
module Resources
|
|
9
|
+
class BoardsResource < BaseResource
|
|
10
|
+
# List boards, newest first. Offset-paginated (Board rows).
|
|
11
|
+
#
|
|
12
|
+
# Requires the `boards:read` scope.
|
|
13
|
+
def list(order: nil, skip: nil, limit: nil)
|
|
14
|
+
params = {}
|
|
15
|
+
params["order"] = order unless order.nil?
|
|
16
|
+
params["skip"] = skip unless skip.nil?
|
|
17
|
+
params["limit"] = limit unless limit.nil?
|
|
18
|
+
env = client.request("GET", "/v1/boards", params: params.empty? ? nil : params)
|
|
19
|
+
Types::PaginatedPage.from_hash(env, item_type: Types::Board)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Create or find a board.
|
|
23
|
+
#
|
|
24
|
+
# Returns the existing board for the given `domain`/`entity_kind` when one
|
|
25
|
+
# exists, otherwise creates it. Requires the `boards:write` scope.
|
|
26
|
+
def create(domain: nil, entity_kind: nil, name: nil, description: nil,
|
|
27
|
+
agent_id: nil, memory_retention_days: nil)
|
|
28
|
+
body = {}
|
|
29
|
+
body["domain"] = domain unless domain.nil?
|
|
30
|
+
body["entity_kind"] = entity_kind unless entity_kind.nil?
|
|
31
|
+
body["name"] = name unless name.nil?
|
|
32
|
+
body["description"] = description unless description.nil?
|
|
33
|
+
body["agent_id"] = agent_id unless agent_id.nil?
|
|
34
|
+
body["memory_retention_days"] = memory_retention_days unless memory_retention_days.nil?
|
|
35
|
+
env = client.request("POST", "/v1/boards", body: body)
|
|
36
|
+
Types::BoardDetail.from_hash(env && env["data"])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Get a board (with its columns) by id.
|
|
40
|
+
#
|
|
41
|
+
# Requires the `boards:read` scope.
|
|
42
|
+
def retrieve(board_id)
|
|
43
|
+
env = client.request("GET", "/v1/boards/#{board_id}")
|
|
44
|
+
Types::BoardDetail.from_hash(env && env["data"])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# List a board's items (tasks). Offset-paginated (BoardItem rows).
|
|
48
|
+
#
|
|
49
|
+
# Pass `active_only: true` to return only items updated within the
|
|
50
|
+
# retention window whose status is non-terminal. Filter by `status` label
|
|
51
|
+
# or `updated_since`. Requires the `boards:read` scope.
|
|
52
|
+
def list_items(board_id, status: nil, order: nil, active_only: nil,
|
|
53
|
+
updated_since: nil, skip: nil, limit: nil)
|
|
54
|
+
params = {}
|
|
55
|
+
params["status"] = status unless status.nil?
|
|
56
|
+
params["order"] = order unless order.nil?
|
|
57
|
+
params["active_only"] = active_only unless active_only.nil?
|
|
58
|
+
params["updated_since"] = updated_since unless updated_since.nil?
|
|
59
|
+
params["skip"] = skip unless skip.nil?
|
|
60
|
+
params["limit"] = limit unless limit.nil?
|
|
61
|
+
env = client.request("GET", "/v1/boards/#{board_id}/items",
|
|
62
|
+
params: params.empty? ? nil : params)
|
|
63
|
+
Types::PaginatedPage.from_hash(env, item_type: Types::BoardItem)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Create a board item.
|
|
67
|
+
#
|
|
68
|
+
# Requires the `boards:write` scope.
|
|
69
|
+
def create_item(board_id, text:, status: nil, priority: nil, due_date: nil, cells: nil,
|
|
70
|
+
source: nil, confidence: nil, allow_duplicate: nil)
|
|
71
|
+
body = { "text" => text }
|
|
72
|
+
body["status"] = status unless status.nil?
|
|
73
|
+
body["priority"] = priority unless priority.nil?
|
|
74
|
+
body["due_date"] = due_date unless due_date.nil?
|
|
75
|
+
body["cells"] = cells unless cells.nil?
|
|
76
|
+
body["source"] = source unless source.nil?
|
|
77
|
+
body["confidence"] = confidence unless confidence.nil?
|
|
78
|
+
body["allow_duplicate"] = allow_duplicate unless allow_duplicate.nil?
|
|
79
|
+
env = client.request("POST", "/v1/boards/#{board_id}/items", body: body)
|
|
80
|
+
Types::BoardItem.from_hash(env && env["data"])
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Update a board item. Pass any subset of the editable fields.
|
|
84
|
+
#
|
|
85
|
+
# Requires the `boards:write` scope.
|
|
86
|
+
def update_item(board_id, item_id, text: nil, status: nil, priority: nil, due_date: nil,
|
|
87
|
+
cells: nil, source: nil, confidence: nil, deleted: nil, note: nil)
|
|
88
|
+
body = {}
|
|
89
|
+
body["text"] = text unless text.nil?
|
|
90
|
+
body["status"] = status unless status.nil?
|
|
91
|
+
body["priority"] = priority unless priority.nil?
|
|
92
|
+
body["due_date"] = due_date unless due_date.nil?
|
|
93
|
+
body["cells"] = cells unless cells.nil?
|
|
94
|
+
body["source"] = source unless source.nil?
|
|
95
|
+
body["confidence"] = confidence unless confidence.nil?
|
|
96
|
+
body["deleted"] = deleted unless deleted.nil?
|
|
97
|
+
body["note"] = note unless note.nil?
|
|
98
|
+
env = client.request("PATCH", "/v1/boards/#{board_id}/items/#{item_id}", body: body)
|
|
99
|
+
Types::BoardItem.from_hash(env && env["data"])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Bulk upsert board items.
|
|
103
|
+
#
|
|
104
|
+
# `items` is an Array of item Hashes (same keys as `create_item`, string
|
|
105
|
+
# keys on the wire). Requires the `boards:write` scope.
|
|
106
|
+
def bulk_upsert_items(board_id, items:, mode: nil)
|
|
107
|
+
body = { "items" => items }
|
|
108
|
+
body["mode"] = mode unless mode.nil?
|
|
109
|
+
env = client.request("POST", "/v1/boards/#{board_id}/items/bulk", body: body)
|
|
110
|
+
Types::BulkItemsResult.from_hash(env && env["data"])
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Find existing board items similar to the given candidates.
|
|
114
|
+
#
|
|
115
|
+
# `candidates` is an Array of `{ "text" => "..." }` Hashes. Requires the
|
|
116
|
+
# `boards:read` scope.
|
|
117
|
+
def find_similar_items(board_id, candidates:)
|
|
118
|
+
env = client.request("POST", "/v1/boards/#{board_id}/items/find-similar",
|
|
119
|
+
body: { "candidates" => candidates })
|
|
120
|
+
Types::FindSimilarResult.from_hash(env && env["data"])
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -9,9 +9,12 @@ module Blueticks
|
|
|
9
9
|
module Resources
|
|
10
10
|
class ChatsResource < BaseResource
|
|
11
11
|
# List/search chats, newest first. Offset-paginated.
|
|
12
|
+
#
|
|
13
|
+
# `kinds` is an Array of chat kinds to keep (`%w[contact group newsletter]`);
|
|
14
|
+
# `since` keeps only chats whose last message is at/after that ISO 8601 instant.
|
|
12
15
|
def list(search_token: nil, filter: nil, include_last_message: nil,
|
|
13
16
|
include_extended_info: nil, include_without_name: nil,
|
|
14
|
-
include_archive: nil, skip: nil, limit: nil)
|
|
17
|
+
include_archive: nil, skip: nil, limit: nil, kinds: nil, since: nil)
|
|
15
18
|
params = {}
|
|
16
19
|
params["searchToken"] = search_token unless search_token.nil?
|
|
17
20
|
params["filter"] = filter unless filter.nil?
|
|
@@ -21,6 +24,8 @@ module Blueticks
|
|
|
21
24
|
params["includeArchive"] = include_archive unless include_archive.nil?
|
|
22
25
|
params["skip"] = skip unless skip.nil?
|
|
23
26
|
params["limit"] = limit unless limit.nil?
|
|
27
|
+
params["kinds"] = kinds unless kinds.nil? || kinds.empty?
|
|
28
|
+
params["since"] = since unless since.nil?
|
|
24
29
|
env = client.request("GET", "/v1/chats", params: params.empty? ? nil : params)
|
|
25
30
|
Types::PaginatedPage.from_hash(env, item_type: Types::Chat)
|
|
26
31
|
end
|
|
@@ -88,6 +88,21 @@ module Blueticks
|
|
|
88
88
|
Types::Group.from_hash(env && env["data"])
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
+
# Get the current group picture as a short-lived WhatsApp CDN `url`, or
|
|
92
|
+
# `url: nil` when the group has none. Requires `groups:read`.
|
|
93
|
+
def get_picture(group_id)
|
|
94
|
+
env = client.request("GET", "/v1/groups/#{group_id}/picture")
|
|
95
|
+
Types::GroupPicture.from_hash(env && env["data"])
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Remove the group picture. Gateway (Baileys) engine only: a
|
|
99
|
+
# Chrome-extension-only account gets 501 `unsupported_command`. Requires
|
|
100
|
+
# `groups:write`.
|
|
101
|
+
def remove_picture(group_id)
|
|
102
|
+
env = client.request("DELETE", "/v1/groups/#{group_id}/picture")
|
|
103
|
+
Types::GroupPictureRemoved.from_hash(env && env["data"])
|
|
104
|
+
end
|
|
105
|
+
|
|
91
106
|
# Leave the group as the authenticated identity. Idempotent (204).
|
|
92
107
|
def leave(group_id)
|
|
93
108
|
client.request("DELETE", "/v1/groups/#{group_id}/members/me")
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base_resource"
|
|
4
|
+
require_relative "../types/identity"
|
|
5
|
+
|
|
6
|
+
module Blueticks
|
|
7
|
+
module Resources
|
|
8
|
+
class IdentityResource < BaseResource
|
|
9
|
+
# Resolve an identity.
|
|
10
|
+
#
|
|
11
|
+
# Maps a WhatsApp JID (phone, `@lid` or group) to its canonical form and
|
|
12
|
+
# aliases. Requires the `contacts:read` scope.
|
|
13
|
+
def retrieve(id)
|
|
14
|
+
env = client.request("GET", "/v1/identity/#{id}")
|
|
15
|
+
Types::Identity.from_hash(env && env["data"])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Resolve identities (batch).
|
|
19
|
+
#
|
|
20
|
+
# Resolves many JIDs in one call. Requires the `contacts:read` scope.
|
|
21
|
+
def resolve_batch(ids:)
|
|
22
|
+
env = client.request("POST", "/v1/identity/resolve", body: { "ids" => ids })
|
|
23
|
+
Types::IdentityBatch.from_hash(env && env["data"])
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base_resource"
|
|
4
|
+
require_relative "../types/latest_chats"
|
|
5
|
+
|
|
6
|
+
module Blueticks
|
|
7
|
+
module Resources
|
|
8
|
+
class LatestChatsResource < BaseResource
|
|
9
|
+
# Get latest chats & messages.
|
|
10
|
+
#
|
|
11
|
+
# Returns the most recent chats, each with its latest messages, in one
|
|
12
|
+
# call. Requires the `chats:read` scope.
|
|
13
|
+
def retrieve(number_of_chats: nil, number_of_messages: nil)
|
|
14
|
+
params = {}
|
|
15
|
+
params["numberOfChats"] = number_of_chats unless number_of_chats.nil?
|
|
16
|
+
params["numberOfMessages"] = number_of_messages unless number_of_messages.nil?
|
|
17
|
+
env = client.request("GET", "/v1/latest-chats", params: params.empty? ? nil : params)
|
|
18
|
+
Types::LatestChats.from_hash(env && env["data"])
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -10,10 +10,13 @@ module Blueticks
|
|
|
10
10
|
class MessagesResource < BaseResource
|
|
11
11
|
# Query messages from the WhatsApp store, newest first. Offset-paginated
|
|
12
12
|
# (PublicMessage rows). `message_types` is an Array of wire message types
|
|
13
|
-
# (e.g. `%w[chat image]`).
|
|
13
|
+
# (e.g. `%w[chat image]`). `query_any` is an Array of keywords matched with OR
|
|
14
|
+
# semantics; `mime`, `filename_contains`, `has_media` and `sender` narrow the
|
|
15
|
+
# result further.
|
|
14
16
|
def list(chat_id: nil, search_token: nil, order: nil, since: nil, until_: nil,
|
|
15
17
|
message_types: nil, load_from_phone_if_needed: nil,
|
|
16
|
-
include_media_content: nil, skip: nil, limit: nil
|
|
18
|
+
include_media_content: nil, skip: nil, limit: nil,
|
|
19
|
+
query_any: nil, mime: nil, filename_contains: nil, has_media: nil, sender: nil)
|
|
17
20
|
params = {}
|
|
18
21
|
params["chatId"] = chat_id unless chat_id.nil?
|
|
19
22
|
params["searchToken"] = search_token unless search_token.nil?
|
|
@@ -25,6 +28,11 @@ module Blueticks
|
|
|
25
28
|
params["includeMediaContent"] = include_media_content unless include_media_content.nil?
|
|
26
29
|
params["skip"] = skip unless skip.nil?
|
|
27
30
|
params["limit"] = limit unless limit.nil?
|
|
31
|
+
params["queryAny"] = query_any unless query_any.nil? || query_any.empty?
|
|
32
|
+
params["mime"] = mime unless mime.nil?
|
|
33
|
+
params["filenameContains"] = filename_contains unless filename_contains.nil?
|
|
34
|
+
params["hasMedia"] = has_media unless has_media.nil?
|
|
35
|
+
params["sender"] = sender unless sender.nil?
|
|
28
36
|
env = client.request("GET", "/v1/messages", params: params.empty? ? nil : params)
|
|
29
37
|
Types::PaginatedPage.from_hash(env, item_type: Types::PublicMessage)
|
|
30
38
|
end
|
|
@@ -54,8 +62,15 @@ module Blueticks
|
|
|
54
62
|
end
|
|
55
63
|
|
|
56
64
|
# Ask the engine to pull older history from the connected phone.
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
#
|
|
66
|
+
# `pages` (1-10, default 1) is how many older pages to pull in one call;
|
|
67
|
+
# `until_date` (ISO 8601 string or epoch seconds/ms) stops paging once the
|
|
68
|
+
# oldest loaded message is at/before that date.
|
|
69
|
+
def load_older(chat_id, pages: nil, until_date: nil)
|
|
70
|
+
body = {}
|
|
71
|
+
body["pages"] = pages unless pages.nil?
|
|
72
|
+
body["until_date"] = until_date unless until_date.nil?
|
|
73
|
+
env = client.request("POST", "/v1/messages/load_older/#{chat_id}", body: body.empty? ? nil : body)
|
|
59
74
|
Types::LoadOlderResult.from_hash(env && env["data"])
|
|
60
75
|
end
|
|
61
76
|
|
|
@@ -105,7 +120,8 @@ module Blueticks
|
|
|
105
120
|
def create(chat_id, type:, text: nil, media_url: nil, media_base64: nil,
|
|
106
121
|
media_kind: nil, media_filename: nil, poll_question: nil,
|
|
107
122
|
poll_options: nil, poll_allow_multiple: nil, reply_to: nil,
|
|
108
|
-
secret: nil, with_typing: nil, typing_seconds: nil, idempotency_key: nil
|
|
123
|
+
secret: nil, with_typing: nil, typing_seconds: nil, idempotency_key: nil,
|
|
124
|
+
mentions: nil)
|
|
109
125
|
body = { "type" => type }
|
|
110
126
|
body["text"] = text unless text.nil?
|
|
111
127
|
body["mediaUrl"] = media_url unless media_url.nil?
|
|
@@ -119,6 +135,7 @@ module Blueticks
|
|
|
119
135
|
body["secret"] = secret unless secret.nil?
|
|
120
136
|
body["withTyping"] = with_typing unless with_typing.nil?
|
|
121
137
|
body["typingSeconds"] = typing_seconds unless typing_seconds.nil?
|
|
138
|
+
body["mentions"] = mentions unless mentions.nil?
|
|
122
139
|
env = client.request("POST", "/v1/messages/#{chat_id}", body: body, idempotency_key: idempotency_key)
|
|
123
140
|
Types::Message.from_hash(env && env["data"])
|
|
124
141
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base_resource"
|
|
4
|
+
require_relative "../types/realtime"
|
|
5
|
+
|
|
6
|
+
module Blueticks
|
|
7
|
+
module Resources
|
|
8
|
+
class RealtimeResource < BaseResource
|
|
9
|
+
# Get MQTT credentials for receiving messages in real time.
|
|
10
|
+
#
|
|
11
|
+
# Returns short-lived broker credentials and the topic to subscribe to.
|
|
12
|
+
# Requires the `chats:read` scope.
|
|
13
|
+
def create_token
|
|
14
|
+
env = client.request("POST", "/v1/realtime/token")
|
|
15
|
+
Types::RealtimeToken.from_hash(env && env["data"])
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -15,6 +15,9 @@ module Blueticks
|
|
|
15
15
|
# Omit `send_at` to dispatch as soon as possible, or pass an ISO-8601
|
|
16
16
|
# timestamp to schedule it.
|
|
17
17
|
#
|
|
18
|
+
# `mentions` is an Array of participant JIDs to @mention in a group;
|
|
19
|
+
# `recipient_name` is an optional display name for the scheduled-message list.
|
|
20
|
+
#
|
|
18
21
|
# - `type: "text"` — requires `text`.
|
|
19
22
|
# - `type: "media"` — requires `media_url` or `media_base64`; optional
|
|
20
23
|
# `media_kind`, `media_filename`.
|
|
@@ -23,7 +26,8 @@ module Blueticks
|
|
|
23
26
|
def create(chat_id, type:, text: nil, media_url: nil, media_base64: nil,
|
|
24
27
|
media_kind: nil, media_filename: nil, poll_question: nil,
|
|
25
28
|
poll_options: nil, poll_allow_multiple: nil, reply_to: nil,
|
|
26
|
-
secret: nil, send_at: nil, idempotency_key: nil
|
|
29
|
+
secret: nil, send_at: nil, idempotency_key: nil,
|
|
30
|
+
mentions: nil, recipient_name: nil)
|
|
27
31
|
body = { "type" => type }
|
|
28
32
|
body["text"] = text unless text.nil?
|
|
29
33
|
body["mediaUrl"] = media_url unless media_url.nil?
|
|
@@ -36,6 +40,8 @@ module Blueticks
|
|
|
36
40
|
body["replyTo"] = reply_to unless reply_to.nil?
|
|
37
41
|
body["secret"] = secret unless secret.nil?
|
|
38
42
|
body["sendAt"] = send_at unless send_at.nil?
|
|
43
|
+
body["mentions"] = mentions unless mentions.nil?
|
|
44
|
+
body["recipientName"] = recipient_name unless recipient_name.nil?
|
|
39
45
|
env = client.request("POST", "/v1/scheduled-messages/#{chat_id}", body: body,
|
|
40
46
|
idempotency_key: idempotency_key)
|
|
41
47
|
Types::ScheduledMessage.from_hash(env && env["data"])
|
|
@@ -67,7 +73,7 @@ module Blueticks
|
|
|
67
73
|
def update(message_id, type: nil, text: nil, media_url: nil, media_base64: nil,
|
|
68
74
|
media_kind: nil, media_filename: nil, poll_question: nil,
|
|
69
75
|
poll_options: nil, poll_allow_multiple: nil, reply_to: nil,
|
|
70
|
-
secret: nil, send_at: nil)
|
|
76
|
+
secret: nil, send_at: nil, mentions: nil)
|
|
71
77
|
body = {}
|
|
72
78
|
body["type"] = type unless type.nil?
|
|
73
79
|
body["text"] = text unless text.nil?
|
|
@@ -81,6 +87,7 @@ module Blueticks
|
|
|
81
87
|
body["replyTo"] = reply_to unless reply_to.nil?
|
|
82
88
|
body["secret"] = secret unless secret.nil?
|
|
83
89
|
body["sendAt"] = send_at unless send_at.nil?
|
|
90
|
+
body["mentions"] = mentions unless mentions.nil?
|
|
84
91
|
env = client.request("PATCH", "/v1/scheduled-messages/#{message_id}", body: body)
|
|
85
92
|
Types::ScheduledMessage.from_hash(env && env["data"])
|
|
86
93
|
end
|
|
@@ -12,15 +12,16 @@ module Blueticks
|
|
|
12
12
|
Types::SunoAccount.from_hash(env && env["data"])
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
# Submit a song generation job. Requires `lyrics`
|
|
15
|
+
# Submit a song generation job. Requires `style`; `lyrics` is required unless `instrumental` is true. The many
|
|
16
16
|
# optional knobs mirror the Suno request (vocal_gender, weirdness,
|
|
17
17
|
# style_influence, audio_influence, instrumental, model, title, upload_id,
|
|
18
18
|
# captcha_token, negative_style).
|
|
19
|
-
def create_song(
|
|
19
|
+
def create_song(style:, lyrics: nil, negative_style: nil, vocal_gender: nil,
|
|
20
20
|
weirdness: nil, style_influence: nil, audio_influence: nil,
|
|
21
21
|
instrumental: nil, model: nil, title: nil, upload_id: nil,
|
|
22
22
|
captcha_token: nil)
|
|
23
|
-
body = { "
|
|
23
|
+
body = { "style" => style }
|
|
24
|
+
body["lyrics"] = lyrics unless lyrics.nil?
|
|
24
25
|
body["negativeStyle"] = negative_style unless negative_style.nil?
|
|
25
26
|
body["vocalGender"] = vocal_gender unless vocal_gender.nil?
|
|
26
27
|
body["weirdness"] = weirdness unless weirdness.nil?
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module Blueticks
|
|
6
|
+
module Types
|
|
7
|
+
# A status/priority label with its colour (OptionRef).
|
|
8
|
+
class BoardOption < Base
|
|
9
|
+
field :label, :string
|
|
10
|
+
field :bgcolor, :string
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# A board column definition (BoardColumn). `type` is the column kind
|
|
14
|
+
# (e.g. "status", "text"); `options` lists the selectable labels.
|
|
15
|
+
class BoardColumn < Base
|
|
16
|
+
field :column_id, :string
|
|
17
|
+
field :title, :string
|
|
18
|
+
field :type, :string
|
|
19
|
+
field :options, [:array, BoardOption]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# A board summary (BoardRow) as returned by boards.list.
|
|
23
|
+
class Board < Base
|
|
24
|
+
field :board_id, :string
|
|
25
|
+
field :name, :string
|
|
26
|
+
field :description, :string, optional: true
|
|
27
|
+
field :domain, :string, optional: true
|
|
28
|
+
field :agent_managed, :boolean
|
|
29
|
+
field :memory_retention_days, :integer, optional: true
|
|
30
|
+
field :item_count, :integer, optional: true
|
|
31
|
+
field :web_url, :string
|
|
32
|
+
field :created_at, :string
|
|
33
|
+
field :updated_at, :string
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# A board with its columns (BoardDetail) as returned by boards.create and
|
|
37
|
+
# boards.retrieve.
|
|
38
|
+
class BoardDetail < Base
|
|
39
|
+
field :board_id, :string
|
|
40
|
+
field :name, :string
|
|
41
|
+
field :description, :string, optional: true
|
|
42
|
+
field :domain, :string, optional: true
|
|
43
|
+
field :agent_managed, :boolean
|
|
44
|
+
field :memory_retention_days, :integer, optional: true
|
|
45
|
+
field :item_count, :integer, optional: true
|
|
46
|
+
field :web_url, :string
|
|
47
|
+
field :created_at, :string
|
|
48
|
+
field :updated_at, :string
|
|
49
|
+
field :columns, [:array, BoardColumn]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Short board reference (BoardRef) embedded in a bulk-upsert result.
|
|
53
|
+
class BoardRef < Base
|
|
54
|
+
field :board_id, :string
|
|
55
|
+
field :name, :string
|
|
56
|
+
field :description, :string, optional: true
|
|
57
|
+
field :domain, :string, optional: true
|
|
58
|
+
field :web_url, :string
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# The chat message an item was extracted from (ItemSource).
|
|
62
|
+
class ItemSource < Base
|
|
63
|
+
field :chat_id, :string, optional: true
|
|
64
|
+
field :chat_name, :string, optional: true
|
|
65
|
+
field :message_key, :string, optional: true
|
|
66
|
+
field :excerpt, :string, optional: true
|
|
67
|
+
field :extracted_at, :integer, optional: true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# A board item / task (BoardItem). `cells` holds custom column values keyed
|
|
71
|
+
# by column title (string or number).
|
|
72
|
+
class BoardItem < Base
|
|
73
|
+
field :item_id, :string
|
|
74
|
+
field :text, :string
|
|
75
|
+
field :status, BoardOption, optional: true
|
|
76
|
+
field :priority, BoardOption, optional: true
|
|
77
|
+
field :due_date, :string, optional: true
|
|
78
|
+
field :cells, :hash, optional: true
|
|
79
|
+
field :source, ItemSource, optional: true
|
|
80
|
+
field :confidence, :number, optional: true
|
|
81
|
+
field :last_seen_at, :integer, optional: true
|
|
82
|
+
field :web_url, :string
|
|
83
|
+
field :created_at, :string
|
|
84
|
+
field :updated_at, :string
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Result of a bulk upsert (BulkItemsResponse).
|
|
88
|
+
class BulkItemsResult < Base
|
|
89
|
+
field :created, [:array, BoardItem]
|
|
90
|
+
field :updated, [:array, BoardItem]
|
|
91
|
+
field :unchanged, :integer
|
|
92
|
+
field :board, BoardRef
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# One candidate-to-existing-item match (FindSimilarResponse.matches[]).
|
|
96
|
+
class SimilarMatch < Base
|
|
97
|
+
field :candidate_index, :integer
|
|
98
|
+
field :item_id, :string
|
|
99
|
+
field :text, :string
|
|
100
|
+
field :score, :number
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Result of boards.find_similar_items (FindSimilarResponse). `misses` holds
|
|
104
|
+
# the indexes of candidates with no match.
|
|
105
|
+
class FindSimilarResult < Base
|
|
106
|
+
field :matches, [:array, SimilarMatch]
|
|
107
|
+
field :misses, %i[array integer]
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -9,12 +9,12 @@ module Blueticks
|
|
|
9
9
|
# A chat row (Chat) returned by chats.list / chats.retrieve.
|
|
10
10
|
class Chat < Base
|
|
11
11
|
field :chat_id, :string, wire_name: "chatId"
|
|
12
|
-
field :name, :string, nullable: true
|
|
12
|
+
field :name, :string, nullable: true, optional: true
|
|
13
13
|
field :chat_type, [:enum, CHAT_TYPES], wire_name: "chatType"
|
|
14
14
|
field :pinned, :boolean, optional: true
|
|
15
15
|
field :archived, :boolean, optional: true
|
|
16
|
-
field :last_message_at, :string, nullable: true, wire_name: "lastMessageAt"
|
|
17
|
-
field :unread_count, :integer, nullable: true, wire_name: "unreadCount"
|
|
16
|
+
field :last_message_at, :string, nullable: true, optional: true, wire_name: "lastMessageAt"
|
|
17
|
+
field :unread_count, :integer, nullable: true, optional: true, wire_name: "unreadCount"
|
|
18
18
|
field :marked_unread, :boolean, wire_name: "markedUnread"
|
|
19
19
|
field :last_message_text, :string, nullable: true, optional: true, wire_name: "lastMessageText"
|
|
20
20
|
field :last_message_from_me, :boolean, nullable: true, optional: true, wire_name: "lastMessageFromMe"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module Blueticks
|
|
6
|
+
module Types
|
|
7
|
+
# How far back a chat is loaded (LoadCoverage). `oldest_loaded_iso` is the
|
|
8
|
+
# deterministic answer to "have I reached far enough back?".
|
|
9
|
+
class Coverage < Base
|
|
10
|
+
field :oldest_loaded_timestamp, :number, optional: true, wire_name: "oldestLoadedTimestamp"
|
|
11
|
+
field :oldest_loaded_iso, :string, optional: true, wire_name: "oldestLoadedIso"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -27,6 +27,17 @@ module Blueticks
|
|
|
27
27
|
field :participants, [:array, GroupParticipant], nullable: true
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
# Current group picture (GroupPicture). `url` is a short-lived WhatsApp CDN
|
|
31
|
+
# URL, or nil when the group has no picture.
|
|
32
|
+
class GroupPicture < Base
|
|
33
|
+
field :url, :string, nullable: true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Result of removing a group picture (GroupPictureRemoved).
|
|
37
|
+
class GroupPictureRemoved < Base
|
|
38
|
+
field :ok, :boolean
|
|
39
|
+
end
|
|
40
|
+
|
|
30
41
|
# A group row in the groups.list / contacts.common_groups page
|
|
31
42
|
# (GroupListItem) — a slimmer projection without announce/participants.
|
|
32
43
|
class GroupListItem < Base
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module Blueticks
|
|
6
|
+
module Types
|
|
7
|
+
IDENTITY_TYPES = %w[user group unknown].freeze
|
|
8
|
+
IDENTITY_SOURCES = %w[engine cache unknown].freeze
|
|
9
|
+
|
|
10
|
+
# A resolved WhatsApp identity (Identity). `canonical`, `phone` and `lid`
|
|
11
|
+
# are absent/null when the identity could not be resolved.
|
|
12
|
+
class Identity < Base
|
|
13
|
+
field :input, :string
|
|
14
|
+
field :resolved, :boolean
|
|
15
|
+
field :canonical, :string, optional: true, nullable: true
|
|
16
|
+
field :phone, :string, optional: true, nullable: true
|
|
17
|
+
field :lid, :string, optional: true, nullable: true
|
|
18
|
+
field :aliases, %i[array string]
|
|
19
|
+
field :type, [:enum, IDENTITY_TYPES]
|
|
20
|
+
field :source, [:enum, IDENTITY_SOURCES]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Batch identity-resolution result (IdentityBatchResponse).
|
|
24
|
+
class IdentityBatch < Base
|
|
25
|
+
field :data, [:array, Identity]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
require_relative "chats"
|
|
5
|
+
require_relative "messages"
|
|
6
|
+
|
|
7
|
+
module Blueticks
|
|
8
|
+
module Types
|
|
9
|
+
# A chat row together with its latest messages (LatestChatWithMessages).
|
|
10
|
+
class LatestChat < Base
|
|
11
|
+
field :chat_id, :string, wire_name: "chatId"
|
|
12
|
+
field :name, :string, optional: true, nullable: true
|
|
13
|
+
field :chat_type, [:enum, CHAT_TYPES], wire_name: "chatType"
|
|
14
|
+
field :pinned, :boolean, optional: true
|
|
15
|
+
field :archived, :boolean, optional: true
|
|
16
|
+
field :last_message_at, :string, optional: true, nullable: true, wire_name: "lastMessageAt"
|
|
17
|
+
field :unread_count, :integer, optional: true, nullable: true, wire_name: "unreadCount"
|
|
18
|
+
field :marked_unread, :boolean, wire_name: "markedUnread"
|
|
19
|
+
field :last_message_text, :string, nullable: true, optional: true, wire_name: "lastMessageText"
|
|
20
|
+
field :last_message_from_me, :boolean, nullable: true, optional: true, wire_name: "lastMessageFromMe"
|
|
21
|
+
field :messages, [:array, PublicMessage]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Latest chats and their messages (LatestChatsResponse) from GET /v1/latest-chats.
|
|
25
|
+
class LatestChats < Base
|
|
26
|
+
field :chats, [:array, LatestChat]
|
|
27
|
+
field :total_chats, :integer, wire_name: "totalChats"
|
|
28
|
+
field :number_of_chats, :integer, wire_name: "numberOfChats"
|
|
29
|
+
field :number_of_messages, :integer, wire_name: "numberOfMessages"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "base"
|
|
4
|
+
require_relative "coverage"
|
|
4
5
|
|
|
5
6
|
module Blueticks
|
|
6
7
|
module Types
|
|
7
8
|
MESSAGE_KINDS = %w[text media poll].freeze
|
|
8
9
|
MESSAGE_MEDIA_KINDS = %w[image video audio document sticker voice gif].freeze
|
|
9
10
|
MEDIA_UNAVAILABLE_REASONS = %w[expired fetching awaiting_sender error no_media].freeze
|
|
11
|
+
MESSAGE_SOURCES = %w[vault backup].freeze
|
|
10
12
|
MESSAGE_STATUSES = %w[
|
|
11
13
|
pending before-wa-send bt-sent sending sent sent_pending_ack confirmed
|
|
12
14
|
delivered received read played cancelled error failed expired
|
|
@@ -65,6 +67,8 @@ module Blueticks
|
|
|
65
67
|
field :filename, :string, optional: true
|
|
66
68
|
field :link_preview, PublicLinkPreview, optional: true, wire_name: "linkPreview"
|
|
67
69
|
field :quoted_message, QuotedMessage, optional: true, wire_name: "quotedMessage"
|
|
70
|
+
field :source, [:enum, MESSAGE_SOURCES], optional: true
|
|
71
|
+
field :secret, :string, optional: true
|
|
68
72
|
end
|
|
69
73
|
|
|
70
74
|
# Media payload for a message (Media) returned by messages.get_media.
|
|
@@ -97,13 +101,17 @@ module Blueticks
|
|
|
97
101
|
field :text, :string, nullable: true
|
|
98
102
|
end
|
|
99
103
|
|
|
100
|
-
# Result of a load-older request (LoadOlderResult).
|
|
104
|
+
# Result of a load-older request (LoadOlderResult). `pages_executed` is how
|
|
105
|
+
# many older pages this call pulled; `coverage` says how far back the chat is
|
|
106
|
+
# now loaded.
|
|
101
107
|
class LoadOlderResult < Base
|
|
102
108
|
field :total_messages, :integer, nullable: true, wire_name: "totalMessages"
|
|
103
109
|
field :added, :integer, nullable: true
|
|
104
110
|
field :can_load_more, :boolean, wire_name: "canLoadMore"
|
|
105
111
|
field :history_unavailable, :boolean, wire_name: "historyUnavailable"
|
|
106
112
|
field :error, :string, nullable: true
|
|
113
|
+
field :pages_executed, :integer, wire_name: "pagesExecuted"
|
|
114
|
+
field :coverage, Coverage
|
|
107
115
|
end
|
|
108
116
|
|
|
109
117
|
# A sent/queued outbound message record — the shape returned by
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "base"
|
|
4
|
+
require_relative "coverage"
|
|
4
5
|
require_relative "../errors"
|
|
5
6
|
|
|
6
7
|
module Blueticks
|
|
@@ -11,21 +12,23 @@ module Blueticks
|
|
|
11
12
|
# Iterate `data` for the current page; advance by passing `skip: skip + limit`
|
|
12
13
|
# (or any offset) back on the next list call. `total` is the full match count
|
|
13
14
|
# across all pages. `has_more` is populated only by endpoints that echo a
|
|
14
|
-
# `hasMore` flag (e.g. messages.list); nil elsewhere.
|
|
15
|
+
# `hasMore` flag (e.g. messages.list); nil elsewhere. `coverage` (Types::Coverage) is
|
|
16
|
+
# likewise populated only by messages.list.
|
|
15
17
|
class PaginatedPage
|
|
16
|
-
attr_reader :data, :limit, :skip, :total, :has_more
|
|
18
|
+
attr_reader :data, :limit, :skip, :total, :has_more, :coverage
|
|
17
19
|
|
|
18
|
-
def initialize(data:, limit:, skip:, total:, has_more: nil)
|
|
20
|
+
def initialize(data:, limit:, skip:, total:, has_more: nil, coverage: nil)
|
|
19
21
|
@data = data
|
|
20
22
|
@limit = limit
|
|
21
23
|
@skip = skip
|
|
22
24
|
@total = total
|
|
23
25
|
@has_more = has_more
|
|
26
|
+
@coverage = coverage
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
# Build a PaginatedPage from a raw list envelope, decoding each item via
|
|
27
30
|
# item_type.from_hash. Reads `data`/`limit`/`skip`/`total` (and optional
|
|
28
|
-
# `hasMore`) off the envelope; ignores the `success` flag.
|
|
31
|
+
# `hasMore` / `coverage`) off the envelope; ignores the `success` flag.
|
|
29
32
|
def self.from_hash(raw, item_type:)
|
|
30
33
|
unless raw.is_a?(Hash)
|
|
31
34
|
raise Errors::ValidationError.new(message: "Expected Hash for PaginatedPage, got #{raw.class}")
|
|
@@ -43,11 +46,13 @@ module Blueticks
|
|
|
43
46
|
raise Errors::ValidationError.new(message: "Field 'hasMore' must be boolean or absent in PaginatedPage")
|
|
44
47
|
end
|
|
45
48
|
|
|
49
|
+
coverage = raw["coverage"].nil? ? nil : Coverage.from_hash(raw["coverage"], context: "PaginatedPage.coverage")
|
|
50
|
+
|
|
46
51
|
decoded = raw["data"].each_with_index.map do |item, i|
|
|
47
52
|
item_type.from_hash(item, context: "PaginatedPage.data[#{i}]")
|
|
48
53
|
end
|
|
49
54
|
|
|
50
|
-
new(data: decoded, limit: limit, skip: skip, total: total, has_more: has_more)
|
|
55
|
+
new(data: decoded, limit: limit, skip: skip, total: total, has_more: has_more, coverage: coverage)
|
|
51
56
|
end
|
|
52
57
|
|
|
53
58
|
def self.require_integer(raw, key)
|
|
@@ -62,7 +67,7 @@ module Blueticks
|
|
|
62
67
|
def to_h
|
|
63
68
|
{
|
|
64
69
|
data: data.map { |d| d.respond_to?(:to_h) ? d.to_h : d },
|
|
65
|
-
limit: limit, skip: skip, total: total, has_more: has_more
|
|
70
|
+
limit: limit, skip: skip, total: total, has_more: has_more, coverage: coverage&.to_h
|
|
66
71
|
}
|
|
67
72
|
end
|
|
68
73
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module Blueticks
|
|
6
|
+
module Types
|
|
7
|
+
# MQTT topics the realtime credentials are authorised for.
|
|
8
|
+
class RealtimeTopics < Base
|
|
9
|
+
field :messages, :string
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Short-lived MQTT credentials for receiving messages in real time
|
|
13
|
+
# (RealtimeTokenResponse).
|
|
14
|
+
class RealtimeToken < Base
|
|
15
|
+
field :broker_url, :string, wire_name: "brokerUrl"
|
|
16
|
+
field :username, :string
|
|
17
|
+
field :password, :string
|
|
18
|
+
field :expires_at, :string, wire_name: "expiresAt"
|
|
19
|
+
field :expires_in_seconds, :integer, wire_name: "expiresInSeconds"
|
|
20
|
+
field :topics, RealtimeTopics
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -16,11 +16,11 @@ module Blueticks
|
|
|
16
16
|
group_admin_changed_webhook group_name_changed_webhook group_description_changed_webhook
|
|
17
17
|
group_message_pinned_webhook poll_vote_webhook reply_to_my_message_webhook
|
|
18
18
|
message_deleted_revoked_webhook message_edited_webhook
|
|
19
|
+
new_message_received_from_me_webhook
|
|
19
20
|
].freeze
|
|
20
21
|
|
|
21
|
-
# A webhook subscription (WebhookResponse).
|
|
22
|
-
#
|
|
23
|
-
# API response body in 2.x.
|
|
22
|
+
# A webhook subscription (WebhookResponse). `signing_secret` is present only
|
|
23
|
+
# when the API includes it in the response body.
|
|
24
24
|
class Webhook < Base
|
|
25
25
|
field :id, :string
|
|
26
26
|
field :url, :string
|
|
@@ -28,6 +28,7 @@ module Blueticks
|
|
|
28
28
|
field :description, :string, nullable: true
|
|
29
29
|
field :status, [:enum, WEBHOOK_STATUSES]
|
|
30
30
|
field :created_at, :string, wire_name: "createdAt"
|
|
31
|
+
field :signing_secret, :string, optional: true, wire_name: "signingSecret"
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
# A delivered webhook event, as parsed by Blueticks::Webhooks.verify. Note
|
data/lib/blueticks/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: blueticks
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Blueticks
|
|
@@ -68,14 +68,18 @@ files:
|
|
|
68
68
|
- lib/blueticks/errors.rb
|
|
69
69
|
- lib/blueticks/resources/account.rb
|
|
70
70
|
- lib/blueticks/resources/audiences.rb
|
|
71
|
+
- lib/blueticks/resources/boards.rb
|
|
71
72
|
- lib/blueticks/resources/campaigns.rb
|
|
72
73
|
- lib/blueticks/resources/chats.rb
|
|
73
74
|
- lib/blueticks/resources/contacts.rb
|
|
74
75
|
- lib/blueticks/resources/engines.rb
|
|
75
76
|
- lib/blueticks/resources/groups.rb
|
|
77
|
+
- lib/blueticks/resources/identity.rb
|
|
78
|
+
- lib/blueticks/resources/latest_chats.rb
|
|
76
79
|
- lib/blueticks/resources/messages.rb
|
|
77
80
|
- lib/blueticks/resources/newsletters.rb
|
|
78
81
|
- lib/blueticks/resources/ping.rb
|
|
82
|
+
- lib/blueticks/resources/realtime.rb
|
|
79
83
|
- lib/blueticks/resources/scheduled_messages.rb
|
|
80
84
|
- lib/blueticks/resources/suno.rb
|
|
81
85
|
- lib/blueticks/resources/utils.rb
|
|
@@ -84,18 +88,23 @@ files:
|
|
|
84
88
|
- lib/blueticks/types/account.rb
|
|
85
89
|
- lib/blueticks/types/audiences.rb
|
|
86
90
|
- lib/blueticks/types/base.rb
|
|
91
|
+
- lib/blueticks/types/boards.rb
|
|
87
92
|
- lib/blueticks/types/campaigns.rb
|
|
88
93
|
- lib/blueticks/types/chats.rb
|
|
89
94
|
- lib/blueticks/types/contacts.rb
|
|
95
|
+
- lib/blueticks/types/coverage.rb
|
|
90
96
|
- lib/blueticks/types/deleted_resource.rb
|
|
91
97
|
- lib/blueticks/types/engines.rb
|
|
92
98
|
- lib/blueticks/types/groups.rb
|
|
99
|
+
- lib/blueticks/types/identity.rb
|
|
100
|
+
- lib/blueticks/types/latest_chats.rb
|
|
93
101
|
- lib/blueticks/types/messages.rb
|
|
94
102
|
- lib/blueticks/types/newsletter.rb
|
|
95
103
|
- lib/blueticks/types/ok_result.rb
|
|
96
104
|
- lib/blueticks/types/page.rb
|
|
97
105
|
- lib/blueticks/types/paginated.rb
|
|
98
106
|
- lib/blueticks/types/ping.rb
|
|
107
|
+
- lib/blueticks/types/realtime.rb
|
|
99
108
|
- lib/blueticks/types/scheduled_messages.rb
|
|
100
109
|
- lib/blueticks/types/suno.rb
|
|
101
110
|
- lib/blueticks/types/utils.rb
|