atlantispro 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|