Compare commits

..

No commits in common. "master" and "f0ck_local" have entirely different histories.

25 changed files with 340 additions and 774 deletions

View File

@ -5,7 +5,6 @@
"domain": "f0ck.dev",
"regex": "f0ck\\.dev"
},
"socks": "",
"maxfilesize": 83886080,
"adminmultiplier": 3.5,
"ignored": [

611
f0ck.sql
View File

@ -1,9 +1,4 @@
--
-- PostgreSQL database dump
--
-- Dumped from database version 16.2
-- Dumped by pg_dump version 16.2
\connect "f0ck";
SET statement_timeout = 0;
SET lock_timeout = 0;
@ -16,33 +11,7 @@ SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: public; Type: SCHEMA; Schema: -; Owner: postgres
--
-- *not* creating schema, since initdb creates it
ALTER SCHEMA public OWNER TO postgres;
--
-- Name: unaccent; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS unaccent WITH SCHEMA public;
--
-- Name: EXTENSION unaccent; Type: COMMENT; Schema: -; Owner:
--
COMMENT ON EXTENSION unaccent IS 'text search dictionary that removes accents';
--
-- Name: delete_unused_tags(); Type: FUNCTION; Schema: public; Owner: f0ck
--
CREATE EXTENSION unaccent;
CREATE FUNCTION public.delete_unused_tags() RETURNS trigger
LANGUAGE plpgsql
AS $$
@ -52,17 +21,14 @@ begin
tags.id not in (select tag_id from tags_assign) and
tags.id = OLD.tag_id and
tags.tag != 'sfw' and
tags.tag != 'nsfw';
tags.tag != 'nsfw' and
tags.tag != 'hentai' and
tags.tag != 'audio';
return OLD;
end $$;
ALTER FUNCTION public.delete_unused_tags() OWNER TO f0ck;
--
-- Name: fill_normalized(); Type: FUNCTION; Schema: public; Owner: f0ck
--
CREATE FUNCTION public.fill_normalized() RETURNS trigger
LANGUAGE plpgsql
AS $$
@ -71,13 +37,8 @@ begin
return NEW;
end$$;
ALTER FUNCTION public.fill_normalized() OWNER TO f0ck;
--
-- Name: slugify(text); Type: FUNCTION; Schema: public; Owner: f0ck
--
CREATE FUNCTION public.slugify(v text) RETURNS text
LANGUAGE plpgsql
AS $$
@ -86,47 +47,15 @@ BEGIN
END;
$$;
ALTER FUNCTION public.slugify(v text) OWNER TO f0ck;
--
-- Name: unaccent_text(text); Type: FUNCTION; Schema: public; Owner: f0ck
--
CREATE FUNCTION public.unaccent_text(text) RETURNS text
LANGUAGE sql IMMUTABLE COST 1
AS $_$
-- unaccent is STABLE, but the indexes must use IMMUTABLE functions.
-- comment this line out when calling pg_dump.
SELECT unaccent($1);
-- Uncomment this line when calling pg_dump.
--SELECT ''::text;
$_$;
ALTER FUNCTION public.unaccent_text(text) OWNER TO f0ck;
SET default_tablespace = '';
SET default_table_access_method = heap;
--
-- Name: favorites; Type: TABLE; Schema: public; Owner: f0ck
--
CREATE TABLE public.favorites (
user_id integer NOT NULL,
item_id integer NOT NULL
);
ALTER TABLE public.favorites OWNER TO f0ck;
--
-- Name: items_id_seq; Type: SEQUENCE; Schema: public; Owner: f0ck
--
CREATE SEQUENCE public.items_id_seq
START WITH 1
INCREMENT BY 1
@ -134,12 +63,7 @@ CREATE SEQUENCE public.items_id_seq
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE public.items_id_seq OWNER TO f0ck;
--
-- Name: items; Type: TABLE; Schema: public; Owner: f0ck
--
ALTER TABLE public.items_id_seq OWNER TO f0ck;
CREATE TABLE public.items (
id integer DEFAULT nextval('public.items_id_seq'::regclass) NOT NULL,
@ -149,115 +73,18 @@ CREATE TABLE public.items (
size integer NOT NULL,
checksum character varying(255) NOT NULL,
username character varying(40) NOT NULL,
userchannel character varying(255) NOT NULL,
userchannel character varying(100) NOT NULL,
usernetwork character varying(40) NOT NULL,
stamp integer NOT NULL,
active boolean NOT NULL,
thumb character varying(100)
);
ALTER TABLE public.items OWNER TO f0ck;
--
-- Name: COLUMN items.src; Type: COMMENT; Schema: public; Owner: f0ck
--
COMMENT ON COLUMN public.items.src IS 'src-Link';
--
-- Name: COLUMN items.dest; Type: COMMENT; Schema: public; Owner: f0ck
--
COMMENT ON COLUMN public.items.dest IS 'filename';
--
-- Name: items_li; Type: VIEW; Schema: public; Owner: f0ck
--
CREATE VIEW public.items_li AS
SELECT
NULL::integer AS id,
NULL::character varying(255) AS src,
NULL::character varying(40) AS dest,
NULL::character varying(100) AS mime,
NULL::integer AS size,
NULL::character varying(255) AS checksum,
NULL::character varying(40) AS username,
NULL::character varying(255) AS userchannel,
NULL::character varying(40) AS usernetwork,
NULL::integer AS stamp;
ALTER VIEW public.items_li OWNER TO f0ck;
--
-- Name: tags_assign; Type: TABLE; Schema: public; Owner: f0ck
--
CREATE TABLE public.tags_assign (
item_id integer NOT NULL,
tag_id integer NOT NULL,
user_id integer DEFAULT 10 NOT NULL
);
ALTER TABLE public.tags_assign OWNER TO f0ck;
--
-- Name: tags_nsfp; Type: TABLE; Schema: public; Owner: f0ck
--
CREATE TABLE public.tags_nsfp (
id integer NOT NULL
);
ALTER TABLE public.tags_nsfp OWNER TO f0ck;
--
-- Name: items_sfw; Type: VIEW; Schema: public; Owner: f0ck
--
CREATE VIEW public.items_sfw AS
SELECT ( SELECT
CASE
WHEN (tags_assign.tag_id > 0) THEN tags_assign.tag_id
ELSE 0
END AS "case"
FROM public.tags_assign
WHERE ((tags_assign.tag_id = ANY (ARRAY[1, 2])) AND (tags_assign.item_id = items.id))) AS sfw,
( SELECT
CASE
WHEN (tags_assign.tag_id > 0) THEN 1
ELSE 0
END AS "case"
FROM public.tags_assign
WHERE ((tags_assign.tag_id IN ( SELECT tags_nsfp.id
FROM public.tags_nsfp)) AND (tags_assign.item_id = items.id))
LIMIT 1) AS nsfp,
id,
src,
dest,
mime,
size,
checksum,
username,
userchannel,
usernetwork,
stamp,
active
FROM public.items;
ALTER VIEW public.items_sfw OWNER TO f0ck;
--
-- Name: tags_id_seq; Type: SEQUENCE; Schema: public; Owner: f0ck
--
CREATE SEQUENCE public.tags_id_seq
START WITH 1
INCREMENT BY 1
@ -265,25 +92,30 @@ CREATE SEQUENCE public.tags_id_seq
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE public.tags_id_seq OWNER TO f0ck;
--
-- Name: tags; Type: TABLE; Schema: public; Owner: f0ck
--
ALTER TABLE public.tags_id_seq OWNER TO f0ck;
CREATE TABLE public.tags (
id integer DEFAULT nextval('public.tags_id_seq'::regclass) NOT NULL,
tag character varying(70) NOT NULL,
normalized character varying(70) NOT NULL
tag character varying(45) NOT NULL,
normalized character varying(45) NOT NULL
);
ALTER TABLE public.tags OWNER TO f0ck;
--
-- Name: user_id_seq; Type: SEQUENCE; Schema: public; Owner: f0ck
--
CREATE TABLE public.tags_alias (
tag_orig_id integer NOT NULL,
tag_alias character varying NOT NULL
);
ALTER TABLE public.tags_alias OWNER TO f0ck;
CREATE TABLE public.tags_assign (
item_id integer NOT NULL,
tag_id integer NOT NULL,
user_id integer DEFAULT 2 NOT NULL
);
ALTER TABLE public.tags_assign OWNER TO f0ck;
CREATE SEQUENCE public.user_id_seq
START WITH 1
@ -292,128 +124,31 @@ CREATE SEQUENCE public.user_id_seq
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE public.user_id_seq OWNER TO f0ck;
--
-- Name: user; Type: TABLE; Schema: public; Owner: f0ck
--
ALTER TABLE public.user_id_seq OWNER TO f0ck;
CREATE TABLE public."user" (
id integer DEFAULT nextval('public.user_id_seq'::regclass) NOT NULL,
login character varying(255) NOT NULL,
"user" character varying(255) NOT NULL,
password character varying(167) NOT NULL,
admin boolean NOT NULL,
created_at timestamp without time zone DEFAULT now() NOT NULL
level integer NOT NULL
);
ALTER TABLE public."user" OWNER TO f0ck;
--
-- Name: items_tags; Type: VIEW; Schema: public; Owner: f0ck
--
CREATE VIEW public.items_tags AS
SELECT ( SELECT
CASE
WHEN (tags_assign.tag_id > 0) THEN tags_assign.tag_id
ELSE 0
END AS "case"
FROM public.tags_assign
WHERE ((tags_assign.tag_id = ANY (ARRAY[1, 2])) AND (tags_assign.item_id = items.id))) AS sfw,
( SELECT
CASE
WHEN (tags_assign.tag_id > 0) THEN 1
ELSE 0
END AS "case"
FROM public.tags_assign
WHERE ((tags_assign.tag_id IN ( SELECT tags_nsfp.id
FROM public.tags_nsfp)) AND (tags_assign.item_id = items.id))
LIMIT 1) AS nsfp,
( SELECT jsonb_agg(jsonb_build_object('id', tags.id, 'normalized', tags.normalized)) AS jsonb_agg
FROM (public.tags_assign
LEFT JOIN public.tags ON ((tags.id = tags_assign.tag_id)))
WHERE (tags_assign.item_id = items.id)) AS tags,
( SELECT jsonb_agg(jsonb_build_object('id', favorites.user_id, 'user', "user"."user")) AS jsonb_agg
FROM (public.favorites
LEFT JOIN public."user" ON (("user".id = favorites.user_id)))
WHERE (favorites.item_id = items.id)) AS favs,
id,
src,
dest,
mime,
size,
checksum,
username,
userchannel,
usernetwork,
stamp,
active
FROM public.items;
ALTER VIEW public.items_tags OWNER TO f0ck;
--
-- Name: tags_alias; Type: TABLE; Schema: public; Owner: f0ck
--
CREATE TABLE public.tags_alias (
tag_orig_id integer NOT NULL,
tag_alias character varying NOT NULL
);
ALTER TABLE public.tags_alias OWNER TO f0ck;
--
-- Name: user_alias; Type: TABLE; Schema: public; Owner: f0ck
--
CREATE TABLE public.user_alias (
userid integer NOT NULL,
alias character varying(255) NOT NULL
);
ALTER TABLE ONLY public.user_alias REPLICA IDENTITY FULL;
ALTER TABLE public.user_alias OWNER TO f0ck;
--
-- Name: user_options; Type: TABLE; Schema: public; Owner: f0ck
--
CREATE TABLE public.user_options (
user_id integer NOT NULL,
mode integer NOT NULL,
theme character varying(50) NOT NULL,
avatar integer DEFAULT 56660 NOT NULL,
fullscreen smallint DEFAULT '0'::smallint NOT NULL
avatar integer DEFAULT 1 NOT NULL,
fullscreen integer DEFAULT 0 NOT NULL
);
ALTER TABLE public.user_options OWNER TO f0ck;
--
-- Name: user_sessions_id_seq; Type: SEQUENCE; Schema: public; Owner: f0ck
--
CREATE SEQUENCE public.user_sessions_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1;
CREATE SEQUENCE public.user_sessions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE public.user_sessions_id_seq OWNER TO f0ck;
--
-- Name: user_sessions; Type: TABLE; Schema: public; Owner: f0ck
--
ALTER TABLE public.user_sessions_id_seq OWNER TO f0ck;
CREATE TABLE public.user_sessions (
id integer DEFAULT nextval('public.user_sessions_id_seq'::regclass) NOT NULL,
@ -426,255 +161,55 @@ CREATE TABLE public.user_sessions (
kmsi smallint DEFAULT '0'::smallint NOT NULL
);
ALTER TABLE public.user_sessions OWNER TO f0ck;
--
-- Name: favorites idx_16521_primary; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
COPY public.items (id, src, dest, mime, size, checksum, username, userchannel, usernetwork, stamp, active, thumb) FROM stdin;
1 b761fa9339.png b761fa9339.png image/png 164 keinPlan Flummi #f0ck n0xy 1471250800 t
\.
ALTER TABLE ONLY public.favorites
ADD CONSTRAINT idx_16521_primary PRIMARY KEY (user_id, item_id);
COPY public.tags (id, tag, normalized) FROM stdin;
1 sfw sfw
2 nsfw nsfw
3 audio audio
4 hentai hentai
\.
COPY public.tags_assign (item_id, tag_id, user_id) FROM stdin;
1 1 1
\.
--
-- Name: items idx_16526_primary; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.items
ADD CONSTRAINT idx_16526_primary PRIMARY KEY (id);
--
-- Name: user idx_16554_primary; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public."user"
ADD CONSTRAINT idx_16554_primary PRIMARY KEY (id);
--
-- Name: user_options idx_16567_user_id; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.user_options
ADD CONSTRAINT idx_16567_user_id UNIQUE (user_id);
--
-- Name: user_sessions idx_16572_primary; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.user_sessions
ADD CONSTRAINT idx_16572_primary PRIMARY KEY (id);
--
-- Name: items items_checksum; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.items
ADD CONSTRAINT items_checksum UNIQUE (checksum);
--
-- Name: tags_alias tags_alias_tag_alias_tag_orig_id; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags_alias
ADD CONSTRAINT tags_alias_tag_alias_tag_orig_id UNIQUE (tag_alias, tag_orig_id);
--
-- Name: tags_alias tags_alias_tag_orig_id; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags_alias
ADD CONSTRAINT tags_alias_tag_orig_id PRIMARY KEY (tag_orig_id);
--
-- Name: tags_assign tags_assign_item_id_tag_id_primary; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags_assign
ADD CONSTRAINT tags_assign_item_id_tag_id_primary PRIMARY KEY (item_id, tag_id);
--
-- Name: tags_assign tags_assign_item_id_tag_id_unique; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags_assign
ADD CONSTRAINT tags_assign_item_id_tag_id_unique UNIQUE (item_id, tag_id);
--
-- Name: tags tags_id; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags
ADD CONSTRAINT tags_id PRIMARY KEY (id);
--
-- Name: tags tags_normalized; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags
ADD CONSTRAINT tags_normalized UNIQUE (normalized);
--
-- Name: tags tags_tag; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags
ADD CONSTRAINT tags_tag UNIQUE (tag);
--
-- Name: user_options user_options_user_id; Type: CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.user_options
ADD CONSTRAINT user_options_user_id PRIMARY KEY (user_id);
--
-- Name: items_li _RETURN; Type: RULE; Schema: public; Owner: f0ck
--
CREATE OR REPLACE VIEW public.items_li AS
SELECT items.id,
items.src,
items.dest,
items.mime,
items.size,
items.checksum,
items.username,
items.userchannel,
items.usernetwork,
items.stamp
FROM ((public.items
JOIN public.tags_assign ta1 ON (((ta1.tag_id = 1) AND (ta1.item_id = items.id))))
JOIN public.tags_assign ta2 ON (((NOT (ta2.tag_id IN ( SELECT tags_nsfp.id
FROM public.tags_nsfp))) AND (ta2.item_id = items.id))))
WHERE items.active
GROUP BY items.id;
--
-- Name: tags_assign tags_assign_ad; Type: TRIGGER; Schema: public; Owner: f0ck
--
COPY public."user" (id, login, "user", password, level) FROM stdin;
1 autotagger autotagger f0ck you 0
2 deleted deleted f0ck you 0
\.
SELECT pg_catalog.setval('public.items_id_seq', 2, true);
SELECT pg_catalog.setval('public.tags_id_seq', 5, true);
SELECT pg_catalog.setval('public.user_id_seq', 3, true);
SELECT pg_catalog.setval('public.user_sessions_id_seq', 1, true);
ALTER TABLE ONLY public.favorites ADD CONSTRAINT idx_16521_primary PRIMARY KEY (user_id, item_id);
ALTER TABLE ONLY public.items ADD CONSTRAINT idx_16526_primary PRIMARY KEY (id);
ALTER TABLE ONLY public."user" ADD CONSTRAINT idx_16554_primary PRIMARY KEY (id);
ALTER TABLE ONLY public.user_options ADD CONSTRAINT idx_16567_user_id UNIQUE (user_id);
ALTER TABLE ONLY public.user_sessions ADD CONSTRAINT idx_16572_primary PRIMARY KEY (id);
ALTER TABLE ONLY public.items ADD CONSTRAINT items_checksum UNIQUE (checksum);
ALTER TABLE ONLY public.tags_alias ADD CONSTRAINT tags_alias_tag_alias_tag_orig_id UNIQUE (tag_alias, tag_orig_id);
ALTER TABLE ONLY public.tags_alias ADD CONSTRAINT tags_alias_tag_orig_id PRIMARY KEY (tag_orig_id);
ALTER TABLE ONLY public.tags_assign ADD CONSTRAINT tags_assign_item_id_tag_id_primary PRIMARY KEY (item_id, tag_id);
ALTER TABLE ONLY public.tags_assign ADD CONSTRAINT tags_assign_item_id_tag_id_unique UNIQUE (item_id, tag_id);
ALTER TABLE ONLY public.tags ADD CONSTRAINT tags_id PRIMARY KEY (id);
ALTER TABLE ONLY public.tags ADD CONSTRAINT tags_normalized UNIQUE (normalized);
ALTER TABLE ONLY public.tags ADD CONSTRAINT tags_tag UNIQUE (tag);
ALTER TABLE ONLY public.user_options ADD CONSTRAINT user_options_user_id PRIMARY KEY (user_id);
CREATE TRIGGER tags_assign_ad AFTER DELETE ON public.tags_assign FOR EACH ROW EXECUTE FUNCTION public.delete_unused_tags();
--
-- Name: tags tags_bi; Type: TRIGGER; Schema: public; Owner: f0ck
--
CREATE TRIGGER tags_bi BEFORE INSERT ON public.tags FOR EACH ROW EXECUTE FUNCTION public.fill_normalized();
--
-- Name: tags tags_bu; Type: TRIGGER; Schema: public; Owner: f0ck
--
CREATE TRIGGER tags_bu BEFORE UPDATE ON public.tags FOR EACH ROW EXECUTE FUNCTION public.fill_normalized();
--
-- Name: favorites favorites_item_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.favorites
ADD CONSTRAINT favorites_item_id_fkey FOREIGN KEY (item_id) REFERENCES public.items(id) ON DELETE CASCADE;
--
-- Name: favorites favorites_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.favorites
ADD CONSTRAINT favorites_user_id_fkey FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE CASCADE;
--
-- Name: tags_alias tags_alias_tag_orig_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags_alias
ADD CONSTRAINT tags_alias_tag_orig_id_fkey FOREIGN KEY (tag_orig_id) REFERENCES public.tags(id) ON DELETE CASCADE;
--
-- Name: tags_assign tags_assign_item_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags_assign
ADD CONSTRAINT tags_assign_item_id_fkey FOREIGN KEY (item_id) REFERENCES public.items(id) ON DELETE CASCADE;
--
-- Name: tags_assign tags_assign_tag_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags_assign
ADD CONSTRAINT tags_assign_tag_id_fkey FOREIGN KEY (tag_id) REFERENCES public.tags(id) ON DELETE CASCADE;
--
-- Name: tags_assign tags_assign_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.tags_assign
ADD CONSTRAINT tags_assign_user_id_fkey FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE SET DEFAULT;
--
-- Name: user_options user_options_avatar_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.user_options
ADD CONSTRAINT user_options_avatar_fkey FOREIGN KEY (avatar) REFERENCES public.items(id) ON DELETE SET DEFAULT;
--
-- Name: user_options user_options_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.user_options
ADD CONSTRAINT user_options_user_id_fkey FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE CASCADE;
--
-- Name: user_sessions user_sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: f0ck
--
ALTER TABLE ONLY public.user_sessions
ADD CONSTRAINT user_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE CASCADE;
--
-- Name: alltables; Type: PUBLICATION; Schema: -; Owner: postgres
--
CREATE PUBLICATION alltables FOR ALL TABLES WITH (publish = 'insert, update, delete, truncate');
ALTER PUBLICATION alltables OWNER TO postgres;
--
-- Name: SCHEMA public; Type: ACL; Schema: -; Owner: postgres
--
REVOKE USAGE ON SCHEMA public FROM PUBLIC;
GRANT ALL ON SCHEMA public TO PUBLIC;
--
-- PostgreSQL database dump complete
--
ALTER TABLE ONLY public.favorites ADD CONSTRAINT favorites_item_id_fkey FOREIGN KEY (item_id) REFERENCES public.items(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.favorites ADD CONSTRAINT favorites_user_id_fkey FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.tags_alias ADD CONSTRAINT tags_alias_tag_orig_id_fkey FOREIGN KEY (tag_orig_id) REFERENCES public.tags(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.tags_assign ADD CONSTRAINT tags_assign_item_id_fkey FOREIGN KEY (item_id) REFERENCES public.items(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.tags_assign ADD CONSTRAINT tags_assign_tag_id_fkey FOREIGN KEY (tag_id) REFERENCES public.tags(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.tags_assign ADD CONSTRAINT tags_assign_user_id_fkey FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE SET DEFAULT;
ALTER TABLE ONLY public.user_options ADD CONSTRAINT user_options_avatar_fkey FOREIGN KEY (avatar) REFERENCES public.items(id) ON DELETE SET DEFAULT;
ALTER TABLE ONLY public.user_options ADD CONSTRAINT user_options_user_id_fkey FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.user_sessions ADD CONSTRAINT user_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE CASCADE;

View File

@ -2992,27 +2992,3 @@ button#togglebg {
.fader-out {
animation: fadeOut .8s steps(100) forwards
}
.settings {
display: grid;
justify-content: center;
}
input[name="i_avatar"] {
text-align: center;
width: 50px;
padding: 10px;
}
input#s_avatar {
padding: 5px;
border: 1px solid var(--black);
border-radius: 3px;
background-image: linear-gradient(to bottom, var(--nav-link-background-linear-gradient));
box-shadow: var(--nav-link-box-shadow);
cursor: pointer;
}
#s_avatar:hover {
background: #ffffff0f;
}

View File

@ -333,8 +333,7 @@ const flash = ({ type, msg }) => {
document.querySelector("a#a_toggle").addEventListener("click", toggleEvent);
[...document.querySelectorAll("#tags > .badge > a:first-child")].map(t => t.addEventListener("click", editTagEvent));
[...document.querySelectorAll("#tags > .badge > a:last-child")].map(t => t.addEventListener("click", deleteEvent));
if(document.querySelector("svg#a_delete"))
document.querySelector("svg#a_delete").addEventListener("click", deleteButtonEvent);
document.querySelector("svg#a_delete").addEventListener("click", deleteButtonEvent);
document.querySelector("svg#a_favo").addEventListener("click", toggleFavEvent);
document.addEventListener("keyup", e => {

View File

@ -1,4 +1,4 @@
import _config from "../../config.json" with { type: "json" };
import _config from "../../config.json" assert { type: "json" };
let config = JSON.parse(JSON.stringify(_config));

View File

@ -134,6 +134,15 @@ export default new class {
const derivedKey = await scrypt(str, salt, 64);
return crypto.timingSafeEqual(keyBuffer, derivedKey);
};
async auth(req, res, next) {
if(!req.session) {
return res.reply({
code: 401,
body: "401 - Unauthorized"
});
}
return next();
};
async getTags(itemid) {
const tags = await db`
select "tags".id, "tags".tag, "tags".normalized, "user".user
@ -208,27 +217,6 @@ export default new class {
TABLE_NAME='user_options' and
COLUMN_NAME = 'avatar'
`)[0].avatar;
};
// meddlware
async auth(req, res, next) {
if(!req.session || !req.session.admin) {
return res.reply({
code: 401,
body: "401 - Unauthorized"
});
}
return next();
};
async loggedin(req, res, next) {
if(!req.session) {
return res.reply({
code: 401,
body: "401 - Unauthorized"
});
}
return next();
};
}
};

View File

@ -7,13 +7,12 @@ import url from "url";
const globalfilter = cfg.nsfp.map(n => `tag_id = ${n}`).join(' or ');
export default {
getf0cks: async (o = { user, tag, mime, page, mode, fav, session, limit }) => {
getf0cks: async (o = { user, tag, mime, page, mode, fav, session }) => {
const user = o.user ? decodeURI(o.user) : null;
const tag = lib.parseTag(o.tag ?? null);
const mime = o.mime ?? null;
const page = +(o.page ?? 1);
const smime = cfg.allowedMimes.includes(mime) ? mime + "/%" : mime === "" ? "%" : "%";
const eps = o.limit ?? cfg.websrv.eps;
const tmp = { user, tag, mime, smime, page, mode: o.mode };
const modequery = mime == "audio" ? lib.getMode(0) : lib.getMode(o.mode ?? 0);
@ -71,7 +70,7 @@ export default {
group by items.id, tags.tag, ta.tag_id
order by items.id desc
offset ${offset}
limit ${eps}
limit ${cfg.websrv.eps}
`;
const cheat = [];

View File

@ -3,7 +3,18 @@ import lib from "../lib.mjs";
import { exec } from "child_process";
import { promises as fs } from "fs";
const auth = async (req, res, next) => {
if(!req.session) {
return res.reply({
code: 401,
body: "401 - Unauthorized"
});
}
return next();
};
export default (router, tpl) => {
router.get(/^\/login(\/)?$/, async (req, res) => {
if(req.cookies.session) {
return res.reply({
@ -61,7 +72,7 @@ export default (router, tpl) => {
}).end();
});
router.get(/^\/logout$/, lib.loggedin, async (req, res) => {
router.get(/^\/logout$/, auth, async (req, res) => {
const usersession = await db`
select *
from "user_sessions"
@ -92,7 +103,7 @@ export default (router, tpl) => {
});
});
router.get(/^\/admin(\/)?$/, lib.auth, async (req, res) => { // frontpage
router.get(/^\/admin(\/)?$/, auth, async (req, res) => { // frontpage
res.reply({
body: tpl.render("admin", {
@ -103,7 +114,7 @@ export default (router, tpl) => {
});
});
router.get(/^\/admin\/sessions(\/)?$/, lib.auth, async (req, res) => {
router.get(/^\/admin\/sessions(\/)?$/, auth, async (req, res) => {
const rows = await db`
select "user_sessions".*, "user".user
from "user_sessions"
@ -121,7 +132,7 @@ export default (router, tpl) => {
});
});
router.get(/^\/admin\/log(\/)?$/, lib.auth, async (req, res) => {
router.get(/^\/admin\/log(\/)?$/, auth, async (req, res) => {
exec("journalctl -qeu f0ck --no-pager", (err, stdout) => {
res.reply({
body: tpl.render("admin/log", {
@ -132,7 +143,7 @@ export default (router, tpl) => {
});
});
router.get(/^\/admin\/recover\/?/, lib.auth, async (req, res) => {
router.get(/^\/admin\/recover\/?/, auth, async (req, res) => {
if(req.url.qs?.id) {
const id = +req.url.qs.id;
const f0ck = await db`

View File

@ -139,7 +139,7 @@ export default router => {
// tags lol
group.put(/\/admin\/tags\/(?<tagname>.*)/, lib.loggedin, async (req, res) => {
group.put(/\/admin\/tags\/(?<tagname>.*)/, lib.auth, async (req, res) => {
if(!req.params.tagname || !req.post.newtag) {
return res.json({
success: false,
@ -187,7 +187,7 @@ export default router => {
return res.json(q, tagname === newtag ? 200 : 201); // created (modified)
});
group.get(/\/admin\/tags\/suggest$/, lib.loggedin, async (req, res) => {
group.get(/\/admin\/tags\/suggest$/, lib.auth, async (req, res) => {
const reply = {
success: false,
suggestions: {}
@ -267,7 +267,7 @@ export default router => {
});
});
group.post(/\/admin\/togglefav$/, lib.loggedin, async (req, res) => {
group.post(/\/admin\/togglefav$/, lib.auth, async (req, res) => {
const postid = +req.post.postid;
let favs = await db`

View File

@ -3,7 +3,7 @@ import lib from '../../lib.mjs';
export default router => {
router.group(/^\/api\/v2\/settings/, group => {
group.put(/\/setAvatar/, lib.loggedin, async (req, res) => {
group.put(/\/setAvatar/, lib.auth, async (req, res) => {
if(!req.post.avatar) {
return res.json({
msg: 'no avatar provided',

View File

@ -3,7 +3,7 @@ import lib from '../../lib.mjs';
export default router => {
router.group(/^\/api\/v2\/admin\/(?<postid>\d+)\/tags/, group => {
group.get(/$/, lib.loggedin, async (req, res) => {
group.get(/$/, lib.auth, async (req, res) => {
// get tags
if(!req.params.postid) {
return res.json({
@ -18,7 +18,7 @@ export default router => {
});
});
group.post(/$/, lib.loggedin, async (req, res) => {
group.post(/$/, lib.auth, async (req, res) => {
// assign and/or create tag
if(!req.params.postid || !req.post.tagname) {
return res.json({
@ -80,7 +80,7 @@ export default router => {
});
});
group.put(/\/toggle$/, lib.loggedin, async (req, res) => {
group.put(/\/toggle$/, lib.auth, async (req, res) => {
// xD
if(!req.params.postid) {
return res.json({

View File

@ -14,7 +14,7 @@ export default (router, tpl) => {
const user = decodeURIComponent(req.params.user);
const query = await db`
select "user".user, "user".admin, "user".created_at, user_options.*
select "user".user, "user".created_at, user_options.*
from user_options
left join "user" on "user".id = user_options.user_id
where "user".user ilike ${user}
@ -31,42 +31,31 @@ export default (router, tpl) => {
});
}
let f0cks, favs;
const f0cks = await f0cklib.getf0cks({
user: user,
mode: req.session.mode,
fav: false,
session: !!req.session
});
const favs = await f0cklib.getf0cks({
user: user,
mode: req.session.mode,
fav: true,
session: !!req.session
});
const count = {
f0cks: 0,
favs: 0
};
try {
f0cks = await f0cklib.getf0cks({
user: user,
mode: req.session.mode,
fav: false,
session: !!req.session,
limit: 99999999
});
if('items' in f0cks) {
count.f0cks = f0cks.items.length;
f0cks.items = f0cks.items.slice(0, 50);
}
} catch(err) {
f0cks = false;
count.f0cks = 0;
if('items' in f0cks) {
count.f0cks = f0cks.items.length;
f0cks.items = f0cks.items.slice(0, 50);
}
try {
favs = await f0cklib.getf0cks({
user: user,
mode: req.session.mode,
fav: true,
session: !!req.session,
limit: 99999999
});
if('items' in favs) {
count.favs = favs.items.length;
favs.items = favs.items.slice(0, 50);
}
} catch(err) {
favs = false;
count.favs = 0;
if('items' in favs) {
count.favs = favs.items.length;
favs.items = favs.items.slice(0, 50);
}
const data = {
@ -111,7 +100,7 @@ export default (router, tpl) => {
});
});
router.get(/^\/mode\/(\d)/, lib.loggedin, async (req, res) => {
router.get(/^\/mode\/(\d)/, auth, async (req, res) => {
const mode = +req.url.split[1];
let referertmp = req.headers.referer;
let referer = "";

View File

@ -1,26 +0,0 @@
import db from "../../inc/sql.mjs";
import cfg from "../../inc/config.mjs";
import f0cklib from "../routeinc/f0cklib.mjs";
export default (router, tpl) => {
router.get(/^\/picdump$/, async (req, res) => {
const dump = await db`
SELECT *
FROM items
WHERE (
to_timestamp(stamp) >= date_trunc('week', CURRENT_TIMESTAMP - interval '1 week') AND
to_timestamp(stamp) < date_trunc('week', CURRENT_TIMESTAMP)
) AND
mime LIKE 'image/%'
ORDER BY stamp DESC
`;
res.reply({
body: tpl.render('picdump', {
dump,
tmp: null
}, req)
});
});
return router;
};

View File

@ -8,13 +8,13 @@ export default (router, tpl) => {
try {
const list = await db`
select
"user".user, "user".admin,
"user".user,
coalesce("user_options".avatar, ${await lib.getDefaultAvatar()}) as avatar,
count(distinct(tag_id, item_id)) as count
from "tags_assign"
left join "user" on "user".id = "tags_assign".user_id
left join "user_options" on "user_options".user_id = "user".id
group by "user".user, "user_options".avatar, "user".admin
group by "user".user, "user_options".avatar
order by count desc
`;
const stats = await lib.countf0cks();

View File

@ -5,7 +5,7 @@ import search from "../routeinc/search.mjs";
const _eps = 20;
export default (router, tpl) => {
router.get(/^\/search(\/)?$/, lib.loggedin, async (req, res) => {
router.get(/^\/search(\/)?$/, lib.auth, async (req, res) => {
let ret;
let tag = req.url.qs.tag ?? [];
let page = req.url.qs.page ?? 1;

View File

@ -11,7 +11,7 @@ import path from "path";
const regex = {
all: /https?:\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?/gi,
yt: /(?:youtube\.com\/\S*(?:(?:\/e(?:mbed))?\/|watch\/?\?(?:\S*?&?v\=))|youtu\.be\/)([a-zA-Z0-9_-]{6,11})/gi,
imgur: /(?:https?:)?\/\/(\w+\.)?imgur\.com\/(\S*)(\..{3,4})/i,
imgur: /(?:https?:)?\/\/(\w+\.)?imgur\.com\/(\S*)(\.[a-zA-Z]{3})/gm,
instagram: /(?:https?:\/\/www\.)?instagram\.com\S*?\/(?:p|reel)\/(\w{11})\/?/im
};
const mediagroupids = new Set();
@ -51,8 +51,8 @@ export default async bot => {
console.log(`parsing ${links.length} link${links.length > 1 ? "s" : ""}...`);
links.forEach(async link => {
//if(regex.imgur.test(link))
// return await e.reply(`fuck imgur... seriously`);
if(regex.imgur.test(link))
await e.reply(`imgur schmimigur`);
if(regex.instagram.test(link))
await e.reply(`insta schminsta`);
@ -69,26 +69,21 @@ export default async bot => {
// read metadata
let ext;
if(link.match(regex.instagram)) {
// is instagram
if(regex.imgur.test(link)) {
// is imgur
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 ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext;
// will die extension von der url
ext = link.split(".").slice(-1).join(".");
} catch(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];
}
}
else if(link.match(regex.imgur)) {
// imghure
ext = link.split('.').pop();
}
else {
// is not instagram
try {
const meta = JSON.parse((await queue.exec(`yt-dlp ${cfg.main.socks} -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 -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"];
@ -105,43 +100,52 @@ export default async bot => {
disable_notification: true
});
// <download data>
// download data
const start = new Date();
let source;
if(link.match(regex.instagram)) {
try {
// add --cookies <path-to-cookies-file> on local instance if you want to avoid getting rate limited
source = (await queue.exec(`yt-dlp ${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, "instagram dl error");
return await e.reply("instagram dl error", err);
try {
if(regex.instagram.test(link))
try {
// add --cookies <path-to-cookies-file> on local instance if you want to avoid getting rate limited
source = (await queue.exec(`yt-dlp -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, "instagram dl error");
return await e.reply("instagram dl error", err);
}
else if(regex.imgur.test(link)) {
console.log("penis123");
try {
await queue.exec(`torsocks wget "${link}" -O "./tmp/${uuid}.${ext}"`);
source = "./tmp/"+uuid+"."+ext;
console.log(source);
} catch(err) {
console.log(err);
}
}
}
else if(link.match(regex.imgur)) {
// imghure via torsocks
try {
await queue.exec(`torsocks wget ${link} -O ./tmp/${uuid}.${ext}`);
source = `./tmp/${uuid}.${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');
else
{
try {
source = (await queue.exec(`yt-dlp -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, err);
return await e.reply(err);
}
}
} catch(err) {
console.log(err);
}
else {
try {
source = (await queue.exec(`yt-dlp ${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) {
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');
}
}
// </download data>
// this is how it was before I fucked it up :>
// try {
// source = (await queue.exec(`yt-dlp -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, "something went wrong lol");
// return await e.reply("something went wrong lol");
// }
if(!source) {
if(e.type == 'tg')
@ -211,19 +215,6 @@ export default async bot => {
await fs.promises.copyFile(source, `./public/b/${filename}`);
await fs.promises.unlink(source).catch(_=>{});
// user alias
let username = e.user.nick || e.user.username;
const alias = (await db`
select "user"."user"
from "user_alias"
join "user" on "user".id = user_alias.userid
where lower(user_alias.alias) ilike ${username}
limit 1
`)?.[0]?.user;
if(alias) {
username = alias;
}
await db`
insert into items ${
db({
@ -232,7 +223,7 @@ export default async bot => {
mime: mime,
size: size,
checksum: checksum,
username: username,
username: e.user.nick || e.user.username,
userchannel: e.channel,
usernetwork: e.network,
stamp: ~~(new Date() / 1000),

View File

@ -71,7 +71,7 @@ process.on('unhandledRejection', err => {
if(req.cookies.session) {
const user = await db`
select "user".id, "user".login, "user".user, "user".admin, "user_sessions".id as sess_id, "user_options".*
select "user".id, "user".login, "user".user, "user".level, "user_sessions".id as sess_id, "user_options".*
from "user_sessions"
left join "user" on "user".id = "user_sessions".user_id
left join "user_options" on "user_options".user_id = "user_sessions".user_id

View File

@ -2,7 +2,7 @@
<div class="pagewrapper">
<div id="main">
<div class="index-container">
@if(tmp.user)<h2>user: <a href="/user/{{ tmp.user.toLowerCase() }}">{!! tmp.user.toLowerCase() !!}</a>@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif</h2>@endif
@if(tmp.user)<h2>user: {!! tmp.user.toLowerCase() !!}@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif</h2>@endif
@if(tmp.tag)<h2>tag: @if(session)<a href="/search?tag={!! tmp.tag.toLowerCase() !!}" target="_blank">{!! tmp.tag.toLowerCase() !!}</a>@else{!! tmp.tag.toLowerCase() !!}@endif@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif</h2>@endif
<div class="posts">
@each(items as item)

View File

@ -14,7 +14,7 @@
<div class="gapRight">
<svg class="iconset" id="a_favo"><use href="/s/img/iconset.svg#heart_{{ Object.values(item.favorites).filter(u => u.user == session.user)[0] ? 'solid' : 'regular' }}"></use></svg>
<svg class="iconset" id="a_tfull"><use href="/s/img/iconset.svg#window-{{ fullscreen == 1 ? 'minimize' : 'maximize' }}"></use></svg>
@if(session.admin)<svg class="iconset" id="a_delete"><use href="/s/img/iconset.svg#cross"></use></svg>@endif
<svg class="iconset" id="a_delete"><use href="/s/img/iconset.svg#cross"></use></svg>
</div>
@endif
</div>
@ -83,7 +83,7 @@
@if(typeof item.tags !== "undefined")
@each(item.tags as tag)
<span @if(session)tooltip="{{ tag.user }}"@endif class="badge {{ tag.badge }} mr-2">
<a href="/tag/{{ tag.normalized }}">{!! tag.tag !!}</a>@if(session.admin)&nbsp;<a class="removetag" href="#">&#215;</a>@endif
<a href="/tag/{{ tag.normalized }}">{!! tag.tag !!}</a>@if(session)&nbsp;<a class="removetag" href="#">&#215;</a>@endif
</span>
@endeach
@endif

View File

@ -1,22 +0,0 @@
@include(snippets/header)
<div id="main">
<h2>Picdump (last week)</h2>
<div class="picdump">
@each(dump as line)
<a href="/{{ line.id }}"><img src="/t/{{ line.id }}.webp"></a>
@endeach
</div>
</div>
<style>
.picdump {
width: 100%;
padding: 10px;
}
.picdump > a {
margin-top: 12px;
}
.picdump > a > img {
width: 100%;
}
</style>
@include(snippets/footer)

View File

@ -11,8 +11,8 @@
@for(let i = 0; i < list.length; i++)
<tr>
<td>{{ i + 1 }}</td>
<td><a href="/{{ list[i].avatar }}"><img class="avatar" src="/t/{{ list[i].avatar }}.webp"></a></td>
<td>@if(list[i].admin)&#11088;&nbsp;@endif<a href="/user/{!! list[i].user !!}">{!! list[i].user !!}</a></td>
<td><a href="/{{ list[i].avatar }}"><img class="avatar" src="/t/{{ list[i].avatar }}.webp" /></a></td>
<td><a href="/user/{!! list[i].user !!}">{!! list[i].user !!}</a></td>
<td>{{ list[i].count }}</td>
</tr>
@endfor

View File

@ -1,6 +1,7 @@
@include(snippets/header)
<div class="settings">
<div id="main">
<h1>Settings</h1>
@if(session.avatar)<a href="/{{ session.avatar }}"><img id="img_avatar" src="/t/{{ session.avatar }}.webp" /></a>@endif
<h2>Account</h2>
<table class="table">
<tbody>
@ -9,23 +10,16 @@
<td>{{ session.id }}</td>
</tr>
<tr>
<td>admin</td>
<td>{{ !!session.admin }}</td>
<td>level</td>
<td>{{ session.level }}/100</td>
</tr>
<tr>
<td>username</td>
<td>{!! session.user !!}</td>
</tr>
<tr>
<td>@if(session.avatar)<a href="/{{ session.avatar }}"><img id="img_avatar" src="/t/{{ session.avatar }}.webp"></a>@endif</td>
<td><input type="text" class="input" name="i_avatar" value="{{ session.avatar }}"></td>
</tr>
<tr>
<td>mail</td>
<td><input type="text" class="input" name="i_mail" placeholder="hashed" disabled></td>
</tr>
<tr>
<td colspan="2"><input type="submit" id="s_avatar" value="save"></td>
<td>avatar</td>
<td><input type="text" class="input" name="i_avatar" value="{{ session.avatar }}" /><input type="submit" id="s_avatar" value="save" /></td>
</tr>
</tbody>
</table>

View File

@ -5,14 +5,14 @@
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link user" href="#" content="{{ session.user }}" data-toggle="dropdown">
<img src="@if(session.avatar)/t/{{ session.avatar }}.webp@else/s/img/ava/default.png@endif" class="avatar"><span>@if(session.admin)&#11088;&nbsp;@endif{{ session.user }}</span>
<img src="@if(session.avatar)/t/{{ session.avatar }}.webp@else/s/img/ava/default.png@endif" class="avatar" /><span>{{ session.user }}</span>
</a>
<ul class="dropdown-menu">
<li><a href="/user/{{ session.user.toLowerCase() }}">my profile</a></li>
<li><a href="/user/{{ session.user.toLowerCase() }}/f0cks">my f0cks</a></li>
<li><a href="/user/{{ session.user.toLowerCase() }}/favs">my favs</a></li>
<li><a href="/search">search</a></li>
@if(session.admin)<li><a href="/admin">Admin</a></li>@endif
<li><a href="/admin">Admin</a></li>
<li><a href="/about">About</a></li>
<li><a href="/ranking">ranking</a></li>
<li><a href="/settings">settings</a></li>

133
views/snippets/navbar2.html Normal file
View File

@ -0,0 +1,133 @@
@if(session)
<nav class="navbar navbar-expand-lg">
<a class="navbar-brand" href="/"><span class="f0ck" width="" height="">F0CK</span></a>
<div class="navigation-links">
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link" href="#" content="{{ session.user }}" data-toggle="dropdown">
<img src="@if(session.avatar)/t/{{ session.avatar }}.webp@else/s/img/ava/default.png@endif" class="avatar" /><span>{{ session.user }}</span>
</a>
<ul class="dropdown-menu">
<li><a href="/admin">adminpanel</a></li>
<li><a href="/user/{{ session.user.toLowerCase() }}/f0cks">my f0cks</a></li>
<li><a href="/user/{{ session.user.toLowerCase() }}/favs">my favs</a></li>
<li><a href="/settings">settings</a></li>
<li><a href="/search">search</a></li>
<li><a href="/about">About</a></li>
<li><a href="/ranking">Ranking</a></li>
<li><a href="/logout">logout</a></li>
</ul>
</li>
<li class="nav-item dropdown" id="themes">
<a class="nav-link ddcontent" href="#" content="{{ theme }}" data-toggle="dropdown">Themes</a>
<ul class="dropdown-menu">
@each(themes as t)
<li><a href="/theme/{{ t }}">{{ t }}</a></li>
@endeach
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link ddcontent" href="#"@if(tmp?.mime) content="{{ tmp?.mime }}" data-toggle="dropdown"@endif>Filter@if(!tmp?.mime)&nbsp;&#9660;@endif</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/@if(tmp?.user)user/{{ tmp?.user }}/@endif">All</a></li>
<li><a class="dropdown-item" href="/@if(tmp?.user)user/{{ tmp?.user }}/@endifaudio">Audio</a></li>
<li><a class="dropdown-item" href="/@if(tmp?.user)user/{{ tmp?.user }}/@endifvideo">Video</a></li>
<li><a class="dropdown-item" href="/@if(tmp?.user)user/{{ tmp?.user }}/@endifimage">Image</a></li>
</ul>
</li>
<li class="nav-item @if(session)dropdown@endif">
<a class="nav-link ddcontent" href="#"@if(typeof session.mode !== "undefined") content="{{ modes[session.mode] ?? 'sfw' }}" data-toggle="dropdown"@endif>Mode</a>
<ul class="dropdown-menu">
@for(let i = 0; i < modes.length; i++)
<li><a class="dropdown-item" href="/mode/{{ i }}">{{ modes[i] }}</a></li>
@endfor
</ul>
</li>
<li class="nav-item">
<a id="random" class="nav-link" href="/random">
<span class="nav-link-identifier">Random</span>
</a>
</li>
</ul>
</div>
<div class="collapse navbar-collapse show" id="navbarSupportedContent">
<div class="pagination-container-fluid">
<div class="pagination-wrapper">
@if(typeof pagination !== "undefined")
<nav class="pagination">
<a href="{{ link.main }}{{ link.path }}{{ pagination.start }}" class="page-item-1 btn start@if(!pagination.prev) disabled@endif">&laquo;</a>
<a href="{{ link.main }}{{ link.path }}{{ pagination.prev }}" class="page-item-2 btn prev@if(!pagination.prev) disabled@endif">&lsaquo;</a>
@each(pagination.cheat as i)
@if(i == pagination.page)
<span class="btn disabled">{{ i }}</span>
@else
<a href="{{ link.main }}{{ link.path }}{{ i }}" class="pagination-int-item btn">{{ i }}</a>
@endif
@endeach
<a href="{{ link.main }}{{ link.path }}{{ pagination.next }}" class="page-item-3 btn next@if(!pagination.next) disabled@endif">&rsaquo;</a>
<a href="{{ link.main }}{{ link.path }}{{ pagination.end }}" class="page-item-4 btn start@if(!pagination.next) disabled@endif">&raquo;</a>
</nav>
@endif
</div>
</div>
</div>
</nav>
@else
<nav class="navbar navbar-expand-lg">
<a class="navbar-brand" href="/"><span class="f0ck" width="" height="">F0CK</span></a>
<div class="navigation-links-guest">
<ul class="navbar-nav-guests">
<li class="nav-item dropdown">
<a class="nav-link" href="/about" data-toggle="dropdown">About</a>
<ul class="dropdown-menu">
<li><a href="/login">login</a></li>
</ul>
</li>
<li class="nav-item dropdown" id="themes">
<a class="nav-link ddcontent" href="#" content="{{ theme }}" data-toggle="dropdown">Themes</a>
<ul class="dropdown-menu">
@each(themes as t)
<li><a href="/theme/{{ t }}">{{ t }}</a></li>
@endeach
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link ddcontent" href="#"@if(tmp?.mime) content="{{ tmp?.mime }}" data-toggle="dropdown"@endif>Filter@if(!tmp?.mime)&nbsp;&#9660;@endif</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/@if(tmp?.user)user/{{ tmp?.user }}/@endif">All</a></li>
<li><a class="dropdown-item" href="/@if(tmp?.user)user/{{ tmp?.user }}/@endifaudio">Audio</a></li>
<li><a class="dropdown-item" href="/@if(tmp?.user)user/{{ tmp?.user }}/@endifvideo">Video</a></li>
<li><a class="dropdown-item" href="/@if(tmp?.user)user/{{ tmp?.user }}/@endifimage">Image</a></li>
</ul>
</li>
<li class="nav-item">
<a id="random" class="nav-link" href="/random">
<span class="nav-link-identifier">Random</span>
</a>
</li>
</ul>
</div>
<div class="collapse navbar-collapse show" id="navbarSupportedContent">
<div class="pagination-container-fluid">
<div class="pagination-wrapper">
@if(typeof pagination !== "undefined")
<nav class="pagination">
<a href="{{ link.main }}{{ link.path }}{{ pagination.start }}" class="page-item-1 btn start@if(!pagination.prev) disabled@endif">&laquo;</a>
<a href="{{ link.main }}{{ link.path }}{{ pagination.prev }}" class="page-item-2 btn prev@if(!pagination.prev) disabled@endif">&lsaquo;</a>
@each(pagination.cheat as i)
@if(i == pagination.page)
<span class="btn disabled">{{ i }}</span>
@else
<a href="{{ link.main }}{{ link.path }}{{ i }}" class="pagination-int-item btn">{{ i }}</a>
@endif
@endeach
<a href="{{ link.main }}{{ link.path }}{{ pagination.next }}" class="page-item-3 btn next@if(!pagination.next) disabled@endif">&rsaquo;</a>
<a href="{{ link.main }}{{ link.path }}{{ pagination.end }}" class="page-item-4 btn start@if(!pagination.next) disabled@endif">&raquo;</a>
</nav>
@endif
</div>
</div>
</div>
</nav>
@endif

View File

@ -8,7 +8,7 @@
@endif
<div class="layersoffear">
<div class="profile_head_username">
<span>@if(user.admin)&#11088;&nbsp;@endif{{ user.user }}</span>
<span>{{ user.user }}</span>
</div>
<div class="profile_head_user_stats">
ID: {{ user.user_id }} Joined: {{ user.created_at }}
@ -18,9 +18,9 @@
<div class="user_content_wrapper">
<div class="f0cks">
<div class="f0cks-header">
f0ck{{ count.f0cks == 1 ? '' : 's' }}: {{ count.f0cks }} <a href="{{ f0cks.link?.main }}">view all</a>
f0ck{{ count.f0cks == 1 ? '' : 's' }}: {{ count.f0cks }} <a href="{{ f0cks.link.main }}">view all</a>
</div>
@if(count.f0cks)
@if('items' in f0cks)
<div class="posts">
@each(f0cks.items as item)
<a href="{{ f0cks.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>
@ -32,9 +32,9 @@
</div>
<div class="favs">
<div class="favs-header">
fav{{ count.favs == 1 ? '' : 's' }}: {{ count.favs }} <a href="{{ favs.link?.main }}">view all</a>
fav{{ count.favs == 1 ? '' : 's' }}: {{ count.favs }} <a href="{{ favs.link.main }}">view all</a>
</div>
@if(count.favs)
@if('items' in favs)
<div class="posts">
@each(favs.items as item)
<a href="{{ favs.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>