RSSHub/lib/routes/qweather/3days.ts

104 lines
3.9 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 { Route } from '@/types';
import { getCurrentPath } from '@/utils/helpers';
const __dirname = getCurrentPath(import.meta.url);
import cache from '@/utils/cache';
import got from '@/utils/got';
import { art } from '@/utils/render';
import path from 'node:path';
import { config } from '@/config';
import ConfigNotFoundError from '@/errors/types/config-not-found';
const WEATHER_API = 'https://devapi.qweather.com/v7/weather/3d';
const AIR_QUALITY_API = 'https://devapi.qweather.com/v7/air/5d';
const CIRY_LOOKUP_API = 'https://geoapi.qweather.com/v2/city/lookup';
const author = 'QWeather';
export const route: Route = {
path: '/3days/:location',
categories: ['forecast'],
example: '/qweather/3days/广州',
parameters: { location: 'N' },
features: {
requireConfig: [
{
name: 'HEFENG_KEY',
description: '',
},
],
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: '近三天天气',
maintainers: ['Rein-Ou', 'la3rence'],
handler,
description: `需自行注册获取 api 的 key并在环境变量 HEFENG\_KEY 中进行配置,获取订阅近三天天气预报`,
};
async function handler(ctx) {
if (!config.hefeng.key) {
throw new ConfigNotFoundError('QWeather RSS is disabled due to the lack of <a href="https://docs.rsshub.app/zh/install/config#%E5%92%8C%E9%A3%8E%E5%A4%A9%E6%B0%94">relevant config</a>');
}
const id = await cache.tryGet(ctx.req.param('location') + '_id', async () => {
const response = await got(`${CIRY_LOOKUP_API}?location=${ctx.req.param('location')}&key=${config.hefeng.key}`);
return response.data.location[0].id;
});
const weatherData = await cache.tryGet(
ctx.req.param('location'),
async () => {
const response = await got(`${WEATHER_API}?key=${config.hefeng.key}&location=${id}`);
return response.data;
},
config.cache.contentExpire,
false
);
const airQualityData = await cache.tryGet(
`qweather:air:${ctx.req.param('location')}`,
async () => {
const airQualityResponse = await got(`${AIR_QUALITY_API}?location=${id}&key=${config.hefeng.key}`);
return airQualityResponse.data;
},
config.cache.contentExpire,
false
);
// merge weather data with air quality data
const combined = {
updateTime: weatherData.updateTime,
fxLink: weatherData.fxLink,
daily: weatherData.daily.map((weatherItem) => {
const dailyAirQuality = airQualityData.daily.find((airQualityItem) => airQualityItem.fxDate === weatherItem.fxDate);
if (dailyAirQuality) {
return {
...weatherItem,
aqi: dailyAirQuality.aqi,
aqiLevel: dailyAirQuality.level,
aqiCategory: dailyAirQuality.category,
aqiPrimary: dailyAirQuality.primary,
};
}
return weatherItem;
}),
};
const items = combined.daily.map((item) => ({
title: `${item.fxDate}: ${item.textDay === item.textNight ? item.textDay : item.textDay + '转' + item.textNight} ${item.tempMin}~${item.tempMax}`,
description: art(path.join(__dirname, 'templates/3days.art'), {
item,
}),
pubDate: combined.updateTime,
guid: '位置:' + ctx.req.param('location') + '--日期:' + item.fxDate,
link: combined.fxLink,
author,
}));
return {
title: ctx.req.param('location') + '未来三天天气',
description: ctx.req.param('location') + '未来三天天气情况,使用和风彩云 API (包括空气质量)',
item: items,
link: combined.fxLink,
author,
};
}