Exemplo n.º 1
0
    def validate(self, query):
        logger.info(lambda: "Validating Reddit query " + query)
        if not "/" in query:
            query = "https://www.reddit.com/r/%s" % query
        try:
            if not query.startswith("http://") and not query.startswith(
                    "https://"):
                query = "http://" + query

            if not "//reddit.com" in query and not "//www.reddit.com" in query:
                return False, _("This does not seem to be a valid Reddit URL")

            dl = RedditDownloader(self, query)
            queue = dl.fill_queue()
            return (
                query,
                None if len(queue) > 0 else
                _("We could not find any image submissions there."),
            )
        except Exception:
            logger.exception(
                lambda:
                "Error while validating URL, probably no image posts for this URL"
            )
            return query, _("We could not find any image submissions there.")
Exemplo n.º 2
0
    def browse(self, widget=None):
        try:
            self.chooser = Gtk.FileChooserDialog(
                _("Choose a folder"),
                parent=self.button.get_toplevel(),
                action=Gtk.FileChooserAction.SELECT_FOLDER,
                buttons=[
                    _("Cancel"), Gtk.ResponseType.CANCEL,
                    _("OK"), Gtk.ResponseType.OK
                ],
            )
            self.chooser.set_filename(self.folder)
            self.chooser.set_select_multiple(False)
            self.chooser.set_local_only(False)

            if self.chooser.run() == Gtk.ResponseType.OK:
                self.set_folder(self.chooser.get_filename())
                try:
                    if self.on_change:
                        self.on_change()
                except Exception:
                    logger.exception(
                        lambda: "Exception during FolderChooser on_change:")
        finally:
            if self.chooser:
                try:
                    self.chooser.destroy()
                    self.chooser = None
                except Exception:
                    logger.exception(
                        lambda: "Exception during FolderChooser destroying:")
Exemplo n.º 3
0
    def validate(self, query):
        logger.info(lambda: "Validating ArtStation query " + query)
        if query.endswith("/"):
            query = query[:-1]
        if "artstation.com/artwork/" in query:
            logger.exception(lambda: "Error while validating URL, artwork url")
            return query, _("We cannot download individual artworks.")
        if "/" not in query:
            query = "https://www.artstation.com/%s" % query
        if not query.endswith(".rss"):
            query += ".rss"
        try:
            # normalize the URL to "https://artstation.com/artist"
            query = query.replace("http://", "https://")
            if not query.startswith("https://"):
                query = "https://" + query
            query = query.replace("//artstation.com", "//www.artstation.com")

            if "//www.artstation.com" not in query:
                return False, _(
                    "This does not seem to be a valid ArtStation URL")

            dl = ArtStationDownloader(self, query)
            queue = dl.fill_queue()
            return (
                query,
                None if len(queue) > 0 else
                _("We could not find any image submissions there."),
            )
        except Exception:
            logger.exception(
                lambda:
                "Error while validating URL, probably no image posts for this URL"
            )
            return query, _("We could not find any image submissions there.")
Exemplo n.º 4
0
        def _go():
            self.thumbs_window = ThumbsWindow(screen=self.screen,
                                              position=options.position,
                                              breadth=options.breadth)
            try:
                icon = varietyconfig.get_data_file("media", "variety.svg")
                self.thumbs_window.set_icon_from_file(icon)
            except Exception:
                logger.exception(lambda: "Could not set thumbs window icon")

            if self.type == "history":
                title = _("Variety History")
            elif self.type == "downloads":
                title = _("Variety Recent Downloads")
            else:
                title = _("Variety Images")

            self.thumbs_window.set_title(title)
            self.thumbs_window.connect("clicked", self.on_click)

            def _on_close(window, event):
                self.hide(force=True)

            self.thumbs_window.connect("delete-event", _on_close)

            self.mark_active(self.active_file, self.active_position)

            self.thumbs_window.start(self.images)
Exemplo n.º 5
0
 def validate(self, config):
     try:
         url = self.UnsplashConfigurableDownloader(self, config).get_unsplash_api_url()
         data = Util.fetch_json(url)
         valid = "errors" not in data
         return config, None if valid else _("No images found")
     except UnsupportedConfig:
         return config, _("We do not support this type of URL")
     except Exception as e:
         if isinstance(e, HTTPError) and e.response.status_code == 404:
             return config, _("No images found")
         else:
             return config, _("Oops, this didn't work. Is the remote service up?")
Exemplo n.º 6
0
 def display_modes(self) -> List[DisplayMode]:
     return [
         StaticDisplayMode(
             id="os",
             title=_(
                 "[Legacy] Controlled via OS settings, not by Variety. Fast."
             ),
             description=
             _("Display mode is controlled by your OS Appearance settings and by the logic "
               "for your desktop environment in ~/.config/variety/scripts/set_wallpaper. "
               "Provides compatibility with past Variety versions."),
             set_wallpaper_param="os",
         )
     ]
Exemplo n.º 7
0
    def validate(self, query):
        if not "/" in query:
            query = "https://www.reddit.com/r/%s" % query
        else:
            if not query.startswith("http://") and not query.startswith(
                    "https://"):
                query = "https://" + query
            if not "//reddit.com" in query and not "//www.reddit.com" in query:
                return query, False, _(
                    "This does not seem to be a valid Reddit URL")

        valid = RedditDownloader.validate(query, self.parent)
        return (query, None if valid else
                _("We could not find any image submissions there."))
Exemplo n.º 8
0
 def display_modes(self) -> List[DisplayMode]:
     modes = [
         "centered", "scaled", "stretched", "zoom", "spanned", "wallpaper"
     ]
     return [
         StaticDisplayMode(
             id="gnome-%s" % mode,
             title=_("[GNOME/Mate/Cinnamon] %s") % mode.capitalize(),
             description=
             _("Variety will instruct the desktop environment to use this mode when "
               "calling set_wallpaper, and will not itself scale the image, unless needed "
               "by other options, e.g. clock. "),
             set_wallpaper_param=mode,
         ) for mode in modes
     ]
Exemplo n.º 9
0
 def get_info(cls):
     return {
         "name": "Goodreads",
         "description": _("Fetches quotes from Goodreads.com"),
         "author": "Peter Levi",
         "version": "0.1",
     }
Exemplo n.º 10
0
 def get_info(cls):
     return {
         "name": "TheQuotationsPage.com",
         "description": _("Fetches quotes from TheQuotationsPage.com"),
         "author": "Peter Levi",
         "version": "0.1",
     }
Exemplo n.º 11
0
class DesktopprDownloader(SimpleDownloader):
    DESCRIPTION = _("Random wallpapers from Desktoppr.co")

    @classmethod
    def get_info(cls):
        return {
            "name": "DesktopprDownloader",
            "description": DesktopprDownloader.DESCRIPTION,
            "author": "Peter Levi",
            "version": "0.1",
        }

    def get_source_type(self):
        return "desktoppr"

    def get_description(self):
        return DesktopprDownloader.DESCRIPTION

    def get_source_name(self):
        return "Desktoppr.co"

    def get_folder_name(self):
        return "Desktoppr"

    def fill_queue(self):
        response = Util.fetch_json("https://api.desktoppr.co/1/wallpapers/random")

        if response["response"]["review_state"] != "safe":
            logger.info(lambda: "Non-safe image returned by Desktoppr, skipping")
            return None

        origin_url = response["response"]["url"]
        image_url = response["response"]["image"]["url"]
        return [QueueItem(origin_url, image_url, {})]
Exemplo n.º 12
0
 def get_info(cls):
     return {
         "name": "UnsplashConfigurableSource",
         "description": _("Configurable source for fetching photos from Unsplash.com"),
         "author": "Peter Levi",
         "version": "0.1",
     }
