Module: Pikuri::Thunderbird::IcalLine

Defined in:
lib/pikuri/thunderbird/ical_line.rb

Overview

Parses the little iCalendar that Thunderbird leaves opaque — pikuri needs it only for cal_attendees, whose rows are raw +ATTENDEE+/+ORGANIZER+ content lines (everything else is already in normalized columns). The inbound counterpart to IcsEvent's outbound line building. Two entry points:

# domain: an attendee line → a typed {Attendee}
who = IcalLine.attendee('ATTENDEE;CN="Last, First";PARTSTAT=ACCEPTED:mailto:x@y.com')
who.name        # => "Last, First"
who.email       # => "x@y.com"
who.optional?   # => false

# generic: any content line → its name/params/value
line = IcalLine.parse('ATTENDEE;PARTSTAT=ACCEPTED:mailto:x@y.com')
line.params["PARTSTAT"]   # => "ACCEPTED"

Both are quote-aware — a +;+/+:+ inside a double-quoted param value doesn't split — and upcase param names (RFC 5545 §3.2: case-insensitive). +TEXT+-value backslash unescaping is deliberately not done: the names and addresses cal_attendees carries arrive quoted, not +,+/+;+-escaped, so it would be dead code.

Immutable.

Defined Under Namespace

Classes: Attendee, Parsed

Class Method Summary collapse

Class Method Details

.attendee(line) ⇒ Attendee

Parse one +ATTENDEE+/+ORGANIZER+ content line into an Attendee.

Parameters:

  • line (String)

    one raw cal_attendees.icalString.

Returns:



70
71
72
73
74
75
76
77
78
79
# File 'lib/pikuri/thunderbird/ical_line.rb', line 70

def self.attendee(line)
  parsed = parse(line)
  email = (parsed.params['EMAIL'].to_s.empty? ? parsed.value.sub(/\Amailto:/i, '') : parsed.params['EMAIL']).strip
  name = parsed.params['CN'].to_s.strip
  Attendee.new(
    name: name.empty? ? email : name, email: email,
    status: parsed.params['PARTSTAT'], role: parsed.params['ROLE'],
    cutype: parsed.params['CUTYPE'], organizer: parsed.name == 'ORGANIZER'
  )
end

.parse(line) ⇒ Parsed

Parse one content line into its Parsed parts. Never raises — a line with no : yields an empty value, a token with no = is skipped.

Parameters:

  • line (String)

    a raw iCal content line.

Returns:



86
87
88
89
90
91
92
93
94
# File 'lib/pikuri/thunderbird/ical_line.rb', line 86

def self.parse(line)
  head, value = split_unquoted(line, ':', max: 2)
  name, *param_tokens = split_unquoted(head, ';')
  params = param_tokens.each_with_object({}) do |token, h|
    key, val = token.split('=', 2)
    h[key.to_s.upcase] = unquote(val) if val
  end
  Parsed.new(name: name.to_s.upcase, params: params, value: value.to_s)
end