You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
15 KiB
449 lines
15 KiB
// Package kind includes a type for convenient handling of event kinds, and a |
|
// kind database with reverse lookup for human-readable information about event |
|
// kinds. |
|
package kind |
|
|
|
import ( |
|
"sync" |
|
|
|
"golang.org/x/exp/constraints" |
|
"lol.mleku.dev/chk" |
|
"next.orly.dev/pkg/encoders/ints" |
|
) |
|
|
|
// K - which will be externally referenced as kind.K is the event type in the |
|
// nostr protocol, the use of the capital K signifying type, consistent with Go |
|
// idiom, the Go standard library, and much, conformant, existing code. |
|
type K struct { |
|
K uint16 |
|
} |
|
|
|
// New creates a new kind.K with a provided integer value. Note that anything |
|
// larger than 2^16 will be truncated. |
|
func New[V constraints.Integer](k V) (ki *K) { return &K{uint16(k)} } |
|
|
|
// ToInt returns the value of the kind.K as an int. |
|
func (k *K) ToInt() int { |
|
if k == nil { |
|
return 0 |
|
} |
|
return int(k.K) |
|
} |
|
|
|
// ToU16 returns the value of the kind.K as an uint16 (the native form). |
|
func (k *K) ToU16() uint16 { |
|
if k == nil { |
|
return 0 |
|
} |
|
return k.K |
|
} |
|
|
|
// ToI32 returns the value of the kind.K as an int32. |
|
func (k *K) ToI32() int32 { |
|
if k == nil { |
|
return 0 |
|
} |
|
return int32(k.K) |
|
} |
|
|
|
// ToU64 returns the value of the kind.K as an uint64. |
|
func (k *K) ToU64() uint64 { |
|
if k == nil { |
|
return 0 |
|
} |
|
return uint64(k.K) |
|
} |
|
|
|
// Name returns the human readable string describing the semantics of the |
|
// kind.K. |
|
func (k *K) Name() string { return GetString(k.K) } |
|
|
|
// Equal checks if |
|
func (k *K) Equal(k2 uint16) bool { |
|
if k == nil { |
|
return false |
|
} |
|
return k.K == k2 |
|
} |
|
|
|
var Privileged = []*K{ |
|
EncryptedDirectMessage, |
|
GiftWrap, |
|
GiftWrapWithKind4, |
|
JWTBinding, |
|
ApplicationSpecificData, |
|
Seal, |
|
DirectMessage, |
|
FileMessage, |
|
} |
|
|
|
// IsPrivileged returns true if the type is the kind of message nobody else than |
|
// the pubkeys in the event and p tags of the event are party to. |
|
func IsPrivileged(k uint16) (is bool) { |
|
for i := range Privileged { |
|
if k == Privileged[i].K { |
|
return true |
|
} |
|
} |
|
return |
|
} |
|
|
|
// Marshal renders the kind.K into bytes containing the ASCII string form of the |
|
// kind number. |
|
func (k *K) Marshal(dst []byte) (b []byte) { |
|
return ints.New(k.ToU64()).Marshal(dst) |
|
} |
|
|
|
// Unmarshal decodes a byte string into a kind.K. |
|
func (k *K) Unmarshal(b []byte) (r []byte, err error) { |
|
n := ints.New(0) |
|
if r, err = n.Unmarshal(b); chk.T(err) { |
|
return |
|
} |
|
k.K = n.Uint16() |
|
return |
|
} |
|
|
|
// GetString returns a human-readable identifier for a kind.K. |
|
func GetString(t uint16) string { |
|
MapMx.RLock() |
|
defer MapMx.RUnlock() |
|
return Map[t] |
|
} |
|
|
|
// IsEphemeral returns true if the event kind is an ephemeral event. (not to be |
|
// stored) |
|
func IsEphemeral(k uint16) bool { |
|
return k >= EphemeralStart.K && k < EphemeralEnd.K |
|
} |
|
|
|
// IsReplaceable returns true if the event kind is a replaceable kind - that is, |
|
// if the newest version is the one that is in force (eg follow lists, relay |
|
// lists, etc. |
|
func IsReplaceable(k uint16) bool { |
|
return k == ProfileMetadata.K || k == FollowList.K || |
|
(k >= ReplaceableStart.K && k < ReplaceableEnd.K) |
|
} |
|
|
|
// IsParameterizedReplaceable is a kind of event that is one of a group of |
|
// events that replaces based on matching criteria. |
|
func IsParameterizedReplaceable(k uint16) bool { |
|
return k >= ParameterizedReplaceableStart.K && |
|
k < ParameterizedReplaceableEnd.K |
|
} |
|
|
|
// Directory events are events that necessarily need to be readable by anyone in |
|
// order to interact with users who have access to the relay, in order to |
|
// facilitate other users to find and interact with users on an auth-required |
|
// relay. |
|
var Directory = []*K{ |
|
ProfileMetadata, |
|
FollowList, |
|
EventDeletion, |
|
Reporting, |
|
RelayListMetadata, |
|
MuteList, |
|
DMRelaysList, |
|
} |
|
|
|
// IsDirectoryEvent returns whether an event kind is a Directory event, which |
|
// should grant permission to read such events without requiring authentication. |
|
func IsDirectoryEvent(k uint16) bool { |
|
for i := range Directory { |
|
if k == Directory[i].K { |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
var ( |
|
// ProfileMetadata is an event type that stores user profile data, pet |
|
// names, bio, lightning address, etc. |
|
ProfileMetadata = &K{0} |
|
// SetMetadata is a synonym for ProfileMetadata. |
|
SetMetadata = &K{0} |
|
// TextNote is a standard short text note of plain text a la twitter |
|
TextNote = &K{1} |
|
// RecommendServer is an event type that... |
|
RecommendRelay = &K{2} |
|
// FollowList an event containing a list of pubkeys of users that should be |
|
// shown as follows in a timeline. |
|
FollowList = &K{3} |
|
Follows = &K{3} |
|
// EncryptedDirectMessage is an event type that... |
|
EncryptedDirectMessage = &K{4} |
|
// EventDeletion is an event type that... |
|
EventDeletion = &K{5} |
|
Deletion = &K{5} |
|
// Repost is an event type that... |
|
Repost = &K{6} |
|
// Reaction is an event type that... |
|
Reaction = &K{7} |
|
// BadgeAward is an event type |
|
BadgeAward = &K{8} |
|
// ChatMessage is an event type for NIP-C7 chat messages |
|
ChatMessage = &K{9} |
|
// GroupChatThreadedReply is deprecated |
|
GroupChatThreadedReply = &K{10} |
|
// Thread is an event type for NIP-7D threads |
|
Thread = &K{11} |
|
// GroupThreadReply is deprecated |
|
GroupThreadReply = &K{12} |
|
// Seal is an event that wraps a PrivateDirectMessage and is placed inside a |
|
// GiftWrap or GiftWrapWithKind4 |
|
Seal = &K{13} |
|
// DirectMessage is a nip-17 direct message with a different |
|
// construction. It doesn't actually appear as an event a relay might receive |
|
// but only as the stringified content of a GiftWrap or GiftWrapWithKind4 inside |
|
// a |
|
DirectMessage = &K{14} |
|
// FileMessage is a NIP-17 file message |
|
FileMessage = &K{15} |
|
// GenericRepost is an event type that... |
|
GenericRepost = &K{16} |
|
// ReactionToWebsite is a reaction to a website |
|
ReactionToWebsite = &K{17} |
|
// Picture is an event type for NIP-68 picture-first feeds |
|
Picture = &K{20} |
|
// VideoEventHorizontal is for horizontal video events |
|
VideoEventHorizontal = &K{34235} |
|
// VideoEventVertical is for vertical video events |
|
VideoEventVertical = &K{34236} |
|
// ChannelCreation is an event type that... |
|
ChannelCreation = &K{40} |
|
// ChannelMetadata is an event type that... |
|
ChannelMetadata = &K{41} |
|
// ChannelMessage is an event type that... |
|
ChannelMessage = &K{42} |
|
// ChannelHideMessage is an event type that... |
|
ChannelHideMessage = &K{43} |
|
// ChannelMuteUser is an event type that... |
|
ChannelMuteUser = &K{44} |
|
// Bid is an event type that... |
|
Bid = &K{1021} |
|
// BidConfirmation is an event type that... |
|
BidConfirmation = &K{1022} |
|
// OpenTimestamps is an event type that... |
|
OpenTimestamps = &K{1040} |
|
GiftWrap = &K{1059} |
|
GiftWrapWithKind4 = &K{1060} |
|
// FileMetadata is an event type that... |
|
FileMetadata = &K{1063} |
|
// LiveChatMessage is an event type that... |
|
LiveChatMessage = &K{1311} |
|
// BitcoinBlock is an event type created for the Nostrocket |
|
BitcoinBlock = &K{1517} |
|
// LiveStream from zap.stream |
|
LiveStream = &K{1808} |
|
// ProblemTracker is an event type used by Nostrocket |
|
ProblemTracker = &K{1971} |
|
// MemoryHole is an event type contains a report about an event (usually |
|
// text note or other human readable) |
|
MemoryHole = &K{1984} |
|
Reporting = &K{1984} |
|
// Label is an event type has L and l tags, namespace and type - NIP-32 |
|
Label = &K{1985} |
|
// CommunityPostApproval is an event type that... |
|
CommunityPostApproval = &K{4550} |
|
JobRequestStart = &K{5000} |
|
JobRequestEnd = &K{5999} |
|
JobResultStart = &K{6000} |
|
JobResultEnd = &K{6999} |
|
JobFeedback = &K{7000} |
|
ZapGoal = &K{9041} |
|
// ZapRequest is an event type that... |
|
ZapRequest = &K{9734} |
|
// Zap is an event type that... |
|
Zap = &K{9735} |
|
Highlights = &K{9882} |
|
// ReplaceableStart is an event type that... |
|
ReplaceableStart = &K{10000} |
|
// MuteList is an event type that... |
|
MuteList = &K{10000} |
|
BlockList = &K{10000} |
|
// PinList is an event type that... |
|
PinList = &K{10001} |
|
// RelayListMetadata is an event type that... |
|
RelayListMetadata = &K{10002} |
|
BookmarkList = &K{10003} |
|
CommunitiesList = &K{10004} |
|
PublicChatsList = &K{10005} |
|
BlockedRelaysList = &K{10006} |
|
SearchRelaysList = &K{10007} |
|
RelayGroupConfig = &K{10008} |
|
InterestsList = &K{10015} |
|
UserEmojiList = &K{10030} |
|
DMRelaysList = &K{10050} |
|
FileStorageServerList = &K{10096} |
|
// JWTBinding is an event kind that creates a link between a JWT certificate and a pubkey |
|
JWTBinding = &K{13004} |
|
// NWCWalletServiceInfo is an event type that... |
|
NWCWalletServiceInfo = &K{13194} |
|
WalletServiceInfo = &K{13194} |
|
// ReplaceableEnd is an event type that... |
|
ReplaceableEnd = &K{19999} |
|
// EphemeralStart is an event type that... |
|
EphemeralStart = &K{20000} |
|
LightningPubRPC = &K{21000} |
|
// ClientAuthentication is an event type that... |
|
ClientAuthentication = &K{22242} |
|
// NWCWalletRequest is an event type that... |
|
NWCWalletRequest = &K{23194} |
|
WalletRequest = &K{23194} |
|
// NWCWalletResponse is an event type that... |
|
NWCWalletResponse = &K{23195} |
|
WalletResponse = &K{23195} |
|
NWCNotification = &K{23196} |
|
WalletNotificationNip4 = &K{23196} |
|
WalletNotification = &K{23197} |
|
// NostrConnect is an event type that... |
|
NostrConnect = &K{24133} |
|
HTTPAuth = &K{27235} |
|
// EphemeralEnd is an event type that... |
|
EphemeralEnd = &K{29999} |
|
// ParameterizedReplaceableStart is an event type that... |
|
ParameterizedReplaceableStart = &K{30000} |
|
// CategorizedPeopleList is an event type that... |
|
CategorizedPeopleList = &K{30000} |
|
FollowSets = &K{30000} |
|
// CategorizedBookmarksList is an event type that... |
|
CategorizedBookmarksList = &K{30001} |
|
GenericLists = &K{30001} |
|
RelaySets = &K{30002} |
|
BookmarkSets = &K{30003} |
|
CurationSets = &K{30004} |
|
// ProfileBadges is an event type that... |
|
ProfileBadges = &K{30008} |
|
// BadgeDefinition is an event type that... |
|
BadgeDefinition = &K{30009} |
|
InterestSets = &K{30015} |
|
// StallDefinition creates or updates a stall |
|
StallDefinition = &K{30017} |
|
// ProductDefinition creates or updates a product |
|
ProductDefinition = &K{30018} |
|
MarketplaceUIUX = &K{30019} |
|
ProductSoldAsAuction = &K{30020} |
|
// Article is an event type that... |
|
Article = &K{30023} |
|
LongFormContent = &K{30023} |
|
DraftLongFormContent = &K{30024} |
|
EmojiSets = &K{30030} |
|
// ApplicationSpecificData is an event type stores data about application |
|
// configuration, this, like DMs and giftwraps must be protected by user |
|
// auth. |
|
ApplicationSpecificData = &K{30078} |
|
LiveEvent = &K{30311} |
|
UserStatuses = &K{30315} |
|
ClassifiedListing = &K{30402} |
|
DraftClassifiedListing = &K{30403} |
|
DateBasedCalendarEvent = &K{31922} |
|
TimeBasedCalendarEvent = &K{31923} |
|
Calendar = &K{31924} |
|
CalendarEventRSVP = &K{31925} |
|
HandlerRecommendation = &K{31989} |
|
HandlerInformation = &K{31990} |
|
// WaveLakeTrack which has no spec and uses malformed tags |
|
WaveLakeTrack = &K{32123} |
|
CommunityDefinition = &K{34550} |
|
ACLEvent = &K{39998} |
|
// ParameterizedReplaceableEnd is an event type that... |
|
ParameterizedReplaceableEnd = &K{40000} |
|
) |
|
|
|
var MapMx sync.RWMutex |
|
var Map = map[uint16]string{ |
|
ProfileMetadata.K: "User Metadata", |
|
TextNote.K: "Short Text Note", |
|
RecommendRelay.K: "Recommend Relay", |
|
FollowList.K: "Follows", |
|
EncryptedDirectMessage.K: "Encrypted Direct Messages", |
|
EventDeletion.K: "Event Deletion Request", |
|
Repost.K: "Repost", |
|
Reaction.K: "Reaction", |
|
BadgeAward.K: "Badge Award", |
|
ChatMessage.K: "Chat Message", |
|
GroupChatThreadedReply.K: "Group Chat Threaded Reply", |
|
Thread.K: "Thread", |
|
GroupThreadReply.K: "Group Thread Reply", |
|
Seal.K: "Seal", |
|
DirectMessage.K: "Direct Message", |
|
FileMessage.K: "File Message", |
|
GenericRepost.K: "Generic Repost", |
|
ReactionToWebsite.K: "Reaction to a website", |
|
Picture.K: "Picture", |
|
ChannelCreation.K: "Channel Creation", |
|
ChannelMetadata.K: "Channel Metadata", |
|
ChannelMessage.K: "Channel Message", |
|
ChannelHideMessage.K: "Channel Hide Message", |
|
ChannelMuteUser.K: "Channel Mute User", |
|
Bid.K: "Bid", |
|
BidConfirmation.K: "Bid Confirmation", |
|
OpenTimestamps.K: "OpenTimestamps", |
|
FileMetadata.K: "File Metadata", |
|
LiveChatMessage.K: "Live Chat Message", |
|
ProblemTracker.K: "Problem Tracker", |
|
Reporting.K: "Reporting", |
|
Label.K: "Label", |
|
CommunityPostApproval.K: "Community Post Approval", |
|
JobRequestStart.K: "Job Request", |
|
JobRequestEnd.K: "Job Request", |
|
JobResultStart.K: "Job Result", |
|
JobResultEnd.K: "Job Result", |
|
JobFeedback.K: "Job Feedback", |
|
ZapGoal.K: "Zap Goal", |
|
ZapRequest.K: "Zap Request", |
|
Zap.K: "Zap", |
|
Highlights.K: "Highlights", |
|
BlockList.K: "Mute list", |
|
PinList.K: "Pin list", |
|
RelayListMetadata.K: "Relay List Metadata", |
|
BookmarkList.K: "Bookmarks list", |
|
CommunitiesList.K: "Communities list", |
|
PublicChatsList.K: "Public Chats list", |
|
BlockedRelaysList.K: "Blocked Relays list", |
|
SearchRelaysList.K: "Search Relays list", |
|
RelayGroupConfig.K: "Relay Group Configuration", |
|
InterestsList.K: "Interests", |
|
UserEmojiList.K: "User Emoji list", |
|
DMRelaysList.K: "DM relays", |
|
FileStorageServerList.K: "File Storage Server List", |
|
NWCWalletServiceInfo.K: "Wallet Service Info", |
|
LightningPubRPC.K: "Lightning pub RPC", |
|
ClientAuthentication.K: "Client Authentication", |
|
WalletRequest.K: "Wallet Request", |
|
WalletResponse.K: "Wallet Response", |
|
WalletNotificationNip4.K: "Wallet Notification", |
|
WalletNotification.K: "Wallet Notification", |
|
NostrConnect.K: "Nostr Connect", |
|
HTTPAuth.K: "HTTP Auth", |
|
FollowSets.K: "Follow sets", |
|
GenericLists.K: "Generic lists", |
|
RelaySets.K: "Relay sets", |
|
BookmarkSets.K: "Bookmark sets", |
|
CurationSets.K: "Curation sets", |
|
ProfileBadges.K: "Profile Badges", |
|
BadgeDefinition.K: "Badge Definition", |
|
InterestSets.K: "Interest sets", |
|
StallDefinition.K: "Stall Definition", |
|
ProductDefinition.K: "Product Definition", |
|
MarketplaceUIUX.K: "Marketplace UI/UX", |
|
ProductSoldAsAuction.K: "Product sold as an auction", |
|
LongFormContent.K: "Long-form Content", |
|
DraftLongFormContent.K: "Draft Long-form Content", |
|
EmojiSets.K: "Emoji sets", |
|
ApplicationSpecificData.K: "Application-specific Data", |
|
LiveEvent.K: "Live Event", |
|
UserStatuses.K: "User Statuses", |
|
ClassifiedListing.K: "Classified Listing", |
|
DraftClassifiedListing.K: "Draft Classified Listing", |
|
DateBasedCalendarEvent.K: "Date-Based Calendar Event", |
|
TimeBasedCalendarEvent.K: "Time-Based Calendar Event", |
|
Calendar.K: "Calendar", |
|
CalendarEventRSVP.K: "Calendar Event RSVP", |
|
HandlerRecommendation.K: "Handler recommendation", |
|
HandlerInformation.K: "Handler information", |
|
CommunityDefinition.K: "Community Definition", |
|
VideoEventHorizontal.K: "Video Event Horizontal", |
|
VideoEventVertical.K: "Video Event Vertical", |
|
}
|
|
|