diff options
Diffstat (limited to 'vendor/maunium.net/go/mautrix')
-rw-r--r-- | vendor/maunium.net/go/mautrix/.gitignore | 2 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/LICENSE | 201 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/README.md | 4 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/client.go | 796 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/events.go | 438 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/filter.go | 90 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/format/htmlparser.go | 257 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/format/markdown.go | 38 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/reply.go | 97 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/requests.go | 82 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/responses.go | 182 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/room.go | 44 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/store.go | 65 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/sync.go | 159 | ||||
-rw-r--r-- | vendor/maunium.net/go/mautrix/userids.go | 130 |
15 files changed, 0 insertions, 2585 deletions
diff --git a/vendor/maunium.net/go/mautrix/.gitignore b/vendor/maunium.net/go/mautrix/.gitignore deleted file mode 100644 index 66f8fb5..0000000 --- a/vendor/maunium.net/go/mautrix/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.idea/ -.vscode/ diff --git a/vendor/maunium.net/go/mautrix/LICENSE b/vendor/maunium.net/go/mautrix/LICENSE deleted file mode 100644 index 8dada3e..0000000 --- a/vendor/maunium.net/go/mautrix/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/maunium.net/go/mautrix/README.md b/vendor/maunium.net/go/mautrix/README.md deleted file mode 100644 index ca135a6..0000000 --- a/vendor/maunium.net/go/mautrix/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# mautrix-go -[![GoDoc](https://godoc.org/maunium.net/go/mautrix?status.svg)](https://godoc.org/maunium.net/go/mautrix) - -A Golang Matrix framework. diff --git a/vendor/maunium.net/go/mautrix/client.go b/vendor/maunium.net/go/mautrix/client.go deleted file mode 100644 index d908b62..0000000 --- a/vendor/maunium.net/go/mautrix/client.go +++ /dev/null @@ -1,796 +0,0 @@ -// Package mautrix implements the Matrix Client-Server API. -// -// Specification can be found at http://matrix.org/docs/spec/client_server/r0.4.0.html -package mautrix - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "path" - "strconv" - "strings" - "sync" - "time" -) - -type Logger interface { - Debugfln(message string, args ...interface{}) -} - -// Client represents a Matrix client. -type Client struct { - HomeserverURL *url.URL // The base homeserver URL - Prefix string // The API prefix eg '/_matrix/client/r0' - UserID string // The user ID of the client. Used for forming HTTP paths which use the client's user ID. - AccessToken string // The access_token for the client. - Client *http.Client // The underlying HTTP client which will be used to make HTTP requests. - Syncer Syncer // The thing which can process /sync responses - Store Storer // The thing which can store rooms/tokens/ids - Logger Logger - - // The ?user_id= query parameter for application services. This must be set *prior* to calling a method. If this is empty, - // no user_id parameter will be sent. - // See http://matrix.org/docs/spec/application_service/unstable.html#identity-assertion - AppServiceUserID string - - syncingMutex sync.Mutex // protects syncingID - syncingID uint32 // Identifies the current Sync. Only one Sync can be active at any given time. -} - -// HTTPError An HTTP Error response, which may wrap an underlying native Go Error. -type HTTPError struct { - WrappedError error - RespError *RespError - Message string - Code int -} - -func (e HTTPError) Error() string { - var wrappedErrMsg string - if e.WrappedError != nil { - wrappedErrMsg = e.WrappedError.Error() - } - return fmt.Sprintf("msg=%s code=%d wrapped=%s", e.Message, e.Code, wrappedErrMsg) -} - -// BuildURL builds a URL with the Client's homserver/prefix/access_token set already. -func (cli *Client) BuildURL(urlPath ...string) string { - ps := []string{cli.Prefix} - for _, p := range urlPath { - ps = append(ps, p) - } - return cli.BuildBaseURL(ps...) -} - -// BuildBaseURL builds a URL with the Client's homeserver/access_token set already. You must -// supply the prefix in the path. -func (cli *Client) BuildBaseURL(urlPath ...string) string { - // copy the URL. Purposefully ignore error as the input is from a valid URL already - hsURL, _ := url.Parse(cli.HomeserverURL.String()) - parts := []string{hsURL.Path} - parts = append(parts, urlPath...) - hsURL.Path = path.Join(parts...) - query := hsURL.Query() - if cli.AccessToken != "" { - query.Set("access_token", cli.AccessToken) - } - if cli.AppServiceUserID != "" { - query.Set("user_id", cli.AppServiceUserID) - } - hsURL.RawQuery = query.Encode() - return hsURL.String() -} - -// BuildURLWithQuery builds a URL with query parameters in addition to the Client's homeserver/prefix/access_token set already. -func (cli *Client) BuildURLWithQuery(urlPath []string, urlQuery map[string]string) string { - u, _ := url.Parse(cli.BuildURL(urlPath...)) - q := u.Query() - for k, v := range urlQuery { - q.Set(k, v) - } - u.RawQuery = q.Encode() - return u.String() -} - -// SetCredentials sets the user ID and access token on this client instance. -func (cli *Client) SetCredentials(userID, accessToken string) { - cli.AccessToken = accessToken - cli.UserID = userID -} - -// ClearCredentials removes the user ID and access token on this client instance. -func (cli *Client) ClearCredentials() { - cli.AccessToken = "" - cli.UserID = "" -} - -// Sync starts syncing with the provided Homeserver. If Sync() is called twice then the first sync will be stopped and the -// error will be nil. -// -// This function will block until a fatal /sync error occurs, so it should almost always be started as a new goroutine. -// Fatal sync errors can be caused by: -// - The failure to create a filter. -// - Client.Syncer.OnFailedSync returning an error in response to a failed sync. -// - Client.Syncer.ProcessResponse returning an error. -// If you wish to continue retrying in spite of these fatal errors, call Sync() again. -func (cli *Client) Sync() error { - // Mark the client as syncing. - // We will keep syncing until the syncing state changes. Either because - // Sync is called or StopSync is called. - syncingID := cli.incrementSyncingID() - nextBatch := cli.Store.LoadNextBatch(cli.UserID) - filterID := cli.Store.LoadFilterID(cli.UserID) - if filterID == "" { - filterJSON := cli.Syncer.GetFilterJSON(cli.UserID) - resFilter, err := cli.CreateFilter(filterJSON) - if err != nil { - return err - } - filterID = resFilter.FilterID - cli.Store.SaveFilterID(cli.UserID, filterID) - } - for { - resSync, err := cli.SyncRequest(30000, nextBatch, filterID, false, "") - if err != nil { - duration, err2 := cli.Syncer.OnFailedSync(resSync, err) - if err2 != nil { - return err2 - } - time.Sleep(duration) - continue - } - - // Check that the syncing state hasn't changed - // Either because we've stopped syncing or another sync has been started. - // We discard the response from our sync. - if cli.getSyncingID() != syncingID { - return nil - } - - // Save the token now *before* processing it. This means it's possible - // to not process some events, but it means that we won't get constantly stuck processing - // a malformed/buggy event which keeps making us panic. - cli.Store.SaveNextBatch(cli.UserID, resSync.NextBatch) - if err = cli.Syncer.ProcessResponse(resSync, nextBatch); err != nil { - return err - } - - nextBatch = resSync.NextBatch - } -} - -func (cli *Client) incrementSyncingID() uint32 { - cli.syncingMutex.Lock() - defer cli.syncingMutex.Unlock() - cli.syncingID++ - return cli.syncingID -} - -func (cli *Client) getSyncingID() uint32 { - cli.syncingMutex.Lock() - defer cli.syncingMutex.Unlock() - return cli.syncingID -} - -// StopSync stops the ongoing sync started by Sync. -func (cli *Client) StopSync() { - // Advance the syncing state so that any running Syncs will terminate. - cli.incrementSyncingID() -} - -func (cli *Client) LogRequest(req *http.Request, body string) { - if cli.Logger == nil { - return - } - - cli.Logger.Debugfln("%s %s %s", req.Method, req.URL.Path, body) -} - -// MakeRequest makes a JSON HTTP request to the given URL. -// If "resBody" is not nil, the response body will be json.Unmarshalled into it. -// -// Returns the HTTP body as bytes on 2xx with a nil error. Returns an error if the response is not 2xx along -// with the HTTP body bytes if it got that far. This error is an HTTPError which includes the returned -// HTTP status code and possibly a RespError as the WrappedError, if the HTTP body could be decoded as a RespError. -func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{}, resBody interface{}) ([]byte, error) { - var req *http.Request - var err error - logBody := "{}" - if reqBody != nil { - var jsonStr []byte - jsonStr, err = json.Marshal(reqBody) - if err != nil { - return nil, err - } - logBody = string(jsonStr) - req, err = http.NewRequest(method, httpURL, bytes.NewBuffer(jsonStr)) - } else { - req, err = http.NewRequest(method, httpURL, nil) - } - - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/json") - cli.LogRequest(req, logBody) - res, err := cli.Client.Do(req) - if res != nil { - defer res.Body.Close() - } - if err != nil { - return nil, err - } - contents, err := ioutil.ReadAll(res.Body) - if res.StatusCode/100 != 2 { // not 2xx - var wrap error - respErr := &RespError{} - if _ = json.Unmarshal(contents, respErr); respErr.ErrCode != "" { - wrap = respErr - } else { - respErr = nil - } - - // If we failed to decode as RespError, don't just drop the HTTP body, include it in the - // HTTP error instead (e.g proxy errors which return HTML). - msg := "Failed to " + method + " JSON to " + req.URL.Path - if wrap == nil { - msg = msg + ": " + string(contents) - } - - return contents, HTTPError{ - Code: res.StatusCode, - Message: msg, - WrappedError: wrap, - RespError: respErr, - } - } - if err != nil { - return nil, err - } - - if resBody != nil { - if err = json.Unmarshal(contents, &resBody); err != nil { - return nil, err - } - } - - return contents, nil -} - -// CreateFilter makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-user-userid-filter -func (cli *Client) CreateFilter(filter json.RawMessage) (resp *RespCreateFilter, err error) { - urlPath := cli.BuildURL("user", cli.UserID, "filter") - _, err = cli.MakeRequest("POST", urlPath, &filter, &resp) - return -} - -// SyncRequest makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync -func (cli *Client) SyncRequest(timeout int, since, filterID string, fullState bool, setPresence string) (resp *RespSync, err error) { - query := map[string]string{ - "timeout": strconv.Itoa(timeout), - } - if since != "" { - query["since"] = since - } - if filterID != "" { - query["filter"] = filterID - } - if setPresence != "" { - query["set_presence"] = setPresence - } - if fullState { - query["full_state"] = "true" - } - urlPath := cli.BuildURLWithQuery([]string{"sync"}, query) - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -func (cli *Client) register(u string, req *ReqRegister) (resp *RespRegister, uiaResp *RespUserInteractive, err error) { - var bodyBytes []byte - bodyBytes, err = cli.MakeRequest("POST", u, req, nil) - if err != nil { - httpErr, ok := err.(HTTPError) - if !ok { // network error - return - } - if httpErr.Code == 401 { - // body should be RespUserInteractive, if it isn't, fail with the error - err = json.Unmarshal(bodyBytes, &uiaResp) - return - } - return - } - // body should be RespRegister - err = json.Unmarshal(bodyBytes, &resp) - return -} - -// Register makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register -// -// Registers with kind=user. For kind=guest, see RegisterGuest. -func (cli *Client) Register(req *ReqRegister) (*RespRegister, *RespUserInteractive, error) { - u := cli.BuildURL("register") - return cli.register(u, req) -} - -// RegisterGuest makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register -// with kind=guest. -// -// For kind=user, see Register. -func (cli *Client) RegisterGuest(req *ReqRegister) (*RespRegister, *RespUserInteractive, error) { - query := map[string]string{ - "kind": "guest", - } - u := cli.BuildURLWithQuery([]string{"register"}, query) - return cli.register(u, req) -} - -// RegisterDummy performs m.login.dummy registration according to https://matrix.org/docs/spec/client_server/r0.2.0.html#dummy-auth -// -// Only a username and password need to be provided on the ReqRegister struct. Most local/developer homeservers will allow registration -// this way. If the homeserver does not, an error is returned. -// -// This does not set credentials on the client instance. See SetCredentials() instead. -// -// res, err := cli.RegisterDummy(&mautrix.ReqRegister{ -// Username: "alice", -// Password: "wonderland", -// }) -// if err != nil { -// panic(err) -// } -// token := res.AccessToken -func (cli *Client) RegisterDummy(req *ReqRegister) (*RespRegister, error) { - res, uia, err := cli.Register(req) - if err != nil && uia == nil { - return nil, err - } - if uia != nil && uia.HasSingleStageFlow("m.login.dummy") { - req.Auth = struct { - Type string `json:"type"` - Session string `json:"session,omitempty"` - }{"m.login.dummy", uia.Session} - res, _, err = cli.Register(req) - if err != nil { - return nil, err - } - } - if res == nil { - return nil, fmt.Errorf("registration failed: does this server support m.login.dummy? ") - } - return res, nil -} - -// Login a user to the homeserver according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-login -// This does not set credentials on this client instance. See SetCredentials() instead. -func (cli *Client) Login(req *ReqLogin) (resp *RespLogin, err error) { - urlPath := cli.BuildURL("login") - _, err = cli.MakeRequest("POST", urlPath, req, &resp) - return -} - -// Logout the current user. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-logout -// This does not clear the credentials from the client instance. See ClearCredentials() instead. -func (cli *Client) Logout() (resp *RespLogout, err error) { - urlPath := cli.BuildURL("logout") - _, err = cli.MakeRequest("POST", urlPath, nil, &resp) - return -} - -// Versions returns the list of supported Matrix versions on this homeserver. See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-versions -func (cli *Client) Versions() (resp *RespVersions, err error) { - urlPath := cli.BuildBaseURL("_matrix", "client", "versions") - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -// JoinRoom joins the client to a room ID or alias. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-join-roomidoralias -// -// If serverName is specified, this will be added as a query param to instruct the homeserver to join via that server. If content is specified, it will -// be JSON encoded and used as the request body. -func (cli *Client) JoinRoom(roomIDorAlias, serverName string, content interface{}) (resp *RespJoinRoom, err error) { - var urlPath string - if serverName != "" { - urlPath = cli.BuildURLWithQuery([]string{"join", roomIDorAlias}, map[string]string{ - "server_name": serverName, - }) - } else { - urlPath = cli.BuildURL("join", roomIDorAlias) - } - _, err = cli.MakeRequest("POST", urlPath, content, &resp) - return -} - -// GetDisplayName returns the display name of the user from the specified MXID. See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-profile-userid-displayname -func (cli *Client) GetDisplayName(mxid string) (resp *RespUserDisplayName, err error) { - urlPath := cli.BuildURL("profile", mxid, "displayname") - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -// GetOwnDisplayName returns the user's display name. See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-profile-userid-displayname -func (cli *Client) GetOwnDisplayName() (resp *RespUserDisplayName, err error) { - urlPath := cli.BuildURL("profile", cli.UserID, "displayname") - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -// SetDisplayName sets the user's profile display name. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-profile-userid-displayname -func (cli *Client) SetDisplayName(displayName string) (err error) { - urlPath := cli.BuildURL("profile", cli.UserID, "displayname") - s := struct { - DisplayName string `json:"displayname"` - }{displayName} - _, err = cli.MakeRequest("PUT", urlPath, &s, nil) - return -} - -// GetAvatarURL gets the user's avatar URL. See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-profile-userid-avatar-url -func (cli *Client) GetAvatarURL() (url string, err error) { - urlPath := cli.BuildURL("profile", cli.UserID, "avatar_url") - s := struct { - AvatarURL string `json:"avatar_url"` - }{} - - _, err = cli.MakeRequest("GET", urlPath, nil, &s) - if err != nil { - return "", err - } - - return s.AvatarURL, nil -} - -// SetAvatarURL sets the user's avatar URL. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-profile-userid-avatar-url -func (cli *Client) SetAvatarURL(url string) (err error) { - urlPath := cli.BuildURL("profile", cli.UserID, "avatar_url") - s := struct { - AvatarURL string `json:"avatar_url"` - }{url} - _, err = cli.MakeRequest("PUT", urlPath, &s, nil) - if err != nil { - return err - } - - return nil -} - -// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid -// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal. -func (cli *Client) SendMessageEvent(roomID string, eventType EventType, contentJSON interface{}) (resp *RespSendEvent, err error) { - txnID := txnID() - urlPath := cli.BuildURL("rooms", roomID, "send", eventType.String(), txnID) - _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp) - return -} - -// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid -// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal. -func (cli *Client) SendMassagedMessageEvent(roomID string, eventType EventType, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) { - txnID := txnID() - urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "send", eventType.String(), txnID}, map[string]string{ - "ts": strconv.FormatInt(ts, 10), - }) - _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp) - return -} - -// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey -// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal. -func (cli *Client) SendStateEvent(roomID string, eventType EventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) { - urlPath := cli.BuildURL("rooms", roomID, "state", eventType.String(), stateKey) - _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp) - return -} - -// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey -// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal. -func (cli *Client) SendMassagedStateEvent(roomID string, eventType EventType, stateKey string, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) { - urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "state", eventType.String(), stateKey}, map[string]string{ - "ts": strconv.FormatInt(ts, 10), - }) - _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp) - return -} - -// SendText sends an m.room.message event into the given room with a msgtype of m.text -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-text -func (cli *Client) SendText(roomID, text string) (*RespSendEvent, error) { - return cli.SendMessageEvent(roomID, EventMessage, Content{ - MsgType: MsgText, - Body: text, - }) -} - -// SendImage sends an m.room.message event into the given room with a msgtype of m.image -// See https://matrix.org/docs/spec/client_server/r0.2.0.html#m-image -func (cli *Client) SendImage(roomID, body, url string) (*RespSendEvent, error) { - return cli.SendMessageEvent(roomID, EventMessage, Content{ - MsgType: MsgImage, - Body: body, - URL: url, - }) -} - -// SendVideo sends an m.room.message event into the given room with a msgtype of m.video -// See https://matrix.org/docs/spec/client_server/r0.2.0.html#m-video -func (cli *Client) SendVideo(roomID, body, url string) (*RespSendEvent, error) { - return cli.SendMessageEvent(roomID, EventMessage, Content{ - MsgType: MsgVideo, - Body: body, - URL: url, - }) -} - -// SendNotice sends an m.room.message event into the given room with a msgtype of m.notice -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-notice -func (cli *Client) SendNotice(roomID, text string) (*RespSendEvent, error) { - return cli.SendMessageEvent(roomID, EventMessage, Content{ - MsgType: MsgNotice, - Body: text, - }) -} - -// RedactEvent redacts the given event. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid -func (cli *Client) RedactEvent(roomID, eventID string, req *ReqRedact) (resp *RespSendEvent, err error) { - txnID := txnID() - urlPath := cli.BuildURL("rooms", roomID, "redact", eventID, txnID) - _, err = cli.MakeRequest("PUT", urlPath, req, &resp) - return -} - -// CreateRoom creates a new Matrix room. See https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom -// resp, err := cli.CreateRoom(&mautrix.ReqCreateRoom{ -// Preset: "public_chat", -// }) -// fmt.Println("Room:", resp.RoomID) -func (cli *Client) CreateRoom(req *ReqCreateRoom) (resp *RespCreateRoom, err error) { - urlPath := cli.BuildURL("createRoom") - _, err = cli.MakeRequest("POST", urlPath, req, &resp) - return -} - -// LeaveRoom leaves the given room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-leave -func (cli *Client) LeaveRoom(roomID string) (resp *RespLeaveRoom, err error) { - u := cli.BuildURL("rooms", roomID, "leave") - _, err = cli.MakeRequest("POST", u, struct{}{}, &resp) - return -} - -// ForgetRoom forgets a room entirely. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-forget -func (cli *Client) ForgetRoom(roomID string) (resp *RespForgetRoom, err error) { - u := cli.BuildURL("rooms", roomID, "forget") - _, err = cli.MakeRequest("POST", u, struct{}{}, &resp) - return -} - -// InviteUser invites a user to a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-invite -func (cli *Client) InviteUser(roomID string, req *ReqInviteUser) (resp *RespInviteUser, err error) { - u := cli.BuildURL("rooms", roomID, "invite") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// InviteUserByThirdParty invites a third-party identifier to a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#invite-by-third-party-id-endpoint -func (cli *Client) InviteUserByThirdParty(roomID string, req *ReqInvite3PID) (resp *RespInviteUser, err error) { - u := cli.BuildURL("rooms", roomID, "invite") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// KickUser kicks a user from a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-kick -func (cli *Client) KickUser(roomID string, req *ReqKickUser) (resp *RespKickUser, err error) { - u := cli.BuildURL("rooms", roomID, "kick") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// BanUser bans a user from a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-ban -func (cli *Client) BanUser(roomID string, req *ReqBanUser) (resp *RespBanUser, err error) { - u := cli.BuildURL("rooms", roomID, "ban") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// UnbanUser unbans a user from a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-unban -func (cli *Client) UnbanUser(roomID string, req *ReqUnbanUser) (resp *RespUnbanUser, err error) { - u := cli.BuildURL("rooms", roomID, "unban") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// UserTyping sets the typing status of the user. See https://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-typing-userid -func (cli *Client) UserTyping(roomID string, typing bool, timeout int64) (resp *RespTyping, err error) { - req := ReqTyping{Typing: typing, Timeout: timeout} - u := cli.BuildURL("rooms", roomID, "typing", cli.UserID) - _, err = cli.MakeRequest("PUT", u, req, &resp) - return -} - -func (cli *Client) SetPresence(status string) (err error) { - req := ReqPresence{Presence: status} - u := cli.BuildURL("presence", cli.UserID, "status") - _, err = cli.MakeRequest("PUT", u, req, nil) - return -} - -// StateEvent gets a single state event in a room. It will attempt to JSON unmarshal into the given "outContent" struct with -// the HTTP response body, or return an error. -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey -func (cli *Client) StateEvent(roomID string, eventType EventType, stateKey string, outContent interface{}) (err error) { - u := cli.BuildURL("rooms", roomID, "state", eventType.String(), stateKey) - _, err = cli.MakeRequest("GET", u, nil, outContent) - return -} - -// UploadLink uploads an HTTP URL and then returns an MXC URI. -func (cli *Client) UploadLink(link string) (*RespMediaUpload, error) { - res, err := cli.Client.Get(link) - if res != nil { - defer res.Body.Close() - } - if err != nil { - return nil, err - } - return cli.Upload(res.Body, res.Header.Get("Content-Type"), res.ContentLength) -} - -func (cli *Client) Download(mxcURL string) (io.ReadCloser, error) { - if !strings.HasPrefix(mxcURL, "mxc://") { - return nil, errors.New("invalid Matrix content URL") - } - parts := strings.Split(mxcURL[len("mxc://"):], "/") - if len(parts) != 2 { - return nil, errors.New("invalid Matrix content URL") - } - u := cli.BuildBaseURL("_matrix/media/r0/download", parts[0], parts[1]) - resp, err := cli.Client.Get(u) - if err != nil { - return nil, err - } - return resp.Body, nil -} - -func (cli *Client) DownloadBytes(mxcURL string) ([]byte, error) { - resp, err := cli.Download(mxcURL) - if err != nil { - return nil, err - } - defer resp.Close() - return ioutil.ReadAll(resp) -} - -func (cli *Client) UploadBytes(data []byte, contentType string) (*RespMediaUpload, error) { - return cli.Upload(bytes.NewReader(data), contentType, int64(len(data))) -} - -// UploadToContentRepo uploads the given bytes to the content repository and returns an MXC URI. -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-media-r0-upload -func (cli *Client) Upload(content io.Reader, contentType string, contentLength int64) (*RespMediaUpload, error) { - req, err := http.NewRequest("POST", cli.BuildBaseURL("_matrix/media/r0/upload"), content) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", contentType) - req.ContentLength = contentLength - cli.LogRequest(req, fmt.Sprintf("%d bytes", contentLength)) - res, err := cli.Client.Do(req) - if res != nil { - defer res.Body.Close() - } - if err != nil { - return nil, err - } - if res.StatusCode != 200 { - contents, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, HTTPError{ - Message: "Upload request failed - Failed to read response body: " + err.Error(), - Code: res.StatusCode, - } - } - return nil, HTTPError{ - Message: "Upload request failed: " + string(contents), - Code: res.StatusCode, - } - } - var m RespMediaUpload - if err := json.NewDecoder(res.Body).Decode(&m); err != nil { - return nil, err - } - return &m, nil -} - -// JoinedMembers returns a map of joined room members. See TODO-SPEC. https://github.com/matrix-org/synapse/pull/1680 -// -// In general, usage of this API is discouraged in favour of /sync, as calling this API can race with incoming membership changes. -// This API is primarily designed for application services which may want to efficiently look up joined members in a room. -func (cli *Client) JoinedMembers(roomID string) (resp *RespJoinedMembers, err error) { - u := cli.BuildURL("rooms", roomID, "joined_members") - _, err = cli.MakeRequest("GET", u, nil, &resp) - return -} - -// JoinedRooms returns a list of rooms which the client is joined to. See TODO-SPEC. https://github.com/matrix-org/synapse/pull/1680 -// -// In general, usage of this API is discouraged in favour of /sync, as calling this API can race with incoming membership changes. -// This API is primarily designed for application services which may want to efficiently look up joined rooms. -func (cli *Client) JoinedRooms() (resp *RespJoinedRooms, err error) { - u := cli.BuildURL("joined_rooms") - _, err = cli.MakeRequest("GET", u, nil, &resp) - return -} - -// Messages returns a list of message and state events for a room. It uses -// pagination query parameters to paginate history in the room. -// See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-messages -func (cli *Client) Messages(roomID, from, to string, dir rune, limit int) (resp *RespMessages, err error) { - query := map[string]string{ - "from": from, - "dir": string(dir), - } - if to != "" { - query["to"] = to - } - if limit != 0 { - query["limit"] = strconv.Itoa(limit) - } - - urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "messages"}, query) - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -func (cli *Client) GetEvent(roomID, eventID string) (resp *Event, err error) { - urlPath := cli.BuildURL("rooms", roomID, "event", eventID) - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -func (cli *Client) MarkRead(roomID, eventID string) (err error) { - urlPath := cli.BuildURL("rooms", roomID, "receipt", "m.read", eventID) - _, err = cli.MakeRequest("POST", urlPath, struct{}{}, nil) - return -} - -// TurnServer returns turn server details and credentials for the client to use when initiating calls. -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-voip-turnserver -func (cli *Client) TurnServer() (resp *RespTurnServer, err error) { - urlPath := cli.BuildURL("voip", "turnServer") - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -func txnID() string { - return "go" + strconv.FormatInt(time.Now().UnixNano(), 10) -} - -// NewClient creates a new Matrix Client ready for syncing -func NewClient(homeserverURL, userID, accessToken string) (*Client, error) { - hsURL, err := url.Parse(homeserverURL) - if err != nil { - return nil, err - } - // By default, use an in-memory store which will never save filter ids / next batch tokens to disk. - // The client will work with this storer: it just won't remember across restarts. - // In practice, a database backend should be used. - store := NewInMemoryStore() - cli := Client{ - AccessToken: accessToken, - HomeserverURL: hsURL, - UserID: userID, - Prefix: "/_matrix/client/r0", - Syncer: NewDefaultSyncer(userID, store), - Store: store, - } - // By default, use the default HTTP client. - cli.Client = http.DefaultClient - - return &cli, nil -} diff --git a/vendor/maunium.net/go/mautrix/events.go b/vendor/maunium.net/go/mautrix/events.go deleted file mode 100644 index efd3795..0000000 --- a/vendor/maunium.net/go/mautrix/events.go +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright 2018 Tulir Asokan -package mautrix - -import ( - "encoding/json" - "strings" - "sync" -) - -type EventTypeClass int - -const ( - // Normal message events - MessageEventType EventTypeClass = iota - // State events - StateEventType - // Ephemeral events - EphemeralEventType - // Account data events - AccountDataEventType - // Unknown events - UnknownEventType -) - -type EventType struct { - Type string - Class EventTypeClass -} - -func NewEventType(name string) EventType { - evtType := EventType{Type: name} - evtType.Class = evtType.GuessClass() - return evtType -} - -func (et *EventType) IsState() bool { - return et.Class == StateEventType -} - -func (et *EventType) IsEphemeral() bool { - return et.Class == EphemeralEventType -} - -func (et *EventType) IsCustom() bool { - return !strings.HasPrefix(et.Type, "m.") -} - -func (et *EventType) GuessClass() EventTypeClass { - switch et.Type { - case StateAliases.Type, StateCanonicalAlias.Type, StateCreate.Type, StateJoinRules.Type, StateMember.Type, - StatePowerLevels.Type, StateRoomName.Type, StateRoomAvatar.Type, StateTopic.Type, StatePinnedEvents.Type: - return StateEventType - case EphemeralEventReceipt.Type, EphemeralEventTyping.Type: - return EphemeralEventType - case AccountDataDirectChats.Type, AccountDataPushRules.Type, AccountDataRoomTags.Type: - return AccountDataEventType - case EventRedaction.Type, EventMessage.Type, EventSticker.Type: - return MessageEventType - default: - return UnknownEventType - } -} - -func (et *EventType) UnmarshalJSON(data []byte) error { - err := json.Unmarshal(data, &et.Type) - if err != nil { - return err - } - et.Class = et.GuessClass() - return nil -} - -func (et *EventType) MarshalJSON() ([]byte, error) { - return json.Marshal(&et.Type) -} - -func (et *EventType) String() string { - return et.Type -} - -// State events -var ( - StateAliases = EventType{"m.room.aliases", StateEventType} - StateCanonicalAlias = EventType{"m.room.canonical_alias", StateEventType} - StateCreate = EventType{"m.room.create", StateEventType} - StateJoinRules = EventType{"m.room.join_rules", StateEventType} - StateMember = EventType{"m.room.member", StateEventType} - StatePowerLevels = EventType{"m.room.power_levels", StateEventType} - StateRoomName = EventType{"m.room.name", StateEventType} - StateTopic = EventType{"m.room.topic", StateEventType} - StateRoomAvatar = EventType{"m.room.avatar", StateEventType} - StatePinnedEvents = EventType{"m.room.pinned_events", StateEventType} -) - -// Message events -var ( - EventRedaction = EventType{"m.room.redaction", MessageEventType} - EventMessage = EventType{"m.room.message", MessageEventType} - EventSticker = EventType{"m.sticker", MessageEventType} -) - -// Ephemeral events -var ( - EphemeralEventReceipt = EventType{"m.receipt", EphemeralEventType} - EphemeralEventTyping = EventType{"m.typing", EphemeralEventType} -) - -// Account data events -var ( - AccountDataDirectChats = EventType{"m.direct", AccountDataEventType} - AccountDataPushRules = EventType{"m.push_rules", AccountDataEventType} - AccountDataRoomTags = EventType{"m.tag", AccountDataEventType} -) - -type MessageType string - -// Msgtypes -const ( - MsgText MessageType = "m.text" - MsgEmote = "m.emote" - MsgNotice = "m.notice" - MsgImage = "m.image" - MsgLocation = "m.location" - MsgVideo = "m.video" - MsgAudio = "m.audio" - MsgFile = "m.file" -) - -type Format string - -// Message formats -const ( - FormatHTML Format = "org.matrix.custom.html" -) - -// Event represents a single Matrix event. -type Event struct { - StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events. - Sender string `json:"sender"` // The user ID of the sender of the event - Type EventType `json:"type"` // The event type - Timestamp int64 `json:"origin_server_ts"` // The unix timestamp when this message was sent by the origin server - ID string `json:"event_id"` // The unique ID of this event - RoomID string `json:"room_id"` // The room the event was sent to. May be nil (e.g. for presence) - Content Content `json:"content"` // The JSON content of the event. - Redacts string `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event - Unsigned Unsigned `json:"unsigned,omitempty"` // Unsigned content set by own homeserver. - - InviteRoomState []StrippedState `json:"invite_room_state"` -} - -func (evt *Event) GetStateKey() string { - if evt.StateKey != nil { - return *evt.StateKey - } - return "" -} - -type StrippedState struct { - Content Content `json:"content"` - Type EventType `json:"type"` - StateKey string `json:"state_key"` -} - -type Unsigned struct { - PrevContent *Content `json:"prev_content,omitempty"` - PrevSender string `json:"prev_sender,omitempty"` - ReplacesState string `json:"replaces_state,omitempty"` - Age int64 `json:"age,omitempty"` - - PassiveCommand map[string]*MatchedPassiveCommand `json:"m.passive_command,omitempty"` -} - -type MatchedPassiveCommand struct { - // Matched string `json:"matched"` - // Value string `json:"value"` - Captured [][]string `json:"captured"` - - BackCompatCommand string `json:"command"` - BackCompatArguments map[string]string `json:"arguments"` -} - -type Content struct { - VeryRaw json.RawMessage `json:"-"` - Raw map[string]interface{} `json:"-"` - - MsgType MessageType `json:"msgtype,omitempty"` - Body string `json:"body,omitempty"` - Format Format `json:"format,omitempty"` - FormattedBody string `json:"formatted_body,omitempty"` - - Info *FileInfo `json:"info,omitempty"` - URL string `json:"url,omitempty"` - - // Membership key for easy access in m.room.member events - Membership Membership `json:"membership,omitempty"` - - RelatesTo *RelatesTo `json:"m.relates_to,omitempty"` - Command *MatchedCommand `json:"m.command,omitempty"` - - *PowerLevels - Member - Aliases []string `json:"aliases,omitempty"` - Alias string `json:"alias,omitempty"` - Name string `json:"name,omitempty"` - Topic string `json:"name,omitempty"` - - RoomTags Tags `json:"tags,omitempty"` - TypingUserIDs []string `json:"user_ids,omitempty"` -} - -type serializableContent Content - -var DisableFancyEventParsing = false - -func (content *Content) UnmarshalJSON(data []byte) error { - content.VeryRaw = data - if err := json.Unmarshal(data, &content.Raw); err != nil || DisableFancyEventParsing { - return err - } - return json.Unmarshal(data, (*serializableContent)(content)) -} - -func (content *Content) GetCommand() *MatchedCommand { - if content.Command == nil { - content.Command = &MatchedCommand{} - } - return content.Command -} - -func (content *Content) GetRelatesTo() *RelatesTo { - if content.RelatesTo == nil { - content.RelatesTo = &RelatesTo{} - } - return content.RelatesTo -} - -func (content *Content) GetPowerLevels() *PowerLevels { - if content.PowerLevels == nil { - content.PowerLevels = &PowerLevels{} - } - return content.PowerLevels -} - -func (content *Content) UnmarshalPowerLevels() (pl PowerLevels, err error) { - err = json.Unmarshal(content.VeryRaw, &pl) - return -} - -func (content *Content) UnmarshalMember() (m Member, err error) { - err = json.Unmarshal(content.VeryRaw, &m) - return -} - -func (content *Content) GetInfo() *FileInfo { - if content.Info == nil { - content.Info = &FileInfo{} - } - return content.Info -} - -type Tags map[string]struct { - Order json.Number `json:"order"` -} - -// Membership is an enum specifying the membership state of a room member. -type Membership string - -// The allowed membership states as specified in spec section 10.5.5. -const ( - MembershipJoin Membership = "join" - MembershipLeave Membership = "leave" - MembershipInvite Membership = "invite" - MembershipBan Membership = "ban" - MembershipKnock Membership = "knock" -) - -type Member struct { - Membership Membership `json:"membership,omitempty"` - AvatarURL string `json:"avatar_url,omitempty"` - Displayname string `json:"displayname,omitempty"` - ThirdPartyInvite *ThirdPartyInvite `json:"third_party_invite,omitempty"` - Reason string `json:"reason,omitempty"` -} - -type ThirdPartyInvite struct { - DisplayName string `json:"display_name"` - Signed struct { - Token string `json:"token"` - Signatures json.RawMessage `json:"signatures"` - MXID string `json:"mxid"` - } -} - -type PowerLevels struct { - usersLock sync.RWMutex `json:"-"` - Users map[string]int `json:"users,omitempty"` - UsersDefault int `json:"users_default,omitempty"` - - eventsLock sync.RWMutex `json:"-"` - Events map[string]int `json:"events,omitempty"` - EventsDefault int `json:"events_default,omitempty"` - - StateDefaultPtr *int `json:"state_default,omitempty"` - - InvitePtr *int `json:"invite,omitempty"` - KickPtr *int `json:"kick,omitempty"` - BanPtr *int `json:"ban,omitempty"` - RedactPtr *int `json:"redact,omitempty"` -} - -func (pl *PowerLevels) Invite() int { - if pl.InvitePtr != nil { - return *pl.InvitePtr - } - return 50 -} - -func (pl *PowerLevels) Kick() int { - if pl.KickPtr != nil { - return *pl.KickPtr - } - return 50 -} - -func (pl *PowerLevels) Ban() int { - if pl.BanPtr != nil { - return *pl.BanPtr - } - return 50 -} - -func (pl *PowerLevels) Redact() int { - if pl.RedactPtr != nil { - return *pl.RedactPtr - } - return 50 -} - -func (pl *PowerLevels) StateDefault() int { - if pl.StateDefaultPtr != nil { - return *pl.StateDefaultPtr - } - return 50 -} - -func (pl *PowerLevels) GetUserLevel(userID string) int { - pl.usersLock.RLock() - defer pl.usersLock.RUnlock() - level, ok := pl.Users[userID] - if !ok { - return pl.UsersDefault - } - return level -} - -func (pl *PowerLevels) SetUserLevel(userID string, level int) { - pl.usersLock.Lock() - defer pl.usersLock.Unlock() - if level == pl.UsersDefault { - delete(pl.Users, userID) - } else { - pl.Users[userID] = level - } -} - -func (pl *PowerLevels) EnsureUserLevel(userID string, level int) bool { - existingLevel := pl.GetUserLevel(userID) - if existingLevel != level { - pl.SetUserLevel(userID, level) - return true - } - return false -} - -func (pl *PowerLevels) GetEventLevel(eventType EventType) int { - pl.eventsLock.RLock() - defer pl.eventsLock.RUnlock() - level, ok := pl.Events[eventType.String()] - if !ok { - if eventType.IsState() { - return pl.StateDefault() - } - return pl.EventsDefault - } - return level -} - -func (pl *PowerLevels) SetEventLevel(eventType EventType, level int) { - pl.eventsLock.Lock() - defer pl.eventsLock.Unlock() - if (eventType.IsState() && level == pl.StateDefault()) || (!eventType.IsState() && level == pl.EventsDefault) { - delete(pl.Events, eventType.String()) - } else { - pl.Events[eventType.String()] = level - } -} - -func (pl *PowerLevels) EnsureEventLevel(eventType EventType, level int) bool { - existingLevel := pl.GetEventLevel(eventType) - if existingLevel != level { - pl.SetEventLevel(eventType, level) - return true - } - return false -} - -type FileInfo struct { - MimeType string `json:"mimetype,omitempty"` - ThumbnailInfo *FileInfo `json:"thumbnail_info,omitempty"` - ThumbnailURL string `json:"thumbnail_url,omitempty"` - Height int `json:"h,omitempty"` - Width int `json:"w,omitempty"` - Duration uint `json:"duration,omitempty"` - Size int `json:"size,omitempty"` -} - -func (fileInfo *FileInfo) GetThumbnailInfo() *FileInfo { - if fileInfo.ThumbnailInfo == nil { - fileInfo.ThumbnailInfo = &FileInfo{} - } - return fileInfo.ThumbnailInfo -} - -type RelatesTo struct { - InReplyTo InReplyTo `json:"m.in_reply_to,omitempty"` -} - -type InReplyTo struct { - EventID string `json:"event_id,omitempty"` - // Not required, just for future-proofing - RoomID string `json:"room_id,omitempty"` -} - -type MatchedCommand struct { - Target string `json:"target"` - Matched string `json:"matched"` - Arguments map[string]string `json:"arguments"` -} diff --git a/vendor/maunium.net/go/mautrix/filter.go b/vendor/maunium.net/go/mautrix/filter.go deleted file mode 100644 index 41cab2d..0000000 --- a/vendor/maunium.net/go/mautrix/filter.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2017 Jan Christian Grünhage -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package mautrix - -import "errors" - -//Filter is used by clients to specify how the server should filter responses to e.g. sync requests -//Specified by: https://matrix.org/docs/spec/client_server/r0.2.0.html#filtering -type Filter struct { - AccountData FilterPart `json:"account_data,omitempty"` - EventFields []string `json:"event_fields,omitempty"` - EventFormat string `json:"event_format,omitempty"` - Presence FilterPart `json:"presence,omitempty"` - Room RoomFilter `json:"room,omitempty"` -} - -// RoomFilter is used to define filtering rules for room events -type RoomFilter struct { - AccountData FilterPart `json:"account_data,omitempty"` - Ephemeral FilterPart `json:"ephemeral,omitempty"` - IncludeLeave bool `json:"include_leave,omitempty"` - NotRooms []string `json:"not_rooms,omitempty"` - Rooms []string `json:"rooms,omitempty"` - State FilterPart `json:"state,omitempty"` - Timeline FilterPart `json:"timeline,omitempty"` -} - -// FilterPart is used to define filtering rules for specific categories of events -type FilterPart struct { - NotRooms []string `json:"not_rooms,omitempty"` - Rooms []string `json:"rooms,omitempty"` - Limit int `json:"limit,omitempty"` - NotSenders []string `json:"not_senders,omitempty"` - NotTypes []string `json:"not_types,omitempty"` - Senders []string `json:"senders,omitempty"` - Types []string `json:"types,omitempty"` - ContainsURL *bool `json:"contains_url,omitempty"` -} - -// Validate checks if the filter contains valid property values -func (filter *Filter) Validate() error { - if filter.EventFormat != "client" && filter.EventFormat != "federation" { - return errors.New("Bad event_format value. Must be one of [\"client\", \"federation\"]") - } - return nil -} - -// DefaultFilter returns the default filter used by the Matrix server if no filter is provided in the request -func DefaultFilter() Filter { - return Filter{ - AccountData: DefaultFilterPart(), - EventFields: nil, - EventFormat: "client", - Presence: DefaultFilterPart(), - Room: RoomFilter{ - AccountData: DefaultFilterPart(), - Ephemeral: DefaultFilterPart(), - IncludeLeave: false, - NotRooms: nil, - Rooms: nil, - State: DefaultFilterPart(), - Timeline: DefaultFilterPart(), - }, - } -} - -// DefaultFilterPart returns the default filter part used by the Matrix server if no filter is provided in the request -func DefaultFilterPart() FilterPart { - return FilterPart{ - NotRooms: nil, - Rooms: nil, - Limit: 20, - NotSenders: nil, - NotTypes: nil, - Senders: nil, - Types: nil, - } -} diff --git a/vendor/maunium.net/go/mautrix/format/htmlparser.go b/vendor/maunium.net/go/mautrix/format/htmlparser.go deleted file mode 100644 index b681be6..0000000 --- a/vendor/maunium.net/go/mautrix/format/htmlparser.go +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2018 Tulir Asokan -package format - -import ( - "fmt" - "math" - "regexp" - "strings" - - "golang.org/x/net/html" - "strconv" -) - -var MatrixToURL = regexp.MustCompile("^(?:https?://)?(?:www\\.)?matrix\\.to/#/([#@!+].*)(?:/(\\$.+))?") - -type TextConverter func(string) string - -type HTMLParser struct { - PillConverter func(mxid, eventID string) string - TabsToSpaces int - Newline string - BoldConverter TextConverter - ItalicConverter TextConverter - StrikethroughConverter TextConverter - UnderlineConverter TextConverter - MonospaceBlockConverter TextConverter - MonospaceConverter TextConverter -} - -type TaggedString struct { - string - tag string -} - -func (parser *HTMLParser) getAttribute(node *html.Node, attribute string) string { - for _, attr := range node.Attr { - if attr.Key == attribute { - return attr.Val - } - } - return "" -} - -func Digits(num int) int { - return int(math.Floor(math.Log10(float64(num))) + 1) -} - -func (parser *HTMLParser) listToString(node *html.Node, stripLinebreak bool) string { - ordered := node.Data == "ol" - taggedChildren := parser.nodeToTaggedStrings(node.FirstChild, stripLinebreak) - counter := 1 - indentLength := 0 - if ordered { - start := parser.getAttribute(node, "start") - if len(start) > 0 { - counter, _ = strconv.Atoi(start) - } - - longestIndex := (counter - 1) + len(taggedChildren) - indentLength = Digits(longestIndex) - } - indent := strings.Repeat(" ", indentLength+2) - var children []string - for _, child := range taggedChildren { - if child.tag != "li" { - continue - } - var prefix string - if ordered { - indexPadding := indentLength - Digits(counter) - prefix = fmt.Sprintf("%d. %s", counter, strings.Repeat(" ", indexPadding)) - } else { - prefix = "● " - } - str := prefix + child.string - counter++ - parts := strings.Split(str, "\n") - for i, part := range parts[1:] { - parts[i+1] = indent + part - } - str = strings.Join(parts, "\n") - children = append(children, str) - } - return strings.Join(children, "\n") -} - -func (parser *HTMLParser) basicFormatToString(node *html.Node, stripLinebreak bool) string { - str := parser.nodeToTagAwareString(node.FirstChild, stripLinebreak) - switch node.Data { - case "b", "strong": - if parser.BoldConverter != nil { - return parser.BoldConverter(str) - } - return fmt.Sprintf("**%s**", str) - case "i", "em": - if parser.ItalicConverter != nil { - return parser.ItalicConverter(str) - } - return fmt.Sprintf("_%s_", str) - case "s", "del": - if parser.StrikethroughConverter != nil { - return parser.StrikethroughConverter(str) - } - return fmt.Sprintf("~~%s~~", str) - case "u", "ins": - if parser.UnderlineConverter != nil { - return parser.UnderlineConverter(str) - } - case "tt", "code": - if parser.MonospaceConverter != nil { - return parser.MonospaceConverter(str) - } - } - return str -} - -func (parser *HTMLParser) headerToString(node *html.Node, stripLinebreak bool) string { - children := parser.nodeToStrings(node.FirstChild, stripLinebreak) - length := int(node.Data[1] - '0') - prefix := strings.Repeat("#", length) + " " - return prefix + strings.Join(children, "") -} - -func (parser *HTMLParser) blockquoteToString(node *html.Node, stripLinebreak bool) string { - str := parser.nodeToTagAwareString(node.FirstChild, stripLinebreak) - childrenArr := strings.Split(strings.TrimSpace(str), "\n") - for index, child := range childrenArr { - childrenArr[index] = "> " + child - } - return strings.Join(childrenArr, "\n") -} - -func (parser *HTMLParser) linkToString(node *html.Node, stripLinebreak bool) string { - str := parser.nodeToTagAwareString(node.FirstChild, stripLinebreak) - href := parser.getAttribute(node, "href") - if len(href) == 0 { - return str - } - match := MatrixToURL.FindStringSubmatch(href) - if len(match) == 2 || len(match) == 3 { - if parser.PillConverter != nil { - mxid := match[1] - eventID := "" - if len(match) == 3 { - eventID = match[2] - } - return parser.PillConverter(mxid, eventID) - } - return str - } - return fmt.Sprintf("%s (%s)", str, href) -} - -func (parser *HTMLParser) tagToString(node *html.Node, stripLinebreak bool) string { - switch node.Data { - case "blockquote": - return parser.blockquoteToString(node, stripLinebreak) - case "ol", "ul": - return parser.listToString(node, stripLinebreak) - case "h1", "h2", "h3", "h4", "h5", "h6": - return parser.headerToString(node, stripLinebreak) - case "br": - return parser.Newline - case "b", "strong", "i", "em", "s", "del", "u", "ins", "tt", "code": - return parser.basicFormatToString(node, stripLinebreak) - case "a": - return parser.linkToString(node, stripLinebreak) - case "p": - return parser.nodeToTagAwareString(node.FirstChild, stripLinebreak) + "\n" - case "pre": - var preStr string - if node.FirstChild != nil && node.FirstChild.Type == html.ElementNode && node.FirstChild.Data == "code" { - preStr = parser.nodeToString(node.FirstChild.FirstChild, false) - } else { - preStr = parser.nodeToString(node.FirstChild, false) - } - if parser.MonospaceBlockConverter != nil { - return parser.MonospaceBlockConverter(preStr) - } - return preStr - default: - return parser.nodeToTagAwareString(node.FirstChild, stripLinebreak) - } -} - -func (parser *HTMLParser) singleNodeToString(node *html.Node, stripLinebreak bool) TaggedString { - switch node.Type { - case html.TextNode: - if stripLinebreak { - node.Data = strings.Replace(node.Data, "\n", "", -1) - } - return TaggedString{node.Data, "text"} - case html.ElementNode: - return TaggedString{parser.tagToString(node, stripLinebreak), node.Data} - case html.DocumentNode: - return TaggedString{parser.nodeToTagAwareString(node.FirstChild, stripLinebreak), "html"} - default: - return TaggedString{"", "unknown"} - } -} - -func (parser *HTMLParser) nodeToTaggedStrings(node *html.Node, stripLinebreak bool) (strs []TaggedString) { - for ; node != nil; node = node.NextSibling { - strs = append(strs, parser.singleNodeToString(node, stripLinebreak)) - } - return -} - -var BlockTags = []string{"p", "h1", "h2", "h3", "h4", "h5", "h6", "ol", "ul", "pre", "blockquote", "div", "hr", "table"} - -func (parser *HTMLParser) isBlockTag(tag string) bool { - for _, blockTag := range BlockTags { - if tag == blockTag { - return true - } - } - return false -} - -func (parser *HTMLParser) nodeToTagAwareString(node *html.Node, stripLinebreak bool) string { - strs := parser.nodeToTaggedStrings(node, stripLinebreak) - var output strings.Builder - for _, str := range strs { - tstr := str.string - if parser.isBlockTag(str.tag) { - tstr = fmt.Sprintf("\n%s\n", tstr) - } - output.WriteString(tstr) - } - return strings.TrimSpace(output.String()) -} - -func (parser *HTMLParser) nodeToStrings(node *html.Node, stripLinebreak bool) (strs []string) { - for ; node != nil; node = node.NextSibling { - strs = append(strs, parser.singleNodeToString(node, stripLinebreak).string) - } - return -} - -func (parser *HTMLParser) nodeToString(node *html.Node, stripLinebreak bool) string { - return strings.Join(parser.nodeToStrings(node, stripLinebreak), "") -} - -func (parser *HTMLParser) Parse(htmlData string) string { - if parser.TabsToSpaces >= 0 { - htmlData = strings.Replace(htmlData, "\t", strings.Repeat(" ", parser.TabsToSpaces), -1) - } - node, _ := html.Parse(strings.NewReader(htmlData)) - return parser.nodeToTagAwareString(node, true) -} - -func HTMLToText(html string) string { - return (&HTMLParser{ - TabsToSpaces: 4, - Newline: "\n", - }).Parse(html) -} diff --git a/vendor/maunium.net/go/mautrix/format/markdown.go b/vendor/maunium.net/go/mautrix/format/markdown.go deleted file mode 100644 index 65abf56..0000000 --- a/vendor/maunium.net/go/mautrix/format/markdown.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2018 Tulir Asokan -package format - -import ( - "gopkg.in/russross/blackfriday.v2" - "maunium.net/go/mautrix" - "strings" -) - -func RenderMarkdown(text string) mautrix.Content { - parser := blackfriday.New( - blackfriday.WithExtensions(blackfriday.NoIntraEmphasis | - blackfriday.Tables | - blackfriday.FencedCode | - blackfriday.Strikethrough | - blackfriday.SpaceHeadings | - blackfriday.DefinitionLists)) - ast := parser.Parse([]byte(text)) - - renderer := blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{ - Flags: blackfriday.UseXHTML, - }) - - var buf strings.Builder - renderer.RenderHeader(&buf, ast) - ast.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus { - return renderer.RenderNode(&buf, node, entering) - }) - renderer.RenderFooter(&buf, ast) - htmlBody := buf.String() - - return mautrix.Content{ - FormattedBody: htmlBody, - Format: mautrix.FormatHTML, - MsgType: mautrix.MsgText, - Body: HTMLToText(htmlBody), - } -} diff --git a/vendor/maunium.net/go/mautrix/reply.go b/vendor/maunium.net/go/mautrix/reply.go deleted file mode 100644 index 5e3af92..0000000 --- a/vendor/maunium.net/go/mautrix/reply.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2018 Tulir Asokan -package mautrix - -import ( - "fmt" - "regexp" - "strings" - - "golang.org/x/net/html" -) - -var HTMLReplyFallbackRegex = regexp.MustCompile(`^<mx-reply>[\s\S]+?</mx-reply>`) - -func TrimReplyFallbackHTML(html string) string { - return HTMLReplyFallbackRegex.ReplaceAllString(html, "") -} - -func TrimReplyFallbackText(text string) string { - if !strings.HasPrefix(text, "> ") || !strings.Contains(text, "\n") { - return text - } - - lines := strings.Split(text, "\n") - for len(lines) > 0 && strings.HasPrefix(lines[0], "> ") { - lines = lines[1:] - } - return strings.TrimSpace(strings.Join(lines, "\n")) -} - -func (content *Content) RemoveReplyFallback() { - if len(content.GetReplyTo()) > 0 { - if content.Format == FormatHTML { - content.FormattedBody = TrimReplyFallbackHTML(content.FormattedBody) - } - content.Body = TrimReplyFallbackText(content.Body) - } -} - -func (content *Content) GetReplyTo() string { - if content.RelatesTo != nil { - return content.RelatesTo.InReplyTo.EventID - } - return "" -} - -const ReplyFormat = `<mx-reply><blockquote> -<a href="https://matrix.to/#/%s/%s">In reply to</a> -<a href="https://matrix.to/#/%s">%s</a> -%s -</blockquote></mx-reply> -` - -func (evt *Event) GenerateReplyFallbackHTML() string { - body := evt.Content.FormattedBody - if len(body) == 0 { - body = html.EscapeString(evt.Content.Body) - } - - senderDisplayName := evt.Sender - - return fmt.Sprintf(ReplyFormat, evt.RoomID, evt.ID, evt.Sender, senderDisplayName, body) -} - -func (evt *Event) GenerateReplyFallbackText() string { - body := evt.Content.Body - lines := strings.Split(strings.TrimSpace(body), "\n") - firstLine, lines := lines[0], lines[1:] - - senderDisplayName := evt.Sender - - var fallbackText strings.Builder - fmt.Fprintf(&fallbackText, "> <%s> %s", senderDisplayName, firstLine) - for _, line := range lines { - fmt.Fprintf(&fallbackText, "\n> %s", line) - } - fallbackText.WriteString("\n\n") - return fallbackText.String() -} - -func (content *Content) SetReply(inReplyTo *Event) { - if content.RelatesTo == nil { - content.RelatesTo = &RelatesTo{} - } - content.RelatesTo.InReplyTo = InReplyTo{ - EventID: inReplyTo.ID, - RoomID: inReplyTo.RoomID, - } - - if content.MsgType == MsgText || content.MsgType == MsgNotice { - if len(content.FormattedBody) == 0 || content.Format != FormatHTML { - content.FormattedBody = html.EscapeString(content.Body) - content.Format = FormatHTML - } - content.FormattedBody = inReplyTo.GenerateReplyFallbackHTML() + content.FormattedBody - content.Body = inReplyTo.GenerateReplyFallbackText() + content.Body - } -} diff --git a/vendor/maunium.net/go/mautrix/requests.go b/vendor/maunium.net/go/mautrix/requests.go deleted file mode 100644 index b90e6fb..0000000 --- a/vendor/maunium.net/go/mautrix/requests.go +++ /dev/null @@ -1,82 +0,0 @@ -package mautrix - -// ReqRegister is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register -type ReqRegister struct { - Username string `json:"username,omitempty"` - BindEmail bool `json:"bind_email,omitempty"` - Password string `json:"password,omitempty"` - DeviceID string `json:"device_id,omitempty"` - InitialDeviceDisplayName string `json:"initial_device_display_name"` - Auth interface{} `json:"auth,omitempty"` -} - -// ReqLogin is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-login -type ReqLogin struct { - Type string `json:"type"` - Password string `json:"password,omitempty"` - Medium string `json:"medium,omitempty"` - User string `json:"user,omitempty"` - Address string `json:"address,omitempty"` - Token string `json:"token,omitempty"` - DeviceID string `json:"device_id,omitempty"` - InitialDeviceDisplayName string `json:"initial_device_display_name,omitempty"` -} - -// ReqCreateRoom is the JSON request for https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom -type ReqCreateRoom struct { - Visibility string `json:"visibility,omitempty"` - RoomAliasName string `json:"room_alias_name,omitempty"` - Name string `json:"name,omitempty"` - Topic string `json:"topic,omitempty"` - Invite []string `json:"invite,omitempty"` - Invite3PID []ReqInvite3PID `json:"invite_3pid,omitempty"` - CreationContent map[string]interface{} `json:"creation_content,omitempty"` - InitialState []*Event `json:"initial_state,omitempty"` - Preset string `json:"preset,omitempty"` - IsDirect bool `json:"is_direct,omitempty"` -} - -// ReqRedact is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid -type ReqRedact struct { - Reason string `json:"reason,omitempty"` -} - -// ReqInvite3PID is the JSON request for https://matrix.org/docs/spec/client_server/r0.2.0.html#id57 -// It is also a JSON object used in https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom -type ReqInvite3PID struct { - IDServer string `json:"id_server"` - Medium string `json:"medium"` - Address string `json:"address"` -} - -// ReqInviteUser is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-invite -type ReqInviteUser struct { - UserID string `json:"user_id"` -} - -// ReqKickUser is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-kick -type ReqKickUser struct { - Reason string `json:"reason,omitempty"` - UserID string `json:"user_id"` -} - -// ReqBanUser is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-ban -type ReqBanUser struct { - Reason string `json:"reason,omitempty"` - UserID string `json:"user_id"` -} - -// ReqUnbanUser is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-unban -type ReqUnbanUser struct { - UserID string `json:"user_id"` -} - -// ReqTyping is the JSON request for https://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-typing-userid -type ReqTyping struct { - Typing bool `json:"typing"` - Timeout int64 `json:"timeout,omitempty"` -} - -type ReqPresence struct { - Presence string `json:"presence"` -} diff --git a/vendor/maunium.net/go/mautrix/responses.go b/vendor/maunium.net/go/mautrix/responses.go deleted file mode 100644 index 2adf90a..0000000 --- a/vendor/maunium.net/go/mautrix/responses.go +++ /dev/null @@ -1,182 +0,0 @@ -package mautrix - -// RespError is the standard JSON error response from Homeservers. It also implements the Golang "error" interface. -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#api-standards -type RespError struct { - ErrCode string `json:"errcode"` - Err string `json:"error"` -} - -// Error returns the errcode and error message. -func (e RespError) Error() string { - return e.ErrCode + ": " + e.Err -} - -// RespCreateFilter is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-user-userid-filter -type RespCreateFilter struct { - FilterID string `json:"filter_id"` -} - -// RespVersions is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-versions -type RespVersions struct { - Versions []string `json:"versions"` -} - -// RespJoinRoom is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-join -type RespJoinRoom struct { - RoomID string `json:"room_id"` -} - -// RespLeaveRoom is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-leave -type RespLeaveRoom struct{} - -// RespForgetRoom is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-forget -type RespForgetRoom struct{} - -// RespInviteUser is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-invite -type RespInviteUser struct{} - -// RespKickUser is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-kick -type RespKickUser struct{} - -// RespBanUser is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-ban -type RespBanUser struct{} - -// RespUnbanUser is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-unban -type RespUnbanUser struct{} - -// RespTyping is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-typing-userid -type RespTyping struct{} - -// RespJoinedRooms is the JSON response for TODO-SPEC https://github.com/matrix-org/synapse/pull/1680 -type RespJoinedRooms struct { - JoinedRooms []string `json:"joined_rooms"` -} - -// RespJoinedMembers is the JSON response for TODO-SPEC https://github.com/matrix-org/synapse/pull/1680 -type RespJoinedMembers struct { - Joined map[string]struct { - DisplayName *string `json:"display_name"` - AvatarURL *string `json:"avatar_url"` - } `json:"joined"` -} - -// RespMessages is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-messages -type RespMessages struct { - Start string `json:"start"` - Chunk []*Event `json:"chunk"` - End string `json:"end"` -} - -// RespSendEvent is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid -type RespSendEvent struct { - EventID string `json:"event_id"` -} - -// RespMediaUpload is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-media-r0-upload -type RespMediaUpload struct { - ContentURI string `json:"content_uri"` -} - -// RespUserInteractive is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#user-interactive-authentication-api -type RespUserInteractive struct { - Flows []struct { - Stages []string `json:"stages"` - } `json:"flows"` - Params map[string]interface{} `json:"params"` - Session string `json:"string"` - Completed []string `json:"completed"` - ErrCode string `json:"errcode"` - Error string `json:"error"` -} - -// HasSingleStageFlow returns true if there exists at least 1 Flow with a single stage of stageName. -func (r RespUserInteractive) HasSingleStageFlow(stageName string) bool { - for _, f := range r.Flows { - if len(f.Stages) == 1 && f.Stages[0] == stageName { - return true - } - } - return false -} - -// RespUserDisplayName is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-profile-userid-displayname -type RespUserDisplayName struct { - DisplayName string `json:"displayname"` -} - -// RespRegister is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register -type RespRegister struct { - AccessToken string `json:"access_token"` - DeviceID string `json:"device_id"` - HomeServer string `json:"home_server"` - RefreshToken string `json:"refresh_token"` - UserID string `json:"user_id"` -} - -// RespLogin is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-login -type RespLogin struct { - AccessToken string `json:"access_token"` - DeviceID string `json:"device_id"` - HomeServer string `json:"home_server"` - UserID string `json:"user_id"` -} - -// RespLogout is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-logout -type RespLogout struct{} - -// RespCreateRoom is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom -type RespCreateRoom struct { - RoomID string `json:"room_id"` -} - -// RespSync is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync -type RespSync struct { - NextBatch string `json:"next_batch"` - AccountData struct { - Events []*Event `json:"events"` - } `json:"account_data"` - Presence struct { - Events []*Event `json:"events"` - } `json:"presence"` - Rooms struct { - Leave map[string]struct { - State struct { - Events []*Event `json:"events"` - } `json:"state"` - Timeline struct { - Events []*Event `json:"events"` - Limited bool `json:"limited"` - PrevBatch string `json:"prev_batch"` - } `json:"timeline"` - } `json:"leave"` - Join map[string]struct { - State struct { - Events []*Event `json:"events"` - } `json:"state"` - Timeline struct { - Events []*Event `json:"events"` - Limited bool `json:"limited"` - PrevBatch string `json:"prev_batch"` - } `json:"timeline"` - Ephemeral struct { - Events []*Event `json:"events"` - } `json:"ephemeral"` - AccountData struct { - Events []*Event `json:"events"` - } `json:"account_data"` - } `json:"join"` - Invite map[string]struct { - State struct { - Events []*Event `json:"events"` - } `json:"invite_state"` - } `json:"invite"` - } `json:"rooms"` -} - -type RespTurnServer struct { - Username string `json:"username"` - Password string `json:"password"` - TTL int `json:"ttl"` - URIs []string `json:"uris"` -} diff --git a/vendor/maunium.net/go/mautrix/room.go b/vendor/maunium.net/go/mautrix/room.go deleted file mode 100644 index 086e259..0000000 --- a/vendor/maunium.net/go/mautrix/room.go +++ /dev/null @@ -1,44 +0,0 @@ -package mautrix - -// Room represents a single Matrix room. -type Room struct { - ID string - State map[EventType]map[string]*Event -} - -// UpdateState updates the room's current state with the given Event. This will clobber events based -// on the type/state_key combination. -func (room Room) UpdateState(event *Event) { - _, exists := room.State[event.Type] - if !exists { - room.State[event.Type] = make(map[string]*Event) - } - room.State[event.Type][*event.StateKey] = event -} - -// GetStateEvent returns the state event for the given type/state_key combo, or nil. -func (room Room) GetStateEvent(eventType EventType, stateKey string) *Event { - stateEventMap, _ := room.State[eventType] - event, _ := stateEventMap[stateKey] - return event -} - -// GetMembershipState returns the membership state of the given user ID in this room. If there is -// no entry for this member, 'leave' is returned for consistency with left users. -func (room Room) GetMembershipState(userID string) Membership { - state := MembershipLeave - event := room.GetStateEvent(StateMember, userID) - if event != nil { - state = event.Content.Membership - } - return state -} - -// NewRoom creates a new Room with the given ID -func NewRoom(roomID string) *Room { - // Init the State map and return a pointer to the Room - return &Room{ - ID: roomID, - State: make(map[EventType]map[string]*Event), - } -} diff --git a/vendor/maunium.net/go/mautrix/store.go b/vendor/maunium.net/go/mautrix/store.go deleted file mode 100644 index 774398e..0000000 --- a/vendor/maunium.net/go/mautrix/store.go +++ /dev/null @@ -1,65 +0,0 @@ -package mautrix - -// Storer is an interface which must be satisfied to store client data. -// -// You can either write a struct which persists this data to disk, or you can use the -// provided "InMemoryStore" which just keeps data around in-memory which is lost on -// restarts. -type Storer interface { - SaveFilterID(userID, filterID string) - LoadFilterID(userID string) string - SaveNextBatch(userID, nextBatchToken string) - LoadNextBatch(userID string) string - SaveRoom(room *Room) - LoadRoom(roomID string) *Room -} - -// InMemoryStore implements the Storer interface. -// -// Everything is persisted in-memory as maps. It is not safe to load/save filter IDs -// or next batch tokens on any goroutine other than the syncing goroutine: the one -// which called Client.Sync(). -type InMemoryStore struct { - Filters map[string]string - NextBatch map[string]string - Rooms map[string]*Room -} - -// SaveFilterID to memory. -func (s *InMemoryStore) SaveFilterID(userID, filterID string) { - s.Filters[userID] = filterID -} - -// LoadFilterID from memory. -func (s *InMemoryStore) LoadFilterID(userID string) string { - return s.Filters[userID] -} - -// SaveNextBatch to memory. -func (s *InMemoryStore) SaveNextBatch(userID, nextBatchToken string) { - s.NextBatch[userID] = nextBatchToken -} - -// LoadNextBatch from memory. -func (s *InMemoryStore) LoadNextBatch(userID string) string { - return s.NextBatch[userID] -} - -// SaveRoom to memory. -func (s *InMemoryStore) SaveRoom(room *Room) { - s.Rooms[room.ID] = room -} - -// LoadRoom from memory. -func (s *InMemoryStore) LoadRoom(roomID string) *Room { - return s.Rooms[roomID] -} - -// NewInMemoryStore constructs a new InMemoryStore. -func NewInMemoryStore() *InMemoryStore { - return &InMemoryStore{ - Filters: make(map[string]string), - NextBatch: make(map[string]string), - Rooms: make(map[string]*Room), - } -} diff --git a/vendor/maunium.net/go/mautrix/sync.go b/vendor/maunium.net/go/mautrix/sync.go deleted file mode 100644 index 9589edc..0000000 --- a/vendor/maunium.net/go/mautrix/sync.go +++ /dev/null @@ -1,159 +0,0 @@ -package mautrix - -import ( - "encoding/json" - "fmt" - "runtime/debug" - "time" -) - -// Syncer represents an interface that must be satisfied in order to do /sync requests on a client. -type Syncer interface { - // Process the /sync response. The since parameter is the since= value that was used to produce the response. - // This is useful for detecting the very first sync (since=""). If an error is return, Syncing will be stopped - // permanently. - ProcessResponse(resp *RespSync, since string) error - // OnFailedSync returns either the time to wait before retrying or an error to stop syncing permanently. - OnFailedSync(res *RespSync, err error) (time.Duration, error) - // GetFilterJSON for the given user ID. NOT the filter ID. - GetFilterJSON(userID string) json.RawMessage -} - -// DefaultSyncer is the default syncing implementation. You can either write your own syncer, or selectively -// replace parts of this default syncer (e.g. the ProcessResponse method). The default syncer uses the observer -// pattern to notify callers about incoming events. See DefaultSyncer.OnEventType for more information. -type DefaultSyncer struct { - UserID string - Store Storer - listeners map[EventType][]OnEventListener // event type to listeners array -} - -// OnEventListener can be used with DefaultSyncer.OnEventType to be informed of incoming events. -type OnEventListener func(*Event) - -// NewDefaultSyncer returns an instantiated DefaultSyncer -func NewDefaultSyncer(userID string, store Storer) *DefaultSyncer { - return &DefaultSyncer{ - UserID: userID, - Store: store, - listeners: make(map[EventType][]OnEventListener), - } -} - -// ProcessResponse processes the /sync response in a way suitable for bots. "Suitable for bots" means a stream of -// unrepeating events. Returns a fatal error if a listener panics. -func (s *DefaultSyncer) ProcessResponse(res *RespSync, since string) (err error) { - if !s.shouldProcessResponse(res, since) { - return - } - - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("ProcessResponse panicked! userID=%s since=%s panic=%s\n%s", s.UserID, since, r, debug.Stack()) - } - }() - - for roomID, roomData := range res.Rooms.Join { - room := s.getOrCreateRoom(roomID) - for _, event := range roomData.State.Events { - event.RoomID = roomID - room.UpdateState(event) - s.notifyListeners(event) - } - for _, event := range roomData.Timeline.Events { - event.RoomID = roomID - s.notifyListeners(event) - } - } - for roomID, roomData := range res.Rooms.Invite { - room := s.getOrCreateRoom(roomID) - for _, event := range roomData.State.Events { - event.RoomID = roomID - room.UpdateState(event) - s.notifyListeners(event) - } - } - for roomID, roomData := range res.Rooms.Leave { - room := s.getOrCreateRoom(roomID) - for _, event := range roomData.Timeline.Events { - if event.StateKey != nil { - event.RoomID = roomID - room.UpdateState(event) - s.notifyListeners(event) - } - } - } - return -} - -// OnEventType allows callers to be notified when there are new events for the given event type. -// There are no duplicate checks. -func (s *DefaultSyncer) OnEventType(eventType EventType, callback OnEventListener) { - _, exists := s.listeners[eventType] - if !exists { - s.listeners[eventType] = []OnEventListener{} - } - s.listeners[eventType] = append(s.listeners[eventType], callback) -} - -// shouldProcessResponse returns true if the response should be processed. May modify the response to remove -// stuff that shouldn't be processed. -func (s *DefaultSyncer) shouldProcessResponse(resp *RespSync, since string) bool { - if since == "" { - return false - } - // This is a horrible hack because /sync will return the most recent messages for a room - // as soon as you /join it. We do NOT want to process those events in that particular room - // because they may have already been processed (if you toggle the bot in/out of the room). - // - // Work around this by inspecting each room's timeline and seeing if an m.room.member event for us - // exists and is "join" and then discard processing that room entirely if so. - // TODO: We probably want to process messages from after the last join event in the timeline. - for roomID, roomData := range resp.Rooms.Join { - for i := len(roomData.Timeline.Events) - 1; i >= 0; i-- { - e := roomData.Timeline.Events[i] - if e.Type == StateMember && e.GetStateKey() == s.UserID { - if e.Content.Membership == "join" { - _, ok := resp.Rooms.Join[roomID] - if !ok { - continue - } - delete(resp.Rooms.Join, roomID) // don't re-process messages - delete(resp.Rooms.Invite, roomID) // don't re-process invites - break - } - } - } - } - return true -} - -// getOrCreateRoom must only be called by the Sync() goroutine which calls ProcessResponse() -func (s *DefaultSyncer) getOrCreateRoom(roomID string) *Room { - room := s.Store.LoadRoom(roomID) - if room == nil { // create a new Room - room = NewRoom(roomID) - s.Store.SaveRoom(room) - } - return room -} - -func (s *DefaultSyncer) notifyListeners(event *Event) { - listeners, exists := s.listeners[event.Type] - if !exists { - return - } - for _, fn := range listeners { - fn(event) - } -} - -// OnFailedSync always returns a 10 second wait period between failed /syncs, never a fatal error. -func (s *DefaultSyncer) OnFailedSync(res *RespSync, err error) (time.Duration, error) { - return 10 * time.Second, nil -} - -// GetFilterJSON returns a filter with a timeline limit of 50. -func (s *DefaultSyncer) GetFilterJSON(userID string) json.RawMessage { - return json.RawMessage(`{"room":{"timeline":{"limit":50}}}`) -} diff --git a/vendor/maunium.net/go/mautrix/userids.go b/vendor/maunium.net/go/mautrix/userids.go deleted file mode 100644 index ce6e02d..0000000 --- a/vendor/maunium.net/go/mautrix/userids.go +++ /dev/null @@ -1,130 +0,0 @@ -package mautrix - -import ( - "bytes" - "encoding/hex" - "fmt" - "strings" -) - -const lowerhex = "0123456789abcdef" - -// encode the given byte using quoted-printable encoding (e.g "=2f") -// and writes it to the buffer -// See https://golang.org/src/mime/quotedprintable/writer.go -func encode(buf *bytes.Buffer, b byte) { - buf.WriteByte('=') - buf.WriteByte(lowerhex[b>>4]) - buf.WriteByte(lowerhex[b&0x0f]) -} - -// escape the given alpha character and writes it to the buffer -func escape(buf *bytes.Buffer, b byte) { - buf.WriteByte('_') - if b == '_' { - buf.WriteByte('_') // another _ - } else { - buf.WriteByte(b + 0x20) // ASCII shift A-Z to a-z - } -} - -func shouldEncode(b byte) bool { - return b != '-' && b != '.' && b != '_' && !(b >= '0' && b <= '9') && !(b >= 'a' && b <= 'z') && !(b >= 'A' && b <= 'Z') -} - -func shouldEscape(b byte) bool { - return (b >= 'A' && b <= 'Z') || b == '_' -} - -func isValidByte(b byte) bool { - return isValidEscapedChar(b) || (b >= '0' && b <= '9') || b == '.' || b == '=' || b == '-' -} - -func isValidEscapedChar(b byte) bool { - return b == '_' || (b >= 'a' && b <= 'z') -} - -// EncodeUserLocalpart encodes the given string into Matrix-compliant user ID localpart form. -// See http://matrix.org/docs/spec/intro.html#mapping-from-other-character-sets -// -// This returns a string with only the characters "a-z0-9._=-". The uppercase range A-Z -// are encoded using leading underscores ("_"). Characters outside the aforementioned ranges -// (including literal underscores ("_") and equals ("=")) are encoded as UTF8 code points (NOT NCRs) -// and converted to lower-case hex with a leading "=". For example: -// Alph@Bet_50up => _alph=40_bet=5f50up -func EncodeUserLocalpart(str string) string { - strBytes := []byte(str) - var outputBuffer bytes.Buffer - for _, b := range strBytes { - if shouldEncode(b) { - encode(&outputBuffer, b) - } else if shouldEscape(b) { - escape(&outputBuffer, b) - } else { - outputBuffer.WriteByte(b) - } - } - return outputBuffer.String() -} - -// DecodeUserLocalpart decodes the given string back into the original input string. -// Returns an error if the given string is not a valid user ID localpart encoding. -// See http://matrix.org/docs/spec/intro.html#mapping-from-other-character-sets -// -// This decodes quoted-printable bytes back into UTF8, and unescapes casing. For -// example: -// _alph=40_bet=5f50up => Alph@Bet_50up -// Returns an error if the input string contains characters outside the -// range "a-z0-9._=-", has an invalid quote-printable byte (e.g. not hex), or has -// an invalid _ escaped byte (e.g. "_5"). -func DecodeUserLocalpart(str string) (string, error) { - strBytes := []byte(str) - var outputBuffer bytes.Buffer - for i := 0; i < len(strBytes); i++ { - b := strBytes[i] - if !isValidByte(b) { - return "", fmt.Errorf("Byte pos %d: Invalid byte", i) - } - - if b == '_' { // next byte is a-z and should be upper-case or is another _ and should be a literal _ - if i+1 >= len(strBytes) { - return "", fmt.Errorf("Byte pos %d: expected _[a-z_] encoding but ran out of string", i) - } - if !isValidEscapedChar(strBytes[i+1]) { // invalid escaping - return "", fmt.Errorf("Byte pos %d: expected _[a-z_] encoding", i) - } - if strBytes[i+1] == '_' { - outputBuffer.WriteByte('_') - } else { - outputBuffer.WriteByte(strBytes[i+1] - 0x20) // ASCII shift a-z to A-Z - } - i++ // skip next byte since we just handled it - } else if b == '=' { // next 2 bytes are hex and should be buffered ready to be read as utf8 - if i+2 >= len(strBytes) { - return "", fmt.Errorf("Byte pos: %d: expected quote-printable encoding but ran out of string", i) - } - dst := make([]byte, 1) - _, err := hex.Decode(dst, strBytes[i+1:i+3]) - if err != nil { - return "", err - } - outputBuffer.WriteByte(dst[0]) - i += 2 // skip next 2 bytes since we just handled it - } else { // pass through - outputBuffer.WriteByte(b) - } - } - return outputBuffer.String(), nil -} - -// ExtractUserLocalpart extracts the localpart portion of a user ID. -// See http://matrix.org/docs/spec/intro.html#user-identifiers -func ExtractUserLocalpart(userID string) (string, error) { - if len(userID) == 0 || userID[0] != '@' { - return "", fmt.Errorf("%s is not a valid user id", userID) - } - return strings.TrimPrefix( - strings.SplitN(userID, ":", 2)[0], // @foo:bar:8448 => [ "@foo", "bar:8448" ] - "@", // remove "@" prefix - ), nil -} |