Browse Source

first commit

pull/2/head
asiekierka 7 years ago
commit
f9e7e62714

+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
img
node_modules
private

+ 128
- 0
app.js View File

@@ -0,0 +1,128 @@
var express = require('express')
, mkdirp = require('mkdirp')
, _ = require('underscore')
, fs = require('fs')
, JSON = require('JSON2')
, imageDB = require('./imagedb.js').ImageDB
, im = require('imagemagick')
, program = require('commander')
, path = require('path')
, qs = require('querystring');

var app = express()
, config = require('./config.json')
, templates = {};

var defaultImage = { author: "Unknown", source: "/", uploader: "Computer" };

_.each(fs.readdirSync("templates/"),function(filename) {
var name = filename.split(".")[0];
console.log("[Template] Loading template "+name);
templates[name] = fs.readFileSync("templates/"+filename,"utf8");
});

function fileExt(name) {
var ext = path.extname(name).split(".");
return ext[ext.length-1];
}

var thumbW = 300, thumbH = 300;

function resize(src,dest,w,h) {
var cnf = { srcPath: src, dstPath: dest,
width: w, height: h+"^",
customArgs: [ "-gravity", "center", "-extent", w+"x"+h ] };
im.resize(cnf,null);
}

function thumbnail(src,dest,dest2x) {
resize(src,dest,thumbW,thumbH);
if(_.isString(dest2x))
resize(src,dest2x,thumbW*2,thumbH*2);
}

function addImage(rawdata,format,info) {
imageDB.count("imageId",function(err,id) {
var path = id+"."+format;
fs.writeFile("img/src/"+path,rawdata,"utf8",function() {
im.identify("img/src/"+path, function(err,features) {
if(err) throw err;
var data = { id: id, format: format, filename: path, originalName: info.filename,
width: features.width, height: features.height,
tags: info.tags, uploader: info.uploader, author: info.author};
imageDB.set(id,_.defaults(data,defaultImage));
});
thumbnail("img/src/"+path,"img/thumb/"+path,"img/thumb2x/"+path);
});
});
}

function makeRawTemplate(name,conf,noHeader) {
var conf2 = _.defaults(conf,config);
var body = _.template(templates[name],conf2);
if(!noHeader)
body = _.template(templates["header"],conf2) + body;
return body;
}
function makeTemplate(name,conf,raw,noHeader) {
if(raw=="raw") return makeRawTemplate(name,conf,noHeader);
var conf2 = _.defaults(conf,config);
return _.template(templates["main"],_.defaults(conf2,{page: makeRawTemplate(name,conf,noHeader)}));
}

// Create missing directories (just in case)
mkdirp.sync("img/src");
mkdirp.sync("img/thumb");
mkdirp.sync("img/thumb2x");

// Load directory dependencies
app.use("/static/",express.static("bootstrap"));
app.use("/static/",express.static("static"));
app.use("/img/",express.static("img"));
app.use("/img/thumb/", function(req,res) { res.redirect("/static/img/thumbnotfound.png"); });
app.use("/img/thumb2x/", function(req,res) { res.redirect("/static/img/thumbnotfound.png"); });
app.use("/upload/",express.basicAuth("test","test"));
app.use("/upload/",function(req,res) {
var p = qs.unescape(req.path).split("/");
res.send(makeTemplate("upload",{title: "Boorushy Upload"},p[1]));
});
app.use("/image/",function(req,res) {
var p = qs.unescape(req.path).split("/");
if(!p[1]) res.send(500);
imageDB.get(p[1],function(data) {
res.send(makeTemplate("view",{image: _.defaults(data, defaultImage), title: "Boorushy v.2"},p[2]));
});
});
function listImages(res,images1,p,p2) {
var start = parseInt(p) || 0;
var isRaw = p2 || false;
var noHeader = false;
if(parseInt(p)==NaN) { start = 0; isRaw = p; }
console.log("listImages: " + start + " " + isRaw);
imageDB.range(images1,start,config.pageSize,function(images2) {
var conf = {images: images2, position: start, maxpos: images1.length, title: "Boorushy v.2"};
var imagesLi = makeRawTemplate("images-li",conf,"raw",true);
conf.imagesLi = imagesLi;
if(isRaw == "append") res.send(conf.imagesLi);
else res.send(makeTemplate("images",conf,isRaw,noHeader));
});
}
app.use("/",function(req,res) {
var p = qs.unescape(req.path).split("/");
console.log("Request: " + JSON.stringify(p));
if(p.length>2 && (p[1] == "tag" || p[1] == "author" || p[1] == "uploader")) imageDB.imagesBy(p[1],p[2],function(images) { listImages(res,images,p[3],p[4]); });
else imageDB.images(function(images) { listImages(res,images,p[1],p[2]); });
});

