Skip to content

Commit 4497e63

Browse files
Added missing files to plugins RenameFile and FileMonitor (#497)
1 parent d76e2e2 commit 4497e63

File tree

15 files changed

+820
-7
lines changed

15 files changed

+820
-7
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# ModulesValidate (By David Maisonave aka Axter)
2+
# Description:
3+
# Checks if packages are installed, and optionally install packages if missing.
4+
# The below example usage code should be plave at the very top of the scource code before any other imports.
5+
# Example Usage:
6+
# import ModulesValidate
7+
# ModulesValidate.modulesInstalled(["watchdog", "schedule", "requests"])
8+
# Testing:
9+
# To test, uninstall packages via command line: pip uninstall -y watchdog schedule requests
10+
import sys, os, pathlib, platform, traceback
11+
# ToDo: Add logic to optionally pull package requirements from requirements.txt file.
12+
# Add logic to report error sys.exit(126) -- 126 (0x7E) ERROR_MOD_NOT_FOUND: The specified module could not be found.
13+
14+
def modulesInstalled(moduleNames, install=True, silent=False):
15+
retrnValue = True
16+
for moduleName in moduleNames:
17+
try: # Try Python 3.3 > way
18+
import importlib
19+
import importlib.util
20+
if moduleName in sys.modules:
21+
if not silent: print(f"{moduleName!r} already in sys.modules")
22+
elif isModuleInstalled(moduleName):
23+
if not silent: print(f"Module {moduleName!r} is available.")
24+
else:
25+
if install and (results:=installModule(moduleName)) > 0:
26+
if results == 1:
27+
print(f"Module {moduleName!r} has been installed")
28+
else:
29+
if not silent: print(f"Module {moduleName!r} is already installed")
30+
continue
31+
else:
32+
if install:
33+
print(f"Can't find the {moduleName!r} module")
34+
retrnValue = False
35+
except Exception as e:
36+
try:
37+
i = importlib.import_module(moduleName)
38+
except ImportError as e:
39+
if install and (results:=installModule(moduleName)) > 0:
40+
if results == 1:
41+
print(f"Module {moduleName!r} has been installed")
42+
else:
43+
if not silent: print(f"Module {moduleName!r} is already installed")
44+
continue
45+
else:
46+
if install:
47+
tb = traceback.format_exc()
48+
print(f"Can't find the {moduleName!r} module! Error: {e}\nTraceBack={tb}")
49+
retrnValue = False
50+
return retrnValue
51+
52+
def isModuleInstalled(moduleName):
53+
try:
54+
__import__(moduleName)
55+
return True
56+
except Exception as e:
57+
pass
58+
return False
59+
60+
def installModule(moduleName):
61+
try:
62+
if isLinux():
63+
# Note: Linux may first need : sudo apt install python3-pip
64+
# if error starts with "Command 'pip' not found"
65+
# or includes "No module named pip"
66+
results = os.popen(f"pip --disable-pip-version-check --version").read()
67+
if results.find("Command 'pip' not found") != -1 or results.find("No module named pip") != -1:
68+
results = os.popen(f"sudo apt install python3-pip").read()
69+
results = os.popen(f"pip --disable-pip-version-check --version").read()
70+
if results.find("Command 'pip' not found") != -1 or results.find("No module named pip") != -1:
71+
return -1
72+
if isFreeBSD():
73+
print("Warning: installModule may NOT work on freebsd")
74+
pipArg = " --disable-pip-version-check"
75+
if isDocker():
76+
pipArg += " --break-system-packages"
77+
results = os.popen(f"{sys.executable} -m pip install {moduleName}{pipArg}").read() # May need to be f"{sys.executable} -m pip install {moduleName}"
78+
results = results.strip("\n")
79+
if results.find("Requirement already satisfied:") > -1:
80+
return 2
81+
elif results.find("Successfully installed") > -1:
82+
return 1
83+
elif modulesInstalled(moduleNames=[moduleName], install=False):
84+
return 1
85+
except Exception as e:
86+
pass
87+
return 0
88+
89+
def installPackage(package): # Should delete this. It doesn't work consistently
90+
try:
91+
import pip
92+
if hasattr(pip, 'main'):
93+
pip.main(['install', package])
94+
else:
95+
pip._internal.main(['install', package])
96+
except Exception as e:
97+
return False
98+
return True
99+
100+
def isDocker():
101+
cgroup = pathlib.Path('/proc/self/cgroup')
102+
return pathlib.Path('/.dockerenv').is_file() or cgroup.is_file() and 'docker' in cgroup.read_text()
103+
104+
def isWindows():
105+
if any(platform.win32_ver()):
106+
return True
107+
return False
108+
109+
def isLinux():
110+
if platform.system().lower().startswith("linux"):
111+
return True
112+
return False
113+
114+
def isFreeBSD():
115+
if platform.system().lower().startswith("freebsd"):
116+
return True
117+
return False
118+
119+
def isMacOS():
120+
if sys.platform == "darwin":
121+
return True
122+
return False
123+
124+
def isWindows():
125+
if any(platform.win32_ver()):
126+
return True
127+
return False

plugins/FileMonitor/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# FileMonitor: Ver 1.0.3 (By David Maisonave)
1+
# FileMonitor: Ver 1.0.4 (By David Maisonave)
22

33
FileMonitor is a [Stash](https://github.com/stashapp/stash) plugin with the following two main features:
44

plugins/FileMonitor/StashPluginHelper.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# Sets CALLED_AS_STASH_PLUGIN to True if it's able to read from STDIN_READ
1818
from stashapi.stashapp import StashInterface
1919
from logging.handlers import RotatingFileHandler
20-
import re, inspect, sys, os, pathlib, logging, json, platform, subprocess, traceback, time
20+
import re, inspect, sys, os, pathlib, logging, json, platform, subprocess, traceback, time, socket
2121
import concurrent.futures
2222
from stashapi.stash_types import PhashDistance
2323
from enum import Enum, IntEnum
@@ -849,6 +849,26 @@ def renameFileNameInDB(self, fileId, oldName, newName, UpdateUsingIdOnly = False
849849
if 'rows_affected' in results and results['rows_affected'] == 1:
850850
return True
851851
return False
852+
853+
def pingGql(self, Gql,timeout=2, doTraceLog=False):
854+
try:
855+
hostAndPort = Gql.split(':')
856+
host = hostAndPort[1][2:]
857+
port = int(hostAndPort[2])
858+
if host == "localhost":
859+
host = "127.0.0.1"
860+
self.Debug(f"Checking connection Gql {Gql}; host {host}; port {port}.")
861+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
862+
s.settimeout(timeout)
863+
s.connect((host, port))
864+
return True
865+
except Exception as e:
866+
if doTraceLog:
867+
tb = traceback.format_exc()
868+
self.Error(f"pingGql failed for Stash GQL {Gql} Error: {e}\nTraceBack={tb}")
869+
else:
870+
self.Error(f"pingGql failed for Stash GQL {Gql}")
871+
return False
852872

853873
# This only works if filename has not changed. If file name has changed, call renameFileNameInDB first.
854874
def updateFileScene(self, fullFilePath):

plugins/FileMonitor/filemonitor.js

Lines changed: 191 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/FileMonitor/filemonitor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@
167167

168168
dockerStashes = {}
169169
for docker in stash.pluginConfig['dockers']:
170+
if stash.pingGql(docker['GQL']) == False:
171+
stash.Warn(f"Skipping monitoring Docker Stash {docker['GQL']} because ping failed.")
172+
continue
170173
stash.Log(f"Adding monitoring to Docker Stash {docker['GQL']}")
171174
dockerStashes[docker['GQL']] = StashPluginHelper(
172175
stash_url=docker['GQL'],

plugins/FileMonitor/filemonitor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: FileMonitor
22
description: Monitors the Stash library folders, and updates Stash if any changes occurs in the Stash library paths.
3-
version: 1.0.3
3+
version: 1.0.4
44
url: https://github.com/David-Maisonave/Axter-Stash/tree/main/plugins/FileMonitor
55
ui:
66
javascript:
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
##### This page was added starting on version 1.0.0 to keep track of newly added features between versions.
2+
23
### 1.0.0
4+
35
- Added Tools-UI option to get FileMonitor running status.
46
- Added Stash toolbar icon to get FileMonitor running status.
7+
58
### 1.0.1
9+
610
- Added Docker support.
11+
712
### 1.0.2
13+
814
- Added ability to monitor host file system for multiple Docker Stash installations.
15+
916
### 1.0.3
17+
1018
- Added start and stop FileMonitor button to Tools-UI FileMonitor Status
11-
- Fixed bug associated with starting FileMonitor service with no jobs waiting.
19+
- Fixed bug associated with starting FileMonitor service with no jobs waiting.
20+
21+
### 1.0.4
22+
23+
- Added ping Docker GQL check before attempting to monitor Stash Dockers
24+
- Uploaded missing filemonitor.js to CommunityScripts
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# ModulesValidate (By David Maisonave aka Axter)
2+
# Description:
3+
# Checks if packages are installed, and optionally install packages if missing.
4+
# The below example usage code should be plave at the very top of the scource code before any other imports.
5+
# Example Usage:
6+
# import ModulesValidate
7+
# ModulesValidate.modulesInstalled(["watchdog", "schedule", "requests"])
8+
# Testing:
9+
# To test, uninstall packages via command line: pip uninstall -y watchdog schedule requests
10+
import sys, os, pathlib, platform, traceback
11+
# ToDo: Add logic to optionally pull package requirements from requirements.txt file.
12+
# Add logic to report error sys.exit(126) -- 126 (0x7E) ERROR_MOD_NOT_FOUND: The specified module could not be found.
13+
14+
def modulesInstalled(moduleNames, install=True, silent=False):
15+
retrnValue = True
16+
for moduleName in moduleNames:
17+
try: # Try Python 3.3 > way
18+
import importlib
19+
import importlib.util
20+
if moduleName in sys.modules:
21+
if not silent: print(f"{moduleName!r} already in sys.modules")
22+
elif isModuleInstalled(moduleName):
23+
if not silent: print(f"Module {moduleName!r} is available.")
24+
else:
25+
if install and (results:=installModule(moduleName)) > 0:
26+
if results == 1:
27+
print(f"Module {moduleName!r} has been installed")
28+
else:
29+
if not silent: print(f"Module {moduleName!r} is already installed")
30+
continue
31+
else:
32+
if install:
33+
print(f"Can't find the {moduleName!r} module")
34+
retrnValue = False
35+
except Exception as e:
36+
try:
37+
i = importlib.import_module(moduleName)
38+
except ImportError as e:
39+
if install and (results:=installModule(moduleName)) > 0:
40+
if results == 1:
41+
print(f"Module {moduleName!r} has been installed")
42+
else:
43+
if not silent: print(f"Module {moduleName!r} is already installed")
44+
continue
45+
else:
46+
if install:
47+
tb = traceback.format_exc()
48+
print(f"Can't find the {moduleName!r} module! Error: {e}\nTraceBack={tb}")
49+
retrnValue = False
50+
return retrnValue
51+
52+
def isModuleInstalled(moduleName):
53+
try:
54+
__import__(moduleName)
55+
return True
56+
except Exception as e:
57+
pass
58+
return False
59+
60+
def installModule(moduleName):
61+
try:
62+
if isLinux():
63+
# Note: Linux may first need : sudo apt install python3-pip
64+
# if error starts with "Command 'pip' not found"
65+
# or includes "No module named pip"
66+
results = os.popen(f"pip --disable-pip-version-check --version").read()
67+
if results.find("Command 'pip' not found") != -1 or results.find("No module named pip") != -1:
68+
results = os.popen(f"sudo apt install python3-pip").read()
69+
results = os.popen(f"pip --disable-pip-version-check --version").read()
70+
if results.find("Command 'pip' not found") != -1 or results.find("No module named pip") != -1:
71+
return -1
72+
if isFreeBSD():
73+
print("Warning: installModule may NOT work on freebsd")
74+
pipArg = " --disable-pip-version-check"
75+
if isDocker():
76+
pipArg += " --break-system-packages"
77+
results = os.popen(f"{sys.executable} -m pip install {moduleName}{pipArg}").read() # May need to be f"{sys.executable} -m pip install {moduleName}"
78+
results = results.strip("\n")
79+
if results.find("Requirement already satisfied:") > -1:
80+
return 2
81+
elif results.find("Successfully installed") > -1:
82+
return 1
83+
elif modulesInstalled(moduleNames=[moduleName], install=False):
84+
return 1
85+
except Exception as e:
86+
pass
87+
return 0
88+
89+
def installPackage(package): # Should delete this. It doesn't work consistently
90+
try:
91+
import pip
92+
if hasattr(pip, 'main'):
93+
pip.main(['install', package])
94+
else:
95+
pip._internal.main(['install', package])
96+
except Exception as e:
97+
return False
98+
return True
99+
100+
def isDocker():
101+
cgroup = pathlib.Path('/proc/self/cgroup')
102+
return pathlib.Path('/.dockerenv').is_file() or cgroup.is_file() and 'docker' in cgroup.read_text()
103+
104+
def isWindows():
105+
if any(platform.win32_ver()):
106+
return True
107+
return False
108+
109+
def isLinux():
110+
if platform.system().lower().startswith("linux"):
111+
return True
112+
return False
113+
114+
def isFreeBSD():
115+
if platform.system().lower().startswith("freebsd"):
116+
return True
117+
return False
118+
119+
def isMacOS():
120+
if sys.platform == "darwin":
121+
return True
122+
return False
123+
124+
def isWindows():
125+
if any(platform.win32_ver()):
126+
return True
127+
return False

plugins/RenameFile/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# RenameFile: Ver 0.5.6 (By David Maisonave)
1+
# RenameFile: Ver 0.5.7 (By David Maisonave)
22

33
RenameFile is a [Stash](https://github.com/stashapp/stash) plugin. Starting version 0.5.5, user can add the current title to the title input field by clicking on the current title. Also, the Stash database gets updated directly instead of running a scan task as long as the database is version 68.
44

plugins/RenameFile/StashPluginHelper.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# Sets CALLED_AS_STASH_PLUGIN to True if it's able to read from STDIN_READ
1818
from stashapi.stashapp import StashInterface
1919
from logging.handlers import RotatingFileHandler
20-
import re, inspect, sys, os, pathlib, logging, json, platform, subprocess, traceback, time
20+
import re, inspect, sys, os, pathlib, logging, json, platform, subprocess, traceback, time, socket
2121
import concurrent.futures
2222
from stashapi.stash_types import PhashDistance
2323
from enum import Enum, IntEnum
@@ -849,6 +849,26 @@ def renameFileNameInDB(self, fileId, oldName, newName, UpdateUsingIdOnly = False
849849
if 'rows_affected' in results and results['rows_affected'] == 1:
850850
return True
851851
return False
852+
853+
def pingGql(self, Gql,timeout=2, doTraceLog=False):
854+
try:
855+
hostAndPort = Gql.split(':')
856+
host = hostAndPort[1][2:]
857+
port = int(hostAndPort[2])
858+
if host == "localhost":
859+
host = "127.0.0.1"
860+
self.Debug(f"Checking connection Gql {Gql}; host {host}; port {port}.")
861+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
862+
s.settimeout(timeout)
863+
s.connect((host, port))
864+
return True
865+
except Exception as e:
866+
if doTraceLog:
867+
tb = traceback.format_exc()
868+
self.Error(f"pingGql failed for Stash GQL {Gql} Error: {e}\nTraceBack={tb}")
869+
else:
870+
self.Error(f"pingGql failed for Stash GQL {Gql}")
871+
return False
852872

853873
# This only works if filename has not changed. If file name has changed, call renameFileNameInDB first.
854874
def updateFileScene(self, fullFilePath):

0 commit comments

Comments
 (0)