codes 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 34b56b7948df3498826c2deed30e0b559ee3b0ae
4
- data.tar.gz: 8c1e4e68aaaae4125efefcc4a7e57e88927ec011
3
+ metadata.gz: 5de44a06df82ccf5f52fb7012beb8fbb45ea091f
4
+ data.tar.gz: 3815b7cafc3affe3801c642b72227326d6d89af9
5
5
  SHA512:
6
- metadata.gz: aa064ec5e1229d765f377227dd26f138e89e8fdcf8a48ebae235dbec31a4eb19e0ae65a9034097dfe9d347ffd56c4cd5793355e0b35831c76257cb75369e3f8b
7
- data.tar.gz: 45e3a769ce73b7ac8fa38e18fa2853d39fd77b10fe42102debb1790e76b12bbca30ee31285085e58634deffc45613906565e565fe68226b09fe8862a1f9d36ff
6
+ metadata.gz: 12a724b931a13c7d6a04a4f5fa6370fd6bd5a2d67d252e4bad9619b0e68aa36c3929bac652267577f70c94706ec43e8360f6ff6361f58737e24d03a48df585c4
7
+ data.tar.gz: 22e7597ee1a3f194f4e4943432f682e0022aa956344fc25196863d685dd3de8bd8cdd0a270cbb397cc55b7ffc86b76870b6678ff2933de427fd36119cdff7bb9
data/bin/codes CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.push File.expand_path("../../lib", __FILE__)
3
+ $:.push File.expand_path('../../lib', __FILE__)
4
4
 
5
5
  require 'codes'
6
6
  require 'commander'
@@ -17,6 +17,43 @@ class CodesApplication
17
17
  end
18
18
 
19
19
  def run
20
+ prepare_command
21
+
22
+ command :download do |c|
23
+ c.syntax = 'codes download [num]'
24
+ c.description = 'Download [num] new promo codes from iTunes Connect'
25
+
26
+ c.action do |args, options|
27
+ username options
28
+ number_of_codes = count(args)
29
+ apple_id = apple_id(options)
30
+ app_identifier = bundle_id(options, apple_id)
31
+ format = download_format options
32
+
33
+ Codes::CodesRunner.download(number_of_codes: number_of_codes, app_identifier: app_identifier, apple_id: apple_id, output_file_path: options.output_file, format: format, country: options.country)
34
+ end
35
+ end
36
+
37
+ command :display do |c|
38
+ c.syntax = 'codes display'
39
+ c.description = 'Display remaining number of promo codes from iTunes Connect'
40
+
41
+ c.action do |args, options|
42
+ username options
43
+ apple_id = apple_id(options)
44
+ app_identifier = bundle_id(options, apple_id)
45
+
46
+ Codes::CodesRunner.display(app_identifier: app_identifier, apple_id: apple_id, output_file_path: options.output_file, country: options.country)
47
+ end
48
+ end
49
+ default_command :download
50
+
51
+ run!
52
+ end
53
+
54
+ private
55
+
56
+ def prepare_command
20
57
  program :version, Codes::VERSION
21
58
  program :description, 'CLI for \'codes\' - Create promo codes for iOS Apps using the command line'
22
59
  program :help, 'Author', 'Felix Krause <codes@krausefx.com>'
@@ -34,85 +71,48 @@ class CodesApplication
34
71
  global_option '-f', '--format STRING', 'If specified, modifies the format of the output to the specified format'
35
72
  global_option '-X', '--verbose', "If specified, defines the default output. Similar to -f \'#{download_verbose_format}\'"
36
73
  global_option '-x', '--urls', 'If specified, includes a full URL for each code that can be used to redeem that code.'
74
+ end
37
75
 
76
+ def count(args)
77
+ [args[0].to_i, 1].max # minimum of 1 code
78
+ end
38
79
 
39
- command :download do |c|
40
- c.syntax = "codes download [num]"
41
- c.description = "Download [num] new promo codes from iTunes Connect"
42
-
43
- c.action do |args, options|
44
- user = username options
45
- number_of_codes = count(args)
46
- apple_id = apple_id(options)
47
- app_identifier = bundle_id(options, apple_id)
48
- format = download_format options
49
-
50
- Codes::CodesRunner.download(number_of_codes: number_of_codes, app_identifier: app_identifier, apple_id: apple_id, output_file_path: options.output_file, format: format, country: options.country)
51
- end
52
- end
53
-
54
- command :display do |c|
55
- c.syntax = "codes display"
56
- c.description = "Display remaining number of promo codes from iTunes Connect"
57
-
58
- c.action do |args, options|
59
- user = username options
60
- apple_id = apple_id(options)
61
- app_identifier = bundle_id(options, apple_id)
62
-
63
- Codes::CodesRunner.display(app_identifier: app_identifier, apple_id: apple_id, output_file_path: options.output_file, country: options.country)
64
- end
65
- end
66
- default_command :download
67
-
68
- def count(args)
69
- [args[0].to_i, 1].max # minimum of 1 code
70
- end
71
-
72
- def username(options)
73
- user = options.username
74
- user ||= ENV["CODES_USERNAME"]
75
- user ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
76
-
77
-
78
- CredentialsManager::PasswordManager.shared_manager(user) if user
80
+ def username(options)
81
+ user = options.username
82
+ user ||= ENV['CODES_USERNAME']
83
+ user ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
79
84
 
80
- user
81
- end
85
+ CredentialsManager::PasswordManager.shared_manager(user) if user
82
86
 
83
- def download_format(options)
84
- verbose = options.X || options.verbose
85
- urls = options.x || options.urls
86
- format = options.f || options.format
87
- # backward compatibility...
88
- if urls && !format
89
- format = "%c - %u"
90
- end
91
- if verbose && !format
92
- format = download_verbose_format
93
- end
94
- format
95
- end
87
+ user
88
+ end
96
89
 
97
- def bundle_id(options, apple_id)
98
- app_identifier = options.app_identifier
99
- app_identifier ||= ENV["CODES_APP_IDENTIFIER"]
100
- app_identifier ||= CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)
101
- app_identifier ||= (FastlaneCore::ItunesSearchApi.fetch(apple_id)['bundleId'] rescue nil) if apple_id
102
- app_identifier ||= ask("App Identifier (Bundle ID, e.g. com.krausefx.app): ")
103
- app_identifier
104
- end
90
+ def download_format(options)
91
+ verbose = options.X || options.verbose
92
+ urls = options.x || options.urls
93
+ format = options.f || options.format
94
+ # backward compatibility...
95
+ format = '%c - %u' if urls && !format
96
+ format = download_verbose_format if verbose && !format
97
+ format
98
+ end
105
99
 
106
- def apple_id(options)
107
- apple_id = options.apple_id
108
- apple_id ||= ENV["CODES_APP_ID"]
109
- end
100
+ def bundle_id(options, apple_id)
101
+ app_identifier = options.app_identifier
102
+ app_identifier ||= ENV['CODES_APP_IDENTIFIER']
103
+ app_identifier ||= CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)
104
+ app_identifier ||= (FastlaneCore::ItunesSearchApi.fetch(apple_id)['bundleId'] rescue nil) if apple_id
105
+ app_identifier ||= ask('App Identifier (Bundle ID, e.g. com.krausefx.app): ')
106
+ app_identifier
107
+ end
110
108
 
111
- run!
109
+ def apple_id(options)
110
+ apple_id = options.apple_id
111
+ apple_id ||= ENV['CODES_APP_ID']
112
+ apple_id
112
113
  end
113
114
  end
114
115
 
115
-
116
116
  begin
117
117
  FastlaneCore::UpdateChecker.start_looking_for_update('codes')
118
118
  CodesApplication.new.run
@@ -6,7 +6,7 @@ require 'codes/itunes_connect'
6
6
  require 'fastlane_core'
7
7
 
8
8
  module Codes
9
- Helper = FastlaneCore::Helper
9
+ Helper = FastlaneCore::Helper
10
10
 
11
11
  DependencyChecker.check_dependencies
12
12
  end
