优化了代码风格,增加了代码可读性,通过多线程避免了一些卡bug的方法

This commit is contained in:
千嶂夹城 2025-06-22 15:11:48 +08:00
parent b79b34719a
commit 9eb637e927
3 changed files with 163 additions and 101 deletions

5
.gitignore vendored
View File

@ -1,3 +1,6 @@
.vscode/
*.exe
*.txt
*.txt
.env
*.bak
*.log

View File

@ -3,14 +3,35 @@
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<string>
#include<thread>
#include<vector>
#include<ctime>
#include<map>
using namespace std;
// 黑名单
const int BLACK_LIST_SIZE = 3;
string blackList[]={"哔哩哔哩","MuMu模拟器","知乎"};
int blackListTimeCount = 0;
const int MAX_BLACKLIST_TIME_COUNT = 1800;
const int TOLENT_MORE_TIME = 1200;
ofstream logFile; // 日志文件
vector<string> blackList; // 黑名单
int blackListTimeCount = 0; // 黑名单时间计数
const int MAX_BLACKLIST_TIME_COUNT = 1800; // 黑名单最大时间
const int TOLENT_MORE_TIME = 1200; // 超出黑名单时间后,多长时间禁止摸鱼
const int PUNISH_CLICKS = 20; // 连续点击次数超过多少次后允许继续
const int PUNISH_CLICKS_RND = 10; // 连续点击次数向上飘逸上限
// 从字符串中读取黑名单
void getBlackList(string str){
if(str.substr(0, 10)!="BLACK_LIST") return;
str = str.substr(str.find("=")+1);
stringstream ss(str); string item;
while(ss>>quoted(item)){
if(item==",") continue;
blackList.push_back(item);
}
}
// 保存黑名单时间
void saveData(){
// 保存黑名单时间到save.txt
FILE *fp = fopen("save.txt", "w");
@ -25,24 +46,8 @@ void saveData(){
fclose(fp);
}
}
bool beginWithMuteFlag=false;
void muteAll(){
keybd_event(VK_SPACE, 0, 0, 0);
Sleep(1);
keybd_event(VK_SPACE, 0, KEYEVENTF_KEYUP, 0);
}
void unmuteAll(){
keybd_event(VK_SPACE, 0, 0, 0);
Sleep(1);
keybd_event(VK_SPACE, 0, KEYEVENTF_KEYUP, 0);
}
int main(){
ShowWindow(GetConsoleWindow(), SW_HIDE);
system("chcp 936 >>nul");
FreeConsole();
srand((unsigned)time(0));
char title[1024];
// 从save.txt中读取黑名单时间
// 加载黑名单时间
void loadData(){
FILE *fp = fopen("save.txt", "r");
if(fp!=NULL){
int curYear,curMonth,curDay;
@ -58,87 +63,139 @@ int main(){
}
fclose(fp);
}
cout<<"Hello, Self Monitor!";
}
// 获取当前时间字符串
string getTimeStr(){
time_t now = time(0);
tm *ltm = localtime(&now);
char timeStr[1024];
strftime(timeStr, sizeof(timeStr), "[%Y-%m-%d %H:%M:%S]", ltm);
return (string)timeStr;
}
// 初始化程序
void initMonitor(){
ShowWindow(GetConsoleWindow(), SW_HIDE); // 隐藏控制台窗口
system("chcp 936 >>nul"); // 设置编码为GBK
FreeConsole(); // 隐藏控制台窗口
srand((unsigned)time(0)); // 初始化随机数种子
logFile.open("selfMonitor.log", ios::out); // 打开日志文件
ifstream ifs(".env");
if(ifs.is_open()){
string line;
while(getline(ifs, line))
getBlackList(line);
ifs.close();
}
loadData();
logFile<<getTimeStr()<<"- INFO: 自监控程序启动,冰澄向你问好!"<<endl;
logFile<<getTimeStr()<<"- INFO: 黑名单列表:"<<endl;
for(int i=0;i<blackList.size();i++)
logFile<<'\"'<<blackList[i]<<'\"'<<endl;
logFile<<getTimeStr()<<"- INFO: 当前黑名单时间计数:"<<blackListTimeCount<<endl;
}
bool beginWithMuteFlag=false;
// TODO: 设置 muteAll 和 unmuteAll 函数,实现暂停播放功能
void muteAll(){ // 目前效果为:按压空格键(已取消)
// keybd_event(VK_SPACE, 0, 0, 0); Sleep(1);
// keybd_event(VK_SPACE, 0, KEYEVENTF_KEYUP, 0);
}
void unmuteAll(){muteAll();}
// 判断是否是早上四点
inline bool judgeEarlyMorning(){
time_t now = time(0);
tm *ltm = localtime(&now);
if(ltm->tm_hour==4&&ltm->tm_min<5)
return true;
return false;
}
// 获取当前窗口标题
string getForegroundTitle(HWND hwnd){
char title[1024];
if (hwnd == NULL) return "";
if(GetWindowTextA(hwnd, title, 1024) == 0){
logFile<<getTimeStr()<<"- WARN: GetWindowTextW failed at hwnd: "<<hwnd<<endl;
logFile<<getTimeStr()<<"- WARN: Error content: "<<GetLastError()<<endl;
return "";
}
return (string)title;
}
// 判断是否在黑名单中
bool inBlackList(string title){
if(title=="") return false;
bool isInBlackList = false;
for(string blackTitle:blackList)
if(title.find(blackTitle)!=string::npos)
return true;
return false;
}
// 关闭过程,通过复杂的操作迫使用户思考是否应该继续摸鱼
bool closingGame(HWND hwnd){
bool isContinue = MessageBoxA(hwnd, "半小时到了!你确定你需要继续看这个?", "半个小时提醒", MB_YESNO) == IDYES;
if(!isContinue) return false;
MessageBoxA(hwnd, "如果你真的确定的话,按照我的指令连续点正确选项:", "唉,拿你没办法呢", MB_OK);
for(int i=PUNISH_CLICKS+rand()%(PUNISH_CLICKS_RND+1);i>0;i--){
if(rand()&1) isContinue = MessageBoxA(hwnd, "先思考一下,你现在真的有用电脑的必要吗?\n你现在应该做什么?\n想好了按确认", "请思考请思考", MB_YESNO) == IDYES;
else isContinue = MessageBoxA(hwnd, "先思考一下,你现在真的有用电脑的必要吗?\n你现在应该做什么?\n想好了按取消", "请思考请思考", MB_YESNO) == IDNO;
if(!isContinue){
MessageBoxA(hwnd, "看来你并没有真正下定决心呢……", "叹气……", MB_OK);
return false;
}
}
return true;
}
map<HWND,thread> warningSet;
// 启动超出时间限制禁言程序
void operateTimeExceeded(HWND hwnd){
logFile<<getTimeStr()<<"- WARN: 黑名单时间超过"<<MAX_BLACKLIST_TIME_COUNT<<"秒,开始禁言程序"<<endl;
if(warningSet.find(hwnd)!=warningSet.end()) return;
warningSet[hwnd] = thread([hwnd](){
muteAll();
if(closingGame(hwnd)){
MessageBoxA(hwnd, "好吧,看来你确实有急事,去忙吧,你再用二十分钟后我还会回来的!", "你先忙吧", MB_OK);
blackListTimeCount = MAX_BLACKLIST_TIME_COUNT - TOLENT_MORE_TIME;
}else{
MessageBoxA(hwnd, "根据反摸鱼条例,你今天不准再摸鱼了!\n你有五秒钟保存重要文件,我数到五就强制关掉!","True Ending",MB_OK);
Sleep(5*1000);
PostMessageA(hwnd, WM_CLOSE, 0, 0);
}
unmuteAll();
warningSet.erase(hwnd);
});
warningSet[hwnd].detach();
}
// 启动提醒程序
void operateTimeWarning(HWND hwnd,string warningMsg){
logFile<<getTimeStr()<<"- INFO: 当前黑名单时间到达"<<blackListTimeCount<<"秒,开始提醒程序"<<endl;
if(warningSet.find(hwnd)!=warningSet.end()) return;
warningSet[hwnd] = thread([hwnd,warningMsg](){
muteAll();
MessageBoxA(hwnd, warningMsg.c_str(), "摸鱼提醒", MB_OK);
unmuteAll();
warningSet.erase(hwnd);
});
warningSet[hwnd].detach();
}
int main(){
initMonitor();
while(true){
// 判断时间如果是早上四点就重置
time_t now = time(0);
tm *ltm = localtime(&now);
if(ltm->tm_hour==4&&ltm->tm_min==0){
if(judgeEarlyMorning())
blackListTimeCount = 0;
}
// 获取顶层窗口名称
HWND hwnd = GetForegroundWindow();
if (hwnd == NULL) {
continue;
}
if(GetWindowTextA(hwnd, title, 1024) == 0){
cout<<"GetWindowTextW failed"<<endl;
cout<<"hwnd: "<<hwnd<<endl;
cout<<"Error code: "<<GetLastError()<<endl;
Sleep(1000);
continue;
}
cout<<"*"<<title<<endl;
// 判断是否在黑名单中
bool isInBlackList = false; string strTitle = title;
for(int i=0;i<BLACK_LIST_SIZE;i++){
if(strTitle.find(blackList[i])!=string::npos){
isInBlackList = true;
break;
}
}
cout<<"*"<<title<<endl<<isInBlackList<<endl;
if(isInBlackList){
cout<<hwnd<<','<<title<<"\n";
HWND hwnd = GetForegroundWindow(); // 获取当前窗口句柄
string title=getForegroundTitle(hwnd); // 获取窗口标题
if(inBlackList(title)){ // 判断是否在黑名单中
blackListTimeCount++;
if(blackListTimeCount>=MAX_BLACKLIST_TIME_COUNT){
muteAll();
bool isContinue = true;
isContinue = MessageBoxA(hwnd, "半小时到了!你确定你需要继续看这个?", "半个小时提醒", MB_YESNO) == IDYES;
if(isContinue){
MessageBoxA(hwnd, "如果你真的确定的话,按照我的指令连续点十次:", "唉,拿你没办法呢", MB_OK);
for(int i=0;i<10;i++){
int randNum = rand()&1;
if(randNum){
isContinue = MessageBoxA(hwnd, "先思考一下,你现在真的有用电脑的必要吗?\n你现在应该做什么?\n想好了按确认", "请思考请思考", MB_YESNO) == IDYES;
}else{
isContinue = MessageBoxA(hwnd, "先思考一下,你现在真的有用电脑的必要吗?\n你现在应该做什么?\n想好了按取消", "请思考请思考", MB_YESNO) == IDNO;
}
if(!isContinue){
MessageBoxA(hwnd, "看来你并没有真正下定决心呢……", "叹气……", MB_OK);
break;
}
}
}
unmuteAll();
if(isContinue){
MessageBoxA(hwnd, "好吧,看来你确实有急事,去忙吧,你再用二十分钟后我还会回来的!", "你先忙吧", MB_OK);
blackListTimeCount = MAX_BLACKLIST_TIME_COUNT - TOLENT_MORE_TIME;
}else{
MessageBoxA(hwnd, "根据千嶂夹城制定的反摸鱼条例,你今天不准再摸鱼了!\n你有五秒钟保存重要文件,我数到五就强制关掉!","True Ending",MB_OK);
Sleep(5*1000);
// 强制关闭hwnd窗口
PostMessageA(hwnd, WM_CLOSE, 0, 0);
}
}else if(blackListTimeCount%600==0){
muteAll();
MessageBoxA(hwnd, "你摸鱼已经十分钟了,冰澄命令你停下!", "十分钟提醒", MB_OK);
unmuteAll();
}else if(blackListTimeCount%300==0){
muteAll();
MessageBoxA(hwnd, "你在摸鱼吗,又摸了五分钟了,冰澄提醒你正确休息", "五分钟提醒", MB_OK);
unmuteAll();
}
if(blackListTimeCount>=MAX_BLACKLIST_TIME_COUNT)
operateTimeExceeded(hwnd);
else if (blackListTimeCount%600==0)
operateTimeWarning(hwnd,"你摸鱼已经十分钟了,冰澄命令你停下!");
else if (blackListTimeCount%300==0)
operateTimeWarning(hwnd,"你在摸鱼吗,又摸了五分钟了,冰澄提醒你正确休息");
}
// 延时
Sleep(1000);
static int clockCount = 0;
clockCount++;
if(clockCount%60==0){
Sleep(1000); // 休眠1秒钟
static int clockCount = 0; // 存档计时器
if((++clockCount)%60==0) // 每分钟存档一次
saveData();
}
// cout<<title<<endl;
// cout<<"blackListTimeCount: "<<blackListTimeCount<<endl;
}
return 0;
}

2
template.env Normal file
View File

@ -0,0 +1,2 @@
# 将此文件命名为 .env放到项目根目录下
BLACK_LIST = "ProgramName" "\"ProgramWithQuotesAndBackSlashes\"\\"