Bläddra i källkod

Merge pull request #1985 from pixelfed/staging

AP Refactor
daniel 5 år sedan
förälder
incheckning
6350b71cdd

+ 1 - 0
CHANGELOG.md

@@ -9,6 +9,7 @@
 - Updated StatusController, restrict edits to 24 hours ([ae24433b](https://github.com/pixelfed/pixelfed/commit/ae24433b))
 - Updated StatusController, restrict edits to 24 hours ([ae24433b](https://github.com/pixelfed/pixelfed/commit/ae24433b))
 - Updated RateLimit, add max post edits per hour and day ([51fbfcdc](https://github.com/pixelfed/pixelfed/commit/51fbfcdc))
 - Updated RateLimit, add max post edits per hour and day ([51fbfcdc](https://github.com/pixelfed/pixelfed/commit/51fbfcdc))
 - Updated Timeline.vue, move announcements from sidebar to top of timeline ([228f5044](https://github.com/pixelfed/pixelfed/commit/228f5044))
 - Updated Timeline.vue, move announcements from sidebar to top of timeline ([228f5044](https://github.com/pixelfed/pixelfed/commit/228f5044))
+- Updated lexer autolinker and extractor, add support for mentioned usernames containing dashes, periods and underscore characters ([f911c96d](https://github.com/pixelfed/pixelfed/commit/f911c96d))
 
 
 ## [v0.10.8 (2020-01-29)](https://github.com/pixelfed/pixelfed/compare/v0.10.7...v0.10.8)
 ## [v0.10.8 (2020-01-29)](https://github.com/pixelfed/pixelfed/compare/v0.10.7...v0.10.8)
 ### Added
 ### Added

+ 61 - 0
app/Services/ActivityPubDeliveryService.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace App\Services;
+
+use App\Profile;
+use App\Util\ActivityPub\Helpers;
+use App\Util\ActivityPub\HttpSignature;
+
+class ActivityPubDeliveryService {
+
+	public $sender;
+	public $to;
+	public $payload;
+
+	public static function queue()
+	{
+		return new self;
+	}
+
+	public function from($profile)
+	{
+		$this->sender = $profile;
+		return $this;
+	}
+
+	public function to(string $url)
+	{
+		$this->to = $url;
+		return $this;
+	}
+
+	public function payload($payload)
+	{
+		$this->payload = $payload;
+		return $this;
+	}
+
+	public function send()
+	{
+		return $this->queueDelivery();
+	}
+
+	protected function queueDelivery()
+	{
+		abort_if(!$this->sender || !$this->to || !$this->payload, 400);
+		abort_if(!Helpers::validateUrl($this->to), 400);
+		abort_if($this->sender->domain != null || $this->sender->status != null, 400);
+
+		$body = $this->payload;
+		$payload = json_encode($body);
+		$headers = HttpSignature::sign($this->sender, $this->to, $body);
+
+		$ch = curl_init($this->to);
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+		curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
+		curl_setopt($ch, CURLOPT_HEADER, true);
+		curl_exec($ch);
+	}
+
+}

+ 7 - 29
app/Util/ActivityPub/Helpers.php

@@ -23,6 +23,7 @@ use App\Jobs\ImageOptimizePipeline\{ImageOptimize,ImageThumbnail};
 use App\Jobs\StatusPipeline\NewStatusPipeline;
 use App\Jobs\StatusPipeline\NewStatusPipeline;
 use App\Util\ActivityPub\HttpSignature;
 use App\Util\ActivityPub\HttpSignature;
 use Illuminate\Support\Str;
 use Illuminate\Support\Str;
+use App\Services\ActivityPubDeliveryService;
 
 
 class Helpers {
 class Helpers {
 
 
@@ -435,35 +436,12 @@ class Helpers {
 		return self::profileFirstOrNew($url);
 		return self::profileFirstOrNew($url);
 	}
 	}
 
 
-	public static function sendSignedObject($senderProfile, $url, $body)
+	public static function sendSignedObject($profile, $url, $body)
 	{
 	{
-		abort_if(!self::validateUrl($url), 400);
-
-		$payload = json_encode($body);
-		$headers = HttpSignature::sign($senderProfile, $url, $body);
-
-		$ch = curl_init($url);
-		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
-		curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
-		curl_setopt($ch, CURLOPT_HEADER, true);
-		$response = curl_exec($ch);
-		return;
-	}
-
-	public static function apSignedPostRequest($senderProfile, $url, $body)
-	{
-		abort_if(!self::validateUrl($url), 400);
-
-		$payload = json_encode($body);
-		$headers = HttpSignature::sign($senderProfile, $url, $body);
-
-		$ch = curl_init($url);
-		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
-		curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
-		curl_setopt($ch, CURLOPT_HEADER, true);
-		$response = curl_exec($ch);
-		return;
+		ActivityPubDeliveryService::queue()
+			->from($profile)
+			->to($url)
+			->payload($body)
+			->send();
 	}
 	}
 }
 }

+ 2 - 2
app/Util/Lexer/Regex.php

@@ -162,9 +162,9 @@ abstract class Regex
         //      look-ahead capture here and don't append $after when we return.
         //      look-ahead capture here and don't append $after when we return.
         $tmp['valid_mention_preceding_chars'] = '([^a-zA-Z0-9_!#\$%&*@@\/]|^|(?:^|[^a-z0-9_+~.-])RT:?)';
         $tmp['valid_mention_preceding_chars'] = '([^a-zA-Z0-9_!#\$%&*@@\/]|^|(?:^|[^a-z0-9_+~.-])RT:?)';
 
 
-        $re['valid_mentions_or_lists'] = '/'.$tmp['valid_mention_preceding_chars'].'(['.$tmp['at_signs'].'])([a-z0-9_]{1,20})((\/[a-z][a-z0-9_\-]{0,24})?(?=(.*|$))(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i';
+        $re['valid_mentions_or_lists'] = '/'.$tmp['valid_mention_preceding_chars'].'(['.$tmp['at_signs'].'])([a-z0-9_\-.]{1,20})((\/[a-z][a-z0-9_\-]{0,24})?(?=(.*|$))(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i';
 
 
-        $re['valid_reply'] = '/^(?:['.$tmp['spaces'].'])*['.$tmp['at_signs'].']([a-z0-9_]{1,20})(?=(.*|$))/iu';
+        $re['valid_reply'] = '/^(?:['.$tmp['spaces'].'])*['.$tmp['at_signs'].']([a-z0-9_\-.]{1,20})(?=(.*|$))/iu';
         $re['end_mention_match'] = '/\A(?:['.$tmp['at_signs'].']|['.$tmp['latin_accents'].']|:\/\/)/iu';
         $re['end_mention_match'] = '/\A(?:['.$tmp['at_signs'].']|['.$tmp['latin_accents'].']|:\/\/)/iu';
 
 
         // URL related hash regex collection
         // URL related hash regex collection

+ 179 - 0
tests/Unit/Lexer/UsernameTest.php

@@ -0,0 +1,179 @@
+<?php
+
+namespace Tests\Unit\Lexer;
+
+use Tests\TestCase;
+use Illuminate\Foundation\Testing\WithFaker;
+use App\Util\Lexer\Autolink;
+use App\Util\Lexer\Extractor;
+
+class UsernameTest extends TestCase
+{
+	/** @test **/
+	public function genericUsername()
+	{
+		$username = '@dansup';
+		$entities = Extractor::create()->extract($username);
+		$autolink = Autolink::create()->autolink($username);
+		$expectedAutolink = '<a class="u-url mention" href="https://pixelfed.dev/dansup" rel="external nofollow noopener" target="_blank">@dansup</a>';
+		$expectedEntity = [
+			"hashtags" => [],
+			"urls" => [],
+			"mentions" => [
+				"dansup",
+			],
+			"replyto" => "dansup",
+			"hashtags_with_indices" => [],
+			"urls_with_indices" => [],
+			"mentions_with_indices" => [
+				[
+					"screen_name" => "dansup",
+					"indices" => [
+						0,
+						7,
+					],
+				],
+			],
+		];
+		$this->assertEquals($expectedAutolink, $autolink);
+		$this->assertEquals($expectedEntity, $entities);
+	}
+
+	/** @test **/
+	public function usernameWithPeriod()
+	{
+		$username = '@dansup.two';
+		$autolink = Autolink::create()->autolink($username);
+		$entities = Extractor::create()->extract($username);
+		$expectedAutolink = '<a class="u-url mention" href="https://pixelfed.dev/dansup.two" rel="external nofollow noopener" target="_blank">@dansup.two</a>';
+		$expectedEntity = [
+			"hashtags" => [],
+			"urls" => [],
+			"mentions" => [
+				"dansup.two",
+			],
+			"replyto" => "dansup.two",
+			"hashtags_with_indices" => [],
+			"urls_with_indices" => [],
+			"mentions_with_indices" => [
+				[
+					"screen_name" => "dansup.two",
+					"indices" => [
+						0,
+						11,
+					],
+				],
+			],
+		];
+		$this->assertEquals($expectedAutolink, $autolink);
+		$this->assertEquals($expectedEntity, $entities);
+	}
+
+	/** @test **/
+	public function usernameWithDash()
+	{
+		$username = '@dansup-too';
+		$autolink = Autolink::create()->autolink($username);
+		$entities = Extractor::create()->extract($username);
+		$expectedAutolink = '<a class="u-url mention" href="https://pixelfed.dev/dansup-too" rel="external nofollow noopener" target="_blank">@dansup-too</a>';
+		$expectedEntity = [
+			"hashtags" => [],
+			"urls" => [],
+			"mentions" => [
+				"dansup-too",
+			],
+			"replyto" => "dansup-too",
+			"hashtags_with_indices" => [],
+			"urls_with_indices" => [],
+			"mentions_with_indices" => [
+				[
+					"screen_name" => "dansup-too",
+					"indices" => [
+						0,
+						11,
+					],
+				],
+			],
+		];
+		$this->assertEquals($expectedAutolink, $autolink);
+		$this->assertEquals($expectedEntity, $entities);
+	}
+
+	/** @test **/
+	public function usernameWithUnderscore()
+	{
+		$username = '@dansup_too';
+		$autolink = Autolink::create()->autolink($username);
+		$entities = Extractor::create()->extract($username);
+		$expectedAutolink = '<a class="u-url mention" href="https://pixelfed.dev/dansup_too" rel="external nofollow noopener" target="_blank">@dansup_too</a>';
+		$expectedEntity = [
+			"hashtags" => [],
+			"urls" => [],
+			"mentions" => [
+				"dansup_too",
+			],
+			"replyto" => "dansup_too",
+			"hashtags_with_indices" => [],
+			"urls_with_indices" => [],
+			"mentions_with_indices" => [
+				[
+					"screen_name" => "dansup_too",
+					"indices" => [
+						0,
+						11,
+					],
+				],
+			],
+		];
+		$this->assertEquals($expectedAutolink, $autolink);
+		$this->assertEquals($expectedEntity, $entities);
+	}
+
+	/** @test **/
+	public function multipleMentions()
+	{
+		$text = 'hello @dansup and @pixelfed.team from @username_underscore';
+		$autolink = Autolink::create()->autolink($text);
+		$entities = Extractor::create()->extract($text);
+		$expectedAutolink = 'hello <a class="u-url mention" href="https://pixelfed.dev/dansup" rel="external nofollow noopener" target="_blank">@dansup</a> and <a class="u-url mention" href="https://pixelfed.dev/pixelfed.team" rel="external nofollow noopener" target="_blank">@pixelfed.team</a> from <a class="u-url mention" href="https://pixelfed.dev/username_underscore" rel="external nofollow noopener" target="_blank">@username_underscore</a>';
+		$expectedEntity = [
+			"hashtags" => [],
+			"urls" => [],
+			"mentions" => [
+				"dansup",
+				"pixelfed.team",
+				"username_underscore",
+			],
+			"replyto" => null,
+			"hashtags_with_indices" => [],
+			"urls_with_indices" => [],
+			"mentions_with_indices" => [
+				[
+					"screen_name" => "dansup",
+					"indices" => [
+						6,
+						13,
+					],
+				],
+				[
+					"screen_name" => "pixelfed.team",
+					"indices" => [
+						18,
+						32,
+					],
+				],
+				[
+					"screen_name" => "username_underscore",
+					"indices" => [
+						38,
+						58,
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expectedAutolink, $autolink);
+		$this->assertEquals($expectedEntity, $entities);
+	}
+
+}