2055a663a18e574c19bb9768a9af492e0f902586
[mediagoblin.git] / mediagoblin / plugins / api / views.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
3 #
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.
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 json
18 import logging
19
20 from os.path import splitext
21 from werkzeug.datastructures import FileStorage
22 from werkzeug.exceptions import BadRequest, Forbidden
23 from werkzeug.wrappers import Response
24
25 from mediagoblin.decorators import require_active_login
26 from mediagoblin.meddleware.csrf import csrf_exempt
27 from mediagoblin.media_types import sniff_media
28 from mediagoblin.plugins.api.tools import api_auth, get_entry_serializable, \
29 json_response
30 from mediagoblin.submit.lib import prepare_queue_task, run_process_media
31
32 _log = logging.getLogger(__name__)
33
34
35 @csrf_exempt
36 @api_auth
37 @require_active_login
38 def post_entry(request):
39 _log.debug('Posting entry')
40
41 if request.method == 'OPTIONS':
42 return json_response({'status': 200})
43
44 if request.method != 'POST':
45 _log.debug('Must POST against post_entry')
46 raise BadRequest()
47
48 if not 'file' in request.files \
49 or not isinstance(request.files['file'], FileStorage) \
50 or not request.files['file'].stream:
51 _log.debug('File field not found')
52 raise BadRequest()
53
54 media_file = request.files['file']
55
56 media_type, media_manager = sniff_media(media_file)
57
58 entry = request.db.MediaEntry()
59 entry.media_type = unicode(media_type)
60 entry.title = unicode(request.form.get('title')
61 or splitext(media_file.filename)[0])
62
63 entry.description = unicode(request.form.get('description'))
64 entry.license = unicode(request.form.get('license', ''))
65
66 entry.uploader = request.user.id
67
68 entry.generate_slug()
69
70 # queue appropriately
71 queue_file = prepare_queue_task(request.app, entry, media_file.filename)
72
73 with queue_file:
74 queue_file.write(request.files['file'].stream.read())
75
76 # Save now so we have this data before kicking off processing
77 entry.save()
78
79 if request.form.get('callback_url'):
80 metadata = request.db.ProcessingMetaData()
81 metadata.media_entry = entry
82 metadata.callback_url = unicode(request.form['callback_url'])
83 metadata.save()
84
85 # Pass off to processing
86 #
87 # (... don't change entry after this point to avoid race
88 # conditions with changes to the document via processing code)
89 feed_url = request.urlgen(
90 'mediagoblin.user_pages.atom_feed',
91 qualified=True, user=request.user.username)
92 run_process_media(entry, feed_url)
93
94 return json_response(get_entry_serializable(entry, request.urlgen))
95
96
97 @api_auth
98 @require_active_login
99 def api_test(request):
100 user_data = {
101 'username': request.user.username,
102 'email': request.user.email}
103
104 # TODO: This is the *only* thing using Response() here, should that
105 # not simply use json_response()?
106 return Response(json.dumps(user_data))
107
108
109 def get_entries(request):
110 entries = request.db.MediaEntry.query
111
112 # TODO: Make it possible to fetch unprocessed media, or media in-processing
113 entries = entries.filter_by(state=u'processed')
114
115 # TODO: Add sort order customization
116 entries = entries.order_by(request.db.MediaEntry.created.desc())
117
118 # TODO: Fetch default and upper limit from config
119 entries = entries.limit(int(request.GET.get('limit') or 10))
120
121 entries_serializable = []
122
123 for entry in entries:
124 entries_serializable.append(get_entry_serializable(entry, request.urlgen))
125
126 return json_response(entries_serializable)