Skip to content

Instantly share code, notes, and snippets.

@af12066
Created July 19, 2019 05:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save af12066/982d8386e6367bfd74ddeace55c658df to your computer and use it in GitHub Desktop.
Save af12066/982d8386e6367bfd74ddeace55c658df to your computer and use it in GitHub Desktop.
勤怠を自動化する技術 LT Night
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>freee-kintai-break-time-end</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>load</string>
<string>-w</string>
<string>/Users/your-name/Library/LaunchAgents/freee-kintai-taikin.plist</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>14</integer>
<key>Minute</key>
<integer>00</integer>
</dict>
<key>ExitTimeout</key>
<integer>30</integer>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>freee-kintai-break-time</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>unload</string>
<string>-w</string>
<string>/Users/your-name/Library/LaunchAgents/freee-kintai-taikin.plist</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>12</integer>
<key>Minute</key>
<integer>30</integer>
</dict>
<key>ExitTimeout</key>
<integer>30</integer>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>
#!/bin/bash
set -u
# See https://app.secure.freee.co.jp/developers/tutorials/3-%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B#%E8%AA%8D%E5%8F%AF%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B
#
# CLIENT_ID, CLIENT_SECRET, AUTHORIZATION_CODEは環境変数に設定しておいてください。
readonly REFRESH_TOKEN=$(curl -X POST \
-H "Content-Type:application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}" \
-d "code=${AUTHORIZATION_CODE}" \
-d "redirect_uri=urn:ietf:wg:oauth:2.0:oob" 'https://accounts.secure.freee.co.jp/public_api/token' \
| jq -r '.refresh_token')
readonly KEYCHAIN_SERVICE_NAME='freee-kintai'
security add-generic-password -a client-id -w "${CLIENT_ID}" -s "${KEYCHAIN_SERVICE_NAME}"
security add-generic-password -a client-secret -w "${CLIENT_SECRET}" -s "${KEYCHAIN_SERVICE_NAME}"
security add-generic-password -a refresh-token -w "${REFRESH_TOKEN}" -s "${KEYCHAIN_SERVICE_NAME}"
# 事前にplistを置いといてください
launchctl load -w ~/Library/LaunchAgents/freee-kintai-taikin.plist
launchctl load -w ~/Library/LaunchAgents/freee-kintai-break-time.plist # 休憩時間は退勤できないので定期実行を停止する。停止するための定期ジョブ
launchctl load -w ~/Library/LaunchAgents/freee-kintai-break-time-end.plist # 定期実行を再開するためのジョブ
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>freee-kintai-taikin</string>
<key>ProgramArguments</key>
<array>
<string>/Users/your-name/kintai.sh</string>
<string>clock_out</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
<key>StartInterval</key>
<integer>120</integer>
<key>ExitTimeout</key>
<integer>30</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
#!/bin/bash
set -u
readonly time_clocks_type=$1
readonly CLIENT_ID=$(security find-generic-password -a client-id -w -s freee-kintai)
readonly CLIENT_SECRET=$(security find-generic-password -a client-secret -w -s freee-kintai)
readonly TOKEN=$(security find-generic-password -a refresh-token -w -s freee-kintai)
dig +time=1 +tries=3 freee.co.jp > /dev/null
readonly DIG_EXITCODE=$?
if (( "${DIG_EXITCODE}" > 0 )); then
osascript -e "display notification \"APIサーバに到達できませんでした\" with title \"出退勤\""
exit
fi
readonly AUTH_RESP=$(curl -X POST \
-H "Content-Type:application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}" \
-d "refresh_token=${TOKEN}" \
'https://accounts.secure.freee.co.jp/public_api/token' 2>/dev/null)
readonly ACCESS_TOKEN=$(echo ${AUTH_RESP} | jq -r '.access_token')
readonly REFRESH_TOKEN=$(echo ${AUTH_RESP} | jq -r '.refresh_token')
if [[ "${REFRESH_TOKEN}" == 'null' ]]; then
osascript -e "display notification \"認証に失敗しました\" with title \"出退勤\""
exit
fi
security add-generic-password -a refresh-token -w "${REFRESH_TOKEN}" -s freee-kintai -U
readonly COMPANY_RESPONSE=$(curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
https://api.freee.co.jp/hr/api/v1/users/me 2>/dev/null)
readonly COMPANY_ID=$(echo ${COMPANY_RESPONSE} | jq -r '.companies[] | select(.name | test("フリー株式会社")) | .id')
readonly EMPROYEE_ID=$(echo ${COMPANY_RESPONSE} | jq -r '.companies[] | select(.name | test("フリー株式会社")) | .employee_id')
readonly TIME_CLOCK_RESP=$(curl -X POST -H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type:application/json" \
-d "{\"company_id\":${COMPANY_ID},\"type\":\"${time_clocks_type}\",\"base_date\":\"$(date "+%Y-%m-%d")\"}" \
https://api.freee.co.jp/hr/api/v1/employees/${EMPROYEE_ID}/time_clocks 2>/dev/null)
readonly TIME_CLOCK_MESSAGE=$(echo ${TIME_CLOCK_RESP} | jq -r '.message')
if [[ ${TIME_CLOCK_MESSAGE} != 'null' ]]; then
osascript -e "display notification \"${TIME_CLOCK_MESSAGE}\" with title \"出退勤\""
exit
fi
if [[ ${time_clocks_type} == 'clock_in' ]]; then
osascript -e 'display notification "人事労務freeeで打刻しました" with title "出勤"'
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment