-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Exporting to GitHub. Early work in progress, bot can generate text po…
…sts using Tracery and keeps track of its followers.
- Loading branch information
Glitch (glitch-fediverse-bot)
committed
Sep 29, 2018
1 parent
24d24fa
commit 3e35b08
Showing
42 changed files
with
6,114 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{"name":"drag-in-files.svg","date":"2016-10-22T16:17:49.954Z","url":"https://cdn.hyperdev.com/drag-in-files.svg","type":"image/svg","size":7646,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/drag-in-files.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(102, 153, 205)","uuid":"adSBq97hhhpFNUna"} | ||
{"name":"click-me.svg","date":"2016-10-23T16:17:49.954Z","url":"https://cdn.hyperdev.com/click-me.svg","type":"image/svg","size":7116,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/click-me.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(243, 185, 186)","uuid":"adSBq97hhhpFNUnb"} | ||
{"name":"paste-me.svg","date":"2016-10-24T16:17:49.954Z","url":"https://cdn.hyperdev.com/paste-me.svg","type":"image/svg","size":7242,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/paste-me.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(42, 179, 185)","uuid":"adSBq97hhhpFNUnc"} | ||
{"uuid":"adSBq97hhhpFNUna","deleted":true} | ||
{"uuid":"adSBq97hhhpFNUnb","deleted":true} | ||
{"uuid":"adSBq97hhhpFNUnc","deleted":true} | ||
{"name":"null.png","date":"2018-09-13T21:12:59.652Z","url":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fnull.png","type":"image/png","size":5255,"imageWidth":128,"imageHeight":128,"thumbnail":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fnull.png","thumbnailWidth":128,"thumbnailHeight":128,"dominantColor":"rgb(76,172,220)","uuid":"y4bX37K73cQTbTjE"} | ||
{"uuid":"y4bX37K73cQTbTjE","deleted":true} | ||
{"name":"smiling-face-with-smiling-eyes.png","date":"2018-09-27T21:38:47.331Z","url":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fsmiling-face-with-smiling-eyes.png","type":"image/png","size":31773,"imageWidth":400,"imageHeight":400,"thumbnail":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fthumbnails%2Fsmiling-face-with-smiling-eyes.png","thumbnailWidth":330,"thumbnailHeight":330,"dominantColor":null,"uuid":"lmZRNK6DdCO5aJr7"} | ||
{"name":"glitch-fediverse-bot.png","date":"2018-09-29T12:44:17.606Z","url":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fglitch-fediverse-bot.png","type":"image/png","size":55034,"imageWidth":1920,"imageHeight":1079,"thumbnail":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fthumbnails%2Fglitch-fediverse-bot.png","thumbnailWidth":330,"thumbnailHeight":186,"dominantColor":"rgb(252,252,252)","uuid":"4Jq94M3MUTFcsK6b"} | ||
{"uuid":"4Jq94M3MUTFcsK6b","deleted":true} | ||
{"name":"glitch-fediverse-bot-small-1024px.png","date":"2018-09-29T12:49:07.895Z","url":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fglitch-fediverse-bot-small-1024px.png","type":"image/png","size":60397,"imageWidth":1024,"imageHeight":509,"thumbnail":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fthumbnails%2Fglitch-fediverse-bot-small-1024px.png","thumbnailWidth":330,"thumbnailHeight":165,"dominantColor":"rgb(252,252,252)","uuid":"iLCHg6pDTsAX7jkg"} | ||
{"name":"glitch-fediverse-bot.png","date":"2018-09-29T12:49:07.963Z","url":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fglitch-fediverse-bot.png","type":"image/png","size":58653,"imageWidth":1920,"imageHeight":1079,"thumbnail":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fthumbnails%2Fglitch-fediverse-bot.png","thumbnailWidth":330,"thumbnailHeight":186,"dominantColor":"rgb(252,252,252)","uuid":"0KNy0WXAgI1pZ0fd"} | ||
{"name":"glitch-fediverse-bot-960px.png","date":"2018-09-29T12:49:08.030Z","url":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fglitch-fediverse-bot-960px.png","type":"image/png","size":50867,"imageWidth":960,"imageHeight":540,"thumbnail":"https://cdn.glitch.com/a4825d5c-d1d6-4780-8464-8636780177ef%2Fthumbnails%2Fglitch-fediverse-bot-960px.png","thumbnailWidth":330,"thumbnailHeight":186,"dominantColor":"rgb(252,252,252)","uuid":"8tHyMsnvvVKkjFXF"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,49 @@ | ||
# glitch-fediverse-bot | ||
A fediverse bot hosted on Glitch. | ||
 | ||
|
||
# Glitch Fediverse bot | ||
|
||
*Work in progress.* | ||
|
||
## Bot logic (the back end) | ||
|
||
- `TBD` | ||
|
||
## The look of your bot's page (the front end) | ||
|
||
- You can update the style files inside `src/styles`. You can use [sass](https://sass-lang.com/guide), it will be compiled using [node-sass-middleware](https://github.com/sass/node-sass-middleware). | ||
- Update the scripts inside `src/scripts`. You can use [ES6](http://es6-features.org/#Constants), you script files will be compiled using [express-babelify-middleware](https://github.com/luisfarzati/express-babelify-middleware). | ||
- All templates are inside the `views` folder and use [handlebars.js](http://handlebarsjs.com/). | ||
|
||
## TO-DO: | ||
|
||
- ~~profile customization via .env~~ | ||
- ~~account discovery via webfinger~~ | ||
- ~~follow the bot~~ | ||
- ~~unfollow the bot~~ | ||
- ~~notify followers about new posts~~ | ||
- ~~add post pagination~~ | ||
- a way to delete posts (password-protected, with the password stored in `.env`) | ||
- upload images: | ||
- https://neocities.org/api, https://neocities.org/supporter, https://github.com/neocities/neocities-node | ||
- https://www.digitalocean.com/products/spaces/, https://glitch.com/~digitalocean-spaces-example | ||
- Flickr API | ||
- reply to messages | ||
- verify the payload | ||
|
||
## Resources: | ||
|
||
- https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/ | ||
- https://github.com/tootsuite/mastodon/issues/1441 | ||
- https://github.com/dariusk/express-activitypub | ||
|
||
## Notes | ||
|
||
- https://glitch-fediverse-bot.glitch.me/.well-known/webfinger?resource=acct:[email protected] | ||
- https://glitch-fediverse-bot.glitch.me/bot?debug=true | ||
|
||
|
||
|
||
Powered by [Glitch](https://glitch.com/) | ||
------------------- | ||
|
||
\ ゜o゜)ノ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
var path = require('path'), | ||
express = require('express'), | ||
exphbs = require('express-handlebars'), | ||
bodyParser = require('body-parser'), | ||
pubSubHubbub = require('pubsubhubbub'), | ||
sassMiddleware = require('node-sass-middleware'), | ||
babelify = require('express-babelify-middleware'), | ||
helpers = require(__dirname + '/helpers/general.js'), | ||
db = require(__dirname + '/helpers/db.js'), | ||
app = express(); | ||
|
||
app.use(express.static('public')); | ||
|
||
app.use(bodyParser.json({ | ||
type: 'application/activity+json' | ||
})); | ||
|
||
app.use(bodyParser.urlencoded({ | ||
extended: true | ||
})); | ||
|
||
app.use(sassMiddleware({ | ||
// src: __dirname, | ||
src: __dirname + '/src/styles', | ||
dest: path.join(__dirname, 'public'), | ||
force: true, | ||
// debug: true, | ||
outputStyle: 'compressed', | ||
response: true | ||
})); | ||
|
||
app.use('/js/scripts.js', babelify('src/scripts/scripts.js', { | ||
minify: true | ||
})); | ||
|
||
app.engine('handlebars', exphbs({ | ||
defaultLayout: 'main', | ||
helpers: { | ||
for: require('./handlebar-helpers/for'), | ||
equals: require('./handlebar-helpers/equals') | ||
} | ||
})); | ||
|
||
app.set('views', __dirname + '/views'); | ||
app.set('view engine', 'handlebars'); | ||
|
||
app.use('/', require('./routes/index.js')) | ||
app.use('/bot', require('./routes/bot.js')); | ||
app.use('/feed', require('./routes/feed.js')); | ||
app.use('/inbox', require('./routes/inbox.js')); | ||
app.use('/outbox', require('./routes/outbox.js')); | ||
app.use('/post', require('./routes/post.js')); | ||
app.use('/pubsub', require('./routes/pubsub.js')); | ||
app.use('/salmon', require('./routes/salmon.js')); | ||
app.use('/webhook', require('./routes/webhook.js')); | ||
app.use('/.well-known', require('./routes/well-known.js')); | ||
|
||
app.use(`/${process.env.BOT_ENDPOINT}`, require('./routes/bot-endpoint.js')); | ||
|
||
app.get('/js/helpers.js', function (req, res) { | ||
res.sendFile(path.join(__dirname + '/helpers/general.js')); | ||
}); | ||
|
||
module.exports = app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
var fs = require('fs'), | ||
crypto = require('crypto'), | ||
url = require('url'), | ||
util = require('util'), | ||
moment = require('moment'), | ||
db = require(__dirname + '/helpers/db.js'), | ||
keys = require(__dirname + '/helpers/keys.js'), | ||
request = require('request'), | ||
crypto = require('crypto'), | ||
public_key_path = '.data/rsa/pubKey', | ||
private_key_path = '.data/rsa/privKey', | ||
bot_url = `https://${process.env.PROJECT_DOMAIN}.glitch.me`; | ||
|
||
if (!fs.existsSync(public_key_path) || !fs.existsSync(private_key_path)) { | ||
keys.generate_keys(function(){ | ||
process.kill(process.pid); | ||
}); | ||
} | ||
else{ | ||
var public_key = fs.readFileSync(public_key_path, 'utf8'), | ||
private_key = fs.readFileSync(private_key_path, 'utf8'); | ||
|
||
module.exports = { | ||
bot_url: bot_url, | ||
links: [ | ||
// { | ||
// rel: 'http://webfinger.net/rel/profile-page', | ||
// type: 'text/html', | ||
// href: `${bot_url}` | ||
// }, | ||
// { | ||
// rel: 'http://schemas.google.com/g/2010#updates-from', | ||
// type: 'application/atom+xml', | ||
// href: `${bot_url}/feed` | ||
// }, | ||
{ | ||
rel: 'self', | ||
type: 'application/activity+json', | ||
href: `${bot_url}/bot` | ||
}, | ||
// { | ||
// rel: 'hub', | ||
// href: `${bot_url}/pubsub` | ||
// }, | ||
// { | ||
// rel: 'salmon', | ||
// href: `${bot_url}/salmon` | ||
// }, | ||
// { | ||
// rel: 'magic-public-key', | ||
// href: `data:application/magic-public-key,RSA.${public_key.replace('-----BEGIN PUBLIC KEY-----\n', '').replace('\n-----END PUBLIC KEY-----', '').replace('\\n', '')}` | ||
// } | ||
], | ||
info: { | ||
'@context': [ | ||
'https://www.w3.org/ns/activitystreams', | ||
'https://w3id.org/security/v1' | ||
], | ||
'id': `${bot_url}/bot`, | ||
'icon': [{ | ||
'url': process.env.BOT_AVATAR_URL, | ||
'type': 'Image' | ||
}], | ||
'image': [{ | ||
'url': process.env.BOT_AVATAR_URL, | ||
'type': 'Image' | ||
}], | ||
'type': 'Person', | ||
'name': process.env.BOT_USERNAME, | ||
'preferredUsername': process.env.BOT_USERNAME, | ||
'inbox': `${bot_url}/inbox`, | ||
'publicKey': { | ||
'id': `${bot_url}/bot#main-key`, | ||
'owner': `${bot_url}/bot`, | ||
'publicKeyPem': public_key | ||
} | ||
}, | ||
create_post: function(options, cb){ | ||
var bot = this; | ||
|
||
if (!options.content || options.content.trim().length === 0 ){ | ||
console.log('error: missing post content') | ||
return false; | ||
} | ||
|
||
var type = options.type || 'Note', | ||
post_date = moment().format(), | ||
post_in_reply_to = options.in_reply_to || null, | ||
post_content = options.content || ''; | ||
|
||
db.save_post({ | ||
type: type, | ||
content: post_content | ||
}, function(err, data){ | ||
var post_id = data.lastID; | ||
var obj = { | ||
'@context': 'https://www.w3.org/ns/activitystreams', | ||
'id': `${bot_url}/post/${post_id}`, | ||
'type': 'Create', | ||
'actor': `${bot_url}/bot`, | ||
|
||
'object': { | ||
'id': `${bot_url}/post/${post_id}`, | ||
'type': type, | ||
'published': post_date, | ||
'attributedTo': `${bot_url}/bot`, | ||
// 'inReplyTo': post_in_reply_to, | ||
'content': post_content, | ||
'to': 'https://www.w3.org/ns/activitystreams#Public' | ||
} | ||
} | ||
if (cb){ | ||
cb(null, obj); | ||
} | ||
}); | ||
}, | ||
accept: function(payload, cb){ | ||
var bot = this, | ||
guid = crypto.randomBytes(16).toString('hex'); | ||
|
||
bot.sign_and_send({ | ||
follower: { | ||
url: payload.actor | ||
}, | ||
message: { | ||
'@context': 'https://www.w3.org/ns/activitystreams', | ||
'id': `${bot.bot_url}/${guid}`, | ||
'type': 'Accept', | ||
'actor': `${bot.bot_url}/bot`, | ||
'object': payload, | ||
} | ||
}, function(err, data){ | ||
if (cb){ | ||
cb(err, payload, data); | ||
} | ||
}); | ||
}, | ||
sign_and_send: function(options, cb){ | ||
var bot = this; | ||
// console.log('message to sign:'); | ||
// console.log(util.inspect(options.message, false, null, true)); | ||
|
||
options.follower.url = options.follower.url.replace('http://localhost:3000', 'https://befc66af.ngrok.io'); | ||
|
||
if (options.follower.url && options.follower.url !== 'undefined'){ | ||
options.follower.domain = url.parse(options.follower.url).hostname; | ||
|
||
var signer = crypto.createSign('sha256'), | ||
d = new Date(), | ||
string_to_sign = `(request-target): post /inbox\nhost: ${options.follower.domain}\ndate: ${d.toUTCString()}`; | ||
|
||
signer.update(string_to_sign); | ||
signer.end(); | ||
|
||
var signature = signer.sign(private_key); | ||
var signature_b64 = signature.toString('base64'); | ||
var header = `keyId="${bot_url}/bot",headers="(request-target) host date",signature="${signature_b64}"`; | ||
|
||
var req_object = { | ||
url: `https://${options.follower.domain}/inbox`, | ||
headers: { | ||
'Host': options.follower.domain, | ||
'Date': d.toUTCString(), | ||
'Signature': header | ||
}, | ||
method: 'POST', | ||
json: true, | ||
body: options.message | ||
}; | ||
|
||
// console.log('request object:'); | ||
// console.log(util.inspect(req_object, false, null, true)); | ||
|
||
request(req_object, function (error, response){ | ||
console.log(`sent message to ${options.follower.url}...`); | ||
if (error) { | ||
console.log('error:', error, response); | ||
} | ||
else { | ||
console.log('response:', response.statusCode, response.statusMessage); | ||
// console.log(response); | ||
} | ||
|
||
if (cb){ | ||
cb(error, response); | ||
} | ||
}); | ||
} | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = function(arg1, arg2, options){ | ||
return (arg1 == arg2) ? options.fn(this) : options.inverse(this); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = function(from, to, incr, block){ | ||
var accum = ''; | ||
for(var i = from; i <= to; i += incr) | ||
accum += block.fn(i); | ||
return accum; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
module.exports = function(arg1, arg2, options){ | ||
console.log(arg1, arg2); | ||
return (arg1 != arg2) ? options.fn(this) : options.inverse(this); | ||
} |
Oops, something went wrong.