mirror of
https://github.com/tcsenpai/pensieve.git
synced 2025-06-06 03:05:25 +00:00
feat(win): enable autostart
This commit is contained in:
parent
a2f488858e
commit
d830b136de
31
dict/README.md
Normal file
31
dict/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# CppJieba字典
|
||||
|
||||
文件后缀名代表的是词典的编码方式。
|
||||
比如filename.utf8 是 utf8编码,filename.gbk 是 gbk编码方式。
|
||||
|
||||
|
||||
## 分词
|
||||
|
||||
### jieba.dict.utf8/gbk
|
||||
|
||||
作为最大概率法(MPSegment: Max Probability)分词所使用的词典。
|
||||
|
||||
### hmm_model.utf8/gbk
|
||||
|
||||
作为隐式马尔科夫模型(HMMSegment: Hidden Markov Model)分词所使用的词典。
|
||||
|
||||
__对于MixSegment(混合MPSegment和HMMSegment两者)则同时使用以上两个词典__
|
||||
|
||||
|
||||
## 关键词抽取
|
||||
|
||||
### idf.utf8
|
||||
|
||||
IDF(Inverse Document Frequency)
|
||||
在KeywordExtractor中,使用的是经典的TF-IDF算法,所以需要这么一个词典提供IDF信息。
|
||||
|
||||
### stop_words.utf8
|
||||
|
||||
停用词词典
|
||||
|
||||
|
34
dict/hmm_model.utf8
Normal file
34
dict/hmm_model.utf8
Normal file
File diff suppressed because one or more lines are too long
258826
dict/idf.utf8
Normal file
258826
dict/idf.utf8
Normal file
File diff suppressed because it is too large
Load Diff
348982
dict/jieba.dict.utf8
Normal file
348982
dict/jieba.dict.utf8
Normal file
File diff suppressed because it is too large
Load Diff
6653
dict/pos_dict/char_state_tab.utf8
Normal file
6653
dict/pos_dict/char_state_tab.utf8
Normal file
File diff suppressed because it is too large
Load Diff
166
dict/pos_dict/prob_emit.utf8
Normal file
166
dict/pos_dict/prob_emit.utf8
Normal file
File diff suppressed because one or more lines are too long
259
dict/pos_dict/prob_start.utf8
Normal file
259
dict/pos_dict/prob_start.utf8
Normal file
@ -0,0 +1,259 @@
|
||||
#初始状态的概率
|
||||
#格式
|
||||
#状态:概率
|
||||
B,a:-4.7623052146
|
||||
B,ad:-6.68006603678
|
||||
B,ag:-3.14e+100
|
||||
B,an:-8.69708322302
|
||||
B,b:-5.01837436211
|
||||
B,bg:-3.14e+100
|
||||
B,c:-3.42388018495
|
||||
B,d:-3.97504752976
|
||||
B,df:-8.88897423083
|
||||
B,dg:-3.14e+100
|
||||
B,e:-8.56355183039
|
||||
B,en:-3.14e+100
|
||||
B,f:-5.49163041848
|
||||
B,g:-3.14e+100
|
||||
B,h:-13.53336513
|
||||
B,i:-6.11578472756
|
||||
B,in:-3.14e+100
|
||||
B,j:-5.05761912847
|
||||
B,jn:-3.14e+100
|
||||
B,k:-3.14e+100
|
||||
B,l:-4.90588358466
|
||||
B,ln:-3.14e+100
|
||||
B,m:-3.6524299819
|
||||
B,mg:-3.14e+100
|
||||
B,mq:-6.7869530014
|
||||
B,n:-1.69662577975
|
||||
B,ng:-3.14e+100
|
||||
B,nr:-2.23104959138
|
||||
B,nrfg:-5.87372217541
|
||||
B,nrt:-4.98564273352
|
||||
B,ns:-2.8228438315
|
||||
B,nt:-4.84609166818
|
||||
B,nz:-3.94698846058
|
||||
B,o:-8.43349870215
|
||||
B,p:-4.20098413209
|
||||
B,q:-6.99812385896
|
||||
B,qe:-3.14e+100
|
||||
B,qg:-3.14e+100
|
||||
B,r:-3.40981877908
|
||||
B,rg:-3.14e+100
|
||||
B,rr:-12.4347528413
|
||||
B,rz:-7.94611647157
|
||||
B,s:-5.52267359084
|
||||
B,t:-3.36474790945
|
||||
B,tg:-3.14e+100
|
||||
B,u:-9.1639172775
|
||||
B,ud:-3.14e+100
|
||||
B,ug:-3.14e+100
|
||||
B,uj:-3.14e+100
|
||||
B,ul:-3.14e+100
|
||||
B,uv:-3.14e+100
|
||||
B,uz:-3.14e+100
|
||||
B,v:-2.67405848743
|
||||
B,vd:-9.04472876024
|
||||
B,vg:-3.14e+100
|
||||
B,vi:-12.4347528413
|
||||
B,vn:-4.33156108902
|
||||
B,vq:-12.1470707689
|
||||
B,w:-3.14e+100
|
||||
B,x:-3.14e+100
|
||||
B,y:-9.84448567586
|
||||
B,yg:-3.14e+100
|
||||
B,z:-7.04568111149
|
||||
B,zg:-3.14e+100
|
||||
E,a:-3.14e+100
|
||||
E,ad:-3.14e+100
|
||||
E,ag:-3.14e+100
|
||||
E,an:-3.14e+100
|
||||
E,b:-3.14e+100
|
||||
E,bg:-3.14e+100
|
||||
E,c:-3.14e+100
|
||||
E,d:-3.14e+100
|
||||
E,df:-3.14e+100
|
||||
E,dg:-3.14e+100
|
||||
E,e:-3.14e+100
|
||||
E,en:-3.14e+100
|
||||
E,f:-3.14e+100
|
||||
E,g:-3.14e+100
|
||||
E,h:-3.14e+100
|
||||
E,i:-3.14e+100
|
||||
E,in:-3.14e+100
|
||||
E,j:-3.14e+100
|
||||
E,jn:-3.14e+100
|
||||
E,k:-3.14e+100
|
||||
E,l:-3.14e+100
|
||||
E,ln:-3.14e+100
|
||||
E,m:-3.14e+100
|
||||
E,mg:-3.14e+100
|
||||
E,mq:-3.14e+100
|
||||
E,n:-3.14e+100
|
||||
E,ng:-3.14e+100
|
||||
E,nr:-3.14e+100
|
||||
E,nrfg:-3.14e+100
|
||||
E,nrt:-3.14e+100
|
||||
E,ns:-3.14e+100
|
||||
E,nt:-3.14e+100
|
||||
E,nz:-3.14e+100
|
||||
E,o:-3.14e+100
|
||||
E,p:-3.14e+100
|
||||
E,q:-3.14e+100
|
||||
E,qe:-3.14e+100
|
||||
E,qg:-3.14e+100
|
||||
E,r:-3.14e+100
|
||||
E,rg:-3.14e+100
|
||||
E,rr:-3.14e+100
|
||||
E,rz:-3.14e+100
|
||||
E,s:-3.14e+100
|
||||
E,t:-3.14e+100
|
||||
E,tg:-3.14e+100
|
||||
E,u:-3.14e+100
|
||||
E,ud:-3.14e+100
|
||||
E,ug:-3.14e+100
|
||||
E,uj:-3.14e+100
|
||||
E,ul:-3.14e+100
|
||||
E,uv:-3.14e+100
|
||||
E,uz:-3.14e+100
|
||||
E,v:-3.14e+100
|
||||
E,vd:-3.14e+100
|
||||
E,vg:-3.14e+100
|
||||
E,vi:-3.14e+100
|
||||
E,vn:-3.14e+100
|
||||
E,vq:-3.14e+100
|
||||
E,w:-3.14e+100
|
||||
E,x:-3.14e+100
|
||||
E,y:-3.14e+100
|
||||
E,yg:-3.14e+100
|
||||
E,z:-3.14e+100
|
||||
E,zg:-3.14e+100
|
||||
M,a:-3.14e+100
|
||||
M,ad:-3.14e+100
|
||||
M,ag:-3.14e+100
|
||||
M,an:-3.14e+100
|
||||
M,b:-3.14e+100
|
||||
M,bg:-3.14e+100
|
||||
M,c:-3.14e+100
|
||||
M,d:-3.14e+100
|
||||
M,df:-3.14e+100
|
||||
M,dg:-3.14e+100
|
||||
M,e:-3.14e+100
|
||||
M,en:-3.14e+100
|
||||
M,f:-3.14e+100
|
||||
M,g:-3.14e+100
|
||||
M,h:-3.14e+100
|
||||
M,i:-3.14e+100
|
||||
M,in:-3.14e+100
|
||||
M,j:-3.14e+100
|
||||
M,jn:-3.14e+100
|
||||
M,k:-3.14e+100
|
||||
M,l:-3.14e+100
|
||||
M,ln:-3.14e+100
|
||||
M,m:-3.14e+100
|
||||
M,mg:-3.14e+100
|
||||
M,mq:-3.14e+100
|
||||
M,n:-3.14e+100
|
||||
M,ng:-3.14e+100
|
||||
M,nr:-3.14e+100
|
||||
M,nrfg:-3.14e+100
|
||||
M,nrt:-3.14e+100
|
||||
M,ns:-3.14e+100
|
||||
M,nt:-3.14e+100
|
||||
M,nz:-3.14e+100
|
||||
M,o:-3.14e+100
|
||||
M,p:-3.14e+100
|
||||
M,q:-3.14e+100
|
||||
M,qe:-3.14e+100
|
||||
M,qg:-3.14e+100
|
||||
M,r:-3.14e+100
|
||||
M,rg:-3.14e+100
|
||||
M,rr:-3.14e+100
|
||||
M,rz:-3.14e+100
|
||||
M,s:-3.14e+100
|
||||
M,t:-3.14e+100
|
||||
M,tg:-3.14e+100
|
||||
M,u:-3.14e+100
|
||||
M,ud:-3.14e+100
|
||||
M,ug:-3.14e+100
|
||||
M,uj:-3.14e+100
|
||||
M,ul:-3.14e+100
|
||||
M,uv:-3.14e+100
|
||||
M,uz:-3.14e+100
|
||||
M,v:-3.14e+100
|
||||
M,vd:-3.14e+100
|
||||
M,vg:-3.14e+100
|
||||
M,vi:-3.14e+100
|
||||
M,vn:-3.14e+100
|
||||
M,vq:-3.14e+100
|
||||
M,w:-3.14e+100
|
||||
M,x:-3.14e+100
|
||||
M,y:-3.14e+100
|
||||
M,yg:-3.14e+100
|
||||
M,z:-3.14e+100
|
||||
M,zg:-3.14e+100
|
||||
S,a:-3.90253968313
|
||||
S,ad:-11.0484584802
|
||||
S,ag:-6.95411391796
|
||||
S,an:-12.8402179494
|
||||
S,b:-6.47288876397
|
||||
S,bg:-3.14e+100
|
||||
S,c:-4.78696679586
|
||||
S,d:-3.90391976418
|
||||
S,df:-3.14e+100
|
||||
S,dg:-8.9483976513
|
||||
S,e:-5.94251300628
|
||||
S,en:-3.14e+100
|
||||
S,f:-5.19482024998
|
||||
S,g:-6.50782681533
|
||||
S,h:-8.65056320738
|
||||
S,i:-3.14e+100
|
||||
S,in:-3.14e+100
|
||||
S,j:-4.91199211964
|
||||
S,jn:-3.14e+100
|
||||
S,k:-6.94032059583
|
||||
S,l:-3.14e+100
|
||||
S,ln:-3.14e+100
|
||||
S,m:-3.26920065212
|
||||
S,mg:-10.8253149289
|
||||
S,mq:-3.14e+100
|
||||
S,n:-3.85514838976
|
||||
S,ng:-4.9134348611
|
||||
S,nr:-4.48366310396
|
||||
S,nrfg:-3.14e+100
|
||||
S,nrt:-3.14e+100
|
||||
S,ns:-3.14e+100
|
||||
S,nt:-12.1470707689
|
||||
S,nz:-3.14e+100
|
||||
S,o:-8.46446092775
|
||||
S,p:-2.98684018136
|
||||
S,q:-4.88865861826
|
||||
S,qe:-3.14e+100
|
||||
S,qg:-3.14e+100
|
||||
S,r:-2.76353367841
|
||||
S,rg:-10.2752685919
|
||||
S,rr:-3.14e+100
|
||||
S,rz:-3.14e+100
|
||||
S,s:-3.14e+100
|
||||
S,t:-3.14e+100
|
||||
S,tg:-6.27284253188
|
||||
S,u:-6.94032059583
|
||||
S,ud:-7.72823016105
|
||||
S,ug:-7.53940370266
|
||||
S,uj:-6.85251045118
|
||||
S,ul:-8.41537131755
|
||||
S,uv:-8.15808672229
|
||||
S,uz:-9.29925862537
|
||||
S,v:-3.05329230341
|
||||
S,vd:-3.14e+100
|
||||
S,vg:-5.94301818437
|
||||
S,vi:-3.14e+100
|
||||
S,vn:-11.4539235883
|
||||
S,vq:-3.14e+100
|
||||
S,w:-3.14e+100
|
||||
S,x:-8.42741965607
|
||||
S,y:-6.19707946995
|
||||
S,yg:-13.53336513
|
||||
S,z:-3.14e+100
|
||||
S,zg:-3.14e+100
|
5222
dict/pos_dict/prob_trans.utf8
Normal file
5222
dict/pos_dict/prob_trans.utf8
Normal file
File diff suppressed because it is too large
Load Diff
1534
dict/stop_words.utf8
Normal file
1534
dict/stop_words.utf8
Normal file
File diff suppressed because it is too large
Load Diff
4
dict/user.dict.utf8
Normal file
4
dict/user.dict.utf8
Normal file
@ -0,0 +1,4 @@
|
||||
云计算
|
||||
韩玉鉴赏
|
||||
蓝翔 nz
|
||||
区块链 10 nz
|
@ -1,7 +1,7 @@
|
||||
import os
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import httpx
|
||||
import typer
|
||||
@ -19,6 +19,7 @@ import subprocess
|
||||
import platform
|
||||
from .cmds.plugin import plugin_app, bind
|
||||
from .cmds.library import lib_app, scan, index, watch
|
||||
import psutil
|
||||
|
||||
|
||||
app = typer.Typer(context_settings={"help_option_names": ["-h", "--help"]})
|
||||
@ -228,19 +229,28 @@ def get_memos_dir():
|
||||
def generate_windows_bat():
|
||||
memos_dir = get_memos_dir()
|
||||
python_path = get_python_path()
|
||||
pythonw_path = python_path.replace("python.exe", "pythonw.exe")
|
||||
conda_prefix = os.environ.get("CONDA_PREFIX")
|
||||
log_dir = memos_dir / "logs"
|
||||
log_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if conda_prefix:
|
||||
# If we're in a Conda environment
|
||||
activate_path = os.path.join(conda_prefix, "Scripts", "activate.bat")
|
||||
content = f"""@echo off
|
||||
call "{activate_path}"
|
||||
start "Memos" cmd /c ""{python_path}" -m memos.commands record & "{python_path}" -m memos.commands serve & timeout /t 5 /nobreak >nul & "{python_path}" -m memos.commands watch"
|
||||
start /B "" "{pythonw_path}" -m memos.commands record > "{log_dir / 'record.log'}" 2>&1
|
||||
start /B "" "{pythonw_path}" -m memos.commands serve > "{log_dir / 'serve.log'}" 2>&1
|
||||
timeout /t 5 /nobreak >nul
|
||||
start /B "" "{pythonw_path}" -m memos.commands watch > "{log_dir / 'watch.log'}" 2>&1
|
||||
"""
|
||||
else:
|
||||
# If we're not in a Conda environment, use the original content
|
||||
# If we're not in a Conda environment
|
||||
content = f"""@echo off
|
||||
start "Memos" cmd /c ""{python_path}" -m memos.commands record & "{python_path}" -m memos.commands serve & timeout /t 5 /nobreak >nul & "{python_path}" -m memos.commands watch"
|
||||
start /B "" "{pythonw_path}" -m memos.commands record > "{log_dir / 'record.log'}" 2>&1
|
||||
start /B "" "{pythonw_path}" -m memos.commands serve > "{log_dir / 'serve.log'}" 2>&1
|
||||
timeout /t 5 /nobreak >nul
|
||||
start /B "" "{pythonw_path}" -m memos.commands watch > "{log_dir / 'watch.log'}" 2>&1
|
||||
"""
|
||||
|
||||
bat_path = memos_dir / "launch.bat"
|
||||
@ -291,6 +301,7 @@ def setup_windows_autostart(bat_path):
|
||||
shortcut = shell.CreateShortCut(str(shortcut_path))
|
||||
shortcut.Targetpath = str(bat_path)
|
||||
shortcut.WorkingDirectory = str(bat_path.parent)
|
||||
shortcut.WindowStyle = 7 # Minimized
|
||||
shortcut.save()
|
||||
|
||||
|
||||
@ -364,6 +375,46 @@ def is_windows():
|
||||
return platform.system() == "Windows"
|
||||
|
||||
|
||||
def remove_windows_autostart():
|
||||
startup_folder = Path(os.getenv("APPDATA")) / r"Microsoft\Windows\Start Menu\Programs\Startup"
|
||||
shortcut_path = startup_folder / "Memos.lnk"
|
||||
|
||||
if shortcut_path.exists():
|
||||
shortcut_path.unlink()
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@app.command()
|
||||
def disable():
|
||||
"""Disable memos from running at startup"""
|
||||
if is_windows():
|
||||
if remove_windows_autostart():
|
||||
typer.echo("Removed Memos shortcut from startup folder. Memos will no longer run at startup.")
|
||||
else:
|
||||
typer.echo("Memos shortcut not found in startup folder. Memos is not set to run at startup.")
|
||||
elif is_macos():
|
||||
plist_path = Path.home() / "Library/LaunchAgents/com.user.memos.plist"
|
||||
if plist_path.exists():
|
||||
user_domain = f"gui/{os.getuid()}"
|
||||
service_name = "com.user.memos"
|
||||
|
||||
if is_service_loaded(service_name):
|
||||
subprocess.run(
|
||||
["launchctl", "bootout", user_domain, str(plist_path)], check=False
|
||||
)
|
||||
typer.echo("Unloaded Memos service.")
|
||||
else:
|
||||
typer.echo("Memos service was not running.")
|
||||
|
||||
plist_path.unlink()
|
||||
typer.echo("Removed plist file. Memos will no longer run at startup.")
|
||||
else:
|
||||
typer.echo("Plist file does not exist. Memos is not set to run at startup.")
|
||||
else:
|
||||
typer.echo("Unsupported operating system.")
|
||||
|
||||
|
||||
@app.command()
|
||||
def enable():
|
||||
"""Enable memos to run at startup"""
|
||||
@ -391,29 +442,27 @@ def enable():
|
||||
|
||||
|
||||
@app.command()
|
||||
def disable():
|
||||
"""Disable memos from running at startup"""
|
||||
if not is_macos():
|
||||
typer.echo("Error: This feature is only supported on macOS.")
|
||||
raise typer.Exit(code=1)
|
||||
def ps():
|
||||
"""Show the status of Memos processes"""
|
||||
services = ["serve", "watch", "record"]
|
||||
|
||||
plist_path = Path.home() / "Library/LaunchAgents/com.user.memos.plist"
|
||||
if plist_path.exists():
|
||||
user_domain = f"gui/{os.getuid()}"
|
||||
service_name = "com.user.memos"
|
||||
for service in services:
|
||||
processes = [p for p in psutil.process_iter(['pid', 'name', 'cmdline', 'create_time'])
|
||||
if 'python' in p.info['name'].lower() and
|
||||
'memos.commands' in p.info['cmdline'] and
|
||||
service in p.info['cmdline']]
|
||||
|
||||
if is_service_loaded(service_name):
|
||||
subprocess.run(
|
||||
["launchctl", "bootout", user_domain, str(plist_path)], check=False
|
||||
)
|
||||
typer.echo("Unloaded Memos service.")
|
||||
if processes:
|
||||
for process in processes:
|
||||
create_time = datetime.fromtimestamp(process.info['create_time']).strftime('%Y-%m-%d %H:%M:%S')
|
||||
running_time = str(timedelta(seconds=int(time.time() - process.info['create_time'])))
|
||||
typer.echo(f"{service.capitalize()} is running:")
|
||||
typer.echo(f" PID: {process.info['pid']}")
|
||||
typer.echo(f" Started at: {create_time}")
|
||||
typer.echo(f" Running for: {running_time}")
|
||||
else:
|
||||
typer.echo("Memos service was not running.")
|
||||
|
||||
plist_path.unlink()
|
||||
typer.echo("Removed plist file. Memos will no longer run at startup.")
|
||||
else:
|
||||
typer.echo("Plist file does not exist. Memos is not set to run at startup.")
|
||||
typer.echo(f"{service.capitalize()} is not running")
|
||||
typer.echo("---")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
55
memos/process_webp.py
Normal file
55
memos/process_webp.py
Normal file
@ -0,0 +1,55 @@
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
import piexif
|
||||
import json
|
||||
from memos.utils import write_image_metadata, get_image_metadata
|
||||
from tqdm import tqdm
|
||||
|
||||
def convert_webp_metadata(directory):
|
||||
webp_files = list(Path(directory).glob('**/*.webp'))
|
||||
|
||||
for webp_file in tqdm(webp_files, desc="Converting WebP metadata", unit="file"):
|
||||
try:
|
||||
# Try to get metadata using the new method
|
||||
new_metadata = get_image_metadata(webp_file)
|
||||
|
||||
if new_metadata:
|
||||
tqdm.write(f"Skipping {webp_file}: Already in new format")
|
||||
continue
|
||||
|
||||
# If new method fails, try to get old metadata
|
||||
img = Image.open(webp_file)
|
||||
old_metadata = img.info.get("exif", None)
|
||||
|
||||
if old_metadata is None:
|
||||
tqdm.write(f"Skipping {webp_file}: No metadata found")
|
||||
continue
|
||||
|
||||
if isinstance(old_metadata, bytes):
|
||||
try:
|
||||
old_metadata = old_metadata.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
tqdm.write(f"Skipping {webp_file}: Unable to decode metadata")
|
||||
continue
|
||||
|
||||
try:
|
||||
metadata = json.loads(old_metadata)
|
||||
except json.JSONDecodeError:
|
||||
tqdm.write(f"Skipping {webp_file}: Invalid metadata format")
|
||||
continue
|
||||
|
||||
# Convert to new format
|
||||
write_image_metadata(webp_file, metadata)
|
||||
tqdm.write(f"Converted metadata for {webp_file}")
|
||||
|
||||
except Exception as e:
|
||||
tqdm.write(f"Error processing {webp_file}: {str(e)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python convert_webp_metadata.py <directory>")
|
||||
sys.exit(1)
|
||||
|
||||
directory = sys.argv[1]
|
||||
convert_webp_metadata(directory)
|
19
memos/t.py
Normal file
19
memos/t.py
Normal file
@ -0,0 +1,19 @@
|
||||
import typer
|
||||
from rich import print
|
||||
|
||||
data = {
|
||||
"name": "Rick",
|
||||
"age": 42,
|
||||
"items": [{"name": "Portal Gun"}, {"name": "Plumbus"}],
|
||||
"active": True,
|
||||
"affiliation": None,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
print("Here's the data")
|
||||
print(data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
typer.run(main)
|
101
memos/watchfiles.py
Normal file
101
memos/watchfiles.py
Normal file
@ -0,0 +1,101 @@
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
import argparse
|
||||
from watchdog.observers import Observer
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
|
||||
# 定义图片文件扩展名
|
||||
IMAGE_EXTENSIONS = (".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp")
|
||||
|
||||
|
||||
class ImageHandler(FileSystemEventHandler):
|
||||
def __init__(self):
|
||||
self.last_modified = {}
|
||||
|
||||
def is_image_file(self, path):
|
||||
return path.lower().endswith(IMAGE_EXTENSIONS)
|
||||
|
||||
def is_temp_file(self, path):
|
||||
filename = os.path.basename(path)
|
||||
return (
|
||||
filename.startswith(".")
|
||||
or filename.startswith("tmp")
|
||||
or filename.startswith("temp")
|
||||
)
|
||||
|
||||
def handle_event(self, event):
|
||||
if (
|
||||
not event.is_directory
|
||||
and self.is_image_file(event.src_path)
|
||||
and not self.is_temp_file(event.src_path)
|
||||
):
|
||||
current_time = time.time()
|
||||
last_modified_time = self.last_modified.get(event.src_path, 0)
|
||||
if current_time - last_modified_time > 1: # 防止重复触发
|
||||
self.last_modified[event.src_path] = current_time
|
||||
return True
|
||||
return False
|
||||
|
||||
def on_modified(self, event):
|
||||
if self.handle_event(event):
|
||||
print(f"Image file modified: {event.src_path}")
|
||||
|
||||
def on_created(self, event):
|
||||
if self.handle_event(event):
|
||||
print(f"Image file created: {event.src_path}")
|
||||
|
||||
def on_deleted(self, event):
|
||||
if self.handle_event(event):
|
||||
print(f"Image file deleted: {event.src_path}")
|
||||
|
||||
|
||||
def watch_folders(folders, recursive):
|
||||
event_handler = ImageHandler()
|
||||
observer = Observer()
|
||||
|
||||
# 监听多个文件夹
|
||||
for folder in folders:
|
||||
observer.schedule(event_handler, folder, recursive=recursive)
|
||||
|
||||
observer.start()
|
||||
try:
|
||||
while True:
|
||||
time.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
observer.stop()
|
||||
observer.join()
|
||||
|
||||
|
||||
# main 函数保持不变
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Watch for image file changes in specified folders."
|
||||
)
|
||||
parser.add_argument(
|
||||
"folders",
|
||||
metavar="FOLDER",
|
||||
type=str,
|
||||
nargs="+",
|
||||
help="One or more folders to watch for image file changes.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--recursive",
|
||||
action="store_true",
|
||||
help="Watch folders recursively (may impact performance for large directories).",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 确认所有提供的目录都存在
|
||||
for folder in args.folders:
|
||||
if not os.path.isdir(folder):
|
||||
print(f"Error: {folder} is not a valid directory.")
|
||||
sys.exit(1)
|
||||
|
||||
watch_folders(args.folders, args.recursive)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
BIN
simple.dll
Normal file
BIN
simple.dll
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user