Initial commit
This commit is contained in:
commit
e747e04af6
|
@ -0,0 +1,2 @@
|
|||
vendor/
|
||||
.phpunit.cache/
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"name": "zoomyboy/matrix-api",
|
||||
"description": "PHP Matrix API to send a message",
|
||||
"type": "library",
|
||||
"require": {
|
||||
"laravel/framework": "^9.0",
|
||||
"guzzlehttp/guzzle": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^7.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Zoomyboy\\MatrixApi\\": "src/"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Philipp Lang",
|
||||
"email": "philipp@zoomyboy.de"
|
||||
}
|
||||
],
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Workbench\\App\\": "workbench/app/",
|
||||
"Workbench\\Database\\Factories\\": "workbench/database/factories/",
|
||||
"Workbench\\Database\\Seeders\\": "workbench/database/seeders/",
|
||||
"Zoomyboy\\MatrixApi\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-autoload-dump": [
|
||||
"@clear",
|
||||
"@prepare"
|
||||
],
|
||||
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
|
||||
"prepare": "@php vendor/bin/testbench package:discover --ansi",
|
||||
"build": "@php vendor/bin/testbench workbench:build --ansi",
|
||||
"serve": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"@build",
|
||||
"@php vendor/bin/testbench serve"
|
||||
],
|
||||
"lint": [
|
||||
"@php vendor/bin/phpstan analyse"
|
||||
]
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'base_url' => env('MATRIX_BASE_URL'),
|
||||
'token' => env('MATRIX_TOKEN'),
|
||||
'room_id' => env('MATRIX_ROOM_ID'),
|
||||
];
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.6/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
cacheResultFile=".phpunit.cache/test-results"
|
||||
executionOrder="depends,defects"
|
||||
forceCoversAnnotation="true"
|
||||
beStrictAboutCoversAnnotation="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
beStrictAboutTodoAnnotatedTests="true"
|
||||
convertDeprecationsToExceptions="true"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
verbose="true">
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory suffix="Test.php">./tests/Unit</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<php>
|
||||
<server name="MATRIX_BASE_URL" value="https://example.com"/>
|
||||
<server name="MATRIX_TOKEN" value="lktzzgggg"/>
|
||||
<server name="MATRIX_ROOM_ID" value="!ttggzzuu:example.com"/>
|
||||
</php>
|
||||
|
||||
</phpunit>
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MatrixApi;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
use Throwable;
|
||||
|
||||
class Matrix
|
||||
{
|
||||
|
||||
public function __construct(private string $baseUrl, private string $roomId, private string $token)
|
||||
{
|
||||
}
|
||||
|
||||
public function message(string $message): void
|
||||
{
|
||||
Http::withToken($this->token)
|
||||
->put("{$this->baseUrl}/_matrix/client/v3/rooms/{$this->roomParam()}/send/m.room.message/{$this->transactionId()}", [
|
||||
'body' => $message,
|
||||
'msgtype' => 'm.text',
|
||||
]);
|
||||
}
|
||||
|
||||
public function exception(Throwable $e): void
|
||||
{
|
||||
$return = '';
|
||||
|
||||
$publicProperties = collect((new ReflectionClass($e))->getProperties(ReflectionProperty::IS_PUBLIC));
|
||||
|
||||
foreach ($publicProperties as $property) {
|
||||
if ($property->name === 'message') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$return .= '<li><b>' . $property->getName() . ':</b> ' . $property->getValue($e) . '</li>';
|
||||
}
|
||||
|
||||
if ($publicProperties->count()) {
|
||||
$return = '<ul>' . $return . '</ul>';
|
||||
}
|
||||
|
||||
$this->message('<p>' . $e->getMessage() . '</p>' . $return);
|
||||
}
|
||||
|
||||
protected function roomParam(): string
|
||||
{
|
||||
return rawurlencode($this->roomId);
|
||||
}
|
||||
|
||||
protected function transactionId(): string
|
||||
{
|
||||
return str()->random(16);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MatrixApi;
|
||||
|
||||
trait ReportsToMatrix
|
||||
{
|
||||
|
||||
public function report(): bool
|
||||
{
|
||||
app(Matrix::class)->exception($this);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MatrixApi;
|
||||
|
||||
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
|
||||
|
||||
class ServiceProvider extends BaseServiceProvider
|
||||
{
|
||||
|
||||
public function register(): void
|
||||
{
|
||||
$this->mergeConfigFrom(__DIR__ . '/../config/matrix.php', 'matrix');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../config/matrix.php' => config_path('matrix.php'),
|
||||
]);
|
||||
|
||||
$this->app->bind(Matrix::class, function ($app) {
|
||||
return new Matrix(config('matrix.base_url'), config('matrix.room_id'), config('matrix.token'));
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
providers:
|
||||
# - Workbench\App\Providers\WorkbenchServiceProvider
|
||||
|
||||
migrations:
|
||||
- workbench/database/migrations
|
||||
|
||||
seeders:
|
||||
- Workbench\Database\Seeders\DatabaseSeeder
|
||||
|
||||
workbench:
|
||||
start: '/'
|
||||
install: true
|
||||
discovers:
|
||||
web: true
|
||||
api: false
|
||||
commands: false
|
||||
components: false
|
||||
views: false
|
||||
build: []
|
||||
assets: []
|
||||
sync: []
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MatrixApi\Tests\Fakes;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class HttpFake
|
||||
{
|
||||
|
||||
public string $roomId;
|
||||
public string $baseUrl;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->roomId = config('matrix.room_id');
|
||||
$this->baseUrl = config('matrix.base_url');
|
||||
}
|
||||
|
||||
public function sendsMessage(): void
|
||||
{
|
||||
|
||||
Http::fake(function ($request) {
|
||||
if ($request->method() !== 'PUT') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!str($request->url())->startsWith("{$this->baseUrl}/_matrix/client/v3/rooms/{$this->roomIdParam()}/send/m.room.message/")) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Http::response(json_encode([
|
||||
'event_id' => str()->random(32),
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
public function assertMessageSent(string $message): void
|
||||
{
|
||||
Http::assertSent(function ($request) use ($message) {
|
||||
if ($request['body'] !== $message) {
|
||||
dump($message, $request['body']);
|
||||
}
|
||||
|
||||
return $request->method() === 'PUT'
|
||||
&& $request['body'] === $message
|
||||
&& $request['msgtype'] === 'm.text'
|
||||
&& str($request->url())->startsWith("{$this->baseUrl}/_matrix/client/v3/rooms/{$this->roomIdParam()}/send/m.room.message/");
|
||||
});
|
||||
}
|
||||
|
||||
protected function roomIdParam(): string
|
||||
{
|
||||
return rawurlencode($this->roomId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MatrixApi\Tests;
|
||||
|
||||
use Orchestra\Testbench\Concerns\WithWorkbench;
|
||||
use Orchestra\Testbench\TestCase as TestbenchTestCase;
|
||||
use Zoomyboy\MatrixApi\ServiceProvider;
|
||||
use Zoomyboy\MatrixApi\Tests\Fakes\HttpFake;
|
||||
|
||||
class TestCase extends TestbenchTestCase
|
||||
{
|
||||
use WithWorkbench;
|
||||
|
||||
public HttpFake $httpFake;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->httpFake = app(HttpFake::class);
|
||||
}
|
||||
|
||||
protected function defineEnvironment($app)
|
||||
{
|
||||
$app->register(ServiceProvider::class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MatrixApi\Tests\Unit;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Client\HttpClientException;
|
||||
use Zoomyboy\MatrixApi\Matrix;
|
||||
use Zoomyboy\MatrixApi\ReportsToMatrix;
|
||||
use Zoomyboy\MatrixApi\Tests\TestCase;
|
||||
|
||||
class MessageTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @covers Matrix
|
||||
*/
|
||||
public function testItSendsMessageViaMethod(): void
|
||||
{
|
||||
$this->httpFake->sendsMessage();
|
||||
|
||||
app(Matrix::class)->message('lalatt');
|
||||
|
||||
$this->httpFake->assertMessageSent('lalatt');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Matrix
|
||||
*/
|
||||
public function testItSendsMessageWithException(): void
|
||||
{
|
||||
$this->httpFake->sendsMessage();
|
||||
|
||||
app(Matrix::class)->exception(new TestException('The error Message'));
|
||||
|
||||
$this->httpFake->assertMessageSent('<p>The error Message</p>');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Matrix
|
||||
*/
|
||||
public function testItSendsExceptionWhenExceptionIsReported(): void
|
||||
{
|
||||
$this->httpFake->sendsMessage();
|
||||
|
||||
try {
|
||||
throw new MatrixException('This is the error');
|
||||
} catch (MatrixException $e) {
|
||||
$e->report();
|
||||
}
|
||||
|
||||
$this->httpFake->assertMessageSent('<p>This is the error</p>');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Matrix
|
||||
*/
|
||||
public function testItSendsExceptionsWithStringParameters(): void
|
||||
{
|
||||
$this->httpFake->sendsMessage();
|
||||
|
||||
app(Matrix::class)->exception((new StringPropertyException('This is the error', '::param content::', 'third param')));
|
||||
|
||||
$this->httpFake->assertMessageSent('<p>This is the error</p><ul><li><b>testParam:</b> ::param content::</li><li><b>thirdParam:</b> third param</li></ul>');
|
||||
}
|
||||
}
|
||||
|
||||
class TestException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
class MatrixException extends Exception
|
||||
{
|
||||
use ReportsToMatrix;
|
||||
}
|
||||
|
||||
class StringPropertyException extends HttpClientException
|
||||
{
|
||||
|
||||
public function __construct(public $message, public string $testParam, public string $thirdParam)
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
.env
|
||||
.env.dusk
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Workbench\App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class WorkbenchServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Workbench\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register API routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider and all of them will
|
||||
| be assigned to the "api" middleware group. Make something great!
|
||||
|
|
||||
*/
|
||||
|
||||
// Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
||||
// return $request->user();
|
||||
// });
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Console Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is where you may define all of your Closure based console
|
||||
| commands. Each Closure is bound to a command instance allowing a
|
||||
| simple approach to interacting with each command's IO methods.
|
||||
|
|
||||
*/
|
||||
|
||||
// Artisan::command('inspire', function () {
|
||||
// $this->comment(Inspiring::quote());
|
||||
// })->purpose('Display an inspiring quote');
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register web routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider and all of them will
|
||||
| be assigned to the "web" middleware group. Make something great!
|
||||
|
|
||||
*/
|
||||
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
});
|
Loading…
Reference in New Issue