Comments (5)
What version of tornado do you have running?
Also can you attach your main.py if you've made any changes to it? It'll help me debug this issue.
from collabdraw.
Hi Thanks for reply,
I am using Torndao-3.1. I have changed the two files one is websockethandler.py and another one is main.py.
Please find code here for main.py:
import logging
import uuid
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.template as template
from websockethandler import RealtimeHandler
from uploadhandler import UploadHandler
from loginhandler import LoginHandler
from logouthandler import LogoutHandler
from registerhandler import RegisterHandler
import config
logger = logging.getLogger('websocket')
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.DEBUG)
class IndexHandler(tornado.web.RequestHandler):
def get_current_user(self):
if not config.DEMO_MODE:
return self.get_secure_cookie("loginId")
else:
return True
@tornado.web.authenticated
def get(self):
#print('...........authenticated.......')
loader = template.Loader(config.ROOT_DIR)
return_str = loader.load("index.html").generate(app_ip_address=config.APP_IP_ADDRESS,
app_port=config.PUBLIC_LISTEN_PORT, token='')
self.finish(return_str)
class RedirectHandler(tornado.web.RequestHandler):
def get(self, token_id):
loader = template.Loader(config.ROOT_DIR)
return_str = loader.load("index.html").generate(app_ip_address=config.APP_IP_ADDRESS,
app_port=config.PUBLIC_LISTEN_PORT, token=token_id)
self.finish(return_str)
class Application(tornado.web.Application):
def init(self):
handlers = [
(r'/realtime/', RealtimeHandler),
(r'/resource/(.)', tornado.web.StaticFileHandler,
dict(path=config.RESOURCE_DIR)),
(r'/test/resource/(.)', tornado.web.StaticFileHandler,
dict(path=config.RESOURCE_DIR)),
(r'/upload', UploadHandler),
(r'/login.html', LoginHandler),
(r'/logout.html', LogoutHandler),
(r'/register.html', RegisterHandler),
(r'/index.html', IndexHandler),
(r'/test/(?P<token_id>\w+)', RedirectHandler),
(r'/(.*)', tornado.web.StaticFileHandler,
dict(path=config.ROOT_DIR)),
]
self.LISTENERS = {}
self.LISTENER_THREADS = {}
settings = dict(
auto_reload = True,
gzip = True,
login_url = "login.html",
cookie_secret = str(uuid.uuid4()),
)
tornado.web.Application.__init__(self, handlers, **settings)
if name == "main":
if not config.ENABLE_SSL:
http_server = tornado.httpserver.HTTPServer(Application())
else:
http_server = tornado.httpserver.HTTPServer(Application(), ssl_options={
"certfile": config.SERVER_CERT,
"keyfile": config.SERVER_KEY,
})
logger.info("Listening on port %s" % config.APP_PORT)
http_server.listen(config.APP_PORT)
tornado.ioloop.IOLoop.instance().start()
Here for websockethandler.py:
import logging
import json
import os
import threading
import subprocess
import uuid
from zlib import compress
from urllib.parse import quote
from base64 import b64encode
import tornado.websocket
import tornado.web
import redis
from pystacia import read
from tools import hexColorToRGB, createCairoContext
import config
class RealtimeHandler(tornado.websocket.WebSocketHandler):
room_name = ''
token = ''
paths = []
redis_client = None
page_no = 1
num_pages = 1
def construct_key(self, namespace, key, *keys):
publish_key = ""
if len(keys) == 0:
publish_key = "%s:%s" % (namespace, key)
else:
publish_key = "%s:%s:%s" % (namespace, key, ":".join(keys))
return publish_key
def redis_listener(self, room_name, page_no):
self.logger.info("Starting listener thread for room %s" % room_name)
rr = redis.Redis(host=config.REDIS_IP_ADDRESS, port=config.REDIS_PORT, db=1)
r = rr.pubsub()
r.subscribe(self.construct_key(room_name, page_no))
for message in r.listen():
for listener in self.application.LISTENERS.get(room_name, {}).get(page_no, []):
self.logger.debug("Sending message to room %s" % room_name)
listener.send_message(message['data'])
def open(self):
self.logger = logging.getLogger('websocket')
self.logger.info("Open connection")
self.send_message(self.construct_message("ready"))
self.redis_client = redis.Redis(host=config.REDIS_IP_ADDRESS, db=2)
def on_message(self, message):
m = json.loads(message)
event = m.get('event', '').strip()
data = m.get('data', {})
self.logger.debug("Processing event %s" % event)
if not event:
self.logger.error("No event specified")
return
if event == "init":
token = data.get('token', '')
find_token = self.redis_client.exists(self.construct_key('token', token))
print(token, find_token)
room_name = data.get('room', '')
page_no = data.get('page', '1')
if token:
if not find_token:
self.send_message(self.construct_message("forword", {}))
else:
room_name = 'token'
self.token = token
page_no = token
else:
self.token = ''
print('.........................')
self.logger.info("Initializing with room name %s" % self.room_name)
room_name = data.get('room', '')
if not room_name:
self.logger.error("Room name not provided. Can't initialize")
return
self.init(room_name, page_no)
elif event == "draw-click":
singlePath = data['singlePath']
if not self.paths:
self.logger.debug("None")
self.paths = []
self.paths.extend(singlePath)
self.broadcast_message(self.construct_message("draw", {'singlePath': singlePath}))
if not self.token:
self.redis_client.set(self.construct_key(self.room_name, self.page_no), self.paths)
else:
self.redis_client.set(self.construct_key('token', self.token), self.paths)
elif event == "save":
self.redis_client.set(self.construct_key(self.room_name, self.page_no), self.paths)
self.init(self.room_name, self.page_no)
elif event == "savesession":
token = data['token']
self.paths = []
self.redis_client.set(self.construct_key('token', token), self.paths)
self.send_message(self.construct_message("token", {'token': token}))
#self.init(self.room_name, self.page_no)
elif event == "clear":
self.broadcast_message(self.construct_message("clear"))
self.redis_client.delete(self.construct_key(self.room_name, self.page_no))
elif event == "get-image":
if self.room_name != data['room'] or self.page_no != data['page']:
self.logger.warning("Room name %s and/or page no. %s doesn't match with current room name %s and/or page no. %s. Ignoring" % (data['room'],
data['page'], self.room_name, self.page_no))
image_url, width, height = self.get_image_data(self.room_name, self.page_no)
self.send_message(self.construct_message("image", {'url': image_url,
'width': width, 'height': height}))
elif event == "video":
self.make_video(self.room_name, self.page_no)
elif event == "new-page":
self.logger.info("num_pages was %d" % self.num_pages)
self.redis_client.set(self.construct_key("info", self.room_name, "npages"),
self.num_pages + 1)
self.num_pages += 1
self.logger.info("num_pages is now %d" % self.num_pages)
self.init(self.room_name, self.num_pages)
def on_close(self):
self.leave_room(self.room_name)
def construct_message(self, event, data = {}):
m = json.dumps({"event": event, "data": data})
return m
def broadcast_message(self, message):
self.leave_room(self.room_name, False)
self.redis_client.publish(self.construct_key(self.room_name, self.page_no), message)
self.join_room(self.room_name)
def send_message(self, message):
if type(message) == type(b''):
self.logger.info("Decoding binary string")
message = message.decode('utf-8')
elif type(message) != type(''):
self.logger.info("Converting message from %s to %s" % (type(message),
type('')))
message = str(message)
message = b64encode(compress(bytes(quote(message), 'utf-8'), 9))
self.write_message(message)
def leave_room(self, room_name, clear_paths = True):
self.logger.info("Leaving room %s" % room_name)
if self in self.application.LISTENERS.get(room_name, {}).get(self.page_no, []):
self.application.LISTENERS[room_name][self.page_no].remove(self)
if clear_paths:
self.paths = []
def join_room(self, room_name):
self.logger.info("Joining room %s" % room_name)
self.application.LISTENERS.setdefault(room_name, {}).setdefault(self.page_no, []).append(self)
def init(self, room_name, page_no):
self.logger.info("Initializing %s and %s" % (room_name, page_no))
if room_name not in self.application.LISTENERS or page_no not in self.application.LISTENERS[room_name]:
t = threading.Thread(target=self.redis_listener, args=(room_name, page_no))
t.start()
print("find ....", t)
self.application.LISTENER_THREADS.setdefault(room_name, {}).setdefault(page_no, []).append(t)
self.leave_room(self.room_name)
self.room_name = room_name
self.page_no = page_no
self.join_room(self.room_name)
n_pages = self.redis_client.get(self.construct_key("info", self.room_name, "npages"))
if n_pages:
self.num_pages = int(n_pages.decode('utf-8'))
# First send the image if it exists
image_url, width, height = self.get_image_data(self.room_name, self.page_no)
self.send_message(self.construct_message("image", {'url': image_url,
'width': width, 'height': height}))
# Then send the paths
p = self.redis_client.get(self.construct_key(self.room_name, self.page_no))
if p:
self.paths = json.loads(p.decode('utf-8').replace("'", '"'))
else:
self.paths = []
self.logger.info("No data in database")
self.send_message(self.construct_message("draw-many",
{'datas': self.paths, 'npages': self.num_pages}))
def get_image_data(self, room_name, page_no):
image_url = "files/" + room_name + "/" + str(page_no) + "_image.png";
image_path = os.path.realpath(__file__).replace(__file__, '') + image_url
try:
image = read(image_path)
except IOError as e:
self.logger.error("Error %s while reading image at location %s" % (e, image_path))
return '', -1, -1
width, height = image.size
return image_url, width, height
def make_video(self, room_name, page_no):
p = self.redis_client.get(self.construct_key(room_name, page_no))
os.makedirs('tmp', exist_ok=True)
prefix = 'tmp/'+str(uuid.uuid4())
if p:
points = json.loads(p.decode('utf-8').replace("'",'"'))
i = 0
c = createCairoContext(920, 550)
for point in points:
c.set_line_width(float(point['lineWidth'].replace('px','')))
c.set_source_rgb(*hexColorToRGB(point['lineColor']))
if point['type'] == 'dragstart' or point['type'] == 'touchstart':
c.move_to(point['oldx'], point['oldy'])
elif point['type'] == 'drag' or point['type'] == 'touchmove':
c.move_to(point['oldx'], point['oldy'])
c.line_to(point['x'], point['y'])
c.stroke()
f = open(prefix+"_img_"+str(i)+".png", "wb")
c.get_target().write_to_png(f)
f.close()
i += 1
video_file_name = prefix+'_video.mp4'
retval = subprocess.call(['ffmpeg', '-f', 'image2', '-i', prefix+'_img_%d.png', video_file_name])
self.logger.info("Image for room %s and page %s successfully created. File name is %s" % (room_name, page_no, video_file_name))
if retval == 0:
# Clean up if successfull
cleanup_files = prefix+'_img_*'
self.logger.info("Cleaning up %s" % cleanup_files)
subprocess.call(['rm', cleanup_files])
May be I think I solved this issue. But few issues are there. When the user first time draws on whiteboard it is not saved into database. I am expecting feedback from you. Thanks.
from collabdraw.
I'm looking into it.
from collabdraw.
Ok thanks for your supporting. I am looking forward for your reply.
from collabdraw.
I can't seem to reproduce the issue of the first time drawing not being saved in database. Please open a new issue with more details if you're still seeing the problem.
For the record, can you post your solution to your first problem?
from collabdraw.
Related Issues (8)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from collabdraw.