├── .rspec ├── .env.example ├── renovate.json ├── lib ├── mailerlite-ruby.rb ├── mailerlite │ ├── version.rb │ ├── timezones │ │ └── timezones.rb │ ├── batch │ │ └── batch.rb │ ├── client.rb │ ├── fields │ │ └── fields.rb │ ├── webhooks │ │ └── webhooks.rb │ ├── segments │ │ └── segments.rb │ ├── forms │ │ └── forms.rb │ ├── automations │ │ └── automations.rb │ ├── groups │ │ └── groups.rb │ ├── subscribers │ │ └── subscribers.rb │ └── campaigns │ │ └── campaigns.rb └── mailerlite.rb ├── Gemfile ├── bin ├── setup └── console ├── Rakefile ├── CHANGELOG.md ├── .github └── workflows │ ├── main.yml │ └── publish_gem.yml ├── .rubocop.yml ├── spec ├── timezones_rspec.rb ├── batches_rspec.rb ├── automations_rspec.rb ├── fields_rspec.rb ├── segments_rspec.rb ├── forms_rspec.rb ├── webhooks_rspec.rb ├── groups_rspec.rb ├── subscribers_rspec.rb ├── spec_helper.rb └── campaigns_rspec.rb ├── LICENSE.txt ├── fixtures ├── subscribers │ ├── delete.yml │ ├── fetch_count.yml │ ├── create.yml │ ├── update.yml │ ├── forget.yml │ ├── get.yml │ └── fetch.yml ├── fields │ ├── delete.yml │ ├── update.yml │ ├── create.yml │ └── get.yml ├── forms │ ├── delete.yml │ ├── fetch_subscribers.yml │ ├── fetch.yml │ ├── update.yml │ └── list.yml ├── groups │ ├── delete.yml │ ├── unassign_subscriber.yml │ ├── create.yml │ ├── update.yml │ ├── assign_subscriber.yml │ ├── get_subscribers.yml │ └── get.yml ├── segments │ ├── delete.yml │ ├── update.yml │ ├── list.yml │ └── get_subscribers.yml ├── webhooks │ ├── delete.yml │ ├── get.yml │ ├── update.yml │ ├── create.yml │ └── list.yml ├── campaigns │ ├── delete.yml │ ├── activity.yml │ ├── fetch.yml │ ├── create.yml │ ├── languages.yml │ ├── get.yml │ ├── schedule.yml │ └── update.yml ├── batch │ └── request.yml └── automations │ ├── fetch.yml │ ├── get_subscriber_activity.yml │ └── get.yml ├── .gitignore └── mailerlite-ruby.gemspec /.rspec: -------------------------------------------------------------------------------- 1 | --require spec_helper 2 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | MAILERLITE_API_TOKEN="superlongkey" -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /lib/mailerlite-ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'mailerlite' 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/mailerlite/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | VERSION = '1.0.5' 5 | end 6 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'rubocop/rake_task' 5 | 6 | RuboCop::RakeTask.new 7 | 8 | task default: :rubocop 9 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'bundler/setup' 5 | require_relative '../lib/mailerlite/version' 6 | 7 | require 'irb' 8 | IRB.start(__FILE__) 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.5] - 2024-03-12 2 | - Update constant name 3 | 4 | ## [1.0.4] - 2023-11-20 5 | - Update subscribers update 6 | - Add forget subscriber method 7 | 8 | ## [1.0.3] - 2023-06-02 9 | - Documentation update 10 | - mailerlite.rb missing version 11 | 12 | ## [1.0.2] - 2023-03-22 13 | - Gemfile.lock removed 14 | 15 | ## [1.0.1] - 2023-03-22 16 | - Version update 17 | 18 | ## [1.0.0] - 2023-03-06 19 | - Initial release -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Ruby 2 | 3 | on: [push,pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | 11 | - name: Set up Ruby 12 | uses: ruby/setup-ruby@v1 13 | with: 14 | ruby-version: 3.0 15 | 16 | - name: Install Bundler 17 | run: gem install bundler -v 2.4.22 18 | 19 | - name: Install dependencies 20 | run: bundle _2.4.22_ install 21 | 22 | - name: Run tests 23 | run: export MAILERLITE_API_TOKEN=dummy_token && bundle exec rspec spec/*rspec.rb 24 | -------------------------------------------------------------------------------- /lib/mailerlite.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'mailerlite/client' 4 | require_relative 'mailerlite/version' 5 | require_relative 'mailerlite/subscribers/subscribers' 6 | require_relative 'mailerlite/campaigns/campaigns' 7 | require_relative 'mailerlite/forms/forms' 8 | require_relative 'mailerlite/groups/groups' 9 | require_relative 'mailerlite/segments/segments' 10 | require_relative 'mailerlite/fields/fields' 11 | require_relative 'mailerlite/automations/automations' 12 | require_relative 'mailerlite/webhooks/webhooks' 13 | require_relative 'mailerlite/batch/batch' 14 | require_relative 'mailerlite/timezones/timezones' 15 | -------------------------------------------------------------------------------- /lib/mailerlite/timezones/timezones.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Timezones from MailerLite API. 5 | class Timezones 6 | attr_reader :client 7 | 8 | # Inits the `Timezones` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of Timezones 16 | # 17 | # @return [HTTP::Response] the response from the API 18 | def list 19 | client.http.get("#{MAILERLITE_API_URL}/timezones") 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | TargetRubyVersion: 2.5 3 | SuggestExtensions: false 4 | NewCops: enable 5 | 6 | Style/StringLiterals: 7 | Enabled: true 8 | 9 | Style/StringLiteralsInInterpolation: 10 | Enabled: true 11 | EnforcedStyle: double_quotes 12 | 13 | Layout/LineLength: 14 | Enabled: false 15 | 16 | Metrics/ParameterLists: 17 | Enabled: false 18 | Metrics/MethodLength: 19 | Enabled: false 20 | 21 | Metrics/AbcSize: 22 | Enabled: false 23 | 24 | Naming/FileName: 25 | Enabled: false 26 | 27 | Metrics/BlockLength: 28 | AllowedMethods: ['describe', 'context'] 29 | 30 | Metrics/CyclomaticComplexity: 31 | Max: 16 32 | Metrics/PerceivedComplexity: 33 | Max: 16 34 | Metrics/ClassLength: 35 | Max: 150 36 | 37 | -------------------------------------------------------------------------------- /.github/workflows/publish_gem.yml: -------------------------------------------------------------------------------- 1 | name: Publish Gem 2 | 3 | on: 4 | push: 5 | tags: 6 | - v* 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Set up Ruby 15 | uses: actions/setup-ruby@v1 16 | with: 17 | ruby-version: 3.0 18 | 19 | - name: Install Bundler 20 | run: gem install bundler -v 2.4.22 21 | 22 | - name: Install dependencies 23 | run: bundle _2.4.22_ install 24 | 25 | - name: Release Gem 26 | if: contains(github.ref, 'refs/tags/v') 27 | uses: cadwallion/publish-rubygems-action@master 28 | env: 29 | GITHUB_TOKEN: ${{secrets.GITHUBTOKEN}} 30 | RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}} 31 | RELEASE_COMMAND: rake release 32 | 33 | -------------------------------------------------------------------------------- /lib/mailerlite/batch/batch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Batch from MailerLite API. 5 | class Batch 6 | attr_reader :client 7 | 8 | # Inits the `Batch` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Create a Batch Request 16 | # 17 | # @param requests [Array] Array of objects containing required method and path properties and optional body 18 | # @return [HTTP::Response] the response from the API 19 | def request(requests:) 20 | params = { requests: requests } 21 | client.http.post("#{MAILERLITE_API_URL}/batch", body: params.to_json) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/timezones_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Timezones` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Timezones` class 21 | RSpec.describe MailerLite::Timezones do 22 | let(:client) { MailerLite::Client.new } 23 | let(:timezones) { described_class.new(client: client) } 24 | 25 | describe '#list' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'lists all Timezones' do 28 | VCR.use_cassette('timezones/list') do 29 | response = timezones.list 30 | body = JSON.parse(response.body) 31 | expect(response.status).to eq 200 32 | expect(body['data']).to be_an Array 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Nikola Milojević 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /spec/batches_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Batch` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Batch` class 21 | RSpec.describe MailerLite::Batch do 22 | let(:client) { MailerLite::Client.new } 23 | let(:batch) { described_class.new(client: client) } 24 | 25 | describe '#request' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'executes a batch request' do 28 | VCR.use_cassette('batch/request') do 29 | response = batch.request( 30 | requests: [ 31 | { method: 'GET', path: 'api/subscribers/list' }, 32 | { method: 'GET', path: 'api/campaigns/list' } 33 | ] 34 | ) 35 | body = JSON.parse(response.body) 36 | expect(response.status).to eq 200 37 | expect(body['responses']).to be_an Array 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /fixtures/subscribers/delete.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://connect.mailerlite.com/api/subscribers/73871649530709291 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 204 25 | message: No Content 26 | headers: 27 | Date: 28 | - Wed, 07 Dec 2022 22:09:47 GMT 29 | Connection: 30 | - close 31 | Cache-Control: 32 | - no-cache, private 33 | X-Ratelimit-Limit: 34 | - '120' 35 | X-Ratelimit-Remaining: 36 | - '114' 37 | Access-Control-Allow-Origin: 38 | - "*" 39 | Strict-Transport-Security: 40 | - max-age=15724800; includeSubDomains 41 | Cf-Cache-Status: 42 | - DYNAMIC 43 | Server: 44 | - cloudflare 45 | Cf-Ray: 46 | - 7760966ffb87de4b-MCT 47 | body: 48 | encoding: ASCII-8BIT 49 | string: '' 50 | recorded_at: Wed, 07 Dec 2022 22:09:47 GMT 51 | recorded_with: VCR 6.1.0 52 | -------------------------------------------------------------------------------- /fixtures/fields/delete.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://connect.mailerlite.com/api/fields/91115 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 204 25 | message: No Content 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 22:09:50 GMT 29 | Connection: 30 | - close 31 | Cache-Control: 32 | - no-cache, private 33 | X-Locale: 34 | - en 35 | X-Ratelimit-Limit: 36 | - '120' 37 | X-Ratelimit-Remaining: 38 | - '119' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Strict-Transport-Security: 42 | - max-age=15724800; includeSubDomains 43 | Cf-Cache-Status: 44 | - DYNAMIC 45 | Server: 46 | - cloudflare 47 | Cf-Ray: 48 | - 77d3f1bfaf84d1f8-MCT 49 | body: 50 | encoding: ASCII-8BIT 51 | string: '' 52 | recorded_at: Wed, 21 Dec 2022 22:09:48 GMT 53 | recorded_with: VCR 6.1.0 54 | -------------------------------------------------------------------------------- /fixtures/forms/delete.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://connect.mailerlite.com/api/forms/75016692854425001 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 204 25 | message: No Content 26 | headers: 27 | Date: 28 | - Tue, 20 Dec 2022 13:20:22 GMT 29 | Connection: 30 | - close 31 | Cache-Control: 32 | - no-cache, private 33 | X-Locale: 34 | - en 35 | X-Ratelimit-Limit: 36 | - '120' 37 | X-Ratelimit-Remaining: 38 | - '118' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Strict-Transport-Security: 42 | - max-age=15724800; includeSubDomains 43 | Cf-Cache-Status: 44 | - DYNAMIC 45 | Server: 46 | - cloudflare 47 | Cf-Ray: 48 | - 77c8acc95d46d1e0-MCT 49 | body: 50 | encoding: ASCII-8BIT 51 | string: '' 52 | recorded_at: Tue, 20 Dec 2022 13:20:22 GMT 53 | recorded_with: VCR 6.1.0 54 | -------------------------------------------------------------------------------- /fixtures/groups/delete.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://connect.mailerlite.com/api/groups/75138589423306653 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 204 25 | message: No Content 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:24:28 GMT 29 | Connection: 30 | - close 31 | Cache-Control: 32 | - no-cache, private 33 | X-Locale: 34 | - en 35 | X-Ratelimit-Limit: 36 | - '120' 37 | X-Ratelimit-Remaining: 38 | - '114' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Strict-Transport-Security: 42 | - max-age=15724800; includeSubDomains 43 | Cf-Cache-Status: 44 | - DYNAMIC 45 | Server: 46 | - cloudflare 47 | Cf-Ray: 48 | - 77d3af4cafa1de53-MCT 49 | body: 50 | encoding: ASCII-8BIT 51 | string: '' 52 | recorded_at: Wed, 21 Dec 2022 21:24:26 GMT 53 | recorded_with: VCR 6.1.0 54 | -------------------------------------------------------------------------------- /fixtures/segments/delete.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://connect.mailerlite.com/api/segments/75140256628737109 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 204 25 | message: No Content 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:54:32 GMT 29 | Connection: 30 | - close 31 | Cache-Control: 32 | - no-cache, private 33 | X-Locale: 34 | - en 35 | X-Ratelimit-Limit: 36 | - '120' 37 | X-Ratelimit-Remaining: 38 | - '118' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Strict-Transport-Security: 42 | - max-age=15724800; includeSubDomains 43 | Cf-Cache-Status: 44 | - DYNAMIC 45 | Server: 46 | - cloudflare 47 | Cf-Ray: 48 | - 77d3db56af89de53-MCT 49 | body: 50 | encoding: ASCII-8BIT 51 | string: '' 52 | recorded_at: Wed, 21 Dec 2022 21:54:29 GMT 53 | recorded_with: VCR 6.1.0 54 | -------------------------------------------------------------------------------- /fixtures/webhooks/delete.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://connect.mailerlite.com/api/webhooks/75321640600209302 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 204 25 | message: No Content 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 21:52:46 GMT 29 | Connection: 30 | - close 31 | Cache-Control: 32 | - no-cache, private 33 | X-Locale: 34 | - en 35 | X-Ratelimit-Limit: 36 | - '120' 37 | X-Ratelimit-Remaining: 38 | - '119' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Strict-Transport-Security: 42 | - max-age=15724800; includeSubDomains 43 | Cf-Cache-Status: 44 | - DYNAMIC 45 | Server: 46 | - cloudflare 47 | Cf-Ray: 48 | - 77e453821df6de47-MCT 49 | body: 50 | encoding: ASCII-8BIT 51 | string: '' 52 | recorded_at: Fri, 23 Dec 2022 21:52:45 GMT 53 | recorded_with: VCR 6.1.0 54 | -------------------------------------------------------------------------------- /fixtures/campaigns/delete.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://connect.mailerlite.com/api/campaigns/74917804992628332 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 204 25 | message: No Content 26 | headers: 27 | Date: 28 | - Mon, 19 Dec 2022 11:01:04 GMT 29 | Connection: 30 | - close 31 | Cache-Control: 32 | - no-cache, private 33 | X-Locale: 34 | - en 35 | X-Ratelimit-Limit: 36 | - '120' 37 | X-Ratelimit-Remaining: 38 | - '118' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Strict-Transport-Security: 42 | - max-age=15724800; includeSubDomains 43 | Cf-Cache-Status: 44 | - DYNAMIC 45 | Server: 46 | - cloudflare 47 | Cf-Ray: 48 | - 77bfa35c0ac0d1ec-MCT 49 | body: 50 | encoding: ASCII-8BIT 51 | string: '' 52 | recorded_at: Mon, 19 Dec 2022 11:01:04 GMT 53 | recorded_with: VCR 6.1.0 54 | -------------------------------------------------------------------------------- /fixtures/groups/unassign_subscriber.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: https://connect.mailerlite.com/api/subscribers/75009808379414225/groups/75138557045376452 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 204 25 | message: No Content 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:43:06 GMT 29 | Connection: 30 | - close 31 | Cache-Control: 32 | - no-cache, private 33 | X-Locale: 34 | - en 35 | X-Ratelimit-Limit: 36 | - '120' 37 | X-Ratelimit-Remaining: 38 | - '118' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Strict-Transport-Security: 42 | - max-age=15724800; includeSubDomains 43 | Cf-Cache-Status: 44 | - DYNAMIC 45 | Server: 46 | - cloudflare 47 | Cf-Ray: 48 | - 77d3ca954a5ad1f0-MCT 49 | body: 50 | encoding: ASCII-8BIT 51 | string: '' 52 | recorded_at: Wed, 21 Dec 2022 21:43:03 GMT 53 | recorded_with: VCR 6.1.0 54 | -------------------------------------------------------------------------------- /fixtures/subscribers/fetch_count.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/subscribers/?limit=0 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 07 Dec 2022 22:09:47 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Ratelimit-Limit: 38 | - '120' 39 | X-Ratelimit-Remaining: 40 | - '115' 41 | Access-Control-Allow-Origin: 42 | - "*" 43 | Strict-Transport-Security: 44 | - max-age=15724800; includeSubDomains 45 | Cf-Cache-Status: 46 | - DYNAMIC 47 | Server: 48 | - cloudflare 49 | Cf-Ray: 50 | - 7760966d0aa9d1d4-MCT 51 | body: 52 | encoding: UTF-8 53 | string: '{"total":2}' 54 | recorded_at: Wed, 07 Dec 2022 22:09:47 GMT 55 | recorded_with: VCR 6.1.0 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .idea 3 | .DS_Store 4 | 5 | *.gem 6 | *.rbc 7 | /.config 8 | /coverage/ 9 | /InstalledFiles 10 | /pkg/ 11 | /spec/reports/ 12 | /spec/examples.txt 13 | /test/tmp/ 14 | /test/version_tmp/ 15 | /tmp/ 16 | 17 | # Used by dotenv library to load environment variables. 18 | # .env 19 | 20 | # Ignore Byebug command history file. 21 | .byebug_history 22 | 23 | ## Specific to RubyMotion: 24 | .dat* 25 | .repl_history 26 | build/ 27 | *.bridgesupport 28 | build-iPhoneOS/ 29 | build-iPhoneSimulator/ 30 | 31 | ## Specific to RubyMotion (use of CocoaPods): 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # vendor/Pods/ 38 | 39 | ## Documentation cache and generated files: 40 | /.yardoc/ 41 | /_yardoc/ 42 | /doc/ 43 | /rdoc/ 44 | 45 | ## Environment normalization: 46 | /.bundle/ 47 | /vendor/bundle 48 | /lib/bundler/man/ 49 | 50 | # for a library or gem, you might want to ignore these files since the code is 51 | # intended to run in multiple environments; otherwise, check them in: 52 | # Gemfile.lock 53 | # .ruby-version 54 | # .ruby-gemset 55 | 56 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 57 | .rvmrc 58 | 59 | # Used by RuboCop. Remote config files pulled in from inherit_from directive. 60 | # .rubocop-https?--* -------------------------------------------------------------------------------- /lib/mailerlite/client.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'http' 4 | 5 | MAILERLITE_API_URL = 'https://connect.mailerlite.com/api' 6 | 7 | # mailerlite-ruby is a gem that integrates all endpoints from MailerLite API 8 | module MailerLite 9 | class << self 10 | attr_accessor :api_token 11 | 12 | # Config method to allow passing API token through an initializer 13 | def configure 14 | yield self 15 | end 16 | end 17 | 18 | class Client 19 | attr_reader :api_token 20 | 21 | def initialize(api_token = nil) 22 | # Use passed token or fallback to global config, Rails credentials, or ENV 23 | @api_token = api_token || MailerLite.api_token || fetch_api_token 24 | end 25 | 26 | def fetch_api_token 27 | # Check for Rails credentials if Rails is defined 28 | if defined?(Rails) && Rails.application.credentials&.mailer_lite&[:api_token] 29 | Rails.application.credentials.mailer_lite[:api_token] 30 | else 31 | # Fall back to ENV variable 32 | ENV['MAILERLITE_API_TOKEN'] 33 | end 34 | end 35 | 36 | def headers 37 | { 38 | 'User-Agent' => "MailerLite-client-ruby/#{MailerLite::VERSION}", 39 | 'Accept' => 'application/json', 40 | 'Content-type' => 'application/json' 41 | } 42 | end 43 | 44 | def http 45 | raise 'API token is missing' unless @api_token 46 | 47 | HTTP 48 | .timeout(connect: 15, read: 30) 49 | .auth("Bearer #{@api_token}") 50 | .headers(headers) 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /fixtures/fields/update.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://connect.mailerlite.com/api/fields/91115 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"test_field2"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 22:08:34 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3efe54855de5b-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"91115","name":"test_field2","key":"test_field_name","type":"text","is_default":false,"used_in_automations":false}}' 56 | recorded_at: Wed, 21 Dec 2022 22:08:32 GMT 57 | recorded_with: VCR 6.1.0 58 | -------------------------------------------------------------------------------- /fixtures/fields/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/fields 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"test_field_name","type":"text"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 201 25 | message: Created 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 22:06:26 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3ecc359ccde4f-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"91115","name":"test_field_name","key":"test_field_name","type":"text","is_default":false,"used_in_automations":false}}' 56 | recorded_at: Wed, 21 Dec 2022 22:06:23 GMT 57 | recorded_with: VCR 6.1.0 58 | -------------------------------------------------------------------------------- /fixtures/segments/update.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://connect.mailerlite.com/api/segments/75140256628737109 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"test_segment2"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:53:09 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '116' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3d94c7d26de47-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75140256628737109","name":"test_segment2","total":2,"open_rate":{"float":0,"string":"0%"},"click_rate":{"float":0,"string":"0%"},"created_at":"2022-12-21 56 | 21:48:52"}}' 57 | recorded_at: Wed, 21 Dec 2022 21:53:06 GMT 58 | recorded_with: VCR 6.1.0 59 | -------------------------------------------------------------------------------- /fixtures/webhooks/get.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/webhooks/75321551702984317 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 21:51:22 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e45174ed1fd1f0-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75321551702984317","name":"test_webhook","url":"http:\/\/foobar.hook","events":["subscriber.created"],"enabled":true,"secret":"pv04URxAE4","created_at":"2022-12-23 56 | 21:50:29","updated_at":"2022-12-23 21:50:29"}}' 57 | recorded_at: Fri, 23 Dec 2022 21:51:21 GMT 58 | recorded_with: VCR 6.1.0 59 | -------------------------------------------------------------------------------- /fixtures/webhooks/update.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://connect.mailerlite.com/api/webhooks/75233700096247795 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"test_webhook2"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Thu, 22 Dec 2022 22:35:04 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '117' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77dc54153eb8d1d8-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75233700096247795","name":"test_webhook2","url":"http:\/\/foobar.hook","events":["subscriber.created"],"enabled":true,"secret":"Hym6hUN1bO","created_at":"2022-12-22 56 | 22:34:07","updated_at":"2022-12-22 22:35:04"}}' 57 | recorded_at: Thu, 22 Dec 2022 22:35:03 GMT 58 | recorded_with: VCR 6.1.0 59 | -------------------------------------------------------------------------------- /fixtures/webhooks/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/webhooks 6 | body: 7 | encoding: UTF-8 8 | string: '{"events":["subscriber.created"],"url":"http://foobar.hook","name":"test_webhook"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 201 25 | message: Created 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 21:51:54 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '117' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e45238dbecde53-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75321640600209302","name":"test_webhook","url":"http:\/\/foobar.hook","events":["subscriber.created"],"enabled":true,"secret":"HigkdhMVbp","created_at":"2022-12-23 56 | 21:51:54","updated_at":"2022-12-23 21:51:54"}}' 57 | recorded_at: Fri, 23 Dec 2022 21:51:53 GMT 58 | recorded_with: VCR 6.1.0 59 | -------------------------------------------------------------------------------- /fixtures/groups/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/groups 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"test_group2"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 201 25 | message: Created 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:22:22 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '117' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3ac3a893cd1e4-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75138589423306653","name":"test_group2","active_count":0,"sent_count":0,"opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-21 56 | 21:22:22"}}' 57 | recorded_at: Wed, 21 Dec 2022 21:22:20 GMT 58 | recorded_with: VCR 6.1.0 59 | -------------------------------------------------------------------------------- /fixtures/batch/request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/batch 6 | body: 7 | encoding: UTF-8 8 | string: '{"requests":[{"method":"GET","path":"api/subscribers/list"},{"method":"GET","path":"api/campaigns/list"}]}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 20:38:06 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '118' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e3e6206cc0de47-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"total":2,"successful":0,"failed":2,"responses":[{"code":404,"body":{"message":"No 56 | query results for model [App\\Models\\Subscriber\\Subscriber]."}},{"code":404,"body":{"message":"The 57 | route api\/campaigns\/list could not be found."}}]}' 58 | recorded_at: Fri, 23 Dec 2022 20:38:06 GMT 59 | recorded_with: VCR 6.1.0 60 | -------------------------------------------------------------------------------- /fixtures/groups/update.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://connect.mailerlite.com/api/groups/75138589423306653 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"test_group3"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:23:52 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '118' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3ae697e08d1d4-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75138589423306653","name":"test_group3","active_count":0,"sent_count":0,"opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-21 56 | 21:22:22"}}' 57 | recorded_at: Wed, 21 Dec 2022 21:23:49 GMT 58 | recorded_with: VCR 6.1.0 59 | -------------------------------------------------------------------------------- /fixtures/groups/assign_subscriber.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/subscribers/75009808379414225/groups/75138557045376452 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:42:06 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3c91e1fb8d1e4-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75138557045376452","name":"A test Group","active_count":0,"sent_count":0,"opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-21 56 | 21:21:52"}}' 57 | recorded_at: Wed, 21 Dec 2022 21:42:04 GMT 58 | recorded_with: VCR 6.1.0 59 | -------------------------------------------------------------------------------- /mailerlite-ruby.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'mailerlite/version' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = 'mailerlite-ruby' 9 | spec.version = MailerLite::VERSION 10 | spec.authors = ['Nikola Milojević', 'Ahsan Gondal'] 11 | spec.email = ['info@mailerlite.com'] 12 | 13 | spec.summary = "MailerLite's official Ruby SDK" 14 | spec.description = "MailerLite's official Ruby SDK. Interacts with all endpoints at MailerLite API." 15 | spec.homepage = 'https://www.MailerLite.com' 16 | spec.license = 'MIT' 17 | spec.required_ruby_version = '>= 2.5.0' 18 | 19 | spec.metadata['allowed_push_host'] = 'https://rubygems.org' 20 | 21 | spec.metadata['homepage_uri'] = spec.homepage 22 | spec.metadata['source_code_uri'] = 'https://github.com/mailerlite/mailerlite-ruby' 23 | spec.metadata['changelog_uri'] = 'https://github.com/mailerlite/mailerlite-ruby/blob/main/CHANGELOG.md' 24 | spec.metadata['rubygems_mfa_required'] = 'true' 25 | 26 | spec.files = `git ls-files -z`.split("\x0") 27 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 28 | spec.require_paths = ['lib'] 29 | 30 | spec.add_development_dependency 'bundler', '~> 2.4.1' 31 | spec.add_development_dependency 'rake', '~> 13.0' 32 | spec.add_development_dependency 'rubocop', '~> 1.7' 33 | spec.add_dependency 'http', '~> 5.0' 34 | spec.add_dependency 'json', '~> 2.5' 35 | spec.add_dependency 'uri', '~> 0.13.0' 36 | spec.add_development_dependency 'rspec' 37 | spec.add_development_dependency 'simplecov' 38 | spec.add_development_dependency 'vcr' 39 | spec.add_development_dependency 'webmock' 40 | spec.add_development_dependency 'yard' 41 | end 42 | -------------------------------------------------------------------------------- /fixtures/subscribers/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/subscribers 6 | body: 7 | encoding: UTF-8 8 | string: '{"email":"user@example.com"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 07 Dec 2022 22:09:46 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Ratelimit-Limit: 38 | - '120' 39 | X-Ratelimit-Remaining: 40 | - '117' 41 | Access-Control-Allow-Origin: 42 | - "*" 43 | Strict-Transport-Security: 44 | - max-age=15724800; includeSubDomains 45 | Cf-Cache-Status: 46 | - DYNAMIC 47 | Server: 48 | - cloudflare 49 | Cf-Ray: 50 | - 776096643ba4d1d0-MCT 51 | body: 52 | encoding: UTF-8 53 | string: '{"data":{"id":"73871649530709291","email":"user@example.com","status":"active","source":"api","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-07 54 | 21:44:54","unsubscribed_at":null,"created_at":"2022-12-07 21:44:54","updated_at":"2022-12-07 55 | 22:07:37","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null},"groups":[],"location":null,"opted_in_at":null,"optin_ip":null}}' 56 | recorded_at: Wed, 07 Dec 2022 22:09:46 GMT 57 | recorded_with: VCR 6.1.0 58 | -------------------------------------------------------------------------------- /fixtures/subscribers/update.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://connect.mailerlite.com/api/subscribers/98112484192290662 6 | body: 7 | encoding: ASCII-8BIT 8 | string: '{"email":"updated@email.com"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/1.0.3 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 01 Sep 2023 11:24:29 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Via: 48 | - Ingress 49 | Cf-Cache-Status: 50 | - DYNAMIC 51 | Server: 52 | - cloudflare 53 | Cf-Ray: 54 | - 7ffd25a40bf22118-HKG 55 | body: 56 | encoding: UTF-8 57 | string: '{"data":{"id":"98112484192290662","email":"updated@email.com","status":"active","source":"api","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2023-09-01 58 | 11:22:36","unsubscribed_at":null,"created_at":"2023-09-01 11:22:36","updated_at":"2023-09-01 59 | 11:24:29","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null,"github_handle":null},"groups":[],"location":null,"opted_in_at":null,"optin_ip":null}}' 60 | recorded_at: Fri, 01 Sep 2023 11:24:29 GMT 61 | recorded_with: VCR 6.2.0 62 | -------------------------------------------------------------------------------- /fixtures/forms/fetch_subscribers.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/forms/75231510415803781/subscribers 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Thu, 22 Dec 2022 21:59:58 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77dc20ab0ff9d1d8-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/forms\/75231510415803781\/subscribers?page=1","last":"https:\/\/connect.mailerlite.com\/api\/forms\/75231510415803781\/subscribers?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":null,"last_page":1,"links":[{"url":null,"label":"« 56 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/forms\/75231510415803781\/subscribers?page=1","label":"1","active":true},{"url":null,"label":"Next 57 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/forms\/75231510415803781\/subscribers","per_page":25,"to":null,"total":0}}' 58 | recorded_at: Thu, 22 Dec 2022 21:59:56 GMT 59 | recorded_with: VCR 6.1.0 60 | -------------------------------------------------------------------------------- /fixtures/segments/list.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/segments 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 21:16:48 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e41ecf8b15d1e4-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75230139503346765","name":"test_segment2","total":4,"open_rate":{"float":1,"string":"100%"},"click_rate":{"float":0,"string":"0%"},"created_at":"2022-12-22 56 | 21:37:31"}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/segments?page=1","last":"https:\/\/connect.mailerlite.com\/api\/segments?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 57 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/segments?page=1","label":"1","active":true},{"url":null,"label":"Next 58 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/segments","per_page":250,"to":1,"total":1}}' 59 | recorded_at: Fri, 23 Dec 2022 21:16:47 GMT 60 | recorded_with: VCR 6.1.0 61 | -------------------------------------------------------------------------------- /spec/automations_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Automations` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Automations` class 21 | RSpec.describe MailerLite::Automations do 22 | let(:client) { MailerLite::Client.new } 23 | let(:automations) { described_class.new(client: client) } 24 | 25 | describe '#get' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'gets all automation' do 28 | VCR.use_cassette('automations/get') do 29 | response = automations.get 30 | body = JSON.parse(response.body) 31 | expect(response.status).to eq 200 32 | expect(body['data']).to be_an Array 33 | end 34 | end 35 | end 36 | 37 | describe '#fetch' do 38 | # Use VCR to record and replay the HTTP request 39 | it 'fetchs all automation' do 40 | VCR.use_cassette('automations/fetch') do 41 | response = automations.fetch(75_040_845_299_975_641) 42 | body = JSON.parse(response.body) 43 | expect(response.status).to eq 200 44 | expect(Integer(body['data']['id'])).to be_an Integer 45 | end 46 | end 47 | end 48 | 49 | describe '#get_subscriber_activity' do 50 | # Use VCR to record and replay the HTTP request 51 | it 'get_subscriber_activitys all automation' do 52 | VCR.use_cassette('automations/get_subscriber_activity') do 53 | response = automations.get_subscriber_activity( 54 | automation_id: '75040845299975641', 55 | filter: { status: 'completed' } 56 | ) 57 | # body = JSON.parse(response.body) 58 | expect(response.status).to eq 200 59 | # expect(Integer(body['data']['id'])).to be_an Integer 60 | end 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /fixtures/subscribers/forget.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/subscribers/98121614828242796/forget 6 | body: 7 | encoding: ASCII-8BIT 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/1.0.3 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 01 Sep 2023 13:48:18 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '117' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Via: 48 | - Ingress 49 | Cf-Cache-Status: 50 | - DYNAMIC 51 | Server: 52 | - cloudflare 53 | Cf-Ray: 54 | - 7ffdf84ede2b1096-HKG 55 | body: 56 | encoding: UTF-8 57 | string: '{"data":{"id":"98121614828242796","email":"test@mail.com","status":"active","source":"api","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2023-09-01 58 | 13:47:44","unsubscribed_at":null,"created_at":"2023-09-01 13:47:43","updated_at":"2023-09-01 59 | 13:48:17","deleted_at":"2023-09-01 13:48:17","forget_at":"2023-10-01 13:48:17","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null,"github_handle":null},"groups":[],"location":null,"opted_in_at":null,"optin_ip":null},"message":"Subscriber 60 | data will be completely deleted and forgotten within 30 days."}' 61 | recorded_at: Fri, 01 Sep 2023 13:48:18 GMT 62 | recorded_with: VCR 6.2.0 63 | -------------------------------------------------------------------------------- /spec/fields_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Fields` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Fields` class 21 | RSpec.describe MailerLite::Fields do 22 | let(:client) { MailerLite::Client.new } 23 | let(:fields) { described_class.new(client: client) } 24 | 25 | describe '#get' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'returns a list of Fields' do 28 | VCR.use_cassette('fields/get') do 29 | response = fields.get 30 | body = JSON.parse(response.body) 31 | expect(response.status).to eq 200 32 | expect(body['data']).to be_an Array 33 | end 34 | end 35 | end 36 | 37 | describe '#create' do 38 | # Use VCR to record and replay the HTTP request 39 | it 'creates a field' do 40 | VCR.use_cassette('fields/create') do 41 | response = fields.create(type: 'text', name: 'test_field_name') 42 | body = JSON.parse(response.body) 43 | expect(response.status).to eq 201 44 | expect(Integer(body['data']['id'])).to be_an Integer 45 | end 46 | end 47 | end 48 | 49 | describe '#update' do 50 | # Use VCR to record and replay the HTTP request 51 | it 'updates a field' do 52 | VCR.use_cassette('fields/update') do 53 | response = fields.update(field_id: 91_115, name: 'test_field2') 54 | body = JSON.parse(response.body) 55 | expect(response.status).to eq 200 56 | expect(Integer(body['data']['id'])).to be_an Integer 57 | end 58 | end 59 | end 60 | 61 | describe '#delete' do 62 | # Use VCR to record and replay the HTTP request 63 | it 'deletes a field' do 64 | VCR.use_cassette('fields/delete') do 65 | response = fields.delete(91_115) 66 | expect(response.status).to eq 204 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /spec/segments_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Segments` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Segments` class 21 | RSpec.describe MailerLite::Segments do 22 | let(:client) { MailerLite::Client.new } 23 | let(:segments) { described_class.new(client: client) } 24 | 25 | describe '#list' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'returns a list of Segments' do 28 | VCR.use_cassette('segments/list') do 29 | response = segments.list 30 | body = JSON.parse(response.body) 31 | expect(response.status).to eq 200 32 | expect(body['data']).to be_an Array 33 | end 34 | end 35 | end 36 | 37 | describe '#update' do 38 | # Use VCR to record and replay the HTTP request 39 | it 'updates a segment' do 40 | VCR.use_cassette('segments/update') do 41 | response = segments.update(segment_id: 75_140_256_628_737_109, name: 'test_segment2') 42 | body = JSON.parse(response.body) 43 | expect(response.status).to eq 200 44 | expect(Integer(body['data']['id'])).to be_an Integer 45 | end 46 | end 47 | end 48 | 49 | describe '#get_subscribers' do 50 | # Use VCR to record and replay the HTTP request 51 | it 'get_subscribers for a segment' do 52 | VCR.use_cassette('segments/get_subscribers') do 53 | response = segments.get_subscribers(segment_id: 75_140_256_628_737_109) 54 | body = JSON.parse(response.body) 55 | expect(response.status).to eq 200 56 | expect(body['data']).to be_an Array 57 | end 58 | end 59 | end 60 | 61 | describe '#delete' do 62 | # Use VCR to record and replay the HTTP request 63 | it 'deletes a segment' do 64 | VCR.use_cassette('segments/delete') do 65 | response = segments.delete(75_140_256_628_737_109) 66 | expect(response.status).to eq 204 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /fixtures/webhooks/list.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/webhooks 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 21:52:21 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '116' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e452e6ae74de4f-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75321640600209302","name":"test_webhook","url":"http:\/\/foobar.hook","events":["subscriber.created"],"enabled":true,"secret":"HigkdhMVbp","created_at":"2022-12-23 56 | 21:51:54","updated_at":"2022-12-23 21:51:54"},{"id":"75321551702984317","name":"test_webhook","url":"http:\/\/foobar.hook","events":["subscriber.created"],"enabled":true,"secret":"pv04URxAE4","created_at":"2022-12-23 57 | 21:50:29","updated_at":"2022-12-23 21:50:29"}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/webhooks?page=1","last":"https:\/\/connect.mailerlite.com\/api\/webhooks?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 58 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/webhooks?page=1","label":"1","active":true},{"url":null,"label":"Next 59 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/webhooks","per_page":50,"to":2,"total":2}}' 60 | recorded_at: Fri, 23 Dec 2022 21:52:20 GMT 61 | recorded_with: VCR 6.1.0 62 | -------------------------------------------------------------------------------- /lib/mailerlite/fields/fields.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Fields from MailerLite API. 5 | class Fields 6 | attr_reader :client 7 | 8 | # Inits the `Fields` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of Fields that match the specified filter criteria. 16 | # 17 | # @param filter [:keyword, :type] Returns partial matches for fields 18 | # @param limit [Integer] the maximum number of Fields to return 19 | # @param page [Integer] the page number of the results to return 20 | # @return [HTTP::Response] the response from the API 21 | def get(limit: nil, page: nil, filter: {}, sort: nil) 22 | params = {} 23 | params['filter[keyword]'] = filter[:keyword] if filter.key?(:keyword) 24 | params['filter[type]'] = filter[:type] if filter.key?(:type) 25 | params['sort'] = sort if sort 26 | params['limit'] = limit if limit 27 | params['page'] = page if page 28 | uri = URI("#{MAILERLITE_API_URL}/fields") 29 | uri.query = URI.encode_www_form(params.compact) 30 | client.http.get(uri) 31 | end 32 | 33 | # Update the specified Field 34 | # 35 | # @param name [String] the name of the field to create 36 | # @param type [String] the type, can be text, number or date 37 | # @return [HTTP::Response] the response from the API 38 | def create(type:, name:) 39 | params = { 'name' => name, 'type' => type } 40 | client.http.post("#{MAILERLITE_API_URL}/fields", json: params.compact) 41 | end 42 | 43 | # Update the specified Field 44 | # 45 | # @param field_id [Integer] the field_id to update 46 | # @param name [String] the name to update 47 | # @return [HTTP::Response] the response from the API 48 | def update(field_id:, name:) 49 | params = { 'name' => name } 50 | client.http.put("#{MAILERLITE_API_URL}/fields/#{field_id}", json: params.compact) 51 | end 52 | 53 | # Deletes the specified Field. 54 | # 55 | # @param field_id [String] the ID of the Field to delete 56 | # @return [HTTP::Response] the response from the API 57 | def delete(field_id) 58 | client.http.delete("#{MAILERLITE_API_URL}/fields/#{field_id}") 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /fixtures/segments/get_subscribers.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/segments/75140256628737109/subscribers 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:53:49 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3da492d7bde57-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75009808379414225","email":"second@email.com","status":"active","source":"import","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-20 56 | 11:15:27","unsubscribed_at":null,"created_at":"2022-12-20 11:15:27","updated_at":"2022-12-21 57 | 18:32:20","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null},"groups":[],"opted_in_at":null,"optin_ip":null},{"id":"75009808377317072","email":"first@email.com","status":"active","source":"import","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-20 58 | 11:15:27","unsubscribed_at":null,"created_at":"2022-12-20 11:15:27","updated_at":"2022-12-21 59 | 18:32:20","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null},"groups":[],"opted_in_at":null,"optin_ip":null}],"meta":{"total":2,"count":2,"last":75009808377317072}}' 60 | recorded_at: Wed, 21 Dec 2022 21:53:47 GMT 61 | recorded_with: VCR 6.1.0 62 | -------------------------------------------------------------------------------- /fixtures/subscribers/get.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/subscribers/second@email.com 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 21:05:09 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e40dbfed54d1cc-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75009808379414225","email":"second@email.com","status":"active","source":"import","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-20 56 | 11:15:27","unsubscribed_at":null,"created_at":"2022-12-20 11:15:27","updated_at":"2022-12-21 57 | 18:32:20","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":"Lajpcig","phone":null,"state":null,"z_i_p":null},"groups":[{"id":"75011449370445335","name":"My 58 | Group","active_count":4,"sent_count":3,"opens_count":3,"open_rate":{"float":1,"string":"100%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":2,"bounced_count":0,"junk_count":0,"created_at":"2022-12-20 59 | 11:41:32"},{"id":"75138838590129612","name":"SMmwGofyQP","active_count":1,"sent_count":1,"opens_count":1,"open_rate":{"float":1,"string":"100%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-21 60 | 21:26:20"}],"opted_in_at":null,"optin_ip":null}}' 61 | recorded_at: Fri, 23 Dec 2022 21:05:08 GMT 62 | recorded_with: VCR 6.1.0 63 | -------------------------------------------------------------------------------- /lib/mailerlite/webhooks/webhooks.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Webhooks from MailerLite API. 5 | class Webhooks 6 | attr_reader :client 7 | 8 | # Inits the `Webhooks` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of Webhooks 16 | # 17 | # @return [HTTP::Response] the response from the API 18 | def list 19 | client.http.get("#{MAILERLITE_API_URL}/webhooks") 20 | end 21 | 22 | # Returns the details of the specified webhooks 23 | # 24 | # @param webhook_id [String] the ID of the webhooks to fetch 25 | # @return [HTTP::Response] the response from the API 26 | def get(webhook_id) 27 | client.http.get("#{MAILERLITE_API_URL}/webhooks/#{webhook_id}") 28 | end 29 | 30 | # Create a Webhook 31 | # 32 | # @param name [String] the name of the Webhook to create 33 | # @param events [Array] the events, must one from the list of supported events 34 | # @param url [String] the events, can be text, number or date 35 | # @return [HTTP::Response] the response from the API 36 | def create(events:, url:, name: nil) 37 | params = { 'events' => events, 'url' => url } 38 | params['name'] = name if name 39 | client.http.post("#{MAILERLITE_API_URL}/webhooks", json: params.compact) 40 | end 41 | 42 | # Update the specified Webhook 43 | # 44 | # @param webhook_id [String] the ID of the Webhook to update 45 | # @param name [String] the name to update 46 | # @param events [Array] the events to update 47 | # @param url [String] the url to update 48 | # @param enabled [Boolean] the enabled to update 49 | # @return [HTTP::Response] the response from the API 50 | def update(webhook_id:, events: nil, name: nil, url: nil, enabled: nil) 51 | params = {} 52 | params['events'] = events if events 53 | params['name'] = name if name 54 | params['url'] = url if url 55 | params['enabled'] = enabled if enabled 56 | client.http.put("#{MAILERLITE_API_URL}/webhooks/#{webhook_id}", json: params.compact) 57 | end 58 | 59 | # Deletes the specified Webhook. 60 | # 61 | # @param webhook_id [String] the ID of the Webhook to delete 62 | # @return [HTTP::Response] the response from the API 63 | def delete(webhook_id) 64 | client.http.delete("#{MAILERLITE_API_URL}/webhooks/#{webhook_id}") 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /fixtures/groups/get_subscribers.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/groups/75011449370445335/subscribers 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:32:00 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3ba52be90de43-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75030636641911843","email":"igor@hrcek.rs","status":"active","source":"webform","sent":1,"opens_count":1,"clicks_count":0,"open_rate":100,"click_rate":0,"ip_address":"89.216.27.147","subscribed_at":"2022-12-20 56 | 16:46:31","unsubscribed_at":null,"created_at":"2022-12-20 16:46:31","updated_at":"2022-12-21 57 | 07:45:50","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null},"opted_in_at":"2022-12-20 58 | 16:46:42","optin_ip":"89.216.27.147"}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/groups\/75011449370445335\/subscribers?page=1","last":"https:\/\/connect.mailerlite.com\/api\/groups\/75011449370445335\/subscribers?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 59 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/groups\/75011449370445335\/subscribers?page=1","label":"1","active":true},{"url":null,"label":"Next 60 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/groups\/75011449370445335\/subscribers","per_page":50,"to":1,"total":1}}' 61 | recorded_at: Wed, 21 Dec 2022 21:31:57 GMT 62 | recorded_with: VCR 6.1.0 63 | -------------------------------------------------------------------------------- /lib/mailerlite/segments/segments.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Segments from MailerLite API. 5 | class Segments 6 | attr_reader :client 7 | 8 | # Inits the `Segments` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of Segments that match the specified filter criteria. 16 | # 17 | # @param limit [Integer] the maximum number of Segments to return 18 | # @param page [Integer] the page number of the results to return 19 | # @return [HTTP::Response] the response from the API 20 | def list(limit: nil, page: nil) 21 | params = {} 22 | params['limit'] = limit if limit 23 | params['page'] = page if page 24 | 25 | client.http.get("#{MAILERLITE_API_URL}/segments", json: params.compact) 26 | end 27 | 28 | # Update the specified Segment 29 | # 30 | # @param segment_id [String] the ID of the Segments to update 31 | # @param name [String] the name to update 32 | # @return [HTTP::Response] the response from the API 33 | def update(segment_id:, name:) 34 | params = { 'name' => name } 35 | client.http.put("#{MAILERLITE_API_URL}/segments/#{segment_id}", json: params.compact) 36 | end 37 | 38 | # Get Subscribers assigned to the specified Segment. 39 | # @param segment_id [Integer] The id of existing Segment belonging to the account 40 | # @param filter[status] [String] Must be one of the possible statuses: active, unsubscribed, unconfirmed, bounced or junk. Defaults to active. 41 | # @param limit [Integer] the maximum number of subscribers to return 42 | # @param after [Integer] The last subscriber id, available in meta.last 43 | # @return [HTTP::Response] the response from the API 44 | def get_subscribers(segment_id:, filter: {}, limit: nil, after: nil) 45 | params = {} 46 | params['filter[status]'] = filter[:status] if filter.key?(:status) 47 | params['limit'] = limit if limit 48 | params['after'] = after if after 49 | uri = URI("#{MAILERLITE_API_URL}/segments/#{segment_id}/subscribers") 50 | uri.query = URI.encode_www_form(params.compact) 51 | client.http.get(uri) 52 | end 53 | 54 | # Deletes the specified Segments. 55 | # 56 | # @param segment_id [String] the ID of the Segments to delete 57 | # @return [HTTP::Response] the response from the API 58 | def delete(segment_id) 59 | client.http.delete("#{MAILERLITE_API_URL}/segments/#{segment_id}") 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /spec/forms_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Forms` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Forms` class 21 | RSpec.describe MailerLite::Forms do 22 | let(:client) { MailerLite::Client.new } 23 | let(:forms) { described_class.new(client: client) } 24 | 25 | describe '#list' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'lists all form' do 28 | VCR.use_cassette('forms/list') do 29 | response = forms.list(type: 'popup') 30 | body = JSON.parse(response.body) 31 | expect(response.status).to eq 200 32 | expect(body['data']).to be_an Array 33 | end 34 | end 35 | end 36 | describe '#update' do 37 | # Use VCR to record and replay the HTTP request 38 | it 'updates a form' do 39 | VCR.use_cassette('forms/update') do 40 | response = forms.update(form_id: 75_017_795_259_074_408, name: 'test_form2') 41 | body = JSON.parse(response.body) 42 | expect(response.status).to eq 200 43 | expect(Integer(body['data']['id'])).to be_an Integer 44 | end 45 | end 46 | end 47 | 48 | describe '#fetch' do 49 | # Use VCR to record and replay the HTTP request 50 | it 'fetchs all form' do 51 | VCR.use_cassette('forms/fetch') do 52 | response = forms.fetch(75_016_692_854_425_001) 53 | body = JSON.parse(response.body) 54 | expect(response.status).to eq 200 55 | expect(Integer(body['data']['id'])).to be_an Integer 56 | end 57 | end 58 | end 59 | 60 | describe '#fetch_subscribers' do 61 | # Use VCR to record and replay the HTTP request 62 | it 'fetch_subscribers of a form' do 63 | VCR.use_cassette('forms/fetch_subscribers') do 64 | response = forms.fetch_subscribers(75_231_510_415_803_781) 65 | body = JSON.parse(response.body) 66 | expect(response.status).to eq 200 67 | expect(body['data']).to be_an Array 68 | end 69 | end 70 | end 71 | 72 | describe '#delete' do 73 | # Use VCR to record and replay the HTTP request 74 | it 'deletes a form' do 75 | VCR.use_cassette('forms/delete') do 76 | response = forms.delete(75_016_692_854_425_001) 77 | expect(response.status).to eq 204 78 | end 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /fixtures/fields/get.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/fields 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 22:01:22 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3e5596b22d1d0-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"5","name":"City","key":"city","type":"text","is_default":true,"used_in_automations":true},{"id":"3","name":"Company","key":"company","type":"text","is_default":true,"used_in_automations":false},{"id":"4","name":"Country","key":"country","type":"text","is_default":true,"used_in_automations":false},{"id":"2","name":"Last 56 | name","key":"last_name","type":"text","is_default":true,"used_in_automations":false},{"id":"1","name":"Name","key":"name","type":"text","is_default":true,"used_in_automations":false},{"id":"6","name":"Phone","key":"phone","type":"text","is_default":true,"used_in_automations":false},{"id":"7","name":"State","key":"state","type":"text","is_default":true,"used_in_automations":false},{"id":"8","name":"ZIP","key":"z_i_p","type":"text","is_default":true,"used_in_automations":false}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/fields?page=1","last":"https:\/\/connect.mailerlite.com\/api\/fields?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 57 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/fields?page=1","label":"1","active":true},{"url":null,"label":"Next 58 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/fields","per_page":100,"to":8,"total":8}}' 59 | recorded_at: Wed, 21 Dec 2022 22:01:20 GMT 60 | recorded_with: VCR 6.1.0 61 | -------------------------------------------------------------------------------- /lib/mailerlite/forms/forms.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Forms from MailerLite API. 5 | class Forms 6 | attr_reader :client 7 | 8 | # Inits the `Forms` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of Forms that match the specified filter criteria. 16 | # 17 | # @param filter [#name] the name of the Forms to include in the results 18 | # @param limit [Integer] the maximum number of Forms to return 19 | # @param page [Integer] the page number of the results to return 20 | # @return [HTTP::Response] the response from the API 21 | def list(type:, filter: {}, limit: nil, sort: nil, page: nil) 22 | params = {} 23 | params['filter[name]'] = filter[:name] if filter.key?(:name) 24 | params['limit'] = limit if limit 25 | params['sort'] = sort if sort 26 | params['page'] = page if page 27 | uri = URI("#{MAILERLITE_API_URL}/forms/#{type}") 28 | uri.query = URI.encode_www_form(params.compact) 29 | client.http.get(uri) 30 | end 31 | 32 | # Returns the details of the specified Forms 33 | # 34 | # @param form_id [String] the ID of the forms to fetch 35 | # @return [HTTP::Response] the response from the API 36 | def fetch(form_id) 37 | client.http.get("#{MAILERLITE_API_URL}/forms/#{form_id}") 38 | end 39 | 40 | # Returns the subscribers who signed up to a specific form 41 | # 42 | # @param form_id [String] the ID of the forms to fetch 43 | # @return [HTTP::Response] the response from the API 44 | def fetch_subscribers(form_id) 45 | client.http.get("#{MAILERLITE_API_URL}/forms/#{form_id}/subscribers") 46 | end 47 | 48 | # Update the specified Forms 49 | # 50 | # @param form_id [String] the ID of the forms to fetch 51 | # @param name [String] the name to update 52 | # @return [HTTP::Response] the response from the API 53 | def update(form_id:, name:) 54 | params = { 'name' => name } 55 | client.http.put("#{MAILERLITE_API_URL}/forms/#{form_id}", json: params.compact) 56 | end 57 | 58 | # Returns the total number of Forms in the MailerLite account. 59 | # 60 | # @return [HTTP::Response] the response from the API 61 | def fetch_count 62 | client.http.get("#{MAILERLITE_API_URL}/forms/?limit=0") 63 | end 64 | 65 | # Deletes the specified forms. 66 | # 67 | # @param form_id [String] the ID of the forms to delete 68 | # @return [HTTP::Response] the response from the API 69 | def delete(form_id) 70 | client.http.delete("#{MAILERLITE_API_URL}/forms/#{form_id}") 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/webhooks_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Webhooks` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Webhooks` class 21 | RSpec.describe MailerLite::Webhooks do 22 | let(:client) { MailerLite::Client.new } 23 | let(:webhooks) { described_class.new(client: client) } 24 | 25 | describe '#create' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'creates a webhook' do 28 | VCR.use_cassette('webhooks/create') do 29 | response = webhooks.create( 30 | name: 'test_webhook', 31 | events: ['subscriber.created'], 32 | url: 'http://foobar.hook' 33 | ) 34 | body = JSON.parse(response.body) 35 | expect(response.status).to eq 201 36 | expect(Integer(body['data']['id'])).to be_an Integer 37 | end 38 | end 39 | end 40 | 41 | describe '#list' do 42 | # Use VCR to record and replay the HTTP request 43 | it 'lists all webhooks' do 44 | VCR.use_cassette('webhooks/list') do 45 | response = webhooks.list 46 | body = JSON.parse(response.body) 47 | expect(response.status).to eq 200 48 | expect(body['data']).to be_an Array 49 | end 50 | end 51 | end 52 | 53 | describe '#update' do 54 | # Use VCR to record and replay the HTTP request 55 | it 'updates a webhook' do 56 | VCR.use_cassette('webhooks/update') do 57 | response = webhooks.update(webhook_id: 75_233_700_096_247_795, name: 'test_webhook2') 58 | body = JSON.parse(response.body) 59 | expect(response.status).to eq 200 60 | expect(Integer(body['data']['id'])).to be_an Integer 61 | end 62 | end 63 | end 64 | 65 | describe '#get' do 66 | # Use VCR to record and replay the HTTP request 67 | it 'gets all webhook' do 68 | VCR.use_cassette('webhooks/get') do 69 | response = webhooks.get(75_321_551_702_984_317) 70 | body = JSON.parse(response.body) 71 | expect(response.status).to eq 200 72 | expect(Integer(body['data']['id'])).to be_an Integer 73 | end 74 | end 75 | end 76 | 77 | describe '#delete' do 78 | # Use VCR to record and replay the HTTP request 79 | it 'deletes a webhook' do 80 | VCR.use_cassette('webhooks/delete') do 81 | response = webhooks.delete(75_321_640_600_209_302) 82 | expect(response.status).to eq 204 83 | end 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /fixtures/forms/fetch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/forms/75016692854425001 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Tue, 20 Dec 2022 13:19:57 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77c8ac2c3d40d1e8-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75016692854425001","type":"popup","slug":"ikMxMV","name":"test 56 | form","created_at":"2022-12-20 13:04:53","conversions_count":0,"opens_count":0,"conversion_rate":{"float":0,"string":"0%"},"conversions_count_including_children":0,"opens_count_including_children":0,"conversion_rate_including_children":{"float":0,"string":"0%"},"settings":{"double_optin":true,"groot_id":2684442,"form_type":"popup","triggers":["timeout"],"timeout_seconds":5,"scroll_percentage":50,"frequency":1,"frequency_unit":"months","visibility":"always","url_list":[],"url_list_strict":null,"hide_on":[],"schedule":"no"},"last_registration_at":null,"active":false,"is_broken":false,"warning_messages":[],"has_content":true,"can":{"update":true},"used_in_automations":false,"warnings":[],"double_optin":true,"screenshot_url":"https:\/\/storage.googleapis.com\/mailerlite-screenshots-prod\/screenshot\/forms\/75016692854425001\/1284x1284.png","has_missing_groups":false,"groups":[{"id":"75011449370445335","name":"My 57 | Group","active_count":0,"sent_count":1,"opens_count":1,"open_rate":{"float":1,"string":"100%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-20 58 | 11:41:32"}],"has_split_tests":false,"split_test_finished":false,"split_test_enabled":false,"split_percentage":0,"is_split_test_winner":false,"children":[],"parent_id":null,"original_name":null,"analytics_reset_at":null}}' 59 | recorded_at: Tue, 20 Dec 2022 13:19:57 GMT 60 | recorded_with: VCR 6.1.0 61 | -------------------------------------------------------------------------------- /fixtures/forms/update.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://connect.mailerlite.com/api/forms/75017795259074408 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"test_form2"}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Tue, 20 Dec 2022 13:25:27 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77c8b43d8962de57-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75017795259074408","type":"popup","slug":"RxLjh1","name":"test_form2","created_at":"2022-12-20 56 | 13:22:24","conversions_count":0,"opens_count":0,"conversion_rate":{"float":0,"string":"0%"},"conversions_count_including_children":0,"opens_count_including_children":0,"conversion_rate_including_children":{"float":0,"string":"0%"},"settings":{"double_optin":true,"groot_id":2684721,"form_type":"popup","triggers":["timeout"],"timeout_seconds":5,"scroll_percentage":50,"frequency":1,"frequency_unit":"months","visibility":"always","url_list":[],"url_list_strict":null,"hide_on":[],"schedule":"no"},"last_registration_at":null,"active":false,"is_broken":false,"warning_messages":[],"has_content":true,"can":{"update":true},"used_in_automations":false,"warnings":[],"double_optin":true,"screenshot_url":"https:\/\/storage.googleapis.com\/mailerlite-screenshots-prod\/screenshot\/forms\/75017795259074408\/1284x1284.png","has_missing_groups":false,"groups":[{"id":"75011449370445335","name":"My 57 | Group","active_count":0,"sent_count":1,"opens_count":1,"open_rate":{"float":1,"string":"100%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-20 58 | 11:41:32"}],"has_split_tests":false,"split_test_finished":false,"split_test_enabled":false,"split_percentage":0,"is_split_test_winner":false,"children":[],"parent_id":null,"original_name":null,"analytics_reset_at":null}}' 59 | recorded_at: Tue, 20 Dec 2022 13:25:27 GMT 60 | recorded_with: VCR 6.1.0 61 | -------------------------------------------------------------------------------- /fixtures/automations/fetch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/automations/75040845299975641 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Thu, 22 Dec 2022 21:06:28 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77dbd24dffd7de57-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75040845299975641","name":"Test Automation","enabled":true,"trigger_data":{"track_ecommerce":false,"repeatable":false,"valid":true},"steps":[{"id":"75040874340287587","type":"action","parent_id":null,"complete":true,"broken":false,"created_at":"2022-12-20 56 | 19:29:14","updated_at":"2022-12-20 19:29:31","action_type":"update_custom_field","field_id":"5","field":{"id":"5","name":"City","key":"city","type":"text"},"date_operation":null,"value":"Lajpcig","description":"Update 57 | custom field to \"Lajpcig\""}],"triggers":[{"id":"75040865662273074","type":"subscriber_joins_group","group_id":"75011449370445335","group":{"id":"75011449370445335","name":"My 58 | Group","url":"https:\/\/dashboard.mailerlite.com\/subscribers?rules=W1t7Im9wZXJhdG9yIjoiaW5fYW55IiwiY29uZGl0aW9uIjoiZ3JvdXBzIiwiYXJncyI6WyJncm91cHMiLFsiNzUwMTE0NDkzNzA0NDUzMzUiXV19XV0%3D"},"exclude_group_ids":[],"excluded_groups":[],"broken":false}],"complete":true,"broken":false,"warnings":[],"stats":{"completed_subscribers_count":0,"subscribers_in_queue_count":0,"bounce_rate":{"float":0,"string":"0%"},"click_to_open_rate":{"float":0,"string":"0%"},"sent":0,"opens_count":0,"unique_opens_count":null,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"unique_clicks_count":null,"click_rate":{"float":0,"string":"0%"},"unsubscribes_count":0,"unsubscribe_rate":{"float":0,"string":"0%"},"spam_count":0,"spam_rate":{"float":0,"string":"0%"},"hard_bounces_count":0,"hard_bounce_rate":{"float":0,"string":"0%"},"soft_bounces_count":0,"soft_bounce_rate":{"float":0,"string":"0%"}},"created_at":"2022-12-20 59 | 19:28:46","has_banned_content":false,"qualified_subscribers_count":1}}' 60 | recorded_at: Thu, 22 Dec 2022 21:06:26 GMT 61 | recorded_with: VCR 6.1.0 62 | -------------------------------------------------------------------------------- /lib/mailerlite/automations/automations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Automation from MailerLite API. 5 | class Automations 6 | attr_reader :client 7 | 8 | # Inits the `Automations` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of Automations that match the specified filter criteria. 16 | # 17 | # @param filter[:status,:name,:group] [Array] filters for automation 18 | # @param limit [Integer] the maximum number of Automations to return 19 | # @param page [Integer] the page number of the results to return 20 | # @return [HTTP::Response] the response from the API 21 | def get(limit: nil, page: nil, filter: {}) 22 | params = {} 23 | params['filter[status]'] = filter[:status] if filter.key?(:status) 24 | params['filter[name]'] = filter[:name] if filter.key?(:name) 25 | params['filter[group]'] = filter[:group] if filter.key?(:group) 26 | params['limit'] = limit if limit 27 | params['page'] = page if page 28 | uri = URI("#{MAILERLITE_API_URL}/automations") 29 | uri.query = URI.encode_www_form(params.compact) 30 | client.http.get(uri) 31 | end 32 | 33 | # fetch the specified Automation 34 | # 35 | # @param automation_id [String] the ID of the Automation to fetch 36 | # @return [HTTP::Response] the response from the API 37 | def fetch(automation_id) 38 | client.http.get("#{MAILERLITE_API_URL}/automations/#{automation_id}") 39 | end 40 | 41 | # get_subscriber_activity the subscriber activity for specified Automation 42 | # 43 | # @param automation_id [Integer] the ID of the Automation to get_subscriber_activity 44 | # @param filter[:status,:date_from,:date_to,:scheduled_from,:scheduled_to,:keyword] [Array] Must be one of the following: completed, active, canceled, failed 45 | # @param limit [Integer] the maximum number of Automations to return 46 | # @param page [Integer] the page number of the results to return 47 | # @return [HTTP::Response] the response from the API 48 | def get_subscriber_activity(automation_id:, filter: {}, page: nil, limit: nil) 49 | params = { 'filter[status]' => filter[:status] } 50 | params['filter[date_from]'] = filter[:date_from] if filter.key?(:date_from) 51 | params['filter[date_to]'] = filter[:date_to] if filter.key?(:date_to) 52 | params['filter[scheduled_from]'] = filter[:scheduled_from] if filter.key?(:scheduled_from) 53 | params['filter[scheduled_to]'] = filter[:scheduled_to] if filter.key?(:scheduled_to) 54 | params['filter[keyword]'] = filter[:keyword] if filter.key?(:keyword) 55 | params['page'] = page if page 56 | params['limit'] = limit if limit 57 | uri = URI("#{MAILERLITE_API_URL}/automations/#{automation_id}/activity") 58 | uri.query = URI.encode_www_form(params.compact) 59 | client.http.get(uri) 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /fixtures/groups/get.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/groups 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Wed, 21 Dec 2022 21:38:56 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77d3c47c0dffd1d0-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75138557045376452","name":"A test Group","active_count":0,"sent_count":0,"opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-21 56 | 21:21:52"},{"id":"75011449370445335","name":"My Group","active_count":1,"sent_count":0,"opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":3,"bounced_count":0,"junk_count":0,"created_at":"2022-12-20 57 | 11:41:32"},{"id":"75138838590129612","name":"SMmwGofyQP","active_count":0,"sent_count":0,"opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-21 58 | 21:26:20"},{"id":"75138532090315810","name":"test_group","active_count":0,"sent_count":0,"opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-21 59 | 21:21:28"}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/groups?page=1","last":"https:\/\/connect.mailerlite.com\/api\/groups?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 60 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/groups?page=1","label":"1","active":true},{"url":null,"label":"Next 61 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/groups","per_page":250,"to":4,"total":4}}' 62 | recorded_at: Wed, 21 Dec 2022 21:38:54 GMT 63 | recorded_with: VCR 6.1.0 64 | -------------------------------------------------------------------------------- /spec/groups_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # Configure VCR to save and replay HTTP requests 9 | VCR.configure do |config| 10 | config.cassette_library_dir = './fixtures' 11 | config.hook_into :webmock 12 | config.filter_sensitive_data('') do |interaction| 13 | interaction.request.headers['Authorization'][0] 14 | end 15 | end 16 | 17 | # Set up the test for the `Groups` class 18 | RSpec.describe MailerLite::Groups do 19 | let(:client) { MailerLite::Client.new } 20 | let(:groups) { described_class.new(client: client) } 21 | 22 | describe '#get' do 23 | # Use VCR to record and replay the HTTP request 24 | it 'returns a list of groups' do 25 | VCR.use_cassette('groups/get') do 26 | response = groups.get 27 | body = JSON.parse(response.body) 28 | expect(response.status).to eq 200 29 | expect(body['data']).to be_an Array 30 | end 31 | end 32 | end 33 | describe '#create' do 34 | # Use VCR to record and replay the HTTP request 35 | it 'creates a group' do 36 | VCR.use_cassette('groups/create') do 37 | response = groups.create(name: 'test_group2') 38 | body = JSON.parse(response.body) 39 | expect(response.status).to eq 201 40 | expect(Integer(body['data']['id'])).to be_an Integer 41 | end 42 | end 43 | end 44 | describe '#update' do 45 | # Use VCR to record and replay the HTTP request 46 | it 'updates a group' do 47 | VCR.use_cassette('groups/update') do 48 | response = groups.update(group_id: 75_138_589_423_306_653, name: 'test_group3') 49 | body = JSON.parse(response.body) 50 | expect(response.status).to eq 200 51 | expect(Integer(body['data']['id'])).to be_an Integer 52 | end 53 | end 54 | end 55 | 56 | describe '#delete' do 57 | # Use VCR to record and replay the HTTP request 58 | it 'deletes a group' do 59 | VCR.use_cassette('groups/delete') do 60 | response = groups.delete(75_138_589_423_306_653) 61 | expect(response.status).to eq 204 62 | end 63 | end 64 | end 65 | 66 | describe '#get_subscribers' do 67 | # Use VCR to record and replay the HTTP request 68 | it 'get_subscribers for a group' do 69 | VCR.use_cassette('groups/get_subscribers') do 70 | response = groups.get_subscribers(group_id: 75_011_449_370_445_335) 71 | body = JSON.parse(response.body) 72 | expect(response.status).to eq 200 73 | expect(body['data']).to be_an Array 74 | end 75 | end 76 | end 77 | 78 | describe '#assign_subscribers' do 79 | # Use VCR to record and replay the HTTP request 80 | it 'assign_subscribers for a group' do 81 | VCR.use_cassette('groups/assign_subscriber') do 82 | response = groups.assign_subscriber(group_id: 75_138_557_045_376_452, subscriber: 75_009_808_379_414_225) 83 | expect(response.status).to eq 200 84 | end 85 | end 86 | end 87 | 88 | describe '#unassign_subscribers' do 89 | # Use VCR to record and replay the HTTP request 90 | it 'unassign_subscribers for a group' do 91 | VCR.use_cassette('groups/unassign_subscriber') do 92 | response = groups.unassign_subscriber(group_id: 75_138_557_045_376_452, subscriber: 75_009_808_379_414_225) 93 | expect(response.status).to eq 204 94 | end 95 | end 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /fixtures/forms/list.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/forms/popup 6 | body: 7 | encoding: UTF-8 8 | string: "{}" 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Tue, 20 Dec 2022 13:11:19 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77c89f89fd6bd1e8-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75016692854425001","type":"popup","slug":"ikMxMV","name":"test 56 | form","created_at":"2022-12-20 13:04:53","conversions_count":0,"opens_count":0,"conversion_rate":{"float":0,"string":"0%"},"conversions_count_including_children":0,"opens_count_including_children":0,"conversion_rate_including_children":{"float":0,"string":"0%"},"settings":{"double_optin":true,"groot_id":2684442,"form_type":"popup","triggers":["timeout"],"timeout_seconds":5,"scroll_percentage":50,"frequency":1,"frequency_unit":"months","visibility":"always","url_list":[],"url_list_strict":null,"hide_on":[],"schedule":"no"},"last_registration_at":null,"active":false,"is_broken":false,"warning_messages":[],"has_content":true,"can":{"update":true},"used_in_automations":false,"warnings":[],"double_optin":true,"screenshot_url":"https:\/\/storage.googleapis.com\/mailerlite-screenshots-prod\/screenshot\/forms\/75016692854425001\/1284x1284.png","has_missing_groups":false,"groups":[{"id":"75011449370445335","name":"My 57 | Group","active_count":0,"sent_count":1,"opens_count":1,"open_rate":{"float":1,"string":"100%"},"clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribed_count":0,"unconfirmed_count":0,"bounced_count":0,"junk_count":0,"created_at":"2022-12-20 58 | 11:41:32"}],"has_split_tests":false,"split_test_finished":false,"split_test_enabled":false,"split_percentage":0,"is_split_test_winner":false,"children":[],"parent_id":null,"original_name":null,"analytics_reset_at":null}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/forms\/popup?page=1","last":"https:\/\/connect.mailerlite.com\/api\/forms\/popup?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 59 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/forms\/popup?page=1","label":"1","active":true},{"url":null,"label":"Next 60 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/forms\/popup","per_page":25,"to":1,"total":1,"aggregations":{"popup":1,"embedded":0,"promotion":0}}}' 61 | recorded_at: Tue, 20 Dec 2022 13:11:19 GMT 62 | recorded_with: VCR 6.1.0 63 | -------------------------------------------------------------------------------- /fixtures/campaigns/activity.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/campaigns/75037917434611569/reports/subscriber-activity 6 | body: 7 | encoding: UTF-8 8 | string: '{"filter":{"type":"opened"}}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 22:22:59 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e47fc539c7de43-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75038031542749150","opens_count":1,"clicks_count":0,"subscriber":{"id":"73931277474989872","email":"sdk@mailerlite.com","status":"active","source":"manual","sent":2,"opens_count":2,"clicks_count":0,"open_rate":100,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-08 56 | 13:32:40","unsubscribed_at":null,"created_at":"2022-12-08 13:32:40","updated_at":"2022-12-20 57 | 18:45:03","fields":{"name":"SDK","last_name":null,"company":null,"country":null,"city":"Lajpcig","phone":null,"state":null,"z_i_p":null},"opted_in_at":null,"optin_ip":null}},{"id":"75038031600420839","opens_count":2,"clicks_count":0,"subscriber":{"id":"75030636641911843","email":"igor@hrcek.rs","status":"active","source":"webform","sent":1,"opens_count":1,"clicks_count":0,"open_rate":100,"click_rate":0,"ip_address":"89.216.27.147","subscribed_at":"2022-12-20 58 | 16:46:31","unsubscribed_at":null,"created_at":"2022-12-20 16:46:31","updated_at":"2022-12-21 59 | 07:45:50","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null},"opted_in_at":"2022-12-20 60 | 16:46:42","optin_ip":"89.216.27.147"}}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/campaigns\/75037917434611569\/reports\/subscriber-activity?page=1","last":"https:\/\/connect.mailerlite.com\/api\/campaigns\/75037917434611569\/reports\/subscriber-activity?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 61 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/campaigns\/75037917434611569\/reports\/subscriber-activity?page=1","label":"1","active":true},{"url":null,"label":"Next 62 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/campaigns\/75037917434611569\/reports\/subscriber-activity","per_page":50,"to":2,"total":2,"counts":{"all":2,"opened":2,"unopened":0,"clicked":0,"unsubscribed":0,"forwarded":0,"hardbounced":0,"softbounced":0,"junk":0}}}' 63 | recorded_at: Fri, 23 Dec 2022 22:22:58 GMT 64 | recorded_with: VCR 6.1.0 65 | -------------------------------------------------------------------------------- /spec/subscribers_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Subscribers` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Subscribers` class 21 | RSpec.describe MailerLite::Subscribers do 22 | let(:client) { MailerLite::Client.new } 23 | let(:subscribers) { described_class.new(client: client) } 24 | 25 | describe '#fetch' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'returns a list of subscribers' do 28 | VCR.use_cassette('subscribers/fetch') do 29 | response = subscribers.fetch(filter: { status: 'active' }) 30 | body = JSON.parse(response.body) 31 | expect(response.status).to eq 200 32 | expect(body['data']).to be_an Array 33 | end 34 | end 35 | end 36 | 37 | describe '#create' do 38 | # Use VCR to record and replay the HTTP request 39 | it 'creates a new subscriber' do 40 | VCR.use_cassette('subscribers/create') do 41 | response = subscribers.create(email: 'user@example.com') 42 | body = JSON.parse(response.body) 43 | expect(response.status).to eq 200 44 | expect(Integer(body['data']['id'])).to be_a Integer 45 | expect(body['data']['email']).to eq 'user@example.com' 46 | end 47 | end 48 | end 49 | 50 | describe '#get' do 51 | # Use VCR to record and replay the HTTP request 52 | it 'gets a subscriber' do 53 | VCR.use_cassette('subscribers/get') do 54 | response = subscribers.get('second@email.com') 55 | body = JSON.parse(response.body) 56 | expect(response.status).to eq 200 57 | expect(Integer(body['data']['id'])).to eq 75_009_808_379_414_225 58 | expect(body['data']['email']).to be_a String 59 | end 60 | end 61 | end 62 | 63 | describe '#fetch_count' do 64 | # Use VCR to record and replay the HTTP request 65 | it 'fetches the subscriber count' do 66 | VCR.use_cassette('subscribers/fetch_count') do 67 | response = subscribers.fetch_count 68 | body = JSON.parse(response.body) 69 | expect(response.status).to eq 200 70 | expect(body['total']).to be_a Integer 71 | end 72 | end 73 | end 74 | 75 | describe '#update' do 76 | # Use VCR to record and replay the HTTP request 77 | it 'updates a subscriber' do 78 | VCR.use_cassette('subscribers/update') do 79 | response = subscribers.update(98_112_484_192_290_662, email: 'updated@email.com') 80 | body = JSON.parse(response.body) 81 | expect(response.status).to eq 200 82 | expect(body['data']['email']).to eq 'updated@email.com' 83 | end 84 | end 85 | end 86 | 87 | describe '#delete' do 88 | # Use VCR to record and replay the HTTP request 89 | it 'deletes a subscriber' do 90 | VCR.use_cassette('subscribers/delete') do 91 | response = subscribers.delete(73_871_649_530_709_291) 92 | expect(response.status).to eq 204 93 | end 94 | end 95 | end 96 | 97 | describe '#forget' do 98 | # Use VCR to record and replay the HTTP request 99 | it 'forgets a subscriber' do 100 | VCR.use_cassette('subscribers/forget') do 101 | response = subscribers.forget(98_121_614_828_242_796) 102 | body = JSON.parse(response.body) 103 | expect(response.status).to eq 200 104 | expect(body['message']).to eq 'Subscriber data will be completely deleted and forgotten within 30 days.' 105 | end 106 | end 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /fixtures/subscribers/fetch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/subscribers?filter%5Bstatus%5D=active 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 21:03:41 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e40b99cbd0d1ec-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75030636641911843","email":"igor@hrcek.rs","status":"active","source":"webform","sent":1,"opens_count":1,"clicks_count":0,"open_rate":100,"click_rate":0,"ip_address":"89.216.27.147","subscribed_at":"2022-12-20 56 | 16:46:31","unsubscribed_at":null,"created_at":"2022-12-20 16:46:31","updated_at":"2022-12-21 57 | 07:45:50","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null},"opted_in_at":"2022-12-20 58 | 16:46:42","optin_ip":"89.216.27.147"},{"id":"75009808379414225","email":"second@email.com","status":"active","source":"import","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-20 59 | 11:15:27","unsubscribed_at":null,"created_at":"2022-12-20 11:15:27","updated_at":"2022-12-21 60 | 18:32:20","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":"Lajpcig","phone":null,"state":null,"z_i_p":null},"opted_in_at":null,"optin_ip":null},{"id":"75009808377317072","email":"first@email.com","status":"active","source":"import","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-20 61 | 11:15:27","unsubscribed_at":null,"created_at":"2022-12-20 11:15:27","updated_at":"2022-12-21 62 | 18:32:20","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":"Lajpcig","phone":null,"state":null,"z_i_p":null},"opted_in_at":null,"optin_ip":null},{"id":"75005710539163012","email":"some3@email.com","status":"active","source":"api","sent":0,"opens_count":0,"clicks_count":0,"open_rate":0,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-20 63 | 10:10:19","unsubscribed_at":null,"created_at":"2022-12-20 10:10:19","updated_at":"2022-12-20 64 | 10:10:19","fields":{"name":null,"last_name":null,"company":null,"country":null,"city":null,"phone":null,"state":null,"z_i_p":null},"opted_in_at":null,"optin_ip":null},{"id":"73931277474989872","email":"sdk@mailerlite.com","status":"active","source":"manual","sent":2,"opens_count":2,"clicks_count":0,"open_rate":100,"click_rate":0,"ip_address":null,"subscribed_at":"2022-12-08 65 | 13:32:40","unsubscribed_at":null,"created_at":"2022-12-08 13:32:40","updated_at":"2022-12-20 66 | 18:45:03","fields":{"name":"SDK","last_name":null,"company":null,"country":null,"city":"Lajpcig","phone":null,"state":null,"z_i_p":null},"opted_in_at":null,"optin_ip":null}],"links":{"first":null,"last":null,"prev":null,"next":null},"meta":{"path":"https:\/\/connect.mailerlite.com\/api\/subscribers","per_page":25,"next_cursor":null,"prev_cursor":null}}' 67 | recorded_at: Fri, 23 Dec 2022 21:03:40 GMT 68 | recorded_with: VCR 6.1.0 69 | -------------------------------------------------------------------------------- /lib/mailerlite/groups/groups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Groups from MailerLite API. 5 | class Groups 6 | attr_reader :client 7 | 8 | # Inits the `Groups` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of Groups that match the specified filter criteria. 16 | # 17 | # @param filter[:name] the name of the Groups to include in the results 18 | # @param limit [Integer] the maximum number of Groups to return 19 | # @param page [Integer] the page number of the results to return 20 | # @return [HTTP::Response] the response from the API 21 | def get(filter: {}, limit: nil, sort: nil, page: nil) 22 | params = {} 23 | params['filter[name]'] = filter[:name] if filter.key?(:name) 24 | params['limit'] = limit if limit 25 | params['sort'] = sort if sort 26 | params['page'] = page if page 27 | uri = URI("#{MAILERLITE_API_URL}/groups") 28 | uri.query = URI.encode_www_form(params.compact) 29 | client.http.get(uri) 30 | end 31 | 32 | # create a Group 33 | # 34 | # @param name [String] the name to update 35 | # @return [HTTP::Response] the response from the API 36 | def create(name:) 37 | params = { 'name' => name } 38 | client.http.post("#{MAILERLITE_API_URL}/groups", json: params.compact) 39 | end 40 | 41 | # Update the specified Group 42 | # 43 | # @param group_id [String] the ID of the Groups to update 44 | # @param name [String] the name to update 45 | # @return [HTTP::Response] the response from the API 46 | def update(group_id:, name:) 47 | params = { 'name' => name } 48 | client.http.put("#{MAILERLITE_API_URL}/groups/#{group_id}", json: params.compact) 49 | end 50 | 51 | # Get Subscribers assigned to the specified group. 52 | # @param group_id [Integer] The id of existing group belonging to the account 53 | # @param filter[:status] [String] Must be one of the possible statuses: active, unsubscribed, unconfirmed, bounced or junk. Defaults to active. 54 | # @param limit [Integer] the maximum number of subscribers to return 55 | # @param page [Integer] the page number of the results to return 56 | # @return [HTTP::Response] the response from the API 57 | def get_subscribers(group_id:, filter: {}, limit: nil, page: nil, sort: nil) 58 | params = {} 59 | params['filter[status]'] = filter[:status] if filter.key?(:status) 60 | params['limit'] = limit if limit 61 | params['sort'] = sort if sort 62 | params['page'] = page if page 63 | client.http.get("#{MAILERLITE_API_URL}/groups/#{group_id}/subscribers", json: params.compact) 64 | end 65 | 66 | # Assign Subscriber to the specified group. 67 | # @param group_id [Integer] The id of existing group belonging to the account 68 | # @param subscriber [Integer] The id of existing subscriber belonging to the account 69 | # @return [HTTP::Response] the response from the API 70 | def assign_subscriber(group_id:, subscriber:) 71 | client.http.post("#{MAILERLITE_API_URL}/subscribers/#{subscriber}/groups/#{group_id}") 72 | end 73 | 74 | # Unassign Subscriber to the specified group. 75 | # @param group_id [Integer] The id of existing group belonging to the account 76 | # @param subscriber [Integer] The id of existing subscriber belonging to the account 77 | # @return [HTTP::Response] the response from the API 78 | def unassign_subscriber(group_id:, subscriber:) 79 | client.http.delete("#{MAILERLITE_API_URL}/subscribers/#{subscriber}/groups/#{group_id}") 80 | end 81 | 82 | # Deletes the specified Groups. 83 | # 84 | # @param group_id [String] the ID of the Groups to delete 85 | # @return [HTTP::Response] the response from the API 86 | def delete(group_id) 87 | client.http.delete("#{MAILERLITE_API_URL}/groups/#{group_id}") 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /fixtures/automations/get_subscriber_activity.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/automations/75040845299975641/activity?filter%5Bstatus%5D=completed 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 12:29:52 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e11aee5eabd1e8-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75230485820736830","status":"Completed","date":"2022-12-22 56 | 21:43:02","reason":null,"reason_description":"","subscriber":{"id":"73931277474989872","email":"sdk@mailerlite.com"},"stepRuns":[{"id":"75230485910914375","step_id":"75040874340287587","description":"Update 57 | custom field to \"Lajpcig\"","scheduled_for":null}],"currentStep":{"id":"75040874340287587","type":"action","parent_id":null,"complete":true,"broken":false,"created_at":"2022-12-20 58 | 19:29:14","updated_at":"2022-12-20 19:29:31","action_type":"update_custom_field","field_id":"5","field":{"id":"5","name":"City","key":"city","type":"text"},"date_operation":null,"value":"Lajpcig","description":"Update 59 | custom field to \"Lajpcig\""}},{"id":"75230486001091919","status":"Completed","date":"2022-12-22 60 | 21:43:02","reason":null,"reason_description":"","subscriber":{"id":"75009808377317072","email":"first@email.com"},"stepRuns":[{"id":"75230486081832277","step_id":"75040874340287587","description":"Update 61 | custom field to \"Lajpcig\"","scheduled_for":null}],"currentStep":{"id":"75040874340287587","type":"action","parent_id":null,"complete":true,"broken":false,"created_at":"2022-12-20 62 | 19:29:14","updated_at":"2022-12-20 19:29:31","action_type":"update_custom_field","field_id":"5","field":{"id":"5","name":"City","key":"city","type":"text"},"date_operation":null,"value":"Lajpcig","description":"Update 63 | custom field to \"Lajpcig\""}},{"id":"75230485991654734","status":"Completed","date":"2022-12-22 64 | 21:43:02","reason":null,"reason_description":"","subscriber":{"id":"75009808379414225","email":"second@email.com"},"stepRuns":[{"id":"75230486076589396","step_id":"75040874340287587","description":"Update 65 | custom field to \"Lajpcig\"","scheduled_for":null}],"currentStep":{"id":"75040874340287587","type":"action","parent_id":null,"complete":true,"broken":false,"created_at":"2022-12-20 66 | 19:29:14","updated_at":"2022-12-20 19:29:31","action_type":"update_custom_field","field_id":"5","field":{"id":"5","name":"City","key":"city","type":"text"},"date_operation":null,"value":"Lajpcig","description":"Update 67 | custom field to \"Lajpcig\""}}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/automations\/75040845299975641\/activity?page=1","last":"https:\/\/connect.mailerlite.com\/api\/automations\/75040845299975641\/activity?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 68 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/automations\/75040845299975641\/activity?page=1","label":"1","active":true},{"url":null,"label":"Next 69 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/automations\/75040845299975641\/activity","per_page":10,"to":3,"total":3}}' 70 | recorded_at: Fri, 23 Dec 2022 12:29:49 GMT 71 | recorded_with: VCR 6.1.0 72 | -------------------------------------------------------------------------------- /fixtures/campaigns/fetch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/campaigns/74917804992628332 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Mon, 19 Dec 2022 10:53:37 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '118' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77bf987469e7de5b-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"74917804992628332","account_id":"252151","name":"test_campaign","type":"regular","status":"draft","missing_data":["content"],"settings":[],"filter":[],"filter_for_humans":[],"delivery_schedule":null,"language_id":"4","language":{"id":"4","shortcode":"en","iso639":"en-US","name":"English","direction":"ltr"},"created_at":"2022-12-19 56 | 10:53:06","updated_at":"2022-12-19 10:53:06","scheduled_for":null,"queued_at":null,"started_at":null,"finished_at":null,"stopped_at":null,"default_email_id":"74917805026182765","emails":[{"id":"74917805026182765","account_id":"252151","emailable_id":"74917804992628332","emailable_type":"campaigns","type":null,"from":"sdk@mailerlite.com","from_name":"user","name":null,"subject":"test 57 | subject","content":null,"plain_text":"Hello,\n\nYou have received a newsletter 58 | from {$account}.\n\nHowever, your email software can''t display HTML emails. 59 | You can view the newsletter by clicking here:\n\n{$url}\n\n\n\nYou''re receiving 60 | this newsletter because you have shown interest in {$account}.\nNot interested 61 | anymore? Click here to unsubscribe:\n{$unsubscribe}\n","screenshot_url":null,"preview_url":"https:\/\/preview.mailerlite.io\/preview\/252151\/emails\/74917805026182765","created_at":"2022-12-19 62 | 10:53:06","updated_at":"2022-12-19 10:53:06","click_map":[],"is_designed":false,"language_id":4,"language":{"id":"4","shortcode":"en","iso639":"en-US","name":"English","direction":"ltr"},"is_winner":false,"stats":{"sent":0,"opens_count":0,"unique_opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"unique_clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribes_count":0,"unsubscribe_rate":{"float":0,"string":"0%"},"spam_count":0,"spam_rate":{"float":0,"string":"0%"},"hard_bounces_count":0,"hard_bounce_rate":{"float":0,"string":"0%"},"soft_bounces_count":0,"soft_bounce_rate":{"float":0,"string":"0%"},"forwards_count":0},"send_after":null,"track_opens":true,"uses_quiz":false}],"used_in_automations":false,"type_for_humans":"Regular","is_stopped":false,"has_winner":null,"winner_version_for_human":null,"winner_sending_time_for_humans":null,"winner_selected_manually_at":null,"can":{"update":true,"delete":true,"send":true,"copy":true,"resend":false},"uses_ecommerce":false,"uses_survey":false,"can_be_scheduled":false,"breadcrumbs":[{"url":"https:\/\/dashboard.mailerlite.com\/campaigns\/74917804992628332\/edit","text":"Details","active":false,"disabled":false,"upcoming":false,"state":null},{"url":"https:\/\/dashboard.mailerlite.com\/emails\/74917805026182765\/edit","text":"Content","active":false,"disabled":false,"upcoming":false,"state":null},{"url":"https:\/\/dashboard.mailerlite.com\/campaigns\/74917804992628332\/recipients\/basic","text":"Recipients","active":false,"disabled":false,"upcoming":false,"state":null},{"url":"https:\/\/dashboard.mailerlite.com\/campaigns\/74917804992628332\/review","text":"Review","active":false,"disabled":false,"upcoming":false,"state":null},{"url":null,"text":"Schedule","active":false,"disabled":true,"upcoming":false,"state":"disabled"}],"warnings":[],"recipients_count":3,"next_step":"https:\/\/dashboard.mailerlite.com\/campaigns\/74917804992628332\/review","is_currently_sending_out":false}}' 63 | recorded_at: Mon, 19 Dec 2022 10:53:37 GMT 64 | recorded_with: VCR 6.1.0 65 | -------------------------------------------------------------------------------- /fixtures/campaigns/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/campaigns 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"test_campaign","type":"regular","emails":[{"subject":"test 9 | subject","from":"sdk@mailerlite.com","from_name":"user"}]}' 10 | headers: 11 | Authorization: 12 | - "" 13 | User-Agent: 14 | - MailerLite-client-ruby/0.1.1 15 | Accept: 16 | - application/json 17 | Content-Type: 18 | - application/json 19 | Connection: 20 | - close 21 | Host: 22 | - connect.mailerlite.com 23 | response: 24 | status: 25 | code: 201 26 | message: Created 27 | headers: 28 | Date: 29 | - Mon, 19 Dec 2022 10:53:06 GMT 30 | Content-Type: 31 | - application/json 32 | Transfer-Encoding: 33 | - chunked 34 | Connection: 35 | - close 36 | Cache-Control: 37 | - no-cache, private 38 | X-Locale: 39 | - en 40 | X-Ratelimit-Limit: 41 | - '120' 42 | X-Ratelimit-Remaining: 43 | - '119' 44 | Access-Control-Allow-Origin: 45 | - "*" 46 | Strict-Transport-Security: 47 | - max-age=15724800; includeSubDomains 48 | Cf-Cache-Status: 49 | - DYNAMIC 50 | Server: 51 | - cloudflare 52 | Cf-Ray: 53 | - 77bf97b0e8b0d1e0-MCT 54 | body: 55 | encoding: UTF-8 56 | string: '{"data":{"id":"74917804992628332","account_id":"252151","name":"test_campaign","type":"regular","status":"draft","missing_data":["content"],"settings":[],"filter":[],"filter_for_humans":[],"delivery_schedule":null,"language_id":"4","language":{"id":"4","shortcode":"en","iso639":"en-US","name":"English","direction":"ltr"},"created_at":"2022-12-19 57 | 10:53:06","updated_at":"2022-12-19 10:53:06","scheduled_for":null,"queued_at":null,"started_at":null,"finished_at":null,"stopped_at":null,"default_email_id":"74917805026182765","emails":[{"id":"74917805026182765","account_id":"252151","emailable_id":"74917804992628332","emailable_type":"campaigns","type":null,"from":"sdk@mailerlite.com","from_name":"user","name":null,"subject":"test 58 | subject","plain_text":"Hello,\n\nYou have received a newsletter from {$account}.\n\nHowever, 59 | your email software can''t display HTML emails. You can view the newsletter 60 | by clicking here:\n\n{$url}\n\n\n\nYou''re receiving this newsletter because 61 | you have shown interest in {$account}.\nNot interested anymore? Click here 62 | to unsubscribe:\n{$unsubscribe}\n","screenshot_url":null,"preview_url":"https:\/\/preview.mailerlite.io\/preview\/252151\/emails\/74917805026182765","created_at":"2022-12-19 63 | 10:53:06","updated_at":"2022-12-19 10:53:06","is_designed":false,"language_id":4,"language":{"id":"4","shortcode":"en","iso639":"en-US","name":"English","direction":"ltr"},"is_winner":false,"stats":{"sent":0,"opens_count":0,"unique_opens_count":0,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"unique_clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribes_count":0,"unsubscribe_rate":{"float":0,"string":"0%"},"spam_count":0,"spam_rate":{"float":0,"string":"0%"},"hard_bounces_count":0,"hard_bounce_rate":{"float":0,"string":"0%"},"soft_bounces_count":0,"soft_bounce_rate":{"float":0,"string":"0%"},"forwards_count":0},"send_after":null,"track_opens":true,"uses_quiz":false}],"used_in_automations":false,"type_for_humans":"Regular","is_stopped":false,"has_winner":null,"winner_version_for_human":null,"winner_sending_time_for_humans":null,"winner_selected_manually_at":null,"can":{"update":true,"delete":true,"send":true,"copy":true,"resend":false},"uses_ecommerce":false,"uses_survey":false,"can_be_scheduled":false,"breadcrumbs":[{"url":"https:\/\/dashboard.mailerlite.com\/campaigns\/74917804992628332\/edit","text":"Details","active":false,"disabled":false,"upcoming":false,"state":null},{"url":"https:\/\/dashboard.mailerlite.com\/emails\/74917805026182765\/edit","text":"Content","active":false,"disabled":false,"upcoming":false,"state":null},{"url":"https:\/\/dashboard.mailerlite.com\/campaigns\/74917804992628332\/recipients\/basic","text":"Recipients","active":false,"disabled":false,"upcoming":false,"state":null},{"url":"https:\/\/dashboard.mailerlite.com\/campaigns\/74917804992628332\/review","text":"Review","active":false,"disabled":false,"upcoming":false,"state":null},{"url":null,"text":"Schedule","active":false,"disabled":true,"upcoming":false,"state":"disabled"}],"warnings":[],"recipients_count":3,"next_step":"https:\/\/dashboard.mailerlite.com\/campaigns\/74917804992628332\/review","is_currently_sending_out":false}}' 64 | recorded_at: Mon, 19 Dec 2022 10:53:06 GMT 65 | recorded_with: VCR 6.1.0 66 | -------------------------------------------------------------------------------- /fixtures/campaigns/languages.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/campaigns/languages 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 21:56:57 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e459a36d91de47-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"23","shortcode":"ar","iso639":"ar","name":"(arabic)\u0627\u0644\u0639\u0631\u0628\u064a\u0629","direction":"rtl"},{"id":"34","shortcode":"ca","iso639":"ca","name":"Catal\u00e0","direction":"ltr"},{"id":"21","shortcode":"cz","iso639":"cs-CZ","name":"\u010cesk\u00fd","direction":"ltr"},{"id":"35","shortcode":"ch","iso639":"ch","name":"Chinese","direction":"ltr"},{"id":"16","shortcode":"dk","iso639":"da-DK","name":"Dansk","direction":"ltr"},{"id":"5","shortcode":"de","iso639":"de-DE","name":"Deutsch","direction":"ltr"},{"id":"15","shortcode":"ee","iso639":"et-EE","name":"Eesti","direction":"ltr"},{"id":"4","shortcode":"en","iso639":"en-US","name":"English","direction":"ltr"},{"id":"8","shortcode":"es","iso639":"es-ES","name":"Espa\u00f1ol","direction":"ltr"},{"id":"9","shortcode":"mx","iso639":"es-MX","name":"Espa\u00f1ol 56 | (Mexican)","direction":"ltr"},{"id":"17","shortcode":"fi","iso639":"fi-FI","name":"Finnish","direction":"ltr"},{"id":"6","shortcode":"fr","iso639":"fr-FR","name":"Fran\u00e7ais","direction":"ltr"},{"id":"26","shortcode":"frq","iso639":"fr-CA","name":"Fran\u00e7ais 57 | - Qu\u00e9bec","direction":"ltr"},{"id":"36","shortcode":"he","iso639":"he","name":"(hebrew)\u05e2\u05d1\u05e8\u05d9\u05ea","direction":"rtl"},{"id":"20","shortcode":"hr","iso639":"hr-HR","name":"Hrvatski","direction":"ltr"},{"id":"7","shortcode":"it","iso639":"it-IT","name":"Italiano","direction":"ltr"},{"id":"37","shortcode":"ja","iso639":"jpn","name":"Japanese","direction":"ltr"},{"id":"14","shortcode":"lv","iso639":"lv-LV","name":"Latvie\u0161u","direction":"ltr"},{"id":"1","shortcode":"lt","iso639":"lt-LT","name":"Lietuvi\u0161kai","direction":"ltr"},{"id":"32","shortcode":"hu","iso639":"hu-HU","name":"Magyar","direction":"ltr"},{"id":"13","shortcode":"nl","iso639":"nl-NL","name":"Nederlands","direction":"ltr"},{"id":"28","shortcode":"no","iso639":"nn-NO","name":"Norsk","direction":"ltr"},{"id":"33","shortcode":"pr","iso639":"fa-IR","name":"(persian)\u0641\u0627\u0631\u0633\u06cc","direction":"rtl"},{"id":"2","shortcode":"pl","iso639":"pl-PL","name":"Polski","direction":"ltr"},{"id":"18","shortcode":"pt","iso639":"pt-PT","name":"Portugu\u00eas","direction":"ltr"},{"id":"19","shortcode":"ptbr","iso639":"pt-BR","name":"Portugu\u00eas 58 | (Brazil)","direction":"ltr"},{"id":"27","shortcode":"ro","iso639":"ro-RO","name":"Rom\u00e2n\u0103","direction":"ltr"},{"id":"22","shortcode":"sl","iso639":"sl-SI","name":"Slovenski","direction":"ltr"},{"id":"10","shortcode":"sk","iso639":"sk-SK","name":"Slovensky","direction":"ltr"},{"id":"11","shortcode":"se","iso639":"sv-SE","name":"Svenska","direction":"ltr"},{"id":"25","shortcode":"tr","iso639":"tr-TR","name":"T\u00fcrk\u00e7e","direction":"ltr"},{"id":"24","shortcode":"gr","iso639":"el-GR","name":"\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac","direction":"ltr"},{"id":"30","shortcode":"bg","iso639":"bg-BG","name":"\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438","direction":"ltr"},{"id":"29","shortcode":"mk","iso639":"mk-MK","name":"\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438","direction":"ltr"},{"id":"3","shortcode":"ru","iso639":"ru-RU","name":"\u0420\u0443\u0441\u0441\u043a\u0438\u0439","direction":"ltr"},{"id":"31","shortcode":"sr","iso639":"sr-Cyrl","name":"\u0421\u0440\u043f\u0441\u043a\u0438","direction":"ltr"},{"id":"12","shortcode":"ua","iso639":"uk-UA","name":"\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430","direction":"ltr"}]}' 59 | recorded_at: Fri, 23 Dec 2022 21:56:56 GMT 60 | recorded_with: VCR 6.1.0 61 | -------------------------------------------------------------------------------- /fixtures/campaigns/get.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/campaigns?filter%5Bstatus%5D=sent&filter%5Btype%5D=regular 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 22:12:23 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e4703cdd83d1f4-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75037917434611569","account_id":"252151","name":"Test 56 | Campaign","type":"regular","status":"sent","missing_data":[],"settings":{"track_opens":"1","use_google_analytics":"0","ecommerce_tracking":"0"},"filter":[],"filter_for_humans":[],"delivery_schedule":"instant","language_id":"1","created_at":"2022-12-20 57 | 18:42:14","updated_at":"2022-12-20 18:44:03","scheduled_for":"2022-12-20 18:43:43","queued_at":"2022-12-20 58 | 18:44:02","started_at":"2022-12-20 18:44:03","finished_at":"2022-12-20 18:44:03","stopped_at":null,"default_email_id":"75037917465020274","emails":[{"id":"75037917465020274","account_id":"252151","emailable_id":"75037917434611569","emailable_type":"campaigns","type":"builder_html","from":"testuser@mailerlite.com","from_name":"Test 59 | Man","name":null,"subject":"This is a test campaign","plain_text":"Sveiki,\n\nJ\u016bs 60 | gavote {$account} naujienlai\u0161k\u012f. Ta\u010diau J\u016bs\u0173 el. 61 | pa\u0161to programa programa nepalaiko HTML formato.\n\nNaujienlai\u0161k\u012f 62 | galite rasti \u010dia:\n\n{$url}\n\nPagarbiai,\n{$account}\n\n\n\nJeigu ateityje 63 | nebenorite gauti {$account} naujien\u0173, spauskite \u010dia:\n{$unsubscribe}\n","screenshot_url":"https:\/\/storage.googleapis.com\/mailerlite-screenshots-prod\/screenshot\/emails\/75037917465020274\/1284x736.png","preview_url":"https:\/\/preview.mailerlite.io\/preview\/252151\/emails\/75037917465020274","created_at":"2022-12-20 64 | 18:42:14","updated_at":"2022-12-21 07:46:52","is_designed":true,"language_id":1,"is_winner":false,"stats":{"sent":2,"opens_count":3,"unique_opens_count":2,"open_rate":{"float":1,"string":"100%"},"clicks_count":0,"unique_clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribes_count":0,"unsubscribe_rate":{"float":0,"string":"0%"},"spam_count":0,"spam_rate":{"float":0,"string":"0%"},"hard_bounces_count":0,"hard_bounce_rate":{"float":0,"string":"0%"},"soft_bounces_count":0,"soft_bounce_rate":{"float":0,"string":"0%"},"forwards_count":0},"send_after":null,"track_opens":true,"uses_quiz":false}],"used_in_automations":false,"type_for_humans":"Regular","stats":{"sent":2,"opens_count":2,"unique_opens_count":2,"open_rate":{"float":1,"string":"100%"},"clicks_count":0,"unique_clicks_count":0,"click_rate":{"float":0,"string":"0%"},"unsubscribes_count":0,"unsubscribe_rate":{"float":0,"string":"0%"},"spam_count":0,"spam_rate":{"float":0,"string":"0%"},"hard_bounces_count":0,"hard_bounce_rate":{"float":0,"string":"0%"},"soft_bounces_count":0,"soft_bounce_rate":{"float":0,"string":"0%"},"forwards_count":0,"click_to_open_rate":{"float":0,"string":"0%"}},"is_stopped":false,"has_winner":null,"winner_version_for_human":null,"winner_sending_time_for_humans":null,"winner_selected_manually_at":null,"can":{"update":true,"delete":true,"send":true,"copy":true,"resend":true},"uses_ecommerce":false,"uses_survey":false,"can_be_scheduled":false,"warnings":[],"initial_created_at":null,"is_currently_sending_out":false}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/campaigns?page=1","last":"https:\/\/connect.mailerlite.com\/api\/campaigns?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 65 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/campaigns?page=1","label":"1","active":true},{"url":null,"label":"Next 66 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/campaigns","per_page":25,"to":1,"total":1,"aggregations":{"total":2,"draft":1,"ready":0,"sent":1}}}' 67 | recorded_at: Fri, 23 Dec 2022 22:12:22 GMT 68 | recorded_with: VCR 6.1.0 69 | -------------------------------------------------------------------------------- /fixtures/automations/get.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://connect.mailerlite.com/api/automations 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 12:28:38 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e1191ea97dde43-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":[{"id":"75040845299975641","name":"Test Automation","enabled":true,"trigger_data":{"track_ecommerce":false,"repeatable":false,"valid":true},"steps":[{"id":"75040874340287587","type":"action","parent_id":null,"complete":true,"broken":false,"created_at":"2022-12-20 56 | 19:29:14","updated_at":"2022-12-20 19:29:31","action_type":"update_custom_field","field_id":"5","field":{"id":"5","name":"City","key":"city","type":"text"},"date_operation":null,"value":"Lajpcig","description":"Update 57 | custom field to \"Lajpcig\""}],"triggers":[{"id":"75040865662273074","type":"subscriber_joins_group","group_id":"75011449370445335","group":{"id":"75011449370445335","name":"My 58 | Group","url":"https:\/\/dashboard.mailerlite.com\/subscribers?rules=W1t7Im9wZXJhdG9yIjoiaW5fYW55IiwiY29uZGl0aW9uIjoiZ3JvdXBzIiwiYXJncyI6WyJncm91cHMiLFsiNzUwMTE0NDkzNzA0NDUzMzUiXV19XV0%3D"},"exclude_group_ids":[],"excluded_groups":[],"broken":false}],"complete":true,"broken":false,"warnings":[],"emails_count":0,"first_email_screenshot_url":null,"stats":{"completed_subscribers_count":3,"subscribers_in_queue_count":0,"bounce_rate":{"float":0,"string":"0%"},"click_to_open_rate":{"float":0,"string":"0%"},"sent":0,"opens_count":0,"unique_opens_count":null,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"unique_clicks_count":null,"click_rate":{"float":0,"string":"0%"},"unsubscribes_count":0,"unsubscribe_rate":{"float":0,"string":"0%"},"spam_count":0,"spam_rate":{"float":0,"string":"0%"},"hard_bounces_count":0,"hard_bounce_rate":{"float":0,"string":"0%"},"soft_bounces_count":0,"soft_bounce_rate":{"float":0,"string":"0%"}},"created_at":"2022-12-20 59 | 19:28:46","has_banned_content":false,"qualified_subscribers_count":1},{"id":"75230383331869729","name":"test 60 | automation 2","enabled":true,"trigger_data":{"track_ecommerce":false,"repeatable":true,"valid":true},"steps":[{"id":"75230414735672857","type":"action","parent_id":null,"complete":true,"broken":false,"created_at":"2022-12-22 61 | 21:41:54","updated_at":"2022-12-22 21:42:06","action_type":"copy_to_group","group_id":"75138838590129612","group_name":"SMmwGofyQP","description":"Copy 62 | to a group"}],"triggers":[{"id":"75230409252668552","type":"subscriber_joins_group","group_id":"75011449370445335","group":{"id":"75011449370445335","name":"My 63 | Group","url":"https:\/\/dashboard.mailerlite.com\/subscribers?rules=W1t7Im9wZXJhdG9yIjoiaW5fYW55IiwiY29uZGl0aW9uIjoiZ3JvdXBzIiwiYXJncyI6WyJncm91cHMiLFsiNzUwMTE0NDkzNzA0NDUzMzUiXV19XV0%3D"},"exclude_group_ids":[],"excluded_groups":[],"broken":false}],"complete":true,"broken":false,"warnings":[],"emails_count":0,"first_email_screenshot_url":null,"stats":{"completed_subscribers_count":4,"subscribers_in_queue_count":0,"bounce_rate":{"float":0,"string":"0%"},"click_to_open_rate":{"float":0,"string":"0%"},"sent":0,"opens_count":0,"unique_opens_count":null,"open_rate":{"float":0,"string":"0%"},"clicks_count":0,"unique_clicks_count":null,"click_rate":{"float":0,"string":"0%"},"unsubscribes_count":0,"unsubscribe_rate":{"float":0,"string":"0%"},"spam_count":0,"spam_rate":{"float":0,"string":"0%"},"hard_bounces_count":0,"hard_bounce_rate":{"float":0,"string":"0%"},"soft_bounces_count":0,"soft_bounce_rate":{"float":0,"string":"0%"}},"created_at":"2022-12-22 64 | 21:41:24","has_banned_content":false,"qualified_subscribers_count":0}],"links":{"first":"https:\/\/connect.mailerlite.com\/api\/automations?page=1","last":"https:\/\/connect.mailerlite.com\/api\/automations?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"links":[{"url":null,"label":"« 65 | Previous","active":false},{"url":"https:\/\/connect.mailerlite.com\/api\/automations?page=1","label":"1","active":true},{"url":null,"label":"Next 66 | »","active":false}],"path":"https:\/\/connect.mailerlite.com\/api\/automations","per_page":10,"to":2,"total":2,"total_unfiltered":2}}' 67 | recorded_at: Fri, 23 Dec 2022 12:28:35 GMT 68 | recorded_with: VCR 6.1.0 69 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'simplecov' 4 | SimpleCov.start 5 | require 'mailerlite' 6 | # This file was generated by the `rspec --init` command. Conventionally, all 7 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. 8 | # The generated `.rspec` file contains `--require spec_helper` which will cause 9 | # this file to always be loaded, without a need to explicitly require it in any 10 | # files. 11 | # 12 | # Given that it is always loaded, you are encouraged to keep this file as 13 | # light-weight as possible. Requiring heavyweight dependencies from this file 14 | # will add to the boot time of your test suite on EVERY test run, even for an 15 | # individual file that may not need all of that loaded. Instead, consider making 16 | # a separate helper file that requires the additional dependencies and performs 17 | # the additional setup, and require it from the spec files that actually need 18 | # it. 19 | # 20 | # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 21 | RSpec.configure do |config| 22 | # rspec-expectations config goes here. You can use an alternate 23 | # assertion/expectation library such as wrong or the stdlib/minitest 24 | # assertions if you prefer. 25 | config.expect_with :rspec do |expectations| 26 | # This option will default to `true` in RSpec 4. It makes the `description` 27 | # and `failure_message` of custom matchers include text for helper methods 28 | # defined using `chain`, e.g.: 29 | # be_bigger_than(2).and_smaller_than(4).description 30 | # # => "be bigger than 2 and smaller than 4" 31 | # ...rather than: 32 | # # => "be bigger than 2" 33 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 34 | end 35 | 36 | # rspec-mocks config goes here. You can use an alternate test double 37 | # library (such as bogus or mocha) by changing the `mock_with` option here. 38 | config.mock_with :rspec do |mocks| 39 | # Prevents you from mocking or stubbing a method that does not exist on 40 | # a real object. This is generally recommended, and will default to 41 | # `true` in RSpec 4. 42 | mocks.verify_partial_doubles = true 43 | end 44 | 45 | # This option will default to `:apply_to_host_groups` in RSpec 4 (and will 46 | # have no way to turn it off -- the option exists only for backwards 47 | # compatibility in RSpec 3). It causes shared context metadata to be 48 | # inherited by the metadata hash of host groups and examples, rather than 49 | # triggering implicit auto-inclusion in groups with matching metadata. 50 | config.shared_context_metadata_behavior = :apply_to_host_groups 51 | 52 | # The settings below are suggested to provide a good initial experience 53 | # with RSpec, but feel free to customize to your heart's content. 54 | # # This allows you to limit a spec run to individual examples or groups 55 | # # you care about by tagging them with `:focus` metadata. When nothing 56 | # # is tagged with `:focus`, all examples get run. RSpec also provides 57 | # # aliases for `it`, `describe`, and `context` that include `:focus` 58 | # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. 59 | # config.filter_run_when_matching :focus 60 | # 61 | # # Allows RSpec to persist some state between runs in order to support 62 | # # the `--only-failures` and `--next-failure` CLI options. We recommend 63 | # # you configure your source control system to ignore this file. 64 | # config.example_status_persistence_file_path = "spec/examples.txt" 65 | # 66 | # # Limits the available syntax to the non-monkey patched syntax that is 67 | # # recommended. For more details, see: 68 | # # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode 69 | # config.disable_monkey_patching! 70 | # 71 | # # This setting enables warnings. It's recommended, but in some cases may 72 | # # be too noisy due to issues in dependencies. 73 | # config.warnings = true 74 | # 75 | # # Many RSpec users commonly either run the entire suite or an individual 76 | # # file, and it's useful to allow more verbose output when running an 77 | # # individual spec file. 78 | # if config.files_to_run.one? 79 | # # Use the documentation formatter for detailed output, 80 | # # unless a formatter has already been configured 81 | # # (e.g. via a command-line flag). 82 | # config.default_formatter = "doc" 83 | # end 84 | # 85 | # # Print the 10 slowest examples and example groups at the 86 | # # end of the spec run, to help surface which specs are running 87 | # # particularly slow. 88 | # config.profile_examples = 10 89 | # 90 | # # Run specs in random order to surface order dependencies. If you find an 91 | # # order dependency and want to debug it, you can fix the order by providing 92 | # # the seed, which is printed after each run. 93 | # # --seed 1234 94 | # config.order = :random 95 | # 96 | # # Seed global randomization in this process using the `--seed` CLI option. 97 | # # Setting this allows you to use `--seed` to deterministically reproduce 98 | # # test failures related to randomization by passing the same `--seed` value 99 | # # as the one that triggered the failure. 100 | # Kernel.srand config.seed 101 | end 102 | -------------------------------------------------------------------------------- /spec/campaigns_rspec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Import the RSpec and VCR gems 4 | require 'spec_helper' 5 | require 'vcr' 6 | require 'json' 7 | 8 | # require "webmock/rspec" 9 | # Import the `Campaigns` class 10 | 11 | # Configure VCR to save and replay HTTP requests 12 | VCR.configure do |config| 13 | config.cassette_library_dir = './fixtures' 14 | config.hook_into :webmock 15 | config.filter_sensitive_data('') do |interaction| 16 | interaction.request.headers['Authorization'][0] 17 | end 18 | end 19 | 20 | # Set up the test for the `Campaigns` class 21 | RSpec.describe MailerLite::Campaigns do 22 | let(:client) { MailerLite::Client.new } 23 | let(:campaigns) { described_class.new(client: client) } 24 | 25 | describe '#get' do 26 | # Use VCR to record and replay the HTTP request 27 | it 'returns a list of Campaigns' do 28 | VCR.use_cassette('campaigns/get') do 29 | response = campaigns.get( 30 | filter: { 31 | status: 'sent', 32 | type: 'regular' 33 | } 34 | ) 35 | body = JSON.parse(response.body) 36 | expect(response.status).to eq 200 37 | expect(body['data']).to be_an Array 38 | end 39 | end 40 | end 41 | 42 | describe '#create' do 43 | # Use VCR to record and replay the HTTP request 44 | it 'creates a new campaign' do 45 | VCR.use_cassette('campaigns/create') do 46 | response = campaigns.create(name: 'test_campaign', 47 | type: 'regular', 48 | emails: [{ 49 | subject: 'test subject', 50 | from: 'sdk@mailerlite.com', 51 | from_name: 'user' 52 | }]) 53 | body = JSON.parse(response.body) 54 | expect(response.status).to eq 201 55 | expect(Integer(body['data']['id'])).to be_a Integer 56 | end 57 | end 58 | end 59 | describe '#update' do 60 | # Use VCR to record and replay the HTTP request 61 | it 'updates a new campaign' do 62 | VCR.use_cassette('campaigns/update') do 63 | response = campaigns.update( 64 | campaign_id: 74_917_804_992_628_332, 65 | name: 'test_campaign1', 66 | type: 'regular', 67 | emails: [{ 68 | subject: 'testsubject1', 69 | from: 'sdk@mailerlite.com', 70 | from_name: 'user', 71 | content: ' 72 | 73 | 74 | This is a test email 75 | 76 | ' 77 | }] 78 | ) 79 | body = JSON.parse(response.body) 80 | expect(response.status).to eq 200 81 | expect(Integer(body['data']['id'])).to be_a Integer 82 | end 83 | end 84 | end 85 | 86 | describe '#fetch' do 87 | # Use VCR to record and replay the HTTP request 88 | it 'fetches a campaign' do 89 | VCR.use_cassette('campaigns/fetch') do 90 | response = campaigns.fetch(74_917_804_992_628_332) 91 | body = JSON.parse(response.body) 92 | expect(response.status).to eq 200 93 | expect(Integer(body['data']['id'])).to be_a Integer 94 | expect(Integer(body['data']['account_id'])).to be_a Integer 95 | end 96 | end 97 | end 98 | 99 | describe '#schedule' do 100 | # Use VCR to record and replay the HTTP request 101 | it 'schedules a campaign' do 102 | VCR.use_cassette('campaigns/schedule') do 103 | response = campaigns.schedule( 104 | campaign_id: 75_323_121_649_846_116, 105 | delivery: 'scheduled', 106 | schedule: { date: '2022-12-31', hours: '22', minutes: '00' } 107 | ) 108 | body = JSON.parse(response.body) 109 | expect(response.status).to eq 200 110 | expect(body['data']['status']).to eq 'ready' 111 | expect(Integer(body['data']['account_id'])).to be_a Integer 112 | expect(Integer(body['data']['id'])).to be_a Integer 113 | end 114 | end 115 | end 116 | 117 | describe '#activity' do 118 | # Use VCR to record and replay the HTTP request 119 | it 'gets subscriber activity of a campaign' do 120 | VCR.use_cassette('campaigns/activity') do 121 | response = campaigns.activity( 122 | campaign_id: 75_037_917_434_611_569, 123 | filter: { 124 | type: 'opened' 125 | } 126 | ) 127 | body = JSON.parse(response.body) 128 | expect(response.status).to eq 200 129 | expect(body['data']).to be_a Array 130 | end 131 | end 132 | end 133 | 134 | describe '#languages' do 135 | # Use VCR to record and replay the HTTP request 136 | it 'gets subscriber languages of a campaign' do 137 | VCR.use_cassette('campaigns/languages') do 138 | response = campaigns.languages 139 | body = JSON.parse(response.body) 140 | expect(response.status).to eq 200 141 | expect(body['data']).to be_a Array 142 | end 143 | end 144 | end 145 | 146 | describe '#delete' do 147 | # Use VCR to record and replay the HTTP request 148 | it 'deletes a campaign' do 149 | VCR.use_cassette('campaigns/delete') do 150 | response = campaigns.delete(74_917_804_992_628_332) 151 | expect(response.status).to eq 204 152 | end 153 | end 154 | end 155 | end 156 | -------------------------------------------------------------------------------- /lib/mailerlite/subscribers/subscribers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the subscribers from MailerLite API. 5 | class Subscribers 6 | attr_reader :client 7 | 8 | # Inits the `Subscribers` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of subscribers that match the specified filter criteria. 16 | # 17 | # @param filter[:status] [Array] the status of the subscribers to include in the results 18 | # @param limit [Integer] the maximum number of subscribers to return 19 | # @param page [Integer] the page number of the results to return 20 | # @return [HTTP::Response] the response from the API 21 | def fetch(filter:, limit: nil, page: nil) 22 | params = { 'filter[status]' => filter[:status] } 23 | 24 | params['limit'] = limit if limit 25 | params['page'] = page if page 26 | uri = URI("#{MAILERLITE_API_URL}/subscribers") 27 | uri.query = URI.encode_www_form(params.compact) 28 | client.http.get(uri) 29 | end 30 | 31 | # Creates a new subscriber with the specified details. 32 | # 33 | # @param email [String] the email address of the new subscriber 34 | # @param fields [Hash] a hash of custom fields and their values for the subscriber 35 | # @param groups [Array] an array of group IDs to add the subscriber to 36 | # @param status [String] the status of the new subscriber 37 | # @param subscribed_at [DateTime] the date and time when the subscriber was added 38 | # @param ip_address [String] the IP address of the subscriber 39 | # @param opted_in_at [DateTime] the date and time when the subscriber confirmed their subscription 40 | # @param optin_ip [String] the IP address of the subscriber when they confirmed their subscription 41 | # @param unsubscribed_at [DateTime] the date and time when the subscriber was unsubscribed 42 | # @return [HTTP::Response] the response from the API 43 | def create(email:, fields: nil, groups: nil, status: nil, subscribed_at: nil, ip_address: nil, opted_in_at: nil, optin_ip: nil, unsubscribed_at: nil) 44 | params = { 'email' => email } 45 | 46 | params['fields'] = fields if fields 47 | params['groups'] = groups if groups 48 | params['status'] = status if status 49 | params['subscribed_at'] = subscribed_at if subscribed_at 50 | params['ip_address'] = ip_address if ip_address 51 | params['opted_in_at'] = opted_in_at if opted_in_at 52 | params['optin_ip'] = optin_ip if optin_ip 53 | params['unsubscribed_at'] = unsubscribed_at if unsubscribed_at 54 | 55 | client.http.post("#{MAILERLITE_API_URL}/subscribers", json: params.compact) 56 | end 57 | 58 | # Updates an existing subscriber with the specified details. 59 | # 60 | # @param subscriber_id [String] the ID of the subscriber to update 61 | # @param email [String] the email address of the new subscriber 62 | # @param fields [Hash] a hash of custom fields and their values for the subscriber 63 | # @param groups [Array] an array of group IDs to add the subscriber to 64 | # @param status [String] the status of the new subscriber 65 | # @param subscribed_at [DateTime] the date and time when the subscriber was added 66 | # @param ip_address [String] the IP address of the subscriber 67 | # @param opted_in_at [DateTime] the date and time when the subscriber confirmed their subscription 68 | # @param optin_ip [String] the IP address of the subscriber when they confirmed their subscription 69 | # @param unsubscribed_at [DateTime] the date and time when the subscriber was unsubscribed 70 | # @return [HTTP::Response] the response from the API 71 | def update(subscriber_id, email: nil, fields: nil, groups: nil, status: nil, subscribed_at: nil, ip_address: nil, opted_in_at: nil, optin_ip: nil, unsubscribed_at: nil) 72 | params = {} 73 | 74 | params['email'] = email if email 75 | params['fields'] = fields if fields 76 | params['groups'] = groups if groups 77 | params['status'] = status if status 78 | params['subscribed_at'] = subscribed_at if subscribed_at 79 | params['ip_address'] = ip_address if ip_address 80 | params['opted_in_at'] = opted_in_at if opted_in_at 81 | params['optin_ip'] = optin_ip if optin_ip 82 | params['unsubscribed_at'] = unsubscribed_at if unsubscribed_at 83 | 84 | client.http.put("#{MAILERLITE_API_URL}/subscribers/#{subscriber_id}", json: params.compact) 85 | end 86 | 87 | # Returns the details of the specified subscribers 88 | # 89 | # @param subscriber_id [String] the ID of the subscriber to get 90 | # @return [HTTP::Response] the response from the API 91 | def get(subscriber_id) 92 | client.http.get("#{MAILERLITE_API_URL}/subscribers/#{subscriber_id}") 93 | end 94 | 95 | # Returns the details of the specified subscribers 96 | # 97 | # @param import_id [String] the ID of the import to fetch report 98 | # @return [HTTP::Response] the response from the API 99 | def get_single_import(import_id) 100 | client.http.get("#{MAILERLITE_API_URL}/subscribers/import/#{import_id}") 101 | end 102 | 103 | # Returns the total number of subscribers in the MailerLite account. 104 | # 105 | # @return [HTTP::Response] the response from the API 106 | def fetch_count 107 | client.http.get("#{MAILERLITE_API_URL}/subscribers/?limit=0") 108 | end 109 | 110 | # Deletes the specified subscriber. 111 | # 112 | # @param subscriber_id [String] the ID of the subscriber to delete 113 | # @return [HTTP::Response] the response from the API 114 | def delete(subscriber_id) 115 | client.http.delete("#{MAILERLITE_API_URL}/subscribers/#{subscriber_id}") 116 | end 117 | 118 | # Forgets the specified subscriber. 119 | # 120 | # @param subscriber_id [String] the ID of the subscriber to forget 121 | # @return [HTTP::Response] the response from the API 122 | def forget(subscriber_id) 123 | client.http.post("#{MAILERLITE_API_URL}/subscribers/#{subscriber_id}/forget") 124 | end 125 | end 126 | end 127 | -------------------------------------------------------------------------------- /lib/mailerlite/campaigns/campaigns.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MailerLite 4 | # This is a class for manipulating the Campaigns from MailerLite API. 5 | class Campaigns 6 | attr_reader :client 7 | 8 | # Inits the `Campaigns` class with the specified `client`. 9 | # 10 | # @param client [MailerLite::Client] the `Client` instance to use 11 | def initialize(client: MailerLite::Client.new) 12 | @client = client 13 | end 14 | 15 | # Returns a list of Campaigns that match the specified filter criteria. 16 | # 17 | # @param filter[:status,:type] [String] the status of the Campaigns to include in the results, must be one of [sent, draft, ready], Defaults to ready. 18 | # The filter type of the Campaigns to include in the results, must be one of [regular, ab, resend, rss], Defaults to all 19 | # @param limit [Integer] the maximum number of Campaigns to return 20 | # @param page [Integer] the page number of the results to return 21 | # @return [HTTP::Response] the response from the API 22 | def get(filter:, limit: nil, page: nil) 23 | params = { 'filter[status]' => filter[:status] } 24 | params['filter[type]'] = filter[:type] if filter.key?(:type) 25 | params['limit'] = limit if limit 26 | params['page'] = page if page 27 | uri = URI("#{MAILERLITE_API_URL}/campaigns") 28 | uri.query = URI.encode_www_form(params.compact) 29 | client.http.get(uri) 30 | end 31 | 32 | # Creates a new campaign with the specified details. 33 | # 34 | # @param name [String] Maximum string length of 255 characters 35 | # @param language_id [integer] Used to define the language in the unsubscribe template. Must be a valid language id. Defaults to english 36 | # @param type [String] Must be one of the following: regular, ab, resend. Type resend is only available for accounts on growing or advanced plans 37 | # @param emails [Array] Must contain 1 email object item 38 | # @param groups [Array] Must contain valid group ids belonging to the account 39 | # @param segments [Array] Must contain valid segment ids belonging to the account. If both groups and segments are provided, only segments are used 40 | # @param ab_settings [Array] only if type is ab - All items of the array are required 41 | # @param resend_settings [:test_type,:select_winner_by,:b_value] https://developers.mailerlite.com/docs/campaigns.html#create-a-campaign 42 | # @return [HTTP::Response] the response from the API 43 | def create(name:, type:, emails:, language_id: nil, groups: nil, segments: nil, ab_settings: nil, resend_settings: nil) 44 | params = { 'name' => name } 45 | params['type'] = type 46 | params['emails'] = emails 47 | params['language_id'] = language_id if language_id 48 | params['groups'] = groups if groups 49 | params['segments'] = segments if segments 50 | case type 51 | when 'ab' 52 | params['ab_settings'] = { 53 | test_type: ab_settings[:test_type], 54 | select_winner_by: ab_settings[:select_winner_by], 55 | after_time_amount: ab_settings[:after_time_amount], 56 | after_time_unit: ab_settings[:after_time_unit], 57 | test_split: ab_settings[:test_split] 58 | } 59 | case ab_settings[:test_type] 60 | when 'subject' 61 | params['ab_settings']['b_value'] = { 62 | subject: ab_settings[:b_value][:subject] 63 | } 64 | 65 | when 'sender' 66 | params['ab_settings']['b_value'] = { 67 | from_name: ab_settings[:b_value][:from_name], 68 | from: ab_settings[:b_value][:from] 69 | } 70 | end 71 | when 'resend' 72 | params['resend_settings'] = { 73 | test_type: resend_settings[:test_type], 74 | select_winner_by: resend_settings[:select_winner_by], 75 | b_value: { 76 | subject: resend_settings[:b_value][:subject] 77 | } 78 | } 79 | end 80 | 81 | client.http.post("#{MAILERLITE_API_URL}/campaigns", body: params.compact.to_json) 82 | end 83 | 84 | # Update a new campaign with the specified details. 85 | # 86 | # @param campaign_id [Integer] the ID of the campaign to update 87 | # @param name [String] Maximum string length of 255 characters 88 | # @param language_id [integer] Used to define the language in the unsubscribe template. Must be a valid language id. Defaults to english 89 | # @param type [String] Must be one of the following: regular, ab, resend. Type resend is only available for accounts on growing or advanced plans 90 | # @param emails [Array] Must contain 1 email object item 91 | # @param groups [Array] Must contain valid group ids belonging to the account 92 | # @param segments [Array] Must contain valid segment ids belonging to the account. If both groups and segments are provided, only segments are used 93 | # @param ab_settings [Array] only if type is ab - All items of the array are required 94 | # @param resend_settings [:test_type,:select_winner_by,:b_value] https://developers.mailerlite.com/docs/campaigns.html#update-campaign 95 | # @return [HTTP::Response] the response from the API 96 | def update(campaign_id:, name:, type:, emails:, language_id: nil, groups: nil, segments: nil, ab_settings: nil, resend_settings: nil) 97 | params = { 'name' => name } 98 | params['emails'] = emails 99 | params['language_id'] = language_id if language_id 100 | params['groups'] = groups if groups 101 | params['segments'] = segments if segments 102 | case type 103 | when 'ab' 104 | params['ab_settings'] = { 105 | test_type: ab_settings[:test_type], 106 | select_winner_by: ab_settings[:select_winner_by], 107 | after_time_amount: ab_settings[:after_time_amount], 108 | after_time_unit: ab_settings[:after_time_unit], 109 | test_split: ab_settings[:test_split] 110 | } 111 | case ab_settings[:test_type] 112 | when 'subject' 113 | params['ab_settings']['b_value'] = { 114 | subject: ab_settings[:b_value][:subject] 115 | } 116 | 117 | when 'sender' 118 | params['ab_settings']['b_value'] = { 119 | from_name: ab_settings[:b_value][:from_name], 120 | from: ab_settings[:b_value][:from] 121 | } 122 | 123 | end 124 | when 'resend' 125 | params['resend_settings'] = { 126 | test_type: resend_settings[:test_type], 127 | select_winner_by: resend_settings[:select_winner_by], 128 | b_value: { 129 | subject: resend_settings[:b_value][:subject] 130 | } 131 | } 132 | 133 | end 134 | 135 | client.http.put("#{MAILERLITE_API_URL}/campaigns/#{campaign_id}", body: params.compact.to_json) 136 | end 137 | 138 | # Schedules the specified campaign. 139 | # 140 | # @param campaign_id [Integer] the ID of the campaign to schedule 141 | # @param delivery [String] yes unless campaign type is rss Must be one of the following: instant, scheduled, timezone_based 142 | # @param schedule[:date,:hours,:minutes,:timezone_id] [Array] campaign schedule 143 | # @param resend[:delivery,:date,:hours,:minutes,:timezone_id] [String] resend settings 144 | # https://developers.mailerlite.com/docs/campaigns.html#schedule-a-campaign 145 | # @return [HTTP::Response] the response from the API 146 | def schedule(campaign_id:, delivery:, schedule: nil, resend: nil) 147 | params = {} 148 | params['delivery'] = delivery if delivery 149 | if %w[scheduled timezone_based].include?(delivery) && schedule 150 | params['schedule'] = {} 151 | params['schedule']['date'] = schedule[:date] if (delivery == 'scheduled') && schedule.key?(:date) 152 | params['schedule']['hours'] = schedule[:hours] if schedule.key?(:hours) 153 | params['schedule']['minutes'] = schedule[:minutes] if schedule.key?(:minutes) 154 | params['schedule']['timezone_id'] = schedule[:timezone_id] if schedule.key?(:timezone_id) 155 | end 156 | params['resend'] = {} if resend 157 | params['resend']['delivery'] = resend[:delivery] if resend&.key?(:delivery) 158 | params['resend']['date'] = resend[:date] if resend&.key?(:date) 159 | params['resend']['hours'] = resend[:hours] if resend&.key?(:hours) 160 | params['resend']['minutes'] = resend[:minutes] if resend&.key?(:minutes) 161 | params['resend']['timezone_id'] = resend[:timezone_id] if resend&.key?(:timezone_id) 162 | 163 | client.http.post("#{MAILERLITE_API_URL}/campaigns/#{campaign_id}/schedule", body: params.compact.to_json) 164 | end 165 | 166 | # Returns the details of the specified Campaigns 167 | # 168 | # @param campaign_id [String] the ID of the campaign to fetch 169 | # @return [HTTP::Response] the response from the API 170 | def fetch(campaign_id) 171 | client.http.get("#{MAILERLITE_API_URL}/campaigns/#{campaign_id}") 172 | end 173 | 174 | # Cancels the specified campaign. 175 | # 176 | # @param campaign_id [String] the ID of the campaign to delete 177 | # @return [HTTP::Response] the response from the API 178 | def cancel(campaign_id) 179 | client.http.post("#{MAILERLITE_API_URL}/campaigns/#{campaign_id}/cancel") 180 | end 181 | 182 | # Deletes the specified campaign. 183 | # 184 | # @param campaign_id [String] the ID of the campaign to delete 185 | # @return [HTTP::Response] the response from the API 186 | def delete(campaign_id) 187 | client.http.delete("#{MAILERLITE_API_URL}/campaigns/#{campaign_id}") 188 | end 189 | 190 | # activity the subscriber activity for specified campaign 191 | # 192 | # @param campaign_id [Integer] the ID of the campaign to activity 193 | # @param filter[:type,:search] [String] specify filters 194 | # @param limit [Integer] the maximum number of campaigns to return 195 | # @param page [Integer] the page number of the results to return 196 | # https://developers.mailerlite.com/docs/campaigns.html#get-subscribers-activity-of-a-sent-campaign 197 | # @return [HTTP::Response] the response from the API 198 | def activity(campaign_id:, filter: nil, page: nil, limit: nil, sort: nil) 199 | params = {} 200 | params['filter'] = {} if filter 201 | params['filter']['type'] = filter[:type] if filter.key?(:type) 202 | params['filter']['search'] = filter[:search] if filter.key?(:search) 203 | params['page'] = page if page 204 | params['limit'] = limit if limit 205 | params['sort'] = sort if sort 206 | client.http.post("#{MAILERLITE_API_URL}/campaigns/#{campaign_id}/reports/subscriber-activity", body: params.compact.to_json) 207 | end 208 | 209 | # Get a list of all campaign languages available 210 | # 211 | # @return [HTTP::Response] the response from the API 212 | def languages 213 | client.http.get("#{MAILERLITE_API_URL}/campaigns/languages") 214 | end 215 | end 216 | end 217 | -------------------------------------------------------------------------------- /fixtures/campaigns/schedule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://connect.mailerlite.com/api/campaigns/75323121649846116/schedule 6 | body: 7 | encoding: UTF-8 8 | string: '{"delivery":"scheduled","schedule":{"date":"2022-12-31","hours":"22","minutes":"00"}}' 9 | headers: 10 | Authorization: 11 | - "" 12 | User-Agent: 13 | - MailerLite-client-ruby/0.1.1 14 | Accept: 15 | - application/json 16 | Content-Type: 17 | - application/json 18 | Connection: 19 | - close 20 | Host: 21 | - connect.mailerlite.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Fri, 23 Dec 2022 22:18:04 GMT 29 | Content-Type: 30 | - application/json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Cache-Control: 36 | - no-cache, private 37 | X-Locale: 38 | - en 39 | X-Ratelimit-Limit: 40 | - '120' 41 | X-Ratelimit-Remaining: 42 | - '119' 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Strict-Transport-Security: 46 | - max-age=15724800; includeSubDomains 47 | Cf-Cache-Status: 48 | - DYNAMIC 49 | Server: 50 | - cloudflare 51 | Cf-Ray: 52 | - 77e4788f5f71d1e8-MCT 53 | body: 54 | encoding: UTF-8 55 | string: '{"data":{"id":"75323121649846116","account_id":"252151","name":"Test 56 | Campaign 2","type":"regular","status":"ready","missing_data":[],"settings":{"track_opens":"1","use_google_analytics":"0","ecommerce_tracking":"0"},"filter":[],"filter_for_humans":[],"delivery_schedule":"scheduled","language_id":"4","created_at":"2022-12-23 57 | 22:15:26","updated_at":"2022-12-23 22:18:04","scheduled_for":"2022-12-31 22:00:00","queued_at":null,"started_at":null,"finished_at":null,"stopped_at":null,"default_email_id":"75323121669769061","emails":[{"id":"75323121669769061","account_id":"252151","emailable_id":"75323121649846116","emailable_type":"campaigns","type":"builder_rich_text","from":"sdk@mailerlite.com","from_name":"SDK 58 | account","name":null,"subject":"Test Campaign 2","content":"\n\n \n \n \n \n \n \n \n \n \n \n\n