]> git.cworth.org Git - sup/blob - lib/sup/person.rb
c4f40a523e77907590d6eb1e546a37905fef6576
[sup] / lib / sup / person.rb
1 module Redwood
2
3 class Person 
4   attr_accessor :name, :email
5
6   def initialize name, email
7     raise ArgumentError, "email can't be nil" unless email
8     
9     if name
10       @name = name.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ")
11       if @name =~ /^(['"]\s*)(.*?)(\s*["'])$/
12         @name = $2
13       end
14     end
15
16     @email = email.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ").downcase
17   end
18
19   def to_s; "#@name <#@email>" end
20
21 #   def == o; o && o.email == email; end
22 #   alias :eql? :==
23 #   def hash; [name, email].hash; end
24
25   def shortname
26     case @name
27     when /\S+, (\S+)/
28       $1
29     when /(\S+) \S+/
30       $1
31     when nil
32       @email
33     else
34       @name
35     end
36   end
37
38   def longname
39     if @name && @email
40       "#@name <#@email>"
41     else
42       @email
43     end
44   end
45
46   def mediumname; @name || @email; end
47
48   def full_address
49     if @name && @email
50       if @name =~ /[",@]/
51         "#{@name.inspect} <#{@email}>" # escape quotes
52       else
53         "#{@name} <#{@email}>"
54       end
55     else
56       email
57     end
58   end
59
60   ## when sorting addresses, sort by this 
61   def sort_by_me
62     case @name
63     when /^(\S+), \S+/
64       $1
65     when /^\S+ \S+ (\S+)/
66       $1
67     when /^\S+ (\S+)/
68       $1
69     when nil
70       @email
71     else
72       @name
73     end.downcase
74   end
75
76   def self.from_address s
77     return nil if s.nil?
78
79     ## try and parse an email address and name
80     name, email = case s
81       when /(.+?) ((\S+?)@\S+) \3/
82         ## ok, this first match cause is insane, but bear with me.  email
83         ## addresses are stored in the to/from/etc fields of the index in a
84         ## weird format: "name address first-part-of-address", i.e.  spaces
85         ## separating those three bits, and no <>'s. this is the output of
86         ## #indexable_content. here, we reverse-engineer that format to extract
87         ## a valid address.
88         ##
89         ## we store things this way to allow searches on a to/from/etc field to
90         ## match any of those parts. a more robust solution would be to store a
91         ## separate, non-indexed field with the proper headers. but this way we
92         ## save precious bits, and it's backwards-compatible with older indexes.
93         [$1, $2]
94       when /["'](.*?)["'] <(.*?)>/, /([^,]+) <(.*?)>/
95         a, b = $1, $2
96         [a.gsub('\"', '"'), b]
97       when /<((\S+?)@\S+?)>/
98         [$2, $1]
99       when /((\S+?)@\S+)/
100         [$2, $1]
101       else
102         [nil, s]
103       end
104
105     Person.new name, email
106   end
107
108   def self.from_address_list ss
109     return [] if ss.nil?
110     ss.split_on_commas.map { |s| self.from_address s }
111   end
112
113   ## see comments in self.from_address
114   def indexable_content
115     [name, email, email.split(/@/).first].join(" ")
116   end
117
118   def eql? o; email.eql? o.email end
119   def hash; email.hash end
120 end
121
122 end