Exemplo n.º 13
0
 def get_info(cls):
     return {
         "name": "RedditSource",
         "description":
         _("Configurable source for fetching images from Reddit"),
         "author": "Peter Levi",
         "version": "0.1",
     }
Exemplo n.º 14
0
    def create_rating_menu(file, main_window):
        def _set_rating_maker(rating):
            def _set_rating(widget, rating=rating):
                try:
                    Util.set_rating(file, rating)
                    main_window.on_rating_changed(file)
                except Exception:
                    logger.exception(lambda: "Could not set EXIF rating")
                    main_window.show_notification(
                        _("Could not set EXIF rating"))

            return _set_rating

        try:
            actual_rating = Util.get_rating(file)
        except Exception:
            actual_rating = None

        rating_menu = Gtk.Menu()
        for rating in range(5, 0, -1):
            item = Gtk.CheckMenuItem("\u2605" * rating)
            item.set_draw_as_radio(True)
            item.set_active(actual_rating == rating)
            item.set_sensitive(not item.get_active())
            item.connect("activate", _set_rating_maker(rating))
            rating_menu.append(item)

        rating_menu.append(Gtk.SeparatorMenuItem.new())

        unrated_item = Gtk.CheckMenuItem(_("Unrated"))
        unrated_item.set_draw_as_radio(True)
        unrated_item.set_active(actual_rating is None or actual_rating == 0)
        unrated_item.set_sensitive(not unrated_item.get_active())
        unrated_item.connect("activate", _set_rating_maker(None))
        rating_menu.append(unrated_item)

        rejected_item = Gtk.CheckMenuItem(_("Rejected"))
        rejected_item.set_draw_as_radio(True)
        rejected_item.set_active(actual_rating is not None
                                 and actual_rating < 0)
        rejected_item.set_sensitive(not rejected_item.get_active())
        rejected_item.connect("activate", _set_rating_maker(-1))
        rating_menu.append(rejected_item)

        rating_menu.show_all()
        return rating_menu
Exemplo n.º 15
0
 def _set_rating(widget, rating=rating):
     try:
         Util.set_rating(file, rating)
         main_window.on_rating_changed(file)
     except Exception:
         logger.exception(lambda: "Could not set EXIF rating")
         main_window.show_notification(
             _("Could not set EXIF rating"))
Exemplo n.º 16
0
 def validate(self, url):
     if not url.startswith("http://") and not url.startswith("https://"):
         url = "https://" + url
     valid = MediaRSSDownloader.validate(url)
     error = _(
         "This does not seem to be a valid Media RSS feed URL or there is no content there."
     )
     return url, None if valid else error
Exemplo n.º 17
0
 def get_ui_instruction(self):
     return _(
         "Enter the name of an artist or paste the full URL of their "
         "artstation page with .rss extenstion or without it. \n"
         "Example: You may specify simply 'leimin' or "
         "<a href='https://www.artstation.com/leimin'>https://www.artstation.com/leimin</a>\n"
         "Example: Or direct it to the RSS: "
         "<a href='https://www.artstation.com/leimin.rss'>https://www.artstation.com/leimin.rss</a>"
     )
Exemplo n.º 18
0
 def get_info(cls):
     return {
         "name":
         "ArtStationSource",
         "description":
         _("Configurable source for fetching images from ArtStation"),
         "author":
         "Denis Gordeev",
         "version":
         "0.1",
     }
Exemplo n.º 19
0
 def get_info(cls):
     return {
         "name":
         "MediaRSSSource",
         "description":
         _("Configurable source for fetching images from MediaRSS feeds"),
         "author":
         "Peter Levi",
         "version":
         "0.1",
     }
