.
This commit is contained in:
		
							
								
								
									
										34
									
								
								debug/trigger.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								debug/trigger.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
import { promises as fs } from "fs";
 | 
			
		||||
 | 
			
		||||
(async () => {
 | 
			
		||||
  const _args = process.argv.slice(2);
 | 
			
		||||
  const _e = {
 | 
			
		||||
    network: "console",
 | 
			
		||||
    message: _args.join(" "),
 | 
			
		||||
    args: _args.slice(1),
 | 
			
		||||
    channel: "console",
 | 
			
		||||
    user: {
 | 
			
		||||
      prefix: "console!console@console",
 | 
			
		||||
      nick: "console",
 | 
			
		||||
      username: "console",
 | 
			
		||||
      account: "console"
 | 
			
		||||
    },
 | 
			
		||||
    reply: (...args) => console.log(args),
 | 
			
		||||
    replyAction: (...args) => console.log(args),
 | 
			
		||||
    replyNotice: (...args) => console.log(args)
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const trigger = (await Promise.all((await fs.readdir("./src/inc/trigger"))
 | 
			
		||||
    .filter(f => f.endsWith(".mjs"))
 | 
			
		||||
    .map(async t => await (await import(`../src/inc/trigger/${t}`)).default())
 | 
			
		||||
  )).filter(t => t[0].call.test(_e.message)).map(t => ({ name: t[0].name, f: t[0].f }));
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    if(trigger.length === 0)
 | 
			
		||||
      return console.error("no matches");
 | 
			
		||||
    console.log(`triggered > ${trigger[0].name} (${_e.message})`);
 | 
			
		||||
    await trigger[0].f(_e);
 | 
			
		||||
  } catch(err) {
 | 
			
		||||
    console.error(err);
 | 
			
		||||
  }
 | 
			
		||||
})();
 | 
			
		||||
							
								
								
									
										107
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										107
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -10,38 +10,18 @@
 | 
			
		||||
      "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/node": {
 | 
			
		||||
      "version": "13.9.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.8.tgz",
 | 
			
		||||
      "integrity": "sha512-1WgO8hsyHynlx7nhP1kr0OFzsgKz5XDQL+Lfc3b1Q3qIln/n8cKD4m09NJ0+P1Rq7Zgnc7N0+SsMnoD1rEb0kA=="
 | 
			
		||||
    },
 | 
			
		||||
    "amdefine": {
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
 | 
			
		||||
    },
 | 
			
		||||
    "async": {
 | 
			
		||||
      "version": "0.2.10",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
 | 
			
		||||
      "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
 | 
			
		||||
    },
 | 
			
		||||
    "camelcase": {
 | 
			
		||||
      "version": "1.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
 | 
			
		||||
      "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
 | 
			
		||||
      "version": "13.11.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz",
 | 
			
		||||
      "integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "cuffeo": {
 | 
			
		||||
      "version": "1.0.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cuffeo/-/cuffeo-1.0.6.tgz",
 | 
			
		||||
      "integrity": "sha512-TdrkkDM4uR/iTEtazfxbmLUXoNB3NLC/RMgpWVUQC8j2uOiaLl7U7agdLdxfJq4uEt56cJUftqH9Tb3BofslNg==",
 | 
			
		||||
      "version": "1.0.6-1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cuffeo/-/cuffeo-1.0.6-1.tgz",
 | 
			
		||||
      "integrity": "sha512-r7MCG7rIuG86leo4aB73YEkl7UWAGprd2A/9xy4iZmrbMepIFaCgHOn7SC6wemPbS4LRXQAgqvV9a6PCyHaCfg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "flumm-fetch-cookies": "^1.3.5"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "decamelize": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
 | 
			
		||||
    },
 | 
			
		||||
    "denque": {
 | 
			
		||||
      "version": "1.4.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
 | 
			
		||||
@@ -86,11 +66,6 @@
 | 
			
		||||
        "moment-timezone": "^0.5.27"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "minimist": {
 | 
			
		||||
      "version": "0.0.10",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
 | 
			
		||||
      "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
 | 
			
		||||
    },
 | 
			
		||||
    "moment": {
 | 
			
		||||
      "version": "2.24.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
 | 
			
		||||
@@ -104,80 +79,10 @@
 | 
			
		||||
        "moment": ">= 2.9.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "optimist": {
 | 
			
		||||
      "version": "0.6.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
 | 
			
		||||
      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "minimist": "~0.0.1",
 | 
			
		||||
        "wordwrap": "~0.0.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "safer-buffer": {
 | 
			
		||||
      "version": "2.1.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
 | 
			
		||||
      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
 | 
			
		||||
    },
 | 
			
		||||
    "source-map": {
 | 
			
		||||
      "version": "0.1.34",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz",
 | 
			
		||||
      "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "amdefine": ">=0.0.4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "swig": {
 | 
			
		||||
      "version": "1.4.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/swig/-/swig-1.4.2.tgz",
 | 
			
		||||
      "integrity": "sha1-QIXKBFM2kQS11IPihBs5t64aq6U=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "optimist": "~0.6",
 | 
			
		||||
        "uglify-js": "~2.4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "uglify-js": {
 | 
			
		||||
      "version": "2.4.24",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz",
 | 
			
		||||
      "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "async": "~0.2.6",
 | 
			
		||||
        "source-map": "0.1.34",
 | 
			
		||||
        "uglify-to-browserify": "~1.0.0",
 | 
			
		||||
        "yargs": "~3.5.4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "uglify-to-browserify": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc="
 | 
			
		||||
    },
 | 
			
		||||
    "window-size": {
 | 
			
		||||
      "version": "0.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
 | 
			
		||||
      "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
 | 
			
		||||
    },
 | 
			
		||||
    "wordwrap": {
 | 
			
		||||
      "version": "0.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
 | 
			
		||||
      "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
 | 
			
		||||
    },
 | 
			
		||||
    "yargs": {
 | 
			
		||||
      "version": "3.5.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz",
 | 
			
		||||
      "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "camelcase": "^1.0.2",
 | 
			
		||||
        "decamelize": "^1.0.0",
 | 
			
		||||
        "window-size": "0.1.0",
 | 
			
		||||
        "wordwrap": "0.0.2"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "wordwrap": {
 | 
			
		||||
          "version": "0.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,14 +4,14 @@
 | 
			
		||||
  "description": "f0ck, kennste?",
 | 
			
		||||
  "main": "index.mjs",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "node --experimental-json-modules --harmony-optional-chaining src/index.mjs"
 | 
			
		||||
    "start": "node --experimental-json-modules --harmony-optional-chaining src/index.mjs",
 | 
			
		||||
    "trigger": "node --experimental-json-modules --harmony-optional-chaining debug/trigger.mjs"
 | 
			
		||||
  },
 | 
			
		||||
  "author": "Flummi",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "cuffeo": "^1.0.6-1",
 | 
			
		||||
    "flumm-fetch-cookies": "^1.3.5",
 | 
			
		||||
    "mariadb": "^2.3.1",
 | 
			
		||||
    "swig": "^1.4.2"
 | 
			
		||||
    "mariadb": "^2.3.1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								public/s/js/item.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								public/s/js/item.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
const epochs = [
 | 
			
		||||
  ["year", 31536000],
 | 
			
		||||
  ["month", 2592000],
 | 
			
		||||
  ["day", 86400],
 | 
			
		||||
  ["hour", 3600],
 | 
			
		||||
  ["minute", 60],
 | 
			
		||||
  ["second", 1]
 | 
			
		||||
];
 | 
			
		||||
const getDuration = timeAgoInSeconds => {
 | 
			
		||||
  for(let [name, seconds] of epochs) {
 | 
			
		||||
    const interval = ~~(timeAgoInSeconds / seconds);
 | 
			
		||||
    if(interval >= 1) return {
 | 
			
		||||
      interval: interval,
 | 
			
		||||
      epoch: name
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
const timeAgo = date => {
 | 
			
		||||
  const { interval, epoch } = getDuration(~~((new Date() - new Date(date)) / 1000));
 | 
			
		||||
  return `${interval} ${epoch}${interval === 1 ? "" : "s"} ago`;
 | 
			
		||||
};
 | 
			
		||||
const clickOnElementBinding = selector => () => (elem = document.querySelector(selector))?elem.click():null;
 | 
			
		||||
const keybindings = {
 | 
			
		||||
  "ArrowLeft": clickOnElementBinding("#next"),
 | 
			
		||||
  "ArrowRight": clickOnElementBinding("#prev"),
 | 
			
		||||
  "r": clickOnElementBinding("#random")
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
(() => {
 | 
			
		||||
  if(video = document.querySelector(".video-js")) {
 | 
			
		||||
    const vid1 = videojs(video);
 | 
			
		||||
    vid1.persistvolume({
 | 
			
		||||
      namespace: "f0ck"
 | 
			
		||||
    });
 | 
			
		||||
    if(vid1.autoplay() && !vid1.paused() && vid1.hasClass("vjs-paused")) {
 | 
			
		||||
      vid1.pause();
 | 
			
		||||
      vid1.play();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  document.querySelectorAll("time.timeago").forEach(e => e.innerHTML = timeAgo(e.title));
 | 
			
		||||
 | 
			
		||||
  document.addEventListener("keydown", e => {
 | 
			
		||||
    if(e.key in keybindings) {
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      keybindings[e.key]();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if(f0ckimage = document.querySelector("#f0ck-image"))
 | 
			
		||||
    f0ckimage.addEventListener("click", e => {
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      f0ckimage.hasAttribute("style")?f0ckimage.removeAttribute("style"):f0ckimage.setAttribute("style", "max-height: unset;");
 | 
			
		||||
    });
 | 
			
		||||
})();
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
const clickOnElementBinding = selector => () => (elem = document.querySelector(selector))?elem.click():null;
 | 
			
		||||
 | 
			
		||||
const keybindings = {
 | 
			
		||||
  "ArrowLeft": clickOnElementBinding("#next"),
 | 
			
		||||
  "ArrowRight": clickOnElementBinding("#prev"),
 | 
			
		||||
  "r": clickOnElementBinding("#random")
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
(() => {
 | 
			
		||||
  document.addEventListener("keydown", e => {
 | 
			
		||||
    if(e.key in keybindings) {
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      keybindings[e.key]();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const f0ckimage = document.querySelector("#f0ck-image");
 | 
			
		||||
  if(f0ckimage) {
 | 
			
		||||
    f0ckimage.addEventListener("click", e => {
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
      f0ckimage.hasAttribute("style")?f0ckimage.removeAttribute("style"):f0ckimage.setAttribute("style", "max-height: unset;");
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
})();
 | 
			
		||||
//sorry, jQuery ist dumm :--D sorry sirx, dass ich wonnes Kot auskommentiert habe
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
import router from "../router.mjs";
 | 
			
		||||
import cfg from "../../../config.json";
 | 
			
		||||
import fs from "fs";
 | 
			
		||||
import sql from "../sql.mjs";
 | 
			
		||||
import swig from "swig";
 | 
			
		||||
import url from "url";
 | 
			
		||||
import sql from "../sql.mjs";
 | 
			
		||||
import lib from "../lib.mjs";
 | 
			
		||||
import tpl from "../tpl.mjs";
 | 
			
		||||
 | 
			
		||||
const templates = {
 | 
			
		||||
  contact: fs.readFileSync("./views/contact.html", "utf-8"),
 | 
			
		||||
@@ -21,7 +22,7 @@ router.get("/", async (req, res) => {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  res.reply({
 | 
			
		||||
    body: swig.compile(templates.index)(data)
 | 
			
		||||
    body: tpl.render(templates.index, data)
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -74,7 +75,7 @@ router.get(/^\/([0-9]+)$/, async (req, res) => {
 | 
			
		||||
    data.thumb = `${cfg.websrv.paths.thumbnails}/${e.id}.png`;
 | 
			
		||||
    data.dest = `${cfg.websrv.paths.images}/${e.dest}`;
 | 
			
		||||
    data.mime = e.mime;
 | 
			
		||||
    data.size = e.size;//lib.formatSize(e.size);
 | 
			
		||||
    data.size = lib.formatSize(e.size);
 | 
			
		||||
    data.userchannel = e.userchannel;
 | 
			
		||||
    data.usernetwork = e.usernetwork;
 | 
			
		||||
    data.timestamp = new Date(e.stamp * 1000).toISOString();
 | 
			
		||||
@@ -84,7 +85,7 @@ router.get(/^\/([0-9]+)$/, async (req, res) => {
 | 
			
		||||
      data.prev = query[2][0].id;
 | 
			
		||||
  }
 | 
			
		||||
  res.reply({
 | 
			
		||||
    body: swig.compile(templates.item)(data)
 | 
			
		||||
    body: tpl.render(templates.item, data)
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								src/inc/tpl.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/inc/tpl.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
export default new class {
 | 
			
		||||
  syntax = [
 | 
			
		||||
    [ "each", t => `util.forEach(${t.slice(4).trim()},($value,$key)=>{` ],
 | 
			
		||||
    [ "/each", () => "});" ],
 | 
			
		||||
    [ "if", t => `if(${t.slice(2).trim()}){` ],
 | 
			
		||||
    [ "elseif", t => `}else if(${t.slice(6).trim()}){` ],
 | 
			
		||||
    [ "else", () => "}else{" ],
 | 
			
		||||
    [ "/if", () => "}" ],
 | 
			
		||||
    [ "=", t => `html+=${t.slice(1).trim()};` ]
 | 
			
		||||
  ];
 | 
			
		||||
  forEach(o, f) {
 | 
			
		||||
    if(Array.isArray(o))
 | 
			
		||||
      o.forEach(f);
 | 
			
		||||
    else if(typeof o === "object")
 | 
			
		||||
      Object.keys(o).forEach(k => f.call(null, o[k], k));
 | 
			
		||||
    else
 | 
			
		||||
      throw new Error(`${o} is not a iterable object`);
 | 
			
		||||
  }
 | 
			
		||||
  render(tpl, data) {
 | 
			
		||||
    return new Function("util", "data", "let html = \"\";with(data){"
 | 
			
		||||
      + tpl.trim().replace(/[\n\r]/g, "").split(/{{\s*([^}]+)\s*}}/).filter(Boolean).map(t => {
 | 
			
		||||
        for(let i = 0; i < this.syntax.length; i++)
 | 
			
		||||
          if(t.indexOf(this.syntax[i][0]) === 0)
 | 
			
		||||
            return this.syntax[i][1](t);
 | 
			
		||||
        return `html+='${t}';`;
 | 
			
		||||
      })
 | 
			
		||||
      .join`` + "}return html.trim().replace(/>[\\n\\r\\s]*?</g, '><')")
 | 
			
		||||
      .bind(null, { forEach: this.forEach })(data);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -18,12 +18,22 @@ export default async bot => {
 | 
			
		||||
            t: await fs.readdir("./public/t")
 | 
			
		||||
          };
 | 
			
		||||
          const sizes = {
 | 
			
		||||
            b: (await Promise.all(dirs.b.map(async file => (await fs.stat(`./public/b/${file}`)).size))).reduce((a, b) => b + a),
 | 
			
		||||
            t: (await Promise.all(dirs.t.map(async file => (await fs.stat(`./public/t/${file}`)).size))).reduce((a, b) => b + a),
 | 
			
		||||
            b: lib.formatSize((await Promise.all(dirs.b.map(async file => (await fs.stat(`./public/b/${file}`)).size))).reduce((a, b) => b + a)),
 | 
			
		||||
            t: lib.formatSize((await Promise.all(dirs.t.map(async file => (await fs.stat(`./public/t/${file}`)).size))).reduce((a, b) => b + a)),
 | 
			
		||||
          };
 | 
			
		||||
          return e.reply(`${dirs.b.length} f0cks: ${sizes.b}, ${dirs.t.length} thumbnails: ${sizes.t}`);
 | 
			
		||||
        case "limit":
 | 
			
		||||
          return e.reply(`up to ${lib.formatSize(cfg.main.maxfilesize)} (${lib.formatSize(cfg.main.maxfilesize * 2.5)} for admins)`);
 | 
			
		||||
        case "thumb":
 | 
			
		||||
          const rows = await sql.query("select id from items");
 | 
			
		||||
          const dir = (await fs.readdir("./public/t")).filter(d => d.endsWith(".png")).map(e => +e.split(".")[0]);
 | 
			
		||||
 | 
			
		||||
          const tmp = [];
 | 
			
		||||
          for(let row of rows) {
 | 
			
		||||
            !dir.includes(row.id) ? tmp.push(row.id) : null;
 | 
			
		||||
          }
 | 
			
		||||
          e.reply(`${tmp.length}, ${rows.length}, ${dir.length}`);
 | 
			
		||||
        break;
 | 
			
		||||
        default:
 | 
			
		||||
          return e.reply("lul");
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
<!DOCTYPE f0ck>
 | 
			
		||||
<!doctype f0ck>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
  <title>f0ck!</title>
 | 
			
		||||
@@ -29,15 +29,15 @@
 | 
			
		||||
</nav>
 | 
			
		||||
 | 
			
		||||
<div class="container-fluid">
 | 
			
		||||
	<ul id="posts" data-last="{{ last }}">
 | 
			
		||||
    	{% for item in items %}
 | 
			
		||||
    	<li class="post"><a href="/{{ item.id }}" title="{{ item.mime }}">
 | 
			
		||||
    		<img class="thumb" src="/t/{{ item.id }}.png" />
 | 
			
		||||
    			<span class="item-mime">{{ item.mime }}</span>
 | 
			
		||||
    		</a>
 | 
			
		||||
    	</li>
 | 
			
		||||
    	{% endfor %}
 | 
			
		||||
  	</ul>
 | 
			
		||||
	<ul id="posts" data-last="{{=last}}">
 | 
			
		||||
    {{each items}}
 | 
			
		||||
    <li class="post"><a href="/{{=$value.id}}" title="{{=$value.mime}}">
 | 
			
		||||
      <img class="thumb" src="/t/{{=$value.id}}.png" />
 | 
			
		||||
        <span class="item-mime">{{=$value.mime}}</span>
 | 
			
		||||
      </a>
 | 
			
		||||
    </li>
 | 
			
		||||
    {{/each}}
 | 
			
		||||
  </ul>
 | 
			
		||||
</div>
 | 
			
		||||
  <script src="./s/js/scroller.js"></script>
 | 
			
		||||
  <script src="./s/js/theme.js"></script>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										120
									
								
								views/item.html
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								views/item.html
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
<!doctype f0ck>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
  <title>{{ id }} - f0ck.me</title>
 | 
			
		||||
  <title>{{=id}} - f0ck.me</title>
 | 
			
		||||
  <link rel="stylesheet" type="text/css" href="./s/css/video-js.min.css" />
 | 
			
		||||
  <link rel="stylesheet" type="text/css" href="./s/css/vsg-skin.css" />
 | 
			
		||||
  <link rel="stylesheet" type="text/css" href="./s/css/bootstrap.css">
 | 
			
		||||
@@ -9,9 +9,9 @@
 | 
			
		||||
  <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
  <link rel="icon" type="image/png" href="./s/img/favicon.png" />
 | 
			
		||||
  <meta property="og:site_name" content="f0ck.me" />
 | 
			
		||||
  <meta property="og:description" content="f0cked by {{ username }}" />
 | 
			
		||||
  <meta name="Description" content="f0cked by {{ username }}" />
 | 
			
		||||
  <meta property="og:image" content="{{ thumbnail }}" />
 | 
			
		||||
  <meta property="og:description" content="f0cked by {{=username}}" />
 | 
			
		||||
  <meta name="Description" content="f0cked by {{=username}}" />
 | 
			
		||||
  <meta property="og:image" content="{{=thumbnail}}" />
 | 
			
		||||
  <meta charset="utf-8" />
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
@@ -40,105 +40,49 @@
 | 
			
		||||
  <div class="content">
 | 
			
		||||
 | 
			
		||||
    <div class="next-post">
 | 
			
		||||
      {% if next != null %}
 | 
			
		||||
        <a id="next" href="/{{ next }}">«</a>
 | 
			
		||||
      {% else %}
 | 
			
		||||
      {{if next}}
 | 
			
		||||
        <a id="next" href="/{{=next}}">«</a>
 | 
			
		||||
      {{else}}
 | 
			
		||||
        <a id="next" href="#" style="color: #ccc !important;">«</a>
 | 
			
		||||
      {% endif %}
 | 
			
		||||
      {{/if}}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="media-object">
 | 
			
		||||
              {% if item == "video" %}
 | 
			
		||||
              <div class="embed-responsive embed-responsive-16by9">
 | 
			
		||||
        <video id="my-video" class="video-js embed-responsive-item" width="640" height="360" src="{{ dest }}" preload="auto" autoplay controls loop data-setup="{}"></video>
 | 
			
		||||
      </div>
 | 
			
		||||
      {% elseif item == "audio" %}
 | 
			
		||||
    
 | 
			
		||||
      {% if thumb != null %}
 | 
			
		||||
    <div>
 | 
			
		||||
    
 | 
			
		||||
    <!-- <img src="{{ thumb }}" /><br />  -->
 | 
			
		||||
    
 | 
			
		||||
      {% endif %}
 | 
			
		||||
      <div class="embed-responsive embed-responsive-16by9">
 | 
			
		||||
        <audio id="my-video" class="embed-responsive-item video-js audiojs" autoplay controls loop src="{{ dest }}" data-setup="{}" poster="{% if thumb !== null %}{{ thumb }}{% else %}/s/200.gif{% endif %}" type="audio/mp3" ></audio>
 | 
			
		||||
      </div>
 | 
			
		||||
      {% if thumb != null %}
 | 
			
		||||
      {{if item === "video"}}
 | 
			
		||||
        <div class="embed-responsive embed-responsive-16by9">
 | 
			
		||||
          <video id="my-video" class="video-js embed-responsive-item" width="640" height="360" src="{{=dest}}" preload="auto" autoplay controls loop data-setup="{}"></video>
 | 
			
		||||
        </div>
 | 
			
		||||
      {{elseif item === "audio"}}
 | 
			
		||||
        <div class="embed-responsive embed-responsive-16by9">
 | 
			
		||||
          <audio id="my-video" class="embed-responsive-item video-js audiojs" autoplay controls loop src="{{=dest}}" data-setup="{}" poster="{{if thumb}}{{=thumb}}{{else}}/s/200.gif{{/if}}" type="audio/mp3" ></audio>
 | 
			
		||||
        </div>
 | 
			
		||||
      {{elseif item === "image"}}
 | 
			
		||||
        <a href="{{=dest}}" id="elfe" target="_blank"><img id="f0ck-image" src="{{=dest}}" /></a>
 | 
			
		||||
      {{else}}
 | 
			
		||||
        <h1>404 - Not f0cked</h1>
 | 
			
		||||
      {{/if}}
 | 
			
		||||
    </div>
 | 
			
		||||
    
 | 
			
		||||
    {% endif %}
 | 
			
		||||
      {% elseif item == "image" %}
 | 
			
		||||
        <a href="{{ dest }}" id="elfe" target="_blank"><img id="f0ck-image" src="{{ dest }}" /></a>
 | 
			
		||||
      {% else %}
 | 
			
		||||
    
 | 
			
		||||
      <h1>404 - Not f0cked</h1>
 | 
			
		||||
      {% endif %}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
        <div class="previous-post">
 | 
			
		||||
      {% if prev != null %}
 | 
			
		||||
        <a id="prev" href="/{{ prev }}">»</a>
 | 
			
		||||
      {% else %}
 | 
			
		||||
    <div class="previous-post">
 | 
			
		||||
      {{if prev}}
 | 
			
		||||
        <a id="prev" href="/{{=prev}}">»</a>
 | 
			
		||||
      {{else}}
 | 
			
		||||
        <a id="prev" href="#" style="color: #ccc !important;">»</a>
 | 
			
		||||
      {% endif %}      
 | 
			
		||||
      {{/if}}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="metadata">
 | 
			
		||||
      <span class="badge badge-dark"><a href="/{{ id }}" class="id-link">{{ id }} </a> by {{ username }}</span>
 | 
			
		||||
      <span class="badge badge-dark">{{ usernetwork }} / {{ userchannel }}</span>
 | 
			
		||||
      <span class="badge badge-dark"><a id="post_source" href="{{ srcurl }}" target="_blank">{{ src }}</a></span>
 | 
			
		||||
      <span class="badge badge-dark">{{ size }}</span>
 | 
			
		||||
      <span class="badge badge-dark"><time class="timeago" title="{{ timestamp }}" datetime="{{ timestamp }}"> </time></span>
 | 
			
		||||
      <span class="badge badge-dark"><a href="/{{=id}}" class="id-link">{{=id}} </a> by {{=username}}</span>
 | 
			
		||||
      <span class="badge badge-dark">{{=usernetwork}} / {{=userchannel}}</span>
 | 
			
		||||
      <span class="badge badge-dark"><a id="post_source" href="{{=srcurl}}" target="_blank">{{=src}}</a></span>
 | 
			
		||||
      <span class="badge badge-dark">{{=size}}</span>
 | 
			
		||||
      <span class="badge badge-dark"><time class="timeago" title="{{=timestamp}}" datetime="{{=timestamp}}"> </time></span>
 | 
			
		||||
      <span class="badge badge-dark" id="themes"></span>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
  <script src="./s/js/shit.js"></script>
 | 
			
		||||
  <script src="./s/js/theme.js"></script>
 | 
			
		||||
  <script src="./s/js/video.min.js"></script>
 | 
			
		||||
  <script src="./s/js/videojs.persistvolume.js"></script>
 | 
			
		||||
  <script>
 | 
			
		||||
    (function() {
 | 
			
		||||
      let video = document.querySelector(".video-js");
 | 
			
		||||
      if(!video)
 | 
			
		||||
        return;
 | 
			
		||||
      var vid1 = videojs(video);
 | 
			
		||||
      vid1.persistvolume({
 | 
			
		||||
        namespace: "f0ck"
 | 
			
		||||
      });
 | 
			
		||||
      if(vid1.autoplay() && !vid1.paused() && vid1.hasClass('vjs-paused')) {
 | 
			
		||||
        vid1.pause();
 | 
			
		||||
        vid1.play();
 | 
			
		||||
      }
 | 
			
		||||
    })();
 | 
			
		||||
    const epochs = [
 | 
			
		||||
      ["year", 31536000],
 | 
			
		||||
      ["month", 2592000],
 | 
			
		||||
      ["day", 86400],
 | 
			
		||||
      ["hour", 3600],
 | 
			
		||||
      ["minute", 60],
 | 
			
		||||
      ["second", 1]
 | 
			
		||||
    ];
 | 
			
		||||
    const getDuration = timeAgoInSeconds => {
 | 
			
		||||
      for(let [name, seconds] of epochs) {
 | 
			
		||||
        const interval = ~~(timeAgoInSeconds / seconds);
 | 
			
		||||
        if (interval >= 1) {
 | 
			
		||||
          return {
 | 
			
		||||
            interval: interval,
 | 
			
		||||
            epoch: name
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
    const timeAgo = date => {
 | 
			
		||||
      const timeAgoInSeconds = ~~((new Date() - new Date(date)) / 1000);
 | 
			
		||||
      const {interval, epoch} = getDuration(timeAgoInSeconds);
 | 
			
		||||
      const suffix = interval === 1 ? "" : "s";
 | 
			
		||||
      return `${interval} ${epoch}${suffix} ago`;
 | 
			
		||||
    };
 | 
			
		||||
    (() => {
 | 
			
		||||
      document.querySelectorAll("time.timeago").forEach(e => e.innerHTML = timeAgo(e.title));
 | 
			
		||||
    })();
 | 
			
		||||
  </script>
 | 
			
		||||
  <script src="./s/js/item.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user