-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjiraWaka.js
193 lines (157 loc) · 5.87 KB
/
jiraWaka.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
require('dotenv').config();
const fs = require('fs');
const path = require('path');
const nodemailer = require('nodemailer');
const express = require('express');
const bodyParser = require('body-parser');
const JiraClient = require('jira-connector');
const app = express();
const port = 3001;
const settingPath = path.join(__dirname, 'settings');
app.use(bodyParser.json());
app.post('/api/save-config', (req, res) => {
const configData = req.body;
delete req.body?.today;
const { projects } = configData;
const projectArray = projects.replace(/\s/g, '').split(',');
for (const project of projectArray) {
if (!fs.existsSync(settingPath)) {
fs.mkdirSync(settingPath);
}
fs.writeFile(`settings/${project}.json`, JSON.stringify({ ...configData, project }), 'utf8', err => {
if (err) {
console.error(err);
return res.status(500).send('Error saving configuration');
}
});
}
res.send('Configuration saved successfully');
});
app.post('/api/submit-config', async (req, res) => {
const { today, wakatimeApiKey, jiraApiKey, jiraServer, jiraUsername, project, assignDisplayName } = req.body;
// Jira 클라이언트 설정
const jira = new JiraClient({
host: jiraServer,
basic_auth: {
username: jiraUsername,
password: jiraApiKey,
},
});
const TODAY = today ?? getCurrentDateInTimezone(process.env.COUNTRY).toISOString().split('T')[0];
const branchDurations = {};
try {
// WakaTime API에서 데이터 가져오기
const wakatimeResponse = await fetch(
`https://wakatime.com/api/v1/users/current/durations?date=${TODAY}&project=${project}&api_key=${wakatimeApiKey}`
);
if (!wakatimeResponse.ok) {
throw new Error('Failed to fetch from WakaTime API');
}
const wakatimeData = await wakatimeResponse.json();
for (const work of wakatimeData.data) {
if (work.branch) {
const projectMatchKey = new RegExp(`\\/${projectKey}-(\\d+)`, 'i');
const match = work.branch.match(projectMatchKey);
if (match) {
const ticketNumber = match[0];
if (!branchDurations[ticketNumber]) {
branchDurations[ticketNumber] = 0;
}
branchDurations[ticketNumber] += work.duration;
}
}
}
let messages = [];
// Jira API를 사용하여 시간 로그 기록
for (const ticketNumber in branchDurations) {
const totalDuration = Math.round(branchDurations[ticketNumber] / 60);
const ticket = await jira.issue.getIssue({ issueKey: ticketNumber });
if (ticket.fields.assignee && ticket.fields.assignee.displayName !== assignDisplayName) {
messages.push(
`Assignee is not ${assignDisplayName} for ticket ${ticket.key}, ${ticket.fields.assignee.displayName} is assigned.`
);
continue;
}
await jira.issue.addWorkLog({
issueKey: ticket.key,
worklog: {
timeSpent: `${totalDuration}m`,
},
});
messages.push(`${ticket.key} : ${totalDuration}m`);
}
const totalWorkTime = Math.round(Object.values(branchDurations).reduce((a, b) => a + b, 0) / 60) + 'm';
const assigneeMessages = messages.filter(msg => msg.startsWith('Assignee is not'));
res.json({
messages,
branchDurations,
totalWorkTime,
});
onWorkCompleted(branchDurations, totalWorkTime, project, assigneeMessages, jiraUsername);
} catch (error) {
console.error('Error:', error);
res.status(500).json({ message: 'Internal Server Error' });
}
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
function appendLog(message, project, jiraUsername) {
const logDirectory = path.join(__dirname, 'log');
if (!fs.existsSync(logDirectory)) {
fs.mkdirSync(logDirectory);
}
const timestamp = getCurrentDateInTimezone(process.env.COUNTRY).toISOString();
const logMessage = `\n${message}\n${timestamp}\n`;
fs.appendFile(logFilePath(project), logMessage, err => {
if (err) {
return console.error('Error appending to log file:', err);
}
sendEmail(jiraUsername, `${project} 작업시간 기록 완료`, message.split('\n').join('<br/>'));
});
}
function logFilePath(project) {
return path.join(__dirname, `log/${project}.log`);
}
async function sendEmail(to, subject, html) {
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
let info = await transporter.sendMail({
from: `"Wakatime-Jira Integration" <${process.env.EMAIL_USER}>`,
to: to,
subject: subject,
html: html,
});
console.log('Message sent: %s', info.messageId);
}
function onWorkCompleted(branchDurations, totalWorkTime, project, assigneeMessages, jiraUsername) {
const timestamp = getCurrentDateInTimezone(process.env.COUNTRY).toISOString().split('T')[0];
const logMessages = [`오늘 ${timestamp}`];
assigneeMessages.forEach(message => logMessages.push(message));
for (const [branch, duration] of Object.entries(branchDurations)) {
const ticketNumber = branch.replace(`/${projectKey}-`, `${projectKey.toUpperCase()}-`);
const durationInMinutes = Math.round(duration / 60);
logMessages.push(`${ticketNumber} : ${durationInMinutes}m`);
}
logMessages.push(`각 브랜치별 작업시간 (초단위) ${JSON.stringify(branchDurations)}`);
logMessages.push(`오늘 총 작업시간 (분단위): ${totalWorkTime}`);
appendLog(logMessages.join('\n'), project, jiraUsername);
}
function getCurrentDateInTimezone(country) {
const date = new Date();
const timeZone = getTimeZoneByCountry(country);
return new Date(date.toLocaleString('en-US', { timeZone }));
}
function getTimeZoneByCountry(country) {
const timeZones = {
Korea: 'Asia/Seoul',
USA: 'America/New_York',
// Add more countries and their timezones as needed
};
return timeZones[country] || 'UTC';
}