Exemplo n.º 20
0
 def get_ui_instruction(self):
     return _(
         "Enter the name of a subreddit or paste the full URL of a subreddit or a "
         "<a href='http://reddit.com'>Reddit</a> user. You may specify sort order and time "
         "period if you wish. Variety will use posts to direct images or to Imgur pages "
         "within the first 100 submissions returned by Reddit.\n\n"
         "Example: You may specify simply 'comics' or "
         "<a href='http://www.reddit.com/r/comics'>http://www.reddit.com/r/comics</a>\n"
         "Example: Top posts from the month: "
         "<a href='http://www.reddit.com/r/comics/top/?sort=top&amp;t=month'>http://www.reddit.com/r/comics/top/?sort=top&amp;t=month</a>"
     )
Exemplo n.º 21
0
 def get_ui_instruction(self):
     return _(
         "We use the <a href='https://unsplash.com'>Unsplash</a> API to fetch random images "
         "that match the given search term or URL. The Unsplash API is rate-limited, so "
         "Variety fetches images from Unsplash sources as a reduced rate.\n"
         "\n"
         "Please specify either a search keyword, or the URL of a search result, user or "
         "collection.\n"
         "Example: <a href='https://unsplash.com/collections/3863203/desktop-wallpapers'>https://unsplash.com/collections/3863203/desktop-wallpapers</a>\n"
         "Example: <a href='https://unsplash.com/@pawel_czerwinski'>https://unsplash.com/@pawel_czerwinski</a>"
     )
Exemplo n.º 22
0
class EarthDownloader(SimpleDownloader):
    DESCRIPTION = _("World Sunlight Map - live wallpaper from Die.net")

    @classmethod
    def get_info(cls):
        return {
            "name": "EarthDownloader",
            "description": EarthDownloader.DESCRIPTION,
            "author": "Peter Levi",
            "version": "0.1",
        }

    def get_source_type(self):
        return "earth"

    def get_description(self):
        return EarthDownloader.DESCRIPTION

    def get_source_name(self):
        return "Die.net"

    def get_folder_name(self):
        return "Earth"

    def get_source_location(self):
        return EARTH_ORIGIN_URL

    def get_refresh_interval_seconds(self):
        return 15 * 60

    def download_one(self):
        logger.info(
            lambda: "Downloading world sunlight map from " + EARTH_ORIGIN_URL)
        downloaded = self.save_locally(
            EARTH_ORIGIN_URL,
            EARTH_IMAGE_URL,
            force_download=True,
            extra_metadata={"headline": "World Sunlight Map"},
        )
        final_path = os.path.join(self.target_folder, EARTH_FILENAME)
        shutil.move(downloaded, final_path)
        for f in os.listdir(self.target_folder):
            if f != EARTH_FILENAME and f.lower().endswith(".jpg"):
                os.unlink(os.path.join(self.target_folder, f))
        return final_path

    def fill_queue(self):
        """ Not needed here """
        return []

    def on_variety_start_complete(self):
        if not os.path.exists(os.path.join(self.target_folder,
                                           EARTH_FILENAME)):
            self.download_one()
Exemplo n.º 23
0
 def get_ui_instruction(self):
     return _(
         "Please paste the URL of the Media RSS feed below. Please note that only Media RSS "
         "feeds are supported, not arbitrary RSS feeds. Media RSS feeds contain media:content "
         "tags linking directly to the actual image content. "
         "Some examples of sites that provide Media RSS feeds are: "
         "<a href='https://picasaweb.google.com/'>Picasa</a>, "
         "<a href='http://www.deviantart.com'>deviantART</a>, "
         "<a href='http://www.smugmug.com/browse/'>SmugMug</a>, "
         "<a href='http://www.flickr.com'>Flickr</a>, "
         "<a href='http://interfacelift.com'>InterfaceLIFT</a>.")
Exemplo n.º 24
0
 def get_ui_instruction(self):
     return _(
         "<a href='http://wallhaven.cc'>Wallhaven.cc</a> provides a variety of image search options. "
         "Below you can specify keywords to search for, or visit <a href='http://wallhaven.cc'>Wallhaven.cc</a>, "
         "setup your search criteria there, ensure you like the results, and paste the full Wallhaven URL "
         "in the box.\n"
         "\n"
         "If you specify keywords, the most liked safe-for-work images that match all of the keywords will "
         "be used. \n"
         "\n"
         "If you specify a Wallhaven URL, please choose the sorting criteria carefully - Variety regularly "
         "requests images, but uses only images from the first several hundred returned. Random or Date will "
         "mean this image source will have a longer 'lifetime' till it is exhausted. Favorites will provide "
         "better images and Relevance will provide closer matches when searching for phrases or colors."
     )
Exemplo n.º 25
0
 def get_info(cls):
     return {
         "name":
         "Local text files",
         "description":
         _("Displays quotes, defined in local text files.\n"
           "Put your own txt files in: {}pluginconfig/quotes/.\n"
           "The file format is:\n\nquote -- author\n.\nsecond quote -- another author\n.\netc...\n\n"
           "Example: http://rvelthuis.de/zips/quotes.txt").format(
               get_profile_path(expanded=False)),
         "author":
         "Peter Levi",
         "version":
         "0.1",
     }
Exemplo n.º 26
0
class EarthviewDownloader(SimpleDownloader):
    DESCRIPTION = _("Google Earth View Wallpapers")
    ROOT_URL = "https://earthview.withgoogle.com/"

    @classmethod
    def get_info(cls):
        return {
            "name": "EarthviewDownloader",
            "description": EarthviewDownloader.DESCRIPTION,
            "author": "Peter Levi",
            "version": "0.1",
        }

    def get_description(self):
        return EarthviewDownloader.DESCRIPTION

    def get_source_type(self):
        return "earthview"

    def get_source_name(self):
        return "Earth View"

    def get_source_location(self):
        return self.ROOT_URL

    def fill_queue(self):
        queue = Util.fetch_json(DATA_URL)
        random.shuffle(queue)
        return queue

    def get_default_throttling(self):
        # throttle this source, as otherwise maps "overpower" all other types of images
        # with Variety's default settings, and we have no other way to control source "weights"
        return Throttling(max_downloads_per_hour=20,
                          max_queue_fills_per_hour=None)

    def download_queue_item(self, item):
        region = item["Region"]
        filename = "{}{} (ID-{}).jpg".format(
            region + ", " if region and region != "-" else "", item["Country"],
            item["ID"])
        origin_url = EarthviewDownloader.ROOT_URL + str(item["ID"])
        image_url = item["Image URL"]
        if not image_url.startswith("http"):
            image_url = "https://" + image_url
        return self.save_locally(origin_url,
                                 image_url,
                                 local_filename=filename)
Exemplo n.º 27
0
class NationalGeographicDownloader(SimpleDownloader):
    DESCRIPTION = _("National Geographic's photo of the day")
    ROOT_URL = "https://www.nationalgeographic.co.uk/photo-of-day"

    @classmethod
    def get_info(cls):
        return {
            "name": "NationalGeographicDownloader",
            "description": NationalGeographicDownloader.DESCRIPTION,
            "author": "Eric Rösch",
            "version": "0.1",
        }

    def get_description(self):
        return NationalGeographicDownloader.DESCRIPTION

    def get_source_type(self):
        return "natgeo"

    def get_source_name(self):
        return "National Geographic"

    def get_source_location(self):
        return self.ROOT_URL

    def fill_queue(self):
        queue = Util.fetch_json(DATA_URL)
        images = queue["result"]["pageContext"]["node"]["data"]["content"][
            "images"]
        return images

    def download_queue_item(self, item):
        url = item["entity"]["mediaImage"]["url"]
        origin_url = NationalGeographicDownloader.ROOT_URL + "?image=" + splitext(
            basename(url))[0]
        image_url = "https://static.nationalgeographic.co.uk" + url
        author = item["entity"]["credit"]
        extra_metadata = {
            "author": author,
            "authorURL":
            "http://google.com/search?sourceid=variety&q=" + author,
            "headline": item["entity"]["mediaImage"]["alt"],
            "description": item["entity"]["caption"][3:-6],
        }
        return self.save_locally(origin_url,
                                 image_url,
                                 extra_metadata=extra_metadata)
