pic2ch 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [maiha@wota.jp]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,33 @@
1
+ pic2ch
2
+ ======
3
+
4
+ A gem that provides api to pic2ch
5
+
6
+
7
+ Usage
8
+ =====
9
+
10
+ threads = Pic2ch.pages.index.threads
11
+ => [thread, thread, ...]
12
+
13
+ thread = threads.first
14
+ => #<struct Pic2ch::Thread
15
+ name="【はだし】裸足の女の子の画像 Part6【ハダシ】",
16
+ link="/thread/34071/",
17
+ created="10/02/02",
18
+ star=1>
19
+
20
+ thread.jpgs
21
+ => ["06db8842090121983bd48f7d3bbd8b1d.jpg", ...]
22
+
23
+ thread.images
24
+ => ["http://strage.giox.info/pics3/1257261441/06db8842090121983bd48f7d3bbd8b1d.jpg", ...]
25
+
26
+ thread.thumbs
27
+ => ["http://strage.giox.info/thumbs/1257261441/06db8842090121983bd48f7d3bbd8b1d.jpg", ...]
28
+
29
+
30
+ Author
31
+ ======
32
+
33
+ maiha@wota.jp
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+
4
+ GEM_NAME = "pic2ch"
5
+ AUTHOR = "maiha"
6
+ EMAIL = "maiha@wota.jp"
7
+ HOMEPAGE = "http://github.com/maiha/pic2ch"
8
+ SUMMARY = "A gem that provides api to pic2ch"
9
+ GEM_VERSION = "0.0.1"
10
+
11
+ spec = Gem::Specification.new do |s|
12
+ s.rubyforge_project = 'asakusarb'
13
+ s.executables = []
14
+ s.name = GEM_NAME
15
+ s.version = GEM_VERSION
16
+ s.platform = Gem::Platform::RUBY
17
+ s.has_rdoc = true
18
+ s.extra_rdoc_files = ["README", "MIT-LICENSE"]
19
+ s.summary = SUMMARY
20
+ s.description = s.summary
21
+ s.author = AUTHOR
22
+ s.email = EMAIL
23
+ s.homepage = HOMEPAGE
24
+ s.require_path = 'lib'
25
+ s.add_dependency('nokogiri', '>= 1.4.1')
26
+ s.add_dependency('dsl_accessor', '>= 0.4.0')
27
+ s.files = %w(MIT-LICENSE README Rakefile) + Dir.glob("{lib,spec,app,public,stubs}/**/*")
28
+ end
29
+
30
+ Rake::GemPackageTask.new(spec) do |pkg|
31
+ pkg.gem_spec = spec
32
+ end
33
+
34
+ desc "Install the gem"
35
+ task :install do
36
+ Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
37
+ end
38
+
39
+ desc "Uninstall the gem"
40
+ task :uninstall do
41
+ Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
42
+ end
43
+
44
+ desc "Create a gemspec file"
45
+ task :gemspec do
46
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
47
+ file.puts spec.to_ruby
48
+ end
49
+ end
50
+
51
+ require 'spec/rake/spectask'
52
+ desc 'Default: run spec examples'
53
+ task :default => 'spec'
data/lib/pic2ch.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'pathname'
3
+ require 'dsl_accessor'
4
+
5
+ module Pic2ch
6
+ dsl_accessor :root , Dir.pwd, :writer=>proc{|dir| Pathname(dir)}
7
+ dsl_accessor :url , 'http://pic2ch.giox.org/' , :writer=>:parse_uri
8
+ dsl_accessor :image_url, 'http://strage.giox.info/', :writer=>:parse_uri
9
+
10
+ private
11
+ def self.parse_uri(url)
12
+ URI.parse(url)
13
+ end
14
+ end
15
+
16
+
17
+ dir = File.dirname(__FILE__) + '/' + File.basename(__FILE__, '.rb') + '/'
18
+
19
+ require dir + 'thread'
20
+ require dir + 'pages'
21
+ require dir + 'parsers'
22
+ require dir + 'downloaders'
@@ -0,0 +1,28 @@
1
+ ######################################################################
2
+ ### CachedAccessor
3
+
4
+ module CachedAccessor
5
+ def self.included(klass)
6
+ def klass.cached_accessor(&block)
7
+ Thread.current[:cached_accessor] = true
8
+ Define.new(self, &block)
9
+ ensure
10
+ Thread.current[:cached_accessor] = false
11
+ end
12
+ super
13
+ end
14
+
15
+ class Define
16
+ def initialize(klass, &block)
17
+ @klass = klass
18
+ instance_eval(&block)
19
+ end
20
+
21
+ def method_missing(symbol, &block)
22
+ cached = "__cached__#{symbol}"
23
+ @klass.send(:define_method, cached, &block)
24
+ @klass.class_eval("def #{symbol} ;@#{symbol} ||= #{cached}; end", "(__CACHED_ACCESSOR__)", 1)
25
+ @klass.class_eval("def #{symbol}!;@#{symbol} = #{cached}; end", "(__CACHED_ACCESSOR__)", 2) unless /\?|!/ === symbol.to_s
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ dir = File.dirname(__FILE__) + '/' + File.basename(__FILE__, '.rb') + '/'
2
+
3
+ require dir + 'thread'
@@ -0,0 +1,54 @@
1
+ module Pic2ch
2
+ module Downloaders
3
+ class Thread
4
+ delegate :time, :to=>"@thread"
5
+
6
+ def initialize(thread)
7
+ @thread = thread
8
+ end
9
+
10
+ def base_path
11
+ @base_path ||= (
12
+ path = Pic2ch.root + Pic2ch::Thread.image_url.host + "urls" + time.to_s
13
+ path.mkpath
14
+ path
15
+ )
16
+ end
17
+
18
+ def images_path_for(type = :images)
19
+ base_path + "#{type}.txt"
20
+ end
21
+
22
+ def request(type = nil)
23
+ if type
24
+ requested?(type) or
25
+ images_path_for(type).open("w+"){|f| f.puts @thread.send(type)}
26
+ else
27
+ request(:thumbs)
28
+ request(:images)
29
+ end
30
+ end
31
+
32
+ def requested?(type = :images)
33
+ images_path_for(type).exist?
34
+ end
35
+
36
+ def done_flag_for(type = :images)
37
+ base_path + "#{type}.log"
38
+ end
39
+
40
+ def done?(type = :images)
41
+ done_flag_for(type).exist?
42
+ end
43
+
44
+ def command(type = :images)
45
+ "wget -x -i %s > %s 2>&1" % [images_path_for(type), done_flag_for(type)]
46
+ end
47
+
48
+ def execute(type = :images)
49
+ request(type)
50
+ system(command(type))
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,19 @@
1
+ module Pic2ch
2
+ module Pages
3
+ def self.index(p = 1)
4
+ Index.new(p)
5
+ end
6
+
7
+ def self.threads
8
+ index.threads
9
+ end
10
+ end
11
+
12
+ def self.pages
13
+ Pages
14
+ end
15
+ end
16
+
17
+ dir = File.dirname(__FILE__) + '/' + File.basename(__FILE__, '.rb') + '/'
18
+
19
+ require dir + 'index'
@@ -0,0 +1,38 @@
1
+ module Pic2ch
2
+ module Pages
3
+ class Index
4
+ attr_reader :p
5
+
6
+ def initialize(p)
7
+ @p = p.to_i
8
+ @p = 1 if @p < 1
9
+ end
10
+
11
+ ######################################################################
12
+ ### Accessors
13
+
14
+ def url
15
+ Pic2ch.url + path
16
+ end
17
+
18
+ def path
19
+ p == 1 ? '' : "/?p=#{p}"
20
+ end
21
+
22
+ ######################################################################
23
+ ### Fetch
24
+
25
+ def html
26
+ @html ||= open(url).read{}
27
+ end
28
+
29
+ ######################################################################
30
+ ### Parsers
31
+ def parser
32
+ @parser ||= Parsers::Index.new(html)
33
+ end
34
+
35
+ delegate :threads, :pages, :to=>"parser"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,4 @@
1
+ dir = File.dirname(__FILE__) + '/' + File.basename(__FILE__, '.rb') + '/'
2
+
3
+ require dir + 'index'
4
+ require dir + 'thread'
@@ -0,0 +1,54 @@
1
+ module Pic2ch
2
+ module Parsers
3
+ class Index
4
+ module ElementParser
5
+ def self.next_class_for(e, name, limit = 10, &block)
6
+ limit.times do
7
+ e = e.next or return nil
8
+ next unless e["class"] == name.to_s
9
+ return block ? block.call(e) : e
10
+ end
11
+ return nil
12
+ end
13
+ end
14
+
15
+ def initialize(html)
16
+ @html = html
17
+ end
18
+
19
+ def doc
20
+ @doc ||= Nokogiri::HTML(@html)
21
+ end
22
+
23
+ def elements
24
+ @elements ||= doc.xpath("/html/body/div[2]/div[2]/a")
25
+ end
26
+
27
+ def threads
28
+ @threads ||= elements.map{|e| Pic2ch::Thread.new(*construct(e))}
29
+ end
30
+
31
+ def coded
32
+ @coded ||= all.inject({}){|hash,obj| hash[obj.code] = obj; hash}
33
+ end
34
+
35
+ def pages
36
+ @pages ||= doc.css("div.paginate a span.enable_page").map{|span| Pages::Index.new(span.text)}
37
+ end
38
+
39
+ # def get(code)
40
+ # Static.new(code)
41
+ # end
42
+
43
+ def construct(e)
44
+ [
45
+ e.text, # name
46
+ e["href"], # link
47
+ ElementParser.next_class_for(e, :created){|e| e.text}, # created
48
+ ElementParser.next_class_for(e, :star ){|e| e.text}.to_i, # star
49
+ ]
50
+ end
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,45 @@
1
+ module Pic2ch
2
+ module Parsers
3
+ class Thread
4
+ delegate :image_url, :to=>"Pic2ch"
5
+ delegate :url, :to=>"@thread"
6
+
7
+ def initialize(thread)
8
+ @thread = thread
9
+ end
10
+
11
+ def html
12
+ @html ||= open(url).read{}
13
+ end
14
+
15
+ def doc
16
+ @doc ||= Nokogiri::HTML(html)
17
+ end
18
+
19
+ # {id:'1243648801',urls:'54b14715c000a6334ad2e8771cbf70e8.jpg:1e611e8710dd60d616e345aa69334c2d.jpg:...'}
20
+ def jpgs
21
+ @jpgs ||= html.scan(/',urls:'(.*?)'/).first.first.split(/:/)
22
+ end
23
+
24
+ def time
25
+ @time ||= html.scan(/\{id:'(\d+)',urls:'/).first.first.to_i
26
+ end
27
+
28
+ def title
29
+ @title ||= doc.search("title").text
30
+ end
31
+
32
+ def thumbs
33
+ @thumbs ||= jpgs.map{|jpg| image_url + "/thumbs/#{time}/#{jpg}" }
34
+ end
35
+
36
+ def images
37
+ @images ||= jpgs.map{|jpg| image_url + "/pics3/#{time}/#{jpg}" }
38
+ end
39
+
40
+ def images_with_thumbs
41
+ @images_with_thumbs ||= [images, thumbs].transpose
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,41 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+
4
+ module Pic2ch
5
+ Thread = Struct.new(:name, :link, :created, :star)
6
+ class Thread
7
+ ######################################################################
8
+ ### Accessors
9
+
10
+ def url
11
+ Pic2ch.url + link
12
+ end
13
+
14
+ def code
15
+ link.to_s.scan(/\d+/).flatten.first.to_i
16
+ end
17
+
18
+ ######################################################################
19
+ ### Parser
20
+
21
+ def parser
22
+ @parser ||= Parsers::Thread.new(self)
23
+ end
24
+
25
+ delegate :jpgs, :thumbs, :images, :title, :to=>"parser"
26
+
27
+ ######################################################################
28
+ ### Downloader
29
+
30
+ def downloader
31
+ Downloaders::Thread.new(self)
32
+ end
33
+
34
+ def download
35
+ Dir.chdir(Pic2ch.root) do
36
+ downloader.execute
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,14 @@
1
+ module Pic2ch
2
+ class Thread
3
+ module ElementParser
4
+ def self.next_class_for(e, name, limit = 10, &block)
5
+ limit.times do
6
+ e = e.next or return nil
7
+ next unless e["class"] == name.to_s
8
+ return block ? block.call(e) : e
9
+ end
10
+ return nil
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module Pic2ch
2
+ class Thread
3
+ class Static < Thread
4
+ def initialize(code)
5
+ @code = code.to_i
6
+ @url = self.class.url + "/thread/#{@code}"
7
+ end
8
+ end
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pic2ch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - maiha
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-02 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.4.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: dsl_accessor
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.0
34
+ version:
35
+ description: A gem that provides api to pic2ch
36
+ email: maiha@wota.jp
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README
43
+ - MIT-LICENSE
44
+ files:
45
+ - MIT-LICENSE
46
+ - README
47
+ - Rakefile
48
+ - lib/pic2ch.rb
49
+ - lib/pic2ch/pages/index.rb
50
+ - lib/pic2ch/parsers/thread.rb
51
+ - lib/pic2ch/parsers/index.rb
52
+ - lib/pic2ch/downloaders.rb
53
+ - lib/pic2ch/thread.rb
54
+ - lib/pic2ch/downloaders/thread.rb
55
+ - lib/pic2ch/thread/element_parser.rb
56
+ - lib/pic2ch/thread/static.rb
57
+ - lib/pic2ch/parsers.rb
58
+ - lib/pic2ch/cached_accessor.rb
59
+ - lib/pic2ch/pages.rb
60
+ has_rdoc: true
61
+ homepage: http://github.com/maiha/pic2ch
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options: []
66
+
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ requirements: []
82
+
83
+ rubyforge_project: asakusarb
84
+ rubygems_version: 1.3.5
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: A gem that provides api to pic2ch
88
+ test_files: []
89
+