feat: update topic lists

This commit is contained in:
Kieran 2023-11-13 22:55:51 +00:00
parent 24978f4e62
commit 81d6f41050
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
5 changed files with 287 additions and 32 deletions

View File

@ -34,14 +34,14 @@ const Timeline = (props: TimelineProps) => {
}, [props]);
const feed: TimelineFeed = useTimelineFeed(props.subject, feedOptions);
const { muted, isMuted } = useModeration();
const { muted, isEventMuted } = useModeration();
const filterPosts = useCallback(
(nts: readonly TaggedNostrEvent[]) => {
const a = [...nts.filter(a => a.kind !== EventKind.LiveEvent)];
props.noSort || a.sort((a, b) => b.created_at - a.created_at);
return a
?.filter(a => (props.postsOnly ? !a.tags.some(b => b[0] === "e") : true))
.filter(a => props.ignoreModeration || !isMuted(a.pubkey));
.filter(a => props.ignoreModeration || !isEventMuted(a));
},
[props.postsOnly, muted, props.ignoreModeration],
);

View File

@ -39,7 +39,7 @@ const TimelineFollows = (props: TimelineFollowsProps) => {
);
const system = useContext(SnortContext);
const login = useLogin();
const { muted, isMuted } = useModeration();
const { muted, isEventMuted } = useModeration();
const sortedFeed = useMemo(() => orderDescending(feed), [feed]);
@ -49,11 +49,11 @@ const TimelineFollows = (props: TimelineFollowsProps) => {
);
const filterPosts = useCallback(
function <T extends NostrEvent>(nts: Array<T>) {
(nts: Array<TaggedNostrEvent>) => {
const a = nts.filter(a => a.kind !== EventKind.LiveEvent);
return a
?.filter(postsOnly)
.filter(a => !isMuted(a.pubkey) && login.follows.item.includes(a.pubkey) && (props.noteFilter?.(a) ?? true));
.filter(a => !isEventMuted(a) && login.follows.item.includes(a.pubkey) && (props.noteFilter?.(a) ?? true));
},
[postsOnly, muted, login.follows.timestamp],
);

View File

@ -1,4 +1,4 @@
import { HexKey, TaggedNostrEvent } from "@snort/system";
import { HexKey, NostrEvent, TaggedNostrEvent } from "@snort/system";
import useEventPublisher from "Hooks/useEventPublisher";
import useLogin from "Hooks/useLogin";
import { setBlocked, setMuted } from "Login";
@ -60,7 +60,7 @@ export default function useModeration() {
return appData.item.mutedWords.includes(word.toLowerCase());
}
function isEventMuted(ev: TaggedNostrEvent) {
function isEventMuted(ev: TaggedNostrEvent | NostrEvent) {
return isMuted(ev.pubkey) || appData.item.mutedWords.some(w => ev.content.toLowerCase().includes(w));
}

View File

@ -1,16 +1,16 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { ReactNode, useState } from "react";
import { useState } from "react";
import { FormattedMessage } from "react-intl";
import { useNavigate } from "react-router-dom";
import { unixNowMs } from "@snort/shared";
import AsyncButton from "Element/AsyncButton";
import classNames from "classnames";
import { appendDedupe } from "SnortUtils";
import useEventPublisher from "Hooks/useEventPublisher";
import { setMuted } from "Login";
import { ToggleSwitch } from "Icons/Toggle";
import { updateAppData } from "Login";
import useLogin from "Hooks/useLogin";
export const FixedModeration = {
hateSpeech: {
/*hateSpeech: {
title: <FormattedMessage defaultMessage="Hate Speech" />,
words: [],
canEdit: false,
@ -19,7 +19,7 @@ export const FixedModeration = {
title: <FormattedMessage defaultMessage="Derogatory" />,
words: [],
canEdit: false,
},
},*/
nsfw: {
title: <FormattedMessage defaultMessage="NSFW" />,
words: [
@ -43,6 +43,7 @@ export const FixedModeration = {
"explicit language",
"adult-only",
"mature language",
"sex"
],
canEdit: false,
},
@ -72,18 +73,50 @@ export const FixedModeration = {
"crypto wallet",
"satoshi nakamoto",
],
canEdit: true,
canEdit: false,
},
politics: {
title: <FormattedMessage defaultMessage="Politics" />,
words: [],
canEdit: true,
words: [
"politics",
"election",
"democrat",
"republican",
"senate",
"congress",
"parliament",
"president",
"prime minister",
"policy",
"legislation",
"vote",
"campaign",
"government",
"political party",
"lobbying",
"referendum",
"bill",
"conservative",
"liberal",
"left-wing",
"right-wing",
"socialist",
"capitalist",
"diplomacy",
"sanction",
"geopolitics",
"activism",
"protest",
"rally"
],
canEdit: false,
},
};
export function Moderation() {
const { publisher, system } = useEventPublisher();
const id = useLogin(s => s.id);
const [topics, setTopics] = useState<Array<string>>(Object.keys(FixedModeration));
const [extraTerms, setExtraTerms] = useState("");
const navigate = useNavigate();
return (
@ -135,7 +168,7 @@ export function Moderation() {
<small className="font-medium">
<FormattedMessage defaultMessage="Use commas to separate words e.g. word1, word2, word3" />
</small>
<textarea></textarea>
<textarea onChange={e => setExtraTerms(e.target.value)} value={extraTerms}></textarea>
</div>
<AsyncButton
className="primary"
@ -143,9 +176,18 @@ export function Moderation() {
const words = Object.entries(FixedModeration)
.filter(([k]) => topics.includes(k))
.map(([, v]) => v.words)
.flat();
.flat()
.concat(extraTerms.split(",").map(a => a.trim()));
if (words.length > 0) {
// no
updateAppData(id, ad => {
return {
item: {
...ad,
mutedWords: appendDedupe(ad.mutedWords, words)
},
timestamp: unixNowMs()
}
})
}
navigate("/");
}}>

View File

@ -10,35 +10,248 @@ import { NostrHashtagLink } from "@snort/system";
export const FixedTopics = {
life: {
text: <FormattedMessage defaultMessage="Life" />,
tags: ["life"],
tags: [
"life",
"lifestyle",
"dailyinspiration",
"motivation",
"lifelessons",
"personaldevelopment",
"happiness",
"wellbeing",
"mindfulness",
"selfcare",
"positivity",
"growth",
"inspiration",
"lifegoals",
"mindset",
"joy",
"balance",
"fulfillment",
"purpose",
"living",
"lifetips",
"lifehacks",
"wellness",
"lifejourney",
"enjoylife",
"simplepleasures",
"gratitude",
"lifeadvice",
"lifecoaching",
"lifelove"
],
},
science: {
text: <FormattedMessage defaultMessage="Science" />,
tags: ["science"],
tags: [
"science",
"research",
"innovation",
"technology",
"biology",
"physics",
"chemistry",
"astronomy",
"environment",
"ecology",
"geology",
"neuroscience",
"genetics",
"data",
"experiment",
"theory",
"discovery",
"engineering",
"mathematics",
"robotics",
"artificialintelligence",
"climate",
"space",
"quantum",
"microbiology",
"biotechnology",
"nanotechnology",
"pharmacology",
"astrophysics",
"scientificmethod"
],
},
nature: {
text: <FormattedMessage defaultMessage="Nature" />,
tags: ["nature"],
tags: [
"nature",
"wildlife",
"forest",
"mountains",
"rivers",
"oceans",
"flora",
"fauna",
"ecosystem",
"biodiversity",
"conservation",
"habitat",
"landscape",
"outdoors",
"environment",
"geography",
"earth",
"climate",
"naturalbeauty",
"wilderness",
"green",
"sustainability",
"wildlifeconservation",
"nationalpark",
"gardening",
"hiking",
"birdwatching",
"ecotourism",
"photography",
"naturelovers"
],
},
business: {
text: <FormattedMessage defaultMessage="Business" />,
tags: ["business"],
tags: [
"business",
"entrepreneurship",
"marketing",
"finance",
"innovation",
"management",
"startup",
"leadership",
"economics",
"strategy",
"branding",
"sales",
"technology",
"investment",
"networking",
"growth",
"corporate",
"customer",
"market",
"productivity",
"advertising",
"ecommerce",
"analytics",
"humanresources",
"globalbusiness",
"digitalmarketing",
"socialmedia",
"sustainability",
"entrepreneur",
"businessdevelopment"
],
},
game: {
text: <FormattedMessage defaultMessage="Game" />,
tags: ["game", "gaming"],
tags: [
"gaming",
"videogames",
"esports",
"multiplayer",
"onlinegaming",
"gameplay",
"streaming",
"gamer",
"console",
"pcgaming",
"mobilegaming",
"gamedevelopment",
"virtualreality",
"roleplaying",
"strategygames",
"actiongames",
"simulation",
"indiegames",
"adventuregames",
"puzzle",
"fantasy",
"scifi",
"horror",
"sports",
"racing",
"fighting",
"platformer",
"mmorpg",
"retrogaming",
"arcade"
],
},
sport: {
text: <FormattedMessage defaultMessage="Sport" />,
tags: ["sport"],
tags: [
"sports",
"athletics",
"soccer",
"basketball",
"baseball",
"football",
"tennis",
"golf",
"swimming",
"running",
"cycling",
"volleyball",
"hockey",
"skiing",
"boxing",
"martialarts",
"gymnastics",
"cricket",
"rugby",
"tabletennis",
"badminton",
"fishing",
"archery",
"bowling",
"surfing",
"skateboarding",
"motorsports",
"equestrian",
"fitness",
"yoga"
],
},
photography: {
text: <FormattedMessage defaultMessage="Photography" />,
tags: ["photography"],
},
bitcoin: {
text: <FormattedMessage defaultMessage="Bitcoin" />,
tags: ["bitcoin"],
tags: [
"photography",
"landscape",
"portrait",
"naturephotography",
"streetphotography",
"blackandwhite",
"travelphotography",
"macro",
"wildlifephotography",
"urbanphotography",
"nightphotography",
"fashionphotography",
"fineartphotography",
"documentary",
"sportsphotography",
"foodphotography",
"architecturalphotography",
"candid",
"aerialphotography",
"underwaterphotography",
"filmphotography",
"digitalphotography",
"photographytips",
"photoediting",
"photographygear",
"lighting",
"composition",
"exposure",
"photographyworkshop",
"photographyart"
],
},
};