Merge pull request #2216 from fabrixxm/feature-api-like
Works on API and a small refractor, updated docs
This commit is contained in:
commit
99861b9fa6
10 changed files with 1436 additions and 850 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -13,7 +13,7 @@ addon
|
||||||
robots.txt
|
robots.txt
|
||||||
|
|
||||||
#ignore documentation, it should be newly built
|
#ignore documentation, it should be newly built
|
||||||
doc/api
|
doc/html
|
||||||
|
|
||||||
#ignore reports, should be generted with every build
|
#ignore reports, should be generted with every build
|
||||||
report/
|
report/
|
||||||
|
|
|
||||||
197
doc/api.md
197
doc/api.md
|
|
@ -1,4 +1,4 @@
|
||||||
Implemented API calls
|
Friendica API
|
||||||
===
|
===
|
||||||
The Friendica API aims to be compatible to the [GNU Social API](http://skilledtests.com/wiki/Twitter-compatible_API) and the [Twitter API](https://dev.twitter.com/rest/public).
|
The Friendica API aims to be compatible to the [GNU Social API](http://skilledtests.com/wiki/Twitter-compatible_API) and the [Twitter API](https://dev.twitter.com/rest/public).
|
||||||
|
|
||||||
|
|
@ -24,13 +24,45 @@ Please refer to the linked documentation for further information.
|
||||||
* cid: Contact id of the user (important for "contact_allow" and "contact_deny")
|
* cid: Contact id of the user (important for "contact_allow" and "contact_deny")
|
||||||
* network: network of the user
|
* network: network of the user
|
||||||
|
|
||||||
|
#### Errors
|
||||||
|
When an error occour in API call, an HTTP error code is returned, with an error message
|
||||||
|
Usually:
|
||||||
|
- 400 Bad Request: if parameter are missing or items can't be found
|
||||||
|
- 403 Forbidden: if authenticated user is missing
|
||||||
|
- 405 Method Not Allowed: if API was called with invalid method, eg. GET when API require POST
|
||||||
|
- 501 Not Implemented: if requested API doesn't exists
|
||||||
|
- 500 Internal Server Error: on other error contitions
|
||||||
|
|
||||||
|
Error body is
|
||||||
|
|
||||||
|
json:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"error": "Specific error message",
|
||||||
|
"request": "API path requested",
|
||||||
|
"code": "HTTP error code"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
xml:
|
||||||
|
```
|
||||||
|
<status>
|
||||||
|
<error>Specific error message</error>
|
||||||
|
<request>API path requested</request>
|
||||||
|
<code>HTTP error code</code>
|
||||||
|
</status>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
### account/rate_limit_status
|
### account/rate_limit_status
|
||||||
|
|
||||||
|
---
|
||||||
### account/verify_credentials
|
### account/verify_credentials
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* skip_status: Don't show the "status" field. (Default: false)
|
* skip_status: Don't show the "status" field. (Default: false)
|
||||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||||
|
|
||||||
|
---
|
||||||
### conversation/show
|
### conversation/show
|
||||||
Unofficial Twitter command. It shows all direct answers (excluding the original post) to a given id.
|
Unofficial Twitter command. It shows all direct answers (excluding the original post) to a given id.
|
||||||
|
|
||||||
|
|
@ -47,6 +79,7 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
|
||||||
* trim_user
|
* trim_user
|
||||||
* contributor_details
|
* contributor_details
|
||||||
|
|
||||||
|
---
|
||||||
### direct_messages
|
### direct_messages
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -59,6 +92,7 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
|
||||||
#### Unsupported parameters
|
#### Unsupported parameters
|
||||||
* skip_status
|
* skip_status
|
||||||
|
|
||||||
|
---
|
||||||
### direct_messages/all
|
### direct_messages/all
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -67,6 +101,7 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
|
||||||
* max_id: maximum id
|
* max_id: maximum id
|
||||||
* getText: Defines the format of the status field. Can be "html" or "plain"
|
* getText: Defines the format of the status field. Can be "html" or "plain"
|
||||||
|
|
||||||
|
---
|
||||||
### direct_messages/conversation
|
### direct_messages/conversation
|
||||||
Shows all direct messages of a conversation
|
Shows all direct messages of a conversation
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
@ -77,6 +112,7 @@ Shows all direct messages of a conversation
|
||||||
* getText: Defines the format of the status field. Can be "html" or "plain"
|
* getText: Defines the format of the status field. Can be "html" or "plain"
|
||||||
* uri: URI of the conversation
|
* uri: URI of the conversation
|
||||||
|
|
||||||
|
---
|
||||||
### direct_messages/new
|
### direct_messages/new
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* user_id: id of the user
|
* user_id: id of the user
|
||||||
|
|
@ -85,6 +121,7 @@ Shows all direct messages of a conversation
|
||||||
* replyto: ID of the replied direct message
|
* replyto: ID of the replied direct message
|
||||||
* title: Title of the direct message
|
* title: Title of the direct message
|
||||||
|
|
||||||
|
---
|
||||||
### direct_messages/sent
|
### direct_messages/sent
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -94,6 +131,7 @@ Shows all direct messages of a conversation
|
||||||
* getText: Defines the format of the status field. Can be "html" or "plain"
|
* getText: Defines the format of the status field. Can be "html" or "plain"
|
||||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||||
|
|
||||||
|
---
|
||||||
### favorites
|
### favorites
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -108,16 +146,19 @@ Shows all direct messages of a conversation
|
||||||
|
|
||||||
Favorites aren't displayed to other users, so "user_id" and "screen_name". So setting this value will result in an empty array.
|
Favorites aren't displayed to other users, so "user_id" and "screen_name". So setting this value will result in an empty array.
|
||||||
|
|
||||||
|
---
|
||||||
### favorites/create
|
### favorites/create
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* id
|
* id
|
||||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||||
|
|
||||||
|
---
|
||||||
### favorites/destroy
|
### favorites/destroy
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* id
|
* id
|
||||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||||
|
|
||||||
|
---
|
||||||
### followers/ids
|
### followers/ids
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
|
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
|
||||||
|
|
@ -129,16 +170,139 @@ Favorites aren't displayed to other users, so "user_id" and "screen_name". So se
|
||||||
|
|
||||||
Friendica doesn't allow showing followers of other users.
|
Friendica doesn't allow showing followers of other users.
|
||||||
|
|
||||||
|
---
|
||||||
|
### friendica/activity/<verb>
|
||||||
|
#### parameters
|
||||||
|
* id: item id
|
||||||
|
|
||||||
|
Add or remove an activity from an item.
|
||||||
|
'verb' can be one of:
|
||||||
|
- like
|
||||||
|
- dislike
|
||||||
|
- attendyes
|
||||||
|
- attendno
|
||||||
|
- attendmaybe
|
||||||
|
|
||||||
|
To remove an activity, prepend the verb with "un", eg. "unlike" or "undislike"
|
||||||
|
Attend verbs disable eachother: that means that if "attendyes" was added to an item, adding "attendno" remove previous "attendyes".
|
||||||
|
Attend verbs should be used only with event-related items (there is no check at the moment)
|
||||||
|
|
||||||
|
#### Return values
|
||||||
|
|
||||||
|
On success:
|
||||||
|
json
|
||||||
|
```"ok"```
|
||||||
|
|
||||||
|
xml
|
||||||
|
```<ok>true</ok>```
|
||||||
|
|
||||||
|
On error:
|
||||||
|
HTTP 400 BadRequest
|
||||||
|
|
||||||
|
---
|
||||||
### friendica/photo
|
### friendica/photo
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* photo_id: Resource id of a photo.
|
* photo_id: Resource id of a photo.
|
||||||
|
* scale: (optional) scale value of the photo
|
||||||
|
|
||||||
Returns data of a picture with the given resource.
|
Returns data of a picture with the given resource.
|
||||||
|
If 'scale' isn't provided, returned data include full url to each scale of the photo.
|
||||||
|
If 'scale' is set, returned data include image data base64 encoded.
|
||||||
|
|
||||||
|
possibile scale value are:
|
||||||
|
0: original or max size by server settings
|
||||||
|
1: image with or height at <= 640
|
||||||
|
2: image with or height at <= 320
|
||||||
|
3: thumbnail 160x160
|
||||||
|
|
||||||
|
4: Profile image at 175x175
|
||||||
|
5: Profile image at 80x80
|
||||||
|
6: Profile image at 48x48
|
||||||
|
|
||||||
|
An image used as profile image has only scale 4-6, other images only 0-3
|
||||||
|
|
||||||
|
#### Return values
|
||||||
|
|
||||||
|
json
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"id": "photo id"
|
||||||
|
"created": "date(YYYY-MM-GG HH:MM:SS)",
|
||||||
|
"edited": "date(YYYY-MM-GG HH:MM:SS)",
|
||||||
|
"title": "photo title",
|
||||||
|
"desc": "photo description",
|
||||||
|
"album": "album name",
|
||||||
|
"filename": "original file name",
|
||||||
|
"type": "mime type",
|
||||||
|
"height": "number",
|
||||||
|
"width": "number",
|
||||||
|
"profile": "1 if is profile photo",
|
||||||
|
"link": {
|
||||||
|
"<scale>": "url to image"
|
||||||
|
...
|
||||||
|
},
|
||||||
|
// if 'scale' is set
|
||||||
|
"datasize": "size in byte",
|
||||||
|
"data": "base64 encoded image data"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
xml
|
||||||
|
```
|
||||||
|
<photo>
|
||||||
|
<id>photo id</id>
|
||||||
|
<created>date(YYYY-MM-GG HH:MM:SS)</created>
|
||||||
|
<edited>date(YYYY-MM-GG HH:MM:SS)</edited>
|
||||||
|
<title>photo title</title>
|
||||||
|
<desc>photo description</desc>
|
||||||
|
<album>album name</album>
|
||||||
|
<filename>original file name</filename>
|
||||||
|
<type>mime type</type>
|
||||||
|
<height>number</height>
|
||||||
|
<width>number</width>
|
||||||
|
<profile>1 if is profile photo</profile>
|
||||||
|
<links type="array">
|
||||||
|
<link type="mime type" scale="scale number" href="image url"/>
|
||||||
|
...
|
||||||
|
</links>
|
||||||
|
</photo>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
### friendica/photos/list
|
### friendica/photos/list
|
||||||
|
|
||||||
Returns a list of all photo resources of the logged in user.
|
Returns a list of all photo resources of the logged in user.
|
||||||
|
|
||||||
|
#### Return values
|
||||||
|
|
||||||
|
json
|
||||||
|
```
|
||||||
|
[
|
||||||
|
{
|
||||||
|
id: "resource_id",
|
||||||
|
album: "album name",
|
||||||
|
filename: "original file name",
|
||||||
|
type: "image mime type",
|
||||||
|
thumb: "url to thumb sized image"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
xml
|
||||||
|
```
|
||||||
|
<photos type="array">
|
||||||
|
<photo id="resource_id"
|
||||||
|
album="album name"
|
||||||
|
filename="original file name"
|
||||||
|
type="image mime type">
|
||||||
|
"url to thumb sized image"
|
||||||
|
</photo>
|
||||||
|
...
|
||||||
|
</photos>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
### friends/ids
|
### friends/ids
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
|
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
|
||||||
|
|
@ -150,12 +314,15 @@ Returns a list of all photo resources of the logged in user.
|
||||||
|
|
||||||
Friendica doesn't allow showing friends of other users.
|
Friendica doesn't allow showing friends of other users.
|
||||||
|
|
||||||
|
---
|
||||||
### help/test
|
### help/test
|
||||||
|
|
||||||
|
---
|
||||||
### media/upload
|
### media/upload
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* media: image data
|
* media: image data
|
||||||
|
|
||||||
|
---
|
||||||
### oauth/request_token
|
### oauth/request_token
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* oauth_callback
|
* oauth_callback
|
||||||
|
|
@ -163,6 +330,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
#### Unsupported parameters
|
#### Unsupported parameters
|
||||||
* x_auth_access_type
|
* x_auth_access_type
|
||||||
|
|
||||||
|
---
|
||||||
### oauth/access_token
|
### oauth/access_token
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* oauth_verifier
|
* oauth_verifier
|
||||||
|
|
@ -172,6 +340,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
* x_auth_username
|
* x_auth_username
|
||||||
* x_auth_mode
|
* x_auth_mode
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/destroy
|
### statuses/destroy
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* id: message number
|
* id: message number
|
||||||
|
|
@ -180,12 +349,15 @@ Friendica doesn't allow showing friends of other users.
|
||||||
#### Unsupported parameters
|
#### Unsupported parameters
|
||||||
* trim_user
|
* trim_user
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/followers
|
### statuses/followers
|
||||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/friends
|
### statuses/friends
|
||||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/friends_timeline
|
### statuses/friends_timeline
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -201,6 +373,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
* trim_user
|
* trim_user
|
||||||
* contributor_details
|
* contributor_details
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/home_timeline
|
### statuses/home_timeline
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -216,6 +389,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
* trim_user
|
* trim_user
|
||||||
* contributor_details
|
* contributor_details
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/mentions
|
### statuses/mentions
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -229,6 +403,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
* trim_user
|
* trim_user
|
||||||
* contributor_details
|
* contributor_details
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/public_timeline
|
### statuses/public_timeline
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -242,6 +417,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
#### Unsupported parameters
|
#### Unsupported parameters
|
||||||
* trim_user
|
* trim_user
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/replies
|
### statuses/replies
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* count: Items per page (default: 20)
|
* count: Items per page (default: 20)
|
||||||
|
|
@ -255,6 +431,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
* trim_user
|
* trim_user
|
||||||
* contributor_details
|
* contributor_details
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/retweet
|
### statuses/retweet
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* id: message number
|
* id: message number
|
||||||
|
|
@ -263,6 +440,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
#### Unsupported parameters
|
#### Unsupported parameters
|
||||||
* trim_user
|
* trim_user
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/show
|
### statuses/show
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* id: message number
|
* id: message number
|
||||||
|
|
@ -273,6 +451,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
* include_my_retweet
|
* include_my_retweet
|
||||||
* trim_user
|
* trim_user
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/update, statuses/update_with_media
|
### statuses/update, statuses/update_with_media
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* title: Title of the status
|
* title: Title of the status
|
||||||
|
|
@ -296,6 +475,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
* place_id
|
* place_id
|
||||||
* display_coordinates
|
* display_coordinates
|
||||||
|
|
||||||
|
---
|
||||||
### statuses/user_timeline
|
### statuses/user_timeline
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* user_id: id of the user
|
* user_id: id of the user
|
||||||
|
|
@ -313,8 +493,10 @@ Friendica doesn't allow showing friends of other users.
|
||||||
* trim_user
|
* trim_user
|
||||||
* contributor_details
|
* contributor_details
|
||||||
|
|
||||||
|
---
|
||||||
### statusnet/config
|
### statusnet/config
|
||||||
|
|
||||||
|
---
|
||||||
### statusnet/version
|
### statusnet/version
|
||||||
|
|
||||||
#### Unsupported parameters
|
#### Unsupported parameters
|
||||||
|
|
@ -324,6 +506,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
|
|
||||||
Friendica doesn't allow showing followers of other users.
|
Friendica doesn't allow showing followers of other users.
|
||||||
|
|
||||||
|
---
|
||||||
### users/search
|
### users/search
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* q: name of the user
|
* q: name of the user
|
||||||
|
|
@ -333,6 +516,7 @@ Friendica doesn't allow showing followers of other users.
|
||||||
* count
|
* count
|
||||||
* include_entities
|
* include_entities
|
||||||
|
|
||||||
|
---
|
||||||
### users/show
|
### users/show
|
||||||
#### Parameters
|
#### Parameters
|
||||||
* user_id: id of the user
|
* user_id: id of the user
|
||||||
|
|
@ -349,6 +533,7 @@ Friendica doesn't allow showing friends of other users.
|
||||||
|
|
||||||
## Implemented API calls (not compatible with other APIs)
|
## Implemented API calls (not compatible with other APIs)
|
||||||
|
|
||||||
|
---
|
||||||
### friendica/group_show
|
### friendica/group_show
|
||||||
Return all or a specified group of the user with the containing contacts as array.
|
Return all or a specified group of the user with the containing contacts as array.
|
||||||
|
|
||||||
|
|
@ -362,9 +547,11 @@ Array of:
|
||||||
* user: array of group members (return from api_get_user() function for each member)
|
* user: array of group members (return from api_get_user() function for each member)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
### friendica/group_delete
|
### friendica/group_delete
|
||||||
delete the specified group of contacts; API call need to include the correct gid AND name of the group to be deleted.
|
delete the specified group of contacts; API call need to include the correct gid AND name of the group to be deleted.
|
||||||
|
|
||||||
|
---
|
||||||
### Parameters
|
### Parameters
|
||||||
* gid: id of the group to be deleted
|
* gid: id of the group to be deleted
|
||||||
* name: name of the group to be deleted
|
* name: name of the group to be deleted
|
||||||
|
|
@ -378,6 +565,7 @@ Array of:
|
||||||
* wrong users: empty array
|
* wrong users: empty array
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
### friendica/group_create
|
### friendica/group_create
|
||||||
Create the group with the posted array of contacts as members.
|
Create the group with the posted array of contacts as members.
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
@ -398,6 +586,7 @@ Array of:
|
||||||
* wrong users: array of users, which were not available in the contact table
|
* wrong users: array of users, which were not available in the contact table
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
### friendica/group_update
|
### friendica/group_update
|
||||||
Update the group with the posted array of contacts as members (post all members of the group to the call; function will remove members not posted).
|
Update the group with the posted array of contacts as members (post all members of the group to the call; function will remove members not posted).
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
@ -418,7 +607,7 @@ Array of:
|
||||||
* status: „missing user“ | „ok“
|
* status: „missing user“ | „ok“
|
||||||
* wrong users: array of users, which were not available in the contact table
|
* wrong users: array of users, which were not available in the contact table
|
||||||
|
|
||||||
|
---
|
||||||
## Not Implemented API calls
|
## Not Implemented API calls
|
||||||
The following API calls are implemented in GNU Social but not in Friendica: (incomplete)
|
The following API calls are implemented in GNU Social but not in Friendica: (incomplete)
|
||||||
|
|
||||||
|
|
@ -505,6 +694,10 @@ The following API calls from the Twitter API aren't implemented neither in Frien
|
||||||
* trends/closest
|
* trends/closest
|
||||||
* users/report_spam
|
* users/report_spam
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Usage Examples
|
## Usage Examples
|
||||||
### BASH / cURL
|
### BASH / cURL
|
||||||
Betamax has documentated some example API usage from a [bash script](https://en.wikipedia.org/wiki/Bash_(Unix_shell) employing [curl](https://en.wikipedia.org/wiki/CURL) (see [his posting](https://betamax65.de/display/betamax65/43539)).
|
Betamax has documentated some example API usage from a [bash script](https://en.wikipedia.org/wiki/Bash_(Unix_shell) employing [curl](https://en.wikipedia.org/wiki/CURL) (see [his posting](https://betamax65.de/display/betamax65/43539)).
|
||||||
|
|
|
||||||
105
include/HTTPExceptions.php
Normal file
105
include/HTTPExceptions.php
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Throwable exceptions to return HTTP status code
|
||||||
|
*
|
||||||
|
* This list of Exception has be extracted from
|
||||||
|
* here http://racksburg.com/choosing-an-http-status-code/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class HTTPException extends Exception {
|
||||||
|
var $httpcode = 200;
|
||||||
|
var $httpdesc = "";
|
||||||
|
public function __construct($message="", $code = 0, Exception $previous = null) {
|
||||||
|
if ($this->httpdesc=="") {
|
||||||
|
$this->httpdesc = preg_replace("|([a-z])([A-Z])|",'$1 $2', str_replace("Exception","",get_class($this)));
|
||||||
|
}
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4xx
|
||||||
|
class TooManyRequestsException extends HTTPException {
|
||||||
|
var $httpcode = 429;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnauthorizedException extends HTTPException {
|
||||||
|
var $httpcode = 401;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ForbiddenException extends HTTPException {
|
||||||
|
var $httpcode = 403;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotFoundException extends HTTPException {
|
||||||
|
var $httpcode = 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GoneException extends HTTPException {
|
||||||
|
var $httpcode = 410;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MethodNotAllowedException extends HTTPException {
|
||||||
|
var $httpcode = 405;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NonAcceptableException extends HTTPException {
|
||||||
|
var $httpcode = 406;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LenghtRequiredException extends HTTPException {
|
||||||
|
var $httpcode = 411;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PreconditionFailedException extends HTTPException {
|
||||||
|
var $httpcode = 412;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnsupportedMediaTypeException extends HTTPException {
|
||||||
|
var $httpcode = 415;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpetationFailesException extends HTTPException {
|
||||||
|
var $httpcode = 417;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConflictException extends HTTPException {
|
||||||
|
var $httpcode = 409;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnprocessableEntityException extends HTTPException {
|
||||||
|
var $httpcode = 422;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImATeapotException extends HTTPException {
|
||||||
|
var $httpcode = 418;
|
||||||
|
var $httpdesc = "I'm A Teapot";
|
||||||
|
}
|
||||||
|
|
||||||
|
class BadRequestException extends HTTPException {
|
||||||
|
var $httpcode = 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5xx
|
||||||
|
|
||||||
|
class ServiceUnavaiableException extends HTTPException {
|
||||||
|
var $httpcode = 503;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BadGatewayException extends HTTPException {
|
||||||
|
var $httpcode = 502;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GatewayTimeoutException extends HTTPException {
|
||||||
|
var $httpcode = 504;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotImplementedException extends HTTPException {
|
||||||
|
var $httpcode = 501;
|
||||||
|
}
|
||||||
|
|
||||||
|
class InternalServerErrorException extends HTTPException {
|
||||||
|
var $httpcode = 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
561
include/api.php
561
include/api.php
|
|
@ -1,66 +1,65 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @file include/api.php
|
* @file include/api.php
|
||||||
|
* Friendica implementation of statusnet/twitter API
|
||||||
*
|
*
|
||||||
* @todo Automatically detect if incoming data is HTML or BBCode
|
* @todo Automatically detect if incoming data is HTML or BBCode
|
||||||
*/
|
*/
|
||||||
|
require_once('include/HTTPExceptions.php');
|
||||||
|
|
||||||
/* Contact details:
|
require_once('include/bbcode.php');
|
||||||
Gerhard Seeber Mail: gerhard@seeber.at Friendica: http://mozartweg.dyndns.org/friendica/gerhard
|
require_once('include/datetime.php');
|
||||||
|
require_once('include/conversation.php');
|
||||||
*/
|
require_once('include/oauth.php');
|
||||||
|
require_once('include/html2plain.php');
|
||||||
|
require_once('mod/share.php');
|
||||||
/*
|
require_once('include/Photo.php');
|
||||||
* Change history:
|
require_once('mod/item.php');
|
||||||
Gerhard Seeber 2015-NOV-25 Add API call /friendica/group_show to return all or a single group
|
|
||||||
with the containing contacts (necessary for Windows 10 Universal app)
|
|
||||||
Gerhard Seeber 2015-NOV-27 Add API call /friendica/group_delete to delete the specified group id
|
|
||||||
(necessary for Windows 10 Universal app)
|
|
||||||
Gerhard Seeber 2015-DEC-01 Add API call /friendica/group_create to create a group with the specified
|
|
||||||
name and the given list of contacts (necessary for Windows 10 Universal
|
|
||||||
app)
|
|
||||||
Gerhard Seeber 2015-DEC-07 Add API call /friendica/group_update to update a group with the given
|
|
||||||
list of contacts (necessary for Windows 10 Universal app)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once("include/bbcode.php");
|
|
||||||
require_once("include/datetime.php");
|
|
||||||
require_once("include/conversation.php");
|
|
||||||
require_once("include/oauth.php");
|
|
||||||
require_once("include/html2plain.php");
|
|
||||||
require_once("mod/share.php");
|
|
||||||
require_once("include/Photo.php");
|
|
||||||
require_once("mod/item.php");
|
|
||||||
require_once('include/security.php');
|
require_once('include/security.php');
|
||||||
require_once('include/contact_selectors.php');
|
require_once('include/contact_selectors.php');
|
||||||
require_once('include/html2bbcode.php');
|
require_once('include/html2bbcode.php');
|
||||||
require_once('mod/wall_upload.php');
|
require_once('mod/wall_upload.php');
|
||||||
require_once("mod/proxy.php");
|
require_once('mod/proxy.php');
|
||||||
require_once("include/message.php");
|
require_once('include/message.php');
|
||||||
require_once("include/group.php");
|
require_once('include/group.php');
|
||||||
|
require_once('include/like.php');
|
||||||
|
|
||||||
|
|
||||||
|
define('API_METHOD_ANY','*');
|
||||||
|
define('API_METHOD_GET','GET');
|
||||||
|
define('API_METHOD_POST','POST,PUT');
|
||||||
|
define('API_METHOD_DELETE','POST,DELETE');
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Twitter-Like API
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
$API = Array();
|
$API = Array();
|
||||||
$called_api = Null;
|
$called_api = Null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Auth API user
|
||||||
|
*
|
||||||
|
* It is not sufficient to use local_user() to check whether someone is allowed to use the API,
|
||||||
|
* because this will open CSRF holes (just embed an image with src=friendicasite.com/api/statuses/update?status=CSRF
|
||||||
|
* into a page, and visitors will post something without noticing it).
|
||||||
|
*/
|
||||||
function api_user() {
|
function api_user() {
|
||||||
// It is not sufficient to use local_user() to check whether someone is allowed to use the API,
|
if ($_SESSION['allow_api'])
|
||||||
// because this will open CSRF holes (just embed an image with src=friendicasite.com/api/statuses/update?status=CSRF
|
|
||||||
// into a page, and visitors will post something without noticing it).
|
|
||||||
// Instead, use this function.
|
|
||||||
if ($_SESSION["allow_api"])
|
|
||||||
return local_user();
|
return local_user();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get source name from API client
|
||||||
|
*
|
||||||
|
* Clients can send 'source' parameter to be show in post metadata
|
||||||
|
* as "sent via <source>".
|
||||||
|
* Some clients doesn't send a source param, we support ones we know
|
||||||
|
* (only Twidere, atm)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* Client source name, default to "api" if unset/unknown
|
||||||
|
*/
|
||||||
function api_source() {
|
function api_source() {
|
||||||
if (requestdata('source'))
|
if (requestdata('source'))
|
||||||
return (requestdata('source'));
|
return (requestdata('source'));
|
||||||
|
|
@ -74,25 +73,63 @@
|
||||||
return ("api");
|
return ("api");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Format date for API
|
||||||
|
*
|
||||||
|
* @param string $str Source date, as UTC
|
||||||
|
* @return string Date in UTC formatted as "D M d H:i:s +0000 Y"
|
||||||
|
*/
|
||||||
function api_date($str){
|
function api_date($str){
|
||||||
//Wed May 23 06:01:13 +0000 2007
|
//Wed May 23 06:01:13 +0000 2007
|
||||||
return datetime_convert('UTC', 'UTC', $str, "D M d H:i:s +0000 Y" );
|
return datetime_convert('UTC', 'UTC', $str, "D M d H:i:s +0000 Y" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
function api_register_func($path, $func, $auth=false){
|
* @brief Register API endpoint
|
||||||
|
*
|
||||||
|
* Register a function to be the endpont for defined API path.
|
||||||
|
*
|
||||||
|
* @param string $path API URL path, relative to $a->get_baseurl()
|
||||||
|
* @param string $func Function name to call on path request
|
||||||
|
* @param bool $auth API need logged user
|
||||||
|
* @param string $method
|
||||||
|
* HTTP method reqiured to call this endpoint.
|
||||||
|
* One of API_METHOD_ANY, API_METHOD_GET, API_METHOD_POST.
|
||||||
|
* Default to API_METHOD_ANY
|
||||||
|
*/
|
||||||
|
function api_register_func($path, $func, $auth=false, $method=API_METHOD_ANY){
|
||||||
global $API;
|
global $API;
|
||||||
$API[$path] = array('func'=>$func, 'auth'=>$auth);
|
$API[$path] = array(
|
||||||
|
'func'=>$func,
|
||||||
|
'auth'=>$auth,
|
||||||
|
'method'=> $method
|
||||||
|
);
|
||||||
|
|
||||||
// Workaround for hotot
|
// Workaround for hotot
|
||||||
$path = str_replace("api/", "api/1.1/", $path);
|
$path = str_replace("api/", "api/1.1/", $path);
|
||||||
$API[$path] = array('func'=>$func, 'auth'=>$auth);
|
$API[$path] = array(
|
||||||
|
'func'=>$func,
|
||||||
|
'auth'=>$auth,
|
||||||
|
'method'=> $method
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple HTTP Login
|
* @brief Login API user
|
||||||
|
*
|
||||||
|
* Log in user via OAuth1 or Simple HTTP Auth.
|
||||||
|
* Simple Auth allow username in form of <pre>user@server</pre>, ignoring server part
|
||||||
|
*
|
||||||
|
* @param App $a
|
||||||
|
* @hook 'authenticate'
|
||||||
|
* array $addon_auth
|
||||||
|
* 'username' => username from login form
|
||||||
|
* 'password' => password from login form
|
||||||
|
* 'authenticated' => return status,
|
||||||
|
* 'user_record' => return authenticated user record
|
||||||
|
* @hook 'logged_in'
|
||||||
|
* array $user logged user record
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function api_login(&$a){
|
function api_login(&$a){
|
||||||
// login with oauth
|
// login with oauth
|
||||||
try{
|
try{
|
||||||
|
|
@ -105,8 +142,7 @@
|
||||||
}
|
}
|
||||||
echo __file__.__line__.__function__."<pre>"; var_dump($consumer, $token); die();
|
echo __file__.__line__.__function__."<pre>"; var_dump($consumer, $token); die();
|
||||||
}catch(Exception $e){
|
}catch(Exception $e){
|
||||||
logger(__file__.__line__.__function__."\n".$e);
|
logger($e);
|
||||||
//die(__file__.__line__.__function__."<pre>".$e); die();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -189,16 +225,45 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************
|
/**
|
||||||
* MAIN API ENTRY POINT *
|
* @brief Check HTTP method of called API
|
||||||
**************************/
|
*
|
||||||
|
* API endpoints can define which HTTP method to accept when called.
|
||||||
|
* This function check the current HTTP method agains endpoint
|
||||||
|
* registered method.
|
||||||
|
*
|
||||||
|
* @param string $method Required methods, uppercase, separated by comma
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function api_check_method($method) {
|
||||||
|
if ($method=="*") return True;
|
||||||
|
return strpos($method, $_SERVER['REQUEST_METHOD']) !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main API entry point
|
||||||
|
*
|
||||||
|
* Authenticate user, call registered API function, set HTTP headers
|
||||||
|
*
|
||||||
|
* @param App $a
|
||||||
|
* @return string API call result
|
||||||
|
*/
|
||||||
function api_call(&$a){
|
function api_call(&$a){
|
||||||
GLOBAL $API, $called_api;
|
GLOBAL $API, $called_api;
|
||||||
|
|
||||||
// preset
|
|
||||||
$type="json";
|
$type="json";
|
||||||
|
if (strpos($a->query_string, ".xml")>0) $type="xml";
|
||||||
|
if (strpos($a->query_string, ".json")>0) $type="json";
|
||||||
|
if (strpos($a->query_string, ".rss")>0) $type="rss";
|
||||||
|
if (strpos($a->query_string, ".atom")>0) $type="atom";
|
||||||
|
if (strpos($a->query_string, ".as")>0) $type="as";
|
||||||
|
try {
|
||||||
foreach ($API as $p=>$info){
|
foreach ($API as $p=>$info){
|
||||||
if (strpos($a->query_string, $p)===0){
|
if (strpos($a->query_string, $p)===0){
|
||||||
|
if (!api_check_method($info['method'])){
|
||||||
|
throw new MethodNotAllowedException();
|
||||||
|
}
|
||||||
|
|
||||||
$called_api= explode("/",$p);
|
$called_api= explode("/",$p);
|
||||||
//unset($_SERVER['PHP_AUTH_USER']);
|
//unset($_SERVER['PHP_AUTH_USER']);
|
||||||
if ($info['auth']===true && api_user()===false) {
|
if ($info['auth']===true && api_user()===false) {
|
||||||
|
|
@ -209,19 +274,17 @@
|
||||||
|
|
||||||
logger('API call for ' . $a->user['username'] . ': ' . $a->query_string);
|
logger('API call for ' . $a->user['username'] . ': ' . $a->query_string);
|
||||||
logger('API parameters: ' . print_r($_REQUEST,true));
|
logger('API parameters: ' . print_r($_REQUEST,true));
|
||||||
$type="json";
|
|
||||||
if (strpos($a->query_string, ".xml")>0) $type="xml";
|
|
||||||
if (strpos($a->query_string, ".json")>0) $type="json";
|
|
||||||
if (strpos($a->query_string, ".rss")>0) $type="rss";
|
|
||||||
if (strpos($a->query_string, ".atom")>0) $type="atom";
|
|
||||||
if (strpos($a->query_string, ".as")>0) $type="as";
|
|
||||||
|
|
||||||
$stamp = microtime(true);
|
$stamp = microtime(true);
|
||||||
$r = call_user_func($info['func'], $a, $type);
|
$r = call_user_func($info['func'], $a, $type);
|
||||||
$duration = (float)(microtime(true)-$stamp);
|
$duration = (float)(microtime(true)-$stamp);
|
||||||
logger("API call duration: ".round($duration, 2)."\t".$a->query_string, LOGGER_DEBUG);
|
logger("API call duration: ".round($duration, 2)."\t".$a->query_string, LOGGER_DEBUG);
|
||||||
|
|
||||||
if ($r===false) return;
|
if ($r===false) {
|
||||||
|
// api function returned false withour throw an
|
||||||
|
// exception. This should not happend, throw a 500
|
||||||
|
throw new InternalServerErrorException();
|
||||||
|
}
|
||||||
|
|
||||||
switch($type){
|
switch($type){
|
||||||
case "xml":
|
case "xml":
|
||||||
|
|
@ -253,40 +316,57 @@
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
//echo "<pre>"; var_dump($r); die();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
header("HTTP/1.1 404 Not Found");
|
throw new NotImplementedException();
|
||||||
logger('API call not implemented: '.$a->query_string." - ".print_r($_REQUEST,true));
|
} catch (HTTPException $e) {
|
||||||
return(api_error($a, $type, "not implemented"));
|
header("HTTP/1.1 {$e->httpcode} {$e->httpdesc}");
|
||||||
|
return api_error($a, $type, $e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function api_error(&$a, $type, $error) {
|
/**
|
||||||
/// @TODO https://dev.twitter.com/overview/api/response-codes
|
* @brief Format API error string
|
||||||
$r = "<status><error>".$error."</error><request>".$a->query_string."</request></status>";
|
*
|
||||||
|
* @param Api $a
|
||||||
|
* @param string $type Return type (xml, json, rss, as)
|
||||||
|
* @param string $error Error message
|
||||||
|
*/
|
||||||
|
function api_error(&$a, $type, $e) {
|
||||||
|
$error = ($e->getMessage()!==""?$e->getMessage():$e->httpdesc);
|
||||||
|
# TODO: https://dev.twitter.com/overview/api/response-codes
|
||||||
|
$xmlstr = "<status><error>{$error}</error><code>{$e->httpcode} {$e->httpdesc}</code><request>{$a->query_string}</request></status>";
|
||||||
switch($type){
|
switch($type){
|
||||||
case "xml":
|
case "xml":
|
||||||
header ("Content-Type: text/xml");
|
header ("Content-Type: text/xml");
|
||||||
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
|
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$xmlstr;
|
||||||
break;
|
break;
|
||||||
case "json":
|
case "json":
|
||||||
header ("Content-Type: application/json");
|
header ("Content-Type: application/json");
|
||||||
return json_encode(array('error' => $error, 'request' => $a->query_string));
|
return json_encode(array(
|
||||||
|
'error' => $error,
|
||||||
|
'request' => $a->query_string,
|
||||||
|
'code' => $e->httpcode." ".$e->httpdesc
|
||||||
|
));
|
||||||
break;
|
break;
|
||||||
case "rss":
|
case "rss":
|
||||||
header ("Content-Type: application/rss+xml");
|
header ("Content-Type: application/rss+xml");
|
||||||
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
|
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$xmlstr;
|
||||||
break;
|
break;
|
||||||
case "atom":
|
case "atom":
|
||||||
header ("Content-Type: application/atom+xml");
|
header ("Content-Type: application/atom+xml");
|
||||||
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
|
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$xmlstr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RSS extra info
|
* @brief Set values for RSS template
|
||||||
|
*
|
||||||
|
* @param App $a
|
||||||
|
* @param array $arr Array to be passed to template
|
||||||
|
* @param array $user_info
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
function api_rss_extra(&$a, $arr, $user_info){
|
function api_rss_extra(&$a, $arr, $user_info){
|
||||||
if (is_null($user_info)) $user_info = api_get_user($a);
|
if (is_null($user_info)) $user_info = api_get_user($a);
|
||||||
|
|
@ -306,7 +386,11 @@
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique contact to contact url.
|
* @brief Unique contact to contact url.
|
||||||
|
*
|
||||||
|
* @param int $id Contact id
|
||||||
|
* @return bool|string
|
||||||
|
* Contact url or False if contact id is unknown
|
||||||
*/
|
*/
|
||||||
function api_unique_id_to_url($id){
|
function api_unique_id_to_url($id){
|
||||||
$r = q("SELECT `url` FROM `unique_contacts` WHERE `id`=%d LIMIT 1",
|
$r = q("SELECT `url` FROM `unique_contacts` WHERE `id`=%d LIMIT 1",
|
||||||
|
|
@ -318,7 +402,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns user info array.
|
* @brief Get user info array.
|
||||||
|
*
|
||||||
|
* @param Api $a
|
||||||
|
* @param int|string $contact_id Contact ID or URL
|
||||||
|
* @param string $type Return type (for errors)
|
||||||
*/
|
*/
|
||||||
function api_get_user(&$a, $contact_id = Null, $type = "json"){
|
function api_get_user(&$a, $contact_id = Null, $type = "json"){
|
||||||
global $called_api;
|
global $called_api;
|
||||||
|
|
@ -342,7 +430,7 @@
|
||||||
$user = dbesc(api_unique_id_to_url($contact_id));
|
$user = dbesc(api_unique_id_to_url($contact_id));
|
||||||
|
|
||||||
if ($user == "")
|
if ($user == "")
|
||||||
die(api_error($a, $type, t("User not found.")));
|
throw new BadRequestException("User not found.");
|
||||||
|
|
||||||
$url = $user;
|
$url = $user;
|
||||||
$extra_query = "AND `contact`.`nurl` = '%s' ";
|
$extra_query = "AND `contact`.`nurl` = '%s' ";
|
||||||
|
|
@ -353,7 +441,7 @@
|
||||||
$user = dbesc(api_unique_id_to_url($_GET['user_id']));
|
$user = dbesc(api_unique_id_to_url($_GET['user_id']));
|
||||||
|
|
||||||
if ($user == "")
|
if ($user == "")
|
||||||
die(api_error($a, $type, t("User not found.")));
|
throw new BadRequestException("User not found.");
|
||||||
|
|
||||||
$url = $user;
|
$url = $user;
|
||||||
$extra_query = "AND `contact`.`nurl` = '%s' ";
|
$extra_query = "AND `contact`.`nurl` = '%s' ";
|
||||||
|
|
@ -390,7 +478,8 @@
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
if (api_user()===false) {
|
if (api_user()===false) {
|
||||||
api_login($a); return False;
|
api_login($a);
|
||||||
|
return False;
|
||||||
} else {
|
} else {
|
||||||
$user = $_SESSION['uid'];
|
$user = $_SESSION['uid'];
|
||||||
$extra_query = "AND `contact`.`uid` = %d AND `contact`.`self` = 1 ";
|
$extra_query = "AND `contact`.`uid` = %d AND `contact`.`self` = 1 ";
|
||||||
|
|
@ -461,9 +550,9 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
} else
|
} else {
|
||||||
die(api_error($a, $type, t("User not found.")));
|
throw new BadRequestException("User not found.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($uinfo[0]['self']) {
|
if($uinfo[0]['self']) {
|
||||||
|
|
@ -672,7 +761,7 @@
|
||||||
* http://developer.twitter.com/doc/get/account/verify_credentials
|
* http://developer.twitter.com/doc/get/account/verify_credentials
|
||||||
*/
|
*/
|
||||||
function api_account_verify_credentials(&$a, $type){
|
function api_account_verify_credentials(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
unset($_REQUEST["user_id"]);
|
unset($_REQUEST["user_id"]);
|
||||||
unset($_GET["user_id"]);
|
unset($_GET["user_id"]);
|
||||||
|
|
@ -723,7 +812,7 @@
|
||||||
function api_statuses_mediap(&$a, $type) {
|
function api_statuses_mediap(&$a, $type) {
|
||||||
if (api_user()===false) {
|
if (api_user()===false) {
|
||||||
logger('api_statuses_update: no user');
|
logger('api_statuses_update: no user');
|
||||||
return false;
|
throw new ForbiddenException();
|
||||||
}
|
}
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
||||||
|
|
@ -757,14 +846,14 @@
|
||||||
// this should output the last post (the one we just posted).
|
// this should output the last post (the one we just posted).
|
||||||
return api_status_show($a,$type);
|
return api_status_show($a,$type);
|
||||||
}
|
}
|
||||||
api_register_func('api/statuses/mediap','api_statuses_mediap', true);
|
api_register_func('api/statuses/mediap','api_statuses_mediap', true, API_METHOD_POST);
|
||||||
/*Waitman Gobble Mod*/
|
/*Waitman Gobble Mod*/
|
||||||
|
|
||||||
|
|
||||||
function api_statuses_update(&$a, $type) {
|
function api_statuses_update(&$a, $type) {
|
||||||
if (api_user()===false) {
|
if (api_user()===false) {
|
||||||
logger('api_statuses_update: no user');
|
logger('api_statuses_update: no user');
|
||||||
return false;
|
throw new ForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
@ -882,7 +971,7 @@
|
||||||
$_REQUEST['body'] .= "\n\n".$media;
|
$_REQUEST['body'] .= "\n\n".$media;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @TODO Multiple IDs
|
// To-Do: Multiple IDs
|
||||||
if (requestdata('media_ids')) {
|
if (requestdata('media_ids')) {
|
||||||
$r = q("SELECT `resource-id`, `scale`, `nickname`, `type` FROM `photo` INNER JOIN `user` ON `user`.`uid` = `photo`.`uid` WHERE `resource-id` IN (SELECT `resource-id` FROM `photo` WHERE `id` = %d) AND `scale` > 0 AND `photo`.`uid` = %d ORDER BY `photo`.`width` DESC LIMIT 1",
|
$r = q("SELECT `resource-id`, `scale`, `nickname`, `type` FROM `photo` INNER JOIN `user` ON `user`.`uid` = `photo`.`uid` WHERE `resource-id` IN (SELECT `resource-id` FROM `photo` WHERE `id` = %d) AND `scale` > 0 AND `photo`.`uid` = %d ORDER BY `photo`.`width` DESC LIMIT 1",
|
||||||
intval(requestdata('media_ids')), api_user());
|
intval(requestdata('media_ids')), api_user());
|
||||||
|
|
@ -908,27 +997,27 @@
|
||||||
// this should output the last post (the one we just posted).
|
// this should output the last post (the one we just posted).
|
||||||
return api_status_show($a,$type);
|
return api_status_show($a,$type);
|
||||||
}
|
}
|
||||||
api_register_func('api/statuses/update','api_statuses_update', true);
|
api_register_func('api/statuses/update','api_statuses_update', true, API_METHOD_POST);
|
||||||
api_register_func('api/statuses/update_with_media','api_statuses_update', true);
|
api_register_func('api/statuses/update_with_media','api_statuses_update', true, API_METHOD_POST);
|
||||||
|
|
||||||
|
|
||||||
function api_media_upload(&$a, $type) {
|
function api_media_upload(&$a, $type) {
|
||||||
if (api_user()===false) {
|
if (api_user()===false) {
|
||||||
logger('no user');
|
logger('no user');
|
||||||
return false;
|
throw new ForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
||||||
if(!x($_FILES,'media')) {
|
if(!x($_FILES,'media')) {
|
||||||
// Output error
|
// Output error
|
||||||
return false;
|
throw new BadRequestException("No media.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$media = wall_upload_post($a, false);
|
$media = wall_upload_post($a, false);
|
||||||
if(!$media) {
|
if(!$media) {
|
||||||
// Output error
|
// Output error
|
||||||
return false;
|
throw new InternalServerErrorException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$returndata = array();
|
$returndata = array();
|
||||||
|
|
@ -943,8 +1032,7 @@
|
||||||
|
|
||||||
return array("media" => $returndata);
|
return array("media" => $returndata);
|
||||||
}
|
}
|
||||||
|
api_register_func('api/media/upload','api_media_upload', true, API_METHOD_POST);
|
||||||
api_register_func('api/media/upload','api_media_upload', true);
|
|
||||||
|
|
||||||
function api_status_show(&$a, $type){
|
function api_status_show(&$a, $type){
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
@ -1180,11 +1268,12 @@
|
||||||
$userlist[] = $userdata["user"];
|
$userlist[] = $userdata["user"];
|
||||||
}
|
}
|
||||||
$userlist = array("users" => $userlist);
|
$userlist = array("users" => $userlist);
|
||||||
} else
|
} else {
|
||||||
die(api_error($a, $type, t("User not found.")));
|
throw new BadRequestException("User not found.");
|
||||||
} else
|
}
|
||||||
die(api_error($a, $type, t("User not found.")));
|
} else {
|
||||||
|
throw new BadRequestException("User not found.");
|
||||||
|
}
|
||||||
return ($userlist);
|
return ($userlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1194,11 +1283,11 @@
|
||||||
*
|
*
|
||||||
* http://developer.twitter.com/doc/get/statuses/home_timeline
|
* http://developer.twitter.com/doc/get/statuses/home_timeline
|
||||||
*
|
*
|
||||||
* @TODO Optional parameters
|
* TODO: Optional parameters
|
||||||
* @TODO Add reply info
|
* TODO: Add reply info
|
||||||
*/
|
*/
|
||||||
function api_statuses_home_timeline(&$a, $type){
|
function api_statuses_home_timeline(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
unset($_REQUEST["user_id"]);
|
unset($_REQUEST["user_id"]);
|
||||||
unset($_GET["user_id"]);
|
unset($_GET["user_id"]);
|
||||||
|
|
@ -1281,7 +1370,7 @@
|
||||||
api_register_func('api/statuses/friends_timeline','api_statuses_home_timeline', true);
|
api_register_func('api/statuses/friends_timeline','api_statuses_home_timeline', true);
|
||||||
|
|
||||||
function api_statuses_public_timeline(&$a, $type){
|
function api_statuses_public_timeline(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
// get last newtork messages
|
// get last newtork messages
|
||||||
|
|
@ -1351,7 +1440,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function api_statuses_show(&$a, $type){
|
function api_statuses_show(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
||||||
|
|
@ -1389,8 +1478,9 @@
|
||||||
intval($id)
|
intval($id)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!$r)
|
if (!$r) {
|
||||||
die(api_error($a, $type, t("There is no status with this id.")));
|
throw new BadRequestException("There is no status with this id.");
|
||||||
|
}
|
||||||
|
|
||||||
$ret = api_format_items($r,$user_info);
|
$ret = api_format_items($r,$user_info);
|
||||||
|
|
||||||
|
|
@ -1414,7 +1504,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function api_conversation_show(&$a, $type){
|
function api_conversation_show(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
||||||
|
|
@ -1464,7 +1554,7 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!$r)
|
if (!$r)
|
||||||
die(api_error($a, $type, t("There is no conversation with this id.")));
|
throw new BadRequestException("There is no conversation with this id.");
|
||||||
|
|
||||||
$ret = api_format_items($r,$user_info);
|
$ret = api_format_items($r,$user_info);
|
||||||
|
|
||||||
|
|
@ -1480,7 +1570,7 @@
|
||||||
function api_statuses_repeat(&$a, $type){
|
function api_statuses_repeat(&$a, $type){
|
||||||
global $called_api;
|
global $called_api;
|
||||||
|
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
||||||
|
|
@ -1538,13 +1628,13 @@
|
||||||
$called_api = null;
|
$called_api = null;
|
||||||
return(api_status_show($a,$type));
|
return(api_status_show($a,$type));
|
||||||
}
|
}
|
||||||
api_register_func('api/statuses/retweet','api_statuses_repeat', true);
|
api_register_func('api/statuses/retweet','api_statuses_repeat', true, API_METHOD_POST);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function api_statuses_destroy(&$a, $type){
|
function api_statuses_destroy(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
||||||
|
|
@ -1566,7 +1656,7 @@
|
||||||
|
|
||||||
return($ret);
|
return($ret);
|
||||||
}
|
}
|
||||||
api_register_func('api/statuses/destroy','api_statuses_destroy', true);
|
api_register_func('api/statuses/destroy','api_statuses_destroy', true, API_METHOD_DELETE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1574,7 +1664,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function api_statuses_mentions(&$a, $type){
|
function api_statuses_mentions(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
unset($_REQUEST["user_id"]);
|
unset($_REQUEST["user_id"]);
|
||||||
unset($_GET["user_id"]);
|
unset($_GET["user_id"]);
|
||||||
|
|
@ -1653,7 +1743,7 @@
|
||||||
|
|
||||||
|
|
||||||
function api_statuses_user_timeline(&$a, $type){
|
function api_statuses_user_timeline(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
// get last network messages
|
// get last network messages
|
||||||
|
|
@ -1714,7 +1804,6 @@
|
||||||
|
|
||||||
return api_apply_template("timeline", $type, $data);
|
return api_apply_template("timeline", $type, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_register_func('api/statuses/user_timeline','api_statuses_user_timeline', true);
|
api_register_func('api/statuses/user_timeline','api_statuses_user_timeline', true);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1725,7 +1814,7 @@
|
||||||
* api v1 : https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
|
* api v1 : https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
|
||||||
*/
|
*/
|
||||||
function api_favorites_create_destroy(&$a, $type){
|
function api_favorites_create_destroy(&$a, $type){
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
// for versioned api.
|
// for versioned api.
|
||||||
/// @TODO We need a better global soluton
|
/// @TODO We need a better global soluton
|
||||||
|
|
@ -1743,7 +1832,8 @@
|
||||||
$item = q("SELECT * FROM item WHERE id=%d AND uid=%d",
|
$item = q("SELECT * FROM item WHERE id=%d AND uid=%d",
|
||||||
$itemid, api_user());
|
$itemid, api_user());
|
||||||
|
|
||||||
if ($item===false || count($item)==0) die(api_error($a, $type, t("Invalid item.")));
|
if ($item===false || count($item)==0)
|
||||||
|
throw new BadRequestException("Invalid item.");
|
||||||
|
|
||||||
switch($action){
|
switch($action){
|
||||||
case "create":
|
case "create":
|
||||||
|
|
@ -1753,7 +1843,7 @@
|
||||||
$item[0]['starred']=0;
|
$item[0]['starred']=0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
die(api_error($a, $type, t("Invalid action. ".$action)));
|
throw new BadRequestException("Invalid action ".$action);
|
||||||
}
|
}
|
||||||
$r = q("UPDATE item SET starred=%d WHERE id=%d AND uid=%d",
|
$r = q("UPDATE item SET starred=%d WHERE id=%d AND uid=%d",
|
||||||
$item[0]['starred'], $itemid, api_user());
|
$item[0]['starred'], $itemid, api_user());
|
||||||
|
|
@ -1761,7 +1851,8 @@
|
||||||
q("UPDATE thread SET starred=%d WHERE iid=%d AND uid=%d",
|
q("UPDATE thread SET starred=%d WHERE iid=%d AND uid=%d",
|
||||||
$item[0]['starred'], $itemid, api_user());
|
$item[0]['starred'], $itemid, api_user());
|
||||||
|
|
||||||
if ($r===false) die(api_error($a, $type, t("DB error")));
|
if ($r===false)
|
||||||
|
throw InternalServerErrorException("DB error");
|
||||||
|
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
@ -1777,14 +1868,13 @@
|
||||||
|
|
||||||
return api_apply_template("status", $type, $data);
|
return api_apply_template("status", $type, $data);
|
||||||
}
|
}
|
||||||
|
api_register_func('api/favorites/create', 'api_favorites_create_destroy', true, API_METHOD_POST);
|
||||||
api_register_func('api/favorites/create', 'api_favorites_create_destroy', true);
|
api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true, API_METHOD_DELETE);
|
||||||
api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true);
|
|
||||||
|
|
||||||
function api_favorites(&$a, $type){
|
function api_favorites(&$a, $type){
|
||||||
global $called_api;
|
global $called_api;
|
||||||
|
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
$called_api= array();
|
$called_api= array();
|
||||||
|
|
||||||
|
|
@ -1842,14 +1932,12 @@
|
||||||
|
|
||||||
return api_apply_template("timeline", $type, $data);
|
return api_apply_template("timeline", $type, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_register_func('api/favorites','api_favorites', true);
|
api_register_func('api/favorites','api_favorites', true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function api_format_as($a, $ret, $user_info) {
|
function api_format_as($a, $ret, $user_info) {
|
||||||
|
|
||||||
$as = array();
|
$as = array();
|
||||||
$as['title'] = $a->config['sitename']." Public Timeline";
|
$as['title'] = $a->config['sitename']." Public Timeline";
|
||||||
$items = array();
|
$items = array();
|
||||||
|
|
@ -2015,8 +2103,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function api_get_entitities(&$text, $bbcode) {
|
function api_get_entitities(&$text, $bbcode) {
|
||||||
/// @todo
|
/*
|
||||||
/// Links at the first character of the post
|
To-Do:
|
||||||
|
* Links at the first character of the post
|
||||||
|
*/
|
||||||
|
|
||||||
$a = get_app();
|
$a = get_app();
|
||||||
|
|
||||||
|
|
@ -2166,7 +2256,7 @@
|
||||||
|
|
||||||
return($entities);
|
return($entities);
|
||||||
}
|
}
|
||||||
function api_format_items_embeded_images($item, $text){
|
function api_format_items_embeded_images(&$item, $text){
|
||||||
$a = get_app();
|
$a = get_app();
|
||||||
$text = preg_replace_callback(
|
$text = preg_replace_callback(
|
||||||
"|data:image/([^;]+)[^=]+=*|m",
|
"|data:image/([^;]+)[^=]+=*|m",
|
||||||
|
|
@ -2177,7 +2267,42 @@
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function api_format_items($r,$user_info, $filter_user = false) {
|
/**
|
||||||
|
* @brief return likes, dislikes and attend status for item
|
||||||
|
*
|
||||||
|
* @param array $item
|
||||||
|
* @return array
|
||||||
|
* likes => int count
|
||||||
|
* dislikes => int count
|
||||||
|
*/
|
||||||
|
function api_format_items_likes(&$item) {
|
||||||
|
$activities = array(
|
||||||
|
ACTIVITY_LIKE => 'like',
|
||||||
|
ACTIVITY_DISLIKE => 'dislike',
|
||||||
|
ACTIVITY_ATTEND => 'attendyes',
|
||||||
|
ACTIVITY_ATTENDNO => 'attendno',
|
||||||
|
ACTIVITY_ATTENDMAYBE => 'attendmaybe'
|
||||||
|
);
|
||||||
|
$r = q("SELECT verb, count(verb) as n FROM item WHERE parent=%d GROUP BY verb",
|
||||||
|
intval($item['id']));
|
||||||
|
|
||||||
|
$res = array();
|
||||||
|
foreach($r as $row) {
|
||||||
|
if (x($activities, $row['verb'])) {
|
||||||
|
$res[$activities[$row['verb']]] = $row['n'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief format items to be returned by api
|
||||||
|
*
|
||||||
|
* @param array $r array of items
|
||||||
|
* @param array $user_info
|
||||||
|
* @param bool $filter_user filter items by $user_info
|
||||||
|
*/
|
||||||
|
function api_format_items(&$r,$user_info, $filter_user = false) {
|
||||||
|
|
||||||
$a = get_app();
|
$a = get_app();
|
||||||
$ret = Array();
|
$ret = Array();
|
||||||
|
|
@ -2250,6 +2375,7 @@
|
||||||
//'entities' => NULL,
|
//'entities' => NULL,
|
||||||
'statusnet_html' => $converted["html"],
|
'statusnet_html' => $converted["html"],
|
||||||
'statusnet_conversation_id' => $item['parent'],
|
'statusnet_conversation_id' => $item['parent'],
|
||||||
|
'friendica_activities' => api_format_items_likes($item),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (count($converted["attachments"]) > 0)
|
if (count($converted["attachments"]) > 0)
|
||||||
|
|
@ -2297,7 +2423,6 @@
|
||||||
|
|
||||||
|
|
||||||
function api_account_rate_limit_status(&$a,$type) {
|
function api_account_rate_limit_status(&$a,$type) {
|
||||||
|
|
||||||
$hash = array(
|
$hash = array(
|
||||||
'reset_time_in_seconds' => strtotime('now + 1 hour'),
|
'reset_time_in_seconds' => strtotime('now + 1 hour'),
|
||||||
'remaining_hits' => (string) 150,
|
'remaining_hits' => (string) 150,
|
||||||
|
|
@ -2308,31 +2433,26 @@
|
||||||
$hash['resettime_in_seconds'] = $hash['reset_time_in_seconds'];
|
$hash['resettime_in_seconds'] = $hash['reset_time_in_seconds'];
|
||||||
|
|
||||||
return api_apply_template('ratelimit', $type, array('$hash' => $hash));
|
return api_apply_template('ratelimit', $type, array('$hash' => $hash));
|
||||||
|
|
||||||
}
|
}
|
||||||
api_register_func('api/account/rate_limit_status','api_account_rate_limit_status',true);
|
api_register_func('api/account/rate_limit_status','api_account_rate_limit_status',true);
|
||||||
|
|
||||||
function api_help_test(&$a,$type) {
|
function api_help_test(&$a,$type) {
|
||||||
|
|
||||||
if ($type == 'xml')
|
if ($type == 'xml')
|
||||||
$ok = "true";
|
$ok = "true";
|
||||||
else
|
else
|
||||||
$ok = "ok";
|
$ok = "ok";
|
||||||
|
|
||||||
return api_apply_template('test', $type, array("$ok" => $ok));
|
return api_apply_template('test', $type, array("$ok" => $ok));
|
||||||
|
|
||||||
}
|
}
|
||||||
api_register_func('api/help/test','api_help_test',false);
|
api_register_func('api/help/test','api_help_test',false);
|
||||||
|
|
||||||
function api_lists(&$a,$type) {
|
function api_lists(&$a,$type) {
|
||||||
|
|
||||||
$ret = array();
|
$ret = array();
|
||||||
return array($ret);
|
return array($ret);
|
||||||
}
|
}
|
||||||
api_register_func('api/lists','api_lists',true);
|
api_register_func('api/lists','api_lists',true);
|
||||||
|
|
||||||
function api_lists_list(&$a,$type) {
|
function api_lists_list(&$a,$type) {
|
||||||
|
|
||||||
$ret = array();
|
$ret = array();
|
||||||
return array($ret);
|
return array($ret);
|
||||||
}
|
}
|
||||||
|
|
@ -2344,7 +2464,7 @@
|
||||||
* returns: json, xml
|
* returns: json, xml
|
||||||
**/
|
**/
|
||||||
function api_statuses_f(&$a, $type, $qtype) {
|
function api_statuses_f(&$a, $type, $qtype) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
||||||
if (x($_GET,'cursor') && $_GET['cursor']=='undefined'){
|
if (x($_GET,'cursor') && $_GET['cursor']=='undefined'){
|
||||||
|
|
@ -2437,26 +2557,27 @@
|
||||||
api_register_func('api/statusnet/config','api_statusnet_config',false);
|
api_register_func('api/statusnet/config','api_statusnet_config',false);
|
||||||
|
|
||||||
function api_statusnet_version(&$a,$type) {
|
function api_statusnet_version(&$a,$type) {
|
||||||
|
|
||||||
// liar
|
// liar
|
||||||
|
$fake_statusnet_version = "0.9.7";
|
||||||
|
|
||||||
if($type === 'xml') {
|
if($type === 'xml') {
|
||||||
header("Content-type: application/xml");
|
header("Content-type: application/xml");
|
||||||
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>0.9.7</version>' . "\r\n";
|
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>'.$fake_statusnet_version.'</version>' . "\r\n";
|
||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
elseif($type === 'json') {
|
elseif($type === 'json') {
|
||||||
header("Content-type: application/json");
|
header("Content-type: application/json");
|
||||||
echo '"0.9.7"';
|
echo '"'.$fake_statusnet_version.'"';
|
||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api_register_func('api/statusnet/version','api_statusnet_version',false);
|
api_register_func('api/statusnet/version','api_statusnet_version',false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo use api_apply_template() to return data
|
||||||
|
*/
|
||||||
function api_ff_ids(&$a,$type,$qtype) {
|
function api_ff_ids(&$a,$type,$qtype) {
|
||||||
if(! api_user())
|
if(! api_user()) throw new ForbiddenException();
|
||||||
return false;
|
|
||||||
|
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
||||||
|
|
@ -2510,7 +2631,7 @@
|
||||||
|
|
||||||
|
|
||||||
function api_direct_messages_new(&$a, $type) {
|
function api_direct_messages_new(&$a, $type) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
if (!x($_POST, "text") OR (!x($_POST,"screen_name") AND !x($_POST,"user_id"))) return;
|
if (!x($_POST, "text") OR (!x($_POST,"screen_name") AND !x($_POST,"user_id"))) return;
|
||||||
|
|
||||||
|
|
@ -2567,11 +2688,10 @@
|
||||||
return api_apply_template("direct_messages", $type, $data);
|
return api_apply_template("direct_messages", $type, $data);
|
||||||
|
|
||||||
}
|
}
|
||||||
api_register_func('api/direct_messages/new','api_direct_messages_new',true);
|
api_register_func('api/direct_messages/new','api_direct_messages_new',true, API_METHOD_POST);
|
||||||
|
|
||||||
function api_direct_messages_box(&$a, $type, $box) {
|
function api_direct_messages_box(&$a, $type, $box) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
|
|
||||||
// params
|
// params
|
||||||
$count = (x($_GET,'count')?$_GET['count']:20);
|
$count = (x($_GET,'count')?$_GET['count']:20);
|
||||||
|
|
@ -2701,36 +2821,75 @@
|
||||||
|
|
||||||
|
|
||||||
function api_fr_photos_list(&$a,$type) {
|
function api_fr_photos_list(&$a,$type) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
$r = q("select distinct `resource-id` from photo where uid = %d and album != 'Contact Photos' ",
|
$r = q("select `resource-id`, max(scale) as scale, album, filename, type from photo
|
||||||
|
where uid = %d and album != 'Contact Photos' group by `resource-id`",
|
||||||
intval(local_user())
|
intval(local_user())
|
||||||
);
|
);
|
||||||
|
$typetoext = array(
|
||||||
|
'image/jpeg' => 'jpg',
|
||||||
|
'image/png' => 'png',
|
||||||
|
'image/gif' => 'gif'
|
||||||
|
);
|
||||||
|
$data = array('photos'=>array());
|
||||||
if($r) {
|
if($r) {
|
||||||
$ret = array();
|
foreach($r as $rr) {
|
||||||
foreach($r as $rr)
|
$photo = array();
|
||||||
$ret[] = $rr['resource-id'];
|
$photo['id'] = $rr['resource-id'];
|
||||||
header("Content-type: application/json");
|
$photo['album'] = $rr['album'];
|
||||||
echo json_encode($ret);
|
$photo['filename'] = $rr['filename'];
|
||||||
|
$photo['type'] = $rr['type'];
|
||||||
|
$photo['thumb'] = $a->get_baseurl()."/photo/".$rr['resource-id']."-".$rr['scale'].".".$typetoext[$rr['type']];
|
||||||
|
$data['photos'][] = $photo;
|
||||||
}
|
}
|
||||||
killme();
|
}
|
||||||
|
return api_apply_template("photos_list", $type, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function api_fr_photo_detail(&$a,$type) {
|
function api_fr_photo_detail(&$a,$type) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
if(! $_REQUEST['photo_id']) return false;
|
if(!x($_REQUEST,'photo_id')) throw new BadRequestException("No photo id.");
|
||||||
$scale = ((array_key_exists('scale',$_REQUEST)) ? intval($_REQUEST['scale']) : 0);
|
|
||||||
$r = q("select * from photo where uid = %d and `resource-id` = '%s' and scale = %d limit 1",
|
$scale = (x($_REQUEST, 'scale') ? intval($_REQUEST['scale']) : false);
|
||||||
|
$scale_sql = ($scale === false ? "" : sprintf("and scale=%d",intval($scale)));
|
||||||
|
$data_sql = ($scale === false ? "" : "data, ");
|
||||||
|
|
||||||
|
$r = q("select %s `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
|
||||||
|
`type`, `height`, `width`, `datasize`, `profile`, min(`scale`) as minscale, max(`scale`) as maxscale
|
||||||
|
from photo where `uid` = %d and `resource-id` = '%s' %s group by `resource-id`",
|
||||||
|
$data_sql,
|
||||||
intval(local_user()),
|
intval(local_user()),
|
||||||
dbesc($_REQUEST['photo_id']),
|
dbesc($_REQUEST['photo_id']),
|
||||||
intval($scale)
|
$scale_sql
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$typetoext = array(
|
||||||
|
'image/jpeg' => 'jpg',
|
||||||
|
'image/png' => 'png',
|
||||||
|
'image/gif' => 'gif'
|
||||||
|
);
|
||||||
|
|
||||||
if ($r) {
|
if ($r) {
|
||||||
header("Content-type: application/json");
|
$data = array('photo' => $r[0]);
|
||||||
$r[0]['data'] = base64_encode($r[0]['data']);
|
if ($scale !== false) {
|
||||||
echo json_encode($r[0]);
|
$data['photo']['data'] = base64_encode($data['photo']['data']);
|
||||||
|
} else {
|
||||||
|
unset($data['photo']['datasize']); //needed only with scale param
|
||||||
|
}
|
||||||
|
$data['photo']['link'] = array();
|
||||||
|
for($k=intval($data['photo']['minscale']); $k<=intval($data['photo']['maxscale']); $k++) {
|
||||||
|
$data['photo']['link'][$k] = $a->get_baseurl()."/photo/".$data['photo']['resource-id']."-".$k.".".$typetoext[$data['photo']['type']];
|
||||||
|
}
|
||||||
|
$data['photo']['id'] = $data['photo']['resource-id'];
|
||||||
|
unset($data['photo']['resource-id']);
|
||||||
|
unset($data['photo']['minscale']);
|
||||||
|
unset($data['photo']['maxscale']);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
killme();
|
return api_apply_template("photo_detail", $type, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_register_func('api/friendica/photos/list', 'api_fr_photos_list', true);
|
api_register_func('api/friendica/photos/list', 'api_fr_photos_list', true);
|
||||||
|
|
@ -2754,7 +2913,7 @@
|
||||||
$c_url = ((x($_GET,'c_url')) ? $_GET['c_url'] : '');
|
$c_url = ((x($_GET,'c_url')) ? $_GET['c_url'] : '');
|
||||||
|
|
||||||
if ($url === '' || $c_url === '')
|
if ($url === '' || $c_url === '')
|
||||||
die((api_error($a, 'json', "Wrong parameters")));
|
throw new BadRequestException("Wrong parameters.");
|
||||||
|
|
||||||
$c_url = normalise_link($c_url);
|
$c_url = normalise_link($c_url);
|
||||||
|
|
||||||
|
|
@ -2766,7 +2925,7 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
if ((! count($r)) || ($r[0]['network'] !== NETWORK_DFRN))
|
if ((! count($r)) || ($r[0]['network'] !== NETWORK_DFRN))
|
||||||
die((api_error($a, 'json', "Unknown contact")));
|
throw new BadRequestException("Unknown contact");
|
||||||
|
|
||||||
$cid = $r[0]['id'];
|
$cid = $r[0]['id'];
|
||||||
|
|
||||||
|
|
@ -2801,7 +2960,6 @@
|
||||||
api_register_func('api/friendica/remoteauth', 'api_friendica_remoteauth', true);
|
api_register_func('api/friendica/remoteauth', 'api_friendica_remoteauth', true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function api_share_as_retweet(&$item) {
|
function api_share_as_retweet(&$item) {
|
||||||
$body = trim($item["body"]);
|
$body = trim($item["body"]);
|
||||||
|
|
||||||
|
|
@ -2871,8 +3029,10 @@ function api_share_as_retweet(&$item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function api_get_nick($profile) {
|
function api_get_nick($profile) {
|
||||||
/// @TODO Remove trailing junk from profile url
|
/* To-Do:
|
||||||
/// @TODO pump.io check has to check the website
|
- remove trailing junk from profile url
|
||||||
|
- pump.io check has to check the website
|
||||||
|
*/
|
||||||
|
|
||||||
$nick = "";
|
$nick = "";
|
||||||
|
|
||||||
|
|
@ -2920,7 +3080,7 @@ function api_get_nick($profile) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @TODO Look at the page if its really a pumpio site
|
// To-Do: look at the page if its really a pumpio site
|
||||||
//if (!$nick == "") {
|
//if (!$nick == "") {
|
||||||
// $pumpio = preg_replace("=https?://(.*)/(.*)/=ism", "$2", $profile."/");
|
// $pumpio = preg_replace("=https?://(.*)/(.*)/=ism", "$2", $profile."/");
|
||||||
// if ($pumpio != $profile)
|
// if ($pumpio != $profile)
|
||||||
|
|
@ -3034,7 +3194,7 @@ function api_best_nickname(&$contacts) {
|
||||||
|
|
||||||
// return all or a specified group of the user with the containing contacts
|
// return all or a specified group of the user with the containing contacts
|
||||||
function api_friendica_group_show(&$a, $type) {
|
function api_friendica_group_show(&$a, $type) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
// params
|
// params
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
@ -3048,7 +3208,7 @@ function api_best_nickname(&$contacts) {
|
||||||
intval($gid));
|
intval($gid));
|
||||||
// error message if specified gid is not in database
|
// error message if specified gid is not in database
|
||||||
if (count($r) == 0)
|
if (count($r) == 0)
|
||||||
die(api_error($a, $type, 'gid not available'));
|
throw new BadRequestException("gid not available");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
$r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d",
|
$r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d",
|
||||||
|
|
@ -3071,7 +3231,7 @@ function api_best_nickname(&$contacts) {
|
||||||
|
|
||||||
// delete the specified group of the user
|
// delete the specified group of the user
|
||||||
function api_friendica_group_delete(&$a, $type) {
|
function api_friendica_group_delete(&$a, $type) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
// params
|
// params
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
@ -3081,7 +3241,7 @@ function api_best_nickname(&$contacts) {
|
||||||
|
|
||||||
// error if no gid specified
|
// error if no gid specified
|
||||||
if ($gid == 0 || $name == "")
|
if ($gid == 0 || $name == "")
|
||||||
die(api_error($a, $type, 'gid or name not specified'));
|
throw new BadRequestException('gid or name not specified');
|
||||||
|
|
||||||
// get data of the specified group id
|
// get data of the specified group id
|
||||||
$r = q("SELECT * FROM `group` WHERE `uid` = %d AND `id` = %d",
|
$r = q("SELECT * FROM `group` WHERE `uid` = %d AND `id` = %d",
|
||||||
|
|
@ -3089,7 +3249,7 @@ function api_best_nickname(&$contacts) {
|
||||||
intval($gid));
|
intval($gid));
|
||||||
// error message if specified gid is not in database
|
// error message if specified gid is not in database
|
||||||
if (count($r) == 0)
|
if (count($r) == 0)
|
||||||
die(api_error($a, $type, 'gid not available'));
|
throw new BadRequestException('gid not available');
|
||||||
|
|
||||||
// get data of the specified group id and group name
|
// get data of the specified group id and group name
|
||||||
$rname = q("SELECT * FROM `group` WHERE `uid` = %d AND `id` = %d AND `name` = '%s'",
|
$rname = q("SELECT * FROM `group` WHERE `uid` = %d AND `id` = %d AND `name` = '%s'",
|
||||||
|
|
@ -3098,7 +3258,7 @@ function api_best_nickname(&$contacts) {
|
||||||
dbesc($name));
|
dbesc($name));
|
||||||
// error message if specified gid is not in database
|
// error message if specified gid is not in database
|
||||||
if (count($rname) == 0)
|
if (count($rname) == 0)
|
||||||
die(api_error($a, $type, 'wrong group name'));
|
throw new BadRequestException('wrong group name');
|
||||||
|
|
||||||
// delete group
|
// delete group
|
||||||
$ret = group_rmv($uid, $name);
|
$ret = group_rmv($uid, $name);
|
||||||
|
|
@ -3108,14 +3268,14 @@ function api_best_nickname(&$contacts) {
|
||||||
return api_apply_template("group_delete", $type, array('$result' => $success));
|
return api_apply_template("group_delete", $type, array('$result' => $success));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
die(api_error($a, $type, 'other API error'));
|
throw new BadRequestException('other API error');
|
||||||
}
|
}
|
||||||
api_register_func('api/friendica/group_delete', 'api_friendica_group_delete', true);
|
api_register_func('api/friendica/group_delete', 'api_friendica_group_delete', true, API_METHOD_DELETE);
|
||||||
|
|
||||||
|
|
||||||
// create the specified group with the posted array of contacts
|
// create the specified group with the posted array of contacts
|
||||||
function api_friendica_group_create(&$a, $type) {
|
function api_friendica_group_create(&$a, $type) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
// params
|
// params
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
@ -3126,7 +3286,7 @@ function api_best_nickname(&$contacts) {
|
||||||
|
|
||||||
// error if no name specified
|
// error if no name specified
|
||||||
if ($name == "")
|
if ($name == "")
|
||||||
die(api_error($a, $type, 'group name not specified'));
|
throw new BadRequestException('group name not specified');
|
||||||
|
|
||||||
// get data of the specified group name
|
// get data of the specified group name
|
||||||
$rname = q("SELECT * FROM `group` WHERE `uid` = %d AND `name` = '%s' AND `deleted` = 0",
|
$rname = q("SELECT * FROM `group` WHERE `uid` = %d AND `name` = '%s' AND `deleted` = 0",
|
||||||
|
|
@ -3134,7 +3294,7 @@ function api_best_nickname(&$contacts) {
|
||||||
dbesc($name));
|
dbesc($name));
|
||||||
// error message if specified group name already exists
|
// error message if specified group name already exists
|
||||||
if (count($rname) != 0)
|
if (count($rname) != 0)
|
||||||
die(api_error($a, $type, 'group name already exists'));
|
throw new BadRequestException('group name already exists');
|
||||||
|
|
||||||
// check if specified group name is a deleted group
|
// check if specified group name is a deleted group
|
||||||
$rname = q("SELECT * FROM `group` WHERE `uid` = %d AND `name` = '%s' AND `deleted` = 1",
|
$rname = q("SELECT * FROM `group` WHERE `uid` = %d AND `name` = '%s' AND `deleted` = 1",
|
||||||
|
|
@ -3149,7 +3309,7 @@ function api_best_nickname(&$contacts) {
|
||||||
if ($ret)
|
if ($ret)
|
||||||
$gid = group_byname($uid, $name);
|
$gid = group_byname($uid, $name);
|
||||||
else
|
else
|
||||||
die(api_error($a, $type, 'other API error'));
|
throw new BadRequestException('other API error');
|
||||||
|
|
||||||
// add members
|
// add members
|
||||||
$erroraddinguser = false;
|
$erroraddinguser = false;
|
||||||
|
|
@ -3173,12 +3333,12 @@ function api_best_nickname(&$contacts) {
|
||||||
$success = array('success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers);
|
$success = array('success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers);
|
||||||
return api_apply_template("group_create", $type, array('result' => $success));
|
return api_apply_template("group_create", $type, array('result' => $success));
|
||||||
}
|
}
|
||||||
api_register_func('api/friendica/group_create', 'api_friendica_group_create', true);
|
api_register_func('api/friendica/group_create', 'api_friendica_group_create', true, API_METHOD_POST);
|
||||||
|
|
||||||
|
|
||||||
// update the specified group with the posted array of contacts
|
// update the specified group with the posted array of contacts
|
||||||
function api_friendica_group_update(&$a, $type) {
|
function api_friendica_group_update(&$a, $type) {
|
||||||
if (api_user()===false) return false;
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
|
||||||
// params
|
// params
|
||||||
$user_info = api_get_user($a);
|
$user_info = api_get_user($a);
|
||||||
|
|
@ -3190,11 +3350,11 @@ function api_best_nickname(&$contacts) {
|
||||||
|
|
||||||
// error if no name specified
|
// error if no name specified
|
||||||
if ($name == "")
|
if ($name == "")
|
||||||
die(api_error($a, $type, 'group name not specified'));
|
throw new BadRequestException('group name not specified');
|
||||||
|
|
||||||
// error if no gid specified
|
// error if no gid specified
|
||||||
if ($gid == "")
|
if ($gid == "")
|
||||||
die(api_error($a, $type, 'gid not specified'));
|
throw new BadRequestException('gid not specified');
|
||||||
|
|
||||||
// remove members
|
// remove members
|
||||||
$members = group_get_members($gid);
|
$members = group_get_members($gid);
|
||||||
|
|
@ -3230,7 +3390,38 @@ function api_best_nickname(&$contacts) {
|
||||||
$success = array('success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers);
|
$success = array('success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers);
|
||||||
return api_apply_template("group_update", $type, array('result' => $success));
|
return api_apply_template("group_update", $type, array('result' => $success));
|
||||||
}
|
}
|
||||||
api_register_func('api/friendica/group_update', 'api_friendica_group_update', true);
|
api_register_func('api/friendica/group_update', 'api_friendica_group_update', true, API_METHOD_POST);
|
||||||
|
|
||||||
|
|
||||||
|
function api_friendica_activity(&$a, $type) {
|
||||||
|
if (api_user()===false) throw new ForbiddenException();
|
||||||
|
#$verb = (x($_REQUEST, 'verb') ? strtolower($_REQUEST['verb']) : '');
|
||||||
|
$verb = strtolower($a->argv[3]);
|
||||||
|
$id = (x($_REQUEST, 'id') ? $_REQUEST['id'] : 0);
|
||||||
|
|
||||||
|
$res = do_like($id, $verb);
|
||||||
|
|
||||||
|
if ($res) {
|
||||||
|
if ($type == 'xml')
|
||||||
|
$ok = "true";
|
||||||
|
else
|
||||||
|
$ok = "ok";
|
||||||
|
return api_apply_template('test', $type, array("$ok" => $ok));
|
||||||
|
} else {
|
||||||
|
throw new BadRequestException('Error adding activity');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
api_register_func('api/friendica/activity/like', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/dislike', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/attendyes', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/attendno', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/attendmaybe', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/unlike', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/undislike', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/unattendyes', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/unattendno', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activity', true, API_METHOD_POST);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
To.Do:
|
To.Do:
|
||||||
|
|
@ -3243,7 +3434,7 @@ To.Do:
|
||||||
[include_rts] => 1
|
[include_rts] => 1
|
||||||
[include_reply_count] => true
|
[include_reply_count] => true
|
||||||
[include_descendent_reply_count] => true
|
[include_descendent_reply_count] => true
|
||||||
|
(?)
|
||||||
|
|
||||||
|
|
||||||
Not implemented by now:
|
Not implemented by now:
|
||||||
|
|
|
||||||
374
include/like.php
Normal file
374
include/like.php
Normal file
|
|
@ -0,0 +1,374 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief add/remove activity to an item
|
||||||
|
*
|
||||||
|
* Toggle activities as like,dislike,attend of an item
|
||||||
|
*
|
||||||
|
* @param string $item_id
|
||||||
|
* @param string $verb
|
||||||
|
* Activity verb. One of
|
||||||
|
* like, unlike, dislike, undislike, attendyes, unattendyes,
|
||||||
|
* attendno, unattendno, attendmaybe, unattendmaybe
|
||||||
|
* @hook 'post_local_end'
|
||||||
|
* array $arr
|
||||||
|
* 'post_id' => ID of posted item
|
||||||
|
*/
|
||||||
|
function do_like($item_id, $verb) {
|
||||||
|
$a = get_app();
|
||||||
|
|
||||||
|
if(! local_user() && ! remote_user()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch($verb) {
|
||||||
|
case 'like':
|
||||||
|
case 'unlike':
|
||||||
|
$activity = ACTIVITY_LIKE;
|
||||||
|
break;
|
||||||
|
case 'dislike':
|
||||||
|
case 'undislike':
|
||||||
|
$activity = ACTIVITY_DISLIKE;
|
||||||
|
break;
|
||||||
|
case 'attendyes':
|
||||||
|
case 'unattendyes':
|
||||||
|
$activity = ACTIVITY_ATTEND;
|
||||||
|
break;
|
||||||
|
case 'attendno':
|
||||||
|
case 'unattendno':
|
||||||
|
$activity = ACTIVITY_ATTENDNO;
|
||||||
|
break;
|
||||||
|
case 'attendmaybe':
|
||||||
|
case 'unattendmaybe':
|
||||||
|
$activity = ACTIVITY_ATTENDMAYBE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
logger('like: verb ' . $verb . ' item ' . $item_id);
|
||||||
|
|
||||||
|
|
||||||
|
$r = q("SELECT * FROM `item` WHERE `id` = '%s' OR `uri` = '%s' LIMIT 1",
|
||||||
|
dbesc($item_id),
|
||||||
|
dbesc($item_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
if(! $item_id || (! count($r))) {
|
||||||
|
logger('like: no item ' . $item_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = $r[0];
|
||||||
|
|
||||||
|
$owner_uid = $item['uid'];
|
||||||
|
|
||||||
|
if(! can_write_wall($a,$owner_uid)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$remote_owner = null;
|
||||||
|
|
||||||
|
if(! $item['wall']) {
|
||||||
|
// The top level post may have been written by somebody on another system
|
||||||
|
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
|
||||||
|
intval($item['contact-id']),
|
||||||
|
intval($item['uid'])
|
||||||
|
);
|
||||||
|
if(! count($r))
|
||||||
|
return false;
|
||||||
|
if(! $r[0]['self'])
|
||||||
|
$remote_owner = $r[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// this represents the post owner on this system.
|
||||||
|
|
||||||
|
$r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
|
||||||
|
WHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1",
|
||||||
|
intval($owner_uid)
|
||||||
|
);
|
||||||
|
if(count($r))
|
||||||
|
$owner = $r[0];
|
||||||
|
|
||||||
|
if(! $owner) {
|
||||||
|
logger('like: no owner');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! $remote_owner)
|
||||||
|
$remote_owner = $owner;
|
||||||
|
|
||||||
|
|
||||||
|
// This represents the person posting
|
||||||
|
|
||||||
|
if((local_user()) && (local_user() == $owner_uid)) {
|
||||||
|
$contact = $owner;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
|
||||||
|
intval($_SESSION['visitor_id']),
|
||||||
|
intval($owner_uid)
|
||||||
|
);
|
||||||
|
if(count($r))
|
||||||
|
$contact = $r[0];
|
||||||
|
}
|
||||||
|
if(! $contact) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$verbs = " '".dbesc($activity)."' ";
|
||||||
|
|
||||||
|
// event participation are essentially radio toggles. If you make a subsequent choice,
|
||||||
|
// we need to eradicate your first choice.
|
||||||
|
if($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
|
||||||
|
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = q("SELECT `id`, `guid` FROM `item` WHERE `verb` IN ( $verbs ) AND `deleted` = 0
|
||||||
|
AND `contact-id` = %d AND `uid` = %d
|
||||||
|
AND (`parent` = '%s' OR `parent-uri` = '%s' OR `thr-parent` = '%s') LIMIT 1",
|
||||||
|
intval($contact['id']), intval($owner_uid),
|
||||||
|
dbesc($item_id), dbesc($item_id), dbesc($item['uri'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if(count($r)) {
|
||||||
|
$like_item = $r[0];
|
||||||
|
|
||||||
|
// Already voted, undo it
|
||||||
|
$r = q("UPDATE `item` SET `deleted` = 1, `unseen` = 1, `changed` = '%s' WHERE `id` = %d",
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
intval($like_item['id'])
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Clean up the Diaspora signatures for this like
|
||||||
|
// Go ahead and do it even if Diaspora support is disabled. We still want to clean up
|
||||||
|
// if it had been enabled in the past
|
||||||
|
$r = q("DELETE FROM `sign` WHERE `iid` = %d",
|
||||||
|
intval($like_item['id'])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save the author information for the unlike in case we need to relay to Diaspora
|
||||||
|
store_diaspora_like_retract_sig($activity, $item, $like_item, $contact);
|
||||||
|
|
||||||
|
$like_item_id = $like_item['id'];
|
||||||
|
proc_run('php',"include/notifier.php","like","$like_item_id");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uri = item_new_uri($a->get_hostname(),$owner_uid);
|
||||||
|
|
||||||
|
$post_type = (($item['resource-id']) ? t('photo') : t('status'));
|
||||||
|
if($item['obj_type'] === ACTIVITY_OBJ_EVENT)
|
||||||
|
$post_type = t('event');
|
||||||
|
$objtype = (($item['resource-id']) ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
|
||||||
|
$link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n") ;
|
||||||
|
$body = $item['body'];
|
||||||
|
|
||||||
|
$obj = <<< EOT
|
||||||
|
|
||||||
|
<object>
|
||||||
|
<type>$objtype</type>
|
||||||
|
<local>1</local>
|
||||||
|
<id>{$item['uri']}</id>
|
||||||
|
<link>$link</link>
|
||||||
|
<title></title>
|
||||||
|
<content>$body</content>
|
||||||
|
</object>
|
||||||
|
EOT;
|
||||||
|
if($verb === 'like')
|
||||||
|
$bodyverb = t('%1$s likes %2$s\'s %3$s');
|
||||||
|
if($verb === 'dislike')
|
||||||
|
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
|
||||||
|
if($verb === 'attendyes')
|
||||||
|
$bodyverb = t('%1$s is attending %2$s\'s %3$s');
|
||||||
|
if($verb === 'attendno')
|
||||||
|
$bodyverb = t('%1$s is not attending %2$s\'s %3$s');
|
||||||
|
if($verb === 'attendmaybe')
|
||||||
|
$bodyverb = t('%1$s may attend %2$s\'s %3$s');
|
||||||
|
|
||||||
|
if(! isset($bodyverb))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$arr = array();
|
||||||
|
|
||||||
|
$arr['uri'] = $uri;
|
||||||
|
$arr['uid'] = $owner_uid;
|
||||||
|
$arr['contact-id'] = $contact['id'];
|
||||||
|
$arr['type'] = 'activity';
|
||||||
|
$arr['wall'] = $item['wall'];
|
||||||
|
$arr['origin'] = 1;
|
||||||
|
$arr['gravity'] = GRAVITY_LIKE;
|
||||||
|
$arr['parent'] = $item['id'];
|
||||||
|
$arr['parent-uri'] = $item['uri'];
|
||||||
|
$arr['thr-parent'] = $item['uri'];
|
||||||
|
$arr['owner-name'] = $remote_owner['name'];
|
||||||
|
$arr['owner-link'] = $remote_owner['url'];
|
||||||
|
$arr['owner-avatar'] = $remote_owner['thumb'];
|
||||||
|
$arr['author-name'] = $contact['name'];
|
||||||
|
$arr['author-link'] = $contact['url'];
|
||||||
|
$arr['author-avatar'] = $contact['thumb'];
|
||||||
|
|
||||||
|
$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
|
||||||
|
$alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
|
||||||
|
$plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]';
|
||||||
|
$arr['body'] = sprintf( $bodyverb, $ulink, $alink, $plink );
|
||||||
|
|
||||||
|
$arr['verb'] = $activity;
|
||||||
|
$arr['object-type'] = $objtype;
|
||||||
|
$arr['object'] = $obj;
|
||||||
|
$arr['allow_cid'] = $item['allow_cid'];
|
||||||
|
$arr['allow_gid'] = $item['allow_gid'];
|
||||||
|
$arr['deny_cid'] = $item['deny_cid'];
|
||||||
|
$arr['deny_gid'] = $item['deny_gid'];
|
||||||
|
$arr['visible'] = 1;
|
||||||
|
$arr['unseen'] = 1;
|
||||||
|
$arr['last-child'] = 0;
|
||||||
|
|
||||||
|
$post_id = item_store($arr);
|
||||||
|
|
||||||
|
if(! $item['visible']) {
|
||||||
|
$r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d",
|
||||||
|
intval($item['id']),
|
||||||
|
intval($owner_uid)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Save the author information for the like in case we need to relay to Diaspora
|
||||||
|
store_diaspora_like_sig($activity, $post_type, $contact, $post_id);
|
||||||
|
|
||||||
|
$arr['id'] = $post_id;
|
||||||
|
|
||||||
|
call_hooks('post_local_end', $arr);
|
||||||
|
|
||||||
|
proc_run('php',"include/notifier.php","like","$post_id");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function store_diaspora_like_retract_sig($activity, $item, $like_item, $contact) {
|
||||||
|
// Note that we can only create a signature for a user of the local server. We don't have
|
||||||
|
// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
|
||||||
|
// means we are the relay, and for relayable_retractions, Diaspora
|
||||||
|
// only checks the parent_author_signature if it doesn't have to relay further
|
||||||
|
//
|
||||||
|
// If $item['resource-id'] exists, it means the item is a photo. Diaspora doesn't support
|
||||||
|
// likes on photos, so don't bother.
|
||||||
|
|
||||||
|
$enabled = intval(get_config('system','diaspora_enabled'));
|
||||||
|
if(! $enabled) {
|
||||||
|
logger('mod_like: diaspora support disabled, not storing like retraction signature', LOGGER_DEBUG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger('mod_like: storing diaspora like retraction signature');
|
||||||
|
|
||||||
|
if(($activity === ACTIVITY_LIKE) && (! $item['resource-id'])) {
|
||||||
|
$signed_text = $like_item['guid'] . ';' . 'Like';
|
||||||
|
|
||||||
|
// Only works for NETWORK_DFRN
|
||||||
|
$contact_baseurl_start = strpos($contact['url'],'://') + 3;
|
||||||
|
$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
|
||||||
|
$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
|
||||||
|
$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
|
||||||
|
|
||||||
|
// Get contact's private key if he's a user of the local Friendica server
|
||||||
|
$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
|
||||||
|
dbesc($contact['url'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if( $r) {
|
||||||
|
$contact_uid = $r['uid'];
|
||||||
|
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
|
||||||
|
intval($contact_uid)
|
||||||
|
);
|
||||||
|
|
||||||
|
if( $r)
|
||||||
|
$authorsig = base64_encode(rsa_sign($signed_text,$r['prvkey'],'sha256'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! isset($authorsig))
|
||||||
|
$authorsig = '';
|
||||||
|
|
||||||
|
q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
||||||
|
intval($like_item['id']),
|
||||||
|
dbesc($signed_text),
|
||||||
|
dbesc($authorsig),
|
||||||
|
dbesc($diaspora_handle)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function store_diaspora_like_sig($activity, $post_type, $contact, $post_id) {
|
||||||
|
// Note that we can only create a signature for a user of the local server. We don't have
|
||||||
|
// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
|
||||||
|
// means we are the relay, and for relayable_retractions, Diaspora
|
||||||
|
// only checks the parent_author_signature if it doesn't have to relay further
|
||||||
|
|
||||||
|
$enabled = intval(get_config('system','diaspora_enabled'));
|
||||||
|
if(! $enabled) {
|
||||||
|
logger('mod_like: diaspora support disabled, not storing like signature', LOGGER_DEBUG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger('mod_like: storing diaspora like signature');
|
||||||
|
|
||||||
|
if(($activity === ACTIVITY_LIKE) && ($post_type === t('status'))) {
|
||||||
|
// Only works for NETWORK_DFRN
|
||||||
|
$contact_baseurl_start = strpos($contact['url'],'://') + 3;
|
||||||
|
$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
|
||||||
|
$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
|
||||||
|
$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
|
||||||
|
|
||||||
|
// Get contact's private key if he's a user of the local Friendica server
|
||||||
|
$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
|
||||||
|
dbesc($contact['url'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if( $r) {
|
||||||
|
$contact_uid = $r['uid'];
|
||||||
|
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
|
||||||
|
intval($contact_uid)
|
||||||
|
);
|
||||||
|
|
||||||
|
if( $r)
|
||||||
|
$contact_uprvkey = $r['prvkey'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = q("SELECT guid, parent FROM `item` WHERE id = %d LIMIT 1",
|
||||||
|
intval($post_id)
|
||||||
|
);
|
||||||
|
if( $r) {
|
||||||
|
$p = q("SELECT guid FROM `item` WHERE id = %d AND parent = %d LIMIT 1",
|
||||||
|
intval($r[0]['parent']),
|
||||||
|
intval($r[0]['parent'])
|
||||||
|
);
|
||||||
|
if( $p) {
|
||||||
|
$signed_text = $r[0]['guid'] . ';Post;' . $p[0]['guid'] . ';true;' . $diaspora_handle;
|
||||||
|
|
||||||
|
if(isset($contact_uprvkey))
|
||||||
|
$authorsig = base64_encode(rsa_sign($signed_text,$contact_uprvkey,'sha256'));
|
||||||
|
else
|
||||||
|
$authorsig = '';
|
||||||
|
|
||||||
|
q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
||||||
|
intval($post_id),
|
||||||
|
dbesc($signed_text),
|
||||||
|
dbesc($authorsig),
|
||||||
|
dbesc($diaspora_handle)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
43
mod/help.php
43
mod/help.php
|
|
@ -36,13 +36,14 @@ function help_content(&$a) {
|
||||||
$path .= argv($x);
|
$path .= argv($x);
|
||||||
}
|
}
|
||||||
$title = basename($path);
|
$title = basename($path);
|
||||||
|
$filename = $path;
|
||||||
$text = load_doc_file('doc/' . $path . '.md');
|
$text = load_doc_file('doc/' . $path . '.md');
|
||||||
$a->page['title'] = t('Help:') . ' ' . str_replace('-', ' ', notags($title));
|
$a->page['title'] = t('Help:') . ' ' . str_replace('-', ' ', notags($title));
|
||||||
}
|
}
|
||||||
$home = load_doc_file('doc/Home.md');
|
$home = load_doc_file('doc/Home.md');
|
||||||
if (!$text) {
|
if (!$text) {
|
||||||
$text = $home;
|
$text = $home;
|
||||||
|
$filename = "Home";
|
||||||
$a->page['title'] = t('Help');
|
$a->page['title'] = t('Help');
|
||||||
} else {
|
} else {
|
||||||
$a->page['aside'] = Markdown($home);
|
$a->page['aside'] = Markdown($home);
|
||||||
|
|
@ -57,7 +58,45 @@ function help_content(&$a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$html = Markdown($text);
|
$html = Markdown($text);
|
||||||
$html = "<style>.md_warning { padding: 1em; border: #ff0000 solid 2px; background-color: #f9a3a3; color: #ffffff;</style>".$html;
|
|
||||||
|
if ($filename !== "Home") {
|
||||||
|
// create TOC but not for home
|
||||||
|
$lines = explode("\n", $html);
|
||||||
|
$toc="<style>aside ul {padding-left: 1em;}</style><h2>TOC</h2><ul id='toc'>";
|
||||||
|
$lastlevel=1;
|
||||||
|
$idnum = array(0,0,0,0,0,0,0);
|
||||||
|
foreach($lines as &$line){
|
||||||
|
if (substr($line,0,2)=="<h") {
|
||||||
|
$level = substr($line,2,1);
|
||||||
|
if ($level!="r") {
|
||||||
|
$level = intval($level);
|
||||||
|
if ($level<$lastlevel) {
|
||||||
|
for($k=$level;$k<$lastlevel; $k++) $toc.="</ul>";
|
||||||
|
for($k=$level+1;$k<count($idnum);$k++) $idnum[$k]=0;
|
||||||
|
}
|
||||||
|
if ($level>$lastlevel) $toc.="<ul>";
|
||||||
|
$idnum[$level]++;
|
||||||
|
$id = implode("_", array_slice($idnum,1,$level));
|
||||||
|
$href = $a->get_baseurl()."/help/{$filename}#{$id}";
|
||||||
|
$toc .= "<li><a href='{$href}'>".strip_tags($line)."</a></li>";
|
||||||
|
$line = "<a name='{$id}'></a>".$line;
|
||||||
|
$lastlevel = $level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for($k=1;$k<$lastlevel; $k++) $toc.="</ul>";
|
||||||
|
$html = implode("\n",$lines);
|
||||||
|
|
||||||
|
$a->page['aside'] = $toc.$a->page['aside'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = "
|
||||||
|
<style>
|
||||||
|
.md_warning {
|
||||||
|
padding: 1em; border: #ff0000 solid 2px;
|
||||||
|
background-color: #f9a3a3; color: #ffffff;
|
||||||
|
}
|
||||||
|
</style>".$html;
|
||||||
return $html;
|
return $html;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
357
mod/like.php
357
mod/like.php
|
|
@ -3,254 +3,27 @@
|
||||||
require_once('include/security.php');
|
require_once('include/security.php');
|
||||||
require_once('include/bbcode.php');
|
require_once('include/bbcode.php');
|
||||||
require_once('include/items.php');
|
require_once('include/items.php');
|
||||||
|
require_once('include/like.php');
|
||||||
|
|
||||||
function like_content(&$a) {
|
function like_content(&$a) {
|
||||||
|
|
||||||
if(! local_user() && ! remote_user()) {
|
if(! local_user() && ! remote_user()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$verb = notags(trim($_GET['verb']));
|
$verb = notags(trim($_GET['verb']));
|
||||||
|
|
||||||
if(! $verb)
|
if(! $verb)
|
||||||
$verb = 'like';
|
$verb = 'like';
|
||||||
|
|
||||||
|
|
||||||
switch($verb) {
|
|
||||||
case 'like':
|
|
||||||
case 'unlike':
|
|
||||||
$activity = ACTIVITY_LIKE;
|
|
||||||
break;
|
|
||||||
case 'dislike':
|
|
||||||
case 'undislike':
|
|
||||||
$activity = ACTIVITY_DISLIKE;
|
|
||||||
break;
|
|
||||||
case 'attendyes':
|
|
||||||
case 'unattendyes':
|
|
||||||
$activity = ACTIVITY_ATTEND;
|
|
||||||
break;
|
|
||||||
case 'attendno':
|
|
||||||
case 'unattendno':
|
|
||||||
$activity = ACTIVITY_ATTENDNO;
|
|
||||||
break;
|
|
||||||
case 'attendmaybe':
|
|
||||||
case 'unattendmaybe':
|
|
||||||
$activity = ACTIVITY_ATTENDMAYBE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$item_id = (($a->argc > 1) ? notags(trim($a->argv[1])) : 0);
|
$item_id = (($a->argc > 1) ? notags(trim($a->argv[1])) : 0);
|
||||||
|
|
||||||
logger('like: verb ' . $verb . ' item ' . $item_id);
|
$r = do_like($item_id, $verb);
|
||||||
|
if (!$r) return;
|
||||||
|
|
||||||
$r = q("SELECT * FROM `item` WHERE `id` = '%s' OR `uri` = '%s' LIMIT 1",
|
|
||||||
dbesc($item_id),
|
|
||||||
dbesc($item_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
if(! $item_id || (! count($r))) {
|
|
||||||
logger('like: no item ' . $item_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = $r[0];
|
|
||||||
|
|
||||||
$owner_uid = $item['uid'];
|
|
||||||
|
|
||||||
if(! can_write_wall($a,$owner_uid)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$remote_owner = null;
|
|
||||||
|
|
||||||
if(! $item['wall']) {
|
|
||||||
// The top level post may have been written by somebody on another system
|
|
||||||
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
|
|
||||||
intval($item['contact-id']),
|
|
||||||
intval($item['uid'])
|
|
||||||
);
|
|
||||||
if(! count($r))
|
|
||||||
return;
|
|
||||||
if(! $r[0]['self'])
|
|
||||||
$remote_owner = $r[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// this represents the post owner on this system.
|
|
||||||
|
|
||||||
$r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
|
|
||||||
WHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1",
|
|
||||||
intval($owner_uid)
|
|
||||||
);
|
|
||||||
if(count($r))
|
|
||||||
$owner = $r[0];
|
|
||||||
|
|
||||||
if(! $owner) {
|
|
||||||
logger('like: no owner');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(! $remote_owner)
|
|
||||||
$remote_owner = $owner;
|
|
||||||
|
|
||||||
|
|
||||||
// This represents the person posting
|
|
||||||
|
|
||||||
if((local_user()) && (local_user() == $owner_uid)) {
|
|
||||||
$contact = $owner;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
|
|
||||||
intval($_SESSION['visitor_id']),
|
|
||||||
intval($owner_uid)
|
|
||||||
);
|
|
||||||
if(count($r))
|
|
||||||
$contact = $r[0];
|
|
||||||
}
|
|
||||||
if(! $contact) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// See if we've been passed a return path to redirect to
|
// See if we've been passed a return path to redirect to
|
||||||
$return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : '');
|
$return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : '');
|
||||||
|
|
||||||
$verbs = " '".dbesc($activity)."' ";
|
|
||||||
|
|
||||||
// event participation are essentially radio toggles. If you make a subsequent choice,
|
|
||||||
// we need to eradicate your first choice.
|
|
||||||
if($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
|
|
||||||
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$r = q("SELECT `id`, `guid` FROM `item` WHERE `verb` IN ( $verbs ) AND `deleted` = 0
|
|
||||||
AND `contact-id` = %d AND `uid` = %d
|
|
||||||
AND (`parent` = '%s' OR `parent-uri` = '%s' OR `thr-parent` = '%s') LIMIT 1",
|
|
||||||
intval($contact['id']), intval($owner_uid),
|
|
||||||
dbesc($item_id), dbesc($item_id), dbesc($item['uri'])
|
|
||||||
);
|
|
||||||
|
|
||||||
if(count($r)) {
|
|
||||||
$like_item = $r[0];
|
|
||||||
|
|
||||||
// Already voted, undo it
|
|
||||||
$r = q("UPDATE `item` SET `deleted` = 1, `unseen` = 1, `changed` = '%s' WHERE `id` = %d",
|
|
||||||
dbesc(datetime_convert()),
|
|
||||||
intval($like_item['id'])
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Clean up the Diaspora signatures for this like
|
|
||||||
// Go ahead and do it even if Diaspora support is disabled. We still want to clean up
|
|
||||||
// if it had been enabled in the past
|
|
||||||
$r = q("DELETE FROM `sign` WHERE `iid` = %d",
|
|
||||||
intval($like_item['id'])
|
|
||||||
);
|
|
||||||
|
|
||||||
// Save the author information for the unlike in case we need to relay to Diaspora
|
|
||||||
store_diaspora_like_retract_sig($activity, $item, $like_item, $contact);
|
|
||||||
|
|
||||||
// proc_run('php',"include/notifier.php","like","$post_id"); // $post_id isn't defined here!
|
|
||||||
$like_item_id = $like_item['id'];
|
|
||||||
proc_run('php',"include/notifier.php","like","$like_item_id");
|
|
||||||
|
|
||||||
like_content_return($a->get_baseurl(), $return_path);
|
|
||||||
return; // NOTREACHED
|
|
||||||
}
|
|
||||||
|
|
||||||
$uri = item_new_uri($a->get_hostname(),$owner_uid);
|
|
||||||
|
|
||||||
$post_type = (($item['resource-id']) ? t('photo') : t('status'));
|
|
||||||
if($item['obj_type'] === ACTIVITY_OBJ_EVENT)
|
|
||||||
$post_type = t('event');
|
|
||||||
$objtype = (($item['resource-id']) ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
|
|
||||||
$link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n") ;
|
|
||||||
$body = $item['body'];
|
|
||||||
|
|
||||||
$obj = <<< EOT
|
|
||||||
|
|
||||||
<object>
|
|
||||||
<type>$objtype</type>
|
|
||||||
<local>1</local>
|
|
||||||
<id>{$item['uri']}</id>
|
|
||||||
<link>$link</link>
|
|
||||||
<title></title>
|
|
||||||
<content>$body</content>
|
|
||||||
</object>
|
|
||||||
EOT;
|
|
||||||
if($verb === 'like')
|
|
||||||
$bodyverb = t('%1$s likes %2$s\'s %3$s');
|
|
||||||
if($verb === 'dislike')
|
|
||||||
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
|
|
||||||
if($verb === 'attendyes')
|
|
||||||
$bodyverb = t('%1$s is attending %2$s\'s %3$s');
|
|
||||||
if($verb === 'attendno')
|
|
||||||
$bodyverb = t('%1$s is not attending %2$s\'s %3$s');
|
|
||||||
if($verb === 'attendmaybe')
|
|
||||||
$bodyverb = t('%1$s may attend %2$s\'s %3$s');
|
|
||||||
|
|
||||||
if(! isset($bodyverb))
|
|
||||||
return;
|
|
||||||
|
|
||||||
$arr = array();
|
|
||||||
|
|
||||||
$arr['uri'] = $uri;
|
|
||||||
$arr['uid'] = $owner_uid;
|
|
||||||
$arr['contact-id'] = $contact['id'];
|
|
||||||
$arr['type'] = 'activity';
|
|
||||||
$arr['wall'] = $item['wall'];
|
|
||||||
$arr['origin'] = 1;
|
|
||||||
$arr['gravity'] = GRAVITY_LIKE;
|
|
||||||
$arr['parent'] = $item['id'];
|
|
||||||
$arr['parent-uri'] = $item['uri'];
|
|
||||||
$arr['thr-parent'] = $item['uri'];
|
|
||||||
$arr['owner-name'] = $remote_owner['name'];
|
|
||||||
$arr['owner-link'] = $remote_owner['url'];
|
|
||||||
$arr['owner-avatar'] = $remote_owner['thumb'];
|
|
||||||
$arr['author-name'] = $contact['name'];
|
|
||||||
$arr['author-link'] = $contact['url'];
|
|
||||||
$arr['author-avatar'] = $contact['thumb'];
|
|
||||||
|
|
||||||
$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
|
|
||||||
$alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
|
|
||||||
$plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]';
|
|
||||||
$arr['body'] = sprintf( $bodyverb, $ulink, $alink, $plink );
|
|
||||||
|
|
||||||
$arr['verb'] = $activity;
|
|
||||||
$arr['object-type'] = $objtype;
|
|
||||||
$arr['object'] = $obj;
|
|
||||||
$arr['allow_cid'] = $item['allow_cid'];
|
|
||||||
$arr['allow_gid'] = $item['allow_gid'];
|
|
||||||
$arr['deny_cid'] = $item['deny_cid'];
|
|
||||||
$arr['deny_gid'] = $item['deny_gid'];
|
|
||||||
$arr['visible'] = 1;
|
|
||||||
$arr['unseen'] = 1;
|
|
||||||
$arr['last-child'] = 0;
|
|
||||||
|
|
||||||
$post_id = item_store($arr);
|
|
||||||
|
|
||||||
if(! $item['visible']) {
|
|
||||||
$r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d",
|
|
||||||
intval($item['id']),
|
|
||||||
intval($owner_uid)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Save the author information for the like in case we need to relay to Diaspora
|
|
||||||
store_diaspora_like_sig($activity, $post_type, $contact, $post_id);
|
|
||||||
|
|
||||||
$arr['id'] = $post_id;
|
|
||||||
|
|
||||||
call_hooks('post_local_end', $arr);
|
|
||||||
|
|
||||||
proc_run('php',"include/notifier.php","like","$post_id");
|
|
||||||
|
|
||||||
like_content_return($a->get_baseurl(), $return_path);
|
like_content_return($a->get_baseurl(), $return_path);
|
||||||
killme(); // NOTREACHED
|
killme(); // NOTREACHED
|
||||||
// return; // NOTREACHED
|
// return; // NOTREACHED
|
||||||
|
|
@ -273,123 +46,3 @@ function like_content_return($baseurl, $return_path) {
|
||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function store_diaspora_like_retract_sig($activity, $item, $like_item, $contact) {
|
|
||||||
// Note that we can only create a signature for a user of the local server. We don't have
|
|
||||||
// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
|
|
||||||
// means we are the relay, and for relayable_retractions, Diaspora
|
|
||||||
// only checks the parent_author_signature if it doesn't have to relay further
|
|
||||||
//
|
|
||||||
// If $item['resource-id'] exists, it means the item is a photo. Diaspora doesn't support
|
|
||||||
// likes on photos, so don't bother.
|
|
||||||
|
|
||||||
$enabled = intval(get_config('system','diaspora_enabled'));
|
|
||||||
if(! $enabled) {
|
|
||||||
logger('mod_like: diaspora support disabled, not storing like retraction signature', LOGGER_DEBUG);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger('mod_like: storing diaspora like retraction signature');
|
|
||||||
|
|
||||||
if(($activity === ACTIVITY_LIKE) && (! $item['resource-id'])) {
|
|
||||||
$signed_text = $like_item['guid'] . ';' . 'Like';
|
|
||||||
|
|
||||||
// Only works for NETWORK_DFRN
|
|
||||||
$contact_baseurl_start = strpos($contact['url'],'://') + 3;
|
|
||||||
$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
|
|
||||||
$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
|
|
||||||
$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
|
|
||||||
|
|
||||||
// Get contact's private key if he's a user of the local Friendica server
|
|
||||||
$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
|
|
||||||
dbesc($contact['url'])
|
|
||||||
);
|
|
||||||
|
|
||||||
if( $r) {
|
|
||||||
$contact_uid = $r['uid'];
|
|
||||||
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
|
|
||||||
intval($contact_uid)
|
|
||||||
);
|
|
||||||
|
|
||||||
if( $r)
|
|
||||||
$authorsig = base64_encode(rsa_sign($signed_text,$r['prvkey'],'sha256'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(! isset($authorsig))
|
|
||||||
$authorsig = '';
|
|
||||||
|
|
||||||
q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
|
||||||
intval($like_item['id']),
|
|
||||||
dbesc($signed_text),
|
|
||||||
dbesc($authorsig),
|
|
||||||
dbesc($diaspora_handle)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
function store_diaspora_like_sig($activity, $post_type, $contact, $post_id) {
|
|
||||||
// Note that we can only create a signature for a user of the local server. We don't have
|
|
||||||
// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
|
|
||||||
// means we are the relay, and for relayable_retractions, Diaspora
|
|
||||||
// only checks the parent_author_signature if it doesn't have to relay further
|
|
||||||
|
|
||||||
$enabled = intval(get_config('system','diaspora_enabled'));
|
|
||||||
if(! $enabled) {
|
|
||||||
logger('mod_like: diaspora support disabled, not storing like signature', LOGGER_DEBUG);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger('mod_like: storing diaspora like signature');
|
|
||||||
|
|
||||||
if(($activity === ACTIVITY_LIKE) && ($post_type === t('status'))) {
|
|
||||||
// Only works for NETWORK_DFRN
|
|
||||||
$contact_baseurl_start = strpos($contact['url'],'://') + 3;
|
|
||||||
$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
|
|
||||||
$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
|
|
||||||
$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
|
|
||||||
|
|
||||||
// Get contact's private key if he's a user of the local Friendica server
|
|
||||||
$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
|
|
||||||
dbesc($contact['url'])
|
|
||||||
);
|
|
||||||
|
|
||||||
if( $r) {
|
|
||||||
$contact_uid = $r['uid'];
|
|
||||||
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
|
|
||||||
intval($contact_uid)
|
|
||||||
);
|
|
||||||
|
|
||||||
if( $r)
|
|
||||||
$contact_uprvkey = $r['prvkey'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$r = q("SELECT guid, parent FROM `item` WHERE id = %d LIMIT 1",
|
|
||||||
intval($post_id)
|
|
||||||
);
|
|
||||||
if( $r) {
|
|
||||||
$p = q("SELECT guid FROM `item` WHERE id = %d AND parent = %d LIMIT 1",
|
|
||||||
intval($r[0]['parent']),
|
|
||||||
intval($r[0]['parent'])
|
|
||||||
);
|
|
||||||
if( $p) {
|
|
||||||
$signed_text = $r[0]['guid'] . ';Post;' . $p[0]['guid'] . ';true;' . $diaspora_handle;
|
|
||||||
|
|
||||||
if(isset($contact_uprvkey))
|
|
||||||
$authorsig = base64_encode(rsa_sign($signed_text,$contact_uprvkey,'sha256'));
|
|
||||||
else
|
|
||||||
$authorsig = '';
|
|
||||||
|
|
||||||
q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
|
||||||
intval($post_id),
|
|
||||||
dbesc($signed_text),
|
|
||||||
dbesc($authorsig),
|
|
||||||
dbesc($diaspora_handle)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
21
view/templates/api_photo_detail_xml.tpl
Normal file
21
view/templates/api_photo_detail_xml.tpl
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
<photo>
|
||||||
|
<id>{{$photo.id}}</id>
|
||||||
|
<created>{{$photo.created}}</created>
|
||||||
|
<edited>{{$photo.edited}}</edited>
|
||||||
|
<title>{{$photo.title}}</title>
|
||||||
|
<desc>{{$photo.desc}}</desc>
|
||||||
|
<album>{{$photo.album}}</album>
|
||||||
|
<filename>{{$photo.filename}}</filename>
|
||||||
|
<type>{{$photo.type}}</type>
|
||||||
|
<height>{{$photo.height}}</height>
|
||||||
|
<width>{{$photo.width}}</width>
|
||||||
|
<datasize>{{$photo.datasize}}</datasize>
|
||||||
|
<profile>1</profile>
|
||||||
|
<links type="array">{{foreach $photo.link as $scale => $url}}
|
||||||
|
<link type="{{$photo.type}}" scale="{{$scale}}" href="{{$url}}" />
|
||||||
|
{{/foreach}}</links>
|
||||||
|
{{if $photo.data}}
|
||||||
|
<data encode="base64">{{$photo.data}}</data>
|
||||||
|
{{/if}}
|
||||||
|
</photo>
|
||||||
5
view/templates/api_photos_list_xml.tpl
Normal file
5
view/templates/api_photos_list_xml.tpl
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
<photos type="array">
|
||||||
|
{{foreach $photos as $photo}}
|
||||||
|
<photo id="{{$photo.id}}" album="{{$photo.album}}" filename="{{$photo.filename}}" type="{{$photo.type}}">{{$photo.thumb}}</photo>
|
||||||
|
{{/foreach}}</photos>
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
|
||||||
<statuses type="array" xmlns:statusnet="http://status.net/schema/api/1/">
|
<statuses type="array"
|
||||||
|
xmlns:statusnet="http://status.net/schema/api/1/"
|
||||||
|
xmlns:friendica="http://friendi.ca/schema/api/1/">
|
||||||
{{foreach $statuses as $status}} <status>
|
{{foreach $statuses as $status}} <status>
|
||||||
<text>{{$status.text}}</text>
|
<text>{{$status.text}}</text>
|
||||||
<truncated>{{$status.truncated}}</truncated>
|
<truncated>{{$status.truncated}}</truncated>
|
||||||
|
|
@ -17,5 +19,8 @@
|
||||||
<coordinates>{{$status.coordinates}}</coordinates>
|
<coordinates>{{$status.coordinates}}</coordinates>
|
||||||
<place>{{$status.place}}</place>
|
<place>{{$status.place}}</place>
|
||||||
<contributors>{{$status.contributors}}</contributors>
|
<contributors>{{$status.contributors}}</contributors>
|
||||||
|
<friendica:activities>{{foreach $status.friendica_activities as $k=>$v}}
|
||||||
|
<friendica:{{$k}}>{{$v}}</friendica:{{$k}}>
|
||||||
|
{{/foreach}}</friendica:activities>
|
||||||
</status>
|
</status>
|
||||||
{{/foreach}}</statuses>
|
{{/foreach}}</statuses>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue