mailshake-ruby 0.1.0 → 0.2.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +80 -19
  3. data/lib/mailshake/activity.rb +14 -7
  4. data/lib/mailshake/campaigns.rb +10 -5
  5. data/lib/mailshake/client.rb +2 -1
  6. data/lib/mailshake/leads.rb +6 -3
  7. data/lib/mailshake/models/add_recipients_request.rb +8 -0
  8. data/lib/mailshake/models/added_recipients.rb +8 -0
  9. data/lib/mailshake/models/base_model.rb +79 -0
  10. data/lib/mailshake/models/campaign.rb +10 -0
  11. data/lib/mailshake/models/campaign_export.rb +8 -0
  12. data/lib/mailshake/models/campaign_export_request.rb +8 -0
  13. data/lib/mailshake/models/click.rb +11 -0
  14. data/lib/mailshake/models/created_leads.rb +8 -0
  15. data/lib/mailshake/models/lead.rb +11 -0
  16. data/lib/mailshake/models/lead_status.rb +8 -0
  17. data/lib/mailshake/models/list.rb +30 -0
  18. data/lib/mailshake/models/message.rb +8 -0
  19. data/lib/mailshake/models/open.rb +11 -0
  20. data/lib/mailshake/models/recipient.rb +8 -0
  21. data/lib/mailshake/models/reply.rb +11 -0
  22. data/lib/mailshake/models/sender.rb +8 -0
  23. data/lib/mailshake/models/sent_message.rb +11 -0
  24. data/lib/mailshake/models/user.rb +8 -0
  25. data/lib/mailshake/recipients.rb +8 -4
  26. data/lib/mailshake/senders.rb +2 -1
  27. data/lib/mailshake/team.rb +2 -1
  28. data/lib/mailshake.rb +21 -0
  29. data/spec/examples.txt +86 -60
  30. data/spec/mailshake/activity_spec.rb +4 -2
  31. data/spec/mailshake/campaigns_spec.rb +10 -4
  32. data/spec/mailshake/client_spec.rb +1 -0
  33. data/spec/mailshake/leads_spec.rb +5 -2
  34. data/spec/mailshake/models/base_model_spec.rb +118 -0
  35. data/spec/mailshake/models/list_spec.rb +103 -0
  36. data/spec/mailshake/push_spec.rb +1 -0
  37. data/spec/mailshake/recipients_spec.rb +7 -3
  38. data/spec/mailshake/senders_spec.rb +2 -1
  39. data/spec/mailshake/team_spec.rb +2 -1
  40. metadata +24 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dac51d36d81055f0ee4b47e3e0cbebef824b7b7b88168d2327869d8fa9ec6b8b
4
- data.tar.gz: e595b5f7e002badc7ab1f1035fcd95500e27686f074aba1cbbc6a72801cb9bad
3
+ metadata.gz: 173cfe60415683c55435fdd081c79a9824daa162b7dee69738ea74940326d36b
4
+ data.tar.gz: 6e7324f62f055eb0d7482c4e93cec793a033d291d5a3ecc0a6ff2557cfb9a779
5
5
  SHA512:
6
- metadata.gz: d98021363059d25659da7be92cd6e69fe0219e029b661f709fc8dc0a73a20d0412374c66bfa75b348a07c06070f0acf55d18e8bcbd5a7c5586e33c6b0b39650f
7
- data.tar.gz: e2d4bc194b916370ba0c0e059ecd06e74052eb662265e13ed1d8f5bce58862c14d8cbf28c7515fec5f20eb5f7c53075557c6a0d3a4df9bae08317c1693bdc4fb
6
+ metadata.gz: 7531e6410d2417febd4142731dab363e37d8fe9986c2bc06866153ff589a057fc63b8539ce0b8d17372f9c59864e51a303875cfb05eddf48ccc6e48af2415e86
7
+ data.tar.gz: ef2a7a8450785b67d28e1266135343418eca95af48f5674feed3e0779bc757a4ddb2f3506e188a95fafa752e597a665343949a6cf1a0c6a4a17bbb7eb5b3a260
data/README.md CHANGED
@@ -32,18 +32,29 @@ end
32
32
 
33
33
  ## Usage
34
34
 
35
+ All API responses return model objects with snake_case accessors and nested model hydration. Hash-style access (`result["key"]`) is still supported for backwards compatibility.
36
+
35
37
  ### Campaigns
36
38
 
37
39
  ```ruby
38
40
  campaigns = Mailshake::Campaigns.new
39
41
 
40
- campaigns.list(search: "onboarding", per_page: 10)
41
- campaigns.get(campaign_id: 1)
42
+ list = campaigns.list(search: "onboarding", per_page: 10)
43
+ list.each { |c| puts c.title }
44
+
45
+ campaign = campaigns.get(campaign_id: 1)
46
+ campaign.title # => "Q2 Outreach"
47
+ campaign.is_paused # => false
48
+ campaign.sender.email_address # => "sales@company.com"
49
+ campaign.messages.first.subject # => "Hey {{first}}"
50
+
42
51
  campaigns.create(title: "Q2 Outreach", sender_id: 5)
43
52
  campaigns.pause(campaign_id: 1)
44
53
  campaigns.unpause(campaign_id: 1)
45
- campaigns.export(campaign_ids: [1, 2], export_type: "csv", timezone: "US/Pacific")
46
- campaigns.export_status(status_id: 42)
54
+
55
+ export = campaigns.export(campaign_ids: [1, 2], export_type: "csv", timezone: "US/Pacific")
56
+ status = campaigns.export_status(status_id: export.check_status_id)
57
+ puts status.csv_download_url if status.is_finished
47
58
  ```
48
59
 
49
60
  ### Recipients
@@ -51,10 +62,16 @@ campaigns.export_status(status_id: 42)
51
62
  ```ruby
52
63
  recipients = Mailshake::Recipients.new
53
64
 
54
- recipients.add(campaign_id: 1, addresses: [{ emailAddress: "john@example.com" }])
55
- recipients.add_status(status_id: 42)
56
- recipients.list(campaign_id: 1, filter: "active", per_page: 25)
57
- recipients.get(recipient_id: 100)
65
+ result = recipients.add(campaign_id: 1, addresses: [{ emailAddress: "john@example.com" }])
66
+ status = recipients.add_status(status_id: result.check_status_id)
67
+
68
+ list = recipients.list(campaign_id: 1, filter: "active", per_page: 25)
69
+ list.each { |r| puts "#{r.full_name} <#{r.email_address}>" }
70
+
71
+ recipient = recipients.get(recipient_id: 100)
72
+ recipient.email_address # => "john@example.com"
73
+ recipient.is_paused # => false
74
+
58
75
  recipients.pause(campaign_id: 1, email_address: "john@example.com")
59
76
  recipients.unpause(campaign_id: 1, email_address: "john@example.com")
60
77
  recipients.unsubscribe(email_addresses: ["john@example.com"])
@@ -65,10 +82,18 @@ recipients.unsubscribe(email_addresses: ["john@example.com"])
65
82
  ```ruby
66
83
  activity = Mailshake::Activity.new
67
84
 
68
- activity.sent(campaign_id: 1, per_page: 50)
69
- activity.opens(campaign_id: 1, exclude_duplicates: true)
70
- activity.clicks(campaign_id: 1, match_url: "https://example.com")
71
- activity.replies(campaign_id: 1, reply_type: "reply")
85
+ sent = activity.sent(campaign_id: 1, per_page: 50)
86
+ sent.each { |msg| puts "#{msg.subject} -> #{msg.recipient.email_address}" }
87
+
88
+ opens = activity.opens(campaign_id: 1, exclude_duplicates: true)
89
+ opens.each { |o| puts "#{o.recipient.email_address} opened at #{o.action_date}" }
90
+
91
+ clicks = activity.clicks(campaign_id: 1, match_url: "https://example.com")
92
+ clicks.each { |c| puts "#{c.recipient.email_address} clicked #{c.link}" }
93
+
94
+ replies = activity.replies(campaign_id: 1, reply_type: "reply")
95
+ replies.each { |r| puts "#{r.recipient.email_address}: #{r.plain_text_body}" }
96
+
72
97
  activity.created_leads(campaign_id: 1, since: "2026-01-01")
73
98
  activity.lead_assignments(campaign_id: 1)
74
99
  activity.lead_status_changes(campaign_id: 1)
@@ -79,8 +104,17 @@ activity.lead_status_changes(campaign_id: 1)
79
104
  ```ruby
80
105
  leads = Mailshake::Leads.new
81
106
 
82
- leads.list(campaign_id: 1, status: "open")
83
- leads.get(lead_id: 42)
107
+ list = leads.list(campaign_id: 1, status: "open")
108
+ list.each do |lead|
109
+ puts "#{lead.recipient.email_address} - #{lead.status}"
110
+ puts " assigned to: #{lead.assigned_to&.full_name}"
111
+ end
112
+
113
+ lead = leads.get(lead_id: 42)
114
+ lead.status # => "open"
115
+ lead.recipient.email_address # => "john@example.com"
116
+ lead.campaign.title # => "Q2 Outreach"
117
+
84
118
  leads.create(campaign_id: 1, email_addresses: ["john@example.com"])
85
119
  leads.close(lead_id: 42, status: "won")
86
120
  leads.ignore(lead_id: 42)
@@ -92,7 +126,8 @@ leads.reopen(lead_id: 42)
92
126
  ```ruby
93
127
  team = Mailshake::Team.new
94
128
 
95
- team.list_members(search: "john", per_page: 10)
129
+ members = team.list_members(search: "john", per_page: 10)
130
+ members.each { |u| puts "#{u.full_name} <#{u.email_address}>" }
96
131
  ```
97
132
 
98
133
  ### Senders
@@ -100,7 +135,8 @@ team.list_members(search: "john", per_page: 10)
100
135
  ```ruby
101
136
  senders = Mailshake::Senders.new
102
137
 
103
- senders.list(search: "sales", per_page: 10)
138
+ list = senders.list(search: "sales", per_page: 10)
139
+ list.each { |s| puts "#{s.from_name} <#{s.email_address}>" }
104
140
  ```
105
141
 
106
142
  ### Push/Webhooks
@@ -116,16 +152,41 @@ push.delete(target_url: "https://example.com/webhook")
116
152
 
117
153
  ```ruby
118
154
  client = Mailshake.client
119
- client.me
155
+ user = client.me
156
+ user.full_name # => "Eduardo Souza"
157
+ user.email_address # => "eduardo@example.com"
158
+ user.is_team_admin # => true
120
159
  ```
121
160
 
161
+ ## Models
162
+
163
+ All responses are wrapped in model objects under `Mailshake::Models`. Models provide:
164
+
165
+ - **Snake_case accessors** - `campaign.is_paused` instead of `campaign["isPaused"]`
166
+ - **Nested model hydration** - `lead.recipient.email_address` returns a `Recipient` model
167
+ - **Backwards compatibility** - `campaign["title"]` still works
168
+ - **`to_h`** - convert back to the original hash
169
+
170
+ See the [full model reference](https://github.com/ESouza/mailshake-ruby/wiki/Models) in the wiki.
171
+
122
172
  ## Pagination
123
173
 
124
- Endpoints that return lists support pagination via `next_token` and `per_page`:
174
+ List endpoints return a `Models::List` object with `Enumerable` support:
125
175
 
126
176
  ```ruby
127
177
  result = campaigns.list(per_page: 10)
128
- next_page = campaigns.list(per_page: 10, next_token: result["nextToken"])
178
+ result.each { |c| puts c.title }
179
+ result.map(&:title)
180
+
181
+ # Paginate through all results
182
+ all = []
183
+ result = campaigns.list(per_page: 25)
184
+ all.concat(result.results)
185
+
186
+ while result.next_token
187
+ result = campaigns.list(per_page: 25, next_token: result.next_token)
188
+ all.concat(result.results)
189
+ end
129
190
  ```
130
191
 
131
192
  ## Error Handling
@@ -3,7 +3,7 @@
3
3
  module Mailshake
4
4
  class Activity < Base
5
5
  def sent(message_type: nil, campaign_message_type: nil, campaign_id: nil, recipient_email_address: nil, exclude_body: nil, next_token: nil, per_page: nil)
6
- client.get("/activity/sent", camelize_params(
6
+ response = client.get("/activity/sent", camelize_params(
7
7
  message_type: message_type,
8
8
  campaign_message_type: campaign_message_type,
9
9
  campaign_id: campaign_id,
@@ -12,10 +12,11 @@ module Mailshake
12
12
  next_token: next_token,
13
13
  per_page: per_page
14
14
  ))
15
+ Models::List.new(response, Models::SentMessage)
15
16
  end
16
17
 
17
18
  def opens(campaign_id: nil, exclude_duplicates: nil, recipient_email_address: nil, next_token: nil, per_page: nil, since: nil)
18
- client.get("/activity/opens", camelize_params(
19
+ response = client.get("/activity/opens", camelize_params(
19
20
  campaign_id: campaign_id,
20
21
  exclude_duplicates: exclude_duplicates,
21
22
  recipient_email_address: recipient_email_address,
@@ -23,10 +24,11 @@ module Mailshake
23
24
  per_page: per_page,
24
25
  since: since
25
26
  ))
27
+ Models::List.new(response, Models::Open)
26
28
  end
27
29
 
28
30
  def clicks(campaign_id: nil, exclude_duplicates: nil, match_url: nil, recipient_email_address: nil, next_token: nil, per_page: nil, since: nil)
29
- client.get("/activity/clicks", camelize_params(
31
+ response = client.get("/activity/clicks", camelize_params(
30
32
  campaign_id: campaign_id,
31
33
  exclude_duplicates: exclude_duplicates,
32
34
  match_url: match_url,
@@ -35,20 +37,22 @@ module Mailshake
35
37
  per_page: per_page,
36
38
  since: since
37
39
  ))
40
+ Models::List.new(response, Models::Click)
38
41
  end
39
42
 
40
43
  def replies(reply_type: nil, campaign_id: nil, recipient_email_address: nil, next_token: nil, per_page: nil)
41
- client.get("/activity/replies", camelize_params(
44
+ response = client.get("/activity/replies", camelize_params(
42
45
  reply_type: reply_type,
43
46
  campaign_id: campaign_id,
44
47
  recipient_email_address: recipient_email_address,
45
48
  next_token: next_token,
46
49
  per_page: per_page
47
50
  ))
51
+ Models::List.new(response, Models::Reply)
48
52
  end
49
53
 
50
54
  def created_leads(campaign_id: nil, recipient_email_address: nil, assigned_to_email_address: nil, next_token: nil, per_page: nil, since: nil)
51
- client.get("/activity/created-leads", camelize_params(
55
+ response = client.get("/activity/created-leads", camelize_params(
52
56
  campaign_id: campaign_id,
53
57
  recipient_email_address: recipient_email_address,
54
58
  assigned_to_email_address: assigned_to_email_address,
@@ -56,19 +60,21 @@ module Mailshake
56
60
  per_page: per_page,
57
61
  since: since
58
62
  ))
63
+ Models::List.new(response, Models::Lead)
59
64
  end
60
65
 
61
66
  def lead_assignments(campaign_id: nil, next_token: nil, per_page: nil, since: nil)
62
- client.get("/activity/lead-assignments", camelize_params(
67
+ response = client.get("/activity/lead-assignments", camelize_params(
63
68
  campaign_id: campaign_id,
64
69
  next_token: next_token,
65
70
  per_page: per_page,
66
71
  since: since
67
72
  ))
73
+ Models::List.new(response, Models::Lead)
68
74
  end
69
75
 
70
76
  def lead_status_changes(campaign_id: nil, recipient_email_address: nil, assigned_to_email_address: nil, next_token: nil, per_page: nil, since: nil)
71
- client.get("/activity/lead-status-changes", camelize_params(
77
+ response = client.get("/activity/lead-status-changes", camelize_params(
72
78
  campaign_id: campaign_id,
73
79
  recipient_email_address: recipient_email_address,
74
80
  assigned_to_email_address: assigned_to_email_address,
@@ -76,6 +82,7 @@ module Mailshake
76
82
  per_page: per_page,
77
83
  since: since
78
84
  ))
85
+ Models::List.new(response, Models::LeadStatus)
79
86
  end
80
87
  end
81
88
  end
@@ -3,15 +3,18 @@
3
3
  module Mailshake
4
4
  class Campaigns < Base
5
5
  def list(search: nil, next_token: nil, per_page: nil)
6
- client.get("/campaigns/list", camelize_params(search: search, next_token: next_token, per_page: per_page))
6
+ response = client.get("/campaigns/list", camelize_params(search: search, next_token: next_token, per_page: per_page))
7
+ Models::List.new(response, Models::Campaign)
7
8
  end
8
9
 
9
10
  def get(campaign_id:)
10
- client.get("/campaigns/get", camelize_params(campaign_id: campaign_id))
11
+ response = client.get("/campaigns/get", camelize_params(campaign_id: campaign_id))
12
+ Models::Campaign.new(response)
11
13
  end
12
14
 
13
15
  def create(title:, sender_id: nil)
14
- client.post("/campaigns/create", camelize_params(title: title, sender_id: sender_id))
16
+ response = client.post("/campaigns/create", camelize_params(title: title, sender_id: sender_id))
17
+ Models::Campaign.new(response)
15
18
  end
16
19
 
17
20
  def pause(campaign_id:)
@@ -23,11 +26,13 @@ module Mailshake
23
26
  end
24
27
 
25
28
  def export(campaign_ids: nil, export_type: nil, timezone: nil)
26
- client.post("/campaigns/export", camelize_params(campaign_ids: campaign_ids, export_type: export_type, timezone: timezone))
29
+ response = client.post("/campaigns/export", camelize_params(campaign_ids: campaign_ids, export_type: export_type, timezone: timezone))
30
+ Models::CampaignExportRequest.new(response)
27
31
  end
28
32
 
29
33
  def export_status(status_id:)
30
- client.get("/campaigns/export-status", camelize_params(status_id: status_id))
34
+ response = client.get("/campaigns/export-status", camelize_params(status_id: status_id))
35
+ Models::CampaignExport.new(response)
31
36
  end
32
37
  end
33
38
  end
@@ -22,7 +22,8 @@ module Mailshake
22
22
  end
23
23
 
24
24
  def me
25
- get("/me")
25
+ response = get("/me")
26
+ Models::User.new(response)
26
27
  end
27
28
 
28
29
  private
@@ -3,7 +3,7 @@
3
3
  module Mailshake
4
4
  class Leads < Base
5
5
  def list(campaign_id: nil, status: nil, assigned_to_email_address: nil, search: nil, next_token: nil, per_page: nil)
6
- client.get("/leads/list", camelize_params(
6
+ response = client.get("/leads/list", camelize_params(
7
7
  campaign_id: campaign_id,
8
8
  status: status,
9
9
  assigned_to_email_address: assigned_to_email_address,
@@ -11,23 +11,26 @@ module Mailshake
11
11
  next_token: next_token,
12
12
  per_page: per_page
13
13
  ))
14
+ Models::List.new(response, Models::Lead)
14
15
  end
15
16
 
16
17
  def get(lead_id: nil, recipient_id: nil, campaign_id: nil, email_address: nil)
17
- client.get("/leads/get", camelize_params(
18
+ response = client.get("/leads/get", camelize_params(
18
19
  lead_id: lead_id,
19
20
  recipient_id: recipient_id,
20
21
  campaign_id: campaign_id,
21
22
  email_address: email_address
22
23
  ))
24
+ Models::Lead.new(response)
23
25
  end
24
26
 
25
27
  def create(campaign_id:, email_addresses: nil, recipient_ids: nil)
26
- client.post("/leads/create", camelize_params(
28
+ response = client.post("/leads/create", camelize_params(
27
29
  campaign_id: campaign_id,
28
30
  email_addresses: email_addresses,
29
31
  recipient_ids: recipient_ids
30
32
  ))
33
+ Models::CreatedLeads.new(response)
31
34
  end
32
35
 
33
36
  def close(lead_id: nil, campaign_id: nil, email_address: nil, recipient_id: nil, status: nil)
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class AddRecipientsRequest < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class AddedRecipients < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class BaseModel
6
+ class << self
7
+ def has_one(field, klass)
8
+ nested_one[field.to_s] = klass
9
+ end
10
+
11
+ def has_many(field, klass)
12
+ nested_many[field.to_s] = klass
13
+ end
14
+
15
+ def nested_one
16
+ @nested_one ||= {}
17
+ end
18
+
19
+ def nested_many
20
+ @nested_many ||= {}
21
+ end
22
+ end
23
+
24
+ attr_reader :data
25
+
26
+ def initialize(data = {})
27
+ @data = data || {}
28
+ define_accessors
29
+ end
30
+
31
+ def [](key)
32
+ @data[key]
33
+ end
34
+
35
+ def to_h
36
+ @data
37
+ end
38
+
39
+ def respond_to_missing?(method_name, include_private = false)
40
+ @accessors&.key?(method_name.to_s) || super
41
+ end
42
+
43
+ private
44
+
45
+ def define_accessors
46
+ @accessors = {}
47
+ @data.each do |key, value|
48
+ snake_key = underscore(key.to_s)
49
+ hydrated = hydrate(snake_key, value)
50
+ @accessors[snake_key] = hydrated
51
+
52
+ define_singleton_method(snake_key) { @accessors[snake_key] }
53
+ end
54
+ end
55
+
56
+ def hydrate(snake_key, value)
57
+ one_klass = self.class.nested_one[snake_key]
58
+ many_klass = self.class.nested_many[snake_key]
59
+
60
+ if one_klass && value.is_a?(Hash)
61
+ one_klass.new(value)
62
+ elsif many_klass && value.is_a?(Array)
63
+ value.map { |item| item.is_a?(Hash) ? many_klass.new(item) : item }
64
+ else
65
+ value
66
+ end
67
+ end
68
+
69
+ def underscore(camel_cased_word)
70
+ word = camel_cased_word.to_s.dup
71
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
72
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
73
+ word.tr!("-", "_")
74
+ word.downcase!
75
+ word
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class Campaign < BaseModel
6
+ has_one :sender, Sender
7
+ has_many :messages, Message
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class CampaignExport < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class CampaignExportRequest < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class Click < BaseModel
6
+ has_one :recipient, Recipient
7
+ has_one :campaign, Campaign
8
+ has_one :parent, SentMessage
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class CreatedLeads < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class Lead < BaseModel
6
+ has_one :recipient, Recipient
7
+ has_one :campaign, Campaign
8
+ has_one :assigned_to, User
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class LeadStatus < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class List
6
+ include Enumerable
7
+
8
+ attr_reader :results, :next_token, :data
9
+
10
+ def initialize(data, model_class)
11
+ @data = data || {}
12
+ raw_results = @data["results"] || []
13
+ @results = raw_results.map { |item| item.is_a?(Hash) ? model_class.new(item) : item }
14
+ @next_token = @data["nextToken"]
15
+ end
16
+
17
+ def each(&block)
18
+ @results.each(&block)
19
+ end
20
+
21
+ def [](key)
22
+ @data[key]
23
+ end
24
+
25
+ def to_h
26
+ @data
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class Message < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class Open < BaseModel
6
+ has_one :recipient, Recipient
7
+ has_one :campaign, Campaign
8
+ has_one :parent, SentMessage
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class Recipient < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class Reply < BaseModel
6
+ has_one :recipient, Recipient
7
+ has_one :campaign, Campaign
8
+ has_one :parent, SentMessage
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class Sender < BaseModel
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class SentMessage < BaseModel
6
+ has_one :recipient, Recipient
7
+ has_one :campaign, Campaign
8
+ has_one :message, Message
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailshake
4
+ module Models
5
+ class User < BaseModel
6
+ end
7
+ end
8
+ end