From 9624183cebc4849ba420f45fea2d3fb616e98994 Mon Sep 17 00:00:00 2001
From: fiatjaf <fiatjaf@gmail.com>
Date: Mon, 1 Jan 2024 12:42:37 -0300
Subject: [PATCH] dedicated Kind type.

---
 binary/binary.go   |  4 ++--
 binary/event.go    |  6 +++---
 binary/hybrid.go   |  2 +-
 event.go           | 37 +------------------------------------
 event_easyjson.go  |  4 ++--
 example/example.go |  2 +-
 filter.go          |  2 +-
 filter_easyjson.go |  7 +++----
 kinds.go           | 38 ++++++++++++++++++++++++++++++++++++++
 nson/nson.go       |  5 +++--
 10 files changed, 55 insertions(+), 52 deletions(-)
 create mode 100644 kinds.go

diff --git a/binary/binary.go b/binary/binary.go
index 912aeeb..84e799b 100644
--- a/binary/binary.go
+++ b/binary/binary.go
@@ -18,7 +18,7 @@ func UnmarshalBinary(data []byte, evt *Event) (err error) {
 	copy(evt.PubKey[:], data[32:64])
 	copy(evt.Sig[:], data[64:128])
 	evt.CreatedAt = nostr.Timestamp(binary.BigEndian.Uint32(data[128:132]))
-	evt.Kind = binary.BigEndian.Uint16(data[132:134])
+	evt.Kind = nostr.Kind(binary.BigEndian.Uint16(data[132:134]))
 	contentLength := int(binary.BigEndian.Uint16(data[134:136]))
 	evt.Content = string(data[136 : 136+contentLength])
 
@@ -54,7 +54,7 @@ func MarshalBinary(evt *Event) []byte {
 	copy(buf[32:64], evt.PubKey[:])
 	copy(buf[64:128], evt.Sig[:])
 	binary.BigEndian.PutUint32(buf[128:132], uint32(evt.CreatedAt))
-	binary.BigEndian.PutUint16(buf[132:134], evt.Kind)
+	binary.BigEndian.PutUint16(buf[132:134], uint16(evt.Kind))
 	binary.BigEndian.PutUint16(buf[134:136], uint16(len(content)))
 	copy(buf[136:], content)
 
diff --git a/binary/event.go b/binary/event.go
index 5aa0536..7916436 100644
--- a/binary/event.go
+++ b/binary/event.go
@@ -10,7 +10,7 @@ type Event struct {
 	PubKey    [32]byte
 	Sig       [64]byte
 	ID        [32]byte
-	Kind      uint16
+	Kind      nostr.Kind
 	CreatedAt nostr.Timestamp
 	Content   string
 	Tags      nostr.Tags
@@ -20,7 +20,7 @@ func BinaryEvent(evt *nostr.Event) *Event {
 	bevt := Event{
 		Tags:      evt.Tags,
 		Content:   evt.Content,
-		Kind:      uint16(evt.Kind),
+		Kind:      evt.Kind,
 		CreatedAt: evt.CreatedAt,
 	}
 
@@ -35,7 +35,7 @@ func (bevt *Event) ToNormalEvent() *nostr.Event {
 	return &nostr.Event{
 		Tags:      bevt.Tags,
 		Content:   bevt.Content,
-		Kind:      int(bevt.Kind),
+		Kind:      bevt.Kind,
 		CreatedAt: bevt.CreatedAt,
 		ID:        hex.EncodeToString(bevt.ID[:]),
 		PubKey:    hex.EncodeToString(bevt.PubKey[:]),
diff --git a/binary/hybrid.go b/binary/hybrid.go
index d7e31ac..fef268c 100644
--- a/binary/hybrid.go
+++ b/binary/hybrid.go
@@ -19,7 +19,7 @@ func Unmarshal(data []byte, evt *nostr.Event) (err error) {
 	evt.PubKey = hex.EncodeToString(data[32:64])
 	evt.Sig = hex.EncodeToString(data[64:128])
 	evt.CreatedAt = nostr.Timestamp(binary.BigEndian.Uint32(data[128:132]))
-	evt.Kind = int(binary.BigEndian.Uint16(data[132:134]))
+	evt.Kind = nostr.Kind(binary.BigEndian.Uint16(data[132:134]))
 	contentLength := int(binary.BigEndian.Uint16(data[134:136]))
 	evt.Content = string(data[136 : 136+contentLength])
 
diff --git a/event.go b/event.go
index 6c9e60f..3d3b953 100644
--- a/event.go
+++ b/event.go
@@ -14,7 +14,7 @@ type Event struct {
 	ID        string    `json:"id"`
 	PubKey    string    `json:"pubkey"`
 	CreatedAt Timestamp `json:"created_at"`
-	Kind      int       `json:"kind"`
+	Kind      Kind      `json:"kind"`
 	Tags      Tags      `json:"tags"`
 	Content   string    `json:"content"`
 	Sig       string    `json:"sig"`
@@ -23,41 +23,6 @@ type Event struct {
 	extra map[string]any
 }
 
-const (
-	KindProfileMetadata          int = 0
-	KindTextNote                 int = 1
-	KindRecommendServer          int = 2
-	KindContactList              int = 3
-	KindEncryptedDirectMessage   int = 4
-	KindDeletion                 int = 5
-	KindRepost                   int = 6
-	KindReaction                 int = 7
-	KindChannelCreation          int = 40
-	KindChannelMetadata          int = 41
-	KindChannelMessage           int = 42
-	KindChannelHideMessage       int = 43
-	KindChannelMuteUser          int = 44
-	KindFileMetadata             int = 1063
-	KindZapRequest               int = 9734
-	KindZap                      int = 9735
-	KindMuteList                 int = 10000
-	KindPinList                  int = 10001
-	KindRelayListMetadata        int = 10002
-	KindNWCWalletInfo            int = 13194
-	KindClientAuthentication     int = 22242
-	KindNWCWalletRequest         int = 23194
-	KindNWCWalletResponse        int = 23195
-	KindNostrConnect             int = 24133
-	KindCategorizedPeopleList    int = 30000
-	KindCategorizedBookmarksList int = 30001
-	KindProfileBadges            int = 30008
-	KindBadgeDefinition          int = 30009
-	KindStallDefinition          int = 30017
-	KindProductDefinition        int = 30018
-	KindArticle                  int = 30023
-	KindApplicationSpecificData  int = 30078
-)
-
 // Event Stringer interface, just returns the raw JSON as a string.
 func (evt Event) String() string {
 	j, _ := easyjson.Marshal(evt)
diff --git a/event_easyjson.go b/event_easyjson.go
index a17ebc0..85871d2 100644
--- a/event_easyjson.go
+++ b/event_easyjson.go
@@ -45,7 +45,7 @@ func easyjsonF642ad3eDecodeGithubComNbdWtfGoNostr(in *jlexer.Lexer, out *Event)
 		case "created_at":
 			out.CreatedAt = Timestamp(in.Int64())
 		case "kind":
-			out.Kind = in.Int()
+			out.Kind = Kind(in.Uint16())
 		case "tags":
 			if in.IsNull() {
 				in.Skip()
@@ -127,7 +127,7 @@ func easyjsonF642ad3eEncodeGithubComNbdWtfGoNostr(out *jwriter.Writer, in Event)
 	{
 		const prefix string = ",\"kind\":"
 		out.RawString(prefix)
-		out.Int(in.Kind)
+		out.Uint16(uint16(in.Kind))
 	}
 	{
 		const prefix string = ",\"tags\":"
diff --git a/example/example.go b/example/example.go
index 55f0786..1655fd5 100644
--- a/example/example.go
+++ b/example/example.go
@@ -41,7 +41,7 @@ func main() {
 		// this filters for messages tagged with the user, mainly replies.
 		t["p"] = []string{v.(string)}
 		filters = []nostr.Filter{{
-			Kinds: []int{nostr.KindTextNote},
+			Kinds: []nostr.Kind{nostr.KindTextNote},
 			Tags:  t,
 			// limit = 3, get the three most recent notes
 			Limit: 3,
diff --git a/filter.go b/filter.go
index b375032..f09e99c 100644
--- a/filter.go
+++ b/filter.go
@@ -11,7 +11,7 @@ type Filters []Filter
 
 type Filter struct {
 	IDs     []string   `json:"ids,omitempty"`
-	Kinds   []int      `json:"kinds,omitempty"`
+	Kinds   []Kind     `json:"kinds,omitempty"`
 	Authors []string   `json:"authors,omitempty"`
 	Tags    TagMap     `json:"-,omitempty"`
 	Since   *Timestamp `json:"since,omitempty"`
diff --git a/filter_easyjson.go b/filter_easyjson.go
index a89c360..ad16733 100644
--- a/filter_easyjson.go
+++ b/filter_easyjson.go
@@ -69,16 +69,15 @@ func easyjson4d398eaaDecodeGithubComNbdWtfGoNostr(in *jlexer.Lexer, out *Filter)
 				in.Delim('[')
 				if out.Kinds == nil {
 					if !in.IsDelim(']') {
-						out.Kinds = make([]int, 0, 8)
+						out.Kinds = make([]Kind, 0, 8)
 					} else {
-						out.Kinds = []int{}
+						out.Kinds = []Kind{}
 					}
 				} else {
 					out.Kinds = (out.Kinds)[:0]
 				}
 				for !in.IsDelim(']') {
-					var v2 int
-					v2 = int(in.Int())
+					v2 := Kind(in.Uint16())
 					out.Kinds = append(out.Kinds, v2)
 					in.WantComma()
 				}
diff --git a/kinds.go b/kinds.go
new file mode 100644
index 0000000..e8d92e7
--- /dev/null
+++ b/kinds.go
@@ -0,0 +1,38 @@
+package nostr
+
+type Kind uint16
+
+const (
+	KindProfileMetadata          Kind = 0
+	KindTextNote                 Kind = 1
+	KindRecommendServer          Kind = 2
+	KindContactList              Kind = 3
+	KindEncryptedDirectMessage   Kind = 4
+	KindDeletion                 Kind = 5
+	KindRepost                   Kind = 6
+	KindReaction                 Kind = 7
+	KindChannelCreation          Kind = 40
+	KindChannelMetadata          Kind = 41
+	KindChannelMessage           Kind = 42
+	KindChannelHideMessage       Kind = 43
+	KindChannelMuteUser          Kind = 44
+	KindFileMetadata             Kind = 1063
+	KindZapRequest               Kind = 9734
+	KindZap                      Kind = 9735
+	KindMuteList                 Kind = 10000
+	KindPinList                  Kind = 10001
+	KindRelayListMetadata        Kind = 10002
+	KindNWCWalletInfo            Kind = 13194
+	KindClientAuthentication     Kind = 22242
+	KindNWCWalletRequest         Kind = 23194
+	KindNWCWalletResponse        Kind = 23195
+	KindNostrConnect             Kind = 24133
+	KindCategorizedPeopleList    Kind = 30000
+	KindCategorizedBookmarksList Kind = 30001
+	KindProfileBadges            Kind = 30008
+	KindBadgeDefinition          Kind = 30009
+	KindStallDefinition          Kind = 30017
+	KindProductDefinition        Kind = 30018
+	KindArticle                  Kind = 30023
+	KindApplicationSpecificData  Kind = 30078
+)
diff --git a/nson/nson.go b/nson/nson.go
index daa1f93..5a2f45f 100644
--- a/nson/nson.go
+++ b/nson/nson.go
@@ -76,7 +76,8 @@ func Unmarshal(data string, evt *nostr.Event) (err error) {
 	// kind
 	kindChars := int(nsonDescriptors[0])
 	kindStart := NSON_VALUES_START + nsonSize + 9 // len(`","kind":`)
-	evt.Kind, _ = strconv.Atoi(data[kindStart : kindStart+kindChars])
+	kind, _ := strconv.ParseUint(data[kindStart:kindStart+kindChars], 10, 16)
+	evt.Kind = nostr.Kind(kind)
 
 	// content
 	contentChars := int(binary.BigEndian.Uint16(nsonDescriptors[1:3]))
@@ -151,7 +152,7 @@ func Marshal(evt *nostr.Event) (string, error) {
 	tagBuilder.WriteString(`]}`)
 	nsonBuf = nsonBuf[0 : nsonIndex+1]
 
-	kind := strconv.Itoa(evt.Kind)
+	kind := strconv.FormatUint(uint64(evt.Kind), 10)
 	kindChars := len(kind)
 	nsonBuf[0] = uint8(kindChars)