aboutsummaryrefslogtreecommitdiff
path: root/firebase-io
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-05-22 20:59:49 +0200
committertomsmeding <tom.smeding@gmail.com>2017-05-22 20:59:49 +0200
commitdabeb3a9fe2295e9b95a46e72de6e78e78f1befb (patch)
treebfb2ae709c746fb9fd6a807200be27b0e003bc6e /firebase-io
parent9500daf44d23689d83d480acebdd20f9fc78acdd (diff)
server: WIP firebase
Diffstat (limited to 'firebase-io')
-rw-r--r--firebase-io/.gitignore1
-rwxr-xr-xfirebase-io/firebase-io.js134
-rw-r--r--firebase-io/package.json23
3 files changed, 158 insertions, 0 deletions
diff --git a/firebase-io/.gitignore b/firebase-io/.gitignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/firebase-io/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/firebase-io/firebase-io.js b/firebase-io/firebase-io.js
new file mode 100755
index 0000000..8a94076
--- /dev/null
+++ b/firebase-io/firebase-io.js
@@ -0,0 +1,134 @@
+#!/usr/bin/env node
+const firebase=require("firebase-admin");
+const util=require("util");
+
+firebase.initializeApp({
+ credential:firebase.credential.cert(require("./firebaseServiceAccountKey.json")),
+ databaseURL:"https://tomsg-83196.firebaseio.com",
+});
+
+const fieldConverters=new Map([
+ ["token",(b)=>b.toString()],
+ ["user",(b)=>b.toString()],
+ ["room",(b)=>b.toString()],
+ ["message",(b)=>b.toString()],
+ ["timestamp",(b)=>b.toString()], // Nanosecond timestamps are too close to 52-bit range
+ ["online",(b)=>parseInt(b.toString(),10)],
+]);
+
+function typeConvertFields(fields){
+ for(const key of fields.keys()){
+ const conv=fieldConverters.get(key);
+ if(conv!=undefined)fields.set(key,conv(fields.get(key)));
+ }
+}
+
+function readFields(buffer){
+ const fields=new Map();
+ if(buffer.length==0)return fields;
+ let cursor=0;
+ while(true){
+ let idx=buffer.indexOf(32,cursor);
+ if(idx==-1){
+ console.error("ERR: Incomplete field in input line");
+ return null;
+ }
+ const key=String(buffer.slice(cursor,idx));
+ cursor=idx+1;
+
+ idx=buffer.indexOf(32,cursor);
+ if(idx==-1){
+ console.error("ERR: Incomplete field in input line");
+ return null;
+ }
+ const arglen=parseInt(String(buffer.slice(cursor,idx)),10);
+ if(arglen<0||arglen==null||isNaN(arglen)){
+ console.error("ERR: Invalid length in input line");
+ return null;
+ }
+ cursor=idx+1;
+
+ if(cursor+arglen>buffer.length){
+ console.error("ERR: Length larger than remaining line in input line");
+ return null;
+ }
+ const arg=buffer.slice(cursor,cursor+arglen);
+ cursor+=arglen;
+
+ fields.set(key,arg);
+
+ if(cursor==buffer.length)break;
+ if(buffer[cursor]!=32){
+ console.error("ERR: No space after argument in input line");
+ return null;
+ }
+ cursor++;
+ }
+ return fields;
+}
+
+function processMessage(type,fields){
+ switch(type){
+ case "message":
+ const user=fields.get("user");
+ const token=fields.get("token");
+ const payload={
+ notification: {
+ title: user+" ("+fields.get("room")+")",
+ body: fields.get("message"),
+ }
+ };
+ firebase.messaging().sendToDevice(token,payload)
+ .then((response)=>{
+ const result=response.results[0];
+ const realToken=result.canonicalRegistrationToken;
+ if(result.error){
+ console.error("JS: Send error:",result.error);
+ } else if(realToken&&realToken!=token){
+ console.log("delete_token "+user+" "+token);
+ console.log("add_token "+user+" "+realToken);
+ }
+ })
+ .catch((err)=>{
+ console.error("JS: Early send error:",err);
+ });
+ break;
+
+ default:
+ console.error("JS: Unknown type '"+type+"'");
+ }
+}
+
+function handleInputLine(buffer){
+ let idx=buffer.indexOf(32);
+ if(idx==-1){
+ console.error("ERR: No space in input line");
+ return;
+ }
+ const type=String(buffer.slice(0,idx));
+ const fields=readFields(buffer.slice(idx+1));
+ if(fields==null)return;
+ typeConvertFields(fields);
+ processMessage(type,fields);
+}
+
+
+{
+ let buffer=null;
+ process.stdin.on("data",(data)=>{
+ const prevlen=buffer==null?0:buffer.length;
+ if(buffer)buffer=Buffer.concat([buffer,data]);
+ else buffer=data;
+ let cursor=0;
+ let lfidx=buffer.indexOf(10,prevlen);
+ while(lfidx!=-1){
+ handleInputLine(buffer.slice(cursor,lfidx));
+ cursor=lfidx+1;
+ lfidx=buffer.indexOf(10,cursor);
+ }
+ if(cursor>=buffer.length)buffer=null;
+ else buffer=Buffer.from(buffer.slice(cursor));
+ });
+}
+
+console.error("Firebase js plugin loaded!");
diff --git a/firebase-io/package.json b/firebase-io/package.json
new file mode 100644
index 0000000..df6b578
--- /dev/null
+++ b/firebase-io/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "tomsg-firebase",
+ "version": "0.1.0",
+ "description": "Javascript part of firebase plugin to tomsg-server",
+ "main": "firebase-io.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.tomsmeding.com/tomsg"
+ },
+ "keywords": [
+ "tomsg",
+ "chat",
+ "firebase"
+ ],
+ "author": "Tom Smeding <tom.smeding@gmail.com> (https://tomsmeding.com)",
+ "license": "MIT",
+ "dependencies": {
+ "firebase-admin": "^4.2.1"
+ }
+}