Skip to content

Instantly share code, notes, and snippets.

@observerss
Created September 1, 2022 10:11
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 observerss/92a7cc770a14e3529c31c2db111a220a to your computer and use it in GitHub Desktop.
Save observerss/92a7cc770a14e3529c31c2db111a220a to your computer and use it in GitHub Desktop.
Hamibot飞书打卡
[
{
"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通网关)后自动打卡上班, 丢失连接后自动打卡下班; 仅在规定时间且手机解锁时执行"
}
]
// 飞书打卡
// 该脚本应该每分钟执行一次
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