bbs2ch 0.0.3 → 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a038e3331d1a4be3e1fa32b7b41f8f56ad4e0a2c
4
+ data.tar.gz: ad2649a95581f6be3d595cf7d2a2d6d9de95c0bc
5
+ SHA512:
6
+ metadata.gz: 73d04c4ea98e1ad4c566a6b961255a933f7e00a0dd9bdb7582cebb4062439674d608f0feba5fca3c44fae78667e524a2975b9a3e0145994e6a6c6db0b7ace80d
7
+ data.tar.gz: 41c0054c04973b3a63f98ee621fb2d529c06f78362ee2a28341dbb26383f1cbdc58af56e1126cd220b62e2ae68951219a556b20736ecb99c038a271b9ddcb0cd
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Rakefile CHANGED
@@ -4,7 +4,3 @@ require "bundler/gem_tasks"
4
4
  Bundler.setup
5
5
  require 'rspec/core/rake_task'
6
6
 
7
- desc 'run spec'
8
- Rspec::Core::RakeTask.new(:spec) do |t|
9
- t.rspec_opts = ['-c', '-fs']
10
- end
@@ -15,8 +15,8 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = BBS2ch::VERSION
17
17
 
18
- gem.add_dependency "mechanize"
18
+ gem.add_dependency "faraday", '~> 0.8.8'
19
19
 
20
20
  gem.add_development_dependency "rspec"
21
- gem.add_development_dependency "fakefs"
21
+ gem.add_development_dependency "pry"
22
22
  end
@@ -1,7 +1,8 @@
1
1
  require "bbs2ch/version"
2
2
 
3
- require 'bbs2ch/menu'
3
+ require 'bbs2ch/category'
4
4
  require 'bbs2ch/board'
5
5
  require 'bbs2ch/thread'
6
- require 'bbs2ch/response'
7
- require 'bbs2ch/image'
6
+ require 'bbs2ch/post'
7
+ require 'bbs2ch/client'
8
+ require 'bbs2ch/connection'
@@ -1,33 +1,32 @@
1
- require 'mechanize'
2
- require 'bbs2ch/thread'
3
-
4
- SUBJECT_FILE = "subject.txt"
5
-
6
1
  module BBS2ch
7
2
  class Board
8
- def initialize(name, url, extra = {})
9
- @name = name
10
- @url = url
11
- @extra = extra
12
- @extra[:board] = {url: @url, name: @name}
3
+ def initialize(name, url)
4
+ @name = name
5
+ @url = url
6
+ @threads = nil
13
7
  end
14
8
 
15
- # TODO select
16
- def threads(regex = /.*/)
9
+ attr_accessor :name, :url
17
10
 
18
- @agent = Mechanize.new
19
- page = @agent.get(url + SUBJECT_FILE)
11
+ def threads(regex = nil)
12
+ @threads ||= load_threads
13
+ return @threads unless regex
20
14
 
21
- threads = []
22
- page.body.toutf8.lines{|line|
23
- th_dat, th_name = line.chomp.split(/<>/)
24
- if th_name =~ regex
25
- threads << Thread.new(th_name, "#{@url}dat/#{th_dat}", @extra)
26
- end
27
- }
28
- threads
15
+ @threads.select { |thread| thread.name.match(regex) }
29
16
  end
30
17
 
31
- attr_accessor :name, :url, :extra
18
+ def load_threads
19
+ body = Connection.new(url + '/subject.txt').response_body
20
+
21
+ body.each_line.map { |line|
22
+ line.chomp!
23
+
24
+ title_end = line.rindex(' ')
25
+ dat, title = line[0...title_end].split('<>')
26
+ res_count = line[title_end + 1 .. -1][/[0-9]+/].to_i
27
+
28
+ BBS2ch::Thread.new(title, "#{url}/dat/#{dat}", res_count)
29
+ }
30
+ end
32
31
  end
