aboutsummaryrefslogblamecommitdiff
path: root/connector/connector.go
blob: 48fc9e7eb04c4f26f88391145308b680ce11136b (plain) (tree)
1
2
3
4
5
6

                 



            







                                                                                      
 


                                                                                   
 


































                                                                                   
                                             
                                                              

                                                


                            







                                                                                                

















                                                                                     
                                                                     



                                                                                    






                                                                                      


                  
 







                                   
                                    
 


                                                                                  
                             
 


                                                                                    
                                     


                                                                        
                                           


                                                                                 
                                 

                                      
                                 

                                        
                                                       


                      
                                                



                                                                                                                 
                                           


                      

                                   

                                                            
                                             


                            


                         
 


                                                                        

                                           
 


                                                               
 
 



                          
                       

                                  
 
package connector

import (
	"io"
)

/*
	A generic connector framework for instant messaging protocols.

	Model:

	- A connector represents a connection to an outgoing service (IRC, XMPP, etc)
	  It satisfies a generic interface representing the actions that can be called
	  (send messages, join room, etc)

	- A handler represents a consumer of events happening on a connection
	  It satisfies a generic interface representing the events that can happend
	  (message received, rooms autojoined, etc)

	- A connector implements a given protocol that has an identifier
	  Each protocol identifier determines a namespace for user identifiers
	  and room identifiers which are globally unique for all connections using
	  this protocol.
	  For instance, a user can have two IRC conections to different servers.
	  Internally used user names and room identifiers must contain
	  the server name to be able to differentiate.
*/

type UserID string
type RoomID string

type Connector interface {
	// Set the handler that will receive events happening on this connection
	SetHandler(handler Handler)

	// Configure (or reconfigure) the connector and attempt to connect
	Configure(conf Configuration) error

	// Get the identifier of the protocol that is implemented by this connector
	Protocol() string

	// Get the user id of the connected user
	User() UserID

	// Set user information (nickname, picture, etc)
	SetUserInfo(info *UserInfo) error

	// Set room information (name, description, picture, etc)
	SetRoomInfo(roomId RoomID, info *RoomInfo) error

	// Try to join a channel
	// If no error happens, it must fire a Handler.Joined event
	Join(roomId RoomID) error

	// Try to invite someone to a channel
	// Or if roomId == "", just try adding them as friends
	Invite(user UserID, roomId RoomID) error

	// Leave a channel
	Leave(roomId RoomID)

	// Send an event. Returns the ID of the created remote message.
	// This ID is used to deduplicate messages: if it comes back, it should have the same Id
	// than the one returned here.
	// For backends that do not implement IDs (e.g. IRC), an empty string is returned.
	// (FIXME how to deduplicate IRC messages?)
	// The event that is fed in this function may have its ID already set,
	// in which case the backend is free to re-use the ID or select a new one.
	Send(event *Event) (string, error)

	// Close the connection
	Close()
}

type Handler interface {
	// Called when a room was joined (automatically or by call to Connector.Join)
	Joined(roomId RoomID)

	// Called when the user left a room
	Left(roomId RoomID)

	// Called when a user's info is updated (changed their nickname, status, etc)
	// Can also be called with our own user ID when first loaded our user info
	UserInfoUpdated(user UserID, info *UserInfo)

	// Called when a room's info was updated,
	// or the first tome a room's info is retreived
	RoomInfoUpdated(roomId RoomID, author UserID, info *RoomInfo)

	// Called when an event occurs in a room
	// This must not be called for events authored by the user of the connection
	Event(event *Event)

	// These two functions enable the connector to access a simple key/value
	// database to cache some information in order not to generate useless events.
	// The connector should function when they are not implemented,
	// in which case CacheGet always returns ""
	CachePut(key string, value string)
	CacheGet(key string) string
}

type EventType int

const (
	EVENT_JOIN EventType = iota
	EVENT_LEAVE
	EVENT_MESSAGE
	EVENT_ACTION
)

type Event struct {
	Type EventType `json:"type"`

	// If non-empty, the event Id is used to deduplicate events in a channel
	// This is usefull for backends that provide a backlog of channel messages
	// when (re-)joining a room
	Id string `json:"id"`

	// UserID of the user that sent the event
	// If this is a direct message event, this event can only have been authored
	// by the user we are talking to (and not by ourself)
	Author UserID `json:"author"`

	// UserID of the targetted user in the case of a direct message,
	// empty if targetting a room
	Recipient UserID `json:"recipient"`

	// RoomID of the room where the event happenned or of the targetted room,
	// or empty string if it happenned by direct message
	Room RoomID `json:"room"`

	// Message text or action text
	Text string `json:"text"`

	// Attached files such as images
	Attachments []SMediaObject `json:"attachments"`
}

type UserInfo struct {
	DisplayName string `json:"display_name"`

	// If non-empty, the Filename of the avatar object will be used by Easybridge
	// to deduplicate the update events and prevent needless reuploads.
	// Example strategy that works for the mattermost backend: use the update timestamp as fictious file name
	Avatar SMediaObject `json:"avatar"`
}

type RoomInfo struct {
	Name  string `json:"name"`
	Topic string `json:"topic"`

	// Same deduplication comment as for UserInfo.Avatar
	Picture SMediaObject `json:"picture"`
}

type MediaObject interface {
	Filename() string
	Size() int64
	Mimetype() string

	// Returns the size of an image if it is an image, otherwise nil
	ImageSize() *ImageSize

	// Read: must always be implemented
	Read() (io.ReadCloser, error)

	// URL(): not mandatory, may return an empty string
	// If so, Read() is the only way to retrieve the object
	URL() string
}

type SMediaObject struct {
	MediaObject
}

type ImageSize struct {
	Width  int `json:"width"`
	Height int `json:"height"`
}