Skip to content

Fixes and changes/additions, please see readme and examples/molhokwai #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 187 additions & 0 deletions examples/molhokwai/app/static/js/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// File: static/js/app.js
(function() {
'use strict';

var pusher = new Pusher('1ed4f14aec1b394a4ed4', {
authEndpoint: '/emelit/plugin_pusher/pusher_auth.json',
cluster: 'eu',
encrypted: true
});

// ----------------------------------------------------
// Chat Details
// ----------------------------------------------------

let chat = {
name: undefined,
email: undefined,
myChannel: undefined,
}


// ----------------------------------------------------
// Targeted Elements
// ----------------------------------------------------

const chatPage = $(document)
const chatWindow = $('.chatbubble')
const chatHeader = chatWindow.find('.unexpanded')
const chatBody = chatWindow.find('.chat-window')


// ----------------------------------------------------
// Register helpers
// ----------------------------------------------------

let helpers = {

// ----------------------------------------------------
// Toggles the display of the chat window.
// ----------------------------------------------------

ToggleChatWindow: function () {
chatWindow.toggleClass('opened')
chatHeader.find('.title').text(
chatWindow.hasClass('opened') ? 'Minimize Chat Window' : 'Chat with Support'
)
},

// --------------------------------------------------------------------
// Show the appropriate display screen. Login screen or Chat screen.
// --------------------------------------------------------------------

ShowAppropriateChatDisplay: function () {
(chat.name) ? helpers.ShowChatRoomDisplay() : helpers.ShowChatInitiationDisplay()
},

// ----------------------------------------------------
// Show the enter details form.
// ----------------------------------------------------

ShowChatInitiationDisplay: function () {
chatBody.find('.chats').removeClass('active')
chatBody.find('.login-screen').addClass('active')
},

// ----------------------------------------------------
// Show the chat room messages display.
// ----------------------------------------------------

ShowChatRoomDisplay: function () {
chatBody.find('.chats').addClass('active')
chatBody.find('.login-screen').removeClass('active')

setTimeout(function(){
chatBody.find('.loader-wrapper').hide()
chatBody.find('.input, .messages').show()
}, 2000)
},

// ----------------------------------------------------
// Append a message to the chat messages UI.
// ----------------------------------------------------

NewChatMessage: function (message) {
if (message !== undefined) {
const messageClass = message.sender !== chat.email ? 'support' : 'user'

chatBody.find('ul.messages').append(
`<li class="clearfix message ${messageClass}">
<div class="sender">${message.name}</div>
<div class="message">${message.text}</div>
</li>`
)


chatBody.scrollTop(chatBody[0].scrollHeight)
}
},

// ----------------------------------------------------
// Send a message to the chat channel.
// ----------------------------------------------------

SendMessageToSupport: function (evt) {

evt.preventDefault()

let createdAt = new Date()
createdAt = createdAt.toLocaleString()

const message = $('#newMessage').val().trim()

if(false){
// removed client side trigerring
chat.myChannel.trigger('client-guest-new-message', {
'sender': chat.name,
'email': chat.email,
'text': message,
'createdAt': createdAt
});
}
else{
// added server side trigerring for event handling
let sender = chat.name
let email = chat.email
let text = message
axios.post('/emelit/plugin_pusher/message.json', {sender, email, text, createdAt}).then(response => {
// received: sender, email, text, createdAt
// pass
})
}

helpers.NewChatMessage({
'text': message,
'name': chat.name,
'sender': chat.email
})

console.log("Message added!")

$('#newMessage').val('')
},

// ----------------------------------------------------
// Logs user into a chat session.
// ----------------------------------------------------

LogIntoChatSession: function (evt) {
const name = $('#fullname').val().trim()
const email = $('#email').val().trim().toLowerCase()

// Disable the form
chatBody.find('#loginScreenForm input, #loginScreenForm button').attr('disabled', true)

if ((name !== '' && name.length >= 3) && (email !== '' && email.length >= 5)) {
axios.post('/emelit/plugin_pusher/guest.json/new', {name, email}).then(response => {
chat.name = name
chat.email = email
chat.myChannel = pusher.subscribe('private-' + response.data.email);
helpers.ShowAppropriateChatDisplay()
})
} else {
alert('Enter a valid name and email.')
}

evt.preventDefault()
}
}

// ------------------------------------------------------------------
// Listen for a new message event from the admin
// ------------------------------------------------------------------

pusher.bind('client-support-new-message', function(data){
helpers.NewChatMessage(data)
})


// ----------------------------------------------------
// Register page event listeners
// ----------------------------------------------------

chatPage.ready(helpers.ShowAppropriateChatDisplay)
chatHeader.on('click', helpers.ToggleChatWindow)
chatBody.find('#loginScreenForm').on('submit', helpers.LogIntoChatSession)
chatBody.find('#messageSupport').on('submit', helpers.SendMessageToSupport)
}())
79 changes: 79 additions & 0 deletions examples/molhokwai/script/plugin_pusher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python

import sys
sys.path.append('..')

import time

import pusherclient
from plugin_pusher import settings

