bbs2ch 0.0.3 → 0.1.0

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