add atom feeds (with legacy compatibility)
[chloro.git] / chloro / phyll / management / commands / load-old-posts.py
1 # chloro - personal space
2 # Copyright (C) 2019  Frederic Peters
3 #
4 # This program is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published
6 # by the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 import datetime
18 import os
19 import pickle
20 import sys
21
22 from django.core.management.base import BaseCommand
23 from django.utils.timezone import make_aware
24
25 from chloro.phyll.models import Note
26
27
28 class PickledPost:
29     pass
30
31
32 class PickledComment:
33     pass
34
35
36 class UnpicklerClass(pickle.Unpickler):
37     def find_class(self, module, name):
38         if module == 'copy_reg':
39             module = 'copyreg'
40         elif module == '__builtin__':
41             module = 'builtins'
42         elif (module, name) in (('chlorophyll.posts', 'Post'), ('posts', 'Post')):
43             return PickledPost
44         elif (module, name) in (('chlorophyll.posts', 'Comment'), ('posts', 'Comment')):
45             return PickledComment
46         __import__(module)
47         mod = sys.modules[module]
48         klass = getattr(mod, name)
49         return klass
50
51
52 class Command(BaseCommand):
53     def handle(self, verbosity, **options):
54         categories = {
55             1: ('code',),
56             2: ('divers',),
57             3: ('debian', 'code'),
58             4: ('tricoteuse', 'divers'),
59             5: ('bouquins', 'divers'),
60             6: ('antipub', 'divers'),
61             7: ('musique', 'divers'),
62             8: ('gnome', 'code'),
63             9: ('radio',),
64             10: ('ecriture', 'divers'),
65         }
66         slugs = {}
67         for filename in sorted(os.listdir('posts'), key=lambda x: int(x)):
68             old_post = UnpicklerClass(open(os.path.join('posts', filename), 'rb'), encoding='utf-8').load()
69             if old_post.url_name in slugs:
70                 old_post.url_name = '%s-2' % old_post.url_name
71             slugs[old_post.url_name] = True
72             note, created = Note.objects.get_or_create(slug=old_post.url_name)
73             note.title = old_post.title
74             note.text = old_post.content_html
75             note.text = note.text.replace('src="/', 'src="/media/')
76             note.creation_timestamp = make_aware(datetime.datetime(*old_post.issued[:6]))
77             note.published = bool(note.creation_timestamp.date() >= datetime.date(2014, 1, 1))
78             note.save()
79             for tag in categories.get(old_post.category_id):
80                 note.tags.add(tag)
81             if getattr(old_post, 'language', None):
82                 note.tags.add('lang-%s' % old_post.language)
83             note.tags.add('old-post-id-%s' % old_post.id)