1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011 Free Software Foundation, Inc
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
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.
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/>.
19 from mongokit
import Document
21 from mediagoblin
import util
22 from mediagoblin
.auth
import lib
as auth_lib
23 from mediagoblin
import mg_globals
24 from mediagoblin
.db
import migrations
25 from mediagoblin
.db
.util
import ASCENDING
, DESCENDING
, ObjectId
26 from mediagoblin
.util
import Pagination
27 from mediagoblin
.util
import DISPLAY_IMAGE_FETCHING_ORDER
40 __collection__
= 'users'
45 'created': datetime
.datetime
,
46 'plugin_data': dict, # plugins can dump stuff here.
48 'email_verified': bool,
50 'verification_key': unicode,
53 'bio' : unicode, # May contain markdown
54 'bio_html': unicode, # May contain plaintext, or HTML
57 required_fields
= ['username', 'created', 'pw_hash', 'email']
60 'created': datetime
.datetime
.utcnow
,
61 'email_verified': False,
62 'status': u
'needs_email_verification',
63 'verification_key': lambda: unicode(uuid
.uuid4()),
66 def check_login(self
, password
):
68 See if a user can login with this password
70 return auth_lib
.bcrypt_check_password(
71 password
, self
['pw_hash'])
74 class MediaEntry(Document
):
75 __collection__
= 'media_entries'
81 'created': datetime
.datetime
,
82 'description': unicode, # May contain markdown/up
83 'description_html': unicode, # May contain plaintext, or HTML
84 'media_type': unicode,
85 'media_data': dict, # extra data relevant to this media_type
86 'plugin_data': dict, # plugins can dump stuff here.
90 # For now let's assume there can only be one main file queued
92 'queued_media_file': [unicode],
94 # A dictionary of logical names to filepaths
97 # The following should be lists of lists, in appropriate file
99 'attachment_files': list,
101 # This one should just be a single file record
102 'thumbnail_file': [unicode]}
105 'uploader', 'created', 'media_type', 'slug']
108 'created': datetime
.datetime
.utcnow
,
109 'state': u
'unprocessed'}
111 def get_comments(self
):
112 return self
.db
.MediaComment
.find({
113 'media_entry': self
['_id']}).sort('created', DESCENDING
)
115 def get_display_media(self
, media_map
, fetch_order
=DISPLAY_IMAGE_FETCHING_ORDER
):
117 Find the best media for display.
120 - media_map: a dict like
121 {u'image_size': [u'dir1', u'dir2', u'image.jpg']}
122 - fetch_order: the order we should try fetching images in
125 (media_size, media_path)
127 media_sizes
= media_map
.keys()
129 for media_size
in DISPLAY_IMAGE_FETCHING_ORDER
:
130 if media_size
in media_sizes
:
131 return media_map
[media_size
]
133 def main_mediafile(self
):
136 def generate_slug(self
):
137 self
['slug'] = util
.slugify(self
['title'])
139 duplicate
= mg_globals
.database
.media_entries
.find_one(
140 {'slug': self
['slug']})
143 self
['slug'] = "%s-%s" % (self
['_id'], self
['slug'])
145 def url_for_self(self
, urlgen
):
147 Generate an appropriate url for ourselves
149 Use a slug if we have one, else use our '_id'.
151 uploader
= self
.uploader()
155 'mediagoblin.user_pages.media_home',
156 user
=uploader
['username'],
160 'mediagoblin.user_pages.media_home',
161 user
=uploader
['username'],
162 media
=unicode(self
['_id']))
164 def url_to_prev(self
, urlgen
):
166 Provide a url to the previous entry from this user, if there is one
168 cursor
= self
.db
.MediaEntry
.find({'_id' : {"$gt": self
['_id']},
169 'uploader': self
['uploader'],
170 'state': 'processed'}).sort(
171 '_id', ASCENDING
).limit(1)
173 return urlgen('mediagoblin.user_pages.media_home',
174 user
=self
.uploader()['username'],
175 media
=unicode(cursor
[0]['slug']))
177 def url_to_next(self
, urlgen
):
179 Provide a url to the next entry from this user, if there is one
181 cursor
= self
.db
.MediaEntry
.find({'_id' : {"$lt": self
['_id']},
182 'uploader': self
['uploader'],
183 'state': 'processed'}).sort(
184 '_id', DESCENDING
).limit(1)
187 return urlgen('mediagoblin.user_pages.media_home',
188 user
=self
.uploader()['username'],
189 media
=unicode(cursor
[0]['slug']))
192 return self
.db
.User
.find_one({'_id': self
['uploader']})
195 class MediaComment(Document
):
196 __collection__
= 'media_comments'
199 'media_entry': ObjectId
,
201 'created': datetime
.datetime
,
203 'content_html': unicode}
206 'media_entry', 'author', 'created', 'content']
209 'created': datetime
.datetime
.utcnow
}
211 def media_entry(self
):
212 return self
.db
.MediaEntry
.find_one({'_id': self
['media_entry']})
215 return self
.db
.User
.find_one({'_id': self
['author']})
224 def register_models(connection
):
226 Register all models in REGISTER_MODELS with this connection.
228 connection
.register(REGISTER_MODELS
)