Created
March 23, 2016 12:33
-
-
Save Jimmy-Z/921bb2648126730e0478 to your computer and use it in GitHub Desktop.
a node.js script to help you make more use of Windows 10 Spotlight lock screen images
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* a node.js script to help you make more use of Windows 10 Spotlight lock | |
* screen images. | |
* | |
* Usage: | |
* node spotlight-export.js <stage dir> <export dir> | |
* | |
* What it does: | |
* --- | |
* any image in spotlight dir but not in stage dir will be copied to stage dir | |
* any image in stage dir but not in spotlight dir will be moved to export dir | |
* | |
* so after the first run: | |
* if nothing new, no actions are taken. | |
* if anything new, it will be copied to stage dir | |
* if anything disappeared from spotlight dir, the corresponding file in | |
* stage dir will be moved to export dir | |
* | |
* it's designed to run as a scheduled task, you can then set up Windows to use | |
* stage dir as desktop background dir, and periodically check export dir to see | |
* if you want to archive them or trash them | |
* | |
* DO NOT manually move files in the stage dir, it will be copied over again by | |
* the next time the scheduled task is ran. | |
* | |
* Why using node: | |
* --- | |
* I tried to use WSH instead of node, unfortunately WSH doesn't support reading | |
* binary files, so node it is. | |
* simply copy files over a paticular size as jpeg won't work, there're some gif | |
* files above 512K. | |
*/ | |
const path = require("path"); | |
const fs = require("fs"); | |
// I don't think png/gif files I found there are wallpapers | |
const FILE_TYPES = ["jpg"]; | |
// and there are small jpg files not suitable for background, looks like app icons | |
const MIN_SIZE = 128 * 1024; | |
function chk_bytes(f, size, chks){ | |
return chks.every(function(c){ | |
var offset = c[0]; | |
var len = c[1]; | |
var b0 = c[2]; | |
var b1 = new Buffer(len); | |
fs.readSync(f, b1, 0, len, offset >= 0 ? offset : size + offset); | |
return Buffer.compare(b0, b1) == 0; | |
}); | |
} | |
// https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_structure | |
// https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#Compatibility | |
// https://en.wikipedia.org/wiki/Exchangeable_image_file_format | |
const JPEG_CHKS = [[0, 3, new Buffer("ffd8ff", "hex")], [-2, 2, new Buffer("ffd9", "hex")]]; | |
// https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header | |
const PNG_CHKS = [[0, 8, new Buffer("89504e470d0a1a0a", "hex")]]; | |
// https://en.wikipedia.org/wiki/GIF#File_format | |
const GIF87_CHKS = [[0, 6, new Buffer("GIF87a", "utf8")]]; | |
const GIF89_CHKS = [[0, 6, new Buffer("GIF89a", "utf8")]]; | |
const XML_CHKS = [[0, 5, new Buffer("<?xml", "utf8")]]; | |
function get_file_type(f, s){ | |
if(chk_bytes(f, s, JPEG_CHKS)){ | |
return "jpg"; | |
}else if(chk_bytes(f, s, PNG_CHKS)){ | |
return "png"; | |
}else if(chk_bytes(f, s, GIF87_CHKS)||chk_bytes(f, s, GIF89_CHKS)){ | |
return "gif"; | |
}else if(chk_bytes(f, s, XML_CHKS)){ | |
return "xml"; | |
}else{ | |
return null; | |
} | |
} | |
function cp(src, dst){ | |
fs.createReadStream(src).pipe(fs.createWriteStream(dst)); | |
} | |
function spotlight_export(spotlight_path, stage_path, export_path){ | |
var list_src = [], list_src_wtype = []; | |
fs.readdirSync(spotlight_path).forEach(function(n){ | |
var p = path.join(spotlight_path, n); | |
var f = fs.openSync(p, "r"); | |
var s = fs.fstatSync(f); | |
if(s.isFile()){ | |
var ft = get_file_type(f, s.size); | |
if(ft != null){ | |
if(FILE_TYPES.indexOf(ft) != -1 && s.size >= MIN_SIZE){ | |
list_src.push(n); | |
list_src_wtype.push(n + "." + ft); | |
} | |
}else{ | |
console.error("unknown file type:", n); | |
} | |
} | |
fs.closeSync(f); | |
}); | |
var list_stage = fs.readdirSync(stage_path).filter(function(n){ | |
var p = path.join(stage_path, n); | |
if(!fs.statSync(p).isFile()){ | |
return false; | |
} | |
// windows might shit things like "desktop.ini"/"thumbs.db" here | |
return FILE_TYPES.indexOf(path.extname(n)) != -1; | |
}); | |
list_src_wtype.forEach(function(n, i){ | |
if(list_stage.indexOf(n) == -1){ | |
console.error("copy to stage: " + n); | |
cp(path.join(spotlight_path, list_src[i]), path.join(stage_path, n)); | |
} | |
}); | |
list_stage.forEach(function(n){ | |
if(list_src_wtype.indexOf(n) == -1){ | |
console.error("move to export: " + n); | |
fs.renameSync(path.join(stage_path, n), path.join(export_path, n)); | |
} | |
}); | |
} | |
if(process.argv.length == 4){ | |
var spotlight_path = path.join(process.env["LOCALAPPDATA"], | |
"\\Packages\\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\\LocalState\\Assets"); | |
var stage_path = process.argv[2]; | |
var export_path = process.argv[3]; | |
spotlight_export(spotlight_path, stage_path, export_path); | |
}else{ | |
console.error("example:\n\tnode spotlight-export.js \"D:\Pictures\Spotlight stage\" \"D:\Pictures\Spotlight export\""); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment