Convert Firebase Firestore Timestamp to Date (Swift)?

Convert Firebase Firestore Timestamp to Date (Swift)?

ios 앱에서 firebase를 이용해서 notification 작업을 수행하는 경우. 매 기기마다 주어지는 registration id를 이용해서 각각의 기기에 push notification을 보내게된다. 이 id는 기기에서 앱이 시작될때마다 MessagingDelegate의  messaging:didReceiveRegistrationToken이 호출되고 id를 얻을수 있게 된다. 또 새로운 id가 주어진경우에도 이 함수가 호출된다. 사용자가 이미 sign in되어있는 상황에서는 sign in 과정을 거치지 않고 bypass 되므로 이경우 위해 didReceiveRegistrationToken 내에서 registration id을 저장하는 작업을 수행해야 한다.또 sign in 되어있지 않아서 sign in 과정을 거쳐야 하는 경우를 위해서 sign in 과정에서도 registration id를 저장하는 작업을 수행해 주어야 한다. 이때는 

InstanceID.instanceID().instanceID { (result, error) in
 if let error = error {
   print("Error fetching remote instange ID: (error)")
 } else if let result = result {
   print("Remote instance ID token: (result.token)")
   self.instanceIDTokenMessage.text  = "Remote InstanceID token: (result.token)"
 }
}

와 같이 registration id (위의 코드에서 result.token)에 접근가능하다.

ios 앱에서 firebase를 이용해서 notification 작업을 수행하는 경우. 매 기기마다 주어지는 registration id를 이용해서 각각의 기기에 push notification을 보내게된다. 이 id는 기기에서 앱이 시작될때마다 MessagingDelegate의  messaging:didReceiveRegistrationToken이 호출되고 id를 얻을수 있게 된다. 또 새로운 id가 주어진경우에도 이 함수가 호출된다. 사용자가 이미 sign in되어있는 상황에서는 sign in 과정을 거치지 않고 bypass 되므로 이경우 위해 didReceiveRegistrationToken 내에서 registration id을 저장하는 작업을 수행해야 한다.또 sign in 되어있지 않아서 sign in 과정을 거쳐야 하는 경우를 위해서 sign in 과정에서도 registration id를 저장하는 작업을 수행해 주어야 한다. 이때는 

InstanceID.instanceID().instanceID { (result, error) in
 if let error = error {
   print("Error fetching remote instange ID: (error)")
 } else if let result = result {
   print("Remote instance ID token: (result.token)")
   self.instanceIDTokenMessage.text  = "Remote InstanceID token: (result.token)"
 }
}

와 같이 registration id (위의 코드에서 result.token)에 접근가능하다.

firebase functions official examples

https://github.com/firebase/functions-samples

onCreate 을 사용하는 경우 새로 생성된 doc과 context가 되돌려 진다.

doc( DocumentSnapshot ) https://cloud.google.com/nodejs/docs/reference/firestore/0.11.x/DocumentSnapshot

promise error catch 하는 방법

admin.storage().bucket().file('path/to/file').download({
    destination: 'temporary/file/path'
}).then(() => {
    // Change the file and upload it.
}).catch(err => {
    // Handle error(create file) if the file does not exist
})

firestore경로에 있는 문자열을 parameter로 사용하는 방법

exports.observeCreate = functions.firestore.document('/pathOne/{id}/pathTwo/{anotherId}').onCreate((snapshot, context) => {
  console.log(context.params);
  console.log(context.params.id);
});

notification and nested 작업

exports.observeCreate = functions.firestore.document('/pathOne/{id}/pathTwo/{anotherId}').onCreate(event => {
  console.log(event.params);

  //event prints out data but params undefined...
  const data = event.data()

  var id = event.params.id;

  return admin.firestore().collection('path').doc(id).get().then(doc => {
    const data = doc.data();
    var fcmToken = data.fcmToken;

    var message = {
      notification: {
        title: "x",
        body: "x"
      },
      token: fcmToken
    };

    admin.messaging().send(message)
      .then((response) => {
        console.log('Successfully sent message:', response);
        return;
      })
      .catch((error) => {
        console.log('Error sending message:', error);
        return;
      });

      return;
  })
})

device에 notification 보내기

