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
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -12,8 +12,8 @@ addon
|
|||
*~
|
||||
robots.txt
|
||||
|
||||
#ignore documentation, it should be newly built
|
||||
doc/api
|
||||
#ignore documentation, it should be newly built
|
||||
doc/html
|
||||
|
||||
#ignore reports, should be generted with every build
|
||||
report/
|
||||
|
@ -23,7 +23,7 @@ report/
|
|||
.buildpath
|
||||
.externalToolBuilders
|
||||
.settings
|
||||
#ignore OSX .DS_Store files
|
||||
#ignore OSX .DS_Store files
|
||||
.DS_Store
|
||||
|
||||
/nbproject/private/
|
||||
|
|
287
doc/api.md
287
doc/api.md
|
@ -1,6 +1,6 @@
|
|||
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).
|
||||
|
||||
Please refer to the linked documentation for further information.
|
||||
|
||||
|
@ -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")
|
||||
* 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/verify_credentials
|
||||
#### Parameters
|
||||
* skip_status: Don't show the "status" field. (Default: false)
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
---
|
||||
### conversation/show
|
||||
Unofficial Twitter command. It shows all direct answers (excluding the original post) to a given id.
|
||||
|
||||
|
@ -43,10 +75,11 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
|
||||
---
|
||||
### direct_messages
|
||||
#### Parameters
|
||||
* count: Items per page (default: 20)
|
||||
|
@ -57,8 +90,9 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* skip_status
|
||||
* skip_status
|
||||
|
||||
---
|
||||
### direct_messages/all
|
||||
#### Parameters
|
||||
* 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
|
||||
* getText: Defines the format of the status field. Can be "html" or "plain"
|
||||
|
||||
---
|
||||
### direct_messages/conversation
|
||||
Shows all direct messages of a conversation
|
||||
#### Parameters
|
||||
|
@ -77,14 +112,16 @@ Shows all direct messages of a conversation
|
|||
* getText: Defines the format of the status field. Can be "html" or "plain"
|
||||
* uri: URI of the conversation
|
||||
|
||||
---
|
||||
### direct_messages/new
|
||||
#### Parameters
|
||||
* user_id: id of the user
|
||||
* user_id: id of the user
|
||||
* screen_name: screen name (for technical reasons, this value is not unique!)
|
||||
* text: The message
|
||||
* replyto: ID of the replied direct message
|
||||
* title: Title of the direct message
|
||||
|
||||
---
|
||||
### direct_messages/sent
|
||||
#### Parameters
|
||||
* 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"
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
---
|
||||
### favorites
|
||||
#### Parameters
|
||||
* 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/create
|
||||
#### Parameters
|
||||
* id
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
---
|
||||
### favorites/destroy
|
||||
#### Parameters
|
||||
* id
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
---
|
||||
### followers/ids
|
||||
#### Parameters
|
||||
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
|
||||
|
@ -125,20 +166,143 @@ Favorites aren't displayed to other users, so "user_id" and "screen_name". So se
|
|||
#### Unsupported parameters
|
||||
* user_id
|
||||
* screen_name
|
||||
* cursor
|
||||
* cursor
|
||||
|
||||
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
|
||||
#### Parameters
|
||||
* photo_id: Resource id of a photo.
|
||||
* scale: (optional) scale value of the photo
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
#### Parameters
|
||||
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
|
||||
|
@ -146,46 +310,54 @@ Returns a list of all photo resources of the logged in user.
|
|||
#### Unsupported parameters
|
||||
* user_id
|
||||
* screen_name
|
||||
* cursor
|
||||
* cursor
|
||||
|
||||
Friendica doesn't allow showing friends of other users.
|
||||
|
||||
---
|
||||
### help/test
|
||||
|
||||
---
|
||||
### media/upload
|
||||
#### Parameters
|
||||
* media: image data
|
||||
|
||||
---
|
||||
### oauth/request_token
|
||||
#### Parameters
|
||||
* oauth_callback
|
||||
* oauth_callback
|
||||
|
||||
#### Unsupported parameters
|
||||
* x_auth_access_type
|
||||
* x_auth_access_type
|
||||
|
||||
---
|
||||
### oauth/access_token
|
||||
#### Parameters
|
||||
* oauth_verifier
|
||||
* oauth_verifier
|
||||
|
||||
#### Unsupported parameters
|
||||
* x_auth_password
|
||||
* x_auth_username
|
||||
* x_auth_mode
|
||||
* x_auth_password
|
||||
* x_auth_username
|
||||
* x_auth_mode
|
||||
|
||||
---
|
||||
### statuses/destroy
|
||||
#### Parameters
|
||||
* id: message number
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* trim_user
|
||||
* trim_user
|
||||
|
||||
---
|
||||
### statuses/followers
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
---
|
||||
### statuses/friends
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
---
|
||||
### statuses/friends_timeline
|
||||
#### Parameters
|
||||
* count: Items per page (default: 20)
|
||||
|
@ -197,10 +369,11 @@ Friendica doesn't allow showing friends of other users.
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
|
||||
---
|
||||
### statuses/home_timeline
|
||||
#### Parameters
|
||||
* count: Items per page (default: 20)
|
||||
|
@ -212,10 +385,11 @@ Friendica doesn't allow showing friends of other users.
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
|
||||
---
|
||||
### statuses/mentions
|
||||
#### Parameters
|
||||
* count: Items per page (default: 20)
|
||||
|
@ -225,10 +399,11 @@ Friendica doesn't allow showing friends of other users.
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
|
||||
---
|
||||
### statuses/public_timeline
|
||||
#### Parameters
|
||||
* count: Items per page (default: 20)
|
||||
|
@ -240,8 +415,9 @@ Friendica doesn't allow showing friends of other users.
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* trim_user
|
||||
* trim_user
|
||||
|
||||
---
|
||||
### statuses/replies
|
||||
#### Parameters
|
||||
* count: Items per page (default: 20)
|
||||
|
@ -251,18 +427,20 @@ Friendica doesn't allow showing friends of other users.
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
|
||||
---
|
||||
### statuses/retweet
|
||||
#### Parameters
|
||||
* id: message number
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* trim_user
|
||||
* trim_user
|
||||
|
||||
---
|
||||
### statuses/show
|
||||
#### Parameters
|
||||
* id: message number
|
||||
|
@ -270,9 +448,10 @@ Friendica doesn't allow showing friends of other users.
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* include_my_retweet
|
||||
* trim_user
|
||||
* include_my_retweet
|
||||
* trim_user
|
||||
|
||||
---
|
||||
### statuses/update, statuses/update_with_media
|
||||
#### Parameters
|
||||
* title: Title of the status
|
||||
|
@ -289,16 +468,17 @@ Friendica doesn't allow showing friends of other users.
|
|||
* contact_deny
|
||||
* network
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
* media_ids: (By now only a single value, no array)
|
||||
* media_ids: (By now only a single value, no array)
|
||||
|
||||
#### Unsupported parameters
|
||||
* trim_user
|
||||
* place_id
|
||||
* display_coordinates
|
||||
|
||||
---
|
||||
### statuses/user_timeline
|
||||
#### Parameters
|
||||
* user_id: id of the user
|
||||
* user_id: id of the user
|
||||
* screen_name: screen name (for technical reasons, this value is not unique!)
|
||||
* count: Items per page (default: 20)
|
||||
* page: page number
|
||||
|
@ -309,46 +489,51 @@ Friendica doesn't allow showing friends of other users.
|
|||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
* include_rts
|
||||
* trim_user
|
||||
* contributor_details
|
||||
|
||||
---
|
||||
### statusnet/config
|
||||
|
||||
---
|
||||
### statusnet/version
|
||||
|
||||
#### Unsupported parameters
|
||||
* user_id
|
||||
* screen_name
|
||||
* cursor
|
||||
* cursor
|
||||
|
||||
Friendica doesn't allow showing followers of other users.
|
||||
|
||||
---
|
||||
### users/search
|
||||
#### Parameters
|
||||
* q: name of the user
|
||||
* q: name of the user
|
||||
|
||||
#### Unsupported parameters
|
||||
* page
|
||||
* count
|
||||
* include_entities
|
||||
|
||||
---
|
||||
### users/show
|
||||
#### Parameters
|
||||
* user_id: id of the user
|
||||
* user_id: id of the user
|
||||
* screen_name: screen name (for technical reasons, this value is not unique!)
|
||||
* include_entities: "true" shows entities for pictures and links (Default: false)
|
||||
|
||||
#### Unsupported parameters
|
||||
* user_id
|
||||
* screen_name
|
||||
* cursor
|
||||
* cursor
|
||||
|
||||
Friendica doesn't allow showing friends of other users.
|
||||
|
||||
|
||||
## Implemented API calls (not compatible with other APIs)
|
||||
|
||||
---
|
||||
### friendica/group_show
|
||||
Return all or a specified group of the user with the containing contacts as array.
|
||||
|
||||
|
@ -362,12 +547,14 @@ Array of:
|
|||
* user: array of group members (return from api_get_user() function for each member)
|
||||
|
||||
|
||||
---
|
||||
### 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.
|
||||
|
||||
---
|
||||
### Parameters
|
||||
* gid: id of the group to be deleted
|
||||
* name: name of the group to be deleted
|
||||
* name: name of the group to be deleted
|
||||
|
||||
#### Return values
|
||||
Array of:
|
||||
|
@ -378,8 +565,9 @@ Array of:
|
|||
* wrong users: empty array
|
||||
|
||||
|
||||
---
|
||||
### 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
|
||||
* name: name of the group to be created
|
||||
|
||||
|
@ -395,11 +583,12 @@ Array of:
|
|||
* gid: gid of the created group
|
||||
* name: name of the created group
|
||||
* status: „missing user“ | „reactivated“ | „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
|
||||
|
||||
|
||||
---
|
||||
### 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
|
||||
* gid: id of the group to be changed
|
||||
* name: name of the group to be changed
|
||||
|
@ -416,9 +605,9 @@ Array of:
|
|||
* gid: gid of the changed group
|
||||
* name: name of the changed group
|
||||
* 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
|
||||
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
|
||||
* users/report_spam
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Usage Examples
|
||||
### 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)).
|
||||
|
|
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;
|
||||
}
|
||||
|
||||
|
||||
|
1081
include/api.php
1081
include/api.php
File diff suppressed because it is too large
Load diff
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);
|
||||
}
|
||||
$title = basename($path);
|
||||
|
||||
$filename = $path;
|
||||
$text = load_doc_file('doc/' . $path . '.md');
|
||||
$a->page['title'] = t('Help:') . ' ' . str_replace('-', ' ', notags($title));
|
||||
}
|
||||
$home = load_doc_file('doc/Home.md');
|
||||
if (!$text) {
|
||||
$text = $home;
|
||||
$filename = "Home";
|
||||
$a->page['title'] = t('Help');
|
||||
} else {
|
||||
$a->page['aside'] = Markdown($home);
|
||||
|
@ -57,7 +58,45 @@ function help_content(&$a) {
|
|||
}
|
||||
|
||||
$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;
|
||||
|
||||
}
|
||||
|
|
357
mod/like.php
357
mod/like.php
|
@ -3,254 +3,27 @@
|
|||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
|
||||
require_once('include/like.php');
|
||||
|
||||
function like_content(&$a) {
|
||||
|
||||
if(! local_user() && ! remote_user()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$verb = notags(trim($_GET['verb']));
|
||||
|
||||
if(! $verb)
|
||||
$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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
$r = do_like($item_id, $verb);
|
||||
if (!$r) return;
|
||||
|
||||
// See if we've been passed a return path to redirect to
|
||||
$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);
|
||||
killme(); // NOTREACHED
|
||||
// return; // NOTREACHED
|
||||
|
@ -273,123 +46,3 @@ function like_content_return($baseurl, $return_path) {
|
|||
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>
|
||||
<text>{{$status.text}}</text>
|
||||
<truncated>{{$status.truncated}}</truncated>
|
||||
|
@ -17,5 +19,8 @@
|
|||
<coordinates>{{$status.coordinates}}</coordinates>
|
||||
<place>{{$status.place}}</place>
|
||||
<contributors>{{$status.contributors}}</contributors>
|
||||
<friendica:activities>{{foreach $status.friendica_activities as $k=>$v}}
|
||||
<friendica:{{$k}}>{{$v}}</friendica:{{$k}}>
|
||||
{{/foreach}}</friendica:activities>
|
||||
</status>
|
||||
{{/foreach}}</statuses>
|
||||
|
|
Loading…
Reference in a new issue