mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-22 18:52:41 +01:00
move modes code to its own file; fix SQL (un)marshalling
This commit is contained in:
parent
4ed0d78d87
commit
d85e6681d9
@ -444,8 +444,8 @@ func (channel *Channel) Persist() (err error) {
|
|||||||
(name, flags, key, topic, user_limit, ban_list, except_list,
|
(name, flags, key, topic, user_limit, ban_list, except_list,
|
||||||
invite_list)
|
invite_list)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
channel.name, channel.flags.String(), channel.key, channel.topic,
|
channel.name.String(), channel.flags.String(), channel.key.String(),
|
||||||
channel.userLimit, channel.lists[BanMask].String(),
|
channel.topic.String(), channel.userLimit, channel.lists[BanMask].String(),
|
||||||
channel.lists[ExceptMask].String(), channel.lists[InviteMask].String())
|
channel.lists[ExceptMask].String(), channel.lists[InviteMask].String())
|
||||||
} else {
|
} else {
|
||||||
_, err = channel.server.db.Exec(`
|
_, err = channel.server.db.Exec(`
|
||||||
|
@ -153,7 +153,7 @@ func NewClientDB() *ClientDB {
|
|||||||
|
|
||||||
func (db *ClientDB) Add(client *Client) {
|
func (db *ClientDB) Add(client *Client) {
|
||||||
_, err := db.db.Exec(`INSERT INTO client (nickname, userhost) VALUES (?, ?)`,
|
_, err := db.db.Exec(`INSERT INTO client (nickname, userhost) VALUES (?, ?)`,
|
||||||
client.Nick(), client.UserHost())
|
client.Nick().String(), client.UserHost().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log.error.Println("ClientDB.Add:", err)
|
Log.error.Println("ClientDB.Add:", err)
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ func (db *ClientDB) Add(client *Client) {
|
|||||||
|
|
||||||
func (db *ClientDB) Remove(client *Client) {
|
func (db *ClientDB) Remove(client *Client) {
|
||||||
_, err := db.db.Exec(`DELETE FROM client WHERE nickname = ?`,
|
_, err := db.db.Exec(`DELETE FROM client WHERE nickname = ?`,
|
||||||
client.Nick())
|
client.Nick().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log.error.Println("ClientDB.Remove:", err)
|
Log.error.Println("ClientDB.Remove:", err)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
package irc
|
package irc
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// errors
|
|
||||||
ErrAlreadyDestroyed = errors.New("already destroyed")
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SEM_VER = "ergonomadic-1.3.1"
|
SEM_VER = "ergonomadic-1.3.1"
|
||||||
CRLF = "\r\n"
|
CRLF = "\r\n"
|
||||||
@ -184,35 +175,4 @@ const (
|
|||||||
ERR_NOOPERHOST NumericCode = 491
|
ERR_NOOPERHOST NumericCode = 491
|
||||||
ERR_UMODEUNKNOWNFLAG NumericCode = 501
|
ERR_UMODEUNKNOWNFLAG NumericCode = 501
|
||||||
ERR_USERSDONTMATCH NumericCode = 502
|
ERR_USERSDONTMATCH NumericCode = 502
|
||||||
|
|
||||||
Add ModeOp = '+'
|
|
||||||
List ModeOp = '='
|
|
||||||
Remove ModeOp = '-'
|
|
||||||
|
|
||||||
Away UserMode = 'a'
|
|
||||||
Invisible UserMode = 'i'
|
|
||||||
LocalOperator UserMode = 'O'
|
|
||||||
Operator UserMode = 'o'
|
|
||||||
Restricted UserMode = 'r'
|
|
||||||
ServerNotice UserMode = 's' // deprecated
|
|
||||||
WallOps UserMode = 'w'
|
|
||||||
|
|
||||||
Anonymous ChannelMode = 'a' // flag
|
|
||||||
BanMask ChannelMode = 'b' // arg
|
|
||||||
ChannelCreator ChannelMode = 'O' // flag
|
|
||||||
ChannelOperator ChannelMode = 'o' // arg
|
|
||||||
ExceptMask ChannelMode = 'e' // arg
|
|
||||||
InviteMask ChannelMode = 'I' // arg
|
|
||||||
InviteOnly ChannelMode = 'i' // flag
|
|
||||||
Key ChannelMode = 'k' // flag arg
|
|
||||||
Moderated ChannelMode = 'm' // flag
|
|
||||||
NoOutside ChannelMode = 'n' // flag
|
|
||||||
OpOnlyTopic ChannelMode = 't' // flag
|
|
||||||
Persistent ChannelMode = 'P' // flag
|
|
||||||
Private ChannelMode = 'p' // flag
|
|
||||||
Quiet ChannelMode = 'q' // flag
|
|
||||||
ReOp ChannelMode = 'r' // flag
|
|
||||||
Secret ChannelMode = 's' // flag, deprecated
|
|
||||||
UserLimit ChannelMode = 'l' // flag arg
|
|
||||||
Voice ChannelMode = 'v' // arg
|
|
||||||
)
|
)
|
||||||
|
162
irc/modes.go
Normal file
162
irc/modes.go
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
package irc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// user mode flags
|
||||||
|
type UserMode rune
|
||||||
|
|
||||||
|
func (mode UserMode) String() string {
|
||||||
|
return string(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserModes []UserMode
|
||||||
|
|
||||||
|
func (modes UserModes) String() string {
|
||||||
|
strs := make([]string, len(modes))
|
||||||
|
for index, mode := range modes {
|
||||||
|
strs[index] = mode.String()
|
||||||
|
}
|
||||||
|
return strings.Join(strs, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// channel mode flags
|
||||||
|
type ChannelMode rune
|
||||||
|
|
||||||
|
func (mode ChannelMode) String() string {
|
||||||
|
return string(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChannelModes []ChannelMode
|
||||||
|
|
||||||
|
func (modes ChannelModes) String() string {
|
||||||
|
strs := make([]string, len(modes))
|
||||||
|
for index, mode := range modes {
|
||||||
|
strs[index] = mode.String()
|
||||||
|
}
|
||||||
|
return strings.Join(strs, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
type ModeOp rune
|
||||||
|
|
||||||
|
func (op ModeOp) String() string {
|
||||||
|
return string(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
Add ModeOp = '+'
|
||||||
|
List ModeOp = '='
|
||||||
|
Remove ModeOp = '-'
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Away UserMode = 'a'
|
||||||
|
Invisible UserMode = 'i'
|
||||||
|
LocalOperator UserMode = 'O'
|
||||||
|
Operator UserMode = 'o'
|
||||||
|
Restricted UserMode = 'r'
|
||||||
|
ServerNotice UserMode = 's' // deprecated
|
||||||
|
WallOps UserMode = 'w'
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
SupportedUserModes = UserModes{
|
||||||
|
Away, Invisible, Operator,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Anonymous ChannelMode = 'a' // flag
|
||||||
|
BanMask ChannelMode = 'b' // arg
|
||||||
|
ChannelCreator ChannelMode = 'O' // flag
|
||||||
|
ChannelOperator ChannelMode = 'o' // arg
|
||||||
|
ExceptMask ChannelMode = 'e' // arg
|
||||||
|
InviteMask ChannelMode = 'I' // arg
|
||||||
|
InviteOnly ChannelMode = 'i' // flag
|
||||||
|
Key ChannelMode = 'k' // flag arg
|
||||||
|
Moderated ChannelMode = 'm' // flag
|
||||||
|
NoOutside ChannelMode = 'n' // flag
|
||||||
|
OpOnlyTopic ChannelMode = 't' // flag
|
||||||
|
Persistent ChannelMode = 'P' // flag
|
||||||
|
Private ChannelMode = 'p' // flag
|
||||||
|
Quiet ChannelMode = 'q' // flag
|
||||||
|
ReOp ChannelMode = 'r' // flag
|
||||||
|
Secret ChannelMode = 's' // flag, deprecated
|
||||||
|
UserLimit ChannelMode = 'l' // flag arg
|
||||||
|
Voice ChannelMode = 'v' // arg
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
SupportedChannelModes = ChannelModes{
|
||||||
|
BanMask, ExceptMask, InviteMask, InviteOnly, Key, NoOutside,
|
||||||
|
OpOnlyTopic, Persistent, Private, UserLimit,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// commands
|
||||||
|
//
|
||||||
|
|
||||||
|
func (m *ModeCommand) HandleServer(s *Server) {
|
||||||
|
client := m.Client()
|
||||||
|
target := s.clients.Get(m.nickname)
|
||||||
|
|
||||||
|
if target == nil {
|
||||||
|
client.ErrNoSuchNick(m.nickname)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if client != target && !client.flags[Operator] {
|
||||||
|
client.ErrUsersDontMatch()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
changes := make(ModeChanges, 0, len(m.changes))
|
||||||
|
|
||||||
|
for _, change := range m.changes {
|
||||||
|
switch change.mode {
|
||||||
|
case Invisible, ServerNotice, WallOps:
|
||||||
|
switch change.op {
|
||||||
|
case Add:
|
||||||
|
if target.flags[change.mode] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
target.flags[change.mode] = true
|
||||||
|
changes = append(changes, change)
|
||||||
|
|
||||||
|
case Remove:
|
||||||
|
if !target.flags[change.mode] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(target.flags, change.mode)
|
||||||
|
changes = append(changes, change)
|
||||||
|
}
|
||||||
|
|
||||||
|
case Operator, LocalOperator:
|
||||||
|
if change.op == Remove {
|
||||||
|
if !target.flags[change.mode] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(target.flags, change.mode)
|
||||||
|
changes = append(changes, change)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Who should get these replies?
|
||||||
|
if len(changes) > 0 {
|
||||||
|
client.Reply(RplMode(client, target, changes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ChannelModeCommand) HandleServer(server *Server) {
|
||||||
|
client := msg.Client()
|
||||||
|
channel := server.channels.Get(msg.channel)
|
||||||
|
if channel == nil {
|
||||||
|
client.ErrNoSuchChannel(msg.channel)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
channel.Mode(client, msg.changes)
|
||||||
|
}
|
@ -181,7 +181,8 @@ func (target *Client) RplCreated() {
|
|||||||
|
|
||||||
func (target *Client) RplMyInfo() {
|
func (target *Client) RplMyInfo() {
|
||||||
target.NumericReply(RPL_MYINFO,
|
target.NumericReply(RPL_MYINFO,
|
||||||
"%s %s aiOorsw abeIikmntpqrsl", target.server.name, SEM_VER)
|
"%s %s %s %s",
|
||||||
|
target.server.name, SEM_VER, SupportedUserModes, SupportedChannelModes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (target *Client) RplUModeIs(client *Client) {
|
func (target *Client) RplUModeIs(client *Client) {
|
||||||
|
@ -94,9 +94,7 @@ func (server *Server) loadChannels() {
|
|||||||
log.Fatal("error loading channels: ", err)
|
log.Fatal("error loading channels: ", err)
|
||||||
}
|
}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var name Name
|
var name, flags, key, topic string
|
||||||
var flags string
|
|
||||||
var key, topic Text
|
|
||||||
var userLimit uint64
|
var userLimit uint64
|
||||||
var banList, exceptList, inviteList string
|
var banList, exceptList, inviteList string
|
||||||
err = rows.Scan(&name, &flags, &key, &topic, &userLimit, &banList,
|
err = rows.Scan(&name, &flags, &key, &topic, &userLimit, &banList,
|
||||||
@ -106,12 +104,12 @@ func (server *Server) loadChannels() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
channel := NewChannel(server, name)
|
channel := NewChannel(server, NewName(name))
|
||||||
for _, flag := range flags {
|
for _, flag := range flags {
|
||||||
channel.flags[ChannelMode(flag)] = true
|
channel.flags[ChannelMode(flag)] = true
|
||||||
}
|
}
|
||||||
channel.key = key
|
channel.key = NewText(key)
|
||||||
channel.topic = topic
|
channel.topic = NewText(topic)
|
||||||
channel.userLimit = userLimit
|
channel.userLimit = userLimit
|
||||||
loadChannelList(channel, banList, BanMask)
|
loadChannelList(channel, banList, BanMask)
|
||||||
loadChannelList(channel, exceptList, ExceptMask)
|
loadChannelList(channel, exceptList, ExceptMask)
|
||||||
@ -339,7 +337,7 @@ func (msg *RFC2812UserCommand) HandleRegServer(server *Server) {
|
|||||||
}
|
}
|
||||||
flags := msg.Flags()
|
flags := msg.Flags()
|
||||||
if len(flags) > 0 {
|
if len(flags) > 0 {
|
||||||
for _, mode := range msg.Flags() {
|
for _, mode := range flags {
|
||||||
client.flags[mode] = true
|
client.flags[mode] = true
|
||||||
}
|
}
|
||||||
client.RplUModeIs(client)
|
client.RplUModeIs(client)
|
||||||
@ -491,58 +489,6 @@ func (msg *PrivMsgCommand) HandleServer(server *Server) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ModeCommand) HandleServer(s *Server) {
|
|
||||||
client := m.Client()
|
|
||||||
target := s.clients.Get(m.nickname)
|
|
||||||
|
|
||||||
if target == nil {
|
|
||||||
client.ErrNoSuchNick(m.nickname)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if client != target && !client.flags[Operator] {
|
|
||||||
client.ErrUsersDontMatch()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
changes := make(ModeChanges, 0, len(m.changes))
|
|
||||||
|
|
||||||
for _, change := range m.changes {
|
|
||||||
switch change.mode {
|
|
||||||
case Invisible, ServerNotice, WallOps:
|
|
||||||
switch change.op {
|
|
||||||
case Add:
|
|
||||||
if target.flags[change.mode] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
target.flags[change.mode] = true
|
|
||||||
changes = append(changes, change)
|
|
||||||
|
|
||||||
case Remove:
|
|
||||||
if !target.flags[change.mode] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
delete(target.flags, change.mode)
|
|
||||||
changes = append(changes, change)
|
|
||||||
}
|
|
||||||
|
|
||||||
case Operator, LocalOperator:
|
|
||||||
if change.op == Remove {
|
|
||||||
if !target.flags[change.mode] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
delete(target.flags, change.mode)
|
|
||||||
changes = append(changes, change)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Who should get these replies?
|
|
||||||
if len(changes) > 0 {
|
|
||||||
client.Reply(RplMode(client, target, changes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) WhoisChannelsNames() []string {
|
func (client *Client) WhoisChannelsNames() []string {
|
||||||
chstrs := make([]string, len(client.channels))
|
chstrs := make([]string, len(client.channels))
|
||||||
index := 0
|
index := 0
|
||||||
@ -579,17 +525,6 @@ func (m *WhoisCommand) HandleServer(server *Server) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *ChannelModeCommand) HandleServer(server *Server) {
|
|
||||||
client := msg.Client()
|
|
||||||
channel := server.channels.Get(msg.channel)
|
|
||||||
if channel == nil {
|
|
||||||
client.ErrNoSuchChannel(msg.channel)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
channel.Mode(client, msg.changes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func whoChannel(client *Client, channel *Channel, friends ClientSet) {
|
func whoChannel(client *Client, channel *Channel, friends ClientSet) {
|
||||||
for member := range channel.members {
|
for member := range channel.members {
|
||||||
if !client.flags[Invisible] || friends[client] {
|
if !client.flags[Invisible] || friends[client] {
|
||||||
|
21
irc/types.go
21
irc/types.go
@ -9,27 +9,6 @@ import (
|
|||||||
// simple types
|
// simple types
|
||||||
//
|
//
|
||||||
|
|
||||||
// add, remove, list modes
|
|
||||||
type ModeOp rune
|
|
||||||
|
|
||||||
func (op ModeOp) String() string {
|
|
||||||
return string(op)
|
|
||||||
}
|
|
||||||
|
|
||||||
// user mode flags
|
|
||||||
type UserMode rune
|
|
||||||
|
|
||||||
func (mode UserMode) String() string {
|
|
||||||
return string(mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// channel mode flags
|
|
||||||
type ChannelMode rune
|
|
||||||
|
|
||||||
func (mode ChannelMode) String() string {
|
|
||||||
return string(mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChannelNameMap map[Name]*Channel
|
type ChannelNameMap map[Name]*Channel
|
||||||
|
|
||||||
func (channels ChannelNameMap) Get(name Name) *Channel {
|
func (channels ChannelNameMap) Get(name Name) *Channel {
|
||||||
|
Loading…
Reference in New Issue
Block a user