mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
Implement message-ids draft
This commit is contained in:
parent
79d8636c6d
commit
e741c1476b
@ -23,6 +23,7 @@ const (
|
|||||||
ExtendedJoin Capability = "extended-join"
|
ExtendedJoin Capability = "extended-join"
|
||||||
InviteNotify Capability = "invite-notify"
|
InviteNotify Capability = "invite-notify"
|
||||||
MaxLine Capability = "draft/maxline"
|
MaxLine Capability = "draft/maxline"
|
||||||
|
MessageIDs Capability = "draft/message-ids"
|
||||||
MessageTags Capability = "draft/message-tags-0.2"
|
MessageTags Capability = "draft/message-tags-0.2"
|
||||||
MultiPrefix Capability = "multi-prefix"
|
MultiPrefix Capability = "multi-prefix"
|
||||||
SASL Capability = "sasl"
|
SASL Capability = "sasl"
|
||||||
@ -40,6 +41,7 @@ var (
|
|||||||
EchoMessage: true,
|
EchoMessage: true,
|
||||||
ExtendedJoin: true,
|
ExtendedJoin: true,
|
||||||
InviteNotify: true,
|
InviteNotify: true,
|
||||||
|
MessageIDs: true,
|
||||||
// MaxLine is set during server startup
|
// MaxLine is set during server startup
|
||||||
MessageTags: true,
|
MessageTags: true,
|
||||||
MultiPrefix: true,
|
MultiPrefix: true,
|
||||||
|
@ -372,21 +372,21 @@ func (channel *Channel) CanSpeak(client *Client) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TagMsg sends a tag message to everyone in this channel who can accept them.
|
// TagMsg sends a tag message to everyone in this channel who can accept them.
|
||||||
func (channel *Channel) TagMsg(minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client) {
|
func (channel *Channel) TagMsg(msgid string, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client) {
|
||||||
channel.sendMessage("TAGMSG", []Capability{MessageTags}, minPrefix, clientOnlyTags, client, nil)
|
channel.sendMessage(msgid, "TAGMSG", []Capability{MessageTags}, minPrefix, clientOnlyTags, client, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrivMsg sends a private message to everyone in this channel.
|
// PrivMsg sends a private message to everyone in this channel.
|
||||||
func (channel *Channel) PrivMsg(minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message string) {
|
func (channel *Channel) PrivMsg(msgid string, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message string) {
|
||||||
channel.sendMessage("PRIVMSG", nil, minPrefix, clientOnlyTags, client, &message)
|
channel.sendMessage(msgid, "PRIVMSG", nil, minPrefix, clientOnlyTags, client, &message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notice sends a private message to everyone in this channel.
|
// Notice sends a private message to everyone in this channel.
|
||||||
func (channel *Channel) Notice(minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message string) {
|
func (channel *Channel) Notice(msgid string, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message string) {
|
||||||
channel.sendMessage("NOTICE", nil, minPrefix, clientOnlyTags, client, &message)
|
channel.sendMessage(msgid, "NOTICE", nil, minPrefix, clientOnlyTags, client, &message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) sendMessage(cmd string, requiredCaps []Capability, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message *string) {
|
func (channel *Channel) sendMessage(msgid, cmd string, requiredCaps []Capability, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message *string) {
|
||||||
if !channel.CanSpeak(client) {
|
if !channel.CanSpeak(client) {
|
||||||
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
|
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
|
||||||
return
|
return
|
||||||
@ -419,33 +419,30 @@ func (channel *Channel) sendMessage(cmd string, requiredCaps []Capability, minPr
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var messageTagsToUse *map[string]ircmsg.TagValue
|
||||||
if member.capabilities[MessageTags] {
|
if member.capabilities[MessageTags] {
|
||||||
if message == nil {
|
messageTagsToUse = clientOnlyTags
|
||||||
member.SendFromClient(client, clientOnlyTags, client.nickMaskString, cmd, channel.name)
|
}
|
||||||
} else {
|
|
||||||
member.SendFromClient(client, clientOnlyTags, client.nickMaskString, cmd, channel.name, *message)
|
if message == nil {
|
||||||
}
|
member.SendFromClient(msgid, client, messageTagsToUse, client.nickMaskString, cmd, channel.name)
|
||||||
} else {
|
} else {
|
||||||
if message == nil {
|
member.SendFromClient(msgid, client, messageTagsToUse, client.nickMaskString, cmd, channel.name, *message)
|
||||||
member.SendFromClient(client, nil, client.nickMaskString, cmd, channel.name)
|
|
||||||
} else {
|
|
||||||
member.SendFromClient(client, nil, client.nickMaskString, cmd, channel.name, *message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SplitPrivMsg sends a private message to everyone in this channel.
|
// SplitPrivMsg sends a private message to everyone in this channel.
|
||||||
func (channel *Channel) SplitPrivMsg(minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
|
func (channel *Channel) SplitPrivMsg(msgid string, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
|
||||||
channel.sendSplitMessage("PRIVMSG", minPrefix, clientOnlyTags, client, message)
|
channel.sendSplitMessage(msgid, "PRIVMSG", minPrefix, clientOnlyTags, client, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SplitNotice sends a private message to everyone in this channel.
|
// SplitNotice sends a private message to everyone in this channel.
|
||||||
func (channel *Channel) SplitNotice(minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
|
func (channel *Channel) SplitNotice(msgid string, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
|
||||||
channel.sendSplitMessage("NOTICE", minPrefix, clientOnlyTags, client, message)
|
channel.sendSplitMessage(msgid, "NOTICE", minPrefix, clientOnlyTags, client, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) sendSplitMessage(cmd string, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
|
func (channel *Channel) sendSplitMessage(msgid, cmd string, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
|
||||||
if !channel.CanSpeak(client) {
|
if !channel.CanSpeak(client) {
|
||||||
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
|
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
|
||||||
return
|
return
|
||||||
@ -468,9 +465,9 @@ func (channel *Channel) sendSplitMessage(cmd string, minPrefix *ChannelMode, cli
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if member.capabilities[MessageTags] {
|
if member.capabilities[MessageTags] {
|
||||||
member.SendSplitMsgFromClient(client, clientOnlyTags, cmd, channel.name, message)
|
member.SendSplitMsgFromClient(msgid, client, clientOnlyTags, cmd, channel.name, message)
|
||||||
} else {
|
} else {
|
||||||
member.SendSplitMsgFromClient(client, nil, cmd, channel.name, message)
|
member.SendSplitMsgFromClient(msgid, client, nil, cmd, channel.name, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,19 +498,19 @@ func (client *Client) destroy() {
|
|||||||
|
|
||||||
// SendSplitMsgFromClient sends an IRC PRIVMSG/NOTICE coming from a specific client.
|
// SendSplitMsgFromClient sends an IRC PRIVMSG/NOTICE coming from a specific client.
|
||||||
// Adds account-tag to the line as well.
|
// Adds account-tag to the line as well.
|
||||||
func (client *Client) SendSplitMsgFromClient(from *Client, tags *map[string]ircmsg.TagValue, command, target string, message SplitMessage) {
|
func (client *Client) SendSplitMsgFromClient(msgid string, from *Client, tags *map[string]ircmsg.TagValue, command, target string, message SplitMessage) {
|
||||||
if client.capabilities[MaxLine] {
|
if client.capabilities[MaxLine] {
|
||||||
client.SendFromClient(from, tags, from.nickMaskString, command, target, message.ForMaxLine)
|
client.SendFromClient(msgid, from, tags, from.nickMaskString, command, target, message.ForMaxLine)
|
||||||
} else {
|
} else {
|
||||||
for _, str := range message.For512 {
|
for _, str := range message.For512 {
|
||||||
client.SendFromClient(from, tags, from.nickMaskString, command, target, str)
|
client.SendFromClient(msgid, from, tags, from.nickMaskString, command, target, str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendFromClient sends an IRC line coming from a specific client.
|
// SendFromClient sends an IRC line coming from a specific client.
|
||||||
// Adds account-tag to the line as well.
|
// Adds account-tag to the line as well.
|
||||||
func (client *Client) SendFromClient(from *Client, tags *map[string]ircmsg.TagValue, prefix string, command string, params ...string) error {
|
func (client *Client) SendFromClient(msgid string, from *Client, tags *map[string]ircmsg.TagValue, prefix string, command string, params ...string) error {
|
||||||
// attach account-tag
|
// attach account-tag
|
||||||
if client.capabilities[AccountTag] && from.account != &NoAccount {
|
if client.capabilities[AccountTag] && from.account != &NoAccount {
|
||||||
if tags == nil {
|
if tags == nil {
|
||||||
@ -519,6 +519,14 @@ func (client *Client) SendFromClient(from *Client, tags *map[string]ircmsg.TagVa
|
|||||||
(*tags)["account"] = ircmsg.MakeTagValue(from.account.Name)
|
(*tags)["account"] = ircmsg.MakeTagValue(from.account.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// attach message-id
|
||||||
|
if len(msgid) > 0 && client.capabilities[MessageIDs] {
|
||||||
|
if tags == nil {
|
||||||
|
tags = ircmsg.MakeTags("draft/msgid", msgid)
|
||||||
|
} else {
|
||||||
|
(*tags)["draft/msgid"] = ircmsg.MakeTagValue(msgid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return client.Send(tags, prefix, command, params...)
|
return client.Send(tags, prefix, command, params...)
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ func (client *Client) alertMonitors() {
|
|||||||
for _, mClient := range client.server.monitoring[client.nickCasefolded] {
|
for _, mClient := range client.server.monitoring[client.nickCasefolded] {
|
||||||
// don't have to notify ourselves
|
// don't have to notify ourselves
|
||||||
if &mClient != client {
|
if &mClient != client {
|
||||||
mClient.SendFromClient(client, nil, client.server.name, RPL_MONONLINE, mClient.nick, client.nickMaskString)
|
mClient.SendFromClient("", client, nil, client.server.name, RPL_MONONLINE, mClient.nick, client.nickMaskString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -606,6 +607,11 @@ func (server *Server) wslisten(addr string, tlsMap map[string]*TLSListenConfig)
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generateMessageID returns a network-unique message ID.
|
||||||
|
func (server *Server) generateMessageID() string {
|
||||||
|
return fmt.Sprintf("%s-%s", strconv.FormatInt(time.Now().UTC().UnixNano(), 10), strconv.FormatInt(rand.Int63(), 10))
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// server functionality
|
// server functionality
|
||||||
//
|
//
|
||||||
@ -937,7 +943,8 @@ func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
|
|||||||
client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
|
client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
channel.SplitPrivMsg(lowestPrefix, clientOnlyTags, client, splitMsg)
|
msgid := server.generateMessageID()
|
||||||
|
channel.SplitPrivMsg(msgid, lowestPrefix, clientOnlyTags, client, splitMsg)
|
||||||
} else {
|
} else {
|
||||||
target, err = CasefoldName(targetString)
|
target, err = CasefoldName(targetString)
|
||||||
user := server.clients.Get(target)
|
user := server.clients.Get(target)
|
||||||
@ -950,9 +957,10 @@ func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
|
|||||||
if !user.capabilities[MessageTags] {
|
if !user.capabilities[MessageTags] {
|
||||||
clientOnlyTags = nil
|
clientOnlyTags = nil
|
||||||
}
|
}
|
||||||
user.SendSplitMsgFromClient(client, clientOnlyTags, "PRIVMSG", user.nick, splitMsg)
|
msgid := server.generateMessageID()
|
||||||
|
user.SendSplitMsgFromClient(msgid, client, clientOnlyTags, "PRIVMSG", user.nick, splitMsg)
|
||||||
if client.capabilities[EchoMessage] {
|
if client.capabilities[EchoMessage] {
|
||||||
client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "PRIVMSG", user.nick, message)
|
client.SendSplitMsgFromClient(msgid, client, clientOnlyTags, "PRIVMSG", user.nick, splitMsg)
|
||||||
}
|
}
|
||||||
if user.flags[Away] {
|
if user.flags[Away] {
|
||||||
//TODO(dan): possibly implement cooldown of away notifications to users
|
//TODO(dan): possibly implement cooldown of away notifications to users
|
||||||
@ -993,7 +1001,9 @@ func tagmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
|
client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
channel.TagMsg(lowestPrefix, clientOnlyTags, client)
|
msgid := server.generateMessageID()
|
||||||
|
|
||||||
|
channel.TagMsg(msgid, lowestPrefix, clientOnlyTags, client)
|
||||||
} else {
|
} else {
|
||||||
target, err = CasefoldName(targetString)
|
target, err = CasefoldName(targetString)
|
||||||
user := server.clients.Get(target)
|
user := server.clients.Get(target)
|
||||||
@ -1003,13 +1013,15 @@ func tagmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
msgid := server.generateMessageID()
|
||||||
|
|
||||||
// end user can't receive tagmsgs
|
// end user can't receive tagmsgs
|
||||||
if !user.capabilities[MessageTags] {
|
if !user.capabilities[MessageTags] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
user.SendFromClient(client, clientOnlyTags, "TAGMSG", user.nick)
|
user.SendFromClient(msgid, client, clientOnlyTags, "TAGMSG", user.nick)
|
||||||
if client.capabilities[EchoMessage] {
|
if client.capabilities[EchoMessage] {
|
||||||
client.SendFromClient(client, clientOnlyTags, "TAGMSG", user.nick)
|
client.SendFromClient(msgid, client, clientOnlyTags, "TAGMSG", user.nick)
|
||||||
}
|
}
|
||||||
if user.flags[Away] {
|
if user.flags[Away] {
|
||||||
//TODO(dan): possibly implement cooldown of away notifications to users
|
//TODO(dan): possibly implement cooldown of away notifications to users
|
||||||
@ -1210,7 +1222,7 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
originalHost := client.nickMaskString
|
originalHost := client.nickMaskString
|
||||||
client.vhost = server.operators[name].Vhost
|
client.vhost = server.operators[name].Vhost
|
||||||
for fClient := range client.Friends(ChgHost) {
|
for fClient := range client.Friends(ChgHost) {
|
||||||
fClient.SendFromClient(client, nil, originalHost, "CHGHOST", client.username, client.vhost)
|
fClient.SendFromClient("", client, nil, originalHost, "CHGHOST", client.username, client.vhost)
|
||||||
}
|
}
|
||||||
client.updateNickMask()
|
client.updateNickMask()
|
||||||
}
|
}
|
||||||
@ -1449,9 +1461,9 @@ func awayHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
// dispatch away-notify
|
// dispatch away-notify
|
||||||
for friend := range client.Friends(AwayNotify) {
|
for friend := range client.Friends(AwayNotify) {
|
||||||
if client.flags[Away] {
|
if client.flags[Away] {
|
||||||
friend.SendFromClient(client, nil, client.nickMaskString, "AWAY", client.awayMessage)
|
friend.SendFromClient("", client, nil, client.nickMaskString, "AWAY", client.awayMessage)
|
||||||
} else {
|
} else {
|
||||||
friend.SendFromClient(client, nil, client.nickMaskString, "AWAY")
|
friend.SendFromClient("", client, nil, client.nickMaskString, "AWAY")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1515,7 +1527,8 @@ func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
// errors silently ignored with NOTICE as per RFC
|
// errors silently ignored with NOTICE as per RFC
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
channel.SplitNotice(lowestPrefix, clientOnlyTags, client, splitMsg)
|
msgid := server.generateMessageID()
|
||||||
|
channel.SplitNotice(msgid, lowestPrefix, clientOnlyTags, client, splitMsg)
|
||||||
} else {
|
} else {
|
||||||
target, err := CasefoldName(targetString)
|
target, err := CasefoldName(targetString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1530,9 +1543,10 @@ func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
if !user.capabilities[MessageTags] {
|
if !user.capabilities[MessageTags] {
|
||||||
clientOnlyTags = nil
|
clientOnlyTags = nil
|
||||||
}
|
}
|
||||||
user.SendSplitMsgFromClient(client, clientOnlyTags, "NOTICE", user.nick, splitMsg)
|
msgid := server.generateMessageID()
|
||||||
|
user.SendSplitMsgFromClient(msgid, client, clientOnlyTags, "NOTICE", user.nick, splitMsg)
|
||||||
if client.capabilities[EchoMessage] {
|
if client.capabilities[EchoMessage] {
|
||||||
client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "NOTICE", user.nick, message)
|
client.SendSplitMsgFromClient(msgid, client, clientOnlyTags, "NOTICE", user.nick, splitMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/DanielOaks/oragono/irc"
|
"github.com/DanielOaks/oragono/irc"
|
||||||
"github.com/DanielOaks/oragono/mkcerts"
|
"github.com/DanielOaks/oragono/mkcerts"
|
||||||
@ -83,6 +85,7 @@ Options:
|
|||||||
}
|
}
|
||||||
} else if arguments["run"].(bool) {
|
} else if arguments["run"].(bool) {
|
||||||
irc.Log.SetLevel(config.Server.Log)
|
irc.Log.SetLevel(config.Server.Log)
|
||||||
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
server := irc.NewServer(configfile, config)
|
server := irc.NewServer(configfile, config)
|
||||||
if server == nil {
|
if server == nil {
|
||||||
log.Println("Could not load server")
|
log.Println("Could not load server")
|
||||||
|
Loading…
Reference in New Issue
Block a user