Last active
March 2, 2020 14:19
-
-
Save petrasovaa/1dcc751c2759d3813641b64ed5970fd6 to your computer and use it in GitHub Desktop.
Desktop wxPython chat application prototype chatting with Django Channels tutorial chat room
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
import wx | |
from wxasync import AsyncBind, WxAsyncApp, StartCoroutine | |
import asyncio | |
from asyncio.events import get_event_loop | |
import websockets | |
import logging | |
import sys | |
import json | |
logger = logging.getLogger(__name__) | |
logging.basicConfig( | |
stream=sys.stdout, | |
level=logging.DEBUG, | |
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
) | |
def callback_fn(data, *args, **kwargs): | |
# Write here your logic | |
logger.debug('This is the callback speaking!') # ignore data | |
class WSClient(): | |
def __init__(self, url, callback=None): | |
self.url = url | |
self.ws = None | |
self.callback = callback | |
async def connect(self): | |
''' | |
Connecting to webSocket server | |
websockets.client.connect returns a WebSocketClientProtocol, which is used to send and receive messages | |
''' | |
logger.debug('Creating new connection...') | |
self.ws = await websockets.client.connect(self.url) | |
if self.ws.open: | |
logger.debug('Connection stablished. Client correcly connected') | |
async def receiveMessage(self): | |
''' | |
Receiving all server messages and handling them | |
''' | |
while True: | |
logger.debug('receiveMessage') | |
await asyncio.sleep(0.5) | |
if self.ws and self.ws.open: | |
try: | |
message = await self.ws.recv() | |
logger.debug('Server said > {}'.format(message)) | |
if self.callback: | |
message = json.loads(message) | |
self.callback(message['message']) | |
except websockets.exceptions.ConnectionClosed: | |
logger.debug('Connection with server closed') | |
break | |
async def sendMessage(self, message): | |
try: | |
await self.ws.send('{{"message": "{m}" }}'.format(m=message)) | |
except websockets.exceptions.ConnectionClosed: | |
logger.debug('Connection with server closed') | |
class TestFrame(wx.Frame): | |
def __init__(self, parent=None): | |
super(TestFrame, self).__init__(parent) | |
vbox = wx.BoxSizer(wx.VERTICAL) | |
self.text_ctrl = wx.TextCtrl(self) | |
button1 = wx.Button(self, label="Submit") | |
self.chatCtrl = wx.TextCtrl(self, value="", style=wx.TE_MULTILINE) | |
vbox.Add(self.chatCtrl, proportion=1, border=2, flag=wx.EXPAND|wx.ALL) | |
vbox.Add(self.text_ctrl, proportion=0, border=2, flag=wx.EXPAND|wx.ALL) | |
vbox.Add(button1, proportion=0, border=2, flag=wx.EXPAND|wx.ALL) | |
self.SetSizer(vbox) | |
self.Layout() | |
button1.Bind(wx.EVT_BUTTON, self.submit) | |
self.ws_client = WSClient(url='ws://127.0.0.1:8000/ws/chat/lobby/', callback=self.callback_fn) | |
StartCoroutine(self.ws_client.connect, self) | |
StartCoroutine(self.ws_client.receiveMessage, self) | |
def callback_fn(self, message): | |
self.chatCtrl.write(message + '\n') | |
def submit(self, event): | |
message = self.text_ctrl.GetValue() | |
StartCoroutine(self.ws_client.sendMessage(message), self) | |
self.text_ctrl.SetValue('') | |
app = WxAsyncApp() | |
frame = TestFrame() | |
frame.Show() | |
app.SetTopWindow(frame) | |
loop = get_event_loop() | |
loop.run_until_complete(app.MainLoop()) | |
''' | |
async def listen_forever(self): | |
logger.debug('Creating new connection...') | |
try: | |
async with websockets.connect(self.url) as ws: | |
logger.debug(str(type(self.ws))) | |
while True: | |
# listener loop | |
if self.message: | |
await ws.send('{{"message": "{m}" }}'.format(m=self.message)) | |
logger.debug('Client sent > {}'.format(self.message)) | |
self.message = '' | |
try: | |
reply = await asyncio.wait_for(ws.recv(), timeout=self.reply_timeout) | |
except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed): | |
try: | |
pong = await ws.ping() | |
await asyncio.wait_for(pong, timeout=self.ping_timeout) | |
logger.debug('Ping OK, keeping connection alive...') | |
continue | |
except: | |
logger.debug( | |
'Ping error - retrying connection in {} sec (Ctrl-C to quit)'.format(self.sleep_time)) | |
await asyncio.sleep(self.sleep_time) | |
break | |
logger.debug('Server said > {}'.format(reply)) | |
if self.callback: | |
self.callback(reply) | |
except socket.gaierror: | |
logger.debug( | |
'Socket error - retrying connection in {} sec (Ctrl-C to quit)'.format(self.sleep_time)) | |
except ConnectionRefusedError: | |
logger.debug('Nobody seems to listen to this endpoint. Please check the URL.') | |
''' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment