Class: Dropcaster::Channel
- Inherits:
-
Object
- Object
- Dropcaster::Channel
- Includes:
- Logging, ERB::Util
- Defined in:
- lib/dropcaster/channel.rb
Overview
Represents a podcast feed in the RSS 2.0 format
Constant Summary collapse
- STORAGE_UNITS =
%w[Byte KB MB GB TB].freeze
- MAX_KEYWORD_COUNT =
12
Instance Attribute Summary
Attributes included from Logging
Instance Method Summary collapse
-
#humanize_size(number) ⇒ Object
Fixed version of gist.github.com/260184.
- #humanize_time(secs) ⇒ Object
-
#initialize(sources, attributes) ⇒ Channel
constructor
Instantiate a new Channel object.
-
#items ⇒ Object
Returns all items (episodes) of this channel, ordered by newest-first.
-
#method_missing(meth, *args) ⇒ Object
Delegate all unknown methods to @attributes.
-
#respond_to_missing?(meth) ⇒ Boolean
rubocop:enable Style/MethodMissing.
-
#to_rss ⇒ Object
Returns this channel as an RSS representation.
Constructor Details
#initialize(sources, attributes) ⇒ Channel
Instantiate a new Channel object. sources
must be present and can be a String or Array of Strings, pointing to a one or more directories or MP3 files.
attributes
is a hash with all attributes for the channel. The following attributes are mandatory when a new channel is created:
-
:title
- Title (name) of the podcast -
:url
- URL to the podcast -
:description
- Short description of the podcast (a few words)
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/dropcaster/channel.rb', line 28 def initialize(sources, attributes) # Assert mandatory attributes %i[title url description].each { |attr| raise MissingAttributeError.new(attr) if attributes[attr].blank? } @attributes = attributes @attributes[:explicit] = yes_no_or_input(attributes[:explicit]) @source_files = [] # if (sources.respond_to?(:each)) # array if sources.is_a? Array sources.each do |src| add_files(src) end else # single file or directory add_files(sources) end # If not absolute, prepend the image URL with the channel's base to make an absolute URL unless @attributes[:image_url].blank? || @attributes[:image_url] =~ /^https?:/ logger.info("Channel image URL '#{@attributes[:image_url]}' is relative, so we prepend it with the channel URL '#{@attributes[:url]}'") @attributes[:image_url] = (URI.parse(@attributes[:url]) + @attributes[:image_url]).to_s end # If enclosures_url is not given, take the channel URL as a base. if @attributes[:enclosures_url].blank? logger.info("No enclosure URL given, using the channel's enclosure URL") @attributes[:enclosures_url] = @attributes[:url] end # Warn if keyword count is larger than recommended assert_keyword_count(@attributes[:keywords]) channel_template = @attributes[:channel_template] || File.join(File.dirname(__FILE__), '..', '..', 'templates', 'channel.rss.erb') begin @erb_template = ERB.new(IO.read(channel_template)) rescue Errno::ENOENT => e raise TemplateNotFoundError.new(e.) end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args) ⇒ Object
Delegate all unknown methods to @attributes
rubocop:disable Style/MethodMissing
146 147 148 149 150 151 152 153 |
# File 'lib/dropcaster/channel.rb', line 146 def method_missing(meth, *args) m = meth.id2name if m =~ /=$/ @attributes[m.chop.to_sym] = (args.length < 2 ? args[0] : args) else @attributes[m.to_sym] end end |
Instance Method Details
#humanize_size(number) ⇒ Object
Fixed version of gist.github.com/260184
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/dropcaster/channel.rb', line 125 def humanize_size(number) return nil if number.nil? if number.to_i < 1024 unit = number > 1 ? 'Bytes' : 'Byte' else max_exp = STORAGE_UNITS.size - 1 number = Float(number) exponent = (Math.log(number) / Math.log(1024)).to_i # Convert to base 1024 exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit number /= 1024**exponent unit = STORAGE_UNITS[exponent] end '%n %u'.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit) end |
#humanize_time(secs) ⇒ Object
115 116 117 118 119 120 121 122 |
# File 'lib/dropcaster/channel.rb', line 115 def humanize_time(secs) [[60, :s], [60, :m], [24, :h], [1000, :d]].map { |count, name| if secs.positive? secs, n = secs.divmod(count) "#{n.to_i}#{name}" end }.compact.reverse.join(' ') end |
#items ⇒ Object
Returns all items (episodes) of this channel, ordered by newest-first.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/dropcaster/channel.rb', line 84 def items all_items = [] @source_files.each { |src| item = Item.new(src) logger.debug("Adding new item from file #{src}") # set author and image_url from channel if empty if item.tag.artist.blank? logger.info("#{src} has no artist, using the channel's author") item.tag.artist = @attributes[:author] end if item.image_url.blank? logger.info("#{src} has no image URL set, using the channel's image URL") item.image_url = @attributes[:image_url] end # construct absolute URL, based on the channel's enclosures_url attribute item.url = URI.parse(enclosures_url) + item.file_path.each_filename.map { |p| url_encode(p) }.join('/') # Warn if keyword count is larger than recommended assert_keyword_count(item.keywords) all_items << item } all_items.sort { |x, y| y.pub_date <=> x.pub_date } end |
#respond_to_missing?(meth) ⇒ Boolean
rubocop:enable Style/MethodMissing
156 157 158 |
# File 'lib/dropcaster/channel.rb', line 156 def respond_to_missing?(meth, *) (meth.id2name =~ /=$/) || super end |
#to_rss ⇒ Object
Returns this channel as an RSS representation. The actual rendering is done with the help of an ERB template. By default, it is expected as ../../templates/channel.rss.erb (relative) to channel.rb.
77 78 79 |
# File 'lib/dropcaster/channel.rb', line 77 def to_rss @erb_template.result(binding) end |