Beispiel #1
0
        /// <summary>
        /// Load a SpotlightImage object from a Metatada file
        /// </summary>
        /// <param name="metadataFile">File to load information from</param>
        /// <returns>SpotlightImage object</returns>
        public static SpotlightImage LoadMeta(string metadataFile)
        {
            string[] lines = File.ReadAllLines(metadataFile);
            if (lines.Length > 0 && lines[0] == MetaHeader)
            {
                SpotlightImage image = new SpotlightImage();
                foreach (string line in lines)
                {
                    int equalIndex = line.IndexOf('=');
                    if (equalIndex > 0)
                    {
                        string value = "";
                        string key   = line.Substring(0, equalIndex);
                        if (line.Length > (equalIndex + 1))
                        {
                            value = line.Substring(equalIndex + 1);
                        }
                        switch (key)
                        {
                        case "uri":
                            image.Uri = value;
                            break;

                        case "sha256":
                            image.Sha256 = value;
                            break;

                        case "filesize":
                            int fileSize;
                            if (int.TryParse(value, out fileSize))
                            {
                                image.FileSize = fileSize;
                            }
                            break;

                        case "title":
                            image.Title = value;
                            break;

                        case "copyright":
                            image.Copyright = value;
                            break;
                        }
                    }
                }
                return(image);
            }
            else
            {
                throw new InvalidDataException("Not a SpotlightImage metadata file: " + metadataFile);
            }
        }
Beispiel #2
0
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                string action                    = null;
                bool   singleImage               = false;
                bool   maximumRes                = false;
                bool?  portrait                  = false;
                string locale                    = null;
                bool   allLocales                = false;
                string outputDir                 = ".";
                string outputName                = "spotlight";
                bool   integrityCheck            = true;
                bool   downloadMany              = false;
                int    downloadAmount            = int.MaxValue;
                int    cacheSize                 = int.MaxValue;
                bool   metadata                  = false;
                bool   metadataAllowInconsistent = false;
                bool   embedMetadata             = false;
                string fromFile                  = null;
                int    apiTryCount               = 3;
                bool   verbose                   = false;

                switch (args[0].ToLower())
                {
                case "urls":
                case "download":
                case "wallpaper":
                case "lockscreen":
                    action = args[0].ToLower();
                    break;

                default:
                    Console.Error.WriteLine("Unknown action: " + args[0]);
                    Environment.Exit(1);
                    break;
                }

                if (args.Length > 1)
                {
                    for (int i = 1; i < args.Length; i++)
                    {
                        switch (args[i].ToLower())
                        {
                        case "--single":
                            singleImage = true;
                            break;

                        case "--many":
                            downloadMany = true;
                            break;

                        case "--amount":
                            i++;
                            downloadMany = true;
                            if (i >= args.Length)
                            {
                                Console.Error.WriteLine("--amount expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!int.TryParse(args[i], out downloadAmount) || downloadAmount < 0)
                            {
                                Console.Error.WriteLine("Download amount must be a valid and positive number.");
                                Environment.Exit(1);
                            }
                            if (downloadAmount == 0)
                            {
                                downloadAmount = int.MaxValue;
                            }
                            break;

                        case "--cache-size":
                            i++;
                            if (i >= args.Length)
                            {
                                Console.Error.WriteLine("--cache-size expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!int.TryParse(args[i], out cacheSize) || cacheSize <= 0)
                            {
                                Console.Error.WriteLine("Cache size must be a valid and strictly positive number.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--maxres":
                            maximumRes = true;
                            break;

                        case "--portrait":
                            portrait = true;
                            break;

                        case "--landscape":
                            portrait = false;
                            break;

                        case "--locale":
                            i++;
                            if (i < args.Length)
                            {
                                locale = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--locale expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!System.Text.RegularExpressions.Regex.Match(locale, "^[a-z]{2}-[A-Z]{2}$").Success)
                            {
                                Console.Error.WriteLine("--locale expected format is xx-XX, e.g. en-US.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--all-locales":
                            allLocales   = true;
                            downloadMany = true;
                            break;

                        case "--outdir":
                            i++;
                            if (i < args.Length)
                            {
                                outputDir = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--outdir expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!Directory.Exists(outputDir))
                            {
                                Console.Error.WriteLine("Output directory '" + outputDir + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--outname":
                            i++;
                            if (i < args.Length)
                            {
                                outputName = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--outname expects an additional argument.");
                                Environment.Exit(1);
                            }
                            foreach (char invalidChar in Path.GetInvalidFileNameChars())
                            {
                                if (outputName.Contains(invalidChar))
                                {
                                    Console.Error.WriteLine("Invalid character '" + invalidChar + "' in specified output file name.");
                                    Environment.Exit(1);
                                }
                            }
                            break;

                        case "--skip-integrity":
                            integrityCheck = false;
                            break;

                        case "--api-tries":
                            i++;
                            if (i >= args.Length)
                            {
                                Console.Error.WriteLine("--api-tries expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!int.TryParse(args[i], out apiTryCount) || apiTryCount <= 0)
                            {
                                Console.Error.WriteLine("API tries must be a valid and strictly positive number.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--metadata":
                            metadata = true;
                            break;

                        case "--inconsistent-metadata":
                            metadata = true;
                            metadataAllowInconsistent = true;
                            break;

                        case "--embed-meta":
                            embedMetadata = true;
                            break;

                        case "--from-file":
                            i++;
                            if (i < args.Length)
                            {
                                fromFile = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--from-file expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!File.Exists(fromFile))
                            {
                                Console.Error.WriteLine("Input file '" + fromFile + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--from-dir":
                            i++;
                            if (i < args.Length)
                            {
                                fromFile = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--from-dir expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (Directory.Exists(fromFile))
                            {
                                string[] jpegFiles = Directory.EnumerateFiles(fromFile, "*.jpg", SearchOption.AllDirectories).ToArray();
                                if (jpegFiles.Any())
                                {
                                    fromFile = jpegFiles[new Random().Next(0, jpegFiles.Length)];
                                }
                                else
                                {
                                    Console.Error.WriteLine("Input directory '" + fromFile + "' does not contain JPG files.");
                                    Environment.Exit(1);
                                }
                            }
                            else
                            {
                                Console.Error.WriteLine("Input directory '" + fromFile + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--restore":
                            if (action == "lockscreen")
                            {
                                if (FileSystemAdmin.IsAdmin())
                                {
                                    try
                                    {
                                        Lockscreen.RestoreDefaultGlobalLockscreen();
                                        Environment.Exit(0);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                        Environment.Exit(4);
                                    }
                                }
                                else
                                {
                                    Console.Error.WriteLine("This program must run as administrator to restore the global lockscreen.");
                                    Environment.Exit(4);
                                }
                            }
                            break;

                        case "--verbose":
                            verbose = true;
                            break;

                        default:
                            Console.Error.WriteLine("Unknown argument: " + args[i]);
                            Environment.Exit(1);
                            break;
                        }
                    }

                    if (downloadMany && cacheSize < downloadAmount)
                    {
                        Console.Error.WriteLine(
                            "Download amount ({0}) is greater than cache size ({1}). Reducing download amount to {1}.",
                            downloadAmount == int.MaxValue ? "MAX" : downloadAmount.ToString(),
                            cacheSize
                            );
                        downloadAmount = cacheSize;
                    }

                    if (downloadMany && metadata && allLocales && !metadataAllowInconsistent)
                    {
                        Console.Error.WriteLine("--metadata combined with --all-locales will produce random metadata languages.");
                        Console.Error.WriteLine("Please relaunch with --inconsistent-metadata if you really intend to do this.");
                        Environment.Exit(1);
                    }
                }

                try
                {
                    Queue <string> remainingLocales = new Queue <string>();

                    if (allLocales)
                    {
                        remainingLocales = new Queue <string>(Locales.AllKnownSpotlightLocales);
                        Console.Error.WriteLine(String.Format("Starting download using {0} locales", remainingLocales.Count));
                        locale = remainingLocales.Dequeue();
                        Console.Error.WriteLine(String.Format("Switching to {0} - {1} locales remaining", locale, remainingLocales.Count + 1));
                    }

                    int downloadCount = 0;
                    int noNewImgCount = 0;

                    do
                    {
                        SpotlightImage[] images = (fromFile != null && (action == "wallpaper" || action == "lockscreen"))
                            ? new[] { new SpotlightImage() } // Skip API request, we'll use a local file
                            : Spotlight.GetImageUrls(maximumRes, portrait, locale, apiTryCount);

                        if (images.Length < 1)
                        {
                            Console.Error.WriteLine(Program.Name + " received an empty image set from Spotlight API.");
                            Environment.Exit(2);
                        }

                        SpotlightImage randomImage = images.OrderBy(p => new Guid()).First();

                        if (action == "urls")
                        {
                            if (singleImage)
                            {
                                Console.WriteLine(randomImage.Uri);
                            }
                            else
                            {
                                foreach (SpotlightImage image in images)
                                {
                                    Console.WriteLine(image.Uri);
                                }
                            }
                            Environment.Exit(0);
                        }

                        try
                        {
                            if (singleImage || action == "wallpaper" || action == "lockscreen")
                            {
                                string imageFile = fromFile ?? randomImage.DownloadToFile(outputDir, integrityCheck, metadata, outputName, apiTryCount);
                                if (embedMetadata)
                                {
                                    imageFile = SpotlightImage.EmbedMetadata(imageFile, outputDir, outputName);
                                }
                                Console.WriteLine(imageFile);
                                if (action == "wallpaper")
                                {
                                    try
                                    {
                                        Desktop.SetWallpaper(imageFile);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                        Environment.Exit(4);
                                    }
                                }
                                else if (action == "lockscreen")
                                {
                                    if (FileSystemAdmin.IsAdmin())
                                    {
                                        try
                                        {
                                            Lockscreen.SetGlobalLockscreen(imageFile);
                                        }
                                        catch (Exception e)
                                        {
                                            Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                            Environment.Exit(4);
                                        }
                                    }
                                    else
                                    {
                                        Console.Error.WriteLine("This program must run as administrator to change the global lockscreen.");
                                        Environment.Exit(4);
                                    }
                                }
                                Environment.Exit(0);
                            }

                            downloadCount = 0;

                            foreach (SpotlightImage image in images)
                            {
                                string imagePath = image.GetFilePath(outputDir);
                                if (!File.Exists(imagePath))
                                {
                                    try
                                    {
                                        Console.WriteLine(image.DownloadToFile(outputDir, integrityCheck, metadata, null, apiTryCount));
                                        downloadCount++;
                                        downloadAmount--;
                                        if (downloadAmount <= 0)
                                        {
                                            break;
                                        }
                                    }
                                    catch (InvalidDataException)
                                    {
                                        Console.Error.WriteLine("Skipping invalid image: " + image.Uri);
                                    }
                                }
                            }

                            if (verbose)
                            {
                                Console.Error.WriteLine("Successfully downloaded: " + downloadCount + " images.");
                                Console.Error.WriteLine("Already downloaded: " + (images.Length - downloadCount) + " images.");
                            }

                            if (downloadCount == 0)
                            {
                                noNewImgCount++;
                            }
                            else
                            {
                                noNewImgCount = 0;
                            }
                        }
                        catch (Exception e)
                        {
                            Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                            Environment.Exit(3);
                        }

                        if (allLocales && noNewImgCount >= 50 && remainingLocales.Count > 0)
                        {
                            noNewImgCount = 0;
                            locale        = remainingLocales.Dequeue();
                            Console.Error.WriteLine(String.Format("Switching to {0} - {1} locales remaining", locale, remainingLocales.Count + 1));
                        }
                    } while (downloadMany && (downloadCount > 0 || noNewImgCount < 50) && downloadAmount > 0);

                    if (cacheSize < int.MaxValue && cacheSize > 0)
                    {
                        foreach (FileInfo imgToDelete in
                                 Directory.GetFiles(outputDir, "*.jpg", SearchOption.TopDirectoryOnly)
                                 .Select(filePath => new FileInfo(filePath))
                                 .OrderByDescending(fileInfo => fileInfo.CreationTime)
                                 .Skip(cacheSize))
                        {
                            string metadataFile = SpotlightImage.GetMetaLocation(imgToDelete.FullName);
                            if (File.Exists(metadataFile))
                            {
                                File.Delete(metadataFile);
                            }
                            imgToDelete.Delete();
                        }
                    }

                    Environment.Exit(0);
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                    Environment.Exit(2);
                }
            }

            foreach (string str in new[] {
                " ==== " + Program.Name + " v" + Program.Version + " - By ORelio - Microzoom.fr ====",
                "",
                "Retrieve Windows Spotlight images by requesting the Microsoft Spotlight API.",
                Program.Name + " can also define images as wallpaper and system-wide lockscreen image.",
                "",
                "Usage:",
                "  " + Program.Name + ".exe <action> [arguments]",
                "  Only one action must be provided, as first argument",
                "  Then, provide any number of arguments from the list below.",
                "",
                "Actions:",
                "  urls               Query Spotlight API and print image URLs to standard output",
                "  download           Download all images and print file path to standard output",
                "  wallpaper          Download one random image and define it as wallpaper",
                "  lockscreen         Download one random image and define it as global lockscreen",
                "",
                "Arguments:",
                "  --single           Print only one random url or download only one image as spotlight.jpg",
                "  --many             Try downloading as much images as possible by calling API many times",
                "  --amount <n>       Stop downloading after <n> images successfully downloaded, implies --many",
                "  --cache-size <n>   Only keep <n> most recent images in the output directory, delete others",
                "  --maxres           Force maximum image resolution instead of tailoring to current screen res",
                "  --portrait         Force portrait image instead of autodetecting from current screen res",
                "  --landscape        Force landscape image instead of autodetecting from current screen res",
                "  --locale <xx-XX>   Force specified locale, e.g. en-US, instead of autodetecting from system",
                "  --all-locales      Attempt to download images for all known Spotlight locales, implies --many",
                "  --outdir <dir>     Set output directory instead of defaulting to working directory",
                "  --outname <name>   Set output file name as <name>.ext for --single or --embed-meta",
                "  --skip-integrity   Skip integrity check of downloaded files: file size and sha256 hash",
                "  --api-tries <n>    Amount of unsuccessful API calls before giving up. Default is 3.",
                "  --metadata         Also save image metadata such as title & copyright as <image-name>.txt",
                "  --embed-meta       When available, embed metadata into wallpaper or lockscreen image",
                "  --from-file        Set the specified file as wallpaper/lockscreen instead of downloading",
                "  --from-dir         Set a random image from the specified directory as wallpaper/lockscreen",
                "  --restore          Restore the default lockscreen image, has no effect with other actions",
                "  --verbose          Display additional status messages while downloading images from API",
                "",
                "Exit codes:",
                "  0                  Success",
                "  1                  Invalid arguments",
                "  2                  Spotlight API request failure",
                "  3                  Image download failure or Failed to write image to disk",
                "  4                  Failed to define image as wallpaper or lock screen image"
            })
            {
                Console.Error.WriteLine(str);
            }
            Environment.Exit(1);
        }
        /// <summary>
        /// Request new images from the Spotlight API and return image urls (Single Attempt)
        /// </summary>
        /// <param name="maxres">Force maximum image resolution. Otherwise, current main monitor screen resolution is used</param>
        /// <param name="portrait">Null = Auto detect from current main monitor resolution, True = portrait, False = landscape.</param>
        /// <param name="locale">Null = Auto detect from current system, or specify xx-XX value format such as en-US</param>
        /// <returns>List of images</returns>
        /// <exception cref="System.Net.WebException">An exception is thrown if the request fails</exception>
        /// <exception cref="System.IO.InvalidDataException">An exception is thrown if the JSON data is invalid</exception>
        private static SpotlightImage[] GetImageUrlsSingleAttempt(bool maxres = false, bool?portrait = null, string locale = null)
        {
            List <SpotlightImage> images = new List <SpotlightImage>();

            Json.JSONData imageData = Json.ParseJson(PerformApiRequest(maxres, locale));

            if (portrait == null)
            {
                portrait = Screen.PrimaryScreen.Bounds.Height > Screen.PrimaryScreen.Bounds.Width;
            }

            if (imageData.Type == Json.JSONData.DataType.Object && imageData.Properties.ContainsKey("batchrsp"))
            {
                imageData = imageData.Properties["batchrsp"];
                if (imageData.Type == Json.JSONData.DataType.Object && imageData.Properties.ContainsKey("items"))
                {
                    if (!imageData.Properties.ContainsKey("ver") || imageData.Properties["ver"].StringValue != "1.0")
                    {
                        Console.Error.WriteLine("SpotlightAPI: Unknown or missing API response version. Errors may occur.");
                    }
                    imageData = imageData.Properties["items"];
                    if (imageData.Type == Json.JSONData.DataType.Array)
                    {
                        foreach (Json.JSONData element in imageData.DataArray)
                        {
                            if (element.Type == Json.JSONData.DataType.Object && element.Properties.ContainsKey("item"))
                            {
                                Json.JSONData item = element.Properties["item"];
                                if (item.Type == Json.JSONData.DataType.String)
                                {
                                    item = Json.ParseJson(item.StringValue);
                                }
                                if (item.Type == Json.JSONData.DataType.Object && item.Properties.ContainsKey("ad") && item.Properties["ad"].Type == Json.JSONData.DataType.Object)
                                {
                                    item = item.Properties["ad"];

                                    string        title;
                                    Json.JSONData titleObj = item.Properties.ContainsKey("title_text") ? item.Properties["title_text"] : null;
                                    if (titleObj != null && titleObj.Type == Json.JSONData.DataType.Object && titleObj.Properties.ContainsKey("tx"))
                                    {
                                        title = titleObj.Properties["tx"].StringValue;
                                    }
                                    else
                                    {
                                        title = null;
                                    }

                                    string        copyright;
                                    Json.JSONData copyrightObj = item.Properties.ContainsKey("copyright_text") ? item.Properties["copyright_text"] : null;
                                    if (copyrightObj != null && copyrightObj.Type == Json.JSONData.DataType.Object && copyrightObj.Properties.ContainsKey("tx"))
                                    {
                                        copyright = copyrightObj.Properties["tx"].StringValue;
                                    }
                                    else
                                    {
                                        copyright = null;
                                    }

                                    string urlField = portrait.Value ? "image_fullscreen_001_portrait" : "image_fullscreen_001_landscape";
                                    if (item.Properties.ContainsKey(urlField) && item.Properties[urlField].Type == Json.JSONData.DataType.Object)
                                    {
                                        item = item.Properties[urlField];
                                        if (item.Properties.ContainsKey("u") && item.Properties.ContainsKey("sha256") && item.Properties.ContainsKey("fileSize") &&
                                            item.Properties["u"].Type == Json.JSONData.DataType.String &&
                                            item.Properties["sha256"].Type == Json.JSONData.DataType.String &&
                                            item.Properties["fileSize"].Type == Json.JSONData.DataType.String)
                                        {
                                            int fileSizeParsed = 0;
                                            if (int.TryParse(item.Properties["fileSize"].StringValue, out fileSizeParsed))
                                            {
                                                SpotlightImage image = new SpotlightImage()
                                                {
                                                    Uri       = item.Properties["u"].StringValue,
                                                    Sha256    = item.Properties["sha256"].StringValue,
                                                    FileSize  = fileSizeParsed,
                                                    Title     = title,
                                                    Copyright = copyright
                                                };
                                                try
                                                {
                                                    System.Convert.FromBase64String(image.Sha256);
                                                }
                                                catch
                                                {
                                                    image.Sha256 = null;
                                                }
                                                if (!String.IsNullOrEmpty(image.Uri) &&
                                                    !String.IsNullOrEmpty(image.Sha256) &&
                                                    image.FileSize > 0)
                                                {
                                                    images.Add(image);
                                                }
                                                else
                                                {
                                                    Console.Error.WriteLine("SpotlightAPI: Ignoring image with empty uri, hash and/or file size less or equal to 0.");
                                                }
                                            }
                                            else
                                            {
                                                Console.Error.WriteLine("SpotlightAPI: Ignoring image with invalid, non-number file size.");
                                            }
                                        }
                                        else
                                        {
                                            Console.Error.WriteLine("SpotlightAPI: Ignoring item image uri with missing 'u', 'sha256' and/or 'fileSize' field(s).");
                                        }
                                    }
                                    else
                                    {
                                        Console.Error.WriteLine("SpotlightAPI: Ignoring item image with missing uri.");
                                    }
                                }
                                else
                                {
                                    Console.Error.WriteLine("SpotlightAPI: Ignoring item with missing 'ad' object.");
                                }
                            }
                            else
                            {
                                Console.Error.WriteLine("SpotlightAPI: Ignoring non-object item while parsing 'batchrsp/items' field in JSON API response.");
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidDataException("SpotlightAPI: 'batchrsp/items' field in JSON API response is not an array.");
                    }
                }
                else
                {
                    throw new InvalidDataException("SpotlightAPI: Missing 'batchrsp/items' field in JSON API response." + (locale != null ? " Locale '" + locale + "' may be invalid." : ""));
                }
            }
            else
            {
                throw new InvalidDataException("SpotlightAPI: API did not return a 'batchrsp' JSON object.");
            }

            return(images.ToArray());
        }
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                string action         = null;
                bool   singleImage    = false;
                bool   maximumRes     = false;
                bool?  portrait       = false;
                string outputDir      = ".";
                string outputName     = "spotlight";
                bool   integrityCheck = true;
                bool   downloadMany   = false;
                bool   metadata       = false;
                string fromFile       = null;

                switch (args[0].ToLower())
                {
                case "urls":
                case "download":
                case "wallpaper":
                case "lockscreen":
                    action = args[0].ToLower();
                    break;

                default:
                    Console.Error.WriteLine("Unknown action: " + args[0]);
                    Environment.Exit(1);
                    break;
                }

                if (args.Length > 1)
                {
                    for (int i = 1; i < args.Length; i++)
                    {
                        switch (args[i].ToLower())
                        {
                        case "--single":
                            singleImage = true;
                            break;

                        case "--many":
                            downloadMany = true;
                            break;

                        case "--maxres":
                            maximumRes = true;
                            break;

                        case "--portrait":
                            portrait = true;
                            break;

                        case "--landscape":
                            portrait = false;
                            break;

                        case "--outdir":
                            i++;
                            if (i < args.Length)
                            {
                                outputDir = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--outdir expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!Directory.Exists(outputDir))
                            {
                                Console.Error.WriteLine("Output directory '" + outputDir + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--outname":
                            i++;
                            if (i < args.Length)
                            {
                                outputName = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--outname expects an additional argument.");
                                Environment.Exit(1);
                            }
                            foreach (char invalidChar in Path.GetInvalidFileNameChars())
                            {
                                if (outputName.Contains(invalidChar))
                                {
                                    Console.Error.WriteLine("Invalid character '" + invalidChar + "' in specified output file name.");
                                    Environment.Exit(1);
                                }
                            }
                            break;

                        case "--skip-integrity":
                            integrityCheck = false;
                            break;

                        case "--metadata":
                            metadata = true;
                            break;

                        case "--from-file":
                            i++;
                            if (i < args.Length)
                            {
                                fromFile = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--from-file expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!File.Exists(fromFile))
                            {
                                Console.Error.WriteLine("Input file '" + fromFile + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--from-dir":
                            i++;
                            if (i < args.Length)
                            {
                                fromFile = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--from-dir expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (Directory.Exists(fromFile))
                            {
                                string[] jpegFiles = Directory.EnumerateFiles(fromFile, "*.jpg", SearchOption.AllDirectories).ToArray();
                                if (jpegFiles.Any())
                                {
                                    fromFile = jpegFiles[new Random().Next(0, jpegFiles.Length)];
                                }
                                else
                                {
                                    Console.Error.WriteLine("Input directory '" + fromFile + "' does not contain JPG files.");
                                    Environment.Exit(1);
                                }
                            }
                            else
                            {
                                Console.Error.WriteLine("Input directory '" + fromFile + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--restore":
                            if (action == "lockscreen")
                            {
                                if (FileSystemAdmin.IsAdmin())
                                {
                                    try
                                    {
                                        Lockscreen.RestoreDefaultGlobalLockscreen();
                                        Environment.Exit(0);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                        Environment.Exit(4);
                                    }
                                }
                                else
                                {
                                    Console.Error.WriteLine("This program must run as administrator to restore the global lockscreen.");
                                    Environment.Exit(4);
                                }
                            }
                            break;

                        default:
                            Console.Error.WriteLine("Unknown argument: " + args[i]);
                            Environment.Exit(1);
                            break;
                        }
                    }
                }

                try
                {
                    int downloadCount = 0;
                    int noNewImgCount = 0;

                    do
                    {
                        SpotlightImage[] images = (fromFile != null && (action == "wallpaper" || action == "lockscreen"))
                            ? new[] { new SpotlightImage() } // Skip API request, we'll use a local file
                            : Spotlight.GetImageUrls(maximumRes, portrait);

                        if (images.Length < 1)
                        {
                            Console.Error.WriteLine(Program.Name + " received an empty image set from Spotlight API.");
                            Environment.Exit(2);
                        }

                        SpotlightImage randomImage = images.OrderBy(p => new Guid()).First();

                        if (action == "urls")
                        {
                            if (singleImage)
                            {
                                Console.WriteLine(randomImage.Uri);
                            }
                            else
                            {
                                foreach (SpotlightImage image in images)
                                {
                                    Console.WriteLine(image.Uri);
                                }
                            }
                            Environment.Exit(0);
                        }

                        try
                        {
                            if (singleImage || action == "wallpaper" || action == "lockscreen")
                            {
                                string outputFile = fromFile ?? randomImage.DownloadToFile(outputDir, integrityCheck, metadata, outputName);
                                Console.WriteLine(outputFile);
                                if (action == "wallpaper")
                                {
                                    try
                                    {
                                        Desktop.SetWallpaper(fromFile ?? outputFile);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                        Environment.Exit(4);
                                    }
                                }
                                else if (action == "lockscreen")
                                {
                                    if (FileSystemAdmin.IsAdmin())
                                    {
                                        try
                                        {
                                            Lockscreen.SetGlobalLockscreen(fromFile ?? outputFile);
                                        }
                                        catch (Exception e)
                                        {
                                            Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                            Environment.Exit(4);
                                        }
                                    }
                                    else
                                    {
                                        Console.Error.WriteLine("This program must run as administrator to change the global lockscreen.");
                                        Environment.Exit(4);
                                    }
                                }
                                Environment.Exit(0);
                            }

                            downloadCount = 0;

                            foreach (SpotlightImage image in images)
                            {
                                string imagePath = image.GetFilePath(outputDir);
                                if (!File.Exists(imagePath))
                                {
                                    Console.WriteLine(image.DownloadToFile(outputDir, integrityCheck, metadata));
                                    downloadCount++;
                                }
                            }

                            Console.Error.WriteLine("Successfully downloaded: " + downloadCount + " images.");
                            Console.Error.WriteLine("Already downloaded: " + (images.Length - downloadCount) + " images.");

                            if (downloadCount == 0)
                            {
                                noNewImgCount++;
                            }
                            else
                            {
                                noNewImgCount = 0;
                            }
                        }
                        catch (Exception e)
                        {
                            Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                            Environment.Exit(3);
                        }

                        Console.WriteLine(noNewImgCount);

                        //} while (downloadMany && (downloadCount > 0 || noNewImgCount < 10));
                    } while (downloadMany && noNewImgCount < 1000);
                    Environment.Exit(0);
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                    Environment.Exit(2);
                }
            }

            foreach (string str in new[] {
                " ==== " + Program.Name + " v" + Program.Version + " - By ORelio - Microzoom.fr ====",
                "",
                "Retrieve Windows Spotlight images by requesting the Microsoft Spotlight API.",
                Program.Name + " can also define images as wallpaper and system-wide lockscreen image.",
                "",
                "Usage:",
                "  " + Program.Name + ".exe <action> [arguments]",
                "  Only one action must be provided, as first argument",
                "  Then, provide any number of arguments from the list below.",
                "",
                "Actions:",
                "  urls               Query Spotlight API and print image URLs to standard output",
                "  download           Download all images and print file path to standard output",
                "  wallpaper          Download one random image and define it as wallpaper",
                "  lockscreen         Download one random image and define it as global lockscreen",
                "",
                "Arguments:",
                "  --single           Print only one random url or download only one image as spotlight.jpg",
                "  --many             Try downloading as much images as possible by calling API many times",
                "  --maxres           Force maximum image resolution instead of tailoring to current screen res",
                "  --portrait         Force portrait image instead of autodetecting from current screen res",
                "  --landscape        Force landscape image instead of autodetecting from current screen res",
                "  --outdir <dir>     Set output directory instead of defaulting to working directory",
                "  --outname <name>   Set output file name as <name>.jpg in single image mode, ignored otherwise",
                "  --skip-integrity   Skip integrity check of downloaded files: file size and sha256 hash",
                "  --metadata         Also save image metadata such as title & copyright as <image-name>.txt",
                "  --from-file        Set the specified file as wallpaper/lockscreen instead of downloading",
                "  --from-dir         Set a random image from the specified directory as wallpaper/lockscreen",
                "  --restore          Restore the default lockscreen image, has no effect with other actions",
                "",
                "Exit codes:",
                "  0                  Success",
                "  1                  Invalid arguments",
                "  2                  Spotlight API request failure",
                "  3                  Image download failure or Failed to write image to disk",
                "  4                  Failed to define image as wallpaper or lock screen image"
            })
            {
                Console.Error.WriteLine(str);
            }
            Environment.Exit(1);
        }
Beispiel #5
0
        /// <summary>
        /// Load an input image, adjust to screen res, embed metadata using current desktop scaling factor and save the result into a new image file
        /// </summary>
        /// <param name="inputImageFile">Input image file</param>
        /// <param name="outputDir">Output directory</param>
        /// <param name="outputName">Output file name</param>
        /// <param name="adjustToScreen">Auto adjust image to current screen resolution</param>
        /// <param name="adjustToScaling">Auto adjust text to current UI scaling factor</param>
        /// <returns>Output file path</returns>
        public static string EmbedMetadata(string inputImageFile, string outputDir, string outputName, bool adjustToScreen = true, bool adjustToScaling = true)
        {
            //Windows 7 or lower cannot use PNG as wallpaper or will convert PNG to JPG, better use BMP for best quality
            string fileExtension = ".bmp";
            var    imageFormat   = System.Drawing.Imaging.ImageFormat.Bmp;

            //Windows 8 and 10 will convert BMP to JPG, better use PNG for best quality
            if ((WindowsVersion.WinMajorVersion == 6 && WindowsVersion.WinMinorVersion >= 2) ||
                WindowsVersion.WinMajorVersion >= 10)
            {
                fileExtension = ".png";
                imageFormat   = System.Drawing.Imaging.ImageFormat.Png;
            }

            if (String.IsNullOrEmpty(outputName))
            {
                outputName = Path.GetFileNameWithoutExtension(inputImageFile);
            }
            string outputFile = Path.Combine(outputDir, outputName + fileExtension);

            Image img = Image.FromFile(inputImageFile);

            if (adjustToScreen)
            {
                Rectangle screen = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
                Image     img2   = FixedImageResize(img, screen.Width, screen.Height, true);
                img.Dispose();
                img = img2;
            }

            string metadataFile = GetMetaLocation(inputImageFile);

            if (File.Exists(metadataFile))
            {
                SpotlightImage meta = LoadMeta(metadataFile);
                Graphics       gfx  = Graphics.FromImage(img);

                gfx.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                gfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                gfx.PixelOffsetMode   = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

                int fontSize = 11;
                if (adjustToScaling)
                {
                    fontSize = (int)((float)fontSize * Desktop.GetScalingFactor());
                }
                Font  font      = new Font("Segoe UI Semilight", fontSize);
                SizeF titleSize = gfx.MeasureString(meta.Title, font);
                if (titleSize.Width < img.Size.Width - 20)
                {
                    gfx.DrawString(
                        meta.Title,
                        font,
                        Brushes.White,
                        new Rectangle(
                            img.Size.Width - 10 - (int)Math.Ceiling(titleSize.Width),
                            10,
                            (int)Math.Ceiling(titleSize.Width),
                            (int)Math.Ceiling(titleSize.Height)
                            )
                        );
                    gfx.Flush();
                }
            }

            img.Save(outputFile, imageFormat);
            img.Dispose();

            return(outputFile);
        }