texttv-api
v0.1.0
Published
Type-safe client for SVT Text-TV API (texttv.nu)
Maintainers
Readme
texttv-api
Type-safe TypeScript client for SVT Text-TV API (texttv.nu).
1. Vad är detta?
texttv-api är ett TypeScript-bibliotek för att hämta data från Sveriges Televisions (SVT) Text-TV via det inofficiella API:et på texttv.nu.
Funktioner:
- Full TypeScript-support med strikt typning
- Zero runtime dependencies (använder native Fetch API)
- Automatisk cache-busting för färsk data
- Request timeout och cancellation via AbortSignal
- Sök i sidinnehåll
- Stöd för både HTML- och plaintext-innehåll
- Fungerar i Node.js 18+, webbläsare och React Native
2. Hur fungerar det?
Arkitektur
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Din App │────▶│ TextTVClient │────▶│ texttv.nu API │
│ │ │ │ │ │
│ - getPage() │ │ - Validering │ │ GET /api/get/ │
│ - search() │ │ - Cache-bust │ │ │
│ │ │ - Normalisera │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘Dataflöde
- Request - Klienten bygger URL med sidnummer, app-id och cache-buster
- Validering - Sidnummer valideras (100-899)
- Fetch - Native Fetch API med timeout
- Normalisering - API-svar konverteras från raw-format till typsäkra objekt
- Response - Returnerar
TextTVSubpagemed normaliserade typer
Typnormalisering
API:et returnerar data med inkonsistenta typer som biblioteket normaliserar:
| API returnerar | Biblioteket returnerar |
|----------------|------------------------|
| num: "100" (string) | num: 100 (number) |
| content: ["rad1", "rad2"] (array) | content: "rad1\nrad2" (string) |
| next_page: "101" (string) | next_page: 101 (number) |
3. Källor
API
- texttv.nu API - https://texttv.nu/blogg/texttv-api
- Base URL:
https://api.texttv.nu/api/get
Analyserade implementationer
| Projekt | Språk | Beskrivning | |---------|-------|-------------| | bonny/texttv.nu | JavaScript/React | Produktionsapp för iOS/Android | | antrorsum/texttv | Python | Modern async med Pydantic | | claha/pytexttv | Python | Minimal implementation |
4. Tekniska detaljer
Systemkrav
- Node.js 18+ (native Fetch support)
- TypeScript 5.0+ (för full typ-support)
Projektstruktur
src/
├── index.ts # Publika exports
├── client/
│ ├── index.ts
│ └── TextTVClient.ts # Huvudklient
├── models/
│ ├── index.ts
│ └── types.ts # Typdefinitioner
└── utils/
├── index.ts
├── cache-buster.ts # Cache-busting logik
├── validators.ts # Validering
└── html-parser.ts # HTML-utilitiesTypeScript-konfiguration
Biblioteket använder strikt TypeScript med:
strict: truenoUncheckedIndexedAccess: trueexactOptionalPropertyTypes: true- ESM-output (
"type": "module")
Build & Test
# Installera dependencies
npm install
# Bygg biblioteket
npm run build
# Kör tester
npm test
# Kör exempel
npm run example5. API Endpoints och parametrar
Base URL
https://api.texttv.nu/api/get/{page}URL-parametrar
| Parameter | Typ | Obligatorisk | Beskrivning |
|-----------|-----|--------------|-------------|
| {page} | string | Ja | Sidnummer (100-899) eller intervall (100-104) |
Query-parametrar
| Parameter | Typ | Obligatorisk | Default | Beskrivning |
|-----------|-----|--------------|---------|-------------|
| app | string | Ja | - | Unik app-identifierare (obligatorisk sedan 2015) |
| includePlainTextContent | 0/1 | Nej | 0 | Inkludera plaintext utan HTML |
| cb | string | Nej | - | Cache-buster (valfri tidsstämpel) |
Response-format (Raw API)
// API returnerar array av subpages
[
{
"num": "100", // String (ej number!)
"title": "SVT Text",
"content": ["<span class=\"line\">...</span>"], // Array (ej string!)
"content_plain": ["Rubrik", "Text..."], // Endast med includePlainTextContent=1
"date_updated_unix": 1701523200,
"id": "abc123",
"next_page": "101", // String
"prev_page": "100",
"permalink": "https://texttv.nu/100"
}
]Normaliserat format (Biblioteket)
interface TextTVSubpage {
num: number; // Normaliserad till number
title?: string;
content: string; // Normaliserad till string
content_plain?: string; // Normaliserad till string
date_updated_unix: number;
id: string;
next_page?: number; // Normaliserad till number
prev_page?: number;
}Sidkategorier
| Intervall | Kategori | |-----------|----------| | 100-199 | Nyheter | | 300-399 | Sport | | 400-499 | Ekonomi | | 500-599 | TV-tablå | | 700-799 | Väder |
Kända sidor
| Konstant | Sida | Beskrivning |
|----------|------|-------------|
| TEXTTV_PAGES.NEWS_MAIN | 100 | Huvudnyheter |
| TEXTTV_PAGES.NEWS_DOMESTIC | 101 | Inrikes |
| TEXTTV_PAGES.NEWS_FOREIGN | 104 | Utrikes |
| TEXTTV_PAGES.SPORTS_MAIN | 300 | Sport |
| TEXTTV_PAGES.SPORTS_FOOTBALL | 330 | Fotboll |
| TEXTTV_PAGES.WEATHER_MAIN | 400 | Väder |
| TEXTTV_PAGES.TV1_SCHEDULE | 600 | SVT1 tablå |
| TEXTTV_PAGES.TV2_SCHEDULE | 650 | SVT2 tablå |
6. Användningsområden
Nyhetsappar
Hämta senaste nyheterna från Text-TV för visning i app eller webbplats.
Digital signage
Visa Text-TV-innehåll på informationsskärmar.
Tillgänglighet
Text-TV är lättläst och fungerar bra för skärmläsare.
Dataanalys
Samla och analysera Text-TV-innehåll över tid.
Nostalgi-appar
Återskapa den klassiska Text-TV-upplevelsen.
Automatisering
Övervaka specifika sidor för ändringar.
7. Exempel
Installation
npm install texttv-apiGrundläggande användning
import { TextTVClient, TEXTTV_PAGES } from 'texttv-api';
// Skapa klient (appId är obligatorisk)
const client = new TextTVClient({ appId: 'min-app' });
// Hämta en sida
const news = await client.getPage(TEXTTV_PAGES.NEWS_MAIN);
console.log(news.content);
// Hämta med plaintext
const page = await client.getPage(100, { includePlainText: true });
console.log(page.content_plain);Hämta sidintervall
// Hämta sidor 100-110 parallellt
const pages = await client.getPageRange(100, 110);
pages.forEach((page, pageNum) => {
console.log(`Sida ${pageNum}: ${page.title}`);
});Söka i innehåll
// Sök efter "klimat" i nyhetssidorna
const results = await client.search('klimat', 100, 199, {
includePlainText: true
});
console.log(`Hittade ${results.size} sidor med "klimat"`);
results.forEach((page, num) => {
console.log(`Sida ${num}: ${page.content_plain?.substring(0, 100)}...`);
});Request cancellation
const controller = new AbortController();
// Avbryt efter 5 sekunder
setTimeout(() => controller.abort(), 5000);
try {
const page = await client.getPage(100, { signal: controller.signal });
} catch (error) {
if (error.code === 'TIMEOUT') {
console.log('Request avbröts');
}
}Felhantering
import { TextTVClient, TextTVError, TextTVErrorCode } from 'texttv-api';
try {
const page = await client.getPage(999);
} catch (error) {
if (error instanceof TextTVError) {
switch (error.code) {
case TextTVErrorCode.INVALID_PAGE_NUMBER:
console.log('Ogiltigt sidnummer');
break;
case TextTVErrorCode.PAGE_NOT_FOUND:
console.log('Sidan finns inte');
break;
case TextTVErrorCode.NETWORK_ERROR:
console.log('Nätverksfel');
break;
case TextTVErrorCode.TIMEOUT:
console.log('Timeout');
break;
}
}
}Konfiguration
const client = new TextTVClient({
// Obligatorisk - unik identifierare för din app
appId: 'min-app',
// Valfritt - ändra bas-URL (default: api.texttv.nu)
baseUrl: 'https://api.texttv.nu/api/get',
// Valfritt - request timeout i ms (default: 30000)
timeout: 10000,
// Valfritt - cache-bust intervall i sekunder (default: 15)
cacheBustInterval: 30,
// Valfritt - debug-loggning (default: false)
debug: true,
});Utilities
import {
validatePageNumber,
stripHtml,
extractPageLinks,
formatTimestamp,
getRelativeTime,
getCategoryForPage,
TextTVCategory,
} from 'texttv-api';
// Validera sidnummer
const valid = validatePageNumber('100'); // '100'
const invalid = validatePageNumber('999'); // Throws TextTVError
// Ta bort HTML
const text = stripHtml('<span class="Y">Rubrik</span>'); // 'Rubrik'
// Extrahera sidlänkar
const links = extractPageLinks('<a href="/101">Mer</a>'); // [101]
// Formatera tidsstämpel
const time = formatTimestamp(1701523200); // '2023-12-02 14:00:00'
// Relativ tid
const relative = getRelativeTime(1701523200); // '2 timmar sedan'
// Kategori för sida
const category = getCategoryForPage(100); // TextTVCategory.NEWSTerminal-rendering (CLI)
# Visa sida 100 med ANSI-färger
npx tsx examples/terminal-renderer.ts 100
# Interaktivt läge
npx tsx examples/terminal-renderer.ts -iHTML-rendering (Webb)
Öppna examples/tv-renderer.html i webbläsaren för att se Text-TV med autentisk TV-styling.
API:et returnerar färdig HTML med CSS-klasser:
.bgBl- Blå bakgrund.Y- Gul text.C- Cyan text.DH- Dubbelhöjd
Licens
MIT
Författare
Skapad med hjälp av Claude Code.
Version: 0.1.0 Senast uppdaterad: 2025-12-02
