Open20
ポーカーチップ計算LINE Botを作りたい
グループへの参加(Bot自身が参加)イベントはこんな感じで取れる
switch (event.source.type) {
case "group": {
const groupId = event.source.groupId;
const groupSummary = await lineClient.getGroupSummary(groupId);
グループIDからユーザーのIDを取得するには認証済みアカウントになる必要があるみたい。
個人開発アプリだと厳しそう。
それにポーカーが題材だからギャンブルに該当しそうな予感。
認証済みアカウントになるのは諦める。
最初に「ディーラー」とメッセージを送った人がディーラー役になる、というフローでええか
いや、
- 最初は2人(ディーラー役とBot)でグループを作る
- ディーラー役のユーザーが「ディーラー」とメッセ
- Botがそれを検知して、メッセージからUserIDを取得
- DBにグループIDとディーラー役のIDを保存
- メンバーを追加していく
- メンバー追加イベントからはユーザーのIDを取得できるため、DBにメンバーを登録していく
これ良さげ
realtime database を使おうとしたけどFirestoreの方が使いやすいからFirestore使う
これでgroupIdのドキュメントをFirestoreに作成できる
switch (event.source.type) {
case "group": {
const groupId = event.source.groupId;
const groupsRef = databaseClient.collection("groups");
await groupsRef.doc(groupId).create({dealer: null})
Botがグループから退室したときはFirestoreから削除
switch (event.source.type) {
case "group": {
const groupId = event.source.groupId;
const groupRef = databaseClient.collection("groups").doc(groupId);
await groupRef.delete();
LINE グループの作成、削除をやりすぎたのか、グループが作れなくなった。
1ヶ月グループ作成できないらしい…
しょうがないのでLIFFの方にとりかかる。
npx @line/create-liff-app
Create LIFF Appを使ってプロジェクトを作成する。
フレームワークはNext.jsを使ってみる。
LINE関連の処理をここでまとめて
import liff from "@line/liff";
import {LiffMockPlugin} from "@line/liff-mock";
import {LIFF_ID} from "@/utils/secrets";
import {Profile} from "@liff/get-profile";
export const liffInit = async () => {
if (process.env.NODE_ENV === 'development') {
liff.use(new LiffMockPlugin())
// @ts-ignore
await liff.init({ liffId: LIFF_ID, mock: true })
} else {
await liff.init({ liffId: LIFF_ID })
}
}
export const liffLogin = async () => {
if (!liff.isInClient()) liff.login();
}
export const liffGetProfile = async (): Promise<Profile> => {
return await liff.getProfile();
}
export const liffIsLoggedIn = (): boolean => {
return liff.isLoggedIn();
}
こんな感じで使う
import {liffGetProfile, liffInit, liffIsLoggedIn, liffLogin} from "@/lib/line";
import {Profile} from "@liff/get-profile";
import {useEffect, useState} from "react";
import Head from "next/head";
export default function UserProfile() {
const [profile, setProfile] = useState<Profile | null>(null)
useEffect(() => {
(async () => {
await liffInit();
if (!liffIsLoggedIn()) {
await liffLogin();
}
const profile = await liffGetProfile();
setProfile(profile);
})()
}, [])
リロードしたらエラーになった。
error - ReferenceError: self is not defined
at Object.<anonymous>
chatGPTに聞いてもよくわからない。
これはうまくいく
import("@line/liff")
.then((liff) => liff.default)
.then((liff) => {
console.log("LIFF init...");
liff
.init({ liffId: process.env.NEXT_PUBLIC_LIFF_ID! })
.then(() => {
console.log("LIFF init succeeded.");
setLiffObject(liff);
})
.catch((error: Error) => {
console.log("LIFF init failed.");
setLiffError(error.toString());
});
});
結局よくわからないしNext.jsはオーバースペックな気がするので、大人しくReactを使うことにする
Viteの場合の環境変数の取得方法
export const LIFF_ID = import.meta.env.VITE_LIFF_ID;
グループとそこに所属するユーザーの情報を取得するコード
export default function Pot() {
const [pot, setPot] = useState<0 | number>(0);
useEffect(() => {
(async () => {
const group = await getGroupById("hoge");
setPot(group?.pot!)
console.log(group);
})();
}, []);
return (
<>
<h1>{pot}</h1>
</>
)
}
export async function getGroupById(groupId: string): Promise<Group | null> {
try {
// 指定したIDのgroupドキュメントを取得
const groupDocRef = doc(db, 'groups', groupId);
const groupDocSnap = await getDoc(groupDocRef);
if (groupDocSnap.exists()) {
// groupドキュメントのデータを取得
const groupData = groupDocSnap.data();
// サブコレクションusersを取得
const usersCollectionRef = collection(db, 'groups', groupId, 'users');
const usersQuery = query(usersCollectionRef);
const usersQuerySnapshot = await getDocs(usersQuery);
console.log('usersQuerySnapshot: ', usersQuerySnapshot.docs)
const usersData: User[] = usersQuerySnapshot.docs.map((userDoc) => {
// usersドキュメントのデータを取得
const userData = userDoc.data();
return {
id: userDoc.id,
name: userData.name,
isDealer: userData.isDealer,
stack: userData.stack
};
});
// Group型に変換して返す
return {
id: groupDocSnap.id,
pot: groupData.pot,
users: usersData
};
} else {
console.log('Group does not exist.');
return null;
}
} catch (error) {
console.log('Error getting group and users by ID: ', error);
return null;
}
}
(9割chatGPTで生成しました)
LIFFアプリを開かせるためのクイックリプライメッセージの作り方
export const makeQuickReplyMessage = (): Message => {
const liffUrl = `https://your-liff-url`;
const quickReplyItem = {
type: "action",
imageUrl: "https://your-image-url",
action: {
type: "uri",
label: "チップ計算を開く",
uri: liffUrl
}
} as QuickReplyItem;
const quickReply: QuickReply = {
items: [
quickReplyItem
]
}
return {
type: "text",
text: "LIFFアプリを開いてください。",
quickReply: quickReply
}
}
export const liffGetGroupId = async () => {
const context = liffGetContext();
if (context && context.type === 'group') {
return context.groupId;
}
}
liffアプリからこれでGroupIdを取得できると思ったが、このプロパティは廃止されたらしい。
なので、urlのクエリパラメータで送る必要がありあそうだ