Exemplo n.º 28
0
 def display_modes(self) -> List[DisplayMode]:
     return [
         DisplayMode(
             id="smart",
             title=
             _("Smart: Variety picks best mode based on image size. Recommended."
               ),
             description=
             ("Variety uses the fast OS-provided Zoom mode for images that are close to "
              "screen proportions, uses 'Fit & pad with a blurred background' when the image "
              "proportions are significantly different - e.g. portraits on a horizontal "
              "screen, and uses the OS-provided tiling mode for very small images that would "
              "look bad resized."),
             fn=_smart_fn,
         ),
         StaticDisplayMode(
             id="zoom",
             title=_("Zoom to fill screen"),
             description=
             _("Image is zoomed in or out so that it fully fills your primary screen. "
               "Some parts of the image will be cut out if its resolution is different "
               "from the screen's. Slower than using native OS resizing options."
               ),
             set_wallpaper_param="zoom",
             imagemagick_cmd=IMAGEMAGICK_ZOOM,
         ),
         StaticDisplayMode(
             id="fill-with-black",
             title=_("Fit within screen, pad with black"),
             description=_(
                 "Image is zoomed in or out so that it fully fits within your primary screen. "
                 "The rest of the screen is filled with black. "
                 "Slower than using native OS resizing options."),
             set_wallpaper_param="zoom",
             imagemagick_cmd=IMAGEMAGICK_FIT_WITH_BLACK,
         ),
         StaticDisplayMode(
             id="fill-with-blur",
             title=_(
                 "Fit within screen, pad with a blurred background. Slower."
             ),
             description=
             _("Image is zoomed in or out so that it fully fits within your primary screen. "
               "The rest of the screen is a filled with blurred version of the image. "
               ),
             set_wallpaper_param="zoom",
             imagemagick_cmd=IMAGEMAGICK_FIT_WITH_BLUR,
         ),
     ]
Exemplo n.º 29
0
def _check_quit():
    global terminate
    if not terminate:
        GObject.timeout_add(1000, _check_quit)
        return

    logging.getLogger("variety").info("Terminating signal received, quitting...")
    safe_print(
        _("Terminating signal received, quitting..."),
        "Terminating signal received, quitting...",
        file=sys.stderr,
    )

    global VARIETY_WINDOW
    if VARIETY_WINDOW:
        VARIETY_WINDOW.on_quit()
    Util.start_force_exit_thread(10)
Exemplo n.º 30
0
class ChromeOSWallpapersDownloader(SimpleDownloader):
    DESCRIPTION = _("Chrome OS Wallpapers")

    @classmethod
    def get_info(cls):
        return {
            "name": "ChromeOsWallpapersDownloader",
            "description": ChromeOSWallpapersDownloader.DESCRIPTION,
            "author": "Peter Levi",
            "version": "0.1",
        }

    def get_description(self):
        return ChromeOSWallpapersDownloader.DESCRIPTION

    def get_source_type(self):
        return "chromeos"

    def get_source_name(self):
        return "Chrome OS Wallpapers"

    def get_source_location(self):
        return self.get_source_name()

    def fill_queue(self):
        manifest = Util.fetch_json(MANIFEST_URL)
        queue = manifest["wallpaper_list"]
        self.tags = manifest["tags"]
        random.shuffle(queue)
        return queue

    def download_queue_item(self, item):
        image_url = item["base_url"] + "_high_resolution.jpg"
        origin_url = item["dynamic_url"]
        extra_metadata = {}
        if "tags" in item:
            extra_metadata["keywords"] = [
                self.tags[str(tag)] for tag in item["tags"] if str(tag) in self.tags
            ]
        if "author" in item:
            extra_metadata["author"] = item["author"]
        if "author_website" in item:
            extra_metadata["authorURL"] = item["author_website"]

        return self.save_locally(origin_url, image_url, extra_metadata=extra_metadata)