diff --git a/package.json b/package.json index 0600db4..4df10ae 100644 --- a/package.json +++ b/package.json @@ -9,19 +9,20 @@ "lint": "next lint" }, "dependencies": { + "fuse.js": "^7.1.0", + "next": "15.4.6", "react": "19.1.0", - "react-dom": "19.1.0", - "next": "15.4.6" + "react-dom": "19.1.0" }, "devDependencies": { - "typescript": "^5", + "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "@tailwindcss/postcss": "^4", - "tailwindcss": "^4", "eslint": "^9", "eslint-config-next": "15.4.6", - "@eslint/eslintrc": "^3" + "tailwindcss": "^4", + "typescript": "^5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 897ec77..f9046fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + fuse.js: + specifier: ^7.1.0 + version: 7.1.0 next: specifier: 15.4.6 version: 15.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -1026,6 +1029,10 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + fuse.js@7.1.0: + resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} + engines: {node: '>=10'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -2890,6 +2897,8 @@ snapshots: functions-have-names@1.2.3: {} + fuse.js@7.1.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 diff --git a/src/app/iptv/channel/route.ts b/src/app/iptv/channel/route.ts new file mode 100644 index 0000000..7f325f9 --- /dev/null +++ b/src/app/iptv/channel/route.ts @@ -0,0 +1,60 @@ +import { NextRequest } from "next/server" +import Fuse from "fuse.js" + +type ChannelInfo = { + id: string, + name: string, + alt_names: string[], + network: string | null, + owners: string[], + country: string, + subdivision: string | null, + city: string | null, + categories: string[], + is_nsfw: boolean, + launched: string | null, + closed: string | null, + replaced_by: string | null, + website: string | null +} + +export async function GET(request: NextRequest) { + + const searchParams = request.nextUrl.searchParams + const name = searchParams.get('name') + + if (!name) { + return new Response("Must be supplied with a name to search", { status: 400 }) + } + + const channelResp = await fetch("https://iptv-org.github.io/api/channels.json") + + const channelData: ChannelInfo[] = await channelResp.json() + + const limitedChannelData = channelData.filter(c => ["US", "CA", "UK"].includes(c.country)) + + // const expandedChannelData = channelData.map(c => ({ + // ...c, + // all_names: [c.name, ...c.alt_names] + // })) + + // const filteredChannelData = expandedChannelData.filter(c => c.all_names.includes(name)) + + const fuse = new Fuse(limitedChannelData, { + keys: [ + "name", + "alt_names", + "id" + ], + includeScore: true, + distance: 20 + }) + + const found = fuse.search(name, { limit: 10 }) + + return new Response(JSON.stringify(found), { + headers: { + "Content-Type": "application/json" + } + }) +} \ No newline at end of file