feat: add RSS feeds management page with automation rules
This commit is contained in:
@@ -22,6 +22,13 @@ import {
|
||||
getIdeasByUser,
|
||||
repondreIdea,
|
||||
updateIdeaStatut,
|
||||
getRssFeeds,
|
||||
getRssFeedById,
|
||||
createRssFeed,
|
||||
updateRssFeed,
|
||||
deleteRssFeed,
|
||||
getRssSettings,
|
||||
saveRssSettings,
|
||||
} from "./db";
|
||||
import { importVeille, importAAP, runFullImport, getImportConfig } from "./importer";
|
||||
import { loginLocalUser, hashPassword, ensureAdminExists } from "./localAuth";
|
||||
@@ -50,9 +57,9 @@ export const appRouter = router({
|
||||
}),
|
||||
// Connexion locale
|
||||
localLogin: publicProcedure
|
||||
.input(z.object({ email: z.string().min(1), password: z.string().min(1) }))
|
||||
.input(z.object({ identifier: z.string().min(1), password: z.string().min(1) }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const result = await loginLocalUser(input.email, input.password);
|
||||
const result = await loginLocalUser(input.identifier, input.password);
|
||||
// Stocker le token dans un cookie
|
||||
const cookieOptions = getSessionCookieOptions(ctx.req);
|
||||
ctx.res.cookie("veille_local_auth", result.token, {
|
||||
@@ -307,6 +314,94 @@ export const appRouter = router({
|
||||
return { success: true };
|
||||
}),
|
||||
}),
|
||||
});
|
||||
// ─── Flux RSS ───────────────────────────────────────────────────────────────────────────────────
|
||||
rss: router({
|
||||
// Lister tous les flux
|
||||
list: protectedProcedure.query(async () => {
|
||||
return getRssFeeds();
|
||||
}),
|
||||
|
||||
// Créer un flux
|
||||
create: adminProcedure
|
||||
.input(z.object({
|
||||
url: z.string().url("URL invalide"),
|
||||
name: z.string().min(1, "Nom requis").max(255),
|
||||
feedType: z.enum(["veille", "aap"]),
|
||||
defaultTypeVeille: z.enum(["reglementaire", "concurrentielle", "technologique", "generale"]).optional(),
|
||||
defaultCategorieAap: z.enum(["Handicap", "PA", "Enfance", "Précarité", "Sanitaire", "Autre"]).optional(),
|
||||
autoRules: z.array(z.object({
|
||||
keyword: z.string(),
|
||||
value: z.string(),
|
||||
})).optional(),
|
||||
isActive: z.boolean().optional().default(true),
|
||||
}))
|
||||
.mutation(async ({ input }) => {
|
||||
const id = await createRssFeed({
|
||||
url: input.url,
|
||||
name: input.name,
|
||||
feedType: input.feedType,
|
||||
defaultTypeVeille: input.defaultTypeVeille ?? null,
|
||||
defaultCategorieAap: input.defaultCategorieAap ?? null,
|
||||
autoRules: input.autoRules ?? null,
|
||||
isActive: input.isActive ?? true,
|
||||
});
|
||||
return { id };
|
||||
}),
|
||||
|
||||
// Modifier un flux
|
||||
update: adminProcedure
|
||||
.input(z.object({
|
||||
id: z.number().int().positive(),
|
||||
url: z.string().url("URL invalide").optional(),
|
||||
name: z.string().min(1).max(255).optional(),
|
||||
feedType: z.enum(["veille", "aap"]).optional(),
|
||||
defaultTypeVeille: z.enum(["reglementaire", "concurrentielle", "technologique", "generale"]).nullable().optional(),
|
||||
defaultCategorieAap: z.enum(["Handicap", "PA", "Enfance", "Précarité", "Sanitaire", "Autre"]).nullable().optional(),
|
||||
autoRules: z.array(z.object({
|
||||
keyword: z.string(),
|
||||
value: z.string(),
|
||||
})).nullable().optional(),
|
||||
isActive: z.boolean().optional(),
|
||||
}))
|
||||
.mutation(async ({ input }) => {
|
||||
const { id, ...data } = input;
|
||||
await updateRssFeed(id, data);
|
||||
return { success: true };
|
||||
}),
|
||||
|
||||
// Supprimer un flux
|
||||
delete: adminProcedure
|
||||
.input(z.object({ id: z.number().int().positive() }))
|
||||
.mutation(async ({ input }) => {
|
||||
await deleteRssFeed(input.id);
|
||||
return { success: true };
|
||||
}),
|
||||
|
||||
// Activer / désactiver un flux
|
||||
toggleActive: adminProcedure
|
||||
.input(z.object({ id: z.number().int().positive(), isActive: z.boolean() }))
|
||||
.mutation(async ({ input }) => {
|
||||
await updateRssFeed(input.id, { isActive: input.isActive });
|
||||
return { success: true };
|
||||
}),
|
||||
|
||||
// Lire les paramètres globaux RSS
|
||||
getSettings: protectedProcedure.query(async () => {
|
||||
return getRssSettings();
|
||||
}),
|
||||
|
||||
// Sauvegarder les paramètres globaux RSS
|
||||
saveSettings: adminProcedure
|
||||
.input(z.object({
|
||||
fetchIntervalMinutes: z.number().int().min(5).max(10080).optional(),
|
||||
scheduledTime: z.string().regex(/^\d{2}:\d{2}$/, "Format HH:MM requis").optional(),
|
||||
fetchMode: z.enum(["interval", "scheduled"]).optional(),
|
||||
autoFetchEnabled: z.boolean().optional(),
|
||||
}))
|
||||
.mutation(async ({ input }) => {
|
||||
await saveRssSettings(input);
|
||||
return { success: true };
|
||||
}),
|
||||
}),
|
||||
});
|
||||
export type AppRouter = typeof appRouter;
|
||||
|
||||
Reference in New Issue
Block a user