1
0
forked from w0bm/f0bm

Compare commits

1 Commits

Author SHA1 Message Date
4a2925b141 revert a4f9c48e13
revert various fixes to get it working for myself
2026-01-23 13:24:43 +00:00
13 changed files with 261 additions and 486 deletions

1
.gitignore vendored
View File

@@ -8,4 +8,3 @@ deleted/b
deleted/ca
deleted/t
tmp/*
tools

View File

@@ -1,15 +0,0 @@
import db from "../src/inc/sql.mjs";
(async () => {
try {
const item = (await db`select * from items order by id desc limit 1`)?.[0];
console.log("Last Item:", item);
if (item) {
const tags = await db`select * from tags_assign where item_id = ${item.id}`;
console.log("Tags:", tags);
}
} catch (err) {
console.error(err);
}
process.exit(0);
})();

View File

@@ -6,14 +6,13 @@ import { promises as fs } from "fs";
network: "console",
message: _args.join(" "),
args: _args.slice(1),
channel: "#w0bm",
channel: "console",
user: {
prefix: "console!console@console",
nick: "console",
username: "console",
account: "console"
},
raw: {},
reply: (...args) => console.log(args),
replyAction: (...args) => console.log(args),
replyNotice: (...args) => console.log(args)
@@ -27,12 +26,9 @@ import { promises as fs } from "fs";
try {
if(trigger.length === 0)
return console.error("no matches");
for (const t of trigger) {
console.log(`triggered > ${t.name} (${_e.message})`);
await t.f(_e);
}
console.log(`triggered > ${trigger[0].name} (${_e.message})`);
await trigger[0].f(_e);
} catch(err) {
console.error(err);
}
process.exit(0);
})();

View File

@@ -1,3 +0,0 @@
#!/bin/bash
npm i
npm start

View File

@@ -1197,9 +1197,7 @@ body {
overscroll-behavior-y: contain;
overflow: unset;
font-size: 14px;
height:
/* 100%; */
auto;
height: /* 100%; */auto;
}
.wrapper {
@@ -1320,13 +1318,6 @@ div.posts>a:hover::after {
grid-template-columns: auto 1fr 0fr;
justify-content: start;
border-bottom: 1px solid var(--nav-border-color);
background: var(--nav-bg);
transition: background 0.2s ease;
}
.navbar.scrolled {
background: #000 !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
.navbar-brand {
@@ -1793,8 +1784,7 @@ span.placeholder {
width: 100%;
padding: 5px;
/* background-color: var(--navigation-links-bg);
*/
}
*/}
@media (min-width: 361px) {
.embed-responsive-image {
@@ -2789,9 +2779,7 @@ ul.navbar-nav-guests li.nav-item {
margin-right: .5rem;
}
.navbar-expand-lg .navbar-nav-guests .nav-link,
.pagination>a,
.pagination>span {
.navbar-expand-lg .navbar-nav-guests .nav-link, .pagination > a, .pagination > span {
padding-right: .5rem;
padding-left: .5rem;
}
@@ -2824,16 +2812,12 @@ ul.navbar-nav-guests li.nav-item {
/* Pagination Responsiveness */
@media (max-width: 799px) {
.navbar-expand-lg .navbar-nav-guests .nav-link,
.pagination>a,
.pagination>span {
.navbar-expand-lg .navbar-nav-guests .nav-link, .pagination > a, .pagination > span {
padding-right: 2px;
padding-left: 2px;
}
.pagination>a,
.pagination>span {
.pagination > a, .pagination > span {
margin-right: 2px;
margin-left: 2px;
}
@@ -2848,16 +2832,12 @@ ul.navbar-nav-guests li.nav-item {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
img#f0ck-image,
div.imageDoor,
div.posts a,
video {
img#f0ck-image, div.imageDoor, div.posts a, video {
animation: 1s ease-out 0s 1 fadeInFX;
}
@@ -2912,13 +2892,11 @@ video {
padding: 5px;
}
.f0cks h5,
.favs h5 {
.f0cks h5, .favs h5 {
background: var(--dropdown-bg);
}
.f0cks-header,
.favs-header {
.f0cks-header, .favs-header {
display: grid;
grid-template-columns: 1fr auto;
background: var(--img-border-color);
@@ -2962,7 +2940,6 @@ button#togglebg {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
@@ -2972,7 +2949,6 @@ button#togglebg {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
@@ -2983,7 +2959,6 @@ button#togglebg {
0% {
opacity: 0;
}
100% {
opacity: 0.2;
}
@@ -2993,7 +2968,6 @@ button#togglebg {
0% {
opacity: 0.2;
}
100% {
opacity: 0;
}
@@ -3030,7 +3004,6 @@ input#s_avatar {
#s_avatar:hover {
background: #ffffff0f;
}
.theforceofthree {
display: grid;
grid-template-columns: 0.4fr 1fr 0.4fr;
@@ -3039,23 +3012,3 @@ input#s_avatar {
.upload {
padding: 10px;
}
/* Infinite scroll loading indicator */
.loading-spinner {
display: inline-block;
font-size: 12px;
color: var(--footbar-color);
animation: pulse 1s ease-in-out infinite;
}
@keyframes pulse {
0%,
100% {
opacity: 0.4;
}
50% {
opacity: 1;
}
}

View File

@@ -130,12 +130,12 @@
return false;
}
renderTags(res.tags);
if (span.parentElement) span.parentElement.removeChild(span);
span.parentElement.removeChild(span);
testList.innerText = "";
addtagClick();
}
else if (e.key === "Escape") {
if (span.parentElement) span.parentElement.removeChild(span);
span.parentElement.removeChild(span);
testList.innerText = "";
}
else {

View File

@@ -68,18 +68,6 @@ window.requestAnimFrame = (function () {
}
};
// Navbar scroll effect - make background black when scrolling
const navbar = document.querySelector('.navbar');
if (navbar) {
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
navbar.classList.add('scrolled');
} else {
navbar.classList.remove('scrolled');
}
});
}
const loadItemAjax = async (url, inheritContext = true) => {
console.log("loadItemAjax called with:", url, "inheritContext:", inheritContext);
// Show loading indicator
@@ -152,7 +140,7 @@ window.requestAnimFrame = (function () {
html = rawText;
}
let container = document.querySelector('#main .container');
let container = document.querySelector('.container');
if (!container && document.querySelector('.index-container')) {
// Transition from Index to Item View
@@ -160,11 +148,6 @@ window.requestAnimFrame = (function () {
main.innerHTML = '<div class="container"></div>';
container = main.querySelector('.container');
} else if (container) {
// Check if we are on Tags Overview logic (which reuses .container)
const tagsOverview = container.querySelector('.tags');
if (tagsOverview) {
container.innerHTML = '';
} else {
// Already in Item View, clear usage
const oldContent = container.querySelector('.content');
const oldMetadata = container.querySelector('.metadata');
@@ -173,7 +156,6 @@ window.requestAnimFrame = (function () {
if (oldContent) oldContent.remove();
if (oldMetadata) oldMetadata.remove();
}
}
container.insertAdjacentHTML('beforeend', html);
@@ -205,12 +187,13 @@ window.requestAnimFrame = (function () {
};
const changePage = (e, pbwork = true) => {
if (pbwork) {
const nav = document.querySelector("nav.navbar");
if (nav) nav.classList.add("pbwork");
if (e.tagName === 'A') {
e.preventDefault();
loadItemAjax(e.href);
} else {
pbwork && document.querySelector("nav.navbar").classList.add("pbwork");
!tt && (tt = setTimeout(() => e.click(), stimeout));
}
// Trigger native click for navigation
e.click();
};
// Intercept clicks
@@ -225,10 +208,10 @@ window.requestAnimFrame = (function () {
return;
}
const link = e.target.closest('#next, #prev, #random, #nav-random, .id-link, .nav-next, .nav-prev');
const link = e.target.closest('#next, #prev, #random, .id-link, .nav-next, .nav-prev');
if (link && link.href && link.hostname === window.location.hostname && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) {
// Special check for random
if (link.id === 'random' || link.id === 'nav-random') {
if (link.id === 'random') {
e.preventDefault();
const nav = document.querySelector("nav.navbar");
if (nav) nav.classList.add("pbwork");
@@ -257,10 +240,7 @@ window.requestAnimFrame = (function () {
window.location.href = link.href;
}
})
.catch((err) => {
console.error("Random fetch failed:", err);
window.location.href = link.href;
});
.catch(() => window.location.href = link.href);
return;
}
@@ -281,7 +261,7 @@ window.requestAnimFrame = (function () {
"a": clickOnElementBinding("#next"),
"ArrowRight": clickOnElementBinding("#prev"),
"d": clickOnElementBinding("#prev"),
"r": clickOnElementBinding("#random, #nav-random"),
"r": clickOnElementBinding("#random"),
" ": clickOnElementBinding("#f0ck-image")
};
document.addEventListener("keydown", e => {
@@ -347,116 +327,59 @@ window.requestAnimFrame = (function () {
}
// </image-responsive>
// <infinite-scroll>
const postsContainer = document.querySelector("div.posts");
if (postsContainer) {
// Infinite scroll state
let infiniteState = {
loading: false,
hasMore: true,
currentPage: 1
};
// Extract current page from URL
const pageMatch = window.location.pathname.match(/\/p\/(\d+)/);
if (pageMatch) infiniteState.currentPage = parseInt(pageMatch[1]);
// Extract context (tag/user/mime) from URL
const getContext = () => {
const ctx = {};
const tagMatch = window.location.pathname.match(/\/tag\/([^/]+)/);
if (tagMatch) ctx.tag = decodeURIComponent(tagMatch[1]);
const userMatch = window.location.pathname.match(/\/user\/([^/]+)/);
if (userMatch) ctx.user = decodeURIComponent(userMatch[1]);
const mimeMatch = window.location.pathname.match(/\/(image|audio|video)(?:\/|$)/);
if (mimeMatch) ctx.mime = mimeMatch[1];
return ctx;
};
// Build URL path for history
const buildUrl = (page) => {
const ctx = getContext();
let path = '/';
if (ctx.tag) path += `tag/${ctx.tag}/`;
if (ctx.user) path += `user/${ctx.user}/`;
if (ctx.mime) path += `${ctx.mime}/`;
if (page > 1) path += `p/${page}`;
return path.replace(/\/$/, '') || '/';
};
// Fetch and append more items
const loadMoreItems = async () => {
if (infiniteState.loading || !infiniteState.hasMore) return;
infiniteState.loading = true;
const foot = document.querySelector("div#footbar");
if (foot) {
foot.innerHTML = '<span class="loading-spinner">Loading...</span>';
foot.style.color = 'var(--footbar-color)';
}
const nextPage = infiniteState.currentPage + 1;
const ctx = getContext();
const params = new URLSearchParams();
params.append('page', nextPage);
if (ctx.tag) params.append('tag', ctx.tag);
if (ctx.user) params.append('user', ctx.user);
if (ctx.mime) params.append('mime', ctx.mime);
try {
const response = await fetch(`/ajax/items?${params.toString()}`);
const data = await response.json();
if (data.success && data.html) {
// Append new thumbnails
postsContainer.insertAdjacentHTML('beforeend', data.html);
// Update state
infiniteState.currentPage = data.currentPage;
infiniteState.hasMore = data.hasMore;
// Update URL
history.replaceState({}, '', buildUrl(infiniteState.currentPage));
// Update pagination display if exists
const paginationLinks = document.querySelectorAll('.pagination .pagination-int-item, .pagination .btn');
paginationLinks.forEach(el => {
if (el.textContent.trim() == infiniteState.currentPage) {
el.classList.add('disabled');
}
});
} else {
infiniteState.hasMore = false;
}
} catch (err) {
console.error('Infinite scroll fetch error:', err);
} finally {
infiniteState.loading = false;
if (foot) {
foot.innerHTML = infiniteState.hasMore ? '&#9660;' : '&#8212;';
foot.style.color = 'transparent';
}
}
};
// Scroll detection - preload before reaching bottom
const PRELOAD_OFFSET = 500; // pixels before bottom to trigger load
window.addEventListener("scroll", () => {
// <scroller>
let tts = 0;
const scroll_treshold = 1;
if ([...document.querySelectorAll("div.posts")].length === 1) {
document.addEventListener("wheel", e => {
if (!document.querySelector('#main')) return;
const scrollPosition = window.innerHeight + window.scrollY;
const pageHeight = document.querySelector('#main').offsetHeight;
const distanceFromBottom = pageHeight - scrollPosition;
// Load more when within PRELOAD_OFFSET pixels of bottom
if (distanceFromBottom < PRELOAD_OFFSET && infiniteState.hasMore && !infiniteState.loading) {
loadMoreItems();
if (Math.ceil(window.innerHeight + window.scrollY) >= document.querySelector('#main').offsetHeight && e.deltaY > 0) { // down
if (elem = document.querySelector(".pagination > .next:not(.disabled)")) {
if (tts < scroll_treshold) {
const foot = document.querySelector("div#footbar");
if (foot) {
foot.style.boxShadow = "inset 0px 4px 0px var(--footbar-color)";
foot.style.color = "var(--footbar-color)";
}
tts++;
}
else
changePage(elem);
}
}
else if (window.scrollY <= 0 && e.deltaY < 0) { // up
if (elem = document.querySelector(".pagination > .prev:not(.disabled)")) {
if (tts < scroll_treshold) {
const nav = document.querySelector("nav.navbar");
if (nav) {
nav.style.boxShadow = "0px 2px 0px var(--loading-indicator-color)";
nav.style.transition = ".2s ease-in-out";
}
tts++;
}
else
changePage(elem);
}
}
else {
tts = 0;
const foot = document.querySelector("div#footbar");
if (foot) {
foot.style.boxShadow = "unset";
foot.style.color = "transparent";
}
const nav = document.querySelector("nav.navbar");
if (nav) nav.style.boxShadow = "unset";
}
});
}
// </infinite-scroll>
const rmatch = /\/p\/(\d+?)/;
if (document.referrer.match(rmatch) && document.location.href.match(rmatch))
if (document.location.href.match(rmatch) < document.referrer.match(rmatch))
document.body.scrollTop = document.body.scrollHeight;
// </scroller>
// <swipe>
const swipeRT = {
@@ -618,13 +541,10 @@ function init() {
window.addEventListener('load', init);
const sbtForm = document.getElementById('sbtForm');
if (sbtForm) {
sbtForm.addEventListener('submit', (e) => {
document.getElementById('sbtForm').addEventListener('submit', (e) => {
e.preventDefault();
const input = document.getElementById('sbtInput').value.trim();
if (input) {
window.location.href = `/tag/${encodeURIComponent(input)}`;
}
});
}

View File

@@ -17,9 +17,6 @@ const Cookie = {
(() => {
const acttheme = Cookie.get('theme') ?? "w0bm";
const themecontainer = document.querySelector("li#themes > ul.dropdown-menu");
if (!themecontainer) return; // Theme menu not present on this page
const themes = [...themecontainer.querySelectorAll("li > a")].map(t => t.innerText.toLowerCase());
if(acttheme !== document.documentElement.getAttribute("theme") && themes.includes(acttheme))
document.documentElement.setAttribute("theme", acttheme);

View File

@@ -64,58 +64,5 @@ export default (router, tpl) => {
});
});
// Infinite scroll endpoint for index thumbnails
router.get(/\/ajax\/items/, async (req, res) => {
let query = {};
if (typeof req.url === 'string') {
const parsedUrl = url.parse(req.url, true);
query = parsedUrl.query;
} else {
query = req.url.qs || {};
}
const page = parseInt(query.page) || 1;
const data = await f0cklib.getf0cks({
page: page,
tag: query.tag || null,
user: query.user || null,
mime: query.mime || null,
mode: req.session.mode,
session: !!req.session,
fav: false
});
if (!data.success) {
return res.reply({
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
success: false,
html: '',
hasMore: false
})
});
}
// Render just the thumbnail items
const itemsHtml = tpl.render('snippets/items-grid', {
items: data.items,
link: data.link
});
const hasMore = data.pagination.next !== null;
return res.reply({
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
success: true,
html: itemsHtml,
hasMore: hasMore,
nextPage: data.pagination.next,
currentPage: data.pagination.page
})
});
});
return router;
};

View File

@@ -13,18 +13,14 @@ export default router => {
group.get(/\/random(\/user\/.+|\/image|\/video|\/audio)?$/, async (req, res) => {
const user = req.url.split[3] === "user" ? req.url.split[4] : "%";
const mime = (allowedMimes.filter(n => req.url.split[3]?.startsWith(n))[0] ? req.url.split[3] : "") + "%";
const tag = req.url.qs.tag || null;
const rows = await db`
select "items".*
select *
from "items"
left join tags_assign on tags_assign.item_id = items.id
left join tags on tags.id = tags_assign.tag_id
where
mime ilike ${mime} and
username ilike ${user} and
active = 'true'
${tag ? db`and tags.normalized ilike ${'%' + tag + '%'}` : db``}
order by random()
limit 1
`;
@@ -55,13 +51,15 @@ export default router => {
where
${db.unsafe(modequery)} and
active = 'true'
${opt.older
${
opt.older
? db`and id <= ${opt.older}`
: opt.newer
? db`and id >= ${opt.newer}`
: db``
}
order by id ${opt.newer
order by id ${
opt.newer
? db`asc`
: db`desc`
}
@@ -177,7 +175,8 @@ export default router => {
}
const q = (await db`
update "tags" set ${db({
update "tags" set ${
db({
tag: newtag
}, 'tag')
}
@@ -288,7 +287,8 @@ export default router => {
else {
// add fav
await db`
insert into "favorites" ${db({
insert into "favorites" ${
db({
item_id: +postid,
user_id: +req.session.id
}, 'item_id', 'user_id')

View File

@@ -23,7 +23,7 @@ export default async bot => {
name: "parser",
call: regex.all,
active: true,
f: async e => {
f: e => {
const links = e.message.match(regex.all)?.filter(link => !link.includes(cfg.main.url.domain)) || [];
let repost;
if(e.media)
@@ -51,7 +51,7 @@ export default async bot => {
console.log(`parsing ${links.length} link${links.length > 1 ? "s" : ""}...`);
for (const link of links) {
links.forEach(async link => {
//if(regex.imgur.test(link))
// return await e.reply(`fuck imgur... seriously`);
@@ -73,12 +73,11 @@ export default async bot => {
// read metadata
let ext;
const proxyArgs = cfg.main.socks ? `--proxy ${cfg.main.socks}` : '';
if(link.match(regex.instagram)) {
// is instagram
try {
// @flummi -> is there a variable for the actual work directory so it doesn't have to be hardcoded?
const meta = JSON.parse((await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
const meta = JSON.parse((await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext;
} catch(err) {
const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"];
@@ -93,10 +92,9 @@ export default async bot => {
else if(link.match(regex.yt)) {
//yt - fuck anti bot protection
try {
const meta = JSON.parse((await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' -I 1 --skip-download --dump-json "${link}"`)).stdout);
const meta = JSON.parse((await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' -I 1 --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext;
} catch(err) {
console.error("YT-DLP Error:", err);
const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"];
// this can be undefined for unsupported mime types, but will be caught in the general mime check below
ext = cfg.mimes[tmphead];
@@ -105,7 +103,7 @@ export default async bot => {
else if(link.match(regex.fourchan)) {
//4chan - fuck cloudflare :)
try {
const meta = JSON.parse((await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
const meta = JSON.parse((await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext;
} catch(err) {
const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"];
@@ -120,10 +118,9 @@ export default async bot => {
const meta = JSON.parse((await queue.exec(`yt-dlp -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext;
} catch(err) {
console.error('err:', err);
if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, err);
return await e.reply('something went wrong lol / check maxfilesize?');
const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"];
// this can be undefined for unsupported mime types, but will be caught in the general mime check below
ext = cfg.mimes[tmphead];
}
}
@@ -142,7 +139,7 @@ export default async bot => {
if(link.match(regex.instagram)) {
try {
// add --cookies <path-to-cookies-file> on local instance if you want to avoid getting rate limited or optionally use a socks proxy from a network that is not being detected as a public network
source = (await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=1080]+ba/b[height<=1080] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
source = (await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=1080]+ba/b[height<=1080] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
} catch(err) {
if(e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "instagram dl error");
@@ -164,7 +161,7 @@ export default async bot => {
else if(link.match(regex.yt)) {
try {
// add --cookies <path-to-cookies-file> on local instance if you want to avoid getting rate limited or optionally use a socks proxy from a network that is not being detected as a public network
source = (await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" -I 1 --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
source = (await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" -I 1 --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
} catch(err) {
if(e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "yt dl error");
@@ -174,7 +171,7 @@ export default async bot => {
else if(link.match(regex.fourchan)) {
// 4chan via proxy - fuck cloudflare
try {
source = (await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
source = (await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
} catch(err) {
if(e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "yt dl error");
@@ -276,7 +273,8 @@ export default async bot => {
}
await db`
insert into items ${db({
insert into items ${
db({
src: e.media ? "" : link,
dest: filename,
mime: mime,
@@ -293,16 +291,6 @@ export default async bot => {
const itemid = await queue.getItemID(filename);
// auto-tag sfw
await db`
insert into tags_assign ${db({
item_id: itemid,
tag_id: 1, // sfw
user_id: 2 // f0ck
}, 'item_id', 'tag_id', 'user_id')
}
`;
// generate thumbnail
try {
await queue.genThumbnail(filename, mime, itemid, link);
@@ -351,7 +339,7 @@ export default async bot => {
else {
await e.reply(outputmsgirc);
}
}
});
}
}];
};

View File

@@ -1,7 +0,0 @@
@each(items as item)
<a href="{{ link.main }}{{ item.id }}" data-mime="{{ item.mime }}"
data-mode="{{ item.tag_id ? ['','sfw','nsfw'][item.tag_id] : 'null' }}"
style="background-image: url('/t/{{ item.id }}.webp')">
<p></p>
</a>
@endeach

View File

@@ -8,7 +8,7 @@
<a href="/tags">tags</a>
<a href="/about">about</a>
@if(!/^\/\d$/.test(url.pathname))
<a href="/random" id="nav-random">rand</a>
<a href="/random">rand</a>
@endif
</ol>
</div>
@@ -33,7 +33,7 @@
<a href="/tags">tags</a>
<a href="/about">about</a>
@if(!/^\/\d$/.test(url.pathname))
<a href="/random" id="nav-random">rand</a>
<a href="/random">rand</a>
@endif
</ol>
</div>