Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 131 lines (109 sloc) 3.628 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 71 72 73 74 75 76 77 78 79 80 81 82 83 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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
#! /usr/bin/ruby
#
# reader2maildir.rb --- synchronize Google reader with a maildir
#
# version 0.3
#
# Copyright (C) 2011 Jim Fowler
#
# This file is part of reader2maildir.
#
# reader2maildir is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# reader2maildir is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with reader2maildir. If not, see <http://www.gnu.org/licenses/>.

require 'rubygems'
require 'reader'
require 'mail'
require 'fileutils'
require 'message-ids'
require 'uri'

# String encoding is broken in ruby 1.8
class String
  def encode!(string)
    self
  end
end

# Load configuration file from home directory
configuration_filename = "#{ENV['HOME']}/.reader2maildir"
configuration = YAML::load( File.open( configuration_filename ).read )
user = configuration['username']
pass = configuration['password']
root = configuration['maildir']

if user.nil?
  puts "Missing username in #{configuration_filename}"
  exit
end

if pass.nil?
  puts "Missing password in #{configuration_filename}"
  exit
end

if root.nil?
  puts "Missing maildir in #{configuration_filename}"
  exit
end

# Create maildir root
Dir.mkdir( "#{root}" ) unless File.exist?( "#{root}" )

# Download subscriptions from Google reader
reader = GoogleReader::GoogleReader.new
reader.login( user, pass )
subscriptions = reader.subscriptions
maildirs = Hash.new

for subscription in subscriptions
  subdirectory = URI.escape(subscription.feedurl, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
  directory = "#{root}/#{subdirectory}"
  maildirs[subscription] = Maildir.new( directory )
end

# load the guid database
guids = Hash.new

puts "Creating guid database..."
subdirectories = Dir.new( "#{root}" ).entries.select{ |x| File.stat("#{root}/#{x}").directory? }
  
for subdirectory in subdirectories
  maildir = Maildir.new("#{root}/#{subdirectory}", false)
  guids.merge!( maildir.message_ids )
end

# Process fresh items from Google reader
puts "Downloading items from Google reader..."
items = reader.articles(false)

items.each{ |post|
  guid = post.guid.gsub( 'tag:google.com,2005:reader/item/', '' ) + "@reader.google.com"
  message = guids[guid]

  if message.nil?
    puts "Downloading #{post}..."
    mail = Mail.new do
      from "#{post.author}@example.com"
      message_id "<#{guid}>"
      subject post.title.to_s
      date post.published.to_s
      content_type 'text/html; charset=UTF-8'
      body post.description.to_s
    end
    mail['X-URL'] = post.link.to_s

    maildir = maildirs[post.source]
    message = maildir.add(mail.to_s)
    message.process
    guids[guid] = message
  end

  # TODO currently seen marks are only propagated if the message is in the fresh pile... maybe that's alright?

  # Propogate seen mark from local maildir to Reader
  if message.seen?
    if post.categories.select{ |c| c.match( /\/com.google\/read$/ ) }.length == 0
      post.mark_read
      puts "marking remote #{post} as seen"
    end
  end

  # Propogate seen mark from Reader to local maildir
  if post.categories.select{ |c| c.match( /\/com.google\/read$/ ) }.length > 0 and not message.seen?
    puts "marking local #{post} as seen"
    message.process
    message.seen!
  end
}


Something went wrong with that request. Please try again.