Basic follow support
rodzic
195be1afea
commit
b69c08e5bb
113
index.php
113
index.php
|
@ -106,6 +106,10 @@
|
||||||
send(); // API for posting content to the Fediverse
|
send(); // API for posting content to the Fediverse
|
||||||
case "outbox":
|
case "outbox":
|
||||||
outbox(); // Optional. Dynamic.
|
outbox(); // Optional. Dynamic.
|
||||||
|
case "follow":
|
||||||
|
follow(); // User interface for following an external user
|
||||||
|
case "follow_user":
|
||||||
|
follow_user(); // API for following a user
|
||||||
case "/":
|
case "/":
|
||||||
home(); // Optional. Can be dynamic
|
home(); // Optional. Can be dynamic
|
||||||
default:
|
default:
|
||||||
|
@ -713,7 +717,7 @@ HTML;
|
||||||
// This goes in the generic "tag" property
|
// This goes in the generic "tag" property
|
||||||
// TODO: Add this to the CC field
|
// TODO: Add this to the CC field
|
||||||
foreach ( $usernames as $username ) {
|
foreach ( $usernames as $username ) {
|
||||||
list( $null, $user, $domain ) = explode( "@", $username );
|
list( , $user, $domain ) = explode( "@", $username );
|
||||||
$tags[] = array(
|
$tags[] = array(
|
||||||
"type" => "Mention",
|
"type" => "Mention",
|
||||||
"href" => "https://{$domain}/@{$user}",
|
"href" => "https://{$domain}/@{$user}",
|
||||||
|
@ -773,6 +777,113 @@ HTML;
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This creates a UI for the user to follow another user
|
||||||
|
function follow() {
|
||||||
|
echo <<< HTML
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-GB">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Follow</title>
|
||||||
|
<style>
|
||||||
|
*{font-family:sans-serif;font-size:1.1em;}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form action="/follow_user" method="post" enctype="multipart/form-data">
|
||||||
|
<label for="user">User to follow</label>
|
||||||
|
<input name="user" id="user" type="text" size="32" placeholder="@user@example.com" /><br>
|
||||||
|
<label for="password">Password</label><br>
|
||||||
|
<input name="password" id="password" type="password" size="32"><br>
|
||||||
|
<input type="submit" value="Post Message">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTML;
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This receives a request to follow an external user
|
||||||
|
// It looks up the external user's details
|
||||||
|
// Then it sends a follow request
|
||||||
|
// If the request is accepted, it saves the details in `data/following/` as a JSON file
|
||||||
|
function follow_user() {
|
||||||
|
global $password, $server, $username, $key_private;
|
||||||
|
|
||||||
|
// Does the posted password match the stored password?
|
||||||
|
if( $password != $_POST["password"] ) { echo "Wrong Password!"; die(); }
|
||||||
|
|
||||||
|
// Get the posted content
|
||||||
|
$user = $_POST["user"];
|
||||||
|
|
||||||
|
// Split the user into username and server
|
||||||
|
list( , $follow_name, $follow_server ) = explode( "@", $user );
|
||||||
|
|
||||||
|
// Get the Webfinger
|
||||||
|
$webfingerURl = "https://{$follow_server}/.well-known/webfinger?resource=acct:{$follow_name}@{$follow_server}";
|
||||||
|
$webfingerJSON = file_get_contents( $webfingerURl );
|
||||||
|
$webfinger = json_decode( $webfingerJSON, true );
|
||||||
|
|
||||||
|
foreach( $webfinger["links"] as $link ) {
|
||||||
|
if ( "self" == $link["rel"] ) {
|
||||||
|
$profileURl = $link["href"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !isset( $profileURl ) ) { echo "No profile"; die(); }
|
||||||
|
|
||||||
|
// Get the user's details
|
||||||
|
// This request does not need to be signed. But it does need to specify that it wants a JSON response
|
||||||
|
$context = stream_context_create(
|
||||||
|
[ "http" => [ "header" => "Accept: application/activity+json" ] ]
|
||||||
|
);
|
||||||
|
$profileJSON = file_get_contents( $profileURl, false, $context );
|
||||||
|
$profileData = json_decode( $profileJSON, true );
|
||||||
|
|
||||||
|
// Get the user's inbox
|
||||||
|
$profileInbox = $profileData["inbox"];
|
||||||
|
$inbox_host = parse_url( $profileInbox, PHP_URL_HOST );
|
||||||
|
$inbox_path = parse_url( $profileInbox, PHP_URL_PATH );
|
||||||
|
|
||||||
|
// Create a follow request
|
||||||
|
$guid = uuid();
|
||||||
|
$message = [
|
||||||
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id" => "https://{$server}/{$guid}",
|
||||||
|
"type" => "Follow",
|
||||||
|
"actor" => "https://{$server}/{$username}",
|
||||||
|
"object" => $profileURl
|
||||||
|
];
|
||||||
|
|
||||||
|
// Sign a request follow
|
||||||
|
// The Accept is POSTed to the inbox on the server of the user who requested the follow
|
||||||
|
// Get the signed headers
|
||||||
|
$headers = generate_signed_headers( $message, $inbox_host, $inbox_path, "POST" );
|
||||||
|
|
||||||
|
// POST the message and header to the requester's inbox
|
||||||
|
$ch = curl_init( $profileInbox );
|
||||||
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
||||||
|
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
|
||||||
|
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $message ) );
|
||||||
|
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
||||||
|
curl_exec( $ch );
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if( curl_errno( $ch ) ) {
|
||||||
|
file_put_contents( "error.txt", curl_error( $ch ) );
|
||||||
|
}
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
// Save the user's details
|
||||||
|
// Save headers and request data to the timestamped file in the logs directory
|
||||||
|
if( ! is_dir( "data/following" ) ) { mkdir( "data"); mkdir( "data/following"); }
|
||||||
|
$following_filename = urlencode( $profileURl );
|
||||||
|
file_put_contents( "data/following/{$following_filename}.json", $profileJSON );
|
||||||
|
|
||||||
|
// Render the JSON so the user can see the POST has worked
|
||||||
|
header( "Location: https://{$server}/data/following/" . urlencode( $following_filename ) . ".json" );
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
// Verify the signature sent with the message.
|
// Verify the signature sent with the message.
|
||||||
// This is optional
|
// This is optional
|
||||||
// It is very confusing
|
// It is very confusing
|
||||||
|
|
Ładowanie…
Reference in New Issue