🏠️Top Page

🖊️おもしろき こともなき世をおもしろく 住みなすものは 心なりけり.

⏩️グーグルカレンダーの予定を一部表示させたい時のPHPコード.

おはようございます.グーグルカレンダーの予定を一部表示させたい時のPHPコードは下記になります、参考にしたサイトはこちらですが参考にしただけでコードは違うものになります.APIを毎日叩いていると課金しなくてはならないかもなのでデータベースに保存する形にしました.これも良い方法かと言えばどうだろうと言う思いもあります.

<?php
ini_set('display_errors', 0);
require_once './vendor/autoload.php';
require_once './config.php';

use Carbon\Carbon;
use Google\Client;
use Google\Service\Calendar;
use Illuminate\Database\Capsule\Manager as DB;

class openSchedule
{
    public $DB = null;
    public function __construct()
    {
        $database = new DB();
        $database->addConnection([
            'driver' => 'mysql',
            'host' => DB_HOST,
            'port' => PORT,
            'database' => DB_DATABASENAME,
            'username' =>  DB_USER,
            'password' => DB_PASSWORD,
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_general_ci',
        ]);

        $database->setAsGlobal();
        $database->bootEloquent();
        $this->DB = $database;
    }

    public function saveSchedule($dateTimeString):void
    {
        //$this->DB::table('schedules')->delete();
        try {
            $client = new Client();
            $client->useApplicationDefaultCredentials();
            $client->addScope(Calendar::CALENDAR_READONLY);
            $client->setAuthConfig(JSONPATH);
            $service = new Calendar($client);
           // カレンダーID
            $calendarId = GOOGLECALENDARID;

            // 取得時の詳細設定
            $optParams = [
                'maxResults' => 10,
                'orderBy' => 'startTime',
                'singleEvents' => TRUE,
                'timeMin' => (new \DateTime($dateTimeString))->format(DATE_RFC3339),
                'timeZone' => 'Asia/Tokyo',
            ];
            $results = $service->events->listEvents($calendarId, $optParams);
            if (empty($results->getItems())) {
                echo "イベントが見つかりませんでした。";
            } else {
                foreach ($results->getItems() as $event) {
                    $this->DB::table('schedules')->insert([
                        'start' => Carbon::parse($event->getStart()->dateTime)->format('Y-m-d H:i:s'),
                        'end' => Carbon::parse($event->getEnd()->dateTime)->format('Y-m-d H:i:s'),
                        'title' => $event->getSummary(),
                        'detail'=>$event->getDescription()
                    ]);
                }
            }

        } catch (Google\Service\Exception $e) {
            echo 'Google Service Exception: ' . $e->getMessage();
        } catch (Exception $e) {
            echo 'General Exception: ' . $e->getMessage();
        }
    }

    public function getWeekDays($dateTimeString):string
    {
        // Carbonインスタンスに変換してフォーマット
        $carbon = Carbon::parse($dateTimeString);

        // 日本語の曜日名配列
        $japaneseWeekdays = ['日', '月', '火', '水', '木', '金', '土'];

        // 曜日の数値を取得し、日本語の曜日名に変換
        $weekdayNum = $carbon->dayOfWeek;
        $japaneseWeekday = $japaneseWeekdays[$weekdayNum];
        return $japaneseWeekday;
    }

    public function getSchedule($dateTimeString):string
    {   
        $str = '';
        $events = $this->DB::table('schedules')->select(['*'])->where('start','>=',$dateTimeString)->limit(1)->get();
        foreach($events as $event){
            
            $str.= sprintf("%s <br>",$event->title);
            $str.= sprintf("%s %s曜日 <br>",Carbon::parse($event->start)->format('Y年m月d日 H時i分'),$this->getWeekDays($event->start));
            $str.= sprintf("%s<br>",Carbon::parse($event->end)->format('Y年m月d日 H時i分'));
        }
        return $str;
    }

    public function getLastDate():string|null
    {
        $lastRecord = $this->DB::table('schedules')
                   ->orderBy('id', 'desc')
                   ->first();
        return $lastRecord?$lastRecord->start:null;
    }
}

//print (new openSchedule)->getSchedule((new \DateTime())->format('Y-m-d 00:00:00'));

if(isset($argv) && $argv[0]){
    $openSchedule = new openSchedule();
    $dateTimeString = $openSchedule->getLastDate();
    if($dateTimeString){
        $date = new DateTime($dateTimeString);
        $date->modify('+1 day');
        $openSchedule->saveSchedule($date->format('Y-m-d 00:00:00'));
    }else{
        $openSchedule->saveSchedule((new \DateTime())->format('Y-m-d H:i:s'));
    }   
}

因みに近日中にブログに仕事の予定などを記載するようにします.近日中なのでいつになるかは未定です.

そうそうCalendarIDという物がグーグルデベロッパサイトにあると思い込んでいて馬鹿な事をしていました.皆さんは間違わないように(笑).CalendarIDはグーグルカレンダーの設定の中にあります.

明日へ続く

⏩️Radikoに再度課金しました.また解約するかも知れないけれども.

おはようございます.Radikoに再度課金しました.また解約するかも知れないけれども今のところ契約中.去年、仕事をしているときは会議以外はラジコを聞き流して仕事をしていました.無音だといろいろと将来の的なことなどを考えだして集中力がかける時があるのでラジコを聞き流しています.

簡単に言えばある程度の雑音のなかで仕事をするほうが自分は効率的に仕事をこなすことが出来る感じです(ラジコが雑音っていう訳ではないですが...).無音も悪くないけどね.超集中したいときは無音にします、そして速くプルリクエストしないといけないときは無音にしています.そういう訳でケースバイケースです.

何故、有料にしたのかと言えば地元のラジオでは飽きがきてしまってと言うのもある少しあるのだけど、その他の地方のラジオに興味を持ったのとあと都市のラジオを聞きたいと思ったのが有料に切り替えた理由かな.ラジオの良いところは知らない曲を聞けるとか知らないことを知れるということかなと思います.それもたまたま感がラジオは強い.たまたま聞いていたらというのがまた良い所です.

そういう訳でラジコでお仕事はオススメですよー.

明日へ続く

⏩️blueskyAPIが処理されなくなったので、対応を行った話.

おはようございます.今日から仕事始めの方も多いはず自分もそんな感じです.さてblueskyAPIが処理されなくなったので対応を行った話を書いていきます.ブルースカイの独自処理が上手く処理されなくなったのでその対応を行っていました.今まで公式に落ちているPHP言語のライブラリーを使用していたんだけど、レンタルサーバーの環境が変わった関係により処理がされなくなったので、自前のAPI処理を他のエンジニアが公開されているコードを参考にしてカード板自動投稿を作りました.

ソースコードは下記になります.

    public function cardPost($text, $imagePath = null, $link = null)
    {
        $imageUri = $imagePath ? $this->uploadImage($imagePath) : null;

        $record = [
            "\$type" => "app.bsky.feed.post",
            "text" => $text,
            "createdAt" => Carbon::now()->format('c'),
        ];

        if ($imageUri && $link) {
            $record['embed'] = [
                "\$type" => "app.bsky.embed.external",
                "external" => [
                    "uri" => $link,
                    "title" => $text,
                    "description" => $text,
                    "thumb" => $imageUri
                ]
            ];
        }

        $ch = curl_init("https://bsky.social/xrpc/com.atproto.repo.createRecord");
        curl_setopt_array($ch, [
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => [
                "Content-Type: application/json",
                "Authorization: Bearer {$this->jwt}",
            ],
            CURLOPT_POSTFIELDS => json_encode([
                "repo" => $this->handle,
                "collection" => "app.bsky.feed.post",
                "record" => $record,
            ]),
        ]);

        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }

これでカード型のポストが出来ます.参考にしたサイトはこちらの@ma7ma7pipipiさんのソースコードになります.そのコードにカード型のコードを追加した形になります.

https://qiita.com/ma7ma7pipipi/items/bf7fda65ee71c873c70a

一からコードを書かないで良かったのでとても助かりました.感謝ですね😌、ありがとうございます.

明日へ続く

⏩️ブログ通知を付けました.4時間置きに通知が飛びます.#サービスワーカー

おはようございます.去年の暮にブログ通知を付けました.4時間置きに通知が飛びます.ソースコードは以前に書いたコードをベースとして再構築した形になります.平たく言うとLaravelを使用しないでWEB通知を行うものになります.一度作ってしまえば使いましが出来るようにコードを今回は書いたので使いまわそうと考えています.

以前、Laravelで作っていたので考え方は苦労せずに出来たのですが...

今まで知らないことが出てきてしまってそこでロスしてしまいました.知らなかったこととはjavascriptのfetchです.使用する機会は結構多めなんだけど知らないことがありました.それはurlのパラムに/exampleと書くか/example/index.phpと書くかでphp言語のグローバル変数$_SERVER['REQUEST_METHOD']の値がPOSTで送っているのにも関わらずGETになるのです.

fetchを書く場合は/example/index.phpと書くことでPOST送信と判断されます.これをデバックもせずに悩んでいました(笑).デバック大事.

明日へ続く

⏩️地声ベースのAI音声合成モデルを再度構築しました話.たぶん似てる.

おはようございます.地声ベースのAI音声合成モデルを再度構築しました話を書いていきます.まず地声ベースモデルを作る場合.自分の音声を録音しwavなどファイルにします.それが出来ない環境では音声モデルを作ることは難しいです.それが出来たらstyle-bert-vits2をGitHubから落としてきて、ブランチをdevに切り替えておきます.Windowsの場合、app.batを起動します.前提条件としてPythonがインストールされていることとgitがインストールされた環境であることです.

app.batを起動するとターミナルがターミナル立ち上がり次に任意のブラウザが開くことでしょう.ターミナルは閉じずにブラウザ画面のTOPにタブがあるので左から右へタスクをこなしていくと地声ベースの音声合成モデルが生成されます.

音声合成モデルが生成された後にstyle-bert-vits2内でターミナルを開き下記のコマンドを叩きます.

python convert_onnx.py --model model_assets\モデル名

叩く処理が実行されonnxファイルがモデルフォルダに作られます.

作られたファイルをaivm-generator.aivis-project.comサイトにてコンバートします.コンバートするとAIVM / AIVMX ファイルがダウンロードされます.最後にダウンロードされたファイルをAivisSpeechアプリに取り込めば完了です.

で、こちらが地声ベースの音声合成モデルで今回の記事を読み上げている音源になります.

明日へ続く

⏩️ネトフリで映画65 シックスティ・ファイブを中盤まで観てラストまで飛ばし観した話.

おはようございます.ネトフリで映画65 シックスティ・ファイブを中盤まで観てラストまで飛ばし観した話を書いています.まずこの映画、大スクリーンかVRで観ないと楽しめない作りになっています.

ストーリー的には地球が舞台になっています.ストーリー展開はこんな感じです、恐竜が存在していた白亜紀後期に不慮の事故で地球に墜落した1基の母船.生存者は2人、果たして地球から脱出することは出来るのか?というストーリーなのですが、ストーリー展開がベタベタ過ぎる.

中盤まで観てヒヤヒヤドキドキがこのままずっと最後まで続くのかと思って中盤まで観て脱出ポッドが見つかったあたりからラストまで観た感じです.自分としては珍しい見方です.

基本、映画は飛ばし飛ばしで観ないのですがこの映画は例外です.この映画を小さな画面で観ていたことが一番の問題だと思いますが、ラストまで観て再度観たいとは思えなかったので....

全然悪いわけではないけど何かが足りない気がしました.映画の評価も3と微妙な評価でしたが今回は映画評論が正しかった形になります.尚、映画は字幕で見ています.

明日へ続く

⏩️LaravelのViteが使用できない環境でログイン画面などを表示させたい対処法.

おはようございます.さて正月、2日目の記事はLaravelのViteが使用できない環境でログイン画面などを表示させたい対処法です.レンタルサーバーではnpmコマンドが使えないのでローカルでビルドしてサーバーにビルド後のファイルをUPしている方が殆どだと思いますが、npmをビルドするのも面倒、ビルドが出来ない方はソースコードを読んで何のコードが使われているかを判断して使用されているライブラリーのcdnを貼り付けるだけで大体の解決します.

尚、viteで参照しているところは削除してください(viteと差し替える形になります.).

viteでエラーが出る話はこれで終わりです.ここから余談です今年から無料になったGitHub Copilotを個人開発では使用するようにしました、この事によって今までより開発効率が上がるということならば有料プランも検討したいなと思っています.今のところ、無料プランで使っていくというスタンスです.

因みに自分は正月そうそうからコードを書いています.

明日へ続く

⏩️新年、あけましておめでとうございます~🎍🐍🎍

新年、あけましておめでとうございます~🎍🐍🎍、この投稿を読んで頂いた人に福が来るように祈っています.今年は貫徹の年越しでもしようかなと思っていたんだけど、この投稿が公開している頃は寝落ちしている頃かもしれません.

今年は何だか良いことが起きそうな気がします、何だかそういう気がします.気がする時って自分の場合、大体あたっている事が多いのでそうなると思っています.

去年は何かと厳しいかったので、倍返しに運が廻ってくると良いですよね.運が悪い運が良いって言いますが実はこころの持ちようがカナリ影響しているそうです.なので悪いことが起きても塞翁が馬だと思って考え方を切り替えることが大事らしい.

そういう訳なので、去年イマイチ運が悪かった方も良い方向に進んでいると思って前向きに行きましょい!人生は一瞬らしいので後悔のないように!!

では、皆さんにとって良い一年でありますように!!

明日へ続く

⏩️皆様のお陰で今年も何とかなりました.有難う御座います.

おはようございます.皆様のお陰で今年も何とかなりました.有難う御座います.今年は少々厳しい生活を送っていたのですが、訪問者さまのお陰で何とかなりました心より感謝申し上げます.本当に有難う御座います.

馬鹿な自分でもお金を増やせる唯一の方法はお金に働いてもらうということです.そうすることでお金がお金を生みます.生まない場合もありますが長期的に見れば投資することはプラスになると思っています.

理由は人には欲があるので経済成長を辞めることはないでしょうと思うからです.経済が悪化した場合も増えていた分が減る様に見えて価値そのものは変わらないように思います.特に投資信託の場合、株の抱合せを購入しているわけですから.株単体とは話がまた違います.

投資信託や株などを厳しい生活のなかで購入していました.そのお陰で資産が少し増えました.また引き落としなどは副収入で何とかなった時期もあり助かりました.

有難う御座います.

来年も良い一年でありますように!

明日へ続く

⏩️ビットフライヤーはビットコインのビットコインをリアルタイムで受信するphpコード

おはようございます.ビットフライヤーはビットコインのビットコインをリアルタイムで受信するphpコードを書きましたのでお裾分けです.以前書いていたものとは違う感じになります.ビットフライヤーさんのAPIを参照するとルビやJSの例コードはあるものの、何故かPHP言語のコードが無いので書いてみた形になります.ベースは生成AIに出力してもらったの物になります.それを自分の方がクラス化して使いやすくした形になります.

<?php
require 'vendor/autoload.php';

use WebSocket\Client;

class bitflyer
{
    public $client = null;
    public $channelName = "lightning_board_snapshot_BTC_JPY";
    public $wsUrl = 'wss://ws.lightstream.bitflyer.com/json-rpc';

    public function connecting()
    {
        try {
            // WebSocketクライアントを初期化
            echo "Connecting to WebSocket server...\n";
            $this->client = new Client($this->wsUrl);

            echo "Connection established. Subscribing to channel...\n";

            // サブスクライブメッセージを送信
            $subscribeMessage = json_encode([
                'method' => 'subscribe',
                'params' => ['channel' => $this->channelName],
                'id' => null,
            ]);
            $this->client->send($subscribeMessage);
        } catch (\WebSocket\ConnectionException $e) {
            echo "WebSocket connection error: " . $e->getMessage() . "\n";
            sleep(1); // 1秒待機して再接続
            $this->client = null;
            $this->connecting()->receive();
        } catch (Exception $e) {
            echo "General error: " . $e->getMessage() . "\n";
            $this->client = null;
            $this->connecting()->receive();
        }
        return $this;
    }

    public function receive()
    {
        try {
            // メッセージ受信処理
            while (true) {
                $message = $this->client->receive();

                // 受信データが空でないか確認
                if (!empty($message)) {
                    $data = json_decode($message, true);

                    // デコードが成功したか確認
                    if (json_last_error() === JSON_ERROR_NONE) {
                        if (isset($data['method']) && $data['method'] === 'channelMessage') {
                            print_r($data['params']);
                        }
                    } else {
                        echo "JSON デコード エラー: " . json_last_error_msg() . "\n";
                    }
                } else {
                    echo "返却値 空.\n";
                }
            }
        } catch (Exception $e) {
            echo $e->getMessage();
            $this->client = null;
            $this->connecting()->receive();
        }

        echo "Ctrl+C にて終了\n";
        return $this;
    }
}

(new bitflyer)->connecting()->receive();

尚、レンタルサーバーなんかでこのコードを動かすのは禁止されていますので、必ずローカルマシンで動かしてください.もし何かトラブルになっても保証出来ないので注意してください.因みに自分はDocker内で動かしています.

明日へ続く