#!/usr/bin/env ruby require 'rubygems' gem 'gmailer', '>= 0.1.7' require 'gmailer' module Net # :nodoc: module FS # :nodoc: # # = Net::FS::Gmail - store and retrieve files on Gmail # # This is a port of Perl's {Net::FS::Gmail}[http://search.cpan.org/~simonw/Net-FS-Gmail/]. # File storage should be compatible with the original Perl version. # # == License # # Net::FS::Gmail is released under the Apache License, Version 2.0 # # == Author # # Blair Christensen. # # == Copyright # # Copyright (C) 2007, Blair Christensen # class Gmail # Prepend this string to message +Subject+ to mark Net::FS::Gmail files. FILESTORE_PREFIX = 'GmailStore v' # Version of filestore. FILESTORE_VERSION = '0.1' # Append this email domain to Gmail username if not present. GMAIL_DOMAIN = '@gmail.com' # Gmail label where messages may be found. GMAIL_LABEL = 'Inbox' # Files are versioned from newest-to-oldest, starting from this number. MOST_RECENT_VERSION = 1 # Net::FS::Gmail version VERSION = '0.0.1' # # Create connection to Gmail. Returns Net::FS::Gmail object. # # Example: # require 'net/fs/gmail' # fs = Net::FS::Gmail.new('your.gmail.account', 'your password') # def initialize(user, password) @gmail = GMailer.connect(user, password) @user = user end # def initialize(user, password) # # Permanently delete +file+ from Gmail. # # If +version+ is specified only that version will be deleted. Otherwise all # versions will be deleted. # # Example: # fs.delete('example', 2) # Delete version +2+ of file +example+ # fs.delete('example') # Delete all versions of file +example+ # def delete(file, version = nil) # TODO 20070901 DRY w/ "remove()" versions = self.versions(file) raise('No versions found') if versions.size < 1 if version.nil? versions.each { |v| @gmail.delete_message(v.id) } else version = version.to_i raise('Version must be positive integer') if version < 1 v = versions[version - 1] @gmail.delete_message(v.id) end end # def delete(file, version) # # Get a list of all the file names stored on Gmail. # # Example: # fs.files().each { |name| puts name } # def files() files = [] # TODO 20070831 create patch to add rdoc to all gmailer methods i call # TODO 20070831 create otherblog posts for all gmailer methods i call # TODO 20070831 create rdoc2gwiki tranlator? # TODO 20070831 ml.each - yields Gmailer::Box objects # TODO 20070831 ml.each_msg - yields Gmailer::Message objects and debug spew @gmail.messages(:standard => GMAIL_LABEL).each do |box| next unless box.subject =~ /^#{FILESTORE_PREFIX}[\d.]+ (.+)$/ files << $1 end files.uniq # TODO 20070901 i think this deviates from the original Perl end # def files() # # Returns two element array of current quota usage. # # Elements: # * [0] Usage (MB) # * [1] Usage (Percentage) # # Example: # quota = fs.quota() # puts sprintf("%s MB (%s%%)", quota[0], quota[1]) # def quota() # TODO 20070901 why do i need to call this (or something like it) before getting a snapshot? @gmail.fetch(:contact => "freq") snap = @gmail.snap(:standard) # TODO 20070901 add support for quota size [ snap.quota_mb, snap.quota_per ] end # def quota() # # Move +file+ to Gmail trash. # # If +version+ is specified only that version will be removed. Otherwise all # versions will be trashed. # # Example: # fs.remove('example', 2) # Move version +2+ of file +example+ to trash # fs.remove('example') # Move all versions of file +example+ to trash # def remove(file, version) # TODO 20070901 DRY w/ "delete()" versions = self.versions(file) raise('No versions found') if versions.size < 1 if version.nil? versions.each { |v| @gmail.trash(v.id) } else version = version.to_i raise('Version must be positive integer') if version < 1 v = versions[version - 1] @gmail.trash(v.id) end end # def remove(file, version) # # Retrieves +file+ from Gmail and writes to the local filesystem. # # If +as+ is specified, that will be used as the name of the output file. Otherwise +file+ # will be used. If +version+ is not specified, the most recent version of +file+ # will be retrieved. # # Example: # # Retrieve most recent version of +example+ and write to file +example+ # fs.retrieve('example') # # # Retrieve most recent version of +example+ and write to file +example.txt+ # fs.retrieve('example', 'example.txt') # # # Retrieve version +2+ of +example+ and write to file +/tmp/example-v2.txt+ # fs.retrieve('example', '/tmp/example-v2.txt', 2) # def retrieve(file, as = nil, version = MOST_RECENT_VERSION) as = file if ( as.nil? || as.empty? ) v = self.versions(file)[ version.to_i - 1 ] att = v.attachment[0] # TODO 20070901 why "0.1" as the attachment id? and can i retrieve that via the api somehow? @gmail.attachment("0.1", v.id, as, false) end # def retrieve(file, as, version) # # Store +file+ on Gmail. # # If +as+ is specified it will be used as the filename instead of +file+. The name # of +file+ will be expanded to the absolute path if +as+ is not specified. # # Example: # fs.store('example') # Store local file +example+ as +example+ # fs.store('example.txt', 'example') # Store local file +example.txt+ as +example+ # def store(file, as) File.exist?(file) || raise("No such file '#{file}'") file = File.expand_path(file) # TODO 20070901 to expand or not to expand? as = file if ( as.nil? || as.empty? ) user = @user user =~ /#{GMAIL_DOMAIN}$/ || user += GMAIL_DOMAIN @gmail.send( :to => "#{@user}@gmail.com", :subject => "#{FILESTORE_PREFIX}#{FILESTORE_VERSION} #{as}", :files => [ file ] ) end # def store() # # Return array of all versions of +file+ stored on Gmail. # # Files are versioned from newest-to-oldest, beginning with +MOST_RECENT_VERSION+. # # Example: # fs.versions('example').each_with_index do |v,idx| # puts sprintf("%-3d\t%-16s\t%-7s", idx + 1, v.id, v.date) # end # def versions(file) versions = [] @gmail.messages(:standard => GMAIL_LABEL).each do |box| next unless box.subject =~ /^#{FILESTORE_PREFIX}[\d.]+ #{file}$/ versions << box end versions end # def versions(file) end # class Gmail end # module FS end # module Net