add function: save attachment files

This commit is contained in:
wanxp 2022-11-11 20:02:36 +08:00
parent 556788ee75
commit 1a98def0d5
13 changed files with 170 additions and 21 deletions

35
main.ts

@ -17,6 +17,7 @@ import { DoubanPluginSetting } from "@App/setting/model/DoubanPluginSetting";
import {DEFAULT_SETTINGS} from "./src/constant/DefaultSettings"; import {DEFAULT_SETTINGS} from "./src/constant/DefaultSettings";
import UserComponent from "@App/user/UserComponent"; import UserComponent from "@App/user/UserComponent";
import SettingsManager from "@App/setting/SettingsManager"; import SettingsManager from "@App/setting/SettingsManager";
import NetFileHandler from "./src/net/NetFileHandler";
export default class DoubanPlugin extends Plugin { export default class DoubanPlugin extends Plugin {
public settings: DoubanPluginSetting; public settings: DoubanPluginSetting;
@ -25,6 +26,7 @@ export default class DoubanPlugin extends Plugin {
public fileHandler: FileHandler; public fileHandler: FileHandler;
public userComponent: UserComponent; public userComponent: UserComponent;
public settingsManager: SettingsManager; public settingsManager: SettingsManager;
public netFileHandler: NetFileHandler;
async putToObsidian(context: HandleContext, extract: DoubanSubject) { async putToObsidian(context: HandleContext, extract: DoubanSubject) {
@ -111,28 +113,39 @@ export default class DoubanPlugin extends Plugin {
id: "search-douban-import-and-create-file", id: "search-douban-import-and-create-file",
name: i18nHelper.getMessage("110101"), name: i18nHelper.getMessage("110101"),
callback: () => callback: () =>
this.getDoubanTextForCreateNewNote({mode: SearchHandleMode.FOR_CREATE, settings: this.settings, userComponent: this.userComponent}), this.getDoubanTextForCreateNewNote({mode: SearchHandleMode.FOR_CREATE,
settings: this.settings,
userComponent: this.userComponent,
netFileHandler: this.netFileHandler}),
});
this.addCommand({
id: "search-douban-and-input-current-file",
name: i18nHelper.getMessage("110002"),
editorCallback: (editor: Editor) =>
this.getDoubanTextForSearchTerm({mode: SearchHandleMode.FOR_REPLACE,
settings: this.settings,
editor: editor,
userComponent: this.userComponent,
netFileHandler: this.netFileHandler}),
}); });
this.addCommand({ this.addCommand({
id: "search-douban-by-current-file-name", id: "search-douban-by-current-file-name",
name: i18nHelper.getMessage("110001"), name: i18nHelper.getMessage("110001"),
editorCallback: (editor: Editor) => editorCallback: (editor: Editor) =>
this.getDoubanTextForActiveFile({mode: SearchHandleMode.FOR_REPLACE, settings: this.settings, editor: editor, userComponent: this.userComponent}), this.getDoubanTextForActiveFile({mode: SearchHandleMode.FOR_REPLACE,
settings: this.settings,
editor: editor,
userComponent: this.userComponent,
netFileHandler: this.netFileHandler}),
}); });
this.addCommand({
id: "search-douban-and-input-current-file",
name: i18nHelper.getMessage("110002"),
editorCallback: (editor: Editor) =>
this.getDoubanTextForSearchTerm({mode: SearchHandleMode.FOR_REPLACE, settings: this.settings, editor: editor, userComponent: this.userComponent}),
});
this.settingsManager = new SettingsManager(app, this); this.settingsManager = new SettingsManager(app, this);
this.userComponent = new UserComponent(this.settingsManager); this.userComponent = new UserComponent(this.settingsManager);
this.netFileHandler = new NetFileHandler(this.fileHandler);
if (this.userComponent.needLogin()) { if (this.userComponent.needLogin()) {
this.userComponent.loginByCookie(); await this.userComponent.loginByCookie();
} }
this.addSettingTab(new DoubanSettingTab(this.app, this)); this.addSettingTab(new DoubanSettingTab(this.app, this));

@ -27,4 +27,6 @@ export const DEFAULT_SETTINGS: DoubanPluginSetting = {
{name: 'myType', value: 'teleplay', field: SupportType.TELEPLAY}, {name: 'myType', value: 'teleplay', field: SupportType.TELEPLAY},
], ],
loginCookiesContent: '', loginCookiesContent: '',
cacheImage: true,
attachmentPath: 'assets',
} }

@ -57,7 +57,7 @@ export default class DoubanLoginModel {
try { try {
await this.modal.loadURL('https://accounts.douban.com/passport/login'); await this.modal.loadURL('https://accounts.douban.com/passport/login');
} catch (error) { } catch (error) {
log.error('加载豆瓣登录页面失败') log.error(i18nHelper.getMessage('100101'), error)
} }
} }

