Files
PolyWeather/frontend/lib/dashboard-official-sources.ts
T

759 lines
18 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { CityDetail } from "@/lib/dashboard-types";
import { normalizeObservationSourceLabel } from "@/lib/source-labels";
export type OfficialSourceLink = {
label: string;
href: string;
kind: "agency" | "airport" | "metar";
};
function buildJmaAmedasTenMinuteUrl(
localDate?: string | null,
options?: {
blockNo?: string;
precNo?: string;
},
) {
const blockNo = String(options?.blockNo || "0371").trim() || "0371";
const precNo = String(options?.precNo || "44").trim() || "44";
const match = String(localDate || "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
const now = new Date();
const year = match?.[1] || String(now.getFullYear());
const month = match?.[2] || String(now.getMonth() + 1).padStart(2, "0");
const day = match?.[3] || String(now.getDate()).padStart(2, "0");
return `https://www.data.jma.go.jp/stats/etrn/view/10min_a1.php?prec_no=${encodeURIComponent(precNo)}&block_no=${encodeURIComponent(blockNo)}&year=${encodeURIComponent(year)}&month=${encodeURIComponent(month)}&day=${encodeURIComponent(day)}&view=`;
}
const CITY_SPECIFIC_SOURCES: Record<string, OfficialSourceLink[]> = {
singapore: [
{
label: "MSS 官方天气",
href: "https://www.weather.gov.sg/",
kind: "agency",
},
{
label: "樟宜机场",
href: "https://www.changiairport.com/",
kind: "airport",
},
{
label: "WSSS METAR",
href: "https://aviationweather.gov/data/metar/?id=WSSS&decoded=1&taf=1",
kind: "metar",
},
],
wellington: [
{
label: "MetService",
href: "https://www.metservice.com/",
kind: "agency",
},
{
label: "Wellington Airport",
href: "https://www.wellingtonairport.co.nz/",
kind: "airport",
},
{
label: "NZWN METAR",
href: "https://aviationweather.gov/data/metar/?id=NZWN&decoded=1&taf=1",
kind: "metar",
},
],
"hong kong": [
{
label: "香港天文台",
href: "https://www.hko.gov.hk/en/index.html",
kind: "agency",
},
{
label: "香港国际机场",
href: "https://www.hongkongairport.com/",
kind: "airport",
},
{
label: "VHHH METAR",
href: "https://aviationweather.gov/data/metar/?id=VHHH&decoded=1&taf=1",
kind: "metar",
},
{
label: "深圳站(HKO",
href: "https://www.hko.gov.hk/sc/wxinfo/ts/index.htm",
kind: "agency",
},
],
"shenzhen": [
{
label: "香港天文台",
href: "https://www.hko.gov.hk/en/index.html",
kind: "agency",
},
{
label: "深圳站(HKO",
href: "https://www.hko.gov.hk/sc/wxinfo/ts/index.htm",
kind: "airport",
},
],
taipei: [
{
label: "Wunderground RCSS",
href: "https://www.wunderground.com/history/daily/tw/taipei/RCSS",
kind: "agency",
},
{
label: "台北松山机场",
href: "https://www.tsa.gov.tw/?lang=en",
kind: "airport",
},
{
label: "RCSS METAR",
href: "https://aviationweather.gov/data/metar/?id=RCSS&decoded=1&taf=1",
kind: "metar",
},
],
busan: [
{
label: "Wunderground RKPK",
href: "https://www.wunderground.com/history/daily/kr/busan/RKPK",
kind: "agency",
},
{
label: "金海国际机场",
href: "https://www.airport.co.kr/gimhaeeng/index.do",
kind: "airport",
},
{
label: "RKPK METAR",
href: "https://aviationweather.gov/data/metar/?id=RKPK&decoded=1&taf=1",
kind: "metar",
},
],
manila: [
{
label: "Wunderground RPLL",
href: "https://www.wunderground.com/history/daily/ph/manila/RPLL",
kind: "agency",
},
{
label: "Ninoy Aquino International Airport",
href: "https://www.newnaia.com.ph/",
kind: "airport",
},
{
label: "RPLL METAR",
href: "https://aviationweather.gov/data/metar/?id=RPLL&decoded=1&taf=1",
kind: "metar",
},
],
karachi: [
{
label: "Wunderground OPKC",
href: "https://www.wunderground.com/history/daily/pk/karachi/OPKC",
kind: "agency",
},
{
label: "Jinnah International Airport",
href: "https://www.caapakistan.com.pk/",
kind: "airport",
},
{
label: "OPKC METAR",
href: "https://aviationweather.gov/data/metar/?id=OPKC&decoded=1&taf=1",
kind: "metar",
},
],
istanbul: [
{
label: "MGM",
href: "https://www.mgm.gov.tr/?il=Istanbul&ilce=Istanbul%20Havalimani",
kind: "agency",
},
{
label: "NOAA LTFM Timeseries",
href: "https://www.weather.gov/wrh/timeseries?site=LTFM",
kind: "agency",
},
{
label: "Istanbul Airport",
href: "https://www.istairport.com/en",
kind: "airport",
},
{
label: "LTFM METAR",
href: "https://aviationweather.gov/data/metar/?id=LTFM&decoded=1&taf=1",
kind: "metar",
},
],
moscow: [
{
label: "NOAA UUWW Timeseries",
href: "https://www.weather.gov/wrh/timeseries?site=UUWW",
kind: "agency",
},
{
label: "Vnukovo International Airport",
href: "https://vnukovo.ru/en/",
kind: "airport",
},
{
label: "UUWW METAR",
href: "https://metar-taf.com/UUWW",
kind: "metar",
},
],
london: [
{
label: "Met Office",
href: "https://www.metoffice.gov.uk/",
kind: "agency",
},
{
label: "EGLC METAR",
href: "https://aviationweather.gov/data/metar/?id=EGLC&decoded=1&taf=1",
kind: "metar",
},
],
"new york": [
{
label: "NWS",
href: "https://www.weather.gov/",
kind: "agency",
},
{
label: "KLGA METAR",
href: "https://aviationweather.gov/data/metar/?id=KLGA&decoded=1&taf=1",
kind: "metar",
},
],
"los angeles": [
{
label: "NWS Los Angeles/Oxnard",
href: "https://www.weather.gov/lox/",
kind: "agency",
},
{
label: "LAX Airport",
href: "https://www.flylax.com/",
kind: "airport",
},
{
label: "KLAX METAR",
href: "https://aviationweather.gov/data/metar/?id=KLAX&decoded=1&taf=1",
kind: "metar",
},
],
"san francisco": [
{
label: "NWS San Francisco Bay Area",
href: "https://www.weather.gov/mtr/",
kind: "agency",
},
{
label: "SFO Airport",
href: "https://www.flysfo.com/",
kind: "airport",
},
{
label: "KSFO METAR",
href: "https://aviationweather.gov/data/metar/?id=KSFO&decoded=1&taf=1",
kind: "metar",
},
],
denver: [
{
label: "NWS Denver/Boulder",
href: "https://www.weather.gov/bou/",
kind: "agency",
},
{
label: "Buckley Space Force Base",
href: "https://www.buckley.spaceforce.mil/",
kind: "airport",
},
{
label: "KBKF METAR",
href: "https://aviationweather.gov/data/metar/?id=KBKF&decoded=1&taf=1",
kind: "metar",
},
],
austin: [
{
label: "NWS Austin/San Antonio",
href: "https://www.weather.gov/ewx/",
kind: "agency",
},
{
label: "Austin-Bergstrom Airport",
href: "https://www.austintexas.gov/airport",
kind: "airport",
},
{
label: "KAUS METAR",
href: "https://aviationweather.gov/data/metar/?id=KAUS&decoded=1&taf=1",
kind: "metar",
},
],
houston: [
{
label: "NWS Houston/Galveston",
href: "https://www.weather.gov/hgx/",
kind: "agency",
},
{
label: "William P. Hobby Airport",
href: "https://www.fly2houston.com/hobby",
kind: "airport",
},
{
label: "KHOU METAR",
href: "https://aviationweather.gov/data/metar/?id=KHOU&decoded=1&taf=1",
kind: "metar",
},
],
"mexico city": [
{
label: "SMN",
href: "https://smn.conagua.gob.mx/",
kind: "agency",
},
{
label: "AICM",
href: "https://www.aicm.com.mx/",
kind: "airport",
},
{
label: "MMMX METAR",
href: "https://aviationweather.gov/data/metar/?id=MMMX&decoded=1&taf=1",
kind: "metar",
},
],
ankara: [
{
label: "MGM",
href: "https://www.mgm.gov.tr/?il=Ankara&ilce=Esenboga",
kind: "agency",
},
{
label: "LTAC METAR",
href: "https://aviationweather.gov/data/metar/?id=LTAC&decoded=1&taf=1",
kind: "metar",
},
],
paris: [
{
label: "Météo-France",
href: "https://meteofrance.com/",
kind: "agency",
},
{
label: "LFPB METAR",
href: "https://aviationweather.gov/data/metar/?id=LFPB&decoded=1&taf=1",
kind: "metar",
},
],
seoul: [
{
label: "KMA",
href: "https://www.weather.go.kr/",
kind: "agency",
},
{
label: "RKSI METAR",
href: "https://aviationweather.gov/data/metar/?id=RKSI&decoded=1&taf=1",
kind: "metar",
},
],
shanghai: [
{
label: "NMC 浦东天气",
href: "https://m.nmc.cn/publish/forecast/ASH/pudong.html",
kind: "agency",
},
{
label: "上海浦东国际机场",
href: "https://www.shanghai-airport.com/",
kind: "airport",
},
{
label: "ZSPD METAR",
href: "https://aviationweather.gov/data/metar/?id=ZSPD&decoded=1&taf=1",
kind: "metar",
},
],
tokyo: [
{
label: "JMA 羽田10分钟实况",
href: "",
kind: "agency",
},
{
label: "RJTT METAR",
href: "https://aviationweather.gov/data/metar/?id=RJTT&decoded=1&taf=1",
kind: "metar",
},
],
"tel aviv": [
{
label: "IMS",
href: "https://ims.gov.il/en",
kind: "agency",
},
{
label: "LLBG METAR",
href: "https://aviationweather.gov/data/metar/?id=LLBG&decoded=1&taf=1",
kind: "metar",
},
],
toronto: [
{
label: "Environment Canada",
href: "https://weather.gc.ca/",
kind: "agency",
},
{
label: "CYYZ METAR",
href: "https://aviationweather.gov/data/metar/?id=CYYZ&decoded=1&taf=1",
kind: "metar",
},
],
"buenos aires": [
{
label: "SMN",
href: "https://www.smn.gob.ar/",
kind: "agency",
},
{
label: "SAEZ METAR",
href: "https://aviationweather.gov/data/metar/?id=SAEZ&decoded=1&taf=1",
kind: "metar",
},
],
chicago: [
{
label: "NWS Chicago",
href: "https://www.weather.gov/lot/",
kind: "agency",
},
{
label: "KORD METAR",
href: "https://aviationweather.gov/data/metar/?id=KORD&decoded=1&taf=1",
kind: "metar",
},
],
dallas: [
{
label: "NWS Fort Worth",
href: "https://www.weather.gov/fwd/",
kind: "agency",
},
{
label: "KDAL METAR",
href: "https://aviationweather.gov/data/metar/?id=KDAL&decoded=1&taf=1",
kind: "metar",
},
],
miami: [
{
label: "NWS Miami",
href: "https://www.weather.gov/mfl/",
kind: "agency",
},
{
label: "KMIA METAR",
href: "https://aviationweather.gov/data/metar/?id=KMIA&decoded=1&taf=1",
kind: "metar",
},
],
atlanta: [
{
label: "NWS Peachtree City",
href: "https://www.weather.gov/ffc/",
kind: "agency",
},
{
label: "KATL METAR",
href: "https://aviationweather.gov/data/metar/?id=KATL&decoded=1&taf=1",
kind: "metar",
},
],
seattle: [
{
label: "NWS Seattle",
href: "https://www.weather.gov/sew/",
kind: "agency",
},
{
label: "KSEA METAR",
href: "https://aviationweather.gov/data/metar/?id=KSEA&decoded=1&taf=1",
kind: "metar",
},
],
lucknow: [
{
label: "IMD",
href: "https://mausam.imd.gov.in/",
kind: "agency",
},
{
label: "VILK METAR",
href: "https://aviationweather.gov/data/metar/?id=VILK&decoded=1&taf=1",
kind: "metar",
},
],
"sao paulo": [
{
label: "INMET",
href: "https://portal.inmet.gov.br/",
kind: "agency",
},
{
label: "SBGR METAR",
href: "https://aviationweather.gov/data/metar/?id=SBGR&decoded=1&taf=1",
kind: "metar",
},
],
munich: [
{
label: "DWD",
href: "https://www.dwd.de/EN/Home/home_node.html",
kind: "agency",
},
{
label: "EDDM METAR",
href: "https://aviationweather.gov/data/metar/?id=EDDM&decoded=1&taf=1",
kind: "metar",
},
],
milan: [
{
label: "MeteoAM",
href: "https://www.meteoam.it/en/home",
kind: "agency",
},
{
label: "LIMC METAR",
href: "https://aviationweather.gov/data/metar/?id=LIMC&decoded=1&taf=1",
kind: "metar",
},
],
warsaw: [
{
label: "IMGW",
href: "https://meteo.imgw.pl/",
kind: "agency",
},
{
label: "EPWA METAR",
href: "https://aviationweather.gov/data/metar/?id=EPWA&decoded=1&taf=1",
kind: "metar",
},
],
madrid: [
{
label: "AEMET",
href: "https://www.aemet.es/en/portada",
kind: "agency",
},
{
label: "LEMD METAR",
href: "https://aviationweather.gov/data/metar/?id=LEMD&decoded=1&taf=1",
kind: "metar",
},
],
chengdu: [
{
label: "NMC 双流天气",
href: "https://m.nmc.cn/publish/forecast/ASC/shuangliu.html",
kind: "agency",
},
{
label: "成都双流国际机场",
href: "https://www.cdairport.com/",
kind: "airport",
},
{
label: "ZUUU METAR",
href: "https://aviationweather.gov/data/metar/?id=ZUUU&decoded=1&taf=1",
kind: "metar",
},
],
chongqing: [
{
label: "NMC 渝北天气",
href: "https://m.nmc.cn/publish/forecast/ACQ/yubei.html",
kind: "agency",
},
{
label: "重庆江北国际机场",
href: "https://www.cqa.cn/",
kind: "airport",
},
{
label: "ZUCK METAR",
href: "https://aviationweather.gov/data/metar/?id=ZUCK&decoded=1&taf=1",
kind: "metar",
},
],
qingdao: [
{
label: "Wunderground ZSQD",
href: "https://www.wunderground.com/history/daily/cn/qingdao/ZSQD",
kind: "agency",
},
{
label: "青岛胶东国际机场",
href: "https://www.qdairport.com/",
kind: "airport",
},
{
label: "ZSQD METAR",
href: "https://aviationweather.gov/data/metar/?id=ZSQD&decoded=1&taf=1",
kind: "metar",
},
],
"kuala lumpur": [
{
label: "Wunderground WMKK",
href: "https://www.wunderground.com/history/daily/my/sepang-district/WMKK",
kind: "agency",
},
{
label: "吉隆坡国际机场",
href: "https://airports.malaysiaairports.com.my/klia",
kind: "airport",
},
{
label: "WMKK METAR",
href: "https://aviationweather.gov/data/metar/?id=WMKK&decoded=1&taf=1",
kind: "metar",
},
],
jakarta: [
{
label: "Wunderground WIHH",
href: "https://www.wunderground.com/history/daily/id/jakarta/WIHH",
kind: "agency",
},
{
label: "Halim Perdanakusuma Airport",
href: "https://www.angkasapura2.co.id/en/airport/read/HLP",
kind: "airport",
},
{
label: "WIHH METAR",
href: "https://aviationweather.gov/data/metar/?id=WIHH&decoded=1&taf=1",
kind: "metar",
},
],
helsinki: [
{
label: "Wunderground EFHK",
href: "https://www.wunderground.com/history/daily/fi/vantaa/EFHK",
kind: "agency",
},
{
label: "Helsinki Airport",
href: "https://www.finavia.fi/en/airports/helsinki-airport",
kind: "airport",
},
{
label: "EFHK METAR",
href: "https://aviationweather.gov/data/metar/?id=EFHK&decoded=1&taf=1",
kind: "metar",
},
],
amsterdam: [
{
label: "Wunderground EHAM",
href: "https://www.wunderground.com/history/daily/nl/schiphol/EHAM",
kind: "agency",
},
{
label: "Amsterdam Airport Schiphol",
href: "https://www.schiphol.nl/en/",
kind: "airport",
},
{
label: "EHAM METAR",
href: "https://aviationweather.gov/data/metar/?id=EHAM&decoded=1&taf=1",
kind: "metar",
},
],
"panama city": [
{
label: "Wunderground MPMG",
href: "https://www.wunderground.com/history/daily/pa/panama-city/MPMG",
kind: "agency",
},
{
label: "Marcos A. Gelabert Airport",
href: "https://www.aeropuertos.net/aeropuerto-internacional-marcos-a-gelabert/",
kind: "airport",
},
{
label: "MPMG METAR",
href: "https://aviationweather.gov/data/metar/?id=MPMG&decoded=1&taf=1",
kind: "metar",
},
],
beijing: [
{
label: "NMC 顺义天气",
href: "https://m.nmc.cn/publish/forecast/ABJ/shunyi.html",
kind: "agency",
},
{
label: "北京首都国际机场",
href: "https://www.bcia.com.cn/",
kind: "airport",
},
{
label: "ZBAA METAR",
href: "https://aviationweather.gov/data/metar/?id=ZBAA&decoded=1&taf=1",
kind: "metar",
},
],
wuhan: [
{
label: "NMC 武汉天气",
href: "https://m.nmc.cn/publish/forecast/AHB/wuhan.html",
kind: "agency",
},
{
label: "武汉天河国际机场",
href: "https://www.whairport.com/",
kind: "airport",
},
{
label: "ZHHH METAR",
href: "https://aviationweather.gov/data/metar/?id=ZHHH&decoded=1&taf=1",
kind: "metar",
},
],
};
export function getOfficialSourceLinks(detail: CityDetail): OfficialSourceLink[] {
const cityKey = String(detail.name || "").trim().toLowerCase();
const links = [...(CITY_SPECIFIC_SOURCES[cityKey] || [])].map((link) => {
if (cityKey === "tokyo" && link.kind === "agency" && link.label === "JMA 羽田10分钟实况") {
return {
...link,
href: buildJmaAmedasTenMinuteUrl(detail.local_date, {
blockNo: "0371",
precNo: "44",
}),
};
}
return {
...link,
label: normalizeObservationSourceLabel(link.label, link.label),
};
});
const seen = new Set<string>();
return links.filter((link) => {
const key = `${link.label}|${link.href}`;
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}