From d128f9d8118ffe3117d71e21d3e707b8d345ce61 Mon Sep 17 00:00:00 2001 From: Claire Davis Date: Sat, 20 Jun 2020 16:59:20 -0700 Subject: [PATCH] Started creating types for the event (sync) feed --- MatrixDotNetLib/MatrixDotNetCmd/Program.cs | 3 + .../{MatrixApis.cs => MatrixApi.cs} | 26 +- .../MatrixDotNetLib/MatrixApiEntities.cs | 164 +++++++++++++ .../MatrixDotNetLib/MatrixSessionManager.cs | 224 +++++++++++++++++- Other Resources/matrix.org.json | 191 +++++++++++++++ README.md | 6 +- Scripts/.vscode/launch.json | 25 ++ Scripts/.vscode/tasks.json | 42 ++++ Scripts/ParseTest/ParseTest.csproj | 12 + Scripts/ParseTest/Program.cs | 141 +++++++++++ ...ynamic JSON parsing of sync responses.linq | 79 ++++++ 11 files changed, 881 insertions(+), 32 deletions(-) rename MatrixDotNetLib/MatrixDotNetLib/{MatrixApis.cs => MatrixApi.cs} (95%) create mode 100644 MatrixDotNetLib/MatrixDotNetLib/MatrixApiEntities.cs create mode 100644 Other Resources/matrix.org.json create mode 100644 Scripts/.vscode/launch.json create mode 100644 Scripts/.vscode/tasks.json create mode 100644 Scripts/ParseTest/ParseTest.csproj create mode 100644 Scripts/ParseTest/Program.cs create mode 100644 Scripts/dynamic JSON parsing of sync responses.linq diff --git a/MatrixDotNetLib/MatrixDotNetCmd/Program.cs b/MatrixDotNetLib/MatrixDotNetCmd/Program.cs index 4a41df2..771294c 100644 --- a/MatrixDotNetLib/MatrixDotNetCmd/Program.cs +++ b/MatrixDotNetLib/MatrixDotNetCmd/Program.cs @@ -167,6 +167,9 @@ namespace MatrixDotNetCmd string theRoomAlias = roomz[roomListInt].ToString(); // now we can join the room or something + MatrixRoom theRoom = session.JoinRoom(theRoomId); + + // with this room we can sync for events } } diff --git a/MatrixDotNetLib/MatrixDotNetLib/MatrixApis.cs b/MatrixDotNetLib/MatrixDotNetLib/MatrixApi.cs similarity index 95% rename from MatrixDotNetLib/MatrixDotNetLib/MatrixApis.cs rename to MatrixDotNetLib/MatrixDotNetLib/MatrixApi.cs index 52ab865..810560f 100644 --- a/MatrixDotNetLib/MatrixDotNetLib/MatrixApis.cs +++ b/MatrixDotNetLib/MatrixDotNetLib/MatrixApi.cs @@ -4,7 +4,7 @@ using System.Text; namespace MatrixDotNetLib { - public class MatrixApis + public class MatrixApi { public static class Server { @@ -641,30 +641,6 @@ namespace MatrixDotNetLib } } - public class MatrixApiEntities - { - public string DeviceId { get; set; } - public string EventId { get; set; } - public string EventType { get; set; } - public string Filename { get; set; } - public string FilterId { get; set; } - public string Kind { get; set; } - public string MediaId { get; set; } - public string NetworkId { get; set; } - public string ReceiptType { get; set; } - public string RoomAlias { get; set; } - public string RoomId { get; set; } - public string RoomIdOrAlias { get; set; } - public string RuleId { get; set; } - public string Scope { get; set; } - public string ServerName { get; set; } - public string StateKey { get; set; } - public string Tags { get; set; } - public string TxnId { get; set; } - public string Type { get; set; } - public string UserId { get; set; } - } - //public static Dictionary Server = new Dictionary() //{ // { "discovery", "/.well-known/matrix/client" }, diff --git a/MatrixDotNetLib/MatrixDotNetLib/MatrixApiEntities.cs b/MatrixDotNetLib/MatrixDotNetLib/MatrixApiEntities.cs new file mode 100644 index 0000000..8e9c318 --- /dev/null +++ b/MatrixDotNetLib/MatrixDotNetLib/MatrixApiEntities.cs @@ -0,0 +1,164 @@ +namespace MatrixDotNetLib +{ + public class MatrixApiEntities + { + public string DeviceId { get; set; } + public string EventId { get; set; } + public string EventType { get; set; } + public string Filename { get; set; } + public string FilterId { get; set; } + public string Kind { get; set; } + public string MediaId { get; set; } + public string NetworkId { get; set; } + public string ReceiptType { get; set; } + public string RoomAlias { get; set; } + public string RoomId { get; set; } + public string RoomIdOrAlias { get; set; } + public string RuleId { get; set; } + public string Scope { get; set; } + public string ServerName { get; set; } + public string StateKey { get; set; } + public string Tags { get; set; } + public string TxnId { get; set; } + public string Type { get; set; } + public string UserId { get; set; } + } + + //public static Dictionary Server = new Dictionary() + //{ + // { "discovery", "/.well-known/matrix/client" }, + // { "versions", "/_matrix/client/versions" }, + // { "capabilities", "/_matrix/client/r0/capabilities" }, + // { "whois", "/_matrix/client/r0/admin/whois/{userId}" }, + // { "search", "/_matrix/client/r0/search" }, + // { "usersearch", "/_matrix/client/r0/user_directory/search" }, + // { "roomlist", "/_matrix/client/r0/publicRooms" }, + // { "managerooms", "/_matrix/client/r0/directory/list/appservice/{networkId}/{roomId}" }, + // { "upgraderoom", "/_matrix/client/r0/rooms/{roomId}/upgrade" }, + // { "openid", "/_matrix/client/r0/user/{userId}/openid/request_token" }, + // { "voip", "/_matrix/client/r0/voip/turnServer" } + //}; + + //public static Dictionary Key = new Dictionary() + //{ + // { "latest", "/_matrix/client/r0/keys/changes" }, + // { "claim", "/_matrix/client/r0/keys/claim" }, + // { "download", "/_matrix/client/r0/keys/query" }, + // { "upload", "/_matrix/client/r0/keys/upload" } + //}; + + //public static Dictionary Device = new Dictionary() + //{ + // { "manage", "/_matrix/client/r0/devices" }, + // { "multidelete", "/_matrix/client/r0/delete_devices" }, + // { "send", "/_matrix/client/r0/sendToDevice/{eventType}/{txnId}" } + //}; + + //public static Dictionary Media = new Dictionary() + //{ + // { "config", "/_matrix/media/r0/config" }, + // { "save", "/_matrix/media/r0/download/{serverName}/{mediaId}" }, + // { "saveas", "/_matrix/media/r0/download/{serverName}/{mediaId}/{fileName}" }, + // { "preview", "/_matrix/media/r0/preview_url" }, + // { "thumb", "/_matrix/media/r0/thumbnail/{serverName}/{mediaId}" }, + // { "upload", "/_matrix/media/r0/upload" } + //}; + + //public static Dictionary Notifier = new Dictionary() + //{ + // { "notifiers", "/_matrix/client/r0/notifications" }, + // { "pushers", "/_matrix/client/r0/pushers" }, + // { "set", "/_matrix/client/r0/pushers/set" }, + // { "rules", "/_matrix/client/r0/pushrules/" } + //}; + + //public static Dictionary NotifierRule = new Dictionary() + //{ + // { "manage", "/_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}" }, + // { "actions", "/_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions" }, + // { "toggle", "/_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled" } + //}; + + //public static Dictionary User = new Dictionary() + //{ + // { "thirdparty", "/_matrix/client/r0/account/3pid" }, + // { "deactivate", "/_matrix/client/r0/account/deactivate" }, + // { "password", "/_matrix/client/r0/account/password" }, + // { "register", "/_matrix/client/r0/register" }, + // { "whoami", "/_matrix/client/r0/account/whoami" }, + // { "profile", "/_matrix/client/r0/profile/{userId}" }, + // { "avatar", "/_matrix/client/r0/profile/{userId}/avtatar_url" }, + // { "displayname", "/_matrix/client/r0/profile/{userId}/displayname" }, + // { "extrainfo", "/_matrix/client/r0/user/{userId}/account_data/{type}" }, + // { "eventfilter", "/_matrix/client/r0/user/{userId}/filter" }, + // { "rooms", "/_matrix/client/r0/joined_rooms" }, + // { "login", "/_matrix/client/r0/login" }, + // { "logout", "/_matrix/client/r0/logout" }, + // { "status", "/_matrix/client/r0/presence/{userId}/status" } + //}; + + //public static Dictionary UserRoom = new Dictionary() + //{ + // { "extrainfo", "/_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}" }, + // { "tags", "/_matrix/client/r0/user/{userId}/rooms/{roomId}/tags" } + //}; + + //public static Dictionary Room = new Dictionary() + //{ + // { "create", "/_matrix/client/r0/createRoom" }, + // { "aliases", "/_matrix/client/unstable/org.matrix.msc2432/rooms/{roomId}/aliases" }, + // { "active", "/_matrix/client/r0/rooms/{roomId}/joined_members" }, + // { "members", "/_matrix/client/r0/rooms/{roomId}/members" }, + // { "messages", "/_matrix/client/r0/rooms/{roomId}/messages" }, + // { "join", "/_matrix/client/r0/join/{roomIdOrAlias}" }, + // { "ban", "/_matrix/client/r0/rooms/{roomId}/ban" }, + // { "forget", "/_matrix/client/r0/rooms/{roomId}/forget" }, + // { "invite", "/_matrix/client/r0/rooms/{roomId}/invite" }, + // { "idjoin", "/_matrix/client/r0/rooms/{roomId}/join" }, + // { "kick", "/_matrix/client/r0/rooms/{roomId}/kick" }, + // { "leave", "/_matrix/client/r0/rooms/{roomId}/leave" }, + // { "unban", "/_matrix/client/r0/rooms/{roomId}/unban" }, + // { "marker", "/_matrix/client/r0/rooms/{roomId}/read_markers" } + //}; + + //public static Dictionary RoomEvent = new Dictionary() + //{ + // { "context", "/_matrix/client/r0/rooms/{roomId}/context/{eventId}" }, + // { "event", "/_matrix/client/r0/rooms/{roomId}/event/{eventId}" }, + // { "receipt", "/_matrix/client/r0/rooms/{roomId}/receipt/{receiptType}/{eventId}" }, + // { "redact", "/_matrix/client/r0/rooms/{roomId}/redact/{eventId}/{txnId}" }, + // { "send", "/_matrix/client/r0/rooms/{roomId}/send/{eventType}/{txnId}" }, + // { "typing", "/_matrix/client/r0/rooms/{roomId}/typing/{userId}" }, + // { "flag", "/_matrix/client/r0/rooms/{roomId}/report/{eventId}" } + //}; + + //public static Dictionary RoomState = new Dictionary() + //{ + // { "list", "/_matrix/client/r0/rooms/{roomId}/state" }, + // { "state", "/_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}" } + //}; + + //public Dictionary Entities = new Dictionary() + //{ + // { "deviceId", "" }, + // { "eventId", "" }, + // { "eventType", "" }, + // { "fileName", "" }, + // { "filterId", "" }, + // { "kind", "" }, + // { "mediaId", "" }, + // { "networkId", "" }, + // { "receiptType", "" }, + // { "roomAlias", "" }, + // { "roomId", "" }, + // { "roomIdOrAlias", "" }, + // { "ruleId", "" }, + // { "scope", "" }, + // { "serverName", "" }, + // { "stateKey", "" }, + // { "tags", "" }, + // { "txnId", "" }, + // { "type", "" }, + // { "userId", "" } + //}; +} diff --git a/MatrixDotNetLib/MatrixDotNetLib/MatrixSessionManager.cs b/MatrixDotNetLib/MatrixDotNetLib/MatrixSessionManager.cs index 787a024..50fcfa1 100644 --- a/MatrixDotNetLib/MatrixDotNetLib/MatrixSessionManager.cs +++ b/MatrixDotNetLib/MatrixDotNetLib/MatrixSessionManager.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Diagnostics; @@ -65,7 +66,7 @@ namespace MatrixDotNetLib // serialize object into JSON string requestJson = JsonConvert.SerializeObject(theRequest); - string responseJson = ApiResult(MatrixApis.User.Login, httpAction.POST, requestJson); + string responseJson = ApiResult(MatrixApi.User.Login, httpAction.POST, requestJson); MatrixLoginResponse response = JsonConvert.DeserializeObject(responseJson); @@ -84,7 +85,7 @@ namespace MatrixDotNetLib /// public MatrixUserRooms GetRooms() { - string responseJson = ApiResult(MatrixApis.User.Rooms, httpAction.GET); + string responseJson = ApiResult(MatrixApi.User.Rooms, httpAction.GET); return (MatrixUserRooms)JsonConvert.DeserializeObject(responseJson); } @@ -92,16 +93,31 @@ namespace MatrixDotNetLib /// /// Gets the aliases for the given (string)roomId /// - /// + /// Full string ID (not alias) of a room /// public MatrixRoomAliases GetRoomAliases(string roomId) { MatrixApiEntities entities = new MatrixApiEntities() { RoomId = roomId }; - string responseJson = ApiResult(MatrixApis.Room.Aliases, httpAction.GET, entities: entities); + string responseJson = ApiResult(MatrixApi.Room.Aliases, httpAction.GET, entities: entities); return (MatrixRoomAliases)JsonConvert.DeserializeObject(responseJson); } + /// + /// Joins the user to the given room by (string)roomId + /// + /// Full string ID (not alias) of a room + /// + public MatrixRoom JoinRoom(string roomId) + { + // create entity object + MatrixApiEntities apiEntities = new MatrixApiEntities() { RoomId = roomId }; + + string responseJson = ApiResult(MatrixApi.Room.Join, httpAction.POST, entities: apiEntities); + + return (MatrixRoom)JsonConvert.DeserializeObject(responseJson); + } + public MatrixRoomDirectory GetPublicRooms(int limit = 0, string page = null, string server = null) { string[] querystring = { }; @@ -127,11 +143,11 @@ namespace MatrixDotNetLib { string qs = string.Join("&", querystring); - responseJson = ApiResult(MatrixApis.Server.RoomList, httpAction.GET, query: qs); + responseJson = ApiResult(MatrixApi.Server.RoomList, httpAction.GET, query: qs); } else { - responseJson = ApiResult(MatrixApis.Server.RoomList, httpAction.GET); + responseJson = ApiResult(MatrixApi.Server.RoomList, httpAction.GET); } return (MatrixRoomDirectory)JsonConvert.DeserializeObject(responseJson); @@ -267,6 +283,202 @@ namespace MatrixDotNetLib } } } + + // classes to be moved // + + + public class MatrixSyncBody + { + public MatrixSyncRooms Rooms { get; set; } + } + + public class MatrixSyncRooms + { + // once the JSON from "join" is parsed, this is set to its contents as an object + public Dictionary Joined { get; private set;} + + public Dictionary Invited { get; private set; } + + public Dictionary Left { get; private set; } + + public JObject Join + { + get { return null; } + set + { + // takes JSON children and parses them into objects + // we have to do this bc the entity names under "join" are dynamic + // each entity holds a well-defined object though + + // create dict for Joined + Joined = new Dictionary(); + + // these AREN'T an array + ParseRooms(value, "Joined"); + } + } + + public JObject Invite + { + get { return null; } + set + { + // create dict for Joined + Invited = new Dictionary(); + + // these AREN'T an array + ParseRooms(value, "Invited"); + } + } + + public JObject Leave + { + get { return null; } + set + { + // create dict for Joined + Left = new Dictionary(); + + // these AREN'T an array + ParseRooms(value, "Left"); + } + } + + public void ParseRooms(JObject roomsJson, string valType) + { + // get the children of this object + JEnumerable kids = roomsJson.Children(); + + Dictionary roomList = new Dictionary(); + + foreach (JProperty kid in kids) + { + MatrixSyncRoom msr = JsonConvert.DeserializeObject(kid.Value.ToString()); + + roomList.Add(kid.Name, msr); + } + + // get the target + this.GetType().GetProperty(valType).SetValue(this,roomList); + } + } + + public class MatrixSyncRoom + { + public MatrixTimeline Timeline { get; set; } + } + + public class MatrixTimeline + { + public MatrixEvent[] Events { get; set; } + + [JsonProperty("prev_batch")] + public string PreviousBatch { get; set; } + + public bool IsLimited { get; set; } + } + + public class MatrixEvent + { + [JsonProperty("type")] + public string EventType { get; set; } + + public string Sender { get; set; } + + public MatrixEventContent Content { get; set; } + + [JsonProperty("state_key")] + public string StateKey { get; set; } + + [JsonProperty("origin_server_ts")] + public Int64 OriginTs { get; set; } + + public MatrixEventUnsigned Unsigned { get; set; } + } + + public class MatrixEventUnsigned + { + public int Age { get; set; } + + [JsonProperty("replaces_state")] + public string ReplaceState { get; set; } + + [JsonProperty("prev_content")] + public MatrixEventPrevContent PrevContent { get; set; } + } + + public class MatrixEventPrevContent + { + [JsonProperty("is_direct")] + public bool IsDirect { get; set; } + + public string Membership { get; set; } + + public string DisplayName { get; set; } + } + + public class MatrixEventContent + { + + public string Body { get; set; } + + public string Creator { get; set; } + + public string DisplayName { get; set; } + + [JsonProperty("event_id")] + public string EventId { get; set; } + + /// + /// Gets or sets the event content info property - check FileInfo.MimeType for file type + /// + [JsonProperty("info")] + public MatrixImageInfo FileInfo { get; set; } + + [JsonProperty("currently_active")] + public bool IsActive { get; set; } + + [JsonProperty("join_rule")] + public string JoinRule { get; set; } + + [JsonProperty("last_active_ago")] + public int LastActive { get; set; } + + public string Membership { get; set; } + + public string Name { get; set; } + + public string Presence { get; set; } + + [JsonProperty("room_version")] + public string RoomVersion { get; set; } + + public List Users { get; set; } + } + + public class MatrixFileInfo + { + public Int64 size { get; set; } + + public string MimeType { get; set; } + } + + public class MatrixImageThumbInfo : MatrixFileInfo + { + [JsonProperty("w")] + public int Width { get; set; } + + [JsonProperty("h")] + public int Height { get; set; } + } + + public class MatrixImageInfo : MatrixImageThumbInfo + { + [JsonProperty("thumbnail_info")] + public MatrixImageThumbInfo ThumbnailInfo { get; set; } + + public string ThumbnailUrl { get; set; } + } } diff --git a/Other Resources/matrix.org.json b/Other Resources/matrix.org.json new file mode 100644 index 0000000..adcf9f9 --- /dev/null +++ b/Other Resources/matrix.org.json @@ -0,0 +1,191 @@ +[ + { + "enabled": true, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1591921634962, + "name": "matrix.org", + "sections": [ + { + "code": ".description {\n margin-bottom: 15px;\n}\n\n.description > DIV {\n margin: 1em 0;\n margin-right: 10px;\n}\n\n.description > DIV > SPAN.propDesc {\n display: block;\n margin-top: .25em;\n margin-left: 1em;\n}\n\n.swagger-section .swagger-ui-wrap .content PRE {\n margin-top: 0px;\n}\n\nLI.resource.active > DIV > UL.options,\nINPUT.submit {\n display: none !important;\n}\n\nDIV.description[style] {\n display: block !important;\n}\n\n.signature-container {\n overflow: hidden;\n}\n\n.signature-container DIV.description {\n background: #aacc3333;\n padding: 1em;\n}\n\n.signature-container DIV.description {\n float: left;\n width: 48%;\n}\n\n.signature-container DIV.snippet {\n float: right;\n width: 48%;\n}\n\nTD[width=\"50%\"] .signature-container > DIV {\n width: 100%;\n}\n\n.fullwidth.parameters > THEAD > TR > TH:nth-child(5) {\n display: none;\n}\n\n.operation-params > TR > TD:nth-child(5) {\n float: left;\n clear: both;\n margin-top: 60px;\n margin-left: -740px;\n margin-bottom: 2em;\n width: 1025px;\n}\n\n.operation-params .body-textarea {\n display: none;\n}\n\n.response-content-type {\n clear: both;\n}\n\n.model-signature PRE {\n height: unset !important;\n}\n\n@media only screen and (max-width: 980px)\n{\n .operation-params > TR > TD:nth-child(5) {\n margin-left: -670px;\n width: 660px;\n }\n .signature-container DIV.description,\n .signature-container DIV.snippet {\n width: 47%;\n }\n .signature-container DIV.description {\n float: left;\n }\n\n .signature-container DIV.snippet {\n float: right;\n }\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api" + ] + } + ], + "updateDate": 1591935819656, + "_id": "78c1d175-a540-4e3e-9939-829237f53a9b", + "_rev": 1591935819656, + "id": 4 + }, + { + "enabled": false, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1591933721024, + "name": "matrix.org (show most, hide nav)", + "sections": [ + { + "code": "HEADER#main-header, DIV#message-bar {\n display: none;\n}\n\nDIV#page-container[style] {\n padding-top: 0px !important;\n}\n\n#document {\n margin-top: 0px;\n}\n\nDIV.content[style] {\n display: block !important;\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api" + ] + } + ], + "updateDate": 1592011124949, + "_id": "48c11d9a-061f-4eca-8674-900156a6b187", + "_rev": 1592433818401, + "id": 5 + }, + { + "enabled": false, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1591936252379, + "name": "matrix.org (show all)", + "sections": [ + { + "code": "UL.endpoints[style] {\n display: block !important;\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api" + ] + } + ], + "updateDate": 1592011114678, + "_id": "8f05634d-071a-483f-99ae-48a58043a662", + "_rev": 1592433747949, + "id": 6 + }, + { + "enabled": true, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1592357694067, + "name": "matrix.org (show lists)", + "sections": [ + { + "code": ".endpoints[style]\n{\n display: block !important;\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api/" + ] + } + ], + "updateDate": 1592358199296, + "_id": "c4cc45dd-4c0f-42c3-b13b-190c81683518", + "_rev": 1592433745119, + "id": 7 + }, + { + "enabled": false, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1592357832873, + "name": "matrix.org (hide DELETE)", + "sections": [ + { + "code": ".operations .delete.operation\n{\n display: none !important;\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api/" + ] + } + ], + "updateDate": 1592357849841, + "_id": "0a76f07e-ca21-4d3e-8880-981941ec0756", + "_rev": 1592358183506, + "id": 8 + }, + { + "enabled": false, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1592357881387, + "name": "matrix.org (hide GET)", + "sections": [ + { + "code": ".operations .get.operation\n{\n display: none !important;\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api/" + ] + } + ], + "updateDate": 1592357901640, + "_id": "e5fea56f-376b-4f1a-b827-346d17e705e7", + "_rev": 1592358181378, + "id": 9 + }, + { + "enabled": false, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1592357963432, + "name": "matrix.org (hide POST)", + "sections": [ + { + "code": ".operations .post.operation\n{\n display: none !important;\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api/" + ] + } + ], + "updateDate": 1592357963432, + "_id": "620abd07-519e-4ac4-8367-e71a2f06d5fb", + "_rev": 1592358023907, + "id": 10 + }, + { + "enabled": false, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1592358008867, + "name": "matrix.org (hide PUT)", + "sections": [ + { + "code": ".operations .put.operation\n{\n display: none !important;\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api/" + ] + } + ], + "updateDate": 1592358008867, + "_id": "c453ff85-f36c-4e05-913c-27ba1f021ba2", + "_rev": 1592358179527, + "id": 11 + }, + { + "enabled": true, + "updateUrl": null, + "md5Url": null, + "url": null, + "originalMd5": null, + "installDate": 1592433579958, + "name": "matrix.org (hide deprecated)", + "sections": [ + { + "code": "#Room32participation_getEvents,\n#Room32participation_getOneEvent,\n#Room32participation_initialSync,\n#Room32participation_roomInitialSync\n{\n display: none !important;\n}", + "urlPrefixes": [ + "https://matrix.org/docs/api/" + ] + } + ], + "updateDate": 1592434969286, + "_id": "f1f1a6db-7ed8-4cdc-9e97-148860429acd", + "_rev": 1592434969286, + "id": 12 + } +] \ No newline at end of file diff --git a/README.md b/README.md index 9293585..c5dd3a4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ # MatrixDotNetLib -A native .NET C# library for developing Matrix clients. \ No newline at end of file +A native .NET C# library for developing Matrix clients. + +## Other Resources + +There's a JSON file in there you can import into Stylus, the non-spyware version of Stylish. This makes it a little easier to use the [Swagger API documentation](https://matrix.org/docs/api/client-server/). \ No newline at end of file diff --git a/Scripts/.vscode/launch.json b/Scripts/.vscode/launch.json new file mode 100644 index 0000000..8efd03e --- /dev/null +++ b/Scripts/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/ParseTest/bin/Debug/netcoreapp3.1/ParseTest.dll", + "args": [], + "cwd": "${workspaceFolder}/ParseTest", + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/Scripts/.vscode/tasks.json b/Scripts/.vscode/tasks.json new file mode 100644 index 0000000..5861a28 --- /dev/null +++ b/Scripts/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/ParseTest/ParseTest.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/ParseTest/ParseTest.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/ParseTest/ParseTest.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/Scripts/ParseTest/ParseTest.csproj b/Scripts/ParseTest/ParseTest.csproj new file mode 100644 index 0000000..0eaee1b --- /dev/null +++ b/Scripts/ParseTest/ParseTest.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/Scripts/ParseTest/Program.cs b/Scripts/ParseTest/Program.cs new file mode 100644 index 0000000..2b48646 --- /dev/null +++ b/Scripts/ParseTest/Program.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace ParseTest +{ + class Program + { + static void Main(string[] args) + { + string txt = "{\n \"account_data\": {\n \"events\": [\n {\n \"type\": \"m.direct\",\n \"content\": {\n \"@jay:post.hyrule.cc\": [\n \"!gGpGMWeoEhhMMaWdGT:post.hyrule.cc\"\n ]\n }\n },\n {\n \"type\": \"m.secret_storage.key.qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\",\n \"content\": {\n \"algorithm\": \"m.secret_storage.v1.aes-hmac-sha2\",\n \"passphrase\": {\n \"algorithm\": \"m.pbkdf2\",\n \"iterations\": 500000,\n \"salt\": \"yluvcuEslWDOoGjx0kdSpL6XypugFAlF\"\n },\n \"iv\": \"r44S20rG0vYHmS/1f9JE8A==\",\n \"mac\": \"0hJUMdPcwfFsUcAD3J4GrbTIbW+f52lbOmTxzEewvYE=\"\n }\n },\n {\n \"type\": \"m.secret_storage.default_key\",\n \"content\": {\n \"key\": \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\"\n }\n },\n {\n \"type\": \"m.cross_signing.master\",\n \"content\": {\n \"encrypted\": {\n \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\": {\n \"iv\": \"7ghVcptd3VhhfI4b/u17qg==\",\n \"ciphertext\": \"GuyMsI+roUkAfVxZPFOuKTWNuEAkb1CKQ8/VnYVUcJ25F4qHiG0xaaKP4kQ=\",\n \"mac\": \"KvqtwcOy73HCHYem1Oy7+KxUBvu+rw2+XnOPyzpozSc=\"\n }\n }\n }\n },\n {\n \"type\": \"m.cross_signing.self_signing\",\n \"content\": {\n \"encrypted\": {\n \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\": {\n \"iv\": \"qWmjLCQyLGp1Jg7fAMh5lw==\",\n \"ciphertext\": \"mKc9wkV93IhwDWjuB1hPfR5VRuQiFVe+pF+BDZBoEJxOjxRJwXTgs/sXbAc=\",\n \"mac\": \"jaoUtwZGVA1nPP2dySZP0YSDb+QkfeWVqG3BHiNuH60=\"\n }\n }\n }\n },\n {\n \"type\": \"m.cross_signing.user_signing\",\n \"content\": {\n \"encrypted\": {\n \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\": {\n \"iv\": \"lUCmom8R9UEJi6YGFgHESA==\",\n \"ciphertext\": \"vFIpV/NUohPu+G9iWtOi57jbRjWjhNBjS91rdkKolypaMuuOba9C8CjDD+s=\",\n \"mac\": \"5jdCXMplGXv2ufQKS6GEW+16mgaXGGKuThkPJ1qjubk=\"\n }\n }\n }\n },\n {\n \"type\": \"m.megolm_backup.v1\",\n \"content\": {\n \"encrypted\": {\n \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\": {\n \"iv\": \"fiiaOiPwdC4UOgN0z8cujQ==\",\n \"ciphertext\": \"iT1CWwcGw6hRp343hFx00vIGyTDDSsvqCCVOEsU58N5WtQ3K7ilkIJ7xgrU=\",\n \"mac\": \"FgmKjel+mKt7gSlV0zqejfC9VMB+N5v02uv5v49ME74=\"\n }\n }\n }\n },\n {\n \"type\": \"im.vector.setting.breadcrumbs\",\n \"content\": {\n \"recent_rooms\": [\n \"!iEOZzedJhdJtozSkCK:post.hyrule.cc\",\n \"!OdeSTaDBtVXdpAAVue:post.hyrule.cc\",\n \"!gGpGMWeoEhhMMaWdGT:post.hyrule.cc\"\n ]\n }\n },\n {\n \"type\": \"im.vector.web.settings\",\n \"content\": {\n \"theme\": \"light\",\n \"useCompactLayout\": true\n }\n },\n {\n \"type\": \"m.push_rules\",\n \"content\": {\n \"global\": {\n \"underride\": [\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.call.invite\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"ring\"\n },\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.call\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"room_member_count\",\n \"is\": \"2\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.message\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.room_one_to_one\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"room_member_count\",\n \"is\": \"2\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.encrypted\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.encrypted_room_one_to_one\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.message\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.message\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.encrypted\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.encrypted\",\n \"default\": true,\n \"enabled\": true\n }\n ],\n \"sender\": [],\n \"room\": [],\n \"content\": [\n {\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\"\n }\n ],\n \"pattern\": \"claire\",\n \"rule_id\": \".m.rule.contains_user_name\",\n \"default\": true,\n \"enabled\": true\n }\n ],\n \"override\": [\n {\n \"conditions\": [],\n \"actions\": [\n \"dont_notify\"\n ],\n \"rule_id\": \".m.rule.master\",\n \"default\": true,\n \"enabled\": false\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"content.msgtype\",\n \"pattern\": \"m.notice\"\n }\n ],\n \"actions\": [\n \"dont_notify\"\n ],\n \"rule_id\": \".m.rule.suppress_notices\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.member\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"content.membership\",\n \"pattern\": \"invite\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"state_key\",\n \"pattern\": \"@claire:post.hyrule.cc\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.invite_for_me\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.member\"\n }\n ],\n \"actions\": [\n \"dont_notify\"\n ],\n \"rule_id\": \".m.rule.member_event\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"contains_display_name\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\"\n }\n ],\n \"rule_id\": \".m.rule.contains_display_name\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"content.body\",\n \"pattern\": \"@room\"\n },\n {\n \"kind\": \"sender_notification_permission\",\n \"key\": \"room\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"highlight\",\n \"value\": true\n }\n ],\n \"rule_id\": \".m.rule.roomnotif\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.tombstone\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"state_key\",\n \"pattern\": \"\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"highlight\",\n \"value\": true\n }\n ],\n \"rule_id\": \".m.rule.tombstone\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.reaction\"\n }\n ],\n \"actions\": [\n \"dont_notify\"\n ],\n \"rule_id\": \".m.rule.reaction\",\n \"default\": true,\n \"enabled\": true\n }\n ]\n },\n \"device\": {}\n }\n }\n ]\n },\n \"to_device\": {\n \"events\": []\n },\n \"device_lists\": {\n \"changed\": [],\n \"left\": []\n },\n \"presence\": {\n \"events\": [\n {\n \"type\": \"m.presence\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"presence\": \"online\",\n \"last_active_ago\": 444,\n \"currently_active\": true\n }\n }\n ]\n },\n \"rooms\": {\n \"join\": {\n \"!iEOZzedJhdJtozSkCK:post.hyrule.cc\": {\n \"timeline\": {\n \"events\": [\n {\n \"type\": \"m.room.create\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"room_version\": \"5\",\n \"creator\": \"@claire:post.hyrule.cc\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360971618,\n \"unsigned\": {\n \"age\": 324856016\n },\n \"event_id\": \"$sJ6OYdOkSDVmOAngZcufVYZeKaq8MN3tL8Uhk3kbL_c\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\",\n \"avatar_url\": \"mxc://post.hyrule.cc/RKdIOiYvQEBkutEikNQcvywz\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592360972137,\n \"unsigned\": {\n \"age\": 324855497\n },\n \"event_id\": \"$ZSrKxxwepzaisqJf0Y1QLJnHPIYaZNPsXT2xfd3YV1k\"\n },\n {\n \"type\": \"m.room.power_levels\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"users\": {\n \"@claire:post.hyrule.cc\": 100\n },\n \"users_default\": 0,\n \"events\": {\n \"m.room.name\": 50,\n \"m.room.power_levels\": 100,\n \"m.room.history_visibility\": 100,\n \"m.room.canonical_alias\": 50,\n \"m.room.avatar\": 50,\n \"m.room.tombstone\": 100,\n \"m.room.server_acl\": 100,\n \"m.room.encryption\": 100\n },\n \"events_default\": 0,\n \"state_default\": 50,\n \"ban\": 50,\n \"kick\": 50,\n \"redact\": 50,\n \"invite\": 50\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360972461,\n \"unsigned\": {\n \"age\": 324855173\n },\n \"event_id\": \"$LhWiDPlk5TeqdgkmofJi6qwWcynUqEs82vWLFHRKLjg\"\n },\n {\n \"type\": \"m.room.canonical_alias\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"alias\": \"#nerdsonly:post.hyrule.cc\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360972898,\n \"unsigned\": {\n \"age\": 324854736\n },\n \"event_id\": \"$ryY_eCI5Dg9dyOKIRxtz0xmbFMiMXfkCkfYg39E3V3c\"\n },\n {\n \"type\": \"m.room.join_rules\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"join_rule\": \"public\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360973257,\n \"unsigned\": {\n \"age\": 324854377\n },\n \"event_id\": \"$zWqD4UJq9EJDVlxqdekQiPOwWXb0vIa7U6xH9XNggpY\"\n },\n {\n \"type\": \"m.room.history_visibility\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"history_visibility\": \"shared\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360973745,\n \"unsigned\": {\n \"age\": 324853889\n },\n \"event_id\": \"$mAHuhlSnmIUwxwD4zayTSp-6oFPLKO2_uzT5ar24AtU\"\n },\n {\n \"type\": \"m.room.name\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"name\": \"Nerdy Stuff\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360974424,\n \"unsigned\": {\n \"age\": 324853210\n },\n \"event_id\": \"$4-5nBvrGqbIvk05opUCrMvgUNq20V-Jy04QFOrFJ7Rg\"\n },\n {\n \"type\": \"m.room.topic\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"topic\": \"A public channel for nerdy stuff\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360974886,\n \"unsigned\": {\n \"age\": 324852748\n },\n \"event_id\": \"$DvvyuvuhdoehJGW0-tY_H8vWbI9hjR-wd_q0j1G9I80\"\n }\n ],\n \"prev_batch\": \"s84_3821_0_57_1_1_17_86_1\",\n \"limited\": false\n },\n \"state\": {\n \"events\": []\n },\n \"account_data\": {\n \"events\": [\n {\n \"type\": \"m.fully_read\",\n \"content\": {\n \"event_id\": \"$DvvyuvuhdoehJGW0-tY_H8vWbI9hjR-wd_q0j1G9I80\"\n }\n }\n ]\n },\n \"ephemeral\": {\n \"events\": []\n },\n \"unread_notifications\": {},\n \"summary\": {}\n },\n \"!gGpGMWeoEhhMMaWdGT:post.hyrule.cc\": {\n \"timeline\": {\n \"events\": [\n {\n \"type\": \"m.call.candidates\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"version\": 0,\n \"call_id\": \"c15919060032180.7748147521165045\",\n \"candidates\": [\n {\n \"candidate\": \"candidate:4273728266 1 udp 2122260223 192.168.1.125 54952 typ host generation 0 ufrag iyrH network-id 1 network-cost 10\",\n \"sdpMid\": \"0\",\n \"sdpMLineIndex\": 0\n },\n {\n \"candidate\": \"candidate:4273728266 1 udp 2122260223 192.168.1.125 45335 typ host generation 0 ufrag iyrH network-id 1 network-cost 10\",\n \"sdpMid\": \"1\",\n \"sdpMLineIndex\": 1\n },\n {\n \"candidate\": \"candidate:2956466170 1 tcp 1518280447 192.168.1.125 9 typ host tcptype active generation 0 ufrag iyrH network-id 1 network-cost 10\",\n \"sdpMid\": \"0\",\n \"sdpMLineIndex\": 0\n },\n {\n \"candidate\": \"candidate:2956466170 1 tcp 1518280447 192.168.1.125 9 typ host tcptype active generation 0 ufrag iyrH network-id 1 network-cost 10\",\n \"sdpMid\": \"1\",\n \"sdpMLineIndex\": 1\n }\n ]\n },\n \"origin_server_ts\": 1591906006145,\n \"unsigned\": {\n \"age\": 779821489\n },\n \"event_id\": \"$kdssQDx48gI4Xj9e8RPOoMDE28fTNCPN9Al7zzSdlxo\"\n },\n {\n \"type\": \"m.call.hangup\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"version\": 0,\n \"call_id\": \"c15919060032180.7748147521165045\",\n \"reason\": \"invite_timeout\"\n },\n \"origin_server_ts\": 1591906066189,\n \"unsigned\": {\n \"age\": 779761445\n },\n \"event_id\": \"$ORezi_OqdVHh5Y2u-SSsmc4q4NgrOk4keMsOSy-9GfU\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"test\"\n },\n \"origin_server_ts\": 1591910069654,\n \"unsigned\": {\n \"age\": 775757980\n },\n \"event_id\": \"$XMp7Ha2MxfteVmqlmlJk684BdoFZapPFIz0kdpJY8pc\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\",\n \"avatar_url\": \"mxc://post.hyrule.cc/SJvUBWJQkhzpOtGWMAaEAgAj\"\n },\n \"state_key\": \"@jay:post.hyrule.cc\",\n \"origin_server_ts\": 1592019802207,\n \"unsigned\": {\n \"replaces_state\": \"$kulF3B0iVmAHky2EbHJxvmGK8HlcBMolcJN2bpPSuvo\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\"\n },\n \"prev_sender\": \"@jay:post.hyrule.cc\",\n \"age\": 666025427\n },\n \"event_id\": \"$fDB3EP_IPyrTT4L_QfgX0L7mDAWMZepceMkK5qBvBjE\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592020047819,\n \"unsigned\": {\n \"replaces_state\": \"$aWTER7_eLhOTDphn5qun81Yv5pXMdF-9tk880d0HQxw\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"claire\"\n },\n \"prev_sender\": \"@claire:post.hyrule.cc\",\n \"age\": 665779815\n },\n \"event_id\": \"$7jPKVQpUKSYdyJCmLRRho-GMmE5zoR_cDJUJIrv17fo\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\",\n \"avatar_url\": \"mxc://post.hyrule.cc/RKdIOiYvQEBkutEikNQcvywz\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592020049836,\n \"unsigned\": {\n \"replaces_state\": \"$7jPKVQpUKSYdyJCmLRRho-GMmE5zoR_cDJUJIrv17fo\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\"\n },\n \"prev_sender\": \"@claire:post.hyrule.cc\",\n \"age\": 665777798\n },\n \"event_id\": \"$ukskv7VzBOPFv8K44K6HVlmW0TM7ZpLmkaLwn-kJqfQ\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"butts\"\n },\n \"origin_server_ts\": 1592020103438,\n \"unsigned\": {\n \"age\": 665724196\n },\n \"event_id\": \"$tfxzWv0dJxLPDt4kTj91kQfRFyggrqNZLu6fR78d-B0\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"From now on, it'll be with your new avatar\"\n },\n \"origin_server_ts\": 1592020103711,\n \"unsigned\": {\n \"age\": 665723923\n },\n \"event_id\": \"$p3k4jtfejod6tZMWdecAMSttQNzkKRSTaZJCtOU8hAs\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"this is neat\"\n },\n \"origin_server_ts\": 1592020107312,\n \"unsigned\": {\n \"age\": 665720322\n },\n \"event_id\": \"$c2LQnx63ME0JELRdCOwuJG2BINSxatcT82KNN7iPPrE\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"butts butts butts\"\n },\n \"origin_server_ts\": 1592020109549,\n \"unsigned\": {\n \"age\": 665718085\n },\n \"event_id\": \"$RJ1iJAKhVxH28SxHLToYTHVThCcoM2h_FZyAAIUdOl4\"\n }\n ],\n \"prev_batch\": \"t13-19_3821_0_57_1_1_17_86_1\",\n \"limited\": true\n },\n \"state\": {\n \"events\": [\n {\n \"type\": \"m.room.guest_access\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"guest_access\": \"can_join\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901096163,\n \"unsigned\": {\n \"age\": 784731471\n },\n \"event_id\": \"$tVrzSLRrGmiqrhcFAIRxK0bqsMeD4xjo3D7fpgupqTs\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"claire\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1591905639351,\n \"unsigned\": {\n \"replaces_state\": \"$rAIEXypyyC_2eaAZ11VtKvD8qWwTD6px4H8xGiZuaD8\",\n \"prev_content\": {\n \"is_direct\": true,\n \"membership\": \"invite\",\n \"displayname\": \"claire\"\n },\n \"prev_sender\": \"@jay:post.hyrule.cc\",\n \"age\": 780188283\n },\n \"event_id\": \"$aWTER7_eLhOTDphn5qun81Yv5pXMdF-9tk880d0HQxw\"\n },\n {\n \"type\": \"m.room.history_visibility\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"history_visibility\": \"shared\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901095658,\n \"unsigned\": {\n \"age\": 784731976\n },\n \"event_id\": \"$7jCQJmcP0vydaXmYq-7hLytW1IvdlwSHDMdztv-4Aq4\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\"\n },\n \"state_key\": \"@jay:post.hyrule.cc\",\n \"origin_server_ts\": 1591901094466,\n \"unsigned\": {\n \"age\": 784733168\n },\n \"event_id\": \"$kulF3B0iVmAHky2EbHJxvmGK8HlcBMolcJN2bpPSuvo\"\n },\n {\n \"type\": \"m.room.create\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"room_version\": \"5\",\n \"creator\": \"@jay:post.hyrule.cc\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901093918,\n \"unsigned\": {\n \"age\": 784733716\n },\n \"event_id\": \"$ub2hvdrBC8z-LAH0b-cVOahuegTrQRCWkeCz91SaHUA\"\n },\n {\n \"type\": \"m.room.join_rules\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"join_rule\": \"invite\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901095203,\n \"unsigned\": {\n \"age\": 784732431\n },\n \"event_id\": \"$XdaCM5_AumDDtWiAHdfscyLOKzIUBb_ZbkilEfvo4UU\"\n },\n {\n \"type\": \"m.room.power_levels\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"users\": {\n \"@jay:post.hyrule.cc\": 100,\n \"@claire:post.hyrule.cc\": 100\n },\n \"users_default\": 0,\n \"events\": {\n \"m.room.name\": 50,\n \"m.room.power_levels\": 100,\n \"m.room.history_visibility\": 100,\n \"m.room.canonical_alias\": 50,\n \"m.room.avatar\": 50,\n \"m.room.tombstone\": 100,\n \"m.room.server_acl\": 100,\n \"m.room.encryption\": 100\n },\n \"events_default\": 0,\n \"state_default\": 50,\n \"ban\": 50,\n \"kick\": 50,\n \"redact\": 50,\n \"invite\": 0\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901094797,\n \"unsigned\": {\n \"age\": 784732837\n },\n \"event_id\": \"$8EOZ273lTw-8ocwRM4f_1pjQhY9coCqdEe3cjO11P1A\"\n }\n ]\n },\n \"account_data\": {\n \"events\": [\n {\n \"type\": \"m.fully_read\",\n \"content\": {\n \"event_id\": \"$RJ1iJAKhVxH28SxHLToYTHVThCcoM2h_FZyAAIUdOl4\"\n }\n }\n ]\n },\n \"ephemeral\": {\n \"events\": [\n {\n \"type\": \"m.receipt\",\n \"content\": {\n \"$c2LQnx63ME0JELRdCOwuJG2BINSxatcT82KNN7iPPrE\": {\n \"m.read\": {\n \"@jay:post.hyrule.cc\": {\n \"ts\": 1592020107783\n }\n }\n },\n \"$RJ1iJAKhVxH28SxHLToYTHVThCcoM2h_FZyAAIUdOl4\": {\n \"m.read\": {\n \"@claire:post.hyrule.cc\": {\n \"ts\": 1592020662042\n }\n }\n }\n }\n }\n ]\n },\n \"unread_notifications\": {\n \"notification_count\": 0,\n \"highlight_count\": 0\n },\n \"summary\": {}\n },\n \"!OdeSTaDBtVXdpAAVue:post.hyrule.cc\": {\n \"timeline\": {\n \"events\": [\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"the UI is just enormous by comparison\"\n },\n \"origin_server_ts\": 1591907739492,\n \"unsigned\": {\n \"age\": 778088142\n },\n \"event_id\": \"$F3SebL9S7ndGf0kEtD-_O7VNrCJTv7Xrj2187mYyTp0\"\n },\n {\n \"type\": \"m.room.redaction\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {},\n \"redacts\": \"$8CpoHVMQjW6idnAXbM_AqF2cpNCZOfcNrf1y7g1pgIc\",\n \"origin_server_ts\": 1591907782723,\n \"unsigned\": {\n \"age\": 778044911\n },\n \"event_id\": \"$YjvBCC-IzXY1Vn67PHG9ZHflmUsOjKkUOjbUZBSSj7I\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"body\": \"image.png\",\n \"info\": {\n \"size\": 96883,\n \"mimetype\": \"image/png\",\n \"thumbnail_info\": {\n \"w\": 800,\n \"h\": 458,\n \"mimetype\": \"image/png\",\n \"size\": 74584\n },\n \"w\": 1280,\n \"h\": 733,\n \"thumbnail_url\": \"mxc://post.hyrule.cc/vcTfUvRQUHlYtygbQTwEZRUL\"\n },\n \"msgtype\": \"m.image\",\n \"url\": \"mxc://post.hyrule.cc/yrlNZxoteIwWLrkxbsgopLiD\"\n },\n \"origin_server_ts\": 1591907787861,\n \"unsigned\": {\n \"age\": 778039773\n },\n \"event_id\": \"$gtp3cFyjM0NoEAPk8oh0CpW-5wx9YNhua_p2ZBALW9c\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\",\n \"avatar_url\": \"mxc://post.hyrule.cc/SJvUBWJQkhzpOtGWMAaEAgAj\"\n },\n \"state_key\": \"@jay:post.hyrule.cc\",\n \"origin_server_ts\": 1592019801698,\n \"unsigned\": {\n \"replaces_state\": \"$xSq70WplyPage-bR3NcHq4gAEIT-8he0ngu88jr2exU\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\"\n },\n \"prev_sender\": \"@jay:post.hyrule.cc\",\n \"age\": 666025936\n },\n \"event_id\": \"$a2jE7MKG4jQ_-rx6szaayBcIQTO-TNvzvJsZ0qDPUns\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592020047301,\n \"unsigned\": {\n \"replaces_state\": \"$NOkbQMy6nma818erRg31Adh6rVYZXBqclivbKo-4EpY\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"claire\"\n },\n \"prev_sender\": \"@claire:post.hyrule.cc\",\n \"age\": 665780333\n },\n \"event_id\": \"$kcD7ljDlfYOBJYkj-ETsci6mceaKFX83W5ogXDD_qmI\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\",\n \"avatar_url\": \"mxc://post.hyrule.cc/RKdIOiYvQEBkutEikNQcvywz\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592020049343,\n \"unsigned\": {\n \"replaces_state\": \"$kcD7ljDlfYOBJYkj-ETsci6mceaKFX83W5ogXDD_qmI\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\"\n },\n \"prev_sender\": \"@claire:post.hyrule.cc\",\n \"age\": 665778291\n },\n \"event_id\": \"$i-Eyg2S9JhtKIjRgzp5GWGN6hVvDjdJ1_KknHW_XS7Q\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"hi\"\n },\n \"origin_server_ts\": 1592021022525,\n \"unsigned\": {\n \"age\": 664805109\n },\n \"event_id\": \"$78MKiI5wXFlCirtLkpe_BnQH_DcB5q8sXvcHDbzXhZI\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"haha you can't press enter to send a message\"\n },\n \"origin_server_ts\": 1592021034633,\n \"unsigned\": {\n \"age\": 664793001\n },\n \"event_id\": \"$g8gXjqKM7XWZV1t_d5cYyYDEPCzczWVpbUgEpjiR8Y4\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"test]\"\n },\n \"origin_server_ts\": 1592021081708,\n \"unsigned\": {\n \"age\": 664745926\n },\n \"event_id\": \"$H1m50rEleK2tEWmY7-dTdEPlUT46lljQuIUvXkw-rjo\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"eyyy it worked\"\n },\n \"origin_server_ts\": 1592021085433,\n \"unsigned\": {\n \"age\": 664742201\n },\n \"event_id\": \"$hwk9J-XRURGRvVu8EfIM6yIs7oTJX4RHjgsC89L7oXI\"\n }\n ],\n \"prev_batch\": \"t44-58_3821_0_57_1_1_17_86_1\",\n \"limited\": true\n },\n \"state\": {\n \"events\": [\n {\n \"type\": \"m.room.history_visibility\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"history_visibility\": \"shared\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905971725,\n \"unsigned\": {\n \"age\": 779855909\n },\n \"event_id\": \"$h8jIhCdFIGavE_N-_B1PcMxMIzs3PAatR_P2lzKgr8M\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\"\n },\n \"state_key\": \"@jay:post.hyrule.cc\",\n \"origin_server_ts\": 1591907265464,\n \"unsigned\": {\n \"replaces_state\": \"$QAt6I0pTligtc3MOq0fEA4zDMoFaqldG9FkYhEOxp-I\",\n \"age\": 778562170\n },\n \"event_id\": \"$xSq70WplyPage-bR3NcHq4gAEIT-8he0ngu88jr2exU\"\n },\n {\n \"type\": \"m.room.power_levels\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"users\": {\n \"@claire:post.hyrule.cc\": 100\n },\n \"users_default\": 0,\n \"events\": {\n \"m.room.name\": 50,\n \"m.room.power_levels\": 100,\n \"m.room.history_visibility\": 100,\n \"m.room.canonical_alias\": 50,\n \"m.room.avatar\": 50,\n \"m.room.tombstone\": 100,\n \"m.room.server_acl\": 100,\n \"m.room.encryption\": 100\n },\n \"events_default\": 0,\n \"state_default\": 50,\n \"ban\": 50,\n \"kick\": 50,\n \"redact\": 50,\n \"invite\": 50\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905970691,\n \"unsigned\": {\n \"age\": 779856943\n },\n \"event_id\": \"$ILYd8-lWb3vpTyeAm73CAs_Dm3GCyXeJDwM4pgDmt9w\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"claire\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1591905970349,\n \"unsigned\": {\n \"age\": 779857285\n },\n \"event_id\": \"$NOkbQMy6nma818erRg31Adh6rVYZXBqclivbKo-4EpY\"\n },\n {\n \"type\": \"m.room.join_rules\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"join_rule\": \"public\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905971142,\n \"unsigned\": {\n \"age\": 779856492\n },\n \"event_id\": \"$zUSAikyCKbhOfIl0cWb4y8bI8wHWLZhIlelP8BLmBPM\"\n },\n {\n \"type\": \"m.room.name\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"name\": \"boobs\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905972652,\n \"unsigned\": {\n \"age\": 779854982\n },\n \"event_id\": \"$n0A5l9t5_zgy8vlkSBQP3cJbwej3ENW1LckBSW_QxvU\"\n },\n {\n \"type\": \"m.room.create\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"room_version\": \"5\",\n \"creator\": \"@claire:post.hyrule.cc\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905969834,\n \"unsigned\": {\n \"age\": 779857800\n },\n \"event_id\": \"$ukewPt_m8GLbjjB529a1i6mLjOm3YLox1zan0tJr9yU\"\n }\n ]\n },\n \"account_data\": {\n \"events\": [\n {\n \"type\": \"m.fully_read\",\n \"content\": {\n \"event_id\": \"$hwk9J-XRURGRvVu8EfIM6yIs7oTJX4RHjgsC89L7oXI\"\n }\n }\n ]\n },\n \"ephemeral\": {\n \"events\": [\n {\n \"type\": \"m.receipt\",\n \"content\": {\n \"$hwk9J-XRURGRvVu8EfIM6yIs7oTJX4RHjgsC89L7oXI\": {\n \"m.read\": {\n \"@jay:post.hyrule.cc\": {\n \"ts\": 1592021102633\n }\n }\n },\n \"$g8gXjqKM7XWZV1t_d5cYyYDEPCzczWVpbUgEpjiR8Y4\": {\n \"m.read\": {\n \"@claire:post.hyrule.cc\": {\n \"ts\": 1592071800533\n }\n }\n }\n }\n }\n ]\n },\n \"unread_notifications\": {\n \"notification_count\": 0,\n \"highlight_count\": 0\n },\n \"summary\": {}\n }\n },\n \"invite\": {},\n \"leave\": {}\n },\n \"groups\": {\n \"join\": {},\n \"invite\": {},\n \"leave\": {}\n },\n \"device_one_time_keys_count\": {},\n \"next_batch\": \"s84_3821_0_57_1_1_17_86_1\"\n}"; + + dynamic d = JObject.Parse(txt); + + MatrixSyncBody sbody = JsonConvert.DeserializeObject(txt); + + // JObject obj = d.rooms.join; + + // JEnumerable kids = obj.Children(); + + // foreach (JProperty kid in kids) + // { + // Console.WriteLine(kid.Name); + // MatrixSyncRoom msr = JsonConvert.DeserializeObject(kid.Value.ToString()); + + // Console.WriteLine(msr.Timeline.Events[0].Sender); + // } + + //Console.WriteLine(d.rooms.join["!gGpGMWeoEhhMMaWdGT:post.hyrule.cc"].timeline.events); + } + } + + public class MatrixSyncBody + { + public MatrixSyncRooms Rooms { get; set; } + } + + public class MatrixSyncRooms + { + // once the JSON from "join" is parsed, this is set to its contents as an object + public Dictionary Joined { get; private set;} + + public JObject Join + { + get { return null; } + set + { + // takes JSON children and parses them into objects + // we have to do this bc the entity names under "join" are dynamic + // each entity holds a well-defined object though + + // create dict for Joined + Joined = new Dictionary(); + + // these AREN'T an array + ParseRooms(value, "Joined"); + } + } + + public void ParseRooms(JObject roomsJson, string valType) + { + // get the children of this object + JEnumerable kids = roomsJson.Children(); + + Dictionary roomList = new Dictionary(); + + foreach (JProperty kid in kids) + { + MatrixSyncRoom msr = JsonConvert.DeserializeObject(kid.Value.ToString()); + + roomList.Add(kid.Name, msr); + } + + // get the target + this.GetType().GetProperty(valType).SetValue(this,roomList); + } + } + + public class MatrixSyncRoom + { + public MatrixTimeline Timeline { get; set; } + } + + public class MatrixTimeline + { + public MatrixEvent[] Events { get; set; } + + [JsonProperty("prev_batch")] + public string PreviousBatch { get; set; } + + public bool IsLimited { get; set; } + } + + public class MatrixEvent + { + [JsonProperty("type")] + public string EventType { get; set; } + + public string Sender { get; set; } + + public MatrixEventContent Content { get; set; } + + [JsonProperty("state_key")] + public string StateKey { get; set; } + + [JsonProperty("origin_server_ts")] + public Int64 OriginTs { get; set; } + + public MatrixEventUnsigned Unsigned { get; set; } + } + + public class MatrixEventUnsigned + { + public int Age { get; set; } + + [JsonProperty("replaces_state")] + public string ReplaceState { get; set; } + + [JsonProperty("prev_content")] + public MatrixEventPrevContent PrevContent { get; set; } + } + + public class MatrixEventPrevContent + { + [JsonProperty("is_direct")] + public bool IsDirect { get; set; } + + public string Membership { get; set; } + + public string DisplayName { get; set; } + } + + public class MatrixEventContent + { + [JsonProperty("room_version")] + public string RoomVersion { get; set; } + + public string Creator { get; set; } + } +} diff --git a/Scripts/dynamic JSON parsing of sync responses.linq b/Scripts/dynamic JSON parsing of sync responses.linq new file mode 100644 index 0000000..4ccc055 --- /dev/null +++ b/Scripts/dynamic JSON parsing of sync responses.linq @@ -0,0 +1,79 @@ + + Newtonsoft.Json + Newtonsoft.Json + Newtonsoft.Json.Bson + Newtonsoft.Json.Converters + Newtonsoft.Json.Linq + Newtonsoft.Json.Schema + Newtonsoft.Json.Serialization + + +void Main() +{ + string txt = "{\n \"account_data\": {\n \"events\": [\n {\n \"type\": \"m.direct\",\n \"content\": {\n \"@jay:post.hyrule.cc\": [\n \"!gGpGMWeoEhhMMaWdGT:post.hyrule.cc\"\n ]\n }\n },\n {\n \"type\": \"m.secret_storage.key.qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\",\n \"content\": {\n \"algorithm\": \"m.secret_storage.v1.aes-hmac-sha2\",\n \"passphrase\": {\n \"algorithm\": \"m.pbkdf2\",\n \"iterations\": 500000,\n \"salt\": \"yluvcuEslWDOoGjx0kdSpL6XypugFAlF\"\n },\n \"iv\": \"r44S20rG0vYHmS/1f9JE8A==\",\n \"mac\": \"0hJUMdPcwfFsUcAD3J4GrbTIbW+f52lbOmTxzEewvYE=\"\n }\n },\n {\n \"type\": \"m.secret_storage.default_key\",\n \"content\": {\n \"key\": \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\"\n }\n },\n {\n \"type\": \"m.cross_signing.master\",\n \"content\": {\n \"encrypted\": {\n \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\": {\n \"iv\": \"7ghVcptd3VhhfI4b/u17qg==\",\n \"ciphertext\": \"GuyMsI+roUkAfVxZPFOuKTWNuEAkb1CKQ8/VnYVUcJ25F4qHiG0xaaKP4kQ=\",\n \"mac\": \"KvqtwcOy73HCHYem1Oy7+KxUBvu+rw2+XnOPyzpozSc=\"\n }\n }\n }\n },\n {\n \"type\": \"m.cross_signing.self_signing\",\n \"content\": {\n \"encrypted\": {\n \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\": {\n \"iv\": \"qWmjLCQyLGp1Jg7fAMh5lw==\",\n \"ciphertext\": \"mKc9wkV93IhwDWjuB1hPfR5VRuQiFVe+pF+BDZBoEJxOjxRJwXTgs/sXbAc=\",\n \"mac\": \"jaoUtwZGVA1nPP2dySZP0YSDb+QkfeWVqG3BHiNuH60=\"\n }\n }\n }\n },\n {\n \"type\": \"m.cross_signing.user_signing\",\n \"content\": {\n \"encrypted\": {\n \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\": {\n \"iv\": \"lUCmom8R9UEJi6YGFgHESA==\",\n \"ciphertext\": \"vFIpV/NUohPu+G9iWtOi57jbRjWjhNBjS91rdkKolypaMuuOba9C8CjDD+s=\",\n \"mac\": \"5jdCXMplGXv2ufQKS6GEW+16mgaXGGKuThkPJ1qjubk=\"\n }\n }\n }\n },\n {\n \"type\": \"m.megolm_backup.v1\",\n \"content\": {\n \"encrypted\": {\n \"qAQTfRWJpnqBn92JsgmzImEZoEq5I81L\": {\n \"iv\": \"fiiaOiPwdC4UOgN0z8cujQ==\",\n \"ciphertext\": \"iT1CWwcGw6hRp343hFx00vIGyTDDSsvqCCVOEsU58N5WtQ3K7ilkIJ7xgrU=\",\n \"mac\": \"FgmKjel+mKt7gSlV0zqejfC9VMB+N5v02uv5v49ME74=\"\n }\n }\n }\n },\n {\n \"type\": \"im.vector.setting.breadcrumbs\",\n \"content\": {\n \"recent_rooms\": [\n \"!iEOZzedJhdJtozSkCK:post.hyrule.cc\",\n \"!OdeSTaDBtVXdpAAVue:post.hyrule.cc\",\n \"!gGpGMWeoEhhMMaWdGT:post.hyrule.cc\"\n ]\n }\n },\n {\n \"type\": \"im.vector.web.settings\",\n \"content\": {\n \"theme\": \"light\",\n \"useCompactLayout\": true\n }\n },\n {\n \"type\": \"m.push_rules\",\n \"content\": {\n \"global\": {\n \"underride\": [\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.call.invite\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"ring\"\n },\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.call\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"room_member_count\",\n \"is\": \"2\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.message\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.room_one_to_one\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"room_member_count\",\n \"is\": \"2\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.encrypted\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.encrypted_room_one_to_one\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.message\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.message\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.encrypted\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.encrypted\",\n \"default\": true,\n \"enabled\": true\n }\n ],\n \"sender\": [],\n \"room\": [],\n \"content\": [\n {\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\"\n }\n ],\n \"pattern\": \"claire\",\n \"rule_id\": \".m.rule.contains_user_name\",\n \"default\": true,\n \"enabled\": true\n }\n ],\n \"override\": [\n {\n \"conditions\": [],\n \"actions\": [\n \"dont_notify\"\n ],\n \"rule_id\": \".m.rule.master\",\n \"default\": true,\n \"enabled\": false\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"content.msgtype\",\n \"pattern\": \"m.notice\"\n }\n ],\n \"actions\": [\n \"dont_notify\"\n ],\n \"rule_id\": \".m.rule.suppress_notices\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.member\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"content.membership\",\n \"pattern\": \"invite\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"state_key\",\n \"pattern\": \"@claire:post.hyrule.cc\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\",\n \"value\": false\n }\n ],\n \"rule_id\": \".m.rule.invite_for_me\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.member\"\n }\n ],\n \"actions\": [\n \"dont_notify\"\n ],\n \"rule_id\": \".m.rule.member_event\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"contains_display_name\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"sound\",\n \"value\": \"default\"\n },\n {\n \"set_tweak\": \"highlight\"\n }\n ],\n \"rule_id\": \".m.rule.contains_display_name\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"content.body\",\n \"pattern\": \"@room\"\n },\n {\n \"kind\": \"sender_notification_permission\",\n \"key\": \"room\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"highlight\",\n \"value\": true\n }\n ],\n \"rule_id\": \".m.rule.roomnotif\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.room.tombstone\"\n },\n {\n \"kind\": \"event_match\",\n \"key\": \"state_key\",\n \"pattern\": \"\"\n }\n ],\n \"actions\": [\n \"notify\",\n {\n \"set_tweak\": \"highlight\",\n \"value\": true\n }\n ],\n \"rule_id\": \".m.rule.tombstone\",\n \"default\": true,\n \"enabled\": true\n },\n {\n \"conditions\": [\n {\n \"kind\": \"event_match\",\n \"key\": \"type\",\n \"pattern\": \"m.reaction\"\n }\n ],\n \"actions\": [\n \"dont_notify\"\n ],\n \"rule_id\": \".m.rule.reaction\",\n \"default\": true,\n \"enabled\": true\n }\n ]\n },\n \"device\": {}\n }\n }\n ]\n },\n \"to_device\": {\n \"events\": []\n },\n \"device_lists\": {\n \"changed\": [],\n \"left\": []\n },\n \"presence\": {\n \"events\": [\n {\n \"type\": \"m.presence\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"presence\": \"online\",\n \"last_active_ago\": 444,\n \"currently_active\": true\n }\n }\n ]\n },\n \"rooms\": {\n \"join\": {\n \"!iEOZzedJhdJtozSkCK:post.hyrule.cc\": {\n \"timeline\": {\n \"events\": [\n {\n \"type\": \"m.room.create\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"room_version\": \"5\",\n \"creator\": \"@claire:post.hyrule.cc\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360971618,\n \"unsigned\": {\n \"age\": 324856016\n },\n \"event_id\": \"$sJ6OYdOkSDVmOAngZcufVYZeKaq8MN3tL8Uhk3kbL_c\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\",\n \"avatar_url\": \"mxc://post.hyrule.cc/RKdIOiYvQEBkutEikNQcvywz\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592360972137,\n \"unsigned\": {\n \"age\": 324855497\n },\n \"event_id\": \"$ZSrKxxwepzaisqJf0Y1QLJnHPIYaZNPsXT2xfd3YV1k\"\n },\n {\n \"type\": \"m.room.power_levels\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"users\": {\n \"@claire:post.hyrule.cc\": 100\n },\n \"users_default\": 0,\n \"events\": {\n \"m.room.name\": 50,\n \"m.room.power_levels\": 100,\n \"m.room.history_visibility\": 100,\n \"m.room.canonical_alias\": 50,\n \"m.room.avatar\": 50,\n \"m.room.tombstone\": 100,\n \"m.room.server_acl\": 100,\n \"m.room.encryption\": 100\n },\n \"events_default\": 0,\n \"state_default\": 50,\n \"ban\": 50,\n \"kick\": 50,\n \"redact\": 50,\n \"invite\": 50\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360972461,\n \"unsigned\": {\n \"age\": 324855173\n },\n \"event_id\": \"$LhWiDPlk5TeqdgkmofJi6qwWcynUqEs82vWLFHRKLjg\"\n },\n {\n \"type\": \"m.room.canonical_alias\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"alias\": \"#nerdsonly:post.hyrule.cc\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360972898,\n \"unsigned\": {\n \"age\": 324854736\n },\n \"event_id\": \"$ryY_eCI5Dg9dyOKIRxtz0xmbFMiMXfkCkfYg39E3V3c\"\n },\n {\n \"type\": \"m.room.join_rules\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"join_rule\": \"public\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360973257,\n \"unsigned\": {\n \"age\": 324854377\n },\n \"event_id\": \"$zWqD4UJq9EJDVlxqdekQiPOwWXb0vIa7U6xH9XNggpY\"\n },\n {\n \"type\": \"m.room.history_visibility\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"history_visibility\": \"shared\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360973745,\n \"unsigned\": {\n \"age\": 324853889\n },\n \"event_id\": \"$mAHuhlSnmIUwxwD4zayTSp-6oFPLKO2_uzT5ar24AtU\"\n },\n {\n \"type\": \"m.room.name\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"name\": \"Nerdy Stuff\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360974424,\n \"unsigned\": {\n \"age\": 324853210\n },\n \"event_id\": \"$4-5nBvrGqbIvk05opUCrMvgUNq20V-Jy04QFOrFJ7Rg\"\n },\n {\n \"type\": \"m.room.topic\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"topic\": \"A public channel for nerdy stuff\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1592360974886,\n \"unsigned\": {\n \"age\": 324852748\n },\n \"event_id\": \"$DvvyuvuhdoehJGW0-tY_H8vWbI9hjR-wd_q0j1G9I80\"\n }\n ],\n \"prev_batch\": \"s84_3821_0_57_1_1_17_86_1\",\n \"limited\": false\n },\n \"state\": {\n \"events\": []\n },\n \"account_data\": {\n \"events\": [\n {\n \"type\": \"m.fully_read\",\n \"content\": {\n \"event_id\": \"$DvvyuvuhdoehJGW0-tY_H8vWbI9hjR-wd_q0j1G9I80\"\n }\n }\n ]\n },\n \"ephemeral\": {\n \"events\": []\n },\n \"unread_notifications\": {},\n \"summary\": {}\n },\n \"!gGpGMWeoEhhMMaWdGT:post.hyrule.cc\": {\n \"timeline\": {\n \"events\": [\n {\n \"type\": \"m.call.candidates\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"version\": 0,\n \"call_id\": \"c15919060032180.7748147521165045\",\n \"candidates\": [\n {\n \"candidate\": \"candidate:4273728266 1 udp 2122260223 192.168.1.125 54952 typ host generation 0 ufrag iyrH network-id 1 network-cost 10\",\n \"sdpMid\": \"0\",\n \"sdpMLineIndex\": 0\n },\n {\n \"candidate\": \"candidate:4273728266 1 udp 2122260223 192.168.1.125 45335 typ host generation 0 ufrag iyrH network-id 1 network-cost 10\",\n \"sdpMid\": \"1\",\n \"sdpMLineIndex\": 1\n },\n {\n \"candidate\": \"candidate:2956466170 1 tcp 1518280447 192.168.1.125 9 typ host tcptype active generation 0 ufrag iyrH network-id 1 network-cost 10\",\n \"sdpMid\": \"0\",\n \"sdpMLineIndex\": 0\n },\n {\n \"candidate\": \"candidate:2956466170 1 tcp 1518280447 192.168.1.125 9 typ host tcptype active generation 0 ufrag iyrH network-id 1 network-cost 10\",\n \"sdpMid\": \"1\",\n \"sdpMLineIndex\": 1\n }\n ]\n },\n \"origin_server_ts\": 1591906006145,\n \"unsigned\": {\n \"age\": 779821489\n },\n \"event_id\": \"$kdssQDx48gI4Xj9e8RPOoMDE28fTNCPN9Al7zzSdlxo\"\n },\n {\n \"type\": \"m.call.hangup\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"version\": 0,\n \"call_id\": \"c15919060032180.7748147521165045\",\n \"reason\": \"invite_timeout\"\n },\n \"origin_server_ts\": 1591906066189,\n \"unsigned\": {\n \"age\": 779761445\n },\n \"event_id\": \"$ORezi_OqdVHh5Y2u-SSsmc4q4NgrOk4keMsOSy-9GfU\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"test\"\n },\n \"origin_server_ts\": 1591910069654,\n \"unsigned\": {\n \"age\": 775757980\n },\n \"event_id\": \"$XMp7Ha2MxfteVmqlmlJk684BdoFZapPFIz0kdpJY8pc\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\",\n \"avatar_url\": \"mxc://post.hyrule.cc/SJvUBWJQkhzpOtGWMAaEAgAj\"\n },\n \"state_key\": \"@jay:post.hyrule.cc\",\n \"origin_server_ts\": 1592019802207,\n \"unsigned\": {\n \"replaces_state\": \"$kulF3B0iVmAHky2EbHJxvmGK8HlcBMolcJN2bpPSuvo\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\"\n },\n \"prev_sender\": \"@jay:post.hyrule.cc\",\n \"age\": 666025427\n },\n \"event_id\": \"$fDB3EP_IPyrTT4L_QfgX0L7mDAWMZepceMkK5qBvBjE\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592020047819,\n \"unsigned\": {\n \"replaces_state\": \"$aWTER7_eLhOTDphn5qun81Yv5pXMdF-9tk880d0HQxw\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"claire\"\n },\n \"prev_sender\": \"@claire:post.hyrule.cc\",\n \"age\": 665779815\n },\n \"event_id\": \"$7jPKVQpUKSYdyJCmLRRho-GMmE5zoR_cDJUJIrv17fo\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\",\n \"avatar_url\": \"mxc://post.hyrule.cc/RKdIOiYvQEBkutEikNQcvywz\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592020049836,\n \"unsigned\": {\n \"replaces_state\": \"$7jPKVQpUKSYdyJCmLRRho-GMmE5zoR_cDJUJIrv17fo\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\"\n },\n \"prev_sender\": \"@claire:post.hyrule.cc\",\n \"age\": 665777798\n },\n \"event_id\": \"$ukskv7VzBOPFv8K44K6HVlmW0TM7ZpLmkaLwn-kJqfQ\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"butts\"\n },\n \"origin_server_ts\": 1592020103438,\n \"unsigned\": {\n \"age\": 665724196\n },\n \"event_id\": \"$tfxzWv0dJxLPDt4kTj91kQfRFyggrqNZLu6fR78d-B0\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"From now on, it'll be with your new avatar\"\n },\n \"origin_server_ts\": 1592020103711,\n \"unsigned\": {\n \"age\": 665723923\n },\n \"event_id\": \"$p3k4jtfejod6tZMWdecAMSttQNzkKRSTaZJCtOU8hAs\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"this is neat\"\n },\n \"origin_server_ts\": 1592020107312,\n \"unsigned\": {\n \"age\": 665720322\n },\n \"event_id\": \"$c2LQnx63ME0JELRdCOwuJG2BINSxatcT82KNN7iPPrE\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"butts butts butts\"\n },\n \"origin_server_ts\": 1592020109549,\n \"unsigned\": {\n \"age\": 665718085\n },\n \"event_id\": \"$RJ1iJAKhVxH28SxHLToYTHVThCcoM2h_FZyAAIUdOl4\"\n }\n ],\n \"prev_batch\": \"t13-19_3821_0_57_1_1_17_86_1\",\n \"limited\": true\n },\n \"state\": {\n \"events\": [\n {\n \"type\": \"m.room.guest_access\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"guest_access\": \"can_join\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901096163,\n \"unsigned\": {\n \"age\": 784731471\n },\n \"event_id\": \"$tVrzSLRrGmiqrhcFAIRxK0bqsMeD4xjo3D7fpgupqTs\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"claire\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1591905639351,\n \"unsigned\": {\n \"replaces_state\": \"$rAIEXypyyC_2eaAZ11VtKvD8qWwTD6px4H8xGiZuaD8\",\n \"prev_content\": {\n \"is_direct\": true,\n \"membership\": \"invite\",\n \"displayname\": \"claire\"\n },\n \"prev_sender\": \"@jay:post.hyrule.cc\",\n \"age\": 780188283\n },\n \"event_id\": \"$aWTER7_eLhOTDphn5qun81Yv5pXMdF-9tk880d0HQxw\"\n },\n {\n \"type\": \"m.room.history_visibility\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"history_visibility\": \"shared\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901095658,\n \"unsigned\": {\n \"age\": 784731976\n },\n \"event_id\": \"$7jCQJmcP0vydaXmYq-7hLytW1IvdlwSHDMdztv-4Aq4\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\"\n },\n \"state_key\": \"@jay:post.hyrule.cc\",\n \"origin_server_ts\": 1591901094466,\n \"unsigned\": {\n \"age\": 784733168\n },\n \"event_id\": \"$kulF3B0iVmAHky2EbHJxvmGK8HlcBMolcJN2bpPSuvo\"\n },\n {\n \"type\": \"m.room.create\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"room_version\": \"5\",\n \"creator\": \"@jay:post.hyrule.cc\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901093918,\n \"unsigned\": {\n \"age\": 784733716\n },\n \"event_id\": \"$ub2hvdrBC8z-LAH0b-cVOahuegTrQRCWkeCz91SaHUA\"\n },\n {\n \"type\": \"m.room.join_rules\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"join_rule\": \"invite\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901095203,\n \"unsigned\": {\n \"age\": 784732431\n },\n \"event_id\": \"$XdaCM5_AumDDtWiAHdfscyLOKzIUBb_ZbkilEfvo4UU\"\n },\n {\n \"type\": \"m.room.power_levels\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"users\": {\n \"@jay:post.hyrule.cc\": 100,\n \"@claire:post.hyrule.cc\": 100\n },\n \"users_default\": 0,\n \"events\": {\n \"m.room.name\": 50,\n \"m.room.power_levels\": 100,\n \"m.room.history_visibility\": 100,\n \"m.room.canonical_alias\": 50,\n \"m.room.avatar\": 50,\n \"m.room.tombstone\": 100,\n \"m.room.server_acl\": 100,\n \"m.room.encryption\": 100\n },\n \"events_default\": 0,\n \"state_default\": 50,\n \"ban\": 50,\n \"kick\": 50,\n \"redact\": 50,\n \"invite\": 0\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591901094797,\n \"unsigned\": {\n \"age\": 784732837\n },\n \"event_id\": \"$8EOZ273lTw-8ocwRM4f_1pjQhY9coCqdEe3cjO11P1A\"\n }\n ]\n },\n \"account_data\": {\n \"events\": [\n {\n \"type\": \"m.fully_read\",\n \"content\": {\n \"event_id\": \"$RJ1iJAKhVxH28SxHLToYTHVThCcoM2h_FZyAAIUdOl4\"\n }\n }\n ]\n },\n \"ephemeral\": {\n \"events\": [\n {\n \"type\": \"m.receipt\",\n \"content\": {\n \"$c2LQnx63ME0JELRdCOwuJG2BINSxatcT82KNN7iPPrE\": {\n \"m.read\": {\n \"@jay:post.hyrule.cc\": {\n \"ts\": 1592020107783\n }\n }\n },\n \"$RJ1iJAKhVxH28SxHLToYTHVThCcoM2h_FZyAAIUdOl4\": {\n \"m.read\": {\n \"@claire:post.hyrule.cc\": {\n \"ts\": 1592020662042\n }\n }\n }\n }\n }\n ]\n },\n \"unread_notifications\": {\n \"notification_count\": 0,\n \"highlight_count\": 0\n },\n \"summary\": {}\n },\n \"!OdeSTaDBtVXdpAAVue:post.hyrule.cc\": {\n \"timeline\": {\n \"events\": [\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"the UI is just enormous by comparison\"\n },\n \"origin_server_ts\": 1591907739492,\n \"unsigned\": {\n \"age\": 778088142\n },\n \"event_id\": \"$F3SebL9S7ndGf0kEtD-_O7VNrCJTv7Xrj2187mYyTp0\"\n },\n {\n \"type\": \"m.room.redaction\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {},\n \"redacts\": \"$8CpoHVMQjW6idnAXbM_AqF2cpNCZOfcNrf1y7g1pgIc\",\n \"origin_server_ts\": 1591907782723,\n \"unsigned\": {\n \"age\": 778044911\n },\n \"event_id\": \"$YjvBCC-IzXY1Vn67PHG9ZHflmUsOjKkUOjbUZBSSj7I\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"body\": \"image.png\",\n \"info\": {\n \"size\": 96883,\n \"mimetype\": \"image/png\",\n \"thumbnail_info\": {\n \"w\": 800,\n \"h\": 458,\n \"mimetype\": \"image/png\",\n \"size\": 74584\n },\n \"w\": 1280,\n \"h\": 733,\n \"thumbnail_url\": \"mxc://post.hyrule.cc/vcTfUvRQUHlYtygbQTwEZRUL\"\n },\n \"msgtype\": \"m.image\",\n \"url\": \"mxc://post.hyrule.cc/yrlNZxoteIwWLrkxbsgopLiD\"\n },\n \"origin_server_ts\": 1591907787861,\n \"unsigned\": {\n \"age\": 778039773\n },\n \"event_id\": \"$gtp3cFyjM0NoEAPk8oh0CpW-5wx9YNhua_p2ZBALW9c\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\",\n \"avatar_url\": \"mxc://post.hyrule.cc/SJvUBWJQkhzpOtGWMAaEAgAj\"\n },\n \"state_key\": \"@jay:post.hyrule.cc\",\n \"origin_server_ts\": 1592019801698,\n \"unsigned\": {\n \"replaces_state\": \"$xSq70WplyPage-bR3NcHq4gAEIT-8he0ngu88jr2exU\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\"\n },\n \"prev_sender\": \"@jay:post.hyrule.cc\",\n \"age\": 666025936\n },\n \"event_id\": \"$a2jE7MKG4jQ_-rx6szaayBcIQTO-TNvzvJsZ0qDPUns\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592020047301,\n \"unsigned\": {\n \"replaces_state\": \"$NOkbQMy6nma818erRg31Adh6rVYZXBqclivbKo-4EpY\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"claire\"\n },\n \"prev_sender\": \"@claire:post.hyrule.cc\",\n \"age\": 665780333\n },\n \"event_id\": \"$kcD7ljDlfYOBJYkj-ETsci6mceaKFX83W5ogXDD_qmI\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\",\n \"avatar_url\": \"mxc://post.hyrule.cc/RKdIOiYvQEBkutEikNQcvywz\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1592020049343,\n \"unsigned\": {\n \"replaces_state\": \"$kcD7ljDlfYOBJYkj-ETsci6mceaKFX83W5ogXDD_qmI\",\n \"prev_content\": {\n \"membership\": \"join\",\n \"displayname\": \"Claire\"\n },\n \"prev_sender\": \"@claire:post.hyrule.cc\",\n \"age\": 665778291\n },\n \"event_id\": \"$i-Eyg2S9JhtKIjRgzp5GWGN6hVvDjdJ1_KknHW_XS7Q\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"hi\"\n },\n \"origin_server_ts\": 1592021022525,\n \"unsigned\": {\n \"age\": 664805109\n },\n \"event_id\": \"$78MKiI5wXFlCirtLkpe_BnQH_DcB5q8sXvcHDbzXhZI\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"haha you can't press enter to send a message\"\n },\n \"origin_server_ts\": 1592021034633,\n \"unsigned\": {\n \"age\": 664793001\n },\n \"event_id\": \"$g8gXjqKM7XWZV1t_d5cYyYDEPCzczWVpbUgEpjiR8Y4\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"test]\"\n },\n \"origin_server_ts\": 1592021081708,\n \"unsigned\": {\n \"age\": 664745926\n },\n \"event_id\": \"$H1m50rEleK2tEWmY7-dTdEPlUT46lljQuIUvXkw-rjo\"\n },\n {\n \"type\": \"m.room.message\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"msgtype\": \"m.text\",\n \"body\": \"eyyy it worked\"\n },\n \"origin_server_ts\": 1592021085433,\n \"unsigned\": {\n \"age\": 664742201\n },\n \"event_id\": \"$hwk9J-XRURGRvVu8EfIM6yIs7oTJX4RHjgsC89L7oXI\"\n }\n ],\n \"prev_batch\": \"t44-58_3821_0_57_1_1_17_86_1\",\n \"limited\": true\n },\n \"state\": {\n \"events\": [\n {\n \"type\": \"m.room.history_visibility\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"history_visibility\": \"shared\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905971725,\n \"unsigned\": {\n \"age\": 779855909\n },\n \"event_id\": \"$h8jIhCdFIGavE_N-_B1PcMxMIzs3PAatR_P2lzKgr8M\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@jay:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"jay\"\n },\n \"state_key\": \"@jay:post.hyrule.cc\",\n \"origin_server_ts\": 1591907265464,\n \"unsigned\": {\n \"replaces_state\": \"$QAt6I0pTligtc3MOq0fEA4zDMoFaqldG9FkYhEOxp-I\",\n \"age\": 778562170\n },\n \"event_id\": \"$xSq70WplyPage-bR3NcHq4gAEIT-8he0ngu88jr2exU\"\n },\n {\n \"type\": \"m.room.power_levels\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"users\": {\n \"@claire:post.hyrule.cc\": 100\n },\n \"users_default\": 0,\n \"events\": {\n \"m.room.name\": 50,\n \"m.room.power_levels\": 100,\n \"m.room.history_visibility\": 100,\n \"m.room.canonical_alias\": 50,\n \"m.room.avatar\": 50,\n \"m.room.tombstone\": 100,\n \"m.room.server_acl\": 100,\n \"m.room.encryption\": 100\n },\n \"events_default\": 0,\n \"state_default\": 50,\n \"ban\": 50,\n \"kick\": 50,\n \"redact\": 50,\n \"invite\": 50\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905970691,\n \"unsigned\": {\n \"age\": 779856943\n },\n \"event_id\": \"$ILYd8-lWb3vpTyeAm73CAs_Dm3GCyXeJDwM4pgDmt9w\"\n },\n {\n \"type\": \"m.room.member\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"membership\": \"join\",\n \"displayname\": \"claire\"\n },\n \"state_key\": \"@claire:post.hyrule.cc\",\n \"origin_server_ts\": 1591905970349,\n \"unsigned\": {\n \"age\": 779857285\n },\n \"event_id\": \"$NOkbQMy6nma818erRg31Adh6rVYZXBqclivbKo-4EpY\"\n },\n {\n \"type\": \"m.room.join_rules\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"join_rule\": \"public\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905971142,\n \"unsigned\": {\n \"age\": 779856492\n },\n \"event_id\": \"$zUSAikyCKbhOfIl0cWb4y8bI8wHWLZhIlelP8BLmBPM\"\n },\n {\n \"type\": \"m.room.name\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"name\": \"boobs\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905972652,\n \"unsigned\": {\n \"age\": 779854982\n },\n \"event_id\": \"$n0A5l9t5_zgy8vlkSBQP3cJbwej3ENW1LckBSW_QxvU\"\n },\n {\n \"type\": \"m.room.create\",\n \"sender\": \"@claire:post.hyrule.cc\",\n \"content\": {\n \"room_version\": \"5\",\n \"creator\": \"@claire:post.hyrule.cc\"\n },\n \"state_key\": \"\",\n \"origin_server_ts\": 1591905969834,\n \"unsigned\": {\n \"age\": 779857800\n },\n \"event_id\": \"$ukewPt_m8GLbjjB529a1i6mLjOm3YLox1zan0tJr9yU\"\n }\n ]\n },\n \"account_data\": {\n \"events\": [\n {\n \"type\": \"m.fully_read\",\n \"content\": {\n \"event_id\": \"$hwk9J-XRURGRvVu8EfIM6yIs7oTJX4RHjgsC89L7oXI\"\n }\n }\n ]\n },\n \"ephemeral\": {\n \"events\": [\n {\n \"type\": \"m.receipt\",\n \"content\": {\n \"$hwk9J-XRURGRvVu8EfIM6yIs7oTJX4RHjgsC89L7oXI\": {\n \"m.read\": {\n \"@jay:post.hyrule.cc\": {\n \"ts\": 1592021102633\n }\n }\n },\n \"$g8gXjqKM7XWZV1t_d5cYyYDEPCzczWVpbUgEpjiR8Y4\": {\n \"m.read\": {\n \"@claire:post.hyrule.cc\": {\n \"ts\": 1592071800533\n }\n }\n }\n }\n }\n ]\n },\n \"unread_notifications\": {\n \"notification_count\": 0,\n \"highlight_count\": 0\n },\n \"summary\": {}\n }\n },\n \"invite\": {},\n \"leave\": {}\n },\n \"groups\": {\n \"join\": {},\n \"invite\": {},\n \"leave\": {}\n },\n \"device_one_time_keys_count\": {},\n \"next_batch\": \"s84_3821_0_57_1_1_17_86_1\"\n}"; + + dynamic d = JObject.Parse(txt); + + JObject obj = d.rooms.join; + + JEnumerable kids = obj.Children(); + + foreach (JProperty kid in kids) + { + Console.WriteLine(kid.Name); + Console.WriteLine(kid.Value); + } + + //Console.WriteLine(d.rooms.join["!gGpGMWeoEhhMMaWdGT:post.hyrule.cc"].timeline.events); +} + +// Define other methods and classes here +public class MatrixSyncBody +{ + public MatrixSyncRooms Rooms { get; set; } +} + +public class MatrixSyncRooms +{ + // once the JSON from "join" is parsed, this is set to its contents as an object + public Dictionary Joined { get; private set;} + + public JObject Join + { + get { return null; } + set + { + // takes JSON children and parses them into objects + // we have to do this bc the entity names under "join" are dynamic + // each entity holds a well-defined object though + + // these AREN'T an array + ParseRooms(value); + } + } + + public void ParseRooms(JObject roomsJson) + { + // get the children of this object + } +} + +public class MatrixSyncRoom +{ + public MatrixTimeline Timeline { get; set; } +} + +public class MatrixTimeline +{ + public MatrixEvent[] Events { get; set; } + + [JsonProperty("prev_batch")] + public string PreviousBatch { get; set; } + + public bool IsLimited { get; set; } +} + +public class MatrixEvent +{ + public string EventType { get; set; } +} \ No newline at end of file