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
|
@@ -1,52 +1,101 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "../base_resource"
|
|
4
|
-
require_relative "../types/deleted_resource"
|
|
5
4
|
require_relative "../types/scheduled_messages"
|
|
6
|
-
require_relative "../types/
|
|
5
|
+
require_relative "../types/deleted_resource"
|
|
6
|
+
require_relative "../types/paginated"
|
|
7
7
|
|
|
8
8
|
module Blueticks
|
|
9
9
|
module Resources
|
|
10
10
|
class ScheduledMessagesResource < BaseResource
|
|
11
|
-
#
|
|
11
|
+
# Send / schedule a message to a chat.
|
|
12
12
|
#
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
# Queue a message for delivery to `chat_id` (a WhatsApp JID or phone). The
|
|
14
|
+
# body is a discriminated union keyed on `type` (`text`, `media`, `poll`).
|
|
15
|
+
# Omit `send_at` to dispatch as soon as possible, or pass an ISO-8601
|
|
16
|
+
# timestamp to schedule it.
|
|
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
|
+
#
|
|
21
|
+
# - `type: "text"` — requires `text`.
|
|
22
|
+
# - `type: "media"` — requires `media_url` or `media_base64`; optional
|
|
23
|
+
# `media_kind`, `media_filename`.
|
|
24
|
+
# - `type: "poll"` — requires `poll_question` and `poll_options`; optional
|
|
25
|
+
# `poll_allow_multiple`.
|
|
26
|
+
def create(chat_id, type:, text: nil, media_url: nil, media_base64: nil,
|
|
27
|
+
media_kind: nil, media_filename: nil, poll_question: nil,
|
|
28
|
+
poll_options: nil, poll_allow_multiple: nil, reply_to: nil,
|
|
29
|
+
secret: nil, send_at: nil, idempotency_key: nil,
|
|
30
|
+
mentions: nil, recipient_name: nil)
|
|
31
|
+
body = { "type" => type }
|
|
32
|
+
body["text"] = text unless text.nil?
|
|
33
|
+
body["mediaUrl"] = media_url unless media_url.nil?
|
|
34
|
+
body["mediaBase64"] = media_base64 unless media_base64.nil?
|
|
35
|
+
body["mediaKind"] = media_kind unless media_kind.nil?
|
|
36
|
+
body["mediaFilename"] = media_filename unless media_filename.nil?
|
|
37
|
+
body["pollQuestion"] = poll_question unless poll_question.nil?
|
|
38
|
+
body["pollOptions"] = poll_options unless poll_options.nil?
|
|
39
|
+
body["pollAllowMultiple"] = poll_allow_multiple unless poll_allow_multiple.nil?
|
|
40
|
+
body["replyTo"] = reply_to unless reply_to.nil?
|
|
41
|
+
body["secret"] = secret unless secret.nil?
|
|
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?
|
|
45
|
+
env = client.request("POST", "/v1/scheduled-messages/#{chat_id}", body: body,
|
|
46
|
+
idempotency_key: idempotency_key)
|
|
47
|
+
Types::ScheduledMessage.from_hash(env && env["data"])
|
|
20
48
|
end
|
|
21
49
|
|
|
22
|
-
# Get scheduled message.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
data = client.request("GET", "/v1/scheduled-messages/#{id}")
|
|
27
|
-
Types::ScheduledMessage.from_hash(data)
|
|
50
|
+
# Get the current status of a queued/scheduled message by id.
|
|
51
|
+
def retrieve(message_id)
|
|
52
|
+
env = client.request("GET", "/v1/scheduled-messages/#{message_id}")
|
|
53
|
+
Types::ScheduledMessage.from_hash(env && env["data"])
|
|
28
54
|
end
|
|
29
55
|
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
def
|
|
56
|
+
# List messages in the user-messages queue (all sources), newest first.
|
|
57
|
+
# Offset-paginated. Optionally filter by `chat_id` and/or lifecycle
|
|
58
|
+
# `status`.
|
|
59
|
+
def list(chat_id: nil, search_token: nil, status: nil, order: nil, skip: nil, limit: nil)
|
|
60
|
+
params = {}
|
|
61
|
+
params["chatId"] = chat_id unless chat_id.nil?
|
|
62
|
+
params["searchToken"] = search_token unless search_token.nil?
|
|
63
|
+
params["status"] = status unless status.nil?
|
|
64
|
+
params["order"] = order unless order.nil?
|
|
65
|
+
params["skip"] = skip unless skip.nil?
|
|
66
|
+
params["limit"] = limit unless limit.nil?
|
|
67
|
+
env = client.request("GET", "/v1/scheduled-messages", params: params.empty? ? nil : params)
|
|
68
|
+
Types::PaginatedPage.from_hash(env, item_type: Types::ScheduledMessage)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Edit a previously-queued message that has not dispatched yet. Pass any
|
|
72
|
+
# subset of the editable fields.
|
|
73
|
+
def update(message_id, type: nil, text: nil, media_url: nil, media_base64: nil,
|
|
74
|
+
media_kind: nil, media_filename: nil, poll_question: nil,
|
|
75
|
+
poll_options: nil, poll_allow_multiple: nil, reply_to: nil,
|
|
76
|
+
secret: nil, send_at: nil, mentions: nil)
|
|
34
77
|
body = {}
|
|
78
|
+
body["type"] = type unless type.nil?
|
|
35
79
|
body["text"] = text unless text.nil?
|
|
36
|
-
body["
|
|
37
|
-
body["
|
|
38
|
-
body["
|
|
39
|
-
|
|
40
|
-
|
|
80
|
+
body["mediaUrl"] = media_url unless media_url.nil?
|
|
81
|
+
body["mediaBase64"] = media_base64 unless media_base64.nil?
|
|
82
|
+
body["mediaKind"] = media_kind unless media_kind.nil?
|
|
83
|
+
body["mediaFilename"] = media_filename unless media_filename.nil?
|
|
84
|
+
body["pollQuestion"] = poll_question unless poll_question.nil?
|
|
85
|
+
body["pollOptions"] = poll_options unless poll_options.nil?
|
|
86
|
+
body["pollAllowMultiple"] = poll_allow_multiple unless poll_allow_multiple.nil?
|
|
87
|
+
body["replyTo"] = reply_to unless reply_to.nil?
|
|
88
|
+
body["secret"] = secret unless secret.nil?
|
|
89
|
+
body["sendAt"] = send_at unless send_at.nil?
|
|
90
|
+
body["mentions"] = mentions unless mentions.nil?
|
|
91
|
+
env = client.request("PATCH", "/v1/scheduled-messages/#{message_id}", body: body)
|
|
92
|
+
Types::ScheduledMessage.from_hash(env && env["data"])
|
|
41
93
|
end
|
|
42
94
|
|
|
43
|
-
#
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def delete(id)
|
|
48
|
-
data = client.request("DELETE", "/v1/scheduled-messages/#{id}")
|
|
49
|
-
Types::DeletedResource.from_hash(data)
|
|
95
|
+
# Delete (cancel) a queued/scheduled message by id.
|
|
96
|
+
def delete(message_id)
|
|
97
|
+
env = client.request("DELETE", "/v1/scheduled-messages/#{message_id}")
|
|
98
|
+
Types::DeletedResource.from_hash(env && env["data"])
|
|
50
99
|
end
|
|
51
100
|
end
|
|
52
101
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base_resource"
|
|
4
|
+
require_relative "../types/suno"
|
|
5
|
+
|
|
6
|
+
module Blueticks
|
|
7
|
+
module Resources
|
|
8
|
+
class SunoResource < BaseResource
|
|
9
|
+
# Get the Suno credit / plan usage for the workspace.
|
|
10
|
+
def account
|
|
11
|
+
env = client.request("GET", "/v1/suno/account")
|
|
12
|
+
Types::SunoAccount.from_hash(env && env["data"])
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Submit a song generation job. Requires `style`; `lyrics` is required unless `instrumental` is true. The many
|
|
16
|
+
# optional knobs mirror the Suno request (vocal_gender, weirdness,
|
|
17
|
+
# style_influence, audio_influence, instrumental, model, title, upload_id,
|
|
18
|
+
# captcha_token, negative_style).
|
|
19
|
+
def create_song(style:, lyrics: nil, negative_style: nil, vocal_gender: nil,
|
|
20
|
+
weirdness: nil, style_influence: nil, audio_influence: nil,
|
|
21
|
+
instrumental: nil, model: nil, title: nil, upload_id: nil,
|
|
22
|
+
captcha_token: nil)
|
|
23
|
+
body = { "style" => style }
|
|
24
|
+
body["lyrics"] = lyrics unless lyrics.nil?
|
|
25
|
+
body["negativeStyle"] = negative_style unless negative_style.nil?
|
|
26
|
+
body["vocalGender"] = vocal_gender unless vocal_gender.nil?
|
|
27
|
+
body["weirdness"] = weirdness unless weirdness.nil?
|
|
28
|
+
body["styleInfluence"] = style_influence unless style_influence.nil?
|
|
29
|
+
body["audioInfluence"] = audio_influence unless audio_influence.nil?
|
|
30
|
+
body["instrumental"] = instrumental unless instrumental.nil?
|
|
31
|
+
body["model"] = model unless model.nil?
|
|
32
|
+
body["title"] = title unless title.nil?
|
|
33
|
+
body["uploadId"] = upload_id unless upload_id.nil?
|
|
34
|
+
body["captchaToken"] = captcha_token unless captcha_token.nil?
|
|
35
|
+
env = client.request("POST", "/v1/suno/songs", body: body)
|
|
36
|
+
Types::GenerateSongResult.from_hash(env && env["data"])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Get a generated song (clip) by id.
|
|
40
|
+
def get_song(song_id)
|
|
41
|
+
env = client.request("GET", "/v1/suno/songs/#{song_id}")
|
|
42
|
+
Types::SongClip.from_hash(env && env["data"])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Register a reference-audio upload (by URL or base64) for use as an
|
|
46
|
+
# influence on a subsequent song generation.
|
|
47
|
+
def create_upload(audio_url: nil, audio_base64: nil, file_name: nil)
|
|
48
|
+
body = {}
|
|
49
|
+
body["audioUrl"] = audio_url unless audio_url.nil?
|
|
50
|
+
body["audioBase64"] = audio_base64 unless audio_base64.nil?
|
|
51
|
+
body["fileName"] = file_name unless file_name.nil?
|
|
52
|
+
env = client.request("POST", "/v1/suno/uploads", body: body)
|
|
53
|
+
Types::CreateUploadResult.from_hash(env && env["data"])
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "../base_resource"
|
|
4
|
-
require_relative "../types/utils"
|
|
5
4
|
|
|
6
5
|
module Blueticks
|
|
7
6
|
module Resources
|
|
7
|
+
# UtilsResource had methods for /v1/utils/* which are not in the current spec.
|
|
8
|
+
# The accessor is kept for backward compatibility with test_client.rb.
|
|
9
|
+
# No public methods are exposed.
|
|
8
10
|
class UtilsResource < BaseResource
|
|
9
|
-
# Validate a phone number or chat-id; returns the engine's canonical form.
|
|
10
|
-
def validate_phone(phone_or_chat_id:)
|
|
11
|
-
data = client.request("POST", "/v1/utils/validate_phone",
|
|
12
|
-
body: { "phone_or_chat_id" => phone_or_chat_id })
|
|
13
|
-
Types::PhoneValidation.from_hash(data)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Fetch OpenGraph-style metadata for a URL (uses the engine's renderer).
|
|
17
|
-
def link_preview(url:)
|
|
18
|
-
data = client.request("GET", "/v1/utils/link_preview", params: { "url" => url })
|
|
19
|
-
Types::LinkPreview.from_hash(data)
|
|
20
|
-
end
|
|
21
11
|
end
|
|
22
12
|
end
|
|
23
13
|
end
|
|
@@ -3,50 +3,50 @@
|
|
|
3
3
|
require_relative "../base_resource"
|
|
4
4
|
require_relative "../types/deleted_resource"
|
|
5
5
|
require_relative "../types/webhooks"
|
|
6
|
-
require_relative "../types/
|
|
6
|
+
require_relative "../types/paginated"
|
|
7
7
|
|
|
8
8
|
module Blueticks
|
|
9
9
|
module Resources
|
|
10
10
|
class WebhooksResource < BaseResource
|
|
11
|
+
# Create a webhook subscription.
|
|
11
12
|
def create(url:, events:, description: nil)
|
|
12
13
|
body = { "url" => url, "events" => events }
|
|
13
14
|
body["description"] = description unless description.nil?
|
|
14
|
-
|
|
15
|
-
Types::
|
|
15
|
+
env = client.request("POST", "/v1/webhooks", body: body)
|
|
16
|
+
Types::Webhook.from_hash(env && env["data"])
|
|
16
17
|
end
|
|
17
18
|
|
|
18
|
-
# List webhooks, newest first.
|
|
19
|
-
def list(
|
|
19
|
+
# List webhooks, newest first. Offset-paginated.
|
|
20
|
+
def list(order: nil, skip: nil, limit: nil)
|
|
20
21
|
params = {}
|
|
22
|
+
params["order"] = order unless order.nil?
|
|
23
|
+
params["skip"] = skip unless skip.nil?
|
|
21
24
|
params["limit"] = limit unless limit.nil?
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Types::Page.from_hash(data, item_type: Types::Webhook)
|
|
25
|
+
env = client.request("GET", "/v1/webhooks", params: params.empty? ? nil : params)
|
|
26
|
+
Types::PaginatedPage.from_hash(env, item_type: Types::Webhook)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
# Retrieve a webhook by id.
|
|
30
|
+
def retrieve(webhook_id)
|
|
31
|
+
env = client.request("GET", "/v1/webhooks/#{webhook_id}")
|
|
32
|
+
Types::Webhook.from_hash(env && env["data"])
|
|
30
33
|
end
|
|
31
34
|
|
|
35
|
+
# Update a webhook's url, events, description and/or status.
|
|
32
36
|
def update(webhook_id, url: nil, events: nil, description: nil, status: nil)
|
|
33
37
|
body = {}
|
|
34
38
|
body["url"] = url unless url.nil?
|
|
35
39
|
body["events"] = events unless events.nil?
|
|
36
40
|
body["description"] = description unless description.nil?
|
|
37
41
|
body["status"] = status unless status.nil?
|
|
38
|
-
|
|
39
|
-
Types::Webhook.from_hash(data)
|
|
42
|
+
env = client.request("PATCH", "/v1/webhooks/#{webhook_id}", body: body)
|
|
43
|
+
Types::Webhook.from_hash(env && env["data"])
|
|
40
44
|
end
|
|
41
45
|
|
|
46
|
+
# Delete a webhook.
|
|
42
47
|
def delete(webhook_id)
|
|
43
|
-
|
|
44
|
-
Types::DeletedResource.from_hash(data)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def rotate_secret(webhook_id)
|
|
48
|
-
data = client.request("POST", "/v1/webhooks/#{webhook_id}/rotate-secret")
|
|
49
|
-
Types::WebhookCreateResult.from_hash(data)
|
|
48
|
+
env = client.request("DELETE", "/v1/webhooks/#{webhook_id}")
|
|
49
|
+
Types::DeletedResource.from_hash(env && env["data"])
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
end
|
|
@@ -8,8 +8,9 @@ module Blueticks
|
|
|
8
8
|
class Account < Base
|
|
9
9
|
field :id, :string
|
|
10
10
|
field :name, :string
|
|
11
|
+
field :user_email, :string, nullable: true, wire_name: "userEmail"
|
|
11
12
|
field :timezone, :string, nullable: true
|
|
12
|
-
field :created_at, :string
|
|
13
|
+
field :created_at, :string, wire_name: "createdAt"
|
|
13
14
|
end
|
|
14
15
|
end
|
|
15
16
|
end
|
|
@@ -4,26 +4,32 @@ require_relative "base"
|
|
|
4
4
|
|
|
5
5
|
module Blueticks
|
|
6
6
|
module Types
|
|
7
|
-
|
|
7
|
+
# A contact stored inside an audience (ContactResponse). `variables` is a
|
|
8
|
+
# free-form hash of merge-field values.
|
|
9
|
+
class AudienceContact < Base
|
|
8
10
|
field :id, :string
|
|
9
11
|
field :to, :string
|
|
10
|
-
field :variables,
|
|
11
|
-
field :added_at, :string
|
|
12
|
+
field :variables, :hash
|
|
13
|
+
field :added_at, :string, wire_name: "addedAt"
|
|
12
14
|
end
|
|
13
15
|
|
|
16
|
+
# An audience (AudienceResponse).
|
|
14
17
|
class Audience < Base
|
|
15
18
|
field :id, :string
|
|
16
19
|
field :name, :string
|
|
17
|
-
field :contact_count, :integer
|
|
18
|
-
field :created_at, :string
|
|
19
|
-
field :contacts, [:array, Contact], optional: true
|
|
20
|
-
field :page, :integer, optional: true
|
|
21
|
-
field :has_more, :boolean, optional: true
|
|
20
|
+
field :contact_count, :integer, wire_name: "contactCount"
|
|
21
|
+
field :created_at, :string, wire_name: "createdAt"
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
# Result of appending contacts to an audience (POST .../contacts).
|
|
24
25
|
class AppendContactsResult < Base
|
|
25
26
|
field :added, :integer
|
|
26
|
-
field :contact_count, :integer
|
|
27
|
+
field :contact_count, :integer, wire_name: "contactCount"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Result of removing a contact from an audience (DELETE .../contacts/{id}).
|
|
31
|
+
class ContactRemoval < Base
|
|
32
|
+
field :id, :string
|
|
27
33
|
end
|
|
28
34
|
end
|
|
29
35
|
end
|
|
@@ -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
|
|
@@ -8,21 +8,22 @@ module Blueticks
|
|
|
8
8
|
pending running paused complete_sent complete_delivered aborted
|
|
9
9
|
].freeze
|
|
10
10
|
|
|
11
|
+
# A campaign (CampaignResponse). Note the id is carried on `cmp_id`
|
|
12
|
+
# (wire `cmpId`), matching the backend document shape.
|
|
11
13
|
class Campaign < Base
|
|
12
|
-
field :
|
|
14
|
+
field :cmp_id, :string, wire_name: "cmpId"
|
|
13
15
|
field :name, :string
|
|
14
|
-
field :audience_id, :string
|
|
16
|
+
field :audience_id, :string, wire_name: "audienceId"
|
|
15
17
|
field :status, [:enum, CAMPAIGN_STATUSES]
|
|
16
|
-
field :total_count, :integer
|
|
17
|
-
field :sent_count, :integer
|
|
18
|
-
field :delivered_count, :integer
|
|
19
|
-
field :read_count, :integer
|
|
20
|
-
field :failed_count, :integer
|
|
21
|
-
field :
|
|
22
|
-
field :
|
|
23
|
-
field :
|
|
24
|
-
field :
|
|
25
|
-
field :aborted_at, :string, nullable: true
|
|
18
|
+
field :total_count, :integer, wire_name: "totalCount"
|
|
19
|
+
field :sent_count, :integer, wire_name: "sentCount"
|
|
20
|
+
field :delivered_count, :integer, wire_name: "deliveredCount"
|
|
21
|
+
field :read_count, :integer, wire_name: "readCount"
|
|
22
|
+
field :failed_count, :integer, wire_name: "failedCount"
|
|
23
|
+
field :created_at, :string, wire_name: "createdAt"
|
|
24
|
+
field :started_at, :string, nullable: true, wire_name: "startedAt"
|
|
25
|
+
field :completed_at, :string, nullable: true, wire_name: "completedAt"
|
|
26
|
+
field :aborted_at, :string, nullable: true, wire_name: "abortedAt"
|
|
26
27
|
end
|
|
27
28
|
end
|
|
28
29
|
end
|
|
@@ -4,88 +4,29 @@ require_relative "base"
|
|
|
4
4
|
|
|
5
5
|
module Blueticks
|
|
6
6
|
module Types
|
|
7
|
-
|
|
8
|
-
chat image video document audio ptt sticker gif ptv
|
|
9
|
-
poll_creation location vcard revoked
|
|
10
|
-
].freeze
|
|
11
|
-
|
|
12
|
-
MEDIA_UNAVAILABLE_REASONS = %w[expired fetching awaiting_sender error no_media].freeze
|
|
7
|
+
CHAT_TYPES = %w[contact group newsletter].freeze
|
|
13
8
|
|
|
9
|
+
# A chat row (Chat) returned by chats.list / chats.retrieve.
|
|
14
10
|
class Chat < Base
|
|
15
|
-
field :
|
|
16
|
-
field :name, :string, nullable: true
|
|
17
|
-
field :
|
|
18
|
-
field :
|
|
19
|
-
field :
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
field :chat_id, :string, wire_name: "chatId"
|
|
12
|
+
field :name, :string, nullable: true, optional: 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, nullable: true, optional: true, wire_name: "lastMessageAt"
|
|
17
|
+
field :unread_count, :integer, nullable: true, optional: 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
|
+
end
|
|
22
|
+
|
|
23
|
+
# A participant of a group/community chat (Participant) as returned by
|
|
24
|
+
# chats.list_participants.
|
|
22
25
|
class Participant < Base
|
|
23
|
-
field :chat_id, :string
|
|
24
|
-
field :
|
|
25
|
-
field :
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class ChatMessage < Base
|
|
29
|
-
field :key, :string
|
|
30
|
-
field :chat_id, :string
|
|
31
|
-
field :from, :string
|
|
32
|
-
field :timestamp, :string, nullable: true
|
|
33
|
-
field :text, :string, nullable: true
|
|
34
|
-
field :type, :string
|
|
35
|
-
field :from_me, :boolean
|
|
36
|
-
field :ack, :integer, nullable: true
|
|
37
|
-
field :media_url, :string, nullable: true
|
|
38
|
-
field :caption, :string, nullable: true
|
|
39
|
-
field :filename, :string, nullable: true
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
class ChatMedia < Base
|
|
43
|
-
field :url, :string, nullable: true
|
|
44
|
-
field :mimetype, :string, nullable: true
|
|
45
|
-
field :filename, :string, nullable: true
|
|
46
|
-
field :data_base64, :string, nullable: true
|
|
47
|
-
field :original_quality, :boolean, nullable: true
|
|
48
|
-
field :media_unavailable, [:enum, MEDIA_UNAVAILABLE_REASONS], nullable: true
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Generic `{ "ok": true }` response envelope returned by acknowledged side-effects.
|
|
52
|
-
class OkResponse < Base
|
|
53
|
-
field :ok, :boolean
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# `{ "chat_id": "..." }` envelope returned by /v1/chats/{chat_id}/open.
|
|
57
|
-
class ChatRef < Base
|
|
58
|
-
field :chat_id, :string
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# `{ "ack": int|null }` envelope returned by .../messages/{key}/ack.
|
|
62
|
-
class MessageAck < Base
|
|
63
|
-
field :ack, :integer, nullable: true
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Response from POST /v1/chats/{chat_id}/messages/load_older.
|
|
67
|
-
class LoadOlderMessagesResponse < Base
|
|
68
|
-
field :total_messages, :integer, nullable: true
|
|
69
|
-
field :added, :integer, nullable: true
|
|
70
|
-
field :can_load_more, :boolean
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Response from GET /v1/chats/{chat_id}/messages/{key}/media_url.
|
|
74
|
-
class MediaUrlResponse < Base
|
|
75
|
-
field :url, :string, nullable: true
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# Single entry in the BatchMessageAcksResponse `data` array.
|
|
79
|
-
# `{ "key": "<message key>", "ack": <int|null> }`.
|
|
80
|
-
class BatchMessageAckEntry < Base
|
|
81
|
-
field :key, :string
|
|
82
|
-
field :ack, :integer, nullable: true
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Response from POST /v1/chats/message_acks.
|
|
86
|
-
# `{ "data": [BatchMessageAckEntry, ...] }`.
|
|
87
|
-
class BatchMessageAcksResponse < Base
|
|
88
|
-
field :data, [:array, BatchMessageAckEntry]
|
|
26
|
+
field :chat_id, :string, wire_name: "chatId"
|
|
27
|
+
field :name, :string, nullable: true, optional: true
|
|
28
|
+
field :is_admin, :boolean, wire_name: "isAdmin"
|
|
29
|
+
field :is_super_admin, :boolean, optional: true, wire_name: "isSuperAdmin"
|
|
89
30
|
end
|
|
90
31
|
end
|
|
91
32
|
end
|
|
@@ -4,14 +4,13 @@ require_relative "base"
|
|
|
4
4
|
|
|
5
5
|
module Blueticks
|
|
6
6
|
module Types
|
|
7
|
+
# A WhatsApp contact known to the connected engine (contacts.list item).
|
|
8
|
+
# Per the spec, only `chatId` is required; `name` and `isBusiness` are
|
|
9
|
+
# optional and absent from real engine responses.
|
|
7
10
|
class WhatsAppContact < Base
|
|
8
|
-
field :chat_id, :string
|
|
9
|
-
field :name, :string, nullable: true
|
|
10
|
-
field :is_business, :boolean
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
class ProfilePicture < Base
|
|
14
|
-
field :url, :string, nullable: true
|
|
11
|
+
field :chat_id, :string, wire_name: "chatId"
|
|
12
|
+
field :name, :string, optional: true, nullable: true
|
|
13
|
+
field :is_business, :boolean, optional: true, nullable: true, wire_name: "isBusiness"
|
|
15
14
|
end
|
|
16
15
|
end
|
|
17
16
|
end
|
|
@@ -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
|