feat: news service
This commit is contained in:
parent
b43a576615
commit
ed25a8790c
4 changed files with 124 additions and 0 deletions
|
|
@ -164,4 +164,12 @@ export default {
|
||||||
exact: true,
|
exact: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
news: {
|
||||||
|
apiKey: "", // An API key from https://newsdata.io for accessing news
|
||||||
|
countries: ["current"], // A list of country codes or "current" for the current location
|
||||||
|
categories: [] as string[], // A list of news categories to filter by
|
||||||
|
languages: ["en"], // A list of languages codes to filter by
|
||||||
|
domains: [] as string[], // A list of news domains to pull from
|
||||||
|
timezone: "", // A timezone to filter by, e.g. "America/New_York"
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,5 +21,6 @@ export const {
|
||||||
wallpapers,
|
wallpapers,
|
||||||
calendar,
|
calendar,
|
||||||
thumbnailer,
|
thumbnailer,
|
||||||
|
news,
|
||||||
} = config;
|
} = config;
|
||||||
export default config;
|
export default config;
|
||||||
|
|
|
||||||
|
|
@ -94,4 +94,10 @@ export default {
|
||||||
"thumbnailer.defaults.width": NUM,
|
"thumbnailer.defaults.width": NUM,
|
||||||
"thumbnailer.defaults.height": NUM,
|
"thumbnailer.defaults.height": NUM,
|
||||||
"thumbnailer.defaults.exact": BOOL,
|
"thumbnailer.defaults.exact": BOOL,
|
||||||
|
"news.apiKey": STR,
|
||||||
|
"news.countries": ARR(STR),
|
||||||
|
"news.categories": ARR(STR),
|
||||||
|
"news.languages": ARR(STR),
|
||||||
|
"news.domains": ARR(STR),
|
||||||
|
"news.timezone": STR,
|
||||||
} as { [k: string]: string | string[] | number[] };
|
} as { [k: string]: string | string[] | number[] };
|
||||||
|
|
|
||||||
109
src/services/news.ts
Normal file
109
src/services/news.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
import { notify } from "@/utils/system";
|
||||||
|
import { execAsync, GLib, GObject, property, readFileAsync, register, writeFileAsync } from "astal";
|
||||||
|
import { news as config } from "config";
|
||||||
|
|
||||||
|
export interface Article {
|
||||||
|
title: string;
|
||||||
|
link: string;
|
||||||
|
keywords: string;
|
||||||
|
creator: string;
|
||||||
|
description: string;
|
||||||
|
pubDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@register({ GTypeName: "News" })
|
||||||
|
export default class News extends GObject.Object {
|
||||||
|
static instance: News;
|
||||||
|
static get_default() {
|
||||||
|
if (!this.instance) this.instance = new News();
|
||||||
|
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly #cachePath = `${CACHE}/news.json`;
|
||||||
|
|
||||||
|
#loading: boolean = false;
|
||||||
|
#articles: Article[] = [];
|
||||||
|
|
||||||
|
@property(Boolean)
|
||||||
|
get loading() {
|
||||||
|
return this.#loading;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property(Object)
|
||||||
|
get articles() {
|
||||||
|
return this.#articles;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getNews() {
|
||||||
|
if (!config.apiKey.get()) {
|
||||||
|
notify({
|
||||||
|
summary: "A newsdata.io API key is required",
|
||||||
|
body: "You can get one by creating an account at https://newsdata.io",
|
||||||
|
icon: "dialog-error-symbolic",
|
||||||
|
urgency: "critical",
|
||||||
|
actions: {
|
||||||
|
"Get API key": () => execAsync("app2unit -O -- https://newsdata.io").catch(console.error),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#loading = true;
|
||||||
|
this.notify("loading");
|
||||||
|
|
||||||
|
let countries = config.countries.get().join(",");
|
||||||
|
const categories = config.categories.get().join(",");
|
||||||
|
const languages = config.languages.get().join(",");
|
||||||
|
const domains = config.domains.get().join(",");
|
||||||
|
const timezone = config.timezone.get();
|
||||||
|
|
||||||
|
if (countries.includes("current")) {
|
||||||
|
const out = JSON.parse(await execAsync("curl ipinfo.io")).country.toLowerCase();
|
||||||
|
countries = countries.replace("current", out);
|
||||||
|
}
|
||||||
|
|
||||||
|
let args = "removeduplicate=1&prioritydomain=top";
|
||||||
|
if (countries) args += `&country=${countries}`;
|
||||||
|
if (categories) args += `&category=${categories}`;
|
||||||
|
if (languages) args += `&language=${languages}`;
|
||||||
|
if (domains) args += `&domain=${domains}`;
|
||||||
|
if (timezone) args += `&timezone=${timezone}`;
|
||||||
|
|
||||||
|
const url = `https://newsdata.io/api/1/latest?apikey=${config.apiKey.get()}&${args}`;
|
||||||
|
try {
|
||||||
|
const res = JSON.parse(await execAsync(["curl", url]));
|
||||||
|
this.#articles = res.results;
|
||||||
|
|
||||||
|
let page = res.nextPage;
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
const res = JSON.parse(await execAsync(["curl", `${url}&page=${page}`]));
|
||||||
|
this.#articles.push(...res.results);
|
||||||
|
page = res.nextPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFileAsync(this.#cachePath, JSON.stringify(this.#articles)).catch(console.error);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
|
||||||
|
if (GLib.file_test(this.#cachePath, GLib.FileTest.EXISTS))
|
||||||
|
this.#articles = JSON.parse(await readFileAsync(this.#cachePath));
|
||||||
|
}
|
||||||
|
this.notify("articles");
|
||||||
|
|
||||||
|
this.#loading = false;
|
||||||
|
this.notify("loading");
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.getNews().catch(console.error);
|
||||||
|
config.apiKey.subscribe(() => this.getNews().catch(console.error));
|
||||||
|
config.countries.subscribe(() => this.getNews().catch(console.error));
|
||||||
|
config.categories.subscribe(() => this.getNews().catch(console.error));
|
||||||
|
config.languages.subscribe(() => this.getNews().catch(console.error));
|
||||||
|
config.domains.subscribe(() => this.getNews().catch(console.error));
|
||||||
|
config.timezone.subscribe(() => this.getNews().catch(console.error));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue