use JSON::Fast; unit module Matrix::Response; class Matrix::Response::Event { has %.content; has $.type is required; } class Matrix::Response::RoomEvent is Matrix::Response::Event { has Str $.sender; has Int $.origin_server_ts; has $.event_id; has Str $.room_id; method id { $.event_id } method timestamp { $!origin_server_ts } method room-id { $.room_id } } class Matrix::Response::StateEvent is Matrix::Response::RoomEvent { has $.prev_content; has $.state_key; } class Matrix::Response::Timeline { has Matrix::Response::Event @.events; has Bool $limited; has Str $prev-batch; } class Matrix::Response::RoomInfo { has $.room-id is required; has Matrix::Response::Event @.state; has Matrix::Response::Timeline $.timeline; method gist(--> Str) { "" } } class Matrix::Response::InviteInfo { has $.room-id is required; has Matrix::Response::Event @.events; method gist(--> Str) { "" } } sub gather-events($room-id, $from) { gather for $from.List -> $ev { take Matrix::Response::StateEvent.new(:room_id($room-id), |$ev); } } class Matrix::Response::Sync { has Str $.next-batch; has Matrix::Response::Event @.presence; has Matrix::Response::RoomInfo @.joined-rooms; has Matrix::Response::InviteInfo @.invited-rooms; multi method new(Str $json) { return self.new(from-json($json)); } multi method new(Hash $json) { my $next-batch = $json; my Matrix::Response::Event @presence; my Matrix::Response::RoomInfo @joined-rooms; my Matrix::Response::InviteInfo @invited-rooms; for $json.List -> $ev { @presence.push(Matrix::Response::Event.new(|$ev)); } for $json.kv -> $room-id, $data { my @state = gather-events($room-id, $data); my $timeline = Matrix::Response::Timeline.new( limited => $data, prev-batch => $data, events => gather-events($room-id, $data) ); @joined-rooms.push(Matrix::Response::RoomInfo.new( :$room-id, :$timeline, :@state )); } for $json.kv -> $room-id, $data { my @events = gather-events($room-id, $data); @invited-rooms.push(Matrix::Response::InviteInfo.new( :$room-id, :@events )); } return self.bless(:$next-batch, :@presence, :@joined-rooms, :@invited-rooms); } } class Presence { has Str $.presence is required; has Int $.last-active-ago; has Str $.status-message; has Bool $.currently-active; submethod BUILD( Str :$!presence, :last_active_ago(:$!last-active-ago) = 0, :status_message(:$!status-message) = "", :currently_active(:$!currently-active) = False ) { } } class Tag { has @.tags; method new(%json) { my @tags = %json.keys; self.bless(:@tags) } } class Matrix::Response::Device { has Str $.device-id; has $.display-name; has $.last-seen-ip; has $.last-seen-ts; submethod BUILD( Str :device_id(:$!device-id), :display_name(:$!display-name)?, :last_seen_ip(:$!last-seen-ip)?, :last_seen_ts(:$!last-seen-ts)? ) { } }