Files
AgentCompany/src/main/browser/browser-url-helpers.ts
T
2026-04-04 17:01:26 -04:00

129 lines
4.8 KiB
TypeScript

import { BrowserWindow } from "electron";
import log from "electron-log/main.js";
import { PLATFORM_RULES } from "./browser-types";
export function getPlatformRules(platform: string) {
return PLATFORM_RULES[platform] ?? PLATFORM_RULES.other;
}
export function assertAllowedUrl(platform: string, rawUrl: string, actionType: string) {
const allowedHosts = getPlatformRules(platform).allowedHosts;
let url: URL;
try {
url = new URL(rawUrl);
} catch {
throw new Error(`Invalid URL for ${actionType}: ${rawUrl}`);
}
if (url.protocol !== "https:") {
throw new Error(`Navigation blocked for ${actionType}. Only https URLs are allowed.`);
}
const host = url.hostname.toLowerCase();
const isAllowed = allowedHosts.some((allowedHost) => host === allowedHost || host.endsWith(`.${allowedHost}`));
if (!isAllowed) {
throw new Error(`Navigation blocked for ${actionType}. ${host} is outside the allowed ${platform} domains.`);
}
}
export function isAllowedNavigation(platform: string, rawUrl: string): boolean {
try {
assertAllowedUrl(platform, rawUrl, "navigate");
return true;
} catch {
return false;
}
}
export function attachWindowSecurity(win: BrowserWindow, platform: string) {
win.webContents.setWindowOpenHandler(({ url }) => {
if (!isAllowedNavigation(platform, url)) {
return { action: "deny" };
}
setImmediate(() => {
void win.loadURL(url).catch((error) => {
log.warn(`[browser] Failed to open allowed popup target for ${platform}: ${error instanceof Error ? error.message : String(error)}`);
});
});
return { action: "deny" };
});
win.webContents.on("will-navigate", (event, navigationUrl) => {
if (isAllowedNavigation(platform, navigationUrl)) {
return;
}
event.preventDefault();
log.warn(`[browser] Blocked navigation outside allowlist for ${platform}: ${navigationUrl}`);
});
win.webContents.on("will-redirect", (event, navigationUrl) => {
if (isAllowedNavigation(platform, navigationUrl)) {
return;
}
event.preventDefault();
log.warn(`[browser] Blocked redirect outside allowlist for ${platform}: ${navigationUrl}`);
});
}
export function getComposeUrl(platform: string): string {
const urls: Record<string, string> = {
twitter: "https://x.com/compose/tweet",
linkedin: "https://www.linkedin.com/feed/",
instagram: "https://www.instagram.com/",
facebook: "https://www.facebook.com/",
reddit: "https://www.reddit.com/submit",
bluesky: "https://bsky.app/",
youtube: "https://www.youtube.com/",
tiktok: "https://www.tiktok.com/",
discord: "https://discord.com/channels/@me",
threads: "https://www.threads.net/",
pinterest: "https://www.pinterest.com/pin-creation-tool/",
telegram: "https://web.telegram.org/",
whatsapp: "https://web.whatsapp.com/",
wechat: "https://mp.weixin.qq.com/",
weibo: "https://weibo.com/",
xiaohongshu: "https://www.xiaohongshu.com/explore",
douyin: "https://www.douyin.com/",
bilibili: "https://www.bilibili.com/",
zhihu: "https://www.zhihu.com/question/waiting",
};
return urls[platform] || getPlatformRules(platform).loginUrl;
}
export function getFeedUrl(platform: string): string {
const urls: Record<string, string> = {
twitter: "https://x.com/home",
linkedin: "https://www.linkedin.com/feed/",
instagram: "https://www.instagram.com/",
facebook: "https://www.facebook.com/",
reddit: "https://www.reddit.com/",
bluesky: "https://bsky.app/",
youtube: "https://www.youtube.com/",
tiktok: "https://www.tiktok.com/",
discord: "https://discord.com/channels/@me",
threads: "https://www.threads.net/",
pinterest: "https://www.pinterest.com/",
telegram: "https://web.telegram.org/",
whatsapp: "https://web.whatsapp.com/",
wechat: "https://mp.weixin.qq.com/",
weibo: "https://weibo.com/",
xiaohongshu: "https://www.xiaohongshu.com/explore",
douyin: "https://www.douyin.com/",
bilibili: "https://www.bilibili.com/",
zhihu: "https://www.zhihu.com/",
};
return urls[platform] || getPlatformRules(platform).loginUrl;
}
export function getSearchUrl(platform: string, query: string): string {
const q = encodeURIComponent(query);
const urls: Record<string, string> = {
twitter: `https://x.com/search?q=${q}`,
linkedin: `https://www.linkedin.com/search/results/all/?keywords=${q}`,
reddit: `https://www.reddit.com/search/?q=${q}`,
discord: `https://discord.com/channels/@me`,
pinterest: `https://www.pinterest.com/search/pins/?q=${q}`,
weibo: `https://s.weibo.com/weibo?q=${q}`,
xiaohongshu: `https://www.xiaohongshu.com/search_result?keyword=${q}`,
bilibili: `https://search.bilibili.com/all?keyword=${q}`,
zhihu: `https://www.zhihu.com/search?type=content&q=${q}`,
};
return urls[platform] || `https://google.com/search?q=${q}`;
}