Created
April 3, 2014 11:43
-
-
Save atvKumar/9952876 to your computer and use it in GitHub Desktop.
A simple Chat Program using redis Pub/Sub
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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