imageDB.connect();
app.listen(config.port);
console.log("Working on port " + config.port);

program.version("0.0.1");
program.command("add [file]")
.description("add file to db")
.action(function(filename){
addImage(fs.readFileSync(filename),fileExt(filename),{tags: ["test","less tests"],filename: filename});
});

program.parse(process.argv);

+ 1109
- 0
bootstrap/css/bootstrap-responsive.css
File diff suppressed because it is too large
View File


+ 9
- 0
bootstrap/css/bootstrap-responsive.min.css
File diff suppressed because it is too large
View File


+ 6158
- 0
bootstrap/css/bootstrap.css
File diff suppressed because it is too large
View File


+ 9
- 0
bootstrap/css/bootstrap.min.css
File diff suppressed because it is too large
View File


+ 2268
- 0
bootstrap/js/bootstrap.js
File diff suppressed because it is too large
View File


+ 6
- 0
bootstrap/js/bootstrap.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
config.json View File

@@ -0,0 +1 @@
{ "port": 8080, "pageSize": 8 }

+ 113
- 0
imagedb.js View File

@@ -0,0 +1,113 @@
var ImageDB = {}
, redis = require("redis")
, _ = require("underscore")
, JSON = require("JSON2")
, async = require("async");

var client = null;

ImageDB.connect = function(port,host,options) {
client = redis.createClient(port || null,host || null,options || {});
}

ImageDB.get = function(id,callback) {
client.get("data:"+id,function(err,out) {
if(err) throw err;
callback(JSON.parse(out));
});
}
ImageDB.getWithError = function(id,callback) {
client.get("data:"+id,function(err,out) {
callback(err,JSON.parse(out));
});
}

ImageDB.exists = function(id,cb) { return client.exists(client,"data:"+id,cb); }

ImageDB.addField = function(id,key,val) {
client.sadd(key+"s",val);
client.sadd(key+":"+val,id);
}
ImageDB.delField = function(id,key,val) {
client.srem(key+":"+val,id);
client.scard(key+":"+val, function(err,m) {
if(err) throw err;
if(m>0) return;
client.del(key+":"+val);
client.srem(key+"s",val);
});
}

ImageDB.tags = function(callback) {
client.smembers("tags", function(err,m) {
if(err) throw err;
if(_.isNull(m)) callback(new Array());
else callback(m.sort());
});
}
ImageDB.images = function(callback) {
client.smembers("images", function(err,m){
if(err) throw err;
if(_.isNull(m)) callback(new Array());
else callback(_.sortBy(m,function(num){ return 0-num; }));
});
}
ImageDB.imagesBy = function(key,val,callback) {
client.smembers(key+":"+val, function(err,m){
if(err) throw err;
if(_.isNull(m)) callback(new Array());
else callback(_.sortBy(m,function(num){ return 0-num; }));
});
}
ImageDB.range = function(arr2,s,l,callback) {
var out = new Array();
var arr = arr2;
if(_.isNumber(arr2)) arr = new Array(arr2);
arr = _.first(_.rest(arr,s),l);
async.map(arr,this.getWithError,function(err, results) {
if(err) throw err;
callback(results);
});
}

ImageDB.count = function(name,callback) {
client.setnx("counter:"+name,0);
client.incr("counter:"+name,callback);
}
ImageDB.uncount = function(name,callback) {
client.setnx("counter:"+name,0);
client.decr("counter:"+name,callback);
}
ImageDB.add = function(data,callback) {
this.count("imageId",function(count) {
this.set(count,data);
if(_.isFunction(callback))
callback(count);
});
}
ImageDB.set = function(id,data) {
data.id = id;
client.set("data:"+id,JSON.stringify(data));
client.sadd("images",id);
var t = this;
_.each(data.tags,function(tag) { t.addField(id,"tag",tag); });
if(_.isString(data.author))
this.addField(id,"author",data.author);
if(_.isString(data.uploader))
this.addField(id,"uploader",data.uploader);
}

ImageDB.unset = function(id) {
this.get(id,function(data) {
client.del("data:"+id);
client.srem("images",id);
var t = this;
_.each(data.tags,function(tag) { t.delField(id,"tag",tag); });
if(_.isString(data.author))
this.delField(id,"author",data.author);
if(_.isString(data.uploader))
this.delField(id,"uploader",data.uploader);
});
}

exports.ImageDB = ImageDB;

+ 16
- 0
package.json View File

@@ -0,0 +1,16 @@
{
"name": "boorushy2",
"description": "boorushy engine",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "3.x",
"JSON2": "0.1.x",
"underscore": "1.4.x",
"mkdirp": "0.3.x",
"commander": "1.1.x",
"redis": "0.8.x",
"imagemagick": "0.1.x",
"async": ">=0.2.5"
}
}

