Skip to content

Instantly share code, notes, and snippets.

@quanon
Last active February 13, 2019 05:42
Show Gist options
  • Save quanon/a1c8d4ab99bd65e6bfea15141558fbf1 to your computer and use it in GitHub Desktop.
Save quanon/a1c8d4ab99bd65e6bfea15141558fbf1 to your computer and use it in GitHub Desktop.
Raspberry Pi 上で J-MOTTO にログインして打刻する Node.js スクリプト
{
"member_id": "JM0693349",
"user_id": "30588",
"password": "ここにパスワードを入力する"
}
const minimist = require('minimist');
const puppeteer = require('puppeteer');
const fs = require('fs');
const moment = require('moment');
const getKintaiOptions = () => {
const argv = minimist(process.argv.slice(2));
let kintai = null;
if (argv.kin && !argv.tai) {
kintai = {
type: 'start',
label: '出社'
};
} else if (!argv.kin && argv.tai) {
kintai = {
type: 'end',
label: '退社'
};
}
return kintai;
}
const login = async (page) => {
await page.goto(loginUrl);
await page.type('#memberID', config['member_id']);
await page.type('#userID', config['user_id']);
await page.type('#password', config['password']);
const btnSelector = '[name=NAME_DUMMY04]';
await page.waitForSelector(btnSelector);
// Raspberry pi 上だとなぜか page.click() が失敗する。
// await page.click(btnSelector);
await page.evaluate((btnSelector) => {
document.querySelector(btnSelector).click();
}, btnSelector);
await page
.waitForSelector('.portal-timecard', { timeout: 10000 })
.catch(() => { throw new Error('ログインに失敗しました。')});
return page;
};
const sleep = async (delay) => {
return new Promise(resolve => setTimeout(resolve, delay));
};
const config = JSON.parse(fs.readFileSync('./config.json'));
const loginUrl = 'https://www1.j-motto.co.jp/fw/dfw/po80/portal/jsp/J10201.jsp?https://www1.j-motto.co.jp/fw/dfw/gws/cgi-bin/aspioffice/iocjmtgw.cgi?cmd=login';
const kintai = getKintaiOptions();
if (!kintai) process.exit(1);
(async () => {
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium-browser'
});
const page = await browser.newPage();
try {
await login(page);
const btnSelector = `.portal-timecard-${kintai.type} input.portal-timecard-btn`;
const btnVisible = () => {
return page.evaluate((selector) => {
return document.querySelector(selector).offsetParent !== null;
}, btnSelector);
}
if (await btnVisible()) {
while (true) {
if (await btnVisible()) {
await page.evaluate((btnSelector) => {
document.querySelector(btnSelector).click();
}, btnSelector);
} else {
break;
}
await sleep(50);
}
} else {
console.log(`※ ${kintai.label}時刻は打刻済みです。`);
}
const [startTime, endTime] = await Promise.all(
['start', 'end'].map(async (type) => {
const timeSelector = `.portal-timecard-${type} .portal-timecard-time`;
const time = await page.evaluate((selector) => {
return document.querySelector(selector).textContent;
}, timeSelector);
return time.replace(/-/g, '');
})
);
if (startTime) console.log(`出社時刻は ${startTime} です。`);
if (startTime && endTime) {
const diff = moment.utc(
moment.utc(endTime, 'HH:mm').diff(moment.utc(startTime, 'HH:mm'))
).format('HH:mm');
console.log(`退社時刻は ${endTime} です。`);
console.log(`就業時間は ${diff} です。`);
}
} finally {
browser.close();
}
})();
{
"dependencies": {
"minimist": "1.2.0",
"moment": "2.24.0",
"puppeteer": "1.11.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment