atlantispro 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Atlantis.gemspec +3 -3
- data/Gemfile.lock +50 -0
- data/bin/{testflight → distribution} +1 -2
- data/lib/Atlantis/portal.rb +18 -9
- data/lib/Atlantis/portal/agent.rb +1 -197
- data/lib/Atlantis/portal/commands.rb +7 -5
- data/lib/Atlantis/portal/commands/devices.rb +4 -35
- data/lib/Atlantis/portal/commands/groups.rb +11 -0
- data/lib/Atlantis/portal/commands/login.rb +4 -4
- data/lib/Atlantis/portal/commands/logout.rb +4 -4
- data/lib/Atlantis/portal/commands/people.rb +5 -35
- data/lib/Atlantis/portal/crashlytics/crashlyticsservice.rb +315 -0
- data/lib/Atlantis/portal/helpers.rb +74 -1
- data/lib/Atlantis/portal/service.rb +46 -0
- data/lib/Atlantis/portal/testflight/testflightservice.rb +207 -0
- data/lib/Atlantis/version.rb +1 -1
- metadata +15 -10
- data/lib/Atlantis/portal/commands/invites.rb +0 -16
- data/lib/Atlantis/portal/commands/lists.rb +0 -36
- data/lib/Atlantis/portal/commands/teams.rb +0 -23
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
require 'security'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'logger'
|
6
|
+
require 'nokogiri'
|
7
|
+
|
8
|
+
module Atlantis
|
9
|
+
module Portal
|
10
|
+
class Service
|
11
|
+
attr_accessor :host, :arguments
|
12
|
+
|
13
|
+
def username
|
14
|
+
unless (arguments.username.nil?)
|
15
|
+
return arguments.username
|
16
|
+
end
|
17
|
+
|
18
|
+
account = security_account
|
19
|
+
|
20
|
+
return account.attributes['acct'] if account
|
21
|
+
end
|
22
|
+
|
23
|
+
def password
|
24
|
+
unless (arguments.password.nil?)
|
25
|
+
return arguments.password
|
26
|
+
end
|
27
|
+
|
28
|
+
account = security_account
|
29
|
+
|
30
|
+
return account.password if account
|
31
|
+
end
|
32
|
+
|
33
|
+
def security_account
|
34
|
+
pw = Security::InternetPassword.find(:server => self.host)
|
35
|
+
|
36
|
+
return pw
|
37
|
+
end
|
38
|
+
|
39
|
+
def team
|
40
|
+
unless (arguments.team.nil?)
|
41
|
+
return arguments.team
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
require 'security'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'logger'
|
6
|
+
require 'nokogiri'
|
7
|
+
|
8
|
+
include Atlantis::Portal
|
9
|
+
|
10
|
+
module Atlantis
|
11
|
+
module Portal
|
12
|
+
class TestFlightService < ::Service
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
|
17
|
+
self.host = "testflightapp.com"
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(uri, parameters = [], referer = nil, headers = {})
|
21
|
+
uri = ::File.join("https://#{self.host}", uri) unless /^https?/ === uri
|
22
|
+
|
23
|
+
3.times do
|
24
|
+
agent.get(uri, parameters, referer, headers)
|
25
|
+
|
26
|
+
#puts page.body
|
27
|
+
|
28
|
+
return agent.page unless agent.page.respond_to?(:title)
|
29
|
+
|
30
|
+
unless agent.page.parser.at_css('#id_username').nil?
|
31
|
+
#puts "Logging in"
|
32
|
+
login! and next
|
33
|
+
else
|
34
|
+
if !@team.nil? && !@team.empty?
|
35
|
+
select_team! and next
|
36
|
+
else
|
37
|
+
return agent.page
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
raise UnsuccessfulAuthenticationError
|
43
|
+
end
|
44
|
+
|
45
|
+
def list_people(group)
|
46
|
+
|
47
|
+
if group.nil?
|
48
|
+
get('/dashboard/team')
|
49
|
+
else
|
50
|
+
lists = list_groups
|
51
|
+
|
52
|
+
list = lists.find{|p| p.name == group}
|
53
|
+
|
54
|
+
say_warning "No #{group} distribution list found." and abort if list.nil?
|
55
|
+
|
56
|
+
get('/dashboard/team/list/' + list.id)
|
57
|
+
end
|
58
|
+
|
59
|
+
people = {}
|
60
|
+
|
61
|
+
agent.page.parser.css("table#member-table tr").each do |row|
|
62
|
+
cols = row.css('td')
|
63
|
+
|
64
|
+
#puts cols.length
|
65
|
+
|
66
|
+
if (cols.length > 0)
|
67
|
+
person = Person.new
|
68
|
+
|
69
|
+
person.id = cols[0].css("input")[0]['value'];
|
70
|
+
person.name = cols[1].text.strip.split.map(&:capitalize).join(' ')
|
71
|
+
person.email = cols[2].text.strip
|
72
|
+
person.devices = cols[3].text.strip
|
73
|
+
|
74
|
+
people[person.id] = person
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
return people
|
80
|
+
end
|
81
|
+
|
82
|
+
def list_devices(distribution_list)
|
83
|
+
people = list_people(distribution_list)
|
84
|
+
|
85
|
+
people_list = []
|
86
|
+
|
87
|
+
people.each do |id, person|
|
88
|
+
people_list << person.id
|
89
|
+
end
|
90
|
+
|
91
|
+
agent.post('/dashboard/team/export/devices/', { "members" => people_list.join('|'), "csrfmiddlewaretoken" => agent.page.parser.css("[name='csrfmiddlewaretoken']")[0]['value'] } )
|
92
|
+
|
93
|
+
device_list = agent.page.body.split( /\r?\n/ )
|
94
|
+
|
95
|
+
# Remove first one
|
96
|
+
device_list.shift
|
97
|
+
|
98
|
+
devices = []
|
99
|
+
|
100
|
+
device_list.each do |dev|
|
101
|
+
puts dev
|
102
|
+
|
103
|
+
device = Device.new
|
104
|
+
device.identifier = dev.split(/\t/)[0]
|
105
|
+
device.name = dev.split(/\t/)[1]
|
106
|
+
|
107
|
+
devices << device
|
108
|
+
end
|
109
|
+
|
110
|
+
devices
|
111
|
+
end
|
112
|
+
|
113
|
+
def list_groups
|
114
|
+
get('dashboard/team')
|
115
|
+
|
116
|
+
lists = []
|
117
|
+
|
118
|
+
agent.page.parser.css("nav.vert-nav li a").each do |row|
|
119
|
+
|
120
|
+
unless (row['href'].nil?)
|
121
|
+
url = row['href'].split('/')
|
122
|
+
|
123
|
+
#puts url.length
|
124
|
+
|
125
|
+
if (url.length >= 5) && (url[4].is_i?)
|
126
|
+
#puts url[3]
|
127
|
+
|
128
|
+
list = Group.new
|
129
|
+
list.id = url[4]
|
130
|
+
list.name = row.css('> text()').text.strip
|
131
|
+
list.count = row.css('span').text.strip
|
132
|
+
|
133
|
+
lists << list
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
lists
|
140
|
+
end
|
141
|
+
|
142
|
+
def list_teams
|
143
|
+
teams = []
|
144
|
+
|
145
|
+
# Selected team
|
146
|
+
|
147
|
+
selected_team = agent.page.parser.css('ul.dropdown-menu li div div.textcontain180 text()')
|
148
|
+
|
149
|
+
team = Team.new
|
150
|
+
team.name = selected_team
|
151
|
+
|
152
|
+
teams << team
|
153
|
+
|
154
|
+
all_teams = agent.page.parser.css('ul.ddteamlist li a')
|
155
|
+
all_teams.each do |row|
|
156
|
+
team = Team.new
|
157
|
+
team.id = row['data-team-id']
|
158
|
+
team.name = row.text
|
159
|
+
|
160
|
+
teams << team
|
161
|
+
end
|
162
|
+
|
163
|
+
teams
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
def login!
|
169
|
+
if form = agent.page.forms.first
|
170
|
+
#puts "LOGGING IN" + self.username
|
171
|
+
|
172
|
+
form.fields_with(type: 'email').first.value = self.username
|
173
|
+
form.fields_with(type: 'password').first.value = self.password
|
174
|
+
|
175
|
+
form.submit
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def select_team!
|
180
|
+
teams = list_teams
|
181
|
+
|
182
|
+
#puts teams
|
183
|
+
|
184
|
+
# Check if desired team is different to selected team
|
185
|
+
|
186
|
+
if @team != teams[0].name
|
187
|
+
#puts "Selecting team..."
|
188
|
+
|
189
|
+
if form = agent.page.form_with(:id => 'team-change')
|
190
|
+
|
191
|
+
team = teams.find{|t| t.name == @team}
|
192
|
+
|
193
|
+
#puts team
|
194
|
+
|
195
|
+
unless (team.nil?)
|
196
|
+
form.team = team.id
|
197
|
+
form.submit
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
@team = ''
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
data/lib/Atlantis/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atlantispro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dal Rupnik
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: commander
|
@@ -136,35 +136,39 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
-
description:
|
139
|
+
description: A simple command line interface to work with multiple application distribution
|
140
|
+
services, such as TestFlight or Crashlytics. Allows for downloading of device identifiers,
|
141
|
+
registered testers and more.
|
140
142
|
email:
|
141
143
|
- legoless@gmail.com
|
142
144
|
executables:
|
143
|
-
-
|
145
|
+
- distribution
|
144
146
|
extensions: []
|
145
147
|
extra_rdoc_files: []
|
146
148
|
files:
|
147
149
|
- ".gitignore"
|
148
150
|
- Atlantis.gemspec
|
149
151
|
- Gemfile
|
152
|
+
- Gemfile.lock
|
150
153
|
- LICENSE
|
151
154
|
- README.md
|
152
155
|
- Rakefile
|
153
|
-
- bin/
|
156
|
+
- bin/distribution
|
154
157
|
- lib/Atlantis.rb
|
155
158
|
- lib/Atlantis/portal.rb
|
156
159
|
- lib/Atlantis/portal/agent.rb
|
157
160
|
- lib/Atlantis/portal/commands.rb
|
158
161
|
- lib/Atlantis/portal/commands/devices.rb
|
159
|
-
- lib/Atlantis/portal/commands/
|
160
|
-
- lib/Atlantis/portal/commands/lists.rb
|
162
|
+
- lib/Atlantis/portal/commands/groups.rb
|
161
163
|
- lib/Atlantis/portal/commands/login.rb
|
162
164
|
- lib/Atlantis/portal/commands/logout.rb
|
163
165
|
- lib/Atlantis/portal/commands/people.rb
|
164
|
-
- lib/Atlantis/portal/
|
166
|
+
- lib/Atlantis/portal/crashlytics/crashlyticsservice.rb
|
165
167
|
- lib/Atlantis/portal/helpers.rb
|
168
|
+
- lib/Atlantis/portal/service.rb
|
169
|
+
- lib/Atlantis/portal/testflight/testflightservice.rb
|
166
170
|
- lib/Atlantis/version.rb
|
167
|
-
homepage:
|
171
|
+
homepage: https://github.com/legoless/Atlantis
|
168
172
|
licenses:
|
169
173
|
- MIT
|
170
174
|
metadata: {}
|
@@ -187,5 +191,6 @@ rubyforge_project:
|
|
187
191
|
rubygems_version: 2.0.14
|
188
192
|
signing_key:
|
189
193
|
specification_version: 4
|
190
|
-
summary:
|
194
|
+
summary: A command line interface to connect to distribution services such as TestFlight
|
195
|
+
or Crashlytics.
|
191
196
|
test_files: []
|
@@ -1,16 +0,0 @@
|
|
1
|
-
command :login do |c|
|
2
|
-
c.syntax = 'testflight login'
|
3
|
-
c.summary = 'Save account credentials'
|
4
|
-
c.description = ''
|
5
|
-
|
6
|
-
c.action do |args, options|
|
7
|
-
say_warning "You are already authenticated" if Security::InternetPassword.find(:server => Atlantis::Portal::HOST)
|
8
|
-
|
9
|
-
user = ask "Username:"
|
10
|
-
pass = password "Password:"
|
11
|
-
|
12
|
-
Security::InternetPassword.add(Atlantis::Portal::HOST, user, pass)
|
13
|
-
|
14
|
-
say_ok "Account credentials saved"
|
15
|
-
end
|
16
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
command :'lists' do |c|
|
2
|
-
c.syntax = 'testflight lists'
|
3
|
-
c.summary = 'Lists all distribution lists on TestFlight'
|
4
|
-
c.description = ''
|
5
|
-
|
6
|
-
c.action do |args, options|
|
7
|
-
lists = try{agent.list_lists}
|
8
|
-
|
9
|
-
if (agent.format == "csv")
|
10
|
-
csv_string = CSV.generate do |csv|
|
11
|
-
csv << ["ID", "Name", "Count"]
|
12
|
-
|
13
|
-
lists.each do |list|
|
14
|
-
csv << [list.id, list.name, list.count]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
puts csv_string
|
19
|
-
|
20
|
-
else
|
21
|
-
title = "Listing distribution lists"
|
22
|
-
|
23
|
-
table = Terminal::Table.new :title => title do |t|
|
24
|
-
t << ["ID", "Name", "Count"]
|
25
|
-
t.add_separator
|
26
|
-
lists.each do |list|
|
27
|
-
t << [list.id, list.name, list.count]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
#table.align_column 2, :center
|
32
|
-
|
33
|
-
puts table
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
command :'teams' do |c|
|
2
|
-
c.syntax = 'testflight teams'
|
3
|
-
c.summary = 'Lists all teams on TestFlight'
|
4
|
-
c.description = ''
|
5
|
-
|
6
|
-
c.action do |args, options|
|
7
|
-
lists = try{agent.list_lists}
|
8
|
-
|
9
|
-
title = "Listing distribution lists"
|
10
|
-
|
11
|
-
table = Terminal::Table.new :title => title do |t|
|
12
|
-
t << ["ID", "Name", "Count"]
|
13
|
-
t.add_separator
|
14
|
-
lists.each do |list|
|
15
|
-
t << [list.id, list.name, list.count]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
#table.align_column 2, :center
|
20
|
-
|
21
|
-
puts table
|
22
|
-
end
|
23
|
-
end
|