Class: Craigslist::API::Image

Inherits:
Object
  • Object
show all
Defined in:
lib/craigslist/api/image.rb

Overview

An image attached to a bulk posting.

The RSS interface takes images inline as base64 JPEG data, up to 24 per posting. Position is zero-based and the image at position 0 is the one featured on search pages.

Constant Summary collapse

MAX_PER_POSTING =

Craigslist rejects postings carrying more than this many images.

24
MAX_POSITION =

Highest valid zero-based position.

MAX_PER_POSTING - 1

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data, position: nil) ⇒ Image

Returns a new instance of Image.

Parameters:

  • data (String)

    already base64-encoded data

  • position (Integer, nil) (defaults to: nil)


27
28
29
30
31
# File 'lib/craigslist/api/image.rb', line 27

def initialize(data, position: nil)
  @data = data
  @position = position
  freeze
end

Instance Attribute Details

#dataString (readonly)

Returns base64-encoded image data.

Returns:

  • (String)

    base64-encoded image data



20
21
22
# File 'lib/craigslist/api/image.rb', line 20

def data
  @data
end

#positionInteger? (readonly)

Returns zero-based position within the posting.

Returns:

  • (Integer, nil)

    zero-based position within the posting



23
24
25
# File 'lib/craigslist/api/image.rb', line 23

def position
  @position
end

Class Method Details

.from_base64(encoded, position: nil) ⇒ Image

Parameters:

  • encoded (String)

    data that is already base64

Returns:



87
88
89
# File 'lib/craigslist/api/image.rb', line 87

def from_base64(encoded, position: nil)
  new(encoded, position: position)
end

.from_data(binary, position: nil) ⇒ Image

Parameters:

  • binary (String)

    raw (unencoded) image bytes

Returns:



78
79
80
81
82
83
# File 'lib/craigslist/api/image.rb', line 78

def from_data(binary, position: nil)
  # pack("m") produces RFC 2045 base64 with line breaks, matching the
  # form Craigslist's own documentation shows. Using Array#pack rather
  # than the base64 gem keeps this dependency-free on Ruby 3.4+.
  new([binary].pack("m"), position: position)
end

.from_file(path, position: nil) ⇒ Image

Parameters:

  • path (String, Pathname)

Returns:



63
64
65
66
67
# File 'lib/craigslist/api/image.rb', line 63

def from_file(path, position: nil)
  from_data(File.binread(path.to_s), position: position)
rescue SystemCallError => e
  raise ValidationError, ["could not read image #{path}: #{e.message}"]
end

.from_io(io, position: nil) ⇒ Image

Parameters:

  • io (IO)

Returns:



71
72
73
74
# File 'lib/craigslist/api/image.rb', line 71

def from_io(io, position: nil)
  io.binmode if io.respond_to?(:binmode)
  from_data(io.read, position: position)
end

.wrap(source, position: nil) ⇒ Image

Coerces a caller-supplied image into an Craigslist::API::Image.

Accepts an existing Craigslist::API::Image, an IO-like object, or a path as a String or Pathname. Raw base64 has to go through from_base64 — guessing whether a String is a path or a payload would be worse than asking.

Parameters:

  • source (Image, IO, Pathname, String)
  • position (Integer, nil) (defaults to: nil)

Returns:

Raises:



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/craigslist/api/image.rb', line 44

def wrap(source, position: nil)
  case source
  when Image
    position.nil? ? source : new(source.data, position: position)
  when Pathname
    from_file(source, position: position)
  when String
    from_file(source, position: position)
  else
    if source.respond_to?(:read)
      from_io(source, position: position)
    else
      raise ValidationError, ["cannot build an image from #{source.class}"]
    end
  end
end

Instance Method Details

#inspectObject



97
98
99
# File 'lib/craigslist/api/image.rb', line 97

def inspect
  "#<#{self.class.name} position=#{position.inspect} bytes=#{data.bytesize}>"
end

#with_default_position(index) ⇒ Image

Returns a copy pinned to index when no position was set.

Returns:

  • (Image)

    a copy pinned to index when no position was set



93
94
95
# File 'lib/craigslist/api/image.rb', line 93

def with_default_position(index)
  position.nil? ? self.class.new(data, position: index) : self
end