From 98f7dc72f0580536b698cda068a0c389a069702e Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 1 Sep 2024 11:28:08 +0200 Subject: [PATCH 1/4] prepare schedule command --- app/Console/Commands/TweetPostCommand.php | 37 +++ app/Console/ConsoleKernel.php | 16 ++ app/Http/Controllers/ShareBoardController.php | 4 +- app/Providers/AppServiceProvider.php | 27 +++ bootstrap/app.php | 9 +- composer.json | 1 + composer.lock | 228 +++++++++++++----- ...asons-why-doctrine-is-alive-and-kicking.md | 5 +- resources/views/share_board.blade.php | 2 +- routes/console.php | 5 + 10 files changed, 266 insertions(+), 68 deletions(-) create mode 100644 app/Console/Commands/TweetPostCommand.php create mode 100644 app/Console/ConsoleKernel.php create mode 100644 routes/console.php diff --git a/app/Console/Commands/TweetPostCommand.php b/app/Console/Commands/TweetPostCommand.php new file mode 100644 index 00000000000..39ef11e07c2 --- /dev/null +++ b/app/Console/Commands/TweetPostCommand.php @@ -0,0 +1,37 @@ +twitterClient->tweet()->create()->performRequest([ + 'text' => 'Test Tweet... ', + ]); + + $this->info('[DRY-RUN] Tweet is done!'); + } +} diff --git a/app/Console/ConsoleKernel.php b/app/Console/ConsoleKernel.php new file mode 100644 index 00000000000..0348808c7b3 --- /dev/null +++ b/app/Console/ConsoleKernel.php @@ -0,0 +1,16 @@ +command('app:tweet-post')->weekdays()->at('08:00')->timezone('Europe/Paris'); + } +} diff --git a/app/Http/Controllers/ShareBoardController.php b/app/Http/Controllers/ShareBoardController.php index 7d35283f5cd..50fb5bf04c1 100644 --- a/app/Http/Controllers/ShareBoardController.php +++ b/app/Http/Controllers/ShareBoardController.php @@ -15,13 +15,13 @@ final class ShareBoardController extends Controller { public function __construct( private readonly PostRepository $postRepository, - private readonly Client $client + private readonly Client $client, ) { } public function __invoke(): View { - $randomPosts = $this->postRepository->fetchRandom(2); + $randomPosts = $this->postRepository->fetchRandom(4); // @todo do parallel :) $postTweets = []; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 4c01174c03e..626663d6259 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -19,5 +19,32 @@ public function register(): void return OpenAI::client($openApiKey); }); + + $this->app->singleton(\Noweh\TwitterApi\Client::class, function (): \Noweh\TwitterApi\Client { + $twitterAppId = getenv('TWITTER_APP_ID'); + $twitterApiKey = getenv('TWITTER_API_KEY'); + $twitterApiSecret = getenv('TWITTER_API_SECRET'); + $twitterAccessToken = getenv('TWITTER_ACCESS_TOKEN'); + $twitterAccessSecret = getenv('TWITTER_ACCESS_SECRET'); + $twitterBearerToken = getenv('TWITTER_BEARER_TOKEN'); + + Assert::string($twitterAppId); + Assert::string($twitterApiKey); + Assert::string($twitterApiSecret); + Assert::string($twitterAccessToken); + Assert::string($twitterAccessSecret); + Assert::string($twitterBearerToken); + + return new \Noweh\TwitterApi\Client([ + 'account_id' => $twitterAppId, + 'access_token' => $twitterAccessToken, + 'access_token_secret' => $twitterAccessSecret, + 'consumer_key' => $twitterApiKey, + 'consumer_secret' => $twitterApiSecret, + 'bearer_token' => $twitterBearerToken, + // Optional + 'free_mode' => false, + ]); + }); } } diff --git a/bootstrap/app.php b/bootstrap/app.php index 8b9de01b3d7..bb921ac7bba 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -13,11 +13,8 @@ ]) ->withRouting( web: __DIR__.'/../routes/web.php', + commands: __DIR__.'/../routes/console.php', ) - ->withMiddleware(function (Middleware $middleware): void { - // - }) - ->withExceptions(function (Exceptions $exceptions): void { - // - }) + ->withMiddleware(function (Middleware $middleware): void {}) + ->withExceptions(function (Exceptions $exceptions): void {}) ->create(); diff --git a/composer.json b/composer.json index 5298526aace..75077a59f84 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "league/commonmark": "^2.4.1", "nesbot/carbon": "^2.8", "nette/utils": "^4.0", + "noweh/twitter-api-v2-php": "^3.5", "openai-php/client": "^0.10.1", "symfony/yaml": "^6.4" }, diff --git a/composer.lock b/composer.lock index 771f9a29add..d648898e2ab 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f60d507a9fee8e4af001a69b952fcf13", + "content-hash": "6fd8b8db05ca9364f3d64449e10cff2a", "packages": [ { "name": "brick/math", @@ -765,6 +765,65 @@ ], "time": "2024-07-24T11:22:20+00:00" }, + { + "name": "guzzlehttp/oauth-subscriber", + "version": "0.6.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/oauth-subscriber.git", + "reference": "8d6cab29f8397e5712d00a383eeead36108a3c1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/oauth-subscriber/zipball/8d6cab29f8397e5712d00a383eeead36108a3c1f", + "reference": "8d6cab29f8397e5712d00a383eeead36108a3c1f", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.5|^7.2", + "guzzlehttp/psr7": "^1.7|^2.0", + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|^9.3.3" + }, + "suggest": { + "ext-openssl": "Required to sign using RSA-SHA1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.6-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Subscriber\\Oauth\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle OAuth 1.0 subscriber", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "oauth" + ], + "support": { + "issues": "https://github.com/guzzle/oauth-subscriber/issues", + "source": "https://github.com/guzzle/oauth-subscriber/tree/0.6.0" + }, + "time": "2021-07-13T12:01:32+00:00" + }, { "name": "guzzlehttp/promises", "version": "2.0.3", @@ -2169,6 +2228,65 @@ }, "time": "2024-08-07T15:39:19+00:00" }, + { + "name": "noweh/twitter-api-v2-php", + "version": "3.5.0", + "source": { + "type": "git", + "url": "https://github.com/noweh/twitter-api-v2-php.git", + "reference": "9af2a88efdc9bac49c2477b412a6c144dfea7f42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/noweh/twitter-api-v2-php/zipball/9af2a88efdc9bac49c2477b412a6c144dfea7f42", + "reference": "9af2a88efdc9bac49c2477b412a6c144dfea7f42", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "guzzlehttp/guzzle": "^7.5.0", + "guzzlehttp/oauth-subscriber": "^0.6.0", + "php": ">=7.4" + }, + "require-dev": { + "phpstan/phpstan": "^1.9.14", + "phpunit/php-code-coverage": "^9.2.24", + "phpunit/phpunit": "^9.6.3", + "vlucas/phpdotenv": "^v5.5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Noweh\\TwitterApi\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Julien Schmitt", + "email": "jschmitt95@protonmail.com" + }, + { + "name": "Martin Zeitler", + "homepage": "https://github.com/syslogic" + } + ], + "description": "This library provides methods for sending messages to Twitter and receiving statuses.", + "keywords": [ + "api", + "php", + "twitter" + ], + "support": { + "issues": "https://github.com/noweh/twitter-api-v2-php/issues", + "source": "https://github.com/noweh/twitter-api-v2-php/tree/3.5.0" + }, + "time": "2024-04-29T14:39:44+00:00" + }, { "name": "nunomaduro/termwind", "version": "v2.0.1", @@ -3198,16 +3316,16 @@ }, { "name": "symfony/console", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9" + "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9", - "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9", + "url": "https://api.github.com/repos/symfony/console/zipball/1eed7af6961d763e7832e874d7f9b21c3ea9c111", + "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111", "shasum": "" }, "require": { @@ -3271,7 +3389,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.3" + "source": "https://github.com/symfony/console/tree/v7.1.4" }, "funding": [ { @@ -3287,7 +3405,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-08-15T22:48:53+00:00" }, { "name": "symfony/css-selector", @@ -3654,16 +3772,16 @@ }, { "name": "symfony/finder", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "717c6329886f32dc65e27461f80f2a465412fdca" + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/717c6329886f32dc65e27461f80f2a465412fdca", - "reference": "717c6329886f32dc65e27461f80f2a465412fdca", + "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", "shasum": "" }, "require": { @@ -3698,7 +3816,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.3" + "source": "https://github.com/symfony/finder/tree/v7.1.4" }, "funding": [ { @@ -3714,7 +3832,7 @@ "type": "tidelift" } ], - "time": "2024-07-24T07:08:44+00:00" + "time": "2024-08-13T14:28:19+00:00" }, { "name": "symfony/http-foundation", @@ -3795,16 +3913,16 @@ }, { "name": "symfony/http-kernel", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "db9702f3a04cc471ec8c70e881825db26ac5f186" + "reference": "6efcbd1b3f444f631c386504fc83eeca25963747" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/db9702f3a04cc471ec8c70e881825db26ac5f186", - "reference": "db9702f3a04cc471ec8c70e881825db26ac5f186", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6efcbd1b3f444f631c386504fc83eeca25963747", + "reference": "6efcbd1b3f444f631c386504fc83eeca25963747", "shasum": "" }, "require": { @@ -3889,7 +4007,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.3" + "source": "https://github.com/symfony/http-kernel/tree/v7.1.4" }, "funding": [ { @@ -3905,7 +4023,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T14:58:15+00:00" + "time": "2024-08-30T17:02:28+00:00" }, { "name": "symfony/mailer", @@ -3989,16 +4107,16 @@ }, { "name": "symfony/mime", - "version": "v7.1.2", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "26a00b85477e69a4bab63b66c5dce64f18b0cbfc" + "reference": "ccaa6c2503db867f472a587291e764d6a1e58758" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/26a00b85477e69a4bab63b66c5dce64f18b0cbfc", - "reference": "26a00b85477e69a4bab63b66c5dce64f18b0cbfc", + "url": "https://api.github.com/repos/symfony/mime/zipball/ccaa6c2503db867f472a587291e764d6a1e58758", + "reference": "ccaa6c2503db867f472a587291e764d6a1e58758", "shasum": "" }, "require": { @@ -4053,7 +4171,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.1.2" + "source": "https://github.com/symfony/mime/tree/v7.1.4" }, "funding": [ { @@ -4069,7 +4187,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-08-13T14:28:19+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4844,16 +4962,16 @@ }, { "name": "symfony/routing", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "8a908a3f22d5a1b5d297578c2ceb41b02fa916d0" + "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8a908a3f22d5a1b5d297578c2ceb41b02fa916d0", - "reference": "8a908a3f22d5a1b5d297578c2ceb41b02fa916d0", + "url": "https://api.github.com/repos/symfony/routing/zipball/1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", + "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", "shasum": "" }, "require": { @@ -4905,7 +5023,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.1.3" + "source": "https://github.com/symfony/routing/tree/v7.1.4" }, "funding": [ { @@ -4921,7 +5039,7 @@ "type": "tidelift" } ], - "time": "2024-07-17T06:10:24+00:00" + "time": "2024-08-29T08:16:25+00:00" }, { "name": "symfony/service-contracts", @@ -5008,16 +5126,16 @@ }, { "name": "symfony/string", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ea272a882be7f20cad58d5d78c215001617b7f07" + "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ea272a882be7f20cad58d5d78c215001617b7f07", - "reference": "ea272a882be7f20cad58d5d78c215001617b7f07", + "url": "https://api.github.com/repos/symfony/string/zipball/6cd670a6d968eaeb1c77c2e76091c45c56bc367b", + "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b", "shasum": "" }, "require": { @@ -5075,7 +5193,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.3" + "source": "https://github.com/symfony/string/tree/v7.1.4" }, "funding": [ { @@ -5091,7 +5209,7 @@ "type": "tidelift" } ], - "time": "2024-07-22T10:25:37+00:00" + "time": "2024-08-12T09:59:40+00:00" }, { "name": "symfony/translation", @@ -5268,16 +5386,16 @@ }, { "name": "symfony/uid", - "version": "v7.1.1", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "bb59febeecc81528ff672fad5dab7f06db8c8277" + "reference": "82177535395109075cdb45a70533aa3d7a521cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/bb59febeecc81528ff672fad5dab7f06db8c8277", - "reference": "bb59febeecc81528ff672fad5dab7f06db8c8277", + "url": "https://api.github.com/repos/symfony/uid/zipball/82177535395109075cdb45a70533aa3d7a521cdf", + "reference": "82177535395109075cdb45a70533aa3d7a521cdf", "shasum": "" }, "require": { @@ -5322,7 +5440,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.1.1" + "source": "https://github.com/symfony/uid/tree/v7.1.4" }, "funding": [ { @@ -5338,20 +5456,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-08-12T09:59:40+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "86af4617cca75a6e28598f49ae0690f3b9d4591f" + "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/86af4617cca75a6e28598f49ae0690f3b9d4591f", - "reference": "86af4617cca75a6e28598f49ae0690f3b9d4591f", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a5fa7481b199090964d6fd5dab6294d5a870c7aa", + "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa", "shasum": "" }, "require": { @@ -5405,7 +5523,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.4" }, "funding": [ { @@ -5421,20 +5539,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-08-30T16:12:47+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.8", + "version": "v6.4.11", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "52903de178d542850f6f341ba92995d3d63e60c9" + "reference": "be37e7f13195e05ab84ca5269365591edd240335" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/52903de178d542850f6f341ba92995d3d63e60c9", - "reference": "52903de178d542850f6f341ba92995d3d63e60c9", + "url": "https://api.github.com/repos/symfony/yaml/zipball/be37e7f13195e05ab84ca5269365591edd240335", + "reference": "be37e7f13195e05ab84ca5269365591edd240335", "shasum": "" }, "require": { @@ -5477,7 +5595,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.8" + "source": "https://github.com/symfony/yaml/tree/v6.4.11" }, "funding": [ { @@ -5493,7 +5611,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-08-12T09:55:28+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", diff --git a/resources/posts/2018/2018-07-09-6-reasons-why-doctrine-is-alive-and-kicking.md b/resources/posts/2018/2018-07-09-6-reasons-why-doctrine-is-alive-and-kicking.md index ae33a515f4f..668987f1500 100644 --- a/resources/posts/2018/2018-07-09-6-reasons-why-doctrine-is-alive-and-kicking.md +++ b/resources/posts/2018/2018-07-09-6-reasons-why-doctrine-is-alive-and-kicking.md @@ -2,12 +2,10 @@ id: 121 title: "6 Reasons Why Doctrine is Alive and Kicking" perex: | - Almost 1,5 year ago I wrote [Why is Doctrine Dying](/blog/2017/03/27/why-is-doctrine-dying/). I didn't use *dead*, because it's is just state of time being. Open-source projects - like people - tend to find themselves on the top, being stuck or struggling with the right path from time to time. It's a completely normal process of evolution. - + Almost 1,5 year ago I wrote *Why is Doctrine Dying*. I didn't use *dead*, because it's is just state of time being. Open-source projects - like people - tend to find themselves on the top, being stuck or struggling with the right path from time to time. It's a completely normal process of evolution. I don't know if that post helped it, but since then many **things changed for better in Doctrine project**. Saying that this post deprecates my old view and celebrate changes. - **May this be an inspiration for open-source projects that find themselves stuck and the maintainers that find themselves unhappy**. --- @@ -107,4 +105,3 @@ Packages **tagging** is like [publishing a book](https://www.doctrine-project.or And that's all folks. **I'm happy Doctrine is moving forward to the version 3.0 and I really look forward to it** - it will run on PHP 7.2, one more sandbag dropped to make code better. How is your project doing? What do you do when you feel stuck for a while? Let me know in the comments. - diff --git a/resources/views/share_board.blade.php b/resources/views/share_board.blade.php index 12a53b1cc73..246968a7f4d 100644 --- a/resources/views/share_board.blade.php +++ b/resources/views/share_board.blade.php @@ -11,7 +11,7 @@
@foreach ($postTweets as $postTweet)
-
+
diff --git a/routes/console.php b/routes/console.php new file mode 100644 index 00000000000..24196b97ba5 --- /dev/null +++ b/routes/console.php @@ -0,0 +1,5 @@ +weekdays()->at('08:00')->timezone('Europe/Paris'); From 42eb3aa50bcfd15738a37bb617e6083bd4702efd Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 1 Sep 2024 13:14:23 +0200 Subject: [PATCH 2/4] tidy up command --- .env.local | 16 ++++++++++ app/Console/Commands/TweetPostCommand.php | 8 +++-- app/Enum/GptModel.php | 16 ++++++++++ app/Http/Controllers/ShareBoardController.php | 23 ++----------- app/Providers/AppServiceProvider.php | 8 +++-- app/Socials/PostTweetGenerator.php | 32 +++++++++++++++++++ composer.json | 6 ++-- 7 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 app/Enum/GptModel.php create mode 100644 app/Socials/PostTweetGenerator.php diff --git a/.env.local b/.env.local index 7669acd5b67..b576362068a 100644 --- a/.env.local +++ b/.env.local @@ -5,3 +5,19 @@ APP_URL=http://localhost # required for Laravel defautlst to work DB_CONNECTION=sqlite + +# @note this must be a use api key, not a project one +OPENAI_API_KEY="" + +# regenerated 2024-08-31 +TWITTER_API_KEY="" +TWITTER_API_SECRET="" + +TWITTER_ACCESS_TOKEN="" +TWITTER_ACCESS_SECRET="" + +TWITTER_BEARER_TOKEN="" +TWITTER_APP_ID="" + +TWITTER_CLIENT_ID="" +TWITTER_CLIENT_SECRET="" diff --git a/app/Console/Commands/TweetPostCommand.php b/app/Console/Commands/TweetPostCommand.php index 39ef11e07c2..722bce232b5 100644 --- a/app/Console/Commands/TweetPostCommand.php +++ b/app/Console/Commands/TweetPostCommand.php @@ -4,6 +4,7 @@ namespace App\Console\Commands; +use App\Repository\PostRepository; use Illuminate\Console\Command; use Noweh\TwitterApi\Client; @@ -20,14 +21,17 @@ final class TweetPostCommand extends Command protected $description = 'Tweet daily post'; public function __construct( - private Client $twitterClient, + private readonly Client $twitterClient, + private readonly PostRepository $postRepository, ) { parent::__construct(); } - public function handle() + public function handle(): void { + $randomPost = $this->postRepository->fetchRandom(1); + $twitterResponse = $this->twitterClient->tweet()->create()->performRequest([ 'text' => 'Test Tweet... ', ]); diff --git a/app/Enum/GptModel.php b/app/Enum/GptModel.php new file mode 100644 index 00000000000..19ed3ef23ef --- /dev/null +++ b/app/Enum/GptModel.php @@ -0,0 +1,16 @@ +createTweetForPost($randomPost); + $tweet = $this->postTweetGenerator->generateTweet($randomPost); $postTweets[] = new PostTweet($tweet, $randomPost); } @@ -35,20 +34,4 @@ public function __invoke(): View 'postTweets' => $postTweets, ]); } - - private function createTweetForPost(Post $post): string - { - $createResponse = $this->client->chat()->create([ - // @see https://platform.openai.com/docs/models - 'model' => 'gpt-4o-mini', - 'messages' => [ - [ - 'role' => 'user', - 'content' => 'Hello! I need help making a short engaging tweet for a blog post. Also add an emoji. No hash tags, no links, no quotes. Fit it 100-120 chars. Here is a blog post: ' . PHP_EOL . PHP_EOL . $post->getContent(), - ], - ], - ]); - - return (string) $createResponse->choices[0]->message->content; - } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 626663d6259..0bd6b966545 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -15,12 +15,16 @@ public function register(): void { $this->app->singleton(Client::class, function (): Client { $openApiKey = getenv('OPENAI_API_KEY'); - Assert::string($openApiKey); + // dev only + if ($openApiKey === null) { + $openApiKey = 'random_key'; + } return OpenAI::client($openApiKey); }); $this->app->singleton(\Noweh\TwitterApi\Client::class, function (): \Noweh\TwitterApi\Client { + $twitterAppId = getenv('TWITTER_APP_ID'); $twitterApiKey = getenv('TWITTER_API_KEY'); $twitterApiSecret = getenv('TWITTER_API_SECRET'); @@ -43,7 +47,7 @@ public function register(): void 'consumer_secret' => $twitterApiSecret, 'bearer_token' => $twitterBearerToken, // Optional - 'free_mode' => false, + // 'free_mode' => false, ]); }); } diff --git a/app/Socials/PostTweetGenerator.php b/app/Socials/PostTweetGenerator.php new file mode 100644 index 00000000000..0b3f694041f --- /dev/null +++ b/app/Socials/PostTweetGenerator.php @@ -0,0 +1,32 @@ +openAIClient->chat()->create([ + 'model' => GptModel::GPT_4O_MINI, + 'messages' => [ + [ + 'role' => 'user', + 'content' => 'Hello! Please make a short engaging tweet for a blog post. Also add an emoji. No hash tags, no links, no quotes. Fit it 100-140 chars. Here is the blog post: ' . PHP_EOL . PHP_EOL . $post->getContent(), + ], + ], + ]); + + return (string) $createResponse->choices[0]->message->content; + } +} diff --git a/composer.json b/composer.json index 75077a59f84..76af70f4d20 100644 --- a/composer.json +++ b/composer.json @@ -8,9 +8,9 @@ "ext-gd": "*", "ext-mbstring": "*", "imagine/imagine": "^1.3", - "laravel/framework": "^11.0", - "league/commonmark": "^2.4.1", - "nesbot/carbon": "^2.8", + "laravel/framework": "^11.21", + "league/commonmark": "^2.5", + "nesbot/carbon": "^2.72", "nette/utils": "^4.0", "noweh/twitter-api-v2-php": "^3.5", "openai-php/client": "^0.10.1", From d9741dafe49517613966f19b6a921f8029643ebd Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 8 Sep 2024 17:15:40 +0200 Subject: [PATCH 3/4] adddefaults --- .env.local | 19 +++++++------- .env.prod | 16 ++++++++++++ app/Providers/AppServiceProvider.php | 38 ++++++++++++---------------- public/hot | 1 - resources/css/app.scss | 22 +++------------- resources/views/homepage.blade.php | 2 +- 6 files changed, 46 insertions(+), 52 deletions(-) delete mode 100644 public/hot diff --git a/.env.local b/.env.local index b576362068a..ae557aa5593 100644 --- a/.env.local +++ b/.env.local @@ -7,17 +7,16 @@ APP_URL=http://localhost DB_CONNECTION=sqlite # @note this must be a use api key, not a project one -OPENAI_API_KEY="" +OPENAI_API_KEY= -# regenerated 2024-08-31 -TWITTER_API_KEY="" -TWITTER_API_SECRET="" +TWITTER_API_KEY= +TWITTER_API_SECRET= -TWITTER_ACCESS_TOKEN="" -TWITTER_ACCESS_SECRET="" +TWITTER_ACCESS_TOKEN= +TWITTER_ACCESS_SECRET= -TWITTER_BEARER_TOKEN="" -TWITTER_APP_ID="" +TWITTER_BEARER_TOKEN= +TWITTER_APP_ID= -TWITTER_CLIENT_ID="" -TWITTER_CLIENT_SECRET="" +TWITTER_CLIENT_ID= +TWITTER_CLIENT_SECRET= diff --git a/.env.prod b/.env.prod index 6b72c4d1843..79ef2f013da 100644 --- a/.env.prod +++ b/.env.prod @@ -5,3 +5,19 @@ APP_URL=https://tomasvotruba.com # required for Laravel defautlst to work DB_CONNECTION=sqlite + +# @note this must be a use api key, not a project one +OPENAI_API_KEY= + +# regenerated 2024-08-31 +TWITTER_API_KEY= +TWITTER_API_SECRET= + +TWITTER_ACCESS_TOKEN= +TWITTER_ACCESS_SECRET= + +TWITTER_BEARER_TOKEN= +TWITTER_APP_ID= + +TWITTER_CLIENT_ID= +TWITTER_CLIENT_SECRET= diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 0bd6b966545..5dd6b2dc03a 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -14,30 +14,26 @@ final class AppServiceProvider extends ServiceProvider public function register(): void { $this->app->singleton(Client::class, function (): Client { - $openApiKey = getenv('OPENAI_API_KEY'); - // dev only - if ($openApiKey === null) { - $openApiKey = 'random_key'; - } - + $openApiKey = env('OPENAI_API_KEY'); + Assert::string($openApiKey, 'OPEN_API_KEY is missing in .env'); return OpenAI::client($openApiKey); }); - $this->app->singleton(\Noweh\TwitterApi\Client::class, function (): \Noweh\TwitterApi\Client { - - $twitterAppId = getenv('TWITTER_APP_ID'); - $twitterApiKey = getenv('TWITTER_API_KEY'); - $twitterApiSecret = getenv('TWITTER_API_SECRET'); - $twitterAccessToken = getenv('TWITTER_ACCESS_TOKEN'); - $twitterAccessSecret = getenv('TWITTER_ACCESS_SECRET'); - $twitterBearerToken = getenv('TWITTER_BEARER_TOKEN'); - Assert::string($twitterAppId); - Assert::string($twitterApiKey); - Assert::string($twitterApiSecret); - Assert::string($twitterAccessToken); - Assert::string($twitterAccessSecret); - Assert::string($twitterBearerToken); + $this->app->singleton(\Noweh\TwitterApi\Client::class, function (): \Noweh\TwitterApi\Client { + $twitterAppId = env('TWITTER_APP_ID'); + $twitterApiKey = env('TWITTER_API_KEY'); + $twitterApiSecret = env('TWITTER_API_SECRET'); + $twitterAccessToken = env('TWITTER_ACCESS_TOKEN'); + $twitterAccessSecret = env('TWITTER_ACCESS_SECRET'); + $twitterBearerToken = env('TWITTER_BEARER_TOKEN'); + + Assert::string($twitterAppId, '"TWITTER_APP_ID" env value is missing in .env'); + Assert::string($twitterApiKey, '"TWITTER_API_KEY" env value is missing in .env'); + Assert::string($twitterApiSecret, '"TWITTER_API_SECRET" env value is missing in .env'); + Assert::string($twitterAccessToken, '"TWITTER_ACCESS_TOKEN" env value is missing in .env'); + Assert::string($twitterAccessSecret, '"TWITTER_ACCESS_SECRET" env value is missing in .env'); + Assert::string($twitterBearerToken, '"TWITTER_BEARER_TOKEN" env value is missing in .env'); return new \Noweh\TwitterApi\Client([ 'account_id' => $twitterAppId, @@ -46,8 +42,6 @@ public function register(): void 'consumer_key' => $twitterApiKey, 'consumer_secret' => $twitterApiSecret, 'bearer_token' => $twitterBearerToken, - // Optional - // 'free_mode' => false, ]); }); } diff --git a/public/hot b/public/hot deleted file mode 100644 index b727929882a..00000000000 --- a/public/hot +++ /dev/null @@ -1 +0,0 @@ -http://127.0.0.1:5173 \ No newline at end of file diff --git a/resources/css/app.scss b/resources/css/app.scss index 3576f7325f1..54b52702e79 100644 --- a/resources/css/app.scss +++ b/resources/css/app.scss @@ -300,16 +300,6 @@ a.btn { padding-bottom: 1.3em; } -.homepage-face { - width: 10em; - height: 10em; -} - -.homepage-logo { - width: 5em; - height: 5em; -} - .post-snippet { font-size: 1.05rem; line-height: 1.6rem; @@ -317,14 +307,10 @@ a.btn { /* mobile optimization */ @media (max-width: 768px) { - .homepage-face { - width: 7em; - height: 7em; - } - - .homepage-logo { - width: 3em; - height: 3em; + .welcome_card { + h2 { + font-size: 1.3em; + } } #menu { diff --git a/resources/views/homepage.blade.php b/resources/views/homepage.blade.php index abb8d93479b..13a138250e1 100644 --- a/resources/views/homepage.blade.php +++ b/resources/views/homepage.blade.php @@ -4,7 +4,7 @@
-
+
From 233aefda5348e92a48c44820ea9b3caef5403c1b Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 8 Sep 2024 17:33:07 +0200 Subject: [PATCH 4/4] make homepage width --- .env.prod | 1 - .github/workflows/code_analysis.yaml | 4 ++++ .github/workflows/rector.yaml | 3 +++ README.md | 9 +++++++++ app/Providers/AppServiceProvider.php | 1 - resources/css/app.scss | 13 +++++++++---- resources/views/_snippets/menu.blade.php | 2 +- resources/views/homepage.blade.php | 4 ++-- routes/web.php | 5 ++++- 9 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.env.prod b/.env.prod index 79ef2f013da..66a9e09587f 100644 --- a/.env.prod +++ b/.env.prod @@ -9,7 +9,6 @@ DB_CONNECTION=sqlite # @note this must be a use api key, not a project one OPENAI_API_KEY= -# regenerated 2024-08-31 TWITTER_API_KEY= TWITTER_API_SECRET= diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml index b08a1df14bc..225f3a22496 100644 --- a/.github/workflows/code_analysis.yaml +++ b/.github/workflows/code_analysis.yaml @@ -45,7 +45,11 @@ jobs: # disable xdebug coverage: none + # setup default envs, invoke by comopser install Laravel post-install event + - run: cp .env.local .env + # composer install cache - https://github.com/ramsey/composer-install - uses: "ramsey/composer-install@v2" + - run: ${{ matrix.actions.run }} diff --git a/.github/workflows/rector.yaml b/.github/workflows/rector.yaml index 6757d411189..c220d94204b 100644 --- a/.github/workflows/rector.yaml +++ b/.github/workflows/rector.yaml @@ -21,6 +21,9 @@ jobs: with: php-version: 8.2 + # setup default envs, invoke by comopser install Laravel post-install event + - run: cp .env.local .env + - uses: "ramsey/composer-install@v1" ## First run Rector - here can't be --dry-run !!! it would stop the job with it and not commit anything in the future diff --git a/README.md b/README.md index 518ad81b472..c56a15261c8 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,15 @@ cd tomasvotruba.com composer install ``` +- Build assets + +```bash +yarn build + +# or to watch files and reload on scss change +yarn dev +``` + - Run local server ```bash diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 5dd6b2dc03a..2421d8df8b3 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -19,7 +19,6 @@ public function register(): void return OpenAI::client($openApiKey); }); - $this->app->singleton(\Noweh\TwitterApi\Client::class, function (): \Noweh\TwitterApi\Client { $twitterAppId = env('TWITTER_APP_ID'); $twitterApiKey = env('TWITTER_API_KEY'); diff --git a/resources/css/app.scss b/resources/css/app.scss index 54b52702e79..a0b5b49c7a3 100644 --- a/resources/css/app.scss +++ b/resources/css/app.scss @@ -305,12 +305,17 @@ a.btn { line-height: 1.6rem; } +#welcome_card { + h2 { + letter-spacing: .02em; + font-size: 2em; + } +} + /* mobile optimization */ @media (max-width: 768px) { - .welcome_card { - h2 { - font-size: 1.3em; - } + #welcome_card h2 { + font-size: 1.6em; } #menu { diff --git a/resources/views/_snippets/menu.blade.php b/resources/views/_snippets/menu.blade.php index 0628db3206b..6e7f6e6297a 100644 --- a/resources/views/_snippets/menu.blade.php +++ b/resources/views/_snippets/menu.blade.php @@ -17,7 +17,7 @@ - +420 776 778 332 + 420 776 778 332
diff --git a/resources/views/homepage.blade.php b/resources/views/homepage.blade.php index 13a138250e1..40099d9fc0e 100644 --- a/resources/views/homepage.blade.php +++ b/resources/views/homepage.blade.php @@ -4,7 +4,7 @@
-
+
@@ -12,7 +12,7 @@
-

Hi, I'm Tomas Votruba

+

Hi, I'm Tomas Votruba

diff --git a/routes/web.php b/routes/web.php index 2a47bdbd353..59cc7b544dc 100644 --- a/routes/web.php +++ b/routes/web.php @@ -26,7 +26,10 @@ Route::get('/thumbnail/{title}.png', ThumbnailController::class); Route::get('/tools', ToolsController::class); -Route::get('/share-board', ShareBoardController::class); +// use only development environment +if (app()->environment() === 'dev') { + Route::get('/share-board', ShareBoardController::class); +} Route::get('/bank', function () { return view('bank', [