33
- end
32
+ end
@@ -0,0 +1,10 @@
1
+ module BBS2ch
2
+ class Category
3
+ def initialize(name, boards = [])
4
+ @name = name
5
+ @boards = boards
6
+ end
7
+
8
+ attr_accessor :name, :boards
9
+ end
10
+ end
@@ -0,0 +1,56 @@
1
+ require 'faraday'
2
+ require 'kconv'
3
+
4
+ module BBS2ch
5
+ class Client
6
+ def initialize
7
+ load_menu
8
+ end
9
+
10
+ def categories(regex = nil)
11
+ load_menu unless @categories
12
+ return @categories unless regex
13
+
14
+ @categories.select { |category| category.name.match(regex) }
15
+ end
16
+
17
+ def boards(regex = nil)
18
+ load_menu unless @boards
19
+ return @boards unless regex
20
+
21
+ @boards.select { |board| board.name.match(regex) }
22
+ end
23
+
24
+ def load_menu
25
+ body = Connection.new('http://menu.2ch.net/bbsmenu.html').response_body
26
+
27
+ start_pos = body.index('<BR><BR><B>')
28
+ body = body[start_pos..-1].gsub(/<!--.*-->/m, '')
29
+
30
+ @categories = []
31
+ @boards = []
32
+
33
+ category = nil
34
+ body.each_line do |line|
35
+ line.chomp!
36
+
37
+ if line.match('<BR><BR><B>(.+)</B><BR>')
38
+ name = $1
39
+ category = Category.new(name)
40
+ elsif line.match('<A HREF=(.+)/>(.+)</A>')
41
+ name = $2
42
+ url = $1
43
+ board = Board.new(name, url)
44
+ category.boards << board
45
+ @boards << board
46
+ elsif line.length == 0
47
+ @categories << category
48
+ else
49
+ # break
50
+ end
51
+ end
52
+
53
+ self
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ module BBS2ch
2
+ class Connection
3
+ def initialize(url)
4
+ @conn = Faraday.new(url: url) do |faraday|
5
+ # faraday.request :url_encoded # form-encode POST params
6
+ # faraday.response :logger # log requests to STDOUT
7
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
8
+ end
9
+
10
+ @conn.headers[:user_agent] = 'Monazilla/1.00 (bbs2ch-rubygems/0.1.0)'
11
+ end
12
+
13
+ attr_accessor :conn
14
+
15
+ def response_body
16
+ @conn.get.body.toutf8
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ module BBS2ch
2
+ class Post
3
+ def initialize(name, email, time, id, be, body, title)
4
+ @name = name
5
+ @email = email
6
+ @time = time
7
+ @id = id
8
+ @be = be
9
+ @body = body
10
+ @title = title
11
+ end
12
+
13
+ def images
14
+ fix_ttp @body.scan(%r{ttps?:.*\.(?:jpg|png|gif)})
15
+ end
16
+
17
+ def videos
18
+ xvideos + fc2
19
+ end
20
+
21
+ def xvideos
22
+ fix_ttp @body.scan(%r{ttp://(?:www|jp)\.xvideos\.com/video[0-9]+})
23
+ end
24
+
25
+ def fc2
26
+ fix_ttp @body.scan(%r{ttp://video\.fc2\.com/a/content/[0-9a-zA-Z]+})
27
+ end
28
+
29
+ def fix_ttp(urls)
30
+ urls.map { |url| url.gsub(/^ttp/, 'http') }
31
+ end
32
+
33
+ attr_accessor :name, :email, :time, :id, :be, :body, :title
34
+ end
35
+ end
@@ -1,29 +1,41 @@
1
- require 'mechanize'
2
- require 'bbs2ch/response'
3
1
  require 'time'
4
2
 
5
3
  module BBS2ch
6
4
  class Thread
7
- def initialize(name, url, extra = {})
8
- @name = name
9
- @url = url
10
- @extra = extra
11
- @extra[:thread] = {name: @name, url: @url}
5
+ def initialize(name, url, res_count)
6
+ @name = name
7
+ @url = url
8
+ @res_count = res_count
9
+ @posts = nil
12
10
  end
13
11
 
14
- # TODO select, cache
15
- def responses
12
+ attr_accessor :name, :url, :res_count
16
13
 
17
- @agent = Mechanize.new
18
- page = @agent.get @url
14
+ def posts
15
+ @posts ||= load_posts
16
+ end
17
+
18
+ def load_posts
19
+ body = Connection.new(@url).response_body
20
+ body.each_line.map { |line|
21
+ line.chomp!
22
+ # [名前]<>[メール]<>[日付] [ID] [BE-ID]<>[本文]<>[スレッドタイトル]
23
+ name, email, time_and_id, body, title = line.split('<>')
24
+
25
+ body.gsub!('<BR>', "\n")
19
26
 
20
- responses = []
21
- page.body.toutf8.lines{|line|
22
- responses << Response.parse(line)
27
+ begin
28
+ time = Time.parse(time_and_id)
29
+ rescue ArgumentError
30
+ time = nil
31
+ end
32
+ time_and_id.match('ID:(\S+)')
33
+ id = $1
34
+ time_and_id.match('BE:(\S+)')
35
+ be = $1
36
+
37
+ Post.new(name, email, time, id, be, body, title)
23
38
  }
24
- responses
25
39
  end
26
-
27
- attr_accessor :name, :url, :extra
28
40
  end
29
- end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module BBS2ch
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bbs2ch'
4
+
5
+ client = BBS2ch::Client.new
6
+ board = client.boards(/犬猫/).first #=> board: "犬猫大好き"
7
+ thread = board.threads(/猫画像/).first
8
+ posts = thread.posts
9
+ puts posts.map(&:images).flatten
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe BBS2ch::Board do
4
+ describe '#new' do
5
+ before do
6
+ @board = BBS2ch::Board.new('foo', 'http://example.com')
7
+ end
8
+
9
+ it 'has name' do
10
+ expect(@board.name).to eq('foo')
11
+ end
12
+
13
+ it 'has url' do
14
+ expect(@board.url).to eq('http://example.com')
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe BBS2ch::Category do
4
+ describe '#new' do
5
+ before do
6
+ @category = BBS2ch::Category.new('地震', ['board1'])
7
+ end
8
+
9
+ it 'has name' do
10
+ expect(@category.name).to eq('地震')
11
+ end
12
+
13
+ it 'has boards' do
14
+ expect(@category.boards.length).to be > 0
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe BBS2ch::Client do
4
+ before(:all) do
5
+ @client = BBS2ch::Client.new
6
+ end
7
+
8
+ describe '#new' do
9
+ it 'has categories' do
10
+ expect(@client.categories.length).to be > 0
11
+ end
12
+
13
+ it 'has boards' do
14
+ expect(@client.boards.length).to be > 0
15
+ end
16
+ end
17
+
18
+ describe '2ch' do
19
+ it 'first category name' do
20
+ expect(@client.categories.first.name).to eq('地震')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ require 'bbs2ch'
2
+ # This file was generated by the `rspec --init` command. Conventionally, all
3
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
4
+ # Require this file using `require "spec_helper"` to ensure that it is only
5
+ # loaded once.
6
+ #
7
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
8
+ RSpec.configure do |config|
9
+ config.treat_symbols_as_metadata_keys_with_true_values = true
10
+ config.run_all_when_everything_filtered = true
11
+ config.filter_run :focus
12
+
13
+ # Run specs in random order to surface order dependencies. If you find an
14
+ # order dependency and want to debug it, you can fix the order by providing
15
+ # the seed, which is printed after each run.
16
+ # --seed 1234
17
+ config.order = 'random'
18
+ end
metadata CHANGED
@@ -1,62 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bbs2ch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - fukayatsu
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-07-16 00:00:00.000000000 Z
11
+ date: 2013-09-08 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- name: mechanize
14
+ name: faraday
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ~>
20
18
  - !ruby/object:Gem::Version
21
- version: '0'
19
+ version: 0.8.8
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ~>
28
25
  - !ruby/object:Gem::Version
29
- version: '0'
26
+ version: 0.8.8
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rspec
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
- name: fakefs
42
+ name: pry
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  description: A gem to read 2ch BBS
@@ -67,6 +60,7 @@ extensions: []
67
60
  extra_rdoc_files: []
68
61
  files:
69
62
  - .gitignore
63
+ - .rspec
70
64
  - Gemfile
71
65
  - LICENSE
72
66
  - README.md
@@ -74,42 +68,43 @@ files:
74
68
  - bbs2ch.gemspec
75
69
  - lib/bbs2ch.rb
76
70
  - lib/bbs2ch/board.rb
77
- - lib/bbs2ch/image.rb
78
- - lib/bbs2ch/menu.rb
79
- - lib/bbs2ch/response.rb
71
+ - lib/bbs2ch/category.rb
72
+ - lib/bbs2ch/client.rb
73
+ - lib/bbs2ch/connection.rb
74
+ - lib/bbs2ch/post.rb
80
75
  - lib/bbs2ch/thread.rb
81
76
  - lib/bbs2ch/version.rb
82
77
  - memo.md
83
- - spec/bbs2ch_spec.rb
78
+ - sample/cat.rb
79
+ - spec/bbs2ch/board_spec.rb
80
+ - spec/bbs2ch/category_spec.rb
81
+ - spec/bbs2ch/client_spec.rb
82
+ - spec/spec_helper.rb
84
83
  homepage: ''
85
84
  licenses: []
85
+ metadata: {}
86
86
  post_install_message:
87
87
  rdoc_options: []
88
88
  require_paths:
89
89
  - lib
90
90
  required_ruby_version: !ruby/object:Gem::Requirement
91
- none: false
92
91
  requirements:
93
- - - ! '>='
92
+ - - '>='
94
93
  - !ruby/object:Gem::Version
95
94
  version: '0'
96
- segments:
97
- - 0
98
- hash: 3642638197611839710
99
95
  required_rubygems_version: !ruby/object:Gem::Requirement
100
- none: false
101
96
  requirements:
102
- - - ! '>='
97
+ - - '>='
103
98
  - !ruby/object:Gem::Version
104
99
  version: '0'
105
- segments:
106
- - 0
107
- hash: 3642638197611839710
108
100
  requirements: []
109
101
  rubyforge_project:
110
- rubygems_version: 1.8.24
102
+ rubygems_version: 2.0.3
111
103
  signing_key:
112
- specification_version: 3
104
+ specification_version: 4
113
105
  summary: A gem to read 2ch BBS
114
106
  test_files:
115
- - spec/bbs2ch_spec.rb
107
+ - spec/bbs2ch/board_spec.rb
108
+ - spec/bbs2ch/category_spec.rb
109
+ - spec/bbs2ch/client_spec.rb
110
+ - spec/spec_helper.rb
@@ -1,13 +0,0 @@
1
- require 'mechanize'
2
-
3
-
4
- module BBS2ch
5
- class Image
6
- def initialize(url, extra={})
7
- @url = url
8
- @extra = extra
9
- end
10
-
11
- attr_accessor :url, :extra
12
- end
13
- end
@@ -1,30 +0,0 @@
1
- require 'mechanize'
2
- require 'bbs2ch/board'
3
-
4
- module BBS2ch
5
- class Menu
6
- def initialize(url = nil)
7
- @url = url || "http://menu.2ch.net/bbsmenu.html"
8
- @extra = {menu: {url: @url}}
9
- end
10
-
11
- #TODO select
12
- def boards(regex = /.*/)
13
-
14
- @agent = Mechanize.new
15
- page = @agent.get url
16
-
17
- boards = []
18
- page.links.each{|link|
19
- if link.href =~ /[^(www|info)]\.(2ch\.net|bbspink.com|machi\.to|)\//
20
- if link.text =~ regex
21
- boards << Board.new(link.text, link.href, @extra)
22
- end
23
- end
24
- }
25
- boards
26
- end
27
-
28
- attr_accessor :url
29
- end
30
- end
@@ -1,37 +0,0 @@
1
- require 'mechanize'
2
- require 'bbs2ch/image'
3
-
4
- module BBS2ch
5
- class Response
6
- def initialize(name, email, time, message, extra={})
7
- @name = name
8
- @email = email
9
- @time = time
10
- @message = message
11
- @extra = extra
12
- @extra[:response] =
13
- {name: @name, email: @email, time: @time, message: @message}
14
- end
15
-
16
- def images(regex = /((http|https|ttp):\/\/.*\.(jpg|png|gif))/)
17
- images = []
18
- @message.split(/<br>/).each{|line|
19
- match = line.scan regex
20
- if match.size > 0
21
- url = match[0][0]
22
- url = 'h' + url if url[0] != 'h'
23
- images << Image.new(url, @extra)
24
- end
25
- }
26
- images
27
- end
28
-
29
- # TODO arrayに対応
30
- def self.parse(text, extra={})
31
- name, email, time_str, message = text.chomp.split(/<>/)
32
- Response.new(name, email, Time.parse(time_str), message, extra)
33
- end
34
-
35
- attr_reader :name, :email, :time, :message, :extra
36
- end
37
- end
@@ -1,70 +0,0 @@
1
- # coding: utf-8
2
-
3
- # TODO オフラインでもテストできるようにする
4
-
5
- require 'bundler'
6
- Bundler.setup(:default, :test)
7
-
8
- require 'bbs2ch'
9
-
10
- describe BBS2ch do
11
-
12
- describe 'Menu' do
13
-
14
- context '#initialize' do
15
- it 'default url' do
16
- menu = BBS2ch::Menu.new
17
- menu.url.should == "http://menu.2ch.net/bbsmenu.html"
18
- end
19
-
20
- it 'custom url' do
21
- menu = BBS2ch::Menu.new("http://foo.net")
22
- menu.url.should == 'http://foo.net'
23
- end
24
- end
25
-
26
- context '#boards' do
27
- before do
28
- @menu = BBS2ch::Menu.new
29
- end
30
-
31
- it 'size not 0' do
32
- @menu.boards.size.should_not == 0
33
- #p @menu.boards(/料理/).first.threads(/料理/).first.responses.first
34
- end
35
-
36
- end
37
- end
38
-
39
- describe 'Board' do
40
- context '#initialize' do
41
- end
42
- end
43
-
44
- describe 'Thread' do
45
- context '#initialize' do
46
- end
47
- end
48
-
49
- describe 'Response' do
50
- context '#initialize' do
51
- end
52
-
53
- context '#images' do
54
- it 'return 2 images' do
55
- response = BBS2ch::Response.new('name', 'email', 'time', '
56
- http://hoge.com/hoge/piyo.jpg<br>
57
- ttp://hoge.com/hoge/piyo.png<br>')
58
- images = response.images
59
- images[0].url.should == 'http://hoge.com/hoge/piyo.jpg'
60
- images[1].url.should == 'http://hoge.com/hoge/piyo.png'
61
- end
62
- end
63
- end
64
-
65
- describe 'Image' do
66
- context '#initialize' do
67
- end
68
- end
69
-
70
- end