lib/ezmlm/list.rb
changeset 12 3cc813140c80
parent 5 804e1c2b9a40
child 13 a03c08c289e9
equal deleted inserted replaced
11:7fc2d1713795 12:3cc813140c80
     1 #!/usr/bin/ruby
     1 #!/usr/bin/ruby
     2 #
     2 # vim: set nosta noet ts=4 sw=4:
     3 # A Ruby interface to a single Ezmlm-idx mailing list directory
     3 #
       
     4 # A Ruby interface to a single Ezmlm-idx mailing list directory.
     4 #
     5 #
     5 # == Version
     6 # == Version
     6 #
     7 #
     7 #  $Id$
     8 #  $Id$
     8 #
     9 #
     9 # == Authors
       
    10 #
       
    11 # * Michael Granger <mgranger@laika.com>
       
    12 # * Jeremiah Jordan <jjordan@laika.com>
       
    13 #
       
    14 # :include: LICENSE
       
    15 # 
       
    16 #---
    10 #---
    17 #
       
    18 # Please see the file LICENSE in the base directory for licensing details.
       
    19 #
       
    20 
    11 
    21 require 'pathname'
    12 require 'pathname'
    22 require 'ezmlm'
    13 require 'ezmlm'
    23 require 'tmail'
    14 require 'mail'
    24 
    15 
    25 
    16 
    26 ### A Ruby interface to an ezmlm-idx mailing list directory
    17 ### A Ruby interface to an ezmlm-idx mailing list directory
       
    18 ###
    27 class Ezmlm::List
    19 class Ezmlm::List
    28 	
    20 
    29 	### Create a new Ezmlm::List object for the specified +listdir+, which should be
    21 	### Create a new Ezmlm::List object for the specified +listdir+, which should be
    30 	### an ezmlm-idx mailing list directory.
    22 	### an ezmlm-idx mailing list directory.
       
    23 	###
    31 	def initialize( listdir )
    24 	def initialize( listdir )
    32 		listdir = Pathname.new( listdir ) if !listdir.is_a?( Pathname )
    25 		listdir = Pathname.new( listdir ) unless listdir.is_a?( Pathname )
    33 		@listdir = listdir
    26 		@listdir = listdir
    34 
       
    35 		# Cached lookups
       
    36 		@config = nil
       
    37 	end
    27 	end
    38 
    28 
    39 
    29 
    40 	######
    30 	######
    41 	public
    31 	public
    47 
    37 
    48 	### Return the configured name of the list (without the host)
    38 	### Return the configured name of the list (without the host)
    49 	def name
    39 	def name
    50 		return self.config[ 'L' ]
    40 		return self.config[ 'L' ]
    51 	end
    41 	end
    52 	
    42 
    53 
    43 
    54 	### Return the configured host of the list
    44 	### Return the configured host of the list
    55 	def host
    45 	def host
    56 		return self.config[ 'H' ]
    46 		return self.config[ 'H' ]
    57 	end
    47 	end
    58 	
    48 
    59 
    49 
    60 	### Return the configured address of the list (in list@host form)
    50 	### Return the configured address of the list (in list@host form)
    61 	def address
    51 	def address
    62 		return "%s@%s" % [ self.name, self.host ]
    52 		return "%s@%s" % [ self.name, self.host ]
    63 	end
    53 	end
    64 	alias_method :fullname, :address
    54 	alias_method :fullname, :address
    65 	
    55 
    66 
    56 
    67 	### Return the number of messages in the list archive
    57 	### Return the number of messages in the list archive
    68 	def message_count
    58 	def message_count
    69 		numfile = self.listdir + 'num'
    59 		numfile = self.listdir + 'num'
    70 		return 0 unless numfile.exist?
    60 		return 0 unless numfile.exist?
    89 	### Return the list config as a Hash
    79 	### Return the list config as a Hash
    90 	def config
    80 	def config
    91 		unless @config
    81 		unless @config
    92 			configfile = self.listdir + 'config'
    82 			configfile = self.listdir + 'config'
    93 			raise "List config file %p does not exist" % [ configfile ] unless configfile.exist?
    83 			raise "List config file %p does not exist" % [ configfile ] unless configfile.exist?
    94 			
    84 
    95 			@config = configfile.read.scan( /^(\S):([^\n]*)$/m ).inject({}) do |h,pair|
    85 			@config = configfile.read.scan( /^(\S):([^\n]*)$/m ).inject({}) do |h,pair|
    96 				key,val = *pair
    86 				key,val = *pair
    97 				h[key] = val
    87 				h[key] = val
    98 				h
    88 				h
    99 			end
    89 			end
   100 		end
    90 		end
   101 		
    91 
   102 		return @config
    92 		return @config
   103 	end
    93 	end
   104 	
    94 
   105 
    95 
   106 	### Return the email address of the list's owner.
    96 	### Return the email address of the list's owner.
   107 	def owner
    97 	def owner
   108 		self.config['5']
    98 		self.config['5']
   109 	end
    99 	end
   110 	
   100 
   111 
   101 
   112 	### Fetch an Array of the email addresses for all of the list's subscribers.
   102 	### Fetch an Array of the email addresses for all of the list's subscribers.
   113 	def subscribers
   103 	def subscribers
   114 		subscribers_dir = self.listdir + 'subscribers'
   104 		subscribers_dir = self.listdir + 'subscribers'
   115 		return self.read_subscriber_dir( subscribers_dir )
   105 		return self.read_subscriber_dir( subscribers_dir )
   130 
   120 
   131 	### Returns an Array of email addresses of people responsible for moderating subscription
   121 	### Returns an Array of email addresses of people responsible for moderating subscription
   132 	### of a closed list.
   122 	### of a closed list.
   133 	def subscription_moderators
   123 	def subscription_moderators
   134 		return [] unless self.closed?
   124 		return [] unless self.closed?
   135 		
   125 
   136 		modsubfile = self.listdir + 'modsub'
   126 		modsubfile = self.listdir + 'modsub'
   137 		remotefile = self.listdir + 'remote'
   127 		remotefile = self.listdir + 'remote'
   138 		
   128 
   139 		subdir = nil
   129 		subdir = nil
   140 		if modsubfile.exist? && modsubfile.read(1) == '/'
   130 		if modsubfile.exist? && modsubfile.read(1) == '/'
   141 			subdir = Pathname.new( modsubfile.read.chomp )
   131 			subdir = Pathname.new( modsubfile.read.chomp )
   142 		elsif remotefile.exist? && remotefile.read(1) == '/'
   132 		elsif remotefile.exist? && remotefile.read(1) == '/'
   143 			subdir = Pathname.new( remotefile.read.chomp )
   133 			subdir = Pathname.new( remotefile.read.chomp )
   144 		else
   134 		else
   145 			subdir = self.listdir + 'mod/subscribers'
   135 			subdir = self.listdir + 'mod/subscribers'
   146 		end
   136 		end
   147 		
   137 
   148 		return self.read_subscriber_dir( subdir )
   138 		return self.read_subscriber_dir( subdir )
   149 	end
   139 	end
   150 	
   140 
   151 	
   141 
   152 	### Returns an Array of email addresses of people responsible for moderating posts
   142 	### Returns an Array of email addresses of people responsible for moderating posts
   153 	### sent to the list.
   143 	### sent to the list.
   154 	def message_moderators
   144 	def message_moderators
   155 		return [] unless self.moderated?
   145 		return [] unless self.moderated?
   156 		
   146 
   157 		modpostfile = self.listdir + 'modpost'
   147 		modpostfile = self.listdir + 'modpost'
   158 		subdir = nil
   148 		subdir = nil
   159 		
   149 
   160 		if modpostfile.exist? && modpostfile.read(1) == '/'
   150 		if modpostfile.exist? && modpostfile.read(1) == '/'
   161 			subdir = Pathname.new( modpostfile.read.chomp )
   151 			subdir = Pathname.new( modpostfile.read.chomp )
   162 		else
   152 		else
   163 			subdir = self.listdir + 'mod/subscribers'
   153 			subdir = self.listdir + 'mod/subscribers'
   164 		end
   154 		end
   165 		
   155 
   166 		return self.read_subscriber_dir( subdir )
   156 		return self.read_subscriber_dir( subdir )
   167 	end
   157 	end
   168 	
   158 
   169 	
   159 
   170 	### Return a TMail::Mail object loaded from the last post to the list. Returns
   160 	### Return a TMail::Mail object loaded from the last post to the list. Returns
   171 	### +nil+ if there are no archived posts.
   161 	### +nil+ if there are no archived posts.
   172 	def last_post
   162 	def last_post
   173 		archivedir = self.listdir + 'archive'
   163 		archivedir = self.listdir + 'archive'
   174 		return nil unless archivedir.exist?
   164 		return nil unless archivedir.exist?
   187 		raise RuntimeError, "unexpectedly empty archive directory '%s'" % [ last_archdir ] \
   177 		raise RuntimeError, "unexpectedly empty archive directory '%s'" % [ last_archdir ] \
   188 			unless last_post_path
   178 			unless last_post_path
   189 
   179 
   190 		last_post = TMail::Mail.load( last_post_path.to_s )
   180 		last_post = TMail::Mail.load( last_post_path.to_s )
   191 	end
   181 	end
   192 	
   182 
   193 	
   183 
   194 
   184 
   195 	#########
   185 	#########
   196 	protected
   186 	protected
   197 	#########
   187 	#########
   198 
   188 
   199 	### Read the hashed subscriber email addresses from the specified +directory+ and return them in 
   189 	### Read the hashed subscriber email addresses from the specified +directory+ and return them in
   200 	### an Array.
   190 	### an Array.
   201 	def read_subscriber_dir( directory )
   191 	def read_subscriber_dir( directory )
   202 		rval = []
   192 		rval = []
   203 		Pathname.glob( directory + '*' ) do |hashfile|
   193 		Pathname.glob( directory + '*' ) do |hashfile|
   204 			rval.push( hashfile.read.scan(/T([^\0]+)\0/) )
   194 			rval.push( hashfile.read.scan(/T([^\0]+)\0/) )
   205 		end
   195 		end
   206 		
   196 
   207 		return rval.flatten
   197 		return rval.flatten
   208 	end
   198 	end
   209 	
   199 
   210 	
   200 end # class Ezmlm::List
   211 end
   201 
   212 
       
   213 # vim: set nosta noet ts=4 sw=4: