rodzic
5a00070028
commit
273c584e10
36
README.md
36
README.md
|
@ -49,4 +49,38 @@ I actively do *not* want you to use this code in production. It is not suitable
|
|||
|
||||
Please take note of [CRAPL v0](https://matt.might.net/articles/crapl/):
|
||||
|
||||
> Any appearance of design in the Program is purely coincidental and should not in any way be mistaken for evidence of thoughtful software construction.
|
||||
> Any appearance of design in the Program is purely coincidental and should not in any way be mistaken for evidence of thoughtful software construction.
|
||||
|
||||
## Features
|
||||
|
||||
### Working
|
||||
|
||||
* ✅ User can be followed
|
||||
* ✅ User can post messages to followers
|
||||
* ✅ User can post a message to a specific external account
|
||||
* ✅ User can post an image & alt text
|
||||
* ✅ User can follow, unfollow, block, and unblock external accounts
|
||||
* ✅ Server validates the HTTP Message Signatures of all incoming messages
|
||||
* ✅ Incoming messages are saved
|
||||
* ✅ User can read incoming messages (Create, Update, Announce, Like)
|
||||
* ✅ User can read the results of polls
|
||||
* ✅ User can see attached images, videos, audio
|
||||
* ✅ User can hide "Content Warning" text
|
||||
* ✅ User can receive Updates to messages
|
||||
* ✅ User can Announce / boost / repost an external post
|
||||
* ✅ User can see if a post is a reply to them
|
||||
|
||||
### Not Working
|
||||
|
||||
* ❌ See posts from Lemmy communities
|
||||
* ❌ See contents of Announced posts
|
||||
* ❌ Delete own post
|
||||
* ❌ Update own post
|
||||
* ❌ Receive Undo messages (Unfollow, delete post, remove Like, remove Announce)
|
||||
* ❌ Create Polls
|
||||
* ❌ Attach multiple images
|
||||
* ❌ Set focus point for images
|
||||
* ❌ Set sensitivity for images / blur
|
||||
* ❌ Set "Content Warning"
|
||||
* ❌ See external users' avatars, names, or other details
|
||||
* ❌ ...?
|
||||
|
|
67
index.php
67
index.php
|
@ -9,7 +9,7 @@
|
|||
* The Actor can send messages to followers.
|
||||
* The message can have linkable URls, hashtags, and mentions.
|
||||
* An image and alt text can be attached to the message.
|
||||
* The Actor can follow remote accounts.
|
||||
* The Actor can follow, unfollow, block, and unblock remote accounts.
|
||||
* The Server saves logs about requests it receives and sends.
|
||||
* This code is NOT suitable for production use.
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
@ -43,9 +43,9 @@
|
|||
$server = $_SERVER["SERVER_NAME"]; // Do not change this!
|
||||
|
||||
// Some requests require a User-Agent string.
|
||||
define("USERAGENT", "activitypub-single-php-file/0.0");
|
||||
define( "USERAGENT", "activitypub-single-php-file/0.0" );
|
||||
|
||||
// Set up where logs and messages go.
|
||||
// Set up where to save logs, posts, and images.
|
||||
// You can change these directories to something more suitable if you like.
|
||||
$data = "data";
|
||||
$directories = array(
|
||||
|
@ -75,7 +75,11 @@
|
|||
switch ( $path ) {
|
||||
case ".well-known/webfinger":
|
||||
webfinger(); // Mandatory. Static.
|
||||
case rawurldecode( $username ):
|
||||
case ".well-known/nodeinfo":
|
||||
wk_nodeinfo(); // Optional. Static.
|
||||
case "nodeinfo/2.1":
|
||||
nodeinfo(); // Optional. Static.
|
||||
case rawurldecode( $username ):
|
||||
case "@" . rawurldecode( $username ): // Some software assumes usernames start with an `@`
|
||||
username(); // Mandatory. Static
|
||||
case "following":
|
||||
|
@ -93,15 +97,11 @@
|
|||
case "users":
|
||||
users(); // User interface for (un)following & (un)blocking an external user.
|
||||
case "action/users":
|
||||
action_users(); // API for following a user.
|
||||
action_users();// API for following a user.
|
||||
case "read":
|
||||
view( "read" );// User interface for reading posts.
|
||||
case ".well-known/nodeinfo":
|
||||
wk_nodeinfo(); // Optional. Static.
|
||||
case "nodeinfo/2.1":
|
||||
nodeinfo(); // Optional. Static.
|
||||
case "/":
|
||||
view( "home" );// Optional. Can be dynamic
|
||||
view( "home" );// User interface for seeing what the user has posted.
|
||||
default:
|
||||
die();
|
||||
}
|
||||
|
@ -178,7 +178,7 @@
|
|||
global $server, $directories;
|
||||
|
||||
// Get all the files
|
||||
$following_files = glob( $directories["following"] . "/*.json");
|
||||
$following_files = glob( $directories["following"] . "/*.json" );
|
||||
// Number of users
|
||||
$totalItems = count( $following_files );
|
||||
|
||||
|
@ -206,14 +206,14 @@
|
|||
// You can set this to any number you like.
|
||||
|
||||
// Get all the files
|
||||
$follower_files = glob( $directories["followers"] . "/*.json");
|
||||
$follower_files = glob( $directories["followers"] . "/*.json" );
|
||||
// Number of users
|
||||
$totalItems = count( $follower_files );
|
||||
|
||||
// Create a list of everyone being followed
|
||||
$items = array();
|
||||
foreach ( $follower_files as $follower_file ) {
|
||||
$following = json_decode( file_get_contents( $follower_file ),true );
|
||||
$following = json_decode( file_get_contents( $follower_file ), true );
|
||||
$items[] = $following["id"];
|
||||
}
|
||||
|
||||
|
@ -268,28 +268,20 @@
|
|||
}
|
||||
|
||||
if ( !$reply && !$from_following ) {
|
||||
// Don't bother processing it at all.
|
||||
die();
|
||||
}
|
||||
|
||||
// Save any Follow, Create, Update, Announce, Like messages
|
||||
// This ignores Delete, Undo, and anything else
|
||||
if ( match( $inbox_type ) {
|
||||
"Follow", "Create", "Update", "Announce", "Like" => true,
|
||||
default => false,
|
||||
} ) {
|
||||
|
||||
// Validate HTTP Message Signature
|
||||
if ( !verifyHTTPSignature() ) { die(); }
|
||||
|
||||
// Validate HTTP Message Signature
|
||||
// This logs whether the signature was validated or not
|
||||
if ( !verifyHTTPSignature() ) { die(); }
|
||||
// If the message is valid, save the message in `/data/inbox/`
|
||||
$uuid = uuid();
|
||||
$inbox_filename = $uuid . "." . urlencode( $inbox_type ) . ".json";
|
||||
file_put_contents( $directories["inbox"] . "/{$inbox_filename}", json_encode( $inbox_message ) );
|
||||
|
||||
// If the message is valid, save the message in `/data/inbox/`
|
||||
$uuid = uuid();
|
||||
$inbox_filename = $uuid . "." . urlencode( $inbox_type ) . ".json";
|
||||
file_put_contents( $directories["inbox"] . "/{$inbox_filename}", json_encode( $inbox_message ) );
|
||||
}
|
||||
|
||||
// This inbox only responds to follow requests.
|
||||
// A remote server sends the inbox follow request which is a JSON file saying who they are.
|
||||
// This inbox only sends responses to follow requests.
|
||||
// A remote server sends the inbox a follow request which is a JSON file saying who they are.
|
||||
// The details of the remote user's server is saved to a file so that future messages can be delivered to the follower.
|
||||
// An accept request is cryptographically signed and POST'd back to the remote server.
|
||||
if ( "Follow" != $inbox_type ) { die(); }
|
||||
|
@ -328,7 +320,7 @@
|
|||
];
|
||||
|
||||
// The Accept is POSTed to the inbox on the server of the user who requested the follow
|
||||
sentMessageToSingle( $follower_inbox, $message );
|
||||
sendMessageToSingle( $follower_inbox, $message );
|
||||
die();
|
||||
}
|
||||
|
||||
|
@ -426,7 +418,6 @@
|
|||
return $headers;
|
||||
}
|
||||
|
||||
|
||||
// User Interface for Homepage.
|
||||
// This creates a basic HTML page. This content appears when someone visits the root of your site.
|
||||
function view( $style ) {
|
||||
|
@ -721,8 +712,12 @@ HTML;
|
|||
$object = $message["object"];
|
||||
$objectHTML = "<a href=\"$object\">{$object}</a>";
|
||||
$messageHTML = "{$timeHTML} {$actorHTML} boosted {$objectHTML}";
|
||||
} else {
|
||||
// Not a message we're interested in displaying. Probably a delete or undo.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Display the message
|
||||
echo "<li><article class=\"h-entry\">{$messageHTML}<br>{$interactHTML}</article></li>";
|
||||
}
|
||||
echo <<< HTML
|
||||
|
@ -963,7 +958,7 @@ HTML;
|
|||
|
||||
// Is this message going to one user? (Usually a Like)
|
||||
if ( isset( $inbox_single ) ) {
|
||||
$messageSent = sentMessageToSingle( $inbox_single, $message );
|
||||
$messageSent = sendMessageToSingle( $inbox_single, $message );
|
||||
} else { // Send to all the user's followers
|
||||
$messageSent = sendMessageToFollowers( $message );
|
||||
}
|
||||
|
@ -979,7 +974,7 @@ HTML;
|
|||
}
|
||||
|
||||
// POST a signed message to a single inbox
|
||||
function sentMessageToSingle( $inbox, $message ) {
|
||||
function sendMessageToSingle( $inbox, $message ) {
|
||||
global $directories;
|
||||
|
||||
$inbox_host = parse_url( $inbox, PHP_URL_HOST );
|
||||
|
@ -1386,7 +1381,7 @@ HTML;
|
|||
}
|
||||
|
||||
// Sign & send the request
|
||||
sentMessageToSingle( $profileInbox, $message );
|
||||
sendMessageToSingle( $profileInbox, $message );
|
||||
|
||||
if ( "Follow" == $action ) {
|
||||
// Save the user's details
|
||||
|
|
Ładowanie…
Reference in New Issue