저는 작성을 위해 Obsidian을 사용하기 시작했고, 제 Discourse 포럼에 게시물을 올리는 Obsidian 플러그인을 만들어 보려 했습니다. 이론적으로는 쉽게 만들 수 있지만, 첫 시도에 대한 응답은 다음과 같았습니다:
Access to fetch at 'http://localhost:4200/posts.json' from origin 'app://obsidian.md' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
요청은 클라이언트에서 발생하지만, 이 클라이언트는 사용자의 기기입니다. 제 이해가 맞다면, 이는 안전합니다:
import DiscoursePlugin from "./main";
import { TFile } from "obsidian";
export async function publishToDiscourse(
plugin: DiscoursePlugin,
activeFile: TFile
): Promise<{ message: string }> {
try {
const content = await plugin.app.vault.read(activeFile);
const baseUrl = plugin.settings.baseUrl;
const apiKey = plugin.settings.apiKey;
const headers = new Headers({
"Content-Type": "application/json",
"Api-Key": apiKey,
"Api-Username": "scossar", // this needs to be a setting
});
const body = JSON.stringify({
title: activeFile.name,
raw: content, // TODO: parse the content to fix internal links
category: 1, // this needs to be a setting
});
// TODO: check to see if the note has already been published
const url = `${baseUrl}/posts.json`;
const response = await fetch(url, { method: "POST", headers, body });
if (!response.ok) {
console.error("Error publishing to Discourse:", response.status);
return { message: "Error publishing to Discourse" };
}
const jsonResponse = await response.json();
// TODO: use the response to add a discoursePostId file property
console.log(`jsonResponse: ${JSON.stringify(jsonResponse, null, 2)}`);
return { message: "success" };
} catch (error) {
console.error("Error publishing to Discourse:", error);
return { message: `Error: ${error.message}` };
}
}
제가 놓치고 있는 명백한 우회 방법이 있을 수도 있습니다. 만약 그렇지 않다면, Discourse에서 이를 작동하게 할 방법이 있을까요? Obsidian Discourse 플러그인은 유용할 것 같습니다. (적절한 구현은 위에 올린 것보다 더 복잡할 것입니다.)
처음에는 혼란스러웠지만, 이제 이해했습니다. 본인만의 키를 사용하여 Obsidian 앱을 직접 구성했고, 접근 권한은 본인에게만 있다는 것이죠. 이는 브라우저에서 발생하는 것이 아니므로 인터넷상의 다른 사람들이 키를 가지고 있지 않습니다.
저는 임의의 폼을 처리하는 Discourse 플러그인을 하나 가지고 있습니다(https://www.formhoster.com/ 에서 사용 가능합니다). 폼을 처리하는 사이트에 로그인된 상태라면 현재 사용자로 동작하도록 만들고 싶었는데, 제가 생각하기에 동일한 CORS 문제에 부딪혀 금방 포기했습니다. 제 경우는 Obsidian 같은 앱이 아니라 브라우저에서였지만, 문제의 성격은 비슷할 것 같습니다.
결국 제가 좋은 아이디어를 가지고 있지는 않다는 뜻이지만, 다른 누군가가 좋은 방법을 제시해 주기를 희망합니다.
이것은 무언가의 시작이었습니다. 제 개인적인 용도로는 Obsidian 볼트를 Discourse 포럼과 동기화할 수 있는 CLI(명령줄) 애플리케이션에 더 관심이 있습니다. CLI 앱은 볼트 전체 또는 하위 디렉터리를 동기화하는 것, 노트 내의 내부 링크를 처리하는 것, 업로드를 처리하는 것 등을 더 쉽게 다룰 수 있게 해줍니다. CLI 앱 접근법은 제가 진행 중인 다른 작업들과도 잘 어울리며, 이를 통해 유용한 것을 배울 수 있습니다.
CLI 앱의 큰 단점은 사용자들이 컴퓨터에 Ruby를 설치해야 한다는 점입니다. 또한 데스크톱 컴퓨터에서만 작동합니다. Windows 컴퓨터에서 사용할 경우 몇 가지 기술적 도전이 있을 것입니다.
앱이 공유할 준비가 되면 여기에 링크를 게시하겠습니다.
CLI 앱이 아닌 Obsidian Discourse 플러그인에 사람들이 관심이 있다면, 미래에 다시 살펴볼 것입니다. 다른 누군가가 저보다 먼저 그것을 만들 수도 있습니다. 저는 위에 게시된 코드 예제보다 더 많이 진행하지 않았습니다.
지금까지 이 정도라면 꽤 단순해 보입니다. 이 시점에서 이미지는 어떻게 처리할지 궁금합니다. 한번 시도해 볼 의향이 있습니다. 저는 이전에 옵시디언 플러그인을 작성해 본 적이 없지만, 제가 살펴본 바로는 (다른 플러그인들을 슬쩍 살펴보았지만) 그렇게 복잡해 보이지 않습니다.
음, 그 코드를 잃어버린 건 좀 무모했네요. 기억으로는 main.ts에서 정의된 DiscoursePlugin을 this.addCommand 호출을 처리하는 파일로 가져오는 중이었어요. 시작하려면 main.ts에서 모든 것을 처리할 수 있습니다. 예제 플러그인으로 시작하는 가이드를 따르는 걸 추천해요. 먼저 그걸 가지고 이것저것 시도해 보고 무언가를 동작하게 해보세요. 제가 그 플러그인을 제 플러그인의 템플릿으로 사용했거든요.