bbiff 0.3.5 → 0.4.0

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
  SHA256:
3
- metadata.gz: 390245509f3595fee671a77bca02daf4592e2747cd01543de817ae804b509122
4
- data.tar.gz: 3fb134823404b0ce3e93b01ada05e7d1dbd152bfb193e01c1931e3b5ce1afc51
3
+ metadata.gz: 4758c8dd5e687a8cafc4950aff149891315912f57c9c6089d411ca40f64af251
4
+ data.tar.gz: 05201ef427ddafaa0d8319d32da510afdd26363463961b8f70ee115d983a7e0f
5
5
  SHA512:
6
- metadata.gz: 5f1cac9cfc598df67c23fbeaf572f824b2fa775693ccb4d5e99f6ab875edc6843acb3314450bfad11262cf14555616aa8e147d66361e719def0102c431c385b4
7
- data.tar.gz: a499ad13b6f5616df60bfc456373f28705164d1fb1f547c8492f8eac7038c38ec728c06e574071e5a011cc24b46e1a63eebb4fda67a787eec04b343a2635eb04
6
+ metadata.gz: cdb83ce8f345ffedb08e7778f1498aa22cf23e317266b77befb643fbeefe3d470f6c289704a0674e308516f1064513ea8f4410d54012240419b6f56cccb76c63
7
+ data.tar.gz: f3cab0dd96adc6d675491aac3bf2978148474ba8d94680f31422e902db360533e43790da75358d1401e40166069337a1fa0cf62af258ef14429b60363ef61b60
data/README.md CHANGED
@@ -7,6 +7,10 @@
7
7
 
8
8
  sudo apt-get install libnotify-bin
9
9
 
10
+ `BBIFF_NOTIFY_SEND` 環境変数をセットすることで、notify-send 以外のコマ
11
+ ンドをレスの通知に使うこともできます。1つ目の引数にはスレッドタイトル
12
+ が、2つ目の引数には投稿の内容が渡されます。
13
+
10
14
  ## インストール
11
15
 
12
16
  `gem install bbiff` でインストールできます。
@@ -20,12 +24,6 @@
20
24
  んねる互換掲示板の場合は、`http://ホスト名/test/read.cgi/板名/スレID/`
21
25
  のような形式になります。
22
26
 
23
- 単に
24
-
25
- bbiff
26
-
27
- とすると、前回監視したスレッドを監視します。
28
-
29
27
  ## リリース
30
28
 
31
29
  ver 0.1.0
@@ -68,6 +66,14 @@ ver 0.3.3
68
66
  ver 0.3.4
69
67
  * 通知でレスの最後に <><> が表示されるのを修正。
70
68
 
69
+ ver 0.3.5
70
+ * httpsなしたらば掲示板のURLが使えるようにした。
71
+
72
+ ver 0.4.0
73
+ * ロングポーリングに対応。(--long-pollingオプション)
74
+ * スタンドアローンなレンダリングの抑制。(--no-renderオプション)
75
+ * 設定ファイル(~/.config/bbiff/settings.tml)を廃止した。
76
+
71
77
  ## 作者
72
78
 
73
79
  予定地 <plonk@piano.email.ne.jp>
@@ -15,12 +15,10 @@ Gem::Specification.new do |spec|
15
15
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
16
  spec.bindir = "bin"
17
17
  spec.executables << 'bbiff'
18
- spec.executables << 'bbiff-show'
19
18
  spec.require_paths = ["lib"]
20
19
 
21
20
  spec.add_development_dependency "bundler", "~> 1.10"
22
21
  spec.add_development_dependency "rake", "~> 10.0"
23
22
  spec.add_development_dependency "rspec"
24
23
  spec.add_dependency "unicode-display_width", "~>1.4.1"
25
- spec.add_dependency "toml-rb", "~>0.3.12"
26
24
  end
@@ -4,4 +4,3 @@ require_relative 'bbiff/bbs_reader'
4
4
  require_relative 'bbiff/res_format'
5
5
  require_relative 'bbiff/settings'
6
6
  require_relative 'bbiff/executable'
7
- require_relative 'bbiff/show'
@@ -1,12 +1,14 @@
1
1
  require 'net/http'
2
2
  require 'uri'
3
- require 'pp' if $DEBUG
4
3
 
5
4
  module Bbs
6
5
 
7
6
  class NotFoundError < StandardError
8
7
  end
9
8
 
9
+ class FormatError < StandardError
10
+ end
11
+
10
12
  class Post
11
13
  class << self
