letteropend 1.2.0 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a6cdb0d4f3c01c57f54e2ec50cf5e6a4db37ac1e
4
- data.tar.gz: 9ebe34eea4c67947da344db67b8dea136c3ef0e6
3
+ metadata.gz: d5e35304268f8c5572b2229b6e9f1b652fc85558
4
+ data.tar.gz: 5ca98b6f08d5095cabe6c4f13a42baabdc01d024
5
5
  SHA512:
6
- metadata.gz: ccd759632bc898725b6293eb53e3f3145e4a492d3894a8e20d8fb581e0cc6ddcc82613e065246284609a911b5752100cfdadad244ddb3001baa64efada72e8cf
7
- data.tar.gz: 896f9ba1a0f915169d1ed6d4621cad9060208296cf93375178fc9942b628b9d8b2cb3ffc0577a61ad65431eb6657e3a5e557fe43013d669cd0f7d255fb29fa59
6
+ metadata.gz: f80309d6f2665d12fa045e36fb9fb212685468d8574f45b63dd9d47d2bd8e52f602f4b3079645de13c9d53b595f29ec2f235c1eea2e24514f174a3039043f09d
7
+ data.tar.gz: b9737ce23e168e491c00d6f579939378a4b51a7debb096b7d9abd224990ecfe7653c456533e7dc02b434fcfea828db2215083c295adb3b3b685069657eb5e9e0
data/README.md CHANGED
@@ -1,12 +1,19 @@
1
1
  LetterOpend
