use JSON::Fast; unit module Matrix::Client::Response; class Event { has %.content; has $.type is required; } class RoomEvent is 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 StateEvent is RoomEvent { has $.prev_content; has $.state_key; } class MemberEvent is StateEvent { has $.type is required where 'm.room.member'; } class Timeline { has Event @.events; has Bool $limited; has Str $prev-batch; } class RoomInfo { has $.room-id is required; has Event @.state; has Timeline $.timeline; method gist(--> Str) { "" } } class InviteInfo { has $.room-id is required; has Event @.events; method gist(--> Str) { "" } } sub gather-events($room-id, $from) { gather for $from.List -> $ev { take StateEvent.new(:room_id($room-id), |$ev); } } class Messages { has $.start; has $.end; has RoomEvent @.messages; } class Sync { has Str $.next-batch; has Event @.presence; has RoomInfo @.joined-rooms; has InviteInfo @.invited-rooms; multi method new(Str $json) { return self.new(from-json($json)); } multi method new(Hash $json) { my $next-batch = $json; my Event @presence; my RoomInfo @joined-rooms; my InviteInfo @invited-rooms; for $json.List -> $ev { @presence.push(Event.new(|$ev)); } for $json.kv -> $room-id, $data { my @state = gather-events($room-id, $data); my $timeline = Timeline.new( limited => $data, prev-batch => $data, events => gather-events($room-id, $data) ); @joined-rooms.push(RoomInfo.new( :$room-id, :$timeline, :@state )); } for $json.kv -> $room-id, $data { my @events = gather-events($room-id, $data); @invited-rooms.push(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 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)? ) { } } class MediaStore::Config { has Int $.upload-size; method new(%config) { self.bless(:upload-size(%config // Int)); } }