@ -33,6 +33,7 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
async parse(extract: T, context: HandleContext): Promise<HandleResult> { async parse(extract: T, context: HandleContext): Promise<HandleResult> {
let template: string = await this.getTemplate(extract, context); let template: string = await this.getTemplate(extract, context);
await this.saveImage(extract, context);
let frontMatterStart: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, 0); let frontMatterStart: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, 0);
let frontMatterEnd: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, frontMatterStart + 1); let frontMatterEnd: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, frontMatterStart + 1);
let frontMatter: string = ''; let frontMatter: string = '';
@ -388,4 +389,20 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
return v.UNKNOWN; return v.UNKNOWN;
} }
} }
private async saveImage(extract: T, context: HandleContext) {
if (!extract.image || !context.settings.cacheImage) {
return;
}
let image = extract.image;
const filename = image.split('/').pop();
let folder = context.settings.attachmentPath;
if (!folder) {
folder = DEFAULT_SETTINGS.attachmentPath;
}
const {success, filepath} = await context.netFileHandler.downloadFile(image, folder, filename);
if (success) {
extract.image = filepath;
}
}
} }

@ -2,10 +2,12 @@ import {SearchHandleMode} from "../../../constant/Constsant";
import {Editor} from "obsidian"; import {Editor} from "obsidian";
import { DoubanPluginSetting } from "@App/setting/model/DoubanPluginSetting"; import { DoubanPluginSetting } from "@App/setting/model/DoubanPluginSetting";
import UserComponent from "@App/user/UserComponent"; import UserComponent from "@App/user/UserComponent";
import NetFileHandler from "src/net/NetFileHandler";
export default interface HandleContext { export default interface HandleContext {
mode:SearchHandleMode; mode:SearchHandleMode;
settings: DoubanPluginSetting; settings: DoubanPluginSetting;
editor?:Editor; editor?:Editor;
userComponent: UserComponent; userComponent: UserComponent;
netFileHandler: NetFileHandler;
} }

@ -5,6 +5,7 @@ import SettingsManager from "@App/setting/SettingsManager";
import DoubanLoginModel from "@App/component/DoubanLoginModel"; import DoubanLoginModel from "@App/component/DoubanLoginModel";
import DoubanLogoutModel from "@App/component/DoubanLogoutModel"; import DoubanLogoutModel from "@App/component/DoubanLogoutModel";
import User from "@App/user/User"; import User from "@App/user/User";
import {createFolderSelectionSetting} from "@App/setting/TemplateSettingHelper";
export function constructBasicUI(containerEl: HTMLElement, manager: SettingsManager) { export function constructBasicUI(containerEl: HTMLElement, manager: SettingsManager) {
containerEl.createEl('h3', { text: i18nHelper.getMessage('1210') }); containerEl.createEl('h3', { text: i18nHelper.getMessage('1210') });
@ -94,6 +95,8 @@ export function constructBasicUI(containerEl: HTMLElement, manager: SettingsMana
await manager.plugin.saveSettings(); await manager.plugin.saveSettings();
}); });
}); });
} }
export function constructDoubanTokenSettingsUI(containerEl: HTMLElement, manager: SettingsManager) { export function constructDoubanTokenSettingsUI(containerEl: HTMLElement, manager: SettingsManager) {
@ -165,10 +168,10 @@ function showMobileLogout(containerEl: HTMLElement, manager: SettingsManager) {
const user: User = manager.plugin.userComponent.getUser(); const user: User = manager.plugin.userComponent.getUser();
let userDom = new DocumentFragment(); let userDom = new DocumentFragment();
userDom.createDiv().innerHTML = userDom.createDiv().innerHTML =
`已登录<br> `${i18nHelper.getMessage('100120')}<br>
ID: <a href="https://www.douban.com/people/${user.id}/">${user.id}</a><br> ${i18nHelper.getMessage('100123')}: <a href="https://www.douban.com/people/${user.id}/">${user.id}</a><br>
昵称: ${user.name}<br> ${i18nHelper.getMessage('100124')}: ${user.name}<br>
使,.`; ${i18nHelper.getMessage('100125')}`;
new Setting(containerEl) new Setting(containerEl)
.setName(i18nHelper.getMessage('100126')) .setName(i18nHelper.getMessage('100126'))
.setDesc(userDom) .setDesc(userDom)

@ -7,8 +7,14 @@ import SettingsManager from "@App/setting/SettingsManager";
export function constructOutUI(containerEl: HTMLElement, manager: SettingsManager) { export function constructOutUI(containerEl: HTMLElement, manager: SettingsManager) {
containerEl.createEl('h3', { text: i18nHelper.getMessage('1220') }); containerEl.createEl('h3', { text: i18nHelper.getMessage('1220') });
new Setting(containerEl);
let attachmentFileSetting = containerEl.createDiv({ cls: 'settings-item-attachment' });
constructAttachmentFileSettingsUI(attachmentFileSetting, manager);
new Setting(containerEl).then(createFolderSelectionSetting({name: '121501', desc: '121502', placeholder: '121503', key: 'dataFilePath', manager: manager})); new Setting(containerEl).then(createFolderSelectionSetting({name: '121501', desc: '121502', placeholder: '121503', key: 'dataFilePath', manager: manager}));
let outfolder = containerEl.createDiv({ cls: 'settings-item' }); let outfolder = containerEl.createDiv({ cls: 'settings-item' });
constructOutFolderUI(outfolder, manager); constructOutFolderUI(outfolder, manager);
new Setting(containerEl) new Setting(containerEl)
@ -76,3 +82,25 @@ export function constructOutFolderUI(containerEl: HTMLElement, manager: Settings
}); });
}) })
} }
export function constructAttachmentFileSettingsUI(containerEl: HTMLElement, manager: SettingsManager) {
containerEl.empty();
new Setting(containerEl)
.setName(i18nHelper.getMessage('121430'))
.setDesc(i18nHelper.getMessage('121431'))
.addToggle((toggleComponent) => {
toggleComponent
// .setTooltip(i18nHelper.getMessage('121403'))
.setValue(manager.plugin.settings.cacheImage)
.onChange(async (value) => {
manager.plugin.settings.cacheImage = value;
await manager.plugin.saveSettings();
constructAttachmentFileSettingsUI(containerEl, manager);
});
});
if(manager.plugin.settings.cacheImage) {
new Setting(containerEl).then(createFolderSelectionSetting({name: '121432', desc: '121433', placeholder: '121434', key: 'attachmentPath', manager: manager}));
}
}

