mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-22 11:59:40 +01:00
commit
2aded271c5
@ -62,6 +62,8 @@ const (
|
|||||||
RelaymsgTagName = "draft/relaymsg"
|
RelaymsgTagName = "draft/relaymsg"
|
||||||
// BOT mode: https://ircv3.net/specs/extensions/bot-mode
|
// BOT mode: https://ircv3.net/specs/extensions/bot-mode
|
||||||
BotTagName = "bot"
|
BotTagName = "bot"
|
||||||
|
// https://ircv3.net/specs/extensions/chathistory
|
||||||
|
ChathistoryTargetsBatchType = "draft/chathistory-targets"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -1059,7 +1059,7 @@ func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
batchID := rb.StartNestedHistoryBatch(chname)
|
batchID := rb.StartNestedBatch(chname, "chathistory")
|
||||||
defer rb.EndNestedBatch(batchID)
|
defer rb.EndNestedBatch(batchID)
|
||||||
|
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
|
@ -850,7 +850,7 @@ func (client *Client) replayPrivmsgHistory(rb *ResponseBuffer, items []history.I
|
|||||||
if target == "" {
|
if target == "" {
|
||||||
target = nick
|
target = nick
|
||||||
}
|
}
|
||||||
batchID = rb.StartNestedHistoryBatch(target)
|
batchID = rb.StartNestedBatch(target, "chathistory")
|
||||||
|
|
||||||
isSelfMessage := func(item *history.Item) bool {
|
isSelfMessage := func(item *history.Item) bool {
|
||||||
// XXX: Params[0] is the message target. if the source of this message is an in-memory
|
// XXX: Params[0] is the message target. if the source of this message is an in-memory
|
||||||
@ -1425,27 +1425,27 @@ func composeMultilineBatch(batchID, fromNickMask, fromAccount string, isBot bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// these are all the output commands that MUST have their last param be a trailing.
|
// in practice, many clients require that the final parameter be a trailing
|
||||||
// this is needed because dumb clients like to treat trailing params separately from the
|
// (prefixed with `:`) even when this is not syntactically necessary.
|
||||||
// other params in messages.
|
// by default, force the following commands to use a trailing:
|
||||||
commandsThatMustUseTrailing = map[string]bool{
|
commandsThatMustUseTrailing = utils.SetLiteral(
|
||||||
"PRIVMSG": true,
|
"PRIVMSG",
|
||||||
"NOTICE": true,
|
"NOTICE",
|
||||||
|
RPL_WHOISCHANNELS,
|
||||||
RPL_WHOISCHANNELS: true,
|
RPL_USERHOST,
|
||||||
RPL_USERHOST: true,
|
|
||||||
|
|
||||||
// mirc's handling of RPL_NAMREPLY is broken:
|
// mirc's handling of RPL_NAMREPLY is broken:
|
||||||
// https://forums.mirc.com/ubbthreads.php/topics/266939/re-nick-list
|
// https://forums.mirc.com/ubbthreads.php/topics/266939/re-nick-list
|
||||||
RPL_NAMREPLY: true,
|
RPL_NAMREPLY,
|
||||||
}
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func forceTrailing(config *Config, command string) bool {
|
||||||
|
return config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing.Has(command)
|
||||||
|
}
|
||||||
|
|
||||||
// SendRawMessage sends a raw message to the client.
|
// SendRawMessage sends a raw message to the client.
|
||||||
func (session *Session) SendRawMessage(message ircmsg.Message, blocking bool) error {
|
func (session *Session) SendRawMessage(message ircmsg.Message, blocking bool) error {
|
||||||
// use dumb hack to force the last param to be a trailing param if required
|
if forceTrailing(session.client.server.Config(), message.Command) {
|
||||||
config := session.client.server.Config()
|
|
||||||
if config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing[message.Command] {
|
|
||||||
message.ForceTrailing()
|
message.ForceTrailing()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,10 +655,8 @@ func chathistoryHandler(server *Server, client *Client, msg ircmsg.Message, rb *
|
|||||||
} else {
|
} else {
|
||||||
// successful responses are sent as a chathistory or history batch
|
// successful responses are sent as a chathistory or history batch
|
||||||
if listTargets {
|
if listTargets {
|
||||||
if rb.session.capabilities.Has(caps.Batch) { // #2066
|
batchID := rb.StartNestedBatch(caps.ChathistoryTargetsBatchType)
|
||||||
batchID := rb.StartNestedBatch("draft/chathistory-targets")
|
|
||||||
defer rb.EndNestedBatch(batchID)
|
defer rb.EndNestedBatch(batchID)
|
||||||
}
|
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
name := server.UnfoldName(target.CfName)
|
name := server.UnfoldName(target.CfName)
|
||||||
rb.Add(nil, server.name, "CHATHISTORY", "TARGETS", name,
|
rb.Add(nil, server.name, "CHATHISTORY", "TARGETS", name,
|
||||||
|
@ -79,8 +79,7 @@ func (m *MessageCache) Initialize(server *Server, serverTime time.Time, msgid st
|
|||||||
m.params = params
|
m.params = params
|
||||||
|
|
||||||
var msg ircmsg.Message
|
var msg ircmsg.Message
|
||||||
config := server.Config()
|
if forceTrailing(server.Config(), command) {
|
||||||
if config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing[command] {
|
|
||||||
msg.ForceTrailing()
|
msg.ForceTrailing()
|
||||||
}
|
}
|
||||||
msg.Source = nickmask
|
msg.Source = nickmask
|
||||||
@ -111,8 +110,7 @@ func (m *MessageCache) InitializeSplitMessage(server *Server, nickmask, accountN
|
|||||||
m.target = target
|
m.target = target
|
||||||
m.splitMessage = message
|
m.splitMessage = message
|
||||||
|
|
||||||
config := server.Config()
|
forceTrailing := forceTrailing(server.Config(), command)
|
||||||
forceTrailing := config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing[command]
|
|
||||||
|
|
||||||
if message.Is512() {
|
if message.Is512() {
|
||||||
isTagmsg := command == "TAGMSG"
|
isTagmsg := command == "TAGMSG"
|
||||||
|
@ -193,6 +193,9 @@ func (rb *ResponseBuffer) sendBatchEnd(blocking bool) {
|
|||||||
// Starts a nested batch (see the ResponseBuffer struct definition for a description of
|
// Starts a nested batch (see the ResponseBuffer struct definition for a description of
|
||||||
// how this works)
|
// how this works)
|
||||||
func (rb *ResponseBuffer) StartNestedBatch(batchType string, params ...string) (batchID string) {
|
func (rb *ResponseBuffer) StartNestedBatch(batchType string, params ...string) (batchID string) {
|
||||||
|
if !rb.session.capabilities.Has(caps.Batch) {
|
||||||
|
return
|
||||||
|
}
|
||||||
batchID = rb.session.generateBatchID()
|
batchID = rb.session.generateBatchID()
|
||||||
msgParams := make([]string, len(params)+2)
|
msgParams := make([]string, len(params)+2)
|
||||||
msgParams[0] = "+" + batchID
|
msgParams[0] = "+" + batchID
|
||||||
@ -219,19 +222,6 @@ func (rb *ResponseBuffer) EndNestedBatch(batchID string) {
|
|||||||
rb.AddMessage(ircmsg.MakeMessage(nil, rb.target.server.name, "BATCH", "-"+batchID))
|
rb.AddMessage(ircmsg.MakeMessage(nil, rb.target.server.name, "BATCH", "-"+batchID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience to start a nested batch for history lines, at the highest level
|
|
||||||
// supported by the client (`history`, `chathistory`, or no batch, in descending order).
|
|
||||||
func (rb *ResponseBuffer) StartNestedHistoryBatch(params ...string) (batchID string) {
|
|
||||||
var batchType string
|
|
||||||
if rb.session.capabilities.Has(caps.Batch) {
|
|
||||||
batchType = "chathistory"
|
|
||||||
}
|
|
||||||
if batchType != "" {
|
|
||||||
batchID = rb.StartNestedBatch(batchType, params...)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send sends all messages in the buffer to the client.
|
// Send sends all messages in the buffer to the client.
|
||||||
// Afterwards, the buffer is in an undefined state and MUST NOT be used further.
|
// Afterwards, the buffer is in an undefined state and MUST NOT be used further.
|
||||||
// If `blocking` is true you MUST be sending to the client from its own goroutine.
|
// If `blocking` is true you MUST be sending to the client from its own goroutine.
|
||||||
|
@ -20,6 +20,14 @@ func (s HashSet[T]) Remove(elem T) {
|
|||||||
delete(s, elem)
|
delete(s, elem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetLiteral[T comparable](elems ...T) HashSet[T] {
|
||||||
|
result := make(HashSet[T], len(elems))
|
||||||
|
for _, elem := range elems {
|
||||||
|
result.Add(elem)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func CopyMap[K comparable, V any](input map[K]V) (result map[K]V) {
|
func CopyMap[K comparable, V any](input map[K]V) (result map[K]V) {
|
||||||
result = make(map[K]V, len(input))
|
result = make(map[K]V, len(input))
|
||||||
for key, value := range input {
|
for key, value := range input {
|
||||||
|
2
irctest
2
irctest
@ -1 +1 @@
|
|||||||
Subproject commit 22c6743b24f2a85bf79a92fb0c7fab325c047a6c
|
Subproject commit 5a5dbdb50dda3dc9e5ed3d542ab75b1b87fccac9
|
Loading…
Reference in New Issue
Block a user