好きなものだけ書く。ポジティブに。

好きなことを楽しく。プログラミング、写真、音楽、ガジェットとか。

Google検索、辞めました

おつかれさまです!のぶじゃすです。

タイトルの通りなのですが、Chromeのタイトルバーに文字列を入力してEnterを押した時に検索される検索サイトを変えちゃいました。

今まではデフォルトのGoogleだったのですが、 https://www.perplexity.ai/ に変更しました。 PerplexityAI はAI検索のツールです。

なぜ変えたのか

  • Google検索する時のような入力で検索出来るので、行動に変化が少ない
  • 初めてPerplexityAI上で検索してみた時の体験で驚きしかなかった
  • 初めてPerplexityAI上で検索してから、Chromeの検索を変更するまでの導線が自然だった
  • 無料でもGoogle検索より欲しい結果に早くたどり着ける感覚を得られた
  • 5日間ぐらい使ってみて困ることがなかった

普通、はじめはうさぎのことを聞くよね

Proに課金するかどうかは迷ってる

  • 無料でも異常に便利
  • 応援のために課金したいくらいの気持ち
  • GPT4oとか、Claude-3、Sonar Largeなど他モデルを利用出来るのは嬉しい・・・のか?
  • 画像生成もあると嬉しい・・・のか?

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

Durable Functionsで引数を受け取る方法を解説

おつかれさまです!のぶじゃすです。

Azure 関数アプリ で Timeoutの制限や複雑な処理を整理するために Durable Functions という機能があります。とても便利なのでAzure 関数アプリを使っている人は是非試してみると良いと思います。

learn.microsoft.com

今回は、Durable Functions でHTTPトリガーやService Bugトリガーで処理に引数に受け渡す方法が明記されている記事が見つけられなかったので備忘録的な記事です。さくっと結論のみ書きますー

引数の渡し方

learn.microsoft.com

const client = df.getClient(context);
const instanceId: string = await client.startNew(
  request.params.orchestratorName,
  { input: "input string!" }
);

startNew 関数*1 の第2引数の input プロパティ*2 にJSONシリアライザブルな値を渡せる。

引数の受け取り方

