🔄 卡若AI 同步 2026-03-03 10:15 | 更新:水桥平台对接、卡木、火炬、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 14 个
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
- **脚本**:永平项目下 `scripts/send_chapter_poster_to_feishu.py`
|
||||
- **依赖**:`pip install requests Pillow`;飞书应用凭证写在 `scripts/.env.feishu`(FEISHU_APP_ID、FEISHU_APP_SECRET)。
|
||||
- **固定群 webhook**:脚本内置默认发到 **Soul 彩民团队** 飞书群,webhook 为 `https://open.feishu.cn/open-apis/bot/v2/hook/14a7e0d3-864d-4709-ad40-0def6edba566`。无需复制链接,直接运行命令即可。
|
||||
- **自定义 webhook(--webhook)**:用 `--webhook "https://..."` 可指定其他群。**推送前必须确认**:目标群名称含有「瘦」或「IP」,否则不要推送;脚本无法从 webhook 获知群名,需人工在飞书里核对。
|
||||
- **命令示例**(上传完成后执行):
|
||||
|
||||
```bash
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
| 项目 | 规范 |
|
||||
|:---|:---|
|
||||
| **「我」** | **整篇文章最多出现三次**。多用「这边」「直接」「就」「场上」等替代;成稿后全文搜索「我」,超过 3 处必须改写。 |
|
||||
| **「我」** | **整篇文章最多出现三次**(仅指叙述者视角;对话引用里的「我」不占名额)。成稿后全文搜索「我」,超过 3 处必须改写。 |
|
||||
| **「这边」「那边」** | **不要用**。改用灵活表述:房主、场上、就、手头、这种模式、知识星球/小程序 等指代或省略主语。 |
|
||||
| **「回答说」** | **不要用**。房主是强势角色,文章目的是让读者产生深度认同感;房主的话用**直接陈述**呈现,不写「回答说,……」,让语气与性格一致、话一出口就立住。 |
|
||||
| **「卡若」** | 每篇最多提一次;不需要时可完全不出现。 |
|
||||
|
||||
---
|
||||
@@ -47,7 +49,7 @@
|
||||
- **推进方式**:时间线或事件线,逻辑清晰(如「有人问 → 回答」「3 号问 → …」)
|
||||
- **分段**:每段一个主题,小主题隐于叙述中,不列段头小标题
|
||||
- **穿插**:细节、对话、观点分析
|
||||
- **多用对话**:增强真实感(「X 号问」「有人问」「直接回答」「这边说」等)
|
||||
- **多用对话**:增强真实感(「X 号问」「有人问」等);房主的话**直接接在问句后**,不写「回答说」,语气强势、可认同。
|
||||
- **分享句(两处,强制)**:约 20% 处一句、结尾一句,各不超过 50 字,围绕本节主题、紧扣内容,留余味或可执行。**不要出现「干货」二字**,不要用「干货:」或「**干货**:」等格式,直接写一句金句即可,可单独成段。
|
||||
|
||||
---
|
||||
|
||||
@@ -86,7 +86,7 @@ OUT_DIR = Path("/Users/karuo/Documents/聊天记录/soul")
|
||||
|
||||
|
||||
def run_playwright_page_export(from_num: int, to_num: int) -> int:
|
||||
"""在 Playwright 页面内直接请求导出,绕过 Cookie,保证成功。"""
|
||||
"""在 Playwright 用系统默认浏览器打开,页面内直接请求导出,复用已有登录/Cookie。"""
|
||||
import re
|
||||
items = [(n, t, tok, d) for n, t, tok, d in SOUL_ITEMS if from_num <= n <= to_num]
|
||||
if not items:
|
||||
@@ -96,12 +96,29 @@ def run_playwright_page_export(from_num: int, to_num: int) -> int:
|
||||
except ImportError:
|
||||
print("❌ 需安装 playwright: pip install playwright && playwright install chromium", file=sys.stderr)
|
||||
return 1
|
||||
import tempfile
|
||||
ud = tempfile.mkdtemp(prefix="feishu_export_")
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
try:
|
||||
from playwright_default_browser import launch_playwright_with_default_browser
|
||||
except ImportError:
|
||||
launch_playwright_with_default_browser = None
|
||||
try:
|
||||
with sync_playwright() as p:
|
||||
ctx = p.chromium.launch_persistent_context(ud, headless=False, timeout=15000)
|
||||
pg = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
if launch_playwright_with_default_browser:
|
||||
ctx, get_page, cleanup = launch_playwright_with_default_browser(p, headless=False, timeout=15000)
|
||||
pg = get_page()
|
||||
else:
|
||||
import tempfile
|
||||
ud = tempfile.mkdtemp(prefix="feishu_export_")
|
||||
ctx = p.chromium.launch_persistent_context(ud, headless=False, timeout=15000)
|
||||
pg = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
|
||||
def cleanup():
|
||||
try:
|
||||
ctx.close()
|
||||
except Exception:
|
||||
pass
|
||||
import shutil
|
||||
shutil.rmtree(ud, ignore_errors=True)
|
||||
pg.goto(MINUTES_URL, wait_until="domcontentloaded", timeout=25000)
|
||||
print(" ⚠️ 请在此窗口登录飞书妙记(看到列表即可),等待 90 秒…")
|
||||
time.sleep(90)
|
||||
@@ -128,47 +145,66 @@ def run_playwright_page_export(from_num: int, to_num: int) -> int:
|
||||
except Exception as e:
|
||||
print(f" ❌ {topic}: {e}")
|
||||
time.sleep(1)
|
||||
ctx.close()
|
||||
try:
|
||||
cleanup()
|
||||
except Exception:
|
||||
pass
|
||||
print(f"✅ 页面内导出完成 {saved}/{len(items)} 场,目录: {OUT_DIR}")
|
||||
return 0
|
||||
finally:
|
||||
import shutil
|
||||
shutil.rmtree(ud, ignore_errors=True)
|
||||
except Exception as e:
|
||||
print(f"❌ Playwright 导出异常: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
def collect_cookie_via_playwright_standalone() -> str:
|
||||
"""Playwright 启动独立 Chromium,用户登录后抓 Cookie。"""
|
||||
"""Playwright 用系统默认浏览器打开,用户登录后抓 Cookie,复用已有登录态。"""
|
||||
try:
|
||||
from playwright.sync_api import sync_playwright
|
||||
except ImportError:
|
||||
return ""
|
||||
import tempfile
|
||||
ud = tempfile.mkdtemp(prefix="feishu_cookie_")
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
try:
|
||||
from playwright_default_browser import launch_playwright_with_default_browser
|
||||
except ImportError:
|
||||
launch_playwright_with_default_browser = None
|
||||
cookie_str = ""
|
||||
try:
|
||||
with sync_playwright() as p:
|
||||
ctx = p.chromium.launch_persistent_context(
|
||||
user_data_dir=ud,
|
||||
headless=False,
|
||||
args=["--start-maximized"],
|
||||
viewport={"width": 1280, "height": 900},
|
||||
timeout=15000,
|
||||
)
|
||||
try:
|
||||
if launch_playwright_with_default_browser:
|
||||
ctx, get_page, cleanup = launch_playwright_with_default_browser(p, headless=False, timeout=15000)
|
||||
pg = get_page()
|
||||
else:
|
||||
import tempfile
|
||||
ud = tempfile.mkdtemp(prefix="feishu_cookie_")
|
||||
ctx = p.chromium.launch_persistent_context(
|
||||
user_data_dir=ud,
|
||||
headless=False,
|
||||
args=["--start-maximized"],
|
||||
viewport={"width": 1280, "height": 900},
|
||||
timeout=15000,
|
||||
)
|
||||
pg = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
|
||||
def cleanup():
|
||||
try:
|
||||
ctx.close()
|
||||
except Exception:
|
||||
pass
|
||||
import shutil
|
||||
shutil.rmtree(ud, ignore_errors=True)
|
||||
try:
|
||||
pg.goto(MINUTES_URL, wait_until="domcontentloaded", timeout=25000)
|
||||
except Exception:
|
||||
pg = ctx.new_page() if not ctx.pages else ctx.pages[0]
|
||||
try:
|
||||
pg.goto(MINUTES_URL, wait_until="domcontentloaded", timeout=25000)
|
||||
except Exception:
|
||||
pass
|
||||
pass
|
||||
print(" ⚠️ 请在此窗口完成飞书妙记登录(输入账号密码直到看到列表),等待 120 秒…")
|
||||
time.sleep(120)
|
||||
cookies = ctx.cookies("https://cunkebao.feishu.cn")
|
||||
if not cookies:
|
||||
cookies = ctx.cookies()
|
||||
ctx.close()
|
||||
try:
|
||||
cleanup()
|
||||
except Exception:
|
||||
pass
|
||||
seen = set()
|
||||
parts = []
|
||||
for c in cookies:
|
||||
@@ -176,12 +212,8 @@ def collect_cookie_via_playwright_standalone() -> str:
|
||||
seen.add(c["name"])
|
||||
parts.append(f"{c['name']}={c.get('value','')}")
|
||||
cookie_str = "; ".join(parts)
|
||||
finally:
|
||||
import shutil
|
||||
try:
|
||||
shutil.rmtree(ud, ignore_errors=True)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f" Playwright 取 Cookie 失败: {e}", file=sys.stderr)
|
||||
return cookie_str if len(cookie_str) > 200 else ""
|
||||
|
||||
|
||||
|
||||
@@ -71,18 +71,37 @@ def export_via_cookie(object_token: str) -> str | None:
|
||||
|
||||
|
||||
def export_via_playwright_page(object_token: str, title: str = "", wait_sec: int = 30) -> str | None:
|
||||
"""Playwright 打开妙记页,在页面内 fetch 导出接口(带 credentials),无感拿正文。"""
|
||||
"""Playwright 用系统默认浏览器打开妙记页,在页面内 fetch 导出接口(带 credentials),复用已有登录/Cookie。"""
|
||||
try:
|
||||
from playwright.sync_api import sync_playwright
|
||||
except ImportError:
|
||||
return None
|
||||
import tempfile
|
||||
ud = tempfile.mkdtemp(prefix="feishu_one_")
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
try:
|
||||
from playwright_default_browser import launch_playwright_with_default_browser
|
||||
except ImportError:
|
||||
launch_playwright_with_default_browser = None
|
||||
result = [None]
|
||||
cleanup = lambda: None
|
||||
|
||||
try:
|
||||
with sync_playwright() as p:
|
||||
ctx = p.chromium.launch_persistent_context(ud, headless=False, timeout=15000)
|
||||
pg = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
if launch_playwright_with_default_browser:
|
||||
ctx, get_page, cleanup = launch_playwright_with_default_browser(p, headless=False, timeout=15000)
|
||||
pg = get_page()
|
||||
else:
|
||||
import tempfile
|
||||
ud = tempfile.mkdtemp(prefix="feishu_one_")
|
||||
ctx = p.chromium.launch_persistent_context(ud, headless=False, timeout=15000)
|
||||
pg = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
|
||||
def cleanup():
|
||||
try:
|
||||
ctx.close()
|
||||
except Exception:
|
||||
pass
|
||||
import shutil
|
||||
shutil.rmtree(ud, ignore_errors=True)
|
||||
pg.goto(f"https://cunkebao.feishu.cn/minutes/{object_token}", wait_until="domcontentloaded", timeout=25000)
|
||||
print(f" 页面已打开,等待 {wait_sec} 秒(若未登录请先登录)…")
|
||||
time.sleep(wait_sec)
|
||||
@@ -115,11 +134,38 @@ def export_via_playwright_page(object_token: str, title: str = "", wait_sec: int
|
||||
result[0] = text
|
||||
elif len(text) > 400:
|
||||
result[0] = text
|
||||
# 兜底:从页面 DOM 抓取正文(先点「文字记录」再取整页或大块文本)
|
||||
if not result[0]:
|
||||
try:
|
||||
# 尝试点击「文字记录」tab 再取内容
|
||||
for label in ["文字记录", "文字"]:
|
||||
try:
|
||||
pg.get_by_text(label, exact=False).first.click(timeout=3000)
|
||||
time.sleep(1.5)
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
dom_text = pg.evaluate("""() => {
|
||||
let out = '';
|
||||
const candidates = document.querySelectorAll('[class*="content"], [class*="paragraph"], [class*="segment"], [class*="transcript"], [class*="record"], .ne-doc-body, [role="main"]');
|
||||
for (const el of candidates) {
|
||||
const t = (el.innerText || el.textContent || '').trim();
|
||||
if (t.length > 800 && (t.includes(':') || t.includes(':') || /\\d{1,2}:\\d{2}:\\d{2}/.test(t))) { out = t; break; }
|
||||
}
|
||||
if (!out) out = document.body.innerText || document.body.textContent || '';
|
||||
return out;
|
||||
}""")
|
||||
if dom_text and len(dom_text.strip()) > 300:
|
||||
result[0] = dom_text.strip()
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f" Playwright 失败: {e}", file=sys.stderr)
|
||||
finally:
|
||||
import shutil
|
||||
shutil.rmtree(ud, ignore_errors=True)
|
||||
try:
|
||||
cleanup()
|
||||
except Exception:
|
||||
pass
|
||||
return result[0]
|
||||
|
||||
|
||||
|
||||
192
02_卡人(水)/水桥_平台对接/智能纪要/脚本/playwright_default_browser.py
Normal file
192
02_卡人(水)/水桥_平台对接/智能纪要/脚本/playwright_default_browser.py
Normal file
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
检测系统默认浏览器,并用该浏览器启动 Playwright,优先使用其用户数据目录以保留登录/Cookie。
|
||||
供 feishu_minutes_one_url、auto_cookie_and_export、逆向获取Cookie并下载单条 等脚本使用。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def get_system_default_browser():
|
||||
"""
|
||||
检测系统当前使用的默认浏览器。
|
||||
返回 (engine, channel, profile_path):
|
||||
- engine: "chromium" | "webkit" | "firefox"
|
||||
- channel: 仅 chromium 时有效,"chrome" | "msedge" | "chromium" | None
|
||||
- profile_path: 用户数据目录,用于复用登录态;None 表示不使用系统 profile
|
||||
"""
|
||||
system = platform.system()
|
||||
home = Path.home()
|
||||
|
||||
if system == "Darwin": # macOS
|
||||
# 优先读取系统默认 HTTP/HTTPS 处理程序
|
||||
try:
|
||||
out = subprocess.run(
|
||||
["defaults", "read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5,
|
||||
)
|
||||
if out.returncode == 0 and out.stdout:
|
||||
for line in out.stdout.splitlines():
|
||||
if "https" in line.lower() or "http" in line.lower():
|
||||
continue
|
||||
# 解析 LSHandlers 较复杂,改为按应用存在性检测
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 按优先级检测已安装的浏览器(与多数用户习惯一致:Chrome/Edge 常用)
|
||||
apps = [
|
||||
("Google Chrome", "chromium", "chrome", home / "Library/Application Support/Google/Chrome"),
|
||||
("Microsoft Edge", "chromium", "msedge", home / "Library/Application Support/Microsoft Edge"),
|
||||
("Chromium", "chromium", "chromium", home / "Library/Application Support/Chromium"),
|
||||
("Safari", "webkit", None, None),
|
||||
("Firefox", "firefox", None, home / "Library/Application Support/Firefox"),
|
||||
]
|
||||
for app_name, engine, channel, profile in apps:
|
||||
app_path = Path(f"/Applications/{app_name}.app")
|
||||
if app_path.exists():
|
||||
if engine == "firefox" and profile:
|
||||
# Firefox 使用 Profiles/xxx.default 子目录
|
||||
profiles = profile / "Profiles"
|
||||
if profiles.exists():
|
||||
for d in profiles.iterdir():
|
||||
if d.is_dir() and (d / "prefs.js").exists():
|
||||
profile = d
|
||||
break
|
||||
else:
|
||||
profile = None
|
||||
out_profile = str(profile) if profile and profile.exists() else None
|
||||
return (engine, channel, out_profile)
|
||||
# 若都未找到,退回 Chromium(Playwright 自带)
|
||||
return ("chromium", None, None)
|
||||
|
||||
if system == "Windows":
|
||||
try:
|
||||
out = subprocess.run(
|
||||
["reg", "query", "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\https\\UserChoice", "/v", "ProgId"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5,
|
||||
)
|
||||
if out.returncode == 0 and "chrome" in out.stdout.lower():
|
||||
return ("chromium", "chrome", None)
|
||||
if out.returncode == 0 and "edge" in out.stdout.lower():
|
||||
return ("chromium", "msedge", None)
|
||||
except Exception:
|
||||
pass
|
||||
return ("chromium", None, None)
|
||||
|
||||
return ("chromium", None, None)
|
||||
|
||||
|
||||
def launch_playwright_with_default_browser(sync_playwright, headless: bool = False, timeout: int = 15000):
|
||||
"""
|
||||
使用系统默认浏览器启动 Playwright,返回 (context_or_browser, page_getter, cleanup)。
|
||||
page_getter 用于获取当前 page(可能是 context.pages[0] 或 new_page)。
|
||||
cleanup 用于关闭 context/browser。
|
||||
若使用持久 context,则尽量复用系统 profile,避免 Cookie 无法登录。
|
||||
"""
|
||||
import tempfile
|
||||
p = sync_playwright
|
||||
engine, channel, profile_path = get_system_default_browser()
|
||||
|
||||
if engine == "chromium":
|
||||
channel_info = f" (channel={channel})" if channel else ""
|
||||
print(f" 使用系统浏览器: Chromium 系{channel_info},profile={profile_path or '临时目录'}")
|
||||
|
||||
# 优先尝试用系统 profile 启动(已登录则直接用)
|
||||
if profile_path and channel:
|
||||
try:
|
||||
ctx = p.chromium.launch_persistent_context(
|
||||
profile_path,
|
||||
channel=channel,
|
||||
headless=headless,
|
||||
timeout=timeout,
|
||||
args=["--no-first-run"],
|
||||
)
|
||||
page = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
|
||||
def cleanup():
|
||||
try:
|
||||
ctx.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return ctx, lambda: page, cleanup
|
||||
except Exception as e:
|
||||
if "already in use" in str(e).lower() or "User data directory" in str(e):
|
||||
print(f" 系统浏览器正在使用中,改用临时目录(请在新窗口内登录一次): {e}")
|
||||
else:
|
||||
print(f" 使用系统 profile 失败,改用临时目录: {e}")
|
||||
|
||||
# 使用临时目录 + 指定 channel(仍为系统安装的 Chrome/Edge)
|
||||
user_data = tempfile.mkdtemp(prefix="feishu_playwright_")
|
||||
try:
|
||||
kwargs = {"headless": headless, "timeout": timeout}
|
||||
if channel:
|
||||
kwargs["channel"] = channel
|
||||
ctx = p.chromium.launch_persistent_context(user_data, **kwargs)
|
||||
page = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
|
||||
def cleanup():
|
||||
try:
|
||||
ctx.close()
|
||||
except Exception:
|
||||
pass
|
||||
import shutil
|
||||
shutil.rmtree(user_data, ignore_errors=True)
|
||||
|
||||
return ctx, lambda: page, cleanup
|
||||
except Exception:
|
||||
import shutil
|
||||
shutil.rmtree(user_data, ignore_errors=True)
|
||||
raise
|
||||
|
||||
if engine == "webkit":
|
||||
print(" 使用系统浏览器: Safari (WebKit)")
|
||||
browser = p.webkit.launch(headless=headless)
|
||||
ctx = browser
|
||||
page = browser.new_page()
|
||||
|
||||
def cleanup():
|
||||
try:
|
||||
browser.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return ctx, lambda: page, cleanup
|
||||
|
||||
if engine == "firefox":
|
||||
print(" 使用系统浏览器: Firefox")
|
||||
browser = p.firefox.launch(headless=headless)
|
||||
ctx = browser
|
||||
page = browser.new_page()
|
||||
|
||||
def cleanup():
|
||||
try:
|
||||
browser.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return ctx, lambda: page, cleanup
|
||||
|
||||
# 默认
|
||||
print(" 使用 Playwright 自带 Chromium")
|
||||
user_data = tempfile.mkdtemp(prefix="feishu_playwright_")
|
||||
ctx = p.chromium.launch_persistent_context(user_data, headless=headless, timeout=timeout)
|
||||
page = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
|
||||
def cleanup():
|
||||
try:
|
||||
ctx.close()
|
||||
except Exception:
|
||||
pass
|
||||
import shutil
|
||||
shutil.rmtree(user_data, ignore_errors=True)
|
||||
|
||||
return ctx, lambda: page, cleanup
|
||||
35
02_卡人(水)/水桥_平台对接/智能纪要/脚本/浏览器控制台_复制妙记文字.js
Normal file
35
02_卡人(水)/水桥_平台对接/智能纪要/脚本/浏览器控制台_复制妙记文字.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 在已打开的飞书妙记页面(cunkebao.feishu.cn/minutes/xxx)按 F12 → Console 粘贴整段运行,
|
||||
* 会提取当前页「文字记录」区域文字并复制到剪贴板,同时打印到控制台。
|
||||
*/
|
||||
(function () {
|
||||
function getText() {
|
||||
const candidates = document.querySelectorAll(
|
||||
'[class*="content"], [class*="paragraph"], [class*="segment"], [class*="transcript"], [class*="record"], .ne-doc-body, [role="main"]'
|
||||
);
|
||||
for (const el of candidates) {
|
||||
const t = (el.innerText || el.textContent || "").trim();
|
||||
if (t.length > 800 && (t.includes(":") || t.includes(":") || /\d{1,2}:\d{2}:\d{2}/.test(t))) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return (document.body && (document.body.innerText || document.body.textContent)) || "";
|
||||
}
|
||||
const text = getText().trim();
|
||||
if (!text) {
|
||||
console.warn("未找到长文本,请先点击「文字记录」选项卡再运行本脚本。");
|
||||
return;
|
||||
}
|
||||
const title = (document.title || "妙记").replace(/\s*\|\s*.*$/, "");
|
||||
const out = "标题: " + title + "\n\n文字记录:\n\n" + text;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(out).then(function () {
|
||||
console.log("已复制到剪贴板,共 " + out.length + " 字。可粘贴到记事本保存。");
|
||||
}).catch(function () {
|
||||
console.log(out.slice(0, 500) + "\n...(共 " + out.length + " 字,请手动选择上方输出复制)");
|
||||
});
|
||||
} else {
|
||||
console.log(out.slice(0, 2000) + "\n...(共 " + out.length + " 字)");
|
||||
}
|
||||
console.log("前 500 字预览:", out.slice(0, 500));
|
||||
})();
|
||||
@@ -122,7 +122,7 @@ def main() -> int:
|
||||
try:
|
||||
from feishu_minutes_one_url import export_via_playwright_page
|
||||
print(" Cookie 导出 401,改用 Playwright 页面内获取…")
|
||||
text = export_via_playwright_page(token, title=title, wait_sec=45)
|
||||
text = export_via_playwright_page(token, title=title, wait_sec=60)
|
||||
except Exception as e:
|
||||
print(" Playwright 兜底失败:", e, file=sys.stderr)
|
||||
if text:
|
||||
|
||||
@@ -347,6 +347,14 @@ python3 scripts/feishu_wiki_create_doc.py --parent KNf7wA8Rki1NSdkkSIqcdFtTnWb -
|
||||
|
||||
JSON 格式:与 `团队入职流程与新人登记表_feishu_blocks.json` 相同,含 `children` 数组(飞书 docx blocks)。
|
||||
|
||||
### 读书笔记发飞书(链接与子目录)
|
||||
|
||||
- **原则**:读书笔记写完后同步发到飞书知识库,发到**指定链接(父节点)下的对应子目录**。
|
||||
- **链接分析**:飞书知识库链接格式为 `https://cunkebao.feishu.cn/wiki/<node_token>`,其中 `wiki/` 后的 `node_token` 即为父节点;若读书笔记放在「读书笔记」节点下,则用该节点 token 为 parent;若其下还有分类子目录(个人提升/创业/商业思维/投资/人际关系),则先在对应子节点下再建文档。
|
||||
- **目录结构建议**:父节点 = 读书笔记根(如「2、我写的日记」或「读书笔记」)→ 其下可建子目录「读书笔记」或按分类建「个人提升」「创业」等 → 单篇笔记为该目录下的一篇文档。
|
||||
- **执行**:用统一文章上传脚本,`--parent` 取目标父节点 token(即链接中的 node_token),`--title` 与本地笔记标题一致,`--md` 指向 `个人/2、我写的日记/读书笔记/xxx.md`。若需按分类落子目录,需先有该分类子节点 token,再以该 token 为 parent 创建文档。
|
||||
- **配置**:读书笔记默认本地路径为 `个人/2、我写的日记/读书笔记/`;飞书父节点 token 可配置为环境变量 `FEISHU_READING_WIKI_PARENT` 或写在读书笔记 Skill 的「飞书读书笔记配置」中;用户提供飞书「读书笔记」节点链接后,从链接提取 token 填入即可。
|
||||
|
||||
---
|
||||
|
||||
## 飞书导出 JSON 按原格式上传
|
||||
|
||||
77
02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0303_feishu_log.py
Normal file
77
02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0303_feishu_log.py
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
写入 3月3日 飞书日志到 3 月文档。昨日目标与今年总目标一致,百分比按总目标;今日 20 条视频 + 1 朋友圈,视频 Skill 四屏切片完成 20 个视频。
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
|
||||
from auto_log import get_token_silent, write_log, open_result, CONFIG
|
||||
|
||||
|
||||
def _get_march_wiki_token():
|
||||
raw = (CONFIG.get("MONTH_WIKI_TOKENS") or {}).get(3) or os.environ.get("FEISHU_MARCH_WIKI_TOKEN") or ""
|
||||
return (raw or "").strip() or None
|
||||
|
||||
|
||||
def build_tasks_0303():
|
||||
"""3月3日:昨日目标一致、总目标一致、百分比按此;今日 20 条视频 + 1 朋友圈;视频 Skill 四屏切片 20 个;百分比。"""
|
||||
return [
|
||||
{
|
||||
"person": "卡若",
|
||||
"events": ["今日复盘", "本月与最终目标", "今日核心", "视频Skill四屏切片"],
|
||||
"quadrant": "重要紧急",
|
||||
"t_targets": [
|
||||
"昨日目标与今年总目标一致,百分比按总目标执行",
|
||||
"本月目标约 12%,距最终目标差 88%",
|
||||
"今日核心:每天 20 条 Soul 视频 + 20:00 发 1 条朋友圈",
|
||||
"视频 Skill 四屏切片:完成 20 个视频(当日完成度见反馈)",
|
||||
],
|
||||
"n_process": [
|
||||
"【复盘】昨日目标一致、今年总目标一致,百分比按 2026年整体目标 对齐",
|
||||
"【2月突破执行】延续 3 月,本月/最终目标百分比已按进度写入",
|
||||
"【今日】20 条视频(四屏切片)+ 1 条朋友圈;视频切片 Skill 操作执行",
|
||||
],
|
||||
"t_thoughts": [
|
||||
"今日一条核心:20 条 Soul 视频 + 8 点 1 条朋友圈,持续拉齐与最终目标",
|
||||
"四屏切片完成 20 个视频,按当日完成数看百分比",
|
||||
],
|
||||
"w_work": [
|
||||
"20 条 Soul 视频(四屏切片)",
|
||||
"20:00 发 1 条朋友圈",
|
||||
"视频 Skill 操作",
|
||||
"飞书日志",
|
||||
],
|
||||
"f_feedback": [
|
||||
"本月/最终目标 12% / 100%,差 88%",
|
||||
"今日核心→20 条 Soul + 8 点朋友圈 🔄",
|
||||
"四屏切片 20 条→当日完成度待填 % 🔄",
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
token = get_token_silent()
|
||||
if not token:
|
||||
print("❌ 无法获取飞书 Token")
|
||||
sys.exit(1)
|
||||
march_token = _get_march_wiki_token()
|
||||
if not march_token:
|
||||
print("❌ 未配置 3 月文档,请设置 FEISHU_MARCH_WIKI_TOKEN")
|
||||
sys.exit(1)
|
||||
tasks = build_tasks_0303()
|
||||
ok = write_log(token, "3月3日", tasks, march_token, overwrite=False)
|
||||
if ok:
|
||||
open_result(march_token)
|
||||
print("✅ 3月3日 飞书日志已写入")
|
||||
else:
|
||||
print("❌ 写入失败")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user