module Roust::Ticket

Public Instance Methods

create(attrs)

To maintain backwards compatibility with previous versions (and rt-client), alias these methods to their short form.

Alias for: ticket_create
history(id, opts = {})
Alias for: ticket_history
show(id)
Alias for: ticket_show
ticket_comment(id, attrs) click to toggle source
# File lib/roust/ticket.rb, line 85
def ticket_comment(id, attrs)
  attrs['Text'].gsub!(/\n/, "\n ") if attrs['Text'] # insert a space on continuation lines.
  content = compose_content('ticket', id, attrs)

  unless content.match(/Action: (comment|correspond)/i)
    raise "'Action' must be one of 'Comment' or 'Correspond'"
  end

  response = self.class.post(
    "/ticket/#{id}/comment",
    :body => {
      :content => content
    },
  )

    body, _ = explode_response(response)

    case body
    when /^# (Message recorded|Comments added|Correspondence added)/
      ticket_show(id)
    when /^# You are not allowed to modify ticket \d+/
      raise Unauthorized, body
    when /^# Syntax error/
      raise SyntaxError, body
    else
      raise UnhandledResponse, body
    end
end
ticket_create(attrs) click to toggle source
# File lib/roust/ticket.rb, line 13
def ticket_create(attrs)
  default_attrs = {
    'id' => 'ticket/new'
  }
  attrs = default_attrs.merge(attrs).stringify_keys!

  error = create_invalid?(attrs)
  raise InvalidRecord, error if error

  attrs['Text'].gsub!(/\n/, "\n ") if attrs['Text'] # insert a space on continuation lines.

  # We can't set more than one AdminCc when creating a ticket. WTF RT.
  #
  # Delete it from the ticket we are creating, and we'll update the ticket
  # after we've created.
  key, admincc = attrs.detect {|k,v| k =~ /admincc/i }
  attrs.delete(key)

  content = compose_content('ticket', attrs['id'], attrs)

  response = self.class.post(
    '/ticket/new',
    :body => {
      :content => content
    }
  )

  body, _ = explode_response(response)

  case body
  when /^# Ticket (\d+) created/
    id = $1
    # Add the AdminCc after the ticket is created, because we can't set it
    # on ticket creation.
    ticket_update(id, 'AdminCc' => admincc) if admincc

    # Return the whole ticket, not just the id.
    ticket_show(id)
  when /^# Could not create ticket/
    raise BadRequest, body
  when /^# Syntax error/
    raise SyntaxError, body
  else
    raise UnhandledResponse, body
  end
end
Also aliased as: create
ticket_history(id, opts = {}) click to toggle source
# File lib/roust/ticket.rb, line 144
def ticket_history(id, opts = {})
  options = {
    :format   => 'short',
    :comments => false
  }.merge(opts)

  format   = options[:format]
  comments = options[:comments]
  params = {
    :format => format[0]
  }

  response = self.class.get("/ticket/#{id}/history", :query => params)

  body, _ = explode_response(response)

  case format
  when 'short'
    parse_short_history(body, :comments => comments)
  when 'long'
    parse_long_history(body, :comments => comments)
  end
end
Also aliased as: history
ticket_show(id) click to toggle source
# File lib/roust/ticket.rb, line 3
def ticket_show(id)
  response = self.class.get("/ticket/#{id}/show")

  body, _ = explode_response(response)

  return nil if body =~ /^# (Ticket (\d+) does not exist\.)/

  parse_ticket_attributes(body)
end
Also aliased as: show
ticket_update(id, attrs) click to toggle source
# File lib/roust/ticket.rb, line 60
def ticket_update(id, attrs)
  content = compose_content('ticket', id, attrs)

  response = self.class.post(
    "/ticket/#{id}/edit",
    :body => {
      :content => content
    },
  )

    body, _ = explode_response(response)

    case body
    when /^# Ticket (\d+) updated/
      id = $1
      ticket_show(id)
    when /^# You are not allowed to modify ticket \d+/
      raise Unauthorized, body
    when /^# Syntax error/
      raise SyntaxError, body
    else
      raise UnhandledResponse, body
    end
