fix: moderation updates
This commit is contained in:
parent
bfdcbca08b
commit
ee9f941b11
@ -1,10 +1,10 @@
|
||||
import { dedupe } from "@snort/shared";
|
||||
import { EventKind, NostrEvent, NostrLink, TaggedNostrEvent, ToNostrEventTag } from "@snort/system";
|
||||
import { EventKind, NostrEvent, NostrLink, TaggedNostrEvent, ToNostrEventTag, UnknownTag } from "@snort/system";
|
||||
|
||||
import useLogin from "@/Hooks/useLogin";
|
||||
|
||||
export class MutedWordTag implements ToNostrEventTag {
|
||||
constructor(readonly word: string) {}
|
||||
constructor(readonly word: string) { }
|
||||
|
||||
toEventTag(): string[] | undefined {
|
||||
return ["word", this.word.toLowerCase()];
|
||||
@ -43,11 +43,11 @@ export default function useModeration() {
|
||||
}
|
||||
|
||||
async function addMutedWord(word: string) {
|
||||
await state.addToList(EventKind.MuteList, new MutedWordTag(word.toLowerCase()));
|
||||
await state.addToList(EventKind.MuteList, new MutedWordTag(word.toLowerCase()), true);
|
||||
}
|
||||
|
||||
async function removeMutedWord(word: string) {
|
||||
await state.removeFromList(EventKind.MuteList, new MutedWordTag(word.toLowerCase()));
|
||||
await state.removeFromList(EventKind.MuteList, new MutedWordTag(word.toLowerCase()), true);
|
||||
}
|
||||
|
||||
function isEventMuted(ev: TaggedNostrEvent | NostrEvent) {
|
||||
@ -56,13 +56,9 @@ export default function useModeration() {
|
||||
|
||||
function getMutedWords() {
|
||||
return state
|
||||
.getList(EventKind.MuteList, o => {
|
||||
if (o[0] === "word") {
|
||||
return new MutedWordTag(o[1]);
|
||||
}
|
||||
})
|
||||
.filter(a => a instanceof MutedWordTag)
|
||||
.map(a => (a as MutedWordTag).word);
|
||||
.getList(EventKind.MuteList)
|
||||
.filter(a => a instanceof UnknownTag && a.value[0] === "word")
|
||||
.map(a => (a as UnknownTag).value[1]);
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -48,16 +48,19 @@ export default function ModerationSettingsPage() {
|
||||
value={muteWord}
|
||||
onChange={e => setMuteWord(e.target.value.toLowerCase())}
|
||||
/>
|
||||
<AsyncButton type="button" onClick={() => addMutedWord(muteWord)}>
|
||||
<AsyncButton onClick={async () => {
|
||||
await addMutedWord(muteWord);
|
||||
setMuteWord("");
|
||||
}}>
|
||||
<FormattedMessage defaultMessage="Add" id="2/2yg+" />
|
||||
</AsyncButton>
|
||||
</div>
|
||||
{getMutedWords().map(v => (
|
||||
<div key={v} className="p br b flex items-center justify-between">
|
||||
<div>{v}</div>
|
||||
<button type="button" onClick={() => removeMutedWord(v)}>
|
||||
<AsyncButton onClick={() => removeMutedWord(v)}>
|
||||
<FormattedMessage defaultMessage="Delete" id="K3r6DQ" />
|
||||
</button>
|
||||
</AsyncButton>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
@ -12,12 +12,15 @@ import {
|
||||
} from ".";
|
||||
import { findTag } from "./utils";
|
||||
|
||||
/**
|
||||
* An object which can be stored in a nostr event as a tag
|
||||
*/
|
||||
export interface ToNostrEventTag {
|
||||
toEventTag(): Array<string> | undefined;
|
||||
}
|
||||
|
||||
export class NostrHashtagLink implements ToNostrEventTag {
|
||||
constructor(readonly tag: string) {}
|
||||
constructor(readonly tag: string) { }
|
||||
|
||||
toEventTag() {
|
||||
return ["t", this.tag];
|
||||
@ -25,7 +28,7 @@ export class NostrHashtagLink implements ToNostrEventTag {
|
||||
}
|
||||
|
||||
export class UnknownTag implements ToNostrEventTag {
|
||||
constructor(readonly value: Array<string>) {}
|
||||
constructor(readonly value: Array<string>) { }
|
||||
toEventTag(): string[] | undefined {
|
||||
return this.value;
|
||||
}
|
||||
@ -191,11 +194,10 @@ export class NostrLink implements ToNostrEventTag {
|
||||
}
|
||||
}
|
||||
|
||||
static fromTag<T = NostrLink>(
|
||||
static fromTag(
|
||||
tag: Array<string>,
|
||||
author?: string,
|
||||
kind?: number,
|
||||
fnOther?: (tag: Array<string>) => T | undefined,
|
||||
) {
|
||||
const relays = tag.length > 2 ? [tag[2]] : undefined;
|
||||
switch (tag[0]) {
|
||||
@ -209,17 +211,15 @@ export class NostrLink implements ToNostrEventTag {
|
||||
const [kind, author, dTag] = tag[1].split(":");
|
||||
return new NostrLink(NostrPrefix.Address, dTag, Number(kind), author, relays, tag[3]);
|
||||
}
|
||||
default: {
|
||||
return fnOther?.(tag) ?? new UnknownTag(tag);
|
||||
}
|
||||
}
|
||||
throw new Error("Unknown tag!");
|
||||
}
|
||||
|
||||
static fromTags<T = NostrLink>(tags: ReadonlyArray<Array<string>>, fnOther?: (tag: Array<string>) => T | undefined) {
|
||||
static fromTags(tags: ReadonlyArray<Array<string>>) {
|
||||
return removeUndefined(
|
||||
tags.map(a => {
|
||||
try {
|
||||
return NostrLink.fromTag<T>(a, undefined, undefined, fnOther);
|
||||
return NostrLink.fromTag(a);
|
||||
} catch {
|
||||
// ignored, cant be mapped
|
||||
}
|
||||
@ -227,6 +227,21 @@ export class NostrLink implements ToNostrEventTag {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all tags even if they are unknown
|
||||
*/
|
||||
static fromAllTags(tags: ReadonlyArray<Array<string>>): Array<ToNostrEventTag> {
|
||||
return removeUndefined(
|
||||
tags.map(a => {
|
||||
try {
|
||||
return NostrLink.fromTag(a);
|
||||
} catch {
|
||||
return new UnknownTag(a);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
static fromEvent(ev: TaggedNostrEvent | NostrEvent) {
|
||||
const relays = "relays" in ev ? ev.relays : undefined;
|
||||
|
||||
|
@ -343,11 +343,11 @@ export class Query extends EventEmitter<QueryEvents> {
|
||||
this.#log("Starting emit of %s", this.id);
|
||||
const existing = this.filters;
|
||||
if (!(this.request.options?.skipDiff ?? false) && existing.length > 0) {
|
||||
const filters = await this.request.buildDiff(this.#system, existing);
|
||||
const filters = this.request.buildDiff(this.#system, existing);
|
||||
this.#log("Build %s %O", this.id, filters);
|
||||
filters.forEach(f => this.emit("request", this.id, f));
|
||||
} else {
|
||||
const filters = await this.request.build(this.#system);
|
||||
const filters = this.request.build(this.#system);
|
||||
this.#log("Build %s %O", this.id, filters);
|
||||
filters.forEach(f => this.emit("request", this.id, f));
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ export class RequestBuilder {
|
||||
/**
|
||||
* Detects a change in request from a previous set of filters
|
||||
*/
|
||||
async buildDiff(system: SystemInterface, prev: Array<ReqFilter>): Promise<Array<BuiltRawReqFilter>> {
|
||||
buildDiff(system: SystemInterface, prev: Array<ReqFilter>): Array<BuiltRawReqFilter> {
|
||||
const start = unixNowMs();
|
||||
|
||||
let rawFilters = this.buildRaw();
|
||||
|
@ -45,7 +45,7 @@ export class DiffSyncTags extends EventEmitter<SafeSyncEvents> {
|
||||
* Get decrypted content
|
||||
*/
|
||||
get encryptedTags() {
|
||||
if (this.#decryptedContent) {
|
||||
if (this.#decryptedContent && this.#decryptedContent.startsWith("[") && this.#decryptedContent.endsWith("]")) {
|
||||
const tags = JSON.parse(this.#decryptedContent) as Array<Array<string>>;
|
||||
return tags;
|
||||
}
|
||||
@ -99,11 +99,7 @@ export class DiffSyncTags extends EventEmitter<SafeSyncEvents> {
|
||||
async sync(signer: EventSigner, system: SystemInterface) {
|
||||
await this.#sync.sync(system);
|
||||
|
||||
if (
|
||||
this.#sync.value?.content &&
|
||||
this.#sync.value?.content.startsWith("[") &&
|
||||
this.#sync.value?.content.endsWith("]")
|
||||
) {
|
||||
if (this.#sync.value?.content) {
|
||||
const decrypted = await signer.nip4Decrypt(this.#sync.value.content, await signer.getPubKey());
|
||||
this.#decryptedContent = decrypted;
|
||||
}
|
||||
@ -140,10 +136,9 @@ export class DiffSyncTags extends EventEmitter<SafeSyncEvents> {
|
||||
}
|
||||
|
||||
// apply changes onto next
|
||||
this.#applyChanges(next.tags, this.#changes);
|
||||
next.tags = this.#applyChanges(next.tags, this.#changes);
|
||||
if (this.#changesEncrypted.length > 0 && !content) {
|
||||
const encryptedTags = isNew ? [] : this.encryptedTags;
|
||||
this.#applyChanges(encryptedTags, this.#changesEncrypted);
|
||||
const encryptedTags = this.#applyChanges(isNew ? [] : this.encryptedTags, this.#changesEncrypted);
|
||||
next.content = JSON.stringify(encryptedTags);
|
||||
} else if (content) {
|
||||
next.content = content;
|
||||
@ -206,5 +201,17 @@ export class DiffSyncTags extends EventEmitter<SafeSyncEvents> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove duplicates
|
||||
return tags.filter((v, i, arr) => {
|
||||
let hasAnother = false;
|
||||
for (let x = i + 1; x < arr.length; x++) {
|
||||
if (arr[x][0] === v[0] && arr[x][1] === v[1]) {
|
||||
hasAnother = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return !hasAnother;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ export class UserState<TAppData> extends EventEmitter<UserStateEvents> {
|
||||
get muted() {
|
||||
const list = this.#standardLists.get(EventKind.MuteList);
|
||||
if (list) {
|
||||
return NostrLink.fromTags(list.encryptedTags);
|
||||
return NostrLink.fromAllTags(list.encryptedTags);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@ -396,12 +396,9 @@ export class UserState<TAppData> extends EventEmitter<UserStateEvents> {
|
||||
return false;
|
||||
}
|
||||
|
||||
getList<T extends ToNostrEventTag>(
|
||||
kind: EventKind,
|
||||
fnOther?: (tag: Array<string>) => T | undefined,
|
||||
): Array<ToNostrEventTag> {
|
||||
getList(kind: EventKind): Array<ToNostrEventTag> {
|
||||
const list = this.#standardLists.get(kind);
|
||||
return NostrLink.fromTags<T>(list?.tags ?? [], fnOther);
|
||||
return NostrLink.fromAllTags(list?.tags ?? []);
|
||||
}
|
||||
|
||||
serialize(): UserStateObject<TAppData> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user