Skip to content

Instantly share code, notes, and snippets.

@atvKumar
Created April 3, 2014 11:43
Show Gist options
  • Save atvKumar/9952876 to your computer and use it in GitHub Desktop.
Save atvKumar/9952876 to your computer and use it in GitHub Desktop.
A simple Chat Program using redis Pub/Sub
from threading import Thread
# from redisutils import redis_connect
import redis
import wx
###########################################################################
## Class Listener
###########################################################################
class Listener(Thread):
def __init__(self, r, channels, display_function):
Thread.__init__(self)
self.redis = r
self.pubsub = self.redis.pubsub()
self.pubsub.subscribe(channels)
self.wxDisplay = display_function
def work(self, item):
if item['data'] != 1: # Default
# print '>'+item['data']
wx.CallAfter(self.wxDisplay, item['data'])
def run(self):
for item in self.pubsub.listen():
if item['data'] == "KILL":
self.pubsub.unsubscribe()
# print self, "unsubscribed and finished"
break
else:
self.work(item)
###########################################################################
## Class Sender
###########################################################################
class Sender(Thread):
def __init__(self, r, channels):
Thread.__init__(self)
self.redis = r
self.channels = channels
def send(self, msg):
for channel in self.channels:
if msg == 'KILL':
self.redis.publish(channel, msg)
break
else:
self.redis.publish(channel, msg)
# def run(self):
# pass
###########################################################################
## Class wxChat
###########################################################################
class wxChat(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY,
title=u"Redis Pub Sub Chat", pos=wx.DefaultPosition,
size=wx.Size(500, 300),
style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
fgSizer1 = wx.FlexGridSizer(3, 1, 0, 0)
fgSizer1.AddGrowableCol(0)
fgSizer1.AddGrowableRow(1)
fgSizer1.SetFlexibleDirection(wx.BOTH)
fgSizer1.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
gbSizer2 = wx.GridBagSizer(0, 0)
gbSizer2.SetFlexibleDirection(wx.BOTH)
gbSizer2.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
self.tc_serverip = wx.TextCtrl(self, wx.ID_ANY, u"127.0.0.1",
wx.DefaultPosition, wx.DefaultSize, 0)
self.tc_serverip.SetMaxLength(15)
self.tc_serverip.SetMinSize(wx.Size(120, -1))
gbSizer2.Add(self.tc_serverip, wx.GBPosition(0, 0), wx.GBSpan(1, 1),
wx.ALL | wx.EXPAND, 5)
self.tc_username = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString,
wx.DefaultPosition, wx.DefaultSize, 0)
gbSizer2.Add(self.tc_username, wx.GBPosition(0, 1), wx.GBSpan(1, 1),
wx.ALL | wx.EXPAND, 5)
self.btn_connect = wx.Button(self, wx.ID_ANY, u"Connect / Disconnect",
wx.DefaultPosition, wx.DefaultSize, 0)
gbSizer2.Add(self.btn_connect, wx.GBPosition(0, 2), wx.GBSpan(1, 1),
wx.ALL, 5)
gbSizer2.AddGrowableCol(1)
gbSizer2.AddGrowableRow(0)
fgSizer1.Add(gbSizer2, 0, wx.EXPAND, 5)
self.tc_chatroom = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString,
wx.DefaultPosition, wx.DefaultSize, 0)
fgSizer1.Add(self.tc_chatroom, 1, wx.ALL | wx.EXPAND, 5)
gbSizer3 = wx.GridBagSizer(0, 0)
gbSizer3.SetFlexibleDirection(wx.BOTH)
gbSizer3.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
self.tc_msg = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString,
wx.DefaultPosition, wx.DefaultSize,
wx.TE_PROCESS_ENTER)
gbSizer3.Add(self.tc_msg, wx.GBPosition(0, 0), wx.GBSpan(1, 1),
wx.ALL | wx.EXPAND, 5)
self.btn_send = wx.Button(self, wx.ID_ANY, u"Send", wx.DefaultPosition,
wx.DefaultSize, 0)
gbSizer3.Add(self.btn_send, wx.GBPosition(0, 1), wx.GBSpan(1, 1),
wx.ALL, 5)
gbSizer3.AddGrowableCol(0)
fgSizer1.Add(gbSizer3, 1, wx.EXPAND, 5)
self.SetSizer(fgSizer1)
self.Layout()
self.Centre(wx.BOTH)
# Connect Events
self.Bind(wx.EVT_CLOSE, self.close)
self.btn_connect.Bind(wx.EVT_BUTTON, self.connect)
self.btn_send.Bind(wx.EVT_BUTTON, self.send)
self.tc_msg.Bind(wx.EVT_TEXT_ENTER, self.key_enter)
self.cursor = [] # list of line positions inserted
self.connected = False # connection status
self.username = None
def __del__(self):
pass
def updateChatWindow(self, msg):
self.tc_chatroom.AppendText(msg + '\n')
self.cursor.append(self.tc_chatroom.GetInsertionPoint())
if len(self.cursor) > 10: # max lines
clear = self.cursor.pop(0)
self.tc_chatroom.Remove(0, clear)
for i in range(len(self.cursor)):
self.cursor[i] -= clear
# Virtual event handlers, overide them in your derived class
def close(self, event):
try:
self.sender.send('KILL')
self.sender.join()
except AttributeError:
pass
event.Skip()
def connect(self, event):
if not self.connected:
self.redis_conn = redis.StrictRedis(host=self.tc_serverip.GetValue())
# self.redis_conn = redis_connect(self.tc_username.GetValue(),
# host=self.tc_serverip.GetValue())
self.listener = Listener(self.redis_conn,
['chatroom'], self.updateChatWindow)
self.sender = Sender(self.redis_conn, ['chatroom'])
self.listener.start()
self.sender.start()
self.connected = True
self.username = self.tc_username.GetValue()
self.updateChatWindow(self.username + ' Connected!!!')
else:
self.sender.send('KILL')
self.sender.join()
self.connected = False
self.updateChatWindow(self.username + ' Disconnected!!!')
event.Skip()
def key_enter(self, event):
self.send(event)
def send(self, event):
# self.updateChatWindow(self.tc_msg.GetValue())
self.sender.send(self.username + '>' + self.tc_msg.GetValue())
self.tc_msg.Clear()
event.Skip()
if __name__ == '__main__':
app = wx.App(False)
frame = wxChat(None)
frame.Show(True)
app.MainLoop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment