-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstorageController.js
194 lines (174 loc) Β· 5.95 KB
/
storageController.js
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
const fs = require("fs");
const sqlite3 = require("sqlite3").verbose();
const dbFile = "./.data/sqlite.db";
const db = new sqlite3.Database(dbFile);
const exists = fs.existsSync(dbFile);
// Prepare the schema for the database.
const dbSchema = `CREATE TABLE IF NOT EXISTS feed (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
feedUrl TEXT UNIQUE,
lastFetched INTEGER
);
CREATE TABLE IF NOT EXISTS entry (
id INTEGER PRIMARY KEY AUTOINCREMENT,
guid TEXT UNIQUE,
title TEXT,
entryUrl TEXT,
publishDate INTEGER,
feedId INTEGER NOT NULL,
FOREIGN KEY (feedId) REFERENCES feed (id)
);
`;
exports.initialize = () => {
db.serialize(() => {
// If ./.data/sqlite.db does not exist, create it...
if (!exists) {
console.log("π Creating 'feed' and 'entry' tables in database...");
db.exec(dbSchema, error => {
error ? console.log("π« Error creating database:", error) : console.log("β
Done!");
});
} else {
// ...otherwise print records to console.
console.log("β
Database tables 'feed' and 'entry' ready to go!");
db.each("SELECT COUNT(*) AS count FROM feed", (err, row) => {
if (row) {
console.log(
`π« There are ${row.count} entries in the 'feed' table.`
);
} else {
console.log("π₯ The 'feed' table is empty!");
}
});
db.each("SELECT COUNT(*) AS count FROM entry", (err, row) => {
if (row) {
console.log(
`π« There are ${row.count} entries in the 'entry' table.`
);
} else {
console.log("π₯ The 'entry' table is empty!");
}
});
}
});
};
exports.insertNewestEntries = async function(feedObject) {
// Add a way to lock insertions to the database.
if (process.env.DISALLOW_WRITE) {
console.log("π Writing to the database is locked.");
return;
}
const lastFetched = new Date();
let feedId;
// Try to find the feed in the database, and return early if we can't.
try {
feedId = await findFeedIdFromURL(feedObject.meta.link);
}
catch (error) {
console.error(error);
return;
}
// If the feed exists, add any new entries. If not, add all found entries.
if (feedId) {
console.log("β
Found the feed!");
// Get the date of the last article published.
let lastPublishDate;
try {
lastPublishDate = await getLastPublishedDateFromFeedWithId(feedId);
}
catch (error) {
console.error(error);
return;
}
feedObject.items.forEach(item => {
if (item.pubdate > lastPublishDate) {
console.log("π Found newer entry with date", new Date(item.pubdate));
insertEntry(item, feedId);
}
});
console.log("β
Done adding new entries.");
} else {
console.log("π« No feed found!");
// Set up our insert queries.
const feedSql = "INSERT INTO feed (title, feedUrl, lastFetched) VALUES (?, ?, ?)";
const entrySql = "INSERT INTO entry (guid, title, entryUrl, publishDate, feedId) VALUES (?, ?, ?, ?, ?)";
db.serialize(() => {
// Insert the feed metadata into the 'feed' table.
db.run(
feedSql, [feedObject.meta.title, feedObject.meta.link, Date.parse(lastFetched)], function(error) {
console.log("π Inserting metadata into 'feed' table...");
if (error) {
console.log("π« Error inserting feed:", error);
return 400;
} else {
console.log("β
Done inserting feed!");
feedId = this.lastID;
console.log("π Created feed with id", feedId);
// Insert the entries into the 'entry' table.
console.log("π Inserting " + feedObject.items.length + " entries into 'entry' table...");
feedObject.items.forEach(item => {
insertEntry(item, feedId);
});
console.log("β
Done inserting feed entries!");
}
}
);
});
}
};
function findFeedIdFromURL(feedUrl) {
return new Promise((resolve, reject) => {
console.log("π Looking for", feedUrl);
const sql = `SELECT id FROM feed WHERE feedUrl = ?`;
db.serialize(() => {
db.get(sql, [feedUrl], (error, row) => {
if (error) {
console.error("π« Error querying 'feed' table for feedUrl");
reject(undefined);
}
if (row) {
console.log("β
Found a matching feed with id", row.id);
resolve(row.id);
} else {
console.log("π« No matching feed found.");
resolve(undefined);
}
});
});
})
}
function getLastPublishedDateFromFeedWithId(feedId) {
return new Promise((resolve, reject) => {
console.log("π Looking for last publish date for feed with id", feedId);
const sql = `SELECT publishDate FROM entry WHERE feedId = ? ORDER BY publishDate DESC LIMIT 1`;
db.serialize(() => {
db.get(sql, [feedId], (error, row) => {
if (error) {
console.error("π« Error querying 'entry' table for last publishDate");
reject(undefined);
}
if (row) {
const lastPublishDate = new Date(row.publishDate);
console.log("β
Last publishDate found as", lastPublishDate);
resolve(row.publishDate);
} else {
console.log("π« No matching entry found.");
resolve(undefined);
}
})
})
});
}
function insertEntry(item, feedId) {
console.log("π Inserting new item into 'entry' table...");
const entrySql = "INSERT INTO entry (guid, title, entryUrl, publishDate, feedId) VALUES (?, ?, ?, ?, ?)";
const publishDate = Date.parse(item.pubdate);
db.run(entrySql, [item.guid, item.title, item.permalink, publishDate, feedId], function(error) {
if (error) {
console.log("π« Error inserting entry:", error);
return 400;
} else {
console.log("π Inserted entry with title '" + item.title + "'");
}
});
}