mirror of
				https://github.com/matrix-org/gomatrix
				synced 2025-11-04 06:18:05 +00:00 
			
		
		
		
	Merge branch 'master' into add-send-html
This commit is contained in:
		
						commit
						f1931f45c1
					
				
					 19 changed files with 681 additions and 131 deletions
				
			
		
							
								
								
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
*.o
 | 
			
		||||
*.a
 | 
			
		||||
*.so
 | 
			
		||||
*.out
 | 
			
		||||
 | 
			
		||||
# Folders
 | 
			
		||||
_obj
 | 
			
		||||
| 
						 | 
				
			
			@ -22,3 +23,6 @@ _testmain.go
 | 
			
		|||
*.exe
 | 
			
		||||
*.test
 | 
			
		||||
*.prof
 | 
			
		||||
 | 
			
		||||
# test editor files
 | 
			
		||||
*.swp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								.golangci.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.golangci.yml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
run:
 | 
			
		||||
  timeout: 5m
 | 
			
		||||
  linters:
 | 
			
		||||
    enable:
 | 
			
		||||
      - vet
 | 
			
		||||
      - vetshadow
 | 
			
		||||
      - typecheck
 | 
			
		||||
      - deadcode
 | 
			
		||||
      - gocyclo
 | 
			
		||||
      - golint
 | 
			
		||||
      - varcheck
 | 
			
		||||
      - structcheck
 | 
			
		||||
      - maligned
 | 
			
		||||
      - ineffassign
 | 
			
		||||
      - misspell
 | 
			
		||||
      - unparam
 | 
			
		||||
      - goimports
 | 
			
		||||
      - goconst
 | 
			
		||||
      - unconvert
 | 
			
		||||
      - errcheck
 | 
			
		||||
      - interfacer
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,7 @@
 | 
			
		|||
language: go
 | 
			
		||||
go:
 | 
			
		||||
 - 1.10.x
 | 
			
		||||
 - 1.13.10
 | 
			
		||||
install:
 | 
			
		||||
 - go get github.com/golang/lint/golint
 | 
			
		||||
 - go get github.com/fzipp/gocyclo
 | 
			
		||||
 - go get github.com/client9/misspell/...
 | 
			
		||||
 - go get github.com/gordonklaus/ineffassign
 | 
			
		||||
 - go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.24.0
 | 
			
		||||
 - go build
 | 
			
		||||
script: ./hooks/pre-commit
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								CHANGELOG.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								CHANGELOG.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
## Release 0.1.0 (UNRELEASED)
 | 
			
		||||
							
								
								
									
										65
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										65
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,3 +4,68 @@
 | 
			
		|||
A Golang Matrix client.
 | 
			
		||||
 | 
			
		||||
**THIS IS UNDER ACTIVE DEVELOPMENT: BREAKING CHANGES ARE FREQUENT.**
 | 
			
		||||
 | 
			
		||||
# Contributing
 | 
			
		||||
 | 
			
		||||
All contributions are greatly appreciated!
 | 
			
		||||
 | 
			
		||||
## How to report issues
 | 
			
		||||
 | 
			
		||||
Please check the current open issues for similar reports
 | 
			
		||||
in order to avoid duplicates.
 | 
			
		||||
 | 
			
		||||
Some general guidelines:
 | 
			
		||||
 | 
			
		||||
-   Include a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) when possible.
 | 
			
		||||
-   Describe the expected behaviour and what actually happened
 | 
			
		||||
    including a full trace-back in case of exceptions.
 | 
			
		||||
-   Make sure to list details about your environment
 | 
			
		||||
 | 
			
		||||
## Setting up your environment
 | 
			
		||||
 | 
			
		||||
If you intend to contribute to gomatrix you'll first need Go installed on your machine (version 1.12+ is required). Also, make sure to have golangci-lint properly set up since we use it for pre-commit hooks (for instructions on how to install it, check the [official docs](https://golangci-lint.run/usage/install/#local-installation)).
 | 
			
		||||
 | 
			
		||||
