summaryrefslogtreecommitdiff
path: root/fake-service/lib/pixelated_service/contacts.rb
blob: 2f57387dbad1d03f122994f909c44029abbb6a49 (plain)
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
require 'mail'
require 'set'

module PixelatedService
  class Contacts
    include Enumerable

    def initialize(persona)
      @persona = persona
      @contacts = nil
      @contacts_cache = {}
      @contacts_lookup = {}
    end

    def contact(ix)
      @contacts_lookup[ix]
    end

    def each
      curr = @contacts
      while curr
        yield curr
        curr = curr.next
      end
    end

    def normalize(addr)
      addr.downcase
    end

    def parse(a)
      ::Mail::Address.new(a)
    end

    def update c, addr
      @contacts_cache[normalize(addr.address)] = c
      c.name = addr.display_name if addr.display_name
      (c.addresses ||= Set.new) << addr.address
    end

    def create_new_contact(addr)
      old_first = @contacts
      c = Contact.new
      c.ident = addr.hash.abs.to_s
      c.next = old_first
      @contacts_lookup[c.ident] = c
      @contacts = c
      update c, addr
      c
    end

    def find_or_create(addr)
      parsed = parse(addr)
      if cc = @contacts_cache[normalize(parsed.address)]
        update cc, parsed
        cc
      else
        create_new_contact(parsed)
      end
    end

    def latest(prev, n)
      if prev && prev > n
        prev
      else
        n
      end
    end

    def new_mail_from(a, t)
      contact = find_or_create(a)
      contact.last_received = latest(contact.last_received, t)
      contact.mails_received ||= 0
      contact.mails_received += 1
    end

    def new_mail_to(a, t)
      contact = find_or_create(a)
      contact.last_sent = latest(contact.last_sent, t)
      contact.mails_sent ||= 0
      contact.mails_sent += 1
    end
  end
end