CurationTab-DCyBD2cg.js raw

   1  import{r as n,j as e,B as c,t as l,b as ie,c as W}from"./index-DfKg850Q.js";function k(t){return!t||t.length<16?t:`${t.slice(0,8)}...${t.slice(-8)}`}function X(t){if(!t)return"";const i=typeof t=="string"?Date.parse(t):t;return new Date(i).toLocaleString()}const le={0:"Metadata",1:"Text Note",3:"Follow List",4:"Encrypted DM",6:"Repost",7:"Reaction",14:"Chat Message",1063:"File Metadata",10002:"Relay List",30023:"Long-form",30078:"App Data"};function ce(t){return le[t]??`Kind ${t}`}function de(t,i=6){if(!t)return"";const d=t.split(`
   2  `);if(d.length<=i&&t.length<=i*100)return t;let m=d.slice(0,i).join(`
   3  `);return m.length>i*100&&(m=m.substring(0,i*100)),m}function oe(t,i=6){return t?t.split(`
   4  `).length>i||t.length>i*100:!1}async function u(t,i=[]){const d=await ie.nip86Request(t,i);if(d.error)throw new Error(String(d.error));return d.result}function S({active:t,onClick:i,children:d}){return e.jsx("button",{onClick:i,className:W("px-3 py-2 text-sm border-b-2 transition-colors",t?"border-primary text-primary":"border-transparent text-muted-foreground hover:text-foreground hover:bg-accent/20"),children:d})}function ue({pubkey:t,category:i,onClose:d,onChanged:m}){const[x,N]=n.useState([]),[h,E]=n.useState(0),[b,P]=n.useState(!1),[B,z]=n.useState({}),[p,v]=n.useState(!1),w=n.useCallback(async r=>{if(!b){P(!0);try{const o=await u("geteventsforpubkey",[t,100,r]);o&&(N(r===0?o.events??[]:f=>[...f,...o.events??[]]),E(o.total??0))}catch(o){l.error(`Failed to load events: ${o instanceof Error?o.message:String(o)}`)}finally{P(!1)}}},[t,b]);n.useEffect(()=>{w(0)},[t]);const g=async(r,o,f)=>{v(!0);try{await u(r,o),l.success(f),m(),d()}catch(y){l.error(y instanceof Error?y.message:String(y))}finally{v(!1)}},_=async()=>{if(confirm(`Delete ALL ${h} events from this user? This cannot be undone.`)){v(!0);try{const r=await u("deleteeventsforpubkey",[t]);l.success(`Deleted ${(r==null?void 0:r.deleted)??0} events`),N([]),E(0)}catch(r){l.error(r instanceof Error?r.message:String(r))}finally{v(!1)}}};return e.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2 border-b pb-3",children:[e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsx(c,{variant:"outline",size:"sm",onClick:d,children:"← Back"}),e.jsx("span",{className:"font-semibold",children:"User Events"}),e.jsx("code",{className:"rounded bg-muted px-2 py-0.5 text-xs",title:t,children:k(t)}),e.jsxs("span",{className:"text-xs text-green-500 font-medium",children:[h," events"]})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[i==="trusted"&&e.jsxs(e.Fragment,{children:[e.jsx(c,{variant:"destructive",size:"sm",disabled:p,onClick:()=>g("untrustpubkey",[t],"Trust removed"),children:"Remove Trust"}),e.jsx(c,{variant:"destructive",size:"sm",disabled:p,onClick:()=>g("blacklistpubkey",[t,""],"Blacklisted"),children:"Blacklist"})]}),i==="blacklisted"&&e.jsxs(e.Fragment,{children:[e.jsx(c,{variant:"destructive",size:"sm",disabled:p||h===0,onClick:_,className:"bg-red-900 hover:bg-red-950",children:"Delete All Events"}),e.jsx(c,{size:"sm",disabled:p,onClick:()=>g("unblacklistpubkey",[t],"Removed from blacklist"),children:"Remove from Blacklist"}),e.jsx(c,{size:"sm",disabled:p,onClick:()=>g("trustpubkey",[t,""],"Trusted"),children:"Trust"})]}),i==="unclassified"&&e.jsxs(e.Fragment,{children:[e.jsx(c,{size:"sm",disabled:p,onClick:()=>g("trustpubkey",[t,""],"Trusted"),children:"Trust"}),e.jsx(c,{variant:"destructive",size:"sm",disabled:p,onClick:()=>g("blacklistpubkey",[t,""],"Blacklisted"),children:"Blacklist"})]})]})]}),e.jsxs("div",{className:"max-h-[600px] overflow-y-auto space-y-2",children:[b&&x.length===0?e.jsx("p",{className:"text-center py-8 text-muted-foreground",children:"Loading events..."}):x.length===0?e.jsx("p",{className:"text-center py-8 text-muted-foreground italic",children:"No events found."}):x.map(r=>{const o=!!B[r.id],f=oe(r.content);return e.jsxs("div",{className:"rounded-md border bg-background p-3 space-y-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-xs",children:[e.jsx("span",{className:"rounded bg-primary/80 text-primary-foreground px-2 py-0.5 font-medium",children:ce(r.kind)}),e.jsx("code",{className:"text-muted-foreground",title:r.id,children:k(r.id)}),e.jsx("span",{className:"text-muted-foreground/60",children:X(r.created_at*1e3)})]}),e.jsx("pre",{className:W("whitespace-pre-wrap break-words text-sm bg-card rounded p-2",!o&&"max-h-[150px] overflow-hidden"),children:o||!f?r.content||"(empty)":`${de(r.content)}...`}),f&&e.jsx("button",{className:"text-xs text-primary hover:underline",onClick:()=>z(y=>({...y,[r.id]:!y[r.id]})),children:o?"Show less":"Show more"})]},r.id)}),x.length>0&&x.length<h&&e.jsx("div",{className:"text-center py-3",children:e.jsx(c,{variant:"outline",size:"sm",disabled:b,onClick:()=>w(x.length),children:b?"Loading...":`Load more (${x.length} of ${h})`})})]})]})}function xe(){const[t,i]=n.useState("trusted"),[d,m]=n.useState(!1),[x,N]=n.useState([]),[h,E]=n.useState([]),[b,P]=n.useState([]),[B,z]=n.useState([]),[p,v]=n.useState([]),[w,g]=n.useState(""),[_,r]=n.useState(""),[o,f]=n.useState(""),[y,A]=n.useState(""),[F,R]=n.useState(null),[Y,I]=n.useState("unclassified"),[M,H]=n.useState(50),[q,K]=n.useState(1),[G,J]=n.useState(168),D=n.useCallback(async()=>{try{const s=await u("listtrustedpubkeys");N(s??[])}catch{N([])}},[]),U=n.useCallback(async()=>{try{const s=await u("listblacklistedpubkeys");E(s??[])}catch{E([])}},[]),C=n.useCallback(async()=>{try{const s=await u("listunclassifiedusers");P(s??[])}catch{P([])}},[]),T=n.useCallback(async()=>{try{const s=await u("listspamevents");z(s??[])}catch{z([])}},[]),$=n.useCallback(async()=>{try{const s=await u("listblockedips");v(s??[])}catch{v([])}},[]),O=n.useCallback(async()=>{try{const s=await u("getcuratingconfig");s&&(H(s.daily_limit??50),K(s.first_ban_hours??1),J(s.second_ban_hours??168))}catch{}},[]),L=n.useCallback(async()=>{m(!0),await Promise.all([D(),U(),C(),T(),$(),O()]),m(!1)},[D,U,C,T,$,O]);n.useEffect(()=>{L()},[L]);const Q=async(s,a)=>{if(s)try{await u("trustpubkey",[s,a]),l.success("Pubkey trusted"),g(""),r(""),await Promise.all([D(),C()])}catch(j){l.error(j instanceof Error?j.message:String(j))}},Z=async s=>{try{await u("untrustpubkey",[s]),l.success("Trust removed"),await D()}catch(a){l.error(a instanceof Error?a.message:String(a))}},V=async(s,a)=>{if(s)try{await u("blacklistpubkey",[s,a]),l.success("Pubkey blacklisted"),f(""),A(""),await Promise.all([U(),C()])}catch(j){l.error(j instanceof Error?j.message:String(j))}},ee=async s=>{try{await u("unblacklistpubkey",[s]),l.success("Removed from blacklist"),await U()}catch(a){l.error(a instanceof Error?a.message:String(a))}},se=async s=>{try{await u("unmarkspam",[s]),l.success("Spam mark removed"),await T()}catch(a){l.error(a instanceof Error?a.message:String(a))}},te=async s=>{if(confirm("Permanently delete this event?"))try{await u("deleteevent",[s]),l.success("Event deleted"),await T()}catch(a){l.error(a instanceof Error?a.message:String(a))}},ae=async s=>{try{await u("unblockip",[s]),l.success("IP unblocked"),await $()}catch(a){l.error(a instanceof Error?a.message:String(a))}},ne=async()=>{try{const s=await u("scanpubkeys");l.success(`Scanned: ${(s==null?void 0:s.total_pubkeys)??0} pubkeys, ${(s==null?void 0:s.total_events)??0} events (${(s==null?void 0:s.skipped)??0} skipped)`),await C()}catch(s){l.error(s instanceof Error?s.message:String(s))}},re=async()=>{m(!0);try{await u("updatecuratingconfig",[{daily_limit:M,first_ban_hours:q,second_ban_hours:G}]),l.success("Settings updated")}catch(s){l.error(s instanceof Error?s.message:String(s))}finally{m(!1)}};return F?e.jsx("div",{className:"p-4 w-full",children:e.jsx(ue,{pubkey:F,category:Y,onClose:()=>R(null),onChanged:L})}):e.jsxs("div",{className:"p-4 space-y-4 w-full",children:[e.jsx("h3",{className:"text-lg font-semibold",children:"Curation Mode"}),e.jsxs("div",{className:"flex flex-wrap border-b",children:[e.jsxs(S,{active:t==="trusted",onClick:()=>i("trusted"),children:["Trusted (",x.length,")"]}),e.jsxs(S,{active:t==="blacklist",onClick:()=>i("blacklist"),children:["Blacklist (",h.length,")"]}),e.jsxs(S,{active:t==="unclassified",onClick:()=>i("unclassified"),children:["Unclassified (",b.length,")"]}),e.jsxs(S,{active:t==="spam",onClick:()=>i("spam"),children:["Spam (",B.length,")"]}),e.jsxs(S,{active:t==="ips",onClick:()=>i("ips"),children:["Blocked IPs (",p.length,")"]}),e.jsx(S,{active:t==="settings",onClick:()=>i("settings"),children:"Settings"})]}),t==="trusted"&&e.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-3",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium",children:"Trusted Publishers"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Trusted users can publish unlimited events without rate limiting."})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx("input",{className:"flex-1 min-w-[200px] rounded-md border bg-background px-3 py-1.5 text-sm",placeholder:"Pubkey (64 hex chars)",value:w,onChange:s=>g(s.target.value)}),e.jsx("input",{className:"flex-1 min-w-[120px] rounded-md border bg-background px-3 py-1.5 text-sm",placeholder:"Note (optional)",value:_,onChange:s=>r(s.target.value)}),e.jsx(c,{size:"sm",disabled:d||!w,onClick:()=>Q(w,_),children:"Trust"})]}),e.jsx("div",{className:"rounded-md border max-h-[400px] overflow-y-auto divide-y",children:x.length===0?e.jsx("p",{className:"text-center py-6 text-muted-foreground italic",children:"No trusted pubkeys yet."}):x.map(s=>e.jsxs("div",{className:"flex items-center justify-between gap-2 px-3 py-2 cursor-pointer hover:bg-accent/20 transition-colors",onClick:()=>{R(s.pubkey),I("trusted")},children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm",title:s.pubkey,children:k(s.pubkey)}),s.note&&e.jsx("p",{className:"text-xs text-muted-foreground truncate",children:s.note})]}),e.jsx(c,{variant:"destructive",size:"sm",onClick:a=>{a.stopPropagation(),Z(s.pubkey)},children:"Remove"})]},s.pubkey))})]}),t==="blacklist"&&e.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-3",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium",children:"Blacklisted Publishers"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Blacklisted users cannot publish any events."})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx("input",{className:"flex-1 min-w-[200px] rounded-md border bg-background px-3 py-1.5 text-sm",placeholder:"Pubkey (64 hex chars)",value:o,onChange:s=>f(s.target.value)}),e.jsx("input",{className:"flex-1 min-w-[120px] rounded-md border bg-background px-3 py-1.5 text-sm",placeholder:"Reason (optional)",value:y,onChange:s=>A(s.target.value)}),e.jsx(c,{variant:"destructive",size:"sm",disabled:d||!o,onClick:()=>V(o,y),children:"Blacklist"})]}),e.jsx("div",{className:"rounded-md border max-h-[400px] overflow-y-auto divide-y",children:h.length===0?e.jsx("p",{className:"text-center py-6 text-muted-foreground italic",children:"No blacklisted pubkeys."}):h.map(s=>e.jsxs("div",{className:"flex items-center justify-between gap-2 px-3 py-2 cursor-pointer hover:bg-accent/20 transition-colors",onClick:()=>{R(s.pubkey),I("blacklisted")},children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm",title:s.pubkey,children:k(s.pubkey)}),s.reason&&e.jsx("p",{className:"text-xs text-muted-foreground truncate",children:s.reason})]}),e.jsx(c,{size:"sm",onClick:a=>{a.stopPropagation(),ee(s.pubkey)},children:"Remove"})]},s.pubkey))})]}),t==="unclassified"&&e.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-3",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium",children:"Unclassified Users"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Users who have posted events but haven't been classified. Sorted by event count."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(c,{variant:"outline",size:"sm",disabled:d,onClick:C,children:"Refresh"}),e.jsx(c,{variant:"secondary",size:"sm",disabled:d,onClick:ne,children:"Scan Database"})]}),e.jsx("div",{className:"rounded-md border max-h-[400px] overflow-y-auto divide-y",children:b.length===0?e.jsx("p",{className:"text-center py-6 text-muted-foreground italic",children:"No unclassified users."}):b.map(s=>e.jsxs("div",{className:"flex items-center justify-between gap-2 px-3 py-2 cursor-pointer hover:bg-accent/20 transition-colors",onClick:()=>{R(s.pubkey),I("unclassified")},children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm",title:s.pubkey,children:k(s.pubkey)}),e.jsxs("span",{className:"ml-2 text-xs text-green-500 font-medium",children:[s.event_count," events"]})]}),e.jsxs("div",{className:"flex gap-1.5 shrink-0",children:[e.jsx(c,{size:"sm",onClick:a=>{a.stopPropagation(),Q(s.pubkey,"")},children:"Trust"}),e.jsx(c,{variant:"destructive",size:"sm",onClick:a=>{a.stopPropagation(),V(s.pubkey,"")},children:"Blacklist"})]})]},s.pubkey))})]}),t==="spam"&&e.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-3",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium",children:"Spam Events"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Events flagged as spam are hidden from query results but remain in the database."})]}),e.jsx(c,{variant:"outline",size:"sm",disabled:d,onClick:T,children:"Refresh"}),e.jsx("div",{className:"rounded-md border max-h-[400px] overflow-y-auto divide-y",children:B.length===0?e.jsx("p",{className:"text-center py-6 text-muted-foreground italic",children:"No spam events flagged."}):B.map(s=>e.jsxs("div",{className:"flex items-center justify-between gap-2 px-3 py-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm",title:s.event_id,children:k(s.event_id)}),e.jsxs("span",{className:"ml-2 text-xs text-muted-foreground",title:s.pubkey,children:["by ",k(s.pubkey)]}),s.reason&&e.jsx("p",{className:"text-xs text-muted-foreground truncate",children:s.reason})]}),e.jsxs("div",{className:"flex gap-1.5 shrink-0",children:[e.jsx(c,{size:"sm",onClick:()=>se(s.event_id),children:"Unmark"}),e.jsx(c,{variant:"destructive",size:"sm",onClick:()=>te(s.event_id),children:"Delete"})]})]},s.event_id))})]}),t==="ips"&&e.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-3",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium",children:"Blocked IP Addresses"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"IP addresses blocked due to rate limit violations."})]}),e.jsx(c,{variant:"outline",size:"sm",disabled:d,onClick:$,children:"Refresh"}),e.jsx("div",{className:"rounded-md border max-h-[400px] overflow-y-auto divide-y",children:p.length===0?e.jsx("p",{className:"text-center py-6 text-muted-foreground italic",children:"No blocked IPs."}):p.map(s=>e.jsxs("div",{className:"flex items-center justify-between gap-2 px-3 py-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-sm",children:s.ip}),s.reason&&e.jsx("span",{className:"ml-2 text-xs text-muted-foreground",children:s.reason}),s.expires_at&&e.jsxs("span",{className:"ml-2 text-xs text-muted-foreground/60",children:["Expires: ",X(s.expires_at)]})]}),e.jsx(c,{size:"sm",onClick:()=>ae(s.ip),children:"Unblock"})]},s.ip))})]}),t==="settings"&&e.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-4",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium",children:"Rate Limiting"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Configure rate limits for unclassified users and IP ban durations."})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-4",children:[e.jsxs("label",{className:"space-y-1",children:[e.jsx("span",{className:"text-sm font-medium",children:"Daily Event Limit"}),e.jsx("input",{type:"number",min:1,className:"w-full rounded-md border bg-background px-3 py-1.5 text-sm",value:M,onChange:s=>H(Number(s.target.value))})]}),e.jsxs("label",{className:"space-y-1",children:[e.jsx("span",{className:"text-sm font-medium",children:"First Ban (hours)"}),e.jsx("input",{type:"number",min:1,className:"w-full rounded-md border bg-background px-3 py-1.5 text-sm",value:q,onChange:s=>K(Number(s.target.value))})]}),e.jsxs("label",{className:"space-y-1",children:[e.jsx("span",{className:"text-sm font-medium",children:"Second+ Ban (hours)"}),e.jsx("input",{type:"number",min:1,className:"w-full rounded-md border bg-background px-3 py-1.5 text-sm",value:G,onChange:s=>J(Number(s.target.value))})]})]}),e.jsx("div",{children:e.jsx(c,{size:"sm",disabled:d,onClick:re,children:d?"Saving...":"Save Settings"})})]})]})}export{xe as default};
   5