diff --git a/boards/management/commands/invalidate_sync_cache.py b/boards/management/commands/invalidate_sync_cache.py --- a/boards/management/commands/invalidate_sync_cache.py +++ b/boards/management/commands/invalidate_sync_cache.py @@ -15,8 +15,6 @@ class Command(BaseCommand): for global_id in GlobalId.objects.exclude(content__isnull=True).exclude( content=''): if global_id.is_local(): - global_id.content = None - global_id.save() - global_id.signature_set.all().delete() + global_id.clear_cache() count += 1 print('Invalidated {} caches.'.format(count)) diff --git a/boards/management/commands/sync_with_server.py b/boards/management/commands/sync_with_server.py --- a/boards/management/commands/sync_with_server.py +++ b/boards/management/commands/sync_with_server.py @@ -50,10 +50,11 @@ class Command(BaseCommand): else: raise Exception('Invalid global ID') else: - print('Running LIST request') + print('Running LIST request...') h = httplib2.Http() xml = GlobalId.objects.generate_request_list() response, content = h.request(list_url, method="POST", body=xml) + print('Processing response...') root = ET.fromstring(content) status = root.findall('status')[0].text @@ -78,8 +79,9 @@ class Command(BaseCommand): for offset in range(0, len(ids_to_sync), limit): xml = GlobalId.objects.generate_request_get(ids_to_sync[offset:offset+limit]) h = httplib2.Http() - print('Running GET request') + print('Running GET request...') response, content = h.request(get_url, method="POST", body=xml) + print('Processing response...') SyncManager.parse_response_get(content, file_url) else: diff --git a/boards/models/post/__init__.py b/boards/models/post/__init__.py --- a/boards/models/post/__init__.py +++ b/boards/models/post/__init__.py @@ -388,9 +388,10 @@ class Post(models.Model, Viewable): self.version = F('version') + 1 def clear_cache(self): + """ + Clears sync data (content cache, signatures etc). + """ global_id = self.global_id if global_id is not None and global_id.is_local()\ and global_id.content is not None: - global_id.content = None - global_id.save() - global_id.signature_set.all().delete() + global_id.clear_cache() diff --git a/boards/models/post/manager.py b/boards/models/post/manager.py --- a/boards/models/post/manager.py +++ b/boards/models/post/manager.py @@ -130,7 +130,7 @@ class PostManager(models.Manager): @transaction.atomic def import_post(self, title: str, text: str, pub_time: str, global_id, opening_post=None, tags=list(), files=list(), - tripcode=None): + tripcode=None, version=1): is_opening = opening_post is None if is_opening: thread = boards.models.thread.Thread.objects.create( @@ -139,20 +139,43 @@ class PostManager(models.Manager): else: thread = opening_post.get_thread() - post = self.create(title=title, text=text, + post = self.create(title=title, + text=text, pub_time=pub_time, poster_ip=NO_IP, last_edit_time=pub_time, global_id=global_id, opening=is_opening, - thread=thread, tripcode=tripcode) + thread=thread, + tripcode=tripcode, + version=version) - # TODO Add files for file in files: self._add_file_to_post(file, post) post.threads.add(thread) + @transaction.atomic + def update_post(self, post, title: str, text: str, pub_time: str, + tags=list(), files=list(), tripcode=None, version=1): + post.title = title + post.text = text + post.pub_time = pub_time + post.tripcode = tripcode + post.version = version + post.save() + + post.clear_cache() + + post.images.clear() + post.attachments.clear() + for file in files: + self._add_file_to_post(file, post) + + thread = post.get_thread() + thread.tags.clear() + list(map(thread.tags.add, tags)) + def _add_file_to_post(self, file, post): file_type = file.name.split('.')[-1].lower() if file_type in IMAGE_TYPES: diff --git a/boards/models/post/sync.py b/boards/models/post/sync.py --- a/boards/models/post/sync.py +++ b/boards/models/post/sync.py @@ -172,8 +172,10 @@ class SyncManager: global_id, exists = GlobalId.from_xml_element(tag_id) signatures = SyncManager._verify_model(global_id, content_str, tag_model) - if exists: - print('Post with same ID already exists') + version = int(tag_content.find(TAG_VERSION).text) + is_old = exists and global_id.post.version < version + if exists and not is_old: + print('Post with same ID exists and is up to date.') else: global_id.content = content_str global_id.save() @@ -227,11 +229,20 @@ class SyncManager: files.append(attached_file) - Post.objects.import_post( - title=title, text=text, pub_time=pub_time, - opening_post=opening_post, tags=tags, - global_id=global_id, files=files, tripcode=tripcode) - print('Parsed post {}'.format(global_id)) + if is_old: + post = global_id.post + Post.objects.update_post( + post, title=title, text=text, pub_time=pub_time, + tags=tags, files=files, tripcode=tripcode, + version=version) + print('Parsed updated post {}'.format(global_id)) + else: + Post.objects.import_post( + title=title, text=text, pub_time=pub_time, + opening_post=opening_post, tags=tags, + global_id=global_id, files=files, tripcode=tripcode, + version=version) + print('Parsed new post {}'.format(global_id)) else: raise SyncException(EXCEPTION_NODE.format(tag_status.text)) diff --git a/boards/models/signature.py b/boards/models/signature.py --- a/boards/models/signature.py +++ b/boards/models/signature.py @@ -130,6 +130,14 @@ class GlobalId(models.Model): return KeyPair.objects.filter( key_type=self.key_type, public_key=self.key).exists() + def clear_cache(self): + """ + Removes content cache and signatures. + """ + self.content = None + self.save() + self.signature_set.all().delete() + class Signature(models.Model): class Meta: diff --git a/boards/tests/test_sync.py b/boards/tests/test_sync.py --- a/boards/tests/test_sync.py +++ b/boards/tests/test_sync.py @@ -1,3 +1,5 @@ +from django.test import TestCase + from boards.models import KeyPair, Post, Tag from boards.models.post.sync import SyncManager from boards.tests.mocks import MockRequest @@ -6,9 +8,6 @@ from boards.views.sync import response_g __author__ = 'neko259' -from django.test import TestCase - - class SyncTest(TestCase): def test_get(self): """