| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  | __filename__ = "theme.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2024-01-21 19:01:20 +00:00
										 |  |  | __version__ = "1.5.0" | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							| 
									
										
										
										
											2021-09-10 16:14:50 +00:00
										 |  |  | __email__ = "bob@libreserver.org" | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2021-06-26 11:16:41 +00:00
										 |  |  | __module_group__ = "Web Interface" | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  | from utils import data_dir | 
					
						
							| 
									
										
										
										
											2024-04-10 12:36:17 +00:00
										 |  |  | from utils import string_ends_with | 
					
						
							| 
									
										
										
										
											2021-12-26 18:46:43 +00:00
										 |  |  | from utils import is_account_dir | 
					
						
							| 
									
										
										
										
											2021-12-26 15:13:34 +00:00
										 |  |  | from utils import load_json | 
					
						
							| 
									
										
										
										
											2021-12-26 14:47:21 +00:00
										 |  |  | from utils import save_json | 
					
						
							| 
									
										
										
										
											2021-12-26 14:26:16 +00:00
										 |  |  | from utils import get_image_extensions | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  | from utils import copytree | 
					
						
							| 
									
										
										
										
											2021-12-26 12:02:29 +00:00
										 |  |  | from utils import acct_dir | 
					
						
							| 
									
										
										
										
											2021-12-27 21:44:48 +00:00
										 |  |  | from utils import dangerous_svg | 
					
						
							| 
									
										
										
										
											2021-12-26 10:19:59 +00:00
										 |  |  | from utils import local_actor_url | 
					
						
							| 
									
										
										
										
											2022-02-27 11:13:11 +00:00
										 |  |  | from utils import remove_html | 
					
						
							| 
									
										
										
										
											2022-06-10 13:29:51 +00:00
										 |  |  | from utils import text_in_file | 
					
						
							| 
									
										
										
										
											2022-06-21 11:58:50 +00:00
										 |  |  | from utils import remove_eol | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  | from utils import language_right_to_left | 
					
						
							| 
									
										
										
										
											2020-05-28 21:30:40 +00:00
										 |  |  | from shutil import copyfile | 
					
						
							| 
									
										
										
										
											2021-05-28 21:39:34 +00:00
										 |  |  | from shutil import make_archive | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  | from shutil import unpack_archive | 
					
						
							| 
									
										
										
										
											2021-05-30 11:36:20 +00:00
										 |  |  | from shutil import rmtree | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | from content import dangerous_css | 
					
						
							| 
									
										
										
										
											2020-11-15 10:33:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def import_theme(base_dir: str, filename: str) -> bool: | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |     """Imports a theme
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not os.path.isfile(filename): | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     temp_theme_dir = base_dir + '/imports/files' | 
					
						
							|  |  |  |     if os.path.isdir(temp_theme_dir): | 
					
						
							|  |  |  |         rmtree(temp_theme_dir, ignore_errors=False, onerror=None) | 
					
						
							|  |  |  |     os.mkdir(temp_theme_dir) | 
					
						
							|  |  |  |     unpack_archive(filename, temp_theme_dir, 'zip') | 
					
						
							|  |  |  |     essential_theme_files = ('name.txt', 'theme.json') | 
					
						
							|  |  |  |     for theme_file in essential_theme_files: | 
					
						
							|  |  |  |         if not os.path.isfile(temp_theme_dir + '/' + theme_file): | 
					
						
							|  |  |  |             print('WARN: ' + theme_file + | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |                   ' missing from imported theme') | 
					
						
							|  |  |  |             return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     new_theme_name = None | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |     with open(temp_theme_dir + '/name.txt', 'r', | 
					
						
							|  |  |  |               encoding='utf-8') as fp_theme: | 
					
						
							| 
									
										
										
										
											2022-06-21 11:58:50 +00:00
										 |  |  |         new_theme_name1 = fp_theme.read() | 
					
						
							|  |  |  |         new_theme_name = remove_eol(new_theme_name1) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         if len(new_theme_name) > 20: | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |             print('WARN: Imported theme name is too long') | 
					
						
							|  |  |  |             return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         if len(new_theme_name) < 2: | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |             print('WARN: Imported theme name is too short') | 
					
						
							|  |  |  |             return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         new_theme_name = new_theme_name.lower() | 
					
						
							|  |  |  |         forbidden_chars = ( | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |             ' ', ';', '/', '\\', '?', '!', '#', '@', | 
					
						
							|  |  |  |             ':', '%', '&', '"', '+', '<', '>', '$' | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         for char in forbidden_chars: | 
					
						
							|  |  |  |             if char in new_theme_name: | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |                 print('WARN: theme name contains forbidden character') | 
					
						
							|  |  |  |                 return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if not new_theme_name: | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-05-30 11:06:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # if the theme name in the default themes list? | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     default_themes_filename = base_dir + '/defaultthemes.txt' | 
					
						
							|  |  |  |     if os.path.isfile(default_themes_filename): | 
					
						
							| 
									
										
										
										
											2022-06-10 13:29:51 +00:00
										 |  |  |         test_str = new_theme_name.title() + '\n' | 
					
						
							|  |  |  |         if text_in_file(test_str, default_themes_filename): | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             new_theme_name = new_theme_name + '2' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     theme_dir = base_dir + '/theme/' + new_theme_name | 
					
						
							|  |  |  |     if not os.path.isdir(theme_dir): | 
					
						
							|  |  |  |         os.mkdir(theme_dir) | 
					
						
							| 
									
										
										
										
											2024-02-19 18:48:55 +00:00
										 |  |  |     copytree(temp_theme_dir, theme_dir, False, None) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if os.path.isdir(temp_theme_dir): | 
					
						
							|  |  |  |         rmtree(temp_theme_dir, ignore_errors=False, onerror=None) | 
					
						
							|  |  |  |     if scan_themes_for_scripts(theme_dir): | 
					
						
							|  |  |  |         rmtree(theme_dir, ignore_errors=False, onerror=None) | 
					
						
							| 
									
										
										
										
											2021-09-13 18:50:02 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     return os.path.isfile(theme_dir + '/theme.json') | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def export_theme(base_dir: str, theme: str) -> bool: | 
					
						
							| 
									
										
										
										
											2021-05-28 21:39:34 +00:00
										 |  |  |     """Exports a theme as a zip file
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_dir = base_dir + '/theme/' + theme | 
					
						
							|  |  |  |     if not os.path.isfile(theme_dir + '/theme.json'): | 
					
						
							| 
									
										
										
										
											2021-05-28 21:39:34 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |     if not os.path.isdir(base_dir + '/exports'): | 
					
						
							|  |  |  |         os.mkdir(base_dir + '/exports') | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     export_filename = base_dir + '/exports/' + theme + '.zip' | 
					
						
							|  |  |  |     if os.path.isfile(export_filename): | 
					
						
							| 
									
										
										
										
											2021-09-05 10:17:43 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             os.remove(export_filename) | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |         except OSError: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             print('EX: export_theme unable to delete ' + str(export_filename)) | 
					
						
							| 
									
										
										
										
											2021-05-28 21:39:34 +00:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         make_archive(base_dir + '/exports/' + theme, 'zip', theme_dir) | 
					
						
							| 
									
										
										
										
											2021-05-28 21:39:34 +00:00
										 |  |  |     except BaseException: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |         print('EX: export_theme unable to archive ' + | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |               base_dir + '/exports/' + str(theme)) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     return os.path.isfile(export_filename) | 
					
						
							| 
									
										
										
										
											2021-05-28 21:39:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _get_theme_files() -> []: | 
					
						
							| 
									
										
										
										
											2021-02-07 15:22:06 +00:00
										 |  |  |     """Gets the list of theme style sheets
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-07-11 09:30:07 +00:00
										 |  |  |     return ('epicyon.css', 'login.css', 'follow.css', | 
					
						
							| 
									
										
										
										
											2020-07-25 22:12:59 +00:00
										 |  |  |             'suspended.css', 'calendar.css', 'blog.css', | 
					
						
							| 
									
										
										
										
											2021-02-25 12:42:05 +00:00
										 |  |  |             'options.css', 'search.css', 'links.css', | 
					
						
							| 
									
										
										
										
											2022-01-12 20:58:27 +00:00
										 |  |  |             'welcome.css', 'graph.css', 'podcast.css') | 
					
						
							| 
									
										
										
										
											2020-07-11 09:30:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def is_news_theme_name(base_dir: str, theme_name: str) -> bool: | 
					
						
							| 
									
										
										
										
											2021-02-27 11:44:50 +00:00
										 |  |  |     """Returns true if the given theme is a news instance
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_dir = base_dir + '/theme/' + theme_name | 
					
						
							|  |  |  |     if os.path.isfile(theme_dir + '/is_news_instance'): | 
					
						
							| 
									
										
										
										
											2021-02-27 11:44:50 +00:00
										 |  |  |         return True | 
					
						
							|  |  |  |     return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def get_themes_list(base_dir: str) -> []: | 
					
						
							| 
									
										
										
										
											2020-05-28 09:11:21 +00:00
										 |  |  |     """Returns the list of available themes
 | 
					
						
							|  |  |  |     Note that these should be capitalized, since they're | 
					
						
							|  |  |  |     also used to create the web interface dropdown list | 
					
						
							|  |  |  |     and to lookup function names | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-11-14 15:28:29 +00:00
										 |  |  |     themes = [] | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     for _, dirs, _ in os.walk(base_dir + '/theme'): | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |         for theme_name in dirs: | 
					
						
							|  |  |  |             if '~' not in theme_name and \ | 
					
						
							|  |  |  |                theme_name != 'icons' and theme_name != 'fonts': | 
					
						
							|  |  |  |                 themes.append(theme_name.title()) | 
					
						
							| 
									
										
										
										
											2020-11-14 15:37:20 +00:00
										 |  |  |         break | 
					
						
							| 
									
										
										
										
											2020-11-16 15:11:11 +00:00
										 |  |  |     themes.sort() | 
					
						
							| 
									
										
										
										
											2020-11-14 15:28:29 +00:00
										 |  |  |     print('Themes available: ' + str(themes)) | 
					
						
							|  |  |  |     return themes | 
					
						
							| 
									
										
										
										
											2020-05-28 09:11:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _copy_theme_help_files(base_dir: str, theme_name: str, | 
					
						
							|  |  |  |                            system_language: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-02-27 12:36:14 +00:00
										 |  |  |     """Copies any theme specific help files from the welcome subdirectory
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-25 23:03:28 +00:00
										 |  |  |     if not system_language: | 
					
						
							|  |  |  |         system_language = 'en' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_dir = base_dir + '/theme/' + theme_name + '/welcome' | 
					
						
							|  |  |  |     if not os.path.isdir(theme_dir): | 
					
						
							|  |  |  |         theme_dir = base_dir + '/defaultwelcome' | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     dir_str = data_dir(base_dir) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     for _, _, files in os.walk(theme_dir): | 
					
						
							|  |  |  |         for help_markdown_file in files: | 
					
						
							|  |  |  |             if not help_markdown_file.endswith('_' + system_language + '.md'): | 
					
						
							| 
									
										
										
										
											2021-02-27 14:39:35 +00:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             dest_help_markdown_file = \ | 
					
						
							|  |  |  |                 help_markdown_file.replace('_' + system_language + '.md', | 
					
						
							|  |  |  |                                            '.md') | 
					
						
							|  |  |  |             if dest_help_markdown_file in ('profile.md', 'final.md'): | 
					
						
							|  |  |  |                 dest_help_markdown_file = 'welcome_' + dest_help_markdown_file | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |             if os.path.isdir(dir_str): | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 copyfile(theme_dir + '/' + help_markdown_file, | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                          dir_str + '/' + dest_help_markdown_file) | 
					
						
							| 
									
										
										
										
											2021-02-27 12:36:14 +00:00
										 |  |  |         break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _set_theme_in_config(base_dir: str, name: str) -> bool: | 
					
						
							| 
									
										
										
										
											2021-02-07 15:22:06 +00:00
										 |  |  |     """Sets the theme with the given name within config.json
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-26 14:37:28 +00:00
										 |  |  |     config_filename = base_dir + '/config.json' | 
					
						
							|  |  |  |     if not os.path.isfile(config_filename): | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     config_json = load_json(config_filename, 0) | 
					
						
							|  |  |  |     if not config_json: | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     config_json['theme'] = name | 
					
						
							|  |  |  |     return save_json(config_json, config_filename) | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  | def _set_newswire_publish_as_icon(base_dir: str, use_icon: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2020-10-24 16:37:37 +00:00
										 |  |  |     """Shows the newswire publish action as an icon or a button
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-26 14:37:28 +00:00
										 |  |  |     config_filename = base_dir + '/config.json' | 
					
						
							|  |  |  |     if not os.path.isfile(config_filename): | 
					
						
							| 
									
										
										
										
											2020-10-24 16:37:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     config_json = load_json(config_filename, 0) | 
					
						
							|  |  |  |     if not config_json: | 
					
						
							| 
									
										
										
										
											2020-10-24 16:37:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     config_json['showPublishAsIcon'] = use_icon | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     return save_json(config_json, config_filename) | 
					
						
							| 
									
										
										
										
											2020-10-24 16:37:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  | def _set_icons_as_buttons(base_dir: str, use_buttons: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2020-10-25 20:38:01 +00:00
										 |  |  |     """Whether to show icons in the header (inbox, outbox, etc)
 | 
					
						
							|  |  |  |     as buttons | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-26 14:37:28 +00:00
										 |  |  |     config_filename = base_dir + '/config.json' | 
					
						
							|  |  |  |     if not os.path.isfile(config_filename): | 
					
						
							| 
									
										
										
										
											2020-10-25 20:38:01 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     config_json = load_json(config_filename, 0) | 
					
						
							|  |  |  |     if not config_json: | 
					
						
							| 
									
										
										
										
											2020-10-25 20:38:01 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     config_json['iconsAsButtons'] = use_buttons | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     return save_json(config_json, config_filename) | 
					
						
							| 
									
										
										
										
											2020-10-25 20:38:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  | def _set_rss_icon_at_top(base_dir: str, at_top: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2020-10-26 20:32:01 +00:00
										 |  |  |     """Whether to show RSS icon at the top of the timeline
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-26 14:37:28 +00:00
										 |  |  |     config_filename = base_dir + '/config.json' | 
					
						
							|  |  |  |     if not os.path.isfile(config_filename): | 
					
						
							| 
									
										
										
										
											2020-10-26 20:32:01 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     config_json = load_json(config_filename, 0) | 
					
						
							|  |  |  |     if not config_json: | 
					
						
							| 
									
										
										
										
											2020-10-26 20:32:01 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     config_json['rssIconAtTop'] = at_top | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     return save_json(config_json, config_filename) | 
					
						
							| 
									
										
										
										
											2020-10-26 20:32:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 21:33:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  | def _set_publish_button_at_top(base_dir: str, at_top: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2020-10-26 21:33:40 +00:00
										 |  |  |     """Whether to show the publish button above the title image
 | 
					
						
							|  |  |  |     in the newswire column | 
					
						
							| 
									
										
										
										
											2020-10-26 21:32:08 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-26 14:37:28 +00:00
										 |  |  |     config_filename = base_dir + '/config.json' | 
					
						
							|  |  |  |     if not os.path.isfile(config_filename): | 
					
						
							| 
									
										
										
										
											2020-10-26 21:32:08 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     config_json = load_json(config_filename, 0) | 
					
						
							|  |  |  |     if not config_json: | 
					
						
							| 
									
										
										
										
											2020-10-26 21:32:08 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     config_json['publishButtonAtTop'] = at_top | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     return save_json(config_json, config_filename) | 
					
						
							| 
									
										
										
										
											2020-10-26 21:32:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 20:32:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _set_full_width_timeline_button_header(base_dir: str, | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                            full_width: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2020-10-24 17:51:00 +00:00
										 |  |  |     """Shows the timeline button header containing inbox, outbox,
 | 
					
						
							|  |  |  |     calendar, etc as full width | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-26 14:37:28 +00:00
										 |  |  |     config_filename = base_dir + '/config.json' | 
					
						
							|  |  |  |     if not os.path.isfile(config_filename): | 
					
						
							| 
									
										
										
										
											2020-10-24 17:51:00 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     config_json = load_json(config_filename, 0) | 
					
						
							|  |  |  |     if not config_json: | 
					
						
							| 
									
										
										
										
											2020-10-24 17:51:00 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     config_json['fullWidthTlButtonHeader'] = full_width | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |     return save_json(config_json, config_filename) | 
					
						
							| 
									
										
										
										
											2020-10-24 17:51:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def get_theme(base_dir: str) -> str: | 
					
						
							| 
									
										
										
										
											2021-02-07 15:22:06 +00:00
										 |  |  |     """Gets the current theme name from config.json
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-26 14:37:28 +00:00
										 |  |  |     config_filename = base_dir + '/config.json' | 
					
						
							|  |  |  |     if os.path.isfile(config_filename): | 
					
						
							| 
									
										
										
										
											2022-01-01 21:43:34 +00:00
										 |  |  |         config_json = load_json(config_filename, 0) | 
					
						
							|  |  |  |         if config_json: | 
					
						
							|  |  |  |             if config_json.get('theme'): | 
					
						
							|  |  |  |                 return config_json['theme'] | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |     return 'default' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _remove_theme(base_dir: str): | 
					
						
							| 
									
										
										
										
											2021-02-07 15:22:06 +00:00
										 |  |  |     """Removes the current theme style sheets
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_files = _get_theme_files() | 
					
						
							|  |  |  |     for filename in theme_files: | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |         if not os.path.isfile(base_dir + '/' + filename): | 
					
						
							| 
									
										
										
										
											2021-10-29 18:48:15 +00:00
										 |  |  |             continue | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |             os.remove(base_dir + '/' + filename) | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |             print('EX: _remove_theme unable to delete ' + | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |                   base_dir + '/' + filename) | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  | def set_css_param(css: str, param: str, value: str) -> str: | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |     """Sets a CSS parameter to a given value
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-02-27 11:13:11 +00:00
										 |  |  |     value = remove_html(value) | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |     # is this just a simple string replacement? | 
					
						
							|  |  |  |     if ';' in param: | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  |         return css.replace(param, value) | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |     # color replacement | 
					
						
							|  |  |  |     if param.startswith('rgba('): | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  |         return css.replace(param, value) | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |     # if the parameter begins with * then don't prepend -- | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     once_only = False | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |     if param.startswith('*'): | 
					
						
							| 
									
										
										
										
											2020-09-14 12:52:22 +00:00
										 |  |  |         if param.startswith('**'): | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             once_only = True | 
					
						
							|  |  |  |             search_str = param.replace('**', '') + ':' | 
					
						
							| 
									
										
										
										
											2020-09-14 12:52:22 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             search_str = param.replace('*', '') + ':' | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         search_str = '--' + param + ':' | 
					
						
							|  |  |  |     if search_str not in css: | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |         return css | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if once_only: | 
					
						
							|  |  |  |         sstr = css.split(search_str, 1) | 
					
						
							| 
									
										
										
										
											2020-09-14 13:05:12 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         sstr = css.split(search_str) | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  |     newcss = '' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     for section_str in sstr: | 
					
						
							| 
									
										
										
										
											2020-11-16 20:13:48 +00:00
										 |  |  |         # handle font-family which is a variable | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         next_section = section_str | 
					
						
							|  |  |  |         if ';' in next_section: | 
					
						
							|  |  |  |             next_section = next_section.split(';')[0] + ';' | 
					
						
							|  |  |  |         if search_str == 'font-family:' and "var(--" in next_section: | 
					
						
							|  |  |  |             newcss += search_str + ' ' + section_str | 
					
						
							| 
									
										
										
										
											2020-11-16 20:13:48 +00:00
										 |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |         if not newcss: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             if section_str: | 
					
						
							|  |  |  |                 newcss = section_str | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  |                 newcss = ' ' | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             if ';' in section_str: | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  |                 newcss += \ | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                     search_str + ' ' + value + ';' + \ | 
					
						
							|  |  |  |                     section_str.split(';', 1)[1] | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 newcss += search_str + ' ' + section_str | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |     return newcss.strip() | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _set_theme_from_dict(base_dir: str, name: str, | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                          theme_params: {}, bg_params: {}, | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  |                          allow_local_network_access: bool, | 
					
						
							|  |  |  |                          system_language: str) -> None: | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |     """Uses a dictionary to set a theme
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:08:45 +00:00
										 |  |  |     if name: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |         _set_theme_in_config(base_dir, name) | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  |     rtl = language_right_to_left(system_language) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_files = _get_theme_files() | 
					
						
							|  |  |  |     for filename in theme_files: | 
					
						
							| 
									
										
										
										
											2020-11-14 13:18:11 +00:00
										 |  |  |         # check for custom css within the theme directory | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         template_filename = \ | 
					
						
							|  |  |  |             base_dir + '/theme/' + name + '/epicyon-' + filename | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  |         if filename == 'epicyon.css': | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             template_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |                 base_dir + '/theme/' + name + '/epicyon-profile.css' | 
					
						
							| 
									
										
										
										
											2020-11-14 13:18:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-15 11:07:12 +00:00
										 |  |  |         # Ensure that any custom CSS is mostly harmless. | 
					
						
							|  |  |  |         # If not then just use the defaults | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         if dangerous_css(template_filename, allow_local_network_access) or \ | 
					
						
							|  |  |  |            not os.path.isfile(template_filename): | 
					
						
							| 
									
										
										
										
											2020-11-14 13:18:11 +00:00
										 |  |  |             # use default css | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             template_filename = base_dir + '/epicyon-' + filename | 
					
						
							| 
									
										
										
										
											2020-11-14 13:18:11 +00:00
										 |  |  |             if filename == 'epicyon.css': | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 template_filename = base_dir + '/epicyon-profile.css' | 
					
						
							| 
									
										
										
										
											2020-11-14 13:18:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         if not os.path.isfile(template_filename): | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2020-11-14 13:18:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |         with open(template_filename, 'r', encoding='utf-8') as cssfile: | 
					
						
							| 
									
										
										
										
											2021-06-21 22:52:04 +00:00
										 |  |  |             css = cssfile.read() | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             for param_name, param_value in theme_params.items(): | 
					
						
							|  |  |  |                 if param_name == 'newswire-publish-icon': | 
					
						
							|  |  |  |                     if param_value.lower() == 'true': | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_newswire_publish_as_icon(base_dir, True) | 
					
						
							| 
									
										
										
										
											2020-11-14 19:21:11 +00:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_newswire_publish_as_icon(base_dir, False) | 
					
						
							| 
									
										
										
										
											2020-11-14 18:08:46 +00:00
										 |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 if param_name == 'full-width-timeline-buttons': | 
					
						
							|  |  |  |                     if param_value.lower() == 'true': | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_full_width_timeline_button_header(base_dir, True) | 
					
						
							| 
									
										
										
										
											2020-11-14 19:21:11 +00:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_full_width_timeline_button_header(base_dir, False) | 
					
						
							| 
									
										
										
										
											2020-11-14 18:08:46 +00:00
										 |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 if param_name == 'icons-as-buttons': | 
					
						
							|  |  |  |                     if param_value.lower() == 'true': | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_icons_as_buttons(base_dir, True) | 
					
						
							| 
									
										
										
										
											2020-11-14 19:21:11 +00:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_icons_as_buttons(base_dir, False) | 
					
						
							| 
									
										
										
										
											2020-11-14 18:08:46 +00:00
										 |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 if param_name == 'rss-icon-at-top': | 
					
						
							|  |  |  |                     if param_value.lower() == 'true': | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_rss_icon_at_top(base_dir, True) | 
					
						
							| 
									
										
										
										
											2020-11-14 19:21:11 +00:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_rss_icon_at_top(base_dir, False) | 
					
						
							| 
									
										
										
										
											2020-11-14 18:08:46 +00:00
										 |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 if param_name == 'publish-button-at-top': | 
					
						
							|  |  |  |                     if param_value.lower() == 'true': | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_publish_button_at_top(base_dir, True) | 
					
						
							| 
									
										
										
										
											2020-11-14 19:21:11 +00:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                         _set_publish_button_at_top(base_dir, False) | 
					
						
							| 
									
										
										
										
											2020-11-14 18:08:46 +00:00
										 |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |                 css = set_css_param(css, param_name, param_value) | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # set the text direction | 
					
						
							|  |  |  |             if rtl: | 
					
						
							|  |  |  |                 css = set_css_param(css, 'text-justify', 'right') | 
					
						
							|  |  |  |                 css = set_css_param(css, 'language-direction', 'rtl') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |             filename = base_dir + '/' + filename | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 with open(filename, 'w+', encoding='utf-8') as cssfile: | 
					
						
							|  |  |  |                     cssfile.write(css) | 
					
						
							|  |  |  |             except OSError: | 
					
						
							|  |  |  |                 print('EX: _set_theme_from_dict unable to write ' + filename) | 
					
						
							| 
									
										
										
										
											2019-11-23 13:04:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     screen_name = ( | 
					
						
							| 
									
										
										
										
											2021-07-05 16:46:32 +00:00
										 |  |  |         'login', 'follow', 'options', 'search', 'welcome' | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     for scr in screen_name: | 
					
						
							|  |  |  |         if bg_params.get(scr): | 
					
						
							| 
									
										
										
										
											2022-06-12 12:55:04 +00:00
										 |  |  |             _set_background_format(base_dir, scr, bg_params[scr]) | 
					
						
							| 
									
										
										
										
											2020-04-04 12:03:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-26 11:59:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-12 12:55:04 +00:00
										 |  |  | def _set_background_format(base_dir: str, | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                            background_type: str, extension: str) -> None: | 
					
						
							| 
									
										
										
										
											2020-07-25 16:25:04 +00:00
										 |  |  |     """Sets the background file extension
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-07-25 19:07:06 +00:00
										 |  |  |     if extension == 'jpg': | 
					
						
							| 
									
										
										
										
											2020-07-25 16:25:04 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     css_filename = base_dir + '/' + background_type + '.css' | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     if not os.path.isfile(css_filename): | 
					
						
							| 
									
										
										
										
											2020-07-26 11:59:48 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         with open(css_filename, 'r', encoding='utf-8') as cssfile: | 
					
						
							|  |  |  |             css = cssfile.read() | 
					
						
							|  |  |  |             css = css.replace('background.jpg', 'background.' + extension) | 
					
						
							|  |  |  |             with open(css_filename, 'w+', encoding='utf-8') as cssfile2: | 
					
						
							|  |  |  |                 cssfile2.write(css) | 
					
						
							|  |  |  |     except OSError as ex: | 
					
						
							|  |  |  |         print('EX: _set_background_format ' + css_filename + ' ' + str(ex)) | 
					
						
							| 
									
										
										
										
											2020-07-25 16:25:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def enable_grayscale(base_dir: str) -> None: | 
					
						
							| 
									
										
										
										
											2020-07-11 09:22:06 +00:00
										 |  |  |     """Enables grayscale for the current theme
 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:16:33 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_files = _get_theme_files() | 
					
						
							|  |  |  |     for filename in theme_files: | 
					
						
							|  |  |  |         template_filename = base_dir + '/' + filename | 
					
						
							|  |  |  |         if not os.path.isfile(template_filename): | 
					
						
							| 
									
										
										
										
											2020-07-10 18:16:33 +00:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             with open(template_filename, 'r', encoding='utf-8') as cssfile: | 
					
						
							|  |  |  |                 css = cssfile.read() | 
					
						
							|  |  |  |                 if 'grayscale' not in css: | 
					
						
							|  |  |  |                     css = \ | 
					
						
							|  |  |  |                         css.replace('body, html {', | 
					
						
							|  |  |  |                                     'body, html {\n' + | 
					
						
							|  |  |  |                                     '    filter: grayscale(100%);') | 
					
						
							|  |  |  |                     filename = base_dir + '/' + filename | 
					
						
							|  |  |  |                     with open(filename, 'w+', encoding='utf-8') as cssfile: | 
					
						
							|  |  |  |                         cssfile.write(css) | 
					
						
							|  |  |  |         except OSError as ex: | 
					
						
							|  |  |  |             print('EX: enable_grayscale unable to read ' + | 
					
						
							|  |  |  |                   template_filename + ' ' + str(ex)) | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     grayscale_filename = data_dir(base_dir) + '/.grayscale' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if not os.path.isfile(grayscale_filename): | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             with open(grayscale_filename, 'w+', encoding='utf-8') as grayfile: | 
					
						
							|  |  |  |                 grayfile.write(' ') | 
					
						
							|  |  |  |         except OSError as ex: | 
					
						
							|  |  |  |             print('EX: enable_grayscale unable to write ' + | 
					
						
							|  |  |  |                   grayscale_filename + ' ' + str(ex)) | 
					
						
							| 
									
										
										
										
											2020-07-11 09:22:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def disable_grayscale(base_dir: str) -> None: | 
					
						
							| 
									
										
										
										
											2020-07-11 09:22:06 +00:00
										 |  |  |     """Disables grayscale for the current theme
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_files = _get_theme_files() | 
					
						
							|  |  |  |     for filename in theme_files: | 
					
						
							|  |  |  |         template_filename = base_dir + '/' + filename | 
					
						
							|  |  |  |         if not os.path.isfile(template_filename): | 
					
						
							| 
									
										
										
										
											2020-07-11 09:22:06 +00:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             with open(template_filename, 'r', encoding='utf-8') as cssfile: | 
					
						
							|  |  |  |                 css = cssfile.read() | 
					
						
							|  |  |  |                 if 'grayscale' in css: | 
					
						
							|  |  |  |                     css = \ | 
					
						
							|  |  |  |                         css.replace('\n    filter: grayscale(100%);', '') | 
					
						
							|  |  |  |                     filename = base_dir + '/' + filename | 
					
						
							|  |  |  |                     with open(filename, 'w+', encoding='utf-8') as cssfile: | 
					
						
							|  |  |  |                         cssfile.write(css) | 
					
						
							|  |  |  |         except OSError as ex: | 
					
						
							|  |  |  |             print('EX: disable_grayscale unable to read ' + | 
					
						
							|  |  |  |                   template_filename + ' ' + str(ex)) | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     grayscale_filename = data_dir(base_dir) + '/.grayscale' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if os.path.isfile(grayscale_filename): | 
					
						
							| 
									
										
										
										
											2021-09-05 10:17:43 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             os.remove(grayscale_filename) | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |             print('EX: disable_grayscale unable to delete ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                   grayscale_filename) | 
					
						
							| 
									
										
										
										
											2020-07-10 18:16:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  | def _set_dyslexic_font(base_dir: str) -> bool: | 
					
						
							|  |  |  |     """sets the dyslexic font if needed
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     theme_files = _get_theme_files() | 
					
						
							|  |  |  |     for filename in theme_files: | 
					
						
							|  |  |  |         template_filename = base_dir + '/' + filename | 
					
						
							|  |  |  |         if not os.path.isfile(template_filename): | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |         with open(template_filename, 'r', encoding='utf-8') as cssfile: | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |             css = cssfile.read() | 
					
						
							|  |  |  |             css = \ | 
					
						
							|  |  |  |                 set_css_param(css, "*src", | 
					
						
							|  |  |  |                               "url('./fonts/OpenDyslexic-Regular.woff2" + | 
					
						
							|  |  |  |                               "') format('woff2')") | 
					
						
							|  |  |  |             css = set_css_param(css, "*font-family", "'OpenDyslexic'") | 
					
						
							|  |  |  |             filename = base_dir + '/' + filename | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 with open(filename, 'w+', encoding='utf-8') as cssfile: | 
					
						
							|  |  |  |                     cssfile.write(css) | 
					
						
							|  |  |  |             except OSError: | 
					
						
							|  |  |  |                 print('EX: _set_dyslexic_font unable to write ' + filename) | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |     return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _set_custom_font(base_dir: str): | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |     """Uses a dictionary to set a theme
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     custom_font_ext = None | 
					
						
							|  |  |  |     custom_font_type = None | 
					
						
							|  |  |  |     font_extension = { | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |         'woff': 'woff', | 
					
						
							|  |  |  |         'woff2': 'woff2', | 
					
						
							|  |  |  |         'otf': 'opentype', | 
					
						
							|  |  |  |         'ttf': 'truetype' | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     for ext, ext_type in font_extension.items(): | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |         filename = base_dir + '/fonts/custom.' + ext | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |         if os.path.isfile(filename): | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             custom_font_ext = ext | 
					
						
							|  |  |  |             custom_font_type = ext_type | 
					
						
							|  |  |  |     if not custom_font_ext: | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_files = _get_theme_files() | 
					
						
							|  |  |  |     for filename in theme_files: | 
					
						
							|  |  |  |         template_filename = base_dir + '/' + filename | 
					
						
							|  |  |  |         if not os.path.isfile(template_filename): | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |         with open(template_filename, 'r', encoding='utf-8') as cssfile: | 
					
						
							| 
									
										
										
										
											2021-06-21 22:52:04 +00:00
										 |  |  |             css = cssfile.read() | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |             css = \ | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |                 set_css_param(css, "*src", | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                               "url('./fonts/custom." + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                               custom_font_ext + | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                               "') format('" + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                               custom_font_type + "')") | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |             css = set_css_param(css, "*font-family", "'CustomFont'") | 
					
						
							| 
									
										
										
										
											2022-02-27 14:28:03 +00:00
										 |  |  |             css = set_css_param(css, "header-font", "'CustomFont'") | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |             filename = base_dir + '/' + filename | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 with open(filename, 'w+', encoding='utf-8') as cssfile: | 
					
						
							|  |  |  |                     cssfile.write(css) | 
					
						
							|  |  |  |             except OSError: | 
					
						
							|  |  |  |                 print('EX: _set_custom_font unable to write ' + filename) | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def set_theme_from_designer(base_dir: str, theme_name: str, domain: str, | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                             theme_params: {}, | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                             allow_local_network_access: bool, | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |                             system_language: str, | 
					
						
							|  |  |  |                             dyslexic_font: bool): | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     custom_theme_filename = data_dir(base_dir) + '/theme.json' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     save_json(theme_params, custom_theme_filename) | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     set_theme(base_dir, theme_name, domain, | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |               allow_local_network_access, system_language, | 
					
						
							| 
									
										
										
										
											2022-04-05 11:10:08 +00:00
										 |  |  |               dyslexic_font, False) | 
					
						
							| 
									
										
										
										
											2021-12-05 12:52:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-12 12:55:04 +00:00
										 |  |  | def reset_theme_designer_settings(base_dir: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-12-05 12:52:59 +00:00
										 |  |  |     """Resets the theme designer settings
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     custom_variables_file = data_dir(base_dir) + '/theme.json' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if os.path.isfile(custom_variables_file): | 
					
						
							| 
									
										
										
										
											2021-12-05 12:52:59 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             os.remove(custom_variables_file) | 
					
						
							| 
									
										
										
										
											2022-08-29 09:48:39 +00:00
										 |  |  |             print('Theme designer settings were reset') | 
					
						
							| 
									
										
										
										
											2021-12-05 12:52:59 +00:00
										 |  |  |         except OSError: | 
					
						
							|  |  |  |             print('EX: unable to remove theme designer settings on reset') | 
					
						
							| 
									
										
										
										
											2020-11-14 17:34:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _read_variables_file(base_dir: str, theme_name: str, | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                          variables_file: str, | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  |                          allow_local_network_access: bool, | 
					
						
							|  |  |  |                          system_language: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-12-04 19:39:00 +00:00
										 |  |  |     """Reads variables from a file in the theme directory
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     theme_params = load_json(variables_file, 0) | 
					
						
							|  |  |  |     if not theme_params: | 
					
						
							| 
									
										
										
										
											2021-12-04 19:39:00 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2021-12-05 11:03:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # set custom theme parameters | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     custom_variables_file = data_dir(base_dir) + '/theme.json' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if os.path.isfile(custom_variables_file): | 
					
						
							|  |  |  |         custom_theme_params = load_json(custom_variables_file, 0) | 
					
						
							|  |  |  |         if custom_theme_params: | 
					
						
							|  |  |  |             for variable_name, value in custom_theme_params.items(): | 
					
						
							|  |  |  |                 theme_params[variable_name] = value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bg_params = { | 
					
						
							| 
									
										
										
										
											2021-12-05 11:03:25 +00:00
										 |  |  |         "login": "jpg", | 
					
						
							|  |  |  |         "follow": "jpg", | 
					
						
							|  |  |  |         "options": "jpg", | 
					
						
							|  |  |  |         "search": "jpg" | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     _set_theme_from_dict(base_dir, theme_name, theme_params, bg_params, | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  |                          allow_local_network_access, system_language) | 
					
						
							| 
									
										
										
										
											2021-12-04 19:39:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  | def _set_theme_default(base_dir: str, allow_local_network_access: bool, | 
					
						
							|  |  |  |                        system_language: str): | 
					
						
							| 
									
										
										
										
											2020-07-26 11:45:09 +00:00
										 |  |  |     name = 'default' | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     _remove_theme(base_dir) | 
					
						
							|  |  |  |     _set_theme_in_config(base_dir, name) | 
					
						
							| 
									
										
										
										
											2022-04-05 11:29:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     variables_file = base_dir + '/theme/' + name + '/theme.json' | 
					
						
							|  |  |  |     if os.path.isfile(variables_file): | 
					
						
							|  |  |  |         _read_variables_file(base_dir, name, variables_file, | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  |                              allow_local_network_access, | 
					
						
							|  |  |  |                              system_language) | 
					
						
							| 
									
										
										
										
											2022-04-05 11:29:06 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         bg_params = { | 
					
						
							|  |  |  |             "login": "jpg", | 
					
						
							|  |  |  |             "follow": "jpg", | 
					
						
							|  |  |  |             "options": "jpg", | 
					
						
							|  |  |  |             "search": "jpg" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         theme_params = { | 
					
						
							|  |  |  |             "newswire-publish-icon": True, | 
					
						
							|  |  |  |             "full-width-timeline-buttons": False, | 
					
						
							|  |  |  |             "icons-as-buttons": False, | 
					
						
							|  |  |  |             "rss-icon-at-top": True, | 
					
						
							|  |  |  |             "publish-button-at-top": False, | 
					
						
							|  |  |  |             "banner-height": "20vh", | 
					
						
							|  |  |  |             "banner-height-mobile": "10vh", | 
					
						
							|  |  |  |             "search-banner-height-mobile": "15vh" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         _set_theme_from_dict(base_dir, name, theme_params, bg_params, | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  |                              allow_local_network_access, | 
					
						
							|  |  |  |                              system_language) | 
					
						
							| 
									
										
										
										
											2020-05-29 10:00:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _set_theme_fonts(base_dir: str, theme_name: str) -> None: | 
					
						
							| 
									
										
										
										
											2020-11-15 09:55:49 +00:00
										 |  |  |     """Adds custom theme fonts
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |     theme_name_lower = theme_name.lower() | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     fonts_dir = base_dir + '/fonts' | 
					
						
							|  |  |  |     theme_fonts_dir = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |         base_dir + '/theme/' + theme_name_lower + '/fonts' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if not os.path.isdir(theme_fonts_dir): | 
					
						
							| 
									
										
										
										
											2020-11-15 09:55:49 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     for _, _, files in os.walk(theme_fonts_dir): | 
					
						
							| 
									
										
										
										
											2020-11-15 09:55:49 +00:00
										 |  |  |         for filename in files: | 
					
						
							| 
									
										
										
										
											2024-04-10 12:36:17 +00:00
										 |  |  |             if string_ends_with(filename, ('.woff2', '.woff', '.ttf', '.otf')): | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 dest_filename = fonts_dir + '/' + filename | 
					
						
							|  |  |  |                 if os.path.isfile(dest_filename): | 
					
						
							| 
									
										
										
										
											2020-11-15 09:55:49 +00:00
										 |  |  |                     # font already exists in the destination location | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 copyfile(theme_fonts_dir + '/' + filename, | 
					
						
							|  |  |  |                          dest_filename) | 
					
						
							| 
									
										
										
										
											2020-11-15 09:55:49 +00:00
										 |  |  |         break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def get_text_mode_banner(base_dir: str) -> str: | 
					
						
							| 
									
										
										
										
											2021-02-05 19:50:09 +00:00
										 |  |  |     """Returns the banner used for shell browsers, like Lynx
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     text_mode_banner_filename = data_dir(base_dir) + '/banner.txt' | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     if os.path.isfile(text_mode_banner_filename): | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |         with open(text_mode_banner_filename, 'r', | 
					
						
							|  |  |  |                   encoding='utf-8') as fp_text: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             banner_str = fp_text.read() | 
					
						
							|  |  |  |             if banner_str: | 
					
						
							|  |  |  |                 return banner_str.replace('\n', '<br>') | 
					
						
							| 
									
										
										
										
											2021-02-05 19:50:09 +00:00
										 |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def get_text_mode_logo(base_dir: str) -> str: | 
					
						
							| 
									
										
										
										
											2021-02-06 14:30:18 +00:00
										 |  |  |     """Returns the login screen logo used for shell browsers, like Lynx
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     text_mode_logo_filename = data_dir(base_dir) + '/logo.txt' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if not os.path.isfile(text_mode_logo_filename): | 
					
						
							|  |  |  |         text_mode_logo_filename = base_dir + '/img/logo.txt' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |     with open(text_mode_logo_filename, 'r', encoding='utf-8') as fp_text: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         logo_str = fp_text.read() | 
					
						
							|  |  |  |         if logo_str: | 
					
						
							|  |  |  |             return logo_str.replace('\n', '<br>') | 
					
						
							| 
									
										
										
										
											2021-02-06 14:30:18 +00:00
										 |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _set_text_mode_theme(base_dir: str, name: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-02-07 15:32:15 +00:00
										 |  |  |     # set the text mode logo which appears on the login screen | 
					
						
							|  |  |  |     # in browsers such as Lynx | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     text_mode_logo_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |         base_dir + '/theme/' + name + '/logo.txt' | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     dir_str = data_dir(base_dir) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if os.path.isfile(text_mode_logo_filename): | 
					
						
							| 
									
										
										
										
											2021-02-06 18:51:36 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |             copyfile(text_mode_logo_filename, dir_str + '/logo.txt') | 
					
						
							| 
									
										
										
										
											2021-11-25 22:22:54 +00:00
										 |  |  |         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |             print('EX: _set_text_mode_theme unable to copy ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                   text_mode_logo_filename + ' ' + | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                   dir_str + '/logo.txt') | 
					
						
							| 
									
										
										
										
											2021-02-06 18:51:36 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |         dir_str = data_dir(base_dir) | 
					
						
							| 
									
										
										
										
											2021-02-06 18:51:36 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |             copyfile(base_dir + '/img/logo.txt', dir_str + '/logo.txt') | 
					
						
							| 
									
										
										
										
											2021-11-25 22:22:54 +00:00
										 |  |  |         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |             print('EX: _set_text_mode_theme unable to copy ' + | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                   base_dir + '/img/logo.txt ' + dir_str + '/logo.txt') | 
					
						
							| 
									
										
										
										
											2021-02-06 18:51:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 15:32:15 +00:00
										 |  |  |     # set the text mode banner which appears in browsers such as Lynx | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     text_mode_banner_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |         base_dir + '/theme/' + name + '/banner.txt' | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     if os.path.isfile(dir_str + '/banner.txt'): | 
					
						
							| 
									
										
										
										
											2021-09-05 10:17:43 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |             os.remove(dir_str + '/banner.txt') | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |             print('EX: _set_text_mode_theme unable to delete ' + | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                   dir_str + '/banner.txt') | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     if os.path.isfile(text_mode_banner_filename): | 
					
						
							| 
									
										
										
										
											2021-02-05 19:39:21 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |             copyfile(text_mode_banner_filename, dir_str + '/banner.txt') | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |             print('EX: _set_text_mode_theme unable to copy ' + | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |                   text_mode_banner_filename + ' ' + | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                   dir_str + '/banner.txt') | 
					
						
							| 
									
										
										
										
											2021-02-05 19:39:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 15:32:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _set_theme_images(base_dir: str, name: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-02-07 15:32:15 +00:00
										 |  |  |     """Changes the profile background image
 | 
					
						
							|  |  |  |     and banner to the defaults | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |     theme_name_lower = name.lower() | 
					
						
							| 
									
										
										
										
											2021-02-07 15:32:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     profile_image_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |         base_dir + '/theme/' + theme_name_lower + '/image.png' | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     banner_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |         base_dir + '/theme/' + theme_name_lower + '/banner.png' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     search_banner_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |         base_dir + '/theme/' + theme_name_lower + '/search_banner.png' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     left_col_image_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |         base_dir + '/theme/' + theme_name_lower + '/left_col_image.png' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     right_col_image_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |         base_dir + '/theme/' + theme_name_lower + '/right_col_image.png' | 
					
						
							| 
									
										
										
										
											2021-02-07 15:32:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     _set_text_mode_theme(base_dir, theme_name_lower) | 
					
						
							| 
									
										
										
										
											2021-02-07 15:32:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     background_names = ('login', 'shares', 'delete', 'follow', | 
					
						
							|  |  |  |                         'options', 'block', 'search', 'calendar', | 
					
						
							|  |  |  |                         'welcome') | 
					
						
							| 
									
										
										
										
											2021-12-26 14:26:16 +00:00
										 |  |  |     extensions = get_image_extensions() | 
					
						
							| 
									
										
										
										
											2020-07-25 14:03:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     dir_str = data_dir(base_dir) | 
					
						
							|  |  |  |     for _, dirs, _ in os.walk(dir_str): | 
					
						
							| 
									
										
										
										
											2020-07-25 09:55:11 +00:00
										 |  |  |         for acct in dirs: | 
					
						
							| 
									
										
										
										
											2021-12-26 18:46:43 +00:00
										 |  |  |             if not is_account_dir(acct): | 
					
						
							| 
									
										
										
										
											2020-07-25 09:55:11 +00:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |             account_dir = os.path.join(dir_str, acct) | 
					
						
							| 
									
										
										
										
											2020-07-25 09:55:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             for background_type in background_names: | 
					
						
							| 
									
										
										
										
											2020-07-25 16:12:14 +00:00
										 |  |  |                 for ext in extensions: | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |                     if theme_name_lower == 'default': | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                         background_image_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |                             base_dir + '/theme/default/' + \ | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                             background_type + '_background.' + ext | 
					
						
							| 
									
										
										
										
											2020-07-25 16:12:14 +00:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                         background_image_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |                             base_dir + '/theme/' + theme_name_lower + '/' + \ | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                             background_type + '_background' + '.' + ext | 
					
						
							| 
									
										
										
										
											2020-07-25 16:12:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                     if os.path.isfile(background_image_filename): | 
					
						
							| 
									
										
										
										
											2020-07-25 16:12:14 +00:00
										 |  |  |                         try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                             copyfile(background_image_filename, | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                                      dir_str + '/' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                      background_type + '-background.' + ext) | 
					
						
							| 
									
										
										
										
											2020-07-25 17:56:06 +00:00
										 |  |  |                             continue | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |                         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                             print('EX: _set_theme_images unable to copy ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                   background_image_filename) | 
					
						
							| 
									
										
										
										
											2020-07-25 16:12:14 +00:00
										 |  |  |                     # background image was not found | 
					
						
							|  |  |  |                     # so remove any existing file | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                     if os.path.isfile(dir_str + '/' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                       background_type + '-background.' + ext): | 
					
						
							| 
									
										
										
										
											2020-07-25 16:12:14 +00:00
										 |  |  |                         try: | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                             os.remove(dir_str + '/' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                       background_type + '-background.' + ext) | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |                         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                             print('EX: _set_theme_images unable to delete ' + | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |                                   dir_str + '/' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                   background_type + '-background.' + ext) | 
					
						
							| 
									
										
										
										
											2020-07-25 10:03:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             if os.path.isfile(profile_image_filename) and \ | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |                os.path.isfile(banner_filename): | 
					
						
							| 
									
										
										
										
											2020-05-28 21:39:41 +00:00
										 |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                     copyfile(profile_image_filename, | 
					
						
							|  |  |  |                              account_dir + '/image.png') | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |                 except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                     print('EX: _set_theme_images unable to copy ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                           profile_image_filename) | 
					
						
							| 
									
										
										
										
											2020-06-10 15:09:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |                     copyfile(banner_filename, | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                              account_dir + '/banner.png') | 
					
						
							| 
									
										
										
										
											2021-11-25 22:22:54 +00:00
										 |  |  |                 except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                     print('EX: _set_theme_images unable to copy ' + | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |                           banner_filename) | 
					
						
							| 
									
										
										
										
											2020-05-28 21:39:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 15:09:14 +00:00
										 |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                     if os.path.isfile(search_banner_filename): | 
					
						
							|  |  |  |                         copyfile(search_banner_filename, | 
					
						
							|  |  |  |                                  account_dir + '/search_banner.png') | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |                 except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                     print('EX: _set_theme_images unable to copy ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                           search_banner_filename) | 
					
						
							| 
									
										
										
										
											2020-06-10 15:09:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-03 10:09:21 +00:00
										 |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                     if os.path.isfile(left_col_image_filename): | 
					
						
							|  |  |  |                         copyfile(left_col_image_filename, | 
					
						
							|  |  |  |                                  account_dir + '/left_col_image.png') | 
					
						
							|  |  |  |                     elif os.path.isfile(account_dir + | 
					
						
							| 
									
										
										
										
											2021-10-29 18:48:15 +00:00
										 |  |  |                                         '/left_col_image.png'): | 
					
						
							|  |  |  |                         try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                             os.remove(account_dir + '/left_col_image.png') | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |                         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                             print('EX: _set_theme_images unable to delete ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                   account_dir + '/left_col_image.png') | 
					
						
							| 
									
										
										
										
											2021-11-25 22:22:54 +00:00
										 |  |  |                 except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                     print('EX: _set_theme_images unable to copy ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                           left_col_image_filename) | 
					
						
							| 
									
										
										
										
											2020-10-03 10:09:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                     if os.path.isfile(right_col_image_filename): | 
					
						
							|  |  |  |                         copyfile(right_col_image_filename, | 
					
						
							|  |  |  |                                  account_dir + '/right_col_image.png') | 
					
						
							| 
									
										
										
										
											2020-10-03 10:11:26 +00:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                         if os.path.isfile(account_dir + | 
					
						
							| 
									
										
										
										
											2020-10-03 10:11:26 +00:00
										 |  |  |                                           '/right_col_image.png'): | 
					
						
							| 
									
										
										
										
											2021-09-05 10:17:43 +00:00
										 |  |  |                             try: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                 os.remove(account_dir + '/right_col_image.png') | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |                             except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                                 print('EX: _set_theme_images ' + | 
					
						
							|  |  |  |                                       'unable to delete ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                                       account_dir + '/right_col_image.png') | 
					
						
							| 
									
										
										
										
											2021-11-25 22:22:54 +00:00
										 |  |  |                 except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                     print('EX: _set_theme_images unable to copy ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                           right_col_image_filename) | 
					
						
							| 
									
										
										
										
											2020-12-13 22:13:45 +00:00
										 |  |  |         break | 
					
						
							| 
									
										
										
										
											2020-10-03 10:09:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-28 21:39:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def set_news_avatar(base_dir: str, name: str, | 
					
						
							|  |  |  |                     http_prefix: str, | 
					
						
							|  |  |  |                     domain: str, domain_full: str) -> None: | 
					
						
							| 
									
										
										
										
											2020-10-13 21:38:19 +00:00
										 |  |  |     """Sets the avatar for the news account
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     nickname = 'news' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     new_filename = base_dir + '/theme/' + name + '/icons/avatar_news.png' | 
					
						
							|  |  |  |     if not os.path.isfile(new_filename): | 
					
						
							|  |  |  |         new_filename = base_dir + '/theme/default/icons/avatar_news.png' | 
					
						
							|  |  |  |     if not os.path.isfile(new_filename): | 
					
						
							| 
									
										
										
										
											2020-10-13 21:38:19 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     avatar_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-26 10:19:59 +00:00
										 |  |  |         local_actor_url(http_prefix, domain_full, nickname) + '.png' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     avatar_filename = avatar_filename.replace('/', '-') | 
					
						
							|  |  |  |     filename = base_dir + '/cache/avatars/' + avatar_filename | 
					
						
							| 
									
										
										
										
											2020-10-13 21:45:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 21:38:19 +00:00
										 |  |  |     if os.path.isfile(filename): | 
					
						
							| 
									
										
										
										
											2021-09-05 10:17:43 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             os.remove(filename) | 
					
						
							| 
									
										
										
										
											2021-11-25 22:22:54 +00:00
										 |  |  |         except OSError: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |             print('EX: set_news_avatar unable to delete ' + filename) | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |     if os.path.isdir(base_dir + '/cache/avatars'): | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         copyfile(new_filename, filename) | 
					
						
							|  |  |  |     account_dir = acct_dir(base_dir, nickname, domain) | 
					
						
							|  |  |  |     copyfile(new_filename, account_dir + '/avatar.png') | 
					
						
							| 
									
										
										
										
											2020-10-13 21:38:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _set_clear_cache_flag(base_dir: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-02-23 14:01:22 +00:00
										 |  |  |     """Sets a flag which can be used by an external system
 | 
					
						
							|  |  |  |     (eg. a script in a cron job) to clear the browser cache | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     dir_str = data_dir(base_dir) | 
					
						
							|  |  |  |     if not os.path.isdir(dir_str): | 
					
						
							| 
									
										
										
										
											2021-03-03 13:39:39 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     flag_filename = dir_str + '/.clear_cache' | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         with open(flag_filename, 'w+', encoding='utf-8') as fp_flag: | 
					
						
							|  |  |  |             fp_flag.write('\n') | 
					
						
							|  |  |  |     except OSError: | 
					
						
							|  |  |  |         print('EX: _set_clear_cache_flag unable to write ' + flag_filename) | 
					
						
							| 
									
										
										
										
											2021-02-23 14:01:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def set_theme(base_dir: str, name: str, domain: str, | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |               allow_local_network_access: bool, system_language: str, | 
					
						
							| 
									
										
										
										
											2022-04-05 11:10:08 +00:00
										 |  |  |               dyslexic_font: bool, designer_reset: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2021-02-07 15:22:06 +00:00
										 |  |  |     """Sets the theme with the given name as the current theme
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |     result = False | 
					
						
							| 
									
										
										
										
											2020-05-28 09:11:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     prev_theme_name = get_theme(base_dir) | 
					
						
							| 
									
										
										
										
											2021-12-05 11:03:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # if the theme has changed then remove any custom settings | 
					
						
							| 
									
										
										
										
											2022-04-05 11:10:08 +00:00
										 |  |  |     if prev_theme_name != name or designer_reset: | 
					
						
							| 
									
										
										
										
											2022-06-12 12:55:04 +00:00
										 |  |  |         reset_theme_designer_settings(base_dir) | 
					
						
							| 
									
										
										
										
											2021-12-05 11:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     _remove_theme(base_dir) | 
					
						
							| 
									
										
										
										
											2020-05-28 21:30:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 10:29:27 +00:00
										 |  |  |     # has the theme changed? | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     themes = get_themes_list(base_dir) | 
					
						
							| 
									
										
										
										
											2021-12-25 23:35:50 +00:00
										 |  |  |     for theme_name in themes: | 
					
						
							|  |  |  |         theme_name_lower = theme_name.lower() | 
					
						
							|  |  |  |         if name == theme_name_lower: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             if prev_theme_name: | 
					
						
							| 
									
										
										
										
											2022-04-05 11:14:37 +00:00
										 |  |  |                 if prev_theme_name.lower() != theme_name_lower or \ | 
					
						
							|  |  |  |                    designer_reset: | 
					
						
							| 
									
										
										
										
											2020-05-28 21:30:40 +00:00
										 |  |  |                     # change the banner and profile image | 
					
						
							|  |  |  |                     # to the default for the theme | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                     _set_theme_images(base_dir, name) | 
					
						
							|  |  |  |                     _set_theme_fonts(base_dir, name) | 
					
						
							| 
									
										
										
										
											2020-05-28 09:11:21 +00:00
										 |  |  |             result = True | 
					
						
							| 
									
										
										
										
											2022-03-13 10:29:27 +00:00
										 |  |  |             break | 
					
						
							| 
									
										
										
										
											2020-05-28 09:11:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if not result: | 
					
						
							| 
									
										
										
										
											2020-05-27 11:02:51 +00:00
										 |  |  |         # default | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  |         _set_theme_default(base_dir, allow_local_network_access, | 
					
						
							|  |  |  |                            system_language) | 
					
						
							| 
									
										
										
										
											2020-05-27 11:02:51 +00:00
										 |  |  |         result = True | 
					
						
							| 
									
										
										
										
											2020-05-28 09:11:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 10:29:27 +00:00
										 |  |  |     # read theme settings from a json file in the theme directory | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     variables_file = base_dir + '/theme/' + name + '/theme.json' | 
					
						
							|  |  |  |     if os.path.isfile(variables_file): | 
					
						
							|  |  |  |         _read_variables_file(base_dir, name, variables_file, | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  |                              allow_local_network_access, | 
					
						
							|  |  |  |                              system_language) | 
					
						
							| 
									
										
										
										
											2020-11-14 17:34:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 23:17:53 +00:00
										 |  |  |     if dyslexic_font: | 
					
						
							|  |  |  |         _set_dyslexic_font(base_dir) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         _set_custom_font(base_dir) | 
					
						
							| 
									
										
										
										
											2020-10-09 19:28:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # set the news avatar | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     news_avatar_theme_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |         base_dir + '/theme/' + name + '/icons/avatar_news.png' | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     dir_str = data_dir(base_dir) | 
					
						
							|  |  |  |     if os.path.isdir(dir_str + '/news@' + domain): | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |         if os.path.isfile(news_avatar_theme_filename): | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |             news_avatar_filename = dir_str + '/news@' + domain + '/avatar.png' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             copyfile(news_avatar_theme_filename, news_avatar_filename) | 
					
						
							| 
									
										
										
										
											2020-10-09 19:28:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-12 12:35:26 +00:00
										 |  |  |     grayscale_filename = dir_str + '/.grayscale' | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     if os.path.isfile(grayscale_filename): | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |         enable_grayscale(base_dir) | 
					
						
							| 
									
										
										
										
											2020-07-10 18:08:45 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |         disable_grayscale(base_dir) | 
					
						
							| 
									
										
										
										
											2020-11-14 18:32:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     _copy_theme_help_files(base_dir, name, system_language) | 
					
						
							|  |  |  |     _set_theme_in_config(base_dir, name) | 
					
						
							|  |  |  |     _set_clear_cache_flag(base_dir) | 
					
						
							| 
									
										
										
										
											2023-09-10 10:12:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 20:17:16 +00:00
										 |  |  |     return result | 
					
						
							| 
									
										
										
										
											2021-05-30 11:06:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def update_default_themes_list(base_dir: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-05-30 11:06:15 +00:00
										 |  |  |     """Recreates the list of default themes
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     theme_names = get_themes_list(base_dir) | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     default_themes_filename = base_dir + '/defaultthemes.txt' | 
					
						
							| 
									
										
										
										
											2024-02-01 13:30:59 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         with open(default_themes_filename, 'w+', encoding='utf-8') as fp_def: | 
					
						
							|  |  |  |             for name in theme_names: | 
					
						
							|  |  |  |                 fp_def.write(name + '\n') | 
					
						
							|  |  |  |     except OSError: | 
					
						
							|  |  |  |         print('EX: update_default_themes_list unable to write ' + | 
					
						
							|  |  |  |               default_themes_filename) | 
					
						
							| 
									
										
										
										
											2021-09-13 18:37:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def scan_themes_for_scripts(base_dir: str) -> bool: | 
					
						
							| 
									
										
										
										
											2021-09-13 18:37:51 +00:00
										 |  |  |     """Scans the theme directory for any svg files containing scripts
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-07-22 09:58:42 +00:00
										 |  |  |     # allow recursive walk | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |     for subdir, _, files in os.walk(base_dir + '/theme'): | 
					
						
							|  |  |  |         for fname in files: | 
					
						
							|  |  |  |             if not fname.endswith('.svg'): | 
					
						
							| 
									
										
										
										
											2021-09-13 18:37:51 +00:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |             svg_filename = os.path.join(subdir, fname) | 
					
						
							| 
									
										
										
										
											2021-09-13 18:37:51 +00:00
										 |  |  |             content = '' | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |             with open(svg_filename, 'r', encoding='utf-8') as fp_svg: | 
					
						
							| 
									
										
										
										
											2022-01-03 18:37:14 +00:00
										 |  |  |                 content = fp_svg.read() | 
					
						
							|  |  |  |             svg_dangerous = dangerous_svg(content, False) | 
					
						
							|  |  |  |             if svg_dangerous: | 
					
						
							|  |  |  |                 print('svg file contains script: ' + svg_filename) | 
					
						
							| 
									
										
										
										
											2021-09-13 18:50:02 +00:00
										 |  |  |                 return True | 
					
						
							| 
									
										
										
										
											2021-09-13 18:37:51 +00:00
										 |  |  |         # deliberately no break - should resursively scan | 
					
						
							| 
									
										
										
										
											2021-09-13 18:50:02 +00:00
										 |  |  |     return False |