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