From 053725852ada084d47cd38193f53c2c8c05237c4 Mon Sep 17 00:00:00 2001 From: jimlee Date: Thu, 19 Mar 2026 14:53:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E8=8A=82=E5=81=87=E6=97=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 +- .../pomelotea/hoperun/sign/DakaApplication.kt | 24 +- .../hoperun/sign/api/HoperunDakaController.kt | 16 +- .../pomelotea/hoperun/sign/common/Common.kt | 25 -- .../hoperun/sign/holiday/HolidayConfig.kt | 23 ++ .../hoperun/sign/holiday/HolidayModels.kt | 17 ++ .../hoperun/sign/holiday/HolidayService.kt | 231 ++++++++++++++++++ .../sign/scheduler/AutoDakaScheduler.kt | 18 +- .../scheduler/AutoRenewSessionScheduler.kt | 70 ------ src/main/resources/config/application.yml | 15 +- 10 files changed, 298 insertions(+), 148 deletions(-) create mode 100644 src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayConfig.kt create mode 100644 src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayModels.kt create mode 100644 src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayService.kt delete mode 100644 src/main/kotlin/com/pomelotea/hoperun/sign/scheduler/AutoRenewSessionScheduler.kt diff --git a/pom.xml b/pom.xml index c3c975d..52366eb 100644 --- a/pom.xml +++ b/pom.xml @@ -131,11 +131,6 @@ jsoup 1.15.3 - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - org.jetbrains.kotlin kotlin-test @@ -158,4 +153,4 @@ - \ No newline at end of file + diff --git a/src/main/kotlin/com/pomelotea/hoperun/sign/DakaApplication.kt b/src/main/kotlin/com/pomelotea/hoperun/sign/DakaApplication.kt index 5e263b1..fd00b29 100644 --- a/src/main/kotlin/com/pomelotea/hoperun/sign/DakaApplication.kt +++ b/src/main/kotlin/com/pomelotea/hoperun/sign/DakaApplication.kt @@ -1,6 +1,5 @@ package com.pomelotea.hoperun.sign -import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication @@ -19,29 +18,8 @@ import java.util.* @ConfigurationPropertiesScan open class DakaApplication -val T.logger: Logger - get() = LoggerFactory.getLogger(this::class.java) - -val holidays: List = listOf( - // 元旦 - "2025-01-01", - // 春节 - "2025-01-28", "2025-01-29", "2025-01-30", "2025-01-31", "2025-02-01", "2025-02-02", "2025-02-03", "2025-02-04", - // 清明 - "2025-04-04", "2025-04-05", "2025-04-06", - // 劳动节 - "2025-05-01", "2025-05-02", "2025-05-05", "2025-05-04", "2025-05-05", - // 端午节 - "2025-05-31", "2025-06-01", "2025-06-02", - // 中秋 - // 国庆 - "2025-10-01", "2025-10-02", "2025-10-03", "2025-10-04", "2025-10-05", "2025-10-06", "2025-10-07", "2025-10-08") - -// 周末要上班的日期 -val workdays: List = listOf("2025-01-26", "2025-02-08", "2025-04-27", "2025-10-11", "2025-09-28", "2025-10-12") - private val logger = LoggerFactory.getLogger("APPLICATION-STARTER") fun main(args: Array) { SpringApplication.run(DakaApplication::class.java, *args) logger.info("hoperun打卡服务启动成功:{}", SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(Date())) -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/pomelotea/hoperun/sign/api/HoperunDakaController.kt b/src/main/kotlin/com/pomelotea/hoperun/sign/api/HoperunDakaController.kt index 52c22c4..9256048 100644 --- a/src/main/kotlin/com/pomelotea/hoperun/sign/api/HoperunDakaController.kt +++ b/src/main/kotlin/com/pomelotea/hoperun/sign/api/HoperunDakaController.kt @@ -8,7 +8,7 @@ import com.pomelotea.hoperun.sign.config.HoperunUserConfig.deviceMap import com.pomelotea.hoperun.sign.config.HoperunUserConfig.getUserConfig import com.pomelotea.hoperun.sign.config.HoperunUserConfig.userConfigMap import com.pomelotea.hoperun.sign.config.UserConfig -import com.pomelotea.hoperun.sign.notify.ServerChan3NotifyHelper +import com.pomelotea.hoperun.sign.holiday.HolidayService import com.pomelotea.hoperun.sign.service.NotificationService import com.pomelotea.hoperun.sign.scheduler.AutoDakaScheduler import com.pomelotea.hoperun.sign.scheduler.AutoDakaScheduler.Companion.dakaQueue @@ -33,14 +33,14 @@ import java.util.* @RestController @RequestMapping("/api/daka") class HoperunSignController( - @field:Autowired private val notificationService: NotificationService + @field:Autowired private val notificationService: NotificationService, + @field:Autowired private val holidayService: HolidayService ) { init { - AutoDakaScheduler(notificationService) -// AutoRenewSessionScheduler() + AutoDakaScheduler(notificationService, holidayService) val yxl = UserConfig( project_id = "U2103S000112", projectcode = "U2103S000112", @@ -50,17 +50,11 @@ class HoperunSignController( userConfigMap["16638"] = yxl } -// @GetMapping("/username/{employeeNo}/{checked}/{jsessionId}") @GetMapping("/username/{employeeNo}/{checked}") fun getUsername( @PathVariable employeeNo: String, @PathVariable checked: Boolean ): WebResult { -/* - if (jsessionId != null) { - getJsessionIdAutoLogin(employeeNo, jsessionId) - }*/ - val userConfig = getUserConfig(employeeNo).let { defaultLogin(employeeNo) getUserConfig(employeeNo) @@ -430,4 +424,4 @@ data class LoginResponse( var project_id: String? = null, var projectname: String? = null, var area: String? = null -) \ No newline at end of file +) diff --git a/src/main/kotlin/com/pomelotea/hoperun/sign/common/Common.kt b/src/main/kotlin/com/pomelotea/hoperun/sign/common/Common.kt index 42296ed..e94176c 100644 --- a/src/main/kotlin/com/pomelotea/hoperun/sign/common/Common.kt +++ b/src/main/kotlin/com/pomelotea/hoperun/sign/common/Common.kt @@ -7,18 +7,14 @@ import com.pomelotea.hoperun.sign.api.HoperunDakaRequest import com.pomelotea.hoperun.sign.config.HoperunUserConfig import com.pomelotea.hoperun.sign.config.HoperunUserConfig.getUserConfig import com.pomelotea.hoperun.sign.config.UserConfig -import com.pomelotea.hoperun.sign.holidays -import com.pomelotea.hoperun.sign.workdays import okhttp3.FormBody import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody -import java.time.DayOfWeek import java.time.Duration import java.time.LocalDate import java.time.ZoneOffset -import java.time.format.DateTimeFormatter import java.util.* /** @@ -38,7 +34,6 @@ val client = OkHttpClient() .newBuilder() .connectTimeout(Duration.ofSeconds(10)) .callTimeout(Duration.ofSeconds(10)) -// .addInterceptor(LogInterceptor()) .build() val sessionMap: MutableMap = HashMap() @@ -57,26 +52,9 @@ fun getNowDateyyyy_MM_dd(): String { return "${localDate.year}-${pad(localDate.monthValue)}-${pad(localDate.dayOfMonth)}" } -fun getYesterdayyyyy_MM_dd(): String { - val localDate = LocalDate.now() - localDate.plusDays(-1) - return "${localDate.year}-${pad(localDate.monthValue)}-${pad(localDate.dayOfMonth)}" -} - - private fun pad(num: Int): String { return if (num < 10) "0$num" else "$num" } -fun isWeekend(dakaDate: String): Boolean { - val date = LocalDate.parse(dakaDate, DateTimeFormatter.ISO_LOCAL_DATE) - return date.dayOfWeek == DayOfWeek.SATURDAY || date.dayOfWeek == DayOfWeek.SUNDAY -} - -fun isWeekday(dakaDate: String): Boolean { - val date = LocalDate.parse(dakaDate, DateTimeFormatter.ISO_LOCAL_DATE) - return date.dayOfWeek == DayOfWeek.MONDAY || date.dayOfWeek == DayOfWeek.TUESDAY - || date.dayOfWeek == DayOfWeek.WEDNESDAY || date.dayOfWeek == DayOfWeek.THURSDAY || date.dayOfWeek == DayOfWeek.FRIDAY -} fun beginTime(employeeNo: String, date: String, time: String, jsessionId: String = sessionMap.get(employeeNo)!!): DakaResponse { val dakaRequest = Request.Builder() @@ -183,6 +161,3 @@ fun randowSecond(): String { return if (second < 10) "0$second" else "$second" } -fun isNeedDaka(dakaDate: String): Boolean { - return workdays.contains(dakaDate) || (isWeekday(dakaDate) && !holidays.contains(dakaDate)) -} \ No newline at end of file diff --git a/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayConfig.kt b/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayConfig.kt new file mode 100644 index 0000000..e07c448 --- /dev/null +++ b/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayConfig.kt @@ -0,0 +1,23 @@ +package com.pomelotea.hoperun.sign.holiday + +import org.springframework.boot.context.properties.ConfigurationProperties + +@ConfigurationProperties(prefix = "holiday") +data class HolidayConfig( + var enabled: Boolean = true, + var sources: List = listOf( + "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{year}.json" + ), + var proxySources: List = listOf( + "https://ghproxy.com/https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{year}.json" + ), + var cacheDir: String = "./data/holiday", + var cacheTtlDays: Long = 30, + var yearsAhead: Int = 1, + var fallback: Fallback = Fallback() +) { + data class Fallback( + var holidays: List = emptyList(), + var workdays: List = emptyList() + ) +} diff --git a/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayModels.kt b/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayModels.kt new file mode 100644 index 0000000..89d2097 --- /dev/null +++ b/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayModels.kt @@ -0,0 +1,17 @@ +package com.pomelotea.hoperun.sign.holiday + +import com.alibaba.fastjson.annotation.JSONField +import java.time.Instant + +data class HolidayEntry( + val name: String? = null, + val date: String? = null, + @field:JSONField(name = "isOffDay") + val isOffDay: Boolean? = null +) + +data class HolidayCalendar( + val holidays: Set, + val workdays: Set, + val updatedAt: Instant +) diff --git a/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayService.kt b/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayService.kt new file mode 100644 index 0000000..6afcfda --- /dev/null +++ b/src/main/kotlin/com/pomelotea/hoperun/sign/holiday/HolidayService.kt @@ -0,0 +1,231 @@ +package com.pomelotea.hoperun.sign.holiday + +import com.alibaba.fastjson.JSON +import okhttp3.OkHttpClient +import okhttp3.Request +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths +import java.time.DayOfWeek +import java.time.Duration +import java.time.Instant +import java.time.LocalDate +import java.time.format.DateTimeFormatter +import java.util.concurrent.ConcurrentHashMap +import javax.annotation.PostConstruct + +@Service +class HolidayService( + private val config: HolidayConfig +) { + private val logger = LoggerFactory.getLogger(HolidayService::class.java) + private val cache = ConcurrentHashMap() + private val dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE + private val httpClient = OkHttpClient.Builder() + .connectTimeout(Duration.ofSeconds(10)) + .callTimeout(Duration.ofSeconds(10)) + .build() + + @PostConstruct + fun preload() { + if (!config.enabled) { + return + } + val now = LocalDate.now() + val endYear = now.year + config.yearsAhead + logger.info("节假日配置预加载开始: years={}..{}", now.year, endYear) + for (year in now.year..endYear) { + runCatching { getCalendar(year) } + .onFailure { logger.warn("节假日配置预加载失败: year={}, err={}", year, it.message) } + } + } + + fun isWorkingDay(dateStr: String): Boolean { + val date = LocalDate.parse(dateStr, dateFormatter) + return isWorkingDay(date) + } + + fun isWorkingDay(date: LocalDate): Boolean { + if (!config.enabled) { + return defaultIsWorkingDay(date) + } + val dateKey = date.format(dateFormatter) + val calendar = getCalendar(date.year) + if (calendar.workdays.contains(dateKey)) { + return true + } + if (calendar.holidays.contains(dateKey)) { + return false + } + return defaultIsWorkingDay(date) + } + + private fun defaultIsWorkingDay(date: LocalDate): Boolean { + return date.dayOfWeek != DayOfWeek.SATURDAY && date.dayOfWeek != DayOfWeek.SUNDAY + } + + private fun getCalendar(year: Int): HolidayCalendar { + val now = Instant.now() + val cached = cache[year] + if (cached != null && !isExpired(cached.updatedAt, now)) { + return cached + } + + val remoteResult = fetchRemote(year) + if (remoteResult != null) { + val calendar = applyFallback(parse(remoteResult.body)).copy(updatedAt = now) + cache[year] = calendar + writeCache(year, remoteResult.body) + logger.info( + "节假日配置加载成功(远程): year={}, url={}, holidays={}, workdays={}", + year, + remoteResult.url, + calendar.holidays.size, + calendar.workdays.size + ) + return calendar + } + + if (cached != null) { + val refreshed = cached.copy(updatedAt = now) + cache[year] = refreshed + logger.warn( + "节假日远程刷新失败,继续使用内存缓存: year={}, holidays={}, workdays={}", + year, + refreshed.holidays.size, + refreshed.workdays.size + ) + return refreshed + } + + val cachedRaw = readCache(year) + if (cachedRaw != null) { + val calendar = applyFallback(parse(cachedRaw)).copy(updatedAt = now) + cache[year] = calendar + logger.info( + "节假日配置加载成功(本地缓存): year={}, path={}, holidays={}, workdays={}", + year, + cachePath(year).toString(), + calendar.holidays.size, + calendar.workdays.size + ) + return calendar + } + + logger.warn("节假日配置缺失,仅使用fallback: year={}", year) + val fallbackCalendar = applyFallback(HolidayCalendar(emptySet(), emptySet(), now)) + cache[year] = fallbackCalendar + return fallbackCalendar + } + + private fun isExpired(updatedAt: Instant, now: Instant): Boolean { + if (config.cacheTtlDays <= 0) { + return false + } + return Duration.between(updatedAt, now).toDays() >= config.cacheTtlDays + } + + private fun fetchRemote(year: Int): FetchResult? { + val urls = buildUrls(year) + for (url in urls) { + try { + val request = Request.Builder().url(url).get().build() + httpClient.newCall(request).execute().use { response -> + if (!response.isSuccessful) { + logger.warn("节假日配置拉取失败: url={}, code={}", url, response.code) + return@use + } + val body = response.body?.string() + if (!body.isNullOrBlank()) { + return FetchResult(url = url, body = body) + } + logger.warn("节假日配置拉取为空: url={}", url) + } + } catch (ex: Exception) { + logger.warn("节假日配置拉取异常: url={}, err={}", url, ex.message) + } + } + return null + } + + private fun buildUrls(year: Int): List { + if (config.sources.isEmpty() && config.proxySources.isEmpty()) { + return emptyList() + } + val urls = ArrayList() + config.sources.forEach { urls.add(it.replace("{year}", year.toString())) } + config.proxySources.forEach { urls.add(it.replace("{year}", year.toString())) } + return urls + } + + private fun parse(raw: String): HolidayCalendar { + val entries = JSON.parseArray(raw, HolidayEntry::class.java) ?: emptyList() + val holidays = LinkedHashSet() + val workdays = LinkedHashSet() + for (entry in entries) { + val date = entry.date?.trim() + if (date.isNullOrEmpty()) { + continue + } + when (entry.isOffDay) { + true -> holidays.add(date) + false -> workdays.add(date) + else -> {} + } + } + return HolidayCalendar(holidays, workdays, Instant.now()) + } + + private fun applyFallback(calendar: HolidayCalendar): HolidayCalendar { + if (config.fallback.holidays.isEmpty() && config.fallback.workdays.isEmpty()) { + return calendar + } + val holidays = calendar.holidays.toMutableSet() + val workdays = calendar.workdays.toMutableSet() + for (date in config.fallback.holidays) { + holidays.add(date) + workdays.remove(date) + } + for (date in config.fallback.workdays) { + workdays.add(date) + holidays.remove(date) + } + return calendar.copy(holidays = holidays, workdays = workdays) + } + + private fun cachePath(year: Int): Path { + return Paths.get(config.cacheDir).resolve("$year.json") + } + + private fun writeCache(year: Int, raw: String) { + try { + val path = cachePath(year) + Files.createDirectories(path.parent) + Files.write(path, raw.toByteArray(StandardCharsets.UTF_8)) + logger.info("节假日缓存写入成功: year={}, path={}", year, path.toString()) + } catch (ex: Exception) { + logger.warn("节假日缓存写入失败: year={}, err={}", year, ex.message) + } + } + + private fun readCache(year: Int): String? { + return try { + val path = cachePath(year) + if (!Files.exists(path)) { + return null + } + String(Files.readAllBytes(path), StandardCharsets.UTF_8) + } catch (ex: Exception) { + logger.warn("节假日缓存读取失败: year={}, err={}", year, ex.message) + null + } + } + + private data class FetchResult( + val url: String, + val body: String + ) +} diff --git a/src/main/kotlin/com/pomelotea/hoperun/sign/scheduler/AutoDakaScheduler.kt b/src/main/kotlin/com/pomelotea/hoperun/sign/scheduler/AutoDakaScheduler.kt index e90d404..eca5e84 100644 --- a/src/main/kotlin/com/pomelotea/hoperun/sign/scheduler/AutoDakaScheduler.kt +++ b/src/main/kotlin/com/pomelotea/hoperun/sign/scheduler/AutoDakaScheduler.kt @@ -1,21 +1,16 @@ package com.pomelotea.hoperun.sign.scheduler -import com.alibaba.fastjson.JSON -import com.alibaba.fastjson.JSONObject import com.pomelotea.hoperun.sign.api.DakaResponse -import com.pomelotea.hoperun.sign.api.model.ScNotifyRequest -import com.pomelotea.hoperun.sign.api.model.ScNotifyResponse import com.pomelotea.hoperun.sign.common.* import com.pomelotea.hoperun.sign.config.HoperunUserConfig import com.pomelotea.hoperun.sign.config.UserConfig -import com.pomelotea.hoperun.sign.notify.ServerChan3NotifyHelper +import com.pomelotea.hoperun.sign.holiday.HolidayService import com.pomelotea.hoperun.sign.service.NotificationService import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import org.slf4j.Logger import org.slf4j.LoggerFactory -import org.springframework.stereotype.Service import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.* @@ -32,7 +27,8 @@ import java.util.concurrent.TimeUnit * 自动打卡定时任务 **/ open class AutoDakaScheduler( - private val notificationService: NotificationService + private val notificationService: NotificationService, + private val holidayService: HolidayService ) { val timeThreadPool: ScheduledExecutorService = Executors.newScheduledThreadPool(1) @@ -49,7 +45,7 @@ open class AutoDakaScheduler( private fun addAutoDakaScheduled(dakaDate: String = getNowDateyyyy_MM_dd()) { // 调休的工作日 - if (isNeedDaka(dakaDate)) { + if (holidayService.isWorkingDay(dakaDate)) { HoperunUserConfig.userConfigMap.forEach { (_, v) -> if (v.autoDaka) { // 没有当日的打卡信息才插入 @@ -98,11 +94,9 @@ open class AutoDakaScheduler( schedulerThreadPool.schedule({ endDaka(it) }, endSeconds, TimeUnit.SECONDS) } } -// schedulerThreadPool.schedule({beginDaka(it)}, 5, TimeUnit.SECONDS) -// schedulerThreadPool.schedule({ endDaka(it) }, 10, TimeUnit.SECONDS) } - dakaQueue.removeIf { it.dakaDate.compareTo(dakaDate) == -1 } + dakaQueue.removeIf { it.dakaDate.compareTo(dakaDate) < 0 } printScheduler() dakaQueue.forEach { logger.info("Task: ${it.toCsv()}") @@ -239,4 +233,4 @@ data class Daka( override fun toString(): String { return "工号: $employeeNo, 日期: $dakaDate, 上班卡: $beginTime, 下班卡: $endTime, 定时开关: $added" } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/pomelotea/hoperun/sign/scheduler/AutoRenewSessionScheduler.kt b/src/main/kotlin/com/pomelotea/hoperun/sign/scheduler/AutoRenewSessionScheduler.kt deleted file mode 100644 index 03cdc35..0000000 --- a/src/main/kotlin/com/pomelotea/hoperun/sign/scheduler/AutoRenewSessionScheduler.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.pomelotea.hoperun.sign.scheduler - -import com.pomelotea.hoperun.sign.common.client -import com.pomelotea.hoperun.sign.common.sessionMap -import com.pomelotea.hoperun.sign.logger -import okhttp3.Request -import org.jsoup.Jsoup -import java.util.* -import java.util.concurrent.Executors -import java.util.concurrent.ScheduledExecutorService -import java.util.concurrent.TimeUnit - -/** - * - * @version 0.0.1 - * @author jimlee - * date 2023-03-23 08:54 - * - **/ -class AutoRenewSessionScheduler { - - val schedulerThreadPool: ScheduledExecutorService = Executors.newScheduledThreadPool(1) - - init { - schedulerThreadPool.schedule({renewSession()}, 2, TimeUnit.MINUTES) - } - - private fun renewSession() { - val iterator = sessionMap.iterator() - while (iterator.hasNext()) { - val item = iterator.next() - item.value?.let { - val result = index(it) - if (result != null) { - logger.info("[RENEW-SESSION]:SUCCESS:USER:$result") - } else { - logger.info("[REMOVE-SESSION]:USER:$result") - iterator.remove() - } - } - } - schedulerThreadPool.schedule({renewSession()}, (30 + Random().nextInt(30)).toLong(), TimeUnit.MINUTES) - } - - private fun index(jsessionId: String): String? { - val indexRequest = Request.Builder() - .url("http://pom.hoperun.com:8187/attm/attence/getInfo") - .get() - .addHeader("Cookie", "JSESSIONID=$jsessionId") - .addHeader( - "User-Agent", - "Qing/0.9.113;iOS 16.3.1;Apple;iPhone13,2;deviceId:a8baf66f-fdeb-4f4d-b1e5-9fafcd5045b6;deviceName:iOS;clientId:10200;os:iOS 16.3.1;brand:Apple;model:iPhone13,2;lang:zh-CN;fontNum:0;fontScale:1.0;ver:10.7.14;Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" - ) - .addHeader("accept", "*/*") - .addHeader("Origin", "http://pom.hoperun.com:8187") - .addHeader("Referer", "http://pom.hoperun.com:8187/attm/attence/getInfo") - .addHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8") - .build() - val indexResp = client.newCall(indexRequest).execute() - val indexHtml = indexResp.body?.string() - val username = try { - Jsoup.parse(indexHtml!!).select("#attendance-detail-content > div.container.none-padding > div > div:nth-child(1) > div:nth-child(4)") - .text() - } catch (e: Exception) { - null - } - return username - } - -} \ No newline at end of file diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml index 6ef1551..ce671c9 100644 --- a/src/main/resources/config/application.yml +++ b/src/main/resources/config/application.yml @@ -40,4 +40,17 @@ hoperun: sc3: uid: 7248 - sendKey: sctp7248ta-yehg0lpo6cr9xl6ikqwbpn4l \ No newline at end of file + sendKey: sctp7248ta-yehg0lpo6cr9xl6ikqwbpn4l + +holiday: + enabled: true + sources: + - https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{year}.json + proxy-sources: + - https://ghproxy.com/https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{year}.json + cache-dir: ./data/holiday + cache-ttl-days: 30 + years-ahead: 1 + fallback: + holidays: [] + workdays: []