Initial API draft

This commit is contained in:
diamondburned (Forefront) 2020-05-18 23:07:22 -07:00
commit 3e8f0a0921
3 changed files with 171 additions and 0 deletions

110
cchat.go Normal file
View File

@ -0,0 +1,110 @@
package cchat
import (
"time"
"github.com/diamondburned/cchat/text"
)
// Core contains the bare minimum set of interface that a backend has to
// implement. Core can also implement Authenticator.
type Core interface {
Server
ServerList
}
// Authenticator is what the backend can implement for authentication.
type Authenticator interface {
// AuthenticateForm should return a list of authentication entries for
// the frontend to render.
AuthenticateForm() []AuthenticateEntry
// Authenticate will be called with a list of values with indices
// correspond to the returned slice of AuthenticateEntry.
Authenticate([]string) error
}
// AuthenticateEntry represents a single authentication entry, usually an email
// or password prompt. Passwords or similar entries should have Secrets set to
// true, which should imply to frontends that the fields be masked.
type AuthenticateEntry struct {
Name string
Secret bool
}
// Server is a single server-like entity that could translate to a guild, a
// channel, a chat-room, and such. A server must implement at least ServerList
// or ServerMessage, else the frontend must treat it as a no-op.
type Server interface {
// Name returns the server's name or the service's name.
Name() (string, error)
// Implement ServerList and/or ServerMessage.
}
// ServerList is for servers that contain children servers. This is similar to
// guilds containing channels in Discord, or IRC servers containing channels.
type ServerList interface {
// Servers should return a list of children servers/channels or nil if
// none.
Servers() ([]Server, error)
}
// ServerMessage is for servers that contain messages. This is similar to
// Discord or IRC channels.
type ServerMessage interface {
// JoinServer should be called if Servers() returns nil, in which the
// backend should connect to the server and start calling methods in the
// container.
JoinServer(MessageContainer) error
// LeaveServer indicates the backend to stop calling the controller over.
// This should be called before any other JoinServer() calls are made.
LeaveServer() error
}
// ServerIcon is an extra interface that Server could implement for an icon.
type ServerIcon interface {
IconURL() (string, error)
}
// Worth pointing out that frontend container interfaces will not have an error
// handling API, as frontends can do that themselves.
// MessageContainer is a frontend implementation for a message view, with
// synchronous callbacks to render those events.
type MessageContainer interface {
CreateMessage(MessageCreate)
UpdateMessage(MessageUpdate)
DeleteMessage(MessageDelete)
}
// MessageHeader implements the interface for any message event.
type MessageHeader interface {
ID() string
Time() time.Time
}
// MessageCreate is the interface for an incoming message.
type MessageCreate interface {
MessageHeader
Author() text.Rich
Content() text.Rich
}
// MessageUpdate is the interface for a message update (or edit) event. If the
// returned text.Rich returns true for Empty(), then the element shouldn't be
// changed.
type MessageUpdate interface {
MessageHeader
Author() text.Rich // optional
Content() text.Rich // optional
}
// MessageDelete is the interface for a message delete event.
type MessageDelete interface {
MessageHeader
}
// MessageAuthorAvatar is an optional interface that messages could implement. A
// frontend may optionally support this.
type MessageAuthorAvatar interface {
AuthorAvatar() (url string)
}

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module github.com/diamondburned/cchat
go 1.14

58
text/text.go Normal file
View File

@ -0,0 +1,58 @@
package text
// Rich is a normal text wrapped with optional format segments.
type Rich struct {
Content string
// Segments are optional rich-text segment markers.
Segments []Segment
}
func (r Rich) Empty() bool {
return r.Content == ""
}
// Segment is the minimum requirement for a format segment. Frontends will use
// this to determine when the format starts and ends. They will also assert this
// interface to any other formatting interface, including Linker, Colorer and
// Attributor.
type Segment interface {
Bounds() (start, end int)
}
// Linker is a hyperlink format that a segment could implement. This implies
// that the segment should be replaced with a hyperlink, similarly to the anchor
// tag with href being the URL and the inner text being the text string.
type Linker interface {
Link() (text, url string)
}
// Imager implies the segment should be replaced with a (possibly inlined)
// image.
type Imager interface {
Image() (url string)
}
// Colorer is a text color format that a segment could implement. This is to be
// applied directly onto the text.
type Colorer interface {
Color() uint16
}
// Attributor is a rich text markup format that a segment could implement. This
// is to be applied directly onto the text.
type Attributor interface {
Attribute() Attribute
}
// Attribute is the type for basic rich text markup attributes.
type Attribute uint16
const (
AttrBold Attribute = 1 << iota
AttrItalics
AttrUnderline
AttrStrikethrough
AttrSpoiler
AttrMonospace
AttrQuoted
)