mirror of
				https://github.com/matrix-org/gomatrix
				synced 2025-11-03 22:08:04 +00:00 
			
		
		
		
	Add responses/room types. Add buildURL functions with examples
This commit is contained in:
		
							parent
							
								
									97f4e98e1d
								
							
						
					
					
						commit
						527c6568c9
					
				
					 4 changed files with 160 additions and 4 deletions
				
			
		
							
								
								
									
										51
									
								
								client.go
									
										
									
									
									
								
							
							
						
						
									
										51
									
								
								client.go
									
										
									
									
									
								
							| 
						 | 
					@ -1,8 +1,12 @@
 | 
				
			||||||
 | 
					// Package gomatrix implements the Matrix Client-Server API.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Specification can be found at http://matrix.org/docs/spec/client_server/r0.2.0.html
 | 
				
			||||||
package gomatrix
 | 
					package gomatrix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,11 +24,49 @@ type Client struct {
 | 
				
			||||||
	// TODO: Worker and Rooms
 | 
						// TODO: Worker and Rooms
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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()
 | 
				
			||||||
 | 
						query.Set("access_token", cli.AccessToken)
 | 
				
			||||||
 | 
						hsURL.RawQuery = query.Encode()
 | 
				
			||||||
 | 
						return hsURL.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BuildURLWithQuery builds a URL with query paramters 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()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewClient creates a new Matrix Client ready for syncing
 | 
					// NewClient creates a new Matrix Client ready for syncing
 | 
				
			||||||
func NewClient(httpClient *http.Client, homeserverURL *url.URL, accessToken, userID string) *Client {
 | 
					func NewClient(homeserverURL, userID, accessToken string) (*Client, error) {
 | 
				
			||||||
 | 
						hsURL, err := url.Parse(homeserverURL)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	cli := Client{
 | 
						cli := Client{
 | 
				
			||||||
		AccessToken:   accessToken,
 | 
							AccessToken:   accessToken,
 | 
				
			||||||
		HomeserverURL: homeserverURL,
 | 
							HomeserverURL: hsURL,
 | 
				
			||||||
		UserID:        userID,
 | 
							UserID:        userID,
 | 
				
			||||||
		Prefix:        "/_matrix/client/r0",
 | 
							Prefix:        "/_matrix/client/r0",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -36,7 +78,8 @@ func NewClient(httpClient *http.Client, homeserverURL *url.URL, accessToken, use
 | 
				
			||||||
	// "load" nothing. The client will work with this storer: it just won't remember the filter
 | 
						// "load" nothing. The client will work with this storer: it just won't remember the filter
 | 
				
			||||||
	// ID across restarts and hence request a new one. In practice, a database backend should be used.
 | 
						// ID across restarts and hence request a new one. In practice, a database backend should be used.
 | 
				
			||||||
	cli.FilterStorer = NopFilterStore{}
 | 
						cli.FilterStorer = NopFilterStore{}
 | 
				
			||||||
	cli.Client = httpClient
 | 
						// By default, use the default HTTP client.
 | 
				
			||||||
 | 
						cli.Client = http.DefaultClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &cli
 | 
						return &cli, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										28
									
								
								client_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								client_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,28 @@
 | 
				
			||||||
 | 
					package gomatrix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ExampleBuildURLWithQuery() {
 | 
				
			||||||
 | 
						cli, _ := NewClient("https://matrix.org", "@example:matrix.org", "abcdef123456")
 | 
				
			||||||
 | 
						out := cli.BuildURLWithQuery([]string{"sync"}, map[string]string{
 | 
				
			||||||
 | 
							"filter_id": "5",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						fmt.Println(out)
 | 
				
			||||||
 | 
						// Output: https://matrix.org/_matrix/client/r0/sync?access_token=abcdef123456&filter_id=5
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ExampleBuildURL() {
 | 
				
			||||||
 | 
						userID := "@example:matrix.org"
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ExampleBuildBaseURL() {
 | 
				
			||||||
 | 
						userID := "@example:matrix.org"
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										44
									
								
								responses.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								responses.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					package gomatrix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
							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"`
 | 
				
			||||||
 | 
							} `json:"join"`
 | 
				
			||||||
 | 
							Invite map[string]struct {
 | 
				
			||||||
 | 
								State struct {
 | 
				
			||||||
 | 
									Events []Event
 | 
				
			||||||
 | 
								} `json:"invite_state"`
 | 
				
			||||||
 | 
							} `json:"invite"`
 | 
				
			||||||
 | 
						} `json:"rooms"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								room.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								room.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					package gomatrix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Room represents a single Matrix room.
 | 
				
			||||||
 | 
					type Room struct {
 | 
				
			||||||
 | 
						ID    string
 | 
				
			||||||
 | 
						State map[string]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 string, 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) string {
 | 
				
			||||||
 | 
						state := "leave"
 | 
				
			||||||
 | 
						event := room.GetStateEvent("m.room.member", userID)
 | 
				
			||||||
 | 
						if event != nil {
 | 
				
			||||||
 | 
							membershipState, found := event.Content["membership"]
 | 
				
			||||||
 | 
							if found {
 | 
				
			||||||
 | 
								mState, isString := membershipState.(string)
 | 
				
			||||||
 | 
								if isString {
 | 
				
			||||||
 | 
									state = mState
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return state
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue