225 lines
3.9 KiB
Go
225 lines
3.9 KiB
Go
package chat
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Message is an interface for messages.
|
|
type Message interface {
|
|
Render(*Theme) string
|
|
String() string
|
|
Command() string
|
|
}
|
|
|
|
type MessageTo interface {
|
|
Message
|
|
To() *User
|
|
}
|
|
|
|
type MessageFrom interface {
|
|
Message
|
|
From() *User
|
|
}
|
|
|
|
func ParseInput(body string, from *User) Message {
|
|
m := NewPublicMsg(body, from)
|
|
cmd, isCmd := m.ParseCommand()
|
|
if isCmd {
|
|
return cmd
|
|
}
|
|
return m
|
|
}
|
|
|
|
// Msg is a base type for other message types.
|
|
type Msg struct {
|
|
Message
|
|
body string
|
|
timestamp time.Time
|
|
// TODO: themeCache *map[*Theme]string
|
|
}
|
|
|
|
// Render message based on a theme.
|
|
func (m *Msg) Render(t *Theme) string {
|
|
// TODO: Render based on theme
|
|
// TODO: Cache based on theme
|
|
return m.String()
|
|
}
|
|
|
|
func (m *Msg) String() string {
|
|
return m.body
|
|
}
|
|
|
|
func (m *Msg) Command() string {
|
|
return ""
|
|
}
|
|
|
|
// PublicMsg is any message from a user sent to the channel.
|
|
type PublicMsg struct {
|
|
Msg
|
|
from *User
|
|
}
|
|
|
|
func NewPublicMsg(body string, from *User) *PublicMsg {
|
|
return &PublicMsg{
|
|
Msg: Msg{
|
|
body: body,
|
|
timestamp: time.Now(),
|
|
},
|
|
from: from,
|
|
}
|
|
}
|
|
|
|
func (m *PublicMsg) From() *User {
|
|
return m.from
|
|
}
|
|
|
|
func (m *PublicMsg) ParseCommand() (*CommandMsg, bool) {
|
|
// Check if the message is a command
|
|
if !strings.HasPrefix(m.body, "/") {
|
|
return nil, false
|
|
}
|
|
|
|
// Parse
|
|
// TODO: Handle quoted fields properly
|
|
fields := strings.Fields(m.body)
|
|
command, args := fields[0], fields[1:]
|
|
msg := CommandMsg{
|
|
PublicMsg: m,
|
|
command: command,
|
|
args: args,
|
|
}
|
|
return &msg, true
|
|
}
|
|
|
|
func (m *PublicMsg) Render(t *Theme) string {
|
|
if t == nil {
|
|
return m.String()
|
|
}
|
|
|
|
return fmt.Sprintf("%s: %s", t.ColorName(m.from), m.body)
|
|
}
|
|
|
|
func (m *PublicMsg) String() string {
|
|
return fmt.Sprintf("%s: %s", m.from.Name(), m.body)
|
|
}
|
|
|
|
// EmoteMsg is a /me message sent to the channel. It specifically does not
|
|
// extend PublicMsg because it doesn't implement MessageFrom to allow the
|
|
// sender to see the emote.
|
|
type EmoteMsg struct {
|
|
Msg
|
|
from *User
|
|
}
|
|
|
|
func NewEmoteMsg(body string, from *User) *EmoteMsg {
|
|
return &EmoteMsg{
|
|
Msg: Msg{
|
|
body: body,
|
|
timestamp: time.Now(),
|
|
},
|
|
from: from,
|
|
}
|
|
}
|
|
|
|
func (m *EmoteMsg) Render(t *Theme) string {
|
|
return fmt.Sprintf("** %s %s", m.from.Name(), m.body)
|
|
}
|
|
|
|
func (m *EmoteMsg) String() string {
|
|
return m.Render(nil)
|
|
}
|
|
|
|
// PrivateMsg is a message sent to another user, not shown to anyone else.
|
|
type PrivateMsg struct {
|
|
PublicMsg
|
|
to *User
|
|
}
|
|
|
|
func NewPrivateMsg(body string, from *User, to *User) *PrivateMsg {
|
|
return &PrivateMsg{
|
|
PublicMsg: *NewPublicMsg(body, from),
|
|
to: to,
|
|
}
|
|
}
|
|
|
|
func (m *PrivateMsg) To() *User {
|
|
return m.to
|
|
}
|
|
|
|
func (m *PrivateMsg) Render(t *Theme) string {
|
|
return fmt.Sprintf("[PM from %s] %s", m.from.Name(), m.body)
|
|
}
|
|
|
|
func (m *PrivateMsg) String() string {
|
|
return m.Render(nil)
|
|
}
|
|
|
|
// SystemMsg is a response sent from the server directly to a user, not shown
|
|
// to anyone else. Usually in response to something, like /help.
|
|
type SystemMsg struct {
|
|
Msg
|
|
to *User
|
|
}
|
|
|
|
func NewSystemMsg(body string, to *User) *SystemMsg {
|
|
return &SystemMsg{
|
|
Msg: Msg{
|
|
body: body,
|
|
timestamp: time.Now(),
|
|
},
|
|
to: to,
|
|
}
|
|
}
|
|
|
|
func (m *SystemMsg) Render(t *Theme) string {
|
|
return fmt.Sprintf("-> %s", m.body)
|
|
}
|
|
|
|
func (m *SystemMsg) String() string {
|
|
return m.Render(nil)
|
|
}
|
|
|
|
func (m *SystemMsg) To() *User {
|
|
return m.to
|
|
}
|
|
|
|
// AnnounceMsg is a message sent from the server to everyone, like a join or
|
|
// leave event.
|
|
type AnnounceMsg struct {
|
|
Msg
|
|
}
|
|
|
|
func NewAnnounceMsg(body string) *AnnounceMsg {
|
|
return &AnnounceMsg{
|
|
Msg: Msg{
|
|
body: body,
|
|
timestamp: time.Now(),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (m *AnnounceMsg) Render(t *Theme) string {
|
|
return fmt.Sprintf(" * %s", m.body)
|
|
}
|
|
|
|
func (m *AnnounceMsg) String() string {
|
|
return m.Render(nil)
|
|
}
|
|
|
|
type CommandMsg struct {
|
|
*PublicMsg
|
|
command string
|
|
args []string
|
|
channel *Channel
|
|
}
|
|
|
|
func (m *CommandMsg) Command() string {
|
|
return m.command
|
|
}
|
|
|
|
func (m *CommandMsg) Args() []string {
|
|
return m.args
|
|
}
|