exports.sendNotification = 
functions.firestore.document('Users/{userId}/Notifications/{notificationId}')
.onWrite((c hange, context) =>{

const userId = context.params.userId;
const notificationId = context.params.notificationId;

console.log('The User id is : ', userId);
console.log('The Notification id is : ', notificationId);

// ref to the parent document

return admin.firestore().collection("Users").doc(userId).collection("Token").doc(userId).get().then(queryResult => {
    const tokenId = queryResult.data().deviceToken;

    //const toUser = admin.firestore().collection("Users").doc(userId).collection("Notifications").doc(notificationId).get();

        const notificationContent = {
                notification:{
                    title: "/*App name */",
                    body: "You have a new Comment!",
                    icon: "default",
                    click_action: "/*Package */_TARGET_NOTIFICATION"
            }
        };

        return admin.messaging().sendToDevice(tokenId, notificationContent).then(result => {
            console.log("Notification sent!");
            //admin.firestore().collection("notifications").doc(userEmail).collection("userNotifications").doc(notificationId).delete();
        });

   });

});

onwrite에 반응해서 특정topic으로 구분된 그룹에게 notification 보내기

exports.sendNotification = functions.firestore
.document('chats/{chatID}')
.onWrite((change, context) => {
  // Get an object representing the document
   console.log('chat triggered');
  // perform desired operations ...

    // See documentation on defining a message payload.
    var message = {
      notification: {
        title: 'Hello World!',
        body: 'Hello World!'
      },
      topic: context.params.chatID.   //<- If you are using a CF version under v1.0 don't change here
    };

    // Send a message to devices subscribed to the provided topic.
    return admin.messaging().send(message).  //<- return the resulting Promise
      .then((response) => {
        // Response is a message ID string.
        console.log('Successfully sent message:', response);
        return true;    //<- return a value
      })
      .catch((error) => {
        console.log('Error sending message:', error);
        //return.  <- No need to return here
      });

});

firestore에서 data fetch해서 가져오기 

firestore.collection('products').doc(payment.product).get().then(product => {
    if (!product.exists) {
        console.log('No such product!');
    } else {
        console.log('Document data:', product.data());
    }
})

function을 이용해서 firestore에 document만들기

exports.createProfile = functions.auth.user().onCreate((user) => {

  var userObject = {
     displayName : user.displayName,
     email : user.email,
  };

  return admin.firestore().doc('users/'+user.uid).set(userObject);

});

firebase auth에 새로운 유저가 생성되는 경우에 따른 작업을 만들때

export const accountCreate = functions.auth.user().onCreate(user => {
    console.log(user.data);
    userDoc = {'email' = user.data.email, 
               'displayName' = user.data.displayName}
    admin.firestore().collection('users').doc(user.data.uid)
    .set(userDoc).then(writeResult => {
        console.log('User Created result:', writeResult);
        return;
    }).catch(err => {
       console.log(err);
       return;
    });
});

firebase functions official examples

https://github.com/firebase/functions-samples

onCreate 을 사용하는 경우 새로 생성된 doc과 context가 되돌려 진다.

doc( DocumentSnapshot ) https://cloud.google.com/nodejs/docs/reference/firestore/0.11.x/DocumentSnapshot

promise error catch 하는 방법

admin.storage().bucket().file('path/to/file').download({
    destination: 'temporary/file/path'
}).then(() => {
    // Change the file and upload it.
}).catch(err => {
    // Handle error(create file) if the file does not exist
})

firestore경로에 있는 문자열을 parameter로 사용하는 방법

exports.observeCreate = functions.firestore.document('/pathOne/{id}/pathTwo/{anotherId}').onCreate((snapshot, context) => {
  console.log(context.params);
  console.log(context.params.id);
});

notification and nested 작업

exports.observeCreate = functions.firestore.document('/pathOne/{id}/pathTwo/{anotherId}').onCreate(event => {
  console.log(event.params);

  //event prints out data but params undefined...
  const data = event.data()

  var id = event.params.id;

  return admin.firestore().collection('path').doc(id).get().then(doc => {
    const data = doc.data();
    var fcmToken = data.fcmToken;

    var message = {
      notification: {
        title: "x",
        body: "x"
      },
      token: fcmToken
    };

    admin.messaging().send(message)
      .then((response) => {
        console.log('Successfully sent message:', response);
        return;
      })
      .catch((error) => {
        console.log('Error sending message:', error);
        return;
      });

      return;
  })
})

device에 notification 보내기

exports.sendNotification = 
functions.firestore.document('Users/{userId}/Notifications/{notificationId}')
.onWrite((c hange, context) =>{

const userId = context.params.userId;
const notificationId = context.params.notificationId;

console.log('The User id is : ', userId);
console.log('The Notification id is : ', notificationId);

// ref to the parent document

return admin.firestore().collection("Users").doc(userId).collection("Token").doc(userId).get().then(queryResult => {
    const tokenId = queryResult.data().deviceToken;

    //const toUser = admin.firestore().collection("Users").doc(userId).collection("Notifications").doc(notificationId).get();

        const notificationContent = {
                notification:{
                    title: "/*App name */",
                    body: "You have a new Comment!",
                    icon: "default",
                    click_action: "/*Package */_TARGET_NOTIFICATION"
            }
        };

        return admin.messaging().sendToDevice(tokenId, notificationContent).then(result => {
            console.log("Notification sent!");
            //admin.firestore().collection("notifications").doc(userEmail).collection("userNotifications").doc(notificationId).delete();
        });

   });

});

onwrite에 반응해서 특정topic으로 구분된 그룹에게 notification 보내기

exports.sendNotification = functions.firestore
.document('chats/{chatID}')
.onWrite((change, context) => {
  // Get an object representing the document
   console.log('chat triggered');
  // perform desired operations ...

    // See documentation on defining a message payload.
    var message = {
      notification: {
        title: 'Hello World!',
        body: 'Hello World!'
      },
      topic: context.params.chatID.   //<- If you are using a CF version under v1.0 don't change here
    };

    // Send a message to devices subscribed to the provided topic.
    return admin.messaging().send(message).  //<- return the resulting Promise
      .then((response) => {
        // Response is a message ID string.
        console.log('Successfully sent message:', response);
        return true;    //<- return a value
      })
      .catch((error) => {
        console.log('Error sending message:', error);
        //return.  <- No need to return here
      });

});

firestore에서 data fetch해서 가져오기 

firestore.collection('products').doc(payment.product).get().then(product => {
    if (!product.exists) {
        console.log('No such product!');
    } else {
        console.log('Document data:', product.data());
    }
})

function을 이용해서 firestore에 document만들기

exports.createProfile = functions.auth.user().onCreate((user) => {

  var userObject = {
     displayName : user.displayName,
     email : user.email,
  };

  return admin.firestore().doc('users/'+user.uid).set(userObject);

});

firebase auth에 새로운 유저가 생성되는 경우에 따른 작업을 만들때

export const accountCreate = functions.auth.user().onCreate(user => {
    console.log(user.data);
    userDoc = {'email' = user.data.email, 
               'displayName' = user.data.displayName}
    admin.firestore().collection('users').doc(user.data.uid)
    .set(userDoc).then(writeResult => {
        console.log('User Created result:', writeResult);
        return;
    }).catch(err => {
       console.log(err);
       return;
    });
});

firebase cloud functions은 node js를 이용한 server없이 server기능을 이용할수 있게 해준다. 


Firebase functions ( javascript node.js를 기반으로 하고 있다)

관련자료)

Firebase functions official tutorials

https://www.youtube.com/playlist?list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM

1.화일 다운 로드 받아서 컴퓨터에 Node js v11 설치 (설치시 grpc 설치과정에서 문제 발생 이부분만 따로 또 설치)


2.컴퓨터에 sudo npm install -g firebase-tools 를 통해 firebase cli firebase-tools@6.0.1 설치


3.Visual studio code ( text editor ) 설치


4. firebase를 설치할 폴더를 만들어 그 폴더 안으로 이동


5. 터미널에 firebase login 을 실행

6. 터미널에 firebase init을 실행

npm을 통해 dependencies를 설치중 문제가 발생했었다. grpc설치에 문제 발생 이부분만 따로 다시 install했다.

visual studio에서 firebase를 위해 만들었던 폴더를 연다.

visual studio작업후에는 firebase 폴더안에 들어가서 firebase deploy를 실행한다.