Created
September 1, 2022 10:11
-
-
Save observerss/92a7cc770a14e3529c31c2db111a220a to your computer and use it in GitHub Desktop.
Hamibot飞书打卡
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"label": "内网网关地址", | |
"name": "gateway", | |
"value": "10.86.30.1" | |
}, | |
{ | |
"label": "上班打卡时间范围", | |
"name": "clockInRange", | |
"value": "07:00-11:00" | |
}, | |
{ | |
"label": "下班打卡时间范围", | |
"name": "clockOutRange", | |
"value": "19:00-24:00" | |
}, | |
{ | |
"label": "使用说明", | |
"type": "radio", | |
"help": "连上内网(ping通网关)后自动打卡上班, 丢失连接后自动打卡下班; 仅在规定时间且手机解锁时执行" | |
} | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 飞书打卡 | |
// 该脚本应该每分钟执行一次 | |
importClass(android.content.Context); | |
auto.waitFor() | |
log('开始运行: 飞书打卡') | |
const STORAGE_NAME = '飞书打卡' | |
const IN = "in" | |
const OUT = "out" | |
// 配置属性放入全局变量 | |
const { | |
gateway, | |
clockInRange, | |
clockOutRange, | |
} = hamibot.env; | |
// 检查wifi是否能连接到指定的网关 | |
function wifiConnected() { | |
const result = shell('ping -c 1 -W 1 ' + gateway) | |
const matched = result.result.match(/1 received/) | |
return Boolean(matched) | |
} | |
// 检查手机锁屏状态 | |
function screenLocked() { | |
const km = context.getSystemService(Context.KEYGUARD_SERVICE); | |
return km.isKeyguardLocked() && km.isKeyguardSecure(); | |
} | |
// 检查当前时间是否在可打卡时间内 | |
function canClockNow(range) { | |
const now = new Date(); | |
try { | |
const yearMonthDay = getDateTime("yyyy/mm/dd") | |
const startHMS = range.split("-")[0] + ":00" | |
const endHMS = range.split("-")[1] + ":00" | |
const start = new Date(yearMonthDay + " " + startHMS) | |
const end = new Date(yearMonthDay + " " + endHMS) | |
} catch (err) { | |
toastLog("请检查时间格式", range) | |
exit() | |
} | |
return (now > start && now < end) | |
} | |
// 检查是否有执行自动化脚本的权限 | |
function checkPermissions() { | |
if (auto.service == null) { | |
toastLog("请先打开无障碍服务,再来运行脚本吧!"); | |
sleep(3000); | |
app.startActivity({action: "android.settings.ACCESSIBILITY_SETTINGS"}); | |
exit(); | |
} | |
} | |
// 检查当天是否已打卡 | |
function isClockedIn() { | |
const storage = storages.create(STORAGE_NAME) | |
const key = getDateTime("yyyy/mm/dd") | |
return storage.get(key) | |
} | |
// 标记当天已打卡 | |
function doneClocked(direction, nameCompany) { | |
const storage = storages.create(STORAGE_NAME) | |
const key = getDateTime("yyyy/mm/dd") | |
if (direction === IN) { | |
storage.put(key, true) | |
} else { | |
storage.put(key, false) | |
} | |
// remoteSave(direction, nameCompany) | |
} | |
// 强制点击一个UiObject | |
function forceClick(obj) { | |
const rect = obj.bounds() | |
toastLog(rect.centerX()) | |
toastLog(rect.centerY()) | |
click(rect.centerX(), rect.centerY()) | |
} | |
// 执行自动化打卡脚本 | |
function doClock(direction) { | |
const timeout1 = 1000 | |
const timeout2 = 5000 | |
try { | |
toastLog("打开飞书应用") | |
// 快速打开打卡应用 | |
app.startActivity({ | |
action: 'VIEW', | |
data: 'lark://applink.feishu.cn/client/app_share/open?appId=cli_9c21a4767c305107', | |
}) | |
text("考勤规则").findOne(timeout2) | |
toastLog("点击打卡按钮") | |
let clockBtn = null | |
let retries = 0 | |
while (clockBtn === null && retries < 5) { | |
if (direction === IN) { | |
clockBtn = text("上班打卡").findOne(timeout1) | |
} else { | |
clockBtn = text("下班打卡").findOne(timeout1) | |
} | |
if (clockBtn !== null) { | |
break | |
} | |
swipe(device.width, device.height + 50, device.width, device.height - 50, 100) | |
retries += 1 | |
} | |
if (retries >= 5) { | |
throw Error("cannot find clock button, max retry count reached") | |
} | |
forceClick(clockBtn) | |
toastLog("保存今日打卡状态") | |
doneClocked(direction, "") | |
// 回到手机首页 | |
setTimeout( | |
() => { | |
home() | |
}, | |
2000 | |
) | |
} catch (err) { | |
toastLog(err) | |
exit() | |
} | |
} | |
// 获取时间日期 | |
function getDateTime(rule) { | |
const date = new Date(); | |
const year = date.getFullYear(); | |
const month = date.getMonth() + 1; | |
const day = date.getDate(); | |
const hour = date.getHours(); | |
const minute = date.getMinutes(); | |
const second = date.getSeconds(); | |
if (month < 10) { | |
month = "0" + month; | |
} | |
if (day < 10) { | |
day = "0" + day; | |
} | |
if (hour < 10) { | |
hour = "0" + hour; | |
} | |
if (minute < 10) { | |
minute = "0" + minute | |
} | |
if (second < 10) { | |
second = "0" + second; | |
} | |
switch (rule) { | |
case "yyyy/mm/dd": | |
return year + "/" + month + "/" + day | |
case "yyyy-mm-dd": | |
return year + "-" + month + "-" + day | |
default: | |
return year + "/" + month + "/" + day + " " + hour + ":" + minute + ":" + second; | |
} | |
} | |
// 主流程 | |
function main() { | |
checkPermissions() | |
const connected = wifiConnected() | |
log("screenLocked", screenLocked()) | |
log("inClockInRange", canClockNow(clockInRange)) | |
log("inClockOutRange", canClockNow(clockOutRange)) | |
log("isClockedIn", isClockedIn()) | |
log("wifiConnected", connected) | |
// 屏幕 | |
if (!screenLocked()) { | |
// 在运行打卡上班的时间范围内, and | |
// 当天不在已打卡状态, and | |
// 连上了指定的WiFi | |
if (canClockNow(clockInRange) && !isClockedIn() && connected) { | |
doClock(IN) | |
} | |
// 在运行打卡下班的时间范围内, and | |
// 当天在已打卡状态, and | |
// 没连接指定的WiFi | |
else if (canClockNow(clockOutRange) && isClockedIn() && !connected) { | |
doClock(OUT) | |
} | |
// // 在打卡时间, 并且已经打卡过了 | |
// else if (canClockNow(clockInRange) && isClockedIn()) { | |
// remoteSave(IN) | |
// } | |
// // 在打卡时间, 并且已经打卡过了 | |
// else if (canClockNow(clockOutRange) && !isClockedIn()) { | |
// remoteSave(OUT) | |
// } | |
} | |
log('结束运行: 飞书打卡') | |
} | |
// 主流程 | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
哈喽,老板这个怎么用啊~ 小白求教