plex-ruby
Advanced tools
+11
-1
@@ -12,3 +12,3 @@ require 'nokogiri' | ||
| # @return [String] snake case form | ||
| def self.snake_case(string) | ||
| def self.underscore(string) | ||
| string.gsub(/::/, '/'). | ||
@@ -21,2 +21,12 @@ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). | ||
| # Converts ruby style snake case names into the cammel case names that are | ||
| # used in the Plex APIs. I.E. <tt>play_media</tt> -> <tt>playMedia</tt> | ||
| def self.camelize(string, first_letter_uppercase = false) | ||
| if first_letter_uppercase | ||
| string.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } | ||
| else | ||
| string.to_s[0].chr.downcase + camelize(string, true)[1..-1] | ||
| end | ||
| end | ||
| end | ||
@@ -23,0 +33,0 @@ |
@@ -12,3 +12,3 @@ module Plex | ||
| attr_reader *ATTRIBUTES.map {|m| Plex.snake_case(m) } | ||
| attr_reader *ATTRIBUTES.map {|m| Plex.underscore(m) } | ||
| attr_reader :server | ||
@@ -22,3 +22,3 @@ | ||
| ATTRIBUTES.each { |e| | ||
| instance_variable_set("@#{Plex.snake_case(e)}", node.attr(e)) | ||
| instance_variable_set("@#{Plex.underscore(e)}", node.attr(e)) | ||
| } | ||
@@ -34,3 +34,3 @@ end | ||
| class_eval %( | ||
| def #{Plex.snake_case(nav)} | ||
| def #{Plex.underscore(nav)} | ||
| ping player_url+'/navigation/#{nav}' | ||
@@ -48,3 +48,3 @@ end | ||
| class_eval %( | ||
| def #{Plex.snake_case(playback)} | ||
| def #{Plex.underscore(playback)} | ||
| ping player_url+'/playback/#{playback}' | ||
@@ -51,0 +51,0 @@ end |
@@ -7,3 +7,2 @@ module Plex | ||
| attr_reader *ATTRIBUTES.map {|m| Plex.snake_case(m) } | ||
| attr_reader :parts | ||
@@ -14,5 +13,7 @@ | ||
| def initialize(node) | ||
| ATTRIBUTES.each { |e| | ||
| instance_variable_set("@#{Plex.snake_case(e)}", node.attr(e)) | ||
| } | ||
| node.attributes.each do |method, val| | ||
| define_singleton_method(Plex.underscore(method).to_sym) do | ||
| val.value | ||
| end | ||
| end | ||
@@ -19,0 +20,0 @@ @parts = node.search("Part").map { |m| Plex::Part.new(m) } |
@@ -6,3 +6,2 @@ module Plex | ||
| attr_reader *ATTRIBUTES.map {|m| Plex.snake_case(m) } | ||
| attr_reader :streams | ||
@@ -13,5 +12,7 @@ | ||
| def initialize(node) | ||
| ATTRIBUTES.each { |e| | ||
| instance_variable_set("@#{Plex.snake_case(e)}", node.attr(e)) | ||
| } | ||
| node.attributes.each do |method, val| | ||
| define_singleton_method(Plex.underscore(method).to_sym) do | ||
| val.value | ||
| end | ||
| end | ||
@@ -18,0 +19,0 @@ @streams = node.search('Stream').map { |m| Plex::Stream.new(m) } |
+16
-28
@@ -15,17 +15,14 @@ module Plex | ||
| @key = key | ||
| directory.attributes.each do |method, val| | ||
| define_singleton_method(Plex.underscore(method).to_sym) do | ||
| val.value | ||
| end | ||
| define_singleton_method(Plex.underscore(method+'!').to_sym) do | ||
| puts "Plex::Season##{Plex.underscore(method+'!')} IS DEPRECATED! Use Plex::Season##{Plex.underscore(method)} instead." | ||
| self.send(Plex.underscore(method)) | ||
| end | ||
| end | ||
| end | ||
| # A Season has a key, which allows us to do lazy loading. A season will | ||
| # not be fully loaded unless one of its attributes is called. Then the | ||
| # Season will load itself from its key. Once loaded it caches its self. | ||
| # For every attribute there is a cache busting version wich is just the | ||
| # name of the attribute followed by '!'. For exsample <tt>season.type</tt> | ||
| # and <tt>season.type!</tt> | ||
| ATTRIBUTES.each { |method| | ||
| class_eval %( | ||
| def #{Plex.snake_case(method)}; directory.attr('#{method}') end | ||
| def #{Plex.snake_case(method)}!; directory!.attr('#{method}') end | ||
| ) | ||
| } | ||
| # Returns the list of episodes in the library that are a part of this Season | ||
@@ -38,5 +35,8 @@ # | ||
| # Cache busting version of #episodes | ||
| def episodes! | ||
| @episodes = episodes_from_video(children!) | ||
| # Select a particular episode | ||
| # | ||
| # @param [Fixnum, String] episode index number | ||
| # @return [Episode] episode with the index of number | ||
| def episode(number) | ||
| episodes.select { |epi| epi.index.to_i == number.to_i }.first | ||
| end | ||
@@ -70,6 +70,2 @@ | ||
| def xml_doc! | ||
| @xml_doc = base_doc | ||
| end | ||
| def children | ||
@@ -79,6 +75,2 @@ @children ||= base_children_doc | ||
| def children! | ||
| @children = base_children_doc | ||
| end | ||
| def episodes_from_video(node) | ||
@@ -92,7 +84,3 @@ node.search("Video").map { |m| Plex::Episode.new(self, m.attr('key')) } | ||
| def directory! | ||
| @directory = xml_doc!.search("Directory").first | ||
| end | ||
| end | ||
| end |
@@ -10,3 +10,3 @@ module Plex | ||
| attr_reader *ATTRIBUTES.map {|m| Plex.snake_case(m) } | ||
| attr_reader *ATTRIBUTES.map {|m| Plex.underscore(m) } | ||
| attr_reader :library | ||
@@ -20,3 +20,3 @@ | ||
| ATTRIBUTES.each { |e| | ||
| instance_variable_set("@#{Plex.snake_case(e)}", node.attr(e)) | ||
| instance_variable_set("@#{Plex.underscore(e)}", node.attr(e)) | ||
| } | ||
@@ -42,3 +42,3 @@ end | ||
| class_eval %( | ||
| def #{Plex.snake_case(method)} | ||
| def #{Plex.underscore(method)} | ||
| Plex::Parser.new( self, Nokogiri::XML(open(url+key+'/#{method}')) ).parse | ||
@@ -70,9 +70,9 @@ end | ||
| class_eval %( | ||
| def #{Plex.snake_case(method)}s | ||
| @#{Plex.snake_case(method)}s ||= grab_keys('#{method}') | ||
| def #{Plex.underscore(method)}s | ||
| @#{Plex.underscore(method)}s ||= grab_keys('#{method}') | ||
| end | ||
| def #{Plex.snake_case(method)}s! | ||
| @#{Plex.snake_case(method)}s = grab_keys('#{method}') | ||
| def #{Plex.underscore(method)}s! | ||
| @#{Plex.underscore(method)}s = grab_keys('#{method}') | ||
| end | ||
| def by_#{Plex.snake_case(method)}(val) | ||
| def by_#{Plex.underscore(method)}(val) | ||
| Plex::Parser.new( self, Nokogiri::XML(open(url+key+"/#{method}/\#{val}")) ).parse | ||
@@ -79,0 +79,0 @@ end |
+24
-29
| module Plex | ||
| # Found at /library/metadata/:key | ||
| class Show | ||
| ATTRIBUTES = %w(guid studio title contentRating summary index rating year thumb | ||
| art banner theme duration originallyAvailableAt leafCount | ||
| viewedLeafCount addedAt updatedAt) | ||
| ATTRIBUTES = %w(ratingKey guid studio type title contentRating summary index | ||
| rating year thumb art leafCount viewedLeafCount addedAt | ||
| updatedAt) | ||
@@ -16,14 +15,14 @@ attr_reader :section, :key | ||
| @key = key | ||
| directory.attributes.each do |method, val| | ||
| define_singleton_method(Plex.underscore(method).to_sym) do | ||
| val.value | ||
| end | ||
| define_singleton_method(Plex.underscore(method+'!').to_sym) do | ||
| puts "Plex::Show##{Plex.underscore(method+'!')} IS DEPRECATED! Use Plex::Show##{Plex.underscore(method)} instead." | ||
| self.send(Plex.underscore(method)) | ||
| end | ||
| end | ||
| end | ||
| # A Show has a key, which allows us to do lazy loading. A Show will | ||
| # not be fully loaded unless one of its attributes is called. Then the | ||
| # Show will load itself from its key. Once loaded it caches its self. | ||
| ATTRIBUTES.each { |method| | ||
| class_eval %( | ||
| def #{Plex.snake_case(method)}; @#{method} ||= directory.attr('#{method}') end | ||
| def #{Plex.snake_case(method)}!; @#{method} = directory!.attr('#{method}') end | ||
| ) | ||
| } | ||
| # The list of seasons in the library that belong to this Show | ||
@@ -36,4 +35,8 @@ # | ||
| def seasons! | ||
| @seasons = search_children children! | ||
| # Select a particular season | ||
| # | ||
| # @param [Fixnum, String] season index number | ||
| # @return [Season] season with the index of number | ||
| def season(number) | ||
| seasons.select { |sea| sea.index.to_i == sea.to_i }.first | ||
| end | ||
@@ -67,6 +70,2 @@ | ||
| def xml_doc! | ||
| @xml_doc = base_doc | ||
| end | ||
| def children | ||
@@ -76,6 +75,2 @@ @children ||= children_base | ||
| def children! | ||
| @children = children_base | ||
| end | ||
| def directory | ||
@@ -85,14 +80,14 @@ @directory ||= xml_doc.search('Directory').first | ||
| def directory! | ||
| @directory = xml_doc!.search('Directory').first | ||
| end | ||
| def search_children(node) | ||
| node.search('Directory').map do |season| | ||
| Plex::Season.new(self, season.attr('key')[0..-10]) # Remove /children | ||
| plex_season.new(self, season.attr('key')[0..-10]) # Remove /children | ||
| end | ||
| end | ||
| def plex_season | ||
| @plex_season ||= Plex::Season | ||
| end | ||
| end | ||
| end |
@@ -6,10 +6,10 @@ module Plex | ||
| attr_reader *ATTRIBUTES.map {|m| Plex.snake_case(m) } | ||
| # @param [Nokogiri::XML::Element] nokogiri element that represents this | ||
| # Stream | ||
| def initialize(node) | ||
| ATTRIBUTES.each { |e| | ||
| instance_variable_set("@#{Plex.snake_case(e)}", node.attr(e)) | ||
| } | ||
| node.attributes.each do |method, val| | ||
| define_singleton_method(Plex.underscore(method).to_sym) do | ||
| val.value | ||
| end | ||
| end | ||
| end | ||
@@ -16,0 +16,0 @@ |
| module Plex | ||
| VERSION = "1.2.0" | ||
| VERSION = "1.3.0" | ||
| end |
@@ -8,3 +8,2 @@ module Plex | ||
| attr_reader *ATTRIBUTES.map {|m| Plex.snake_case(m) } | ||
| attr_reader :media, :genres, :writers, :directors, :roles | ||
@@ -15,5 +14,7 @@ | ||
| def initialize(node) | ||
| ATTRIBUTES.each { |e| | ||
| instance_variable_set("@#{Plex.snake_case(e)}", node.attr(e)) | ||
| } | ||
| node.attributes.each do |method, val| | ||
| define_singleton_method(Plex.underscore(method).to_sym) do | ||
| val.value | ||
| end | ||
| end | ||
@@ -20,0 +21,0 @@ @media = Plex::Media.new(node.search('Media').first) |
+1
-1
@@ -53,3 +53,3 @@ # Plex-Ruby [](https://secure.travis-ci.org/ekosz/Plex-Ruby.png) | ||
| episodes = bsg.seasons.last.episodes # Array the last seasons episodes | ||
| episode = episodes[4] # The fith episode in the season | ||
| episode = episodes[4] # The fifth episode in the season | ||
| puts "#{episode.title} - #{episode.summary}" # Looks good | ||
@@ -56,0 +56,0 @@ client.play_media(episode) # Play it! |
@@ -16,4 +16,4 @@ require 'test_helper' | ||
| Plex::Client::NAV_METHODS.each { |method| | ||
| it "should properly communicate its ##{Plex.snake_case(method)} method" do | ||
| assert @client.send(Plex.snake_case(method).to_sym) | ||
| it "should properly communicate its ##{Plex.underscore(method)} method" do | ||
| assert @client.send(Plex.underscore(method).to_sym) | ||
| FakeWeb.last_request.path.must_equal "/system/players/#{@client.name}/navigation/#{method}" | ||
@@ -24,4 +24,4 @@ end | ||
| Plex::Client::PLAYBACK_METHODS.each { |method| | ||
| it "should properly communicate its ##{Plex.snake_case(method)} method" do | ||
| assert @client.send(Plex.snake_case(method).to_sym) | ||
| it "should properly communicate its ##{Plex.underscore(method)} method" do | ||
| assert @client.send(Plex.underscore(method).to_sym) | ||
| FakeWeb.last_request.path.must_equal "/system/players/#{@client.name}/playback/#{method}" | ||
@@ -28,0 +28,0 @@ end |
@@ -16,3 +16,3 @@ require 'test_helper' | ||
| (Plex::Video::ATTRIBUTES - %w(key)).map {|m| Plex.snake_case(m) }.each { |method| | ||
| (Plex::Video::ATTRIBUTES - %w(key)).map {|m| Plex.underscore(m) }.each { |method| | ||
| @episode.send(method.to_sym).must_equal fake_video.send(method.to_sym) | ||
@@ -19,0 +19,0 @@ } |
+51
-31
| require 'plex-ruby' | ||
| require 'minitest/autorun' | ||
| class FakeAttr | ||
| def initialize(val) | ||
| @val = val | ||
| end | ||
| def value | ||
| @val | ||
| end | ||
| end | ||
| class FakeNode | ||
@@ -12,5 +24,11 @@ | ||
| def attr(value) | ||
| @hash[Plex.snake_case(value).to_sym] | ||
| @hash[Plex.underscore(value).to_sym] | ||
| end | ||
| def attributes | ||
| @hash.each_with_object({}) do |(key, val), obj| | ||
| obj[Plex.camelize(key)] = FakeAttr.new(val) | ||
| end | ||
| end | ||
| def search(value) | ||
@@ -41,20 +59,22 @@ Array( @hash[value.to_sym] ) | ||
| Directory: FakeNode.new({ | ||
| guid: 'com.plexapp.agents.thetvdb://73545/1?lang=en', | ||
| studio: 'Big Dog', | ||
| title: 'Friends', | ||
| content_rating: 'MV-14', | ||
| summary: '3 friends go on an adventure', | ||
| index: '1', | ||
| rating: '10', | ||
| year: '3033', | ||
| thumb: '/file/path.jpg', | ||
| art: '/other/file/path.png', | ||
| banner: '/yet/another/file/path.jpg2000', | ||
| theme: 'Chrismasy?', | ||
| duration: '2345234', | ||
| originally_available_at: '1323213639', | ||
| leaf_count: '1', | ||
| viewed_leaf_count: '0', | ||
| added_at: '1323213639', | ||
| updated_at: '1323220437', | ||
| rating_key: "9", | ||
| guid: "com.plexapp.agents.thetvdb://73545?lang=en", | ||
| studio: "SciFi", | ||
| type: "show", | ||
| title: "Battlestar Galactica (2003)", | ||
| content_rating: "TV-14", | ||
| summary: "In a distant part of the universe, a civilization of humans live on planets known as the Twelve Colonies. In the past, the Colonies have been at war with a cybernetic race known as the Cylons. 40 years after the first war the Cylons launch a devastating attack on the Colonies. The only military ship that survived the attack takes up the task of leading a small fugitive fleet of survivors into space in search of a fabled refuge known as Earth.", | ||
| index: "1", | ||
| rating: "9.3", | ||
| year: "2003", | ||
| thumb: "/library/metadata/9/thumb?t=1323220437", | ||
| art: "/library/metadata/9/art?t=1323220437", | ||
| banner: "/library/metadata/9/banner?t=1323220437", | ||
| theme: "/library/metadata/9/theme?t=1323220437", | ||
| duration: "3600000", | ||
| originally_available_at: "2003-12-08", | ||
| leaf_count: "13", | ||
| viewed_leaf_count: "0", | ||
| added_at: "1323213639", | ||
| updated_at: "1323220437" | ||
| }) | ||
@@ -65,14 +85,14 @@ } | ||
| Directory: FakeNode.new({ | ||
| key: '/library/metadata/10/children', | ||
| rating_key: '10', | ||
| guid: 'com.plexapp.agents.thetvdb://73545/1?lang=en', | ||
| type: 'season', | ||
| title: 'Season 1', | ||
| summary: '', | ||
| index: '1', | ||
| thumb: '/library/metadata/10/thumb?t=1323220437', | ||
| leaf_count: '13', | ||
| viewed_leaf_count: '0', | ||
| added_at: '1323213639', | ||
| updated_at: '1323220437' | ||
| rating_key: "10", | ||
| key: "/library/metadata/10/children", | ||
| guid: "com.plexapp.agents.thetvdb://73545/1?lang=en", | ||
| type: "season", | ||
| title: "Season 1", | ||
| summary: "", | ||
| index: "1", | ||
| thumb: "/library/metadata/10/thumb?t=1323220437", | ||
| leaf_count: "13", | ||
| viewed_leaf_count: "0", | ||
| added_at: "1323213639", | ||
| updated_at: "1323220437" | ||
| }) | ||
@@ -79,0 +99,0 @@ } |
@@ -8,3 +8,3 @@ require 'test_helper' | ||
| Plex::Media::ATTRIBUTES.map {|m| Plex.snake_case(m) }.each { |method| | ||
| Plex::Media::ATTRIBUTES.map {|m| Plex.underscore(m) }.each { |method| | ||
| it "should properly respond to ##{method}" do | ||
@@ -11,0 +11,0 @@ @media.send(method.to_sym).must_equal FAKE_MEDIA_NODE_HASH[method.to_sym] |
@@ -16,3 +16,3 @@ require 'test_helper' | ||
| (Plex::Video::ATTRIBUTES - %w(key)).map {|m| Plex.snake_case(m) }.each { |method| | ||
| (Plex::Video::ATTRIBUTES - %w(key)).map {|m| Plex.underscore(m) }.each { |method| | ||
| @movie.send(method.to_sym).must_equal fake_video.send(method.to_sym) | ||
@@ -19,0 +19,0 @@ } |
@@ -8,3 +8,3 @@ require 'test_helper' | ||
| Plex::Part::ATTRIBUTES.map {|m| Plex.snake_case(m) }.each { |method| | ||
| Plex::Part::ATTRIBUTES.map {|m| Plex.underscore(m) }.each { |method| | ||
| it "should properly respond to ##{method}" do | ||
@@ -11,0 +11,0 @@ @part.send(method.to_sym).must_equal FAKE_PART_NODE_HASH[method.to_sym] |
@@ -5,8 +5,8 @@ require 'test_helper' | ||
| it "converts words from camelCase to snake_case" do | ||
| Plex.snake_case("camelCase").must_equal "camel_case" | ||
| Plex.snake_case("snake_case").must_equal "snake_case" | ||
| Plex.snake_case("normal").must_equal "normal" | ||
| it "converts words from camelCase to underscore" do | ||
| Plex.underscore("camelCase").must_equal "camel_case" | ||
| Plex.underscore("snake_case").must_equal "snake_case" | ||
| Plex.underscore("normal").must_equal "normal" | ||
| end | ||
| end |
| require 'test_helper' | ||
| class TestSeason < Plex::Season | ||
| def initialize(parent, key) | ||
| @xml_doc = FakeNode.new(FAKE_SEASON_NODE_HASH) | ||
| super(parent, key) | ||
| end | ||
| end | ||
| describe Plex::Season do | ||
| before do | ||
| @show = FakeParent.new | ||
| @season = Plex::Season.new(@show, '/library/metadata/10') | ||
| @season.instance_variable_set("@xml_doc", FakeNode.new(FAKE_SEASON_NODE_HASH)) | ||
| @season = TestSeason.new(@show, '/library/metadata/10') | ||
| end | ||
| Plex::Season::ATTRIBUTES.map{|m| Plex.snake_case(m)}.each { |method| | ||
| Plex::Season::ATTRIBUTES.map{|m| Plex.underscore(m)}.each { |method| | ||
| it "should properly respond to ##{method}" do | ||
@@ -12,0 +18,0 @@ @season.send(method.to_sym).must_equal FAKE_SEASON_NODE_HASH[:Directory].attr(method) |
@@ -9,3 +9,3 @@ require 'test_helper' | ||
| (Plex::Section::ATTRIBUTES - %w(key)).map{|m| Plex.snake_case(m)}.each { |method| | ||
| (Plex::Section::ATTRIBUTES - %w(key)).map{|m| Plex.underscore(m)}.each { |method| | ||
| it "should respond to ##{method}" do | ||
@@ -12,0 +12,0 @@ @section.send(method.to_sym).must_equal FAKE_SECTION_NODE_HASH[method.to_sym] |
+13
-5
| require 'test_helper' | ||
| class TestShow < Plex::Show | ||
| def initialize(parent, key) | ||
| @xml_doc = FakeNode.new(FAKE_SHOW_NODE_HASH) | ||
| super(parent, key) | ||
| end | ||
| end | ||
| describe Plex::Show do | ||
| before do | ||
| @section = FakeParent.new | ||
| @show = Plex::Show.new(@section, '/library/metadata/10') | ||
| @show.instance_variable_set("@xml_doc", FakeNode.new(FAKE_SHOW_NODE_HASH)) | ||
| @show = TestShow.new(@section, '/library/metadata/10') | ||
| end | ||
| Plex::Show::ATTRIBUTES.map{|m| Plex.snake_case(m)}.each { |method| | ||
| Plex::Show::ATTRIBUTES.map{|m| Plex.underscore(m)}.each { |method| | ||
| it "should properly respond to ##{method}" do | ||
@@ -16,8 +23,9 @@ @show.send(method.to_sym).must_equal FAKE_SHOW_NODE_HASH[:Directory].attr(method) | ||
| it "should return a list of episodes" do | ||
| it "should return a list of seasons" do | ||
| @show.instance_variable_set( | ||
| "@children", FakeNode.new(FAKE_SEASON_NODE_HASH) | ||
| ) | ||
| @show.instance_variable_set( "@plex_season", TestSeason ) | ||
| @show.seasons.must_equal( | ||
| [ Plex::Season.new(FakeParent.new, FAKE_SEASON_NODE_HASH[:Directory].attr('key')[0..-10]) ] | ||
| [ TestSeason.new(FakeParent.new, FAKE_SEASON_NODE_HASH[:Directory].attr('key')[0..-10]) ] | ||
| ) | ||
@@ -24,0 +32,0 @@ end |
@@ -8,3 +8,3 @@ require 'test_helper' | ||
| Plex::Stream::ATTRIBUTES.map{|m| Plex.snake_case(m)}.each { |method| | ||
| Plex::Stream::ATTRIBUTES.map{|m| Plex.underscore(m)}.each { |method| | ||
| it "should properly respond to ##{method}" do | ||
@@ -11,0 +11,0 @@ @stream.send(method.to_sym).must_equal FAKE_STREAM_NODE_HASH[method.to_sym] |
@@ -9,3 +9,3 @@ require 'test_helper' | ||
| Plex::Video::ATTRIBUTES.map {|m| Plex.snake_case(m) }.each { |method| | ||
| Plex::Video::ATTRIBUTES.map {|m| Plex.underscore(m) }.each { |method| | ||
| it "should correctly respond to ##{method}" do | ||
@@ -17,3 +17,3 @@ @video.send(method.to_sym).must_equal FAKE_VIDEO_NODE_HASH[method.to_sym] | ||
| it "should correctly referance its media object" do | ||
| @video.media.must_equal Plex::Media.new(FAKE_VIDEO_NODE_HASH[:Media]) | ||
| @video.instance_variable_get("@media").must_equal Plex::Media.new(FAKE_VIDEO_NODE_HASH[:Media]) | ||
| end | ||
@@ -20,0 +20,0 @@ |