end
Also aliased as: update
update(id, attrs)
Alias for: ticket_update

Private Instance Methods

create_invalid?(attrs) click to toggle source
# File lib/roust/ticket.rb, line 323
def create_invalid?(attrs)
  missing = %w(id Subject Queue).select { |k| !attrs.include?(k) }

  if missing.empty?
    return false
  else
    "Needs attributes: #{missing.join(', ')}"
  end
end
parse_long_history(body, opts = {}) click to toggle source
# File lib/roust/ticket.rb, line 379
def parse_long_history(body, opts = {})
  comments = opts[:comments]
  items = body.split("\n--\n")
  list = []
  items.each do |item|
    # Yes, this messes with the "content:" field but that's the one that's upsetting Mail.new
    item.gsub!(/\r/, "\n") # Mail doesn't handle \r at all.  Convert them all to \n, then remove the extra lines in the next step
    item.gsub!(/\n\s*\n/, "\n") # remove blank lines for Mail
    history = Mail.new(item)
    next if not comments and history['type'].to_s =~ /Comment/ # skip comments
      reply = {}

    history.header.fields.each_with_index do |header, index|
      next if index == 0

      key   = header.name.to_s.downcase
      value = header.value.to_s

      attachments = []
      case key
      when 'attachments'
        temp = item.match(/Attachments:\s*(.*)/m)
        if temp.class != NilClass
          atarr = temp[1].split("\n")
          atarr.map { |a| a.gsub!(/^\s*/, '') }
          atarr.each do |a|
            i = a.match(/(\d+):\s+(.*)/)
            # Something is wrong here, probably "\n\nAttachments" in the body of the transaction :(
            next unless i
            s = {
              :id   => i[1].to_s,
              :name => i[2].to_s
            }
            sz = i[2].match(/(.*?)\s*\((.*?)\)/)
            if sz.class == MatchData
              s[:name] = sz[1].to_s
              s[:size] = sz[2].to_s
            end
            attachments << s
          end
          reply['attachments'] = attachments
        end
      when 'content'
        reply['content'] = value
      else
        reply["#{key}"] = value
      end
    end
    list << reply
  end

  list
end
parse_short_history(body, opts = {}) click to toggle source
# File lib/roust/ticket.rb, line 372
def parse_short_history(body, opts = {})
  comments = opts[:comments]
  regex    = comments ? '^\d+:' : '^\d+: [^Comments]'
  history  = body.split("\n").select { |l| l =~ /#{regex}/ }
    history.map { |l| l.split(': ', 2) }
end
parse_ticket_attributes(body) click to toggle source

parse_ticket_attributes decodes a response body of ticket metadata.

Used by ticket_show and verbose ticket_search.

# File lib/roust/ticket.rb, line 336
def parse_ticket_attributes(body)
  # Replace CF spaces with underscores
  while body.match(/CF\.\{[\w_ ]*[ ]+[\w ]*\}/)
    body.gsub!(/CF\.\{([\w_ ]*)([ ]+)([\w ]*)\}/, 'CF.{\1_\3}')
  end

  # Sometimes the API returns requestors formatted like this:
  #
  #   Requestors: foo@example.org,
  #               bar@example.org, baz@example.org
  #               qux@example.org, quux@example.org,
  #               corge@example.org
  #
  # Turn it into this:
  #
  #   Requestors: foo@example.org, bar@example.org, baz@example.org, ...
  #
  body.gsub!(/\n\n/, "\n")

  %w(Requestors Cc AdminCc).each do |field|
    body.gsub!(/^#{field}:(.+)^\n/m) do |m|
      m.strip.split(/,\s+/).join(', ').strip
    end
  end

  hash = body_to_hash(body)

  %w(Requestors Cc AdminCc).each do |field|
    hash[field] = hash[field].split(', ') if hash[field]
  end

  hash['id'] = hash['id'].split('/').last

  hash
end