import { getActiveBlocklistDomains, getUserCustomDomains, } from "../../db/domains"; /** * GET /api/blocklist/personal * Query: ?format=hosts|ublock|dns|json (default: hosts) */ export default defineEventHandler(async (event) => { const user = await requireUser(event); const query = getQuery(event); const format = (query.format as string) ?? "hosts"; const [globalDomains, userDomains] = await Promise.all([ getActiveBlocklistDomains(), getUserCustomDomains(user.id), ]); const allDomains = new Set(); for (const d of globalDomains) allDomains.add(d.domain); for (const d of userDomains) allDomains.add(d.domain); const domains = [...allDomains].sort(); const timestamp = new Date().toISOString(); const header = `# Rebreak Personal Blocklist\n# User: ${user.id}\n# Generated: ${timestamp}\n# Total: ${domains.length} domains\n# https://rebreak.app\n\n`; if (format === "json") { return { total: domains.length, global: globalDomains.length, custom: userDomains.length, domains, generated: timestamp, }; } let content = header; switch (format) { case "hosts": content += domains.map((d) => `0.0.0.0 ${d}`).join("\n"); setResponseHeader(event, "content-type", "text/plain; charset=utf-8"); setResponseHeader( event, "content-disposition", 'attachment; filename="rebreak-personal-hosts.txt"', ); break; case "ublock": content += domains.map((d) => `||${d}^`).join("\n"); setResponseHeader(event, "content-type", "text/plain; charset=utf-8"); setResponseHeader( event, "content-disposition", 'attachment; filename="rebreak-personal-ublock.txt"', ); break; case "dns": content += domains.join("\n"); setResponseHeader(event, "content-type", "text/plain; charset=utf-8"); setResponseHeader( event, "content-disposition", 'attachment; filename="rebreak-personal-dns.txt"', ); break; default: content += domains.map((d) => `0.0.0.0 ${d}`).join("\n"); setResponseHeader(event, "content-type", "text/plain; charset=utf-8"); } setResponseHeader(event, "cache-control", "private, max-age=3600"); return content; });