better relaymaster and fixes

This commit is contained in:
github-tijlxyz 2023-09-18 19:18:24 +00:00
parent a4bb3f7833
commit c4ef0a5f25
15 changed files with 209 additions and 107 deletions

2
.env
View File

@ -5,4 +5,4 @@ RELAY_PUBKEY=""
RELAY_CONTACT=""
# Custom invite-relay settings
INVITE_MASTER="" # Master of the relay
INVITE_RELAY_MASTER="" # Master of the relay (pubkey hex)

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
whitelist.json
khatru-invite
.env
khatru-badgern-db

8
README.md Normal file
View File

@ -0,0 +1,8 @@
# Khatru Invite
A relay based on [Khatru](https://github.com/fiatjaf/khatru) with a invite hierarchy feature.
some notes before running:
1. change `ws://localhost:3334` in `ui/src/lib/consts.ts` to your relay url endpoint and build the UI
2. configure the relay settings in `.env`
3. manually add someone to the `whitelist.json` file, like this: `[{"pk":"07adfda9c5adc80881bb2a5220f6e3181e0c043b90fa115c4f183464022968e6","invited_by":""}]`

7
go.mod
View File

@ -1,15 +1,16 @@
module github.com/github-tijlxyz/khatru-invite
go 1.20
go 1.21.1
require (
github.com/fiatjaf/khatru v0.0.2
github.com/fiatjaf/khatru v0.0.0-20230916185141-24d1e3aebd67
github.com/joho/godotenv v1.5.1
github.com/nbd-wtf/go-nostr v0.20.0
)
require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/bmatsuo/lmdb-go v1.8.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
@ -28,9 +29,11 @@ require (
github.com/golang/protobuf v1.3.1 // indirect
github.com/golang/snappy v0.0.3 // indirect
github.com/google/flatbuffers v1.12.1 // indirect
github.com/jmoiron/sqlx v1.3.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-sqlite3 v1.14.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/puzpuzpuz/xsync v1.5.2 // indirect
github.com/rs/cors v1.7.0 // indirect

14
go.sum
View File

@ -2,6 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/bmatsuo/lmdb-go v1.8.0 h1:ohf3Q4xjXZBKh4AayUY4bb2CXuhRAI8BYGlJq08EfNA=
github.com/bmatsuo/lmdb-go v1.8.0/go.mod h1:wWPZmKdOAZsl4qOqkowQ1aCrFie1HU8gWloHMCeAUdM=
github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM=
@ -27,8 +29,9 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/fasthttp/websocket v1.5.3 h1:TPpQuLwJYfd4LJPXvHDYPMFWbLjsT91n3GpWtCQtdek=
github.com/fasthttp/websocket v1.5.3/go.mod h1:46gg/UBmTU1kUaTcwQXpUxtRwG2PvIZYeA8oL6vF3Fs=
github.com/fiatjaf/khatru v0.0.2 h1:+OaARQhrColJG1NypLDWgkaERjJhbLAtUk8RIYETeGU=
github.com/fiatjaf/khatru v0.0.2/go.mod h1:XDX+UIURFlTrAAw/ya7M5YRC4ft2Qm2gAAvs3ELoVps=
github.com/fiatjaf/khatru v0.0.0-20230916185141-24d1e3aebd67 h1:nsaUBS6rjAZCvPDgGUxG3tzfZnx6DX9iUBqPtDWDT/g=
github.com/fiatjaf/khatru v0.0.0-20230916185141-24d1e3aebd67/go.mod h1:XDX+UIURFlTrAAw/ya7M5YRC4ft2Qm2gAAvs3ELoVps=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
@ -50,6 +53,8 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw=
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/jmoiron/sqlx v1.3.1 h1:aLN7YINNZ7cYOPK3QC83dbM6KT0NMqVMw961TqrejlE=
github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@ -58,8 +63,11 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/nbd-wtf/go-nostr v0.20.0 h1:97SYhg68jWh5G1bW1g454hA0dTV7btwtPg836n4no0o=
github.com/nbd-wtf/go-nostr v0.20.0/go.mod h1:iFfiZr8YYSC1vmdUei0VfDB7GH/RjS3cbmiD1I5BKyo=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -75,6 +83,7 @@ github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJ
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
@ -148,4 +157,5 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -7,20 +7,6 @@ import (
"strings"
)
func inviteDataApiHandler(w http.ResponseWriter, re *http.Request) {
jsonBytes, err := json.Marshal(whitelist)
if err != nil {
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusOK)
if _, err := w.Write(jsonBytes); err != nil {
http.Error(w, "internal server error", http.StatusInternalServerError)
}
}
// embed ui files
//go:embed ui/dist/*
var uiContent embed.FS
@ -52,3 +38,31 @@ func embeddedUIHandler(w http.ResponseWriter, r *http.Request) {
return
}
}
func inviteDataApiHandler(w http.ResponseWriter, re *http.Request) {
jsonBytes, err := json.Marshal(whitelist)
if err != nil {
http.Error(w, "internal server error 00", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusOK)
if _, err := w.Write(jsonBytes); err != nil {
http.Error(w, "internal server error 01", http.StatusInternalServerError)
}
}
func relayMasterApiHandler(w http.ResponseWriter, re *http.Request) {
jsonBytes, err := json.Marshal(relayMaster)
if err != nil {
http.Error(w, "internal server error 10", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusOK)
if _, err := w.Write(jsonBytes); err != nil {
http.Error(w, "internal server error 11", http.StatusInternalServerError)
}
}

View File

@ -40,7 +40,7 @@ func main() {
// init relay
relay := khatru.NewRelay()
relayMaster = os.Getenv("INVITE_MASTER")
relayMaster = os.Getenv("INVITE_RELAY_MASTER")
relay.Name = os.Getenv("RELAY_NAME")
relay.Description = os.Getenv("RELAY_DESCRIPTION")
relay.PubKey = os.Getenv("RELAY_PUBKEY")
@ -52,7 +52,7 @@ func main() {
}
// load db
db = badgern.BadgerBackend{Path: "/tmp/khatru-badgern-tmp"}
db = badgern.BadgerBackend{Path: "./khatru-badgern-db"}
if err := db.Init(); err != nil {
panic(err)
}
@ -62,11 +62,12 @@ func main() {
relay.CountEvents = append(relay.CountEvents, db.CountEvents)
relay.DeleteEvent = append(relay.DeleteEvent, db.DeleteEvent)
relay.RejectEvent = append(relay.RejectEvent, whitelistRejecter)
// invitedata api
relay.Router().HandleFunc("/invitedata", inviteDataApiHandler)
relay.Router().HandleFunc("/relaymaster", relayMasterApiHandler)
// ui
relay.Router().HandleFunc("/", embeddedUIHandler)

View File

@ -3,7 +3,7 @@
import Hieracy from "./components/Hierarchy.svelte";
import Invite from "./components/Invite.svelte";
import { onMount } from "svelte";
import { ndk, userPublickey } from "./lib/nostr";
import { ndk, relayMaster, userPublickey } from "./lib/nostr";
import { NDKNip07Signer } from "@nostr-dev-kit/ndk";
import { buildHierarchy } from "./lib/utils";
import { nip19 } from "nostr-tools";
@ -20,9 +20,15 @@
}
async function fetchData() {
// Fetch Invite Data
const response = await fetch("/invitedata");
invitedata = Object.values(await response.json());
hierarchy = buildHierarchy(invitedata, { pk: "", invited_by: "" });
// Fetch Relay Master Pubkey
const response0 = await fetch("/relaymaster");
$relayMaster = await response0.json();
relayMaster.set($relayMaster);
}
let invitedata = [];
@ -30,21 +36,27 @@
onMount(() => {
addEventListener("load", (e) => {
setTimeout(() => {
login();
}, 1);
});
fetchData();
});
</script>
<article class="font-sans px-4 py-6 lg:max-w-7xl lg:pt-6 lg:pb-28">
<h1>Invite Relay</h1>
<h1 class="text-xl">Invite Relay</h1>
{#if adminView == true}
<button
on:click={() => adminView = false}
on:click={() => (adminView = false)}
type="button"
class="inline-flex mr-2 items-center px-3 py-2 border border-gray-300 shadow-sm text-sm leading-4 font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"
>Leave Admin View</button
>Leave Reports Viewer</button
>
<p>
You are{$userPublickey == nip19.npubEncode($relayMaster) ? "" : " not"} logged
in as a relay master
</p>
<AdminView />
{:else if adminView == false}
<div>
@ -57,14 +69,16 @@
>
{/if}
</div>
{#if $userPublickey !== undefined}
<div>
<button
on:click={() => adminView = true}
on:click={() => (adminView = true)}
type="button"
class="inline-flex mr-2 items-center px-3 py-2 border border-gray-300 shadow-sm text-sm leading-4 font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"
>Open Admin View</button
>Open Reports Viewer</button
>
</div>
{/if}
{#if invitedata.find((p) => $userPublickey == nip19.npubEncode(p.pk))}
<div>
<h3>Invite Someone</h3>

View File

@ -1,12 +1,9 @@
<script lang="js">
import {
NDKRelay,
NDKRelaySet,
} from "@nostr-dev-kit/ndk";
<script>
import { NDKRelay, NDKRelaySet } from "@nostr-dev-kit/ndk";
import { ndk } from "../lib/nostr";
import { onMount } from "svelte";
import ReportEvent from "./ReportEvent.svelte";
import { relayUrl } from '../lib/consts';
import { relayUrl } from "../lib/consts";
let events = [];
@ -17,18 +14,18 @@
const relaySet = new NDKRelaySet(specificRelay, $ndk);
relaySet.relays.forEach(async (relay) => {
await relay.connect().catch((err) => {
console.log("RELAY CONNECT ERROR");
console.error(err);
console.log("error while connecting to relay", err);
});
relay.on("connect", () => {
console.log(relay.url, "connected");
console.log("connected");
});
});
let filter = { kinds: [1984], limit: 250 };
let es = await $ndk.fetchEvents(filter, relaySet);
let options = { closeOnEose: true };
let es = await $ndk.fetchEvents(filter, options, relaySet);
events = Array.from(es);
} catch {
} catch (error) {
console.log("error while getting feed", error);
}
});
@ -36,8 +33,9 @@
<div>
{#each events as event}
{#if event.relay.url == relayUrl}
<ReportEvent {event} />
{/if}
{/each}
{#if events.length == 0}
<span>Didn't found any events</span>
{/if}
</div>

View File

@ -1,4 +1,4 @@
<script lang="js">
<script>
import { NDKEvent, NDKRelay, NDKRelaySet } from "@nostr-dev-kit/ndk";
import { ndk } from "../lib/nostr";
import { nip19 } from "nostr-tools";

View File

@ -6,11 +6,42 @@
let show = true;
async function dismissReportEvent() {
let confirmation = confirm(
"Are you sure you want to delete this event? (You can only do this if you are a relay master)",
);
if (confirmation) {
try {
// remove report event
// only publish to the relay in question, dont know why this needs so much code
let specificRelay = [new NDKRelay(relayUrl)];
const relaySet = new NDKRelaySet(specificRelay, $ndk);
relaySet.relays.forEach(async (relay) => {
await relay.connect().catch((err) => {
console.log("RELAY CONNECT ERROR");
console.error(err);
});
relay.on("connect", () => {
console.log(relay.url, "connected");
});
});
const newevent = new NDKEvent($ndk);
newevent.kind = 20203;
newevent.tags.push(["e", event.id]);
await newevent.publish(relaySet);
show = false;
} catch (error) {
console.log("error publishing event", error);
}
}
}
async function removeUser(username, pk) {
let confirmation = confirm(
`Are you sure you want to remove ${
username ? username : pk
}? All people they invited will also be removed. (you can only do this if you invited this user or are the relay admin)`
}? All people they invited will also be removed. (you can only do this if you invited this user or are the relay admin)`,
);
if (confirmation) {
try {
@ -26,10 +57,10 @@
});
});
const event = new NDKEvent($ndk);
event.kind = 20202;
event.tags.push(["p", pk]);
await event.publish(relaySet).then(() => reload());
const newevent = new NDKEvent($ndk);
newevent.kind = 20202;
newevent.tags.push(["p", pk]);
await newevent.publish(relaySet);
} catch (error) {
console.log("error while publishing", error);
}
@ -51,7 +82,7 @@
JSON.parse(Array.from(profile)[0]?.content)?.picture}
alt=""
/>
<a href={`nostr:${event.author.npub}`}
<a class="hover:underline" href={`nostr:${event.author.npub}`}
>{profile && JSON.parse(Array.from(profile)[0]?.content)?.name}</a
>
{/await}
@ -72,13 +103,15 @@
JSON.parse(Array.from(profile)[0]?.content)?.picture}
alt=""
/>
<a href={`nostr:${event.tags.find((e) => e[0] == "p")?.[1]}`}
<a
class="hover:underline"
href={`nostr:${event.tags.find((e) => e[0] == "p")?.[1]}`}
>{profile &&
JSON.parse(Array.from(profile)[0]?.content)?.name.length <= 16
? JSON.parse(Array.from(profile)[0]?.content)?.name
: JSON.parse(Array.from(profile)[0]?.content)?.name.substring(
0,
13
13,
) + "..."}</a
>
{/await}
@ -101,7 +134,7 @@
<div
class="bg-white max-h-64 max-w-full overflow-y-scroll rounded-lg m-0 p-4 mt-2"
>
{#await $ndk.fetchEvent( { ids: [event?.tags.find((e) => e[0] == "e")?.[1]] } )}
{#await $ndk.fetchEvent( { ids: [event?.tags.find((e) => e[0] == "e")?.[1]] }, )}
<p class="text-gray-500 p-0 m-0">... (can we find this event?)</p>
{:then theevent}
<p class="m-0 p-0">{theevent.content}</p>
@ -130,22 +163,17 @@
Open in client
</a>
<button
class="rounded-lg inline bg-slate-100 p-2 cursor-pointer hover:bg-white"
>
View in invite tree
</button>
<button
on:click={() => (show = false)}
on:click={dismissReportEvent}
class="rounded-lg inline bg-green-500 p-2 cursor-pointer hover:bg-green-400"
>
Dismiss <!-- TO BE IMPLEMENTED: Remove report event? -->
Remove This Report Event
</button>
<button
on:click={() =>
removeUser("user", event.tags.find((e) => e[0] == "p")?.[1])}
class="rounded-lg inline bg-red-500 p-2 cursor-pointer hover:bg-red-400"
>
Exlude this user
Exlude reported user
</button>
</div>
</div>

View File

@ -1,2 +1,2 @@
export const relayUrl = "ws://localhost:3334";
export const relayUrl = "ws://localhost:3334"; // Important: Change this and rebuild ui if needed
export const someRelays = ["wss://nos.lol", "wss://relay.snort.social"];

View File

@ -10,3 +10,4 @@ Ndk.connect().then(() => console.log("ndk connected"));
export const ndk: Writable<NDK> = writable(Ndk);
export const userPublickey: Writable<string | undefined> = writable(undefined);
export const relayMaster: Writable<string> = writable("");

View File

@ -2,6 +2,7 @@ package main
import (
"context"
"log"
"github.com/nbd-wtf/go-nostr"
)
@ -15,7 +16,7 @@ func isPkInWhitelist(targetPk string) bool {
return false
}
func deleteFromWhitelistRecursively (target string) {
func deleteFromWhitelistRecursively (ctx context.Context, target string) {
var updatedWhitelist []User
var queue []string
@ -31,18 +32,19 @@ func deleteFromWhitelistRecursively (target string) {
whitelist = updatedWhitelist
// Remove all events
go func () {
var filter nostr.Filter = nostr.Filter{
filter := nostr.Filter{
Authors: []string{target},
}
events, _ := db.QueryEvents(context.TODO(), filter)
events, _ := db.QueryEvents(ctx, filter)
for ev := range events {
db.DeleteEvent(context.TODO(), ev)
err := db.DeleteEvent(ctx, ev)
if err != nil {
log.Println("error while deleting event", err)
}
}
}()
// Recursive
for _, pk := range queue {
deleteFromWhitelistRecursively(pk)
deleteFromWhitelistRecursively(ctx, pk)
}
}

View File

@ -3,6 +3,7 @@ package main
import (
"context"
"encoding/json"
"log"
"os"
"github.com/nbd-wtf/go-nostr"
@ -22,23 +23,43 @@ func whitelistRejecter(ctx context.Context, evt *nostr.Event) (reject bool, msg
return true, "You are not invited to this relay"
}
// add user(s) if needed
// 20201 = user invites new user
if (evt.Kind == 20201) {
pTags := evt.Tags.GetAll([]string{"p"})
for _, tag := range pTags {
if !isPkInWhitelist(tag.Value()) {
if nostr.IsValidPublicKeyHex(tag.Value()) {
whitelist = append(whitelist, User{Pk: tag.Value(), InvitedBy: evt.PubKey})
}
}
}
}
// remove user(s) if needed
// 20202 = user removes user they invited or admin removes invite
if (evt.Kind == 20202) {
pTags := evt.Tags.GetAll([]string{"p"})
for _, tag := range pTags {
for _, user := range whitelist {
if user.Pk == tag.Value() && (user.InvitedBy == evt.PubKey || evt.PubKey == relayMaster) {
deleteFromWhitelistRecursively(tag.Value())
deleteFromWhitelistRecursively(ctx, tag.Value())
}
}
}
}
// 20203 = admin deletes event
if (evt.Kind == 20203 && evt.PubKey == relayMaster) {
eTags := evt.Tags.GetAll([]string{"e"})
for _, tag := range eTags {
filter := nostr.Filter{
IDs: []string{tag.Value()},
}
events, _ := db.QueryEvents(ctx, filter);
for ev := range events {
err := db.DeleteEvent(ctx, ev)
if err != nil {
log.Println("error while deleting event", err)
}
}
}