Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
#!/usr/bin/env ruby
# SweDB XMLTV Grabber for EyeTV
# by Henrik Nyh <> under the MIT License.
# Configure the list of channels below and run this script as a cron job, e.g.
# 0 */12 * * * ruby /path/to/this/script.rb
# to run it every 12 hours (suggested since cron jobs don't run if the computer is off).
# Every time it runs it will get schedules for those channels and import them into EyeTV.
# The script uses conditional GET to only update files if they've changed.
# If you're on OS X Mavericks, you probably need to run this for the script to work:
# xcode-select --install
# sudo gem install hpricot
# If you're on Lion or Mountain Lion, install Xcode and its command-line tools and then run:
# sudo gem install hpricot
# On Snow Leopard, it should just work.
# 2015-06-17 1.6: New root URL.
# 2013-10-25 1.5: Unbreak on Mavericks.
# 2012-01-14 1.4: cron example is once per 12 hours, not once a minute every 12th hour.
# 2009-05-05 1.3: MIT License.
# 2008-10-30 1.2: EyeTV no longer steals focus on import.
# 2008-09-15 1.1: Always update channel list; not just if updated on server. Don't break on 404.
# 2008-03-09 1.0: First version.
# Use ids as listed in
%w[zlib open-uri date fileutils rubygems hpricot].each {|lib| require lib }
DAYS = 15 # A value from 1 to 15. Fetches yesterday + n days.
# We need yesterday for today's early morning shows.
USER_AGENT = "SweDB XMLTV Grabber for EyeTV/1.6 <>"
DIRECTORY = "/Library/Application Support/EyeTV/XMLTV"
DB = File.join(DIRECTORY, "condget.db")
SCHEDULE_RE = /_(\d{4}-\d{2}-\d{2})\.xml$/
# Load or create DB hash mapping file paths to Conditional GET modification dates.
# Using file paths instead of URLs since this makes removing out-of-date entries easier.
$db = {|file| Marshal.load(file) } rescue"")
# This method does conditional GET based on Last-Modified/If-Modified-Since only (no etag)
# and assumes gzipped content.
# Returns local file path if new content was retrieved, false otherwise.
def condget(url)
filename = File.basename(url, ".gz")
path = path_from_url(url)
open(url, "If-Modified-Since" => $db[path], "User-Agent" => USER_AGENT) do |response|
# Store last-modified
$db[path] = response.meta["last-modified"]
# Gunzip
response_body =
rescue Zlib::GzipFile::Error
response_body =
end, 'w') {|file| file.write response_body }
rescue OpenURI::HTTPError => e
raise unless e.message =~ /^(304|404)/
def path_from_url(url)
filename = File.basename(url, ".gz")
File.join(DIRECTORY, filename)
# Remove expired schedules
glob = File.join(DIRECTORY, "*.xml")
expired_files = Dir[glob].select {|file| file =~ SCHEDULE_RE && Date.parse($1) < YESTERDAY }
expired_files.each do |file|
# Update scheduling
updates = []
# Create directory structure if it doesn't exist already
FileUtils.mkdir_p DIRECTORY
# Get and parse root file
new_root_file = condget(ROOT_URL)
doc = Hpricot(open(path_from_url(ROOT_URL)))
# Create active_channels.xml file containing only the requested channels
excluded_channels ='channel').reject {|channel| CHANNELS.include?(channel[:id]) }
active_channels_file = File.join(DIRECTORY, "active_channels.xml")
active_channels_xml = doc.to_s.gsub(/\n\s+\n/, "\n") # get rid of excess whitespace, "w") {|file| file.write active_channels_xml }
updates << active_channels_file
# Loop over channels and get schedules
channels ='channel').map {|channel| [channel[:id],'base-url').inner_text] }
channels.each do |channel|
id, base_url = channel
filename = "#{id}_#{day}.xml.gz"
url = File.join(base_url, filename)
if path = condget(url)
updates << path
# Persist the conditional GET DB hash to disk, "w") {|file| Marshal.dump($db, file) }
# Do the actual EyeTV import
command = %w[open -ga EyeTV] + updates

This comment has been minimized.

Copy link
Owner Author

@henrik henrik commented Jun 29, 2015

Någon rapporterade följande fel – kanske nån annan som har samma:

Tydligen hade någon av de senaste OSX-uppdateringarna ändrat säkerhetsinställningarna till att endast tillåta exekvering av mjukvara från ”App Store och angivna utvecklare” (Systeminställningar -> Tillåt program hämtade från -> Säkerhet och integritet). Så simpelt, men ändå så svårt att finna.

Det var troligtvis detta som förhindrade Ruby att laddas in korrekt och därmed även skriptet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment