1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
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/>.
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
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
, \
30 from mediagoblin
.submit
.lib
import prepare_queue_task
, run_process_media
32 _log
= logging
.getLogger(__name__
)
38 def post_entry(request
):
39 _log
.debug('Posting entry')
41 if request
.method
== 'OPTIONS':
42 return json_response({'status': 200})
44 if request
.method
!= 'POST':
45 _log
.debug('Must POST against post_entry')
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')
54 media_file
= request
.files
['file']
56 media_type
, media_manager
= sniff_media(media_file
)
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])
63 entry
.description
= unicode(request
.form
.get('description'))
64 entry
.license
= unicode(request
.form
.get('license', ''))
66 entry
.uploader
= request
.user
.id
71 queue_file
= prepare_queue_task(request
.app
, entry
, media_file
.filename
)
74 queue_file
.write(request
.files
['file'].stream
.read())
76 # Save now so we have this data before kicking off processing
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'])
85 # Pass off to processing
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
)
94 return json_response(get_entry_serializable(entry
, request
.urlgen
))
99 def api_test(request
):
101 'username': request
.user
.username
,
102 'email': request
.user
.email
}
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
))
109 def get_entries(request
):
110 entries
= request
.db
.MediaEntry
.query
112 # TODO: Make it possible to fetch unprocessed media, or media in-processing
113 entries
= entries
.filter_by(state
=u
'processed')
115 # TODO: Add sort order customization
116 entries
= entries
.order_by(request
.db
.MediaEntry
.created
.desc())
118 # TODO: Fetch default and upper limit from config
119 entries
= entries
.limit(int(request
.GET
.get('limit') or 10))
121 entries_serializable
= []
123 for entry
in entries
:
124 entries_serializable
.append(get_entry_serializable(entry
, request
.urlgen
))
126 return json_response(entries_serializable
)