blueticks 1.1.2 → 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 +52 -0
- data/lib/blueticks/client.rb +47 -5
- data/lib/blueticks/resources/account.rb +2 -2
- data/lib/blueticks/resources/audiences.rb +30 -22
- data/lib/blueticks/resources/boards.rb +124 -0
- data/lib/blueticks/resources/campaigns.rb +28 -23
- data/lib/blueticks/resources/chats.rb +42 -86
- data/lib/blueticks/resources/contacts.rb +18 -11
- data/lib/blueticks/resources/engines.rb +12 -19
- data/lib/blueticks/resources/groups.rb +69 -28
- data/lib/blueticks/resources/identity.rb +27 -0
- data/lib/blueticks/resources/latest_chats.rb +22 -0
- data/lib/blueticks/resources/messages.rb +127 -31
- data/lib/blueticks/resources/newsletters.rb +43 -0
- data/lib/blueticks/resources/ping.rb +6 -3
- data/lib/blueticks/resources/realtime.rb +19 -0
- data/lib/blueticks/resources/scheduled_messages.rb +81 -32
- data/lib/blueticks/resources/suno.rb +57 -0
- data/lib/blueticks/resources/utils.rb +3 -13
- data/lib/blueticks/resources/webhooks.rb +20 -20
- data/lib/blueticks/types/account.rb +2 -1
- data/lib/blueticks/types/audiences.rb +15 -9
- data/lib/blueticks/types/boards.rb +110 -0
- data/lib/blueticks/types/campaigns.rb +13 -12
- data/lib/blueticks/types/chats.rb +20 -79
- data/lib/blueticks/types/contacts.rb +6 -7
- data/lib/blueticks/types/coverage.rb +14 -0
- data/lib/blueticks/types/engines.rb +9 -8
- data/lib/blueticks/types/groups.rb +33 -6
- data/lib/blueticks/types/identity.rb +28 -0
- data/lib/blueticks/types/latest_chats.rb +32 -0
- data/lib/blueticks/types/messages.rb +132 -11
- data/lib/blueticks/types/newsletter.rb +33 -0
- data/lib/blueticks/types/ok_result.rb +13 -0
- data/lib/blueticks/types/paginated.rb +75 -0
- data/lib/blueticks/types/ping.rb +11 -3
- data/lib/blueticks/types/realtime.rb +23 -0
- data/lib/blueticks/types/scheduled_messages.rb +28 -14
- data/lib/blueticks/types/suno.rb +42 -0
- data/lib/blueticks/types/utils.rb +5 -12
- data/lib/blueticks/types/webhooks.rb +14 -11
- data/lib/blueticks/version.rb +1 -1
- data/lib/blueticks.rb +2 -2
- metadata +16 -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,58 @@ 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
|
+
|
|
18
|
+
## 1.2.0 — 2026-05-22
|
|
19
|
+
|
|
20
|
+
OpenAPI parity pass. The SDK now matches `backend/openapi.json`
|
|
21
|
+
operation-for-operation; an engineless drift check
|
|
22
|
+
(`.github/workflows/sdk-spec-drift.yml`) gates future regressions. The
|
|
23
|
+
`/v1/*` surface is pre-release — none of these changes affect production
|
|
24
|
+
callers yet.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- `messages.send` now takes the discriminated body shape matching the
|
|
29
|
+
backend's strict `anyOf` (BE#50):
|
|
30
|
+
```ruby
|
|
31
|
+
client.messages.send(to: '+1...', type: 'text', text: 'hi')
|
|
32
|
+
client.messages.send(to: '+1...', type: 'media', media: { url: '...', kind: 'image' })
|
|
33
|
+
client.messages.send(to: '+1...', type: 'poll', poll: { question: '...', options: [...] })
|
|
34
|
+
```
|
|
35
|
+
- Single-item GETs now use `.retrieve(id)` instead of `.get(id)` where the
|
|
36
|
+
spec uses GET-by-id. Also `engines.status` → `engines.retrieve`.
|
|
37
|
+
- `newsletters.create` returns the typed `Blueticks::Types::Newsletter` (8
|
|
38
|
+
fields) instead of a raw Hash.
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- `newsletters.list(limit:, cursor:)` — `GET /v1/newsletters` (cursor-paginated → `Page<Newsletter>`)
|
|
43
|
+
- `newsletters.retrieve(id)` — `GET /v1/newsletters/{id}`
|
|
44
|
+
- `ping.retrieve` — typed `Ping` (`account_id`, `key_prefix`, `scopes`). The
|
|
45
|
+
`ping` resource had been deleted in a prior interim regen; restored here.
|
|
46
|
+
- `Message` now exposes `key`, `type`, `media_kind`, `poll_question`, `link_preview`
|
|
47
|
+
|
|
48
|
+
### Removed
|
|
49
|
+
|
|
50
|
+
- `engines.me`, `engines.logout`, `engines.reload`
|
|
51
|
+
- `contacts.get_profile_picture`
|
|
52
|
+
- `utils.validate_phone`, `utils.link_preview` (the `utils` resource was emptied)
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- `groups.list` was documented at `dev.blueticks.co` but absent from the
|
|
57
|
+
SDK for ~9 days — now present.
|
|
58
|
+
|
|
7
59
|
## 1.0.0 — 2026-04-30
|
|
8
60
|
|
|
9
61
|
Initial release.
|
data/lib/blueticks/client.rb
CHANGED
|
@@ -2,13 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "errors"
|
|
4
4
|
require_relative "transport"
|
|
5
|
+
require_relative "resources/account"
|
|
6
|
+
require_relative "resources/audiences"
|
|
7
|
+
require_relative "resources/boards"
|
|
8
|
+
require_relative "resources/campaigns"
|
|
9
|
+
require_relative "resources/chats"
|
|
10
|
+
require_relative "resources/contacts"
|
|
11
|
+
require_relative "resources/engines"
|
|
12
|
+
require_relative "resources/groups"
|
|
13
|
+
require_relative "resources/identity"
|
|
14
|
+
require_relative "resources/latest_chats"
|
|
15
|
+
require_relative "resources/messages"
|
|
16
|
+
require_relative "resources/newsletters"
|
|
17
|
+
require_relative "resources/ping"
|
|
18
|
+
require_relative "resources/realtime"
|
|
5
19
|
require_relative "resources/scheduled_messages"
|
|
20
|
+
require_relative "resources/suno"
|
|
21
|
+
require_relative "resources/utils"
|
|
22
|
+
require_relative "resources/webhooks"
|
|
6
23
|
|
|
7
24
|
module Blueticks
|
|
8
25
|
# Top-level entry point. Construct one and access resources via accessor methods:
|
|
9
26
|
#
|
|
10
27
|
# client = Blueticks::Client.new(api_key: "bt_live_...")
|
|
11
|
-
# client.
|
|
28
|
+
# client.scheduled_messages.create(type: "text", to: "12025550100", text: "Hello!")
|
|
12
29
|
#
|
|
13
30
|
# Configuration order of precedence:
|
|
14
31
|
# 1. Explicit keyword args.
|
|
@@ -47,10 +64,6 @@ module Blueticks
|
|
|
47
64
|
@ping ||= Resources::PingResource.new(self)
|
|
48
65
|
end
|
|
49
66
|
|
|
50
|
-
def messages
|
|
51
|
-
@messages ||= Resources::MessagesResource.new(self)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
67
|
def scheduled_messages
|
|
55
68
|
@scheduled_messages ||= Resources::ScheduledMessagesResource.new(self)
|
|
56
69
|
end
|
|
@@ -83,6 +96,35 @@ module Blueticks
|
|
|
83
96
|
@contacts ||= Resources::ContactsResource.new(self)
|
|
84
97
|
end
|
|
85
98
|
|
|
99
|
+
def newsletters
|
|
100
|
+
@newsletters ||= Resources::NewslettersResource.new(self)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def messages
|
|
104
|
+
@messages ||= Resources::MessagesResource.new(self)
|
|
105
|
+
end
|
|
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
|
+
|
|
123
|
+
def suno
|
|
124
|
+
@suno ||= Resources::SunoResource.new(self)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Kept for backward compatibility. No spec-backed operations exposed.
|
|
86
128
|
def utils
|
|
87
129
|
@utils ||= Resources::UtilsResource.new(self)
|
|
88
130
|
end
|
|
@@ -10,8 +10,8 @@ module Blueticks
|
|
|
10
10
|
#
|
|
11
11
|
# Returns the account associated with the API key used for this request.
|
|
12
12
|
def retrieve
|
|
13
|
-
|
|
14
|
-
Types::Account.from_hash(data)
|
|
13
|
+
env = client.request("GET", "/v1/account")
|
|
14
|
+
Types::Account.from_hash(env && env["data"])
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -3,67 +3,75 @@
|
|
|
3
3
|
require_relative "../base_resource"
|
|
4
4
|
require_relative "../types/audiences"
|
|
5
5
|
require_relative "../types/deleted_resource"
|
|
6
|
-
require_relative "../types/
|
|
6
|
+
require_relative "../types/paginated"
|
|
7
7
|
|
|
8
8
|
module Blueticks
|
|
9
9
|
module Resources
|
|
10
10
|
class AudiencesResource < BaseResource
|
|
11
|
+
# Create an audience, optionally seeding it with contacts.
|
|
12
|
+
# `contacts` is an Array of `{ "to" => ..., "variables" => {...} }` hashes.
|
|
11
13
|
def create(name:, contacts: nil)
|
|
12
14
|
body = { "name" => name }
|
|
13
15
|
body["contacts"] = contacts unless contacts.nil?
|
|
14
|
-
|
|
15
|
-
Types::Audience.from_hash(data)
|
|
16
|
+
env = client.request("POST", "/v1/audiences", body: body)
|
|
17
|
+
Types::Audience.from_hash(env && env["data"])
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
# List audiences, newest first.
|
|
19
|
-
def list(
|
|
20
|
+
# List audiences, newest first. Offset-paginated.
|
|
21
|
+
def list(order: nil, skip: nil, limit: nil)
|
|
20
22
|
params = {}
|
|
23
|
+
params["order"] = order unless order.nil?
|
|
24
|
+
params["skip"] = skip unless skip.nil?
|
|
21
25
|
params["limit"] = limit unless limit.nil?
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Types::Page.from_hash(data, item_type: Types::Audience)
|
|
26
|
+
env = client.request("GET", "/v1/audiences", params: params.empty? ? nil : params)
|
|
27
|
+
Types::PaginatedPage.from_hash(env, item_type: Types::Audience)
|
|
25
28
|
end
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Types::Audience.from_hash(data)
|
|
30
|
+
# Retrieve an audience by id.
|
|
31
|
+
def retrieve(audience_id)
|
|
32
|
+
env = client.request("GET", "/v1/audiences/#{audience_id}")
|
|
33
|
+
Types::Audience.from_hash(env && env["data"])
|
|
31
34
|
end
|
|
32
35
|
|
|
36
|
+
# Rename an audience.
|
|
33
37
|
def update(audience_id, name:)
|
|
34
|
-
|
|
35
|
-
Types::Audience.from_hash(data)
|
|
38
|
+
env = client.request("PATCH", "/v1/audiences/#{audience_id}", body: { "name" => name })
|
|
39
|
+
Types::Audience.from_hash(env && env["data"])
|
|
36
40
|
end
|
|
37
41
|
|
|
42
|
+
# Delete an audience.
|
|
38
43
|
def delete(audience_id)
|
|
39
|
-
|
|
40
|
-
Types::DeletedResource.from_hash(data)
|
|
44
|
+
env = client.request("DELETE", "/v1/audiences/#{audience_id}")
|
|
45
|
+
Types::DeletedResource.from_hash(env && env["data"])
|
|
41
46
|
end
|
|
42
47
|
|
|
48
|
+
# Append contacts to an audience.
|
|
43
49
|
def append_contacts(audience_id, contacts:)
|
|
44
|
-
|
|
50
|
+
env = client.request(
|
|
45
51
|
"POST",
|
|
46
52
|
"/v1/audiences/#{audience_id}/contacts",
|
|
47
53
|
body: { "contacts" => contacts }
|
|
48
54
|
)
|
|
49
|
-
Types::AppendContactsResult.from_hash(data)
|
|
55
|
+
Types::AppendContactsResult.from_hash(env && env["data"])
|
|
50
56
|
end
|
|
51
57
|
|
|
58
|
+
# Update a single contact's recipient and/or merge-field variables.
|
|
52
59
|
def update_contact(audience_id, contact_id, to: nil, variables: nil)
|
|
53
60
|
body = {}
|
|
54
61
|
body["to"] = to unless to.nil?
|
|
55
62
|
body["variables"] = variables unless variables.nil?
|
|
56
|
-
|
|
63
|
+
env = client.request(
|
|
57
64
|
"PATCH",
|
|
58
65
|
"/v1/audiences/#{audience_id}/contacts/#{contact_id}",
|
|
59
66
|
body: body
|
|
60
67
|
)
|
|
61
|
-
Types::
|
|
68
|
+
Types::AudienceContact.from_hash(env && env["data"])
|
|
62
69
|
end
|
|
63
70
|
|
|
71
|
+
# Remove a contact from an audience.
|
|
64
72
|
def delete_contact(audience_id, contact_id)
|
|
65
|
-
client.request("DELETE", "/v1/audiences/#{audience_id}/contacts/#{contact_id}")
|
|
66
|
-
|
|
73
|
+
env = client.request("DELETE", "/v1/audiences/#{audience_id}/contacts/#{contact_id}")
|
|
74
|
+
Types::ContactRemoval.from_hash(env && env["data"])
|
|
67
75
|
end
|
|
68
76
|
end
|
|
69
77
|
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
|
|
@@ -2,50 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "../base_resource"
|
|
4
4
|
require_relative "../types/campaigns"
|
|
5
|
-
require_relative "../types/
|
|
5
|
+
require_relative "../types/paginated"
|
|
6
6
|
|
|
7
7
|
module Blueticks
|
|
8
8
|
module Resources
|
|
9
9
|
class CampaignsResource < BaseResource
|
|
10
|
+
# Create a campaign against an audience.
|
|
10
11
|
def create(name:, audience_id:, text: nil, media_url: nil, media_caption: nil,
|
|
11
|
-
|
|
12
|
-
body = { "name" => name, "
|
|
12
|
+
on_missing_variable: nil)
|
|
13
|
+
body = { "name" => name, "audienceId" => audience_id }
|
|
13
14
|
body["text"] = text unless text.nil?
|
|
14
|
-
body["
|
|
15
|
-
body["
|
|
16
|
-
body["
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Types::Campaign.from_hash(data)
|
|
15
|
+
body["mediaUrl"] = media_url unless media_url.nil?
|
|
16
|
+
body["mediaCaption"] = media_caption unless media_caption.nil?
|
|
17
|
+
body["onMissingVariable"] = on_missing_variable unless on_missing_variable.nil?
|
|
18
|
+
env = client.request("POST", "/v1/campaigns", body: body)
|
|
19
|
+
Types::Campaign.from_hash(env && env["data"])
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
# List campaigns, newest first.
|
|
23
|
-
def list(
|
|
22
|
+
# List campaigns, newest first. Offset-paginated.
|
|
23
|
+
def list(order: nil, skip: nil, limit: nil)
|
|
24
24
|
params = {}
|
|
25
|
+
params["order"] = order unless order.nil?
|
|
26
|
+
params["skip"] = skip unless skip.nil?
|
|
25
27
|
params["limit"] = limit unless limit.nil?
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Types::Page.from_hash(data, item_type: Types::Campaign)
|
|
28
|
+
env = client.request("GET", "/v1/campaigns", params: params.empty? ? nil : params)
|
|
29
|
+
Types::PaginatedPage.from_hash(env, item_type: Types::Campaign)
|
|
29
30
|
end
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
# Retrieve a campaign by id.
|
|
33
|
+
def retrieve(campaign_id)
|
|
34
|
+
env = client.request("GET", "/v1/campaigns/#{campaign_id}")
|
|
35
|
+
Types::Campaign.from_hash(env && env["data"])
|
|
34
36
|
end
|
|
35
37
|
|
|
38
|
+
# Pause a running campaign.
|
|
36
39
|
def pause(campaign_id)
|
|
37
|
-
|
|
38
|
-
Types::Campaign.from_hash(data)
|
|
40
|
+
env = client.request("POST", "/v1/campaigns/#{campaign_id}/pause")
|
|
41
|
+
Types::Campaign.from_hash(env && env["data"])
|
|
39
42
|
end
|
|
40
43
|
|
|
44
|
+
# Resume a paused campaign.
|
|
41
45
|
def resume(campaign_id)
|
|
42
|
-
|
|
43
|
-
Types::Campaign.from_hash(data)
|
|
46
|
+
env = client.request("POST", "/v1/campaigns/#{campaign_id}/resume")
|
|
47
|
+
Types::Campaign.from_hash(env && env["data"])
|
|
44
48
|
end
|
|
45
49
|
|
|
50
|
+
# Cancel a campaign.
|
|
46
51
|
def cancel(campaign_id)
|
|
47
|
-
|
|
48
|
-
Types::Campaign.from_hash(data)
|
|
52
|
+
env = client.request("POST", "/v1/campaigns/#{campaign_id}/cancel")
|
|
53
|
+
Types::Campaign.from_hash(env && env["data"])
|
|
49
54
|
end
|
|
50
55
|
end
|
|
51
56
|
end
|
|
@@ -2,111 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "../base_resource"
|
|
4
4
|
require_relative "../types/chats"
|
|
5
|
-
require_relative "../types/
|
|
5
|
+
require_relative "../types/ok_result"
|
|
6
|
+
require_relative "../types/paginated"
|
|
6
7
|
|
|
7
8
|
module Blueticks
|
|
8
9
|
module Resources
|
|
9
10
|
class ChatsResource < BaseResource
|
|
10
|
-
# List/search chats, newest first.
|
|
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.
|
|
15
|
+
def list(search_token: nil, filter: nil, include_last_message: nil,
|
|
16
|
+
include_extended_info: nil, include_without_name: nil,
|
|
17
|
+
include_archive: nil, skip: nil, limit: nil, kinds: nil, since: nil)
|
|
12
18
|
params = {}
|
|
13
|
-
params["
|
|
19
|
+
params["searchToken"] = search_token unless search_token.nil?
|
|
20
|
+
params["filter"] = filter unless filter.nil?
|
|
21
|
+
params["includeLastMessage"] = include_last_message unless include_last_message.nil?
|
|
22
|
+
params["includeExtendedInfo"] = include_extended_info unless include_extended_info.nil?
|
|
23
|
+
params["includeWithoutName"] = include_without_name unless include_without_name.nil?
|
|
24
|
+
params["includeArchive"] = include_archive unless include_archive.nil?
|
|
25
|
+
params["skip"] = skip unless skip.nil?
|
|
14
26
|
params["limit"] = limit unless limit.nil?
|
|
15
|
-
params["
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
params["kinds"] = kinds unless kinds.nil? || kinds.empty?
|
|
28
|
+
params["since"] = since unless since.nil?
|
|
29
|
+
env = client.request("GET", "/v1/chats", params: params.empty? ? nil : params)
|
|
30
|
+
Types::PaginatedPage.from_hash(env, item_type: Types::Chat)
|
|
18
31
|
end
|
|
19
32
|
|
|
20
33
|
# Retrieve a chat by its JID.
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
Types::Chat.from_hash(data)
|
|
34
|
+
def retrieve(chat_id)
|
|
35
|
+
env = client.request("GET", "/v1/chats/#{chat_id}")
|
|
36
|
+
Types::Chat.from_hash(env && env["data"])
|
|
24
37
|
end
|
|
25
38
|
|
|
26
|
-
# List participants in a group chat.
|
|
27
|
-
def list_participants(chat_id,
|
|
39
|
+
# List participants in a group/community chat. Offset-paginated.
|
|
40
|
+
def list_participants(chat_id, search_token: nil, skip: nil, limit: nil)
|
|
28
41
|
params = {}
|
|
42
|
+
params["searchToken"] = search_token unless search_token.nil?
|
|
43
|
+
params["skip"] = skip unless skip.nil?
|
|
29
44
|
params["limit"] = limit unless limit.nil?
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Types::Page.from_hash(data, item_type: Types::Participant)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Mark a chat as read (sends read receipts if enabled).
|
|
37
|
-
def mark_read(chat_id)
|
|
38
|
-
data = client.request("POST", "/v1/chats/#{chat_id}/mark_read")
|
|
39
|
-
Types::OkResponse.from_hash(data)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Open a chat on the engine (useful for UI-assisted workflows).
|
|
43
|
-
def open(chat_id)
|
|
44
|
-
data = client.request("POST", "/v1/chats/#{chat_id}/open")
|
|
45
|
-
Types::ChatRef.from_hash(data)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# List messages in a chat. `mode` is "latest" or "history".
|
|
49
|
-
def list_messages(chat_id, mode: "latest", query: nil, since: nil, until_: nil,
|
|
50
|
-
message_types: nil, limit: nil, cursor: nil)
|
|
51
|
-
params = { "mode" => mode }
|
|
52
|
-
params["query"] = query unless query.nil?
|
|
53
|
-
params["since"] = since unless since.nil?
|
|
54
|
-
params["until"] = until_ unless until_.nil?
|
|
55
|
-
params["message_types"] = message_types.join(",") if message_types && !message_types.empty?
|
|
56
|
-
params["limit"] = limit unless limit.nil?
|
|
57
|
-
params["cursor"] = cursor unless cursor.nil?
|
|
58
|
-
data = client.request("GET", "/v1/chats/#{chat_id}/messages", params: params)
|
|
59
|
-
Types::Page.from_hash(data, item_type: Types::ChatMessage)
|
|
45
|
+
env = client.request("GET", "/v1/chats/#{chat_id}/participants",
|
|
46
|
+
params: params.empty? ? nil : params)
|
|
47
|
+
Types::PaginatedPage.from_hash(env, item_type: Types::Participant)
|
|
60
48
|
end
|
|
61
49
|
|
|
62
|
-
#
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
-
Types::
|
|
50
|
+
# Archive a chat.
|
|
51
|
+
def archive(chat_id)
|
|
52
|
+
env = client.request("POST", "/v1/chats/#{chat_id}/archive")
|
|
53
|
+
Types::OkResult.from_hash(env && env["data"])
|
|
66
54
|
end
|
|
67
55
|
|
|
68
|
-
#
|
|
69
|
-
def
|
|
70
|
-
|
|
71
|
-
Types::
|
|
56
|
+
# Unarchive a chat.
|
|
57
|
+
def unarchive(chat_id)
|
|
58
|
+
env = client.request("POST", "/v1/chats/#{chat_id}/unarchive")
|
|
59
|
+
Types::OkResult.from_hash(env && env["data"])
|
|
72
60
|
end
|
|
73
61
|
|
|
74
|
-
#
|
|
75
|
-
def
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"/v1/chats/#{chat_id}/messages/#{key}/reactions",
|
|
79
|
-
body: { "emoji" => emoji }
|
|
80
|
-
)
|
|
81
|
-
Types::OkResponse.from_hash(data)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Ask the engine to pull older history from the connected phone.
|
|
85
|
-
def load_older_messages(chat_id)
|
|
86
|
-
data = client.request("POST", "/v1/chats/#{chat_id}/messages/load_older")
|
|
87
|
-
Types::LoadOlderMessagesResponse.from_hash(data)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Get a hosted URL for the message media without inlining bytes.
|
|
91
|
-
def get_media_url(chat_id, key)
|
|
92
|
-
data = client.request("GET", "/v1/chats/#{chat_id}/messages/#{key}/media_url")
|
|
93
|
-
Types::MediaUrlResponse.from_hash(data)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# Fetch full media bytes (base64) for a message.
|
|
97
|
-
def get_media(chat_id, key)
|
|
98
|
-
data = client.request("GET", "/v1/chats/#{chat_id}/messages/#{key}/media")
|
|
99
|
-
Types::ChatMedia.from_hash(data)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Batch get delivery status for up to 200 sent messages.
|
|
103
|
-
def batch_message_acks(message_keys:)
|
|
104
|
-
data = client.request(
|
|
105
|
-
"POST",
|
|
106
|
-
"/v1/chats/message_acks",
|
|
107
|
-
body: { "message_keys" => message_keys }
|
|
108
|
-
)
|
|
109
|
-
Types::BatchMessageAcksResponse.from_hash(data)
|
|
62
|
+
# Mark a chat as read (sends read receipts if enabled).
|
|
63
|
+
def mark_read(chat_id)
|
|
64
|
+
env = client.request("POST", "/v1/chats/#{chat_id}/mark_read")
|
|
65
|
+
Types::OkResult.from_hash(env && env["data"])
|
|
110
66
|
end
|
|
111
67
|
end
|
|
112
68
|
end
|