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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b20d20d7dc1f6a386e74894a57e470c70a1edc3e95bcd61c3b25f02b3e457cd
4
- data.tar.gz: 6fd6807bcbbd09fae222ccd07eee0d66cbb420bc04e83fd49ab98c4340a4ed82
3
+ metadata.gz: 2852d366a306a698457955ea9e631fb4cd05fbc0f55949a772f0b872b19ce0af
4
+ data.tar.gz: 74845607657bcea29116fe1a3d509daea04f0afba3e0ded079068f03b17d3506
5
5
  SHA512:
6
- metadata.gz: c5e18b59805d1aff449eb7e3b8227bd2290b85994ba8e14f38b1c945381facd37a1b77e218d9eaf3c3e8c3183eade0da5268eb86b79762ad1aa9606b015a8e6a
7
- data.tar.gz: ec5a37899a8c3622212e5d7d2b43a540df1e7aff64f9ea99a17a3fd1b0ed1e332a44a7c568eef24882f70fba267fe18302581d9af999ed997651df368dca59cc
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)
@@ -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
 
@@ -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
@@ -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, :parent_external_id,
313
- :like_count, :is_hidden, :permalink, :platform_data,
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,
@@ -1,3 +1,3 @@
1
1
  module PostProxy
2
- VERSION = "1.9.0"
2
+ VERSION = "1.10.0"
3
3
  end
@@ -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.9.0
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