Skip to content

[WIP] Refactoring towards v2.0 #215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
bccb5f3
refactor: User.Ignored, message.User; add: set.Keyize
shazow Aug 29, 2016
4bca1f0
refactor: Identifier.SetID -> Identifier.SetName
shazow Sep 1, 2016
a838ee2
refactor: Remove mentions of message.User from chat.
shazow Sep 1, 2016
b45efc0
refactor: Privatize sshchat.GetPrompt and sshchat.Identity
shazow Sep 1, 2016
f64b2a3
refactor: sshchat.getPrompt() -> message.User.Prompt()
shazow Sep 1, 2016
91718a5
progress: refactor: Remove Identifier interface, reverse ownership of…
shazow Sep 4, 2016
810ef13
set: AddNew vs Add, added Rename
shazow Sep 7, 2016
5f2a230
progress: broken: Multi-client support, tests fail, Whois factored
shazow Sep 7, 2016
01b989c
chat/message/user: screen -> WriteCloser embedded
shazow Sep 8, 2016
a22d938
refactor: fixed failing tests
shazow Sep 9, 2016
9ecd2a6
set: Fix test flake
shazow Sep 9, 2016
33a76bb
broken: Use Member rather than message.User when possible; chat tests…
shazow Sep 11, 2016
50022e9
broken: Split UserScreen into PipedScreen, BufferedScreen, HandledScreen
shazow Sep 11, 2016
0aaaa6a
progress: chat tests pass
shazow Sep 13, 2016
0096404
tests: Add chat.TestIgnore again
shazow Sep 13, 2016
3ef4041
tests: All passing again
shazow Sep 14, 2016
d16b1f5
bugfix: Nil item
shazow Sep 14, 2016
e86996e
progress: Host User interface, and more interfaces in general, tests …
shazow Sep 15, 2016
7f2b8e4
refactor: Add message.Author.ID(), remove a bunch of type assertions
shazow Sep 15, 2016
cd5686e
refactor: Move extraneous User interfaces from chat to host
shazow Sep 16, 2016
7b3818a
refactor: host.UserMember{chat.Member} -> host.Member{chat.Member}
shazow Sep 17, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/build
/vendor
host_key
host_key.pub
ssh-chat
Expand Down
37 changes: 24 additions & 13 deletions chat/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package chat
import (
"errors"
"fmt"
"io"
"strings"

"github.com/shazow/ssh-chat/chat/message"
Expand All @@ -24,6 +25,10 @@ var ErrMissingArg = errors.New("missing argument")
// The error returned when a command is added without a prefix.
var ErrMissingPrefix = errors.New("command missing prefix")

// The error returned when we fail to find a corresponding userMember struct
// for an ID. This should not happen, probably a bug somewhere if encountered.
var ErrMissingMember = errors.New("failed to find member")

// Command is a definition of a handler for a command.
type Command struct {
// The command's key, such as /foo
Expand Down Expand Up @@ -131,8 +136,7 @@ func InitCommands(c *Commands) {
Prefix: "/exit",
Help: "Exit the chat.",
Handler: func(room *Room, msg message.CommandMsg) error {
msg.From().Close()
return nil
return msg.From().(io.Closer).Close()
},
})
c.Alias("/exit", "/quit")
Expand All @@ -146,18 +150,16 @@ func InitCommands(c *Commands) {
if len(args) != 1 {
return ErrMissingArg
}
u := msg.From()

member, ok := room.MemberByID(u.ID())
member, ok := room.MemberByID(msg.From().ID())
if !ok {
return errors.New("failed to find member")
return ErrMissingMember
}

oldID := member.ID()
member.SetID(SanitizeName(args[0]))
member.SetName(args[0])
err := room.Rename(oldID, member)
if err != nil {
member.SetID(oldID)
member.SetName(oldID)
return err
}
return nil
Expand All @@ -182,7 +184,7 @@ func InitCommands(c *Commands) {
PrefixHelp: "[colors|...]",
Help: "Set your color theme. (More themes: solarized, mono, hacker)",
Handler: func(room *Room, msg message.CommandMsg) error {
user := msg.From()
user := msg.From().(Member)
args := msg.Args()
cfg := user.Config()
if len(args) == 0 {
Expand Down Expand Up @@ -213,7 +215,7 @@ func InitCommands(c *Commands) {
Prefix: "/quiet",
Help: "Silence room announcements.",
Handler: func(room *Room, msg message.CommandMsg) error {
u := msg.From()
u := msg.From().(Member)
cfg := u.Config()
cfg.Quiet = !cfg.Quiet
u.SetConfig(cfg)
Expand Down Expand Up @@ -251,11 +253,16 @@ func InitCommands(c *Commands) {
PrefixHelp: "[USER]",
Help: "Hide messages from USER, /unignore USER to stop hiding.",
Handler: func(room *Room, msg message.CommandMsg) error {
from, ok := room.Member(msg.From())
if !ok {
return ErrMissingMember
}

id := strings.TrimSpace(strings.TrimLeft(msg.Body(), "/ignore"))
if id == "" {
// Print ignored names, if any.
var names []string
msg.From().Ignored.Each(func(_ string, item set.Item) error {
from.Ignored.Each(func(_ string, item set.Item) error {
names = append(names, item.Key())
return nil
})
Expand All @@ -279,7 +286,7 @@ func InitCommands(c *Commands) {
return fmt.Errorf("user not found: %s", id)
}

err := msg.From().Ignored.Add(set.Itemize(id, target))
err := from.Ignored.Add(set.Itemize(id, target))
if err == set.ErrCollision {
return fmt.Errorf("user already ignored: %s", id)
} else if err != nil {
Expand All @@ -295,12 +302,16 @@ func InitCommands(c *Commands) {
Prefix: "/unignore",
PrefixHelp: "USER",
Handler: func(room *Room, msg message.CommandMsg) error {
from, ok := room.Member(msg.From())
if !ok {
return ErrMissingMember
}
id := strings.TrimSpace(strings.TrimLeft(msg.Body(), "/unignore"))
if id == "" {
return errors.New("must specify user")
}

if err := msg.From().Ignored.Remove(id); err != nil {
if err := from.Ignored.Remove(id); err != nil {
return err
}

Expand Down
23 changes: 23 additions & 0 deletions chat/member.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package chat

import (
"github.com/shazow/ssh-chat/chat/message"
"github.com/shazow/ssh-chat/set"
)

// Member is a User with per-Room metadata attached to it.
type roomMember struct {
Member
Ignored *set.Set
}

type Member interface {
message.Author

Config() message.UserConfig
SetConfig(message.UserConfig)

Send(message.Message) error

SetName(string)
}
24 changes: 24 additions & 0 deletions chat/message/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package message

import "regexp"

// Container for per-user configurations.
type UserConfig struct {
Highlight *regexp.Regexp
Bell bool
Quiet bool
Theme *Theme
Seed int
}

// Default user configuration to use
var DefaultUserConfig UserConfig

func init() {
DefaultUserConfig = UserConfig{
Bell: true,
Quiet: false,
}

// TODO: Seed random?
}
26 changes: 0 additions & 26 deletions chat/message/identity.go

This file was deleted.

34 changes: 20 additions & 14 deletions chat/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import (
"time"
)

type Author interface {
ID() string
Name() string
Color() int
}

// Message is an interface for messages.
type Message interface {
Render(*Theme) string
Expand All @@ -16,15 +22,15 @@ type Message interface {

type MessageTo interface {
Message
To() *User
To() Author
}

type MessageFrom interface {
Message
From() *User
From() Author
}

func ParseInput(body string, from *User) Message {
func ParseInput(body string, from Author) Message {
m := NewPublicMsg(body, from)
cmd, isCmd := m.ParseCommand()
if isCmd {
Expand Down Expand Up @@ -69,10 +75,10 @@ func (m Msg) Timestamp() time.Time {
// PublicMsg is any message from a user sent to the room.
type PublicMsg struct {
Msg
from *User
from Author
}

func NewPublicMsg(body string, from *User) PublicMsg {
func NewPublicMsg(body string, from Author) PublicMsg {
return PublicMsg{
Msg: Msg{
body: body,
Expand All @@ -82,7 +88,7 @@ func NewPublicMsg(body string, from *User) PublicMsg {
}
}

func (m PublicMsg) From() *User {
func (m PublicMsg) From() Author {
return m.from
}

Expand Down Expand Up @@ -137,10 +143,10 @@ func (m PublicMsg) String() string {
// sender to see the emote.
type EmoteMsg struct {
Msg
from *User
from Author
}

func NewEmoteMsg(body string, from *User) *EmoteMsg {
func NewEmoteMsg(body string, from Author) *EmoteMsg {
return &EmoteMsg{
Msg: Msg{
body: body,
Expand All @@ -161,17 +167,17 @@ func (m EmoteMsg) String() string {
// PrivateMsg is a message sent to another user, not shown to anyone else.
type PrivateMsg struct {
PublicMsg
to *User
to Author
}

func NewPrivateMsg(body string, from *User, to *User) PrivateMsg {
func NewPrivateMsg(body string, from Author, to Author) PrivateMsg {
return PrivateMsg{
PublicMsg: NewPublicMsg(body, from),
to: to,
}
}

func (m PrivateMsg) To() *User {
func (m PrivateMsg) To() Author {
return m.to
}

Expand All @@ -191,10 +197,10 @@ func (m PrivateMsg) String() string {
// to anyone else. Usually in response to something, like /help.
type SystemMsg struct {
Msg
to *User
to Author
}

func NewSystemMsg(body string, to *User) *SystemMsg {
func NewSystemMsg(body string, to Author) *SystemMsg {
return &SystemMsg{
Msg: Msg{
body: body,
Expand All @@ -215,7 +221,7 @@ func (m *SystemMsg) String() string {
return fmt.Sprintf("-> %s", m.body)
}

func (m *SystemMsg) To() *User {
func (m *SystemMsg) To() Author {
return m.to
}

Expand Down
2 changes: 1 addition & 1 deletion chat/message/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestMessage(t *testing.T) {
t.Errorf("Got: `%s`; Expected: `%s`", actual, expected)
}

u := NewUser(SimpleID("foo"))
u := NewUser("foo")
expected = "foo: hello"
actual = NewPublicMsg("hello", u).String()
if actual != expected {
Expand Down
10 changes: 2 additions & 8 deletions chat/sanitize.go → chat/message/sanitize.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package chat
package message

import "regexp"

var reStripName = regexp.MustCompile("[^\\w.-]")

const maxLength = 16

// SanitizeName returns a name with only allowed characters and a reasonable length
Expand All @@ -15,10 +16,3 @@ func SanitizeName(s string) string {
s = s[:nameLength]
return s
}

var reStripData = regexp.MustCompile("[^[:ascii:]]")

// SanitizeData returns a string with only allowed characters for client-provided metadata inputs.
func SanitizeData(s string) string {
return reStripData.ReplaceAllString(s, "")
}
Loading