Merge from yung stanley's master branch
Signed-off-by: kayos@tcp.direct <kayos@tcp.direct>
This commit is contained in:
commit
4be5266426
23
.github/workflows/test.yml
vendored
Normal file
23
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
name: test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push: {}
|
||||||
|
pull_request: { branches: [master] }
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- id: goversion
|
||||||
|
run: |
|
||||||
|
echo ::set-output name=version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | sed -rn 's/.*"version": "([0-9]\.[0-9]+(\.[0-9]+)?)".*/\1/p' | head -1)
|
||||||
|
- uses: actions/setup-go@v2
|
||||||
|
with: { go-version: "${{ steps.goversion.outputs.version }}" }
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: |
|
||||||
|
go install golang.org/x/lint/golint@latest
|
||||||
|
- run: $(go env GOPATH)/bin/golint -min_confidence 0.9 -set_exit_status
|
||||||
|
- run: |
|
||||||
|
GORACE="exitcode=1 halt_on_error=1" go test -v -coverprofile=coverage.txt -race -timeout 3m -count 3 -cpu 1,4
|
||||||
|
bash <(curl -s https://codecov.io/bash)
|
||||||
|
- run: go vet -v .
|
32
README.md
32
README.md
@ -12,10 +12,10 @@
|
|||||||
[Click here to see the changes in girc-atomic vs girc](https://github.com/lrstanley/girc/compare/master...yunginnanet:master)
|
[Click here to see the changes in girc-atomic vs girc](https://github.com/lrstanley/girc/compare/master...yunginnanet:master)
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
### ₜₕₑ ₛₖy ᵢₛ 𝆑ₐₗₗᵢₙg ʇɥǝ sʞʎ ᴉs ⅎɐʅʅᴉuƃ
|
### ₜₕₑ ₛₖy ᵢₛ 𝆑ₐₗₗᵢₙg ʇɥǝ sʞʎ ᴉs ⅎɐʅʅᴉuƃ
|
||||||
### 𝚝𝚑𝚎𝚢 𝚜𝚑𝚘𝚞𝚕𝚍 𝚑𝚊𝚟𝚎 𝚕𝚒𝚜𝚝𝚎𝚗𝚎𝚍
|
### 𝚝𝚑𝚎𝚢 𝚜𝚑𝚘𝚞𝚕𝚍 𝚑𝚊𝚟𝚎 𝚕𝚒𝚜𝚝𝚎𝚗𝚎𝚍
|
||||||
### ʇɥǝ sʞʎ ᴉs ⅎɐʅʅᴉuƃ ₜₕₑ ₛₖy ᵢₛ 𝆑ₐₗₗᵢₙg
|
### ʇɥǝ sʞʎ ᴉs ⅎɐʅʅᴉuƃ ₜₕₑ ₛₖy ᵢₛ 𝆑ₐₗₗᵢₙg
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@ -24,23 +24,23 @@
|
|||||||
- Event based triggering/responses ([example](https://godoc.org/github.com/yunginnanet/girc-atomic#ex-package--Commands), and [CTCP too](https://godoc.org/github.com/yunginnanet/girc-atomic#Commands.SendCTCP)!)
|
- Event based triggering/responses ([example](https://godoc.org/github.com/yunginnanet/girc-atomic#ex-package--Commands), and [CTCP too](https://godoc.org/github.com/yunginnanet/girc-atomic#Commands.SendCTCP)!)
|
||||||
- [Documentation](https://godoc.org/github.com/yunginnanet/girc-atomic) is _mostly_ complete.
|
- [Documentation](https://godoc.org/github.com/yunginnanet/girc-atomic) is _mostly_ complete.
|
||||||
- Support for almost all of the [IRCv3 spec](http://ircv3.net/software/libraries.html).
|
- Support for almost all of the [IRCv3 spec](http://ircv3.net/software/libraries.html).
|
||||||
- SASL Auth (currently only `PLAIN` and `EXTERNAL` is support by default,
|
- SASL Auth (currently only `PLAIN` and `EXTERNAL` is support by default,
|
||||||
however you can simply implement `SASLMech` yourself to support additional
|
however you can simply implement `SASLMech` yourself to support additional
|
||||||
mechanisms.)
|
mechanisms.)
|
||||||
- Message tags (things like `account-tag` on by default)
|
- Message tags (things like `account-tag` on by default)
|
||||||
- `account-notify`, `away-notify`, `chghost`, `extended-join`, etc -- all handled seemlessly ([cap.go](https://github.com/yunginnanet/girc-atomic/blob/master/cap.go) for more info).
|
- `account-notify`, `away-notify`, `chghost`, `extended-join`, etc -- all handled seemlessly ([cap.go](https://github.com/yunginnanet/girc-atomic/blob/master/cap.go) for more info).
|
||||||
- Channel and user tracking. Easily find what users are in a channel, if a
|
- Channel and user tracking. Easily find what users are in a channel, if a
|
||||||
user is away, or if they are authenticated (if the server supports it!)
|
user is away, or if they are authenticated (if the server supports it!)
|
||||||
- Client state/capability tracking. Easy methods to access capability data ([LookupChannel](https://godoc.org/github.com/yunginnanet/girc-atomic#Client.LookupChannel), [LookupUser](https://godoc.org/github.com/yunginnanet/girc-atomic#Client.LookupUser), [GetServerOpt (ISUPPORT)](https://godoc.org/github.com/yunginnanet/girc-atomic#Client.GetServerOpt), etc.)
|
- Client state/capability tracking. Easy methods to access capability data ([LookupChannel](https://godoc.org/github.com/yunginnanet/girc-atomic#Client.LookupChannel), [LookupUser](https://godoc.org/github.com/yunginnanet/girc-atomic#Client.LookupUser), [GetServerOpt (ISUPPORT)](https://godoc.org/github.com/yunginnanet/girc-atomic#Client.GetServerOpt), etc.)
|
||||||
- Built-in support for things you would commonly have to implement yourself.
|
- Built-in support for things you would commonly have to implement yourself.
|
||||||
- Nick collision detection and prevention (also see [Config.HandleNickCollide](https://godoc.org/github.com/yunginnanet/girc-atomic#Config).)
|
- Nick collision detection and prevention (also see [Config.HandleNickCollide](https://godoc.org/github.com/yunginnanet/girc-atomic#Config).)
|
||||||
- Event/message rate limiting.
|
- Event/message rate limiting.
|
||||||
- Channel, nick, and user validation methods ([IsValidChannel](https://godoc.org/github.com/yunginnanet/girc-atomic#IsValidChannel), [IsValidNick](https://godoc.org/github.com/yunginnanet/girc-atomic#IsValidNick), etc.)
|
- Channel, nick, and user validation methods ([IsValidChannel](https://godoc.org/github.com/yunginnanet/girc-atomic#IsValidChannel), [IsValidNick](https://godoc.org/github.com/yunginnanet/girc-atomic#IsValidNick), etc.)
|
||||||
- CTCP handling and auto-responses ([CTCP](https://godoc.org/github.com/yunginnanet/girc-atomic#CTCP))
|
- CTCP handling and auto-responses ([CTCP](https://godoc.org/github.com/yunginnanet/girc-atomic#CTCP))
|
||||||
- Utilizes the atomic/value package from stdlib to reduce backpressure in multi-client usage.
|
- Utilizes the atomic/value package from stdlib to reduce backpressure in multi-client usage.
|
||||||
- Additional CTCP handlers and customization.
|
- Additional CTCP handlers and customization.
|
||||||
- ??????
|
- ??????
|
||||||
- PROFIT!!!1!
|
- PROFIT!!!1!
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@ -59,8 +59,8 @@ Working on a project and want to add it to the list? Submit a pull request!
|
|||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
~~Please review the [CONTRIBUTING](CONTRIBUTING.md) doc for submitting issues/a guide
|
~~Please review the [CONTRIBUTING](CONTRIBUTING.md) doc for submitting issues/a guide
|
||||||
on submitting pull requests and helping out.~~
|
on submitting pull requests and helping out.~~
|
||||||
|
|
||||||
**OH GOD PLEASE MAKE IT STOP**
|
**OH GOD PLEASE MAKE IT STOP**
|
||||||
|
|
||||||
|
|
||||||
|
@ -576,6 +576,7 @@ func handleNAMES(c *Client, e Event) {
|
|||||||
|
|
||||||
var modes, nick string
|
var modes, nick string
|
||||||
var ok bool
|
var ok bool
|
||||||
|
var s *Source
|
||||||
|
|
||||||
for i := 0; i < len(parts); i++ {
|
for i := 0; i < len(parts); i++ {
|
||||||
modes, nick, ok = parseUserPrefix(parts[i])
|
modes, nick, ok = parseUserPrefix(parts[i])
|
||||||
|
@ -120,7 +120,6 @@ func handleSASL(c *Client, e Event) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSASLError(c *Client, e Event) {
|
func handleSASLError(c *Client, e Event) {
|
||||||
|
9
conn.go
9
conn.go
@ -43,7 +43,6 @@ type ircConn struct {
|
|||||||
// lastPong is the last successful time that we pinged the server and
|
// lastPong is the last successful time that we pinged the server and
|
||||||
// received a successful pong back.
|
// received a successful pong back.
|
||||||
lastPong atomic.Value
|
lastPong atomic.Value
|
||||||
// pingDelay time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dialer is an interface implementation of net.Dialer. Use this if you would
|
// Dialer is an interface implementation of net.Dialer. Use this if you would
|
||||||
@ -275,7 +274,6 @@ func (c *Client) MockConnect(conn net.Conn) error {
|
|||||||
|
|
||||||
func (c *Client) internalConnect(mock net.Conn, dialer Dialer) error {
|
func (c *Client) internalConnect(mock net.Conn, dialer Dialer) error {
|
||||||
startConn:
|
startConn:
|
||||||
|
|
||||||
if c.conn != nil {
|
if c.conn != nil {
|
||||||
panic("use of connect more than once")
|
panic("use of connect more than once")
|
||||||
}
|
}
|
||||||
@ -614,13 +612,18 @@ func (c *Client) pingLoop(ctx context.Context, errs chan error, working *int32)
|
|||||||
if time.Since(c.conn.lastPong.Load().(time.Time)) > c.Config.PingDelay+(120*time.Second) {
|
if time.Since(c.conn.lastPong.Load().(time.Time)) > c.Config.PingDelay+(120*time.Second) {
|
||||||
// It's 60 seconds over what out ping delay is, connection
|
// It's 60 seconds over what out ping delay is, connection
|
||||||
// has probably dropped.
|
// has probably dropped.
|
||||||
errs <- ErrTimedOut{
|
|
||||||
|
err := ErrTimedOut{
|
||||||
TimeSinceSuccess: time.Since(c.conn.lastPong.Load().(time.Time)),
|
TimeSinceSuccess: time.Since(c.conn.lastPong.Load().(time.Time)),
|
||||||
LastPong: c.conn.lastPong.Load().(time.Time),
|
LastPong: c.conn.lastPong.Load().(time.Time),
|
||||||
LastPing: c.conn.lastPing.Load().(time.Time),
|
LastPing: c.conn.lastPing.Load().(time.Time),
|
||||||
Delay: c.Config.PingDelay,
|
Delay: c.Config.PingDelay,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
errs <- err
|
||||||
|
}()
|
||||||
|
wg.Done()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +48,6 @@ func TestDecode(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("should have failed to parse decoded event. got: %#v", event)
|
t.Fatalf("should have failed to parse decoded event. got: %#v", event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncode(t *testing.T) {
|
func TestEncode(t *testing.T) {
|
||||||
@ -72,8 +70,6 @@ func TestEncode(t *testing.T) {
|
|||||||
if want != line {
|
if want != line {
|
||||||
t.Fatalf("encoded line wanted: %q, got: %q", want, line)
|
t.Fatalf("encoded line wanted: %q, got: %q", want, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRate(t *testing.T) {
|
func TestRate(t *testing.T) {
|
||||||
@ -90,8 +86,6 @@ func TestRate(t *testing.T) {
|
|||||||
if delay := c.rate(200); delay > (3 * time.Second) {
|
if delay := c.rate(200); delay > (3 * time.Second) {
|
||||||
t.Fatal("rate delay too high")
|
t.Fatal("rate delay too high")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func genMockConn() (client *Client, clientConn net.Conn, serverConn net.Conn) {
|
func genMockConn() (client *Client, clientConn net.Conn, serverConn net.Conn) {
|
||||||
|
@ -348,6 +348,7 @@ const (
|
|||||||
RPL_LOCALUSERS = "265" // aircd/hybrid/bahamut, used on freenode.
|
RPL_LOCALUSERS = "265" // aircd/hybrid/bahamut, used on freenode.
|
||||||
RPL_TOPICWHOTIME = "333" // ircu, used on freenode.
|
RPL_TOPICWHOTIME = "333" // ircu, used on freenode.
|
||||||
RPL_WHOSPCRPL = "354" // ircu, used on networks with WHOX support.
|
RPL_WHOSPCRPL = "354" // ircu, used on networks with WHOX support.
|
||||||
|
RPL_CREATIONTIME = "329"
|
||||||
)
|
)
|
||||||
|
|
||||||
// As seen in the wild.
|
// As seen in the wild.
|
||||||
|
@ -13,32 +13,24 @@ func BenchmarkFormat(b *testing.B) {
|
|||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
Fmt("{red}test{c}")
|
Fmt("{red}test{c}")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkFormatLong(b *testing.B) {
|
func BenchmarkFormatLong(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
Fmt("{red}test {blue}2 {red}3 {brown} {italic}test{c}")
|
Fmt("{red}test {blue}2 {red}3 {brown} {italic}test{c}")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkStripFormat(b *testing.B) {
|
func BenchmarkStripFormat(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
TrimFmt("{red}test{c}")
|
TrimFmt("{red}test{c}")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkStripFormatLong(b *testing.B) {
|
func BenchmarkStripFormatLong(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
TrimFmt("{red}test {blue}2 {red}3 {brown} {italic}test{c}")
|
TrimFmt("{red}test {blue}2 {red}3 {brown} {italic}test{c}")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkStripRaw(b *testing.B) {
|
func BenchmarkStripRaw(b *testing.B) {
|
||||||
@ -46,8 +38,6 @@ func BenchmarkStripRaw(b *testing.B) {
|
|||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
StripRaw(text)
|
StripRaw(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkStripRawLong(b *testing.B) {
|
func BenchmarkStripRawLong(b *testing.B) {
|
||||||
@ -55,8 +45,6 @@ func BenchmarkStripRawLong(b *testing.B) {
|
|||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
StripRaw(text)
|
StripRaw(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFormat(t *testing.T) {
|
func TestFormat(t *testing.T) {
|
||||||
@ -249,8 +237,6 @@ func TestToRFC1459(t *testing.T) {
|
|||||||
t.Errorf("ToRFC1459() = %q, want %q", got, tt.want)
|
t.Errorf("ToRFC1459() = %q, want %q", got, tt.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//func BenchmarkGlob(b *testing.B) {
|
//func BenchmarkGlob(b *testing.B) {
|
||||||
@ -267,23 +253,17 @@ func testGlobMatch(t *testing.T, subj, pattern string) {
|
|||||||
if !Glob(subj, pattern) {
|
if !Glob(subj, pattern) {
|
||||||
t.Fatalf("'%s' should match '%s'", pattern, subj)
|
t.Fatalf("'%s' should match '%s'", pattern, subj)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testGlobNoMatch(t *testing.T, subj, pattern string) {
|
func testGlobNoMatch(t *testing.T, subj, pattern string) {
|
||||||
if Glob(subj, pattern) {
|
if Glob(subj, pattern) {
|
||||||
t.Fatalf("'%s' should not match '%s'", pattern, subj)
|
t.Fatalf("'%s' should not match '%s'", pattern, subj)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmptyPattern(t *testing.T) {
|
func TestEmptyPattern(t *testing.T) {
|
||||||
testGlobMatch(t, "", "")
|
testGlobMatch(t, "", "")
|
||||||
testGlobNoMatch(t, "test", "")
|
testGlobNoMatch(t, "test", "")
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmptySubject(t *testing.T) {
|
func TestEmptySubject(t *testing.T) {
|
||||||
@ -324,14 +304,10 @@ func TestEmptySubject(t *testing.T) {
|
|||||||
for _, pattern := range cases {
|
for _, pattern := range cases {
|
||||||
testGlobNoMatch(t, pattern, "")
|
testGlobNoMatch(t, pattern, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPatternWithoutGlobs(t *testing.T) {
|
func TestPatternWithoutGlobs(t *testing.T) {
|
||||||
testGlobMatch(t, "test", "test")
|
testGlobMatch(t, "test", "test")
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGlob(t *testing.T) {
|
func TestGlob(t *testing.T) {
|
||||||
@ -368,6 +344,4 @@ func TestGlob(t *testing.T) {
|
|||||||
for _, pattern := range cases {
|
for _, pattern := range cases {
|
||||||
testGlobNoMatch(t, "this is a test", pattern)
|
testGlobNoMatch(t, "this is a test", pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user