Download Jar. Libraryless. Click here for Pure Java version (11787L/83K).
1 | !7 |
2 | |
3 | static int id = 5000000; |
4 | |
5 | concept ImageMeta {
|
6 | int imageID; |
7 | S name; |
8 | S md5; // md5 of RGBImage |
9 | S format = "png"; |
10 | |
11 | *() {}
|
12 | *(int *imageID, S *name) { _doneLoading(); change(); }
|
13 | |
14 | void _doneLoading() {
|
15 | //print("_doneLoading " + imageID);
|
16 | metaMap.put(imageID, this); |
17 | } |
18 | |
19 | S mimeType() {
|
20 | ret "image/" + or2(format, "png"); |
21 | } |
22 | } |
23 | |
24 | static Map<Int, ImageMeta> metaMap = synchroMap(); |
25 | |
26 | p {
|
27 | load("id");
|
28 | dbIndexing(ImageMeta, 'imageID, ImageMeta, 'md5); |
29 | for (ImageMeta meta) |
30 | setMD5(meta); |
31 | botWithCommandList("Image DB.");
|
32 | } |
33 | |
34 | svoid setMD5(ImageMeta meta) {
|
35 | if (nempty(meta.md5)) ret; |
36 | S md5 = "error"; |
37 | pcall {
|
38 | md5 = md5OfTransparentImage(loadPNG(imageFile(meta.imageID))); |
39 | } |
40 | cset(meta, +md5); |
41 | } |
42 | |
43 | static File imagesDir() {
|
44 | ret prepareProgramDir("images");
|
45 | } |
46 | |
47 | synchronized html {
|
48 | print("uri: " + uri);
|
49 | uri = dropPrefix("/", uri);
|
50 | |
51 | if (eq(uri, "setp0rn")) {
|
52 | setPornFlag(parseInt(params.get("id")), true);
|
53 | ret "OK"; |
54 | } |
55 | |
56 | if (eq(uri, "unp0rn")) {
|
57 | setPornFlag(parseInt(params.get("id")), false);
|
58 | ret "OK"; |
59 | } |
60 | |
61 | bool p0rnOK = false; |
62 | |
63 | if (uri.endsWith("p") && isInteger(dropLast(uri))) {
|
64 | p0rnOK = true; |
65 | uri = dropLast(uri); |
66 | } |
67 | |
68 | if (eq(uri, "random-id")) |
69 | ret random(list(ImageMeta)).imageID; |
70 | |
71 | if (uri.startsWith("title/")) {
|
72 | int id = parseFirstInt(uri); |
73 | ImageMeta meta = findConcept(ImageMeta, imageID := id); |
74 | ret meta == null ? "" : meta.name; |
75 | } |
76 | |
77 | if (isInteger(uri)) {
|
78 | // serve image |
79 | |
80 | int id = parseInt(uri); |
81 | File file = imageFile(id); |
82 | ImageMeta meta = findConcept(ImageMeta, imageID := id); |
83 | if (meta == null) |
84 | ret "Not found"; |
85 | if (!p0rnOK && isPornFlag(id)) |
86 | ret "n0 p0rn"; |
87 | ret call(getMainBot(), "serveFile_maxCache", imageFile(meta.imageID), meta.mimeType()); |
88 | } |
89 | |
90 | if (uri.startsWith("md5/")) {
|
91 | uri = dropPrefix("md5/", uri);
|
92 | bool jpg = uri.startsWith("jpg/");
|
93 | if (jpg) uri = dropPrefix("jpg/", uri);
|
94 | ImageMeta meta = findConcept(ImageMeta, md5 := uri); |
95 | if (meta == null) |
96 | ret "Not found"; |
97 | if (jpg && neq(meta.format, "jpeg")) |
98 | ret call(getMainBot(), "serveByteArray_maxCache", toJPEG(imageFile(meta.imageID)), "image/jpeg"); |
99 | ret call(getMainBot(), "serveFile_maxCache", imageFile(meta.imageID), meta.mimeType()); |
100 | } |
101 | |
102 | if (uri.startsWith("checkmd5/")) {
|
103 | uri = dropPrefix("checkmd5/", uri);
|
104 | ImageMeta meta = findConcept(ImageMeta, md5 := uri); |
105 | ret meta == null ? "Not found" : str(meta.imageID); |
106 | } |
107 | |
108 | if (eq(uri, "upload")) {
|
109 | print("upload called");
|
110 | S name = params.get("name");
|
111 | |
112 | SS files = getUploadFiles(); |
113 | print("got files: " + l(files));
|
114 | int id; |
115 | S data = params.get("data");
|
116 | if (data != null) {
|
117 | print("got data: " + l(data));
|
118 | id = newImageID(); |
119 | saveBinaryFile(imageFile(id), hexToBytes(data)); |
120 | } else {
|
121 | String tmpfile = files.get("thefile");
|
122 | String originalName = params.get("thefile");
|
123 | name = or2(name, originalName); |
124 | assertNotNull(tmpfile); |
125 | File tmp = new File(tmpfile); |
126 | long l = tmp.length(); |
127 | if (l == 0) ret "Empty file, exiting"; |
128 | id = newImageID(); |
129 | copyFile(tmp, imageFile(id)); |
130 | } |
131 | saveImageMeta(id, name); |
132 | ret "OK:<br>" + himg(rawLink(str(id))); |
133 | } |
134 | |
135 | if (eq(uri, "uploadform")) {
|
136 | ret htitle("Upload")
|
137 | + hmobilefix() |
138 | + huploadform( |
139 | "Image file: " + hfileupload("accept", "image/png,image/jpeg") + " "
|
140 | + "<br>" |
141 | + "Optional name: " + hinputfield("name")
|
142 | + hsubmit(), |
143 | "action", rawLink("upload"));
|
144 | } |
145 | |
146 | if (eq(uri, "")) {
|
147 | // list images |
148 | |
149 | new L<int> ids; |
150 | for (File f : listFiles(imagesDir())) try {
|
151 | S s = dropSuffix(".png", f.getName());
|
152 | if (!isInteger(s)) continue; |
153 | int id = parseInt(s); |
154 | if (!isPornFlag(id)) |
155 | ids.add(id); |
156 | } catch e {
|
157 | silentException(e); |
158 | } |
159 | sortListDesc(ids); |
160 | ret p(n(ids, "N0n-p0rn image") + ":") + ul(map(ids, func(int id) {
|
161 | ImageMeta meta = metaMap.get(id); |
162 | S title = or2(getString(meta, "name"), "Untitled"); |
163 | S linkText = "#" + id + " - " + htmlencode(title); |
164 | S s = ahref(rawLink(str(id)), linkText); |
165 | if (meta != null) |
166 | s += " [md5: " + ahref(rawLink("md5/" + meta.md5), meta.md5) + "]";
|
167 | ret s; |
168 | })) + p(ahref(pageLink("/uploadform"), "Upload."));
|
169 | } |
170 | |
171 | null; |
172 | } |
173 | |
174 | static synchronized int newImageID() {
|
175 | while (imageFile(id).exists()) |
176 | ++id; |
177 | int i = id++; |
178 | save("id");
|
179 | ret i; |
180 | } |
181 | |
182 | static File imageFile(ImageMeta meta) {
|
183 | ret meta == null ? null : imageFile(meta.imageID); |
184 | } |
185 | |
186 | static File imageFile(int id) {
|
187 | ret new File(imagesDir(), id + ".png"); |
188 | } |
189 | |
190 | static void setPornFlag(int id, bool flag) {
|
191 | saveTextFile(new File(imagesDir(), id + ".p0rn"), flag ? "t" : null); |
192 | } |
193 | |
194 | static bool isPornFlag(int id) {
|
195 | ret eq("t", readTextFile(new File(imagesDir(), id + ".p0rn")));
|
196 | } |
197 | |
198 | answer {
|
199 | if "add image from web *" {
|
200 | S url = $1; |
201 | BufferedImage img = loadImage2(url); |
202 | S md5 = md5OfTransparentImage(img); |
203 | ImageMeta meta = findConcept(ImageMeta, +md5); |
204 | if (meta == null) {
|
205 | int id = newImageID(); |
206 | saveBinaryFile(imageFile(id), toPNG(img)); |
207 | meta = saveImageMeta(id, url); |
208 | } |
209 | ret "OK " + meta.imageID; |
210 | } |
211 | |
212 | if "add image data * with name *" {
|
213 | int id = newImageID(); |
214 | saveBinaryFile(imageFile(id), hexToBytes($1)); |
215 | saveImageMeta(id, $2); |
216 | ret "OK " + id; |
217 | } |
218 | |
219 | if "get image path *" {
|
220 | int id = parseInt($1); |
221 | if (!hasConcept(ImageMeta, imageID := id)) ret "Not found"; |
222 | ret format("OK *", f2s(imageFile(id)));
|
223 | } |
224 | if "number of images" ret str(countConcepts(ImageMeta)); |
225 | if "md5 * to image id" {
|
226 | ImageMeta meta = findConcept(ImageMeta, md5 := $1); |
227 | ret meta != null ? "OK " + meta.imageID : "Not found"; |
228 | } |
229 | if "image * info" |
230 | ret renderConcept(findConcept(ImageMeta, imageID := parseInt($1))); |
231 | if "show image *" {
|
232 | ImageMeta meta = findImage($1); |
233 | if (meta == null) ret "Not found"; |
234 | showImage("Image #" + meta.imageID
|
235 | + " - " + or2(meta.name, "Untitled"), loadImage2(imageFile(meta.imageID))); |
236 | ret "OK"; |
237 | } |
238 | if "all image ids" |
239 | ret "OK " + struct(collect(list(ImageMeta), 'imageID)); |
240 | if "data size" // size of all images and meta data (including backups) |
241 | ret "OK " + guessClusteredDirSize(programDir()); |
242 | if "delete image *" {
|
243 | ImageMeta meta = findImage($1); |
244 | if (meta == null) ret "Not found"; |
245 | deleteFile(imageFile(meta)); |
246 | deleteConcept(meta); |
247 | ret "OK, deleted"; |
248 | } |
249 | } |
250 | |
251 | static ImageMeta saveImageMeta(int id, S name) {
|
252 | ImageMeta meta = new(id, unnull(name)); |
253 | byte[] bytes = loadBeginningOfBinaryFile(imageFile(id), 16); |
254 | cset(meta, format := isJPEG(bytes) ? "jpeg" /* correct for mime type! */ : isPNG(bytes) ? "png" : null); |
255 | setMD5(meta); |
256 | ret meta; |
257 | } |
258 | |
259 | static ImageMeta findImage(S s) {
|
260 | if (possibleMD5(s)) |
261 | ret findConcept(ImageMeta, md5 := s); |
262 | else if (isInteger(s)) |
263 | ret findConcept(ImageMeta, imageID := parseInt(s)); |
264 | fail("Not an image ID or MD5: " + s);
|
265 | } |
Began life as a copy of #1004590
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1010165 |
| Snippet name: | Local Image DB [OK] |
| Eternal ID of this version: | #1010165/22 |
| Text MD5: | 4a7401e6c8d239b26f6118d53844271e |
| Transpilation MD5: | 11f09e604fb96be019432d783abbee10 |
| Author: | stefan |
| Category: | javax |
| Type: | JavaX source code (desktop) |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2017-09-05 20:32:47 |
| Source code size: | 7338 bytes / 265 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 720 / 2661 |
| Version history: | 21 change(s) |
| Referenced in: | [show references] |