kapsikkum-unmanic – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3  
4 """
5 unmanic.settings.py
6  
7 Written by: Josh.5 <jsunnex@gmail.com>
8 Date: 16 Mar 2021, (7:14 PM)
9  
10 Copyright:
11 Copyright (C) Josh Sunnex - All Rights Reserved
12  
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19  
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22  
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
27 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
28 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
29 OR OTHER DEALINGS IN THE SOFTWARE.
30  
31 """
32 import json
33 import os
34 import sys
35  
36 from unmanic import config
37 from unmanic.libs.singleton import SingletonType
38  
39  
40 class PluginSettings(object):
41 """
42 A dictionary of settings accessible to the Plugin class and able
43 to be configured by users from within the Unmanic WebUI.
44  
45 """
46 settings = {}
47  
48 """
49 A dictionary of form settings used by Unmanic's WebUI to configure
50 the plugin's settings form.
51  
52 """
53 form_settings = {}
54  
55 """
56 A cached copy of settings as they are stored on disk.
57  
58 """
59 settings_configured = None
60  
61 """
62 The library ID that we are fetching settings for.
63  
64 """
65 library_id = None
66  
67 def __init__(self, *args, **kwargs):
68 self.library_id = kwargs.get('library_id')
69 # If the given library is not None, ensure that it is a number
70 if self.library_id:
71 try:
72 self.library_id = int(self.library_id)
73 except ValueError:
74 raise Exception("Library ID needs to be an integer. You have provided '{}'".format(self.library_id))
75  
76 def __get_plugin_settings_file(self, force_library_settings=False):
77 plugin_directory = self.get_plugin_directory()
78 profile_directory = self.get_profile_directory()
79 # Temp code to migrate settings to userdata
80 # TODO: Remove after initial release
81 if not os.path.exists(os.path.join(profile_directory, 'settings.json')):
82 if os.path.exists(os.path.join(plugin_directory, 'settings.json')):
83 import shutil
84 shutil.move(
85 os.path.join(plugin_directory, 'settings.json'),
86 os.path.join(profile_directory, 'settings.json')
87 )
88 # If provided with a library ID, then the settings file will be different
89 plugin_settings_file = os.path.join(profile_directory, 'settings.json')
90 if self.library_id:
91 plugin_settings_file = os.path.join(profile_directory, 'settings.{}.json'.format(self.library_id))
92 if not os.path.exists(plugin_settings_file) and not force_library_settings:
93 # If the library file does not yet exist, then resort to using the default settings file
94 plugin_settings_file = os.path.join(profile_directory, 'settings.json')
95 return plugin_settings_file
96  
97 def __export_configured_settings(self):
98 """
99 Write settings to settings file
100  
101 :return:
102 """
103 plugin_settings_file = self.__get_plugin_settings_file(force_library_settings=True)
104  
105 with open(plugin_settings_file, 'w') as f:
106 json.dump(self.settings_configured, f, indent=2)
107  
108 def __import_configured_settings(self):
109 """
110 Read settings from settings file
111  
112 :return:
113 """
114 plugin_settings_file = self.__get_plugin_settings_file()
115  
116 # Default the configured settings to the plugin defaults
117 # Loop over the self.settings object to clone the keys/values
118 self.settings_configured = {}
119 for key in self.settings:
120 self.settings_configured[key] = self.settings[key]
121  
122 # if the file does not yet exist, create it
123 if not os.path.exists(plugin_settings_file):
124 self.__export_configured_settings()
125  
126 # Read plugin settings from file
127 with open(plugin_settings_file) as infile:
128 plugin_settings = json.load(infile)
129  
130 # Loop over settings
131 for key in self.settings:
132 if key in plugin_settings:
133 self.settings_configured[key] = plugin_settings.get(key)
134  
135 def reset_settings_to_defaults(self):
136 """
137 Remove all currently configured settings by deleting the settings.json file
138  
139 :return:
140 """
141 plugin_settings_file = self.__get_plugin_settings_file()
142  
143 # If the settings file returned is the global settings file and this was called on a library config,
144 # do not reset the config.
145 if self.library_id is not None and os.path.basename(plugin_settings_file) == 'settings.json':
146 return False
147  
148 # if the file does not yet exist, create it
149 if os.path.exists(plugin_settings_file):
150 os.remove(plugin_settings_file)
151  
152 if not os.path.exists(plugin_settings_file):
153 return True
154 return False
155  
156 def get_plugin_directory(self):
157 """
158 Return the absolute path to the Plugin's directory.
159 This is where the Plugin is currently installed.
160  
161 :return:
162 """
163 return os.path.dirname(os.path.abspath(sys.modules[self.__class__.__module__].__file__))
164  
165 def get_profile_directory(self):
166 """
167 Return the absolute path to the Plugin's profile directory.
168 This is where where Plugin settings are saved and where all mutable data for the
169 Plugin should be stored.
170  
171 :return:
172 """
173 settings = config.Config()
174 userdata_path = settings.get_userdata_path()
175 plugin_directory = self.get_plugin_directory()
176 plugin_id = os.path.basename(plugin_directory)
177 profile_directory = os.path.join(userdata_path, plugin_id)
178 if not os.path.exists(profile_directory):
179 os.makedirs(profile_directory)
180 return profile_directory
181  
182 def get_form_settings(self):
183 """
184 Return the current form settings.
185  
186 :return:
187 """
188 return self.form_settings
189  
190 def get_setting(self, key=None):
191 """
192 Fetch a single configuration value, or, when passed "all" as the key argument,
193 return the full configuration dictionary.
194  
195 :param key:
196 :return:
197 """
198 # First import settings
199 try:
200 self.__import_configured_settings()
201 except json.decoder.JSONDecodeError:
202 # If the import fails, then it will resort to defaults.
203 # That is fine. Better than breaking the rest of the process
204 pass
205 except FileNotFoundError:
206 # If the settings file did not exist, then also resort to defaults.
207 pass
208  
209 if key is None:
210 return self.settings_configured
211 else:
212 return self.settings_configured.get(key)
213  
214 def set_setting(self, key, value):
215 """
216 Set a singe configuration value.
217 Used by the Unmanic WebUI to save user settings.
218 Settings are stored on disk in order to be persistent.
219  
220 :param key:
221 :param value:
222 :return:
223 """
224 # First import settings
225 try:
226 self.__import_configured_settings()
227 except json.decoder.JSONDecodeError:
228 # If the import fails, then it will resort to defaults.
229 # That is fine. Better than breaking the rest of the process
230 pass
231  
232 # Ensure plugin has this setting
233 if key not in self.settings:
234 return False
235  
236 # Set the configured value
237 self.settings_configured[key] = value
238  
239 # Export the settings again
240 self.__export_configured_settings()
241  
242 return True