« Screen Code Analyzer から firebase へデータ送信 | メイン | Firebase Authentication »

javascript

Firebase で BBS

Firebase BBS  Firebase Functions + Firestore の応用で チャット や ツイッター サンプルが見つかるが 古く不完全。 BBS として完成させる備忘録。

前提環境
●Google Chrome 114.0.5735.199(Official Build)(64 ビット)
●FireFox 115.0.2 (64 ビット)
「Firebase Functions」 の Functions 利用登録済。関数名 「a」。[Google Cloud Shell] を利用。
「Firebase Functions + Firestore」 の Firestore 利用登録済。コレクション名「bbs」。
●v18.12.1 (Node)
●9.7.2 (Node Package Manager)
●12.4.4 (Firebase CLI)
●BBS のURL
https://remix.asia/bbs.html
...▼
Cloud Shell Editor
https://console.cloud.google.com/cloudshelleditor
functions/index.js を次のように置き換え。
$ vi functions/index.js
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger}= require("firebase-functions");
const {onRequest}= require("firebase-functions/v2/https");

// The Firebase Admin SDK to access Firestore.
const {initializeApp}= require("firebase-admin/app");
const {getFirestore}= require("firebase-admin/firestore");

const cors= require( "cors" )( {origin: true} );// ★2

initializeApp();

exports.a= onRequest( async (req, res) => {
	const date = new Date();
	logger.log( "req.method:", req.method, date );
	res.set( "Access-Control-Allow-Origin", "https://remix.asia" );// ★1

	let n= "Unknown";// 名前
	let m= "";// メッセージ
	let p= "up";//処理
	switch ( req.method ){
		case "GET":
		case "POST":
			if( undefined === req.body.n ){
				p= "list";// パラメータなければ一覧表示
			}else if( 0 < req.body.n.length ){
				n= req.body.n;
			}
			if( undefined !== req.body.m ){
				m= req.body.m;
			}
			break;
		case "OPTIONS":// ★2
			cors( req, res, () => {
				res.status( 200 ).send();
			});
			return "";
		default:
			p= "other";
	}

	switch( p ){
		case "list":{
			try{
				const map= {};
				const querySnapshot= await getFirestore().collection( "bbs" )
					.orderBy( "when", "asc" )
					.get();
				querySnapshot.forEach( ( m ) => {
					map[m.id]= m.data();
				});
				res.status( 200 ).json( map );
				return "";
			}catch( err ){
				const s= {error: {message: err.toString()}};
				res.status( 400 ).json( s );
			}
			break;
		}
		case "up":{
			const r= await getFirestore()
				.collection( "bbs" )
				.add( {
					when: date,
					who: n,
					msg: m,
				});
			const s= {success: {message: `Message with ID: ${r.id} added.`}};
			res.json( s );
			break;
		}
		default:{
			const s= {error: {message: "bad parameter."}};
			res.status( 400 ).json( s );
		}
	}
	return "";
});
Firebase Functions 関数名 a
Firestore コレクション名 bbs
ポイントは
★1 https://remix.asia からのアクセスを許可
★2 ブラウザから json 受信する為

 関数 a デプロイ
$ firebase deploy --only functions:a
 Function URL
https://a-yukh3omtca-uc.a.run.app


https://remix.asia/bbs.html の内容。
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>BBS</title>
</head>
<body style="background-color:black;color:silver">



<form id="myForm">
	<input type="button" value="renew" id="btnRenew">
	名前:<input type="text" name="n" autocomplete="on">
	メッセージ:<input type="text" name="m">
	<input type="submit" value="submit">
	<input type="reset" value="reset">
</form>
<div id="myList">"renew" update message list.</div>



<script>
const sURL= "https://a-yukh3omtca-uc.a.run.app";// ★Function URL
const myList= document.getElementById( "myList" );
const btnRenew= document.getElementById( "btnRenew" );
const myForm= document.getElementById( "myForm" );

const fetchList= async( str ) => {
	const response = await fetch( str, {
		method: "GET"
	} );
	const json = response.json();
	if ( 200 == response.status ) {
		return Promise.resolve( json );
	} else {
		return Promise.reject( json.error );
	}
};

const getList= ( event ) => {
	fetchList( sURL ).then( ( obj ) => {
		let s= "";
		Object.keys( obj ).forEach( function( k ){
			s= "<hr><div>" + obj[k].who + " : " + obj[k].msg + "</div>" + s;
		});
		myList.innerHTML= s;
	}).catch( ( err ) => {
		console.log( err );
		myList.innerHTML = err;
	});
};

const fetchSendData= async( str ) => {
	let o= new Object();
	let formData= new FormData( myForm );
	for( let kv of formData.entries() ){
		o[kv[0]]= kv[1];
	}
	const s= JSON.stringify( o );
	const response= await fetch( str, {
		method: "POST"
	,	body: s
	,	headers: new Headers( { "Content-type": "application/json" } )
	} );
	const json= response.json();
	if( 200 == response.status ){
		return Promise.resolve( json );
	}else{
		return Promise.reject( json.error );
	}
};

const sendData= ( event ) => {
	event.preventDefault();//イベントデフォルト動作をキャンセル

	fetchSendData( sURL ).then( ( obj ) => {
		getList();
		alert( obj.success.message );
	}).catch( ( err ) => {
		console.log( err );
	});
};

btnRenew.addEventListener( "click", getList );
myForm.addEventListener( "submit", sendData );
</script>



</body>
</html>

 ブラウザで https://remix.asia/bbs.html アクセス直後。

名前とメッセージを送信。
renewボタンで最新メッセージ一覧。

■Firebase Console
https://console.firebase.google.com/
 firestore に記録される。

トラックバック

このエントリーのトラックバックURL:
https://www.remix.asia/cgi/mt/mt-tb.cgi/7756

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)