jedipunkz 🚀 のブログ

SRE になるために孊んでいくブログです

Discord サヌバ運営を補助する Go 実装のボット開発

自分は Discord サヌバの運営を行っおいるのですがその運営の補助をしおもらうためにボット開発を行っおいたす。Go で Discord ボットを開発しメンバヌ数の掚移やログ分析を行うシステムを構築しおいる話ずたたその他幟぀か機胜をもっおいお日々の䜜業の効率化を図っおいたす。この蚘事ではそのボットの玹介をさせお頂きたす。 ※ 以前の蚘事 https://jedipunkz.github.io/post/discord-exporter/ の内容を含んでいたす システム構成 このシステムは以䞋の3぀の䞻芁コンポヌネントで構成されおいたす。 Discord ボット(padawan) - Go 補の Discord ボット discord-exporter - Go 実装の Discord サヌバメトリクス収集甚 Prometheus Exporter 分析基盀 - DuckDB を甚いた構造化ログの分析コンテナ 構成図は䞋蚘になりたす。Prometheus Exporter は Discord API から情報を取埗し Prometheus Server にメトリクスを提䟛。Prometheus Server はそのメトリクスをポヌリングしストレヌゞにデヌタを蓄積。Grafana はそれをデヌタ゜ヌスずしお参照。padawan は Go 実装のボットで Discord API やその他ゲヌム甚 API 等を参照し機胜提䟛。ボットず隣接しおある DuckDB コンテナはボットのログを分析するための Go 実装の CLI を備える。 構成の詳现 ボットの構成 padawan ず名前のボットずそのボットのログを分析する DuckDB コンテナで構成されおいたす。 # padawan/docker-compose.yaml services: padawan: build: context: . dockerfile: Dockerfile volumes: - ./data:/root/data - ./logs:/logs restart: always duckdb: build: context: . dockerfile: Dockerfile.duckdb volumes: - ./logs:/logs:ro restart: "no" profiles: - tools discord-exporter の構成 Go 実装の Discord API から情報を収集する Exporter を䞭心ずし Grafana, Prometheus Server を構成ずしおも持っおいたす。 ...

Claude Code から OpenCode ぞ移行した話

jedipunkz🚀 です。 最近、AI コヌディングアシスタントずしお䜿っおいた Claude Code から OpenCode に移行したした。この蚘事では OpenCode の優れた機胜ず、なぜ移行を決めたのかの決めおを玹介したす。 泚蚘 (2025-12-28) OpenCode プロゞェクトは、2024幎7月に開発元の Charm 瀟による買収ず運営方針を巡っお、コントリビュヌタヌ間で論争が発生したした。その埌、Charm 版は Crush ずしおリブランドされ、珟圚の OpenCode は SST 組織によっお https://github.com/sst/opencode で開発が継続されおいたす。䞡プロゞェクトは珟圚も別々のツヌルずしお存圚しおおり、この蚘事では SST 版の OpenCode に぀いお玹介しおいたす。 OpenCode ずは OpenCode は、タヌミナルベヌスのオヌプン゜ヌス AI コヌディング゚ヌゞェントです。75以䞊の LLM プロバむダヌをサポヌトし、高床にカスタマむズ可胜なむンタヌフェヌスを提䟛したす。 公匏サむト: https://opencode.ai/ 公匏ドキュメント: https://opencode.ai/docs GitHub: https://github.com/opencode-ai/opencode Claude Code から移行した理由 1. 日本語入力 Claude Code では、日本語入力の倉換䞭に文字が暪にずれる珟象が頻繁に発生し、非垞にストレスでした。 OpenCode では、この問題が発生せず日本語入力が自然に行えたす。地味ですが䞀番自分にずっお倧きいメリットだったかもしれたせん。 2. 柔軟なキヌバむンド蚭定 OpenCode の最倧の魅力は、キヌバむンドを自由にカスタマむズできる点です。 日本語入力 Claude Code では、日本語入力の倉換䞭に文字が暪にずれる珟象が頻繁に発生し、非垞にストレスでした。 OpenCode では、この問題が発生せず、日本語入力が自然に行えたす。TUITerminal User Interfaceの実装が優れおおり、IME ずの盞性も良奜です。 Emacs 颚のキヌバむンドをサポヌト Emacs 颚のキヌバむンドが蚭定出来る点は自分にずっおは倧きかったです。蚭定せずずも自然に Emacs 颚にバむンドされおいるキヌもありたす。 Ctrl-a: 行頭に移動 Ctrl-e: 行末に移動 Ctrl-h: 䞀文字削陀 Ctrl-k: カヌ゜ル䜍眮から行末たで削陀 Ctrl-f, Ctrl-b: 前埌に移動 "keybinds": { "input_backspace": "backspace,shift+backspace,ctrl+h", "input_delete_to_line_end": "ctrl+k" }, Enter ず Ctrl-Enter を䜿い分け可胜 特に䟿利なのが、改行ずメッセヌゞ送信を分離できる点です ...

Conftest OPA で Terraform コヌド開発に制玄を蚭ける

こんにちは。jedipunkz🚀 です。 Conftest ず Open Policy Agent (OPA) を䜿った Terraform のポリシヌ怜蚌を行ったのでそれを蚘事にしたいず思いたす。ポリシを曞くこずで Terraform コヌドに制玄を加え、セキュリティ芁件(䟋えば暗号化芁件やポヌト開攟芁件等) を満たしたりベストプラクティスにそったむンフラを構築できたす。毎回レビュヌで人にチェックさせるよりも確実に制玄を守れるようになるのでおすすめです。 この蚘事では、Conftest ず OPA を䜿っお、Terraform コヌドに自動的にポリシヌチェックを適甚する方法をチュヌトリアル圢匏で解説したす。 1. Conftest 抂芁ず基本チュヌトリアル 1.1 Conftest ずは Conftest は、構造化された蚭定デヌタに察しおポリシヌをテストするためのツヌルです。Open Policy Agent (OPA) の Rego 蚀語を䜿甚しおポリシヌを蚘述し、さたざたな蚭定ファむルを怜蚌できたす。 Conftest の特城 汎甚性が高い Terraform.tf、tfplan.json KubernetesYAML、JSON Dockerfile その他の JSON/YAML ファむル シンプルで軜量 単䞀のバむナリで動䜜 倖郚䟝存なし CI/CD に簡単に統合可胜 OPA の Rego 蚀語を採甚 宣蚀的なポリシヌ蚘述 匷力なパタヌンマッチング テスト可胜なポリシヌコヌド なぜ Conftest が必芁なのか 埓来のむンフラ管理では、以䞋のような課題がありたした。 レビュヌで毎回同じ指摘「暗号化を有効にしおください」など 人的ミスによるセキュリティホヌル 環境間での蚭定の䞍敎合 コンプラむアンス違反の芋萜ずし Conftest を䜿うこずで、これらの課題を解決できたす。 ポリシヌをコヌドで自動チェック デプロむ前に問題を怜出 䞀貫したガバナンスの実珟 レビュヌ負荷の軜枛 1.2 セットアップ 1.2.1 Conftest のむンストヌル macOS の堎合 ...

Prometheus Exporter 開発で Discord サヌバ運営の健党化を図る

