发布内容原理
发布函数
在 src/components/Sync 文件夹中,有对应不同平台的发布组件,例如 DynamicTab、ArticleTab、VideoTab 等。
它们在组织好发布所需的信息,即 SyncData 类型的数据后,会调用 src/options/index.tsx 文件中的 funcPublish 函数来进行标签页的创建和脚本的注入。
const funcPublish = async (data: SyncData) => {
// 如果平台数组不为空,则创建标签页
if (Array.isArray(data.platforms) && data.platforms.length > 0) {
// 创建标签页
createTabsForPlatforms(data)
.then(async (tabs) => {
// 注入脚本
injectScriptsToTabs(tabs, data);
// 通知标签页管理器新建了新的标签页
// 这里会触发 `src/background/services/tabs.ts` 文件中的 `tabsManagerMessageHandler` 函数
chrome.runtime.sendMessage({
type: 'MUTLIPOST_EXTENSION_TABS_MANAGER_REQUEST_ADD_TABS',
data: data,
tabs: tabs,
});
// 依次激活标签页,以便注入的脚本可以正常工作
for (const [tab] of tabs) {
if (tab.id) {
await chrome.tabs.update(tab.id, { active: true });
await new Promise((resolve) => setTimeout(resolve, 2000));
}
}
})
.catch((error) => {
console.error('Error creating tabs or groups:', error);
});
} else {
console.error('No valid platforms specified');
}
};创建标签页
在上一节,我们看到 funcPublish 函数会调用 createTabsForPlatforms 函数来创建标签页,并在之后调用 injectScriptsToTabs 函数来注入脚本。这两个函数在 src/sync/common.ts 文件中。
它的原理是使用了 chrome.tabs 和 chrome.scripting 的 API 来创建标签页和注入脚本。
// 平台信息映射,因为定义的类型比较多,所以拆分成了多个文件 article.ts、dynamic.ts、video.ts
export const infoMap: Record<string, PlatformInfo> = {
...DynamicInfoMap,
...ArticleInfoMap,
...VideoInfoMap,
};
// 获取平台信息
export function getDefaultPlatformInfo(platform: string): PlatformInfo | null {
return infoMap[platform] || null;
}
// 创建标签页
export async function createTabsForPlatforms(data: SyncData) {
const tabs = [];
// 从 SyncData 中获取需要发布的平台
for (const platform of data.platforms) {
// 获取平台信息
const info = getDefaultPlatformInfo(platform);
if (info) {
// 创建标签页
const tab = await chrome.tabs.create({ url: info.injectUrl });
// 将标签页和平台信息推入数组
tabs.push([tab, platform]);
}
}
// 创建标签页组
const groupId = await chrome.tabs.group({ tabIds: tabs.map((t) => t[0].id!) });
const group = await chrome.tabGroups.get(groupId);
// 更新标签页组的标题和颜色
await chrome.tabGroups.update(group.id, {
color: 'blue',
title: `MultiPost-${new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })}`,
});
return tabs;
}注入脚本
在 injectScriptsToTabs 函数中,我们为每个标签页添加了监听器,当标签页加载完成后,会调用 getDefaultPlatformInfo 函数来获取平台信息,并注入脚本。
// 注入脚本
export async function injectScriptsToTabs(tabs: [chrome.tabs.Tab, string][], data: SyncData) {
// 遍历标签页
for (const t of tabs) {
// 获取标签页和平台信息
const tab = t[0];
const platform = t[1];
// 如果标签页 ID 存在,则添加监听器
if (tab.id) {
// 添加监听器
chrome.tabs.onUpdated.addListener(function listener(tabId, info) {
// 如果标签页 ID 和平台信息匹配,则注入脚本
if (tabId === tab.id && info.status === 'complete') {
// 移除监听器
chrome.tabs.onUpdated.removeListener(listener);
// 获取平台信息
const info = getDefaultPlatformInfo(platform);
// 如果平台信息存在,则注入脚本
if (info) {
// 注入脚本
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: info.injectFunction,
args: [data],
});
}
}
});
}
}
}