sync_with_server.py
116 lines
| 4.6 KiB
| text/x-python
|
PythonLexer
neko259
|
r841 | import re | ||
neko259
|
r1605 | import logging | ||
neko259
|
r1144 | import xml.etree.ElementTree as ET | ||
neko259
|
r1321 | import httplib2 | ||
neko259
|
r841 | from django.core.management import BaseCommand | ||
neko259
|
r1928 | from django.utils.dateparse import parse_datetime | ||
neko259
|
r1321 | |||
neko259
|
r841 | from boards.models import GlobalId | ||
neko259
|
r1928 | from boards.models.post.sync import SyncManager, TAG_ID, TAG_UPDATE_TIME | ||
neko259
|
r841 | |||
__author__ = 'neko259' | ||||
neko259
|
r1138 | REGEX_GLOBAL_ID = re.compile(r'(\w+)::([\w\+/]+)::(\d+)') | ||
neko259
|
r841 | |||
class Command(BaseCommand): | ||||
neko259
|
r1321 | help = 'Send a sync or get request to the server.' | ||
neko259
|
r841 | |||
neko259
|
r1138 | def add_arguments(self, parser): | ||
neko259
|
r1386 | parser.add_argument('url', type=str, help='Server root url') | ||
parser.add_argument('--global-id', type=str, default='', | ||||
neko259
|
r1321 | help='Post global ID') | ||
neko259
|
r1800 | parser.add_argument('--split-query', type=int, default=1, | ||
neko259
|
r1551 | help='Split GET query into separate by the given' | ||
' number of posts in one') | ||||
neko259
|
r1834 | parser.add_argument('--thread', type=int, | ||
help='Get posts of one specific thread') | ||||
neko259
|
r1844 | parser.add_argument('--tags', type=str, | ||
help='Get posts of the tags, comma-separated') | ||||
neko259
|
r1846 | parser.add_argument('--time-from', type=str, | ||
help='Get posts from the given timestamp') | ||||
neko259
|
r1138 | |||
neko259
|
r841 | def handle(self, *args, **options): | ||
neko259
|
r1605 | logger = logging.getLogger('boards.sync') | ||
neko259
|
r1138 | url = options.get('url') | ||
neko259
|
r1386 | |||
neko259
|
r1566 | list_url = url + 'api/sync/list/' | ||
neko259
|
r1386 | get_url = url + 'api/sync/get/' | ||
neko259
|
r1511 | file_url = url[:-1] | ||
neko259
|
r1386 | |||
neko259
|
r1138 | global_id_str = options.get('global_id') | ||
if global_id_str: | ||||
match = REGEX_GLOBAL_ID.match(global_id_str) | ||||
if match: | ||||
key_type = match.group(1) | ||||
key = match.group(2) | ||||
local_id = match.group(3) | ||||
neko259
|
r841 | |||
neko259
|
r1138 | global_id = GlobalId(key_type=key_type, key=key, | ||
neko259
|
r841 | local_id=local_id) | ||
neko259
|
r1834 | xml = SyncManager.generate_request_get([global_id]) | ||
neko259
|
r1138 | h = httplib2.Http() | ||
neko259
|
r1386 | response, content = h.request(get_url, method="POST", body=xml) | ||
neko259
|
r841 | |||
neko259
|
r1511 | SyncManager.parse_response_get(content, file_url) | ||
neko259
|
r1138 | else: | ||
raise Exception('Invalid global ID') | ||||
neko259
|
r841 | else: | ||
neko259
|
r1605 | logger.info('Running LIST request...') | ||
neko259
|
r1144 | h = httplib2.Http() | ||
neko259
|
r1845 | |||
tags = [] | ||||
tags_str = options.get('tags') | ||||
if tags_str: | ||||
tags = tags_str.split(',') | ||||
neko259
|
r1834 | xml = SyncManager.generate_request_list( | ||
neko259
|
r1846 | opening_post=options.get('thread'), tags=tags, | ||
timestamp_from=options.get('time_from')).encode() | ||||
neko259
|
r1566 | response, content = h.request(list_url, method="POST", body=xml) | ||
neko259
|
r1844 | if response.status != 200: | ||
raise Exception('Server returned error {}'.format(response.status)) | ||||
neko259
|
r1605 | logger.info('Processing response...') | ||
neko259
|
r1144 | |||
root = ET.fromstring(content) | ||||
status = root.findall('status')[0].text | ||||
if status == 'success': | ||||
neko259
|
r1322 | ids_to_sync = list() | ||
neko259
|
r1144 | models = root.findall('models')[0] | ||
for model in models: | ||||
neko259
|
r1571 | tag_id = model.find(TAG_ID) | ||
neko259
|
r1573 | global_id, exists = GlobalId.from_xml_element(tag_id) | ||
neko259
|
r1928 | tag_update_time = model.find(TAG_UPDATE_TIME) | ||
if tag_update_time: | ||||
update_time = tag_update_time.text | ||||
neko259
|
r1571 | else: | ||
neko259
|
r1928 | update_time = None | ||
if not exists or update_time is None or global_id.post.last_edit_time < parse_datetime(update_time): | ||||
neko259
|
r1624 | logger.debug('Processed (+) post {}'.format(global_id)) | ||
neko259
|
r1322 | ids_to_sync.append(global_id) | ||
neko259
|
r1605 | else: | ||
logger.debug('* Processed (-) post {}'.format(global_id)) | ||||
logger.info('Starting sync...') | ||||
neko259
|
r1322 | |||
if len(ids_to_sync) > 0: | ||||
neko259
|
r1551 | limit = options.get('split_query', len(ids_to_sync)) | ||
for offset in range(0, len(ids_to_sync), limit): | ||||
neko259
|
r1834 | xml = SyncManager.generate_request_get(ids_to_sync[offset:offset + limit]) | ||
neko259
|
r1551 | h = httplib2.Http() | ||
neko259
|
r1605 | logger.info('Running GET request...') | ||
neko259
|
r1551 | response, content = h.request(get_url, method="POST", body=xml) | ||
neko259
|
r1605 | logger.info('Processing response...') | ||
neko259
|
r1322 | |||
neko259
|
r1551 | SyncManager.parse_response_get(content, file_url) | ||
neko259
|
r1847 | |||
logger.info('Sync completed successfully') | ||||
neko259
|
r1322 | else: | ||
neko259
|
r1605 | logger.info('Nothing to get, everything synced') | ||
neko259
|
r1144 | else: | ||
raise Exception('Invalid response status') | ||||