(url: string)
| 256 | if (daysToExpire < 45 && !isLongTerm) { |
| 257 | return { isSingle: true, isLongTerm: false, resetInfo: "单次订阅,无重置", daysToReset: daysToExpire }; |
| 258 | } |
| 259 | |
| 260 | // 计算下次重置日 (基于过期日期的日份) |
| 261 | const resetDay = expireTime.getDate(); |
| 262 | const current = new Date(); |
| 263 | |
| 264 | let nextReset = new Date(current.getFullYear(), current.getMonth(), resetDay, 0, 0, 0); |
| 265 | |
| 266 | if (nextReset.getTime() < Date.now()) { |
| 267 | nextReset = new Date(current.getFullYear(), current.getMonth() + 1, resetDay, 0, 0, 0); |
| 268 | } |
| 269 | |
| 270 | const daysToReset = Math.max(1, Math.floor((nextReset.getTime() / 1000 - now) / 86400)); |
| 271 | |
| 272 | return { isSingle: false, isLongTerm, resetInfo: `每月${resetDay}日`, daysToReset }; |
| 273 | } |
| 274 | |
| 275 | // 分割Telegram长消息 |
| 276 | function splitLongMessage(text: string, maxLength = 4000): string[] { |
| 277 | if (text.length <= maxLength) return [text]; |
| 278 | const ret: string[] = []; |
| 279 | let current = ''; |
| 280 | for (const line of text.split('\n')) { |
| 281 | if (current.length + line.length + 1 > maxLength) { |
| 282 | if (current) ret.push(current); |
| 283 | current = line; |
| 284 | } else { |
| 285 | current += (current ? '\n' : '') + line; |
| 286 | } |
| 287 | } |
| 288 | if (current) ret.push(current); |
| 289 | return ret; |
| 290 | } |
| 291 | |
| 292 | // 尝试获取机场官网和网站标题 |
| 293 | async function getWebsiteInfo(url: string): Promise<{ website: string | null; websiteName: string | null }> { |
| 294 | try { |
| 295 | const urlMatch = url.match(/(https?:\/\/)([^/]+)/); |
| 296 | if (!urlMatch) return { website: null, websiteName: null }; |
| 297 | const baseUrl = urlMatch[1] + urlMatch[2]; |
| 298 |
no test coverage detected