-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpublisher.js
More file actions
178 lines (152 loc) · 5.26 KB
/
publisher.js
File metadata and controls
178 lines (152 loc) · 5.26 KB
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
import express from 'express';
import bodyParser from 'body-parser'
import cors from 'cors'
import Datastore from 'nedb'
import webpush from 'web-push'
import Web3 from 'web3'
import freqJSON from '../32Daily/build/contracts/DoxaHub.json';
import factories from '../32Daily/build/factories/freqs.json';
const publishAccount = '0x0b64e7dcb7d1580f8898c78610b38e71ddc79236';
const app = express(),
db = new Datastore({ filename: './subscriptions', autoload: true }),
sentFundsdb = new Datastore({ filename: './sentFunds', autoload: true }),
provider = new Web3.providers.HttpProvider('http://localhost:8545/'),
web3 = new Web3(provider),
vapidKeys = {
publicKey: 'BMxIuowQ1--yaQr7jFqkV6TLDt8ttKEGXGxKqwJFPkaslR9mvL6CtVfIOTzIRrXFgcjQt5AC08hVsT59jaJ729U',
privateKey: 'bteELaCCW9Q950OBOnekQ-c7sh7XUAd44TwRtQpqdDQ'
};
webpush.setVapidDetails(
'mailto:travis@doxa.network',
vapidKeys.publicKey,
vapidKeys.privateKey
);
app.use(cors());
app.use(bodyParser.json());
async function getContract(freq) {
let contractJSON = freqJSON;
const networkId = await web3.eth.net.getId();
const address = factories[freq]['hub'];
const contract = new web3.eth.Contract(contractJSON.abi, address);
return contract;
}
async function publish(freq) {
console.log(`${freq} - publishing now`)
const contract = await getContract(freq);
// const gasEstimate = await contract.methods.publish().estimateGas({from: '0xd45e8cbb5a04c5e98ceb29d8ad9147ee0d0f3ec2'});
let result;
try {
result = await contract.methods.publish().send({from: publishAccount, gas: 7000000, gasPrice: 10*10**9});
} catch(e) {
console.log("error: " + e)
process.exit(1); //this should exit and pm2 should restart the process
}
// must catch an error here and retry
const event = result.events["Published"];
if (event) {
console.log(`${freq} - new item published`);
const owner = event.returnValues.owner;
const version = event.returnValues.version;
const content = event.returnValues.content;
await publishNotification(JSON.stringify({freq, owner}));
}
return result;
}
async function setNextPublish(freq) {
const contract = await getContract(freq);
const nextPublishTime = await contract.methods.nextPublishTime().call();
const nextPublishDate = new Date(nextPublishTime * 1000);
const currentTime = new Date();
let msec = nextPublishDate.getTime() - currentTime.getTime();
console.log(`${freq} - publishing in ${(msec/(1000*60)).toFixed(2)} mins`);
setTimeout(async function() {
await publish(freq);
await setNextPublish(freq);
}, msec + 15*1000)
}
setNextPublish('freq1');
setNextPublish('freq2');
setNextPublish('freq3');
async function publishNotification(dataToSend) {
const subscriptions = await getSubscriptionsFromDatabase()
for (let i = 0; i < subscriptions.length; i++) {
const subscription = subscriptions[i];
try {
await triggerPushMsg(subscription, dataToSend);
} catch(err) {
console.log(`error sending push to ${subscription}`)
console.log(err)
}
}
}
const triggerPushMsg = async function(subscription, dataToSend) {
try {
webpush.sendNotification(subscription, dataToSend);
} catch(err) {
if (err.statusCode === 410) {
return deleteSubscriptionFromDatabase(subscription._id);
} else {
console.log('Subscription is no longer valid: ', err);
}
}
};
app.post('/save-subscription/', async function (req, res) {
const isValidSaveRequest = (req, res) => {
// Check the request body has at least an endpoint.
if (!req.body || !req.body.endpoint) {
// Not a valid subscription.
res.status(400);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({
error: {
id: 'no-endpoint',
message: 'Subscription must have an endpoint.'
}
}));
return false;
}
return true;
};
console.log("valid request:" + isValidSaveRequest(req, res))
try {
const subscriptionId = await saveSubscriptionToDatabase(req.body);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ data: { success: true } }));
} catch(err) {
res.status(500);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({
error: {
id: 'unable-to-save-subscription',
message: 'The subscription was received but we were unable to save it to our database.'
}
}));
}
});
function getSubscriptionsFromDatabase() {
console.log("attempting to load subscriptions from db");
return new Promise(function(resolve, reject) {
db.find({}, function (err, docs) {
if (err) {
console.log("error:" + err)
reject(err);
return;
}
resolve(docs);
});
})
}
function saveSubscriptionToDatabase(subscription) {
console.log("save attempted")
return new Promise(function(resolve, reject) {
db.insert(subscription, function(err, newDoc) {
if (err) {
console.log("error:" + err)
reject(err);
return;
}
resolve(newDoc._id);
});
});
};
app.listen(5000, () => console.log('Publisher up and listening on port 5000'))