incoming_mms.rb

 1# frozen_string_literal: true
 2
 3class IncomingMMS
 4	def self.for(to, json)
 5		raise "Unknown encoding: #{json.inspect}" if json["encoding"] != "native"
 6
 7		txt, media = extract_parts(json)
 8
 9		EMPromise.all(
10			txt.map { |u|
11				EM::HttpRequest.new(u, tls: { verify_peer: true }).get.then(&:response)
12			}
13		).then do |fetched_txt|
14			new(to, fetched_txt, media, clean_fake_array(json["recip"]))
15		end
16	end
17
18	def self.extract_parts(json)
19		clean_fake_array(json["files"])
20			.grep_v(/\.smil\Z/i)
21			.map { |part| "#{json['url']}&authkey=#{json['authkey']}&file=#{part}" }
22			.partition { |url| url.end_with?(".txt") }
23	end
24
25	def self.clean_fake_array(str)
26		# Instead of arrays we get sent comma-seperated strings
27		# which sometimes contain blank elements or random whitespace
28		str.to_s.split(",").map(&:strip).reject(&:empty?)
29	end
30
31	def initialize(to, txt, media, recip)
32		@to = to
33		@txt = txt
34		@media = media
35		@recip = recip
36	end
37
38	def unproxied_to
39		ProxiedJID.new(@to).unproxied
40	end
41
42	def oobs
43		@media.map(&OOB.method(:new))
44	end
45
46	def addresses
47		return nil if @recip.empty?
48
49		@addresses ||= Addresses.new(
50			[{ type: "to", jid: unproxied_to }] +
51			@recip.map { |r| { type: "to", uri: "sms:+#{r}", delivered: true } }
52		)
53	end
54
55	def to_stanza
56		Blather::Stanza::Message.new(
57			addresses ? unproxied_to.domain : unproxied_to,
58			@txt.empty? ? nil : @txt.join("\n\n")
59		).tap do |m|
60			oobs.each { |oob| m << oob }
61			m << addresses if addresses
62		end
63	end
64end