sakura-cli 0.1.3 → 0.2.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
- SHA1:
3
- metadata.gz: 7701178d0eeaad9bf4d8dfb662613ba904a7a1b3
4
- data.tar.gz: 4eac1700d0a8ccbfc0273596bb6e7c31d0ab131a
2
+ SHA256:
3
+ metadata.gz: f4bd482e0d86c365ea75946bc6831c56d30390b30121e289ad5ccdf7daeab02a
4
+ data.tar.gz: e864d3491596ca9919c9a6e5001664e7affdef7281976a50f375bc8817cdbc5d
5
5
  SHA512:
6
- metadata.gz: 2aeba49fdb92a4e05fc17633195b394e3bfaea3371fef68efe8f2c2ebec4651769f1e6c635be235330839f3f0c329aa2c2c8e6618b477f9b05157b616666c3d3
7
- data.tar.gz: 5dc7ced0351d562cc5b0653c2759c07a85b591144283c79d217feed975086fadbb78d892577490d55c09283de718a81fe3ad5c6df1b9d1381ca44a0f4fa4457c
6
+ metadata.gz: 7594da6f2ca11dae4251fe0aba8d61f3860505adcb7005d5ce631c13e61ed8b2e23e93a5ee61404ec87ec812771f4cf031a228a6ea59e50ce84ac1e278770890
7
+ data.tar.gz: '01519f5f2a7aa79001e770700ee4ef6abc80509dc21c405418c565bccc5b6945502ad32fe60f6ac1f3ed767fb088d379d85dec69405b06a5cd18629d8cc9ce3a'
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+
11
+ /.idea/
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2016 Shintaro Kojima
3
+ Copyright (c) 2015-2022 Shintaro Kojima
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -12,18 +12,13 @@ Sakura CLI をインストールします.
12
12
  gem install sakura-cli
13
13
  ```
14
14
 
15
- Sakura CLI は[PhantomJS](http://phantomjs.org/download.html) に依存しています.
15
+ Sakura CLI は[ChromeDriver](https://chromedriver.chromium.org/downloads) に依存しています.
16
16
  お使いのOS に合った方法でインストールしてください.
17
17
 
18
18
  Mac の場合は
19
19
 
20
20
  ```zsh
21
- brew install phantomjs
22
-
23
- # Yosemite or newer
24
- brew cask install phantomjs
25
- brew install upx
26
- upx -d /opt/homebrew-cask/Caskroom/phantomjs/2.0.0/phantomjs-2.0.0-macosx/bin/phantomjs
21
+ brew install chromedriver
27
22
  ```
28
23
 
29
24
  でもインストールできます.
@@ -80,12 +75,12 @@ Commands:
80
75
  ```zsh
81
76
  $ sakura mail list
82
77
  # domain: example.com
83
- address virus_scan usage / quota
78
+ address usage / quota ( %)
84
79
  ---------------------------------------------------------
85
- dummy true 379.13KB / 200MB
86
- dummy001 true 1.79MB / 2GB
87
- dummy002 true 6.28KB / 2GB
88
- postmaster true 0B / 2GB
80
+ dummy 893KB / 200MB ( 0%)
81
+ dummy001 19.5MB / 200MB ( 9%)
82
+ dummy002 11.4MB / 200MB ( 5%)
83
+ postmaster 9.75MB / 200MB ( 4%)
89
84
  ```
90
85
 
91
86
  ### メールアドレス詳細
@@ -94,10 +89,11 @@ postmaster true 0B / 2GB
94
89
 
95
90
  ```zsh
96
91
  $ sakura mail show dummy
97
- usage / quota: 379.13KB / 200MB
92
+ usage / quota: 893KB / 200MB ( 0%)
98
93
  forward_to: foo@example.com
