mirror of
https://git.srhtnin.garden/sarah/SaraSortd.git
synced 2026-10-13 18:38:11 +02:00
Fixed most everything to work well enough. TODO: Add input folders, sorting, and output folders.
This commit is contained in:
1 parent
ef5b40ffef
commit
51ecfe53b5
4 files changed
+227
-126
No files matched your search
+31
-39
@@ -1,47 +1,39 @@
|
|||||||
Title = "SaraSortd Config"
|
Title = "SaraSortd Config"
|
||||||
|
SafeMode = 1
|
||||||
|
SilentMode = 0
|
||||||
|
CheckInput = 10
|
||||||
|
OutputDir = [ "Log",]
|
||||||
|
|
||||||
SafeMode = 1 # If SaraSortd should stop if an error with the config appears. 1 is stop, 0 is continue.
|
[Variables]
|
||||||
SilentMode = 0 # If SaraSortd should write stuff to the terminal as well.
|
NextNum = "*"
|
||||||
|
NextChar = "&"
|
||||||
[Variables] # Only use these in config files, not the actual file names themselves..
|
Parent = "@"
|
||||||
NextNum = "*" # The next available number. If 1 already exists, 2 will be used. Starts at 1.
|
OrgFileName = "~"
|
||||||
NextChar = "&" # The next available character. If A already exists, B will be used.
|
OrgFileType = "^"
|
||||||
|
Year = "[y]"
|
||||||
Parent = "@" # The name of the parent directory.
|
Month = "[m]"
|
||||||
|
Day = "[d]"
|
||||||
OrgFileName = "~" # The original name of the sorted file. If "blahblah.txt" gets sorted, "~" would be equal to "blahblah".
|
Hour = "[h]"
|
||||||
OrgFileType = "^" # The original file type of the sorted file. If "example.png" gets sorted, "^" would be equal to ".png".
|
Minute = "[n]"
|
||||||
|
Second = "[s]"
|
||||||
Year = "[y]" # The current year, E.G. "2026".
|
VarCall = "%%"
|
||||||
Month = "[m]" # The date of the current month, E.G. "03".
|
|
||||||
Day = "[d]" # The date of the current day, E.G. "27".
|
|
||||||
|
|
||||||
Hour = "[h]" # The current hour, E.G. "12".
|
|
||||||
Minute = "[n]" # The current minute, E.G. "44".
|
|
||||||
Second = "[s]" # The current second, E.G. "11".
|
|
||||||
|
|
||||||
VarCall = "%%" # The characters used at the start and end of variable calls. The first character is to the left; second is to the right.
|
|
||||||
# NOTE: If any parameters in the config uses just "%%", it gets a variable from the program itself, not from the config.
|
|
||||||
|
|
||||||
[DirectoryPaths]
|
[DirectoryPaths]
|
||||||
RootDir = "Unset" # Parent directory. Folder where all SaraSortd folders live.
|
RootDir = "/home/sarah/TESTDIR"
|
||||||
InputDir = ["%RootDir%"] # If files get put here, they'll be sorted.
|
InputDir = [ "%RootDir%",]
|
||||||
OutputDir = ["%RootDir%"] # Where sortted files go.
|
OutputDir = [ "%RootDir%/Output",]
|
||||||
LogDir = "%RootDir%/.Logs" # Where log files from SaraSortd go.
|
LogDir = "%RootDir%/.Logs"
|
||||||
FailedDir =".%RootDir%/Failed" # For files that failed to be sorted.
|
FailedDir = "%RootDir%/.Failed"
|
||||||
|
|
||||||
[Names]
|
[Names]
|
||||||
OutputFileName = "*_@^" # Name of sorted files.
|
LogFileName = "[y].[m].[d]._*"
|
||||||
LogFileName = "[y].[m].[d]_*" # Name of log files.
|
DirConfName = ".@Config"
|
||||||
ConfFileName = ".@Config" # Name of config files for directories.
|
|
||||||
|
|
||||||
[Log]
|
[Log]
|
||||||
All = "[h]:[n]:[s] | " # What to put at the start of all lines in Log file.
|
All = "[h]:[n]:[s] | "
|
||||||
|
Start = "Started: SaraSortd"
|
||||||
Start = "Started: SaraSortd" # When SaraSortd starts.
|
NotStart = "Error: Failed to start SaraSortd."
|
||||||
NotStart = "Start Failed: SaraSortd." # When SaraSortd fails to start for some reason.
|
Sorted = "Sorted: %% to %%."
|
||||||
|
ValueSet = "Set: %% to be %% in %%."
|
||||||
Sorted = "Sorted: ~^ to %SortDir%." # When a file gets sorted.
|
WrongType = "Error: %% is not a %%."
|
||||||
|
Unset = "Error: %% is not set."
|
||||||
Unset = "Error: %% is not set." # When a parameter in the config is not set. %% is the parameter that wasn't set.
|
|
||||||
Set = "Set: %% to %%." # When a previously unset parameter in the config is set. %% is the parameter that got set.
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Title = "Unset"
|
||||||
|
|
||||||
|
Files = [
|
||||||
|
{Pattern = "?", NewFileName = "~^", NextNum = 1, NextChar = "A"},
|
||||||
|
]
|
||||||
|
|
||||||
|
LastFile = "Unset"
|
||||||
|
ParentDir = "Unset"
|
||||||
@@ -1,6 +1,71 @@
|
|||||||
# SaraSortd
|
# SaraSortd
|
||||||
A python daemon that can automatically sort your files to your liking without using AI.
|
A python daemon that can automatically sort your files to your liking without using AI.
|
||||||
|
|
||||||
It's made by Sarah, hence the name. :3
|
It's made by Sarah, hence the name. :3
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
toml: Use ```pip install toml``` to install toml.
|
toml: Use ```pip install toml``` to install toml.
|
||||||
|
|
||||||
|
## Config explanation
|
||||||
|
|
||||||
|
### Global config (Config.toml)
|
||||||
|
|
||||||
|
Title = "SaraSortd Config" # NOTE: Do not change the title.
|
||||||
|
|
||||||
|
SafeMode = 1 # If SaraSortd should stop if an error with the config appears. 1 is stop, 0 is continue.
|
||||||
|
SilentMode = 0 # If SaraSortd should write stuff to the terminal as well.
|
||||||
|
|
||||||
|
CheckInput = 10 # How many seconds it takes for SaraSortd to check input directories for new files to sort.
|
||||||
|
|
||||||
|
[Variables] # Only use these in config files, not the actual file names themselves..
|
||||||
|
NextNum = "*" # The next available number. If 1 already exists, 2 will be used. Starts at 1.
|
||||||
|
NextChar = "&" # The next available character. If A already exists, B will be used.
|
||||||
|
|
||||||
|
Parent = "@" # The name of the parent directory.
|
||||||
|
|
||||||
|
OrgFileName = "~" # The original name of the sorted file. If "blahblah.txt" gets sorted, "~" would be equal to "blahblah".
|
||||||
|
OrgFileType = "^" # The original file type of the sorted file. If "example.png" gets sorted, "^" would be equal to ".png".
|
||||||
|
|
||||||
|
Year = "[y]" # The current year, E.G. "2026".
|
||||||
|
Month = "[m]" # The date of the current month, E.G. "03".
|
||||||
|
Day = "[d]" # The date of the current day, E.G. "27".
|
||||||
|
|
||||||
|
Hour = "[h]" # The current hour, E.G. "12".
|
||||||
|
Minute = "[n]" # The current minute, E.G. "44".
|
||||||
|
Second = "[s]" # The current second, E.G. "11".
|
||||||
|
|
||||||
|
VarCall = "%%" # The characters used at the start and end of variable calls. The first character is to the left; second is to the right. NOTE: If any parameters in the config uses just "%%", it gets a variable from the program itself, not from the config.
|
||||||
|
|
||||||
|
[DirectoryPaths]
|
||||||
|
RootDir = "/home/sarah/TESTDIR" # Parent directory. Directory where all SaraSortd directories live.
|
||||||
|
InputDir = ["%RootDir%"] # If files get put here, they'll be sorted.
|
||||||
|
OutputDir = ["%RootDir%/Output"] # Where sortted files go.
|
||||||
|
LogDir = "%RootDir%/.Logs" # Where log files from SaraSortd go.
|
||||||
|
FailedDir ="%RootDir%/.Failed" # For files that failed to be sorted.
|
||||||
|
|
||||||
|
[Names]
|
||||||
|
LogFileName = "[y].[m].[d]._*" # Name of log files.
|
||||||
|
DirConfName = ".@Config" # Name of config files for directories.
|
||||||
|
|
||||||
|
[Log]
|
||||||
|
All = "[h]:[n]:[s] | " # What to put at the start of all lines in Log file.
|
||||||
|
|
||||||
|
Start = "Started: SaraSortd" # When SaraSortd starts.
|
||||||
|
NotStart = "Error: Failed to start SaraSortd." # When SaraSortd fails to start for some reason.
|
||||||
|
|
||||||
|
Sorted = "Sorted: %% to %%." # When a file gets sorted.
|
||||||
|
ValueSet = "Set: %% to be %% in %%." # When a value in a config is set.
|
||||||
|
|
||||||
|
WrongType = "Error: %% is not a %%." # When a parameter in the config is of the wrong type. E.G. setting a text parameter to be a list.
|
||||||
|
Unset = "Error: %% is not set." # When a parameter in the config is not set. %% is the parameter that wasn't set.
|
||||||
|
|
||||||
|
### Directory config (DirConfig.toml)
|
||||||
|
|
||||||
|
Title = "Unset"
|
||||||
|
|
||||||
|
Files = [
|
||||||
|
{Pattern = "?", NewFileName = "~^", NextNum = 1, NextChar = "A"},
|
||||||
|
]
|
||||||
|
|
||||||
|
LastFile = "Unset"
|
||||||
|
ParentDir = "Unset"
|
||||||
+123
-87
@@ -1,4 +1,4 @@
|
|||||||
import toml, os, datetime, re
|
import toml, os, datetime, re, shutil
|
||||||
|
|
||||||
Conf = None
|
Conf = None
|
||||||
ConfVars = None
|
ConfVars = None
|
||||||
@@ -26,91 +26,7 @@ def LoadConf():
|
|||||||
ConfLog = Conf["Log"]
|
ConfLog = Conf["Log"]
|
||||||
|
|
||||||
|
|
||||||
def Error():
|
def CheckConf():
|
||||||
global Start
|
|
||||||
if (Conf["SafeMode"] == 1):
|
|
||||||
Start = False
|
|
||||||
|
|
||||||
|
|
||||||
def Speak(Text):
|
|
||||||
if (Conf["SilentMode"] != 1):
|
|
||||||
print(Text)
|
|
||||||
|
|
||||||
|
|
||||||
def GetConf(Parameter):
|
|
||||||
if Parameter in Conf:
|
|
||||||
return str(Conf[Parameter])
|
|
||||||
|
|
||||||
elif Parameter in ConfVars:
|
|
||||||
return str(ConfVars[Parameter])
|
|
||||||
|
|
||||||
elif Parameter in ConfDirs:
|
|
||||||
return str(ConfDirs[Parameter])
|
|
||||||
|
|
||||||
elif Parameter in ConfNames:
|
|
||||||
return str(ConfNames[Parameter])
|
|
||||||
|
|
||||||
elif Parameter in ConfLog:
|
|
||||||
return str(ConfLog[Parameter])
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def Parse(String = None, Var = None, OrgFile = None, OutputDir = None):
|
|
||||||
def Replacer(Match):
|
|
||||||
Content = Match.group(1)
|
|
||||||
|
|
||||||
if (Content == None or Content == ""):
|
|
||||||
if (Var != None):
|
|
||||||
return str(Var)
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
Value = GetConf(Content)
|
|
||||||
if (Value != None):
|
|
||||||
return Value
|
|
||||||
|
|
||||||
|
|
||||||
Now = datetime.datetime.now()
|
|
||||||
|
|
||||||
VarValues = {
|
|
||||||
ConfVars["NextNum"]: "NOT ADDED",
|
|
||||||
ConfVars["NextChar"]: "NOT ADDED",
|
|
||||||
ConfVars["Parent"]: "NOT ADDED",
|
|
||||||
ConfVars["OrgFileName"]: "NOT ADDED",
|
|
||||||
ConfVars["OrgFileType"]: "NOT ADDED",
|
|
||||||
ConfVars["Year"]: str(Now.year),
|
|
||||||
ConfVars["Month"]: str(Now.month),
|
|
||||||
ConfVars["Day"]: str(Now.day),
|
|
||||||
ConfVars["Hour"]: str(Now.hour),
|
|
||||||
ConfVars["Minute"]: str(Now.minute),
|
|
||||||
ConfVars["Second"]: str(Now.second),
|
|
||||||
ConfVars["VarCall"]: Var
|
|
||||||
}
|
|
||||||
|
|
||||||
for Key, Value in VarValues.items():
|
|
||||||
if Key in String and Value is not None:
|
|
||||||
String = String.replace(Key, Value)
|
|
||||||
|
|
||||||
String = re.sub(r"%([^%]*)%", Replacer, String)
|
|
||||||
|
|
||||||
return String
|
|
||||||
|
|
||||||
|
|
||||||
def Dir(Name):
|
|
||||||
os.makedirs(Name, exist_ok=True)
|
|
||||||
|
|
||||||
|
|
||||||
def LogWrite(Text):
|
|
||||||
if (ConfDirs["LogDir"] != None and ConfNames != "Unset"):
|
|
||||||
if (ConfNames["LogFileName"] != None and ConfNames["LogFileName"] != "Unset"):
|
|
||||||
Dir(Parse(ConfDirs["LogDir"]))
|
|
||||||
LogFile = f"{Parse(ConfDirs["LogDir"])}/{Parse(ConfNames["LogFileName"])}.log"
|
|
||||||
with open(LogFile, "w", encoding="utf-8") as File:
|
|
||||||
File.write(f"{Parse(ConfLog["All"])}{Text}\n")
|
|
||||||
|
|
||||||
|
|
||||||
def ConfCheck():
|
|
||||||
for Parameter, Value in ConfVars.items():
|
for Parameter, Value in ConfVars.items():
|
||||||
if (Value == None or Value == "Unset"):
|
if (Value == None or Value == "Unset"):
|
||||||
TextOutput = Parse(ConfLog["Unset"], Parameter)
|
TextOutput = Parse(ConfLog["Unset"], Parameter)
|
||||||
@@ -140,12 +56,132 @@ def ConfCheck():
|
|||||||
Error()
|
Error()
|
||||||
|
|
||||||
|
|
||||||
|
def GetConf(Parameter):
|
||||||
|
if Parameter in Conf:
|
||||||
|
return (Conf[Parameter])
|
||||||
|
|
||||||
|
for Key, Value in Conf.items():
|
||||||
|
if (isinstance(Value, dict)):
|
||||||
|
if (Parameter in Value):
|
||||||
|
return Value[Parameter]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def UpdateConf(Path, Parameter, Value, Append = False):
|
||||||
|
ConfData = toml.load(Path)
|
||||||
|
|
||||||
|
if (not Append):
|
||||||
|
ConfData[Parameter] = Value
|
||||||
|
|
||||||
|
else:
|
||||||
|
if (Parameter not in ConfData):
|
||||||
|
ConfData[Parameter] = []
|
||||||
|
|
||||||
|
elif (not isinstance(ConfData[Parameter], list)):
|
||||||
|
TextOutput = Parse(ConfLog["WrongType"], Parameter, "list")
|
||||||
|
LogWrite(TextOutput)
|
||||||
|
Speak(TextOutput)
|
||||||
|
|
||||||
|
if (Value not in ConfData[Parameter]):
|
||||||
|
ConfData[Parameter].append(Value)
|
||||||
|
|
||||||
|
with open(Path, 'w', encoding='utf-8') as File:
|
||||||
|
toml.dump(ConfData, File)
|
||||||
|
|
||||||
|
|
||||||
|
def Error():
|
||||||
|
global Start
|
||||||
|
if (Conf["SafeMode"] == 1):
|
||||||
|
Start = False
|
||||||
|
|
||||||
|
|
||||||
|
def Speak(Text):
|
||||||
|
if (Conf["SilentMode"] != 1):
|
||||||
|
print(Text)
|
||||||
|
|
||||||
|
|
||||||
|
def Parse(String = None, Var = None, Path = None):
|
||||||
|
def Replacer(Match):
|
||||||
|
Content = Match.group(1)
|
||||||
|
|
||||||
|
if (Content == None or Content == ""):
|
||||||
|
if (Var != None):
|
||||||
|
return str(Var)
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
Value = GetConf(Content)
|
||||||
|
if (Value != None):
|
||||||
|
return Value
|
||||||
|
|
||||||
|
|
||||||
|
Now = datetime.datetime.now()
|
||||||
|
|
||||||
|
VarValues = {
|
||||||
|
ConfVars["NextNum"]: "NOT ADDED",
|
||||||
|
ConfVars["NextChar"]: "NOT ADDED",
|
||||||
|
ConfVars["Parent"]: Var,
|
||||||
|
ConfVars["OrgFileName"]: Var,
|
||||||
|
ConfVars["OrgFileType"]: Var,
|
||||||
|
ConfVars["Year"]: str(Now.year),
|
||||||
|
ConfVars["Month"]: str(Now.month),
|
||||||
|
ConfVars["Day"]: str(Now.day),
|
||||||
|
ConfVars["Hour"]: str(Now.hour),
|
||||||
|
ConfVars["Minute"]: str(Now.minute),
|
||||||
|
ConfVars["Second"]: str(Now.second),
|
||||||
|
ConfVars["VarCall"]: Var
|
||||||
|
}
|
||||||
|
|
||||||
|
for Key, Value in VarValues.items():
|
||||||
|
if Key in String and Value is not None:
|
||||||
|
String = String.replace(Key, Value)
|
||||||
|
|
||||||
|
VarCall0 = re.escape(ConfVars["VarCall"][0])
|
||||||
|
VarCall1 = re.escape(ConfVars["VarCall"][1])
|
||||||
|
|
||||||
|
Pattern = f"{VarCall0}(.*?){VarCall1}"
|
||||||
|
|
||||||
|
String = re.sub(Pattern, Replacer, String)
|
||||||
|
return String
|
||||||
|
|
||||||
|
|
||||||
|
def Clone(Source, Destination, NewName):
|
||||||
|
shutil.copy(Source, Destination)
|
||||||
|
|
||||||
|
NewPath = f"{Destination}/{NewName}"
|
||||||
|
shutil.move(f"{Destination}/{Source}", NewPath)
|
||||||
|
|
||||||
|
|
||||||
|
def Dir(Path, Output = True, CopyConf = True):
|
||||||
|
ParentName = os.path.basename(os.path.dirname(Path))
|
||||||
|
os.makedirs(Path, exist_ok=True)
|
||||||
|
|
||||||
|
if (CopyConf):
|
||||||
|
Clone("DirConfig.toml", Path, f"{Parse(ConfNames["DirConfName"], ParentName)}.toml")
|
||||||
|
|
||||||
|
UpdateConf(f"{Path}/{Parse(ConfNames["DirConfName"], ParentName)}.toml", "ParentDir", ParentName)
|
||||||
|
UpdateConf(f"{Path}/{Parse(ConfNames["DirConfName"], ParentName)}.toml", "Title", f"{ParentName} Config")
|
||||||
|
|
||||||
|
if (Output):
|
||||||
|
UpdateConf("Config.toml", "OutputDir", Output, True)
|
||||||
|
|
||||||
|
|
||||||
|
def LogWrite(Text):
|
||||||
|
if (ConfDirs["LogDir"] != None and ConfNames != "Unset"):
|
||||||
|
if (ConfNames["LogFileName"] != None and ConfNames["LogFileName"] != "Unset"):
|
||||||
|
Dir(Parse(ConfDirs["LogDir"]), "Log")
|
||||||
|
LogFile = f"{Parse(ConfDirs["LogDir"])}/{Parse(ConfNames["LogFileName"])}.log"
|
||||||
|
with open(LogFile, "w", encoding="utf-8") as File:
|
||||||
|
File.write(f"{Parse(ConfLog["All"])}{Text}\n")
|
||||||
|
|
||||||
|
|
||||||
def Init():
|
def Init():
|
||||||
global Conf, ConfVars, ConfDirs, ConfNames, ConfLog
|
global Conf, ConfVars, ConfDirs, ConfNames, ConfLog
|
||||||
|
|
||||||
LoadConf()
|
LoadConf()
|
||||||
if (Conf != None):
|
if (Conf != None):
|
||||||
ConfCheck()
|
CheckConf()
|
||||||
|
|
||||||
if (Start):
|
if (Start):
|
||||||
TextOutput = Parse(ConfLog["Start"])
|
TextOutput = Parse(ConfLog["Start"])
|
||||||
|
|||||||
Reference in new issue
Block a user