mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-30 19:19:03 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			201 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const PROTOCOL_VERSION_MAJOR = 1;
 | |
| 
 | |
| function isDevEnv() {
 | |
| 	const manifest = browser.runtime.getManifest();
 | |
| 
 | |
| 	return manifest.name.endsWith('(dev)');
 | |
| }
 | |
| 
 | |
| class TriliumServerFacade {
 | |
| 	constructor() {
 | |
| 		this.triggerSearchForTrilium();
 | |
| 
 | |
| 		// continually scan for changes (if e.g. desktop app is started after browser)
 | |
| 		setInterval(() => this.triggerSearchForTrilium(), 60 * 1000);
 | |
| 	}
 | |
| 
 | |
| 	async sendTriliumSearchStatusToPopup() {
 | |
| 		try {
 | |
| 			await browser.runtime.sendMessage({
 | |
| 				name: "trilium-search-status",
 | |
| 				triliumSearch: this.triliumSearch
 | |
| 			});
 | |
| 		}
 | |
| 		catch (e) {} // nothing might be listening
 | |
| 	}
 | |
| 
 | |
| 	setTriliumSearch(ts) {
 | |
| 		this.triliumSearch = ts;
 | |
| 
 | |
| 		this.sendTriliumSearchStatusToPopup();
 | |
| 	}
 | |
| 
 | |
| 	setTriliumSearchWithVersionCheck(json, resp) {
 | |
| 		const [major, minor] = json.protocolVersion
 | |
| 			.split(".")
 | |
| 			.map(chunk => parseInt(chunk));
 | |
| 
 | |
| 		// minor version is intended to be used to dynamically limit features provided by extension
 | |
| 		// if some specific Trilium API is not supported. So far not needed.
 | |
| 
 | |
| 		if (major !== PROTOCOL_VERSION_MAJOR) {
 | |
| 			this.setTriliumSearch({
 | |
| 				status: 'version-mismatch',
 | |
| 				extensionMajor: PROTOCOL_VERSION_MAJOR,
 | |
| 				triliumMajor: major
 | |
| 			});
 | |
| 		}
 | |
| 		else {
 | |
| 			this.setTriliumSearch(resp);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async triggerSearchForTrilium() {
 | |
| 		this.setTriliumSearch({ status: 'searching' });
 | |
| 
 | |
| 		const startingPort = await this.getStartingPort();
 | |
| 
 | |
| 		for (let testedPort = startingPort; testedPort < startingPort + 10; testedPort++) {
 | |
| 			try {
 | |
| 				console.debug('Trying port ' + testedPort);
 | |
| 
 | |
| 				const resp = await fetch(`http://127.0.0.1:${testedPort}/api/clipper/handshake`);
 | |
| 
 | |
| 				const text = await resp.text();
 | |
| 
 | |
| 				console.log("Received response:", text);
 | |
| 
 | |
| 				const json = JSON.parse(text);
 | |
| 
 | |
| 				if (json.appName === 'trilium') {
 | |
| 					this.setTriliumSearchWithVersionCheck(json, {
 | |
| 						status: 'found-desktop',
 | |
| 						port: testedPort,
 | |
| 						url: 'http://127.0.0.1:' + testedPort
 | |
| 					});
 | |
| 
 | |
| 					return;
 | |
| 				}
 | |
| 			}
 | |
| 			catch (error) {
 | |
| 				// continue
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		const {triliumServerUrl} = await browser.storage.sync.get("triliumServerUrl");
 | |
| 		const {authToken} = await browser.storage.sync.get("authToken");
 | |
| 
 | |
| 		if (triliumServerUrl && authToken) {
 | |
| 			try {
 | |
| 				const resp = await fetch(triliumServerUrl + '/api/clipper/handshake', {
 | |
| 					headers: {
 | |
| 						Authorization: authToken
 | |
| 					}
 | |
| 				});
 | |
| 
 | |
| 				const text = await resp.text();
 | |
| 
 | |
| 				console.log("Received response:", text);
 | |
| 
 | |
| 				const json = JSON.parse(text);
 | |
| 
 | |
| 				if (json.appName === 'trilium') {
 | |
| 					this.setTriliumSearchWithVersionCheck(json, {
 | |
| 						status: 'found-server',
 | |
| 						url: triliumServerUrl,
 | |
| 						token: authToken
 | |
| 					});
 | |
| 
 | |
| 					return;
 | |
| 				}
 | |
| 			}
 | |
| 			catch (e) {
 | |
| 				console.log("Request to the configured server instance failed with:", e);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// if all above fails it's not found
 | |
| 		this.setTriliumSearch({ status: 'not-found' });
 | |
| 	}
 | |
| 
 | |
| 	async waitForTriliumSearch() {
 | |
| 		return new Promise((res, rej) => {
 | |
| 			const checkStatus = () => {
 | |
| 				if (this.triliumSearch.status === "searching") {
 | |
| 					setTimeout(checkStatus, 500);
 | |
| 				}
 | |
| 				else if (this.triliumSearch.status === 'not-found') {
 | |
| 					rej(new Error("Trilium instance has not been found."));
 | |
| 				}
 | |
| 				else {
 | |
| 					res();
 | |
| 				}
 | |
| 			};
 | |
| 
 | |
| 			checkStatus();
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	async getStartingPort() {
 | |
| 		const {triliumDesktopPort} = await browser.storage.sync.get("triliumDesktopPort");
 | |
| 
 | |
| 		if (triliumDesktopPort) {
 | |
| 			return parseInt(triliumDesktopPort);
 | |
| 		}
 | |
| 		else {
 | |
| 			return isDevEnv() ? 37740 : 37840;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async callService(method, path, body) {
 | |
| 		const fetchOptions = {
 | |
| 			method: method,
 | |
| 			headers: {
 | |
| 				'Content-Type': 'application/json'
 | |
| 			},
 | |
| 		};
 | |
| 
 | |
| 		if (body) {
 | |
| 			fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
 | |
| 		}
 | |
| 
 | |
| 		try {
 | |
| 			await this.waitForTriliumSearch();
 | |
| 
 | |
| 			fetchOptions.headers.Authorization = this.triliumSearch.token || "";
 | |
| 			fetchOptions.headers['trilium-local-now-datetime'] = this.localNowDateTime();
 | |
| 
 | |
| 			const url = this.triliumSearch.url + "/api/clipper/" + path;
 | |
| 
 | |
| 			console.log(`Sending ${method} request to ${url}`);
 | |
| 
 | |
| 			const response = await fetch(url, fetchOptions);
 | |
| 
 | |
| 			if (!response.ok) {
 | |
| 				throw new Error(await response.text());
 | |
| 			}
 | |
| 
 | |
| 			return await response.json();
 | |
| 		}
 | |
| 		catch (e) {
 | |
| 			console.log("Sending request to trilium failed", e);
 | |
| 
 | |
| 			toast('Your request failed because we could not contact Trilium instance. Please make sure Trilium is running and is accessible.');
 | |
| 
 | |
| 			return null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	localNowDateTime() {
 | |
| 		const date = new Date();
 | |
| 		const off = date.getTimezoneOffset();
 | |
| 		const absoff = Math.abs(off);
 | |
| 		return (new Date(date.getTime() - off * 60 * 1000).toISOString().substr(0,23).replace("T",  " ") +
 | |
| 			(off > 0 ? '-' : '+') +
 | |
| 			(absoff / 60).toFixed(0).padStart(2,'0') + ':' +
 | |
| 			(absoff % 60).toString().padStart(2,'0'));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| window.triliumServerFacade = new TriliumServerFacade();
 | 
