Fixed couple of source syntax issues
[booki.git] / lib / booki / editor / sputnik.py
blob8fa444066264c1b707276a056a64dfa58abd3d94
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()
8 rcon.connect()
10 def hasChannel(channelName):
11 global rcon
13 return rcon.sismember("sputnik:channels", channelName)
15 def createChannel(channelName):
16 global rcon
18 if not hasChannel(channelName):
19 rcon.sadd("sputnik:channels", channelName)
21 return True
23 def removeChannel(channelName):
24 global rcon
26 return rcon.srem("sputnik:channels", channelName)
28 def addClientToChannel(channelName, client):
29 global rcon
31 rcon.sadd("ses:%s:channels" % client, channelName)
33 rcon.sadd("sputnik:channel:%s" % channelName, client)
35 def removeClientFromChannel(channelName, client):
36 global rcon
38 return rcon.srem("sputnik:channel:%s" % channelName, client)
40 def addMessageToChannel(request, channelName, message, myself = False ):
41 global rcon
43 clnts = rcon.smembers("sputnik:channel:%s" % channelName)
45 message["channel"] = channelName
46 message["clientID"] = request.clientID
48 for c in clnts:
49 if not myself and c == request.sputnikID:
50 continue
52 rcon.push( "ses:%s:messages" % c, simplejson.dumps(message), tail = True)
54 def removeClient(clientName):
55 global rcon
57 for chnl in rcon.smembers("ses:%s:channels" % clientName):
58 removeClientFromChannel(chnl, clientName)
59 rcon.srem("ses:%s:channels" % clientName, chnl)
61 rcon.delete("ses:%s:last_access" % clientName)
63 # TODO
64 # also, i should delete all messages
67 ## treba viditi shto opcenito sa onim
69 def booki_main(request, message):
70 global rcon
72 ret = {}
73 if message["command"] == "ping":
74 addMessageToChannel(request, "/booki/", {})
76 if message["command"] == "disconnect":
77 pass
79 if message["command"] == "connect":
81 if not rcon.exists("sputnik:client_id"):
82 rcon.set("sputnik:client_id", 0)
84 clientID = rcon.incr("sputnik:client_id")
85 ret["clientID"] = clientID
86 request.sputnikID = "%s:%s" % (request.session.session_key, clientID)
88 # subscribe to this channels
89 for chnl in message["channels"]:
90 if not hasChannel(chnl):
91 createChannel(chnl)
93 addClientToChannel(chnl, request.sputnikID)
95 # set our last access
96 rcon.set("ses:%s:last_access" % request.sputnikID, time.time())
98 return ret
102 def booki_chat(request, message, projectid, bookid):
103 if message["command"] == "message_send":
104 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_received", "from": request.user.username, "message": message["message"]})
105 return {}
107 return {}
109 # remove all the copy+paste code
112 # getChapters
114 def getTOCForBook(book):
115 from booki.editor import models
117 results = []
119 for chap in list(models.BookToc.objects.filter(book=book).order_by("-weight")):
120 # is it a section or chapter
121 if chap.chapter:
122 results.append((chap.chapter.id, chap.chapter.title, chap.chapter.url_title, chap.typeof, chap.chapter.status.id))
123 else:
124 results.append(('s%s' % chap.id, chap.name, chap.name, chap.typeof))
126 return results
129 # booki_book
132 def getHoldChapters(book_id):
133 from django.db import connection, transaction
134 cursor = connection.cursor()
135 # wgere chapter_id is NULL that is the hold Chapter
136 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, ))
138 chapters = []
139 for row in cursor.fetchall():
140 if row[-2] == None:
141 chapters.append((row[0], row[1], row[2], 1, row[4]))
143 return chapters
146 def booki_book(request, message, projectid, bookid):
147 from booki.editor import models
149 ## init_editor
150 if message["command"] == "init_editor":
152 project = models.Project.objects.get(id=projectid)
153 book = models.Book.objects.get(project=project, id=bookid)
155 ## get chapters
157 chapters = getTOCForBook(book)
158 holdChapters = getHoldChapters(bookid)
160 ## get users
162 def vidi(a):
163 if a == request.sputnikID:
164 return "<b>%s</b>" % a
165 return a
167 users = [vidi(m) for m in list(rcon.smembers("sputnik:channel:%s" % message["channel"]))]
169 ## get workflow statuses
171 statuses = [(status.id, status.name) for status in models.ProjectStatus.objects.filter(project=project).order_by("-weight")]
173 ## get attachments
174 import os.path
176 import Image
177 def _getDimension(att):
178 if att.attachment.name.endswith(".jpg"):
179 try:
180 im = Image.open(att.attachment.name)
181 return im.size
182 except:
183 return (0, 0)
184 return None
187 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)]
189 ## get metadata
191 metadata = [{'name': v.name, 'value': v.getValue()} for v in models.Info.objects.filter(book=book)]
193 ## notify others
194 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "user_joined", "user_joined": request.user.username}, myself = False)
196 return {"chapters": chapters, "metadata": metadata, "hold": holdChapters, "users": users, "statuses": statuses, "attachments": attachments}
198 ## chapter_status
199 if message["command"] == "chapter_status":
200 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_status", "chapterID": message["chapterID"], "status": message["status"], "username": request.user.username})
201 return {}
203 ## chapter_save
204 if message["command"] == "chapter_save":
205 chapter = models.Chapter.objects.get(id=int(message["chapterID"]))
206 chapter.content = message["content"];
207 chapter.save()
209 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)
211 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_status", "chapterID": message["chapterID"], "status": "normal", "username": request.user.username})
213 return {}
215 ## chapter_rename
216 if message["command"] == "chapter_rename":
217 chapter = models.Chapter.objects.get(id=int(message["chapterID"]))
218 oldTitle = chapter.title
219 chapter.title = message["chapter"];
220 chapter.save()
222 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)
224 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_status", "chapterID": message["chapterID"], "status": "normal", "username": request.user.username})
226 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_rename", "chapterID": message["chapterID"], "chapter": message["chapter"]})
228 return {}
230 ## chapters_changed
231 if message["command"] == "chapters_changed":
232 lst = [chap[5:] for chap in message["chapters"]]
233 lstHold = [chap[5:] for chap in message["hold"]]
235 project = models.Project.objects.get(id=projectid)
236 book = models.Book.objects.get(project=project, id=bookid)
238 weight = len(lst)
240 for chap in lst:
241 if chap[0] == 's':
242 m = models.BookToc.objects.get(id__exact=int(chap[1:]))
243 m.weight = weight
244 m.save()
245 else:
246 try:
247 m = models.BookToc.objects.get(chapter__id__exact=int(chap))
248 m.weight = weight
249 m.save()
250 except:
251 chptr = models.Chapter.objects.get(id__exact=int(chap))
252 m = models.BookToc(book = book,
253 name = "SOMETHING",
254 chapter = chptr,
255 weight = weight,
256 typeof=1)
257 m.save()
259 weight -= 1
261 if message["kind"] == "remove":
262 if type(message["chapter_id"]) == type(u' ') and message["chapter_id"][0] == 's':
263 m = models.BookToc.objects.get(id__exact=message["chapter_id"][1:])
264 m.delete()
265 else:
266 m = models.BookToc.objects.get(chapter__id__exact=int(message["chapter_id"]))
267 m.delete()
269 # addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": 'User %s has rearranged chapters.' % request.user.username})
271 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapters_changed", "ids": lst, "hold_ids": lstHold, "kind": message["kind"], "chapter_id": message["chapter_id"]})
272 return {}
274 ## get_users
275 if message["command"] == "get_users":
276 res = {}
277 def vidi(a):
278 if a == request.sputnikID:
279 return "!%s!" % a
280 return a
282 res["users"] = [vidi(m) for m in list(rcon.smembers("sputnik:channel:%s" % message["channel"]))]
283 return res
285 ## get_chapter
286 if message["command"] == "get_chapter":
287 res = {}
289 chapter = models.Chapter.objects.get(id=int(message["chapterID"]))
290 res["title"] = chapter.title
291 res["content"] = chapter.content
293 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_status", "chapterID": message["chapterID"], "status": "edit", "username": request.user.username})
295 return res
297 ## chapter_split
298 if message["command"] == "chapter_split":
299 project = models.Project.objects.get(id=projectid)
300 book = models.Book.objects.get(project=project, id=bookid)
302 allChapters = []
304 try:
305 mainChapter = models.BookToc.objects.get(book=book, chapter__id__exact=message["chapterID"])
306 except:
307 mainChapter = None
309 import datetime
310 from django.template.defaultfilters import slugify
312 if mainChapter:
313 allChapters = [chap for chap in models.BookToc.objects.filter(book=book).order_by("-weight")]
314 initialPosition = len(allChapters)-mainChapter.weight
315 #allChapters.remove(mainChapter)
316 else:
317 initialPosition = 0
319 s = models.ProjectStatus.objects.filter(project=project).order_by("weight")[0]
321 n = 0
322 for chap in message["chapters"]:
323 chapter = models.Chapter(book = book,
324 url_title = slugify(chap[0]),
325 title = chap[0],
326 status = s,
327 content = chap[1],
328 created = datetime.datetime.now(),
329 modified = datetime.datetime.now())
330 chapter.save()
332 if mainChapter:
333 m = models.BookToc(book = book,
334 chapter = chapter,
335 name = chap[0],
336 weight = 0,
337 typeof = 1)
338 m.save()
339 allChapters.insert(initialPosition+n, m)
341 n += 1
343 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)
346 mainChapter.chapter.delete()
348 n = len(allChapters)
349 for chap in allChapters:
350 try:
351 chap.weight = n
352 chap.save()
353 n -= 1
354 except:
355 pass
357 ## get chapters
359 chapters = getTOCForBook(book)
360 holdChapters = getHoldChapters(bookid)
365 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_split", "chapterID": message["chapterID"], "chapters": chapters, "hold": holdChapters, "username": request.user.username}, myself = True)
368 return {}
370 ## create_chapter
371 if message["command"] == "create_chapter":
372 from booki.editor import models
374 import datetime
375 project = models.Project.objects.get(id=projectid)
376 book = models.Book.objects.get(project=project, id=bookid)
378 from django.template.defaultfilters import slugify
380 url_title = slugify(message["chapter"])
382 # here i should probably set it to default project status
383 s = models.ProjectStatus.objects.filter(project=project).order_by("weight")[0]
385 chapter = models.Chapter(book = book,
386 url_title = url_title,
387 title = message["chapter"],
388 status = s,
389 content = '<h1>%s</h1>' % message["chapter"],
390 created = datetime.datetime.now(),
391 modified = datetime.datetime.now())
392 chapter.save()
394 # c = models.BookToc(book = book,
395 # name = message["chapter"],
396 # chapter = chapter,
397 # weight = 0,
398 # typeof=1)
399 # c.save()
401 result = (chapter.id, chapter.title, chapter.url_title, 1, s.id)
403 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)
406 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_create", "chapter": result}, myself = True)
408 return {}
410 ## publish_book
411 if message["command"] == "publish_book":
412 project = models.Project.objects.get(id=projectid)
413 book = models.Book.objects.get(project=project, id=bookid)
415 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": '"%s" is being published.' % (book.title, )}, myself=True)
417 import urllib2
418 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))
419 ta = f.read()
420 lst = ta.split("\n")
421 dta = lst[0]
422 dtas3 = lst[1]
424 addMessageToChannel(request, "/chat/%s/%s/" % (projectid, bookid), {"command": "message_info", "from": request.user.username, "message": '"%s" is published.' % (book.title, )}, myself=True)
426 return {"dtaall": ta, "dta": dta, "dtas3": dtas3}
428 ## create_section
429 if message["command"] == "create_section":
430 from booki.editor import models
432 import datetime
433 project = models.Project.objects.get(id=projectid)
434 book = models.Book.objects.get(project=project, id=bookid)
436 c = models.BookToc(book = book,
437 name = message["chapter"],
438 chapter = None,
439 weight = 0,
440 typeof=0)
441 c.save()
443 result = ("s%s" % c.id, c.name, None, c.typeof)
446 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)
448 addMessageToChannel(request, "/booki/book/%s/%s/" % (projectid, bookid), {"command": "chapter_create", "chapter": result, "typeof": c.typeof}, myself = True)
450 return {}
453 return {}