@@ -3,6 +3,7 @@ module Codes
3
3
  def self.download(args)
4
4
  Codes::ItunesConnect.new.download args
5
5
  end
6
+
6
7
  def self.display(args)
7
8
  Codes::ItunesConnect.new.display args
8
9
  end
@@ -2,30 +2,30 @@ require 'fastlane_core/itunes_connect/itunes_connect'
2
2
 
3
3
  module Codes
4
4
  class ItunesConnect < FastlaneCore::ItunesConnect
5
+ PROMO_URL = 'https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/wa/LCAppPage/viewPromoCodes?adamId=[[app_id]]&platform=[[platform]]'
6
+ CODE_URL = 'https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/redeemLandingPage?code=[[code]]'
5
7
 
6
- PROMO_URL = "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/wa/LCAppPage/viewPromoCodes?adamId=[[app_id]]&platform=[[platform]]"
7
- CODE_URL = "https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/redeemLandingPage?code=[[code]]"
8
-
8
+ # rubocop:disable Metrics/AbcSize
9
9
  def download(args)
10
10
  number_of_codes = args[:number_of_codes]
11
11
 
12
- code_or_codes = number_of_codes == 1 ? "code" : "codes"
13
- Helper.log.info "Downloading #{number_of_codes} promo #{code_or_codes}..."
12
+ code_or_codes = number_of_codes == 1 ? 'code' : 'codes'
13
+ Helper.log.info "Downloading #{number_of_codes} promo #{code_or_codes}..."
14
14
 
15
15
  fetch_app_data args
16
16
 
17
17
  # Use Pathname because it correctly handles the distinction between relative paths vs. absolute paths
18
18
  output_file_path = Pathname.new(args[:output_file_path]) if args[:output_file_path]
19
19
  output_file_path ||= Pathname.new(File.join(Dir.getwd, "#{@app_identifier || @app_id}_codes.txt"))
20
- raise "Insufficient permissions to write to output file".red if File.exists?(output_file_path) and not File.writable?(output_file_path)
21
- visit PROMO_URL.gsub("[[app_id]]", @app_id.to_s).gsub("[[platform]]", @platform)
20
+ fail 'Insufficient permissions to write to output file'.red if File.exist?(output_file_path) && !File.writable?(output_file_path)
21
+ visit PROMO_URL.gsub('[[app_id]]', @app_id.to_s).gsub('[[platform]]', @platform)
22
22
 
23
23
  begin
24
- text_fields = wait_for_elements("input[type=text]")
24
+ text_fields = wait_for_elements('input[type=text]')
25
25
  rescue
26
26
  raise "Could not open details page for app #{@app_identifier}. Are you sure you are using the correct apple account and have access to this app?".red
27
27
  end
28
- raise "There should only be a single text input field to specify the number of codes".red unless text_fields.count == 1
28
+ fail 'There should only be a single text input field to specify the number of codes'.red unless text_fields.count == 1
29
29
 
30
30
  text_fields.first.set(number_of_codes.to_s)
31
31
  click_next
@@ -33,83 +33,84 @@ module Codes
33
33
  # are there any errors ?
34
34
  errors = []
35
35
  begin
36
- errors = wait_for_elements("div[id=LCPurpleSoftwarePageWrapperErrorMessage]")
37
- rescue Exception
36
+ errors = wait_for_elements('div[id=LCPurpleSoftwarePageWrapperErrorMessage]')
37
+ rescue
38
38
  end
39
- raise errors.first.text.red unless errors.count == 0
39
+ fail errors.first.text.red unless errors.count == 0
40
40
 
41
- Helper.log.debug "Accepting the App Store Volume Custom Code Agreement"
42
- wait_for_elements("input[type=checkbox]").first.click
41
+ Helper.log.debug 'Accepting the App Store Volume Custom Code Agreement'
42
+ wait_for_elements('input[type=checkbox]').first.click
43
43
  click_next
44
44
 
45
45
  # the find(:xpath, "..") gets the parent element of the previous expression
46
46
  download_url = wait_for_elements("div[class='large-blue-rect-button']").first.find(:xpath, '..')['href']
47
47
 
48
48
  codes, request_date = download_codes(download_url)
49
-
49
+
50
50
  format = args[:format]
51
51
  codes = download_format(codes, format, request_date, app) if format
52
52
 
53
- bytes_written = File.write(output_file_path.to_s, codes, mode: "a+")
54
- Helper.log.warn "Could not write your codes to the codes.txt file, but you can still access them from iTunes Connect later" if bytes_written == 0
55
- Helper.log.info "Added generated codes to '#{output_file_path.to_s}'".green unless bytes_written == 0
53
+ bytes_written = File.write(output_file_path.to_s, codes, mode: 'a+')
54
+ Helper.log.warn 'Could not write your codes to the codes.txt file, but you can still access them from iTunes Connect later' if bytes_written == 0
55
+ Helper.log.info "Added generated codes to '#{output_file_path}'".green unless bytes_written == 0
56
56
 
57
57
  Helper.log.info "Your codes (requested #{request_date}) were successfully downloaded:".green
58
58
  puts codes
59
59
  end
60
+ # rubocop:enable Metrics/AbcSize
60
61
 
61
62
  def download_format(codes, format, request_date, app)
62
- format = format.gsub(/%([a-z])/, "%{\\1}") # %c => %{c}
63
-
64
- codes = codes.split("\n").map do |code|
65
- format % {
66
- c: code,
67
- b: app['bundleId'],
68
- d: request_date, # e.g. 20150520110716 / Cupertino timestamp...
69
- i: app['trackId'],
70
- n: "\'#{app['trackName']}\'",
71
- p: app_platform(app),
72
- u: CODE_URL.gsub("[[code]]", code)
73
- }
74
- end
75
- codes = codes.join("\n") + "\n"
63
+ format = format.gsub(/%([a-z])/, '%{\\1}') # %c => %{c}
64
+
65
+ codes = codes.split("\n").map do |code|
66
+ format % {
67
+ c: code,
68
+ b: app['bundleId'],
69
+ d: request_date, # e.g. 20150520110716 / Cupertino timestamp...
70
+ i: app['trackId'],
71
+ n: "\'#{app['trackName']}\'",
72
+ p: app_platform(app),
73
+ u: CODE_URL.gsub('[[code]]', code)
74
+ }
75
+ end
76
+ codes.join("\n") + "\n"
76
77
  end
77
78
 
78
79
  def app_platform(app)
79
- app['kind'] == "mac-software" ? "osx" : "ios"
80
+ app['kind'] == 'mac-software' ? 'osx' : 'ios'
80
81
  end
81
82
 
82
83
  def display(args)
83
- Helper.log.info "Displaying remaining number of codes promo"
84
+ Helper.log.info 'Displaying remaining number of codes promo'
84
85
 
85
86
  fetch_app_data args
86
87
 
87
88
  # Use Pathname because it correctly handles the distinction between relative paths vs. absolute paths
88
89
  output_file_path = Pathname.new(args[:output_file_path]) if args[:output_file_path]
89
90
  output_file_path ||= Pathname.new(File.join(Dir.getwd, "#{@app_identifier || @app_id}_codes_info.txt"))
90
- raise "Insufficient permissions to write to output file".red if File.exists?(output_file_path) and not File.writable?(output_file_path)
91
- visit PROMO_URL.gsub("[[app_id]]", @app_id.to_s).gsub("[[platform]]", @platform)
91
+ fail 'Insufficient permissions to write to output file'.red if File.exist?(output_file_path) && !File.writable?(output_file_path)
92
+ visit PROMO_URL.gsub('[[app_id]]', @app_id.to_s).gsub('[[platform]]', @platform)
92
93
 
93
94
  begin
94
- text_fields = wait_for_elements("input[type=text]")
95
+ text_fields = wait_for_elements('input[type=text]')
95
96
  rescue
96
97
  raise "Could not open details page for app #{app_identifier}. Are you sure you are using the correct apple account and have access to this app?".red
97
98
  end
