Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d88c6248b8 | |||
| 4a34ccce26 | |||
| 9d9fcef954 | |||
| 2d19acb846 | |||
| e993e8a32c | |||
| 541cbaabd2 | |||
| 86ad1e1633 | |||
| 19e0120423 | |||
| e9ad8f6962 | |||
| ef36fc0c24 | |||
| 458ab0a054 | |||
| 0e7e2b629c | |||
| 371a7eb9e4 | |||
| 485f68f5d1 | |||
| d465d742c6 | |||
| 37b62ff817 | |||
| fa13755311 | |||
| e83e2dc111 | |||
| a555dbd563 | |||
| f076aeaeda | |||
| 1056493211 | |||
| ddcd65fa47 | |||
| d21b18fc75 | |||
| 53b72e0cb0 | |||
| 839dea016a | |||
| e235ee014e | |||
|
|
c54a271f17 |
3
.hgtags
3
.hgtags
@@ -1,3 +1,6 @@
|
||||
da295cede46d95848348292e04e54fa5a5713ae3 release-1.0.0
|
||||
34892054c34384edeafa2b04a483697d7d8a73a3 release-1.1.0
|
||||
3586b48a5abfdbdeef310f2e154b06f4d16d38bb release-1.2.0
|
||||
49dcc63e80e98f8c2ce3bb029fe0c41a6426678f release-1.2.1
|
||||
111d6e41507dd0f374860b936d18a651a7cb09ce release-1.2.2
|
||||
129377245f8026414df6abc3f4292c10b30f0618 release-1.2.3
|
||||
|
||||
@@ -37,34 +37,51 @@ Tags: nmdc, AGPLv3
|
||||
-servername string
|
||||
Server name displayed to clients (default "nmdc-ircfrontend")
|
||||
-upstream string
|
||||
Upstream NMDC server (default "127.0.0.1:411")
|
||||
Upstream NMDC/ADC server (default "127.0.0.1:411")
|
||||
-verbose
|
||||
Display debugging information`
|
||||
|
||||
=COMPATIBILITY=
|
||||
|
||||
*This section was last updated on or around the release of 1.3.0. Current compatibility may differ.*
|
||||
|
||||
NMDC's smaller community has standardised around comparatively few protocol implementations by means of necessity. In comparison, there are a lot of IRC client implementations with slightly differing interpretations of the protocol.
|
||||
|
||||
Everything works:
|
||||
- Hexchat
|
||||
- Mango IRC
|
||||
- AndroIRC
|
||||
- Mutter
|
||||
- Weechat
|
||||
- mIRC 7
|
||||
- HoloIRC (after version 4.1.0)
|
||||
For passworded DC usernames, your IRC PASS username must be the same as your IRC nickname.
|
||||
|
||||
Usable, with bugs:
|
||||
- Lite IRC - The username and nickname fields must be identical
|
||||
- HoloIRC (4.1.0 and earlier) - Can't parse client tag, upstream bug https://github.com/tilal6991/HoloIRC/issues/140
|
||||
- AndChat - Duplicate usernames appear, upstream bug https://github.com/znc/znc/issues/424
|
||||
- Irssi - Ignorable warning "critical nicklist_set_host: assertion 'host != NULL' failed"
|
||||
Tested working:
|
||||
- AndChat
|
||||
- AndroIRC
|
||||
- Atomic
|
||||
- Hexchat
|
||||
- HoloIRC
|
||||
- Irssi
|
||||
- LiteIRC
|
||||
- Mango IRC
|
||||
- mIRC 7
|
||||
- Mutter
|
||||
- Revolution IRC
|
||||
- Weechat
|
||||
- Yaaic
|
||||
|
||||
Unusable:
|
||||
- Yaaic and Atomic - doesn't properly understand/parse the room join
|
||||
- Rocket.chat 0.6x IRC plugin (can join room and recieve PMs after some regex tweaking)
|
||||
|
||||
=CHANGELOG=
|
||||
|
||||
2018-03-24 1.3.0
|
||||
- Feature: Support ADC hubs
|
||||
- Compatibility: Fix missing userlist in LiteIRC (since 1.2.2)
|
||||
- Compatibility: Avoid sending empty room list (fixes Yaaic, atomic, Revolution IRC)
|
||||
- Update libnmdc to 0.17
|
||||
|
||||
2017-05-28 1.2.3
|
||||
- Fix a regression with userlist display on HexChat (other IRC client compatibility unknown)
|
||||
|
||||
2017-05-27 1.2.2
|
||||
- Update libnmdc to 0.14
|
||||
- Fix a crash that could occur if the server is scanned by a non-irc client
|
||||
|
||||
2016-11-29 1.2.1
|
||||
- Update libnmdc to 0.11
|
||||
- Fix an issue with -devel version tag in 1.2.0 release binaries
|
||||
|
||||
33
chatFormatting.go
Normal file
33
chatFormatting.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
rx_colorControlCode *regexp.Regexp = regexp.MustCompilePOSIX("\x03[0-9]+(,[0-9]+)?")
|
||||
rx_formattingControlCode *regexp.Regexp = regexp.MustCompile("(\x02|\x1D|\x1F|\x16|\x0F)")
|
||||
)
|
||||
|
||||
func reformatOutgoingMessageBody(body string) string {
|
||||
|
||||
// Strip color codes
|
||||
noColors := rx_colorControlCode.ReplaceAllString(body, "")
|
||||
|
||||
// Strip formatting codes
|
||||
return rx_formattingControlCode.ReplaceAllString(noColors, "")
|
||||
|
||||
}
|
||||
|
||||
func reformatIncomingMessageBody(body string) string {
|
||||
|
||||
// "Greentext" filter
|
||||
// TODO markdown filters
|
||||
if len(body) > 0 && body[0] == '>' {
|
||||
return "\x033" + strings.Replace(body, "implying", "\x02implying\x02", -1)
|
||||
|
||||
} else {
|
||||
return body
|
||||
}
|
||||
}
|
||||
68
clientTag.go
Normal file
68
clientTag.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type clientTag struct {
|
||||
AppName string
|
||||
Version string
|
||||
}
|
||||
|
||||
var (
|
||||
rx_bestNumberPart = regexp.MustCompile(`[0-9\.]+`)
|
||||
)
|
||||
|
||||
func parseVersion(ver string) clientTag {
|
||||
// Try our best to turn the supplied text into a structured version
|
||||
ret := clientTag{
|
||||
AppName: APP_NAME,
|
||||
Version: APP_VERSION,
|
||||
}
|
||||
|
||||
// Special case: Some clients use a structured version AppName:Version:Metadata
|
||||
// If we check for that, we can support clients with spaces in the name
|
||||
if cParts := strings.Split(ver, ":"); len(cParts) == 3 {
|
||||
ret.AppName = cParts[0]
|
||||
ret.Version = cParts[1]
|
||||
|
||||
} else if ver == "Atomic - An IRC client for Android https://indrora.github.io/Atomic" {
|
||||
ret.AppName = "Atomic"
|
||||
ret.Version = "2.1" // Abandonware. Last available version
|
||||
|
||||
} else if ver == "Yaaic - Yet Another Android IRC Client - http://www.yaaic.org" {
|
||||
ret.AppName = "Yaaic"
|
||||
ret.Version = "1.1" // Abandonware. Last available version
|
||||
|
||||
} else {
|
||||
|
||||
// Special cases all failed, time for heuristics
|
||||
// Turn colons to spaces; keep the first word, and the the first word containing digits
|
||||
ver = strings.Trim(strings.Replace(ver, ":", " ", -1), " ")
|
||||
|
||||
words := strings.Split(ver, " ")
|
||||
|
||||
for _, word := range words[1:] {
|
||||
if strings.ContainsAny(word, "0123456789") {
|
||||
ret.AppName = words[0]
|
||||
ret.Version = strings.Replace(word, "(", "", -1) // AndroIRC
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We only support digits, periods, and hyphens in the number part
|
||||
// This removes the leading v from mIRC and the trailing deb** from irssi
|
||||
if submatch := rx_bestNumberPart.FindStringSubmatch(ret.Version); len(submatch) == 1 {
|
||||
ret.Version = submatch[0]
|
||||
}
|
||||
|
||||
// Special case: "Relay" means "HoloIRC"
|
||||
if ret.AppName == "Relay" && ret.Version == "1.0" && strings.Contains(ver, "Android") {
|
||||
ret.AppName = "HoloIRC"
|
||||
ret.Version = "4"
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
73
clientTag_test.go
Normal file
73
clientTag_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseVersion(t *testing.T) {
|
||||
|
||||
tests := [][3]string{
|
||||
|
||||
[3]string{
|
||||
"HexChat 2.12.1 [x64] / Microsoft Windows 10 Pro (x64) [Intel(R) Core(TM) i5-2500 CPU @ 3.30GHz (3.60GHz)]",
|
||||
"HexChat", "2.12.1",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"AndroIRC - Android IRC Client (5.2 - Build 6830152) - http://www.androirc.com",
|
||||
"AndroIRC", "5.2",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"AndChat 1.4.3.2 http://www.andchat.ne",
|
||||
"AndChat", "1.4.3.2",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"liteIRC for Android 1.1.8",
|
||||
"liteIRC", "1.1.8",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
":Relay:1.0:Android", // HoloIRC before 4.1.0
|
||||
"HoloIRC", "4",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"Relay:1.0:Android", // HoloIRC after 4.1.0
|
||||
"HoloIRC", "4",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"mIRC v7.45",
|
||||
"mIRC", "7.45",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"Revolution IRC:0.3.2:Android",
|
||||
"Revolution IRC", "0.3.2",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"irssi v1.0.2-1+deb9u3",
|
||||
"irssi", "1.0.2",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"Atomic - An IRC client for Android https://indrora.github.io/Atomic",
|
||||
"Atomic", "2.1",
|
||||
},
|
||||
|
||||
[3]string{
|
||||
"Yaaic - Yet Another Android IRC Client - http://www.yaaic.org",
|
||||
"Yaaic", "1.1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
result := parseVersion(test[0])
|
||||
if result.AppName != test[1] || result.Version != test[2] {
|
||||
t.Fatalf("Got <%s,%s> expecting <%s,%s>\n", result.AppName, result.Version, test[1], test[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
4
main.go
4
main.go
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
Copyright (C) 2016 The `nmdc-ircfrontend' author(s)
|
||||
Copyright (C) 2016-2018 The `nmdc-ircfrontend' author(s)
|
||||
Copyright (C) 2013 Harry Jeffery
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
func main() {
|
||||
|
||||
ircAddress := flag.String("bind", ":6667", "The address:port to bind to and listen for clients on")
|
||||
dcAddress := flag.String("upstream", "127.0.0.1:411", "Upstream NMDC server")
|
||||
dcAddress := flag.String("upstream", "127.0.0.1:411", "Upstream NMDC/ADC server")
|
||||
serverName := flag.String("servername", APP_NAME, "Server name displayed to clients")
|
||||
hubsec := flag.String("hubsecurity", "Hub-Security", "Nick used for administrative events")
|
||||
verbose := flag.Bool("verbose", false, "Display debugging information")
|
||||
|
||||
20
quirks.go
Normal file
20
quirks.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Quirks struct {
|
||||
RequireNickForGeneralMessages bool
|
||||
}
|
||||
|
||||
func GetQuirksForClient(ver string) Quirks {
|
||||
if strings.Contains(ver, "mIRC") || strings.Contains(ver, "Atomic") || strings.Contains(ver, "Yaaic") {
|
||||
return Quirks{
|
||||
RequireNickForGeneralMessages: true,
|
||||
}
|
||||
|
||||
} else {
|
||||
return Quirks{}
|
||||
}
|
||||
}
|
||||
111
server.go
111
server.go
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
Copyright (C) 2016 The `nmdc-ircfrontend' author(s)
|
||||
Copyright (C) 2016-2018 The `nmdc-ircfrontend' author(s)
|
||||
Copyright (C) 2013 Harry Jeffery
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -51,6 +50,7 @@ type Server struct {
|
||||
|
||||
upstreamLauncher libnmdc.HubConnectionOptions
|
||||
upstreamCloser chan struct{}
|
||||
upstreamEvents chan libnmdc.HubEvent
|
||||
upstream *libnmdc.HubConnection
|
||||
|
||||
verbose bool
|
||||
@@ -59,6 +59,9 @@ type Server struct {
|
||||
recievedFirstServerMessage bool
|
||||
recievedCtcpVersion bool
|
||||
nickChangeAttempt int
|
||||
sentFakeSelfJoin bool
|
||||
|
||||
quirks Quirks
|
||||
}
|
||||
|
||||
func NewServer(name string, upstream libnmdc.HubAddress, conn net.Conn) *Server {
|
||||
@@ -73,10 +76,12 @@ func NewServer(name string, upstream libnmdc.HubAddress, conn net.Conn) *Server
|
||||
motd: "Connected to " + name + ". You /must/ join " + BLESSED_CHANNEL + " to continue.",
|
||||
upstreamLauncher: libnmdc.HubConnectionOptions{
|
||||
Address: upstream,
|
||||
Self: *self,
|
||||
Self: self,
|
||||
SkipAutoReconnect: true,
|
||||
},
|
||||
upstreamEvents: make(chan libnmdc.HubEvent, 0), // unbuffered
|
||||
upstreamCloser: make(chan struct{}, 1),
|
||||
quirks: Quirks{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,12 +138,12 @@ func (s *Server) RunWorker() {
|
||||
|
||||
// Client sent a command
|
||||
fields := strings.Fields(string(line))
|
||||
if len(fields) < 1 {
|
||||
if len(fields) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(fields[0], ":") {
|
||||
fields = fields[1:]
|
||||
fields[0] = fields[0][1:]
|
||||
}
|
||||
|
||||
s.handleCommand(strings.ToUpper(fields[0]), fields[1:])
|
||||
@@ -162,7 +167,7 @@ func (s *Server) postGeneralMessageInRoom(msg string) {
|
||||
var sendAs = ""
|
||||
|
||||
// Some clients can't handle blank nicks very well
|
||||
if s.upstreamLauncher.Self.ClientTag == "mIRC" || s.upstreamLauncher.Self.ClientTag == "Atomic" {
|
||||
if s.quirks.RequireNickForGeneralMessages {
|
||||
sendAs = s.hubSecNick + "!" + s.hubSecNick + "@" + s.hubSecNick
|
||||
}
|
||||
|
||||
@@ -192,31 +197,6 @@ func (s *Server) postGeneralMessageInRoom(msg string) {
|
||||
|
||||
}
|
||||
|
||||
var rx_colorControlCode *regexp.Regexp = regexp.MustCompilePOSIX("\x03[0-9]+(,[0-9]+)?")
|
||||
var rx_formattingControlCode *regexp.Regexp = regexp.MustCompile("(\x02|\x1D|\x1F|\x16|\x0F)")
|
||||
|
||||
func reformatOutgoingMessageBody(body string) string {
|
||||
|
||||
// Strip color codes
|
||||
noColors := rx_colorControlCode.ReplaceAllString(body, "")
|
||||
|
||||
// Strip formatting codes
|
||||
return rx_formattingControlCode.ReplaceAllString(noColors, "")
|
||||
|
||||
}
|
||||
|
||||
func reformatIncomingMessageBody(body string) string {
|
||||
|
||||
// "Greentext" filter
|
||||
// TODO markdown filters
|
||||
if len(body) > 0 && body[0] == '>' {
|
||||
return "\x033" + strings.Replace(body, "implying", "\x02implying\x02", -1)
|
||||
|
||||
} else {
|
||||
return body
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) upstreamWorker() {
|
||||
|
||||
// Read loop
|
||||
@@ -228,11 +208,15 @@ func (s *Server) upstreamWorker() {
|
||||
s.upstream.Disconnect()
|
||||
return
|
||||
|
||||
case hubEvent := <-s.upstream.OnEvent:
|
||||
case hubEvent := <-s.upstreamEvents:
|
||||
switch hubEvent.EventType {
|
||||
case libnmdc.EVENT_USER_JOINED:
|
||||
s.reply(rplJoin, hubEvent.Nick, BLESSED_CHANNEL)
|
||||
if hubEvent.Nick == s.clientNick() && s.sentFakeSelfJoin {
|
||||
s.sentFakeSelfJoin = false
|
||||
} else {
|
||||
// If we want to JOIN with the full power of the supplied nick!user@host, then we'll need to actually remember the active client's USER parameters
|
||||
s.reply(rplJoin, hubEvent.Nick, BLESSED_CHANNEL)
|
||||
}
|
||||
|
||||
case libnmdc.EVENT_USER_PART:
|
||||
s.reply(rplPart, hubEvent.Nick, BLESSED_CHANNEL, "Disconnected")
|
||||
@@ -429,7 +413,8 @@ func (s *Server) handleRegisteredCommand(command string, args []string) {
|
||||
return
|
||||
}
|
||||
|
||||
message := strings.Join(args[1:], " ")[1:] // strip leading colon
|
||||
// Strip leading colon (work around a bug in HoloIRC 4.1.0 and older)
|
||||
message := strings.Join(args[1:], " ")[1:]
|
||||
|
||||
if strings.HasPrefix(message, "\x01VERSION ") {
|
||||
// Not a real message - a reply to our internal request. Change the user's tag to match the actual client software
|
||||
@@ -439,6 +424,7 @@ func (s *Server) handleRegisteredCommand(command string, args []string) {
|
||||
versionString := message[9:]
|
||||
versionString = versionString[:len(versionString)-1]
|
||||
s.SetClientSoftwareVersion(versionString)
|
||||
s.quirks = GetQuirksForClient(versionString)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -509,7 +495,7 @@ func (s *Server) maybeStartUpstream() {
|
||||
s.reply(rplJoin, s.clientNick(), BLESSED_CHANNEL)
|
||||
|
||||
// Spawn upstream connection
|
||||
s.upstream = s.upstreamLauncher.Connect()
|
||||
s.upstream = libnmdc.ConnectAsync(&s.upstreamLauncher, s.upstreamEvents)
|
||||
go s.upstreamWorker()
|
||||
|
||||
} else {
|
||||
@@ -519,46 +505,21 @@ func (s *Server) maybeStartUpstream() {
|
||||
}
|
||||
|
||||
func (s *Server) SetClientSoftwareVersion(ver string) {
|
||||
// "HexChat 2.12.1 [x64] / Microsoft Windows 10 Pro (x64) [Intel(R) Core(TM) i5-2500 CPU @ 3.30GHz (3.60GHz)]"
|
||||
// "AndroIRC - Android IRC Client (5.2 - Build 6830152) - http://www.androirc.com"
|
||||
// "AndChat 1.4.3.2 http://www.andchat.net"
|
||||
// "liteIRC for Android 1.1.8"
|
||||
// ":Relay:1.0:Android"
|
||||
// "mIRC v7.45"
|
||||
|
||||
// A bit long and unwieldy.
|
||||
// Heuristic: keep the first word, and the the first word containing digits
|
||||
ct := parseVersion(ver)
|
||||
|
||||
tag := APP_NAME
|
||||
version := APP_VERSION
|
||||
s.verbosef("Replacing client tag with '%s' version '%s'", ct.AppName, ct.Version)
|
||||
|
||||
words := strings.Split(ver, " ")
|
||||
|
||||
for _, word := range words[1:] {
|
||||
if strings.ContainsAny(word, "0123456789") {
|
||||
tag = words[0]
|
||||
version = strings.Replace(word, "(", "", -1) // AndroIRC
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Strip leading v from mIRC
|
||||
if len(version) >= 2 && (version[0] == 'v' || version[0] == 'V') && strings.ContainsAny(string(version[1]), "0123456789") {
|
||||
version = version[1:]
|
||||
}
|
||||
|
||||
s.verbosef("Replacing client tag with '%s' version '%s'", tag, version)
|
||||
|
||||
s.upstreamLauncher.Self.ClientTag = tag
|
||||
s.upstreamLauncher.Self.ClientVersion = version
|
||||
s.upstreamLauncher.Self.ClientTag = ct.AppName
|
||||
s.upstreamLauncher.Self.ClientVersion = ct.Version
|
||||
s.recievedCtcpVersion = true
|
||||
|
||||
s.ClientStateLock.Lock()
|
||||
defer s.ClientStateLock.Unlock()
|
||||
|
||||
if s.upstream != nil {
|
||||
s.upstream.Hco.Self.ClientTag = tag
|
||||
s.upstream.Hco.Self.ClientVersion = version
|
||||
s.upstream.Hco.Self.ClientTag = ct.AppName
|
||||
s.upstream.Hco.Self.ClientVersion = ct.Version
|
||||
s.upstream.SayInfo()
|
||||
|
||||
} else {
|
||||
@@ -633,8 +594,7 @@ func (s *Server) handleJoinedCommand(command string, args []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// s.sendWho(args[0])
|
||||
// s.sendNames() // fixes hexchat, but andchat always sends WHO /immediately/ after NAMES end, causing an infinite loop
|
||||
// Ignore this command
|
||||
|
||||
case "MODE":
|
||||
if len(args) < 1 {
|
||||
@@ -719,6 +679,15 @@ func (s *Server) sendNames() {
|
||||
})
|
||||
}
|
||||
|
||||
if len(nameList) == 0 {
|
||||
// We don't have a nick list yet. Many clients can't handle a blank list
|
||||
// We could delay until we do have a nick list
|
||||
// Or, we could send our nick only, and filter it out of the next join
|
||||
|
||||
nameList = append(nameList, s.clientNick())
|
||||
s.sentFakeSelfJoin = true
|
||||
}
|
||||
|
||||
s.reply(rplNames, BLESSED_CHANNEL, strings.Join(nameList, " "))
|
||||
s.reply(rplEndOfNames, BLESSED_CHANNEL)
|
||||
}
|
||||
@@ -789,9 +758,9 @@ func (s *Server) reply(code replyCode, args ...string) {
|
||||
s.writeClient(fmt.Sprintf(":%s 005 %s NAMESX CHANTYPES=# :are supported by this server", s.name, s.clientNick()))
|
||||
|
||||
case rplJoin:
|
||||
s.writeClient(fmt.Sprintf(":%s JOIN %s", args[0], args[1]))
|
||||
s.writeClient(fmt.Sprintf(":%s!%s@%s JOIN %s", args[0], args[0], args[0], args[1]))
|
||||
case rplPart:
|
||||
s.writeClient(fmt.Sprintf(":%s PART %s %s", args[0], args[1], args[2]))
|
||||
s.writeClient(fmt.Sprintf(":%s!%s@%s PART %s %s", args[0], args[0], args[0], args[1], args[2]))
|
||||
case rplTopic:
|
||||
s.writeClient(fmt.Sprintf(":%s 332 %s %s :%s", s.name, s.clientNick(), args[0], args[1]))
|
||||
case rplNoTopic:
|
||||
@@ -800,7 +769,7 @@ func (s *Server) reply(code replyCode, args ...string) {
|
||||
case rplNames:
|
||||
s.writeClient(fmt.Sprintf(":%s 353 %s = %s :%s", s.name, s.clientNick(), args[0], args[1]))
|
||||
case rplEndOfNames:
|
||||
s.writeClient(fmt.Sprintf(":%s 366 %s %s :End of NAMES list", s.name, s.clientNick(), args[0]))
|
||||
s.writeClient(fmt.Sprintf(":%s 366 %s %s :End of /NAMES list.", s.name, s.clientNick(), args[0]))
|
||||
|
||||
case rplWho:
|
||||
s.writeClient(fmt.Sprintf(":%s 352 %s %s %s %s %s %s H :0 %s", s.name, s.clientNick(), args[1], args[0], args[0], s.name, args[0], args[0]))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
Copyright (C) 2016 The `nmdc-ircfrontend' author(s)
|
||||
Copyright (C) 2016-2018 The `nmdc-ircfrontend' author(s)
|
||||
Copyright (C) 2013 Harry Jeffery
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
var (
|
||||
APP_VERSION = "1.x.x-dev" // overridden with build ldflags
|
||||
APP_VERSION = "0.0" // overridden with build ldflags
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
Reference in New Issue
Block a user