easybridge/connector/connector.go
2020-02-23 20:24:50 +01:00

169 lines
4.6 KiB
Go

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
Send(event *Event) 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
// 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
// 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
// UserID of the targetted user in the case of a direct message,
// empty if targetting a room
Recipient UserID
// RoomID of the room where the event happenned or of the targetted room,
// or empty string if it happenned by direct message
Room RoomID
// Message text or action text
Text string
// Attached files such as images
Attachments []MediaObject
}
type UserInfo struct {
DisplayName string
// 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 MediaObject
}
type RoomInfo struct {
Name string
Topic string
// Same deduplication comment as for UserInfo.Avatar
Picture MediaObject
}
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 ImageSize struct {
Width int
Height int
}