@ -269,6 +269,6 @@ ${i18nHelper.getMessage('160225')}
` `
; ;
new Setting(containerEl) new Setting(containerEl)
.setName(i18nHelper.getMessage('122002')) .setName(i18nHelper.getMessage('122010'))
.setDesc(userInfoVariables); .setDesc(userInfoVariables);
} }

@ -18,5 +18,6 @@ export interface DoubanPluginSetting {
statusBar: boolean, statusBar: boolean,
customProperties: CustomProperty[], customProperties: CustomProperty[],
loginCookiesContent: string, loginCookiesContent: string,
cacheImage: boolean,
attachmentPath: string,
} }

@ -68,6 +68,36 @@ export default class FileHandler {
} }
/**
* Handles creating the new note
* A new markdown file will be created at the given file path (`input`)
* in the specified parent folder (`this.folder`)
*/
async creatAttachmentWithData(originalFilePath: string, data:ArrayBuffer): Promise<void> {
const {vault} = this._app;
const {adapter} = vault;
const prependDirInput = FileUtil.join("", originalFilePath);
const {dir, name} = FileUtil.parse(prependDirInput);
const filePath = FileUtil.join(dir, `${name}`);
try {
const fileExists = await adapter.exists(filePath);
if (fileExists) {
// If the file already exists, respond with error
// throw new Error(i18nHelper.getMessage('110201').replace('{0}', filePath??''));
return ;
}
if (dir !== '') {
// If `input` includes a directory part, create it
await this.createDirectory(dir);
}
await vault.createBinary(filePath, data);
// Create the file and open it in the active leaf
} catch (error) {
log.error(error.toString(), error);
}
}
/** /**
* Handles creating the new note * Handles creating the new note
* A new markdown file will be created at the given file path (`input`) * A new markdown file will be created at the given file path (`input`)

@ -37,6 +37,7 @@ export default {
'100129': `You have not login Douban, please login in computer first! After login, you can use your rating and reading status, see the last for specific variables.`, '100129': `You have not login Douban, please login in computer first! After login, you can use your rating and reading status, see the last for specific variables.`,
'100130': `Login`, '100130': `Login`,
'100131': `Login Douban`, '100131': `Login Douban`,
'100132': `Load Douban Login Page Failed`,
'1210': `Basic Setting`, '1210': `Basic Setting`,
@ -130,6 +131,13 @@ export default {
'121401': `Status Bar`, '121401': `Status Bar`,
'121402': `Display status bar when import data ?`, '121402': `Display status bar when import data ?`,
'121430': `Save Attachment File`,
'121431': `Save attachment file to local disk, such as image ?`,
'121432': `Attachment folder`,
'121433': `Attachment file created from Obsidian-Douban will be placed in this folder, If blank, they will be placed in the default location for this vault.`,
'121434': `assets`,
'121501': `Note folder`, '121501': `Note folder`,
'121502': `Nodes created from Obsidian-Douban will be placed in this folder, If blank, they will be placed in the default location for this vault. `, '121502': `Nodes created from Obsidian-Douban will be placed in this folder, If blank, they will be placed in the default location for this vault. `,
'121503': `Default Folder`, '121503': `Default Folder`,
@ -175,6 +183,7 @@ export default {
'122002': `Extra Variables`, '122002': `Extra Variables`,
'122003': `Basic Variables must has value, Extra Variables can be empty`, '122003': `Basic Variables must has value, Extra Variables can be empty`,
'122004': `To use the template variables, you need to wrap them in double curly brackets. For example, {{title}} will be replaced with the title of the note.`, '122004': `To use the template variables, you need to wrap them in double curly brackets. For example, {{title}} will be replaced with the title of the note.`,
'122010': `My State Variables`,

@ -28,7 +28,7 @@ export default {
'100129': `豆瓣未登录,请先在电脑端登录!登录后导入参数可使用你的评分以及阅读状态等,具体可用参数见最后.`, '100129': `豆瓣未登录,请先在电脑端登录!登录后导入参数可使用你的评分以及阅读状态等,具体可用参数见最后.`,
'100130': `登录`, '100130': `登录`,
'100131': `登录豆瓣`, '100131': `登录豆瓣`,
'100132': `加载豆瓣登录页面失败`,
@ -138,8 +138,15 @@ export default {
'121401': `状态栏`, '121401': `状态栏`,
'121402': `当在导入数据时, 是否需要在状态栏显示处理状态? `, '121402': `当在导入数据时, 是否需要在状态栏显示处理状态? `,
'121430': `保存图片附件`,
'121431': `导入数据会同步保存图片附件到本地文件夹, 如电影封面,书籍封面 `,
'121432': `附件存放位置`,
'121433': `保存的附件将会存放至该文件夹中. 如果为空, 笔记将会存放到默认位置(assets) `,
'121434': `assets`,
'121501': `笔记存放位置`, '121501': `笔记存放位置`,
'121502': `创建的笔记将会存放导该文件夹中. 如果为空, 笔记将会存放到Obsidian的默认位置`, '121502': `创建的笔记将会存放该文件夹中. 如果为空, 笔记将会存放到Obsidian的默认位置`,
'121601': `笔记名称`, '121601': `笔记名称`,
'121602': `创建的笔记将会使用此名称作为模板, 支持所有'通用'的参数作为名称(如:{{type}}/{{title}}), 且支持路径, 比如: 'MyData/{{title}}'. 如果为空, 笔记将会使用默认名称. `, '121602': `创建的笔记将会使用此名称作为模板, 支持所有'通用'的参数作为名称(如:{{type}}/{{title}}), 且支持路径, 比如: 'MyData/{{title}}'. 如果为空, 笔记将会使用默认名称. `,
@ -197,7 +204,7 @@ export default {
'122002': `扩展参数`, '122002': `扩展参数`,
'122003': `通用参数一定有值不为空, 扩展参数可能为空`, '122003': `通用参数一定有值不为空, 扩展参数可能为空`,
'122004': `以下参数使用时请用'{{}}'包裹, 举例: 参数title, 则使用时为{{title}}. `, '122004': `以下参数使用时请用'{{}}'包裹, 举例: 参数title, 则使用时为{{title}}. `,
'122010': `我的状态参数`,
'410101': `其他`, '410101': `其他`,
'410102': `未知`, '410102': `未知`,

37
src/net/NetFileHandler.ts Normal file

@ -0,0 +1,37 @@
import { requestUrl, RequestUrlParam} from "obsidian";
import {log} from "../utils/Logutil";
import {i18nHelper} from "../lang/helper";
import FileHandler from "../file/FileHandler";
import {FileUtil} from "../utils/FileUtil";
export default class NetFileHandler {
private fileHandler: FileHandler;
constructor(fileHandler: FileHandler) {
this.fileHandler = fileHandler;
}
async downloadFile(url: string, folder:string, filename: string): Promise<{ success: boolean, error:string, filepath: string }> {
const requestUrlParam: RequestUrlParam = {
url: url,
method: "GET",
throw: true,
headers: {}
};
const filePath:string = FileUtil.join(folder, filename);
return requestUrl(requestUrlParam)
.then((response) => {
this.fileHandler.creatAttachmentWithData(filePath, response.arrayBuffer);
}).then(() => {
return {success: true, error: '', filepath: filePath};
})
.catch(e => log
.error(
i18nHelper.getMessage('130101')
.replace('{0}', e.toString())
, e));
;
}
}