Bookmarks sync
[wolnelektury.git] / src / bookmarks / models.py
1 import uuid
2 from django.apps import apps
3 from django.db import models
4 from django.utils.timezone import now
5 from social.syncable import Syncable
6
7
8 class Bookmark(Syncable, models.Model):
9     uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
10     user = models.ForeignKey('auth.User', models.CASCADE)
11     book = models.ForeignKey('catalogue.Book', models.CASCADE)
12     anchor = models.CharField(max_length=100, blank=True)
13     created_at = models.DateTimeField(auto_now_add=True)
14     note = models.TextField(blank=True)
15     updated_at = models.DateTimeField(auto_now=True)
16     reported_timestamp = models.DateTimeField(default=now)
17     deleted = models.BooleanField(default=False)
18
19     syncable_fields = [
20         'deleted', 'note',
21     ]
22
23     def __str__(self):
24         return str(self.uuid)
25
26     @classmethod
27     def create_from_data(cls, user, data):
28         if data.get('location'):
29             return cls.get_by_location(user, data['location'], create=True)
30         elif data.get('book') and data.get('anchor'):
31             return cls.objects.create(user=user, book=data['book'], anchor=data['anchor'])
32     
33     @property
34     def timestamp(self):
35         return self.updated_at.timestamp()
36     
37     def location(self):
38         return f'{self.book.slug}/{self.anchor}'
39
40     @classmethod
41     def get_by_location(cls, user, location, create=False):
42         Book = apps.get_model('catalogue', 'Book')
43         try:
44             slug, anchor = location.split('/')
45         except:
46             return None
47         instance = cls.objects.filter(
48             user=user,
49             book__slug=slug,
50             anchor=anchor
51         ).first()
52         if instance is None and create:
53             try:
54                 book = Book.objects.get(slug=slug)
55             except Book.DoesNotExist:
56                 return None
57             instance = cls.objects.create(
58                 user=user,
59                 book=book,
60                 anchor=anchor
61             )
62         return instance
63     
64     def get_for_json(self):
65         return {
66             'uuid': self.uuid,
67             'anchor': self.anchor,
68             'note': self.note,
69             'created_at': self.created_at,
70         }
71
72
73 class Quote(models.Model):
74     uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
75     user = models.ForeignKey('auth.User', models.CASCADE)
76     book = models.ForeignKey('catalogue.Book', models.CASCADE)
77     created_at = models.DateTimeField(auto_now_add=True)
78     start_elem = models.CharField(max_length=100, blank=True)
79     end_elem = models.CharField(max_length=100, blank=True)
80     start_offset = models.IntegerField(null=True, blank=True)
81     end_offset = models.IntegerField(null=True, blank=True)
82     text = models.TextField(blank=True)
83
84     def __str__(self):
85         return str(self.uuid)
86
87     def get_for_json(self):
88         return {
89             'uuid': self.uuid,
90             'startElem': self.start_elem,
91             'endElem': self.end_elem,
92             'startOffset': self.start_offset,
93             'startOffset': self.end_offset,
94             'created_at': self.created_at,
95         }
96
97 def from_path(elem, path):
98     def child_nodes(e):
99         if e.text: yield (e, 'text')
100         for child in e:
101             if child.attrib.get('id') != 'toc':
102                 yield (child, None)
103             if child.tail:
104                 yield (child, 'tail')
105     while len(path) > 1:
106         n = path.pop(0)
107         elem = list(child_nodes(elem))[n]
108     return elem
109             
110             
111