Something went wrong. Try again.
🌈️ apply a wallpaper based on the weather outside
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145import { colordx } from "@colordx/core"import type { ImageAnalysisData } from "../analyze/analysis.ts"import { applyConfigPath, cachePath, chalkDebug, easeOutQuint, loadConfig, map, mapEased, shuffle } from "../utils.ts"import { type ApplicationConfig, defaultConfig, findMatchingImages, getOpenMeteoData } from "./application.ts"import * as SunCalc from "suncalc"import "zx/globals"
console.debug(chalkDebug(`Trying to load application config from ${applyConfigPath}...`))const config = await loadConfig( applyConfigPath, defaultConfig,) as ApplicationConfigif (config == undefined) { throw new Error("Couldn't initialize config!")}
const sunriseDegrees = SunCalc.times.find((element) => element.includes("sunrise"))![0]const dawnDegrees = SunCalc.times.find((element) => element.includes("dawn"))![0]
const openMeteoData = await getOpenMeteoData( config.latitude, config.longitude, config.weatherModel,)const currentSunData = SunCalc.getPosition( new Date(), config.latitude, config.longitude,)const zenithSunData = SunCalc.getPosition( SunCalc.getTimes(new Date(), config.latitude, config.longitude).solarNoon, config.latitude, config.longitude,)const nadirSunData = SunCalc.getPosition( SunCalc.getTimes(new Date(), config.latitude, config.longitude).nadir, config.latitude, config.longitude,)
console.info(`Current cloud cover percentage is ${openMeteoData.cloudCover}%!`)console.info(`Current shortwave radiation is ${openMeteoData.shortwaveRadiation} W/m²!`)console.info(`Current sun altitude is ${currentSunData.altitude}°!`)
const hueValue = Number(currentSunData.altitude) >= sunriseDegrees ? mapEased( Number(currentSunData.altitude), sunriseDegrees, zenithSunData.altitude, 0, config.targetSkyHue, (x: number) => easeOutQuint(x), ) : mapEased( Number(currentSunData.altitude), nadirSunData.altitude, sunriseDegrees, config.targetSkyHue, 360, (x: number) => easeOutQuint(x), )
console.log(hueValue)const chromaValue = map( 100 - Number(openMeteoData.cloudCover), // gotta invert this one 0, 100, config.chromaRange.start, config.chromaRange.end,)
let lightnessValue = mapEased( Number(openMeteoData.shortwaveRadiation), 0, 1000, config.lightnessRange.dawn, config.lightnessRange.noon, (x) => Math.pow(x, 1 / 4))
// if the current sun altitude is less than that of dawn/duskif (currentSunData.altitude < dawnDegrees) { // no light, the sun hasn't even risen yet lightnessValue = config.lightnessRange.night}
const targetColour = colordx({ l: lightnessValue, c: chromaValue, h: hueValue })
console.info(`Calculated target colour ${targetColour.toOklchString()}!`)
console.debug(chalkDebug(`Trying to open cache file ${cachePath}...`))const cacheFile = await fs.promises.readFile(`${cachePath}`, { encoding: "utf8",})const imagesData = JSON.parse(cacheFile) as ImageAnalysisDataconsole.debug(chalkDebug(`Opened cache file ${cachePath}!`))
const matchingImages = shuffle(findMatchingImages(imagesData, targetColour, config.numberOfWallpapers)).slice( 0, config.numberOfWallpapers,)
matchingImages.forEach((image) => console.info( `Found matching image ${image.path} with colour ${colordx(image.colour).toOklchString()}!`, ))
// TODO: implement setting more than one wallpaper. for ppl with multiple monitors
console.info(`Setting wallpaper...`)
if (Deno.build.os == "windows") { const command = `$setwallpapersrc = @"using System.Runtime.InteropServices;public class Wallpaper { public const int SetDesktopWallpaper = 20; public const int UpdateIniFile = 0x01; public const int SendWinIniChange = 0x02;
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
public static void SetWallpaper (string path) { SystemParametersInfo(SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange); }}"@Add-Type -TypeDefinition $setwallpapersrc
[Wallpaper]::SetWallpaper("${matchingImages[0].path}")` usePowerShell() // await $`Write-Host ${command}` await $`${command} | iex`} else if (Deno.build.os == "darwin") { const command = `tell application "System Events" to set picture of (reference to current desktop) to "${matchingImages[0].path}"` await $`osascript -e ${command}`} else { await $`eval ${config.applyWallpaperCommand.replace("%s", matchingImages[0].path)}`}
console.info(`Success! Enjoy :)`)