[Migration] remove unused oldid.py
[mygpo.git] / mygpo / maintenance / migrate.py
blob09bd25a6752582b0d4c68301d9d155cff5e30777
1 from __future__ import unicode_literals
3 import json
4 from datetime import datetime
6 from django.contrib.contenttypes.models import ContentType
7 from django.contrib.auth.models import User
9 from mygpo.podcasts.models import Tag
10 from mygpo.users.models import Chapter as C, EpisodeUserState, Client
11 from mygpo.chapters.models import Chapter
12 from mygpo.subscriptions.models import Subscription, PodcastConfig
13 from mygpo.history.models import EpisodeHistoryEntry
14 from mygpo.podcasts.models import Episode, Podcast
15 from mygpo.favorites.models import FavoriteEpisode
17 import logging
18 logger = logging.getLogger(__name__)
21 def to_maxlength(cls, field, val):
22 """ Cut val to the maximum length of cls's field """
23 max_length = cls._meta.get_field(field).max_length
24 orig_length = len(val)
25 if orig_length > max_length:
26 val = val[:max_length]
27 logger.warn('%s.%s length reduced from %d to %d',
28 cls.__name__, field, orig_length, max_length)
30 return val
33 #class EpisodeUserState(Document, SettingsMixin):
34 # ref_url = StringProperty(required=True)
35 # podcast_ref_url = StringProperty(required=True)
38 def migrate_estate(state):
39 """ migrate a podcast state """
41 try:
42 user = User.objects.get(profile__uuid=state.user)
43 except User.DoesNotExist:
44 logger.warn("User with ID '{id}' does not exist".format(
45 id=state.user))
46 return
48 try:
49 podcast = Podcast.objects.all().get_by_any_id(state.podcast)
50 except Podcast.DoesNotExist:
51 logger.warn("Podcast with ID '{id}' does not exist".format(
52 id=state.podcast))
53 return
55 try:
56 episode = Episode.objects.filter(podcast=podcast).get_by_any_id(state.episode)
57 except Episode.DoesNotExist:
58 logger.warn("Episode with ID '{id}' does not exist".format(
59 id=state.episode))
60 return
62 logger.info('Migrating episode state ({id}) for user {user} and episode {episode}'
63 .format(id=state._id, user=user, episode=episode))
65 for chapter in state.chapters:
66 migrate_chapter(user, episode, chapter)
68 for action in state.actions:
69 migrate_eaction(user, episode, state, action)
71 is_favorite = state.settings.get('is_favorite', False)
72 if is_favorite:
73 logger.info('Favorite episode')
74 FavoriteEpisode.objects.get_or_create(user=user, episode=episode)
75 else:
76 FavoriteEpisode.objects.filter(user=user, episode=episode).delete()
79 def migrate_chapter(user, episode, c):
81 chapter, created = Chapter.objects.get_or_create(
82 user=user,
83 episode=episode,
84 start=c.start,
85 end=c.end,
86 defaults = {
87 'label': c.label or '',
88 'advertisement': c.advertisement,
93 def migrate_eaction(user, episode, state, ea):
95 logger.info('Migrating {action} action'.format(action=ea.action))
97 if ea.device is None:
98 client = None
100 else:
101 try:
102 client = user.client_set.get(id=ea.device)
103 except Client.DoesNotExist:
104 logger.warn("Client '{cid}' does not exist; skipping".format(
105 cid=ea.device))
106 return
108 created = datetime.utcfromtimestamp(ea.upload_timestamp) if ea.upload_timestamp else datetime.utcnow()
109 entry, created = EpisodeHistoryEntry.objects.get_or_create(
110 user=user,
111 client=client,
112 episode=episode,
113 action=ea.action,
114 timestamp=ea.timestamp,
115 defaults = {
116 'created': created,
117 'started': ea.started,
118 'stopped': ea.playmark,
119 'total': ea.total,
120 'podcast_ref_url': state.podcast_ref_url,
121 'episode_ref_url': state.ref_url,
125 if created:
126 logger.info('Episode History Entry created: {user} {action} {episode}'
127 'on {client} @ {timestamp}'.format(user=user,
128 action=entry.action, episode=episode, client=client,
129 timestamp=entry.timestamp))
133 def get_subscribed_devices(state):
134 """ device Ids on which the user subscribed to the podcast """
135 devices = {}
137 for action in state.actions:
138 if action.action == "subscribe":
139 if not action.device in state.disabled_devices:
140 devices[action.device] = action.timestamp
141 else:
142 if action.device in devices:
143 devices.pop(action.device)
145 return devices
149 from couchdbkit import Database
150 db = Database('http://127.0.0.1:5984/mygpo_userdata_copy')
151 from couchdbkit.changes import ChangesStream, fold, foreach
154 MIGRATIONS = {
155 'PodcastUserState': (None, None),
156 'User': (None, None),
157 'Suggestions': (None, None),
158 'EpisodeUserState': (EpisodeUserState, migrate_estate),
161 def migrate_change(c):
162 logger.info('Migrate seq %s', c['seq'])
163 doc = c['doc']
165 if not 'doc_type' in doc:
166 logger.warn('Document contains no doc_type: %r', doc)
167 return
169 doctype = doc['doc_type']
171 cls, migrate = MIGRATIONS[doctype]
173 if cls is None:
174 logger.warn("Skipping '%s'", doctype)
175 return
177 obj = cls.wrap(doc)
178 migrate(obj)
181 def migrate(since=0):
182 with ChangesStream(db,
183 feed="continuous",
184 heartbeat=True,
185 include_docs=True,
186 since=since,
187 ) as stream:
188 for change in stream:
189 migrate_change(change)