!7 static int id = 5000000; concept ImageMeta { int imageID; S name; S md5; // md5 of RGBImage S format = "png"; *() {} *(int *imageID, S *name) { _doneLoading(); change(); } void _doneLoading() { //print("_doneLoading " + imageID); metaMap.put(imageID, this); } S mimeType() { ret "image/" + or2(format, "png"); } } static Map metaMap = synchroMap(); p { load("id"); dbIndexing(ImageMeta, 'imageID, ImageMeta, 'md5); for (ImageMeta meta) setMD5(meta); botWithCommandList("Image DB."); } svoid setMD5(ImageMeta meta) { if (nempty(meta.md5)) ret; S md5 = "error"; pcall { md5 = md5OfTransparentImage(loadPNG(imageFile(meta.imageID))); } cset(meta, +md5); } static File imagesDir() { ret prepareProgramDir("images"); } synchronized html { print("uri: " + uri); uri = dropPrefix("/", uri); if (eq(uri, "setp0rn")) { setPornFlag(parseInt(params.get("id")), true); ret "OK"; } if (eq(uri, "unp0rn")) { setPornFlag(parseInt(params.get("id")), false); ret "OK"; } bool p0rnOK = false; if (uri.endsWith("p") && isInteger(dropLast(uri))) { p0rnOK = true; uri = dropLast(uri); } if (eq(uri, "random-id")) ret random(list(ImageMeta)).imageID; if (uri.startsWith("title/")) { int id = parseFirstInt(uri); ImageMeta meta = findConcept(ImageMeta, imageID := id); ret meta == null ? "" : meta.name; } if (isInteger(uri)) { // serve image int id = parseInt(uri); File file = imageFile(id); ImageMeta meta = findConcept(ImageMeta, imageID := id); if (meta == null) ret "Not found"; if (!p0rnOK && isPornFlag(id)) ret "n0 p0rn"; ret call(getMainBot(), "serveFile_maxCache", imageFile(meta.imageID), meta.mimeType()); } if (uri.startsWith("md5/")) { uri = dropPrefix("md5/", uri); bool jpg = uri.startsWith("jpg/"); if (jpg) uri = dropPrefix("jpg/", uri); ImageMeta meta = findConcept(ImageMeta, md5 := uri); if (meta == null) ret "Not found"; if (jpg && neq(meta.format, "jpeg")) ret call(getMainBot(), "serveByteArray_maxCache", toJPEG(imageFile(meta.imageID)), "image/jpeg"); ret call(getMainBot(), "serveFile_maxCache", imageFile(meta.imageID), meta.mimeType()); } if (uri.startsWith("checkmd5/")) { uri = dropPrefix("checkmd5/", uri); ImageMeta meta = findConcept(ImageMeta, md5 := uri); ret meta == null ? "Not found" : str(meta.imageID); } if (eq(uri, "upload")) { print("upload called"); S name = params.get("name"); SS files = getUploadFiles(); print("got files: " + l(files)); int id; S data = params.get("data"); if (data != null) { print("got data: " + l(data)); id = newImageID(); saveBinaryFile(imageFile(id), hexToBytes(data)); } else { String tmpfile = files.get("thefile"); String originalName = params.get("thefile"); name = or2(name, originalName); assertNotNull(tmpfile); File tmp = new File(tmpfile); long l = tmp.length(); if (l == 0) ret "Empty file, exiting"; id = newImageID(); copyFile(tmp, imageFile(id)); } saveImageMeta(id, name); ret "OK:
" + himg(rawLink(str(id))); } if (eq(uri, "uploadform")) { ret htitle("Upload") + hmobilefix() + huploadform( "Image file: " + hfileupload("accept", "image/png,image/jpeg") + " " + "
" + "Optional name: " + hinputfield("name") + hsubmit(), "action", rawLink("upload")); } if (eq(uri, "")) { // list images new L ids; for (File f : listFiles(imagesDir())) try { S s = dropSuffix(".png", f.getName()); if (!isInteger(s)) continue; int id = parseInt(s); if (!isPornFlag(id)) ids.add(id); } catch e { silentException(e); } sortListDesc(ids); ret p(n(ids, "N0n-p0rn image") + ":") + ul(map(ids, func(int id) { ImageMeta meta = metaMap.get(id); S title = or2(getString(meta, "name"), "Untitled"); S linkText = "#" + id + " - " + htmlencode(title); S s = ahref(rawLink(str(id)), linkText); if (meta != null) s += " [md5: " + ahref(rawLink("md5/" + meta.md5), meta.md5) + "]"; ret s; })) + p(ahref(pageLink("/uploadform"), "Upload.")); } null; } static synchronized int newImageID() { while (imageFile(id).exists()) ++id; int i = id++; save("id"); ret i; } static File imageFile(ImageMeta meta) { ret meta == null ? null : imageFile(meta.imageID); } static File imageFile(int id) { ret new File(imagesDir(), id + ".png"); } static void setPornFlag(int id, bool flag) { saveTextFile(new File(imagesDir(), id + ".p0rn"), flag ? "t" : null); } static bool isPornFlag(int id) { ret eq("t", readTextFile(new File(imagesDir(), id + ".p0rn"))); } answer { if "add image from web *" { S url = $1; BufferedImage img = loadImage2(url); S md5 = md5OfTransparentImage(img); ImageMeta meta = findConcept(ImageMeta, +md5); if (meta == null) { int id = newImageID(); saveBinaryFile(imageFile(id), toPNG(img)); meta = saveImageMeta(id, url); } ret "OK " + meta.imageID; } if "add image data * with name *" { int id = newImageID(); saveBinaryFile(imageFile(id), hexToBytes($1)); saveImageMeta(id, $2); ret "OK " + id; } if "get image path *" { int id = parseInt($1); if (!hasConcept(ImageMeta, imageID := id)) ret "Not found"; ret format("OK *", f2s(imageFile(id))); } if "number of images" ret str(countConcepts(ImageMeta)); if "md5 * to image id" { ImageMeta meta = findConcept(ImageMeta, md5 := $1); ret meta != null ? "OK " + meta.imageID : "Not found"; } if "image * info" ret renderConcept(findConcept(ImageMeta, imageID := parseInt($1))); if "show image *" { ImageMeta meta = findImage($1); if (meta == null) ret "Not found"; showImage("Image #" + meta.imageID + " - " + or2(meta.name, "Untitled"), loadImage2(imageFile(meta.imageID))); ret "OK"; } if "all image ids" ret "OK " + struct(collect(list(ImageMeta), 'imageID)); if "data size" // size of all images and meta data (including backups) ret "OK " + guessClusteredDirSize(programDir()); if "delete image *" { ImageMeta meta = findImage($1); if (meta == null) ret "Not found"; deleteFile(imageFile(meta)); deleteConcept(meta); ret "OK, deleted"; } } static ImageMeta saveImageMeta(int id, S name) { ImageMeta meta = new(id, unnull(name)); byte[] bytes = loadBeginningOfBinaryFile(imageFile(id), 16); cset(meta, format := isJPEG(bytes) ? "jpeg" /* correct for mime type! */ : isPNG(bytes) ? "png" : null); setMD5(meta); ret meta; } static ImageMeta findImage(S s) { if (possibleMD5(s)) ret findConcept(ImageMeta, md5 := s); else if (isInteger(s)) ret findConcept(ImageMeta, imageID := parseInt(s)); fail("Not an image ID or MD5: " + s); }