99
- keep mail?: true
100
- virus_scan?: false
94
+ keep mail: true
95
+ virus scan: false
96
+ spam filter: disable
101
97
  ```
102
98
 
103
99
  ### メールアドレス作成
@@ -185,4 +181,4 @@ dotenv -f ~/.sakura.env sakura
185
181
 
186
182
  ## Copyright and License
187
183
 
188
- Copyright (c) 2016 Shintaro Kojima. Code released under the [MIT license](LICENSE).
184
+ Copyright (c) 2015-2022 Shintaro Kojima. Code released under the [MIT license](LICENSE).
@@ -7,41 +7,51 @@ module Sakura
7
7
  module Cli
8
8
  class Mail < Thor
9
9
  desc 'list', 'List all mail addresses of the domain'
10
+
10
11
  def list
12
+ preprocess
13
+
11
14
  addrs = MailAddress.all
12
15
 
13
16
  puts "# domain: #{Client.current_session.domain}"
14
17
  puts MailAddress.header
15
- addrs.each {|addr| puts addr.to_s }
18
+ addrs.each { |addr| puts addr.to_s }
16
19
  end
17
20
 
18
21
  desc 'create LOCAL_PART [PASSWORD]', 'Create a mail address'
19
- def create(local_part, password=nil)
22
+
23
+ def create(local_part, password = nil)
24
+ preprocess
25
+
20
26
  password ||= ask_password
21
27
 
22
28
  begin
23
29
  MailAddress.create local_part, password
24
30
  rescue
31
+ raise if options[:verbose]
25
32
  abort $!
26
33
  end
27
34
  end
28
35
 
29
36
  desc 'delete LOCAL_PART', 'Delete a mail address'
37
+
30
38
  def delete(local_part)
31
- mail = MailAddress.find(local_part)
32
- abort %(No mail address: "#{local_part}") unless mail
39
+ preprocess
33
40
 
34
41
  begin
35
- mail.delete
42
+ find(local_part).delete
36
43
  rescue
44
+ raise if options[:verbose]
37
45
  abort $!
38
46
  end
39
47
  end
40
48
 
41
49
  desc 'quota LOCAL_PART [VALUE]', 'Update or show quota of a mail address'
42
- def quota(local_part, value=nil)
43
- mail = MailAddress.find(local_part)
44
- abort %(No mail address: "#{local_part}") unless mail
50
+
51
+ def quota(local_part, value = nil)
52
+ preprocess
53
+
54
+ mail = find(local_part)
45
55
 
46
56
  begin
47
57
  if value
@@ -50,29 +60,35 @@ module Sakura
50
60
  puts mail.quota
51
61
  end
52
62
  rescue
63
+ raise if options[:verbose]
53
64
  abort $!
54
65
  end
55
66
  end
56
67
 
57
68
  desc 'password LOCAL_PART [PASSWORD]', 'Update password of a mail address'
58
- def password(local_part, password=nil)
69
+
70
+ def password(local_part, password = nil)
71
+ preprocess
72
+
59
73
  password ||= ask_password
60
- mail = MailAddress.find(local_part)
61
- abort %(No mail address: "#{local_part}") unless mail
74
+ mail = find(local_part)
62
75
 
63
76
  begin
64
77
  mail.password = password
65
78
  rescue
79
+ raise if options[:verbose]
66
80
  abort $!
67
81
  end
68
82
  end
69
83
 
70
84
  desc 'scan LOCAL_PART [enable|disable]', 'Switch virus scan configuration of a mail address'
71
- def scan(local_part, value=nil)
85
+
86
+ def scan(local_part, value = nil)
87
+ preprocess
88
+
72
89
  self.class.handle_argument_error if value && value !~ /enable|disable/
73
90
 
74
- mail = MailAddress.find(local_part)
75
- abort %(No mail address: "#{local_part}") unless mail
91
+ mail = find(local_part)
76
92
 
77
93
  begin
78
94
  case value
@@ -84,18 +100,21 @@ module Sakura
84
100
  puts mail.virus_scan
85
101
  end
86
102
  rescue
103
+ raise if options[:verbose]
87
104
  abort $!
88
105
  end
89
106
  end
90
107
 
91
108
  desc 'forward LOCAL_PART [{add|remove} EMAIL]', 'Add, remove or show mail address(es) to forward'
92
- def forward(local_part, operation=nil, mail_to_forward=nil)
109
+
110
+ def forward(local_part, operation = nil, mail_to_forward = nil)
111
+ preprocess
112
+
93
113
  if (operation && operation !~ /add|remove/) || (!mail_to_forward && operation)
94
114
  self.class.handle_argument_error
95
115
  end
96
116
 
97
- mail = MailAddress.find(local_part)
98
- abort %(No mail address: "#{local_part}") unless mail
117
+ mail = find(local_part)
99
118
 
100
119
  begin
101
120
  case operation
@@ -104,19 +123,22 @@ module Sakura
104
123
  when 'remove'
105
124
  mail.delete_forward_to mail_to_forward
106
125
  when nil
107
- mail.forward_list.each {|m| puts m }
126
+ mail.forward_list.each { |m| puts m }
108
127
  end
109
128
  rescue
129
+ raise if options[:verbose]
110
130
  abort $!
111
131
  end
112
132
  end
113
133
 
114
134
  desc 'keep LOCAL_PART [enable|disable]', 'Switch keep or flush configuration of a mail address'
115
- def keep(local_part, value=nil)
135
+
136
+ def keep(local_part, value = nil)
137
+ preprocess
138
+
116
139
  self.class.handle_argument_error if value && value !~ /enable|disable/
117
140
 
118
- mail = MailAddress.find(local_part)
119
- abort %(No mail address: "#{local_part}") unless mail
141
+ mail = find(local_part)
120
142
 
121
143
  begin
122
144
  case value
@@ -128,25 +150,62 @@ module Sakura
128
150
  puts mail.keep
129
151
  end
130
152
  rescue
153
+ raise if options[:verbose]
154
+ abort $!
155
+ end
156
+ end
157
+
158
+ desc 'filter LOCAL_PART [mark|disable|discard|quarantine]', 'Configure spam filter of a mail address'
159
+
160
+ def filter(local_part, value = nil)
161
+ preprocess
162
+
163
+ self.class.handle_argument_error if value && value !~ /mark|disable|discard|quarantine/
164
+
165
+ mail = find(local_part)
166
+
167
+ begin
168
+ case value
169
+ when nil
170
+ puts mail.spam_filter
171
+ else
172
+ mail.spam_filter = value.to_sym
173
+ end
174
+ rescue
175
+ raise if options[:verbose]
131
176
  abort $!
132
177
  end
133
178
  end
134
179
 
135
180
  desc 'show LOCAL_PART', 'Display information about a mail address'
181
+
136
182
  def show(local_part)
137
- mail = MailAddress.find(local_part)
138
- abort %(No mail address: "#{local_part}") unless mail
183
+ preprocess
139
184
 
140
- puts mail.detail
185
+ puts find(local_part).detail
141
186
  end
142
187
 
143
-
144
188
  private
145
189
 
190
+ def preprocess
191
+ Client.verbose = true if options[:verbose]
192
+ end
193
+
194
+ def find(local_part)
195
+ begin
196
+ mail = MailAddress.find(local_part)
197
+ rescue Capybara::ElementNotFound
198
+ raise if options[:verbose]
199
+ abort %(No mail address: "#{local_part}")
200
+ end
201
+
202
+ mail
203
+ end
204
+
146
205
  def ask_password
147
206
  password = ask('password?', echo: false)
148
207
  puts
149
- confirm = ask('password(confirm)?', echo: false)
208
+ confirm = ask('password(confirm)?', echo: false)
150
209
  puts
151
210
  abort "password doesn't match" unless password == confirm
152
211
 
@@ -4,6 +4,13 @@ require 'sakura/cli/mail'
4
4
  module Sakura
5
5
  module Cli
6
6
  class Root < Thor
7
+ class_option :verbose, type: :boolean
8
+
9
+ # Allow failed exit codes (see https://github.com/erikhuda/thor/issues/244)
10
+ def self.exit_on_failure?
11
+ true
12
+ end
13
+
7
14
  desc 'mail', 'Manage mail addresses'
8
15
  subcommand 'mail', Mail
9
16
  end
@@ -1,5 +1,5 @@
1
1
  module Sakura
2
2
  module Cli
3
- VERSION = "0.1.3"
3
+ VERSION = "0.2.1"
4
4
  end
5
5
  end
data/lib/sakura/client.rb CHANGED
@@ -1,58 +1,77 @@
1
1
  require 'capybara/dsl'
2
- require 'capybara/poltergeist'
2
+ require 'selenium-webdriver'
3
+
3
4
  require 'sakura'
4
5
  require 'sakura/cli/version'
5
6
 
6
- Capybara.default_driver = :poltergeist
7
- Capybara.current_session.driver.headers = {'User-Agent' => "sakura-cli/#{Sakura::Cli::VERSION}"}
7
+ Capybara.default_driver = :selenium_chrome_headless
8
8
 
9
9
  module Sakura
10
10
  class Client
11
11
  include Capybara::DSL
12
12
 
13
13
  attr_reader :domain
14
+ @@verbose = false
14
15
 
15
- def self.current_session
16
- @current_session ||= new
17
- end
16
+ class << self
17
+ def current_session
18
+ @current_session ||= new
19
+ end
18
20
 
21
+ def verbose=(bool)
22
+ @@verbose = !!bool
23
+ end
24
+ end
19
25
 
20
26
  def initialize
21
27
  @domain, @passwd = credentials
22
28
  end
23
29
 
24
30
  def login?
25
- !@last_login.nil?
31
+ @logged_in
26
32
  end
27
33
 
28
34
  def login
35
+ $stderr.puts 'login' if @@verbose
36
+
29
37
  visit BASE_URL
30
- fill_in 'domain', with: @domain
31
- fill_in 'password', with: @passwd
32
- find('form input[type=image]').click
38
+ fill_in 'login-username', with: @domain
39
+ fill_in 'login-password', with: @passwd
40
+ find('form button[type=submit]').click
41
+
42
+ wait_for_loading
33
43
 
34
- @last_login = Time.now if page.text =~ /ログインドメイン: #{@domain}/
44
+ if page.text =~ /サーバコントロールパネル ホーム/
45
+ @logged_in = true
46
+ end
35
47
 
36
48
  raise_when_error
37
49
  login?
38
50
  end
39
51
 
40
- def get(url)
52
+ def get(url, expected)
41
53
  login unless login?
54
+
55
+ $stderr.puts "visit #{url}" if @@verbose
42
56
  visit url
57
+ wait_for_loading
58
+ unless page.text =~ expected
59
+ raise Timeout::Error.new('Timed out')
60
+ end
61
+
43
62
  page
44
63
  end
45
64
 
46
- def process(url, &block)
65
+ def process(url, expected, &block)
47
66
  login unless login?
48
- visit url
49
- instance_eval &block
67
+
68
+ get url, expected
69
+ yield page
50
70
 
51
71
  raise_when_error
52
72
  page
53
73
  end
54
74
 
55
-
56
75
  private
57
76
 
58
77
  def credentials
@@ -67,8 +86,20 @@ module Sakura
67
86
  end
68
87
 
69
88
  def raise_when_error
70
- error = page.all('.error-message')
71
- raise error.first.text unless error.empty?
89
+ %w[.error .input-error].each do |cls|
90
+ error = page.all(cls)
91
+ raise error.first.text unless error.empty?
92
+ end
93
+ end
94
+
95
+ def wait_for_loading
96
+ 5.times do
97
+ if find_all('読み込み中').empty?
98
+ break
99
+ else
100
+ $stderr.puts 'still loading ...' if @@verbose
101
+ end
102
+ end
72
103
  end
73
104
  end
74
105
  end
@@ -2,93 +2,133 @@ require 'sakura/client'
2
2
 
3
3
  module Sakura
4
4
  class MailAddress
5
- MAIL_URL = BASE_URL + 'rs/mail'
5
+ MAIL_URL = BASE_URL + 'users/list/'
6
6
 
7
- attr_reader :address, :virus_scan, :usage, :quota, :link, :link_to_delete
7
+ attr_reader :address, :usage, :quota, :link
8
8
 
9
9
  class << self
10
10
  def create(local_part, password)
11
- Client.current_session.process(MAIL_URL) do
12
- fill_in 'NewUsername', with: local_part
13
- fill_in 'Password1', with: password
14
- fill_in 'Password2', with: password
15
- find('input[name="Submit_useradd"]').click
11
+ Client.current_session.process(MAIL_URL, /メールアドレス一覧/) do |page|
12
+ page.first(:xpath, '//a[text() = "新規追加"]').click
13
+
14
+ page.find(:xpath, '//label[contains(text(), "ユーザ名")]/..//input')
15
+ .fill_in with: local_part
16
+ page.find_all(:xpath, '//label[contains(text(), "パスワード")]/..//input').each do |e|
17
+ e.fill_in with: password
18
+ end
19
+ page.find(:xpath, '//button[text() = "作成する"]').click
16
20
  end
17
21
 
18
22
  true
19
23
  end
20
24
 
21
25
  def all
22
- page = Client.current_session.get(MAIL_URL)
26
+ page = Client.current_session.get(MAIL_URL, /メールアドレス一覧/)
27
+ page.first('.input-text').select '300件'
23
28
 
24
- page.all(:xpath, '//a[contains(@href, "mail?Username=")]/../..').map{|element|
25
- arguments = element.all('td').map(&:text)[0..-2] + element.all('a').map{|i| i[:href] }
26
- MailAddress.new(*arguments)
29
+ page.all(:css, '.entity-lists .entity-lists-row').map { |element|
30
+ MailAddress.new_from_element(element)
27
31
  }
28
32
  end
29
33
 
30
34
  def find(local_part)
31
- all.find {|m| m.address == local_part }
35
+ page = Client.current_session.get(MAIL_URL, /メールアドレス一覧/)
36
+ page.first('.input-text').select '300件'
37
+
38
+ element = page.find(:xpath, "//div[contains(@class, \"entity-lists-row\")]//div[@class=\"username\" and contains(text(), \"#{local_part}\")]/../../..")
39
+ MailAddress.new_from_element(element)
40
+ end
41
+
42
+ def new_from_element(element)
43
+ MailAddress.new(
44
+ element.find('.username').text.split('@').first,
45
+ element.find('.capacity').text
46
+ )
32
47
  end
33
48
 
34
49
  def header
35
- str = tabularize('address', 'virus_scan', 'usage', 'quota', '%')
36
- "#{str}\n#{'-' * (str.size+1)}"
50
+ str = tabularize('address', 'usage', 'quota', '%')
51
+ "#{str}\n#{'-' * (str.size + 1)}"
37
52
  end
38
53
 
39
54
  def tabularize(*args)
40
55
  args[0].ljust(20) <<
41
- args[1].to_s.rjust(11) <<
42
- "#{args[2]} /".to_s.rjust(15) <<
43
- args[3].to_s.rjust(10) <<
44
- " (#{args[4].to_s.rjust(3)})"
56
+ "#{args[1]} /".to_s.rjust(15) <<
57
+ args[2].to_s.rjust(10) <<
58
+ " (#{args[3].to_s.rjust(3)})"
45
59
  end
46
60
  end
47
61
 
48
-
49
- def initialize(address, virus_scan, usage, quota, link, link_to_delete=nil)
50
- @address = address
51
- @virus_scan = virus_scan == '○'
52
- @usage = usage
53
- @quota = quota
54
- @link = link
55
- @link_to_delete = link_to_delete
62
+ def initialize(address, usage)
63
+ @address = address
64
+ @usage, @quota = usage.split(/\s*\/\s*/)
56
65
  end
57
66
 
58
67
  def delete
59
- link = @link_to_delete
60
- Client.current_session.process(MAIL_URL) do
61
- find("a[href=\"#{link}\"]").click
68
+ # FIXME: The URL won't work when mail addresses are more than 300
69
+ Client.current_session.process(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/) do |page|
70
+ page.accept_confirm do
71
+ page.find('button.is-dangerous').click
72
+ end
62
73
  end
63
74
 
64
75
  true
65
76
  end
66
77
 
67
78
  def quota=(value)
68
- page = Client.current_session.process(MAIL_URL + @link) {
69
- fill_in 'MailQuota', with: value
70
- find('input[name="Submit_quotaedit"]').click
71
- }
79
+ # FIXME: The URL won't work when mail addresses are more than 300
80
+ Client.current_session.process(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/) do |page|
81
+ case value
82
+ when /(\d+)\s*GB$/
83
+ page.find(:xpath, '//label[contains(text(), "メール容量制限")]/..//input').fill_in with: $1
84
+ page.find(:xpath, '//label[contains(text(), "メール容量制限")]/..//select').select 'GB'
85
+ when /(\d+)\s*MB$/
86
+ page.find(:xpath, '//label[contains(text(), "メール容量制限")]/..//input').fill_in with: $1
87
+ page.find(:xpath, '//label[contains(text(), "メール容量制限")]/..//select').select 'MB'
88
+ when /(\d+)\s*KB$/
89
+ page.find(:xpath, '//label[contains(text(), "メール容量制限")]/..//input').fill_in with: $1
90
+ page.find(:xpath, '//label[contains(text(), "メール容量制限")]/..//select').select 'KB'
91
+ when /(\d+)\s*B$/
92
+ page.find(:xpath, '//label[contains(text(), "メール容量制限")]/..//input').fill_in with: $1
93
+ page.find(:xpath, '//label[contains(text(), "メール容量制限")]/..//select').select 'B'
94
+ else
95
+ raise %(Unsupported quota value "#{value}")
96
+ end
72
97
 
73
- page.text =~ /利用中のディスク領域: \S+ \/ (\S+)/
74
- @quota = $1
98
+ page.find(:xpath, '//button[text() = "保存する"]').click
99
+ end
100
+
101
+ @quota = value
75
102
  end
76
103
 
77
104
  def password=(value)
78
- Client.current_session.process(MAIL_URL + @link) do
79
- fill_in 'Password1', with: value
80
- fill_in 'Password2', with: value
81
- find('input[name="Submit_password"]').click
105
+ # FIXME: The URL won't work when mail addresses are more than 300
106
+ Client.current_session.process(MAIL_URL + "1/password/#{@address}", /#{@address}のパスワード設定/) do |page|
107
+ page.find_all(:xpath, '//label[contains(text(), "パスワード")]/..//input').each do |e|
108
+ e.fill_in with: value
109
+ end
110
+ page.find(:xpath, '//button[text() = "変更する"]').click
111
+ end
112
+ end
113
+
114
+ def virus_scan(page = nil)
115
+ if @virus_scan.nil?
116
+ # FIXME: The URL won't work when mail addresses are more than 300
117
+ page ||= Client.current_session.get(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/)
118
+ @virus_scan = page.find('[name="usesVirusCheck"]:checked').value == '1'
82
119
  end
120
+
121
+ @virus_scan
83
122
  end
84
123
 
85
124
  def virus_scan=(value)
86
- value = value ? 1 : 0
87
- Client.current_session.process(MAIL_URL + @link) do
88
- find("input[name='VirusScan'][value='#{value}']").click
125
+ # FIXME: The URL won't work when mail addresses are more than 300
126
+ Client.current_session.process(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/) do |page|
127
+ page.find("[name='usesVirusCheck'][value='#{value ? 1 : 0}']").choose
128
+ page.find(:xpath, '//button[text() = "保存する"]').click
89
129
  end
90
130
 
91
- @virus_scan = value == 1
131
+ @virus_scan = value
92
132
  end
93
133
 
94
134
  def enable_virus_scan
@@ -99,22 +139,24 @@ module Sakura
99
139
  virus_scan = false
100
140
  end
101
141
 
102
- def keep(page=nil)
142
+ def keep(page = nil)
103
143
  if @keep.nil?
104
- page ||= Client.current_session.get(MAIL_URL + @link)
105
- @keep = page.find('input[name="Save"]:checked').value == '1'
144
+ # FIXME: The URL won't work when mail addresses are more than 300
145
+ page ||= Client.current_session.get(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/)
146
+ @keep = page.find('[name="receiveType"]:checked').value == '1'
106
147
  end
107
148
 
108
149
  @keep
109
150
  end
110
151
 
111
152
  def keep=(value)
112
- value = value ? 1 : 0
113
- Client.current_session.process(MAIL_URL + @link) do
114
- find("input[name='Save'][value='#{value}']").click
153
+ # FIXME: The URL won't work when mail addresses are more than 300
154
+ Client.current_session.process(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/) do |page|
155
+ page.find("[name='receiveType'][value='#{value ? 1 : 2}']").choose
156
+ page.find(:xpath, '//button[text() = "保存する"]').click
115
157
  end
116
158
 
117
- @keep = value == 1
159
+ @keep = value
118
160
  end
119
161
 
120
162
  def enable_keep
@@ -125,59 +167,104 @@ module Sakura
125
167
  keep = false
126
168
  end
127
169
 
128
- def forward_list(page=nil)
170
+ def spam_filter(page = nil)
171
+ if @spam_filter.nil?
172
+ # FIXME: The URL won't work when mail addresses are more than 300
173
+ page ||= Client.current_session.get(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/)
174
+
175
+ case page.find(:xpath, '//label[contains(text(), "迷惑メールフィルタ")]/..//select').value
176
+ when "0"
177
+ @spam_filter = :disable
178
+ when "1"
179
+ @spam_filter = :quarantine
180
+ when "2"
181
+ @spam_filter = :discard
182
+ when "3"
183
+ @spam_filter = :mark
184
+ end
185
+ end
186
+
187
+ @spam_filter
188
+ end
189
+
190
+ def spam_filter=(value)
191
+ # FIXME: The URL won't work when mail addresses are more than 300
192
+ Client.current_session.process(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/) do |page|
193
+ select = page.find(:xpath, '//label[contains(text(), "迷惑メールフィルタ")]/..//select')
194
+
195
+ value = value.to_sym
196
+ case value
197
+ when :disable
198
+ select.select '利用しない'
199
+ when :quarantine
200
+ select.select '「迷惑メール」フォルダに保存'
201
+ when :discard
202
+ select.select 'メールを破棄'
203
+ when :mark
204
+ select.select 'フィルタの利用'
205
+ end
206
+
207
+ page.find(:xpath, '//button[text() = "保存する"]').click
208
+ end
209
+
210
+ @spam_filter = value
211
+ end
212
+
213
+ def forward_list(page = nil)
129
214
  if @forward_list.nil?
130
- page ||= Client.current_session.get(MAIL_URL + @link)
131
- @forward_list = page.all('select[name="DeleteAddress[]"] option').map(&:text)
215
+ # FIXME: The URL won't work when mail addresses are more than 300
216
+ page ||= Client.current_session.get(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/)
217
+ @forward_list = page.find(:xpath, '//label[contains(text(), "転送先アドレス")]/..//textarea').value.split(/[\n,]+/)
132
218
  end
133
219
 
134
220
  @forward_list
135
221
  end
136
222
 
137
223
  def forward_to(mail)
138
- Client.current_session.process(MAIL_URL + @link) do
139
- execute_script <<-JS
140
- var f = document.Transfer;
141
- f.Address.value = '#{mail}';
142
- f.SubAction.value = 'add';
143
- f.submit();
144
- JS
224
+ # FIXME: The URL won't work when mail addresses are more than 300
225
+ Client.current_session.process(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/) do |page|
226
+ @forward_list = page.find(:xpath, '//label[contains(text(), "転送先アドレス")]/..//textarea').value.split(/[\n,]+/)
227
+ page.find(:xpath, '//label[contains(text(), "転送先アドレス")]/..//textarea')
228
+ .fill_in with: (@forward_list + [mail]).uniq.join("\n")
229
+ page.find(:xpath, '//button[text() = "保存する"]').click
145
230
  end
146
231
 
147
- @forward_list ||= []
148
232
  @forward_list << mail
149
233
  end
150
234
 
151
235
  def delete_forward_to(mail)
152
- Client.current_session.process(MAIL_URL + @link) do
153
- find_field('DeleteAddress[]').select(mail)
154
- find('a[href="javascript:tr_delete();"]').click
236
+ # FIXME: The URL won't work when mail addresses are more than 300
237
+ Client.current_session.process(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/) do |page|
238
+ @forward_list = page.find(:xpath, '//label[contains(text(), "転送先アドレス")]/..//textarea').value.split(/[\n,]+/)
239
+ page.find(:xpath, '//label[contains(text(), "転送先アドレス")]/..//textarea')
240
+ .fill_in with: (@forward_list - [mail]).uniq.join("\n")
241
+ page.find(:xpath, '//button[text() = "保存する"]').click
155
242
  end
156
243
 
157
- @forward_list ||= []
158
244
  @forward_list.delete mail
159
245
  end
160
246
 
161
247
  def to_s
162
- self.class.tabularize(@address, @virus_scan, @usage, @quota, percentage(@usage, @quota))
248
+ self.class.tabularize(@address, @usage, @quota, percentage(@usage, @quota))
163
249
  end
164
250
 
165
251
  def detail
166
- page = Client.current_session.get(MAIL_URL + @link)
252
+ # FIXME: The URL won't work when mail addresses are more than 300
253
+ page = Client.current_session.get(MAIL_URL + "1/edit/#{@address}", /#{@address}の設定/)
167
254
 
168
255
  <<-EOS
169
256
  usage / quota: #{usage} / #{quota} (#{percentage(@usage, @quota)})
170
257
  forward_to: #{forward_list(page).join(' ')}
171
- keep mail?: #{keep(page)}
172
- virus_scan?: #{virus_scan}
258
+ keep mail: #{keep(page)}
259
+ virus scan: #{virus_scan(page)}
260
+ spam filter: #{spam_filter(page)}
173
261
  EOS
174
262
  end
175
263
 
176
-
177
264
  private
178
265
 
179
266
  def percentage(usage, quota)
180
- usage, quota = [usage, quota].map {|i|
267
+ usage, quota = [usage, quota].map { |i|
181
268
  case i
182
269
  when /([\d.]+)TB$/
183
270
  $1.to_f * 1000000000000
@@ -192,7 +279,7 @@ virus_scan?: #{virus_scan}
192
279
  end
193
280
  }
194
281
 
195
- "#{(usage*100/quota).to_i}%"
282
+ "#{(usage * 100 / quota).to_i}%"
196
283
  end
197
284
  end
198
285
  end
data/lib/sakura.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'uri'
2
2
 
3
3
  module Sakura
4
- BASE_URL = URI('https://secure.sakura.ad.jp/rscontrol/')
4
+ BASE_URL = URI('https://secure.sakura.ad.jp/rs/cp/')
5
5
  end
data/sakura-cli.gemspec CHANGED
@@ -20,9 +20,9 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  spec.add_runtime_dependency "capybara"
23
- spec.add_runtime_dependency "poltergeist"
23
+ spec.add_runtime_dependency "selenium-webdriver"
24
24
  spec.add_runtime_dependency "thor"
25
- spec.add_development_dependency "bundler", "~> 1.9"
26
- spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "rake"
27
27
  spec.required_ruby_version = '>= 2.0.0'
28
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sakura-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shintaro Kojima
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-08 00:00:00.000000000 Z
11
+ date: 2022-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: poltergeist
28
+ name: selenium-webdriver
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -56,30 +56,30 @@ dependencies:
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.9'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.9'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '10.0'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '10.0'
82
+ version: '0'
83
83
  description: Command-line tool and client library to control the dashboard of Sakura
84
84
  Rental Server.
85
85
  email:
@@ -106,7 +106,7 @@ homepage: https://github.com/codeout/sakura-cli
106
106
  licenses:
107
107
  - MIT
108
108
  metadata: {}
109
- post_install_message:
109
+ post_install_message:
110
110
  rdoc_options: []
111
111
  require_paths:
112
112
  - lib
@@ -121,9 +121,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  - !ruby/object:Gem::Version
122
122
  version: '0'
123
123
  requirements: []
124
- rubyforge_project:
125
- rubygems_version: 2.5.1
126
- signing_key:
124
+ rubygems_version: 3.3.7
125
+ signing_key:
127
126
  specification_version: 4
128
127
  summary: Command-line tool for Sakura's Rental Server.
129
128
  test_files: []