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
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
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
)
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 """
42 user
= User
.objects
.get(profile__uuid
=state
.user
)
43 except User
.DoesNotExist
:
44 logger
.warn("User with ID '{id}' does not exist".format(
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(
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(
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)
73 logger
.info('Favorite episode')
74 FavoriteEpisode
.objects
.get_or_create(user
=user
, episode
=episode
)
76 FavoriteEpisode
.objects
.filter(user
=user
, episode
=episode
).delete()
79 def migrate_chapter(user
, episode
, c
):
81 chapter
, created
= Chapter
.objects
.get_or_create(
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
))
102 client
= user
.client_set
.get(id=ea
.device
)
103 except Client
.DoesNotExist
:
104 logger
.warn("Client '{cid}' does not exist; skipping".format(
108 created
= datetime
.utcfromtimestamp(ea
.upload_timestamp
) if ea
.upload_timestamp
else datetime
.utcnow()
109 entry
, created
= EpisodeHistoryEntry
.objects
.get_or_create(
114 timestamp
=ea
.timestamp
,
117 'started': ea
.started
,
118 'stopped': ea
.playmark
,
120 'podcast_ref_url': state
.podcast_ref_url
,
121 'episode_ref_url': state
.ref_url
,
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 """
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
142 if action
.device
in devices
:
143 devices
.pop(action
.device
)
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
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'])
165 if not 'doc_type' in doc
:
166 logger
.warn('Document contains no doc_type: %r', doc
)
169 doctype
= doc
['doc_type']
171 cls
, migrate
= MIGRATIONS
[doctype
]
174 logger
.warn("Skipping '%s'", doctype
)
181 def migrate(since
=0):
182 with
ChangesStream(db
,
188 for change
in stream
:
189 migrate_change(change
)