12
14
  def from_s(str)
@@ -79,14 +81,15 @@ module Bbs
79
81
  # ASCII-8BIT エンコーディングの文字列を返す。
80
82
  def download_binary(uri)
81
83
  resource = @resource_cache[uri]
82
- if resource
84
+ if resource && resource.data.size > 0
85
+
83
86
  Net::HTTP.start(uri.host, uri.port) do |http|
84
87
  request = Net::HTTP::Get.new(uri)
85
88
  request['range'] = "bytes=#{resource.data.bytesize}-"
86
89
  response = http.request(request)
87
90
  response.body.force_encoding('ASCII-8BIT')
88
- pp response.code if $DEBUG
89
- pp response.to_hash if $DEBUG
91
+ p response.code if $DEBUG
92
+ p response.to_hash if $DEBUG
90
93
  case response
91
94
  when Net::HTTPPartialContent
92
95
  p :partial if $DEBUG
@@ -117,8 +120,8 @@ module Bbs
117
120
  request = Net::HTTP::Get.new(uri)
118
121
  response = http.request(request)
119
122
  response.body.force_encoding('ASCII-8BIT')
120
- pp response.code if $DEBUG
121
- pp response.to_hash if $DEBUG
123
+ p response.code if $DEBUG
124
+ p response.to_hash if $DEBUG
122
125
  case response
123
126
  when Net::HTTPOK
124
127
  else
@@ -272,7 +275,7 @@ module Bbs
272
275
  super
273
276
  end
274
277
 
275
- def posts(range)
278
+ def posts(range, opts = {})
276
279
  fail ArgumentError unless range.is_a? Range
277
280
  dat_for_range(range).each_line.map do |line|
278
281
  post = create_post(line.chomp)
@@ -329,14 +332,14 @@ module Bbs
329
332
  end
330
333
  end
331
334
 
