Forked from anonymous/nzbmatrix_watchlist_mail2rss.rb
Created
November 3, 2010 20:09
-
-
Save FiXato/661632 to your computer and use it in GitHub Desktop.
Simple IMAP parser script that looks for NZBMatrix Watchlist mails and converts them to an RSS feed and downloads the NZBs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Simple IMAP parser script that looks for NZBMatrix Watchlist mails and converts them to an RSS feed and downloads the NZBs. | |
# Created by request of third party. | |
# | |
# LICENSE: | |
# Copyright 2010 Filip H.F. 'FiXato' Slagter | |
# You may use this work without restrictions, as long as this notice is included. | |
# The work is provided "as is" without warranty of any kind, neither express nor implied. | |
require 'net/imap' | |
require 'rss/maker' | |
require 'fileutils' | |
require 'yaml' | |
require 'set' | |
# DEBUG = (ARGV.include?('--debug') ? true : false) | |
DEBUG = true | |
STATUS_LOCATION = File.expand_path("~/.nzbmatrix_watchlist_mail2rss_status.yaml") | |
def debug(args,&block) | |
puts(args,&block) if DEBUG | |
end | |
class Config | |
CONFIG_LOCATION = File.expand_path("~/.nzbmatrix_watchlist_mail2rss_config.yaml") | |
class << self | |
def load | |
prompt unless exists? | |
@@config = YAML.load_file(CONFIG_LOCATION) | |
end | |
def exists? | |
File.exist?(CONFIG_LOCATION) | |
end | |
def config | |
@@config | |
end | |
def defaults | |
{ | |
:imap => { | |
:server => 'imap.yourmailserver.example', | |
:user => '[email protected]', | |
:password => 'y0urp4ssw0rd!', | |
:folder => 'INBOX', | |
}, | |
:mailparser_sender => '[email protected]', | |
:nzb_watchfolder => '~/downloads/nzb', | |
:nzbmatrix_api => { | |
:username => 'yourNzbMatrixUsername', | |
:key => 'yourNzbMatrixAPIKEY', | |
}, | |
:rss => { | |
:version => '2.0', | |
:filename => '~/sites/yoursite.example/nzbwatchlist.xml', | |
:url => 'http://yoursite.example/nzbwatchlist.rss', | |
:title => 'NZBMatrix Watcher', | |
:description => 'NZBMatrix Watcher mails converted to RSS' | |
}, | |
} | |
end | |
def prompt | |
@@config = defaults | |
@@config.each_pair do |key,v| | |
puts "Configuring section #{key}" | |
if v.kind_of?(Hash) | |
v.each_pair do |subkey,subvalue| | |
print "Please supply value for #{key}->#{subkey}: (default: #{subvalue})" | |
new_value = gets | |
v[subkey] = (new_value.strip == '' ? subvalue : new_value.strip) | |
puts | |
end | |
else | |
print "Please supply value for #{key}: (default: #{v})" | |
new_value = gets | |
@@config[key] = (new_value.strip == '' ? v : new_value.strip) | |
puts | |
end | |
end | |
File.open(CONFIG_LOCATION, "w"){|f| f.write(@@config.to_yaml)} | |
end | |
end | |
end | |
class Parser | |
attr_reader :config, :nzb_items, :status | |
def initialize | |
@config = Config.load | |
@nzb_items = [] | |
@status = {} | |
@status = YAML.load_file(STATUS_LOCATION) if File.exist?(STATUS_LOCATION) | |
end | |
def retrieve_and_parse_mails | |
imap = Net::IMAP.new(config[:imap][:server]) | |
imap.login(config[:imap][:user], config[:imap][:password]) | |
imap.select(config[:imap][:folder]) | |
imap.search(["FROM", config[:mailparser_sender], "BODY", "Download Link:"]).each do |msg_id| | |
status[:parsed_message_ids] = Set.new unless status.has_key?(:parsed_message_ids) | |
next if status[:parsed_message_ids].include?(msg_id) | |
msg = imap.fetch(msg_id, "(UID RFC822.SIZE ENVELOPE BODY[TEXT])")[0] | |
env = imap.fetch(msg_id, "ENVELOPE")[0].attr["ENVELOPE"] | |
date = imap.fetch(msg_id, "INTERNALDATE")[0].attr["INTERNALDATE"] | |
from = env.from[0].name | |
subject = env.subject | |
body = msg.attr["BODY[TEXT]"].gsub("\n"," ").gsub("\t", " ").gsub(13.chr," ").squeeze(" ") | |
#Parse format 1 | |
body =~ /Download Link: ?<a href="([^"]+)"[^>]+>(.+?)<\/a><br>/ | |
download_link = $1 | |
description = $2 | |
#Fallback to Parse format 2 | |
unless download_link && description | |
body =~ /Download Link: ?(.+?)<([^>]+?)>/ | |
download_link = $2 | |
description = $1 | |
end | |
unless download_link && description | |
puts "Could not parse this message: " | |
puts "From: #{from}" | |
puts "Subject: #{subject}" | |
puts "Body:" | |
puts '-' * 10 | |
puts body | |
puts '-' * 10 | |
puts "Description: #{description}" | |
puts "Download link: #{download_link}" | |
puts '-' * 80 | |
next | |
end | |
#Remove redirects | |
download_link.gsub!(/https?:\/\/nzbmatrix\.com\/redirect\.php\?url=/,'') | |
#Force HTTPS links | |
download_link.gsub('http://','https://') | |
debug description | |
debug download_link | |
debug '-' * 80 | |
@nzb_items << { | |
:from => from, | |
:subject => subject, | |
:description => description, | |
:download_link => download_link, | |
:date => date | |
} | |
status[:parsed_message_ids] << msg_id | |
end | |
imap.logout | |
# unless imap.disconnected? | |
# imap.disconnect | |
# end | |
end | |
def build_rss | |
content = RSS::Maker.make(config[:rss][:version]) do |m| | |
m.channel.title = config[:rss][:title] | |
m.channel.link = config[:rss][:url] | |
m.channel.description = config[:rss][:description] | |
m.items.do_sort = true # sort items by date | |
nzb_items.each do |nzb_item| | |
i = m.items.new_item | |
i.title = nzb_item[:description] | |
i.link = nzb_item[:download_link] | |
i.date = Time.parse(nzb_item[:date]) | |
end | |
end | |
File.open(File.expand_path(config[:rss][:filename]),"w") do |f| | |
f.write(content) | |
end | |
end | |
def download_new_nzbs | |
nzb_watchfolder = File.expand_path(config[:nzb_watchfolder]) | |
FileUtils.mkdir_p(nzb_watchfolder) unless File.exist?(nzb_watchfolder) | |
status[:downloaded_nzb_ids] = Set.new unless status.has_key?(:downloaded_nzb_ids) | |
nzb_items.each do |nzb_item| | |
nzb_id = '' | |
if nzb_item[:download_link] =~ /id=(\d+)/ | |
nzb_id = $1 | |
end | |
download_link = "https://api.nzbmatrix.com/v1.1/download.php?id=#{nzb_id}&username=#{config[:nzbmatrix_api][:username]}&apikey=#{config[:nzbmatrix_api][:key]}" | |
filename = nzb_item[:description].gsub(/[^a-zA-Z0-9_-]/,'_') + '-' + nzb_id + '.nzb' | |
filepath = File.expand_path(File.join(nzb_watchfolder,filename)) | |
unless File.exist?(filepath) | |
status[:downloaded_nzb_ids] << nzb_id if `wget -q --no-check-certificate "#{download_link}" -O #{filepath}` | |
end | |
end | |
end | |
def store_status | |
File.open(STATUS_LOCATION,"w") {|f| f.write(status.to_yaml)} | |
end | |
end | |
parser = Parser.new | |
parser.retrieve_and_parse_mails | |
# parser.build_rss | |
parser.download_new_nzbs | |
parser.store_status |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment