capfb 0.0.1-security → 1.4.95-beta

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of capfb might be problematic. Click here for more details.

Files changed (78) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/dependabot.yml +11 -0
  3. package/.github/workflows/nodejs.yml +26 -0
  4. package/.github/workflows/npmpublish.yml +30 -0
  5. package/CHANGELOG.md +2 -0
  6. package/DOCS.md +1738 -0
  7. package/Extra/Database/index.js +399 -0
  8. package/Extra/Database/methods.js +286 -0
  9. package/Extra/ExtraAddons.js +78 -0
  10. package/Extra/ExtraAddonsDeprecated.js +213 -0
  11. package/Extra/ExtraGetThread.js +1 -0
  12. package/Extra/ExtraUptimeRobot.js +59 -0
  13. package/Extra/PM2/ecosystem.config.js +23 -0
  14. package/Extra/Src/Last-Run.js +48 -0
  15. package/LICENSE-MIT +21 -0
  16. package/Language/index.json +151 -0
  17. package/README.md +225 -3
  18. package/StateCrypt.js +22 -0
  19. package/broadcast.js +42 -0
  20. package/index-backup.js +1089 -0
  21. package/index.js +1090 -0
  22. package/logger.js +21 -0
  23. package/package.json +88 -3
  24. package/src/addExternalModule.js +16 -0
  25. package/src/addUserToGroup.js +78 -0
  26. package/src/changeAdminStatus.js +79 -0
  27. package/src/changeArchivedStatus.js +41 -0
  28. package/src/changeBio.js +65 -0
  29. package/src/changeBlockedStatus.js +36 -0
  30. package/src/changeGroupImage.js +106 -0
  31. package/src/changeNickname.js +45 -0
  32. package/src/changeThreadColor.js +62 -0
  33. package/src/changeThreadEmoji.js +42 -0
  34. package/src/createNewGroup.js +70 -0
  35. package/src/createPoll.js +60 -0
  36. package/src/deleteMessage.js +45 -0
  37. package/src/deleteThread.js +43 -0
  38. package/src/forwardAttachment.js +48 -0
  39. package/src/getAccessToken.js +32 -0
  40. package/src/getAccessTokenDeprecated.js +31 -0
  41. package/src/getCurrentUserID.js +7 -0
  42. package/src/getEmojiUrl.js +27 -0
  43. package/src/getFriendsList.js +73 -0
  44. package/src/getMessage.js +80 -0
  45. package/src/getThreadHistory.js +537 -0
  46. package/src/getThreadHistoryDeprecated.js +71 -0
  47. package/src/getThreadInfo.js +197 -0
  48. package/src/getThreadInfoDeprecated.js +56 -0
  49. package/src/getThreadList.js +213 -0
  50. package/src/getThreadListDeprecated.js +46 -0
  51. package/src/getThreadPictures.js +59 -0
  52. package/src/getUserID.js +62 -0
  53. package/src/getUserInfo.js +65 -0
  54. package/src/getUserInfoV2.js +35 -0
  55. package/src/handleFriendRequest.js +46 -0
  56. package/src/handleMessageRequest.js +49 -0
  57. package/src/httpGet.js +49 -0
  58. package/src/httpPost.js +48 -0
  59. package/src/httpPostFormData.js +41 -0
  60. package/src/listenMqtt.js +633 -0
  61. package/src/logout.js +68 -0
  62. package/src/markAsDelivered.js +48 -0
  63. package/src/markAsRead.js +70 -0
  64. package/src/markAsReadAll.js +43 -0
  65. package/src/markAsSeen.js +51 -0
  66. package/src/muteThread.js +47 -0
  67. package/src/removeUserFromGroup.js +49 -0
  68. package/src/resolvePhotoUrl.js +37 -0
  69. package/src/searchForThread.js +43 -0
  70. package/src/sendMessage.js +342 -0
  71. package/src/sendTypingIndicator.js +80 -0
  72. package/src/setMessageReaction.js +109 -0
  73. package/src/setPostReaction.js +102 -0
  74. package/src/setTitle.js +74 -0
  75. package/src/threadColors.js +39 -0
  76. package/src/unfriend.js +43 -0
  77. package/src/unsendMessage.js +40 -0
  78. package/utils.js +1284 -0