const someHandler: OrchestrationHandler = function* (
  context: OrchestrationContext
) {
  const input = context.df.getInput();

OrchestrationContextdf.getInput() 関数*3 で渡した値が受け取れる。

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

BigQuery の js api ライブラリ @google-cloud/bigquery を JWT 認証で実行したい

おつかれさまです!のぶじゃすです。

@google-cloud/bigquery を実行する際にJWT認証で実行出来るようにしたい。サービスアカウントを使って利用していたりするとJWT認証じゃないと厳しい場面が発生する。(credentialファイルを置けないとか)

「@google-cloud/bigquery を JWT 認証で実行したい」という文字が書いてある。鍵をもってこちらを見ている女性が背景。

具体的に今回やりたいのは、googleapis と同様に

const auth = new google.auth.JWT(
  env.GOOGLE_EMAIL,
  undefined,
  env.GOOGLE_PRIVATE_KEY, 
  [
    "https://www.googleapis.com/auth/drive",
  ]
);
export const driveService = google.drive({ version: "v3", auth });

みたいな感じで BigQuery のAPIを実行したい。

結論

まずは結論から。これで動きました。調べた事を後述していますので気になる方はどうぞ。

const auth = new google.auth.JWT(
  env.GOOGLE_EMAIL,
  undefined,
  env.GOOGLE_PRIVATE_KEY, 
  [
    "https://www.googleapis.com/auth/drive",
  ]
);

new BigQuery({
  authClient: auth,
  projectId: `{env.GCP_PROJECT_ID}`
});

BigQuery の API がどうなっているのか調べてみる

BigQuery クラスの constructor は @google-cloud/commonGoogleAuthOptions を継承している
export interface BigQueryOptions extends GoogleAuthOptions

nodejs-bigquery/src/bigquery.ts at main · googleapis/nodejs-bigquery · GitHub

@google-cloud/commonGoogleAuthOptions の実体は google-auth-libraryGoogleAuthOptions
export {GoogleAuthOptions} from 'google-auth-library';

nodejs-common/src/index.ts at main · googleapis/nodejs-common · GitHub

google-auth-libraryGoogleAuthOptions の実体はこれ

google-auth-library-nodejs/src/auth/googleauth.ts at main · googleapis/google-auth-library-nodejs · GitHub

googleapis のAPIがどうなっているのか調べてみる

Drive クラスの constructorgoogleapis-commonGlobalOptions を利用している
 constructor(options: GlobalOptions, google?: GoogleConfigurable) {

google-api-nodejs-client/src/apis/drive/v3.ts at main · googleapis/google-api-nodejs-client · GitHub

googleapis-commonGlobalOptionsauthgoogle-auth-library の OAuth2Client や GoogleAuth を渡せる
export interface GlobalOptions extends MethodOptions {
  auth?: GoogleAuth | OAuth2Client | BaseExternalAccountClient | string;
}

nodejs-googleapis-common/src/api.ts at main · googleapis/nodejs-googleapis-common · GitHub

new google.auth を探ってみる

googleapis-commonAuthPlusgoogle.auth の実体
export class GoogleApis extends GeneratedAPIs {
  private _discovery = new Discovery({debug: false, includePrivate: false});
  auth = new AuthPlus();

google-api-nodejs-client/src/googleapis.ts at main · googleapis/google-api-nodejs-client · GitHub

AuthPlusJWTgoogle-auth-libraryJWT
export class AuthPlus extends GoogleAuth {
  JWT = JWT;

nodejs-googleapis-common/src/authplus.ts at main · googleapis/nodejs-googleapis-common · GitHub

google-auth-libraryJWTOAuth2Client の継承
export class JWT extends OAuth2Client

google-auth-library-nodejs/src/auth/jwtclient.ts at main · googleapis/google-auth-library-nodejs · GitHub

ということで GoogleAuthOptionsJWT を渡せる手段がありそうか探してみる

export interface GoogleAuthOptions<T extends AuthClient = JSONClient> {
  /**
   * An `AuthClient` to use
   */
  authClient?: T;

JSONClient という型がある

export type JSONClient =
  | JWT
  | UserRefreshClient
  | BaseExternalAccountClient
  | ExternalAccountAuthorizedUserClient
  | Impersonated;

JWT が渡せそうだ!

動いた

ということで以下のようにしたら動きました。納得感持って繋げられたのでよかった。

new BigQuery({
  authClient: auth,
  projectId: `{env.GCP_PROJECT_ID}`
});

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

Next.JS App Router でURLクエリー文字列を取得するのはクライアントコンポーネントとpage.tsxで出来る

きっとURLクエリー文字列を使ってなにか魅力的なものを検索していたりするはずの女性のイラスト
なにか検索していますね。クエリー文字列をきっと使っているはずです

おつかれさまです!のぶじゃすです。

URLクエリー文字列を取得する方法

https://example.com/anypage?search=abcdefg の様なURLのクエリー文字列をNext.jsのApp Routerを用いて取得する方法について解説します。

Next.JS App Router ではクエリー文字列を取得する2つの主な方法があります。

  1. クライアントコンポーネントで useSearchParams を使う方法
  2. page.tsxsearchParams を参照する方法

Next.jsのApp Router導入後、ClientとServerの両方を考慮してコーディングする必要が出てきました。 書き味が少し違うので何が何に対比していて、どこに制限があるのかを意識しないと素早く書けないです。 この辺りが頭に入っているのといないのでは、設計時に見通せる世界が広がります。

1. クライアントコンポーネントで useSearchParams を使う方法

"use client";
import { useSearchParams } from "next/navigation";

export const PresentationSearchPanel = () => {
  const sParams = useSearchParams();
  const search = sParams.get("search");
  return <div>{search}</div>;
};

詳細についてはNext.js公式ドキュメントを参照してください。 nextjs.org

2. page.tsxで searchParams を参照する方法

export default async function AnyPage({
  searchParams,
}: {
  searchParams: z.infer<typeof formSchema>;
}) {
  return <div>{searchParams.search}</div>
});

詳細についてはNext.js公式ドキュメントを参照してください。 nextjs.org

検証環境

package.json 抜粋

"next": "^13.5.2",

next.config.mjs 抜粋

const config = {
  reactStrictMode: true,
  experimental: {
    serverActions: true,
  },
};

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

Phaser 3.60.0 で六角形(Hexagon)を描く方法、あるいは本業以外のプログラミングを書くということ

Phaserを試してみたくてやってみた。 sinとcosが思い出せなくて泣いた。手触り感的には結構悪くない。きっとこういうメソッドあるんだろうなーが当たる確率が高い。

stability.ai で生成したプログラミングで正六角形を書く女性
stability.ai で生成したプログラミングで正六角形を書く女性

全然まったく、決して本業とは関係ない。本業はそれなりに忙しくさせてもらっているが、スキマで違うプログラミングを書いたりすると気分転換になるし楽しい。

完成がいつになるのかは分からない。それでもいい。本業でも発想が柔らかくなったりいい効果も少しだけある。

「今日は夜1時間だけやれるように時間作るぞ」と考えて生きていると少し前のめりに動ける。ほんのちょっとだけ潤う。

See the Pen Phaser Hexagon Example by noblejasper (@noblejasper) on CodePen.

ads.txtを設置するために、ブログのURLを変更してFirebaseを利用してリダイレクトする方法

おつかれさまです!のぶじゃすです。

先日当ブログのドメインを y-i.jp から www.y-i.jp に変更しました。ads.txtを設置するのを試してみたかったのでやってみました。もし似たような状況の方とかいらっしゃれば参考になると嬉しいです。

うまく行かなくて頭を抱えている男性のイラスト
ads.txt 置けないじゃん・・・

前提

ads.txt とは、Google AdSense などのアドネットワーク関連の設定で、パブリッシャーが承認したネットワークから広告が配信される事を担保するものです。詳しくはGoogle AdSense ヘルプ をごらんください。

ads.txt はルートドメインの直下に設置する必要があります。今回の場合 https://y-i.jp/ads.txt でアクセス出来る必要がありました。

ルートドメインは私の場合ははてなブログに直接設定していました。これが今回の対応をしなければならなくなった元凶です。

はてなブログでは公式でads.txtを配信する機能は提供していません。はてなヘルプで言及されています

今回クリアしないといけない課題は2つ

  1. ルートドメインでads.txtを配信する
  2. ブログはそのまま稼働させる

ドメインは変更しないとどうしようもなさそう

前提の上で解決方法を考えてみます。はてなブログでads.txtを配信する機能はないので、自力で配信する必要がある。しかし自力で配信するとなるとレンタルサーバーなど何らかのWebサーバで配信しないといけない。

URLをそのままでなんとかするのは難しそう。ではドメインは https://www.y-i.jp/ に変更するようにしよう。しかし旧URLからのリダイレクトをどう処理するか。

最近ホスティングだと、Xserverとかよく聞く気がする。しかしもちろん費用はかかる。とりあえずFirebaseなら動作確認したりテストする分には無料。その後もアクセス数が増えたりしない限りは無料。

という事で気楽にFirebaseで試してみます。

続きを読む