sakura-cli 0.1.3 → 0.2.1

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 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: []