twitter-ads 5.0.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +3 -4
  4. data/Rakefile +1 -2
  5. data/lib/twitter-ads.rb +10 -11
  6. data/lib/twitter-ads/account.rb +12 -12
  7. data/lib/twitter-ads/audiences/audience_intelligence.rb +3 -3
  8. data/lib/twitter-ads/audiences/tailored_audience.rb +12 -156
  9. data/lib/twitter-ads/campaign/app_list.rb +5 -5
  10. data/lib/twitter-ads/campaign/campaign.rb +7 -11
  11. data/lib/twitter-ads/campaign/funding_instrument.rb +6 -5
  12. data/lib/twitter-ads/campaign/iab_category.rb +2 -2
  13. data/lib/twitter-ads/campaign/line_item.rb +18 -21
  14. data/lib/twitter-ads/campaign/organic_tweet.rb +1 -5
  15. data/lib/twitter-ads/campaign/promotable_user.rb +5 -5
  16. data/lib/twitter-ads/campaign/targeting_criteria.rb +7 -7
  17. data/lib/twitter-ads/campaign/tweet.rb +7 -11
  18. data/lib/twitter-ads/client.rb +3 -4
  19. data/lib/twitter-ads/creative/account_media.rb +5 -5
  20. data/lib/twitter-ads/creative/cards_fetch.rb +8 -6
  21. data/lib/twitter-ads/creative/image_app_download_card.rb +5 -5
  22. data/lib/twitter-ads/creative/image_conversation_card.rb +5 -5
  23. data/lib/twitter-ads/creative/media_creative.rb +6 -5
  24. data/lib/twitter-ads/creative/media_library.rb +5 -5
  25. data/lib/twitter-ads/creative/poll_cards.rb +5 -5
  26. data/lib/twitter-ads/creative/promoted_account.rb +5 -9
  27. data/lib/twitter-ads/creative/promoted_tweet.rb +5 -9
  28. data/lib/twitter-ads/creative/scheduled_tweet.rb +7 -7
  29. data/lib/twitter-ads/creative/tweet_previews.rb +36 -0
  30. data/lib/twitter-ads/creative/video_app_download_card.rb +5 -5
  31. data/lib/twitter-ads/creative/video_conversation_card.rb +5 -5
  32. data/lib/twitter-ads/creative/video_website_card.rb +4 -4
  33. data/lib/twitter-ads/creative/website_card.rb +3 -3
  34. data/lib/twitter-ads/cursor.rb +2 -2
  35. data/lib/twitter-ads/enum.rb +128 -122
  36. data/lib/twitter-ads/error.rb +2 -2
  37. data/lib/twitter-ads/http/request.rb +6 -5
  38. data/lib/twitter-ads/http/response.rb +1 -1
  39. data/lib/twitter-ads/legacy.rb +1 -1
  40. data/lib/twitter-ads/measurement/app_event_tag.rb +3 -3
  41. data/lib/twitter-ads/measurement/web_event_tag.rb +3 -3
  42. data/lib/twitter-ads/resources/analytics.rb +38 -8
  43. data/lib/twitter-ads/resources/batch.rb +4 -4
  44. data/lib/twitter-ads/resources/dsl.rb +1 -1
  45. data/lib/twitter-ads/resources/persistence.rb +1 -1
  46. data/lib/twitter-ads/resources/resource.rb +2 -2
  47. data/lib/twitter-ads/settings/tax.rb +3 -3
  48. data/lib/twitter-ads/settings/user.rb +3 -3
  49. data/lib/twitter-ads/targeting/reach_estimate.rb +1 -1
  50. data/lib/twitter-ads/targeting_criteria/app_store_category.rb +3 -3
  51. data/lib/twitter-ads/targeting_criteria/behavior.rb +3 -3
  52. data/lib/twitter-ads/targeting_criteria/behavior_taxonomy.rb +3 -3
  53. data/lib/twitter-ads/targeting_criteria/device.rb +3 -3
  54. data/lib/twitter-ads/targeting_criteria/event.rb +3 -3
  55. data/lib/twitter-ads/targeting_criteria/interest.rb +3 -3
  56. data/lib/twitter-ads/targeting_criteria/language.rb +3 -3
  57. data/lib/twitter-ads/targeting_criteria/location.rb +3 -3
  58. data/lib/twitter-ads/targeting_criteria/network_operator.rb +3 -3
  59. data/lib/twitter-ads/targeting_criteria/platform.rb +3 -3
  60. data/lib/twitter-ads/targeting_criteria/platform_version.rb +3 -3
  61. data/lib/twitter-ads/targeting_criteria/tv_market.rb +3 -3
  62. data/lib/twitter-ads/targeting_criteria/tv_show.rb +3 -3
  63. data/lib/twitter-ads/utils.rb +2 -2
  64. data/lib/twitter-ads/version.rb +2 -2
  65. data/spec/quality_spec.rb +2 -2
  66. data/spec/shared/properties.rb +1 -1
  67. data/spec/spec_helper.rb +9 -8
  68. data/spec/support/helpers.rb +1 -1
  69. data/spec/twitter-ads/account_spec.rb +1 -1
  70. data/spec/twitter-ads/audiences/tailored_audience_spec.rb +1 -1
  71. data/spec/twitter-ads/campaign/app_list_spec.rb +1 -1
  72. data/spec/twitter-ads/campaign/line_item_spec.rb +1 -1
  73. data/spec/twitter-ads/campaign/reach_estimate_spec.rb +1 -1
  74. data/spec/twitter-ads/campaign/targeting_criteria_spec.rb +1 -1
  75. data/spec/twitter-ads/campaign/tweet_spec.rb +1 -1
  76. data/spec/twitter-ads/client_spec.rb +1 -1
  77. data/spec/twitter-ads/creative/account_media_spec.rb +1 -1
  78. data/spec/twitter-ads/creative/image_app_download_card_spec.rb +1 -1
  79. data/spec/twitter-ads/creative/image_conversation_card_spec.rb +1 -1
  80. data/spec/twitter-ads/creative/media_creative_spec.rb +1 -1
  81. data/spec/twitter-ads/creative/promoted_account_spec.rb +1 -1
  82. data/spec/twitter-ads/creative/promoted_tweet_spec.rb +1 -1
  83. data/spec/twitter-ads/creative/video_app_download_card_spec.rb +1 -1
  84. data/spec/twitter-ads/creative/video_conversation_card_spec.rb +1 -1
  85. data/spec/twitter-ads/creative/website_card_spec.rb +1 -1
  86. data/spec/twitter-ads/cursor_spec.rb +1 -1
  87. data/spec/twitter-ads/placements_spec.rb +1 -1
  88. data/spec/twitter-ads/utils_spec.rb +1 -1
  89. data/twitter-ads.gemspec +10 -6
  90. metadata +10 -25
  91. data/lib/twitter-ads/http/ton_upload.rb +0 -156
  92. data/spec/twitter-ads/http/ton_upload_spec.rb +0 -96
@@ -1,156 +0,0 @@
1
- # frozen_string_literal: true
2
- # Copyright (C) 2015 Twitter, Inc.
3
-
4
- module TwitterAds
5
-
6
- # Specialized request class for TON API uploads.
7
- class TONUpload
8
-
9
- DEFAULT_DOMAIN = 'https://ton.twitter.com'.freeze # @api private
10
- DEFAULT_RESOURCE = '/1.1/ton/bucket/'.freeze # @api private
11
- DEFAULT_BUCKET = 'ta_partner'.freeze # @api private
12
- DEFAULT_EXPIRE = (Time.now + 10 * 24 * 60 * 60).httpdate # @api private
13
- DEFAULT_CHUNK_SIZE = 64 # @api private
14
- SINGLE_UPLOAD_MAX = 1024 * 1024 * DEFAULT_CHUNK_SIZE # @api private
15
- # target response time (ref. https://github.com/twitterdev/twitter-ruby-ads-sdk/pull/161)
16
- RESPONSE_TIME_MAX = 5000 # @api private
17
-
18
- private_constant :DEFAULT_DOMAIN,
19
- :DEFAULT_RESOURCE,
20
- :DEFAULT_BUCKET,
21
- :DEFAULT_EXPIRE,
22
- :DEFAULT_CHUNK_SIZE,
23
- :SINGLE_UPLOAD_MAX,
24
- :RESPONSE_TIME_MAX
25
-
26
- # Creates a new TONUpload object instance.
27
- #
28
- # @example
29
- # request = TONUpload.new(client, '/path/to/file')
30
- #
31
- # @param client [Client] The Client object instance.
32
- # @param file_path [String] The path to the file to be uploaded.
33
- #
34
- # @since 0.3.0
35
- #
36
- # @return [TONUpload] The TONUpload request instance.
37
- def initialize(client, file_path, opts = {})
38
- @file_path = File.expand_path(file_path)
39
- unless File.exist?(file_path)
40
- raise ArgumentError.new("Error! The specified file does not exist. (#{file_path})")
41
- end
42
-
43
- @file_size = File.size(@file_path)
44
-
45
- @client = client
46
- @bucket = opts.delete(:bucket) || DEFAULT_BUCKET
47
- @options = opts
48
- self
49
- end
50
-
51
- # Executes the current TONUpload object.
52
- #
53
- # @example
54
- # request = TONUpload.new(client, '/path/to/file')
55
- # request.perform
56
- #
57
- # @since 0.3.0
58
- #
59
- # @return [String] The upload location provided by the TON API.
60
- def perform
61
- if @file_size < SINGLE_UPLOAD_MAX
62
- resource = "#{DEFAULT_RESOURCE}#{@bucket}"
63
- response = upload(resource, File.read(@file_path))
64
- response.headers['location'][0]
65
- else
66
- response = init_chunked_upload
67
- bytes_per_chunk_size = response.headers['x-ton-min-chunk-size'][0].to_i
68
- location = response.headers['location'][0]
69
-
70
- bytes_read = 0
71
- chunk_bytes = bytes_per_chunk_size * DEFAULT_CHUNK_SIZE
72
- File.open(@file_path) do |file|
73
- while bytes = file.read(chunk_bytes)
74
- bytes_start = bytes_read
75
- bytes_read += bytes.size
76
- upload_chunk(location, bytes, bytes_start, bytes_read) do |res|
77
- # Determines the chunk bytes based on response times
78
- response_time = res.headers['x-response-time'][0].to_f
79
- response_based_chunk_size =
80
- (DEFAULT_CHUNK_SIZE * (RESPONSE_TIME_MAX / response_time)).to_i
81
- next_chunk_size = [DEFAULT_CHUNK_SIZE, [1, response_based_chunk_size].max].min
82
- chunk_bytes = bytes_per_chunk_size * next_chunk_size
83
- end
84
- end
85
- end
86
-
87
- location.split('?')[0]
88
- end
89
- end
90
-
91
- # Returns an inspection string for the current object instance.
92
- #
93
- # @since 0.3.0
94
- #
95
- # @return [String] The object instance detail.
96
- def inspect
97
- "#<#{self.class.name}:0x#{object_id} bucket=\"#{@bucket}\" file=\"#{@file_path}\">"
98
- end
99
-
100
- private
101
-
102
- # performs a single chunk upload
103
- def upload(resource, bytes)
104
- headers = {
105
- 'x-ton-expires' => DEFAULT_EXPIRE,
106
- 'content-length' => @file_size,
107
- 'content-type' => content_type
108
- }
109
- TwitterAds::Request.new(
110
- @client, :post, resource, domain: DEFAULT_DOMAIN, headers: headers, body: bytes).perform
111
- end
112
-
113
- # initialization for a multi-chunk upload
114
- def init_chunked_upload
115
- headers = {
116
- 'x-ton-content-type' => content_type,
117
- 'x-ton-content-length' => @file_size,
118
- 'x-ton-expires' => DEFAULT_EXPIRE,
119
- 'content-length' => 0,
120
- 'content-type' => content_type
121
- }
122
- resource = "#{DEFAULT_RESOURCE}#{@bucket}?resumable=true"
123
- TwitterAds::Request.new(
124
- @client, :post, resource, domain: DEFAULT_DOMAIN, headers: headers).perform
125
- end
126
-
127
- # uploads a single chunk of a multi-chunk upload
128
- def upload_chunk(resource, bytes, bytes_start, bytes_read)
129
- headers = {
130
- 'content-type' => content_type,
131
- 'content-length' => bytes.size,
132
- 'content-range' => "bytes #{bytes_start}-#{bytes_read - 1}/#{@file_size}"
133
- }
134
- response = TwitterAds::Request.new(
135
- @client, :put, resource, domain: DEFAULT_DOMAIN, headers: headers, body: bytes).perform
136
-
137
- yield(response)
138
- response
139
- end
140
-
141
- def content_type
142
- @content_type ||= begin
143
- extension = File.extname(@file_path).downcase
144
- if extension == '.csv'
145
- 'text/csv'
146
- elsif extension == '.tsv'
147
- 'text/tab-separated-values'
148
- else
149
- 'text/plain'
150
- end
151
- end
152
- end
153
-
154
- end
155
-
156
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
- # Copyright (C) 2015 Twitter, Inc.
3
-
4
- require 'spec_helper'
5
- require 'tempfile'
6
-
7
- describe TwitterAds::TONUpload do
8
- before(:each) do
9
- stub_fixture(
10
- :post, :no_content, "#{TON_API}/1.1/ton/bucket/#{bucket_name}",
11
- headers: {
12
- 'location' => location_path
13
- }
14
- )
15
- stub_fixture(
16
- :post, :no_content, "#{TON_API}/1.1/ton/bucket/#{bucket_name}?resumable=true",
17
- headers: {
18
- 'location' => "#{location_path}?resumable=true&resumeId=1234567",
19
- 'x-ton-min-chunk-size' => '1048576'
20
- }
21
- )
22
- end
23
- let(:bucket_name) { 'ta_partner' }
24
- let(:location_path) { '/1.1/ton/data/ta_partner/123456789/tYfALUIK-F3ZMxj.txt' }
25
-
26
- around(:each) do |example|
27
- example.run
28
- file.unlink
29
- end
30
- let!(:file) do
31
- Tempfile.open(['', '.dat'], File.expand_path('../../../tmp/', __FILE__)) do |fp|
32
- fp.tap { |f| f.write(SecureRandom.random_bytes(file_size)) }
33
- end
34
- end
35
- let(:file_size) { 100 }
36
-
37
- let(:ton_upload) { described_class.new(client, file_path) }
38
- let(:client) do
39
- Client.new(
40
- Faker::Lorem.characters(15),
41
- Faker::Lorem.characters(40),
42
- "123456-#{Faker::Lorem.characters(40)}",
43
- Faker::Lorem.characters(40)
44
- )
45
- end
46
- let(:file_path) { file.path }
47
-
48
- describe '#initialize' do
49
-
50
- subject { ton_upload }
51
- it { is_expected.to be_an_instance_of described_class }
52
-
53
- context 'when the file path is invalid' do
54
- let(:file_path) { '/invalid/file/path' }
55
-
56
- it do
57
- expect { subject }.to raise_error ArgumentError
58
- end
59
- end
60
- end
61
-
62
- describe '#perform' do
63
- subject { ton_upload.perform }
64
-
65
- it 'should call TwitterAds::Request#perform exactly once' do
66
- expect_any_instance_of(TwitterAds::Request).to receive(:perform).once.and_call_original
67
- subject
68
- end
69
-
70
- it { is_expected.to eq '/1.1/ton/data/ta_partner/123456789/tYfALUIK-F3ZMxj.txt' }
71
-
72
- context 'when the file size is larger than 64MB' do
73
- before(:each) do
74
- allow(ton_upload).to receive(:upload_chunk)
75
- end
76
- let(:file_size) { 65 * 1024 * 1024 }
77
-
78
- it { is_expected.to eq '/1.1/ton/data/ta_partner/123456789/tYfALUIK-F3ZMxj.txt' }
79
- it 'should call TwitterAds::Request#perform exactly once' do
80
- expect(ton_upload).to receive(:upload_chunk).at_least(:twice)
81
- subject
82
- end
83
- end
84
- end
85
-
86
- describe '#inspect' do
87
- subject { ton_upload.inspect }
88
-
89
- it do
90
- is_expected.to include(described_class.name)
91
- is_expected.to include(ton_upload.object_id.to_s)
92
- is_expected.to include(bucket_name)
93
- is_expected.to include(file_path)
94
- end
95
- end
96
- end