skip to content
Архитектура в курилке

Динамическая смена обоев на MacOS

/ чтиво на 2 минуты

Содержание

Проверено на Sonoma 14.7, но может и будет работать на будущих версиях

Обзор

По сути нам требуется сделать cron-джобу, которая будет раз в минуту вызывать питонячий скрипт. Скрипт берет текущее время, проверяет, в какой из диапазонов попадает текущий час, и вызывает созданный нами ранее automator-скрипт. Скрипт просто пробегается по всем рабочим столам, которые у нас активны в данный момент и ставит на фон картинку, которую мы передали ему в параметрах.

Для примера возьмем обои под мою любимую тему catppuccin

Остров

Обои слева направо, сверху вниз:

  • tropic_island_morning - выставляем с 6 до 12 часов

  • tropic_island_day - с 12 до 18

  • tropic_island_evening - с 18 до 00

  • tropic_island_night - с 00 до 6

Automator

  • В поиске находим Automator и запускаем его.

  • Выбираем “Процесс”

  • Сверху в поиске находим “Запустить AppleScript”

applescript
  • В открывшемся окне справа копируем наш скрипт
(*
allDesktops.workflow
Set same wallpaper image on all Desktops.
automator -i full/path/to/wallpaper_img allDesktops.workflow
*)
use framework "Foundation"
use framework "AppKit"
use AppleScript version "2.4" -- Yosemite or later
use scripting additions
property ca : current application
property nil : a reference to missing value
on run {input, parameters}
set desktopImg to ca's NSString's stringWithString:(POSIX path of (item 1 of input) as text)
set desktopURL to ca's NSURL's fileURLWithPath:desktopImg
set nswork to ca's NSWorkspace's sharedWorkspace()
-- get all detected screens into an array
set allScreens to ca's NSScreen's screens()
repeat with ascreen in allScreens
(nswork's setDesktopImageURL:desktopURL forScreen:ascreen options:nil |error|:0)
end repeat
return input
end run
applescript_2
  • Сохраняем его как allDesktops.workflow в папке /Users/<имя пользователя>/.config/wallpapor.

Python

  • Откроем наш текстовый редактор и в него скопируем скрипт:
import subprocess
import datetime
# Менять пути до картинок здесь
# Если оставляете те же, и лежать они будут в Pictures/Wallpapers, то
# достаточно заменить имя пользователя
WALLPAPERS = {
"morning": "/Users/<username>/Pictures/Wallpapers/tropic_island_morning.jpg",
"day": "/Users/<username>/Pictures/Wallpapers/tropic_island_day.jpg",
"evening": "/Users/<username>/Pictures/Wallpapers/tropic_island_evening.jpg",
"night": "/Users/<username>/Pictures/Wallpapers/tropic_island_night.jpg",
}
FILENAME = "/Users/<username>/.config/wallpapor/t.txt"
SCRIPT = (
"automator -i {filename} /Users/<username>/.config/wallpapor/allDesktops.workflow"
)
def datetime_to_part_of_day(time) -> str:
if datetime.time(0) <= time < datetime.time(6):
return "night"
if datetime.time(6) <= time < datetime.time(12):
return "morning"
if datetime.time(12) <= time < datetime.time(18):
return "day"
return "evening"
def main():
current_time = datetime.datetime.now()
day_part = datetime_to_part_of_day(current_time.time())
choosen_file = WALLPAPERS[day_part]
result_command = SCRIPT.format(filename=choosen_file)
print(f"Time is: {current_time.isoformat()}")
print(f"Now is {day_part}")
print(f"I would choose {choosen_file}")
print("Executing:")
print(result_command)
subprocess.run(result_command, shell=True)
if __name__ == "__main__":
main()

Там, где прописаны пути до картинок, прописать полные пути до Ваших.

  • Сохраняем файл как main.py в /Users/<имя пользователя>/.config/wallpapor

  • В идеале нам требуется определить полный путь к интерпретатору Python, для этого откроем терминал и в нем выполним команду:

Terminal window
which python

Если мы получили ошибку

Terminal window
python not found

То можно попробовать

Terminal window
which python3

В любом случае мы должны получить что-то вроде

Terminal window
/Library/Frameworks/Python.framework/Versions/3.11/bin/python3

Эта строка нам пригодится в следующем этапе.

CRON

Теперь, когда все готово, нам необходимо добавить в CRON нашу джобу.

Это можно сделать двумя способами:

Скрипт

Просто открываем терминал и в нем выполняем команду (заменить путь на своего пользователя):

Terminal window
(crontab -l 2>/dev/null; echo "*/5 * * * * /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 /Users/<имя пользователя>/.config/wallpapor/main.py") | crontab -

Выглядит страшно, но по сути все, что мы делаем, это добавляем команду

Terminal window
*/5 * * * * /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 /Users/<имя пользователя>/.config/wallpapor/main.py

в crontab.

Все готово!

Вручную

  • Открываем терминал и выполняем:
Terminal window
crontab -e
  • Скорее всего откроется в дефолтном редакторе пустой файл, в него первой же строкой прописываем
Terminal window
*/5 * * * * /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 /Users/<имя пользователя>/.config/wallpapor/main.py
  • Сохраняем и выходим