mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-01 14:57:14 +08:00
feat(route): wellcee (#15433)
This commit is contained in:
@@ -4,13 +4,13 @@ import { parseDate } from '@/utils/parse-date';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/',
|
||||
example: '/weekendhk',
|
||||
radar: [
|
||||
{
|
||||
source: ['weekendhk.com/'],
|
||||
target: '',
|
||||
},
|
||||
],
|
||||
name: 'Unknown',
|
||||
name: '最新文章',
|
||||
maintainers: ['TonyRL'],
|
||||
handler,
|
||||
url: 'weekendhk.com/',
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { Namespace } from '@/types';
|
||||
|
||||
export const namespace: Namespace = {
|
||||
name: 'Wellcee 唯心所寓',
|
||||
url: 'wellcee.com',
|
||||
categories: ['other'],
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
import { Route } from '@/types';
|
||||
import type { Context } from 'hono';
|
||||
import { District, House } from './types';
|
||||
|
||||
import ofetch from '@/utils/ofetch';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { baseUrl, getCitys, getDistricts } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { art } from '@/utils/render';
|
||||
import path from 'path';
|
||||
import { getCurrentPath } from '@/utils/helpers';
|
||||
|
||||
const __dirname = getCurrentPath(import.meta.url);
|
||||
const render = (data) => art(path.join(__dirname, 'templates', 'house.art'), data);
|
||||
|
||||
export const route: Route = {
|
||||
path: '/rent/:city/:district?',
|
||||
example: '/wellcee/rent/北京',
|
||||
parameters: {
|
||||
city: '城市',
|
||||
district: '地区',
|
||||
},
|
||||
name: '租房信息',
|
||||
maintainers: ['TonyRL'],
|
||||
handler,
|
||||
url: 'www.wellcee.com',
|
||||
description: '支持的城市可以通过 [/wellcee/support-city](https://rsshub.app/wellcee/support-city) 获取',
|
||||
};
|
||||
|
||||
async function handler(ctx: Context) {
|
||||
const { city, district = '' } = ctx.req.param();
|
||||
const citys = await getCitys();
|
||||
const cityInfo = citys.find((item) => item.chCityName === city);
|
||||
if (!cityInfo) {
|
||||
throw new InvalidParameterError('Invalid city');
|
||||
}
|
||||
|
||||
let districtInfo: District | undefined;
|
||||
if (district) {
|
||||
const districts = await getDistricts(cityInfo.id);
|
||||
const d = districts.find((item) => item.name === district);
|
||||
if (!d) {
|
||||
throw new InvalidParameterError('Invalid district');
|
||||
}
|
||||
districtInfo = d;
|
||||
}
|
||||
|
||||
const response = await ofetch(`${baseUrl}/api/house/filter`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
districtIds: districtInfo?.id ? [districtInfo.id] : [],
|
||||
subways: [],
|
||||
rentTypeIds: [],
|
||||
timeTypeIds: [],
|
||||
price: [],
|
||||
tagTypeIds: [],
|
||||
cityId: cityInfo.id,
|
||||
lang: 1,
|
||||
pn: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const items = (response.data.list as House[]).map((item) => ({
|
||||
title: item.address,
|
||||
link: `${baseUrl}/rent-apartment/${item.id}`,
|
||||
description: render({ item }),
|
||||
pubDate: parseDate(item.loginTime, 'X'),
|
||||
author: item.userInfo.name,
|
||||
category: [...item.tags, ...item.typeTags],
|
||||
}));
|
||||
|
||||
return {
|
||||
title: `${city}${districtInfo?.name ?? ''}租房信息 - Wellcee`,
|
||||
description: `${cityInfo.statics.online_text} ${cityInfo.statics.total_text}`,
|
||||
image: cityInfo.icon,
|
||||
icon: cityInfo.icon,
|
||||
logo: cityInfo.icon,
|
||||
link: `${baseUrl}/rent-apartment/${cityInfo.cityName}/list?cityId=${cityInfo.id}&lang=zh${district ? `#districtIds=${districtInfo?.id}` : ''}`,
|
||||
item: items,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Route } from '@/types';
|
||||
import type { Context } from 'hono';
|
||||
|
||||
import { baseUrl, getCitys, getDistricts } from './utils';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/support-city',
|
||||
example: '/wellcee/support-city',
|
||||
name: '支持的城市',
|
||||
maintainers: ['TonyRL'],
|
||||
radar: [
|
||||
{
|
||||
source: ['www.wellcee.com'],
|
||||
},
|
||||
],
|
||||
handler,
|
||||
url: 'www.wellcee.com',
|
||||
};
|
||||
|
||||
async function handler(ctx: Context) {
|
||||
const citys = await getCitys();
|
||||
|
||||
const list = await Promise.all(
|
||||
citys.map(async (city) => ({
|
||||
...city,
|
||||
district: await getDistricts(city.id),
|
||||
}))
|
||||
);
|
||||
const requestHost = new URL(ctx.req.url).host;
|
||||
|
||||
const items = list.flatMap((city) =>
|
||||
city.district.map((district) => ({
|
||||
title: `${city.chCityName} - ${district.name}`,
|
||||
description: `${city.chCityName} - ${district.name}`,
|
||||
link: `https://${requestHost}/wellcee/rent/${city.chCityName}/${district.name}`,
|
||||
}))
|
||||
);
|
||||
|
||||
return {
|
||||
title: '支持的城市 - Wellcee',
|
||||
description:
|
||||
'上海国际化租房平台|北京合租&找室友|香港留学生租房|深圳无中介租房|广州外国人租房 |杭州高品质租房|成都房东直租;同志友好&宠物友好;Wellcee 的生活方式:社交|活动|交友|美食|宠物领养|音乐&艺术;Wellcee 的二手市集:家居|电子|奢侈品|时尚。',
|
||||
link: baseUrl,
|
||||
item: items,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
租金: {{ item.rent }}<br>
|
||||
{{ if item.dailyRent }}
|
||||
日租: {{ item.dailyRent }}<br>
|
||||
{{ /if }}
|
||||
<br>
|
||||
|
||||
{{ if item.video }}
|
||||
<video controls preload="metadata" poster="{{ item.video }}?vframe/png/offset/0">
|
||||
<source src="{{ item.video }}" type="video/mp4">
|
||||
</video>
|
||||
<br>
|
||||
{{ /if }}
|
||||
|
||||
{{ if item.imgs }}
|
||||
{{ each item.imgs img }}
|
||||
<img src="{{ img }}"><br>
|
||||
{{ /each }}
|
||||
{{ /if }}
|
||||
@@ -0,0 +1,58 @@
|
||||
export interface City {
|
||||
id: string;
|
||||
icon: string;
|
||||
city: string;
|
||||
enCityName: string;
|
||||
cityName: string;
|
||||
chCityName: string;
|
||||
twCityName: string;
|
||||
statics: {
|
||||
total_text: string;
|
||||
online_text: string;
|
||||
total_count: number;
|
||||
online_count: number;
|
||||
};
|
||||
district: District[];
|
||||
}
|
||||
|
||||
export interface District {
|
||||
id: string;
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
name: string;
|
||||
business: {
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface House {
|
||||
id: string;
|
||||
imgs: string[];
|
||||
ev: number;
|
||||
city: string;
|
||||
district: string;
|
||||
tagsText: string;
|
||||
tags: string[];
|
||||
typeTags: string[];
|
||||
rent: string;
|
||||
video: string;
|
||||
personalDesc: string;
|
||||
address: string;
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
collectNum: number;
|
||||
isCollect: boolean;
|
||||
userInfo: {
|
||||
id: string;
|
||||
name: string;
|
||||
gender: number;
|
||||
avatar: string;
|
||||
language: string[];
|
||||
loginTime: string;
|
||||
tenant_status: number;
|
||||
landlord_status: number;
|
||||
};
|
||||
loginTime: number;
|
||||
dailyRent: string;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { City, District } from './types';
|
||||
|
||||
import ofetch from '@/utils/ofetch';
|
||||
import cache from '@/utils/cache';
|
||||
import { config } from '@/config';
|
||||
|
||||
export const baseUrl = 'https://www.wellcee.com';
|
||||
export const getCitys = () =>
|
||||
cache.tryGet(
|
||||
'wellcee:citys',
|
||||
async () => {
|
||||
const response = await ofetch(`${baseUrl}/api/home/index`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
lang: '1',
|
||||
userId: '',
|
||||
type: '1',
|
||||
}).toString(),
|
||||
});
|
||||
|
||||
return response.data.citys;
|
||||
},
|
||||
config.cache.routeExpire,
|
||||
false
|
||||
) as Promise<City[]>;
|
||||
|
||||
export const getDistricts = (cityId: string) =>
|
||||
cache.tryGet(
|
||||
`wellcee:city:${cityId}`,
|
||||
async () => {
|
||||
const response = await ofetch(`${baseUrl}/api/house/filterType`, {
|
||||
query: {
|
||||
cityId,
|
||||
lang: '1',
|
||||
},
|
||||
});
|
||||
|
||||
return response.data.district;
|
||||
},
|
||||
config.cache.routeExpire,
|
||||
false
|
||||
) as Promise<District[]>;
|
||||
Reference in New Issue
Block a user