Fixed create_chapter toc creatin bug and created Progress bar when doing Publishing.
[booki.git] / lib / booki / editor / sputnik.py
blobb148a897778b442687223325eb6ab819b87796ea
1 import redis, time
2 import simplejson
4 # must fix this rcon issue somehow.
5 # this is stupid but will work for now
7 rcon = redis.Redis()
9 def hasChannel(channelName):
10 global rcon
12 return rcon.sismember("sputnik:channels", channelName)
14 def createChannel(channelName):
15 global rcon
17 if not hasChannel(channelName):
18 rcon.sadd("sputnik:channels", channelName)
20 return True
22 def removeChannel(channelName):
23 global rcon
25 return rcon.srem("sputnik:channels", channelName)
27 def addClientToChannel(channelName, client):
28 global rcon
30 rcon.sadd("ses:%s:channels" % client, channelName)
32 rcon.sadd("sputnik:channel:%s" % channelName, client)
34 def removeClientFromChannel(channelName, client):
35 global rcon
37 return rcon.srem("sputnik:channel:%s" % channelName, client)
39 def addMessageToChannel(request, channelName, message, myself = False ):
40 global rcon
42 clnts = rcon.smembers("sputnik:channel:%s" % channelName)
44 message["channel"] = channelName
45 message["clientID"] = request.clientID
47 for c in clnts:
48 if not myself and c == request.sputnikID:
49 continue
51 rcon.push( "ses:%s:messages" % c, simplejson.dumps(message), tail = True)
53 def removeClient(clientName):
54 global rcon
56 for chnl in rcon.smembers("ses:%s:channels" % clientName):
57 removeClientFromChannel(chnl, clientName)
58 rcon.srem("ses:%s:channels" % clientName, chnl)
60 rcon.delete("ses:%s:last_access" % clientName)
62 # TODO
63 # also, i should delete all messages
66 ## treba viditi shto opcenito sa onim
68 def booki_main(request, message):
69 global rcon
71 ret = {}
72 if message["command"] == "ping":
73 addMessageToChannel(request, "/booki/", {})
75 if message["command"] == "disconnect":
76 pass
78 if message["command"] == "connect":
80 if not rcon.exists("sputnik:client_id"):
81 rcon.set("sputnik:client_id", 0)
83 clientID = rcon.incr("sputnik:client_id")
84 ret["clientID"] = clientID
85 request.sputnikID = "%s:%s" % (request.session.session_key, clientID)
87 # subscribe to this channels
88 for chnl in message["channels"]:
89 if not hasChannel(chnl):
90 createChannel(chnl)
92 addClientToChannel(chnl, request.sputnikID)
94 # set our last access
95 rcon.set("ses:%s:last_access" % request.sputnikID, time.time())
97 return ret
101 def booki_chat(request, message, projectid, bookid):
102 if message["command"] == "message_send":
103 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_received", "from": request.user.username, "message": message["message"]})
104 return {}
106 return {}
108 # remove all the copy+paste code
111 # getChapters
113 def getTOCForBook(book):
114 from booki.editor import models
116 results = []
118 for chap in list(models.BookToc.objects.filter(book=book).order_by("-weight")):
119 # is it a section or chapter
120 if chap.chapter:
121 results.append((chap.chapter.id, chap.chapter.title, chap.chapter.url_title, chap.typeof, chap.chapter.status.id))
122 else:
123 results.append(('s%s' % chap.id, chap.name, chap.name, chap.typeof))
125 return results
128 # booki_book
131 def getHoldChapters(book_id):
132 from django.db import connection, transaction
133 cursor = connection.cursor()
134 # wgere chapter_id is NULL that is the hold Chapter
135 cursor.execute("select editor_chapter.id, editor_chapter.title, editor_chapter.url_title, editor_booktoc.chapter_id, editor_chapter.status_id from editor_chapter left outer join editor_booktoc on (editor_chapter.id=editor_booktoc.chapter_id) where editor_chapter.book_id=%s;", (book_id, ))
137 chapters = []
138 for row in cursor.fetchall():
139 if row[-2] == None:
140 chapters.append((row[0], row[1], row[2], 1, row[4]))
142 return chapters
145 def booki_book(request, message, projectid, bookid):
146 from booki.editor import models
148 ## init_editor
149 if message["command"] == "init_editor":
151 project = models.Project.objects.get(id=projectid)
152 book = models.Book.objects.get(project=project, id=bookid)
154 ## get chapters
156 chapters = getTOCForBook(book)
157 holdChapters = getHoldChapters(bookid)
159 ## get users
161 def vidi(a):
162 if a == request.sputnikID:
163 return "<b>%s</b>" % a
164 return a
166 users = [vidi(m) for m in list(rcon.smembers("sputnik:channel:%s" % message["channel"]))]
168 ## get workflow statuses
170 statuses = [(status.id, status.name) for status in models.ProjectStatus.objects.filter(project=project).order_by("-weight")]
172 ## get attachments
173 import os.path
175 import Image
176 def _getDimension(att):
177 if att.attachment.name.endswith(".jpg"):
178 try:
179 im = Image.open(att.attachment.name)
180 return im.size
181 except:
182 return (0, 0)
183 return None
186 attachments = [{"id": att.id, "dimension": _getDimension(att), "status": att.status.id, "name": os.path.split(att.attachment.name)[1], "size": att.attachment.size} for att in models.Attachment.objects.filter(book=book)]
188 ## get metadata
190 metadata = [{'name': v.name, 'value': v.getValue()} for v in models.Info.objects.filter(book=book)]
192 ## notify others
193 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "user_joined", "user_joined": request.user.username}, myself = False)
195 return {"chapters": chapters, "metadata": metadata, "hold": holdChapters, "users": users, "statuses": statuses, "attachments": attachments}
197 ## chapter_status
198 if message["command"] == "chapter_status":
199 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_status", "chapterID": message["chapterID"], "status": message["status"], "username": request.user.username})
200 return {}
202 ## chapter_save
203 if message["command"] == "chapter_save":
204 chapter = models.Chapter.objects.get(id=int(message["chapterID"]))
205 chapter.content = message["content"];
206 chapter.save()
208 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": 'User %s has saved chapter "%s".' % (request.user.username, chapter.title)}, myself=True)
210 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_status", "chapterID": message["chapterID"], "status": "normal", "username": request.user.username})
212 return {}
214 ## chapter_rename
215 if message["command"] == "chapter_rename":
216 chapter = models.Chapter.objects.get(id=int(message["chapterID"]))
217 oldTitle = chapter.title
218 chapter.title = message["chapter"];
219 chapter.save()
221 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": 'User %s has renamed chapter "%s" to "%s".' % (request.user.username, oldTitle, message["chapter"])}, myself=True)
223 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_status", "chapterID": message["chapterID"], "status": "normal", "username": request.user.username})
225 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_rename", "chapterID": message["chapterID"], "chapter": message["chapter"]})
227 return {}
229 ## chapters_changed
230 if message["command"] == "chapters_changed":
231 lst = [chap[5:] for chap in message["chapters"]]
232 lstHold = [chap[5:] for chap in message["hold"]]
234 project = models.Project.objects.get(id=projectid)
235 book = models.Book.objects.get(project=project, id=bookid)
237 weight = len(lst)
239 for chap in lst:
240 if chap[0] == 's':
241 m = models.BookToc.objects.get(id__exact=int(chap[1:]))
242 m.weight = weight
243 m.save()
244 else:
245 try:
246 m = models.BookToc.objects.get(chapter__id__exact=int(chap))
247 m.weight = weight
248 m.save()
249 except:
250 chptr = models.Chapter.objects.get(id__exact=int(chap))
251 m = models.BookToc(book = book,
252 name = "SOMETHING",
253 chapter = chptr,
254 weight = weight,
255 typeof=1)
256 m.save()
258 weight -= 1
260 if message["kind"] == "remove":
261 if type(message["chapter_id"]) == type(u' ') and message["chapter_id"][0] == 's':
262 m = models.BookToc.objects.get(id__exact=message["chapter_id"][1:])
263 m.delete()
264 else:
265 m = models.BookToc.objects.get(chapter__id__exact=int(message["chapter_id"]))
266 m.delete()
268 # addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": 'User %s has rearranged chapters.' % request.user.username})
270 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapters_changed", "ids": lst, "hold_ids": lstHold, "kind": message["kind"], "chapter_id": message["chapter_id"]})
271 return {}
273 ## get_users
274 if message["command"] == "get_users":
275 res = {}
276 def vidi(a):
277 if a == request.sputnikID:
278 return "!%s!" % a
279 return a
281 res["users"] = [vidi(m) for m in list(rcon.smembers("sputnik:channel:%s" % message["channel"]))]
282 return res
284 ## get_chapter
285 if message["command"] == "get_chapter":
286 res = {}
288 chapter = models.Chapter.objects.get(id=int(message["chapterID"]))
289 res["title"] = chapter.title
290 res["content"] = chapter.content
292 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_status", "chapterID": message["chapterID"], "status": "edit", "username": request.user.username})
294 return res
296 ## chapter_split
297 if message["command"] == "chapter_split":
298 project = models.Project.objects.get(id=projectid)
299 book = models.Book.objects.get(project=project, id=bookid)
301 allChapters = []
303 try:
304 mainChapter = models.BookToc.objects.get(book=book, chapter__id__exact=message["chapterID"])
305 except:
306 mainChapter = None
308 import datetime
309 from django.template.defaultfilters import slugify
311 if mainChapter:
312 allChapters = [chap for chap in models.BookToc.objects.filter(book=book).order_by("-weight")]
313 initialPosition = len(allChapters)-mainChapter.weight
314 #allChapters.remove(mainChapter)
315 else:
316 initialPosition = 0
318 s = models.ProjectStatus.objects.filter(project=project).order_by("weight")[0]
320 n = 0
321 for chap in message["chapters"]:
322 chapter = models.Chapter(book = book,
323 url_title = slugify(chap[0]),
324 title = chap[0],
325 status = s,
326 content = chap[1],
327 created = datetime.datetime.now(),
328 modified = datetime.datetime.now())
329 chapter.save()
331 if mainChapter:
332 m = models.BookToc(book = book,
333 chapter = chapter,
334 name = chap[0],
335 weight = 0,
336 typeof = 1)
337 m.save()
338 allChapters.insert(initialPosition+n, m)
340 n += 1
342 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": 'User %s has split chapter "%s".' % (request.user.username, mainChapter.chapter.title)}, myself=True)
345 mainChapter.chapter.delete()
347 n = len(allChapters)
348 for chap in allChapters:
349 try:
350 chap.weight = n
351 chap.save()
352 n -= 1
353 except:
354 pass
356 ## get chapters
358 chapters = getTOCForBook(book)
359 holdChapters = getHoldChapters(bookid)
364 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_split", "chapterID": message["chapterID"], "chapters": chapters, "hold": holdChapters, "username": request.user.username}, myself = True)
367 return {}
369 ## create_chapter
370 if message["command"] == "create_chapter":
371 from booki.editor import models
373 import datetime
374 project = models.Project.objects.get(id=projectid)
375 book = models.Book.objects.get(project=project, id=bookid)
377 from django.template.defaultfilters import slugify
379 url_title = slugify(message["chapter"])
381 # here i should probably set it to default project status
382 s = models.ProjectStatus.objects.filter(project=project).order_by("weight")[0]
384 chapter = models.Chapter(book = book,
385 url_title = url_title,
386 title = message["chapter"],
387 status = s,
388 created = datetime.datetime.now(),
389 modified = datetime.datetime.now())
390 chapter.save()
392 c = models.BookToc(book = book,
393 name = message["chapter"],
394 chapter = chapter,
395 weight = 0,
396 typeof=1)
397 c.save()
399 result = (chapter.id, chapter.title, chapter.url_title, 1, s.id)
401 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": 'User %s has created new chapter "%s".' % (request.user.username, message["chapter"])}, myself=True)
404 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_create", "chapter": result}, myself = True)
406 return {}
408 ## publish_book
409 if message["command"] == "publish_book":
410 project = models.Project.objects.get(id=projectid)
411 book = models.Book.objects.get(project=project, id=bookid)
413 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": '"%s" is being published.' % (book.title, )}, myself=True)
415 import urllib2
416 #f = urllib2.urlopen("http://objavi.flossmanuals.net/objavi.cgi?book=%s&project=%s&mode=epub&server=booki.flossmanuals.net&destination=archive.org" % (book.url_title, project.url_name))
417 #f.read()
419 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": '"%s" is published.' % (book.title, )}, myself=True)
421 return {}
423 ## create_section
424 if message["command"] == "create_section":
425 from booki.editor import models
427 import datetime
428 project = models.Project.objects.get(id=projectid)
429 book = models.Book.objects.get(project=project, id=bookid)
431 c = models.BookToc(book = book,
432 name = message["chapter"],
433 chapter = None,
434 weight = 0,
435 typeof=0)
436 c.save()
438 result = ("s%s" % c.id, c.name, None, c.typeof)
441 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": 'User %s has created new section "%s".' % (request.user.username, message["chapter"])}, myself=True)
443 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_create", "chapter": result, "typeof": c.typeof}, myself = True)
445 return {}
448 return {}