# Add a logging handler so we can see the raw communication data
import logging
root = logging.getLogger()
root.setLevel(logging.INFO)
ch = logging.StreamHandler(sys.stdout)
root.addHandler(ch)

global pusher

def print_usage(filename):
print("Usage: python %s <appkey> <appcluster>" % filename)

def channel_callback(data):
print("Channel Callback: %s" % data)

def connect_handler(data):
for c in channel_names:
if not channel_names[c][0]:
channel = pusher.subscribe(c)

_events = channel_names[c][1]
for e in _events:
if not _events[e]:
channel.bind(e, channel_callback)
_events[e] = True
channel_names[c][0] = True


appkey = settings.appkey or None
appcluster = settings.appcluster or None
channel_names = settings.channel_names or {}

if __name__ == '__main__':
if not appkey:
if len(sys.argv) != 3:
print_usage(sys.argv[0])
sys.exit(1)
else:
appkey = sys.argv[1]
appcluster = sys.argv[2]

"""
Changes:
-------
Cluster: Added cluster in host name (also in process file arguments)
Channel names, event names: Added chosen event names binding for given channel name

- Added cluster<string> parameter (<Pusher>)
> Added cluster in host name in <Pusher.__init__>
> Removed <Pusher._build_url> @classmethod attribute
- Added event_names<list> parameter (<Pusher>, <Connection>)
> Added event_names binding in <Connection.__init__>

@acknowledgement: Pysher (https://github.com/nlsdfnbch/Pysher/blob/master/pysher/pusher.py)
@framework: Pusher (https://pusher.com/tutorials/chat-widget-python)
"""
event_names = []
for c in channel_names:
event_names += channel_names[c][1].keys()
pusher = pusherclient.Pusher(appkey, cluster=appcluster, event_names=event_names)
pusher.connection.bind('pusher:connection_established', connect_handler)

pusher.connect()
print
print '------------------------------------------------------------'
print

while True:
time.sleep(1)
1 change: 1 addition & 0 deletions examples/molhokwai/script/plugin_pusher/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/usr/bin/env python
6 changes: 6 additions & 0 deletions examples/molhokwai/script/plugin_pusher/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env python

appkey = '1ed4f14aec1b394a4ed4'
appcluster = 'eu'
# channel_names { [name] : [ subscribed (bool), event_names { [name] : bound (bool) } ] }
channel_names = { 'general-channel': [False, { 'client-guest-new-message': False }] }
19 changes: 12 additions & 7 deletions pusherclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ class Pusher(object):
client_id = 'PythonPusherClient'
protocol = 6

def __init__(self, key, secure=True, secret=None, user_data=None, log_level=logging.INFO, daemon=True, port=None, reconnect_interval=10):
def __init__(self, key, cluster=None, event_names=[], secure=True, secret=None, user_data=None, log_level=logging.INFO, daemon=True, port=None, reconnect_interval=10):
# https://pusher.com/docs/clusters
if cluster:
self.host = "ws-{cluster}.pusher.com".format(cluster=cluster)
else:
self.host = "ws.pusherapp.com"

self.key = key
self.secret = secret
self.user_data = user_data or {}
Expand All @@ -28,7 +34,7 @@ def __init__(self, key, secure=True, secret=None, user_data=None, log_level=logg

self.url = self._build_url(key, secure, port)

self.connection = Connection(self._connection_handler, self.url, log_level=log_level, daemon=daemon, reconnect_interval=reconnect_interval)
self.connection = Connection(self._connection_handler, self.url, event_names=event_names, log_level=log_level, daemon=daemon, reconnect_interval=reconnect_interval)

def connect(self):
"""Connect to Pusher"""
Expand Down Expand Up @@ -122,13 +128,12 @@ def _generate_presence_key(socket_id, key, channel_name, secret, user_data):

return auth_key

@classmethod
def _build_url(cls, key, secure, port=None):
def _build_url(self, key, secure, port=None):
path = "/app/%s?client=%s&version=%s&protocol=%s" % (
key,
cls.client_id,
self.client_id,
VERSION,
cls.protocol
self.protocol
)

proto = "ws"
Expand All @@ -144,7 +149,7 @@ def _build_url(cls, key, secure, port=None):

return "%s://%s:%s%s" % (
proto,
cls.host,
self.host,
port,
path
)
4 changes: 3 additions & 1 deletion pusherclient/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


class Connection(Thread):
def __init__(self, event_handler, url, log_level=logging.INFO, daemon=True, reconnect_interval=10):
def __init__(self, event_handler, url, event_names=[], log_level=logging.INFO, daemon=True, reconnect_interval=10):
self.event_handler = event_handler
self.url = url

Expand All @@ -33,6 +33,8 @@ def __init__(self, event_handler, url, log_level=logging.INFO, daemon=True, reco
self.bind("pusher:pong", self._pong_handler)
self.bind("pusher:ping", self._ping_handler)
self.bind("pusher:error", self._pusher_error_handler)
for event_name in event_names:
self.bind(event_name, event_handler)

self.state = "initialized"

Expand Down