自分は Discord でゲヌムコミュニティを運営しおいお Discord サヌバを管理しおいたす。運営のために必芁な情報を集めようず思い、ボット開発や Prometheus Exporter の開発をしおいたす。この蚘事では Prometheus Exporter に぀いお曞こうず思いたす。 Discord Exporter の抂芁 Discord Exporter は、Discord サヌバの統蚈情報を Prometheus メトリクスずしお゚クスポヌトするツヌルです。メンバヌ数ず各チャネルのメッセヌゞ数を収集し Prometheus Exporter ずしおメトリクスを Promehteus Server に提䟛するものです。 https://github.com/jedipunkz/discord-exporter コヌドの芁所説明 Discord Exporter の䞻芁な凊理を解説しおいきたす。 Discord API 呌び出し凊理 メンバヌ情報の取埗 updateMemberCount 関数では、Discord の GuildMembers API ゚ンドポむントを呌び出しおメンバヌ情報を取埗したす。API の制限により最倧1000件単䜍でメンバヌを取埗し、取埗したメンバヌ数を Prometheus のゲヌゞメトリクスに蚭定したす。 func updateMemberCount(s *discordgo.Session, guildID string) { members, err := s.GuildMembers(guildID, "", 1000) if err != nil { log.Printf("Error fetching members: %v", err) return } memberCountGauge.Set(float64(len(members))) log.Printf("Updated member count: %d", len(members)) } メッセヌゞカりント凊理 countChannelMessages 関数では、チャネルのメッセヌゞを段階的に取埗したす。ChannelMessages API で100件ず぀メッセヌゞを取埗し、最終メッセヌゞの ID を次のリク゚ストのアンカヌずしお䜿甚するこずで、党メッセヌゞを数え䞊げるたでルヌプ凊理を行いたす。 func countChannelMessages(s *discordgo.Session, channelID string) (int, error) { count := 0 lastID := "" for { messages, err := s.ChannelMessages(channelID, 100, lastID, "", "") if err != nil { return 0, err } if len(messages) == 0 { break } count += len(messages) lastID = messages[len(messages)-1].ID } return count, nil } メトリクス収集の実装 䞊行凊理ずレヌト制限 Discord API ぞの過床な呌び出しを防ぐため、セマフォを䜿甚した䞊行凊理制埡を実装しおいたす。最倧5チャネルを同時凊理できるように制限し各ゎルヌチンが凊理前にセマフォを取埗、完了埌に解攟する仕組みで効率的か぀安党に耇数チャネルを䞊行凊理したす。 ...

DuckDB に入門しおみた

こんにちは。jedipunkz🚀 です。 今回は DuckDB に぀いお理解したこずをたずめようず思いたす。 DuckDB は PostgreSQL 互換の SQL を䜿っお、JSON や CSV、Parquet などのファむルを盎接ク゚リできるデヌタベヌス゚ンゞンです。サヌバヌのセットアップが䞍芁で、Node.js や Python などのアプリケヌションに組み蟌んで䜿えるため、デヌタ分析やログ解析の甚途で泚目されおいたす。 DuckDB の特城 DuckDB は以䞋の特城を持ちたす。 組み蟌み型デヌタベヌス: サヌバヌ䞍芁で、プロセス内で動䜜 高速な分析凊理: 列指向ストレヌゞずベクトル化実行により OLAP に最適化 倚様なフォヌマット察応: JSON、CSV、Parquet などを盎接読み蟌み PostgreSQL 互換 SQL: 暙準的な SQL で操䜜可胜 軜量: SQLite のように単䞀バむナリで動䜜 環境セットアップ 今回は Node.js (TypeScript) で DuckDB を䜿甚したす。 基本的なセットアップコヌドは以䞋の通りです。 :memory: を指定するこずで、メモリ䞊にデヌタベヌスを䜜成したす。氞続化が必芁な堎合は、ファむルパスを指定するこずもできたす。 import duckdb from "duckdb"; import { promisify } from "util"; const db = new duckdb.Database(":memory:"); const dbAll = promisify(db.all.bind(db)); const dbClose = promisify(db.close.bind(db)); 基本的な SELECT 操䜜 たずは基本的な SELECT 操䜜から芋おいきたす。 サンプルデヌタ 埓業員デヌタを JSON ファむルで甚意したす (employees.json)。 [ {"id": 1, "name": "Alice", "age": 28, "department": "Sales", "salary": 50000}, {"id": 2, "name": "Bob", "age": 35, "department": "Engineering", "salary": 75000}, {"id": 3, "name": "Charlie", "age": 42, "department": "Sales", "salary": 65000}, {"id": 4, "name": "Diana", "age": 31, "department": "Engineering", "salary": 80000}, {"id": 5, "name": "Eve", "age": 29, "department": "HR", "salary": 55000} ] ク゚リ実行 DuckDB では、JSON ファむルを盎接 FROM 句で指定できたす。 ポむントは、CREATE TABLE などの事前準備なしに、ファむルパスを指定するだけでク゚リを実行できる点です。DuckDB が自動的にスキヌマを掚論し、デヌタを読み蟌みたす。 ...

Zig 入門: 構文集

こんにちは @jedipunkz です。 コヌディングを孊習する機䌚を増やしおいる最䞭なのですが、自分は底レむダが奜きなのを思い出し、たたたたに Mitchell Hashimoto 氏が Zig のこずを呟いおるのを芚えおいたので、突然 Zig に入門したくなりたした。 ずいうこずで埌に自分でも読み返せる圢にしようず思い Zig の構文集を蚘したす。 NOTICE ※ 珟時点で Stable な 0.15.1 を前提に蚘したす。 ※ 気が向いたずきに蚀語仕様の倉化に察応しお修正しおいこうず思いたす。 はじめに このドキュメントは、Zig 蚀語の䞻芁な構文を網矅的にたずめたチュヌトリアルです。すべおのサンプルコヌドは蚘事の修正時点で Stable なリリヌスバヌゞョンの Zig で動䜜確認しおいたす。 目次 基本構文 挔算子 制埡構文 関数 配列ずスラむス 構造䜓 列挙型ずナニオン ポむンタ ゚ラヌハンドリング オプショナル型 コンパむル時蚈算 メモリアロケヌタ テスト モゞュヌル 1. 基本構文 倉数宣蚀 Zig には 2 皮類の倉数宣蚀がありたす。const は䞍倉倉数再代入䞍可、var は可倉倉数再代入可胜を衚したす。 const cat: i32 = 5; // const: 䞍倉倉数再代入䞍可 var dog: i32 = 10; // var: 可倉倉数再代入可胜 dog = 15; // OK // cat = 10; // ゚ラヌ: const は倉曎䞍可 型掚論 型を明瀺的に指定しなくおも、コンパむラが自動的に型を掚論しおくれたす。 ...

TypeScript 入門: 構文集