332
- NICHAN_THREAD_URL_PATTERN = %r{\Ahttp://[a-zA-z\-\.]+(?::\d+)/test/read\.cgi\/(\w+)/(\d+)($|/)}
335
+ NICHAN_THREAD_URL_PATTERN = %r{\Ahttp://[0-9a-zA-z\-\.]+(:\d+)?/test/read\.cgi\/(\w+)/(\d+)($|/)}
333
336
 
334
337
  # 2ちゃんスレッド
335
338
  class Thread < ThreadBase
336
339
  class << self
337
340
  def from_url(url)
338
341
  if url.to_s =~ NICHAN_THREAD_URL_PATTERN
339
- board_name, thread_num = $1, $2.to_i
342
+ board_name, thread_num = $2, $3.to_i
340
343
  uri = URI(url)
341
344
  board = Board.send(:new, uri.hostname, uri.port, board_name)
342
345
  thread = board.thread(thread_num)
@@ -360,15 +363,24 @@ module Bbs
360
363
  super
361
364
  end
362
365
 
363
- def posts(range)
366
+ def posts(range, opts = {})
364
367
  fail ArgumentError unless range.is_a? Range
365
368
  url = URI(dat_url)
366
- lines = @board.send(:download_text, url)
369
+ lines = @board.send(:download_text,
370
+ if opts[:long_polling] then
371
+ url + "?long_polling=1"
372
+ else
373
+ url
374
+ end)
367
375
  ary = []
368
376
  lines.each_line.with_index(1) do |line, res_no|
369
377
  next unless range.include?(res_no)
370
378
 
371
- name, mail, date, body, title = line.chomp.split('<>', 5)
379
+ fields = line.chomp.split('<>', 5)
380
+ if fields.size != 5
381
+ raise FormatError, "invalid line #{line.inspect}"
382
+ end
383
+ name, mail, date, body, title = fields
372
384
  post = Post.new(res_no.to_s, name, mail, date, body)
373
385
  ary << post
374
386
  @last = [post.no, last].max
@@ -19,7 +19,7 @@ class Executable
19
19
  clear
20
20
  if str[-1] == "\n"
21
21
  if str.rindex("\n") != str.size-1 || str.index("\n") < str.rindex("\n")
22
- raise 'multiline'
22
+ raise 'multiline'
23
23
  end
24
24
 
25
25
  @out.print str
@@ -99,6 +99,11 @@ class Executable
99
99
  return {'BBS_TITLE'=>'<不明>'}
100
100
  end
101
101
 
102
+ def show(title, post)
103
+ notify_send = ENV['BBIFF_NOTIFY_SEND'] || (`which notify-send` != "" ? 'notify-send' : 'echo')
104
+ system("#{notify_send} #{Shellwords.escape(title)} #{Shellwords.escape(render_post(post))}")
105
+ end
106
+
102
107
  RETRY_INTERVAL_SECONDS = 3
103
108
 
104
109
  def start_polling(thread, start_no)
@@ -114,25 +119,28 @@ class Executable
114
119
  loop do
115
120
  out.set_line "#{thread.title}(#{thread.last}) 新着レス確認中"
116
121
 
117
- thread.posts(parse_range("#{start_no}-")).each do |post|
122
+ posts = thread.posts(parse_range("#{start_no}-"),
123
+ { long_polling: @settings.current['long_polling'] })
124
+ t = Time.now
125
+ posts.each do |post|
118
126
  out.puts "-----"
119
- puts render_post(post)
120
-
121
- system(@settings.current['bbiff_show'],
122
- thread.title, post.to_s)
127
+ unless @settings.current['no_render']
128
+ puts render_post(post)
129
+ end
123
130
 
124
- sleep 1
131
+ show(thread.title, post)
125
132
  end
126
133
 
127
134
  start_no = thread.last + 1
128
135
  if start_no > thread_stop
129
136
  out.puts "スレッドストップ"
130
- break
137
+ break
131
138
  end
132
139
 
133
- delay.times do |i|
140
+ d = [delay-(Time.now-t), 0].max.round
141
+ d.times do |i|
134
142
  j = i + 1
135
- out.set_line "#{thread.title}(#{thread.last}) 待機中 [#{'.'*j}#{' '*(delay - j)}]"
143
+ out.set_line "#{thread.title}(#{thread.last}) 待機中 [#{'.'*j}#{' '*(d - j)}]"
136
144
  sleep 1
137
145
  end
138
146
  end
@@ -147,30 +155,58 @@ class Executable
147
155
  STDERR.puts e.backtrace if $DEBUG
148
156
  STDERR.puts "#{RETRY_INTERVAL_SECONDS}秒後にリトライ"
149
157
  sleep RETRY_INTERVAL_SECONDS
158
+ thread = Bbs::create_thread(@settings.current['thread_url'])
150
159
  start_polling(thread, start_no)
151
160
  end
152
161
 
153
162
  def usage
154
- STDERR.puts "Usage: bbiff [http://jbbs.shitaraba.net/bbs/read.cgi/CATEGORY/BOARD_ID/THREAD_ID/] [START_NUMBER]"
155
-
163
+ STDERR.puts "Usage: bbiff [OPTIONS] [http://jbbs.shitaraba.net/bbs/read.cgi/CATEGORY/BOARD_ID/THREAD_ID/] [START_NUMBER]"
164
+
156
165
  STDERR.puts <<"EOD"
157
166
 
158
167
  Bbiff version #{Bbiff::VERSION}
159
168
  Copyright © 2016-2019 Yoteichi
169
+
170
+ -h, --help
171
+ --no-render
172
+ --debug
173
+ --long-polling (for Genkai)
174
+ --delay-seconds=N
160
175
  EOD
161
176
  end
162
177
 
163
178
  def main
164
- if ARGV.include?('-h') || ARGV.include?('--help')
165
- raise UsageError
179
+ args = []
180
+ ARGV.each do |arg|
181
+ case arg
182
+ when '-h', '--help'
183
+ raise UsageError
184
+ when '--no-render'
185
+ @settings.current['no_render'] = true
186
+ when '--debug'
187
+ $DEBUG = true
188
+ when '--long-polling'
189
+ @settings.current['long_polling'] = true
190
+ when /\A--delay-seconds=(.+)\z/
191
+ s = $1
192
+ if s =~ /\A\d+\z/
193
+ @settings.current['delay_seconds'] = s.to_i
194
+ else
195
+ STDERR.puts "delay-seconds must be a non-negative integer"
196
+ raise UsageError
197
+ end
198
+ when /\A-/
199
+ STDERR.puts "invalid option #{arg.inspect}"
200
+ raise UsageError
201
+ else
202
+ args << arg
203
+ end
166
204
  end
167
205
 
168
- if ARGV.size < 1 && !@settings.current['thread_url']
206
+ if args.size < 1
169
207
  raise UsageError
170
- elsif ARGV.size < 1
171
- url = @settings.current['thread_url']
172
208
  else
173
- url = ARGV[0]
209
+ url = args[0]
174
210
  end
175
211
 
176
212
  begin
@@ -188,13 +224,11 @@ EOD
188
224
  exit 1
189
225
  end
190
226
 
191
- start_no = ARGV[1] ? ARGV[1].to_i : thread.last + 1
227
+ start_no = args[1] ? args[1].to_i : thread.last + 1
192
228
  start_polling(thread, start_no)
193
229
  rescue UsageError
194
230
  usage
195
231
  exit 1
196
- ensure
197
- @settings.save
198
232
  end
199
233
  end
200
234
 
@@ -1,47 +1,16 @@
1
- require 'fileutils'
2
- require 'toml'
3
-
4
1
  module Bbiff
5
2
 
6
- class Settings
7
- attr_accessor :current
8
-
9
- APP_NAME = 'bbiff'
10
-
11
- def initialize
12
- @current = default.dup
13
- @config_dir = "#{ ENV['HOME'] }/.config/#{ APP_NAME }"
14
- load
15
- end
16
-
17
- def default
18
- { 'delay_seconds' => 10, 'bbiff_show' => 'bbiff-show' }
19
- end
20
-
21
- def load
22
- if File.readable?("#{@config_dir}/settings.tml")
23
- prefs = TOML.load_file("#{@config_dir}/settings.tml")
24
- self.current = current.merge(prefs)
25
- end
26
- end
3
+ class Settings
4
+ attr_accessor :current
27
5
 
28
- def save
29
- FileUtils.mkdir_p(@config_dir)
30
- prefs = (current.to_a - default.to_a).to_h
31
- File.open("#{@config_dir}/settings.tml", 'w') do |f|
32
- f.write(TOML.dump(prefs))
6
+ def initialize
7
+ @current = {
8
+ 'delay_seconds' => 7,
9
+ 'bbiff_show' => 'bbiff-show',
10
+ 'no_render' => false,
11
+ 'long_polling' => false,
12
+ }
33
13
  end
34
14
  end
35
15
 
36
16
  end
37
-
38
- end
39
-
40
- # settings = Bbiff::Settings.new
41
-
42
- # p settings.default
43
- # p settings.current
44
-
45
- # settings.current['delay_seconds'] = 7
46
- # settings.current['thread_url'] = 'http://jbbs.shitaraba.net/bbs/read.cgi/game/48538/1454983964'
47
- # settings.save
@@ -1,3 +1,3 @@
1
1
  module Bbiff
2
- VERSION = "0.3.5"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bbiff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoteichi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-05 00:00:00.000000000 Z
11
+ date: 2019-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,26 +66,11 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.4.1
69
- - !ruby/object:Gem::Dependency
70
- name: toml-rb
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 0.3.12
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 0.3.12
83
69
  description:
84
70
  email:
85
71
  - plonk@piano.email.ne.jp
86
72
  executables:
87
73
  - bbiff
88
- - bbiff-show
89
74
  extensions: []
90
75
  extra_rdoc_files: []
91
76
  files:
@@ -98,13 +83,11 @@ files:
98
83
  - Rakefile
99
84
  - bbiff.gemspec
100
85
  - bin/bbiff
101
- - bin/bbiff-show
102
86
  - lib/bbiff.rb
103
87
  - lib/bbiff/bbs_reader.rb
104
88
  - lib/bbiff/executable.rb
105
89
  - lib/bbiff/res_format.rb
106
90
  - lib/bbiff/settings.rb
107
- - lib/bbiff/show.rb
108
91
  - lib/bbiff/version.rb
109
92
  homepage: https://github.com/plonk/bbiff
110
93
  licenses:
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'bbiff'
4
-
5
- Bbiff::Show.new.main
@@ -1,31 +0,0 @@
1
- module Bbiff
2
-
3
- class Show
4
- class UsageError < StandardError
5
- end
6
-
7
- NOTIFY_SEND = 'notify-send'
8
-
9
- def usage
10
- STDERR.puts 'Usage: bbiff-show TITLE RES_LINE'
11
- end
12
-
13
- def main
14
- if ARGV.size != 2
15
- raise UsageError
16
- end
17
-
18
- title = ARGV[0]
19
- post = Bbs::Post.from_s(ARGV[1])
20
- notify_send = ENV['BBIFF_NOTIFY_SEND'] ||
21
- (`which #{NOTIFY_SEND}` != "" ? NOTIFY_SEND : 'echo')
22
- system("#{notify_send} #{Shellwords.escape(title)} #{Shellwords.escape(render_post(post))}")
23
-
24
- rescue UsageError
25
- usage
26
- end
27
-
28
- end
29
-
30
- end
31
-