Laravel Command line post article to Google Blogger


純屬娛樂,寫一支 Laravel Console Command,可以呼叫 Browser 開一個連結向 Google 驗證後,自動發文到你所擁有的 Blogger。

Environment:
1. PHP >= 7.2
2. Laravel Framework

Composer Package install:
composer require pulkitjalan/google-apiclient
詳細參考:https://github.com/pulkitjalan/google-apiclient

Google Cloud Console:
1. 去 Google Console 申請 Api Key, OAuth2.0 Access
2. OAuth2.0 設定的 Redirect Url 填:http://127.0.0.1:8000/authorization-code/callback

執行:
php artisan oauth:blogger

以下是範例程式:

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use PulkitJalan\Google\Facades\Google;
use Illuminate\Support\Facades\Cache;
class OAuthLogin extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'oauth:blogger';
/**
* The console command description.
*
* @var string
*/
protected $description = 'oauth login blogger';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//
if (
!Cache::get('expiredAt') or
!Cache::get('refreshToken') or
!Cache::get('accessToken')
) {
$ip = '127.0.0.1';
$port = '8000';
$socket_str = 'tcp://' . $ip . ':' . $port;
$client = Google::getClient();
$authorize_url = $client->createAuthUrl();
$this->info('Auto Open Browser connect to: ' . $authorize_url . PHP_EOL);
shell_exec("open '" . $authorize_url . "'");
$response = $this->startHttpServer($socket_str);
$auth = $client->authenticate($response['code']);
$accessToken = $client->getAccessToken();
$refreshToken = $client->getRefreshToken();
$expiredAt = $auth['created'] + $auth['expires_in'];
Cache::store('file')->put('refreshToken', $refreshToken);
Cache::store('file')->put('accessToken', $accessToken);
Cache::store('file')->put('expiredAt', $expiredAt);
}
if (time() > Cache::get('expiredAt')) {
$client = Google::getClient();
$auth = $client->fetchAccessTokenWithRefreshToken(Cache::get('refreshToken'));
$client->setAccessToken($auth['access_token']);
Cache::forget('accessToken');
Cache::forget('refreshToken');
Cache::forget('expiredAt');
$refreshToken = $client->getRefreshToken();
$expiredAt = $auth['created'] + $auth['expires_in'];
Cache::store('file')->put('refreshToken', $refreshToken);
Cache::store('file')->put('accessToken', $auth['access_token']);
Cache::store('file')->put('expiredAt', $expiredAt);
}
$client = Google::getClient();
$client->setAccessToken(Cache::get('accessToken'));
$googlService = Google::make('blogger', $client);
$ownblogs = $googlService->blogs->listByUser('self');
$bloglist = [];
foreach ($ownblogs as $key => $own) {
$bloglist[] = [
'choice' => $key + 1,
'id' => $own->id,
'name' => $own->name,
];
}
$this->table(['select', 'blogId', 'blogName'], $bloglist);
$choice = $this->ask('Select one to Post');
$blogId = (isset($bloglist[$choice - 1])) ? $bloglist[$choice - 1]['id'] : $this->ask('Select one to Post');
// Write a post
$post = Google::make('blogger_post');
$post->setTitle('test');
$post->setContent('<h1>yes</h1>');
$post->setLabels(['news', 'k12']);
$options = [
// 'isDraft' => true, // if want direct publish, comment this line.
];
$result = $googlService->posts->insert(
$blogId,
$post,
$options
);
$this->info(
sprintf(
'Uploaded: { title: %s, status: %s, url: %s, timestamp: %s }%s',
$result->title,
$result->status,
$result->url,
$result->updated,
PHP_EOL
)
);
}
// From: https://developer.okta.com/blog/2018/07/16/oauth-2-command-line
private function startHttpServer($socketStr)
{
// Adapted from http://cweiske.de/shpub.htm
$responseOk = "HTTP/1.0 200 OK\r\n"
. "Content-Type: text/plain\r\n"
. "\r\n"
. "Ok. You may close this tab and return to the shell.\r\n";
$responseErr = "HTTP/1.0 400 Bad Request\r\n"
. "Content-Type: text/plain\r\n"
. "\r\n"
. "Bad Request\r\n";
ini_set('default_socket_timeout', 60 * 5);
$server = stream_socket_server($socketStr, $errno, $errstr);
if (!$server) {
Log::err('Error starting HTTP server');
return false;
}
do {
$sock = stream_socket_accept($server);
if (!$sock) {
Log::err('Error accepting socket connection');
exit(1);
}
$headers = [];
$body = null;
$content_length = 0;
//read request headers
while (false !== ($line = trim(fgets($sock)))) {
if ('' === $line) {
break;
}
$regex = '#^Content-Length:\s*([[:digit:]]+)\s*$#i';
if (preg_match($regex, $line, $matches)) {
$content_length = (int) $matches[1];
}
$headers[] = $line;
}
// read content/body
if ($content_length > 0) {
$body = fread($sock, $content_length);
}
// send response
list($method, $url, $httpver) = explode(' ', $headers[0]);
if ($method == 'GET') {
#echo "Redirected to $url\n";
$parts = parse_url($url);
#print_r($parts);
if (
isset($parts['path']) && $parts['path'] == '/authorization-code/callback'
&& isset($parts['query'])
) {
parse_str($parts['query'], $query);
if (isset($query['code']) && isset($query['scope'])) {
fwrite($sock, $responseOk);
fclose($sock);
return $query;
}
}
}
fwrite($sock, $responseErr);
fclose($sock);
} while (true);
}
}
view raw OAuthLogin.php hosted with ❤ by GitHub

留言

這個網誌中的熱門文章

在 Excel 裡轉換 Unixtime 格式

有點誇張的準專業機.Minolta Alpha 7 (Dynax 7、Maxxum 7).2000

[古典相機] M 系列快門最速.ME MX 合體.Pentax ME Super.1980