Skip to content

Commit

Permalink
Macstodon 1.2 with Toot-to-Speech!
Browse files Browse the repository at this point in the history
  • Loading branch information
smallsco committed Mar 26, 2024
1 parent 5196111 commit c7f0596
Show file tree
Hide file tree
Showing 18 changed files with 63 additions and 29 deletions.
2 changes: 1 addition & 1 deletion AuthWindows.py

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
## CHANGELOG

### v1.2 (2024-03-25)

* Implemented Toot-To-Speech (TTS) support, select a toot and press the new Speak button to have the toot read out to you!
* Fixed a bug that could cause toots from multiple columns to be highlighted at once under certain conditions.
* Improved exception handling - Macstodon will log errors to a file instead of dropping to a console window.
* Removed several MacPython dependencies that were being included during the build process but were unused.
* Dropped support for running Macstodon via the MacPython IDE, which never really worked properly anyway.
* Macstodon is once again a single Fat Binary application - build process has been optimized.
* Tweaks to the image caching process that may _slightly_ improve memory usage.
* Images are now always cached, unconditionally.
* Removed unused media cache directory.
* Updated copyright year to 2024.

### v1.1.2 (2023-12-26)

* Macstodon is now fully compatible with WebOne 0.16+, and should also feature improved compatibility with other web proxies that can strip SSL.
Expand Down
2 changes: 1 addition & 1 deletion ImageHandler.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""Macstodon - a Mastodon client for classic Mac OSMIT LicenseCopyright (c) 2022-2023 Scott Small and ContributorsPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associateddocumentation files (the "Software"), to deal in the Software without restriction, including without limitation therights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permitpersons to whom the Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all copies or substantial portions of theSoftware.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THEWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS ORCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OROTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."""# ############### Python Imports # ##############import Imageimport GifImagePluginimport JpegImagePluginimport PngImagePluginimport osimport stringimport sysimport urllib# #################### Third-Party Imports# ###################from third_party.PixMapWrapper import PixMapWrapper# ########### My Imports# ##########from MacstodonHelpers import dprint, getFilenameFromURL# ############ Application# ###########class ImageHandler: def __init__(self, app): """ Initializes the ImageHandler class. """ self.app = app def getImageFromURL(self, url, cache=None): """ Wrapper function - given an image URL, either downloads and caches the image, or loads it from the cache if it already exists there. """ try: if cache: dprint("Want to cache image: %s" % cache) file_name = getFilenameFromURL(url) if not self.isCached(file_name, cache): dprint("Image is not cached, downloading: %s" % cache) self.downloadImage(url, file_name, cache) dprint("Resizing image: %s" % cache) img = self.resizeAndGetImage(file_name, cache) else: dprint("Image is already cached: %s" % cache) img = self.getImageFromCache(file_name, cache) else: dprint("Do not want to cache image") temp_path = self.downloadImage(url) img = self.resizeAndGetImage(temp_path) urllib.urlcleanup() return img except: etype, evalue = sys.exc_info()[:2] dprint("Error loading image: %s: %s" % (etype, evalue)) return None def isCached(self, file_name, cache): """ Checks if an image exists in cache or not and returns true/false. """ if cache == "account" or cache == "banner": cachepath = self.app.cacheacctfolderpath elif cache == "media": cachepath = self.app.cachemediafolderpath try: os.stat(os.path.join(cachepath, file_name)) return 1 except: exc_info = sys.exc_info() if str(exc_info[0]) == "mac.error" and exc_info[1][0] == 2: return 0 raise def getImageFromCache(self, file_name, cache): """ Loads an image file from the cache. """ pm = PixMapWrapper() if cache == "account" or cache == "banner": file_path = os.path.join(self.app.cacheacctfolderpath, file_name) elif cache == "media": file_path = os.path.join(self.app.cachemediafolderpath, file_name) pil_image = Image.open(file_path) pm.fromImage(pil_image) del pil_image return pm def downloadImage(self, url, file_name=None, cache=None): """ Downloads an image from the given URL and writes it to the cache. """ http_url = string.replace(url, "https://", "http://") if cache == "account" or cache == "banner": file_path = os.path.join(self.app.cacheacctfolderpath, file_name) urllib.urlretrieve(http_url, file_path) elif cache == "media": file_path = os.path.join(self.app.cachemediafolderpath, file_name) urllib.urlretrieve(http_url, file_path) else: file_path = None dest_path, headers = urllib.urlretrieve(http_url) return dest_path def resizeAndGetImage(self, file_name, cache=None): """ Resizes an image to an appropriate size and overwrites the existing cached image. """ if cache == "account" or cache == "banner": file_path = os.path.join(self.app.cacheacctfolderpath, file_name) elif cache == "media": file_path = os.path.join(self.app.cachemediafolderpath, file_name) else: file_path = file_name pil_image = Image.open(file_path) pm = PixMapWrapper() if cache == "account": pil_image_small = pil_image.resize((48, 48)) del pil_image pil_image_small.save(file_path) pm.fromImage(pil_image_small) del pil_image_small elif cache == "banner": pil_image_small = pil_image.resize((384, 128)) del pil_image pil_image_small.save(file_path) pm.fromImage(pil_image_small) del pil_image_small else: pm.fromImage(pil_image) del pil_image return pm
"""Macstodon - a Mastodon client for classic Mac OSMIT LicenseCopyright (c) 2022-2024 Scott Small and ContributorsPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associateddocumentation files (the "Software"), to deal in the Software without restriction, including without limitation therights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permitpersons to whom the Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all copies or substantial portions of theSoftware.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THEWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS ORCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OROTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."""# ############### Python Imports # ##############import Imageimport GifImagePluginimport JpegImagePluginimport PngImagePluginimport osimport stringimport sysimport urllib# #################### Third-Party Imports# ###################from third_party.PixMapWrapper import PixMapWrapper# ########### My Imports# ##########from MacstodonHelpers import dprint, getFilenameFromURL# ############ Application# ###########class ImageHandler: def __init__(self, app): """ Initializes the ImageHandler class. """ self.app = app def getImageFromURL(self, url, imgtype=None): """ Wrapper function - given an image URL, either downloads and caches the image, or loads it from the cache if it already exists there. """ try: dprint("Want to cache image: %s" % imgtype) file_name = getFilenameFromURL(url) if not self.isCached(file_name): dprint("Image is not cached, downloading") self.downloadImage(url, file_name) dprint("Resizing image: %s" % imgtype) img = self.resizeAndGetImage(file_name, imgtype) else: dprint("Image is already cached") img = self.getImageFromCache(file_name) return img except: etype, evalue = sys.exc_info()[:2] dprint("Error loading image: %s: %s" % (etype, evalue)) return None def isCached(self, file_name): """ Checks if an image exists in cache or not and returns true/false. """ cachepath = self.app.cachefolderpath try: os.stat(os.path.join(cachepath, file_name)) return 1 except: exc_info = sys.exc_info() if str(exc_info[0]) == "mac.error" and exc_info[1][0] == 2: return 0 raise def getImageFromCache(self, file_name): """ Loads an image file from the cache. """ pm = PixMapWrapper() file_path = os.path.join(self.app.cachefolderpath, file_name) handle = open(file_path, "rb") pil_image = Image.open(handle, "r") pm.fromImage(pil_image) handle.close() del pil_image return pm def downloadImage(self, url, file_name=None): """ Downloads an image from the given URL and writes it to the cache. """ http_url = string.replace(url, "https://", "http://") file_path = os.path.join(self.app.cachefolderpath, file_name) urllib.urlretrieve(http_url, file_path) def resizeAndGetImage(self, file_name, imgtype): """ Resizes an image to an appropriate size and overwrites the existing cached image. """ file_path = os.path.join(self.app.cachefolderpath, file_name) handle = open(file_path, "rb") pil_image = Image.open(handle, "r") if imgtype == "account": pil_image_small = pil_image.resize((48, 48)) elif imgtype == "banner": pil_image_small = pil_image.resize((384, 128)) del pil_image handle.close() pil_image_small.save(file_path) pm = PixMapWrapper() pm.fromImage(pil_image_small) del pil_image_small return pm
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022-2023 Scott Small and Contributors
Copyright (c) 2022-2024 Scott Small and Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading

0 comments on commit c7f0596

Please sign in to comment.