He comenzado a usar Obsidian para escribir, así que pensé en crear un plugin de Obsidian para publicar en mi foro de Discourse. En teoría, eso es fácil de hacer, pero la respuesta de mi primer intento fue:
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.
La solicitud se está realizando desde el cliente, pero el cliente es el dispositivo del usuario. Si entiendo bien, esto es seguro:
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", // esto necesita ser una configuración
});
const body = JSON.stringify({
title: activeFile.name,
raw: content, // TODO: analizar el contenido para corregir enlaces internos
category: 1, // esto necesita ser una configuración
});
// TODO: verificar si la nota ya ha sido publicada
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: usar la respuesta para agregar una propiedad de archivo discoursePostId
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}` };
}
}
Es posible que haya una solución obvia que me esté perdiendo. Si no es así, ¿hay alguna forma en que Discourse pueda permitir que funcione? Un plugin de Obsidian Discourse podría ser útil. (Una implementación adecuada sería más compleja que lo que publiqué anteriormente).
Me confundí al principio, pero ya veo, has configurado tu propia aplicación Obsidian con tu clave y solo tú tienes acceso a ella. Esto no está sucediendo en un navegador, por lo que las personas en Internet no tienen tu clave.
Tengo un plugin de Discourse que procesa formularios arbitrarios (puedes usarlo en https://www.formhoster.com/). Quería que pudiera funcionar como el usuario actual si el usuario había iniciado sesión en el sitio que procesaba el formulario y me encontré con lo que creo que es el mismo problema de CORS y me di por vencido bastante rápido. El mío estaba en un navegador en lugar de una aplicación como Obsidian, pero creo que el problema podría ser similar.
Todo eso para decir que creo que no tengo buenas ideas, pero espero que alguien más las tenga.
Correcto, Obsidian es una aplicación Electron que se ejecuta localmente. Utiliza almacenamiento local, por lo que la clave API permanece en el dispositivo del usuario.
Resulta que hay una solución para el problema de CORS. Solo la he probado en mi ordenador de escritorio hasta ahora. ¡Además, Discourse es genial!
El código que publiqué anteriormente necesitaba ser modificado a:
¿Es este un plugin en el que estás trabajando? Tengo un usuario (y yo mismo) a quien le encantaría poder usar esto. Puedo intentar recrear lo que has hecho, pero si hay una manera más fácil…
Fue el comienzo de algo. Para mis propios propósitos, estoy más interesado en una aplicación de línea de comandos (CLI) que permita sincronizar una bóveda de Obsidian con un foro de Discourse. Una aplicación CLI facilita el manejo de la sincronización de una bóveda completa o un subdirectorio, el manejo de enlaces internos en las notas, la gestión de subidas, etc. El enfoque de la aplicación CLI también encaja con otro trabajo que estoy haciendo, por lo que estoy aprendiendo algo útil de ello.
La gran desventaja de la aplicación CLI es que requiere que cualquiera que la use tenga Ruby instalado en su computadora. También solo funcionará en computadoras de escritorio. Habría algunos desafíos técnicos al usarla en computadoras con Windows.
Publicaré un enlace a la aplicación aquí una vez que esté lista para compartir.
Si un plugin de Obsidian Discourse, en lugar de una aplicación CLI, es algo que interesa a la gente, lo volveré a examinar en el futuro. Es posible que alguien más lo haga antes que yo. No lo llevé mucho más allá del ejemplo de código que se publicó anteriormente.
Si esto es todo lo que tienes hasta ahora, parece bastante simple. Me pregunto cómo manejaría las imágenes en este momento. Estaría dispuesto a intentarlo. Nunca antes he escrito un plugin para Obsidian, pero por lo que he visto (miradas furtivas a otros plugins), no parece terriblemente complicado.
Este es el lugar para empezar: Build a plugin - Developer Documentation. Me gustaría enlazar a lo que había hecho, pero es uno de los pocos (ojalá el único) proyectos que no subí a Github antes de reinstalar el sistema operativo en mi ordenador la semana pasada.
Hmm, perder ese código fue algo imprudente. Según recuerdo, estaba importando DiscoursePlugin definido en main.ts en un archivo que manejaba una llamada a this.addCommand. Para empezar, puedes hacer todo en main.ts. Simplemente sigue la guía para empezar con el plugin de ejemplo. Empieza jugando con él e intentando que suceda algo. Sé que usé ese plugin como plantilla para el mío.
Bueno, voy a dejar esto en pausa por ahora. He progresado bastante, pero hay algunas cosas que no me gustan.
La clave de la API se almacena en texto plano (MUY MALO)
Las imágenes no se cargan, hay algunas configuraciones que no he explorado todavía. Pero no me gusta configurar un bucket de AWS S3. Lo investigaré más tarde.
algunas decisiones estilísticas podrían ser mejores, pero quería algo funcional
El README necesita ser actualizado. Pero, de nuevo, solo quería algo funcional y publicado.
Me pregunto si hay alguna forma de evitarlo. En la aplicación CLI, la cifro con una contraseña. El usuario tiene que proporcionar la contraseña antes de cualquier operación que utilice la clave de la API.