attestation watcher

This commit is contained in:
Danil Kovtonyuk 2020-02-26 00:13:09 +10:00
parent 4256306fc2
commit e2199c1a95
8 changed files with 145 additions and 8 deletions

View File

@ -10,6 +10,10 @@ MYSQL_DATABASE=phase2
TWITTER_CONSUMER_KEY= TWITTER_CONSUMER_KEY=
TWITTER_CONSUMER_SECRET= TWITTER_CONSUMER_SECRET=
TWITTER_CALLBACK_URL=https://ceremony.tornado.cash/api/oauth_callback/twitter TWITTER_CALLBACK_URL=https://ceremony.tornado.cash/api/oauth_callback/twitter
TWITTER_ACCESS_TOKEN_KEY=
TWITTER_ACCESS_TOKEN_SECRET=
TWITTER_HASHTAG=
TWITTER_INTERVAL_ATTESTATION=300000
GITHUB_CLIEND_ID= GITHUB_CLIEND_ID=
GITHUB_CLIENT_SECRET= GITHUB_CLIENT_SECRET=

View File

@ -27,7 +27,8 @@
"nuxt": "^2.0.0", "nuxt": "^2.0.0",
"nuxt-buefy": "^0.3.2", "nuxt-buefy": "^0.3.2",
"oauth": "^0.9.15", "oauth": "^0.9.15",
"sequelize": "^5.21.3" "sequelize": "^5.21.3",
"twitter": "^1.7.1"
}, },
"devDependencies": { "devDependencies": {
"@nuxtjs/eslint-config": "^1.0.1", "@nuxtjs/eslint-config": "^1.0.1",

View File

@ -57,7 +57,9 @@
<b-table-column :centered="true" label="Attestation"> <b-table-column :centered="true" label="Attestation">
<a <a
v-if="props.row.attestation" v-if="props.row.attestation"
:href="props.row.attestation" :href="
`https://${props.row.socialType}.com/${props.row.handle}/status/${props.row.attestation}`
"
target="_blank" target="_blank"
class="button is-icon" class="button is-icon"
> >

View File

@ -0,0 +1,78 @@
const fs = require('fs')
const Twitter = require('twitter')
const {
TWITTER_CONSUMER_KEY,
TWITTER_CONSUMER_SECRET,
TWITTER_ACCESS_TOKEN_KEY,
TWITTER_ACCESS_TOKEN_SECRET,
TWITTER_HASHTAG,
TWITTER_INTERVAL_ATTESTATION
} = process.env
const client = new Twitter({
consumer_key: TWITTER_CONSUMER_KEY,
consumer_secret: TWITTER_CONSUMER_SECRET,
access_token_key: TWITTER_ACCESS_TOKEN_KEY,
access_token_secret: TWITTER_ACCESS_TOKEN_SECRET
})
const { Contribution } = require('./models')
async function attestationWatcher() {
// get the last saved tweet
let initTweet
try {
initTweet = require('/tmp/lastTweet.json').lastTweet
} catch (e) {
initTweet = process.env.LAST_TWEET
}
// get all contributions without attestation
const contributions = await Contribution.findAll({
where: {
socialType: 'twitter',
attestation: null
},
attributes: ['id', 'handle', 'socialType', 'attestation']
})
const params = {
since_id: initTweet,
q: `#${TWITTER_HASHTAG} -filter:retweets`,
result_type: 'recent',
count: 100
}
// search tweets with params
client.get('search/tweets', params, function(error, tweets, response) {
if (!error) {
tweets.statuses.forEach((tweet) => {
contributions.forEach((contribution) => {
// compare account compliance
if (contribution.handle === tweet.user.screen_name) {
// update the database record by id
Contribution.update({ attestation: tweet.id_str }, { where: { id: contribution.id } })
console.log(
`Succesful attestation https://${contribution.socialType}.com/${contribution.handle}/status/${tweet.id_str}`
)
}
})
})
// save the last tweet received
fs.writeFileSync(
'/tmp/lastTweet.json',
JSON.stringify({ lastTweet: tweets.search_metadata.max_id_str })
)
} else {
console.error('attestationWatcher error', error)
}
})
setTimeout(() => {
attestationWatcher()
}, TWITTER_INTERVAL_ATTESTATION)
}
module.exports = attestationWatcher

View File

@ -46,9 +46,9 @@ router.get('/challenge', (req, res) => {
router.get('/contributions', async (req, res) => { router.get('/contributions', async (req, res) => {
const contributions = await Contribution.findAll({ const contributions = await Contribution.findAll({
attributes: ['id', 'name', 'company', 'handle', 'socialType'] attributes: ['id', 'name', 'company', 'handle', 'socialType', 'attestation']
}) })
res.json(contributions).send() res.json(contributions)
}) })
router.post('/response', upload.single('response'), async (req, res) => { router.post('/response', upload.single('response'), async (req, res) => {

View File

@ -9,6 +9,7 @@ const config = require('../nuxt.config.js')
const sessionsController = require('./controllers/authorize') const sessionsController = require('./controllers/authorize')
const contributionController = require('./controllers/contribute') const contributionController = require('./controllers/contribute')
const models = require('./models') const models = require('./models')
const attestationWatcher = require('./attestationWatcher')
const app = express() const app = express()
@ -50,5 +51,8 @@ async function start() {
app.listen(port, host, () => { app.listen(port, host, () => {
console.log(`Server is running on port ${port}.`) console.log(`Server is running on port ${port}.`)
}) })
attestationWatcher()
console.log('attestationWatcher started')
} }
start() start()

View File

@ -24,7 +24,8 @@ module.exports = (sequelize, DataTypes) => {
company: DataTypes.STRING, company: DataTypes.STRING,
handle: DataTypes.STRING, handle: DataTypes.STRING,
socialType: DataTypes.STRING, socialType: DataTypes.STRING,
hash: DataTypes.STRING hash: DataTypes.STRING,
attestation: DataTypes.STRING
}, },
{ {
hooks: { hooks: {

View File

@ -3004,6 +3004,11 @@ decode-uri-component@^0.2.0:
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
deep-extend@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f"
integrity sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==
deep-extend@^0.6.0: deep-extend@^0.6.0:
version "0.6.0" version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
@ -4308,7 +4313,7 @@ har-schema@^2.0.0:
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
har-validator@~5.1.0: har-validator@~5.1.0, har-validator@~5.1.3:
version "5.1.3" version "5.1.3"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
@ -7405,7 +7410,7 @@ pseudomap@^1.0.2:
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
psl@^1.1.24: psl@^1.1.24, psl@^1.1.28:
version "1.7.0" version "1.7.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
@ -7462,7 +7467,7 @@ punycode@^1.2.4, punycode@^1.4.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
punycode@^2.1.0: punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
@ -7768,6 +7773,32 @@ repeating@^2.0.0:
dependencies: dependencies:
is-finite "^1.0.0" is-finite "^1.0.0"
request@^2.72.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
caseless "~0.12.0"
combined-stream "~1.0.6"
extend "~3.0.2"
forever-agent "~0.6.1"
form-data "~2.3.2"
har-validator "~5.1.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.19"
oauth-sign "~0.9.0"
performance-now "^2.1.0"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "~2.5.0"
tunnel-agent "^0.6.0"
uuid "^3.3.2"
request@^2.87.0, request@^2.88.0: request@^2.87.0, request@^2.88.0:
version "2.88.0" version "2.88.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
@ -8896,6 +8927,14 @@ tough-cookie@~2.4.3:
psl "^1.1.24" psl "^1.1.24"
punycode "^1.4.1" punycode "^1.4.1"
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
psl "^1.1.28"
punycode "^2.1.1"
trim-newlines@^1.0.0: trim-newlines@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
@ -8935,6 +8974,14 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
twitter@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/twitter/-/twitter-1.7.1.tgz#0762378f1dc1c050e48f666aca904e24b1a962f4"
integrity sha1-B2I3jx3BwFDkj2ZqypBOJLGpYvQ=
dependencies:
deep-extend "^0.5.0"
request "^2.72.0"
type-check@~0.3.2: type-check@~0.3.2:
version "0.3.2" version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"