迁移回来了

This commit is contained in:
Cirrus83
2026-04-23 13:39:28 +08:00
commit 35aa1b3559
250 changed files with 17010 additions and 0 deletions
@@ -0,0 +1,198 @@
#!/bin/bash
username=$(whoami)
script_dir=$(dirname "$0")
cd $script_dir
echo "==Tesuto Alarm Dec 2025(By Cirrus)安装程序=="
echo "当前用户: $username"
echo "当前目录: $script_dir"
echo ""
echo "检测程序是否正在运行:"
if launchctl list | grep -q cn.org.cirrus.tesutoalarmdec2025;then
echo "在运行,先终止进程,再安装。"
echo ""
launchctl stop cn.org.cirrus.tesutoalarmdec2025
launchctl unload /Users/$username/Library/LaunchAgents/cn.org.cirrus.tesutoalarmdec2025.plist
echo ""
echo "继续安装。"
else
echo "不在运行,继续安装。"
fi
echo ""
echo "提示:程序文件默认保存目录:"
echo "二进制文件:${script_dir}/tesuto"
echo "STDOUT目录:${script_dir}/tesuto.log"
echo "STDERR目录:${script_dir}/tesuto.error.log"
echo "注意:请勿重命名、移动、修改、删除。"
echo ""
echo "请输入声音文件的绝对路径:(直接回车表示$script_dir/sound.mp3"
read sound
if [ "$sound" == "" ];then
sound="${script_dir}/sound.mp3"
fi
echo "注意:为保证程序运行正常,请保持该文件在原目录,且未重命名。"
echo ""
echo "请输入闹铃JSON文件的保存文件夹目录:(以“/”结尾,请勿加上alarms.json"
echo "(直接回车表示$script_dir/"
read jsonpath
if [ "$jsonpath" == "" ];then
jsonpath="${script_dir}/"
fi
cat > ${jsonpath}alarms.json << EOF
[
{
"name": "Test1",
"hour": 8,
"minute": 45,
"triggered": false
},
{
"name": "Test2",
"hour": 9,
"minute": 41,
"triggered": false
}
]
EOF
cat > ./tesuto.swift << EOF
import UniformTypeIdentifiers
import SwiftUI
import Combine
class Alarm: Codable, ObservableObject
{
let name: String
let hour: Int
let minute: Int
var triggered: Bool
}
let app = NSApplication.shared
NSApp.setActivationPolicy(.regular)
let sound = NSSound(contentsOf: URL(fileURLWithPath: ("$sound" as NSString).expandingTildeInPath), byReference: false)
if sound != nil
{
print("\(Date()): 读取声音文件成功")
print("尝试播放:(2秒后停止)")
fflush(stdout)
sound?.play()
DispatchQueue.main.asyncAfter(deadline: .now() + 2)
{
sound?.stop()
}
}
else
{
print("\(Date()): 读取声音文件失败")
fflush(stdout)
}
var alarms: [Alarm] = []
func readJSON(url: URL) -> Bool
{
do
{
let json = try Data(contentsOf: url)
let loadedData = try JSONDecoder().decode([Alarm].self, from: json)
alarms = loadedData
print("\(Date()): 读取JSON成功")
print("闹钟数据:")
for alarm in alarms
{
print("\n名称:\(alarm.name)")
print("时间:\(alarm.hour):\(alarm.minute)")
}
fflush(stdout)
return true
}
catch
{
print("\(Date()): 读取JSON失败(\(error))")
fflush(stdout)
return false
}
}
func perform(for alarm: Alarm)
{
let window = NSAlert()
window.messageText = "闹钟提醒"
window.informativeText = "\(alarm.name) - \(alarm.hour):\(alarm.minute)"
window.addButton(withTitle: "关闭\(alarm.name)")
print("\(Date()): 触发\(alarm.name) - \(alarm.hour):\(alarm.minute)")
fflush(stdout)
sound?.play()
Task
{
try await Task.sleep(nanoseconds: 1 * 60 * 1_000_000_000)
sound?.stop()
print("\(Date()): 超时自动关闭\(alarm.name) - \(alarm.hour):\(alarm.minute)")
fflush(stdout)
return
}
window.runModal()
sound?.stop()
print("\(Date()): 手动关闭\(alarm.name) - \(alarm.hour):\(alarm.minute)")
fflush(stdout)
}
let timer = Timer.publish(every: 1, on: .main, in: .default).autoconnect()
var cancellables = Set<AnyCancellable>()
_ = readJSON(url: URL(fileURLWithPath: ("${jsonpath}alarms.json" as NSString).expandingTildeInPath))
timer.sink
{
_ in
let now = Date()
let calendar = Calendar.current
let currentSecond = calendar.component(.second, from: now)
if currentSecond < 3
{
let currentHour = calendar.component(.hour, from: now)
let currentMinute = calendar.component(.minute, from: now)
for alarm in alarms
{
if alarm.hour == currentHour && alarm.minute == currentMinute && !alarm.triggered
{
perform(for: alarm)
alarm.triggered.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 5)
{
alarm.triggered.toggle()
print("\(Date()): 清除\(alarm.name)的triggered标识")
fflush(stdout)
}
}
}
}
}
.store(in: &cancellables)
RunLoop.current.run()
EOF
swiftc tesuto.swift
cat > ./cn.org.cirrus.tesutoalarmdec2025.plist << EOF
<?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>cn.org.cirrus.tesutoalarmdec2025</string>
<key>ProgramArguments</key>
<array>
<string>${script_dir}/tesuto</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>${script_dir}/tesuto.log</string>
<key>StandardErrorPath</key>
<string>${script_dir}/tesuto.error.log</string>
</dict>
</plist>
EOF
cp ./cn.org.cirrus.tesutoalarmdec2025.plist /Users/$username/Library/LaunchAgents/cn.org.cirrus.tesutoalarmdec2025.plist
launchctl load /Users/$username/Library/LaunchAgents/cn.org.cirrus.tesutoalarmdec2025.plist
echo ""
echo "如果听到您指定音频文件的开头2秒,则表明程序安装完成。"
echo "详见cirrus.log。"
echo "更改时区代码较为麻烦,故请您将就看,把每个时间的小时数+8即可。"