Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8835

Node.jsとFirebaseを使ってRedmineチケットの更新を通知してくれるSlack Appのバックエンドメモ

$
0
0

通知イメージ

スクリーンショット 2020-05-24 17.48.35.png

root

package.json

{"name":"redticket","version":"1.0.0","description":"","main":"index.js","scripts":{"serve":"firebase emulators:start","deploy":"firebase deploy","logs":"firebase functions:log"},"keywords":[],"author":"","license":"ISC","devDependencies":{"babel-eslint":"^10.1.0","eslint":"^7.0.0","eslint-plugin-promise":"^4.2.1","firebase-tools":"^8.2.0","prettier":"^2.0.5"}}

firebase.json

{"hosting":{"public":"public","ignore":["firebase.json","**/.*","**/node_modules/**"],"rewrites":[{"source":"**","function":"api"}]}}

.prettierrc

{"trailingComma":"es5","tabWidth":2,"semi":false,"singleQuote":true,"printWidth":100,"arrowParens":"avoid"}

.eslintrc

{"extends":["eslint:recommended"],"plugins":[],"parser":"babel-eslint","parserOptions":{},"env":{"es6":true,"node":true},"globals":{},"rules":{"semi":["error","never"],"arrow-parens":"off"}}

functions

package,json

{"name":"functions","description":"Cloud Functions for Firebase","scripts":{},"engines":{"node":"8"},"dependencies":{"@slack/web-api":"^5.8.1","axios":"^0.19.2","express":"^4.17.1","firebase-admin":"^8.10.0","firebase-functions":"^3.6.1"},"devDependencies":{"firebase-functions-test":"^0.2.0"},"private":true}

index.js

constadmin=require('firebase-admin')constaxios=require('axios')constserviceAccount=require('./serviceAccount.json')// Firestoreの秘密鍵constExpress=require('express')constfunctions=require('firebase-functions')const{WebClient}=require('@slack/web-api')constclient=newWebClient('[Bot User OAuth Access Token]')admin.initializeApp({credential:admin.credential.cert(serviceAccount),databaseURL:'https://xxxxxxx-xxxxx.firebaseio.com',})constusersCollection=admin.firestore().collection('users')constredmineBaseURL='http://redmine.url'constapi=Express()api.use(Express.json())api.use(Express.urlencoded({extended:true}))api.post('/redmine',async(req,res)=>{try{constticketUrl=req.body.payload.urlconstticket=req.body.payload.issueconstcomment=req.body.payload.journalconstwatchers=[...ticket.watchers]constquery=usersCollection.where('redmine_mail','in',watchers.map(watcher=>watcher.mail))query.get().then(querySnapshot=>{if(!querySnapshot.empty){querySnapshot.docs.forEach(doc=>{client.chat.postMessage({channel:doc.data().channel_id,text:``,blocks:[{type:'section',text:{type:'mrkdwn',text:`*Subject:*\n${ticket.subject}\n\n*URL:*\n${ticketUrl}\n\n*Description:*\n${ticket.description}`,},},{type:'divider',},{type:'section',text:{type:'mrkdwn',text:`*Latest comment:*\n${comment.notes}\n\n*Comment by:*\n${comment.author.firstname}${comment.author.lastname}`,},},],})})}})}catch(err){console.error(err)}finally{res.status(200).send()}})api.post('/redticket',async(req,res)=>{try{res.send('')// Error avoidawaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Start /redticket ${req.body.text}`,})constmode=req.body.text.trim()!==''?req.body.text.trim().split('')[0]:''switch(mode){case'':case'help':{awaitclient.chat.postMessage({channel:req.body.channel_id,text:'',blocks:[{type:'section',text:{type:'mrkdwn',text:"Hello👋 I will explain how to use RedTicket. The first step is to initialize the user data. The command is `/redticket init` 💻\n\nThe next step is to register your redmine account! You will need redmine's API token to register your account. The command is `/redticket verify [API Token]`. Let's sign up for an account right away 🏃 You can check your registered user data at any time at `/redticket check` 👌\n\nIf you need help, try send the `/redticket` or `/redticket help` 📖",},},{type:'divider',},],})break}case'init':{awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Checking the existence of the user data`,})constuserInfo=awaitusersCollection.doc(`${req.body.team_id}${req.body.user_id}`).get()constsetDocument=async()=>{constdata={team_id:req.body.team_id,team_domain:req.body.team_domain,user_id:req.body.user_id,channel_id:req.body.channel_id,user_name:req.body.user_name,}awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Creating your user data.`,})returnawaitusersCollection.doc(`${req.body.team_id}${req.body.user_id}`).set(data).then(async()=>{constuserInfo=awaitusersCollection.doc(`${req.body.team_id}${req.body.user_id}`).get()returnuserInfo.data()})}constdocRef=userInfo.data()===undefined?awaitsetDocument():userInfo.data()awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Your user data.\n\n${JSON.stringify(docRef,null,'\t')}`,})break}case'check':{awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Reading your user data`,})constuserInfo=awaitusersCollection.doc(`${req.body.team_id}${req.body.user_id}`).get()constdocRef=userInfo.data()awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Your user data.\n\n${JSON.stringify(docRef,null,'\t')}`,})break}case'verify':{if(req.body.text.trim().split('').length<=1){awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🙅: Need Redmine API Token.`,})break}awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Verify the Redmine API Token.`,})constredmineUserInfo=awaitaxios.get(`${redmineBaseURL}/my/account.json`,{params:{key:req.body.text.trim().split('')[1],},})awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Your user data in Redmine.\n\n${JSON.stringify(redmineUserInfo.data.user,null,'\t')}`,})constuserInfo=awaitusersCollection.doc(`${req.body.team_id}${req.body.user_id}`).get()constdocRef=userInfo.data()if(!userInfo.exists){thrownewError('No such your data')}docRef.redmine_login=redmineUserInfo.data.user.logindocRef.redmine_mail=redmineUserInfo.data.user.mailconstupdatedUserData=awaitusersCollection.doc(`${req.body.team_id}${req.body.user_id}`).update(docRef).then(async()=>{constuserInfo=awaitusersCollection.doc(`${req.body.team_id}${req.body.user_id}`).get()returnuserInfo.data()})awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Your user data.\n\n${JSON.stringify(updatedUserData,null,'\t')}`,})break}case'project':{awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🏃: Verify the Redmine API Token.`,})break}default:thrownewError('Invalid parameters.')}}catch(error){awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🙅: ${error}`})}finally{awaitclient.chat.postMessage({channel:req.body.channel_id,text:`🎉: Done /redticket ${req.body.text}`,})}})exports.api=functions.https.onRequest(api)

リファクタしないと。


Viewing all articles
Browse latest Browse all 8835

Trending Articles