Migrate to better-sqlite3
This commit is contained in:
parent
e2ab4dd51e
commit
e989126e86
7 changed files with 148 additions and 164 deletions
8
index.js
8
index.js
|
@ -2,8 +2,8 @@ const config = require('./config.json');
|
|||
const { USER, PASS, DOMAIN, PRIVKEY_PATH, CERT_PATH, PORT } = config;
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
const db = new sqlite3.Database('bot-node.db');
|
||||
const Database = require('better-sqlite3');
|
||||
const db = new Database('bot-node.db');
|
||||
const fs = require('fs');
|
||||
const routes = require('./routes'),
|
||||
bodyParser = require('body-parser'),
|
||||
|
@ -27,9 +27,9 @@ try {
|
|||
}
|
||||
|
||||
// if there is no `accounts` table in the DB, create an empty table
|
||||
db.run('CREATE TABLE IF NOT EXISTS accounts (name TEXT PRIMARY KEY, privkey TEXT, pubkey TEXT, webfinger TEXT, actor TEXT, apikey TEXT, followers TEXT, messages TEXT)');
|
||||
db.prepare('CREATE TABLE IF NOT EXISTS accounts (name TEXT PRIMARY KEY, privkey TEXT, pubkey TEXT, webfinger TEXT, actor TEXT, apikey TEXT, followers TEXT, messages TEXT)').run();
|
||||
// if there is no `messages` table in the DB, create an empty table
|
||||
db.run('CREATE TABLE IF NOT EXISTS messages (guid TEXT PRIMARY KEY, message TEXT)');
|
||||
db.prepare('CREATE TABLE IF NOT EXISTS messages (guid TEXT PRIMARY KEY, message TEXT)').run();
|
||||
|
||||
app.set('db', db);
|
||||
app.set('domain', DOMAIN);
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
"description": "",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^5.4.0",
|
||||
"body-parser": "^1.18.3",
|
||||
"cors": "^2.8.4",
|
||||
"express": "^4.16.3",
|
||||
"express-basic-auth": "^1.1.5",
|
||||
"generate-rsa-keypair": "^0.1.2",
|
||||
"request": "^2.87.0",
|
||||
"sqlite3": "^4.0.2"
|
||||
"request": "^2.87.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.10.0"
|
||||
|
|
|
@ -52,16 +52,13 @@ router.post('/create', function (req, res) {
|
|||
let actorRecord = createActor(account, domain, pair.public);
|
||||
let webfingerRecord = createWebfinger(account, domain);
|
||||
const apikey = crypto.randomBytes(16).toString('hex');
|
||||
db.run('insert or replace into accounts(name, actor, apikey, pubkey, privkey, webfinger) values($name, $actor, $apikey, $pubkey, $privkey, $webfinger)', {
|
||||
$name: `${account}@${domain}`,
|
||||
$apikey: apikey,
|
||||
$pubkey: pair.public,
|
||||
$privkey: pair.private,
|
||||
$actor: JSON.stringify(actorRecord),
|
||||
$webfinger: JSON.stringify(webfingerRecord)
|
||||
}, (err, accounts) => {
|
||||
try {
|
||||
db.prepare('insert or replace into accounts(name, actor, apikey, pubkey, privkey, webfinger) values(?, ?, ?, ?, ?, ?)').run(`${account}@${domain}`, JSON.stringify(actorRecord), apikey, pair.public, pair.private, JSON.stringify(webfingerRecord));
|
||||
res.status(200).json({msg: 'ok', apikey});
|
||||
});
|
||||
}
|
||||
catch(e) {
|
||||
res.status(200).json({error: e});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
|
130
routes/api.js
130
routes/api.js
|
@ -6,61 +6,58 @@ const express = require('express'),
|
|||
|
||||
router.post('/sendMessage', function (req, res) {
|
||||
let db = req.app.get('db');
|
||||
console.log('DB',db);
|
||||
let domain = req.app.get('domain');
|
||||
let acct = req.body.acct;
|
||||
let apikey = req.body.apikey;
|
||||
let message = req.body.message;
|
||||
// check to see if your API key matches
|
||||
db.get('select apikey from accounts where name = $name', {$name: `${acct}@${domain}`}, (err, result) => {
|
||||
if (result.apikey === apikey) {
|
||||
sendCreateMessage(message, acct, domain, req, res);
|
||||
}
|
||||
else {
|
||||
res.status(403).json({msg: 'wrong api key'});
|
||||
}
|
||||
});
|
||||
let result = db.prepare('select apikey from accounts where name = ?').get(`${acct}@${domain}`);
|
||||
if (result.apikey === apikey) {
|
||||
sendCreateMessage(message, acct, domain, req, res);
|
||||
}
|
||||
else {
|
||||
res.status(403).json({msg: 'wrong api key'});
|
||||
}
|
||||
});
|
||||
|
||||
function signAndSend(message, name, domain, req, res, targetDomain, inbox) {
|
||||
// get the private key
|
||||
let db = req.app.get('db');
|
||||
let inboxFragment = inbox.replace('https://'+targetDomain,'');
|
||||
db.get('select privkey from accounts where name = $name', {$name: `${name}@${domain}`}, (err, result) => {
|
||||
if (result === undefined) {
|
||||
console.log(`No record found for ${name}.`);
|
||||
}
|
||||
else {
|
||||
let privkey = result.privkey;
|
||||
const signer = crypto.createSign('sha256');
|
||||
let d = new Date();
|
||||
let stringToSign = `(request-target): post ${inboxFragment}\nhost: ${targetDomain}\ndate: ${d.toUTCString()}`;
|
||||
signer.update(stringToSign);
|
||||
signer.end();
|
||||
const signature = signer.sign(privkey);
|
||||
const signature_b64 = signature.toString('base64');
|
||||
let header = `keyId="https://${domain}/u/${name}",headers="(request-target) host date",signature="${signature_b64}"`;
|
||||
request({
|
||||
url: inbox,
|
||||
headers: {
|
||||
'Host': targetDomain,
|
||||
'Date': d.toUTCString(),
|
||||
'Signature': header
|
||||
},
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: message
|
||||
}, function (error, response){
|
||||
console.log(`Sent message to an inbox at ${targetDomain}!`);
|
||||
if (error) {
|
||||
console.log('Error:', error, response);
|
||||
}
|
||||
else {
|
||||
console.log('Response Status Code:', response.statusCode);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
let result = db.prepare('select privkey from accounts where name = ?').get(`${name}@${domain}`);
|
||||
if (result === undefined) {
|
||||
console.log(`No record found for ${name}.`);
|
||||
}
|
||||
else {
|
||||
let privkey = result.privkey;
|
||||
const signer = crypto.createSign('sha256');
|
||||
let d = new Date();
|
||||
let stringToSign = `(request-target): post ${inboxFragment}\nhost: ${targetDomain}\ndate: ${d.toUTCString()}`;
|
||||
signer.update(stringToSign);
|
||||
signer.end();
|
||||
const signature = signer.sign(privkey);
|
||||
const signature_b64 = signature.toString('base64');
|
||||
let header = `keyId="https://${domain}/u/${name}",headers="(request-target) host date",signature="${signature_b64}"`;
|
||||
request({
|
||||
url: inbox,
|
||||
headers: {
|
||||
'Host': targetDomain,
|
||||
'Date': d.toUTCString(),
|
||||
'Signature': header
|
||||
},
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: message
|
||||
}, function (error, response){
|
||||
console.log(`Sent message to an inbox at ${targetDomain}!`);
|
||||
if (error) {
|
||||
console.log('Error:', error, response);
|
||||
}
|
||||
else {
|
||||
console.log('Response Status Code:', response.statusCode);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createMessage(text, name, domain, req, res) {
|
||||
|
@ -88,16 +85,8 @@ function createMessage(text, name, domain, req, res) {
|
|||
'object': noteMessage
|
||||
};
|
||||
|
||||
db.run('insert or replace into messages(guid, message) values($guid, $message)', {
|
||||
$guid: guidCreate,
|
||||
$message: JSON.stringify(createMessage),
|
||||
}, (err, accounts) => {
|
||||
});
|
||||
db.run('insert or replace into messages(guid, message) values($guid, $message)', {
|
||||
$guid: guidNote,
|
||||
$message: JSON.stringify(noteMessage),
|
||||
}, (err, accounts) => {
|
||||
});
|
||||
db.prepare('insert or replace into messages(guid, message) values(?, ?)').run( guidCreate, JSON.stringify(createMessage));
|
||||
db.prepare('insert or replace into messages(guid, message) values(?, ?)').run( guidNote, JSON.stringify(noteMessage));
|
||||
|
||||
return createMessage;
|
||||
}
|
||||
|
@ -106,24 +95,23 @@ function sendCreateMessage(text, name, domain, req, res) {
|
|||
let message = createMessage(text, name, domain, req, res);
|
||||
let db = req.app.get('db');
|
||||
|
||||
db.get('select followers from accounts where name = $name', {$name: `${name}@${domain}`}, (err, result) => {
|
||||
let followers = JSON.parse(result.followers);
|
||||
console.log(followers);
|
||||
console.log('type',typeof followers);
|
||||
if (followers === null) {
|
||||
console.log('aaaa');
|
||||
res.status(400).json({msg: `No followers for account ${name}@${domain}`});
|
||||
let result = db.prepare('select followers from accounts where name = ?').get(`${name}@${domain}`);
|
||||
let followers = JSON.parse(result.followers);
|
||||
console.log(followers);
|
||||
console.log('type',typeof followers);
|
||||
if (followers === null) {
|
||||
console.log('aaaa');
|
||||
res.status(400).json({msg: `No followers for account ${name}@${domain}`});
|
||||
}
|
||||
else {
|
||||
for (let follower of followers) {
|
||||
let inbox = follower+'/inbox';
|
||||
let myURL = new URL(follower);
|
||||
let targetDomain = myURL.hostname;
|
||||
signAndSend(message, name, domain, req, res, targetDomain, inbox);
|
||||
}
|
||||
else {
|
||||
for (let follower of followers) {
|
||||
let inbox = follower+'/inbox';
|
||||
let myURL = new URL(follower);
|
||||
let targetDomain = myURL.hostname;
|
||||
signAndSend(message, name, domain, req, res, targetDomain, inbox);
|
||||
}
|
||||
res.status(200).json({msg: 'ok'});
|
||||
}
|
||||
});
|
||||
res.status(200).json({msg: 'ok'});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
|
|
110
routes/inbox.js
110
routes/inbox.js
|
@ -10,41 +10,40 @@ function signAndSend(message, name, domain, req, res, targetDomain) {
|
|||
let inboxFragment = inbox.replace('https://'+targetDomain,'');
|
||||
// get the private key
|
||||
let db = req.app.get('db');
|
||||
db.get('select privkey from accounts where name = $name', {$name: `${name}@${domain}`}, (err, result) => {
|
||||
if (result === undefined) {
|
||||
return res.status(404).send(`No record found for ${name}.`);
|
||||
}
|
||||
else {
|
||||
let privkey = result.privkey;
|
||||
const signer = crypto.createSign('sha256');
|
||||
let d = new Date();
|
||||
let stringToSign = `(request-target): post ${inboxFragment}\nhost: ${targetDomain}\ndate: ${d.toUTCString()}`;
|
||||
signer.update(stringToSign);
|
||||
signer.end();
|
||||
const signature = signer.sign(privkey);
|
||||
const signature_b64 = signature.toString('base64');
|
||||
let header = `keyId="https://${domain}/u/${name}",headers="(request-target) host date",signature="${signature_b64}"`;
|
||||
request({
|
||||
url: inbox,
|
||||
headers: {
|
||||
'Host': targetDomain,
|
||||
'Date': d.toUTCString(),
|
||||
'Signature': header
|
||||
},
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: message
|
||||
}, function (error, response){
|
||||
if (error) {
|
||||
console.log('Error:', error, response.body);
|
||||
}
|
||||
else {
|
||||
console.log('Response:', response.body);
|
||||
}
|
||||
});
|
||||
return res.status(200);
|
||||
}
|
||||
});
|
||||
let result = db.prepare('select privkey from accounts where name = ?').get(name);
|
||||
if (result === undefined) {
|
||||
return res.status(404).send(`No record found for ${name}.`);
|
||||
}
|
||||
else {
|
||||
let privkey = result.privkey;
|
||||
const signer = crypto.createSign('sha256');
|
||||
let d = new Date();
|
||||
let stringToSign = `(request-target): post ${inboxFragment}\nhost: ${targetDomain}\ndate: ${d.toUTCString()}`;
|
||||
signer.update(stringToSign);
|
||||
signer.end();
|
||||
const signature = signer.sign(privkey);
|
||||
const signature_b64 = signature.toString('base64');
|
||||
let header = `keyId="https://${domain}/u/${name}",headers="(request-target) host date",signature="${signature_b64}"`;
|
||||
request({
|
||||
url: inbox,
|
||||
headers: {
|
||||
'Host': targetDomain,
|
||||
'Date': d.toUTCString(),
|
||||
'Signature': header
|
||||
},
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: message
|
||||
}, function (error, response){
|
||||
if (error) {
|
||||
console.log('Error:', error, response.body);
|
||||
}
|
||||
else {
|
||||
console.log('Response:', response.body);
|
||||
}
|
||||
});
|
||||
return res.status(200);
|
||||
}
|
||||
}
|
||||
|
||||
function sendAcceptMessage(thebody, name, domain, req, res, targetDomain) {
|
||||
|
@ -79,28 +78,31 @@ router.post('/', function (req, res) {
|
|||
// Add the user to the DB of accounts that follow the account
|
||||
let db = req.app.get('db');
|
||||
// get the followers JSON for the user
|
||||
db.get('select followers from accounts where name = $name', {$name: `${name}@${domain}`}, (err, result) => {
|
||||
if (result === undefined) {
|
||||
console.log(`No record found for ${name}.`);
|
||||
let result = db.prepare('select followers from accounts where name = ?').get(`${name}@${domain}`);
|
||||
if (result === undefined) {
|
||||
console.log(`No record found for ${name}.`);
|
||||
}
|
||||
else {
|
||||
// update followers
|
||||
let followers = parseJSON(result.followers);
|
||||
if (followers) {
|
||||
followers.push(req.body.actor);
|
||||
// unique items
|
||||
followers = [...new Set(followers)];
|
||||
}
|
||||
else {
|
||||
// update followers
|
||||
let followers = parseJSON(result.followers);
|
||||
if (followers) {
|
||||
followers.push(req.body.actor);
|
||||
// unique items
|
||||
followers = [...new Set(followers)];
|
||||
}
|
||||
else {
|
||||
followers = [req.body.actor];
|
||||
}
|
||||
let followersText = JSON.stringify(followers);
|
||||
// update into DB
|
||||
db.run('update accounts set followers=$followers where name = $name', {$name: `${name}@${domain}`, $followers: followersText}, (err, result) => {
|
||||
console.log('updated followers!', err, result);
|
||||
});
|
||||
followers = [req.body.actor];
|
||||
}
|
||||
});
|
||||
let followersText = JSON.stringify(followers);
|
||||
try {
|
||||
// update into DB
|
||||
let newFollowers = db.prepare('update accounts set followers=? where name = ?').run(followersText, `${name}@${domain}`);
|
||||
console.log('updated followers!', newFollowers);
|
||||
}
|
||||
catch(e) {
|
||||
console.log('error', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -12,20 +12,19 @@ router.get('/:name', function (req, res) {
|
|||
let domain = req.app.get('domain');
|
||||
let username = name;
|
||||
name = `${name}@${domain}`;
|
||||
db.get('select actor from accounts where name = $name', {$name: name}, (err, result) => {
|
||||
if (result === undefined) {
|
||||
return res.status(404).send(`No record found for ${name}.`);
|
||||
let result = db.prepare('select actor from accounts where name = ?').get(name);
|
||||
if (result === undefined) {
|
||||
return res.status(404).send(`No record found for ${name}.`);
|
||||
}
|
||||
else {
|
||||
let tempActor = JSON.parse(result.actor);
|
||||
// Added this followers URI for Pleroma compatibility, see https://github.com/dariusk/rss-to-activitypub/issues/11#issuecomment-471390881
|
||||
// New Actors should have this followers URI but in case of migration from an old version this will add it in on the fly
|
||||
if (tempActor.followers === undefined) {
|
||||
tempActor.followers = `https://${domain}/u/${username}/followers`;
|
||||
}
|
||||
else {
|
||||
let tempActor = JSON.parse(result.actor);
|
||||
// Added this followers URI for Pleroma compatibility, see https://github.com/dariusk/rss-to-activitypub/issues/11#issuecomment-471390881
|
||||
// New Actors should have this followers URI but in case of migration from an old version this will add it in on the fly
|
||||
if (tempActor.followers === undefined) {
|
||||
tempActor.followers = `https://${domain}/u/${username}/followers`;
|
||||
}
|
||||
res.json(tempActor);
|
||||
}
|
||||
});
|
||||
res.json(tempActor);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -38,10 +37,9 @@ router.get('/:name/followers', function (req, res) {
|
|||
let db = req.app.get('db');
|
||||
let domain = req.app.get('domain');
|
||||
let result = db.prepare('select followers from accounts where name = ?').get(`${name}@${domain}`);
|
||||
console.log(result);
|
||||
result.followers = result.followers || '[]';
|
||||
let followers = JSON.parse(result.followers);
|
||||
if (!followers) {
|
||||
followers = [];
|
||||
}
|
||||
let followersCollection = {
|
||||
"type":"OrderedCollection",
|
||||
"totalItems":followers.length,
|
||||
|
|
|
@ -10,14 +10,13 @@ router.get('/', function (req, res) {
|
|||
else {
|
||||
let name = resource.replace('acct:','');
|
||||
let db = req.app.get('db');
|
||||
db.get('select webfinger from accounts where name = $name', {$name: name}, (err, result) => {
|
||||
if (result === undefined) {
|
||||
return res.status(404).send(`No record found for ${name}.`);
|
||||
}
|
||||
else {
|
||||
res.json(JSON.parse(result.webfinger));
|
||||
}
|
||||
});
|
||||
let result = db.prepare('select webfinger from accounts where name = ?').get(name);
|
||||
if (result === undefined) {
|
||||
return res.status(404).send(`No record found for ${name}.`);
|
||||
}
|
||||
else {
|
||||
res.json(JSON.parse(result.webfinger));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue