Codync
免費、開源的 1:1 替代方案,取代 Grok Bot 與 Muse。從 iPhone、Mac 或 Linux 桌面將 Claude Code、Codex、Cursor 與 40+ 程式碼代理人作為持續機器人傳訊。群組聊天、主題串…
AI 翻譯
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗MyACTの次世代バックエンドWebサービス
SOTAApp2は、アマチュア無線のアワードプログラム(SOTA、POTA)を管理するための高性能・高可用性Webサービスです。ヘキサゴナルアーキテクチャを採用し、Rustで実装されています。
本システムは**ヘキサゴナルアーキテクチャ(Clean Architecture)**を採用し、以下の6つのレイヤーで構成されています:
┌─────────────────────────────────────────────┐
│ API │ ← RESTエンドポイント・認証・バリデーション
├─────────────────────────────────────────────┤
│ Service │ ← ユースケース・ビジネスロジック
├─────────────────────────────────────────────┤
│ Domain │ ← エンティティ・バリューオブジェクト
├─────────────────────────────────────────────┤
│ Adapter │ ← DB・外部API・APRS・ファイルアクセス
├─────────────────────────────────────────────┤
│ Registry │ ← 依存性注入・モジュール管理
├─────────────────────────────────────────────┤
│ Common │ ← 共通ライブラリ・設定・エラーハンドリング
└─────────────────────────────────────────────┘
api/)service/)UserService: ユーザー向け機能AdminService: 管理者向け機能AdminPeriodicService: バッチ処理・定期実行domain/)Activation: アクティベーション(Alert/Spot)SOTAReference: SOTA山岳データPOTAReference: POTA公園データAprsLog: APRS通信ログadapter/)registry/)common/)| ユースケース | 主要メンテナンス対象 | 変更頻度 | 注意点 |
|---|---|---|---|
| 新機能追加 | Service → API → Domain | 高 | ドメイン変更は慎重に |
| 外部API変更 | Adapter | 中 | インターフェース維持 |
| UI/UX改善 | API(ハンドラー・モデル) | 高 | DTOとドメインの分離 |
| パフォーマンス | Adapter → Service | 中 | N+1問題、キャッシュ |
| セキュリティ | API(認証)→ Common | 低 | 認証・認可ロジック |
| データ移行 | Adapter(migrations) | 低 | スキーマバージョニング |
| 設定変更 | Common | 中 | 環境変数・設定ファイル |
// ✅ 良い例: トレイトによる抽象化
#[async_trait]
pub trait UserService {
async fn find_user(&self, id: UserId) -> AppResult<User>;
}
// ✅ 良い例: 型安全性
pub struct SummitCode(String);
impl SummitCode {
pub fn new(code: String) -> Self {
// バリデーション
Self(code)
}
}
// ❌ 悪い例: 直接的な依存
// Service層からAdapter実装に直接依存
詳細な開発環境構築手順は docs/development-setup.md を参照してください。
git clone https://github.com/jl1nie/sotaapp2.git
cd sotaapp2
cp .env.example .env # 編集してAPIキー等を設定
makers build && makers migrate run && makers run
本番環境: https://sotaapp2.fly.dev
| エンドポイント | 説明 |
|---|---|
GET /api/v2/health | サーバーヘルスチェック |
GET /api/v2/health/db | データベース接続確認 |
| エンドポイント | パラメータ | 説明 |
|---|---|---|
GET /api/v2/activation/alerts | pat_ref (必須) | アラート一覧取得 |
GET /api/v2/activation/spots | pat_ref (必須), hours_ago | スポット一覧取得 |
GET /api/v2/activation/aprs/track | pat_ref (必須), hours_ago | APRSトラック取得 |
パラメータ例:
pat_ref=JA - 日本のアクティベーションpat_ref=JA,HL - 日本と韓国hours_ago=24 - 過去24時間| エンドポイント | 説明 |
|---|---|
GET /api/v2/propagation/geomag | 最新の地磁気指数(A/K指数) |
レスポンス例:
{
"date": "2025-12-26",
"a_index": 12,
"k_index": [3.0, 3.33, 2.67]
}
| エンドポイント | パラメータ | 説明 |
|---|---|---|
GET /api/v2/search | min_lat, max_lat, min_lon, max_lon | 範囲内の山岳・公園検索 |
パラメータ例:
/api/v2/search?min_lat=35&max_lat=36&min_lon=139&max_lon=140
| エンドポイント | パラメータ | 説明 |
|---|---|---|
GET /api/v2/map | lat (必須), lon (必須), zoom, label, tile, embed | 指定座標を中心とした地図をHTMLで表示 |
GET /api/v2/map/view | 同上 | 地図描画に必要な情報をJSONで返す(フロントエンド連携用) |
| パラメータ | 既定値 | 説明 |
|---|---|---|
lat | - | 緯度(-90〜90) |
lon | - | 経度(-180〜180) |
zoom | 15 | ズームレベル(1〜19。タイルの最大ズームに丸められる) |
label | - | マーカーに表示する名称(100文字以内) |
tile | gsi | タイル種別。gsi = 地理院タイル(日本国内のみ)、osm = OpenStreetMap(日本国外はこちら) |
embed | false | trueでヘッダを省略(iframe埋め込み用) |
refs | true | falseで近傍のSOTA山岳・POTA公園の表示を止める |
radius | 1000 | 近傍を探す半径。単位はメートル(1〜10000) |
中心の近く(radius以内)にあるSOTA山岳・POTA公園を、近い順に最大20件マーカーで表示します
(青 = SOTA、緑 = POTA。ポップアップにコード・名称・標高/所在地・距離)。
/api/v2/map/view では nearby 配列として返します。
パラメータ例:
/api/v2/map?lat=35.360556&lon=138.727778&zoom=13&label=富士山&tile=gsi
ブラウザで開くと、指定座標にマーカーを立てた地図(Leaflet)が表示されます。 マーカーのポップアップには座標とグリッドロケータ(メイデンヘッド)が表示されます。
admin/src/lib/api.ts にクライアントヘルパーを用意しています。
import { buildMapUrl, getMapView, hasValidCoordinates } from '$lib/api';
// 1. 別タブで開く / iframeのsrcに指定する
const url = buildMapUrl({ lat, lon, label: summitName });
window.open(url, '_blank', 'noopener');
// 2. iframeに埋め込む(ヘッダ非表示)
const embedUrl = buildMapUrl({ lat, lon, label: summitName, embed: true });
// 3. 自前の地図コンポーネントで描画する
const view = await getMapView({ lat, lon, tile: 'gsi' });
// view.tile.urlTemplate / view.tile.attribution / view.tile.maxZoom を
// Leaflet等にそのまま渡せる。view.externalLinks には外部地図サービスへのリンク。
GET /api/v2/map/view のレスポンス例:
{
"latitude": 35.360556,
"longitude": 138.727778,
"zoom": 15,
"maidenhead": "PM95ii76",
"label": "富士山",
"tile": {
"kind": "gsi",
"urlTemplate": "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png",
"attribution": "<a href=\"https://maps.gsi.go.jp/development/ichiran.html\">地理院タイル</a>",
"maxZoom": 18
},
"mapUrl": "/api/v2/map?lat=35.360556&lon=138.727778&zoom=15&tile=gsi&label=%E5%AF%8C%E5%A3%AB%E5%B1%B1",
"embedUrl": "/api/v2/map?lat=35.360556&lon=138.727778&zoom=15&tile=gsi&label=%E5%AF%8C%E5%A3%AB%E5%B1%B1&embed=true",
"externalLinks": {
"googleMaps": "https://www.google.com/maps?q=35.360556,138.727778",
"openStreetMap": "https://www.openstreetmap.org/?mlat=35.360556&mlon=138.727778#map=15/35.360556/138.727778",
"gsiMaps": "https://maps.gsi.go.jp/#15/35.360556/138.727778/"
},
"nearby": [
{
"kind": "sota",
"code": "JA/YN-001",
"name": "Mt.Fuji",
"nameJ": "富士山",
"latitude": 35.360556,
"longitude": 138.727778,
"distanceM": 0,
"altM": 3776,
"points": 10,
"location": "静岡県富士宮市"
}
]
}
管理コンソール(admin/)のSOTA/POTAリファレンス編集画面には、
編集中の座標を地図で開く「🗺 地図で位置を確認」ボタンを追加しています。
| 変数名 | 説明 | デフォルト |
|---|---|---|
DATABASE_URL | データベースURL | sqlite:sotaapp2.db |
CF_ACCESS_TEAM_DOMAIN / CF_ACCESS_AUD | Cloudflare Access のチームのドメインとアプリの識別子(両方そろうと管理画面の署名を検証) | - |
HOST | バインドホスト | 0.0.0.0 |
PORT | ポート番号 | 8080 |
LOG_LEVEL | ログレベル | info |
詳細はdocker-compose.yaml参照。
# 全テスト実行
makers test
# CI用テスト(fmt-check + clippy-strict + test)
makers ci
Dockerイメージに対する包括的なE2Eテストを実行します。
# Dockerイメージをビルドしてテスト実行
makers e2e
# 既存イメージでテストのみ実行
makers e2e-test jl1nie/sotaapp2:latest
# テストサーバー起動(手動確認用)
makers e2e-server
makers e2e-stop
E2Eテストは以下の4フェーズで構成されています:
| フェーズ | テスト内容 |
|---|---|
| BUILD | 実行ファイル・migrations・staticの存在確認 |
| RUNTIME | SSL/TLS接続・ca-certificates・libssl確認 |
| APP | CLIコマンド(help, migrate等)の動作確認 |
| SERVER/API | サーバー起動・ヘルスチェック・主要APIエンドポイント |
詳細は docs/docker-e2e-test-plan.md を参照。
GitHub Actionsで以下が自動実行されます:
詳細は docs/deployment-manual.md を参照。
# 通常デプロイ(バックアップ付き)
makers deploy
# バックアップなしデプロイ
makers deploy-no-backup
# Fly.io直接デプロイ
makers fly-deploy
# バックアップ作成
makers fly-backup
# バックアップ一覧
makers fly-db-list
# リストア
makers fly-db-restore /data/backup_YYYYMMDD_HHMMSS.db
# 最適化
makers fly-db-optimize
詳しい開発フローは Repository Guidelines を参照してください。
本プロジェクトは Apache License 2.0 の下で公開されています。
Copyright 2024-2026 Minoru Tomobe (JL1NIE)
Happy Coding! 73! 🎯📡