diff --git a/src/geosearch.ts b/src/geosearch.ts index f1b89b9..68fd4c1 100644 --- a/src/geosearch.ts +++ b/src/geosearch.ts @@ -2,7 +2,7 @@ import { request, App } from 'obsidian'; import * as geosearch from 'leaflet-geosearch'; import * as leaflet from 'leaflet'; import queryString from 'query-string'; - +import { readFileSync } from 'fs'; import { type PluginSettings } from 'src/settings'; import { UrlConvertor } from 'src/urlConvertor'; import { FileMarker } from 'src/markers'; @@ -31,12 +31,16 @@ export class GeoSearcher { constructor(app: App, settings: PluginSettings) { this.settings = settings; this.urlConvertor = new UrlConvertor(app, settings); + + const apiKey = + settings.geocodingApiMethod === 'key' + ? settings.geocodingApiKey + : readFileSync(settings.geocodingApiPath, 'utf-8').trim(); + if (settings.searchProvider == 'osm') this.searchProvider = new geosearch.OpenStreetMapProvider(); else if (settings.searchProvider == 'google') { - this.searchProvider = new geosearch.GoogleProvider({ - apiKey: settings.geocodingApiKey, - }); + this.searchProvider = new geosearch.GoogleProvider({ apiKey }); } } @@ -119,10 +123,15 @@ export async function googlePlacesSearch( ): Promise { if (settings.searchProvider != 'google' || !settings.useGooglePlaces) return []; - const googleApiKey = settings.geocodingApiKey; + + const apiKey = + settings.geocodingApiMethod === 'key' + ? settings.geocodingApiKey + : readFileSync(settings.geocodingApiPath, 'utf-8').trim(); + const params = { query: query, - key: googleApiKey, + key: apiKey, }; if (centerOfSearch) (params as any)['location'] = diff --git a/src/settings.ts b/src/settings.ts index 44a0464..1cd6015 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -48,7 +48,9 @@ export type PluginSettings = { maxClusterRadiusPixels: number; searchProvider: 'osm' | 'google'; searchDelayMs: number; - geocodingApiKey: string; + geocodingApiMethod?: 'key' | 'path'; + geocodingApiKey?: string; + geocodingApiPath?: string; useGooglePlaces: boolean; saveHistory: boolean; queryForFollowActiveNote: string; @@ -228,6 +230,7 @@ export const DEFAULT_SETTINGS: PluginSettings = { maxClusterRadiusPixels: 20, searchProvider: 'osm', searchDelayMs: 250, + geocodingApiMethod: 'key', geocodingApiKey: '', useGooglePlaces: false, mapSources: [ diff --git a/src/settingsTab.ts b/src/settingsTab.ts index 7a5994c..ea586fd 100644 --- a/src/settingsTab.ts +++ b/src/settingsTab.ts @@ -54,7 +54,10 @@ export class SettingsTab extends PluginSettingTab { }); }); + let apiMethodControl: Setting = null; let apiKeyControl: Setting = null; + let apiPathControl: Setting = null; + new Setting(containerEl) .setName('Geocoding search provider') .setDesc( @@ -72,8 +75,19 @@ export class SettingsTab extends PluginSettingTab { this.plugin.settings.searchProvider = value; await this.plugin.saveSettings(); this.refreshPluginOnHide = true; - apiKeyControl.settingEl.style.display = + + apiMethodControl.settingEl.style.display = value === 'google' ? '' : 'none'; + apiKeyControl.settingEl.style.display = + value === 'google' && + this.plugin.settings.geocodingApiMethod === 'key' + ? '' + : 'none'; + apiPathControl.settingEl.style.display = + value === 'google' && + this.plugin.settings.geocodingApiMethod === 'path' + ? '' + : 'none'; googlePlacesControl.settingEl.style.display = this.plugin.settings.searchProvider === 'google' ? '' @@ -81,8 +95,37 @@ export class SettingsTab extends PluginSettingTab { }); }); + apiMethodControl = new Setting(containerEl) + .setName('Geocoding API Method') + .setDesc( + 'Choose whether to provide the API key directly or via a file path.' + ) + .addDropdown((component) => { + component + .addOption('key', 'API Key') + .addOption('path', 'API Key Path') + .setValue(this.plugin.settings.geocodingApiMethod || 'key') + .onChange(async (value: 'key' | 'path') => { + this.plugin.settings.geocodingApiMethod = value; + await this.plugin.saveSettings(); + apiKeyControl.settingEl.style.display = + value === 'key' && + this.plugin.settings.searchProvider === 'google' + ? '' + : 'none'; + apiPathControl.settingEl.style.display = + value === 'path' && + this.plugin.settings.searchProvider === 'google' + ? '' + : 'none'; + }); + }); + + apiMethodControl.settingEl.style.display = + this.plugin.settings.searchProvider === 'google' ? '' : 'none'; + apiKeyControl = new Setting(containerEl) - .setName('Gecoding API key') + .setName('Geocoding API key') .setDesc( 'If using Google as the geocoding search provider, paste the API key here. See the plugin documentation for more details. Changes are applied after restart.', ) @@ -101,6 +144,40 @@ export class SettingsTab extends PluginSettingTab { ? '' : 'red'; }); + + apiKeyControl.settingEl.style.display = + this.plugin.settings.searchProvider === 'google' && + this.plugin.settings.geocodingApiMethod === 'key' + ? '' + : 'none'; + + apiPathControl = new Setting(containerEl) + .setName('Geocoding API key path') + .setDesc( + 'If using Google as the geocoding search provider and using a path to the API key, enter the file path here. See the plugin documentation for more details. Changes are applied after restart.' + ) + .addText((component) => { + component + .setValue(this.plugin.settings.geocodingApiPath) + .onChange(async (value) => { + this.plugin.settings.geocodingApiPath = value; + await this.plugin.saveSettings(); + component.inputEl.style.borderColor = value + ? '' + : 'red'; + }); + component.inputEl.style.borderColor = this.plugin.settings + .geocodingApiPath + ? '' + : 'red'; + }); + + apiPathControl.settingEl.style.display = + this.plugin.settings.searchProvider === 'google' && + this.plugin.settings.geocodingApiMethod === 'path' + ? '' + : 'none'; + let googlePlacesControl = new Setting(containerEl) .setName('Use Google Places for searches') .setDesc( @@ -118,9 +195,6 @@ export class SettingsTab extends PluginSettingTab { }); }); - // Display the API key control only if the search provider requires it - apiKeyControl.settingEl.style.display = - this.plugin.settings.searchProvider === 'google' ? '' : 'none'; googlePlacesControl.settingEl.style.display = this.plugin.settings.searchProvider === 'google' ? '' : 'none'; new Setting(containerEl) diff --git a/src/urlConvertor.ts b/src/urlConvertor.ts index 365f49b..2fdf0b8 100644 --- a/src/urlConvertor.ts +++ b/src/urlConvertor.ts @@ -1,6 +1,6 @@ import { App, Editor, TFile, request } from 'obsidian'; import queryString from 'query-string'; - +import { readFileSync } from 'fs'; import * as leaflet from 'leaflet'; import { type PluginSettings, type UrlParsingRule } from 'src/settings'; import * as utils from 'src/utils'; @@ -136,10 +136,15 @@ export class UrlConvertor { const placeName = placeNameMatch[1]; if (this.settings.debug) console.log('Google link: found place name = ', placeName); - const googleApiKey = settings.geocodingApiKey; + + const apiKey = + settings.geocodingApiMethod === 'key' + ? settings.geocodingApiKey + : readFileSync(settings.geocodingApiPath, 'utf-8').trim(); + const params = { query: placeName, - key: googleApiKey, + key: apiKey, }; const googleUrl = 'https://maps.googleapis.com/maps/api/place/textsearch/json?' +