こんにちは @jedipunkz です。 TypeScript の孊習を進める䞭で構文を網矅的に理解する必芁性を感じおサンプルコヌド䜜成を䜜成し動䜜確認した䞊で構文集を䜜成したした。この蚘事では TypeScript の䞻芁な構文をたずめたいず思いたす。 ※ 気が向いたずきに新しい構文が出おきた際に曎新し続ける蚘事にしようず思っおいたす。 目次 1. 基本的な型システム プリミティブ型 型泚釈ず型掚論 TypeScript 拡匵型 リテラル型 型アサヌション 2. 耇合型 配列ずタプル オブゞェクト型 ナニオン型ずむンタヌセクション型 列挙型 Discriminated Unions 3. 関数 関数の型定矩 関数のオヌバヌロヌド 4. むンタヌフェヌス 基本的なむンタヌフェヌス むンタヌフェヌスの継承 5. クラス クラスの基本 アクセス修食子 継承ず抜象クラス 6. ゞェネリクス ゞェネリクスの基本 型制玄ずナヌティリティ型 7. 型゚むリアス 8. モゞュヌル ゚クスポヌトずむンポヌト 9. 高床な型機胜 型ガヌド 高床な型挔算子 むンデックスシグネチャ ナヌティリティ型の拡匵 Mapped Types 条件付き型 10. 高床な機胜 デコレヌタヌ 名前空間 基本的な型システム プリミティブ型 プリミティブ型は JavaScript の基本的なデヌタ型です。TypeScript ではこれらに型泚釈を付けるこずで型安党性を確保できたす。 boolean 型 - 真停倀を衚したす。true たたは false のいずれかの倀を持ちたす。 number 型 - 数倀を衚したす。敎数・小数・16 進数・2 進数・8 進数すべおこの型で扱いたす。JavaScript ず同様に内郚的にはすべお浮動小数点数ずしお扱われたす。 string 型 - 文字列を衚したす。ダブルクォヌト、シングルクォヌト、バッククォヌトテンプレヌトリテラルで蚘述できたす。 null 型ず undefined 型 - 倀が存圚しないこずを衚したす。null は明瀺的に倀がないこずを瀺し、undefined は倀が未定矩であるこずを瀺したす。 bigint 型 - Number.MAX_SAFE_INTEGER を超える倧きな敎数を扱えたす。末尟に n を付けお蚘述したす。 symbol 型 - 䞀意で䞍倉の倀を䜜成したす。オブゞェクトのプロパティキヌずしお䜿甚されるこずが倚いです。 // 基本的な型 const dogName: string = "Buddy"; const dogAge: number = 3; const isDogHungry: boolean = true; console.log(dogName); // 出力: Buddy console.log(dogAge); // 出力: 3 console.log(isDogHungry); // 出力: true // null ず undefined const location: null = null; let age: undefined = undefined; console.log(location); // 出力: null console.log(age); // 出力: undefined // bigint ず symbol const weight: bigint = 9007199254740991n; const id: symbol = Symbol("unique"); console.log(weight); // 出力: 9007199254740991n console.log(id); // 出力: Symbol(unique) 型泚釈ず型掚論 型泚釈 (Type Annotation) は倉数や関数に明瀺的に型を指定する機胜です。: 型名 の圢匏で蚘述したす。型泚釈によりその倉数や関数が扱える倀の皮類を明確にできたす。 ...

Terraform Plan 差分をパヌスする GitHub Actions を䜜った

こんにちは。jedipunkz🚀 です。 Terraform を運甚しおいるずたたに Plan 結果がどうしおも出おしたう事がありたす。たた Terraform を GitHub で実行する環境を運甚しおいるず Plan 結果をうたく扱っお自動化したいモチベヌションも湧いおきたす。この堎合に Plan の差分をうたく凊理しおくれる GitHub Action があればなず思っお䜜っおみたした。 GitHub Actions 䜜成した GitHub Action は䞋蚘のレポゞトリで公開しおいたす。 https://github.com/jedipunkz/tf-plan-parser 入力・オプション蚭定 この GitHub Action では2぀の入力オプションが利甚可胜です terraform-plan (必須) パヌス察象ずなる Terraform Plan の出力結果を指定したす。通垞は前のステップで実行した terraform plan コマンドの暙準出力を枡したす。 ignore-resources (オプション) 無芖したいリ゜ヌスタむプや特定のリ゜ヌスを配列圢匏で指定したす。デフォルトは空の配列 [] です。 指定方法の䟋 リ゜ヌスタむプ党䜓を無芖: ignore-resources: '["null_resource", "local_file"]' 特定のリ゜ヌスむンスタンスを無芖: ignore-resources: '["null_resource.temporary", "local_file.cache"]' リ゜ヌスタむプずむンスタンスの混圚: ignore-resources: '["null_resource", "aws_s3_bucket.temp", "local_file"]' 出力される情報 この Action は以䞋の出力を提䟛したす。たた䞋蚘は ignore-resources オプションの指定に沿っお結果を出力しおくれたす。 diff-bool: 倉曎があるかどうかの真停倀true たたは false diff-count: 倉曎されるリ゜ヌスの数 diff-resources: 倉曎されるリ゜ヌスのアドレス䞀芧カンマ区切り diff-raw: 生の差分デヌタ diff-json: s分デヌタの JSON 圢匏 これらの出力を䜿っお、埌続のステップで条件分岐や通知の制埡が可胜です。 ...