Files: 6454209172a781e000df19c353e8c35ef42b5b84 / index.js
5225 bytesRaw
1 | var fs = require('fs') |
2 | var path = require('path') |
3 | var nested = require('libnested') |
4 | var Stack = require('stack') |
5 | var URL = require('url') |
6 | var QS = require('qs') |
7 | var u = require('./util') |
8 | var toHTML = u.toHTML |
9 | var pull = require('pull-stream') |
10 | var toPull = require('stream-to-pull-stream') |
11 | var ref = require('ssb-ref') |
12 | |
13 | // middleware |
14 | var Logger = require('morgan') |
15 | var Emoji = require('emoji-server') |
16 | var Static = require('ecstatic') |
17 | var BodyParser = require('urlencoded-request-parser') |
18 | var FavIcon = require('serve-favicon') |
19 | var Coherence = require('coherence-framework') |
20 | |
21 | var doctype = '<!DOCTYPE html \n PUBLIC "-//W3C//DTD HTML 4.01//EN"\n "http://www.w3.org/TR/html4/strict.dtd">' |
22 | |
23 | //actions may make writes to sbot, or can set things |
24 | var actions = { |
25 | //note: opts is post body |
26 | identitySelect: function (opts, apply, req, cb) { |
27 | var context = req.cookies |
28 | context.id = opts.id |
29 | cb(null, opts, context) |
30 | }, |
31 | preview: function (opts, apply, req, cb) { |
32 | cb(null, opts) |
33 | }, |
34 | publish: function (opts, apply, req, cb) { |
35 | if(opts.content.recps === '') |
36 | delete opts.content.recps |
37 | else if('string' === typeof opts.content.recps) { |
38 | opts.content.recps = opts.content.recps.split(',') |
39 | } |
40 | |
41 | if(Array.isArray(opts.content.recps)) |
42 | opts.private = true |
43 | |
44 | sbot.identities.publishAs(opts, function (err, msg) { |
45 | if(err) cb(err) |
46 | else cb() |
47 | }) |
48 | } |
49 | } |
50 | |
51 | require('ssb-client')(function (err, sbot) { |
52 | if(err) throw err |
53 | |
54 | var coherence = Coherence(require('./layout')) |
55 | .use('avatar', require('./apis/avatar')(sbot)) |
56 | .use('identitySelect', require('./apis/identity-select')(sbot)) |
57 | .use('public', require('./apis/public')(sbot)) |
58 | .use('private', require('./apis/private')(sbot)) |
59 | .use('message', require('./apis/message')(sbot)) |
60 | .use('messageLink', require('./apis/message-link')(sbot)) |
61 | .use('channelLink', require('./apis/channel-link')(sbot)) |
62 | .use('messages/post', require('./apis/messages/post')(sbot)) |
63 | .use('messages/vote', require('./apis/messages/vote')(sbot)) |
64 | .use('progress', require('./apis/progress')(sbot)) |
65 | .use('thread', require('./apis/thread')(sbot)) |
66 | .use('compose', require('./apis/compose')(sbot)) |
67 | .use('publish', require('./apis/publish')(sbot)) |
68 | .use('preview', require('./apis/preview')(sbot)) |
69 | .use('friends', require('./apis/friends')(sbot)) |
70 | .use('search', require('./apis/search')(sbot)) |
71 | .use('mentions', require('./apis/mentions')(sbot)) |
72 | |
73 | require('http').createServer(Stack( |
74 | Logger(), |
75 | //everything breaks if blobs isn't first, but not sure why? |
76 | require('ssb-ws/blobs')(sbot, {prefix: '/blobs'}), |
77 | FavIcon(path.join(__dirname, 'static', 'favicon.ico')), |
78 | BodyParser(), |
79 | /* |
80 | some settings we want to store in a cookie: |
81 | * current identity |
82 | * current language |
83 | |
84 | stuff that shouldn't be in links. |
85 | this makes it possible to share links without including |
86 | state people might not want for them. |
87 | also: light/dark theme etc |
88 | */ |
89 | function (req, res, next) { |
90 | //just do it this simple way because it works |
91 | //I tried the cookie parser middleware but things got weird. |
92 | req.cookies = QS.parse(req.headers.cookie||'') || {id: sbot.id} |
93 | next() |
94 | }, |
95 | //handle posts. |
96 | function (req, res, next) { |
97 | if(req.method == 'GET') return next() |
98 | var id = req.cookies.id || sbot.id |
99 | var opts = req.body |
100 | function callApi (path, opts) { |
101 | try { |
102 | var fn = nested.get(apis, path) |
103 | if(!fn) return next() |
104 | return fn(opts, apply, req) |
105 | } catch(err) { |
106 | next(err) |
107 | } |
108 | } |
109 | if(opts.type === 'preview') { |
110 | // TODO: pass opts.id in, and wether this message |
111 | // preview should allow recipient selection, or changing id. |
112 | // api.preview can set the shape of the message if it likes. |
113 | |
114 | req.url = '/preview?'+QS.stringify(opts) |
115 | coherence(req, res, next) |
116 | |
117 | //XXX this isn't working |
118 | |
119 | // toHTML(layout.call(self, callApi(['preview'], opts))) (function (err, result) { |
120 | // if(err) next(err) |
121 | // else res.end('<!DOCTYPE html>'+result.outerHTML) |
122 | // }) |
123 | return |
124 | } |
125 | actions[opts.type](opts, null, req, function (err, _opts, context) { |
126 | if(err) return next(err) |
127 | if(context) { |
128 | req.cookies = context |
129 | res.setHeader('set-Cookie', QS.stringify(context)) |
130 | } |
131 | /* |
132 | after handling the post, |
133 | redirect to a normal page. |
134 | this is a work around for if you hit refresh |
135 | and the browser wants to resubmit the POST. |
136 | |
137 | I think we want to do this for most types, |
138 | exception is for preview - in which we return |
139 | the same data rendered differently and don't write |
140 | to DB at all. |
141 | */ |
142 | res.setHeader('location', req.url) |
143 | res.writeHead(303) |
144 | res.end() |
145 | }) |
146 | }, |
147 | |
148 | Emoji('/img/emoji'), |
149 | Static({ |
150 | root: path.join(__dirname, 'static'), baseDir: '/static' |
151 | }), |
152 | coherence |
153 | )).listen(8005) |
154 | }) |
155 | |
156 | |
157 |
Built with git-ssb-web