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
|
@@ -4,17 +4,18 @@ require_relative "base"
|
|
|
4
4
|
|
|
5
5
|
module Blueticks
|
|
6
6
|
module Types
|
|
7
|
-
|
|
7
|
+
ENGINE_TYPES = %w[gateway regular].freeze
|
|
8
|
+
|
|
9
|
+
# A single engine session connected to the workspace (engines.list item).
|
|
10
|
+
# `type` is "gateway" (a remote server-side engine / Blueticks 24/7 gateway
|
|
11
|
+
# or baileys pod) or "regular" (the user's own WhatsApp Web extension).
|
|
12
|
+
class Engine < Base
|
|
13
|
+
field :id, :string
|
|
14
|
+
field :type, [:enum, ENGINE_TYPES]
|
|
8
15
|
field :connected, :boolean
|
|
9
16
|
field :state, :string, nullable: true
|
|
10
17
|
field :stream, :string, nullable: true
|
|
11
|
-
field :has_synced, :boolean, nullable: true
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
class WhatsAppMe < Base
|
|
15
|
-
field :phone, :string, nullable: true
|
|
16
|
-
field :name, :string, nullable: true
|
|
17
|
-
field :platform, :string, nullable: true
|
|
18
|
+
field :has_synced, :boolean, nullable: true, wire_name: "hasSynced"
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
end
|
|
@@ -4,24 +4,51 @@ require_relative "base"
|
|
|
4
4
|
|
|
5
5
|
module Blueticks
|
|
6
6
|
module Types
|
|
7
|
+
# A member of a group (GroupParticipant).
|
|
7
8
|
class GroupParticipant < Base
|
|
8
|
-
field :chat_id, :string
|
|
9
|
-
field :is_admin, :boolean
|
|
10
|
-
field :is_super_admin, :boolean
|
|
9
|
+
field :chat_id, :string, wire_name: "chatId"
|
|
10
|
+
field :is_admin, :boolean, wire_name: "isAdmin"
|
|
11
|
+
field :is_super_admin, :boolean, wire_name: "isSuperAdmin"
|
|
11
12
|
field :name, :string, nullable: true
|
|
12
13
|
end
|
|
13
14
|
|
|
15
|
+
# Full group metadata (Group) returned by group create/get/update and the
|
|
16
|
+
# membership-mutating endpoints.
|
|
14
17
|
class Group < Base
|
|
15
18
|
field :id, :string
|
|
16
19
|
field :name, :string, nullable: true
|
|
17
20
|
field :description, :string, nullable: true
|
|
18
21
|
field :owner, :string, nullable: true
|
|
19
|
-
field :created_at, :string, nullable: true
|
|
20
|
-
field :last_message_at, :string, nullable: true
|
|
21
|
-
field :participant_count, :integer, nullable: true
|
|
22
|
+
field :created_at, :string, nullable: true, wire_name: "createdAt"
|
|
23
|
+
field :last_message_at, :string, nullable: true, wire_name: "lastMessageAt"
|
|
24
|
+
field :participant_count, :integer, nullable: true, wire_name: "participantCount"
|
|
22
25
|
field :announce, :boolean, nullable: true
|
|
23
26
|
field :restrict, :boolean, nullable: true
|
|
24
27
|
field :participants, [:array, GroupParticipant], nullable: true
|
|
25
28
|
end
|
|
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
|
+
|
|
41
|
+
# A group row in the groups.list / contacts.common_groups page
|
|
42
|
+
# (GroupListItem) — a slimmer projection without announce/participants.
|
|
43
|
+
class GroupListItem < Base
|
|
44
|
+
field :id, :string
|
|
45
|
+
field :name, :string, nullable: true
|
|
46
|
+
field :description, :string, nullable: true
|
|
47
|
+
field :owner, :string, nullable: true
|
|
48
|
+
field :created_at, :string, nullable: true, wire_name: "createdAt"
|
|
49
|
+
field :last_message_at, :string, nullable: true, wire_name: "lastMessageAt"
|
|
50
|
+
field :participant_count, :integer, nullable: true, wire_name: "participantCount"
|
|
51
|
+
field :restrict, :boolean, nullable: true
|
|
52
|
+
end
|
|
26
53
|
end
|
|
27
54
|
end
|
|
@@ -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,25 +1,146 @@
|
|
|
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
|
|
9
|
+
MESSAGE_MEDIA_KINDS = %w[image video audio document sticker voice gif].freeze
|
|
10
|
+
MEDIA_UNAVAILABLE_REASONS = %w[expired fetching awaiting_sender error no_media].freeze
|
|
11
|
+
MESSAGE_SOURCES = %w[vault backup].freeze
|
|
12
|
+
MESSAGE_STATUSES = %w[
|
|
13
|
+
pending before-wa-send bt-sent sending sent sent_pending_ack confirmed
|
|
14
|
+
delivered received read played cancelled error failed expired
|
|
15
|
+
].freeze
|
|
8
16
|
|
|
17
|
+
# WhatsApp wire message key (PublicWaMessageKey). `serialized` maps the
|
|
18
|
+
# wire's `_serialized` compact form.
|
|
19
|
+
class WaMessageKey < Base
|
|
20
|
+
field :from_me, :boolean, wire_name: "fromMe"
|
|
21
|
+
field :remote, :string, optional: true
|
|
22
|
+
field :id, :string, optional: true
|
|
23
|
+
field :serialized, :string, optional: true, wire_name: "_serialized"
|
|
24
|
+
field :participant, :string, optional: true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Link preview attached to a queued/scheduled message (MessageResponse).
|
|
28
|
+
# Fields are always present but may be null.
|
|
29
|
+
class LinkPreview < Base
|
|
30
|
+
field :title, :string, nullable: true
|
|
31
|
+
field :description, :string, nullable: true
|
|
32
|
+
field :canonical_url, :string, nullable: true, wire_name: "canonicalUrl"
|
|
33
|
+
field :thumbnail, :string, nullable: true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Link preview attached to a store message (PublicMessage). Fields are all
|
|
37
|
+
# optional here.
|
|
38
|
+
class PublicLinkPreview < Base
|
|
39
|
+
field :title, :string, optional: true
|
|
40
|
+
field :description, :string, optional: true
|
|
41
|
+
field :canonical_url, :string, optional: true, wire_name: "canonicalUrl"
|
|
42
|
+
field :thumbnail, :string, optional: true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# The message a store message replies to (PublicQuotedMessage).
|
|
46
|
+
class QuotedMessage < Base
|
|
47
|
+
field :wa_message_key, WaMessageKey, wire_name: "waMessageKey"
|
|
48
|
+
field :text, :string, optional: true
|
|
49
|
+
field :type, :string, optional: true
|
|
50
|
+
field :author, :string, optional: true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# A message read from the WhatsApp store (PublicMessage) — the shape
|
|
54
|
+
# returned by messages.list and messages.retrieve.
|
|
55
|
+
class PublicMessage < Base
|
|
56
|
+
field :wa_message_key, WaMessageKey, wire_name: "waMessageKey"
|
|
57
|
+
field :chat_id, :string, wire_name: "chatId"
|
|
58
|
+
field :from, :string
|
|
59
|
+
field :author, :string, optional: true
|
|
60
|
+
field :sender_name, :string, optional: true, wire_name: "senderName"
|
|
61
|
+
field :timestamp, :string, optional: true
|
|
62
|
+
field :text, :string, optional: true
|
|
63
|
+
field :type, :string
|
|
64
|
+
field :from_me, :boolean, wire_name: "fromMe"
|
|
65
|
+
field :ack, :integer, optional: true
|
|
66
|
+
field :media_url, :string, optional: true, wire_name: "mediaUrl"
|
|
67
|
+
field :filename, :string, optional: true
|
|
68
|
+
field :link_preview, PublicLinkPreview, optional: true, wire_name: "linkPreview"
|
|
69
|
+
field :quoted_message, QuotedMessage, optional: true, wire_name: "quotedMessage"
|
|
70
|
+
field :source, [:enum, MESSAGE_SOURCES], optional: true
|
|
71
|
+
field :secret, :string, optional: true
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Media payload for a message (Media) returned by messages.get_media.
|
|
75
|
+
class Media < Base
|
|
76
|
+
field :url, :string, optional: true
|
|
77
|
+
field :mimetype, :string, optional: true
|
|
78
|
+
field :filename, :string, optional: true
|
|
79
|
+
field :data_base64, :string, optional: true, wire_name: "dataBase64"
|
|
80
|
+
field :original_quality, :boolean, optional: true, wire_name: "originalQuality"
|
|
81
|
+
field :media_unavailable, [:enum, MEDIA_UNAVAILABLE_REASONS], optional: true, wire_name: "mediaUnavailable"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Delivery acknowledgement (MessageAck). ack: -1=error, 0=pending,
|
|
85
|
+
# 1=server, 2=device, 3=read, 4=played.
|
|
86
|
+
class MessageAck < Base
|
|
87
|
+
field :ack, :integer, nullable: true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# A single entry in the messages.batch_acks page (BatchMessageAckEntry).
|
|
91
|
+
class BatchAckEntry < Base
|
|
92
|
+
field :key, :string
|
|
93
|
+
field :ack, :integer, nullable: true
|
|
94
|
+
field :found, :boolean
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# A pinned message summary (PinnedMessage) in the messages.pinned page.
|
|
98
|
+
class PinnedMessage < Base
|
|
99
|
+
field :key, :string
|
|
100
|
+
field :chat_id, :string, wire_name: "chatId"
|
|
101
|
+
field :text, :string, nullable: true
|
|
102
|
+
end
|
|
103
|
+
|
|
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.
|
|
107
|
+
class LoadOlderResult < Base
|
|
108
|
+
field :total_messages, :integer, nullable: true, wire_name: "totalMessages"
|
|
109
|
+
field :added, :integer, nullable: true
|
|
110
|
+
field :can_load_more, :boolean, wire_name: "canLoadMore"
|
|
111
|
+
field :history_unavailable, :boolean, wire_name: "historyUnavailable"
|
|
112
|
+
field :error, :string, nullable: true
|
|
113
|
+
field :pages_executed, :integer, wire_name: "pagesExecuted"
|
|
114
|
+
field :coverage, Coverage
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# A sent/queued outbound message record — the shape returned by
|
|
118
|
+
# messages.create (direct send). The spec's send response marks only
|
|
119
|
+
# `to`, `type`, `status`, `createdAt` required; `waMessageKey` is optional
|
|
120
|
+
# (absent until the message has a wire key). The scheduled/queued variant is
|
|
121
|
+
# modelled separately by Types::ScheduledMessage.
|
|
9
122
|
class Message < Base
|
|
10
|
-
field :id, :string
|
|
123
|
+
field :id, :string, optional: true
|
|
124
|
+
field :wa_message_key, WaMessageKey, optional: true, nullable: true, wire_name: "waMessageKey"
|
|
11
125
|
field :to, :string
|
|
12
|
-
field :
|
|
126
|
+
field :type, [:enum, MESSAGE_KINDS]
|
|
13
127
|
field :text, :string, nullable: true
|
|
14
|
-
field :media_url, :string, nullable: true
|
|
128
|
+
field :media_url, :string, nullable: true, wire_name: "mediaUrl"
|
|
129
|
+
field :media_kind, [:enum, MESSAGE_MEDIA_KINDS], nullable: true, wire_name: "mediaKind"
|
|
130
|
+
field :poll_question, :string, nullable: true, wire_name: "pollQuestion"
|
|
131
|
+
field :poll_options, %i[array string], nullable: true, wire_name: "pollOptions"
|
|
132
|
+
field :poll_allow_multiple, :boolean, nullable: true, wire_name: "pollAllowMultiple"
|
|
15
133
|
field :status, [:enum, MESSAGE_STATUSES]
|
|
16
|
-
field :send_at, :string, nullable: true
|
|
17
|
-
field :created_at, :string
|
|
18
|
-
field :
|
|
19
|
-
field :
|
|
20
|
-
field :read_at, :string, nullable: true
|
|
21
|
-
field :
|
|
22
|
-
field :
|
|
134
|
+
field :send_at, :string, nullable: true, wire_name: "sendAt"
|
|
135
|
+
field :created_at, :string, wire_name: "createdAt"
|
|
136
|
+
field :confirmed_at, :string, nullable: true, wire_name: "confirmedAt"
|
|
137
|
+
field :received_at, :string, nullable: true, wire_name: "receivedAt"
|
|
138
|
+
field :read_at, :string, nullable: true, wire_name: "readAt"
|
|
139
|
+
field :played_at, :string, nullable: true, wire_name: "playedAt"
|
|
140
|
+
field :failed_at, :string, nullable: true, wire_name: "failedAt"
|
|
141
|
+
field :failure_reason, :string, nullable: true, wire_name: "failureReason"
|
|
142
|
+
field :secret, :string, nullable: true
|
|
143
|
+
field :link_preview, LinkPreview, optional: true, wire_name: "linkPreview"
|
|
23
144
|
end
|
|
24
145
|
end
|
|
25
146
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module Blueticks
|
|
6
|
+
module Types
|
|
7
|
+
NEWSLETTER_VERIFICATIONS = %w[VERIFIED UNVERIFIED].freeze
|
|
8
|
+
|
|
9
|
+
# A WhatsApp newsletter (channel) as returned by create/get
|
|
10
|
+
# (NewsletterResponse). The JID is carried on `newsletter_id`.
|
|
11
|
+
class Newsletter < Base
|
|
12
|
+
field :newsletter_id, :string, wire_name: "newsletterId"
|
|
13
|
+
field :name, :string
|
|
14
|
+
field :description, :string, nullable: true
|
|
15
|
+
field :created_at, :string, nullable: true, wire_name: "createdAt"
|
|
16
|
+
field :subscribers, :integer, nullable: true
|
|
17
|
+
field :invite, :string, nullable: true
|
|
18
|
+
field :verification, [:enum, NEWSLETTER_VERIFICATIONS], nullable: true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# A newsletter row in the newsletters.list page (NewsletterListItem). Here
|
|
22
|
+
# the JID is carried on `chat_id`.
|
|
23
|
+
class NewsletterListItem < Base
|
|
24
|
+
field :chat_id, :string, wire_name: "chatId"
|
|
25
|
+
field :name, :string
|
|
26
|
+
field :description, :string, nullable: true
|
|
27
|
+
field :created_at, :string, nullable: true, wire_name: "createdAt"
|
|
28
|
+
field :subscribers, :integer, nullable: true
|
|
29
|
+
field :invite, :string, nullable: true
|
|
30
|
+
field :verification, [:enum, NEWSLETTER_VERIFICATIONS], nullable: true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module Blueticks
|
|
6
|
+
module Types
|
|
7
|
+
# Generic `{ "ok": true }` acknowledgement returned by side-effecting
|
|
8
|
+
# endpoints (chat archive/mark-read, message pin/unpin/react).
|
|
9
|
+
class OkResult < Base
|
|
10
|
+
field :ok, [:enum, [true]]
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
require_relative "coverage"
|
|
5
|
+
require_relative "../errors"
|
|
6
|
+
|
|
7
|
+
module Blueticks
|
|
8
|
+
module Types
|
|
9
|
+
# Offset-paginated list envelope. Every v1 list endpoint returns this shape
|
|
10
|
+
# inside the success/data wrapper: `{ data: [...], limit, skip, total }`.
|
|
11
|
+
#
|
|
12
|
+
# Iterate `data` for the current page; advance by passing `skip: skip + limit`
|
|
13
|
+
# (or any offset) back on the next list call. `total` is the full match count
|
|
14
|
+
# across all pages. `has_more` is populated only by endpoints that echo a
|
|
15
|
+
# `hasMore` flag (e.g. messages.list); nil elsewhere. `coverage` (Types::Coverage) is
|
|
16
|
+
# likewise populated only by messages.list.
|
|
17
|
+
class PaginatedPage
|
|
18
|
+
attr_reader :data, :limit, :skip, :total, :has_more, :coverage
|
|
19
|
+
|
|
20
|
+
def initialize(data:, limit:, skip:, total:, has_more: nil, coverage: nil)
|
|
21
|
+
@data = data
|
|
22
|
+
@limit = limit
|
|
23
|
+
@skip = skip
|
|
24
|
+
@total = total
|
|
25
|
+
@has_more = has_more
|
|
26
|
+
@coverage = coverage
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Build a PaginatedPage from a raw list envelope, decoding each item via
|
|
30
|
+
# item_type.from_hash. Reads `data`/`limit`/`skip`/`total` (and optional
|
|
31
|
+
# `hasMore` / `coverage`) off the envelope; ignores the `success` flag.
|
|
32
|
+
def self.from_hash(raw, item_type:)
|
|
33
|
+
unless raw.is_a?(Hash)
|
|
34
|
+
raise Errors::ValidationError.new(message: "Expected Hash for PaginatedPage, got #{raw.class}")
|
|
35
|
+
end
|
|
36
|
+
unless raw["data"].is_a?(Array)
|
|
37
|
+
raise Errors::ValidationError.new(message: "Field 'data' must be array in PaginatedPage")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
limit = require_integer(raw, "limit")
|
|
41
|
+
skip = require_integer(raw, "skip")
|
|
42
|
+
total = require_integer(raw, "total")
|
|
43
|
+
|
|
44
|
+
has_more = raw["hasMore"]
|
|
45
|
+
unless has_more.nil? || [true, false].include?(has_more)
|
|
46
|
+
raise Errors::ValidationError.new(message: "Field 'hasMore' must be boolean or absent in PaginatedPage")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
coverage = raw["coverage"].nil? ? nil : Coverage.from_hash(raw["coverage"], context: "PaginatedPage.coverage")
|
|
50
|
+
|
|
51
|
+
decoded = raw["data"].each_with_index.map do |item, i|
|
|
52
|
+
item_type.from_hash(item, context: "PaginatedPage.data[#{i}]")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
new(data: decoded, limit: limit, skip: skip, total: total, has_more: has_more, coverage: coverage)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.require_integer(raw, key)
|
|
59
|
+
value = raw[key]
|
|
60
|
+
unless value.is_a?(Integer) && !value.is_a?(TrueClass) && !value.is_a?(FalseClass)
|
|
61
|
+
raise Errors::ValidationError.new(message: "Field '#{key}' must be integer in PaginatedPage")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
value
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def to_h
|
|
68
|
+
{
|
|
69
|
+
data: data.map { |d| d.respond_to?(:to_h) ? d.to_h : d },
|
|
70
|
+
limit: limit, skip: skip, total: total, has_more: has_more, coverage: coverage&.to_h
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/blueticks/types/ping.rb
CHANGED
|
@@ -4,11 +4,19 @@ require_relative "base"
|
|
|
4
4
|
|
|
5
5
|
module Blueticks
|
|
6
6
|
module Types
|
|
7
|
+
# A connected WhatsApp engine as summarized on the ping response.
|
|
8
|
+
class PingConnection < Base
|
|
9
|
+
field :id, :string
|
|
10
|
+
field :type, [:enum, %w[gateway regular]]
|
|
11
|
+
field :connected, [:enum, [true]]
|
|
12
|
+
end
|
|
13
|
+
|
|
7
14
|
# Response from GET /v1/ping.
|
|
8
15
|
class Ping < Base
|
|
9
|
-
field :
|
|
10
|
-
field :
|
|
11
|
-
field :
|
|
16
|
+
field :api, [:enum, %w[ok]]
|
|
17
|
+
field :account_id, :string, wire_name: "accountId"
|
|
18
|
+
field :whatsapp_connections, [:array, PingConnection], wire_name: "whatsappConnections"
|
|
19
|
+
field :message, :string, optional: true
|
|
12
20
|
end
|
|
13
21
|
end
|
|
14
22
|
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
|
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "
|
|
3
|
+
require_relative "messages"
|
|
4
4
|
|
|
5
5
|
module Blueticks
|
|
6
6
|
module Types
|
|
7
|
+
# A queued / scheduled outbound message record — the shape returned by
|
|
8
|
+
# every scheduled_messages.* endpoint. This is a DISTINCT inline schema in
|
|
9
|
+
# the spec (not MessageResponse): only `to`, `type`, `status`, `createdAt`
|
|
10
|
+
# are required. In particular `waMessageKey` is optional and ABSENT on a
|
|
11
|
+
# record that has not dispatched yet, so it must never be decoded through a
|
|
12
|
+
# type that requires it (see Types::Message, used only by messages.create).
|
|
7
13
|
class ScheduledMessage < Base
|
|
8
|
-
field :id, :string
|
|
9
|
-
field :
|
|
10
|
-
field :
|
|
11
|
-
field :
|
|
12
|
-
field :
|
|
13
|
-
field :
|
|
14
|
-
field :
|
|
15
|
-
field :
|
|
16
|
-
field :
|
|
17
|
-
field :
|
|
18
|
-
field :
|
|
19
|
-
field :
|
|
20
|
-
field :
|
|
14
|
+
field :id, :string, optional: true
|
|
15
|
+
field :wa_message_key, WaMessageKey, optional: true, nullable: true, wire_name: "waMessageKey"
|
|
16
|
+
field :to, :string
|
|
17
|
+
field :type, [:enum, MESSAGE_KINDS]
|
|
18
|
+
field :text, :string, optional: true, nullable: true
|
|
19
|
+
field :media_url, :string, optional: true, nullable: true, wire_name: "mediaUrl"
|
|
20
|
+
field :media_kind, [:enum, MESSAGE_MEDIA_KINDS], optional: true, nullable: true, wire_name: "mediaKind"
|
|
21
|
+
field :poll_question, :string, optional: true, nullable: true, wire_name: "pollQuestion"
|
|
22
|
+
field :poll_options, %i[array string], optional: true, nullable: true, wire_name: "pollOptions"
|
|
23
|
+
field :poll_allow_multiple, :boolean, optional: true, nullable: true, wire_name: "pollAllowMultiple"
|
|
24
|
+
field :status, [:enum, MESSAGE_STATUSES]
|
|
25
|
+
field :send_at, :string, optional: true, nullable: true, wire_name: "sendAt"
|
|
26
|
+
field :created_at, :string, wire_name: "createdAt"
|
|
27
|
+
field :confirmed_at, :string, optional: true, nullable: true, wire_name: "confirmedAt"
|
|
28
|
+
field :received_at, :string, optional: true, nullable: true, wire_name: "receivedAt"
|
|
29
|
+
field :read_at, :string, optional: true, nullable: true, wire_name: "readAt"
|
|
30
|
+
field :played_at, :string, optional: true, nullable: true, wire_name: "playedAt"
|
|
31
|
+
field :failed_at, :string, optional: true, nullable: true, wire_name: "failedAt"
|
|
32
|
+
field :failure_reason, :string, optional: true, nullable: true, wire_name: "failureReason"
|
|
33
|
+
field :secret, :string, optional: true, nullable: true
|
|
34
|
+
field :link_preview, LinkPreview, optional: true, wire_name: "linkPreview"
|
|
21
35
|
end
|
|
22
36
|
end
|
|
23
37
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module Blueticks
|
|
6
|
+
module Types
|
|
7
|
+
SONG_CLIP_STATUSES = %w[submitted queued running streaming complete error].freeze
|
|
8
|
+
|
|
9
|
+
# Suno credit / plan usage (AccountUsageResponse) from GET /v1/suno/account.
|
|
10
|
+
class SunoAccount < Base
|
|
11
|
+
field :credits_left, :number, wire_name: "creditsLeft"
|
|
12
|
+
field :monthly_limit, :number, nullable: true, wire_name: "monthlyLimit"
|
|
13
|
+
field :monthly_usage, :number, nullable: true, wire_name: "monthlyUsage"
|
|
14
|
+
field :plan, :string, nullable: true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# A generated song clip (SongClip / GetSongResponse).
|
|
18
|
+
class SongClip < Base
|
|
19
|
+
field :id, :string
|
|
20
|
+
field :status, [:enum, SONG_CLIP_STATUSES]
|
|
21
|
+
field :audio_url, :string, nullable: true, wire_name: "audioUrl"
|
|
22
|
+
field :image_url, :string, nullable: true, wire_name: "imageUrl"
|
|
23
|
+
field :title, :string, nullable: true
|
|
24
|
+
field :duration_sec, :number, nullable: true, wire_name: "durationSec"
|
|
25
|
+
field :model, :string, nullable: true
|
|
26
|
+
field :error_type, :string, nullable: true, optional: true, wire_name: "errorType"
|
|
27
|
+
field :error_message, :string, nullable: true, optional: true, wire_name: "errorMessage"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Result of submitting a song generation job (GenerateSongResponse).
|
|
31
|
+
class GenerateSongResult < Base
|
|
32
|
+
field :job_id, :string, wire_name: "jobId"
|
|
33
|
+
field :clips, [:array, SongClip]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Result of registering a reference-audio upload (CreateUploadResponse).
|
|
37
|
+
class CreateUploadResult < Base
|
|
38
|
+
field :upload_id, :string, wire_name: "uploadId"
|
|
39
|
+
field :status, :string
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
# Placeholder — UtilsResource exposes no /v1/utils/* methods in the
|
|
4
|
+
# current spec. This file exists because lib/blueticks.rb (MUST-NOT-TOUCH)
|
|
5
|
+
# requires it. Once the spec adds util operations, regenerate this file
|
|
6
|
+
# with the matching response types.
|
|
5
7
|
module Blueticks
|
|
6
8
|
module Types
|
|
7
|
-
|
|
8
|
-
field :valid, :boolean
|
|
9
|
-
field :formatted_chat_id, :string, nullable: true
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
class LinkPreview < Base
|
|
13
|
-
field :title, :string, nullable: true
|
|
14
|
-
field :description, :string, nullable: true
|
|
15
|
-
field :thumbnail, :string, nullable: true
|
|
16
|
-
field :canonical_url, :string, nullable: true
|
|
9
|
+
module Utils
|
|
17
10
|
end
|
|
18
11
|
end
|
|
19
12
|
end
|
|
@@ -10,27 +10,30 @@ module Blueticks
|
|
|
10
10
|
message.queued message.sending message.delivered message.failed message.read
|
|
11
11
|
session.connected session.disconnected
|
|
12
12
|
campaign.started campaign.paused campaign.resumed campaign.completed campaign.aborted
|
|
13
|
+
new_message_received_webhook message_reaction_webhook ack_changed_webhook
|
|
14
|
+
participant_joined_via_link_webhook participant_added_by_admin_webhook
|
|
15
|
+
participant_left_group_webhook participant_kicked_from_group_webhook
|
|
16
|
+
group_admin_changed_webhook group_name_changed_webhook group_description_changed_webhook
|
|
17
|
+
group_message_pinned_webhook poll_vote_webhook reply_to_my_message_webhook
|
|
18
|
+
message_deleted_revoked_webhook message_edited_webhook
|
|
19
|
+
new_message_received_from_me_webhook
|
|
13
20
|
].freeze
|
|
14
21
|
|
|
22
|
+
# A webhook subscription (WebhookResponse). `signing_secret` is present only
|
|
23
|
+
# when the API includes it in the response body.
|
|
15
24
|
class Webhook < Base
|
|
16
25
|
field :id, :string
|
|
17
26
|
field :url, :string
|
|
18
27
|
field :events, %i[array string]
|
|
19
28
|
field :description, :string, nullable: true
|
|
20
29
|
field :status, [:enum, WEBHOOK_STATUSES]
|
|
21
|
-
field :created_at, :string
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class WebhookCreateResult < Base
|
|
25
|
-
field :id, :string
|
|
26
|
-
field :url, :string
|
|
27
|
-
field :events, %i[array string]
|
|
28
|
-
field :description, :string, nullable: true
|
|
29
|
-
field :status, [:enum, WEBHOOK_STATUSES]
|
|
30
|
-
field :created_at, :string
|
|
31
|
-
field :secret, :string
|
|
30
|
+
field :created_at, :string, wire_name: "createdAt"
|
|
31
|
+
field :signing_secret, :string, optional: true, wire_name: "signingSecret"
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
# A delivered webhook event, as parsed by Blueticks::Webhooks.verify. Note
|
|
35
|
+
# the webhook DELIVERY payload is snake_case (distinct from the REST API's
|
|
36
|
+
# camelCase), so `created_at` here has no wire mapping.
|
|
34
37
|
class WebhookEvent < Base
|
|
35
38
|
field :id, :string
|
|
36
39
|
field :type, :string
|
data/lib/blueticks/version.rb
CHANGED