OhMyGame
OhMyGame is the open-source studio for making games with AI. Design, build, playtest, and publish games in one app, with your own model keys.
Record and track Mahjong game scores for up to six players
AI summary · website content
GamesTypeScript · HTMLGitHub @yuxing-leeOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗LINE 群組 Bot + LIFF 記分頁。管理員在群組裡用指令或記分頁記分,Bot 把結果和排行回到群組;其他牌友不用加好友,想看個人戰績的人再到記分頁「認領」自己的名字。
分數只作為遊戲紀錄,不具任何金錢價值。
flowchart LR
subgraph LINE
G[牌友群組] -- 指令 /記 /戰績 ... --> OA[官方帳號<br/>Messaging API]
L[LIFF 記分頁<br/>在 LINE 裡開啟]
end
OA -- webhook --> F
F -- 回覆 / 推播 --> OA
L -- 頁面 --> V[Vercel<br/>liff/index.html]
L -- API + LINE ID token --> F
subgraph Supabase
F[Edge Function mj] --> DB[(Postgres<br/>rooms / players / games / scores / room_admins)]
end
GH[GitHub main] -- push 自動部署 --> V
| 元件 | 負責什麼 | 程式位置 |
|---|---|---|
| LINE 官方帳號(Messaging API) | 群組裡收指令、回覆、推播 | — |
| LINE Login channel + LIFF | 記分頁在 LINE 裡打開、取得使用者身分 | — |
Supabase Edge Function mj | Bot webhook + 記分頁用的 API | supabase/functions/mj/ |
| Supabase Postgres | 存房間、玩家、對局、管理員 | supabase/migrations/ |
| Vercel | 放記分頁(純靜態,只發佈 liff/) | liff/index.html、vercel.json |
| GitHub | 原始碼;推到 main 會觸發 Vercel 部署 | 這個 repo |
| 項目 | 值 |
|---|---|
| GitHub repo | yuxing-lee/mahjong(分支 main) |
| 本機資料夾 | C:\Users\user\Desktop\Side Project\majong-line |
| Supabase 專案 | majong-line,ref hofjzjhqizukceosjufr(Singapore) |
| Edge Function | mj(Verify JWT 關閉) |
| Webhook URL | https://hofjzjhqizukceosjufr.supabase.co/functions/v1/mj/webhook |
| 記分頁 API | https://hofjzjhqizukceosjufr.supabase.co/functions/v1/mj/api |
| 記分頁網址(Vercel) | https://mahjong-gold-ten.vercel.app |
| LINE Provider | AI助手 |
| LIFF ID | 2011866186-iudTebek(LIFF URL:https://liff.line.me/2011866186-iudTebek) |
| 名稱 | 從哪裡拿 |
|---|---|
LINE_CHANNEL_SECRET | Messaging API channel → Basic settings → Channel secret |
LINE_CHANNEL_ACCESS_TOKEN | Messaging API channel → Messaging API 分頁最下面 → Channel access token (long-lived) |
LINE_LOGIN_CHANNEL_ID | LINE Login channel(LIFF 所在的那個)→ Basic settings → Channel ID |
LIFF_ID(選填) | 沒設的話程式預設用 2011866186-iudTebek |
SUPABASE_URL、SUPABASE_SERVICE_ROLE_KEY 由 Supabase 自動提供,不用設。在 Supabase 上程式會自動使用資料庫;STORE 只有本機測試才需要。
這些值不要放進 repo、也不要截圖外流。 外流的話到 LINE Developers 按 Issue 重新產生,再更新 Secrets。
| 指令 | 誰能用 | 說明 |
|---|---|---|
/開房 週五麻將 | 任何人(建的人=房主) | 把群組設成計分房 |
/加人 小明 阿華 老王 阿美 | 管理員 | 加玩家(名字不能有數字、+、-) |
/記 小明+100 阿華-30 老王-70 | 管理員 | 記一場,總和必須是 0(也接受「小明 100 阿華 -30」和全形數字) |
/戰績 | 所有人 | 排行榜卡片(附「開啟記分頁」按鈕) |
/最近 | 所有人 | 最近 5 場 |
/分析 名字 | 所有人 | 個人摘要:勝率、近 10 場、最順的同桌、剋星、提款機(不打名字=看自己,需先認領) |
/撤銷 | 管理員 | 刪最後一場 |
/刪房 | 管理員 | 刪除房間和所有紀錄(會先要求 /刪房 確認) |
/設台費 名字、/取消台費 名字 | 管理員 | 台費帳戶(例如場主設備錢「東」)照樣記分、照樣出現在排行,但不列入個人分析 |
/消費 飲料 300 | 管理員 | 記一筆額外消費(例如飲料錢),只記品項和總金額,不算進任何人的輸贏 |
/消費 | 所有人 | 看這個月的台費收入、額外消費、結餘和最近幾筆消費 |
/選單 | 所有人 | 回一張按鈕卡片:記分、排行、分析、走勢、紀錄、東的消費(點了直接開到記分頁那一頁),下面再一排戰績/最近/本月帳。輸入框上方的快速按鈕也有「選單」 |
/設管理員 @某人 | 管理員 | 設成管理員(也可以用已認領的名字:/設管理員 阿華) |
/移除管理員 @某人 | 管理員 | 取消管理員(房主不能被移除) |
/管理員 | 所有人 | 列出房主和管理員 |
/記分頁 | 所有人 | 取得記分頁連結 |
/說明 | 所有人 | 指令列表 |
/ 開頭的訊息 Bot 不回,不會洗版。/戰績。&tab=record|rank|analysis|trend|history|expense 直接開到某一頁(/選單 的按鈕就是這樣做的);沒權限的分頁會退回第一頁?demo=1 進入試玩模式:不用登入、不連後端,資料只存在那台裝置liff/index.html)推到 GitHub main 就好,Vercel 會自動部署,LINE 不用改。
git add liff/index.html
git commit -m "..."
git push origin main
supabase/functions/mj/)推 GitHub 不會自動更新 Supabase,要另外部署:
npx supabase login # 第一次才需要
npx supabase functions deploy mj --project-ref hofjzjhqizukceosjufr
supabase/config.toml 已經把 mj 設成 verify_jwt = false。如果改從 Supabase 後台部署,記得也要把 Verify JWT 關掉,不然 LINE webhook 和記分頁都會被擋(401)。
supabase/migrations/ 新增一個檔案,例如 003_xxx.sqlnpx supabase link --project-ref hofjzjhqizukceosjufr 後 npx supabase db push目前的資料表:
| 表 | 內容 |
|---|---|
rooms | 房間;line_group_id 綁群組、admin_line_user_id 是房主、code 是記分頁連結用的房號 |
players | 玩家名字;line_user_id 有值代表已被認領 |
games | 每一場 |
scores | 每場每人的分數 |
room_admins | 房主以外的管理員 |
players.is_house = true 代表台費帳戶(目前「紅中」房的「東」)。
記一場是透過資料庫函式 record_game_at()(可指定日期;舊的 record_game() 保留未用),在同一個交易裡再檢查一次「至少兩人、總和為 0、玩家屬於這個房間」。
所有表都開了 RLS 但沒有 policy,這是刻意的:網頁不直接連資料庫,所有讀寫都經過 Edge Function(service role)。Supabase 的安全檢查會提示「RLS Enabled No Policy」,可以忽略。
liff/index.html 最上面的 LIFF_ID、API_BASE兩個 channel 都在 AI助手 Provider 底下(必須同一個 Provider,userId 才對得上)。
Messaging API channel(Bot)
https://hofjzjhqizukceosjufr.supabase.co/functions/v1/mj/webhook,Use webhook 開啟,Verify 成功官方帳號(manager.line.biz → 設定)
LINE Login channel
LINE_LOGIN_CHANNEL_ID2011866186-iudTebek:Size Full、Scopes 勾 openid、profile、Endpoint URL = https://mahjong-gold-ten.vercel.app新的 Messaging API channel 不能直接在 Developers Console 建立,要先在 manager.line.biz 建官方帳號,再到「設定 → Messaging API」啟用。
| 狀況 | 原因 / 處理 |
|---|---|
| Bot 加進群組馬上退出 | 官方帳號沒開「接受邀請加入群組」 |
| Webhook Verify 顯示 timeout | 剛改 Secrets 或剛部署時函式在重啟,等幾秒再按一次 |
| Webhook Verify 顯示 401 | LINE_CHANNEL_SECRET 錯,或 Verify JWT 沒關 |
| 記分頁顯示「LINE Login Channel ID 設定不符」 | LINE_LOGIN_CHANNEL_ID 填成別的 channel 的 ID |
| 記分頁顯示「登入已過期」 | 關掉頁面重新開啟 |
| 記分頁顯示「拿不到 LINE 登入資訊」 | LIFF 的 Scopes 沒勾 openid |
| 群組打指令沒反應 | 看 Supabase → Edge Functions → mj → Logs;確認 Use webhook 有開、自動回應有關 |
| 私訊 Bot 只回「請把我加進群組」 | 目前設計是房間綁群組,指令要在群組裡用 |
查紀錄:Supabase 後台 → Edge Functions → mj → Logs / Invocations。
.
├─ liff/index.html 記分頁(單一檔案,內建試玩模式)
├─ vercel.json Vercel 只發佈 liff/,不跑 build
├─ deno.json dev / test / check 指令
├─ .env.example 本機測試用的環境變數範本
└─ supabase/
├─ config.toml CLI 設定(mj 關閉 verify_jwt)
├─ migrations/
│ ├─ 001_init.sql rooms / players / games / scores + record_game()
│ ├─ 002_room_admins.sql 多位管理員
│ ├─ 003_house_player.sql 台費帳戶(players.is_house)
│ ├─ 004_game_date.sql record_game_at():記分時可指定日期
│ └─ 005_expenses.sql expenses 表:額外消費(品項、金額、日期)
└─ functions/mj/
├─ index.ts Bot webhook + 記分頁 API
├─ logic.ts 解析分數、計算戰績、個人分析(純邏輯)
├─ store.ts 儲存介面;在 Supabase 上自動用資料庫,本機預設用 JSON 檔
├─ store_supabase.ts Supabase 實作
├─ store_file.ts JSON 檔實作(本機測試用)
└─ logic_test.ts / e2e_test.ts 測試
.../functions/v1/mj/ 底下)| 路由 | 說明 |
|---|---|
POST webhook | LINE webhook(用 Channel secret 驗簽章) |
GET api/room?code=房號 | 記分頁讀資料 |
GET api/analysis?code=房號&player=玩家ID | 個人分析 |
POST api/game | 記一場(管理員,可帶 played_at 補記日期),成功後推播到群組 |
POST api/game/delete | 刪一場(管理員) |
POST api/game/date | 改某場的日期(管理員) |
POST api/game/split | 把一場拆成兩桌(管理員;檢查分數對得上後新增兩場、刪掉原本那場) |
POST api/player | 加玩家(管理員) |
POST api/claim | 認領名字 |
GET health | 健康檢查 |
api/* 需要 Authorization: Bearer <LINE ID token>,由記分頁的 LIFF SDK 自動帶入。
需要 Deno 2。
deno task test # 單元測試 + 端到端測試(不連 LINE、不連 Supabase)
deno task check # 型別檢查
想在本機跑一個完整的 Bot(資料存在 ./data.json):
cp .env.example .env # 填 LINE 的值,STORE=file
deno task dev # http://localhost:8000
cloudflared tunnel --url http://localhost:8000 # LINE 需要 HTTPS
再把 LINE 的 Webhook URL 暫時改成 https://<通道網址>/webhook、記分頁的 API_BASE 改成 https://<通道網址>/api。測完記得改回 Supabase 的網址。
沒填 LINE_CHANNEL_ACCESS_TOKEN 時,Bot 要送的訊息只會印在終端機。