Skip to content

Commit

Permalink
Redesign Jinora
Browse files Browse the repository at this point in the history
List of changes are:
    * Redesign of front end
    * Implementation of announcement system
    * Fixing bug which could cause the app to break when specific data is sent to it by the client
    * Changed avatars

The rest below are the squashed commits

Excluded bots from online list, refactored code

-Included a check for is_bot attribute of a user object.
-Refactored announcement.coffee to make it more 'coffee like'.

Removed import of italic Roboto font

Changed font style from italic to normal in <a> tags, which are not used anywhere except possibly in announcement. This will improve page loading time.
  • Loading branch information
tnmy44 authored and apsdehal committed Nov 1, 2015
1 parent c8abe7b commit 9b715b9
Show file tree
Hide file tree
Showing 27 changed files with 353 additions and 783 deletions.
47 changes: 47 additions & 0 deletions announcements.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

# ioObject is the express().http().io().io object for communicating with clients
module.exports = (ioObject, slackObject) ->
io = ioObject
slack = slackObject
announcement =
text: ""

helpText = "*Usage:*\n\t!" +
"ban nick <nick> _to ban a nick._\n\t" +
"!ban user <nick> _to ban the user session corresponding to given nick._\n\t" +
"!unban nick <nick>\n\t!unban user <nick>\n\t" +
"!announcement _to see the current announcement._\n\t" +
"!announce <announcement> _to change announcement._\n\t" +
"!announce - _to remove announcement._\n\t" +
"!help _to show this message._"

io.route 'announcement:demand', (req)->
req.io.emit 'announcement:data', announcement

showHelp : ->
slack.postMessage helpText, process.env.SLACK_CHANNEL, "Jinora"

interpret : (message, adminNick) ->
index = message.indexOf(" ")
command = message.substr(0, index)
content = message.substr(index + 1)
if index == -1
command = message
content = ""
command = command.toLowerCase()

if command == "announcement"
text = "Current announcement is:\n#{announcement.text}"
slack.postMessage text, process.env.SLACK_CHANNEL, "Jinora"

if command == "announce"
if content == ""
slack.postMessage helpText, process.env.SLACK_CHANNEL, "Jinora"
return
announcement['text'] = content
io.broadcast 'announcement:data',announcement
text = "*#{adminNick}* changed announcement to:\n#{announcement.text}"
slack.postMessage text, process.env.SLACK_CHANNEL, "Jinora"



116 changes: 78 additions & 38 deletions app.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,15 @@ slack = require('slack-utils/api')(process.env.API_TOKEN, process.env.INCOMING_H
presence = require('./presence.coffee')
rate_limit = require('./rate_limit.coffee')
app = express().http().io()
announcementHandler = require('./announcements.coffee')(app.io, slack)
if !!process.env.RESERVED_NICKS_URL
user = require('./user.coffee')(slack)
userVerifier = require('./user.coffee')(slack)
else
console.error "ERROR: banning won't work as RESERVED_NICKS_URL is not provided"

# This is a circular buffer of messages, which are stored in memory
messages = new CBuffer(parseInt(process.env.BUFFER_SIZE))

# Note that this is a sorted list
avatars = fs.readdirSync('./public/images/avatars').map (filename)->
path.basename(filename, '.jpg')
onlineMemberList = []

# Setup your sessions, just like normal.
app.use express.cookieParser()
Expand All @@ -31,6 +29,22 @@ app.use express.static __dirname + '/public'

app.io.set 'transports', ['xhr-polling']

# This function is for interpreting the commands sent to jinora from slack by appending ! to the message
interpretCommand = (commandText, adminNick) ->
userVerifierCommands = ["ban", "unban"]
announcementCommands = ["announce", "announcement"]
firstWord = commandText.split(' ')[0]
if (firstWord in userVerifierCommands)
if(userVerifier)
userVerifier.interpret commandText, adminNick
else
errorText = "Banning feature is not configured. Add RESERVED_NICKS_URL to .env file."
slack.postMessage errorText, process.env.SLACK_CHANNEL, "Jinora"
else if (firstWord in announcementCommands)
announcementHandler.interpret commandText, adminNick
else
announcementHandler.showHelp()

# Slack outgoing webhook is caught here
app.post "/webhook", (req, res) ->
throw "Invalid Token" unless req.body.token == process.env.OUTGOING_TOKEN
Expand All @@ -39,31 +53,31 @@ app.post "/webhook", (req, res) ->
# Prevents us from falling into a loop
return res.json {} if req.body.user_id == 'USLACKBOT'

# If the message is not meant to be sent to jinora users, but it is a command meant to be interpreted by jinora
isCommand = (req.body.text[0] == "!")
if isCommand
commandText = req.body.text.substr(1)
adminNick = req.body.user_name
interpretCommand(commandText,adminNick)
res.send ""
return

if slack.userInfoById(req.body.user_id)
avatar = slack.userInfoById(req.body.user_id)['profile']['image_72']
else
avatar = "images/default_admin.png"

message = slack.parseMessage(req.body.text)

# Broadcast the message to all clients
msg =
message: message,
nick: req.body.user_name,
classes: "admin",
timestamp: Math.floor(req.body.timestamp*1000)
admin: 1,
online: 1,
timestamp: (new Date).getTime()
avatar: avatar

# If RESERVED_NICKS_URL doesn't exist => user = ""
if !!typeof(user)
privateMsg = if message[0] == "!" then true else false
# If the message is not meant to be sent to jinora users, but to be interpreted by jinora
if privateMsg
tempMessage = msg.message.substr(1)
adminNick = msg.nick
res.send ""

user.interpret tempMessage, adminNick
return

# Broadcast the message to all connected clients
app.io.broadcast "chat:msg", msg

Expand All @@ -73,64 +87,90 @@ app.post "/webhook", (req, res) ->
# Send a blank response, so slack knows we got it.
res.send ""



# Broadcast the chat message to all connected clients,
# including the one who made the request
# also send it to slack
app.io.route 'chat:msg', (req)->
return if rate_limit(req.socket.id)
return if rate_limit(req.socket.id)
return if typeof req.data != "object"
return if typeof req.data.message != "string"
req.data.timestamp = (new Date).getTime()
# If RESERVED_NICKS_URL doesn't exist => user = ""
req.data.status = if !!typeof(user) then user.verify req.data.nick, req.cookies['connect.sid'] else {"nick": true, "session": true}

slackChannel = process.env.SLACK_CHANNEL
delete req.data.invalidNick
req.data.admin = 0 # Indicates that the message is not sent by a team member
req.data.online = 0 # Online status of end user is not tracked, always set to 0
req.data.timestamp = (new Date).getTime() # Current Time
if !req.data.avatar
req.data.avatar = "https://chat.sdslabs.co/images/default_user.png"
# If RESERVED_NICKS_URL doesn't exist => userVerifier = ""
status = if !!(userVerifier) then userVerifier.verify req.data.nick, req.cookies['connect.sid'] else {"nick": true, "session": true}
storeMsg = true

slackChannel = process.env.SLACK_CHANNEL

# If the nick is reserved
if !req.data.status['nick']
if !status['nick']
req.data.invalidNick = true;
req.io.emit 'chat:msg', req.data
return

# If the session is banned
else if !req.data.status['session']
else if !status['session']
req.io.emit 'chat:msg', req.data
slackChannel = process.env.BANNED_CHANNEL
storeMsg = false

# If the message is private
else if req.data.message[0] == '!'
req.data.private = true
req.io.emit 'chat:msg', req.data
storeMsg = false

else
# Send the message to all jinora users
app.io.broadcast 'chat:msg', req.data

# Send message to slack
# If we were given a valid avatar
if process.env.BASE_URL? and req.data.avatar and avatars[req.data.avatar]
icon = "#{process.env.BASE_URL}/images/avatars/#{avatars[req.data.avatar]}.jpg"
if req.data.avatar
icon = req.data.avatar
slack.postMessage req.data.message, slackChannel, req.data.nick, icon
else
slack.postMessage req.data.message, slackChannel, req.data.nick

# Store message in memory
messages.push req.data
if storeMsg
messages.push req.data

# Once a new chat client connects
# Send them back the last 100 messages
app.io.route 'chat:demand', (req)->
logs = messages.toArray()
# We filter out non-private messages
logs = logs.filter (msg)->
msg.message[0] != '!'
req.io.emit 'chat:log', logs

app.io.route 'presence:demand', (req)->
req.io.emit 'presence:list', presence.online()
req.io.emit 'presence:list', onlineMemberList

presence.on 'change', ()->
app.io.broadcast 'presence:list', presence.online()
onlineMemberList = []
for username in presence.online()
userInfo = slack.userInfoByName(username)
if userInfo
if !!userInfo.is_bot # Continue for loop in case is_bot is true. '!!'' take care of case when is_bot is undefined
continue
avatar = userInfo['profile']['image_72']
else
avatar = "images/default_admin.png"

onlineMemberList.push({
name: username
avatar: avatar
})

app.io.broadcast 'presence:list', onlineMemberList

# Render the homepage
app.get "/", (req, res) ->
res.sendfile "public/index.html"

app.get "/old", (req, res) ->
res.sendfile "index.html"

app.listen process.env.PORT || 3000
43 changes: 0 additions & 43 deletions index.html

This file was deleted.

79 changes: 0 additions & 79 deletions public/app.js

This file was deleted.

Binary file removed public/images/avatars/abyssinian.jpg
Binary file not shown.
Binary file removed public/images/avatars/bengal.jpg
Binary file not shown.
Binary file removed public/images/avatars/japanesebobtail.jpg
Binary file not shown.
Binary file removed public/images/avatars/korat.jpg
Binary file not shown.
Binary file removed public/images/avatars/lion.jpg
Binary file not shown.
Binary file removed public/images/avatars/mainecoon.jpg
Binary file not shown.
Binary file removed public/images/avatars/orangeandwhite.jpg
Binary file not shown.
Binary file removed public/images/avatars/persian.jpg
Binary file not shown.
Binary file removed public/images/avatars/ragdoll.jpg
Binary file not shown.
Binary file removed public/images/avatars/scottishfold.jpg
Binary file not shown.
Binary file removed public/images/avatars/siamese.jpg
Binary file not shown.
Binary file removed public/images/avatars/sphynx.jpg
Binary file not shown.
Binary file removed public/images/avatars/tabby.jpg
Binary file not shown.
Binary file added public/images/default_admin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/default_user.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/jinora.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 9b715b9

Please sign in to comment.