@@ -0,0 +1,399 @@
1
+ /* eslint-disable linebreak-style */
2
+ /* eslint-disable no-global-assign */
3
+
4
+ /**
5
+ *
6
+ */
7
+
8
+ // Require Database
9
+ var Database = require("better-sqlite3");
10
+ const { join } = require("path");
11
+ var db;
12
+ // Create Database Under Conditions
13
+ if (!db) db = new Database(join(__dirname, "../Databasethread.sqlite"));
14
+
15
+
16
+ var { fetch,set,add,subtract,push,deleteDB,has,all,type,clear } = require("./methods");
17
+
18
+ // Declare Methods
19
+ var methods = {
20
+ fetch: fetch,
21
+ set: set,
22
+ add: add,
23
+ subtract: subtract,
24
+ push: push,
25
+ delete: deleteDB,
26
+ has: has,
27
+ all: all,
28
+ type: type,
29
+ clear: clear
30
+ };
31
+
32
+ module.exports = {
33
+ /**
34
+ * Package version. Community requested feature.
35
+ * console.log(require('quick.db').version);
36
+ */
37
+ version: "1.1.1",
38
+
39
+ /**
40
+ * This function fetches data from a key in the database. (alias: .get())
41
+ * @param {key} input any string as a key. Also allows for dot notation following the key.
42
+ * @param {options} [input={ target: null }] Any options to be added to the request.
43
+ * @returns {data} the data requested.
44
+ */
45
+
46
+ fetch: function (key, ops) {
47
+ if (!key)
48
+ throw new TypeError(
49
+ "No key specified."
50
+ );
51
+ return arbitrate("fetch", { id: key, ops: ops || {} });
52
+ },
53
+ get: function (key, ops) {
54
+ if (!key)
55
+ throw new TypeError(
56
+ "No key specified."
57
+ );
58
+ return arbitrate("fetch", { id: key, ops: ops || {} });
59
+ },
60
+
61
+ /**
62
+ * This function sets new data based on a key in the database.
63
+ * @param {key} input any string as a key. Also allows for dot notation following the key.
64
+ * @param {options} [input={ target: null }] Any options to be added to the request.
65
+ * @returns {data} the updated data.
66
+ */
67
+
68
+ set: function (key, value, ops) {
69
+ if (!key)
70
+ throw new TypeError(
71
+ "No key specified."
72
+ );
73
+ if (value === undefined)
74
+ throw new TypeError(
75
+ "No value specified."
76
+ );
77
+ return arbitrate("set", {
78
+ stringify: false,
79
+ id: key,
80
+ data: value,
81
+ ops: ops || {},
82
+ });
83
+ },
84
+
85
+ /**
86
+ * This function adds a number to a key in the database. (If no existing number, it will add to 0)
87
+ * @param {key} input any string as a key. Also allows for dot notation following the key.
88
+ * @param {options} [input={ target: null }] Any options to be added to the request.
89
+ * @returns {data} the updated data.
90
+ */
91
+
92
+ add: function (key, value, ops) {
93
+ if (!key)
94
+ throw new TypeError(
95
+ "No key specified."
96
+ );
97
+ if (isNaN(value))
98
+ throw new TypeError(
99
+ "Must specify value to add."
100
+ );
101
+ return arbitrate("add", { id: key, data: value, ops: ops || {} });
102
+ },
103
+
104
+ /**
105
+ * This function subtracts a number to a key in the database. (If no existing number, it will subtract from 0)
106
+ * @param {key} input any string as a key. Also allows for dot notation following the key.
107
+ * @param {options} [input={ target: null }] Any options to be added to the request.
108
+ * @returns {data} the updated data.
109
+ */
110
+
111
+ subtract: function (key, value, ops) {
112
+ if (!key)
113
+ throw new TypeError(
114
+ "No key specified."
115
+ );
116
+ if (isNaN(value))
117
+ throw new TypeError(
118
+ "Must specify value to add."
119
+ );
120
+ return arbitrate("subtract", { id: key, data: value, ops: ops || {} });
121
+ },
122
+
123
+ /**
124
+ * This function will push into an array in the database based on the key. (If no existing array, it will create one)
125
+ * @param {key} input any string as a key. Also allows for dot notation following the key.
126
+ * @param {options} [input={ target: null }] Any options to be added to the request.
127
+ * @returns {data} the updated data.
128
+ */
129
+
130
+ push: function (key, value, ops) {
131
+ if (!key)
132
+ throw new TypeError(
133
+ "No key specified."
134
+ );
135
+ if (!value && value != 0)
136
+ throw new TypeError(
137
+ "Must specify value to push."
138
+ );
139
+ return arbitrate("push", {
140
+ stringify: true,
141
+ id: key,
142
+ data: value,
143
+ ops: ops || {},
144
+ });
145
+ },
146
+
147
+ /**
148
+
149
+ */
150
+
151
+ /**
152
+ * This function will delete an object (or property) in the database.
153
+ * @param {key} input any string as a key. Also allows for dot notation following the key, this will delete the prop in the object.
154
+ * @param {options} [input={ target: null }] Any options to be added to the request.
155
+ * @returns {boolean} if it was a success or not.
156
+ */
157
+
158
+ delete: function (key, ops) {
159
+ if (!key)
160
+ throw new TypeError(
161
+ "No key specified."
162
+ );
163
+ return arbitrate("delete", { id: key, ops: ops || {} });
164
+ },
165
+
166
+ /**
167
+ * This function returns a boolean indicating whether an element with the specified key exists or not.
168
+ * @param {key} input any string as a key. Also allows for dot notation following the key, this will return if the prop exists or not.
169
+ * @param {options} [input={ target: null }] Any options to be added to the request.
170
+ * @returns {boolean} if it exists.
171
+ */
172
+
173
+ has: function (key, ops) {
174
+ if (!key)
175
+ throw new TypeError(
176
+ "No key specified."
177
+ );
178
+ return arbitrate("has", { id: key, ops: ops || {} });
179
+ },
180
+
181
+ includes: function (key, ops) {
182
+ if (!key)
183
+ throw new TypeError(
184
+ "No key specified."
185
+ );
186
+ return arbitrate("has", { id: key, ops: ops || {} });
187
+ },
188
+
189
+ /**
190
+ * This function fetches the entire active table
191
+ * @param {options} [input={ target: null }] Any options to be added to the request.
192
+ * @returns {boolean} if it exists.
193
+ */
194
+
195
+ all: function (ops) {
196
+ return arbitrate("all", { ops: ops || {} });
197
+ },
198
+
199
+ fetchAll: function (ops) {
200
+ return arbitrate("all", { ops: ops || {} });
201
+ },
202
+
203
+ /*
204
+ * Used to get the type of the value.
205
+ */
206
+
207
+ type: function (key, ops) {
208
+ if (!key)
209
+ throw new TypeError(
210
+ "No key specified."
211
+ );
212
+ return arbitrate("type", { id: key, ops: ops || {} });
213
+ },
214
+
215
+ /**
216
+ * Using 'new' on this function creates a new instance of a table.
217
+ * @param {name} input any string as the name of the table.
218
+ * @param {options} options.
219
+ */
220
+
221
+ table: function (tableName, options = {}) {
222
+ // Set Name
223
+ if (typeof tableName !== "string")
224
+ throw new TypeError(
225
+ "Table name has to be a string."
226
+ );
227
+ else if (tableName.includes(" "))
228
+ throw new TypeError(
229
+ "Table name cannot include spaces."
230
+ );
231
+ this.tableName = tableName;
232
+
233
+ // Methods
234
+ this.fetch = function (key, ops) {
235
+ if (!key)
236
+ throw new TypeError(
237
+ "No key specified."
238
+ );
239
+ return arbitrate(
240
+ "fetch",
241
+ { id: key, ops: ops || {} },
242
+ this.tableName
243
+ );
244
+ };
245
+
246
+ this.get = function (key, ops) {
247
+ if (!key)
248
+ throw new TypeError(
249
+ "No key specified."
250
+ );
251
+ return arbitrate(
252
+ "fetch",
253
+ { id: key, ops: ops || {} },
254
+ this.tableName
255
+ );
256
+ };
257
+
258
+ this.set = function (key, value, ops) {
259
+ if (!key)
260
+ throw new TypeError(
261
+ "No key specified."
262
+ );
263
+ if (!value && value != 0)
264
+ throw new TypeError(
265
+ "No value specified."
266
+ );
267
+ return arbitrate(
268
+ "set",
269
+ { stringify: true, id: key, data: value, ops: ops || {} },
270
+ this.tableName
271
+ );
272
+ };
273
+
274
+ this.add = function (key, value, ops) {
275
+ if (!key)
276
+ throw new TypeError(
277
+ "No key specified."
278
+ );
279
+ if (isNaN(value))
280
+ throw new TypeError(
281
+ "Must specify value to add."
282
+ );
283
+ return arbitrate(
284
+ "add",
285
+ { id: key, data: value, ops: ops || {} },
286
+ this.tableName
287
+ );
288
+ };
289
+
290
+ this.subtract = function (key, value, ops) {
291
+ if (!key)
292
+ throw new TypeError(
293
+ "No key specified."
294
+ );
295
+ if (isNaN(value))
296
+ throw new TypeError(
297
+ "Must specify value to add."
298
+ );
299
+ return arbitrate(
300
+ "subtract",
301
+ { id: key, data: value, ops: ops || {} },
302
+ this.tableName
303
+ );
304
+ };
305
+
306
+ this.push = function (key, value, ops) {
307
+ if (!key)
308
+ throw new TypeError(
309
+ "No key specified."
310
+ );
311
+ if (!value && value != 0)
312
+ throw new TypeError(
313
+ "Must specify value to push."
314
+ );
315
+ return arbitrate(
316
+ "push",
317
+ { stringify: true, id: key, data: value, ops: ops || {} },
318
+ this.tableName
319
+ );
320
+ };
321
+
322
+ this.delete = function (key, ops) {
323
+ if (!key)
324
+ throw new TypeError(
325
+ "No key specified."
326
+ );
327
+ return arbitrate(
328
+ "delete",
329
+ { id: key, ops: ops || {} },
330
+ this.tableName
331
+ );
332
+ };
333
+
334
+ this.has = function (key, ops) {
335
+ if (!key)
336
+ throw new TypeError(
337
+ "No key specified."
338
+ );
339
+ return arbitrate(
340
+ "has",
341
+ { id: key, ops: ops || {} },
342
+ this.tableName
343
+ );
344
+ };
345
+
346
+ this.includes = function (key, ops) {
347
+ if (!key)
348
+ throw new TypeError(
349
+ "No key specified."
350
+ );
351
+ return arbitrate(
352
+ "has",
353
+ { id: key, ops: ops || {} },
354
+ this.tableName
355
+ );
356
+ };
357
+
358
+ this.fetchAll = function (ops) {
359
+ return arbitrate("all", { ops: ops || {} }, this.tableName);
360
+ };
361
+
362
+ this.all = function (ops) {
363
+ return arbitrate("all", { ops: ops || {} }, this.tableName);
364
+ };
365
+ },
366
+ };
367
+
368
+ function arbitrate(method, params, tableName) {
369
+ // Configure Options
370
+ let options = {table: tableName || params.ops.table || "json",};
371
+
372
+ // Access Database
373
+ db.prepare(`CREATE TABLE IF NOT EXISTS ${options.table} (ID TEXT, json TEXT)`).run();
374
+
375
+ // Verify Options
376
+ if (params.ops.target && params.ops.target[0] === ".") params.ops.target = params.ops.target.slice(1); // Remove prefix if necessary
377
+ if (params.data && params.data === Infinity) throw new TypeError(`You cannot set Infinity into the database @ ID: ${params.id}`);
378
+
379
+ // Stringify
380
+ // if (params.stringify) {
381
+ // try {
382
+ // params.data = JSON.stringify(params.data);
383
+ // } catch (e) {
384
+ // throw new TypeError(
385
+ // `Please supply a valid input @ ID: ${params.id}\nError: ${e.message}`
386
+ // );
387
+ // }
388
+ // }
389
+
390
+ // Translate dot notation from keys
391
+ if (params.id && typeof params.id == "string" && params.id.includes(".")) {
392
+ let unparsed = params.id.split(".");
393
+ params.id = unparsed.shift();
394
+ params.ops.target = unparsed.join(".");
395
+ }
396
+
397
+ // Run & Return Method
398
+ return methods[method](db, params, options);
399
+ }
@@ -0,0 +1,286 @@
1
+ /* eslint-disable linebreak-style */
2
+
3
+ function addDB(db, params, options) {
4
+ const get = require('lodash/get');
5
+ const set = require('lodash/set');
6
+
7
+ // Fetch entry
8
+ let fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
9
+
10
+ // If not found, create empty row
11
+ if (!fetched) {
12
+ db.prepare(`INSERT INTO ${options.table} (ID,json) VALUES (?,?)`).run(params.id, '{}');
13
+ fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
14
+ }
15
+
16
+ // Check if a target was supplied
17
+ if (params.ops.target) {
18
+ fetched = JSON.parse(fetched.json);
19
+ try { fetched = JSON.parse(fetched) } catch (e) {}
20
+ params.data = JSON.parse(params.data);
21
+ let oldValue = get(fetched, params.ops.target);
22
+ if (oldValue === undefined) oldValue = 0;
23
+ else if (isNaN(oldValue)) throw new Error(`Data @ ID: "${params.id}" IS NOT A number.\nFOUND: ${fetched}\nEXPECTED: number`);
24
+ params.data = set(fetched, params.ops.target, oldValue + params.data);
25
+ } else {
26
+ if (fetched.json === '{}') fetched.json = 0;
27
+ else fetched.json = JSON.parse(fetched.json)
28
+ try { fetched.json = JSON.parse(fetched) } catch (e) {}
29
+ if (isNaN(fetched.json)) throw new Error(`Data @ ID: "${params.id}" IS NOT A number.\nFOUND: ${fetched.json}\nEXPECTED: number`);
30
+ params.data = parseInt(fetched.json, 10) + parseInt(params.data, 10);
31
+ }
32
+ // Should do the trick!
33
+ // Stringify data
34
+ params.data = JSON.stringify(params.data);
35
+
36
+ // Update entry with new data
37
+ db.prepare(`UPDATE ${options.table} SET json = (?) WHERE ID = (?)`).run(params.data, params.id);
38
+
39
+ // Fetch & return new data
40
+ let newData = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id).json;
41
+ if (newData === '{}') return null;
42
+ else {
43
+ newData = JSON.parse(newData)
44
+ try { newData = JSON.parse(newData); } catch (e) {}
45
+ return newData;
46
+ }
47
+ }
48
+
49
+ function allDB(db, params, options) {
50
+
51
+ // Fetch Entry
52
+ var stmt = db.prepare(`SELECT * FROM ${options.table} WHERE ID IS NOT NULL`);
53
+ let resp = [];
54
+ for (var row of stmt.iterate()) {
55
+ try {
56
+ resp.push({
57
+ ID: row.ID,
58
+ data: JSON.parse(row.json)
59
+ });
60
+ } catch (e) {
61
+ return [];
62
+ }
63
+ }
64
+
65
+ return resp;
66
+ }
67
+
68
+ function clearDB(db, params, options) {
69
+
70
+ // Delete all Rows
71
+ let fetched = db.prepare(`DELETE FROM ${options.table}`).run();
72
+ if(!fetched) return null;
73
+
74
+ // Return Amount of Rows Deleted
75
+ return fetched.changes;
76
+
77
+ }
78
+
79
+ function deleteDB(db, params, options) {
80
+ const unset = require('lodash/unset');
81
+ // Fetch Entry
82
+ let fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
83
+ if (!fetched) return false; // If empty, return null
84
+ else fetched = JSON.parse(fetched.json);
85
+ try { fetched = JSON.parse(fetched); } catch (e) {}
86
+
87
+ // Check if the user wants to delete a prop inside an object
88
+ if (typeof fetched === 'object' && params.ops.target) {
89
+ unset(fetched, params.ops.target);
90
+ fetched = JSON.stringify(fetched);
91
+ db.prepare(`UPDATE ${options.table} SET json = (?) WHERE ID = (?)`).run(fetched, params.id);
92
+ return true;
93
+ }
94
+ else if (params.ops.target) throw new TypeError('Target is not an object.');
95
+ else db.prepare(`DELETE FROM ${options.table} WHERE ID = (?)`).run(params.id);
96
+
97
+ // Resolve
98
+ return true;
99
+ }
100
+
101
+ function fetchDB(db, params, options) {
102
+ const get = require('lodash/get');
103
+ // Fetch Entry
104
+ let fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
105
+ if (!fetched) return null; // If empty, return null
106
+ fetched = JSON.parse(fetched.json)
107
+ try { fetched = JSON.parse(fetched) } catch (e) {}
108
+
109
+ // Check if target was supplied
110
+ if (params.ops.target) fetched = get(fetched, params.ops.target); // Get prop using dot notation
111
+
112
+ // Return data
113
+ return fetched;
114
+ }
115
+
116
+ function hasDB(db, params, options) {
117
+ const get = require('lodash/get');
118
+ // Fetch Entry
119
+ let fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
120
+ if (!fetched) return false; // If empty, return false
121
+ else fetched = JSON.parse(fetched.json);
122
+ try { fetched = JSON.parse(fetched) } catch (e) {}
123
+
124
+ // Check if target was supplied
125
+ if (params.ops.target) fetched = get(fetched, params.ops.target); // Get prop using dot notation
126
+
127
+ // Return boolean
128
+ return (typeof fetched != 'undefined');
129
+ } // Papa bless, you here? I think we need update, push wasn't working.
130
+
131
+ function pushDB(db, params, options) {
132
+ const get = require('lodash/get');
133
+ const set = require('lodash/set');
134
+ // Fetch entry
135
+ let fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
136
+
137
+ // If not found, create empty row
138
+ if (!fetched) {
139
+ db.prepare(`INSERT INTO ${options.table} (ID,json) VALUES (?,?)`).run(params.id, '{}');
140
+ fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
141
+ }
142
+
143
+ // Check if a target was supplied
144
+ if (params.ops.target) {
145
+ fetched = JSON.parse(fetched.json);
146
+ try { fetched = JSON.parse(fetched) } catch (e) {}
147
+ params.data = JSON.parse(params.data);
148
+ if (typeof fetched !== 'object') throw new TypeError('Cannot push into a non-object.');
149
+ let oldArray = get(fetched, params.ops.target);
150
+ if (oldArray === undefined) oldArray = [];
151
+ else if (!Array.isArray(oldArray)) throw new TypeError('Target is not an array.');
152
+ oldArray.push(params.data);
153
+ params.data = set(fetched, params.ops.target, oldArray);
154
+ } else {
155
+ if (fetched.json === '{}') fetched.json = [];
156
+ else fetched.json = JSON.parse(fetched.json);
157
+ try { fetched.json = JSON.parse(fetched.json); } catch (e) {}
158
+ params.data = JSON.parse(params.data);
159
+ if (!Array.isArray(fetched.json)) throw new TypeError('Target is not an array.');
160
+ fetched.json.push(params.data);
161
+ params.data = fetched.json;
162
+ }
163
+
164
+ // Stringify data
165
+ params.data = JSON.stringify(params.data);
166
+
167
+ // Update entry with new data
168
+ db.prepare(`UPDATE ${options.table} SET json = (?) WHERE ID = (?)`).run(params.data, params.id);
169
+
170
+ // Fetch & return new data
171
+ let newData = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id).json;
172
+ if (newData === '{}') return null;
173
+ else {
174
+ newData = JSON.parse(newData)
175
+ try { newData = JSON.parse(newData) } catch (e) {}
176
+ return newData
177
+ }
178
+ }
179
+
180
+ function setDB(db, params, options) {
181
+ const set = require('lodash/set');
182
+ // Fetch entry
183
+ let fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
184
+ // If not found, create empty row
185
+ if (!fetched) {
186
+ db.prepare(`INSERT INTO ${options.table} (ID,json) VALUES (?,?)`).run(params.id, '{}');
187
+ fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
188
+ }
189
+
190
+ // Parse fetched
191
+
192
+ try { fetched = JSON.parse(fetched); console.log(fetched) } catch (e) {}
193
+
194
+ // Check if a target was supplied
195
+ if (typeof fetched === 'object' && params.ops.target) {
196
+ params.data = JSON.parse(params.data);
197
+ params.data = set(fetched, params.ops.target, params.data);
198
+ } else if (params.ops.target) throw new TypeError('Cannot target a non-object.');
199
+
200
+ // Stringify data
201
+ params.data = JSON.stringify(params.data);
202
+
203
+ // Update entry with new data
204
+ db.prepare(`UPDATE ${options.table} SET json = (?) WHERE ID = (?)`).run(params.data, params.id);
205
+
206
+ // Fetch & return new data
207
+ let newData = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id).json;
208
+ if (newData === '{}') return null;
209
+ else {
210
+ try { newData = JSON.parse(newData); } catch (e) {
211
+ console.log(e);
212
+ }
213
+ return newData;
214
+ }
215
+ }
216
+
217
+ function subtractDB(db, params, options) {
218
+ const get = require('lodash/get');
219
+ const set = require('lodash/set');
220
+ // Fetch entry
221
+ let fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
222
+
223
+ // If not found, create empty row
224
+ if (!fetched) {
225
+ db.prepare(`INSERT INTO ${options.table} (ID,json) VALUES (?,?)`).run(params.id, '{}');
226
+ fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
227
+ }
228
+
229
+ // Check if a target was supplied
230
+ if (params.ops.target) {
231
+ try { fetched = JSON.parse(fetched); } catch (e) {}
232
+ params.data = JSON.parse(params.data);
233
+ let oldValue = get(fetched, params.ops.target);
234
+ if (oldValue === undefined) oldValue = 0;
235
+ else if (isNaN(oldValue)) throw new Error('Target is not a number.');
236
+ params.data = set(fetched, params.ops.target, oldValue - params.data);
237
+ } else {
238
+ if (fetched.json === '{}') fetched.json = 0;
239
+ else fetched.json = JSON.parse(fetched.json);
240
+ try { fetched.json = JSON.parse(fetched); } catch (e) {}
241
+ if (isNaN(fetched.json)) throw new Error('Target is not a number.');
242
+ params.data = parseInt(fetched.json, 10) - parseInt(params.data, 10);
243
+ }
244
+
245
+ // Stringify data
246
+ params.data = JSON.stringify(params.data);
247
+
248
+ // Update entry with new data
249
+ db.prepare(`UPDATE ${options.table} SET json = (?) WHERE ID = (?)`).run(params.data, params.id);
250
+
251
+ // Fetch & return new data
252
+ let newData = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id).json;
253
+ if (newData === '{}') return null;
254
+ else {
255
+ try { newData = JSON.parse(newData); } catch (e) {}
256
+ return newData;
257
+ }
258
+ }
259
+
260
+ function typeDB(db, params, options) {
261
+ const get = require('lodash/get');
262
+ // Fetch Entry
263
+ let fetched = db.prepare(`SELECT * FROM ${options.table} WHERE ID = (?)`).get(params.id);
264
+ if (!fetched) return null; // If empty, return null
265
+ fetched = JSON.parse(fetched.json);
266
+ try { fetched = JSON.parse(fetched); } catch (e) {}
267
+
268
+ // Check if target was supplied
269
+ if (params.ops.target) fetched = get(fetched, params.ops.target); // Get prop using dot notation
270
+
271
+ // Return data
272
+ return typeof fetched;
273
+ }
274
+
275
+ module.exports = {
276
+ add:addDB,
277
+ all:allDB,
278
+ clear:clearDB,
279
+ deleteDB:deleteDB,
280
+ fetch:fetchDB,
281
+ has:hasDB,
282
+ push:pushDB,
283
+ set:setDB,
284
+ subtract:subtractDB,
285
+ type:typeDB
286
+ };