From 398b785e031dcb64395c60087da4fe7936a1f133 Mon Sep 17 00:00:00 2001 From: Jiaxin Peng Date: Sun, 5 Nov 2023 17:32:10 +0000 Subject: [PATCH] update the script and support both notionnext and general database --- src/commands/NotionCommands.ts | 20 +- src/lang/I18n.ts | 20 +- src/main.ts | 48 +---- src/ui/settingTabs.ts | 115 +++++++---- src/upload/BaseUpload2Notion.ts | 90 --------- src/upload/Upload2NotionGeneral.ts | 178 ------------------ src/upload/updateYaml.ts | 51 +++++ src/upload/uploadCommand.ts | 72 ++++--- .../BaseUpload2NotionGeneral.ts | 90 +++++++++ .../upload_general/Upload2NotionGeneral.ts | 144 ++++++++++++++ .../upload_general/getMarkdownGeneral.ts | 33 ++++ .../upload_next/BaseUpload2NotionNext.ts | 90 +++++++++ .../{ => upload_next}/Upload2NotionNext.ts | 100 ++++++++-- .../getMarkdownNext.ts} | 9 +- 14 files changed, 650 insertions(+), 410 deletions(-) delete mode 100644 src/upload/BaseUpload2Notion.ts delete mode 100644 src/upload/Upload2NotionGeneral.ts create mode 100644 src/upload/updateYaml.ts create mode 100644 src/upload/upload_general/BaseUpload2NotionGeneral.ts create mode 100644 src/upload/upload_general/Upload2NotionGeneral.ts create mode 100644 src/upload/upload_general/getMarkdownGeneral.ts create mode 100644 src/upload/upload_next/BaseUpload2NotionNext.ts rename src/upload/{ => upload_next}/Upload2NotionNext.ts (68%) rename src/upload/{getMarkdown.ts => upload_next/getMarkdownNext.ts} (87%) diff --git a/src/commands/NotionCommands.ts b/src/commands/NotionCommands.ts index e82d728..0079f49 100644 --- a/src/commands/NotionCommands.ts +++ b/src/commands/NotionCommands.ts @@ -1,7 +1,7 @@ import {i18nConfig} from "src/lang/I18n"; import {Editor, MarkdownView} from "obsidian"; import {FuzzySuggester, DatabaseList} from "./FuzzySuggester"; -import {uploadCommand} from "../upload/uploadCommand"; +import {uploadCommandGeneral, uploadCommandNext} from "../upload/uploadCommand"; import ObsidianSyncNotionPlugin from "src/main"; // create the commands list @@ -12,19 +12,19 @@ export default class RibbonCommands { Ncommand = [ { id: "share-to-notionnext", - name: i18nConfig.ribbonIcon, // Use the translated text from i18nConfig + name: i18nConfig.CommandName, // Use the translated text from i18nConfig editorCallback: async (editor: Editor, view: MarkdownView) => { // await this.plugin.uploadCommand() - await uploadCommand(this.plugin, this.plugin.settings, this.plugin.app) + await uploadCommandNext(this.plugin, this.plugin.settings, this.plugin.app) } }, - // { - // id: "share-to-notion", - // name: i18nConfig.CommandNameGeneral, // Use the translated text from i18nConfig - // editorCallback: async (editor: Editor, view: MarkdownView) => { - // await this.plugin.upload(); - // } - // } + { + id: "share-to-notion", + name: i18nConfig.CommandNameGeneral, // Use the translated text from i18nConfig + editorCallback: async (editor: Editor, view: MarkdownView) => { + await uploadCommandGeneral(this.plugin, this.plugin.settings, this.plugin.app); + } + } ]; async ribbonDisplay() { diff --git a/src/lang/I18n.ts b/src/lang/I18n.ts index 3632e0f..a1185ad 100644 --- a/src/lang/I18n.ts +++ b/src/lang/I18n.ts @@ -1,12 +1,15 @@ export const I18n: { [key: string]: any } = { en: { ribbonIcon: "Share to NotionNext", - CommandName: "share to notionnext", - CommandNameGeneral: "share to notion", + GeneralSetting: "General information Settings", + CommandID: "share-to-notionnext", + CommandName: "Share to NotionNext Database", + CommandIDGeneral: "share-to-notion", + CommandNameGeneral: "Share to Notion General Database", NotionNextVersion: "NotionNext Version Database", NotionNextVersionDesc: "Turn on this option if you are using NotionNext", - NotionNextSetting: "NotionNext Database Settings", + NotionNextSettingHeader: "NotionNext Database Settings", NotionAPI: "Notion API Token", NotionAPIDesc: "It's a secret", NotionAPIText: "Enter your Notion API Token", @@ -20,7 +23,7 @@ export const I18n: { [key: string]: any } = { NotionUserDesc: "Your notion ID (optional),share link likes:https://username.notion.site/,your notion id is [username]", NotionUserText: "Enter your notion ID (options)", - NotionGeneralSetting: "General Notion Database Settings", + NotionGeneralSettingHeader: "General Notion Database Settings", NotYetFinish: "Not finished. This function will be available in the next version", PlaceHolder: "Enter database Name", @@ -41,11 +44,14 @@ export const I18n: { [key: string]: any } = { }, zh: { ribbonIcon: "分享到 NotionNext", + GeneralSetting: "通用信息设置", + CommandID: "share-to-notionnext", CommandName: "分享到 NotionNext", - CommandNameGeneral: "分享到 Notion", + CommandIDGeneral: "share-to-notion", + CommandNameGeneral: "分享到 Notion 普通数据库", NotionNextVersion: "NotionNext 版本数据库", NotionNextVersionDesc: "如果你使用的是NotionNext,请打开此选项", - NotionNextSetting: "NotionNext 数据库参数设置", + NotionNextSettingHeader: "NotionNext 数据库参数设置", NotionAPI: "Notion API 令牌", NotionAPIDesc: "显示为密码", NotionAPIText: "输入你的 Notion API 令牌", @@ -59,7 +65,7 @@ export const I18n: { [key: string]: any } = { NotionUserDesc: "你的 Notion ID(可选),分享链接类似:https://username.notion.site/,你的 Notion ID 是 [username]", NotionUserText: "输入你的 Notion ID(可选)", - NotionGeneralSetting: "普通 Notion 数据库设置", + NotionGeneralSettingHeader: "普通 Notion 数据库设置", NotYetFinish: "未完成。此功能将在之后版本中提供", PlaceHolder: "输入数据库名称", "notion-logo": "分享到NotionNext", diff --git a/src/main.ts b/src/main.ts index 3d8ba40..0c69977 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,11 +1,11 @@ import {App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting} from "obsidian"; import {addIcons} from 'src/ui/icon'; -import {Upload2NotionGeneral} from "src/upload/Upload2NotionGeneral"; -import {Upload2NotionNext} from "src/upload/Upload2NotionNext"; +import {Upload2NotionGeneral} from "src/upload/upload_general/Upload2NotionGeneral"; +import {Upload2NotionNext} from "src/upload/upload_next/Upload2NotionNext"; import {i18nConfig} from "src/lang/I18n"; import ribbonCommands from "src/commands/NotionCommands"; import { ObsidianSettingTab, PluginSettings, DEFAULT_SETTINGS } from "src/ui/settingTabs"; -import {getNowFileMarkdownContent} from "src/upload/getMarkdown"; + // Remember to rename these classes and interfaces! @@ -43,48 +43,6 @@ export default class ObsidianSyncNotionPlugin extends Plugin { onunload() { } - // async uploadCommand() { - // const {notionAPI, databaseID, NNon} = this.settings; - // - // // Check if NNon exists - // if (NNon === undefined) { - // const NNonmessage = i18nConfig.NNonMissing; - // new Notice(NNonmessage); - // return; - // } - // - // // Check if the user has set up the Notion API and database ID - // if (notionAPI === "" || databaseID === "") { - // const setAPIMessage = i18nConfig["set-api-id"]; - // new Notice(setAPIMessage); - // return; - // } - // - // const {markDownData, nowFile, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime} = await getNowFileMarkdownContent(this.app, this.settings) - // - // if (markDownData) { - // const {basename} = nowFile; - // let upload; - // let res; - // - // if (NNon) { - // upload = new Upload2NotionNext(this); - // res = await upload.syncMarkdownToNotionNext(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings); - // } else { - // upload = new Upload2NotionGeneral(this); - // res = await upload.syncMarkdownToNotionGeneral(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings); - // } - // - // - // if (res.status === 200) { - // new Notice(`${i18nConfig["sync-success"]}${basename}`); - // } else { - // new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000); - // } - // } - // } - - async loadSettings() { this.settings = Object.assign( {}, diff --git a/src/ui/settingTabs.ts b/src/ui/settingTabs.ts index 4984fe5..a72005f 100644 --- a/src/ui/settingTabs.ts +++ b/src/ui/settingTabs.ts @@ -4,20 +4,24 @@ import ObsidianSyncNotionPlugin from "../main"; export interface PluginSettings { NNon: boolean; - notionAPI: string; - databaseID: string; + notionAPINext: string; + databaseIDNext: string; bannerUrl: string; notionUser: string; proxy: string; + notionAPIGeneral: string; + databaseIDGeneral: string; } export const DEFAULT_SETTINGS: PluginSettings = { NNon: undefined, - notionAPI: "", - databaseID: "", + notionAPINext: "", + databaseIDNext: "", bannerUrl: "", notionUser: "", proxy: "", + notionAPIGeneral: "", + databaseIDGeneral: "", }; @@ -34,6 +38,8 @@ export class ObsidianSettingTab extends PluginSettingTab { containerEl.empty(); + containerEl.createEl('h2', {text: i18nConfig.GeneralSetting}) + new Setting(containerEl) .setName(i18nConfig.NotionNextVersion) .setDesc(i18nConfig.NotionNextVersionDesc) @@ -46,40 +52,6 @@ export class ObsidianSettingTab extends PluginSettingTab { }) ); - containerEl.createEl('h2', {text: i18nConfig.NotionNextSetting}) - - new Setting(containerEl) - .setName(i18nConfig.NotionAPI) - .setDesc(i18nConfig.NotionAPIDesc) - .addText((text) => { - text.inputEl.type = 'password'; - return text - .setPlaceholder(i18nConfig.NotionAPIText) - .setValue(this.plugin.settings.notionAPI) - .onChange(async (value) => { - this.plugin.settings.notionAPI = value; - await this.plugin.saveSettings(); - }) - }); - - - const notionDatabaseID = new Setting(containerEl) - .setName(i18nConfig.DatabaseID) - .setDesc(i18nConfig.NotionAPIDesc) - .addText((text) => { - text.inputEl.type = 'password'; - return text - .setPlaceholder(i18nConfig.DatabaseIDText) - .setValue(this.plugin.settings.databaseID) - .onChange(async (value) => { - this.plugin.settings.databaseID = value; - await this.plugin.saveSettings(); - }) - } - ); - - // notionDatabaseID.controlEl.querySelector('input').type='password' - new Setting(containerEl) .setName(i18nConfig.BannerUrl) .setDesc(i18nConfig.BannerUrlDesc) @@ -107,8 +79,43 @@ export class ObsidianSettingTab extends PluginSettingTab { }) ); + containerEl.createEl('h2', {text: i18nConfig.NotionNextSettingHeader}) + + new Setting(containerEl) + .setName(i18nConfig.NotionAPI) + .setDesc(i18nConfig.NotionAPIDesc) + .addText((text) => { + text.inputEl.type = 'password'; + return text + .setPlaceholder(i18nConfig.NotionAPIText) + .setValue(this.plugin.settings.notionAPINext) + .onChange(async (value) => { + this.plugin.settings.notionAPINext = value; + await this.plugin.saveSettings(); + }) + }); + + + const notionDatabaseID = new Setting(containerEl) + .setName(i18nConfig.DatabaseID) + .setDesc(i18nConfig.NotionAPIDesc) + .addText((text) => { + text.inputEl.type = 'password'; + return text + .setPlaceholder(i18nConfig.DatabaseIDText) + .setValue(this.plugin.settings.databaseIDNext) + .onChange(async (value) => { + this.plugin.settings.databaseIDNext = value; + await this.plugin.saveSettings(); + }) + } + ); + + // notionDatabaseID.controlEl.querySelector('input').type='password' + + // General Database Settings - containerEl.createEl('h2', {text: i18nConfig.NotionGeneralSetting}); + containerEl.createEl('h2', {text: i18nConfig.NotionGeneralSettingHeader}); new Setting(containerEl) .setName(i18nConfig.NotYetFinish) @@ -124,5 +131,35 @@ export class ObsidianSettingTab extends PluginSettingTab { // await this.plugin.saveSettings(); // }) // ); + new Setting(containerEl) + .setName(i18nConfig.NotionAPI) + .setDesc(i18nConfig.NotionAPIDesc) + .addText((text) => { + text.inputEl.type = 'password'; + return text + .setPlaceholder(i18nConfig.NotionAPIText) + .setValue(this.plugin.settings.notionAPIGeneral) + .onChange(async (value) => { + this.plugin.settings.notionAPIGeneral = value; + await this.plugin.saveSettings(); + }) + }); + + + new Setting(containerEl) + .setName(i18nConfig.DatabaseID) + .setDesc(i18nConfig.NotionAPIDesc) + .addText((text) => { + text.inputEl.type = 'password'; + return text + .setPlaceholder(i18nConfig.NotionIDText) + .setValue(this.plugin.settings.databaseIDGeneral) + .onChange(async (value) => { + this.plugin.settings.databaseIDGeneral = value; + await this.plugin.saveSettings(); + }) + } + ); + } } diff --git a/src/upload/BaseUpload2Notion.ts b/src/upload/BaseUpload2Notion.ts deleted file mode 100644 index 59e8d39..0000000 --- a/src/upload/BaseUpload2Notion.ts +++ /dev/null @@ -1,90 +0,0 @@ -import {App, Notice, requestUrl, TFile} from "obsidian"; -import {Client} from '@notionhq/client'; -import {markdownToBlocks,} from "@tryfabric/martian"; -import * as yamlFrontMatter from "yaml-front-matter"; -// import * as yaml from "yaml" -import MyPlugin from "src/main"; - -export class UploadBase { - plugin: MyPlugin; - notion: Client; - agent: any; - - constructor(plugin: MyPlugin) { - this.plugin = plugin; - } - - async deletePage(notionID: string) { - return requestUrl({ - url: `https://api.notion.com/v1/blocks/${notionID}`, - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' + this.plugin.settings.notionAPI, - 'Notion-Version': '2022-06-28', - }, - body: '' - }); - } - - async getDataBase(databaseID: string) { - const response = await requestUrl({ - url: `https://api.notion.com/v1/databases/${databaseID}`, - method: 'GET', - headers: { - 'Authorization': 'Bearer ' + this.plugin.settings.notionAPI, - 'Notion-Version': '2022-06-28', - } - } - ) - - // Check if cover is present in the JSON response and then get the URL - if (response.json.cover && response.json.cover.external) { - return response.json.cover.external.url; - } else { - return null; // or some other default value, if you prefer - } - } - - async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) { - let {url, id} = res.json - // replace www to notionID - const {notionUser} = this.plugin.settings; - - if (notionUser !== "") { - // replace url str "www" to notionID - url = url.replace("www.notion.so", `${notionUser}.notion.site`) - } - - await app.fileManager.processFrontMatter(nowFile, yamlContent => { - if (yamlContent['notionID']) { - delete yamlContent['notionID'] - } - if (yamlContent['link']) { - delete yamlContent['link'] - } - // add new notionID and link - yamlContent.notionID = id; - yamlContent.link = url; - }); - - try { - await navigator.clipboard.writeText(url) - } catch (error) { - new Notice(`复制链接失败,请手动复制${error}`) - } - // const __content = yamlContent.__content; - // delete yamlContent.__content - // const yamlhead = yaml.stringify(yamlContent) - // // if yamlhead hava last \n remove it - // const yamlhead_remove_n = yamlhead.replace(/\n$/, '') - // // if __content have start \n remove it - // const __content_remove_n = __content.replace(/^\n/, '') - // const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n; - // try { - // await nowFile.vault.modify(nowFile, content) - // } catch (error) { - // new Notice(`write file error ${error}`) - // } - } -} diff --git a/src/upload/Upload2NotionGeneral.ts b/src/upload/Upload2NotionGeneral.ts deleted file mode 100644 index 5a3e85f..0000000 --- a/src/upload/Upload2NotionGeneral.ts +++ /dev/null @@ -1,178 +0,0 @@ -import {UploadBase} from "./BaseUpload2Notion"; -import { App, Notice, requestUrl, TFile } from "obsidian"; -import { Client } from '@notionhq/client'; -import { markdownToBlocks, } from "@tryfabric/martian"; -import * as yamlFrontMatter from "yaml-front-matter"; -// import * as yaml from "yaml" -import MyPlugin from "src/main"; - -export class Upload2NotionGeneral extends UploadBase { - constructor(plugin: MyPlugin) { - super(plugin); - } - - // 因为需要解析notion的block进行对比,非常的麻烦, - // 暂时就直接删除,新建一个page - async updatePage(notionID: string, title: string, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, paword: string, favicon: string, datetime: string, childArr: any) { - await this.deletePage(notionID) - - const databasecover = await this.getDataBase(this.plugin.settings.databaseID) - - if (cover == null) { - cover = databasecover - } - - return await this.createPage( - title, - emoji, - cover, - tags, - type, - slug, - stats, - category, - summary, - paword, - favicon, - datetime, - childArr) - } - - async createPage(title: string, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, pawrod: string, favicon: string, datetime: string, childArr: any) { - const bodyString: any = { - parent: { - database_id: this.plugin.settings.databaseID - }, - icon: { - emoji: emoji || '📜' - }, - properties: { - title: { - title: [ - { - text: { - content: title - }, - }, - ], - }, - tags: { - multi_select: tags && true ? tags.map(tag => { - return { "name": tag } - }) : [], - }, - type: { - select: { - name: type || 'Post' - } - }, - slug: { - rich_text: [ - { - text: { - content: slug || '' - } - } - ] - }, - status: { - select: { - name: stats || 'Draft' - } - }, - category: { - select: { - name: category || 'Obsidian' - } - }, - summary: { - rich_text: [ - { - text: { - content: summary || '' - } - } - ] - }, - password: { - rich_text: [ - { - text: { - content: pawrod || '' - } - } - ] - }, - icon: { - rich_text: [ - { - text: { - content: favicon || '' - } - } - ] - }, - date: { - date: { - start: datetime || new Date().toISOString() - } - } - }, - children: childArr, - } - if (cover) { - bodyString.cover = { - type: "external", - external: { - url: cover - } - } - } - - if (!bodyString.cover && this.plugin.settings.bannerUrl) { - bodyString.cover = { - type: "external", - external: { - url: this.plugin.settings.bannerUrl - } - } - } - - try { - return await requestUrl({ - url: `https://api.notion.com/v1/pages`, - method: 'POST', - headers: { - 'Content-Type': 'application/json', - // 'User-Agent': 'obsidian.md', - 'Authorization': 'Bearer ' + this.plugin.settings.notionAPI, - 'Notion-Version': '2022-06-28', - }, - body: JSON.stringify(bodyString), - }) - } catch (error) { - new Notice(`network error ${error}`) - } - } - - async syncMarkdownToNotionGeneral(title: string, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, paword: string, favicon: string, datetime: string, markdown: string, nowFile: TFile, app: App, settings: any): Promise { - let res: any - const yamlContent: any = yamlFrontMatter.loadFront(markdown); - const __content = yamlContent.__content - const file2Block = markdownToBlocks(__content); - const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter - const notionID = frontmasster ? frontmasster.notionID : null - - if (notionID) { - res = await this.updatePage(notionID, title, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block); - } else { - res = await this.createPage(title, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block); - } - if (res.status === 200) { - await this.updateYamlInfo(markdown, nowFile, res, app, settings) - } else { - new Notice(`${res.text}`) - } - return res - } -} diff --git a/src/upload/updateYaml.ts b/src/upload/updateYaml.ts new file mode 100644 index 0000000..a55e21e --- /dev/null +++ b/src/upload/updateYaml.ts @@ -0,0 +1,51 @@ +import {App, Notice, TFile} from "obsidian"; +import ObsidianSyncNotionPlugin from "../main"; +import {PluginSettings} from "../ui/settingTabs"; + +export async function updateYamlInfo( + yamlContent: string, + nowFile: TFile, + res: any, + app: App, + plugin: ObsidianSyncNotionPlugin, +) { + let {url, id} = res.json + // replace www to notionID + const { notionUser } = plugin.settings; + + if (notionUser !== "") { + // replace url str "www" to notionID + url = url.replace("www.notion.so", `${notionUser}.notion.site`) + } + + await app.fileManager.processFrontMatter(nowFile, yamlContent => { + if (yamlContent['notionID']) { + delete yamlContent['notionID'] + } + if (yamlContent['link']) { + delete yamlContent['link'] + } + // add new notionID and link + yamlContent.notionID = id; + yamlContent.link = url; + }); + + try { + await navigator.clipboard.writeText(url) + } catch (error) { + new Notice(`复制链接失败,请手动复制${error}`) + } + // const __content = yamlContent.__content; + // delete yamlContent.__content + // const yamlhead = yaml.stringify(yamlContent) + // // if yamlhead hava last \n remove it + // const yamlhead_remove_n = yamlhead.replace(/\n$/, '') + // // if __content have start \n remove it + // const __content_remove_n = __content.replace(/^\n/, '') + // const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n; + // try { + // await nowFile.vault.modify(nowFile, content) + // } catch (error) { + // new Notice(`write file error ${error}`) + // } +} diff --git a/src/upload/uploadCommand.ts b/src/upload/uploadCommand.ts index 9752d39..2f2b4c9 100644 --- a/src/upload/uploadCommand.ts +++ b/src/upload/uploadCommand.ts @@ -1,48 +1,74 @@ import {i18nConfig} from "../lang/I18n"; import {App, Notice} from "obsidian"; -import {getNowFileMarkdownContent} from "./getMarkdown"; -import {Upload2NotionNext} from "./Upload2NotionNext"; -import {Upload2NotionGeneral} from "./Upload2NotionGeneral"; +import {Upload2NotionNext} from "./upload_next/Upload2NotionNext"; +import {Upload2NotionGeneral} from "./upload_general/Upload2NotionGeneral"; import {PluginSettings} from "../ui/settingTabs"; import ObsidianSyncNotionPlugin from "../main"; +import {getNowFileMarkdownContentNext} from "./upload_next/getMarkdownNext"; +import {getNowFileMarkdownContentGeneral} from "./upload_general/getMarkdownGeneral"; -export async function uploadCommand( +export async function uploadCommandNext( plugin: ObsidianSyncNotionPlugin, settings: PluginSettings, app: App, ) { - const {notionAPI, databaseID, NNon} = settings; + const {notionAPINext, databaseIDNext} = settings; // Check if NNon exists - if (NNon === undefined) { - const NNonmessage = i18nConfig.NNonMissing; - new Notice(NNonmessage); - return; - } + // if (NNon === undefined) { + // const NNonmessage = i18nConfig.NNonMissing; + // new Notice(NNonmessage); + // return; + // } // Check if the user has set up the Notion API and database ID - if (notionAPI === "" || databaseID === "") { + if (notionAPINext === "" || databaseIDNext === "") { const setAPIMessage = i18nConfig["set-api-id"]; new Notice(setAPIMessage); return; } - const {markDownData, nowFile, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime} = await getNowFileMarkdownContent(app, settings) + const {markDownData, nowFile, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime} = await getNowFileMarkdownContentNext(app, settings) if (markDownData) { const {basename} = nowFile; - let upload; - let res; - - if (NNon) { - upload = new Upload2NotionNext(plugin); - res = await upload.syncMarkdownToNotionNext(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings); - } else { - upload = new Upload2NotionGeneral(plugin); - res = await upload.syncMarkdownToNotionGeneral(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app, this.settings); - } - + const upload = new Upload2NotionNext(plugin); + const res = await upload.syncMarkdownToNotionNext(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app); + + if (res.status === 200) { + new Notice(`${i18nConfig["sync-success"]}${basename}`); + } else { + new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000); + } + + } +} + + + +export async function uploadCommandGeneral( + plugin: ObsidianSyncNotionPlugin, + settings: PluginSettings, + app: App, +) { + + const{ notionAPIGeneral, databaseIDGeneral} = settings; + + // Check if the user has set up the Notion API and database ID + if (notionAPIGeneral === "" || databaseIDGeneral === "") { + const setAPIMessage = i18nConfig["set-api-id"]; + new Notice(setAPIMessage); + return; + } + + const {markDownData, nowFile,cover, tags} = await getNowFileMarkdownContentGeneral(app, settings) + + if (markDownData) { + const {basename} = nowFile; + + const upload = new Upload2NotionGeneral(plugin); + const res = await upload.syncMarkdownToNotionGeneral(basename, cover, tags, markDownData, nowFile, this.app, this.settings); if (res.status === 200) { new Notice(`${i18nConfig["sync-success"]}${basename}`); diff --git a/src/upload/upload_general/BaseUpload2NotionGeneral.ts b/src/upload/upload_general/BaseUpload2NotionGeneral.ts new file mode 100644 index 0000000..1122ce5 --- /dev/null +++ b/src/upload/upload_general/BaseUpload2NotionGeneral.ts @@ -0,0 +1,90 @@ +import {App, Notice, requestUrl, TFile} from "obsidian"; +import {Client} from '@notionhq/client'; +import {markdownToBlocks,} from "@tryfabric/martian"; +import * as yamlFrontMatter from "yaml-front-matter"; +// import * as yaml from "yaml" +import MyPlugin from "src/main"; + +export class UploadBaseGeneral { + plugin: MyPlugin; + notion: Client; + agent: any; + + constructor(plugin: MyPlugin) { + this.plugin = plugin; + } + + async deletePage(notionID: string) { + return requestUrl({ + url: `https://api.notion.com/v1/blocks/${notionID}`, + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext, + 'Notion-Version': '2022-06-28', + }, + body: '' + }); + } + + async getDataBase(databaseID: string) { + const response = await requestUrl({ + url: `https://api.notion.com/v1/databases/${databaseID}`, + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext, + 'Notion-Version': '2022-06-28', + } + } + ) + + // Check if cover is present in the JSON response and then get the URL + if (response.json.cover && response.json.cover.external) { + return response.json.cover.external.url; + } else { + return null; // or some other default value, if you prefer + } + } + + // async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) { + // let {url, id} = res.json + // // replace www to notionID + // const {notionUser} = this.plugin.settings; + // + // if (notionUser !== "") { + // // replace url str "www" to notionID + // url = url.replace("www.notion.so", `${notionUser}.notion.site`) + // } + // + // await app.fileManager.processFrontMatter(nowFile, yamlContent => { + // if (yamlContent['notionID']) { + // delete yamlContent['notionID'] + // } + // if (yamlContent['link']) { + // delete yamlContent['link'] + // } + // // add new notionID and link + // yamlContent.notionID = id; + // yamlContent.link = url; + // }); + // + // try { + // await navigator.clipboard.writeText(url) + // } catch (error) { + // new Notice(`复制链接失败,请手动复制${error}`) + // } + // // const __content = yamlContent.__content; + // // delete yamlContent.__content + // // const yamlhead = yaml.stringify(yamlContent) + // // // if yamlhead hava last \n remove it + // // const yamlhead_remove_n = yamlhead.replace(/\n$/, '') + // // // if __content have start \n remove it + // // const __content_remove_n = __content.replace(/^\n/, '') + // // const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n; + // // try { + // // await nowFile.vault.modify(nowFile, content) + // // } catch (error) { + // // new Notice(`write file error ${error}`) + // // } + // } +} diff --git a/src/upload/upload_general/Upload2NotionGeneral.ts b/src/upload/upload_general/Upload2NotionGeneral.ts new file mode 100644 index 0000000..a73bfb1 --- /dev/null +++ b/src/upload/upload_general/Upload2NotionGeneral.ts @@ -0,0 +1,144 @@ +import { App, Notice, requestUrl, TFile } from "obsidian"; +import { Client } from '@notionhq/client'; +import { markdownToBlocks, } from "@tryfabric/martian"; +import * as yamlFrontMatter from "yaml-front-matter"; +// import * as yaml from "yaml" +import MyPlugin from "src/main"; +import {PluginSettings} from "../../ui/settingTabs"; +import {UploadBaseGeneral} from "./BaseUpload2NotionGeneral"; +import {updateYamlInfo} from "../updateYaml"; + +export class Upload2NotionGeneral extends UploadBaseGeneral { + settings: PluginSettings; + + constructor(plugin: MyPlugin) { + super(plugin); + } + + // 因为需要解析notion的block进行对比,非常的麻烦, + // 暂时就直接删除,新建一个page + async updatePage( + notionID: string, + title: string, + cover: string, + tags: string[], + childArr: any + ) { + await this.deletePage(notionID) + + const databasecover = await this.getDataBase(this.plugin.settings.databaseIDGeneral) + + if (cover == null) { + cover = databasecover + } + + return await this.createPage( + title, + cover, + tags, + childArr) + } + + async createPage( + title: string, + cover: string, + tags: string[], + childArr: any + ) { + const bodyString: any = { + parent: { + database_id: this.plugin.settings.databaseIDGeneral, + }, + properties: { + title: { + title: [ + { + text: { + content: title + }, + }, + ], + }, + tags: { + multi_select: tags && true ? tags.map(tag => { + return { "name": tag } + }) : [], + }, + }, + children: childArr, + } + + if (cover) { + bodyString.cover = { + type: "external", + external: { + url: cover + } + } + } + + if (!bodyString.cover && this.plugin.settings.bannerUrl) { + bodyString.cover = { + type: "external", + external: { + url: this.plugin.settings.bannerUrl + } + } + } + + try { + return await requestUrl({ + url: `https://api.notion.com/v1/pages`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + // 'User-Agent': 'obsidian.md', + 'Authorization': 'Bearer ' + this.plugin.settings.notionAPIGeneral, + 'Notion-Version': '2022-06-28', + }, + body: JSON.stringify(bodyString), + }) + } catch (error) { + new Notice(`network error ${error}`) + } + } + + async syncMarkdownToNotionGeneral( + title: string, + cover: string, + tags: string[], + markdown: string, + nowFile: TFile, + app: App, + ): Promise { + let res: any + const yamlContent: any = yamlFrontMatter.loadFront(markdown); + const __content = yamlContent.__content + const file2Block = markdownToBlocks(__content); + const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter + const notionID = frontmasster ? frontmasster.notionID : null + + if (notionID) { + res = await this.updatePage( + notionID, + title, + cover, + tags, + file2Block + ); + } else { + res = await this.createPage( + title, + cover, + tags, + file2Block + ); + } + if (res.status === 200) { + await updateYamlInfo(markdown, nowFile, res, app, this.plugin) + } else { + new Notice(`${res.text}`) + } + return res + } +} diff --git a/src/upload/upload_general/getMarkdownGeneral.ts b/src/upload/upload_general/getMarkdownGeneral.ts new file mode 100644 index 0000000..f035727 --- /dev/null +++ b/src/upload/upload_general/getMarkdownGeneral.ts @@ -0,0 +1,33 @@ +import {App, Notice} from "obsidian"; +import {i18nConfig} from "../../lang/I18n"; +import {PluginSettings} from "../../ui/settingTabs"; + +export async function getNowFileMarkdownContentGeneral( + app: App, + settings: PluginSettings, +) { + const nowFile = app.workspace.getActiveFile(); + let cover = ''; + let tags = []; + + const FileCache = app.metadataCache.getFileCache(nowFile); + try { + cover = FileCache.frontmatter.coverurl; + tags = FileCache.frontmatter.tags; + } catch (error) { + new Notice(i18nConfig["set-tags-fail"]); + } + + if (nowFile) { + const markDownData = await nowFile.vault.read(nowFile); + return { + markDownData, + nowFile, + cover, + tags, + }; + } else { + new Notice(i18nConfig["open-file"]); + return; + } +} diff --git a/src/upload/upload_next/BaseUpload2NotionNext.ts b/src/upload/upload_next/BaseUpload2NotionNext.ts new file mode 100644 index 0000000..1dd0feb --- /dev/null +++ b/src/upload/upload_next/BaseUpload2NotionNext.ts @@ -0,0 +1,90 @@ +import {App, Notice, requestUrl, TFile} from "obsidian"; +import {Client} from '@notionhq/client'; +import {markdownToBlocks,} from "@tryfabric/martian"; +import * as yamlFrontMatter from "yaml-front-matter"; +// import * as yaml from "yaml" +import MyPlugin from "src/main"; + +export class UploadBaseNext { + plugin: MyPlugin; + notion: Client; + agent: any; + + constructor(plugin: MyPlugin) { + this.plugin = plugin; + } + + async deletePage(notionID: string) { + return requestUrl({ + url: `https://api.notion.com/v1/blocks/${notionID}`, + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext, + 'Notion-Version': '2022-06-28', + }, + body: '' + }); + } + + async getDataBase(databaseID: string) { + const response = await requestUrl({ + url: `https://api.notion.com/v1/databases/${databaseID}`, + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext, + 'Notion-Version': '2022-06-28', + } + } + ) + + // Check if cover is present in the JSON response and then get the URL + if (response.json.cover && response.json.cover.external) { + return response.json.cover.external.url; + } else { + return null; // or some other default value, if you prefer + } + } + + // async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) { + // let {url, id} = res.json + // // replace www to notionID + // const { notionUser} = this.plugin.settings; + // + // if (notionUser !== "") { + // // replace url str "www" to notionID + // url = url.replace("www.notion.so", `${notionUser}.notion.site`) + // } + // + // await app.fileManager.processFrontMatter(nowFile, yamlContent => { + // if (yamlContent['notionID']) { + // delete yamlContent['notionID'] + // } + // if (yamlContent['link']) { + // delete yamlContent['link'] + // } + // // add new notionID and link + // yamlContent.notionID = id; + // yamlContent.link = url; + // }); + // + // try { + // await navigator.clipboard.writeText(url) + // } catch (error) { + // new Notice(`复制链接失败,请手动复制${error}`) + // } + // // const __content = yamlContent.__content; + // // delete yamlContent.__content + // // const yamlhead = yaml.stringify(yamlContent) + // // // if yamlhead hava last \n remove it + // // const yamlhead_remove_n = yamlhead.replace(/\n$/, '') + // // // if __content have start \n remove it + // // const __content_remove_n = __content.replace(/^\n/, '') + // // const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n; + // // try { + // // await nowFile.vault.modify(nowFile, content) + // // } catch (error) { + // // new Notice(`write file error ${error}`) + // // } + // } +} diff --git a/src/upload/Upload2NotionNext.ts b/src/upload/upload_next/Upload2NotionNext.ts similarity index 68% rename from src/upload/Upload2NotionNext.ts rename to src/upload/upload_next/Upload2NotionNext.ts index f042275..f757912 100644 --- a/src/upload/Upload2NotionNext.ts +++ b/src/upload/upload_next/Upload2NotionNext.ts @@ -1,24 +1,41 @@ -import {UploadBase} from "./BaseUpload2Notion"; +import { UploadBaseNext } from "./BaseUpload2NotionNext"; import { App, Notice, requestUrl, TFile } from "obsidian"; import { Client } from '@notionhq/client'; import { markdownToBlocks, } from "@tryfabric/martian"; import * as yamlFrontMatter from "yaml-front-matter"; // import * as yaml from "yaml" import MyPlugin from "src/main"; -import {PluginSettings} from "../ui/settingTabs"; +import {PluginSettings} from "../../ui/settingTabs"; +import {updateYamlInfo} from "../updateYaml"; -export class Upload2NotionNext extends UploadBase { +export class Upload2NotionNext extends UploadBaseNext { settings: PluginSettings; + constructor(plugin: MyPlugin) { super(plugin); } // 因为需要解析notion的block进行对比,非常的麻烦, // 暂时就直接删除,新建一个page - async updatePage(notionID: string, title: string, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, paword: string, favicon: string, datetime: string, childArr: any) { + async updatePage( + notionID: string, + title: string, + emoji: string, + cover: string, + tags: string[], + type: string, + slug: string, + stats: string, + category: string, + summary: string, + paword: string, + favicon: string, + datetime: string, + childArr: any + ) { await this.deletePage(notionID) - const databasecover = await this.getDataBase(this.plugin.settings.databaseID) + const databasecover = await this.getDataBase(this.plugin.settings.databaseIDNext) if (cover == null) { cover = databasecover @@ -40,10 +57,24 @@ export class Upload2NotionNext extends UploadBase { childArr) } - async createPage(title: string, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, pawrod: string, favicon: string, datetime: string, childArr: any) { + async createPage( + title: string, + emoji: string, + cover: string, + tags: string[], + type: string, + slug: string, + stats: string, + category: string, + summary: string, + pawrod: string, + favicon: string, + datetime: string, + childArr: any + ) { const bodyString: any = { parent: { - database_id: this.plugin.settings.databaseID + database_id: this.plugin.settings.databaseIDNext }, icon: { emoji: emoji || '📜' @@ -147,7 +178,7 @@ export class Upload2NotionNext extends UploadBase { headers: { 'Content-Type': 'application/json', // 'User-Agent': 'obsidian.md', - 'Authorization': 'Bearer ' + this.plugin.settings.notionAPI, + 'Authorization': 'Bearer ' + this.plugin.settings.notionAPINext, 'Notion-Version': '2022-06-28', }, body: JSON.stringify(bodyString), @@ -157,7 +188,23 @@ export class Upload2NotionNext extends UploadBase { } } - async syncMarkdownToNotionNext(title: string, emoji: string, cover: string, tags: string[], type: string, slug: string, stats: string, category: string, summary: string, paword: string, favicon: string, datetime: string, markdown: string, nowFile: TFile, app: App, settings: PluginSettings): Promise { + async syncMarkdownToNotionNext( + title: string, + emoji: string, + cover: string, + tags: string[], + type: string, + slug: string, + stats: string, + category: string, + summary: string, + paword: string, + favicon: string, + datetime: string, + markdown: string, + nowFile: TFile, + app: App, + ): Promise { let res: any const yamlContent: any = yamlFrontMatter.loadFront(markdown); const __content = yamlContent.__content @@ -166,12 +213,41 @@ export class Upload2NotionNext extends UploadBase { const notionID = frontmasster ? frontmasster.notionID : null if (notionID) { - res = await this.updatePage(notionID, title, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block); + res = await this.updatePage( + notionID, + title, + emoji, + cover, + tags, + type, + slug, + stats, + category, + summary, + paword, + favicon, + datetime, + file2Block + ); } else { - res = await this.createPage(title, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, file2Block); + res = await this.createPage( + title, + emoji, + cover, + tags, + type, + slug, + stats, + category, + summary, + paword, + favicon, + datetime, + file2Block + ); } if (res.status === 200) { - await this.updateYamlInfo(markdown, nowFile, res, app, settings) + await updateYamlInfo(markdown, nowFile, res, app, this.plugin) } else { new Notice(`${res.text}`) } diff --git a/src/upload/getMarkdown.ts b/src/upload/upload_next/getMarkdownNext.ts similarity index 87% rename from src/upload/getMarkdown.ts rename to src/upload/upload_next/getMarkdownNext.ts index 8ee3406..f4b04c6 100644 --- a/src/upload/getMarkdown.ts +++ b/src/upload/upload_next/getMarkdownNext.ts @@ -1,13 +1,12 @@ import {App, Notice} from "obsidian"; -import {i18nConfig} from "../lang/I18n"; -import {PluginSettings} from "../ui/settingTabs"; +import {i18nConfig} from "../../lang/I18n"; +import {PluginSettings} from "../../ui/settingTabs"; -export async function getNowFileMarkdownContent( +export async function getNowFileMarkdownContentNext( app: App, settings: PluginSettings, ) { const nowFile = app.workspace.getActiveFile(); - const {NNon} = settings; // Change this line let emoji = ''; let cover = ''; let tags = []; @@ -22,7 +21,6 @@ export async function getNowFileMarkdownContent( const FileCache = app.metadataCache.getFileCache(nowFile); try { - if (NNon) { emoji = FileCache.frontmatter.titleicon; cover = FileCache.frontmatter.coverurl; tags = FileCache.frontmatter.tags; @@ -34,7 +32,6 @@ export async function getNowFileMarkdownContent( paword = FileCache.frontmatter.password; favicon = FileCache.frontmatter.icon; datetime = FileCache.frontmatter.date; - } } catch (error) { new Notice(i18nConfig["set-tags-fail"]); }