pagelapse 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3f8d6638ceb44da7aa0d6baaaf1c69e17da1cdfd
4
+ data.tar.gz: a0eec7989c94fb441e0605de10d224010703fe1a
5
+ SHA512:
6
+ metadata.gz: d1f965cab3bad214de6f0866b2a49a3833d99f763e48ca315e50cb3fcca6c68d2fcf7bc6a1d2ff6330de8e47c9ea9669f8be9347449bcd5d78b758eea9e7adfc
7
+ data.tar.gz: c14caa22ad972f86ec36b314fe1e2d4c22e5ce435e9b7a11c9be6cf57536992685ea2a7c1f4b15749e49e191426deec76a0de4451276da4db5aa360e12ee4d0f
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pagelapse.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Robert Lord
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Pagelapse
2
+
3
+ Generates time-lapses of websites, with ease. Inspirational background music not included.
4
+
5
+ ## Installation
6
+
7
+ Pagelapse needs phantomjs to take screenshots, so simply run:
8
+
9
+ $ brew install phantomjs
10
+
11
+ And then install pagelapse:
12
+
13
+ $ gem install pagelapse
14
+
15
+ ## Usage
16
+
17
+ Add a page to start capturing:
18
+
19
+ $ pagelapse record http://reddit.com
20
+
21
+ Pagelapse will check the website every 20 seconds for changes. There are some settings, too:
22
+
23
+ $ pagelapse record http://reddit.com --interval 60 --width 1200 --height 1000 --full-page false
24
+
25
+ To view the websites you've recorded in a nice web interface:
26
+
27
+ $ pagelapse view
28
+
29
+ To stop recording a page:
30
+
31
+ $ pagelapse stop http://reddit.com
32
+
33
+ To pause and resume the background server:
34
+
35
+ $ pagelapse pause
36
+ $ pagelapse resume
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it ( <http://github.com/lord/pagelapse/fork> )
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/pagelapse ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pagelapse'
3
+ Pagelapse.cli(ARGV)
@@ -0,0 +1,32 @@
1
+ # Parses lapsefiles
2
+
3
+ module Pagelapse
4
+ class Parser
5
+ def initialize(file)
6
+ puts "Starting Pagelapse #{Pagelapse::VERSION}"
7
+ @recorders = []
8
+ instance_eval File.read(file), file, 1
9
+ while @recorders.length > 0 do
10
+ @recorders.each do |r|
11
+ if r.ready?
12
+ print "Checking #{r.name}"
13
+ if r.capture
14
+ puts " - captured!"
15
+ else
16
+ puts ""
17
+ end
18
+ end
19
+ end
20
+ @recorders.reject! do |r|
21
+ r.expired?
22
+ end
23
+ end
24
+ end
25
+
26
+ def record(name, url, interval=20)
27
+ r = Pagelapse::Recorder.new(name, url)
28
+ yield r
29
+ @recorders << r
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,67 @@
1
+ require 'fileutils'
2
+ module Pagelapse
3
+ class Recorder
4
+ attr_accessor :interval, :duration, :timeout, :width, :height, :expiration
5
+ attr_reader :name, :url
6
+
7
+ def initialize(name, url)
8
+ @name = name
9
+ @url = url
10
+ @interval = 20
11
+ @duration = nil
12
+ @on_load = nil
13
+ @expiration = nil
14
+ @start = Time.now
15
+ @width = 1240
16
+ @height = 900
17
+ @timer = Time.new 0
18
+ @capture_if = nil
19
+ @save_if = nil
20
+ FileUtils.mkdir_p(File.join 'lapses', @name)
21
+ end
22
+
23
+ def before_capture(&block)
24
+ @on_load = block
25
+ end
26
+
27
+ def capture_if(&block)
28
+ @capture_if = block
29
+ end
30
+
31
+ def save_if(&block)
32
+ @save_if = block
33
+ end
34
+
35
+ def filename
36
+ File.join 'lapses', @name, "#{Time.now.to_i}.png"
37
+ end
38
+
39
+ # Returns true if timer is expired and ready to capture
40
+ def ready?
41
+ @timer < Time.now - @interval
42
+ end
43
+
44
+ # Returns true if recorder has expired
45
+ def expired?
46
+ Time.now > @start + @expiration if @expiration
47
+ end
48
+
49
+ def capture
50
+ @timer = Time.now
51
+ ws = Pagelapse::Screenshot.new
52
+ if @on_load
53
+ ws.start_session(&@on_load)
54
+ else
55
+ ws.start_session
56
+ end.capture(
57
+ @url,
58
+ filename,
59
+ width: @width,
60
+ height: @height,
61
+ timeout: @timeout,
62
+ capture_if: @capture_if,
63
+ save_if: @save_if
64
+ )
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,83 @@
1
+ require "capybara/dsl"
2
+ require "capybara/poltergeist"
3
+
4
+ module Pagelapse
5
+ # Thanks to http://www.cherpec.com/2013/04/30/capturing-web-page-screenshots-from-ruby/
6
+ # for the basis of this code
7
+ class Screenshot
8
+ include Capybara::DSL
9
+
10
+ # Captures a screenshot of +url+ saving it to +output_path+.
11
+ def capture(url, output_path, width: 1024, height: 768, full: false, timeout: false, capture_if: nil, save_if: nil)
12
+ # Browser settings
13
+ page.driver.resize(width, height)
14
+ page.driver.headers = {
15
+ "User-Agent" => "Pagelapse #{Pagelapse::VERSION}",
16
+ }
17
+
18
+ unless capture_if
19
+ capture_if = Proc.new do
20
+ page.driver.status_code == 200
21
+ end
22
+ end
23
+
24
+ unless save_if
25
+ save_if = Proc.new do |old_file, new_file|
26
+ Digest::MD5.file(old_file).hexdigest != Digest::MD5.file(new_file).hexdigest
27
+ end
28
+ end
29
+
30
+ # Open page
31
+ visit url
32
+
33
+ # Timeout
34
+ sleep timeout if timeout
35
+
36
+ if instance_eval(&capture_if)
37
+ old_file = last_file_next_to(output_path)
38
+
39
+ # Save screenshot
40
+ page.driver.save_screenshot(output_path, :full => full)
41
+
42
+ # If no old file, than always save
43
+ return true unless old_file
44
+
45
+ if save_if.call(old_file, output_path)
46
+ true
47
+ else
48
+ File.delete output_path
49
+ false
50
+ end
51
+ else
52
+ false
53
+ end
54
+ end
55
+
56
+ def start_session(&block)
57
+ Capybara.reset_sessions!
58
+ Capybara.current_session.instance_eval(&block) if block_given?
59
+ self
60
+ end
61
+
62
+ private
63
+ def last_file_next_to(file)
64
+ Dir[File.dirname(file) + "/*"].max_by {|f| File.mtime(f)}
65
+ end
66
+ end
67
+
68
+ # By default Capybara will try to boot a rack application
69
+ # automatically. You might want to switch off Capybara's
70
+ # rack server if you are running against a remote application
71
+ Capybara.run_server = false
72
+ Capybara.register_driver :poltergeist do |app|
73
+ Capybara::Poltergeist::Driver.new(app, {
74
+ # Raise JavaScript errors to Ruby
75
+ js_errors: false,
76
+ phantomjs_logger: File.open(File::NULL, "w"),
77
+ debug: false,
78
+ # Additional command line options for PhantomJS
79
+ phantomjs_options: ['--ignore-ssl-errors=yes'],
80
+ })
81
+ end
82
+ Capybara.current_driver = :poltergeist
83
+ end
@@ -0,0 +1,3 @@
1
+ module Pagelapse
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,79 @@
1
+ require 'sinatra'
2
+
3
+ module Pagelapse
4
+ class Viewer < Sinatra::Base
5
+ configure do
6
+ set :public_folder, 'lapses'
7
+ end
8
+ get '/' do
9
+ names = Dir['lapses/*']
10
+ names.map! do |filename|
11
+ filename.match(/^[^\/]+\/(.+)/)[1]
12
+ end
13
+ names.map! do |link|
14
+ "<p><a href='#{link}'>#{link}</a></p>"
15
+ end
16
+ names.join
17
+ end
18
+ get '/:name' do
19
+ files = Dir[File.join('lapses', params[:name], '*')]
20
+ files.map! do |filename|
21
+ filename.match(/^[^\/]+\/(.+)/)[1]
22
+ end
23
+ html = <<-HTML
24
+ <html>
25
+ <head>
26
+ <style>
27
+ body {
28
+ display: table;
29
+ width: 100%;
30
+ height: 100%;
31
+ }
32
+ #wrapper {
33
+ display: table-cell;
34
+ vertical-align: middle;
35
+ max-width: 100%;
36
+ max-height: 100%;
37
+ text-align: center;
38
+ }
39
+ </style>
40
+ <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
41
+ <script>
42
+ var imgs = [];
43
+ var urls = [];
44
+ function preloadImages(urls)
45
+ {
46
+ for(i in urls) {
47
+ var img = new Image();
48
+ img.src=urls[i];
49
+ imgs.push(img);
50
+ }
51
+ }
52
+ urls = <%= files.to_json %>;
53
+ preloadImages(urls);
54
+ function setImage(num) {
55
+ document.getElementById('image').src = urls[num];
56
+ }
57
+
58
+ $(function () {
59
+ $('body').mousemove(function (e) {
60
+ var pagewidth = $(window).width();
61
+ var mousex = event.pageX;
62
+ var num = Math.floor((mousex / pagewidth) * urls.length);
63
+ setImage(num);
64
+ });
65
+ });
66
+ </script>
67
+ </head>
68
+ <body>
69
+ <div id="wrapper">
70
+ <img id="image">
71
+ </div>
72
+ </body>
73
+ </html>
74
+ HTML
75
+
76
+ erb html, locals: {files: files}
77
+ end
78
+ end
79
+ end
data/lib/pagelapse.rb ADDED
@@ -0,0 +1,22 @@
1
+ require "pagelapse/version"
2
+ require "pagelapse/recorder"
3
+ require "pagelapse/screenshot"
4
+ require "pagelapse/parser"
5
+ require "pagelapse/viewer"
6
+
7
+ module Pagelapse
8
+
9
+ def self.cli(args)
10
+ case args[0]
11
+ when nil, 'start'
12
+ begin
13
+ Pagelapse::Parser.new "./Lapsefile"
14
+ rescue Interrupt
15
+ end
16
+ when 'view', 'viewer', 'server'
17
+ Pagelapse::Viewer.run!
18
+ else
19
+ puts "Unknown action #{args[0]}"
20
+ end
21
+ end
22
+ end
data/pagelapse.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pagelapse/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pagelapse"
8
+ spec.version = Pagelapse::VERSION
9
+ spec.authors = ["Robert Lord"]
10
+ spec.email = ["robert@lord.io"]
11
+ spec.summary = %q{Generates time-lapses of websites, with ease.}
12
+ spec.description = %q{}
13
+ spec.homepage = "https://github.com/lord/pagelapse"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_dependency "capybara"
24
+ spec.add_dependency "poltergeist"
25
+ spec.add_dependency "sinatra"
26
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pagelapse
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Robert Lord
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: capybara
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: poltergeist
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sinatra
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: ''
84
+ email:
85
+ - robert@lord.io
86
+ executables:
87
+ - pagelapse
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - bin/pagelapse
97
+ - lib/pagelapse.rb
98
+ - lib/pagelapse/parser.rb
99
+ - lib/pagelapse/recorder.rb
100
+ - lib/pagelapse/screenshot.rb
101
+ - lib/pagelapse/version.rb
102
+ - lib/pagelapse/viewer.rb
103
+ - pagelapse.gemspec
104
+ homepage: https://github.com/lord/pagelapse
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.2.2
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: Generates time-lapses of websites, with ease.
128
+ test_files: []