view bing4desktop/bing4desktop.py @ 10:ed9556d0c5d7

bing4desktop-0.240205-4
author prymula <prymula76@outlook.com>
date Tue, 06 Feb 2024 00:30:36 +0100
parents
children c01d7edb9cb9
line wrap: on
line source

#!/usr/bin/env python3
# bing4desktop.py - skrypt tray dla Cinnamon oraz Matte i innych WM
# inspiracja: https://pystray.readthedocs.io/en/latest/usage.html
# oraz 'zasłyszane' w internecie :)
# licencja: Public Domain
# edytor: Geany
# data: 05-II-2024
# napisał: Prymula

# python3-pillow-tk

import pystray
from pystray import Icon as icon, Menu as menu, MenuItem as item
import tkinter as tk
from tkinter import messagebox
from PIL import ImageTk, Image

import os, sys, subprocess
import requests
import json
import tempfile
import shutil

ver = "0.240205-4"

BING_URI_BASE = "http://www.bing.com"
BING_WALLPAPER_PATH = "/HPImageArchive.aspx?format=js&idx=50&n=1&mkt=en-US"
full_path=""
actualImage = -1
COPYRIGHT_TXT = ""

tmp_path =  tempfile.mkdtemp()



class WPaper:
    def get(self):
        global full_path, COPYRIGHT_TXT
        # open the Bing HPImageArchive URI and ask for a JSON response
        resp = requests.get(BING_URI_BASE + BING_WALLPAPER_PATH)

        if resp.status_code == 200:
            json_response = json.loads(resp.content)
            wallpaper_path = json_response['images'][0]['url']
            COPYRIGHT_TXT = json_response['images'][0]['copyright']
            filename = wallpaper_path.split('/')[-1]
            wallpaper_uri = BING_URI_BASE + wallpaper_path
            filename_short = filename.split('&')
            print ("filemname_short", filename_short[0])
            # open the actual wallpaper uri, and write the response as an image on the filesystem
            response = requests.get(wallpaper_uri)
            if resp.status_code == 200:
                desktop_env = os.environ.get('DESKTOP_SESSION')
                if desktop_env=="windows":
                    messagebox.showinfo("Błąd","Brak wsparcia dla Windows i Mac !")
                    cleanup()
                    exit
                else:
                    full_path = tmp_path + filename_short[0]
                    with open(full_path, 'wb') as f:
                        f.write(response.content)
            else:
                raise ValueError("[ERROR] non-200 response from Bing server for '{}'".format(wallpaper_uri))
                COPYRIGHT_TXT = "[ERROR] non-200 response from Bing server for " + str(format(wallpaper_uri))
                return False
        else:
            raise ValueError("[ERROR] non-200 response from Bing server for '{}'".format(BING_URI_BASE + BING_WALLPAPER_PATH))
            COPYRIGHT_TXT = "[ERROR] non-200 response from Bing server for " + str(format(BING_URI_BASE + BING_WALLPAPER_PATH))
            return False
        return True
        
    def set(self,file_loc, first_run):
        global full_path
        desktop_env = os.environ.get('DESKTOP_SESSION')

        if len(full_path) == 0:
            messagebox.showinfo("Błąd","Niewybrano obrazu, najpierw wybierz obraz")
            return
        try:
            if desktop_env in ["gnome-classic", "gnome", "unity", "default"]:
                uri = "'file://%s'" % file_loc
                try:
                    SCHEMA = "org.gnome.desktop.background"
                    KEY = "picture-uri"
                    gsettings = Gio.Settings.new(SCHEMA)
                    gsettings.set_string(KEY, uri)
                except:
                    args = ["gsettings", "set", "org.gnome.desktop.background", "picture-uri", uri]
                    subprocess.Popen(args)
            elif desktop_env in ["cinnamon"]:
                uri = "'file://%s'" % file_loc
                try:
                    SCHEMA = "org.cinnamon.desktop.background"
                    KEY = "picture-uri"
                    gsettings = Gio.Settings.new(SCHEMA)
                    gsettings.set_string(KEY, uri)
                except:
                    args = ["gsettings", "set", "org.cinnamon.desktop.background", "picture-uri", uri]
                    subprocess.Popen(args)
            elif desktop_env=="mate":
                try: # MATE >= 1.6
                    # info from http://wiki.mate-desktop.org/docs:gsettings
                    args = ["gsettings", "set", "org.mate.background", "picture-filename", "'%s'" % file_loc]
                    subprocess.Popen(args)
                except: # MATE < 1.6
                    # From https://bugs.launchpad.net/variety/+bug/1033918
                    args = ["mateconftool-2","-t","string","--set","/desktop/mate/background/picture_filename",'"%s"' %file_loc]
                    subprocess.Popen(args)
            elif desktop_env=="gnome2": # Not tested
                # From https://bugs.launchpad.net/variety/+bug/1033918
                args = ["gconftool-2","-t","string","--set","/desktop/gnome/background/picture_filename", '"%s"' %file_loc]
                subprocess.Popen(args)
            ## KDE4 is difficult
            ## see http://blog.zx2c4.com/699 for a solution that might work
            elif desktop_env in ["kde3", "trinity"]:
                # From http://ubuntuforums.org/archive/index.php/t-803417.html
                args = 'dcop kdesktop KBackgroundIface setWallpaper 0 "%s" 6' % file_loc
                subprocess.Popen(args,shell=True)

            elif desktop_env=="xfce4":
                #From http://www.commandlinefu.com/commands/view/2055/change-wallpaper-for-xfce4-4.6.0
                if first_run:
                    args0 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-path", "-s", file_loc]
                    args1 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-style", "-s", "3"]
                    args2 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-show", "-s", "true"]
                    subprocess.Popen(args0)
                    subprocess.Popen(args1)
                    subprocess.Popen(args2)
                args = ["xfdesktop","--reload"]
                subprocess.Popen(args)

            elif desktop_env in ["fluxbox","jwm","openbox","afterstep"]:
                #http://fluxbox-wiki.org/index.php/Howto_set_the_background
                # used fbsetbg on jwm too since I am too lazy to edit the XML configuration
                # now where fbsetbg does the job excellent anyway.
                # and I have not figured out how else it can be set on Openbox and AfterSTep
                # but fbsetbg works excellent here too.
                try:
                    args = ["fbsetbg", file_loc]
                    subprocess.Popen(args)
                except:
                    sys.stderr.write("ERROR: Failed to set wallpaper with fbsetbg!\n")
                    sys.stderr.write("Please make sre that You have fbsetbg installed.\n")
            elif desktop_env=="icewm":
                # command found at http://urukrama.wordpress.com/2007/12/05/desktop-backgrounds-in-window-managers/
                args = ["icewmbg", file_loc]
                subprocess.Popen(args)
            elif desktop_env=="blackbox":
                # command found at http://blackboxwm.sourceforge.net/BlackboxDocumentation/BlackboxBackground
                args = ["bsetbg", "-full", file_loc]
                subprocess.Popen(args)
            elif desktop_env=="lxde":
                args = "pcmanfm --set-wallpaper %s --wallpaper-mode=scaled" % file_loc
                subprocess.Popen(args,shell=True)
            elif desktop_env=="WindowMaker":
                # From http://www.commandlinefu.com/commands/view/3857/set-wallpaper-on-windowmaker-in-one-line
                args = "wmsetbg -s -u %s" % file_loc
                subprocess.Popen(args,shell=True)
            elif desktop_env=="windows": #Not tested since I do not run this on Windows
                #From https://stackoverflow.com/questions/1977694/change-desktop-background
                import ctypes
                SPI_SETDESKWALLPAPER = 20
                ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, file_loc , 0)
            else:
                if first_run: #don't spam the user with the same message over and over again
                    sys.stderr.write("Warning: Failed to set wallpaper. Your desktop environment is not supported.")
                    sys.stderr.write("You can try manually to set Your wallpaper to %s" % file_loc)
                return False
            return True
        except:
            sys.stderr.write("ERROR: Failed to set wallpaper. There might be a bug.\n")
            return False


class Gui():
    global COPYRIGHT_TXT
    
    def __init__(self):
        self.window = tk.Tk()
        self.image =  Image.open("bing.ico")
        self.menu = (
            item("Ustaw Tapetę", lambda icon, item: wp.set(full_path, True)),
            item('Tapeta poprzednia', lambda icon, item: self.change_pic(1)),
            item('Tapeta następna', lambda icon, item: self.change_pic(-1)),
            item('Opis zdjęcia', lambda icon, item: icon.notify(COPYRIGHT_TXT)),
            item('O Programie', lambda icon, item: self.about()),

            item('Wyjdź', self.quit_window)
            )
        self.frame = tk.Frame(self.window, width=600, height=400)
        self.frame.pack()
        self.frame.place(anchor='center', relx=0.5, rely=5)
        
        #self.window.title("Bing4Desktop")
        #self.window.geometry('800x600')
        #self.window.protocol('WM_DELETE_WINDOW', self.withdraw_window)
        self.withdraw_window()
        self.window.mainloop()
   
    def about(self):
        global ver
        messagebox.showinfo("Bing4Desktop","Inspracja:\npystray.readthedocs.io/en/latest/usage.html\n\nNapisał: Prymula\n\nLuty 2024\n\nLicencja:\nPublic Domain\n\nWersja: "+ver)
        # możliwe że nieprawidlowe
        self.window.destroy()
        self.window.update()

   
    def change_pic(self, n):
        global actualImage, BING_WALLPAPER_PATH
        BASE = "/HPImageArchive.aspx?format=js&idx="
        OFF = "&n=1&mkt=en-US"

        actualImage = actualImage + n;
        if (actualImage < 0):
             actualImage = 10
        elif (actualImage > 10):
             actualImage = 0
             
        print ("FULL: ", len(full_path))
        
        wp=WPaper()
        if wp.get():
            BING_WALLPAPER_PATH = BASE+str(actualImage)+OFF
            if wp.get() == False:
                cleanup()
                exit
            
            img = Image.open(full_path) #.convert('RGBA')  # PIL solution
            tmp = img.resize((600, 400), None, None, 3.0)
            tmp.show()

    def quit_window(self):
        self.icon.stop()
        self.window.destroy()


    def show_window(self):
        self.icon.stop()
        self.window.protocol('WM_DELETE_WINDOW', self.withdraw_window)
        self.window.after(0, self.window.deiconify)


    def withdraw_window(self):
        self.window.withdraw()
        self.icon = pystray.Icon("name", self.image, "title", self.menu)
        self.icon.run()

def cleanup():
    # NIEBEZPIECZNA ! lepiej niczym innym nie nadpisywać tych zmiennych
    shutil.rmtree(tmp_path)    
        
if __name__ in '__main__':
    wp=WPaper()
    if wp.get():
        wp.set(full_path, True)
        g = Gui()
        cleanup()