weather: store api key directly in config

Also only notify once when no api key for both weather and news
This commit is contained in:
2 * r + 2 * t 2025-04-09 00:14:48 +10:00
parent 55271a93f4
commit a6f26b3d37
5 changed files with 39 additions and 42 deletions

1
.gitignore vendored
View file

@ -1,4 +1,3 @@
@girs/ @girs/
node_modules/ node_modules/
scss/scheme/_index.scss scss/scheme/_index.scss
assets/weather-api-key.txt

View file

@ -125,7 +125,7 @@ export default {
}, },
weather: { weather: {
interval: 600000, interval: 600000,
key: "assets/weather-api-key.txt", // Path to file containing api key relative to the base directory. To get a key, visit https://weatherapi.com/ apiKey: "", // An API key from https://weatherapi.com for accessing weather data
location: "", // Location as a string or empty to autodetect location: "", // Location as a string or empty to autodetect
imperial: false, imperial: false,
}, },

View file

@ -78,7 +78,7 @@ export default {
"math.maxHistory": NUM, "math.maxHistory": NUM,
"updates.interval": NUM, "updates.interval": NUM,
"weather.interval": NUM, "weather.interval": NUM,
"weather.key": STR, "weather.apiKey": STR,
"weather.location": STR, "weather.location": STR,
"weather.imperial": BOOL, "weather.imperial": BOOL,
"cpu.interval": NUM, "cpu.interval": NUM,

View file

@ -21,6 +21,7 @@ export default class News extends GObject.Object {
} }
readonly #cachePath = `${CACHE}/news.json`; readonly #cachePath = `${CACHE}/news.json`;
#notified = false;
#loading: boolean = false; #loading: boolean = false;
#articles: Article[] = []; #articles: Article[] = [];
@ -37,15 +38,18 @@ export default class News extends GObject.Object {
async getNews() { async getNews() {
if (!config.apiKey.get()) { if (!config.apiKey.get()) {
notify({ if (!this.#notified) {
summary: "A newsdata.io API key is required", notify({
body: "You can get one by creating an account at https://newsdata.io", summary: "A newsdata.io API key is required",
icon: "dialog-error-symbolic", body: "You can get one by creating an account at https://newsdata.io",
urgency: "critical", icon: "dialog-warning-symbolic",
actions: { urgency: "critical",
"Get API key": () => execAsync("app2unit -O -- https://newsdata.io").catch(console.error), actions: {
}, "Get API key": () => execAsync("app2unit -O -- https://newsdata.io").catch(console.error),
}); },
});
this.#notified = true;
}
return; return;
} }

View file

@ -217,8 +217,8 @@ export default class Weather extends GObject.Object {
} }
readonly #cache: string = `${CACHE}/weather.json`; readonly #cache: string = `${CACHE}/weather.json`;
#notified = false;
#key: string = "";
#data: WeatherData = DEFAULT; #data: WeatherData = DEFAULT;
#interval: Time | null = null; #interval: Time | null = null;
@ -322,15 +322,28 @@ export default class Weather extends GObject.Object {
async getWeather() { async getWeather() {
const location = config.location || JSON.parse(await execAsync("curl ipinfo.io")).city; const location = config.location || JSON.parse(await execAsync("curl ipinfo.io")).city;
return JSON.parse( const opts = `key=${config.apiKey.get()}&q=${location}&days=1&aqi=no&alerts=no`;
await execAsync([ const url = `https://api.weatherapi.com/v1/forecast.json?${opts}`;
"curl", return JSON.parse(await execAsync(["curl", url]));
`https://api.weatherapi.com/v1/forecast.json?key=${this.#key}&q=${location}&days=1&aqi=no&alerts=no`,
])
);
} }
async updateWeather() { async updateWeather() {
if (!config.apiKey.get()) {
if (!this.#notified) {
notify({
summary: "Weather API key required",
body: `A weather API key is required to get weather data. Get one from https://www.weatherapi.com.`,
icon: "dialog-warning-symbolic",
urgency: "critical",
actions: {
"Get API key": () => execAsync(`app2unit -O 'https://www.weatherapi.com'`).catch(print),
},
});
this.#notified = true;
}
return;
}
if (GLib.file_test(this.#cache, GLib.FileTest.EXISTS)) { if (GLib.file_test(this.#cache, GLib.FileTest.EXISTS)) {
const cache = await readFileAsync(this.#cache); const cache = await readFileAsync(this.#cache);
const cache_data: WeatherData = JSON.parse(cache); const cache_data: WeatherData = JSON.parse(cache);
@ -354,32 +367,13 @@ export default class Weather extends GObject.Object {
this.#notify(); this.#notify();
} }
#init(first: boolean) {
if (GLib.file_test(config.key.get(), GLib.FileTest.EXISTS))
readFileAsync(config.key.get())
.then(k => {
this.#key = k.trim();
this.updateWeather().catch(console.error);
this.#interval = interval(config.interval.get(), () => this.updateWeather().catch(console.error));
})
.catch(console.error);
else if (first)
notify({
summary: "Weather API key required",
body: `A weather API key is required to get weather data. Get one from https://www.weatherapi.com and put it in ${config.key}.`,
icon: "dialog-warning-symbolic",
urgency: "critical",
actions: {
"Get API key": () => execAsync(`app2unit -O 'https://www.weatherapi.com'`).catch(print),
},
});
}
constructor() { constructor() {
super(); super();
this.#init(true); this.updateWeather().catch(console.error);
config.key.subscribe(() => this.#init(false)); this.#interval = interval(config.interval.get(), () => this.updateWeather().catch(console.error));
config.apiKey.subscribe(() => this.updateWeather());
config.interval.subscribe(i => { config.interval.subscribe(i => {
this.#interval?.cancel(); this.#interval?.cancel();