postproxy-sdk 1.9.0 → 1.10.0
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/README.md +77 -1
- data/lib/postproxy/client.rb +12 -0
- data/lib/postproxy/constants.rb +14 -0
- data/lib/postproxy/resources/chats.rb +57 -0
- data/lib/postproxy/resources/comments.rb +8 -0
- data/lib/postproxy/resources/messages.rb +118 -0
- data/lib/postproxy/types.rb +116 -3
- data/lib/postproxy/version.rb +1 -1
- data/lib/postproxy/webhook_events.rb +40 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2852d366a306a698457955ea9e631fb4cd05fbc0f55949a772f0b872b19ce0af
|
|
4
|
+
data.tar.gz: 74845607657bcea29116fe1a3d509daea04f0afba3e0ded079068f03b17d3506
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0650f24d42af376d663521ced5c78be0fe97dc99d117534a132479a02f8290a18404426d5791ea5f90f3ed786041ccb2d3a15486533b149e7ab0c94324839238
|
|
7
|
+
data.tar.gz: 39699c4a07a238f45fc1e12545dfc97b88d85299f03cd3eb1ba97380a1f7bfa79da004abd170c3da87aa707d486a7a103c298c0b34fb9371d9d0c4ada45e3014
|
data/README.md
CHANGED
|
@@ -264,7 +264,7 @@ PostProxy::WebhookSignature.verify(
|
|
|
264
264
|
|
|
265
265
|
Subscribe to any of these events (or pass `["*"]` for all):
|
|
266
266
|
|
|
267
|
-
`post.processed`, `post.imported`, `platform_post.published`, `platform_post.failed`, `platform_post.failed_waiting_for_retry`, `platform_post.insights`, `profile.connected`, `profile.disconnected`, `profile.stats`, `media.failed`, `comment.created`.
|
|
267
|
+
`post.processed`, `post.imported`, `platform_post.published`, `platform_post.failed`, `platform_post.failed_waiting_for_retry`, `platform_post.insights`, `profile.connected`, `profile.disconnected`, `profile.stats`, `media.failed`, `comment.created`, `profile_comment.created`, `message.received`, `message.sent`, `message.delivered`, `message.read`, `message.edited`, `message.deleted`, `message.failed_waiting_for_retry`, `message.failed`, `reaction.received`.
|
|
268
268
|
|
|
269
269
|
`PostProxy::WebhookEvents.parse` validates the envelope and returns a typed `Event` — `event.data` is the right model for the event:
|
|
270
270
|
|
|
@@ -277,9 +277,20 @@ when "platform_post.published"
|
|
|
277
277
|
puts "Published: #{event.data.platform_id}"
|
|
278
278
|
when "comment.created"
|
|
279
279
|
puts "#{event.data.author_username}: #{event.data.body}"
|
|
280
|
+
when "message.received"
|
|
281
|
+
# MessageEventData — event.data.message is a full Message
|
|
282
|
+
puts "DM from #{event.data.message.chat_id}: #{event.data.message.body}"
|
|
283
|
+
when "reaction.received"
|
|
284
|
+
# ReactionEventData
|
|
285
|
+
puts "#{event.data.action}: #{event.data.reaction} on #{event.data.message.id}"
|
|
286
|
+
when "profile_comment.created"
|
|
287
|
+
# ProfileCommentCreatedData
|
|
288
|
+
puts "#{event.data.author_username}: #{event.data.body}"
|
|
280
289
|
end
|
|
281
290
|
```
|
|
282
291
|
|
|
292
|
+
The direct-message events (`message.*`) carry a `MessageEventData` (`data.message` is a full `Message`); `reaction.received` carries a `ReactionEventData`; `profile_comment.created` carries a `ProfileCommentCreatedData`.
|
|
293
|
+
|
|
283
294
|
## Comments
|
|
284
295
|
|
|
285
296
|
```ruby
|
|
@@ -315,6 +326,71 @@ client.comments.unhide("post-id", "comment-id", profile_id: "profile-id")
|
|
|
315
326
|
# Like / unlike a comment
|
|
316
327
|
client.comments.like("post-id", "comment-id", profile_id: "profile-id")
|
|
317
328
|
client.comments.unlike("post-id", "comment-id", profile_id: "profile-id")
|
|
329
|
+
|
|
330
|
+
# Synced comments may carry media attachments and author metadata
|
|
331
|
+
comment = client.comments.get("post-id", "comment-id", profile_id: "profile-id")
|
|
332
|
+
comment.attachments.each { |att| puts "#{att.type} #{att.url} (#{att.status})" }
|
|
333
|
+
puts comment.metadata[:follower_count] if comment.metadata
|
|
334
|
+
|
|
335
|
+
# Private reply to a comment's author (Instagram/Facebook) — returns a Message
|
|
336
|
+
message = client.comments.private_reply("post-id", "comment-id", profile_id: "profile-id", text: "DM-ing you the details.")
|
|
337
|
+
puts message.chat_id, message.status
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Direct Messages
|
|
341
|
+
|
|
342
|
+
Read and send 1:1 messages on DM-capable profiles (Facebook Messenger, Instagram, Telegram, Bluesky). A conversation is a **Chat**; it holds **Messages**. Outbound sends are processed asynchronously (`status` starts as `pending`).
|
|
343
|
+
|
|
344
|
+
```ruby
|
|
345
|
+
# List chats for a profile (paginated, most recent first)
|
|
346
|
+
chats = client.chats.list("profile-id", per_page: 20)
|
|
347
|
+
chats.data.each { |chat| puts "#{chat.participant_username}: #{chat.last_message_at}" }
|
|
348
|
+
|
|
349
|
+
# Find or create a chat with a participant (idempotent)
|
|
350
|
+
chat = client.chats.create("profile-id", "igsid_8675309", participant_username: "jane_doe")
|
|
351
|
+
|
|
352
|
+
# Get a single chat
|
|
353
|
+
chat = client.chats.get(chat.id)
|
|
354
|
+
|
|
355
|
+
# List messages in a chat (filter by direction/status)
|
|
356
|
+
messages = client.messages.list(chat.id, direction: "inbound")
|
|
357
|
+
messages.data.each do |msg|
|
|
358
|
+
puts "#{msg.direction}: #{msg.body}"
|
|
359
|
+
msg.attachments.each { |att| puts " #{att.url}" }
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Send a text message (within the 24h window)
|
|
363
|
+
sent = client.messages.send(chat.id, body: "Yes, we ship worldwide!")
|
|
364
|
+
|
|
365
|
+
# Send outside the 24h window with a tag (Facebook/Instagram)
|
|
366
|
+
client.messages.send(chat.id, body: "Following up.", tag: "HUMAN_AGENT")
|
|
367
|
+
|
|
368
|
+
# Send media — by hosted URL or local file
|
|
369
|
+
client.messages.send(chat.id, media: ["https://cdn.example.com/photo.png"])
|
|
370
|
+
client.messages.send(chat.id, media_files: ["./photo.png"])
|
|
371
|
+
|
|
372
|
+
# Telegram: reply threading + inline keyboard
|
|
373
|
+
client.messages.send(
|
|
374
|
+
chat.id,
|
|
375
|
+
body: "Pick one:",
|
|
376
|
+
reply_markup: { inline_keyboard: [[{ text: "Track order", callback_data: "track:1" }]] }
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
# Get / edit (Telegram only) a message
|
|
380
|
+
msg = client.messages.get(sent.id)
|
|
381
|
+
client.messages.edit(sent.id, body: "Updated answer.")
|
|
382
|
+
|
|
383
|
+
# React / unreact (Facebook & Instagram)
|
|
384
|
+
client.messages.react(sent.id, reaction: "love", emoji: "❤️")
|
|
385
|
+
client.messages.unreact(sent.id)
|
|
386
|
+
|
|
387
|
+
# Archive / unarchive a chat (Bluesky only)
|
|
388
|
+
client.chats.archive(chat.id)
|
|
389
|
+
client.chats.unarchive(chat.id)
|
|
390
|
+
|
|
391
|
+
# Private reply to a comment's author (Instagram/Facebook) — returns a Message
|
|
392
|
+
message = client.comments.private_reply("post-id", "comment-id", profile_id: "profile-id", text: "DM-ing you the details.")
|
|
393
|
+
puts message.chat_id, message.status
|
|
318
394
|
```
|
|
319
395
|
|
|
320
396
|
## Profile comments (Google Business reviews)
|
data/lib/postproxy/client.rb
CHANGED
|
@@ -8,6 +8,8 @@ require_relative "resources/webhooks"
|
|
|
8
8
|
require_relative "resources/queues"
|
|
9
9
|
require_relative "resources/comments"
|
|
10
10
|
require_relative "resources/profile_comments"
|
|
11
|
+
require_relative "resources/chats"
|
|
12
|
+
require_relative "resources/messages"
|
|
11
13
|
|
|
12
14
|
module PostProxy
|
|
13
15
|
class Client
|
|
@@ -25,6 +27,8 @@ module PostProxy
|
|
|
25
27
|
@queues = nil
|
|
26
28
|
@comments = nil
|
|
27
29
|
@profile_comments = nil
|
|
30
|
+
@chats = nil
|
|
31
|
+
@messages = nil
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
def posts
|
|
@@ -55,6 +59,14 @@ module PostProxy
|
|
|
55
59
|
@profile_comments ||= Resources::ProfileComments.new(self)
|
|
56
60
|
end
|
|
57
61
|
|
|
62
|
+
def chats
|
|
63
|
+
@chats ||= Resources::Chats.new(self)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def messages
|
|
67
|
+
@messages ||= Resources::Messages.new(self)
|
|
68
|
+
end
|
|
69
|
+
|
|
58
70
|
def request(method, path, params: nil, json: nil, data: nil, files: nil, profile_group_id: nil)
|
|
59
71
|
url = "/api#{path}"
|
|
60
72
|
|
data/lib/postproxy/constants.rb
CHANGED
|
@@ -32,6 +32,10 @@ module PostProxy
|
|
|
32
32
|
|
|
33
33
|
TELEGRAM_PARSE_MODES = %w[HTML MarkdownV2].freeze
|
|
34
34
|
|
|
35
|
+
MESSAGE_DIRECTIONS = %w[inbound outbound].freeze
|
|
36
|
+
|
|
37
|
+
MESSAGE_STATUSES = %w[pending published failed_waiting_for_retry failed received].freeze
|
|
38
|
+
|
|
35
39
|
WEBHOOK_EVENT_TYPES = %w[
|
|
36
40
|
post.processed
|
|
37
41
|
post.imported
|
|
@@ -44,5 +48,15 @@ module PostProxy
|
|
|
44
48
|
profile.stats
|
|
45
49
|
media.failed
|
|
46
50
|
comment.created
|
|
51
|
+
profile_comment.created
|
|
52
|
+
message.received
|
|
53
|
+
message.sent
|
|
54
|
+
message.delivered
|
|
55
|
+
message.read
|
|
56
|
+
message.edited
|
|
57
|
+
message.deleted
|
|
58
|
+
message.failed_waiting_for_retry
|
|
59
|
+
message.failed
|
|
60
|
+
reaction.received
|
|
47
61
|
].freeze
|
|
48
62
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module PostProxy
|
|
2
|
+
module Resources
|
|
3
|
+
class Chats
|
|
4
|
+
def initialize(client)
|
|
5
|
+
@client = client
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def list(profile_id, page: nil, per_page: nil, before: nil, after: nil, profile_group_id: nil)
|
|
9
|
+
params = {}
|
|
10
|
+
params[:page] = page if page
|
|
11
|
+
params[:per_page] = per_page if per_page
|
|
12
|
+
params[:before] = format_time(before) if before
|
|
13
|
+
params[:after] = format_time(after) if after
|
|
14
|
+
|
|
15
|
+
result = @client.request(:get, "/profiles/#{profile_id}/chats", params: params, profile_group_id: profile_group_id)
|
|
16
|
+
chats = (result[:data] || []).map { |c| Chat.new(**c) }
|
|
17
|
+
PaginatedResponse.new(
|
|
18
|
+
data: chats,
|
|
19
|
+
total: result[:total],
|
|
20
|
+
page: result[:page],
|
|
21
|
+
per_page: result[:per_page]
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def create(profile_id, participant_external_id, participant_username: nil, participant_name: nil, profile_group_id: nil)
|
|
26
|
+
json_body = { participant_external_id: participant_external_id }
|
|
27
|
+
json_body[:participant_username] = participant_username if participant_username
|
|
28
|
+
json_body[:participant_name] = participant_name if participant_name
|
|
29
|
+
|
|
30
|
+
result = @client.request(:post, "/profiles/#{profile_id}/chats", json: json_body, profile_group_id: profile_group_id)
|
|
31
|
+
Chat.new(**result)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get(chat_id, profile_group_id: nil)
|
|
35
|
+
result = @client.request(:get, "/chats/#{chat_id}", profile_group_id: profile_group_id)
|
|
36
|
+
Chat.new(**result)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def archive(chat_id, profile_group_id: nil)
|
|
40
|
+
result = @client.request(:post, "/chats/#{chat_id}/archive", profile_group_id: profile_group_id)
|
|
41
|
+
Chat.new(**result)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def unarchive(chat_id, profile_group_id: nil)
|
|
45
|
+
result = @client.request(:delete, "/chats/#{chat_id}/archive", profile_group_id: profile_group_id)
|
|
46
|
+
Chat.new(**result)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def format_time(value)
|
|
52
|
+
return value if value.is_a?(String)
|
|
53
|
+
value.iso8601
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -57,6 +57,14 @@ module PostProxy
|
|
|
57
57
|
result = @client.request(:post, "/posts/#{post_id}/comments/#{comment_id}/unlike", params: { profile_id: profile_id })
|
|
58
58
|
AcceptedResponse.new(**result)
|
|
59
59
|
end
|
|
60
|
+
|
|
61
|
+
def private_reply(post_id, comment_id, profile_id:, text:)
|
|
62
|
+
result = @client.request(:post, "/posts/#{post_id}/comments/#{comment_id}/private_reply",
|
|
63
|
+
params: { profile_id: profile_id },
|
|
64
|
+
json: { text: text }
|
|
65
|
+
)
|
|
66
|
+
Message.new(**result)
|
|
67
|
+
end
|
|
60
68
|
end
|
|
61
69
|
end
|
|
62
70
|
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module PostProxy
|
|
2
|
+
module Resources
|
|
3
|
+
class Messages
|
|
4
|
+
def initialize(client)
|
|
5
|
+
@client = client
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def list(chat_id, page: nil, per_page: nil, direction: nil, status: nil, profile_group_id: nil)
|
|
9
|
+
params = {}
|
|
10
|
+
params[:page] = page if page
|
|
11
|
+
params[:per_page] = per_page if per_page
|
|
12
|
+
params[:direction] = direction if direction
|
|
13
|
+
params[:status] = status if status
|
|
14
|
+
|
|
15
|
+
result = @client.request(:get, "/chats/#{chat_id}/messages", params: params, profile_group_id: profile_group_id)
|
|
16
|
+
messages = (result[:data] || []).map { |m| Message.new(**m) }
|
|
17
|
+
PaginatedResponse.new(
|
|
18
|
+
data: messages,
|
|
19
|
+
total: result[:total],
|
|
20
|
+
page: result[:page],
|
|
21
|
+
per_page: result[:per_page]
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def send_message(chat_id, body: nil, media: nil, media_files: nil, tag: nil,
|
|
26
|
+
reply_to_external_id: nil, reply_markup: nil, profile_group_id: nil)
|
|
27
|
+
has_files = media_files && !media_files.empty?
|
|
28
|
+
|
|
29
|
+
if has_files
|
|
30
|
+
form_data = {}
|
|
31
|
+
form_data["body"] = body if body
|
|
32
|
+
form_data["tag"] = tag if tag
|
|
33
|
+
form_data["reply_to_external_id"] = reply_to_external_id if reply_to_external_id
|
|
34
|
+
|
|
35
|
+
files = []
|
|
36
|
+
media&.each do |m|
|
|
37
|
+
files << ["media[]", nil, m, "text/plain"]
|
|
38
|
+
end
|
|
39
|
+
media_files.each do |path|
|
|
40
|
+
path = path.to_s
|
|
41
|
+
filename = File.basename(path)
|
|
42
|
+
content_type = mime_type_for(filename)
|
|
43
|
+
io = File.open(path, "rb")
|
|
44
|
+
files << ["media[]", filename, io, content_type]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
result = @client.request(:post, "/chats/#{chat_id}/messages",
|
|
48
|
+
data: form_data,
|
|
49
|
+
files: files,
|
|
50
|
+
profile_group_id: profile_group_id
|
|
51
|
+
)
|
|
52
|
+
else
|
|
53
|
+
json_body = {}
|
|
54
|
+
json_body[:body] = body if body
|
|
55
|
+
json_body[:media] = media if media
|
|
56
|
+
json_body[:tag] = tag if tag
|
|
57
|
+
json_body[:reply_to_external_id] = reply_to_external_id if reply_to_external_id
|
|
58
|
+
json_body[:reply_markup] = reply_markup if reply_markup
|
|
59
|
+
|
|
60
|
+
result = @client.request(:post, "/chats/#{chat_id}/messages", json: json_body, profile_group_id: profile_group_id)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
Message.new(**result)
|
|
64
|
+
end
|
|
65
|
+
alias_method :send, :send_message
|
|
66
|
+
|
|
67
|
+
def get(message_id, profile_group_id: nil)
|
|
68
|
+
result = @client.request(:get, "/messages/#{message_id}", profile_group_id: profile_group_id)
|
|
69
|
+
Message.new(**result)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def edit(message_id, body: nil, reply_markup: nil, profile_group_id: nil)
|
|
73
|
+
json_body = {}
|
|
74
|
+
json_body[:body] = body if body
|
|
75
|
+
json_body[:reply_markup] = reply_markup if reply_markup
|
|
76
|
+
|
|
77
|
+
result = @client.request(:patch, "/messages/#{message_id}", json: json_body, profile_group_id: profile_group_id)
|
|
78
|
+
Message.new(**result)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def react(message_id, reaction: nil, emoji: nil, profile_group_id: nil)
|
|
82
|
+
json_body = {}
|
|
83
|
+
json_body[:reaction] = reaction if reaction
|
|
84
|
+
json_body[:emoji] = emoji if emoji
|
|
85
|
+
|
|
86
|
+
result = @client.request(:post, "/messages/#{message_id}/react",
|
|
87
|
+
json: json_body.empty? ? nil : json_body,
|
|
88
|
+
profile_group_id: profile_group_id
|
|
89
|
+
)
|
|
90
|
+
Message.new(**result)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def unreact(message_id, profile_group_id: nil)
|
|
94
|
+
result = @client.request(:delete, "/messages/#{message_id}/unreact", profile_group_id: profile_group_id)
|
|
95
|
+
Message.new(**result)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def mime_type_for(filename)
|
|
101
|
+
case File.extname(filename).downcase
|
|
102
|
+
when ".jpg", ".jpeg" then "image/jpeg"
|
|
103
|
+
when ".png" then "image/png"
|
|
104
|
+
when ".gif" then "image/gif"
|
|
105
|
+
when ".webp" then "image/webp"
|
|
106
|
+
when ".mp4" then "video/mp4"
|
|
107
|
+
when ".mov" then "video/quicktime"
|
|
108
|
+
when ".avi" then "video/x-msvideo"
|
|
109
|
+
when ".webm" then "video/webm"
|
|
110
|
+
when ".mp3" then "audio/mpeg"
|
|
111
|
+
when ".ogg" then "audio/ogg"
|
|
112
|
+
when ".m4a" then "audio/mp4"
|
|
113
|
+
else "application/octet-stream"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
data/lib/postproxy/types.rb
CHANGED
|
@@ -307,25 +307,59 @@ module PostProxy
|
|
|
307
307
|
end
|
|
308
308
|
end
|
|
309
309
|
|
|
310
|
+
class Attachment < Model
|
|
311
|
+
attr_accessor :id, :type, :url, :status, :external_id
|
|
312
|
+
|
|
313
|
+
def initialize(**attrs)
|
|
314
|
+
@url = nil
|
|
315
|
+
@external_id = nil
|
|
316
|
+
super
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
class Reaction < Model
|
|
321
|
+
attr_accessor :sender_external_id, :emoji, :reaction, :at
|
|
322
|
+
|
|
323
|
+
def initialize(**attrs)
|
|
324
|
+
@emoji = nil
|
|
325
|
+
@reaction = nil
|
|
326
|
+
@at = nil
|
|
327
|
+
super
|
|
328
|
+
@at = parse_time(@at)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
private
|
|
332
|
+
|
|
333
|
+
def parse_time(value)
|
|
334
|
+
return nil if value.nil?
|
|
335
|
+
value.is_a?(Time) ? value : Time.parse(value.to_s)
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
310
339
|
class Comment < Model
|
|
311
340
|
attr_accessor :id, :external_id, :body, :status, :author_username,
|
|
312
|
-
:author_avatar_url, :author_external_id, :
|
|
313
|
-
:like_count, :is_hidden, :permalink,
|
|
314
|
-
:posted_at, :created_at, :replies
|
|
341
|
+
:author_avatar_url, :author_external_id, :metadata,
|
|
342
|
+
:parent_external_id, :like_count, :is_hidden, :permalink,
|
|
343
|
+
:platform_data, :attachments, :posted_at, :created_at, :replies
|
|
315
344
|
|
|
316
345
|
def initialize(**attrs)
|
|
317
346
|
@external_id = nil
|
|
318
347
|
@author_avatar_url = nil
|
|
319
348
|
@author_external_id = nil
|
|
349
|
+
@metadata = nil
|
|
320
350
|
@parent_external_id = nil
|
|
321
351
|
@like_count = 0
|
|
322
352
|
@is_hidden = false
|
|
323
353
|
@permalink = nil
|
|
324
354
|
@platform_data = nil
|
|
355
|
+
@attachments = []
|
|
325
356
|
@replies = []
|
|
326
357
|
super
|
|
327
358
|
@posted_at = parse_time(@posted_at)
|
|
328
359
|
@created_at = parse_time(@created_at)
|
|
360
|
+
@attachments = (@attachments || []).map do |a|
|
|
361
|
+
a.is_a?(Attachment) ? a : Attachment.new(**a.transform_keys(&:to_sym))
|
|
362
|
+
end
|
|
329
363
|
@replies = (@replies || []).map do |r|
|
|
330
364
|
r.is_a?(Comment) ? r : Comment.new(**r.transform_keys(&:to_sym))
|
|
331
365
|
end
|
|
@@ -339,6 +373,85 @@ module PostProxy
|
|
|
339
373
|
end
|
|
340
374
|
end
|
|
341
375
|
|
|
376
|
+
class Chat < Model
|
|
377
|
+
attr_accessor :id, :profile_id, :platform, :participant_external_id,
|
|
378
|
+
:participant_username, :participant_name, :participant_avatar_url,
|
|
379
|
+
:external_conversation_id, :last_inbound_at, :last_outbound_at,
|
|
380
|
+
:last_message_at, :metadata, :archived, :created_at
|
|
381
|
+
|
|
382
|
+
def initialize(**attrs)
|
|
383
|
+
@participant_username = nil
|
|
384
|
+
@participant_name = nil
|
|
385
|
+
@participant_avatar_url = nil
|
|
386
|
+
@external_conversation_id = nil
|
|
387
|
+
@last_inbound_at = nil
|
|
388
|
+
@last_outbound_at = nil
|
|
389
|
+
@last_message_at = nil
|
|
390
|
+
@metadata = nil
|
|
391
|
+
@archived = nil
|
|
392
|
+
super
|
|
393
|
+
@last_inbound_at = parse_time(@last_inbound_at)
|
|
394
|
+
@last_outbound_at = parse_time(@last_outbound_at)
|
|
395
|
+
@last_message_at = parse_time(@last_message_at)
|
|
396
|
+
@created_at = parse_time(@created_at)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
private
|
|
400
|
+
|
|
401
|
+
def parse_time(value)
|
|
402
|
+
return nil if value.nil?
|
|
403
|
+
value.is_a?(Time) ? value : Time.parse(value.to_s)
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
class Message < Model
|
|
408
|
+
attr_accessor :id, :chat_id, :external_id, :direction, :body, :status,
|
|
409
|
+
:tag, :external_comment_id, :error_message, :platform_data,
|
|
410
|
+
:external_posted_at, :external_delivered_at, :external_read_at,
|
|
411
|
+
:external_edited_at, :reply_to_external_id, :reply_markup,
|
|
412
|
+
:external_deleted_at, :reactions, :attachments,
|
|
413
|
+
:is_unsupported, :created_at
|
|
414
|
+
|
|
415
|
+
def initialize(**attrs)
|
|
416
|
+
@external_id = nil
|
|
417
|
+
@body = nil
|
|
418
|
+
@tag = nil
|
|
419
|
+
@external_comment_id = nil
|
|
420
|
+
@error_message = nil
|
|
421
|
+
@platform_data = nil
|
|
422
|
+
@external_posted_at = nil
|
|
423
|
+
@external_delivered_at = nil
|
|
424
|
+
@external_read_at = nil
|
|
425
|
+
@external_edited_at = nil
|
|
426
|
+
@reply_to_external_id = nil
|
|
427
|
+
@reply_markup = nil
|
|
428
|
+
@external_deleted_at = nil
|
|
429
|
+
@reactions = []
|
|
430
|
+
@attachments = []
|
|
431
|
+
@is_unsupported = false
|
|
432
|
+
super
|
|
433
|
+
@external_posted_at = parse_time(@external_posted_at)
|
|
434
|
+
@external_delivered_at = parse_time(@external_delivered_at)
|
|
435
|
+
@external_read_at = parse_time(@external_read_at)
|
|
436
|
+
@external_edited_at = parse_time(@external_edited_at)
|
|
437
|
+
@external_deleted_at = parse_time(@external_deleted_at)
|
|
438
|
+
@created_at = parse_time(@created_at)
|
|
439
|
+
@reactions = (@reactions || []).map do |r|
|
|
440
|
+
r.is_a?(Reaction) ? r : Reaction.new(**r.transform_keys(&:to_sym))
|
|
441
|
+
end
|
|
442
|
+
@attachments = (@attachments || []).map do |a|
|
|
443
|
+
a.is_a?(Attachment) ? a : Attachment.new(**a.transform_keys(&:to_sym))
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
private
|
|
448
|
+
|
|
449
|
+
def parse_time(value)
|
|
450
|
+
return nil if value.nil?
|
|
451
|
+
value.is_a?(Time) ? value : Time.parse(value.to_s)
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
342
455
|
class ProfileComment < Model
|
|
343
456
|
attr_accessor :id, :external_id, :parent_external_id, :placement_id,
|
|
344
457
|
:body, :status, :author_username, :author_avatar_url,
|
data/lib/postproxy/version.rb
CHANGED
|
@@ -71,6 +71,35 @@ module PostProxy
|
|
|
71
71
|
:platform_data, :posted_at, :created_at
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
class MessageEventData < Model
|
|
75
|
+
attr_accessor :message
|
|
76
|
+
|
|
77
|
+
def initialize(**attrs)
|
|
78
|
+
@message = nil
|
|
79
|
+
super
|
|
80
|
+
@message = Message.new(**@message.transform_keys(&:to_sym)) if @message.is_a?(Hash)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class ReactionEventData < Model
|
|
85
|
+
attr_accessor :message, :sender_external_id, :action, :reaction, :emoji, :occurred_at
|
|
86
|
+
|
|
87
|
+
def initialize(**attrs)
|
|
88
|
+
@message = nil
|
|
89
|
+
@reaction = nil
|
|
90
|
+
@emoji = nil
|
|
91
|
+
@occurred_at = nil
|
|
92
|
+
super
|
|
93
|
+
@message = Message.new(**@message.transform_keys(&:to_sym)) if @message.is_a?(Hash)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class ProfileCommentCreatedData < Model
|
|
98
|
+
attr_accessor :id, :profile_id, :platform, :placement_id, :external_id,
|
|
99
|
+
:parent_external_id, :body, :status, :author_username,
|
|
100
|
+
:author_avatar_url, :platform_data, :posted_at, :created_at
|
|
101
|
+
end
|
|
102
|
+
|
|
74
103
|
DATA_CLASSES = {
|
|
75
104
|
"post.processed" => PostProcessedData,
|
|
76
105
|
"post.imported" => PostImportedData,
|
|
@@ -82,7 +111,17 @@ module PostProxy
|
|
|
82
111
|
"profile.disconnected" => ProfileEventData,
|
|
83
112
|
"profile.stats" => ProfileStatsData,
|
|
84
113
|
"media.failed" => MediaFailedData,
|
|
85
|
-
"comment.created" => CommentCreatedData
|
|
114
|
+
"comment.created" => CommentCreatedData,
|
|
115
|
+
"profile_comment.created" => ProfileCommentCreatedData,
|
|
116
|
+
"message.received" => MessageEventData,
|
|
117
|
+
"message.sent" => MessageEventData,
|
|
118
|
+
"message.delivered" => MessageEventData,
|
|
119
|
+
"message.read" => MessageEventData,
|
|
120
|
+
"message.edited" => MessageEventData,
|
|
121
|
+
"message.deleted" => MessageEventData,
|
|
122
|
+
"message.failed_waiting_for_retry" => MessageEventData,
|
|
123
|
+
"message.failed" => MessageEventData,
|
|
124
|
+
"reaction.received" => ReactionEventData
|
|
86
125
|
}.freeze
|
|
87
126
|
|
|
88
127
|
# Parse a webhook body and return a typed Event. `data` is parsed into the
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: postproxy-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- PostProxy
|
|
@@ -78,7 +78,9 @@ files:
|
|
|
78
78
|
- lib/postproxy/client.rb
|
|
79
79
|
- lib/postproxy/constants.rb
|
|
80
80
|
- lib/postproxy/errors.rb
|
|
81
|
+
- lib/postproxy/resources/chats.rb
|
|
81
82
|
- lib/postproxy/resources/comments.rb
|
|
83
|
+
- lib/postproxy/resources/messages.rb
|
|
82
84
|
- lib/postproxy/resources/posts.rb
|
|
83
85
|
- lib/postproxy/resources/profile_comments.rb
|
|
84
86
|
- lib/postproxy/resources/profile_groups.rb
|