2
2
  ===========
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/letteropend.svg)](http://badge.fury.io/rb/letteropend)
5
+ [![Dependency Status](https://gemnasium.com/JRJurman/Letteropend.svg)](https://gemnasium.com/JRJurman/Letteropend)
6
+ [![Code Climate](https://codeclimate.com/github/JRJurman/Letteropend/badges/gpa.svg)](https://codeclimate.com/github/JRJurman/Letteropend)
7
+
4
8
  Scripts and Functions that let you peek at letterboxd films.
5
9
 
6
10
  Sadly, with no API publicly available, this is a quick-hack way of exposing the films that you and your friends have seen, listed, or watchlisted on letterboxd.com
7
11
 
8
12
  This is not associated with letterboxd, nor is it guaranteed to work once an official API is released
9
13
 
14
+ Installation
15
+ ------------
16
+
10
17
  Add this line to your application's Gemfile:
11
18
 
12
19
  ```ruby
@@ -21,7 +28,8 @@ Or install it yourself as:
21
28
 
22
29
  $ gem install letteropend
23
30
 
24
- ## Contributing
31
+ Contributing
32
+ ------------
25
33
 
26
34
  1. Fork it ( https://github.com/jrjurman/letteropend/fork )
27
35
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -1,16 +1,19 @@
1
1
  require_relative "../lib/letteropend"
2
2
 
3
- callbacks = {
4
- :new_page => lambda{ |list| puts "Getting page {#{list.pages.length}} from #{list.username}'s #{list.list}" }
5
- }
3
+ Letteropend::List.config do
4
+ on :new_page do
5
+ puts "Getting page {#{pages.length}} from #{username}'s #{list}"
6
+ end
7
+ end
8
+
6
9
  print "First username: "
7
10
  user1 = gets.chomp
8
11
 
9
12
  print "Second username: "
10
13
  user2 = gets.chomp
11
14
 
12
- user1_wl = Letteropend::List.new(user1, "watchlist", callbacks)
13
- user2_wl = Letteropend::List.new(user2, "watchlist", callbacks)
15
+ user1_wl = Letteropend::List.new(user1, "watchlist")
16
+ user2_wl = Letteropend::List.new(user2, "watchlist")
14
17
 
15
18
  user2_wl.films.delete_if { |film| !user1_wl.films.include? film }
16
19
  user2_wl.films.each do |film|
@@ -19,13 +19,24 @@ def pulled_film(film)
19
19
  end
20
20
  end
21
21
 
22
- callbacks = {
23
- :new_page => lambda{ |l| puts "pulling data from {#{l.pages.last}}" },
24
- :pulling_film => lambda{ |f| puts "pulling data from {#{f.url}}" },
25
- :pulled_film => lambda{ |f| Object.send(:pulled_film, f) }
26
- }
22
+ Letteropend::Film.config do
23
+ on :model_updating do
24
+ puts "pulling data from {#{url}}"
25
+ end
26
+ on :model_updated do
27
+ Object.send(:pulled_film, self)
28
+ end
29
+ end
27
30
 
28
- l = Letteropend::List.new(un, ul, callbacks)
29
- total = l.get_total_time
31
+ l = Letteropend::List.new(un, ul) do
32
+ on :new_page do
33
+ puts "pulling data from {#{pages.last}}"
34
+ end
35
+ end
36
+
37
+ total = 0
38
+ l.films.each do |film|
39
+ total += film.runtime
40
+ end
30
41
 
31
42
  puts "Total Runtime: #{total} minutes"
@@ -0,0 +1,13 @@
1
+ require_relative "../lib/letteropend"
2
+
3
+ puts "Looking at films directed by Alfred Hitchcock"
4
+
5
+ username = "director"
6
+ list = "alfred-hitchcock"
7
+ l = Letteropend::List.new(username, list) do
8
+ on :new_page do
9
+ puts "pulling data from " + pages.last
10
+ end
11
+ end
12
+
13
+ puts "There are #{l.films.length} number of films on #{username} #{list}'s list"
@@ -1,14 +1,46 @@
1
1
  require_relative "../lib/letteropend"
2
2
 
3
- title = "Chopping Mall"
4
- url = "/film/chopping-mall/"
5
- f = Letteropend::Film.new(title, url)
3
+ Letteropend::Film.config do
4
+ on :model_updated do
5
+ puts "Model was updated"
6
+ end
7
+ end
6
8
 
7
- runtime = f.runtime
8
- puts "#{title}'s runtime is: #{runtime} minutes"
9
+ url = "chopping-mall"
10
+ a = Letteropend::Film.new url do
11
+ on :model_updating do
12
+ puts "Runtime: #{runtime}"
13
+ end
14
+ end
9
15
 
10
- tagline = f.tagline
11
- puts "#{title}'s tagline is: #{tagline}"
16
+ url = "ghostbusters"
17
+ b = Letteropend::Film.new url, title: "The Real Ghostbusters", runtime: 107 do
18
+ on :model_updating do
19
+ puts "Runtime: #{runtime}"
20
+ end
21
+ end
12
22
 
13
- overview = f.overview
14
- puts "#{title}'s overview is: #{overview}"
23
+ url = "duck-soup-1933"
24
+ c = Letteropend::Film.new url do
25
+ on :model_updated do
26
+ puts "We have Duck Soup"
27
+ end
28
+ end
29
+
30
+ def we_got_movie_sign(movie)
31
+ puts "The title is : #{movie.title}"
32
+
33
+ runtime = movie.runtime
34
+ puts "#{movie.title}'s runtime is: #{movie.runtime} minutes"
35
+
36
+ tagline = movie.tagline
37
+ puts "#{movie.title}'s tagline is: #{movie.tagline}"
38
+
39
+ overview = movie.overview
40
+ puts "#{movie.title}'s overview is: #{movie.overview}"
41
+ puts "\n\n"
42
+ end
43
+
44
+ we_got_movie_sign(a)
45
+ we_got_movie_sign(b)
46
+ we_got_movie_sign(c)
@@ -5,10 +5,15 @@ un = gets().chomp
5
5
  print "Enter list: "
6
6
  ul = gets().chomp
7
7
 
8
- callbacks = {
9
- :new_page => lambda{ |l| puts "pulling data from " + l.pages.last},
10
- }
8
+ Letteropend::List.config do
9
+ on :new_page do
10
+ puts "Loading "+ pages.last
11
+ end
12
+ on :new_film do
13
+ puts "Got "+films.last.url
14
+ end
15
+ end
11
16
 
12
- l = Letteropend::List.new(un, ul, callbacks)
17
+ l = Letteropend::List.new(un, ul)
13
18
 
14
19
  puts "There are #{l.films.length} number of films on #{un}'s #{ul} list"
@@ -2,66 +2,139 @@ require "nokogiri"
2
2
  require "open-uri"
3
3
 
4
4
  module Letteropend
5
+ # The Film class
5
6
  class Film
6
- attr_reader :title, :url, :runtime, :tagline, :overview
7
- def initialize(title, url, callbacks={})
8
- @title = title
7
+ attr_reader :url
8
+ @@valid_attributes = [:title, :tagline, :overview, :runtime]
9
+ @@valid_events = [:model_updated, :model_updating]
10
+
11
+ # Creates a new film instance
12
+ #
13
+ # @param url - the url letterboxd assigns the film
14
+ # @param details - the attributes the user assigns the film (instead of pulling from letterboxd)
15
+ # @param events - block of user defined events
16
+ def initialize(url, *details, &events)
9
17
  @url = url
10
18
  @pulled = false
11
- @callbacks = callbacks
19
+ @pulling = false
20
+ @events = {}
21
+
22
+ # assign each detail to a method
23
+ details.each do |detail|
24
+ detail.each do |key, value|
25
+
26
+ # only assign valid attributes to a film
27
+ if @@valid_attributes.include? key
28
+ define_singleton_method(key, lambda{value})
29
+ else
30
+ puts "Error: trying to assign invalid film data | film: #{@url}, attribute: #{key}"
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+ # assign events to film object
37
+ if block_given?
38
+ instance_eval(&events)
39
+ end
12
40
  end
13
-
14
- def runtime
15
- if !@pulled
16
- pull_data
41
+
42
+ # Assign events to instance
43
+ #
44
+ # @param event - symbol of event to be triggered
45
+ # @param block - user defined function to be triggered on event
46
+ def on(event, &block)
47
+ if block_given?
48
+ if (@@valid_events.include? event)
49
+ define_singleton_method(event, block)
50
+ else
51
+ puts "Error: trying to assign invalid event | Letteropend::Film, event: #{event}"
52
+ end
17
53
  end
18
- @runtime
19
54
  end
20
55
 
21
- def tagline
22
- if !@pulled
23
- pull_data
56
+ # Method to declare class events
57
+ #
58
+ # @param events - block of user defined events
59
+ def self.config(&events)
60
+ if block_given?
61
+ class_eval(&events)
24
62
  end
25
- @tagline
26
63
  end
27
-
28
- def overview
29
- if !@pulled
30
- pull_data
64
+
65
+ # Assign events to class
66
+ #
67
+ # @param event - symbol of event to be triggered
68
+ # @param block - user defined function to be triggered on event
69
+ def self.on(event, &block)
70
+ if block_given?
71
+ if (@@valid_events.include? event)
72
+ define_method(event, block)
73
+ else
74
+ puts "Error: trying to assign invalid class event | Letteropend::Film, event: #{event}"
75
+ end
31
76
  end
32
- @overview
33
77
  end
34
78
 
79
+ # Goes to Letterboxd and pulls html page with nokogiri
35
80
  def pull_data
36
- if @callbacks[:pulling_film]
37
- @callbacks[:pulling_film].call(self)
38
- end
39
-
81
+ @pulling = true
82
+
83
+ model_updating
84
+
40
85
  # pull the page from the url
41
- page = Nokogiri::HTML(open("http://www.letterboxd.com#{@url}"))
42
- @pulled = true
86
+ page = Nokogiri::HTML(open("http://www.letterboxd.com/film/#{@url}/"))
43
87
 
88
+ # get the title for the film
89
+ title = page.css("h1.film-title").text
90
+ define_singleton_method(:title, lambda{title})
91
+
44
92
  # get the runtime for the film
45
93
  runtime_cap = page.css(".text-link").text.match(/(\d+) mins/)
46
94
  if runtime_cap
47
- @runtime = runtime_cap.captures[0].to_i
95
+ runtime = runtime_cap.captures[0].to_i
48
96
  else
49
- @runtime = 0
97
+ runtime = 0
50
98
  end
99
+ define_singleton_method(:runtime, lambda{runtime})
51
100
 
52
101
  # get the tagline for the film
53
- @tagline = page.css(".tagline").text
102
+ tagline = page.css(".tagline").text
103
+ define_singleton_method(:tagline, lambda{tagline})
54
104
 
55
105
  # get the overview for the film
56
- @overview = page.css("div.truncate").text.strip
106
+ overview = page.css("div.truncate").text.strip
107
+ define_singleton_method(:overview, lambda{overview})
57
108
 
58
- if @callbacks[:pulled_film]
59
- @callbacks[:pulled_film].call(self)
60
- end
109
+ @pulled = true
110
+ @pulling = false
111
+
112
+ model_updated
61
113
  end
62
114
 
115
+ # Equivalence operator
63
116
  def ==(film)
64
- @title == film.title and @url == film.url
117
+ @url == film.url
118
+ end
119
+
120
+ # Method Missing implementation
121
+ #
122
+ # @param sym - method trying to be called
123
+ # @param args - arguments passed into the method call
124
+ def method_missing(sym, *args)
125
+ if (@@valid_attributes.include? sym)
126
+ if !@pulled and !@pulling
127
+ pull_data
128
+ self.send(sym)
129
+ elsif !@pulled and @pulling
130
+ puts "Error: trying to get film data prematurely | film: #{@url}, method: #{sym}"
131
+ end
132
+ elsif (@@valid_events.include? sym)
133
+ # no method was defined for this event
134
+ else
135
+ super
136
+ end
65
137
  end
138
+
66
139
  end
67
140
  end
@@ -3,30 +3,41 @@ require 'open-uri'
3
3
  require_relative './film'
4
4
 
5
5
  module Letteropend
6
+ # The List class
6
7
  class List
7
8
  attr_reader :username, :list, :films, :pages
9
+ @@valid_events = [:new_page, :new_film]
8
10
 
9
- def initialize(username, list="films", callbacks={})
11
+ # Created a new list instance
12
+ #
13
+ # @param username - the username for the list
14
+ # @param list - name of list, defaults to "films" (watched movies)
15
+ # @param events - block of user defined events
16
+ def initialize(username, list="films", &events)
10
17
  @username = username
11
18
  @list = list
12
19
 
13
20
  @films = []
14
21
  @pages = ["/#{username}/#{list}/page/1/"]
22
+
23
+ # assign events to list object
24
+ if block_given?
25
+ instance_eval(&events)
26
+ end
27
+
15
28
  begin
16
29
  # get page using Nokogiri
17
- if callbacks[:new_page]
18
- callbacks[:new_page].call(self)
19
- end
30
+ new_page
31
+
20
32
  page = Nokogiri::HTML(open("http://www.letterboxd.com#{@pages.last}"))
21
33
 
22
34
  # append visible films to @films
23
35
  page.css(".poster").each do |film|
24
36
  title = film.css(".frame-title").text
25
- url = film.css("a")[0].attr("href")
26
- @films.push( Film.new(title, url, callbacks) )
27
- if callbacks[:new_film]
28
- callbacks[:new_film].call(self)
29
- end
37
+ url_full = film.css("a")[0].attr("href")
38
+ url = /\/film\/(\S+)\//.match(url_full).captures[0]
39
+ @films.push( Film.new(url, title: title) )
40
+ new_film
30
41
  end
31
42
 
32
43
  # see if there is a next page
@@ -36,13 +47,50 @@ module Letteropend
36
47
  end
37
48
  end while ( next_page )
38
49
  end
39
-
40
- def get_total_time
41
- total_runtime = 0
42
- @films.each do |film|
43
- total_runtime += film.runtime
50
+
51
+ # Assign events to instance
52
+ #
53
+ # @param event - symbol of event to be triggered
54
+ # @param block - user defined function to be triggered on event
55
+ def on(event, &block)
56
+ if block_given?
57
+ if (@@valid_events.include? event)
58
+ define_singleton_method(event, block)
59
+ else
60
+ puts "Error: trying to assign invalid event | Letteropend::List, event: #{event}"
61
+ end
62
+ end
63
+ end
64
+
65
+ # Method to declare class events
66
+ #
67
+ # @param events - block of user defined events
68
+ def self.config(&events)
69
+ if block_given?
70
+ class_eval(&events)
71
+ end
72
+ end
73
+
74
+ # Assign events to class
75
+ #
76
+ # @param event - symbol of event to be triggered
77
+ # @param block - user defined function to be triggered on event
78
+ def self.on(event, &block)
79
+ if block_given?
80
+ if (@@valid_events.include? event)
81
+ define_method(event, block)
82
+ else
83
+ puts "Error: trying to assign invalid class event | Letteropend::List, event: #{event}"
84
+ end
85
+ end
86
+ end
87
+
88
+ def method_missing(sym, *args)
89
+ if (@@valid_events.include? sym)
90
+ # no method was defined for this event
91
+ else
92
+ super
44
93
  end
45
- return total_runtime
46
94
  end
47
95
 
48
96
  end
@@ -1,3 +1,3 @@
1
1
  module Letteropend
2
- VERSION = "1.2.0"
2
+ VERSION = "2.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: letteropend
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Jurman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-13 00:00:00.000000000 Z
11
+ date: 2014-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -66,6 +66,7 @@ files:
66
66
  - Rakefile
67
67
  - examples/compareWatchlist.rb
68
68
  - examples/getAllTime.rb
69
+ - examples/getDirectedFilms.rb
69
70
  - examples/getFilmDetails.rb
70
71
  - examples/getNumberOfFilms.rb
71
72
  - letteropend.gemspec