| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- var http = require("http")
- ,https = require("https")
- ,clientSession = require("client-sessions")
- ,Url = require("./url.js").Url
- ,config = require("../config.js")
- ,sessionManager = require("./session.js").SessionManager
- ,Slack = require("./slack.js").Slack
- ,slackManager = require("./slackManager.js").SlackManager
- ,FaviconWriter = require("./faviconWriter.js").FaviconWriter;
- function Server(port) {
- var ctx = this;
- this.httpServ = http.createServer(function(req, res) {
- res.ended = false;
- res.on('end', () => {
- res.ended = true;
- });
- ctx.onRequest(req, res);
- });
- this.httpServ.listen(port, ctx.onListen);
- }
- Server.parseCookies = function(req) {
- var cookies = req.headers.cookie
- ,cookieObj = null;
- if (cookies) {
- cookieObj = {};
- cookies = cookies.split(";");
- for (var cookieIndex =0, nbCookies =cookies.length; cookieIndex < nbCookies; cookieIndex++) {
- var cookieParts = cookies[cookieIndex].indexOf("=")
- ,cookieKey = null
- ,cookieValue = null;
- if (cookieParts === -1) {
- cookieKey = cookies[cookieIndex].trim();
- } else {
- cookieKey = cookies[cookieIndex].substr(0, cookieParts).trim();
- cookieValue = cookies[cookieIndex].substr(cookieParts +1).trim();
- }
- cookieObj[cookieKey] = cookieValue;
- }
- }
- return cookieObj;
- };
- Server.stringifyCookies = function(cookies) {
- var cookieString = "";
- for (var cookieKey in cookies) {
- cookieString += cookieString;
- if (cookies[cookieString] !== null) {
- cookieString += "=";
- }
- cookieString += "; ";
- }
- return cookieString;
- };
- Server.prototype.onListen = function() {
- console.log("onListen");
- };
- function redirectToSlackAuth(res) {
- res.writeHeader("302", {
- Location: "https://slack.com/oauth/authorize"
- +"?client_id=" +config.clientId
- +"&scope=" +slackManager.getScope().join(",")
- +"&redirect_uri=" +config.rootUrl
- });
- res.end();
- }
- Server.prototype.onRequest = function(req, res) {
- req.reqT = Date.now();
- req.cookies = Server.parseCookies(req);
- req.session = sessionManager.forRequest(req);
- req.urlObj = new Url(req.url);
- if (!req.session || !req.session.slackToken) {
- if (req.urlObj.queryTokens.code) {
- Slack.getOauthToken(req.urlObj.queryTokens.code, config.rootUrl, (token) => {
- if (token) {
- req.session = sessionManager.lazyForRequest(req);
- req.session.setSlackToken(req.reqT, token);
- res.writeHeader("302", {
- Location: config.rootUrl
- ,"Set-Cookie": "sessID="+req.session.sessId
- });
- sessionManager.saveSession(req.session);
- res.end();
- } else {
- redirectToSlackAuth(res);
- }
- });
- } else {
- redirectToSlackAuth(res);
- }
- } else if (req.urlObj.isPublic()) {
- if (!config.isDebug)
- res.setHeader('Cache-Control', 'private, max-age=' +15 * 60);
- res.setHeader('Content-Length', req.urlObj.serve.stat.size);
- res.writeHeader("200");
- req.urlObj.getReadStream().pipe(res, { end: true });
- sessionManager.saveSession(req.session);
- return; // async pipe will close when finished
- } else if (req.urlObj.match(["favicon.png"])) {
- if (!config.isDebug)
- res.setHeader('Cache-Control', 'private, max-age=' +15 * 60);
- var unreadHi = (req.urlObj.queryTokens.h && req.urlObj.queryTokens.h[0]) ? parseInt(req.urlObj.queryTokens.h[0], 10) : 0
- ,unread = (req.urlObj.queryTokens.m && req.urlObj.queryTokens.m[0]) ? parseInt(req.urlObj.queryTokens.m[0], 10) : 0;
- FaviconWriter.write(unreadHi, unread, (buf) => {
- res.writeHeader("200");
- res.end(buf);
- });
- sessionManager.saveSession(req.session);
- return;
- } else {
- // Api / dynamic content
- var apiSuccess = false;
- res.chatContext = slackManager.lazyGet(req.session, req.reqT);
- if (req.urlObj.match(["api", "hist"])) {
- if (!req.urlObj.queryTokens.room) {
- res.writeHeader("400", "Bad request");
- } else {
- var allFound = true;
- req.urlObj.queryTokens.room.forEach(function(targetId) {
- if (!res.chatContext.data.channels[targetId]) {
- allFound = false;
- }
- res.chatContext.fetchHistory(res.chatContext.data.channels[targetId]);
- });
- if (allFound)
- res.writeHeader("204", "No Content");
- else
- res.writeHeader("404", "Channel not found");
- }
- sessionManager.saveSession(req.session);
- res.end();
- } else if (req.urlObj.match(["api", "typing"])) {
- if (!req.urlObj.queryTokens.room) {
- res.writeHeader("400", "Bad request");
- res.end();
- } else {
- var chan = res.chatContext.data.channels[req.urlObj.queryTokens.room[0]];
- if (!chan) {
- res.writeHeader("404", "Chan not found");
- } else {
- res.chatContext.sendTyping(chan);
- res.writeHeader("204", "No Content");
- }
- res.end();
- }
- } else if (req.urlObj.match(["api", "cmd"])) {
- if (!req.urlObj.queryTokens.room ||
- !req.urlObj.queryTokens.cmd) {
- res.writeHeader("400", "Bad request");
- res.end();
- } else {
- var chan = res.chatContext.data.channels[req.urlObj.queryTokens.room[0]]
- ,cmd = res.chatContext.data.commands.data['/' +req.urlObj.queryTokens.cmd[0]];
- if (!chan) {
- res.writeHeader("404", "Chan not found");
- } else if (!cmd) {
- res.writeHeader("404", "No such command");
- } else {
- var args = req.urlObj.queryTokens.args ? req.urlObj.queryTokens.args[0] : "";
- if (args === true)
- args = "";
- res.chatContext.sendCommand(chan, cmd, args);
- res.writeHeader("204", "No Content");
- }
- res.end();
- }
- } else if (req.urlObj.match(["api", "markread"])) {
- if (!req.urlObj.queryTokens.room || !req.urlObj.queryTokens.ts) {
- res.writeHeader("400", "Bad request");
- res.end();
- } else {
- var chan = res.chatContext.data.channels[req.urlObj.queryTokens.room[0]]
- ,ts = parseFloat(req.urlObj.queryTokens.ts[0]);
- if (!chan)
- res.writeHeader("404", "Chan Not Found");
- else if (isNaN(ts))
- res.writeHeader("400", "Invalid date");
- else
- res.chatContext.markRead(chan, ts);
- res.end();
- }
- sessionManager.saveSession(req.session);
- } else if (req.urlObj.match(["api", "avatar"])) {
- if (!req.urlObj.queryTokens.user) {
- res.writeHeader("400", "Bad request");
- res.end();
- } else {
- var user = res.chatContext.data.users[req.urlObj.queryTokens.user[0]];
- if (!user) {
- res.writeHeader("404", "User Not Found");
- res.end();
- } else {
- var url = user.icons.small;
- if (url.substr(0, 7) === "http://")
- http.get(url, (d) => {
- d.pipe(res, { end: true });
- });
- else if (url.substr(0, 8) === "https://")
- https.get(url, (d) => {
- d.pipe(res, { end: true });
- });
- }
- }
- sessionManager.saveSession(req.session);
- } else if (req.urlObj.match(["api", "msg"])) {
- if (req.method === 'POST') {
- if (!req.urlObj.queryTokens.room || !req.urlObj.queryTokens.text) {
- res.writeHeader("400", "Bad request");
- } else {
- var chan = res.chatContext.data.channels[req.urlObj.queryTokens.room[0]];
- if (chan) {
- var attachments = null;
- if (req.urlObj.queryTokens.attachments) {
- try { attachments = JSON.parse(decodeURIComponent(req.urlObj.queryTokens.attachments[0])); }
- catch (e) {}
- }
- if (req.urlObj.queryTokens.me)
- res.chatContext.sendMeMsg(chan, req.urlObj.queryTokens.text);
- else
- res.chatContext.sendMsg(chan, req.urlObj.queryTokens.text, attachments);
- res.writeHeader("204", "No Content");
- } else {
- res.writeHeader("404", "Channel not found");
- }
- }
- } else if (req.method === "DELETE") {
- if (!req.urlObj.queryTokens.room || !req.urlObj.queryTokens.ts) {
- res.writeHeader("400", "Bad request");
- } else {
- var chan = res.chatContext.data.channels[req.urlObj.queryTokens.room[0]];
- if (chan) {
- res.chatContext.removeMsg(chan, req.urlObj.queryTokens.ts[0]);
- res.writeHeader("204", "No Content");
- } else {
- res.writeHeader("404", "Channel not found");
- }
- }
- } else if (req.method === "PUT") {
- if (!req.urlObj.queryTokens.room || !req.urlObj.queryTokens.ts || !req.urlObj.queryTokens.text) {
- res.writeHeader("400", "Bad request");
- } else {
- var chan = res.chatContext.data.channels[req.urlObj.queryTokens.room[0]];
- if (chan) {
- res.chatContext.editMsg(chan, req.urlObj.queryTokens.ts[0], req.urlObj.queryTokens.text);
- res.writeHeader("204", "No Content");
- } else {
- res.writeHeader("404", "Channel not found");
- }
- }
- } else {
- res.writeHeader("400", "Bad request");
- }
- sessionManager.saveSession(req.session);
- res.end();
- } else if (req.urlObj.match(["api", "reaction"])) {
- var chanId = req.urlObj.queryTokens["room"] ? req.urlObj.queryTokens["room"][0] : undefined
- ,msgId = req.urlObj.queryTokens["msg"] ? req.urlObj.queryTokens["msg"][0] : undefined
- ,reaction = req.urlObj.queryTokens["reaction"] ? req.urlObj.queryTokens["reaction"][0] : undefined;
- if (chanId && msgId && reaction) {
- var chan = res.chatContext.data.channels[chanId];
- if (!chan) {
- res.writeHeader("404", "Channel Not Found");
- } else if (req.method === 'POST') {
- res.writeHeader("204", "No Content");
- res.chatContext.addReaction(chan, msgId, reaction);
- } else if (req.method === 'DELETE') {
- res.writeHeader("204", "No Content");
- res.chatContext.removeReaction(chan, msgId, reaction);
- } else {
- res.writeHeader("405", "Method not allowed");
- }
- } else {
- res.writeHeader("400", "Missing Parameter");
- }
- sessionManager.saveSession(req.session);
- res.end();
- } else if (req.urlObj.match(["api", "file"])) {
- sessionManager.saveSession(req.session);
- if (req.urlObj.queryTokens["room"]) {
- var chan = res.chatContext.data.channels[req.urlObj.queryTokens["room"][0]];
- if (chan) {
- var uploadRequest = res.chatContext.openUploadFileStream(chan, req.headers["content-type"], (errorMsg) => {
- if (!errorMsg)
- res.writeHeader("204", "No Content");
- else
- res.writeHeader("500", errorMsg);
- res.end();
- });
- req.on('end', () => {
- uploadRequest.end();
- });
- req.pipe(uploadRequest);
- } else {
- res.writeHeader("404", "Channel Not Found");
- res.end();
- }
- } else {
- res.writeHeader("400", "Bad Request");
- res.end();
- }
- } else if (req.urlObj.match(["api", "attachmentAction"])) {
- sessionManager.saveSession(req.session);
- res.chatContext.sendAction(req.headers["content-type"], req, (result) => {
- res.end(result);
- });
- } else if (req.urlObj.match(["api"])) {
- res.chatContext.onRequest(
- (req.urlObj.queryTokens.v ? req.urlObj.queryTokens.v[0] : 0) || 0
- , (slack, newData) => {
- if (!res.ended) {
- try {
- if (!slack.connected) {
- res.writeHeader("403", {
- "Content-Type": "application/json"
- });
- res.end(slack.error);
- } else {
- res.writeHeader("200", {
- "Content-Type": "application/json"
- });
- res.end(JSON.stringify(newData));
- }
- } catch (e) {}
- }
- sessionManager.saveSession(req.session);
- });
- } else {
- console.log(JSON.stringify(req.session));
- console.log(JSON.stringify(req.urlObj));
- console.log(JSON.stringify(req.cookies));
- res.writeHeader("404", "Not Found");
- res.end();
- }
- }
- };
- module.exports.HttpServ = Server;
|