BanForm.tsx (9336B)
1 import { PureComponent } from "react"; 2 import { 3 CanonicalAliasEvent, 4 CANONICAL_ALIAS, 5 DEV_NORDGEDANKEN_MJOLNIR_BANLISTS, 6 MJjolnirBanlists, 7 M_POLICY_RULE_SERVER, 8 M_POLICY_RULE_SERVER_ALT, 9 M_POLICY_RULE_SERVER_OLD, 10 M_POLICY_RULE_USER, 11 M_POLICY_RULE_USER_ALT, 12 M_POLICY_RULE_USER_OLD, 13 ORG_MATRIX_MJOLNIR_SHORTCODE, 14 RuleEvent, 15 ShortcodeEvent, 16 } from "../../windowExt"; 17 18 type Props = Record<string, unknown>; 19 type State = { 20 glob: string; 21 reason: string; 22 roomId?: string; 23 aliases_shortcodes: Map<string, string>; 24 banlist: string; 25 bantype: "user" | "server" | "room" | ""; 26 }; 27 28 class BanForm extends PureComponent<Props, State> { 29 constructor(props: Props | Readonly<Props>) { 30 super(props); 31 const urlParams = (new URL(window.location.href)).searchParams; 32 const roomId = urlParams.get("room_id") ?? undefined; 33 this.state = { 34 glob: "", 35 reason: "", 36 roomId: roomId, 37 banlist: "", 38 bantype: "", 39 aliases_shortcodes: new Map() 40 }; 41 } 42 43 async componentDidMount() { 44 const user_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_USER, 250_000_000_000, undefined, ["*"]) as RuleEvent[]; 45 const server_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER, 250_000_000_000, undefined, ["*"]) as RuleEvent[]; 46 const user_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_OLD, 250_000_000_000, undefined, ["*"]) as RuleEvent[]; 47 const server_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_OLD, 250_000_000_000, undefined, ["*"]) as RuleEvent[]; 48 const user_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_ALT, 250_000_000_000, undefined, ["*"]) as RuleEvent[]; 49 const server_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_ALT, 250_000_000_000, undefined, ["*"]) as RuleEvent[]; 50 const banlist_codes = await window.widget_api.readStateEvents(DEV_NORDGEDANKEN_MJOLNIR_BANLISTS, 250_000_000_000, undefined, [this.state.roomId ?? "*"]) as MJjolnirBanlists[]; 51 const user_rules_all = [...user_rules, ...user_rules_old, ...user_rules_alt]; 52 const server_rules_all = [...server_rules, ...server_rules_old, ...server_rules_alt]; 53 const listrooms = [...new Set([...user_rules_all.map(element => element.room_id), ...server_rules_all.map(element => element.room_id)])]; 54 const aliases = await window.widget_api.readStateEvents(CANONICAL_ALIAS, listrooms.length, undefined, listrooms) as CanonicalAliasEvent[]; 55 const shortcodes = await window.widget_api.readStateEvents(ORG_MATRIX_MJOLNIR_SHORTCODE, listrooms.length, undefined, listrooms) as ShortcodeEvent[]; 56 const aliases_shortcodes = new Map(); 57 58 for (const event of aliases) { 59 let result_known = true; 60 if (banlist_codes.length > 0) { 61 if (banlist_codes.some(known_lists_event => (event.room_id in (known_lists_event.content?.banlists ?? {})) || ((event.content?.alias ?? "") in (known_lists_event.content?.banlists ?? {})))) { 62 result_known = true; 63 } else { 64 result_known = false; 65 } 66 } 67 if (event.content?.alias && result_known) { 68 aliases_shortcodes.set(event.content?.alias, shortcodes.find(shortcode_event => shortcode_event.room_id === event.room_id)?.content?.shortcode); 69 } else if (result_known) { 70 aliases_shortcodes.set(event.room_id, shortcodes.find(shortcode_event => shortcode_event.room_id === event.room_id)?.content?.shortcode); 71 } 72 } 73 74 if (banlist_codes.length > 0) { 75 const lists_event = banlist_codes.find(list => list.room_id === this.state.roomId); 76 for (const [list, shortcode] of Object.entries(lists_event?.content?.banlists ?? {})) { 77 if (!aliases_shortcodes.has(list)) { 78 aliases_shortcodes.set(list, shortcode); 79 } 80 } 81 } 82 this.setState({ 83 aliases_shortcodes 84 }); 85 } 86 87 handleInputChange(event: { target: { type: string, checked?: boolean, value: string | boolean, name: string; }; }) { 88 const target = event.target; 89 const value = target.type === 'checkbox' ? target.checked : target.value; 90 const name = target.name; 91 this.setState({ 92 [name]: value 93 } as unknown as State); 94 } 95 96 async handleSubmit(ev: { preventDefault: () => void; }) { 97 ev.preventDefault(); 98 99 const { glob, banlist, bantype, reason, roomId } = this.state; 100 101 if (glob === "" || banlist === "" || bantype === "") { 102 // TODO display warning 103 return; 104 } else { 105 if (reason === "") { 106 await window.widget_api.sendRoomEvent("m.room.message", { 107 msgtype: "m.text", 108 body: `!mjolnir ban ${banlist} ${bantype} ${glob}`, 109 }, roomId); 110 } else { 111 await window.widget_api.sendRoomEvent("m.room.message", { 112 msgtype: "m.text", 113 body: `!mjolnir ban ${banlist} ${bantype} ${glob} ${reason}`, 114 }, roomId); 115 } 116 } 117 } 118 119 render() { 120 const { glob, banlist, aliases_shortcodes, bantype, reason } = this.state; 121 return ( 122 <> 123 <h3 className="text-2xl font-bold text-gray-900 dark:text-gray-200 mb-2">Ban</h3> 124 <form onSubmit={this.handleSubmit.bind(this)} className="grid grid-cols-1 gap-4"> 125 <label className="inner-flex flex-col"> 126 <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Banlist</span> 127 <h4 className="text-gray-900 dark:text-gray-200 text-base font-thin mb-2 w-96 italic">(Warning: This doesn't check if the banlist can be written to or the bot if watches it)</h4> 128 <div className="w-96"> 129 <select aria-label="Banlist" aria-required="true" required name="banlist" value={banlist} className="max-w-full min-w-full placeholder:text-gray-900 text-gray-900 rounded py-1.5 px-2" onChange={this.handleInputChange.bind(this)}> 130 <option value="" disabled>Select an Banlist</option> 131 { 132 [...aliases_shortcodes].map(([alias, shortcode]) => { 133 return <option key={alias} value={shortcode}>{alias}</option>; 134 }) 135 } 136 </select> 137 </div> 138 </label> 139 <label className="inner-flex flex-col w-96"> 140 <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Bantype</span> 141 <div className="w-96"> 142 <select aria-label="Bantype" aria-required="true" required defaultValue="" name="bantype" value={bantype} className="max-w-full min-w-full placeholder:text-gray-900 text-gray-900 rounded py-1.5 px-2" onChange={this.handleInputChange.bind(this)}> 143 <option value="" disabled>Select an Bantype</option> 144 <option value="user">User</option> 145 <option value="server">Server</option> 146 <option value="room">Room</option> 147 </select> 148 </div> 149 </label> 150 <label className="block w-96"> 151 <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Glob</span> 152 <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full"> 153 <input aria-label="Glob" aria-required="true" required placeholder="Glob" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="glob" value={glob} onChange={this.handleInputChange.bind(this)} /> 154 </div> 155 </label> 156 <label className="block w-96"> 157 <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Reason</span> 158 <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full"> 159 <input aria-label="Reason" aria-required="false" placeholder="Reason" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="reason" value={reason} onChange={this.handleInputChange.bind(this)} /> 160 </div> 161 </label> 162 163 <input className="bg-red-400 hover:bg-red-500 cursor-pointer h-10 rounded dark:text-gray-900 text-gray-200 w-96" type="submit" value="Ban" /> 164 </form> 165 </> 166 ); 167 } 168 } 169 170 export default BanForm;