+ 5
- 0
static/js/jquery-1.9.1.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
static/js/underscore-min.js
File diff suppressed because it is too large
View File


+ 5
- 0
templates/header.html View File

@@ -0,0 +1,5 @@
<div class="row padded-row">
<div class="span12" style="text-align: center;">
<h1>Boorushy<sub>2</sub></h1>
</div>
</div>

+ 4
- 0
templates/images-li.html View File

@@ -0,0 +1,4 @@
<% _.each(images, function(img) {
print('<li class="span4"><a href="/image/'+img.id+'/" class="thumbnail">');
print('<img src="/img/thumb/'+img.filename+'" class="to-retinize"></a></li>');
}); %>

+ 40
- 0
templates/images.html View File

@@ -0,0 +1,40 @@
<div class="row padded-row">
<ul class="thumbnails">
<%= imagesLi %>
</ul>
<script type="text/javascript">
// Retinizer!
function retinize() {
if(window.devicePixelRatio>=1.5)
$("img.to-retinize").each(function(idx) {
var mSrc = $(this).attr("src");
if(mSrc.indexOf("thumb2x")<0)
$(this).attr("src",mSrc.replace("thumb","thumb2x"));
$(this).removeClass("to-retinize");
});
}
function pageLoad() {
retinize();
var position = <%= position %>;
var maxpos = <%= maxpos %>;
var pageSize = <%= pageSize %>;
var dwh = $(document).height() - $(window).height() - 300;
var update = function() {
if(position+pageSize < maxpos && $(window).scrollTop() >= dwh) {
position = position + pageSize;
$.get(position + "/append/",function(data) {
$("ul.thumbnails").append(data);
retinize();
setTimeout(update,50); // In case of huge scrollings
});
}
};
$(window).scroll(update);
update();
}
function pageUnload() {
$(window).unbind("scroll");
}
</script>
</div>

+ 59
- 0
templates/main.html View File

@@ -0,0 +1,59 @@
<html>
<head>
<title><%= title %></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/static/css/bootstrap.min.css" rel="stylesheet" media="screen">
<style>
.padded-row {
margin-top: 20px;
}
body {
background-color: #F4F2F0;
}
.thumbnail {
background-color: #FFF;
}
h1 {
color: #222;
}
</style>
</head>
<body>
<script src="/static/js/jquery-1.9.1.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<script src="/static/js/underscore-min.js"></script>
<div class="container" id="page-inject"><%= page %></div>
<script>
function redirect(url,noPush) {
console.log("Redirecting to " + url);
var url2 = url + "raw/";
if(url.substr(url.length-1,1)!="/") url2 = url + "/raw/";
$.get(url2, function(data) {
history.replaceState({currentUrl: location.pathname}, "", location.pathname);
if(!noPush) history.pushState({currentUrl: url}, "", url);
pageUnload();
$("#page-inject").html(data);
$("a").click(changeView);
pageLoad();
});
}
function changeView(ev) {
ev.preventDefault();
redirect($(this).attr("href"));
}

window.onpopstate = function(event) {
if(event.state && typeof(event.state.currentUrl) == "string")
redirect(event.state.currentUrl,true);
}

// ChangeViewize URLs
$("a").each(function(idx) {
var href = $(this).attr("href");
if(href.indexOf("/src/")<0)
$(this).click(changeView);
});
pageLoad();
</script>
</body>
</html>

+ 1
- 0
templates/upload.html View File

@@ -0,0 +1 @@
Hi!

+ 28
- 0
templates/view.html View File

@@ -0,0 +1,28 @@
<div class="row padded-row">
<div class="span12" style="text-align: center;">
<a href="/img/src/<%= image.filename %>">
<img src="/img/src/<%= image.filename %>" style="max-width: 100%; height: auto;" class="img-polaroid to-resize">
</a><br><br>
Tags: <%
var t = 0;
_.each(image.tags,function(v) {
if(t>0) print(', ');
print('<a href="/tag/'+v+'/">'+v+'</a>');
t+=1;
});
%><br>
Author: <a href="/author/<%= image.author %>/"><%= image.author %></a> (<a href="<%= image.source %>">Source</a>)<br>
Uploaded by <a href="/uploader/<%= image.uploader %>/"><%= image.uploader %></a>
</div>
<script type="text/javascript">
function pageLoad() {
var winh = $(window).height()*0.8;
$("img.to-resize").load(function(){
var h = $(this).height();
if(h>winh)
$(this).attr("style","width: auto; max-height: 80%;");
});
}
function pageUnload() { }
</script>
</div>

Loading…
Cancel
Save