/
updater.ts
119 lines (106 loc) · 3.61 KB
/
updater.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import {NewsriverData} from "./newsriver";
import * as firebaseHelper from 'firebase-functions-helper';
import {AxiosInstance, default as axios} from "axios";
import * as https from "https";
export class Updater {
private readonly db: FirebaseFirestore.Firestore;
private readonly collectionName: string;
private readonly interval: number;
private _searchTerms: Array<string>;
private readonly language: string;
private readonly auth: string;
private _path: string | undefined;
get path(): Promise<string> {
if (this._path === undefined)
return this.buildPath()
.then(path => this._path = path);
return Promise.resolve(this._path);
}
get searchTerms(): Array<string> {
return this._searchTerms;
}
set searchTerms(value) {
this._searchTerms = value;
this._path = undefined;
}
get network(): AxiosInstance {
return axios.create({
baseURL: 'https://api.newsriver.io/v2/',
headers: {
'Authorization': this.auth,
'Content-Type': 'application/json'
},
withCredentials: true,
responseType: 'json',
httpsAgent: new https.Agent({ keepAlive: true }),
timeout: 500000
});
}
constructor(db: FirebaseFirestore.Firestore | null,
collectionName: string | null,
searchTerms: Array<string>,
auth: string,
language: string = 'en',
intervalMins: number = 30) {
this.db = db;
this.collectionName = collectionName;
this.searchTerms = searchTerms;
this.language = language;
this.auth = auth;
this.interval = intervalMins * 60 * 1000;
this.doRequest()
.then(response => {
this.updateData(response)
// tslint:disable-next-line:no-empty
.catch(ignored => {
});
})
.catch(err => console.warn(`Unable to update data due to exception: ${err}`));
}
schedule(): NodeJS.Timer {
return setInterval(async () => {
try {
const requestData = await this.doRequest();
await this.updateData(requestData);
} catch (e) {
console.error(`Got error ${e} while querying data`);
}
}, this.interval);
}
async updateData(content: Array<NewsriverData>) {
try {
for (const element of content) {
try {
firebaseHelper.firestore.createDocumentWithID(this.db, this.collectionName, element.id, element)
.then(created => console.debug(`Item with ID: ${element.id} was ${created ? 'created' : 'not created'}`))
.catch(err => console.error(`Error while creating document ${err}`));
} catch (err) {
console.warn(`Error while creating/updating document - ${err}`);
}
}
console.info(`Updated approximately ${content.length} element(s)`);
} catch (error) {
console.error(`Unhandled error ${error}`);
}
}
async doRequest(): Promise<Array<NewsriverData>> {
const response = await this.network.get(await this.path);
if (response.status === 200)
return response.data as Array<NewsriverData>;
else
throw new TypeError(`The response code is not valid - ${response.status}`);
}
async buildPath(): Promise<string> {
const parts = ['/search?query=']
this.searchTerms.forEach((term, i, _) => {
if (i !== 0)
parts.push(encodeURI(' OR '));
parts.push(encodeURI(`title:${term} OR text:${term}`));
});
parts.push(encodeURI(` AND language:${this.language.toUpperCase()}`));
parts.push(encodeURI('&sortBy=discoverDate'));
parts.push(encodeURI('&sortOrder=DESC'));
parts.push(encodeURI('&limit=100'));
return parts.join('');
}
}