Giter Site home page Giter Site logo

broothie / slink Goto Github PK

View Code? Open in Web Editor NEW
24.0 5.0 1.0 1.11 MB

This project has been re-written and migrated to https://github.com/broothie/slink.chat. An AIM clone visually influenced by Windows 95

Home Page: https://slink.chat

Ruby 44.65% JavaScript 39.88% CSS 0.62% HTML 5.19% SCSS 9.60% Procfile 0.05%
slack aim windows95

slink's Introduction

Slink logo

Slink - an AIM clone visually influenced by Windows 95

Slink started as a simple attempt at cloning the much-beloved team collaboration tool Slack, and quickly became an amalgamation of Slack and primordial AOL Instant Messenger.

Features

  • Web-based chat interface
    • Leveraging of Rails' ActionCable for real-time message updates and channel broadcast management
    • Multiple channels open for application event forwarding
  • Unique channel creation
  • Private chat with fellow users and SmarterChild
    • SmarterChild bot running aboard Rails application
    • Homegrown response generation algorithm
  • Nostalgia instillation

Implementation

Stack

Technical Challenges and Solutions

Backend Design

Original schema and controller design can be viewed in the docs folder of this repo. Naturally these designs went through several revisions during development.

The current state of the application persists data regarding users, messages & their relationship to users, and channels & their relationships to users & messages. A user can create public and private channels with other users, and remove or add their own subscriptions from the channel list interface.

Leveraging the use of Rails' ActiveRecord and router, controllers was be easily designed to provide the frontend software with api endpoints for data storage, retrieval, and processing.

Real-Time Chat

Rails' ActionCable does the heavy lifting in creating the live-chat experience provided by Slink. By opening a socket channel for each chat window the client has open, users can have multiple chat streams running at one time, and the server can easily keep track of which users are subscribed to which channels in real time. By creating simple #sign_on! and #sign_off! methods on the Rails ApplicationController, clients can be signed by their user_id from the database:

# application_controller.rb

def sign_on!(user)
  session[:session_token] = user.reset_session_token!
  cookies.signed[:user_id] = user.id
end

def sign_off!
  current_user.reset_session_token!
  session[:session_token] = nil
  cookies.delete :user_id
end

Hence, clients are tracked by that signed cookie:

# connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = User.find_by(id: cookies.signed[:user_id])
    end
  end
end

When a user subscribes to the ChatChannel, they are simply added to a ActionCable channel which corresponds with the channel model they are subscribed to:

# chat_channel.rb

class ChatChannel < ApplicationCable::Channel
  def subscribed
    channel = Channel.find_by(id: params[:id])
    stream_for channel
  end
end

Users are notified of a new message in their channel through a post-then-broadcast pattern. When a user wants to send a message to a channel, a standard AJAX request is made to the message creation api endpoint through the Redux action sendMessage:

// message_stream_window.jsx

handleSend(e) {
  e.preventDefault();
  this.sendMessage();
}

sendMessage() {
  this.props.sendMessage(this.state.message).then(() => (
    this.setState({ message: '' })
  )).then(() => {
    this.props.clearErrors();
    return this.sendSound.play();
  });
}
// message_stream_window.jsx

received: ({ message }) => {
  if (this.props.currentUser.id !== message.authorId) {
    this.receiveAudio.play();
  }
  this.props.receiveMessage(message);
  this.messageInput.scrollTop = this.messageInput.scrollHeight;
}

When the message controller receives this message, it detects the message's corresponding channel and broadcasts it to all of the users currently subscribed to it:

# messages_controller.rb

if @message.save
  ChatChannel.broadcast_to(channel, message: @message.camelized_json)
  # ...
end

Real-Time Private Chat Spawning

Additionally, by keeping track of user status via another channel (AppearanceChannel), private message windows spawning was achieved. By subscribing each user additionally to the AppearanceChannel, clients are notified of new private messages on private channels they are subscribed to, meaning an open window action can be launched at that time via the addChatWindow action:

// buddy_list.jsx

received: channelId => {
  if (!this.props.chatWindows.includes(channelId)) {
    return this.props.requestChannel(channelId).then(
      ({ channel }) => {
        this.props.addChatWindow(channel.id);
        this.newPrivateMessageSound.play();
      }
    );
  }
}

No AIM clone would be complete without some manifestation of SmarterChild. Hours of time and millions of billion were wasted conversing with this chatbot, who offered both bewildering retorts and surprisingly relevant witticisms.

The homegrown algorithm for generating Slink's SmarterChild responses is mounted on the messages model. By adding a self-joining id column to the messages table, a one-to-one relationship can be formed between messages, called reply/prompt. Not all messages have both a reply and prompt, but those that do offer an opportunity for using human chat interactions to influence SmarterChild's responses.

When SmarterChild receives a message, a similar prompt message is found in the database. SmarterChild then uses the reply to that prompt to respond to the original message.

Future Improvements

Credits

Arrows graphic by freepik from Flaticon is licensed under CC BY 3.0. Check out the new logo that I created on LogoMaker.com. https://logomakr.com/5kQFua5kQFua

Icons made by Freepik from Flaticon is licensed by CC 3.0 BY.

I would also like to thank all of my supportive classmates and instructors at App Academy.

And of course, most of all, thank you to my wonderful mother, Kathy Booth.

slink's People

Contributors

broothie avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

hiveforensicsai

slink's Issues

emoji support

when can we expect emoji support?

Please and thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.