🏠️Top Page

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

⏩️映画、孤独のグルメを観てきました.いやこれ.たぶん、そう.

おはようございます.先日の日曜日に映画、孤独のグルメを観てきました.今回はJERAジェラのクーポンコードを使用して日曜日というちょっとコミコミの映画館に行ってきました.ジェラのクーポンコードを使用すると300円の割引になるので、ムビチケよりは割引感はないものの普通に見ると2000円だからお得感はあります.

そんなジェラの話は置いといて映画、孤独のグルメですが今年の始めてみる映画としては幸先良いかなって思いました.全く孤独のグルメのドラマや漫画などは全く見ていない自分でしたが、まずまず良い感じなストーリー展開でし、この映画を観た後に何か食べたいという気持ちになりました.

映画を観た後に何か食べたいな、美味しいご飯を食べたいという気持ちになったのは初めてです.

今年はなんか幸先良い出だしなので楽しみですねぇー.

明日へ続く

⏩️3本のブログ運用は大変なので本命だけを残してあとは不定期.

おはようございます.3本のブログ運用は大変なので本命だけを残してあとは不定期にします.昔より体力が低下しているのか、なかなか3本のブログ運用は大変です、書くことは簡単なことなのですが消耗している気がします.パソコンの前で毎日、作業するのは楽だと思われがちですが実際は結構たいへん.

デスクワークの最強の敵はお腰です、長年このデスクワークという仕事に従事すると腰痛になります、ならない人もいるかもですけど、大体の人がお腰が痛くなります.自分の作業部屋のデスクは昇降のデスクなのでお腰に負担が来たら立って作業をするようにしていますが、それでも腰痛になります.

昇降デスクでなかったら、恐らくもっと大変です.腰痛って結構体力を奪います.そういう事もあり、ブログ運用はこの本命ブログを残してあとは不定期ブログとして更新します.

更新頻度はこのブログはほぼ毎日のように更新されます.兎のはなしは週一か週二程度で更新します.我らウェブ主義は不定期です.

正月そうそう、この決断は自分としてもどうかと思いますが長く続けたいと思うなら無理はしないことだと思います.それが続けれる秘訣だと思います.

イチローさんは先送りする人は出来ないと言います.確かにそうかも知れないけれど嫌々しても続かない.そもそも嫌なものは続かないとも言えます.向いていないものは続けれないのではないだろうかと.

なので好きなものや興味があるものが嫌にならない為にも頑張らないことです.そして自分が毎日して苦にならないものが適職です.適職は一つしか無いというのも思い込みです、適職が2つ3つある人もいると思います、その逆もしかりです.

明日へ続く

⏩️一万円という数字が高いと感じる.インフレなのに.インフレだから.

おはようございます.「一万円という数字が高いと感じる.インフレなのに.インフレだから.」というお題で今日は書いていきます.インフレとはモノやサービスの価格が継続的に上昇することを意味します、なのでお給与が上がるわけではないので商品が高いと感じるわけです.

年間固定費が高い.サブスクリプションでYOUTUBEに1万2千円が来月発生します.そしてアドビ税が3万円が発生します.年間契約にしているので少し割引価格で使用できるのだけど、これだけで4万2千円の現金が消えていくのは痛い.そしてなんだか勿体ない感もある.特にアドビ税を支払っている割にはこの頃はアドビのイラストレーターを使用していないだよね.

だったら、契約しないという選択肢もあるのですが...無いと困るので継続するつもりではいます.YOUTUBEなんて無料で良いだろうという意見もあるけどCMがうざっと感じるのでその為にお金を支払っていたり音楽も聞けるので何だかんだで契約を継続したい.

その他にもウイルス対策のソフトなどにもお金を支払ってる.これ無駄と言われるかもだけど、何度かブロックしてくれた事(誤検知かもだけど)もありなんか入れとかないとと思っている.

そんなわけでサブスクリプションに年間、7-8万円支払っている気がする.

明日へ続く

⏩️VPSサーバーに今年移行するかも🦆.する場合はDocker運用で!?

おはようございます.VPSサーバーに今年移行するかも🦆.する場合はDocker運用で行いたいなって思っているのだけど考え中です.Dockerの場合、環境構築は簡単なんだけど環境を後から追加したいとかいうのが、面倒なところがあるので...考え中.

先日、Xにもポストしたけどこんな感じの構成で運用しようと思っています.

そもそもVPSサーバーに切り替えるとなると結構面倒なのとレンタルサーバーから上手く切り替えることが出来れば良いけど、自分の場合は無料のSSLで運用しているので一旦停止みたいな事が発生する.少しずつドメインを以降するとほど金銭的に余裕資金はないので悩みどころです.

書いていて思ったのだけどVPSサーバーに移行する前に自宅サーバーで試してみてDockerコンテナ運用が良いかもと思ったら移行してみます.

明日へ続く

⏩️映画、歩いても歩いてもを観ました.

おはようございます.映画、歩いても歩いてもを観ましたので感想を残しときます.この映画、家族や人を凄く丁寧に描いている.観終わった後に考えさせられる映画でした.ストーリーに浮き沈みというものは無く何処か映画、東京家族(山田洋次監督)にているものを感じました.

これは20代とかで観ると何も響かなったかもしれないけど、いまの年代で観るといろいろと思う所がある.この映画を70代で観たらまた違った捉え方が出来るのかも知れないと思いますね.

是枝裕和監督はこういう映画を撮るのがとても上手だなって感じました.人をとても見ていないとこういう映画は撮れないかと思います.今見れて本当に良かったです.

因みにこの映画はネトフリでもアマプラでも見れます.

明日へ続く

⏩️生成AIでポートフォリオサイトを作ってでどれぐらい物(単純な指示で)が生成されるのか?

おはようございます.生成AIでポートフォリオサイトを作ってでどれぐらい物(単純な指示で)が生成されるのか?を試してみた結果、ダークモードにも対応出来ていたけどもやっぱ微妙かなと思いました.確かにまずまずの物は作れるようになっているけど、凝ったものを作るのは知識が必要になる.

ひろゆき氏の切り抜きの動画をたまたま見たけど、ひろゆき氏の生成AIに対しての考え方は今のところ間違っていない感じがします.生成AIは平均的なものが生成されます、そして生成AIで生成されたコードを直せない人は生成AIを使えない.それはソースコードも絵や音楽でも同じでそれなりものは出来るけど、その調整を出来るのはそれを専門にしている人だけです.

そして生成AIが作ったものが正しいものなのかが判断する人がいないと難しい.生成AIの提供会社が100%保証してくれるわけでもなく、生成AIで生成されるものは間違いがあることを認めている現状ではやはり普及はしないし専門家の仕事は奪われないというのがひろゆき氏の見解です.AGI(汎用人工知能)やASI(人工超知能)というのは幻想かもしれない.

シンギュラリティは当分来ない、早くても10年、20年後になるじゃないだろうかと.

ただAIはこれからも徐々に進化していくとは思っています.それに伴って医療などの進展は今まで以上に加速すると思っています.そういう訳でエヌビディアの株も今年が天井なのかもしれません.

最後に今回、生成AIが生成したhtmlファイルを添付致します.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Portfolio</title>
  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
  <style>
    body {
      font-family: Arial, sans-serif;
      transition: background-color 0.3s, color 0.3s;
    }
    .hero {
      background: url('https://picsum.photos/1200/600') no-repeat center center/cover;
      height: 60vh;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
    }
    .project img {
      border-radius: 8px;
    }
    footer {
      background: #343a40;
      color: white;
      padding: 1.5rem 0;
      text-align: center;
    }
    .dark-mode {
      background-color: #121212;
      color: #e0e0e0;
    }
    .dark-mode .hero {
      text-shadow: 2px 2px 4px rgba(255, 255, 255, 0.7);
    }
    .dark-mode footer {
      background: #1f1f1f;
    }
  </style>
</head>
<body>
  <header>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
      <div class="container">
        <a class="navbar-brand" href="#">My Portfolio</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
          <ul class="navbar-nav ms-auto">
            <li class="nav-item"><a class="nav-link" href="#about">About</a></li>
            <li class="nav-item"><a class="nav-link" href="#projects">Projects</a></li>
            <li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
            <li class="nav-item">
              <button class="btn btn-outline-light ms-3" id="darkModeToggle">Toggle Dark Mode</button>
            </li>
          </ul>
        </div>
      </div>
    </nav>
  </header>

  <section class="hero text-center">
    <div>
      <h1>Welcome to My Portfolio</h1>
      <p>Showcasing my work and projects</p>
    </div>
  </section>

  <section id="about" class="py-5">
    <div class="container">
      <div class="row">
        <div class="col-md-6">
          <img src="https://picsum.photos/500/400" alt="About Me" class="img-fluid rounded">
        </div>
        <div class="col-md-6">
          <h2>About Me</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce aliquam magna in odio malesuada, vitae vulputate libero sodales. Nulla facilisi.</p>
        </div>
      </div>
    </div>
  </section>

  <section id="projects" class="py-5 bg-light">
    <div class="container">
      <h2 class="text-center mb-4">Projects</h2>
      <div class="row">
        <div class="col-md-4 project mb-4">
          <img src="https://picsum.photos/400/300" alt="Project 1" class="img-fluid">
          <h4 class="mt-2">Project 1</h4>
          <p>Short description of the project goes here.</p>
        </div>
        <div class="col-md-4 project mb-4">
          <img src="https://picsum.photos/400/300" alt="Project 2" class="img-fluid">
          <h4 class="mt-2">Project 2</h4>
          <p>Short description of the project goes here.</p>
        </div>
        <div class="col-md-4 project mb-4">
          <img src="https://picsum.photos/400/300" alt="Project 3" class="img-fluid">
          <h4 class="mt-2">Project 3</h4>
          <p>Short description of the project goes here.</p>
        </div>
      </div>
    </div>
  </section>

  <section id="contact" class="py-5">
    <div class="container">
      <h2 class="text-center mb-4">Contact Me</h2>
      <form>
        <div class="mb-3">
          <label for="name" class="form-label">Name</label>
          <input type="text" class="form-control" id="name" placeholder="Your Name">
        </div>
        <div class="mb-3">
          <label for="email" class="form-label">Email</label>
          <input type="email" class="form-control" id="email" placeholder="Your Email">
        </div>
        <div class="mb-3">
          <label for="message" class="form-label">Message</label>
          <textarea class="form-control" id="message" rows="4" placeholder="Your Message"></textarea>
        </div>
        <button type="submit" class="btn btn-primary">Send Message</button>
      </form>
    </div>
  </section>

  <footer>
    <p>© 2025 My Portfolio. All Rights Reserved.</p>
  </footer>

  <!-- Bootstrap Bundle with Popper -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
  <script>
    const darkModeToggle = document.getElementById('darkModeToggle');
    darkModeToggle.addEventListener('click', () => {
      document.body.classList.toggle('dark-mode');
    });
  </script>
</body>
</html>

明日へ続く

⏩️グーグルカレンダーの予定を一部表示させたい時の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送信と判断されます.これをデバックもせずに悩んでいました(笑).デバック大事.

明日へ続く