4 from werkzeug
.datastructures
import FileStorage
6 from mediagoblin
.media_types
import sniff_media
7 from mediagoblin
.decorators
import oauth_required
8 from mediagoblin
.db
.models
import User
, MediaEntry
, MediaComment
9 from mediagoblin
.tools
.response
import redirect
, json_response
10 from mediagoblin
.meddleware
.csrf
import csrf_exempt
11 from mediagoblin
.submit
.lib
import new_upload_entry
14 def profile(request
, raw
=False):
15 """ This is /api/user/<username>/profile - This will give profile info """
16 user
= request
.matchdict
["username"]
17 requested_user
= User
.query
.filter_by(username
=user
)
19 # check if the user exists
20 if requested_user
is None:
21 error
= "No such 'user' with id '{0}'".format(user
)
22 return json_response({"error": error
}, status
=404)
24 user
= requested_user
[0]
27 return (user
, user
.serialize(request
))
29 # user profiles are public so return information
30 return json_response(user
.serialize(request
))
34 """ This is /api/user/<username> - This will get the user """
35 user
, user_profile
= profile(request
, raw
=True)
37 "nickname": user
.username
,
38 "updated": user
.created
.isoformat(),
39 "published": user
.created
.isoformat(),
40 "profile": user_profile
43 return json_response(data
)
48 """ Endpoint for file uploads """
49 user
= request
.matchdict
["username"]
50 requested_user
= User
.query
.filter_by(username
=user
)
52 if requested_user
is None:
53 error
= "No such 'user' with id '{0}'".format(user
)
54 return json_response({"error": error
}, status
=404)
56 request
.user
= requested_user
[0]
57 if request
.method
== "POST":
58 # Wrap the data in the werkzeug file wrapper
59 file_data
= FileStorage(
60 stream
=io
.BytesIO(request
.data
),
61 filename
=request
.args
.get("qqfile", "unknown"),
62 content_type
=request
.headers
.get("Content-Type", "application/octal-stream")
66 media_type
, media_manager
= sniff_media(file_data
)
67 entry
= new_upload_entry(request
.user
)
68 if hasattr(media_manager
, "api_upload_request"):
69 return media_manager
.api_upload_request(request
, file_data
, entry
)
71 return json_response({"error": "Not yet implemented"}, status
=400)
73 return json_response({"error": "Not yet implemented"}, status
=400)
78 """ Handles the user's outbox - /api/user/<username>/feed """
79 user
= request
.matchdict
["username"]
80 requested_user
= User
.query
.filter_by(username
=user
)
82 # check if the user exists
83 if requested_user
is None:
84 error
= "No such 'user' with id '{0}'".format(user
)
85 return json_response({"error": error
}, status
=404)
87 request
.user
= requested_user
[0]
89 if request
.method
== "POST":
90 data
= json
.loads(request
.data
)
91 obj
= data
.get("object", None)
93 error
= {"error": "Could not find 'object' element."}
94 return json_response(error
, status
=400)
96 if obj
.get("objectType", None) == "comment":
98 media
= int(data
["object"]["inReplyTo"]["id"])
99 comment
= MediaComment(
101 author
=request
.user
.id,
102 content
=data
["object"]["content"]
105 data
= {"verb": "post", "object": comment
.serialize(request
)}
106 return json_response(data
)
108 elif obj
.get("objectType", None) == "image":
109 # Posting an image to the feed
110 # NB: This is currently just handing the image back until we have an
111 # to send the image to the actual feed
113 media_id
= int(data
["object"]["id"])
114 media
= MediaEntry
.query
.filter_by(id=media_id
)
116 error
= "No such 'image' with id '{0}'".format(id=media_id
)
117 return json_response(error
, status
=404)
119 return json_response(media
.serialize(request
))
121 elif obj
.get("objectType", None) is None:
122 # They need to tell us what type of object they're giving us.
123 error
= {"error": "No objectType specified."}
124 return json_response(error
, status
=400)
126 # Oh no! We don't know about this type of object (yet)
127 error_message
= "Unknown object type '{0}'.".format(
128 obj
.get("objectType", None)
131 error
= {"error": error_message
}
132 return json_response(error
, status
=400)
135 feed_url
= request
.urlgen(
136 "mediagoblin.federation.feed",
137 username
=request
.user
.username
,
142 "displayName": "Activities by {user}@{host}".format(
143 user
=request
.user
.username
,
146 "objectTypes": ["activity"],
162 "author": request
.user
.serialize(request
),
167 # Now lookup the user's feed.
168 for media
in MediaEntry
.query
.all():
169 feed
["items"].append({
171 "object": media
.serialize(request
),
172 "actor": request
.user
.serialize(request
),
173 "content": "{0} posted a picture".format(request
.user
.username
),
176 feed
["items"][-1]["updated"] = feed
["items"][-1]["object"]["updated"]
177 feed
["items"][-1]["published"] = feed
["items"][-1]["object"]["published"]
178 feed
["items"][-1]["url"] = feed
["items"][-1]["object"]["url"]
179 feed
["totalItems"] = len(feed
["items"])
181 return json_response(feed
)
184 def object(request
, raw_obj
=False):
185 """ Lookup for a object type """
186 objectType
= request
.matchdict
["objectType"]
187 uuid
= request
.matchdict
["uuid"]
188 if objectType
not in ["image"]:
189 error
= "Unknown type: {0}".format(objectType
)
190 # not sure why this is 404, maybe ask evan. Maybe 400?
191 return json_response({"error": error
}, status
=404)
193 media
= MediaEntry
.query
.filter_by(slug
=uuid
).first()
195 # no media found with that uuid
196 error
= "Can't find a {0} with ID = {1}".format(objectType
, uuid
)
197 return json_response({"error": error
}, status
=404)
202 return json_response(media
.serialize(request
))
205 def object_comments(request
):
206 """ Looks up for the comments on a object """
207 media
= object(request
, raw_obj
=True)
209 if isinstance(response
, MediaEntry
):
210 comments
= response
.serialize(request
)
211 comments
= comments
.get("replies", {
214 "url": request
.urlgen(
215 "mediagoblin.federation.object.comments",
216 objectType
=media
.objectType
,
220 comments
["displayName"] = "Replies to {0}".format(comments
["url"])
221 comments
["links"] = {
222 "first": comments
["url"],
223 "self": comments
["url"],
225 response
= json_response(comments
)
233 def host_meta(request
):
234 """ This is /.well-known/host-meta - provides URL's to resources on server """
237 # Client registration links
239 "ref": "registration_endpoint",
240 "href": request
.urlgen("mediagoblin.oauth.client_register", qualified
=True),
243 "ref": "http://apinamespace.org/oauth/request_token",
244 "href": request
.urlgen("mediagoblin.oauth.request_token", qualified
=True),
247 "ref": "http://apinamespace.org/oauth/authorize",
248 "href": request
.urlgen("mediagoblin.oauth.authorize", qualified
=True),
251 "ref": "http://apinamespace.org/oauth/access_token",
252 "href": request
.urlgen("mediagoblin.oauth.access_token", qualified
=True),
255 return json_response({"links": links
})
258 """ This is /api/whoami - This is a HTTP redirect to api profile """
259 profile
= request
.urlgen(
260 "mediagoblin.federation.user.profile",
261 username
=request
.user
.username
,
265 return redirect(request
, location
=profile
)