Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6790bb01d3 | ||
|
|
131f3f70e1 | ||
|
|
b551e0c1b5 | ||
|
|
c65c0aa258 | ||
|
|
1f0030b514 | ||
|
|
07896f92a3 | ||
|
|
9eddfb02d6 | ||
|
|
f0dd3bb5ef |
@@ -4,7 +4,7 @@ This is yet another unofficial sync plugin for Obsidian. If you like it or find
|
|||||||
|
|
||||||
[](https://github.com/fyears/remotely-save/actions/workflows/auto-build.yml)
|
[](https://github.com/fyears/remotely-save/actions/workflows/auto-build.yml)
|
||||||
|
|
||||||
[](https://github.com/fyears/remotely-save/releases) [](https://github.com/fyears/remotely-save/releases) [](https://github.com/fyears/remotely-save/releases)
|
[](https://github.com/fyears/remotely-save/releases)
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "remotely-save",
|
"id": "remotely-save",
|
||||||
"name": "Remotely Save",
|
"name": "Remotely Save",
|
||||||
"version": "0.2.8",
|
"version": "0.2.10",
|
||||||
"minAppVersion": "0.12.15",
|
"minAppVersion": "0.12.15",
|
||||||
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
|
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
|
||||||
"author": "fyears",
|
"author": "fyears",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "remotely-save",
|
"name": "remotely-save",
|
||||||
"version": "0.2.8",
|
"version": "0.2.10",
|
||||||
"description": "This is yet another sync plugin for Obsidian app.",
|
"description": "This is yet another sync plugin for Obsidian app.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node esbuild.config.mjs",
|
"dev": "node esbuild.config.mjs",
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { base64, base64url } from "rfc4648";
|
||||||
|
import { reverseString } from "./misc";
|
||||||
|
|
||||||
|
import type { RemotelySavePluginSettings } from "./baseTypes";
|
||||||
|
|
||||||
|
import * as origLog from "loglevel";
|
||||||
|
const log = origLog.getLogger("rs-default");
|
||||||
|
|
||||||
|
const DEFAULT_README: string =
|
||||||
|
"Do NOT modify this manually. It's generated automatically.";
|
||||||
|
|
||||||
|
interface MessyConfigType {
|
||||||
|
readme: string;
|
||||||
|
d: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this should accept the result after loadData();
|
||||||
|
*/
|
||||||
|
export const messyConfigToNormal = (
|
||||||
|
x: MessyConfigType | RemotelySavePluginSettings | null | undefined
|
||||||
|
): RemotelySavePluginSettings | null | undefined => {
|
||||||
|
log.debug("loading, original config on disk:");
|
||||||
|
log.debug(x);
|
||||||
|
if (x === null || x === undefined) {
|
||||||
|
log.debug("the messy config is null or undefined, skip");
|
||||||
|
return x as any;
|
||||||
|
}
|
||||||
|
if ("readme" in x && "d" in x) {
|
||||||
|
// we should decode
|
||||||
|
const y = JSON.parse(
|
||||||
|
(
|
||||||
|
base64url.parse(reverseString(x["d"]), {
|
||||||
|
out: Buffer.allocUnsafe as any,
|
||||||
|
loose: true,
|
||||||
|
}) as Buffer
|
||||||
|
).toString("utf-8")
|
||||||
|
);
|
||||||
|
log.debug("loading, parsed config is:");
|
||||||
|
log.debug(y);
|
||||||
|
return y;
|
||||||
|
} else {
|
||||||
|
// return as is
|
||||||
|
log.debug("loading, parsed config is the same");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this should accept the result of original config
|
||||||
|
*/
|
||||||
|
export const normalConfigToMessy = (
|
||||||
|
x: RemotelySavePluginSettings | null | undefined
|
||||||
|
) => {
|
||||||
|
if (x === null || x === undefined) {
|
||||||
|
log.debug("the normal config is null or undefined, skip");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
const y = {
|
||||||
|
readme: DEFAULT_README,
|
||||||
|
d: reverseString(
|
||||||
|
base64url.stringify(Buffer.from(JSON.stringify(x), "utf-8"), {
|
||||||
|
pad: false,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
};
|
||||||
|
log.debug("encoding, encoded config is:");
|
||||||
|
log.debug(y);
|
||||||
|
return y;
|
||||||
|
};
|
||||||
+3
-2
@@ -34,6 +34,7 @@ import { DEFAULT_WEBDAV_CONFIG } from "./remoteForWebdav";
|
|||||||
import { RemotelySaveSettingTab } from "./settings";
|
import { RemotelySaveSettingTab } from "./settings";
|
||||||
import type { SyncStatusType } from "./sync";
|
import type { SyncStatusType } from "./sync";
|
||||||
import { doActualSync, getSyncPlan, isPasswordOk } from "./sync";
|
import { doActualSync, getSyncPlan, isPasswordOk } from "./sync";
|
||||||
|
import { messyConfigToNormal, normalConfigToMessy } from "./configPersist";
|
||||||
|
|
||||||
import * as origLog from "loglevel";
|
import * as origLog from "loglevel";
|
||||||
const log = origLog.getLogger("rs-default");
|
const log = origLog.getLogger("rs-default");
|
||||||
@@ -384,7 +385,7 @@ export default class RemotelySavePlugin extends Plugin {
|
|||||||
this.settings = Object.assign(
|
this.settings = Object.assign(
|
||||||
{},
|
{},
|
||||||
cloneDeep(DEFAULT_SETTINGS),
|
cloneDeep(DEFAULT_SETTINGS),
|
||||||
await this.loadData()
|
messyConfigToNormal(await this.loadData())
|
||||||
);
|
);
|
||||||
if (this.settings.dropbox.clientID === "") {
|
if (this.settings.dropbox.clientID === "") {
|
||||||
this.settings.dropbox.clientID = DEFAULT_SETTINGS.dropbox.clientID;
|
this.settings.dropbox.clientID = DEFAULT_SETTINGS.dropbox.clientID;
|
||||||
@@ -398,7 +399,7 @@ export default class RemotelySavePlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async saveSettings() {
|
async saveSettings() {
|
||||||
await this.saveData(this.settings);
|
await this.saveData(normalConfigToMessy(this.settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkIfOauthExpires() {
|
async checkIfOauthExpires() {
|
||||||
|
|||||||
@@ -199,3 +199,12 @@ export const getRandomArrayBuffer = (byteLength: number) => {
|
|||||||
const k = window.crypto.getRandomValues(new Uint8Array(byteLength));
|
const k = window.crypto.getRandomValues(new Uint8Array(byteLength));
|
||||||
return bufferToArrayBuffer(k);
|
return bufferToArrayBuffer(k);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://stackoverflow.com/questions/958908
|
||||||
|
* @param x
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const reverseString = (x: string) => {
|
||||||
|
return [...x].reverse().join("");
|
||||||
|
};
|
||||||
|
|||||||
@@ -120,6 +120,21 @@ class DropboxAuthModal extends Modal {
|
|||||||
contentEl.createEl("p", {
|
contentEl.createEl("p", {
|
||||||
text: "Finally you should be redirected to Obsidian.",
|
text: "Finally you should be redirected to Obsidian.",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const div2 = contentEl.createDiv();
|
||||||
|
div2.createEl(
|
||||||
|
"button",
|
||||||
|
{
|
||||||
|
text: "Click to copy the auth url",
|
||||||
|
},
|
||||||
|
(el) => {
|
||||||
|
el.onclick = async () => {
|
||||||
|
await navigator.clipboard.writeText(authUrl);
|
||||||
|
new Notice("the auth url copied to clipboard!");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
contentEl.createEl("p").createEl("a", {
|
contentEl.createEl("p").createEl("a", {
|
||||||
href: authUrl,
|
href: authUrl,
|
||||||
text: authUrl,
|
text: authUrl,
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import * as chai from "chai";
|
||||||
|
import chaiAsPromised from "chai-as-promised";
|
||||||
|
|
||||||
|
import { RemotelySavePluginSettings } from "../src/baseTypes";
|
||||||
|
import { messyConfigToNormal, normalConfigToMessy } from "../src/configPersist";
|
||||||
|
|
||||||
|
chai.use(chaiAsPromised);
|
||||||
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
const DEFAULT_SETTINGS: RemotelySavePluginSettings = {
|
||||||
|
s3: {
|
||||||
|
s3AccessKeyID: "acc",
|
||||||
|
} as any,
|
||||||
|
webdav: {
|
||||||
|
address: "addr",
|
||||||
|
} as any,
|
||||||
|
dropbox: {
|
||||||
|
username: "测试中文",
|
||||||
|
} as any,
|
||||||
|
onedrive: {
|
||||||
|
username: "test 🍎 emoji",
|
||||||
|
} as any,
|
||||||
|
password: "password",
|
||||||
|
serviceType: "s3",
|
||||||
|
currLogLevel: "info",
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("Config Persist tests", () => {
|
||||||
|
it("should encrypt go back and forth conrrectly", async () => {
|
||||||
|
const k = DEFAULT_SETTINGS;
|
||||||
|
const k2 = normalConfigToMessy(k);
|
||||||
|
const k3 = messyConfigToNormal(k2);
|
||||||
|
expect(k3).to.deep.equal(k);
|
||||||
|
});
|
||||||
|
});
|
||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"0.2.8": "0.12.15"
|
"0.2.10": "0.12.15"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user