Last active
January 27, 2025 10:44
-
-
Save quinnaissance/4d7eeab657f2d0220bb34de754f1f59d to your computer and use it in GitHub Desktop.
Scriptable widget for Immich library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const API_KEY = "API_KEY" | |
| const SERVER_URL = "SERVER_URL" // requires http/https and port (if relevant) | |
| const REFRESH_EVERY = 6 // Hours | |
| /* Headers for later request */ | |
| let reqBaseHeaders = { | |
| 'x-api-key': API_KEY, | |
| 'Accept': 'application/json' | |
| } | |
| /* Sleep function */ | |
| function sleep(ms) { | |
| return new Promise(resolve => setTimeout(resolve, ms)); | |
| } | |
| /* Generate the Scriptable widget */ | |
| async function createWidget() { | |
| const widget = new ListWidget() | |
| widget.backgroundColor = Color.black() | |
| let imageId = '' | |
| try { | |
| const asset = await getRandomAsset() | |
| if (asset) { | |
| imageId = asset.id | |
| const req = new Request(`${SERVER_URL}/api/assets/${asset.id}/original`) | |
| req.headers = reqBaseHeaders; | |
| const image = await req.loadImage() | |
| const imageStack = widget.addStack() | |
| // imageStack.cornerRadius = 10 | |
| const imageElement = imageStack.addImage(image) | |
| imageElement.applyFillingContentMode() | |
| imageElement.centerAlignImage() | |
| // imageElement.containerRelativeShape = true | |
| // imageElement.cornerRadius = 10 | |
| } | |
| // Set to refresh every 6hrs | |
| widget.refreshAfterDate = new Date(Date.now() + 1000 * 60 * 60 * REFRESH_EVERY) | |
| } catch (error) { | |
| widget.addText('Unable to fetch original of asset ${imageId}') | |
| let errText = widget.addText(error.toString()) | |
| errText.font = Font.systemFont(10); | |
| widget.addSpacer() // Stick text to top | |
| widget.backgroundColor = Color.darkGray() | |
| } | |
| return widget | |
| } | |
| /* Pick a random timeline bucket, and return a suitable image */ | |
| async function getRandomAsset() { | |
| const req = new Request(`${SERVER_URL}/api/search/random`) | |
| req.method = 'POST' | |
| req.headers = { | |
| 'Content-Type': 'application/json', | |
| 'x-api-key': API_KEY, | |
| 'Accept': 'application/json' | |
| } | |
| req.body = JSON.stringify({ | |
| "size": 1, | |
| "type": "IMAGE", | |
| 'withExif': true | |
| }) | |
| try { | |
| // Loop until appropriate image is found | |
| do { | |
| var finalImage = await req.loadJSON() | |
| var model = finalImage[0].exifInfo.lensModel | |
| if (model === null) sleep(100) // filter out screenshots | |
| } while (model === null) | |
| return finalImage[0] | |
| } catch (error) { | |
| widget.addText('Unable to complete /search/random request') | |
| let errText = widget.addText(error.toString()) | |
| errText.font = Font.systemFont(10); | |
| widget.addSpacer() // Stick text to top | |
| widget.backgroundColor = Color.darkGray() | |
| } | |
| } | |
| // Create and run widget | |
| let widget = await createWidget() | |
| Script.setWidget(widget) | |
| Script.complete() |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have no idea what I'm doing so any contributions are much appreciated.
What is this?
How to use
API_KEYandSERVER_URLappropriatelyScriptselect your new scriptOther
nulllensModelvalue (i.e. screenshots), and videos.config.widgetFamilyto get the widget's aspect ratioapplyFillingContentMode()'s image scaling algoWidgetStack.cornerRadiusand `WidgetStack. function does not seem to adapt to widget size.