-   Fork gomatrix to your GitHub account by clicking the [Fork](https://github.com/matrix-org/gomatrix/fork) button.
 | 
			
		||||
-   [Clone](https://help.github.com/en/articles/fork-a-repo#step-2-create-a-local-clone-of-your-fork) the main repository (not your fork) to your local machine.
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        $ git clone https://github.com/matrix-org/gomatrix
 | 
			
		||||
        $ cd gomatrix
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
-   Add your fork as a remote to push your contributions.Replace
 | 
			
		||||
    ``{username}`` with your username.
 | 
			
		||||
 | 
			
		||||
        git remote add fork https://github.com/{username}/gomatrix
 | 
			
		||||
 | 
			
		||||
-   Create a new branch to identify what feature you are working on.
 | 
			
		||||
 | 
			
		||||
        $ git fetch origin
 | 
			
		||||
        $ git checkout -b your-branch-name origin/master
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
-   Make your changes, including tests that cover any code changes you make, and run them as described below.
 | 
			
		||||
 | 
			
		||||
-   Execute pre-commit hooks by running 
 | 
			
		||||
 | 
			
		||||
        <gomatrix dir>/hooks/pre-commit
 | 
			
		||||
 | 
			
		||||
-   Push your changes to your fork and [create a pull request](https://help.github.com/en/articles/creating-a-pull-request) describing your changes.
 | 
			
		||||
 | 
			
		||||
        $ git push --set-upstream fork your-branch-name
 | 
			
		||||
 | 
			
		||||
-   Finally, create a [pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
 | 
			
		||||
 | 
			
		||||
## How to run tests
 | 
			
		||||
 | 
			
		||||
You can run the test suite and example code with `$ go test -v`
 | 
			
		||||
 | 
			
		||||
# Running Coverage
 | 
			
		||||
 | 
			
		||||
To run coverage, first generate the coverage report using `go test`
 | 
			
		||||
 | 
			
		||||
    go test -v -cover -coverprofile=coverage.out
 | 
			
		||||
 | 
			
		||||
You can now show the generated report as a html page with `go tool`
 | 
			
		||||
 | 
			
		||||
    go tool cover -html=coverage.out
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										248
									
								
								client.go
									
										
									
									
									
								
							
							
						
						
									
										248
									
								
								client.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -13,6 +13,7 @@ import (
 | 
			
		|||
	"net/url"
 | 
			
		||||
	"path"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +39,7 @@ type Client struct {
 | 
			
		|||
 | 
			
		||||
// HTTPError An HTTP Error response, which may wrap an underlying native Go Error.
 | 
			
		||||
type HTTPError struct {
 | 
			
		||||
	Contents     []byte
 | 
			
		||||
	WrappedError error
 | 
			
		||||
	Message      string
 | 
			
		||||
	Code         int
 | 
			
		||||
| 
						 | 
				
			
			@ -48,19 +50,16 @@ func (e HTTPError) Error() string {
 | 
			
		|||
	if e.WrappedError != nil {
 | 
			
		||||
		wrappedErrMsg = e.WrappedError.Error()
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("msg=%s code=%d wrapped=%s", e.Message, e.Code, wrappedErrMsg)
 | 
			
		||||
	return fmt.Sprintf("contents=%v msg=%s code=%d wrapped=%s", e.Contents, e.Message, e.Code, wrappedErrMsg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildURL builds a URL with the Client's homserver/prefix/access_token set already.
 | 
			
		||||
// BuildURL builds a URL with the Client's homeserver/prefix set already.
 | 
			
		||||
func (cli *Client) BuildURL(urlPath ...string) string {
 | 
			
		||||
	ps := []string{cli.Prefix}
 | 
			
		||||
	for _, p := range urlPath {
 | 
			
		||||
		ps = append(ps, p)
 | 
			
		||||
	}
 | 
			
		||||
	ps := append([]string{cli.Prefix}, urlPath...)
 | 
			
		||||
	return cli.BuildBaseURL(ps...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildBaseURL builds a URL with the Client's homeserver/access_token set already. You must
 | 
			
		||||
// BuildBaseURL builds a URL with the Client's homeserver 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
 | 
			
		||||
| 
						 | 
				
			
			@ -68,10 +67,11 @@ func (cli *Client) BuildBaseURL(urlPath ...string) 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)
 | 
			
		||||
	// Manually add the trailing slash back to the end of the path if it's explicitly needed
 | 
			
		||||
	if strings.HasSuffix(urlPath[len(urlPath)-1], "/") {
 | 
			
		||||
		hsURL.Path = hsURL.Path + "/"
 | 
			
		||||
	}
 | 
			
		||||
	query := hsURL.Query()
 | 
			
		||||
	if cli.AppServiceUserID != "" {
 | 
			
		||||
		query.Set("user_id", cli.AppServiceUserID)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +79,7 @@ func (cli *Client) BuildBaseURL(urlPath ...string) string {
 | 
			
		|||
	return hsURL.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildURLWithQuery builds a URL with query parameters in addition to the Client's homeserver/prefix/access_token set already.
 | 
			
		||||
// BuildURLWithQuery builds a URL with query parameters in addition to the Client's homeserver/prefix set already.
 | 
			
		||||
func (cli *Client) BuildURLWithQuery(urlPath []string, urlQuery map[string]string) string {
 | 
			
		||||
	u, _ := url.Parse(cli.BuildURL(urlPath...))
 | 
			
		||||
	q := u.Query()
 | 
			
		||||
| 
						 | 
				
			
			@ -178,38 +178,48 @@ func (cli *Client) StopSync() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// MakeRequest makes a JSON HTTP request to the given URL.
 | 
			
		||||
// If "resBody" is not nil, the response body will be json.Unmarshalled into it.
 | 
			
		||||
// The response body will be stream decoded into an interface. This will automatically stop if the response
 | 
			
		||||
// body is nil.
 | 
			
		||||
//
 | 
			
		||||
// 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) {
 | 
			
		||||
// 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, byte contents of the response body 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{}) error {
 | 
			
		||||
	var req *http.Request
 | 
			
		||||
	var err error
 | 
			
		||||
	if reqBody != nil {
 | 
			
		||||
		var jsonStr []byte
 | 
			
		||||
		jsonStr, err = json.Marshal(reqBody)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		if err := json.NewEncoder(buf).Encode(reqBody); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		req, err = http.NewRequest(method, httpURL, bytes.NewBuffer(jsonStr))
 | 
			
		||||
		req, err = http.NewRequest(method, httpURL, buf)
 | 
			
		||||
	} else {
 | 
			
		||||
		req, err = http.NewRequest(method, httpURL, nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req.Header.Set("Content-Type", "application/json")
 | 
			
		||||
 | 
			
		||||
	if cli.AccessToken != "" {
 | 
			
		||||
		req.Header.Set("Authorization", "Bearer "+cli.AccessToken)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := cli.Client.Do(req)
 | 
			
		||||
	if res != nil {
 | 
			
		||||
		defer res.Body.Close()
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	contents, err := ioutil.ReadAll(res.Body)
 | 
			
		||||
	if res.StatusCode/100 != 2 { // not 2xx
 | 
			
		||||
		contents, err := ioutil.ReadAll(res.Body)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var wrap error
 | 
			
		||||
		var respErr RespError
 | 
			
		||||
		if _ = json.Unmarshal(contents, &respErr); respErr.ErrCode != "" {
 | 
			
		||||
| 
						 | 
				
			
			@ -223,29 +233,25 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{
 | 
			
		|||
			msg = msg + ": " + string(contents)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return contents, HTTPError{
 | 
			
		||||
		return HTTPError{
 | 
			
		||||
			Contents:     contents,
 | 
			
		||||
			Code:         res.StatusCode,
 | 
			
		||||
			Message:      msg,
 | 
			
		||||
			WrappedError: wrap,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
 | 
			
		||||
	if resBody != nil && res.Body != nil {
 | 
			
		||||
		return json.NewDecoder(res.Body).Decode(&resBody)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if resBody != nil {
 | 
			
		||||
		if err = json.Unmarshal(contents, &resBody); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return contents, nil
 | 
			
		||||
	return 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)
 | 
			
		||||
	err = cli.MakeRequest("POST", urlPath, &filter, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -267,13 +273,12 @@ func (cli *Client) SyncRequest(timeout int, since, filterID string, fullState bo
 | 
			
		|||
		query["full_state"] = "true"
 | 
			
		||||
	}
 | 
			
		||||
	urlPath := cli.BuildURLWithQuery([]string{"sync"}, query)
 | 
			
		||||
	_, err = cli.MakeRequest("GET", urlPath, nil, &resp)
 | 
			
		||||
	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)
 | 
			
		||||
	err = cli.MakeRequest("POST", u, req, &resp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		httpErr, ok := err.(HTTPError)
 | 
			
		||||
		if !ok { // network error
 | 
			
		||||
| 
						 | 
				
			
			@ -281,13 +286,10 @@ func (cli *Client) register(u string, req *ReqRegister) (resp *RespRegister, uia
 | 
			
		|||
		}
 | 
			
		||||
		if httpErr.Code == 401 {
 | 
			
		||||
			// body should be RespUserInteractive, if it isn't, fail with the error
 | 
			
		||||
			err = json.Unmarshal(bodyBytes, &uiaResp)
 | 
			
		||||
			err = json.Unmarshal(httpErr.Contents, &uiaResp)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// body should be RespRegister
 | 
			
		||||
	err = json.Unmarshal(bodyBytes, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -351,22 +353,77 @@ func (cli *Client) RegisterDummy(req *ReqRegister) (*RespRegister, error) {
 | 
			
		|||
// 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)
 | 
			
		||||
	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
 | 
			
		||||
// Logout the current user. See http://matrix.org/docs/spec/client_server/r0.6.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)
 | 
			
		||||
	err = cli.MakeRequest("POST", urlPath, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LogoutAll logs the current user out on all devices. See https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-logout-all
 | 
			
		||||
// This does not clear the credentials from the client instance. See ClearCredentails() instead.
 | 
			
		||||
func (cli *Client) LogoutAll() (resp *RespLogoutAll, err error) {
 | 
			
		||||
	urlPath := cli.BuildURL("logout/all")
 | 
			
		||||
	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)
 | 
			
		||||
	err = cli.MakeRequest("GET", urlPath, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PublicRooms returns the list of public rooms on target server. See https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-unstable-publicrooms
 | 
			
		||||
func (cli *Client) PublicRooms(limit int, since string, server string) (resp *RespPublicRooms, err error) {
 | 
			
		||||
	args := map[string]string{}
 | 
			
		||||
 | 
			
		||||
	if limit != 0 {
 | 
			
		||||
		args["limit"] = strconv.Itoa(limit)
 | 
			
		||||
	}
 | 
			
		||||
	if since != "" {
 | 
			
		||||
		args["since"] = since
 | 
			
		||||
	}
 | 
			
		||||
	if server != "" {
 | 
			
		||||
		args["server"] = server
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	urlPath := cli.BuildURLWithQuery([]string{"publicRooms"}, args)
 | 
			
		||||
	err = cli.MakeRequest("GET", urlPath, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PublicRoomsFiltered returns a subset of PublicRooms filtered server side.
 | 
			
		||||
// See https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-unstable-publicrooms
 | 
			
		||||
func (cli *Client) PublicRoomsFiltered(limit int, since string, server string, filter string) (resp *RespPublicRooms, err error) {
 | 
			
		||||
	content := map[string]string{}
 | 
			
		||||
 | 
			
		||||
	if limit != 0 {
 | 
			
		||||
		content["limit"] = strconv.Itoa(limit)
 | 
			
		||||
	}
 | 
			
		||||
	if since != "" {
 | 
			
		||||
		content["since"] = since
 | 
			
		||||
	}
 | 
			
		||||
	if filter != "" {
 | 
			
		||||
		content["filter"] = filter
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var urlPath string
 | 
			
		||||
	if server == "" {
 | 
			
		||||
		urlPath = cli.BuildURL("publicRooms")
 | 
			
		||||
	} else {
 | 
			
		||||
		urlPath = cli.BuildURLWithQuery([]string{"publicRooms"}, map[string]string{
 | 
			
		||||
			"server": server,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cli.MakeRequest("POST", urlPath, content, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -383,21 +440,21 @@ func (cli *Client) JoinRoom(roomIDorAlias, serverName string, content interface{
 | 
			
		|||
	} else {
 | 
			
		||||
		urlPath = cli.BuildURL("join", roomIDorAlias)
 | 
			
		||||
	}
 | 
			
		||||
	_, err = cli.MakeRequest("POST", urlPath, content, &resp)
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
	err = cli.MakeRequest("GET", urlPath, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -407,18 +464,18 @@ func (cli *Client) SetDisplayName(displayName string) (err error) {
 | 
			
		|||
	s := struct {
 | 
			
		||||
		DisplayName string `json:"displayname"`
 | 
			
		||||
	}{displayName}
 | 
			
		||||
	_, err = cli.MakeRequest("PUT", urlPath, &s, nil)
 | 
			
		||||
	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) {
 | 
			
		||||
func (cli *Client) GetAvatarURL() (string, error) {
 | 
			
		||||
	urlPath := cli.BuildURL("profile", cli.UserID, "avatar_url")
 | 
			
		||||
	s := struct {
 | 
			
		||||
		AvatarURL string `json:"avatar_url"`
 | 
			
		||||
	}{}
 | 
			
		||||
 | 
			
		||||
	_, err = cli.MakeRequest("GET", urlPath, nil, &s)
 | 
			
		||||
	err := cli.MakeRequest("GET", urlPath, nil, &s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -427,12 +484,12 @@ func (cli *Client) GetAvatarURL() (url string, err error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
func (cli *Client) SetAvatarURL(url string) error {
 | 
			
		||||
	urlPath := cli.BuildURL("profile", cli.UserID, "avatar_url")
 | 
			
		||||
	s := struct {
 | 
			
		||||
		AvatarURL string `json:"avatar_url"`
 | 
			
		||||
	}{url}
 | 
			
		||||
	_, err = cli.MakeRequest("PUT", urlPath, &s, nil)
 | 
			
		||||
	err := cli.MakeRequest("PUT", urlPath, &s, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -440,12 +497,35 @@ func (cli *Client) SetAvatarURL(url string) (err error) {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetStatus returns the status of the user from the specified MXID. See https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-presence-userid-status
 | 
			
		||||
func (cli *Client) GetStatus(mxid string) (resp *RespUserStatus, err error) {
 | 
			
		||||
	urlPath := cli.BuildURL("presence", mxid, "status")
 | 
			
		||||
	err = cli.MakeRequest("GET", urlPath, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetOwnStatus returns the user's status. See https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-presence-userid-status
 | 
			
		||||
func (cli *Client) GetOwnStatus() (resp *RespUserStatus, err error) {
 | 
			
		||||
	return cli.GetStatus(cli.UserID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetStatus sets the user's status. See https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-presence-userid-status
 | 
			
		||||
func (cli *Client) SetStatus(presence, status string) (err error) {
 | 
			
		||||
	urlPath := cli.BuildURL("presence", cli.UserID, "status")
 | 
			
		||||
	s := struct {
 | 
			
		||||
		Presence  string `json:"presence"`
 | 
			
		||||
		StatusMsg string `json:"status_msg"`
 | 
			
		||||
	}{presence, status}
 | 
			
		||||
	err = cli.MakeRequest("PUT", urlPath, &s, nil)
 | 
			
		||||
	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) SendMessageEvent(roomID string, eventType string, contentJSON interface{}) (resp *RespSendEvent, err error) {
 | 
			
		||||
	txnID := txnID()
 | 
			
		||||
	urlPath := cli.BuildURL("rooms", roomID, "send", eventType, txnID)
 | 
			
		||||
	_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
 | 
			
		||||
	err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -453,7 +533,7 @@ func (cli *Client) SendMessageEvent(roomID string, eventType string, contentJSON
 | 
			
		|||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
 | 
			
		||||
func (cli *Client) SendStateEvent(roomID, eventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) {
 | 
			
		||||
	urlPath := cli.BuildURL("rooms", roomID, "state", eventType, stateKey)
 | 
			
		||||
	_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
 | 
			
		||||
	err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -461,7 +541,14 @@ func (cli *Client) SendStateEvent(roomID, eventType, stateKey string, contentJSO
 | 
			
		|||
// 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, "m.room.message",
 | 
			
		||||
		TextMessage{"m.text", text})
 | 
			
		||||
		TextMessage{MsgType: "m.text", Body: text})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SendFormattedText sends an m.room.message event into the given room with a msgtype of m.text, supports a subset of HTML for formatting.
 | 
			
		||||
// See https://matrix.org/docs/spec/client_server/r0.6.0#m-text
 | 
			
		||||
func (cli *Client) SendFormattedText(roomID, text, formattedText string) (*RespSendEvent, error) {
 | 
			
		||||
	return cli.SendMessageEvent(roomID, "m.room.message",
 | 
			
		||||
		TextMessage{MsgType: "m.text", Body: text, FormattedBody: formattedText, Format: "org.matrix.custom.html"})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SendHTML sends an m.room.message event into the given room with a msgtype of m.text and using the org.matrix.custom.html formatting.
 | 
			
		||||
| 
						 | 
				
			
			@ -500,17 +587,23 @@ func (cli *Client) SendVideo(roomID, body, url string) (*RespSendEvent, error) {
 | 
			
		|||
// 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, "m.room.message",
 | 
			
		||||
		TextMessage{"m.notice", text})
 | 
			
		||||
		TextMessage{MsgType: "m.notice", 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)
 | 
			
		||||
	err = cli.MakeRequest("PUT", urlPath, req, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarkRead marks eventID in roomID as read, signifying the event, and all before it have been read. See https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-receipt-receipttype-eventid
 | 
			
		||||
func (cli *Client) MarkRead(roomID, eventID string) error {
 | 
			
		||||
	urlPath := cli.BuildURL("rooms", roomID, "receipt", "m.read", eventID)
 | 
			
		||||
	return cli.MakeRequest("POST", urlPath, nil, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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(&gomatrix.ReqCreateRoom{
 | 
			
		||||
//  	Preset: "public_chat",
 | 
			
		||||
| 
						 | 
				
			
			@ -518,56 +611,56 @@ func (cli *Client) RedactEvent(roomID, eventID string, req *ReqRedact) (resp *Re
 | 
			
		|||
//  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)
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
	err = cli.MakeRequest("POST", u, req, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -575,7 +668,7 @@ func (cli *Client) UnbanUser(roomID string, req *ReqUnbanUser) (resp *RespUnbanU
 | 
			
		|||
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)
 | 
			
		||||
	err = cli.MakeRequest("PUT", u, req, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -584,7 +677,7 @@ func (cli *Client) UserTyping(roomID string, typing bool, timeout int64) (resp *
 | 
			
		|||
// 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, eventType, stateKey string, outContent interface{}) (err error) {
 | 
			
		||||
	u := cli.BuildURL("rooms", roomID, "state", eventType, stateKey)
 | 
			
		||||
	_, err = cli.MakeRequest("GET", u, nil, outContent)
 | 
			
		||||
	err = cli.MakeRequest("GET", u, nil, outContent)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -607,15 +700,21 @@ func (cli *Client) UploadToContentRepo(content io.Reader, contentType string, co
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req.Header.Set("Content-Type", contentType)
 | 
			
		||||
	req.Header.Set("Authorization", "Bearer "+cli.AccessToken)
 | 
			
		||||
 | 
			
		||||
	req.ContentLength = 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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -625,14 +724,17 @@ func (cli *Client) UploadToContentRepo(content io.Reader, contentType string, co
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nil, HTTPError{
 | 
			
		||||
			Contents: contents,
 | 
			
		||||
			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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -642,7 +744,7 @@ func (cli *Client) UploadToContentRepo(content io.Reader, contentType string, co
 | 
			
		|||
// 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)
 | 
			
		||||
	err = cli.MakeRequest("GET", u, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -652,7 +754,7 @@ func (cli *Client) JoinedMembers(roomID string) (resp *RespJoinedMembers, err er
 | 
			
		|||
// 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)
 | 
			
		||||
	err = cli.MakeRequest("GET", u, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -672,7 +774,7 @@ func (cli *Client) Messages(roomID, from, to string, dir rune, limit int) (resp
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "messages"}, query)
 | 
			
		||||
	_, err = cli.MakeRequest("GET", urlPath, nil, &resp)
 | 
			
		||||
	err = cli.MakeRequest("GET", urlPath, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -680,7 +782,7 @@ func (cli *Client) Messages(roomID, from, to string, dir rune, limit int) (resp
 | 
			
		|||
// 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)
 | 
			
		||||
	err = cli.MakeRequest("GET", urlPath, nil, &resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ func Example_customInterfaces() {
 | 
			
		|||
	cli.Client = http.DefaultClient
 | 
			
		||||
 | 
			
		||||
	// Once you call a function, you can't safely change the interfaces.
 | 
			
		||||
	cli.SendText("!foo:bar", "Down the rabbit hole")
 | 
			
		||||
	_, _ = cli.SendText("!foo:bar", "Down the rabbit hole")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ExampleClient_BuildURLWithQuery() {
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ func ExampleClient_BuildURLWithQuery() {
 | 
			
		|||
		"filter_id": "5",
 | 
			
		||||
	})
 | 
			
		||||
	fmt.Println(out)
 | 
			
		||||
	// Output: https://matrix.org/_matrix/client/r0/sync?access_token=abcdef123456&filter_id=5
 | 
			
		||||
	// Output: https://matrix.org/_matrix/client/r0/sync?filter_id=5
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ExampleClient_BuildURL() {
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ func ExampleClient_BuildURL() {
 | 
			
		|||
	cli, _ := NewClient("https://matrix.org", userID, "abcdef123456")
 | 
			
		||||
	out := cli.BuildURL("user", userID, "filter")
 | 
			
		||||
	fmt.Println(out)
 | 
			
		||||
	// Output: https://matrix.org/_matrix/client/r0/user/@example:matrix.org/filter?access_token=abcdef123456
 | 
			
		||||
	// Output: https://matrix.org/_matrix/client/r0/user/@example:matrix.org/filter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ExampleClient_BuildBaseURL() {
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +71,7 @@ func ExampleClient_BuildBaseURL() {
 | 
			
		|||
	cli, _ := NewClient("https://matrix.org", userID, "abcdef123456")
 | 
			
		||||
	out := cli.BuildBaseURL("_matrix", "client", "r0", "directory", "room", "#matrix:matrix.org")
 | 
			
		||||
	fmt.Println(out)
 | 
			
		||||
	// Output: https://matrix.org/_matrix/client/r0/directory/room/%23matrix:matrix.org?access_token=abcdef123456
 | 
			
		||||
	// Output: https://matrix.org/_matrix/client/r0/directory/room/%23matrix:matrix.org
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retrieve the content of a m.room.name state event.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,6 +84,55 @@ func TestClient_StateEvent(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestClient_PublicRooms(t *testing.T) {
 | 
			
		||||
	cli := mockClient(func(req *http.Request) (*http.Response, error) {
 | 
			
		||||
		if req.Method == "GET" && req.URL.Path == "/_matrix/client/r0/publicRooms" {
 | 
			
		||||
			return &http.Response{
 | 
			
		||||
				StatusCode: 200,
 | 
			
		||||
				Body: ioutil.NopCloser(bytes.NewBufferString(`{
 | 
			
		||||
  "chunk": [
 | 
			
		||||
    {
 | 
			
		||||
      "aliases": [
 | 
			
		||||
        "#murrays:cheese.bar"
 | 
			
		||||
      ],
 | 
			
		||||
      "avatar_url": "mxc://bleeker.street/CHEDDARandBRIE",
 | 
			
		||||
      "guest_can_join": false,
 | 
			
		||||
      "name": "CHEESE",
 | 
			
		||||
      "num_joined_members": 37,
 | 
			
		||||
      "room_id": "!ol19s:bleecker.street",
 | 
			
		||||
      "topic": "Tasty tasty cheese",
 | 
			
		||||
      "world_readable": true
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "next_batch": "p190q",
 | 
			
		||||
  "prev_batch": "p1902",
 | 
			
		||||
  "total_room_count_estimate": 115
 | 
			
		||||
}`)),
 | 
			
		||||
			}, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, fmt.Errorf("unhandled URL: %s", req.URL.Path)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	publicRooms, err := cli.PublicRooms(0, "", "")
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("PublicRooms: error, got %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	if publicRooms.TotalRoomCountEstimate != 115 {
 | 
			
		||||
		t.Fatalf("PublicRooms: got %d, want %d", publicRooms.TotalRoomCountEstimate, 115)
 | 
			
		||||
	}
 | 
			
		||||
	if len(publicRooms.Chunk) != 1 {
 | 
			
		||||
		t.Fatalf("PublicRooms: got %d, want %d", len(publicRooms.Chunk), 1)
 | 
			
		||||
	}
 | 
			
		||||
	if publicRooms.Chunk[0].Name != "CHEESE" {
 | 
			
		||||
		t.Fatalf("PublicRooms: got %s, want %s", publicRooms.Chunk[0].Name, "CHEESE")
 | 
			
		||||
	}
 | 
			
		||||
	if publicRooms.Chunk[0].NumJoinedMembers != 37 {
 | 
			
		||||
		t.Fatalf("PublicRooms: got %d, want %d", publicRooms.Chunk[0].NumJoinedMembers, 37)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mockClient(fn func(*http.Request) (*http.Response, error)) *Client {
 | 
			
		||||
	mrt := MockRoundTripper{
 | 
			
		||||
		RT: fn,
 | 
			
		||||
| 
						 | 
				
			
			@ -101,5 +150,8 @@ type MockRoundTripper struct {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (t MockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
 | 
			
		||||
	if req.Header.Get("Authorization") == "" {
 | 
			
		||||
		panic("no auth")
 | 
			
		||||
	}
 | 
			
		||||
	return t.RT(req)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										59
									
								
								events.go
									
										
									
									
									
								
							
							
						
						
									
										59
									
								
								events.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -13,8 +13,10 @@ type Event struct {
 | 
			
		|||
	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   map[string]interface{} `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    map[string]interface{} `json:"unsigned"`               // The unsigned portions of the event, such as age and prev_content
 | 
			
		||||
	Content     map[string]interface{} `json:"content"`                // The JSON content of the event.
 | 
			
		||||
	PrevContent map[string]interface{} `json:"prev_content,omitempty"` // The JSON prev_content of the event.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Body returns the value of the "body" key in the event content if it is
 | 
			
		||||
| 
						 | 
				
			
			@ -43,6 +45,16 @@ func (event *Event) MessageType() (msgtype string, ok bool) {
 | 
			
		|||
type TextMessage struct {
 | 
			
		||||
	MsgType       string `json:"msgtype"`
 | 
			
		||||
	Body          string `json:"body"`
 | 
			
		||||
	FormattedBody string `json:"formatted_body"`
 | 
			
		||||
	Format        string `json:"format"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ThumbnailInfo contains info about an thumbnail image - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-image
 | 
			
		||||
type ThumbnailInfo struct {
 | 
			
		||||
	Height   uint   `json:"h,omitempty"`
 | 
			
		||||
	Width    uint   `json:"w,omitempty"`
 | 
			
		||||
	Mimetype string `json:"mimetype,omitempty"`
 | 
			
		||||
	Size     uint   `json:"size,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ImageInfo contains info about an image - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-image
 | 
			
		||||
| 
						 | 
				
			
			@ -51,12 +63,14 @@ type ImageInfo struct {
 | 
			
		|||
	Width         uint          `json:"w,omitempty"`
 | 
			
		||||
	Mimetype      string        `json:"mimetype,omitempty"`
 | 
			
		||||
	Size          uint          `json:"size,omitempty"`
 | 
			
		||||
	ThumbnailInfo ThumbnailInfo `json:"thumbnail_info,omitempty"`
 | 
			
		||||
	ThumbnailURL  string        `json:"thumbnail_url,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VideoInfo contains info about a video - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-video
 | 
			
		||||
type VideoInfo struct {
 | 
			
		||||
	Mimetype      string        `json:"mimetype,omitempty"`
 | 
			
		||||
	ThumbnailInfo ImageInfo `json:"thumbnail_info"`
 | 
			
		||||
	ThumbnailInfo ThumbnailInfo `json:"thumbnail_info"`
 | 
			
		||||
	ThumbnailURL  string        `json:"thumbnail_url,omitempty"`
 | 
			
		||||
	Height        uint          `json:"h,omitempty"`
 | 
			
		||||
	Width         uint          `json:"w,omitempty"`
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +102,47 @@ type HTMLMessage struct {
 | 
			
		|||
	FormattedBody string `json:"formatted_body"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FileInfo contains info about an file - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-file
 | 
			
		||||
type FileInfo struct {
 | 
			
		||||
	Mimetype string `json:"mimetype,omitempty"`
 | 
			
		||||
	Size     uint   `json:"size,omitempty"` //filesize in bytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FileMessage is an m.file event - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-file
 | 
			
		||||
type FileMessage struct {
 | 
			
		||||
	MsgType       string    `json:"msgtype"`
 | 
			
		||||
	Body          string    `json:"body"`
 | 
			
		||||
	URL           string    `json:"url"`
 | 
			
		||||
	Filename      string    `json:"filename"`
 | 
			
		||||
	Info          FileInfo  `json:"info,omitempty"`
 | 
			
		||||
	ThumbnailURL  string    `json:"thumbnail_url,omitempty"`
 | 
			
		||||
	ThumbnailInfo ImageInfo `json:"thumbnail_info,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LocationMessage is an m.location event - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-location
 | 
			
		||||
type LocationMessage struct {
 | 
			
		||||
	MsgType       string    `json:"msgtype"`
 | 
			
		||||
	Body          string    `json:"body"`
 | 
			
		||||
	GeoURI        string    `json:"geo_uri"`
 | 
			
		||||
	ThumbnailURL  string    `json:"thumbnail_url,omitempty"`
 | 
			
		||||
	ThumbnailInfo ImageInfo `json:"thumbnail_info,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AudioInfo contains info about an file - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-audio
 | 
			
		||||
type AudioInfo struct {
 | 
			
		||||
	Mimetype string `json:"mimetype,omitempty"`
 | 
			
		||||
	Size     uint   `json:"size,omitempty"`     //filesize in bytes
 | 
			
		||||
	Duration uint   `json:"duration,omitempty"` //audio duration in ms
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AudioMessage is an m.audio event - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-audio
 | 
			
		||||
type AudioMessage struct {
 | 
			
		||||
	MsgType string    `json:"msgtype"`
 | 
			
		||||
	Body    string    `json:"body"`
 | 
			
		||||
	URL     string    `json:"url"`
 | 
			
		||||
	Info    AudioInfo `json:"info,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var htmlRegex = regexp.MustCompile("<[^<]+?>")
 | 
			
		||||
 | 
			
		||||
// GetHTMLMessage returns an HTMLMessage with the body set to a stripped version of the provided HTML, in addition
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										110
									
								
								events_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								events_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,110 @@
 | 
			
		|||
package gomatrix
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// example events from docs
 | 
			
		||||
var testEvents = map[string]string{
 | 
			
		||||
	"withFields": `{
 | 
			
		||||
        "content": {
 | 
			
		||||
            "body": "eventbody123",
 | 
			
		||||
            "msgtype": "m.text",
 | 
			
		||||
            "format": "org.matrix.custom.html",
 | 
			
		||||
            "formatted_body": "<b>This is an example text message</b>"
 | 
			
		||||
        },
 | 
			
		||||
        "type": "m.room.message",
 | 
			
		||||
        "event_id": "$143273582443PhrSn:example.org",
 | 
			
		||||
        "room_id": "!726s6s6q:example.com",
 | 
			
		||||
        "sender": "@example:example.org",
 | 
			
		||||
        "origin_server_ts": 1432735824653,
 | 
			
		||||
        "unsigned": {
 | 
			
		||||
            "age": 1234
 | 
			
		||||
        }
 | 
			
		||||
    }`,
 | 
			
		||||
 | 
			
		||||
	"withoutFields": `{
 | 
			
		||||
        "content": {
 | 
			
		||||
            "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
 | 
			
		||||
            "displayname": "Alice Margatroid",
 | 
			
		||||
            "membership": "join"
 | 
			
		||||
        },
 | 
			
		||||
        "event_id": "$143273582443PhrSn:example.org",
 | 
			
		||||
        "origin_server_ts": 1432735824653,
 | 
			
		||||
        "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
 | 
			
		||||
        "sender": "@example:example.org",
 | 
			
		||||
        "state_key": "@alice:example.org",
 | 
			
		||||
        "type": "m.room.member",
 | 
			
		||||
        "unsigned": {
 | 
			
		||||
            "age": 1234
 | 
			
		||||
        }
 | 
			
		||||
    }`,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEventWithBody(t *testing.T) {
 | 
			
		||||
	var e Event
 | 
			
		||||
	err := json.NewDecoder(strings.NewReader(testEvents["withFields"])).Decode(&e)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("TestFetchEventBody: Something went wrong while parsing: %s", testEvents["withFields"])
 | 
			
		||||
	}
 | 
			
		||||
	body, ok := e.Body()
 | 
			
		||||
	if !ok || body != "eventbody123" {
 | 
			
		||||
		t.Fatal("TestEventWithBody: Failed to fetch value of 'body' key in event content")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEventWithoutBody(t *testing.T) {
 | 
			
		||||
	var e Event
 | 
			
		||||
	err := json.NewDecoder(strings.NewReader(testEvents["withoutFields"])).Decode(&e)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("TestEventWithoutBody: Something went wrong while parsing: %s", testEvents["withFields"])
 | 
			
		||||
	}
 | 
			
		||||
	body, ok := e.Body()
 | 
			
		||||
	if ok || body != "" {
 | 
			
		||||
		t.Fatal("TestEventWithoutBody: Failed on 'Event.Body' call for event without a 'body' key")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEventWithMessageType(t *testing.T) {
 | 
			
		||||
	var e Event
 | 
			
		||||
	err := json.NewDecoder(strings.NewReader(testEvents["withFields"])).Decode(&e)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("TestEventWithMessageType: Something went wrong while parsing: %s", testEvents["withFields"])
 | 
			
		||||
	}
 | 
			
		||||
	msgtype, ok := e.MessageType()
 | 
			
		||||
	if !ok || msgtype != "m.text" {
 | 
			
		||||
		t.Fatal("TestEventWithMessageType: Failed to fetch value of 'msgtype' key in event content")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEventWithoutMessageType(t *testing.T) {
 | 
			
		||||
	var e Event
 | 
			
		||||
	err := json.NewDecoder(strings.NewReader(testEvents["withoutFields"])).Decode(&e)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("TestEventWithMessageType: Something went wrong while parsing: %s", testEvents["withFields"])
 | 
			
		||||
	}
 | 
			
		||||
	msgtype, ok := e.MessageType()
 | 
			
		||||
	if ok || msgtype != "" {
 | 
			
		||||
		t.Fatal("TestEventWithoutBody: Failed on 'Event.Body' call for event without a 'msgtype' key")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var testHTML = `<div>a<h1>bc</h1>d<p>e<i>fg</i>hi</p>j<p>k<br/>l<b>m</b>no</p>p<small>q</small>rs</div>`
 | 
			
		||||
 | 
			
		||||
func TestGetHTMLMessage(t *testing.T) {
 | 
			
		||||
	msg := GetHTMLMessage("m.text", testHTML)
 | 
			
		||||
	if expected := "abcdefghijklmnopqrs"; msg.Body != expected {
 | 
			
		||||
		t.Fatalf("TestGetHTMLMessage: got '%s', expected '%s'", msg.Body, expected)
 | 
			
		||||
	}
 | 
			
		||||
	if msg.FormattedBody != testHTML {
 | 
			
		||||
		t.Fatalf("TestGetHTMLMessage: got '%s', expected '%s'", msg.FormattedBody, testHTML)
 | 
			
		||||
	}
 | 
			
		||||
	if msg.MsgType != "m.text" {
 | 
			
		||||
		t.Fatalf("TestGetHTMLMessage: got '%s', expected 'm.text'", msg.FormattedBody)
 | 
			
		||||
	}
 | 
			
		||||
	if expected := "org.matrix.custom.html"; msg.Format != expected {
 | 
			
		||||
		t.Fatalf("TestGetHTMLMessage: got '%s', expected '%s'", msg.Format, expected)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								go.mod
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
module github.com/matrix-org/gomatrix
 | 
			
		||||
 | 
			
		||||
go 1.12
 | 
			
		||||
| 
						 | 
				
			
			@ -2,9 +2,6 @@
 | 
			
		|||
 | 
			
		||||
set -eu
 | 
			
		||||
 | 
			
		||||
golint
 | 
			
		||||
misspell --error .
 | 
			
		||||
 | 
			
		||||
# gofmt doesn't exit with an error code if the files don't match the expected
 | 
			
		||||
# format. So we have to run it and see if it outputs anything.
 | 
			
		||||
if gofmt -l -s . 2>&1 | read
 | 
			
		||||
| 
						 | 
				
			
			@ -18,9 +15,5 @@ then
 | 
			
		|||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
ineffassign .
 | 
			
		||||
 | 
			
		||||
go fmt
 | 
			
		||||
go tool vet --all --shadow .
 | 
			
		||||
gocyclo -over 12 .
 | 
			
		||||
go test -timeout 5s -test.v
 | 
			
		||||
golangci-lint run
 | 
			
		||||
go test -timeout 5s . ./...
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										69
									
								
								identifier.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								identifier.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,69 @@
 | 
			
		|||
package gomatrix
 | 
			
		||||
 | 
			
		||||
// Identifier is the interface for https://matrix.org/docs/spec/client_server/r0.6.0#identifier-types
 | 
			
		||||
type Identifier interface {
 | 
			
		||||
	// Returns the identifier type
 | 
			
		||||
	// https://matrix.org/docs/spec/client_server/r0.6.0#identifier-types
 | 
			
		||||
	Type() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UserIdentifier is the Identifier for https://matrix.org/docs/spec/client_server/r0.6.0#matrix-user-id
 | 
			
		||||
type UserIdentifier struct {
 | 
			
		||||
	IDType string `json:"type"` // Set by NewUserIdentifer
 | 
			
		||||
	User   string `json:"user"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Type implements the Identifier interface
 | 
			
		||||
func (i UserIdentifier) Type() string {
 | 
			
		||||
	return "m.id.user"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewUserIdentifier creates a new UserIdentifier with IDType set to "m.id.user"
 | 
			
		||||
func NewUserIdentifier(user string) UserIdentifier {
 | 
			
		||||
	return UserIdentifier{
 | 
			
		||||
		IDType: "m.id.user",
 | 
			
		||||
		User:   user,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ThirdpartyIdentifier is the Identifier for https://matrix.org/docs/spec/client_server/r0.6.0#third-party-id
 | 
			
		||||
type ThirdpartyIdentifier struct {
 | 
			
		||||
	IDType  string `json:"type"` // Set by NewThirdpartyIdentifier
 | 
			
		||||
	Medium  string `json:"medium"`
 | 
			
		||||
	Address string `json:"address"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Type implements the Identifier interface
 | 
			
		||||
func (i ThirdpartyIdentifier) Type() string {
 | 
			
		||||
	return "m.id.thirdparty"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewThirdpartyIdentifier creates a new UserIdentifier with IDType set to "m.id.user"
 | 
			
		||||
func NewThirdpartyIdentifier(medium, address string) ThirdpartyIdentifier {
 | 
			
		||||
	return ThirdpartyIdentifier{
 | 
			
		||||
		IDType:  "m.id.thirdparty",
 | 
			
		||||
		Medium:  medium,
 | 
			
		||||
		Address: address,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PhoneIdentifier is the Identifier for https://matrix.org/docs/spec/client_server/r0.6.0#phone-number
 | 
			
		||||
type PhoneIdentifier struct {
 | 
			
		||||
	IDType  string `json:"type"` // Set by NewPhoneIdentifier
 | 
			
		||||
	Country string `json:"country"`
 | 
			
		||||
	Phone   string `json:"phone"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Type implements the Identifier interface
 | 
			
		||||
func (i PhoneIdentifier) Type() string {
 | 
			
		||||
	return "m.id.phone"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewPhoneIdentifier creates a new UserIdentifier with IDType set to "m.id.user"
 | 
			
		||||
func NewPhoneIdentifier(country, phone string) PhoneIdentifier {
 | 
			
		||||
	return PhoneIdentifier{
 | 
			
		||||
		IDType:  "m.id.phone",
 | 
			
		||||
		Country: country,
 | 
			
		||||
		Phone:   phone,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,9 +10,10 @@ type ReqRegister struct {
 | 
			
		|||
	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
 | 
			
		||||
// ReqLogin is the JSON request for http://matrix.org/docs/spec/client_server/r0.6.0.html#post-matrix-client-r0-login
 | 
			
		||||
type ReqLogin struct {
 | 
			
		||||
	Type                     string     `json:"type"`
 | 
			
		||||
	Identifier               Identifier `json:"identifier,omitempty"`
 | 
			
		||||
	Password                 string     `json:"password,omitempty"`
 | 
			
		||||
	Medium                   string     `json:"medium,omitempty"`
 | 
			
		||||
	User                     string     `json:"user,omitempty"`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										39
									
								
								responses.go
									
										
									
									
									
								
							
							
						
						
									
										39
									
								
								responses.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -22,6 +22,14 @@ type RespVersions struct {
 | 
			
		|||
	Versions []string `json:"versions"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RespPublicRooms is the JSON response for http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#get-matrix-client-unstable-publicrooms
 | 
			
		||||
type RespPublicRooms struct {
 | 
			
		||||
	TotalRoomCountEstimate int          `json:"total_room_count_estimate"`
 | 
			
		||||
	PrevBatch              string       `json:"prev_batch"`
 | 
			
		||||
	NextBatch              string       `json:"next_batch"`
 | 
			
		||||
	Chunk                  []PublicRoom `json:"chunk"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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"`
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +92,7 @@ type RespUserInteractive struct {
 | 
			
		|||
		Stages []string `json:"stages"`
 | 
			
		||||
	} `json:"flows"`
 | 
			
		||||
	Params    map[string]interface{} `json:"params"`
 | 
			
		||||
	Session   string                 `json:"string"`
 | 
			
		||||
	Session   string                 `json:"session"`
 | 
			
		||||
	Completed []string               `json:"completed"`
 | 
			
		||||
	ErrCode   string                 `json:"errcode"`
 | 
			
		||||
	Error     string                 `json:"error"`
 | 
			
		||||
| 
						 | 
				
			
			@ -105,6 +113,14 @@ type RespUserDisplayName struct {
 | 
			
		|||
	DisplayName string `json:"displayname"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RespUserStatus is the JSON response for https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-presence-userid-status
 | 
			
		||||
type RespUserStatus struct {
 | 
			
		||||
	Presence        string `json:"presence"`
 | 
			
		||||
	StatusMsg       string `json:"status_msg"`
 | 
			
		||||
	LastActiveAgo   int    `json:"last_active_ago"`
 | 
			
		||||
	CurrentlyActive bool   `json:"currently_active"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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"`
 | 
			
		||||
| 
						 | 
				
			
			@ -114,17 +130,31 @@ type RespRegister struct {
 | 
			
		|||
	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
 | 
			
		||||
// RespLogin is the JSON response for http://matrix.org/docs/spec/client_server/r0.6.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"`
 | 
			
		||||
	WellKnown   DiscoveryInformation `json:"well_known"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RespLogout is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-logout
 | 
			
		||||
// DiscoveryInformation is the JSON Response for https://matrix.org/docs/spec/client_server/r0.6.0#get-well-known-matrix-client and a part of the JSON Response for https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-login
 | 
			
		||||
type DiscoveryInformation struct {
 | 
			
		||||
	Homeserver struct {
 | 
			
		||||
		BaseURL string `json:"base_url"`
 | 
			
		||||
	} `json:"m.homeserver"`
 | 
			
		||||
	IdentityServer struct {
 | 
			
		||||
		BaseURL string `json:"base_url"`
 | 
			
		||||
	} `json:"m.identitiy_server"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RespLogout is the JSON response for http://matrix.org/docs/spec/client_server/r0.6.0.html#post-matrix-client-r0-logout
 | 
			
		||||
type RespLogout struct{}
 | 
			
		||||
 | 
			
		||||
// RespLogoutAll is the JSON response for https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-logout-all
 | 
			
		||||
type RespLogoutAll 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"`
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +189,9 @@ type RespSync struct {
 | 
			
		|||
				Limited   bool    `json:"limited"`
 | 
			
		||||
				PrevBatch string  `json:"prev_batch"`
 | 
			
		||||
			} `json:"timeline"`
 | 
			
		||||
			Ephemeral struct {
 | 
			
		||||
				Events []Event `json:"events"`
 | 
			
		||||
			} `json:"ephemeral"`
 | 
			
		||||
		} `json:"join"`
 | 
			
		||||
		Invite map[string]struct {
 | 
			
		||||
			State struct {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								room.go
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								room.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -6,6 +6,19 @@ type Room struct {
 | 
			
		|||
	State map[string]map[string]*Event
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PublicRoom represents the information about a public room obtainable from the room directory
 | 
			
		||||
type PublicRoom struct {
 | 
			
		||||
	CanonicalAlias   string   `json:"canonical_alias"`
 | 
			
		||||
	Name             string   `json:"name"`
 | 
			
		||||
	WorldReadable    bool     `json:"world_readable"`
 | 
			
		||||
	Topic            string   `json:"topic"`
 | 
			
		||||
	NumJoinedMembers int      `json:"num_joined_members"`
 | 
			
		||||
	AvatarURL        string   `json:"avatar_url"`
 | 
			
		||||
	RoomID           string   `json:"room_id"`
 | 
			
		||||
	GuestCanJoin     bool     `json:"guest_can_join"`
 | 
			
		||||
	Aliases          []string `json:"aliases"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -18,8 +31,8 @@ func (room Room) UpdateState(event *Event) {
 | 
			
		|||
 | 
			
		||||
// GetStateEvent returns the state event for the given type/state_key combo, or nil.
 | 
			
		||||
func (room Room) GetStateEvent(eventType string, stateKey string) *Event {
 | 
			
		||||
	stateEventMap, _ := room.State[eventType]
 | 
			
		||||
	event, _ := stateEventMap[stateKey]
 | 
			
		||||
	stateEventMap := room.State[eventType]
 | 
			
		||||
	event := stateEventMap[stateKey]
 | 
			
		||||
	return event
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								sync.go
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								sync.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -64,6 +64,10 @@ func (s *DefaultSyncer) ProcessResponse(res *RespSync, since string) (err error)
 | 
			
		|||
			event.RoomID = roomID
 | 
			
		||||
			s.notifyListeners(&event)
 | 
			
		||||
		}
 | 
			
		||||
		for _, event := range roomData.Ephemeral.Events {
 | 
			
		||||
			event.RoomID = roomID
 | 
			
		||||
			s.notifyListeners(&event)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for roomID, roomData := range res.Rooms.Invite {
 | 
			
		||||
		room := s.getOrCreateRoom(roomID)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										26
									
								
								tags.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tags.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
// Copyright 2019 Sumukha PK
 | 
			
		||||
//
 | 
			
		||||
// 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 gomatrix
 | 
			
		||||
 | 
			
		||||
// TagContent contains the data for an m.tag message type
 | 
			
		||||
// https://matrix.org/docs/spec/client_server/r0.4.0.html#m-tag
 | 
			
		||||
type TagContent struct {
 | 
			
		||||
	Tags map[string]TagProperties `json:"tags"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TagProperties contains the properties of a Tag
 | 
			
		||||
type TagProperties struct {
 | 
			
		||||
	Order float32 `json:"order,omitempty"` // Empty values must be neglected
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue