Harden filter import: item-level validation and user feedback

importFromAyuGram now skips individual malformed entries (missing id/text)
instead of crashing, and validates the top-level structure properly.
Import shows a toast on success, empty result, or parse failure.
This commit is contained in:
Tianrong Zhang 2026-06-11 23:35:43 -04:00
parent 1913174e1c
commit ffb1ba8108
2 changed files with 26 additions and 14 deletions

View File

@ -33,7 +33,7 @@ const SettingsAyuLike = ({
messageFilters,
onReset,
}: OwnProps & StateProps) => {
const { setSharedSettingOption } = getActions();
const { setSharedSettingOption, showNotification } = getActions();
const fileInputRef = useRef<HTMLInputElement>();
const [isClearConfirmOpen, openClearConfirm, closeClearConfirm] = useFlag(false);
@ -59,11 +59,16 @@ const SettingsAyuLike = ({
reader.onload = () => {
try {
const imported = importFromAyuGram(JSON.parse(reader.result as string));
setSharedSettingOption({
ayuLike: { hideSponsoredMessages, messageFilters: imported },
});
if (imported.length === 0) {
showNotification({ message: 'No valid filter rules found in file' });
} else {
setSharedSettingOption({
ayuLike: { hideSponsoredMessages, messageFilters: imported },
});
showNotification({ message: `Imported ${imported.length} filter rules` });
}
} catch {
// Silently ignore malformed files — user will see no change
showNotification({ message: 'Invalid file: not a valid AyuGram filter export' });
}
// Reset so the same file can be re-imported
e.target.value = '';

View File

@ -47,16 +47,23 @@ interface AyuGramExport {
export function importFromAyuGram(json: unknown): MessageFilterRule[] {
const data = json as AyuGramExport;
if (!Array.isArray(data?.filters)) throw new Error('Invalid AyuGram export format');
if (!data || typeof data !== 'object' || !Array.isArray(data.filters)) {
throw new Error('Invalid AyuGram export format');
}
return data.filters.map((f) => ({
id: f.id,
enabled: Boolean(f.enabled),
reversed: Boolean(f.reversed),
caseInsensitive: Boolean(f.caseInsensitive),
regex: f.text,
chatIds: f.dialogId ? [String(f.dialogId)] : undefined,
}));
return data.filters.flatMap((f) => {
if (!f || typeof f !== 'object') return [];
if (typeof f.id !== 'string' || !f.id) return [];
if (typeof f.text !== 'string' || !f.text) return [];
return [{
id: f.id,
enabled: Boolean(f.enabled),
reversed: Boolean(f.reversed),
caseInsensitive: Boolean(f.caseInsensitive),
regex: f.text,
chatIds: f.dialogId ? [String(f.dialogId)] : undefined,
}];
});
}
export function exportToAyuGram(rules: MessageFilterRule[]): string {