1 from __future__
import unicode_literals
4 from datetime
import datetime
6 from django
.contrib
.contenttypes
.models
import ContentType
7 from django
.contrib
.auth
.models
import User
8 from django
.db
import reset_queries
10 from mygpo
.podcasts
.models
import Tag
11 from mygpo
.users
.models
import Chapter
as C
, EpisodeUserState
, Client
12 from mygpo
.chapters
.models
import Chapter
13 from mygpo
.subscriptions
.models
import Subscription
, PodcastConfig
14 from mygpo
.podcastlists
.models
import PodcastList
, PodcastListEntry
15 from mygpo
.history
.models
import EpisodeHistoryEntry
16 from mygpo
.podcasts
.models
import Episode
, Podcast
, PodcastGroup
17 from mygpo
.favorites
.models
import FavoriteEpisode
18 from mygpo
.votes
.models
import Vote
21 logger
= logging
.getLogger(__name__
)
24 def to_maxlength(cls
, field
, val
):
25 """ Cut val to the maximum length of cls's field """
26 max_length
= cls
._meta
.get_field(field
).max_length
27 orig_length
= len(val
)
28 if orig_length
> max_length
:
29 val
= val
[:max_length
]
30 logger
.warn('%s.%s length reduced from %d to %d',
31 cls
.__name
__, field
, orig_length
, max_length
)
36 #class EpisodeUserState(Document, SettingsMixin):
37 # ref_url = StringProperty(required=True)
38 # podcast_ref_url = StringProperty(required=True)
41 def migrate_estate(state
):
42 """ migrate a podcast state """
45 user
= User
.objects
.get(profile__uuid
=state
.user
)
46 except User
.DoesNotExist
:
47 logger
.warn("User with ID '{id}' does not exist".format(
52 podcast
= Podcast
.objects
.all().get_by_any_id(state
.podcast
)
53 except Podcast
.DoesNotExist
:
54 logger
.warn("Podcast with ID '{id}' does not exist".format(
59 episode
= Episode
.objects
.filter(podcast
=podcast
).get_by_any_id(state
.episode
)
60 except Episode
.DoesNotExist
:
61 logger
.warn("Episode with ID '{id}' does not exist".format(
65 logger
.info('Migrating episode state ({id}) for user {user} and episode {episode}'
66 .format(id=state
._id
, user
=user
, episode
=episode
))
68 for chapter
in state
.chapters
:
69 migrate_chapter(user
, episode
, chapter
)
71 for action
in state
.actions
:
72 migrate_eaction(user
, episode
, state
, action
)
74 is_favorite
= state
.settings
.get('is_favorite', False)
76 logger
.info('Favorite episode')
77 FavoriteEpisode
.objects
.get_or_create(user
=user
, episode
=episode
)
79 FavoriteEpisode
.objects
.filter(user
=user
, episode
=episode
).delete()
82 def migrate_chapter(user
, episode
, c
):
84 chapter
, created
= Chapter
.objects
.get_or_create(
90 'label': c
.label
or '',
91 'advertisement': c
.advertisement
,
96 def migrate_eaction(user
, episode
, state
, ea
):
98 logger
.info('Migrating {action} action'.format(action
=ea
.action
))
100 if ea
.device
is None:
105 client
= user
.client_set
.get(id=ea
.device
)
106 except Client
.DoesNotExist
:
107 logger
.warn("Client '{cid}' does not exist; skipping".format(
111 created
= datetime
.utcfromtimestamp(ea
.upload_timestamp
) if ea
.upload_timestamp
else datetime
.utcnow()
112 entry
, created
= EpisodeHistoryEntry
.objects
.get_or_create(
117 timestamp
=ea
.timestamp
,
120 'started': ea
.started
,
121 'stopped': ea
.playmark
,
123 'podcast_ref_url': state
.podcast_ref_url
,
124 'episode_ref_url': state
.ref_url
,
129 logger
.info('Episode History Entry created: {user} {action} {episode}'
130 'on {client} @ {timestamp}'.format(user
=user
,
131 action
=entry
.action
, episode
=episode
, client
=client
,
132 timestamp
=entry
.timestamp
))
135 from couchdbkit
import Database
136 db
= Database('http://127.0.0.1:5984/mygpo_userdata_copy')
137 from couchdbkit
.changes
import ChangesStream
, fold
, foreach
141 'PodcastUserState': (None, None),
142 'User': (None, None),
143 'Suggestions': (None, None),
144 'EpisodeUserState': (EpisodeUserState
, migrate_estate
),
145 'PodcastList': (None, None),
148 def migrate_change(c
):
149 logger
.info('Migrate seq %s', c
['seq'])
152 if not 'doc_type' in doc
:
153 logger
.warn('Document contains no doc_type: %r', doc
)
156 doctype
= doc
['doc_type']
158 cls
, migrate
= MIGRATIONS
[doctype
]
161 logger
.warn("Skipping '%s'", doctype
)
169 def migrate(since
=0, db
=db
):
170 with
ChangesStream(db
,
176 for change
in stream
:
177 migrate_change(change
)