master #50
60
config_example.json
Normal file
60
config_example.json
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"url": {
|
||||||
|
"full": "https://f0ck.dev",
|
||||||
|
"domain": "f0ck.dev",
|
||||||
|
"regex": "f0ck\\.dev"
|
||||||
|
},
|
||||||
|
"maxfilesize": 83886080,
|
||||||
|
"adminmultiplier": 3.5,
|
||||||
|
"ignored": [
|
||||||
|
"f0ck.dev",
|
||||||
|
"f0ck.me"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"allowedModes": [ "sfw", "nsfw", "untagged", "all" ],
|
||||||
|
"allowedMimes": [ "audio", "image", "video" ],
|
||||||
|
"websrv": {
|
||||||
|
"port": "8080",
|
||||||
|
"paths": {
|
||||||
|
"images": "/b",
|
||||||
|
"thumbnails": "/t",
|
||||||
|
"coverarts": "/ca"
|
||||||
|
},
|
||||||
|
"themes": [ "f0ck", "p1nk", "orange", "atmos", "amoled", "paper", "term", "iced" ],
|
||||||
|
"eps": 294,
|
||||||
|
"cache": false,
|
||||||
|
"phrases": [
|
||||||
|
"<img src=\"/s/img/crap/nyancat.gif\" style=\"margin-top: 5px\" />"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"clients": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"sql": {
|
||||||
|
"host": "localhost",
|
||||||
|
"user": "f0ck",
|
||||||
|
"password": "",
|
||||||
|
"database": "f0ck",
|
||||||
|
"schema": "public",
|
||||||
|
"multipleStatements": true
|
||||||
|
},
|
||||||
|
"admins": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"mimes": {
|
||||||
|
"image/png": "png",
|
||||||
|
"video/webm": "webm",
|
||||||
|
"image/gif": "gif",
|
||||||
|
"image/jpeg": "jpg",
|
||||||
|
"image/webp": "webp",
|
||||||
|
"video/mp4": "mp4",
|
||||||
|
"video/quicktime": "mp4",
|
||||||
|
"audio/mpeg": "mpg",
|
||||||
|
"audio/mp3": "mp3",
|
||||||
|
"audio/ogg": "ogg",
|
||||||
|
"audio/flac": "flac",
|
||||||
|
"audio/x-flac": "flac",
|
||||||
|
"video/x-m4v": "mp4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ import lib from "../src/inc/lib.mjs";
|
||||||
db({
|
db({
|
||||||
item_id: f.id,
|
item_id: f.id,
|
||||||
tag_id: tmp.nsfw ? 2 : 1,
|
tag_id: tmp.nsfw ? 2 : 1,
|
||||||
user_id: 7
|
user_id: 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -46,8 +46,8 @@ import lib from "../src/inc/lib.mjs";
|
||||||
insert into "tags_assign" ${
|
insert into "tags_assign" ${
|
||||||
db({
|
db({
|
||||||
item_id: f.id,
|
item_id: f.id,
|
||||||
tag_id: 8, // hentai
|
tag_id: 4, // hentai
|
||||||
user_id: 7 // autotagger
|
user_id: 1 // autotagger
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
213
f0ck.sql
Normal file
213
f0ck.sql
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
\connect "f0ck";
|
||||||
|
|
||||||
|
SET statement_timeout = 0;
|
||||||
|
SET lock_timeout = 0;
|
||||||
|
SET idle_in_transaction_session_timeout = 0;
|
||||||
|
SET client_encoding = 'UTF8';
|
||||||
|
SET standard_conforming_strings = on;
|
||||||
|
SELECT pg_catalog.set_config('search_path', '', false);
|
||||||
|
SET check_function_bodies = false;
|
||||||
|
SET xmloption = content;
|
||||||
|
SET client_min_messages = warning;
|
||||||
|
SET row_security = off;
|
||||||
|
|
||||||
|
CREATE FUNCTION public.delete_unused_tags() RETURNS trigger
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
begin
|
||||||
|
delete from tags
|
||||||
|
where
|
||||||
|
tags.id not in (select tag_id from tags_assign) and
|
||||||
|
tags.id = OLD.tag_id and
|
||||||
|
tags.tag != 'sfw' and
|
||||||
|
tags.tag != 'nsfw' and
|
||||||
|
tags.tag != 'hentai' and
|
||||||
|
tags.tag != 'audio';
|
||||||
|
return OLD;
|
||||||
|
end $$;
|
||||||
|
|
||||||
|
ALTER FUNCTION public.delete_unused_tags() OWNER TO f0ck;
|
||||||
|
|
||||||
|
CREATE FUNCTION public.fill_normalized() RETURNS trigger
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
begin
|
||||||
|
NEW.normalized = slugify(NEW.tag);
|
||||||
|
return NEW;
|
||||||
|
end$$;
|
||||||
|
|
||||||
|
ALTER FUNCTION public.fill_normalized() OWNER TO f0ck;
|
||||||
|
|
||||||
|
CREATE FUNCTION public.slugify(v text) RETURNS text
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
BEGIN
|
||||||
|
RETURN trim(BOTH '-' FROM regexp_replace(lower(unaccent(trim(v))), '[\u0000-\u002f \u003a-\u0040\u005b-\u0060\u007b-\u00bf]+', '', 'gi'));
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
ALTER FUNCTION public.slugify(v text) OWNER TO f0ck;
|
||||||
|
|
||||||
|
CREATE TABLE public.favorites (
|
||||||
|
user_id integer NOT NULL,
|
||||||
|
item_id integer NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE public.favorites OWNER TO f0ck;
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.items_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
ALTER TABLE public.items_id_seq OWNER TO f0ck;
|
||||||
|
|
||||||
|
CREATE TABLE public.items (
|
||||||
|
id integer DEFAULT nextval('public.items_id_seq'::regclass) NOT NULL,
|
||||||
|
src character varying(255) NOT NULL,
|
||||||
|
dest character varying(40) NOT NULL,
|
||||||
|
mime character varying(100) NOT NULL,
|
||||||
|
size integer NOT NULL,
|
||||||
|
checksum character varying(255) NOT NULL,
|
||||||
|
username character varying(40) 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;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public.items.src IS 'src-Link';
|
||||||
|
COMMENT ON COLUMN public.items.dest IS 'filename';
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.tags_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
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(45) NOT NULL,
|
||||||
|
normalized character varying(45) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE public.tags OWNER TO 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
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
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,
|
||||||
|
level integer NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE public."user" OWNER TO f0ck;
|
||||||
|
|
||||||
|
CREATE TABLE public.user_options (
|
||||||
|
user_id integer NOT NULL,
|
||||||
|
mode integer NOT NULL,
|
||||||
|
theme character varying(50) NOT NULL,
|
||||||
|
avatar integer DEFAULT 1 NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE public.user_options OWNER TO f0ck;
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.user_sessions_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1;
|
||||||
|
|
||||||
|
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,
|
||||||
|
user_id integer NOT NULL,
|
||||||
|
session character varying(32) NOT NULL,
|
||||||
|
browser character varying(255) NOT NULL,
|
||||||
|
created_at integer NOT NULL,
|
||||||
|
last_used integer NOT NULL,
|
||||||
|
last_action character varying(255) NOT NULL,
|
||||||
|
kmsi smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE public.user_sessions OWNER TO 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
|
||||||
|
\.
|
||||||
|
|
||||||
|
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
|
||||||
|
\.
|
||||||
|
|
||||||
|
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();
|
||||||
|
CREATE TRIGGER tags_bi BEFORE INSERT ON public.tags FOR EACH ROW EXECUTE FUNCTION public.fill_normalized();
|
||||||
|
CREATE TRIGGER tags_bu BEFORE UPDATE ON public.tags FOR EACH ROW EXECUTE FUNCTION public.fill_normalized();
|
||||||
|
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;
|
BIN
public/b/b761fa9339.png
Executable file
BIN
public/b/b761fa9339.png
Executable file
Binary file not shown.
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 160 KiB |
BIN
public/t/1.webp
Executable file
BIN
public/t/1.webp
Executable file
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -28,27 +28,46 @@ export default router => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group.get(/\/p\/([0-9]+)/, async (req, res) => { // legacy
|
group.get(/\/items\/get/, async (req, res) => {
|
||||||
let eps = 100;
|
let eps = 150;
|
||||||
let id = +req.url.split[3];
|
|
||||||
|
|
||||||
const rows = await db`
|
const opt = {
|
||||||
select *
|
older: req.url.qs.older ?? null,
|
||||||
from "items"
|
newer: req.url.qs.newer ?? null,
|
||||||
where id < ${+id}
|
mode: +req.url.qs.mode ?? 0 // 0 sfw, 1 nsfw, 2 untagged, 3 all
|
||||||
order by id desc
|
|
||||||
limit ${+eps}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const items = {
|
|
||||||
items: rows,
|
|
||||||
last: rows[rows.length - 1].id
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const newest = (await db`select max(id) as id from "items"`)[0].id;
|
||||||
|
const oldest = (await db`select min(id) as id from "items"`)[0].id;
|
||||||
|
const modequery = lib.getMode(opt.mode);
|
||||||
|
|
||||||
|
const rows = (await db`
|
||||||
|
select "items".id, "items".mime, coalesce("tags_assign".tag_id, 0) as tag_id
|
||||||
|
from "items"
|
||||||
|
left join "tags_assign" on "tags_assign".item_id = "items".id and ("tags_assign".tag_id = 1 or "tags_assign".tag_id = 2)
|
||||||
|
where
|
||||||
|
${db.unsafe(modequery)}
|
||||||
|
${
|
||||||
|
opt.older
|
||||||
|
? db`and id <= ${opt.older}`
|
||||||
|
: opt.newer
|
||||||
|
? db`and id >= ${opt.newer}`
|
||||||
|
: db``
|
||||||
|
}
|
||||||
|
order by id ${
|
||||||
|
opt.newer
|
||||||
|
? db`asc`
|
||||||
|
: db`desc`
|
||||||
|
}
|
||||||
|
limit ${eps}
|
||||||
|
`).sort((a, b) => b.id - a.id);
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
|
atEnd: rows[0].id === newest,
|
||||||
|
atStart: rows[rows.length - 1].id === oldest,
|
||||||
success: true,
|
success: true,
|
||||||
items
|
items: rows
|
||||||
});
|
}, 200);
|
||||||
});
|
});
|
||||||
|
|
||||||
group.get(/\/item\/[0-9]+$/, async (req, res) => {
|
group.get(/\/item\/[0-9]+$/, async (req, res) => {
|
||||||
|
@ -205,6 +224,12 @@ export default router => {
|
||||||
}
|
}
|
||||||
const postid = +req.post.postid;
|
const postid = +req.post.postid;
|
||||||
|
|
||||||
|
if(postid <= 1) {
|
||||||
|
return res.json({
|
||||||
|
success: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await db`
|
await db`
|
||||||
delete from "items"
|
delete from "items"
|
||||||
where id = ${+postid}
|
where id = ${+postid}
|
||||||
|
|
|
@ -131,6 +131,14 @@ export default router => {
|
||||||
const postid = +req.params.postid;
|
const postid = +req.params.postid;
|
||||||
const tagname = decodeURIComponent(req.params.tagname);
|
const tagname = decodeURIComponent(req.params.tagname);
|
||||||
|
|
||||||
|
if(tagname == 'sfw' || tagname == 'nsfw' || tagname == 'hentai' || tagname == 'audio') {
|
||||||
|
return res.json({
|
||||||
|
success: false,
|
||||||
|
msg: 'blacklisted',
|
||||||
|
tags: await lib.getTags(postid)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const tags = await lib.getTags(postid);
|
const tags = await lib.getTags(postid);
|
||||||
|
|
||||||
const tagid = tags.filter(t => t.tag === tagname)[0]?.id ?? null;
|
const tagid = tags.filter(t => t.tag === tagname)[0]?.id ?? null;
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
//import knex from "knex";
|
|
||||||
import postgres from "postgres";
|
import postgres from "postgres";
|
||||||
import cfg from "./config.mjs";
|
import cfg from "./config.mjs";
|
||||||
|
|
||||||
const db = postgres(cfg.sql);
|
export default postgres(cfg.sql);
|
||||||
|
|
||||||
if(cfg.sql.schema)
|
|
||||||
await db.unsafe(`set search_path to '${cfg.sql.schema}';`);
|
|
||||||
|
|
||||||
export default db;
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default async bot => {
|
||||||
|
|
||||||
for(let id of e.args) {
|
for(let id of e.args) {
|
||||||
id = +id;
|
id = +id;
|
||||||
if(id <= 0)
|
if(id <= 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const f0ck = await db`
|
const f0ck = await db`
|
||||||
|
|
|
@ -214,8 +214,8 @@ export default async bot => {
|
||||||
insert into "tags_assign" ${
|
insert into "tags_assign" ${
|
||||||
db({
|
db({
|
||||||
item_id: f.id,
|
item_id: f.id,
|
||||||
tag_id: 8, // hentai
|
tag_id: 4, // hentai
|
||||||
user_id: 7 // autotagger
|
user_id: 1 // autotagger
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -228,11 +228,11 @@ export default async bot => {
|
||||||
db([{
|
db([{
|
||||||
item_id: itemid,
|
item_id: itemid,
|
||||||
tag_id: 1,
|
tag_id: 1,
|
||||||
user_id: 7
|
user_id: 1
|
||||||
}, {
|
}, {
|
||||||
item_id: itemid,
|
item_id: itemid,
|
||||||
tag_id: 7178,
|
tag_id: 3, // audio
|
||||||
user_id: 7
|
user_id: 1
|
||||||
}])
|
}])
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user