Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/scheduler publish #3169

Merged
merged 4 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
246 changes: 162 additions & 84 deletions lib/db/getSiteData.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import BLOG from '@/blog.config'
import { getOrSetDataWithCache } from '@/lib/cache/cache_manager'
import { getAllCategories } from '@/lib/notion/getAllCategories'
import getAllPageIds from '@/lib/notion/getAllPageIds'
import { getAllTags } from '@/lib/notion/getAllTags'
Expand All @@ -12,7 +13,6 @@ import { deepClone } from '@/lib/utils'
import { idToUuid } from 'notion-utils'
import { siteConfig } from '../config'
import { extractLangId, extractLangPrefix, getShortId } from '../utils/pageId'
import { getOrSetDataWithCache } from '@/lib/cache/cache_manager'

export { getAllTags } from '../notion/getAllTags'
export { getPost } from '../notion/getNotionPost'
Expand Down Expand Up @@ -230,7 +230,7 @@ async function convertNotionToSiteDate(pageId, from, pageRecordMap) {
// 文章计数
let postCount = 0

// 查找所有的Post和Page
// 查找所有的Post和Page
const allPages = collectionData.filter(post => {
if (post?.type === 'Post' && post.status === 'Published') {
postCount++
Expand Down Expand Up @@ -344,22 +344,53 @@ function handleDataBeforeReturn(db) {
db.allNavPages = cleanPages(db?.allNavPages, db.tagOptions)
db.allPages = cleanPages(db.allPages, db.tagOptions)
db.latestPosts = cleanPages(db.latestPosts, db.tagOptions)

const POST_SCHEDULE_PUBLISH = siteConfig('POST_SCHEDULE_PUBLISH', null, db.NOTION_CONFIG)
if(POST_SCHEDULE_PUBLISH){

const POST_SCHEDULE_PUBLISH = siteConfig(
'POST_SCHEDULE_PUBLISH',
null,
db.NOTION_CONFIG
)
if (POST_SCHEDULE_PUBLISH) {
// console.log('[定时发布] 开启检测')
db.allPages?.forEach(p=>{
// 新特性,判断文章的发布和下架时间,如果不在有效期内则进行下架处理
const publish = isInRange(p.title, p.date)
if (!publish) {
console.log('[定时发布] 隐藏-->', p.title)
// 隐藏
p.status = 'Invisible'
}
})
db.allPages?.forEach(p => {
// 新特性,判断文章的发布和下架时间,如果不在有效期内则进行下架处理
const publish = isInRange(p.title, p.date)
if (!publish) {
const currentTimestamp = Date.now()
const startTimestamp = getTimestamp(
p.date.start_date,
p.date.start_time,
p.date.time_zone
)
const endTimestamp = getTimestamp(
p.date.end_date,
p.date.end_time,
p.date.time_zone
)
console.log(
'[定时发布] 隐藏--> 文章:',
p.title,
'当前时间戳:',
currentTimestamp,
'目标时间戳:',
startTimestamp,
'-',
endTimestamp
)
console.log(
'[定时发布] 隐藏--> 文章:',
p.title,
'当前时间:',
new Date(),
'目标时间:',
p.date
)
// 隐藏
p.status = 'Invisible'
}
})
}


return db
}

Expand Down Expand Up @@ -620,78 +651,125 @@ function getSiteInfo({ collection, block, NOTION_CONFIG }) {

/**
* 判断文章是否在发布时间内
* @param {*} param0
* @returns
* @param {string} title - 文章标题
* @param {Object} date - 时间范围参数
* @param {string} date.start_date - 开始日期(格式:YYYY-MM-DD)
* @param {string} date.start_time - 开始时间(可选,格式:HH:mm)
* @param {string} date.end_date - 结束日期(格式:YYYY-MM-DD)
* @param {string} date.end_time - 结束时间(可选,格式:HH:mm)
* @param {string} date.time_zone - 时区(IANA格式,如 "Asia/Shanghai")
* @returns {boolean} 是否在范围内
*/
function isInRange(title, date = {}) {
const { start_date, start_time, end_date, end_time, time_zone } = date;

// 默认使用北京时间 (Asia/Shanghai)
const effectiveTimeZone = time_zone || "Asia/Shanghai";

// 辅助函数:根据时区和日期时间字符串创建 Date 对象
function parseDateTime(date, time, timeZone) {
if (!date) return null; // 如果没有日期,返回 null
const dateTimeString = `${date}T${time || "00:00"}:00`; // 默认时间为 00:00
// 创建时区正确的 Date 对象
return new Date(
new Date(dateTimeString).toLocaleString("en-US", { timeZone })
);
}

// 获取当前时间(基于目标时区)
function getCurrentDateTimeInZone(timeZone) {
const now = new Date();
const localString = now.toLocaleString("en-US", { timeZone });
return new Date(localString);
}

// 获取当前时间(转换为目标时区)
const currentDateTimeInZone = getCurrentDateTimeInZone(effectiveTimeZone);

// 判断开始时间范围
let startDateTime = null;
if (start_date) {
startDateTime = parseDateTime(start_date, start_time, effectiveTimeZone);
}

// 判断结束时间范围
let endDateTime = null;
if (end_date) {
endDateTime = parseDateTime(end_date, end_time || "23:59", effectiveTimeZone);
}

let isInRange = true;

// 检查是否在开始时间之后
if (startDateTime && currentDateTimeInZone < startDateTime) {
isInRange = false;
console.log(
"[定时发布] 未到发布时间:",
title,
"指定时间:",
startDateTime,
"当前时间:",
currentDateTimeInZone
);
}

// 检查是否在结束时间之前
if (endDateTime && currentDateTimeInZone > endDateTime) {
isInRange = false;
console.log(
"[定时发布] 超过下架时间:",
title,
"指定时间:",
endDateTime,
"当前时间:",
currentDateTimeInZone
);
}

return isInRange; // 如果都符合条件,返回 true
const {
start_date,
start_time = '00:00',
end_date,
end_time = '23:59',
time_zone = 'Asia/Shanghai'
} = date

// 获取当前时间的时间戳(基于目标时区)
const currentTimestamp = Date.now()

// 获取开始和结束时间的时间戳
const startTimestamp = getTimestamp(start_date, start_time, time_zone)
const endTimestamp = getTimestamp(end_date, end_time, time_zone)

// 判断是否在范围内
if (startTimestamp && currentTimestamp < startTimestamp) {
return false
}


if (endTimestamp && currentTimestamp > endTimestamp) {
return false
}

return true
}

/**
* 将指定时区的日期字符串转换为 UTC 时间
* @param {string} dateStr - 日期字符串,格式为 YYYY-MM-DD HH:mm:ss
* @param {string} timeZone - 时区名称(如 "Asia/Shanghai")
* @returns {Date} - 转换后的 Date 对象(UTC 时间)
*/
function convertToUTC(dateStr, timeZone) {
// 维护一个时区偏移映射(以小时为单位)
const timeZoneOffsets = {
// UTC 基础
UTC: 0,
'Etc/GMT': 0,
'Etc/GMT+0': 0,

// 亚洲地区
'Asia/Shanghai': 8, // 中国
'Asia/Tokyo': 9, // 日本
'Asia/Seoul': 9, // 韩国
'Asia/Kolkata': 5.5, // 印度
'Asia/Jakarta': 7, // 印尼
'Asia/Singapore': 8, // 新加坡
'Asia/Hong_Kong': 8, // 香港
'Asia/Bangkok': 7, // 泰国

// 欧洲地区
'Europe/London': 0, // 英国(GMT)
'Europe/Paris': 1, // 法国(CET)
'Europe/Berlin': 1, // 德国
'Europe/Moscow': 3, // 俄罗斯
'Europe/Amsterdam': 1, // 荷兰

// 美洲地区
'America/New_York': -5, // 美国东部(EST)
'America/Chicago': -6, // 美国中部(CST)
'America/Denver': -7, // 美国山区时间(MST)
'America/Los_Angeles': -8, // 美国西部(PST)
'America/Sao_Paulo': -3, // 巴西
'America/Argentina/Buenos_Aires': -3, // 阿根廷

// 非洲地区
'Africa/Johannesburg': 2, // 南非
'Africa/Cairo': 2, // 埃及
'Africa/Nairobi': 3, // 肯尼亚

// 大洋洲地区
'Australia/Sydney': 10, // 澳大利亚东部
'Australia/Perth': 8, // 澳大利亚西部
'Pacific/Auckland': 13, // 新西兰
'Pacific/Fiji': 12, // 斐济

// 中东地区
'Asia/Dubai': 4, // 阿联酋
'Asia/Tehran': 3.5, // 伊朗
'Asia/Riyadh': 3, // 沙特阿拉伯

// 北极与南极
'Antarctica/Palmer': -3, // 南极洲帕尔默
'Antarctica/McMurdo': 13 // 南极洲麦克默多
}

// 获取目标时区的偏移量(以小时为单位)
const offsetHours = timeZoneOffsets[timeZone]
if (offsetHours === undefined) {
throw new Error(`Unsupported time zone: ${timeZone}`)
}

// 将日期字符串转换为本地时间的 Date 对象
const localDate = new Date(`${dateStr.replace(' ', 'T')}Z`)
if (isNaN(localDate.getTime())) {
throw new Error(`Invalid date string: ${dateStr}`)
}

// 计算 UTC 时间的时间戳
const utcTimestamp = localDate.getTime() - offsetHours * 60 * 60 * 1000
return new Date(utcTimestamp)
}

// 辅助函数:生成指定日期时间的时间戳(基于目标时区)
function getTimestamp(date, time, time_zone) {
if (!date) return null
return convertToUTC(`${date} ${time}:00`, time_zone).getTime()
}

/**
* 获取导航用的精减文章列表
Expand Down
4 changes: 2 additions & 2 deletions styles/notion.css
Original file line number Diff line number Diff line change
Expand Up @@ -1682,8 +1682,8 @@ code[class*='language-'] {
color: inherit;
}

svg.notion-page-icon {
/* @apply hidden;*/
notion-callout svg.notion-page-icon {
@apply hidden;
}

svg + .notion-page-title-text {
Expand Down
Loading