Commit 2bae0164e7c0c3554b6f6c2a93fd5b35c82e0417

Parents: bb5d7b521b6c8e85191dc1198328e14fa17a170d

From: Moritz Poldrack <git@moritz.sh>
Date: Sat Jun 11 02:05:49 2022 +0700

added DATE command

		

Stats

README.md +1/-1
reader.go +23/-0
reader_test.go +28/-0
status.go +1/-0

Changeset

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
diff --git a/README.md b/README.md
index 43e8950c3ee7bebc4ba0f0f3a099492892d6086e..4b43d3427f8fb6649b905350a1c2deddbce6ed93 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ | LIST OVERVIEW.FMT | OVER          | ☓           | RFC3977  |
 | POST              | POST          | ☓           | RFC3977  |
 | ARTICLE           | READER        | 🗸           | RFC3977  |
 | BODY              | READER        | 🗸           | RFC3977  |
-| DATE              | READER        | ☓           | RFC3977  |
+| DATE              | READER        | 🗸           | RFC3977  |
 | GROUP             | READER        | 🗸           | RFC3977  |
 | LAST              | READER        | ☓           | RFC3977  |
 | LISTGROUP         | READER        | ☓           | RFC3977  |
diff --git a/reader.go b/reader.go
index 0285c7ee2ca93d2bae93ab1c59be5d13bff8b6ff..92ff81210e4ce2100c498569010a2192004a5692 100644
--- a/reader.go
+++ b/reader.go
@@ -3,6 +3,7 @@
 import (
 	"context"
 	"fmt"
+	"time"
 )
 
 func (c *Conn) Article(ctx context.Context, msg MessageIdentifier) (*Response, error) {
@@ -54,6 +55,28 @@ 	case StatusNoArticleWithGivenNumber:
 		return resp, ErrNoArticleWithGivenNumber
 	default:
 		return resp, ErrUnexpectedResponse
+	}
+}
+
+func (c *Conn) Date(ctx context.Context) (time.Time, error) {
+	if c.caps&CapReader == 0 {
+		return time.Time{}, ErrCapabilityNotSupported
+	}
+
+	resp, err := c.CmdNoBody(ctx, "DATE")
+	if err != nil {
+		return time.Time{}, fmt.Errorf("failed to get date: %w", err)
+	}
+
+	switch resp.Status.Code {
+	case StatusServerDateAndTime:
+		t, err := time.Parse("20060102150405", resp.Status.Message)
+		if err != nil {
+			return t, fmt.Errorf("server returned invalid timeformat: %w", err)
+		}
+		return t, nil
+	default:
+		return time.Time{}, ErrUnexpectedResponse
 	}
 }
 
diff --git a/reader_test.go b/reader_test.go
index 4d20970b2185d548f38b8184e02891d90f67be1b..15a138a691d1141d8276ba0d1ac879f4a6bcd885 100644
--- a/reader_test.go
+++ b/reader_test.go
@@ -148,6 +148,34 @@ 		})
 	}
 }
 
+func TestDate(t *testing.T) {
+	if NewsServerSecure == "" || NewsServerUser == "" || NewsServerPassword == "" {
+		t.Log("secure server address, username, and password required in variables_test.go")
+		t.SkipNow()
+	}
+
+	c, err := nntp.Dial(NewsServerSecure)
+	if err != nil {
+		t.Skipf("connection to '%s' failed: %v", NewsServerSecure, err)
+	}
+	defer c.Close(context.Background())
+
+	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+	err = c.LoginUserPass(ctx, NewsServerUser, NewsServerPassword)
+	if err != nil {
+		t.Skipf("login failed: %v", err)
+	}
+
+	ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+	ts, err := c.Date(ctx)
+	tsNow := time.Now()
+	if err != nil || tsNow.Sub(ts).Seconds() > 5 { // allow up to 5 seconds deviation in both directions
+		t.Errorf("\ndate returned: %s\ndate expected: %s", ts, tsNow)
+	}
+}
+
 func TestGroup(t *testing.T) {
 	if NewsServerSecure == "" || NewsServerUser == "" || NewsServerPassword == "" {
 		t.Log("secure server address, username, and password required in variables_test.go")
diff --git a/status.go b/status.go
index b884707119a292035598616fa66db11ee917c7dc..1ab9a2bcf7ce1467e8b262c3e3b0fe887ea413ed 100644
--- a/status.go
+++ b/status.go
@@ -4,6 +4,7 @@ import "errors"
 
 const (
 	StatusHelpTextFollows             = 100
+	StatusServerDateAndTime           = 111
 	StatusServiceAvailable            = 200
 	StatusServiceNoPosting            = 201
 	StatusConnectionClosing           = 205