diff --git a/nip86/methods.go b/nip86/methods.go new file mode 100644 index 0000000..6942e25 --- /dev/null +++ b/nip86/methods.go @@ -0,0 +1,271 @@ +package nip86 + +import ( + "fmt" + "math" + "net" + + "github.com/nbd-wtf/go-nostr" +) + +func DecodeRequest(req Request) (MethodParams, error) { + switch req.Method { + case "supportedmethods": + return SupportedMethods{}, nil + case "banpubkey": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + pk, ok := req.Params[0].(string) + if !ok || !nostr.IsValidPublicKey(pk) { + return nil, fmt.Errorf("invalid pubkey param for '%s'", req.Method) + } + var reason string + if len(req.Params) >= 2 { + reason, _ = req.Params[1].(string) + } + return BanPubKey{pk, reason}, nil + case "listbannedpubkeys": + return ListBannedPubKeys{}, nil + case "allowpubkey": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + pk, ok := req.Params[0].(string) + if !ok || !nostr.IsValidPublicKey(pk) { + return nil, fmt.Errorf("invalid pubkey param for '%s'", req.Method) + } + var reason string + if len(req.Params) >= 2 { + reason, _ = req.Params[1].(string) + } + return AllowPubKey{pk, reason}, nil + case "listallowedpubkeys": + return ListBannedPubKeys{}, nil + case "listeventsneedingmoderation": + return ListEventsNeedingModeration{}, nil + case "allowevent": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + id, ok := req.Params[0].(string) + if !ok || !nostr.IsValid32ByteHex(id) { + return nil, fmt.Errorf("invalid id param for '%s'", req.Method) + } + var reason string + if len(req.Params) >= 2 { + reason, _ = req.Params[1].(string) + } + return AllowEvent{id, reason}, nil + case "banevent": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + id, ok := req.Params[0].(string) + if !ok || !nostr.IsValid32ByteHex(id) { + return nil, fmt.Errorf("invalid id param for '%s'", req.Method) + } + var reason string + if len(req.Params) >= 2 { + reason, _ = req.Params[1].(string) + } + return BanEvent{id, reason}, nil + case "listbannedevents": + return ListBannedEvents{}, nil + case "changerelayname": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + name, _ := req.Params[0].(string) + return ChangeRelayName{name}, nil + case "changerelaydescription": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + desc, _ := req.Params[0].(string) + return ChangeRelayDescription{desc}, nil + case "changerelayicon": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + url, _ := req.Params[0].(string) + return ChangeRelayIcon{url}, nil + case "allowkind": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + kind, ok := req.Params[0].(float64) + if !ok || math.Trunc(kind) != kind { + return nil, fmt.Errorf("invalid kind '%v' for '%s'", req.Params[0], req.Method) + } + return AllowKind{int(kind)}, nil + case "disallowkind": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + kind, ok := req.Params[0].(float64) + if !ok || math.Trunc(kind) != kind { + return nil, fmt.Errorf("invalid kind '%v' for '%s'", req.Params[0], req.Method) + } + return DisallowKind{int(kind)}, nil + case "listallowedkinds": + return ListAllowedKinds{}, nil + case "blockip": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + ipstr, _ := req.Params[0].(string) + ip := net.ParseIP(ipstr) + if ip == nil { + return nil, fmt.Errorf("invalid ip param for '%s'", req.Method) + } + var reason string + if len(req.Params) >= 2 { + reason, _ = req.Params[1].(string) + } + return BlockIP{ip, reason}, nil + case "unblockip": + if len(req.Params) == 0 { + return nil, fmt.Errorf("invalid number of params for '%s'", req.Method) + } + ipstr, _ := req.Params[0].(string) + ip := net.ParseIP(ipstr) + if ip == nil { + return nil, fmt.Errorf("invalid ip param for '%s'", req.Method) + } + var reason string + if len(req.Params) >= 2 { + reason, _ = req.Params[1].(string) + } + return UnblockIP{ip, reason}, nil + case "listblockedips": + return ListBlockedIPs{}, nil + default: + return nil, fmt.Errorf("unknown method '%s'", req.Method) + } +} + +type MethodParams interface { + MethodName() string +} + +var ( + _ MethodParams = (*SupportedMethods)(nil) + _ MethodParams = (*BanPubKey)(nil) + _ MethodParams = (*ListBannedPubKeys)(nil) + _ MethodParams = (*AllowPubKey)(nil) + _ MethodParams = (*ListAllowedPubKeys)(nil) + _ MethodParams = (*ListEventsNeedingModeration)(nil) + _ MethodParams = (*AllowEvent)(nil) + _ MethodParams = (*BanEvent)(nil) + _ MethodParams = (*ListBannedEvents)(nil) + _ MethodParams = (*ChangeRelayName)(nil) + _ MethodParams = (*ChangeRelayDescription)(nil) + _ MethodParams = (*ChangeRelayIcon)(nil) + _ MethodParams = (*AllowKind)(nil) + _ MethodParams = (*DisallowKind)(nil) + _ MethodParams = (*ListAllowedKinds)(nil) + _ MethodParams = (*BlockIP)(nil) + _ MethodParams = (*UnblockIP)(nil) + _ MethodParams = (*ListBlockedIPs)(nil) +) + +type SupportedMethods struct{} + +func (_ SupportedMethods) MethodName() string { return "supportedmethods" } + +type BanPubKey struct { + PubKey string + Reason string +} + +func (_ BanPubKey) MethodName() string { return "banpubkey" } + +type ListBannedPubKeys struct{} + +func (_ ListBannedPubKeys) MethodName() string { return "listbannedpubkeys" } + +type AllowPubKey struct { + PubKey string + Reason string +} + +func (_ AllowPubKey) MethodName() string { return "allowpubkey" } + +type ListAllowedPubKeys struct{} + +func (_ ListAllowedPubKeys) MethodName() string { return "listallowedpubkeys" } + +type ListEventsNeedingModeration struct{} + +func (_ ListEventsNeedingModeration) MethodName() string { return "listeventsneedingmoderation" } + +type AllowEvent struct { + ID string + Reason string +} + +func (_ AllowEvent) MethodName() string { return "allowevent" } + +type BanEvent struct { + ID string + Reason string +} + +func (_ BanEvent) MethodName() string { return "banevent" } + +type ListBannedEvents struct{} + +func (_ ListBannedEvents) MethodName() string { return "listbannedevents" } + +type ChangeRelayName struct { + Name string +} + +func (_ ChangeRelayName) MethodName() string { return "changerelayname" } + +type ChangeRelayDescription struct { + Description string +} + +func (_ ChangeRelayDescription) MethodName() string { return "changerelaydescription" } + +type ChangeRelayIcon struct { + IconURL string +} + +func (_ ChangeRelayIcon) MethodName() string { return "changerelayicon" } + +type AllowKind struct { + Kind int +} + +func (_ AllowKind) MethodName() string { return "allowkind" } + +type DisallowKind struct { + Kind int +} + +func (_ DisallowKind) MethodName() string { return "disallowkind" } + +type ListAllowedKinds struct{} + +func (_ ListAllowedKinds) MethodName() string { return "listallowedkinds" } + +type BlockIP struct { + IP net.IP + Reason string +} + +func (_ BlockIP) MethodName() string { return "blockip" } + +type UnblockIP struct { + IP net.IP + Reason string +} + +func (_ UnblockIP) MethodName() string { return "unblockip" } + +type ListBlockedIPs struct{} + +func (_ ListBlockedIPs) MethodName() string { return "listblockedips" } diff --git a/nip86/types.go b/nip86/types.go new file mode 100644 index 0000000..322f3f6 --- /dev/null +++ b/nip86/types.go @@ -0,0 +1,11 @@ +package nip86 + +type Request struct { + Method string `json:"method"` + Params []any `json:"params"` +} + +type Response struct { + Result any `json:"result"` + Error string `json:"error,omitempty"` +}