98
- raise "There should only be a single text input field to specify the number of codes".red unless text_fields.count == 1
99
+ fail 'There should only be a single text input field to specify the number of codes'.red unless text_fields.count == 1
99
100
 
100
- remaining_divs = wait_for_elements("div#codes_0")
101
- raise "There should only be a single text div containing the number of remaining codes".red unless remaining_divs.count == 1
102
- remaining = remaining_divs.first.text.split(" ")[0]
101
+ remaining_divs = wait_for_elements('div#codes_0')
102
+ fail 'There should only be a single text div containing the number of remaining codes'.red unless remaining_divs.count == 1
103
+ remaining = remaining_divs.first.text.split(' ')[0]
103
104
 
104
- bytes_written = File.write(output_file_path.to_s, remaining, mode: "a+")
105
- Helper.log.warn "Could not write your codes to the codes_info.txt file, but you can still access them from iTunes Connect later" if bytes_written == 0
106
- Helper.log.info "Added information of quantity of remaining codes to '#{output_file_path.to_s}'".green unless bytes_written == 0
105
+ bytes_written = File.write(output_file_path.to_s, remaining, mode: 'a+')
106
+ Helper.log.warn 'Could not write your codes to the codes_info.txt file, but you can still access them from iTunes Connect later' if bytes_written == 0
107
+ Helper.log.info "Added information of quantity of remaining codes to '#{output_file_path}'".green unless bytes_written == 0
107
108
 
108
109
  puts remaining
109
110
  end
110
111
 
111
112
  def click_next
112
- wait_for_elements("input.continueActionButton").first.click
113
+ wait_for_elements('input.continueActionButton').first.click
113
114
  end
114
115
 
115
116
  def download_codes(url)
@@ -117,16 +118,16 @@ module Codes
117
118
  url = URI.join(host, url)
118
119
  Helper.log.debug "Downloading promo code file from #{url}"
119
120
 
120
- cookie_string = ""
121
+ cookie_string = ''
121
122
  page.driver.cookies.each do |key, cookie|
122
123
  cookie_string << "#{cookie.name}=#{cookie.value};"
123
124
  end
124
125
 
125
- page = open(url, "Cookie" => cookie_string)
126
- request_date = page.metas['content-disposition'][0].gsub(/.*filename=.*_(.*).txt/,"\\1")
126
+ page = open(url, 'Cookie' => cookie_string)
127
+ request_date = page.metas['content-disposition'][0].gsub(/.*filename=.*_(.*).txt/, '\\1')
127
128
  codes = page.read
128
129
 
129
- return codes, request_date
130
+ [codes, request_date]
130
131
  end
131
132
 
132
133
  private
@@ -138,8 +139,8 @@ module Codes
138
139
  @app_id = args[:apple_id]
139
140
  @app_id ||= (FastlaneCore::ItunesSearchApi.fetch_by_identifier(@app_identifier, @country)['trackId'] rescue nil)
140
141
 
141
- if @app_id.to_i == 0 or @app_identifier.to_s.length == 0
142
- raise "Could not find app using the following information: #{args}. Maybe the app is not in the store. Pass the Apple ID of the app as well!".red
142
+ if @app_id.to_i == 0 || @app_identifier.to_s.length == 0
143
+ fail "Could not find app using the following information: #{args}. Maybe the app is not in the store. Pass the Apple ID of the app as well!".red
143
144
  end
144
145
 
145
146
  app = FastlaneCore::ItunesSearchApi.fetch(@app_id, @country)
@@ -1,3 +1,3 @@
1
1
  module Codes
2
- VERSION = "0.4.0"
2
+ VERSION = '0.4.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-03 00:00:00.000000000 Z
11
+ date: 2015-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fastlane_core
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.15.2
19
+ version: 0.16.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 1.0.0
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: 0.15.2
29
+ version: 0.16.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.0
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: bundler
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -158,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
164
  version: '0'
159
165
  requirements: []
160
166
  rubyforge_project:
161
- rubygems_version: 2.4.5
167
+ rubygems_version: 2.4.6
162
168
  signing_key:
163
169
  specification_version: 4
164
170
  summary: Create promo codes for iOS Apps using the command line