fixing url uploads in shitpost mode
This commit is contained in:
@@ -419,6 +419,28 @@ window.initUploadForm = (selector) => {
|
||||
updateSubmitButton();
|
||||
});
|
||||
|
||||
// In shitpost mode: auto-commit each pasted URL to the list immediately
|
||||
urlInput.addEventListener('paste', (e) => {
|
||||
if (!isShitpost) return;
|
||||
e.preventDefault();
|
||||
const pasted = (e.clipboardData || window.clipboardData).getData('text');
|
||||
const lines = pasted.split(/[\n\r]+/).map(u => u.trim()).filter(u => /^https?:\/\//i.test(u));
|
||||
if (!lines.length) {
|
||||
// Not a URL — let the browser insert it normally into the input
|
||||
urlInput.value = pasted.trim();
|
||||
urlInput.dispatchEvent(new Event('input'));
|
||||
return;
|
||||
}
|
||||
lines.forEach(url => {
|
||||
if (!selectedFiles.some(item => item.type === 'url' && item.url === url)) {
|
||||
selectedFiles.push({ type: 'url', url, rating: '', tags: [], comment: '', is_oc: false });
|
||||
}
|
||||
});
|
||||
urlInput.value = '';
|
||||
if (urlBadge) urlBadge.style.display = 'none';
|
||||
handleFile();
|
||||
});
|
||||
|
||||
if (urlBadge) {
|
||||
urlBadge.addEventListener('click', () => {
|
||||
const val = urlInput.value.trim();
|
||||
@@ -429,30 +451,30 @@ window.initUploadForm = (selector) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Add URL button (shitpost mode) — commits the typed/pasted URL to the list
|
||||
const addUrlFn = () => {
|
||||
const val = urlInput.value.trim();
|
||||
if (!val || !/^https?:\/\//i.test(val)) return;
|
||||
if (!selectedFiles.some(item => item.type === 'url' && item.url === val)) {
|
||||
selectedFiles.push({ type: 'url', url: val, rating: '', tags: [], comment: '', is_oc: false });
|
||||
}
|
||||
urlInput.value = '';
|
||||
if (urlBadge) urlBadge.style.display = 'none';
|
||||
handleFile();
|
||||
};
|
||||
|
||||
const btnAddUrls = form.querySelector('.btn-add-urls');
|
||||
if (btnAddUrls) {
|
||||
btnAddUrls.addEventListener('click', () => {
|
||||
const val = urlInput.value.trim();
|
||||
if (!val) return;
|
||||
const lines = val.split('\n').map(u => u.trim()).filter(u => u.length > 0);
|
||||
lines.forEach(url => {
|
||||
if (/^https?:\/\//i.test(url)) {
|
||||
if (!selectedFiles.some(item => item.type === 'url' && item.url === url)) {
|
||||
selectedFiles.push({
|
||||
type: 'url',
|
||||
url: url,
|
||||
rating: '',
|
||||
tags: [],
|
||||
comment: '',
|
||||
is_oc: false
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
urlInput.value = '';
|
||||
handleFile();
|
||||
btnAddUrls.addEventListener('click', addUrlFn);
|
||||
}
|
||||
|
||||
// Also commit on Enter key inside the URL input in shitpost mode
|
||||
if (isShitpost) {
|
||||
urlInput.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') { e.preventDefault(); addUrlFn(); }
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const formatSize = (bytes) => {
|
||||
@@ -1653,7 +1675,8 @@ window.initUploadForm = (selector) => {
|
||||
rating: fileRating,
|
||||
tags: fileTags.join(','),
|
||||
is_oc: (isShitpost ? item.is_oc : isOc),
|
||||
comment: fileComment
|
||||
comment: fileComment,
|
||||
is_shitpost: isShitpost ? true : undefined
|
||||
}));
|
||||
} else {
|
||||
xhr.send(formData);
|
||||
@@ -1663,6 +1686,12 @@ window.initUploadForm = (selector) => {
|
||||
if (res.success) {
|
||||
successCount++;
|
||||
lastData = res;
|
||||
if (res.pending) {
|
||||
// Background URL download — show toast using server's message
|
||||
if (typeof window.flashMessage === 'function') {
|
||||
window.flashMessage(res.msg, 4000, 'info');
|
||||
}
|
||||
}
|
||||
if (res.itemid) {
|
||||
try {
|
||||
const ts = Date.now();
|
||||
|
||||
@@ -202,20 +202,25 @@ export default router => {
|
||||
return res.json({ success: false, msg: 'URL uploads are disabled' }, 403);
|
||||
}
|
||||
|
||||
const { url: inputUrl, rating, tags: tagsRaw, comment, is_oc } = req.post || {};
|
||||
const { url: inputUrl, rating, tags: tagsRaw, comment, is_oc, is_shitpost } = req.post || {};
|
||||
|
||||
if (!inputUrl || !inputUrl.trim()) {
|
||||
return res.json({ success: false, msg: 'URL is required' }, 400);
|
||||
}
|
||||
if (!rating || !['sfw', 'nsfw', 'nsfl'].includes(rating)) {
|
||||
|
||||
// In shitpost mode rating is optional; null = no rating tag assigned
|
||||
const effectiveRating = (rating && ['sfw', 'nsfw', 'nsfl'].includes(rating)) ? rating : (is_shitpost ? null : null);
|
||||
|
||||
if (!is_shitpost && !effectiveRating) {
|
||||
return res.json({ success: false, msg: 'Rating (sfw/nsfw/nsfl) is required' }, 400);
|
||||
}
|
||||
if (rating === 'nsfl' && !cfg.enable_nsfl) {
|
||||
if (effectiveRating === 'nsfl' && !cfg.enable_nsfl) {
|
||||
return res.json({ success: false, msg: 'NSFL mode is currently disabled' }, 400);
|
||||
}
|
||||
const tags = tagsRaw ? tagsRaw.split(',').map(t => t.trim()).filter(t => t.length > 0 && !['sfw', 'nsfw', 'nsfl'].includes(t.toLowerCase())) : [];
|
||||
const minTags = getMinTags();
|
||||
if (tags.length < minTags) {
|
||||
// In shitpost mode tags are optional
|
||||
if (!is_shitpost && tags.length < minTags) {
|
||||
return res.json({ success: false, msg: `At least ${minTags} tag${minTags !== 1 ? 's' : ''} required` }, 400);
|
||||
}
|
||||
|
||||
@@ -287,11 +292,13 @@ export default router => {
|
||||
await queue.spawn('magick', ['-size', '128x128', 'xc:#1a1a1a', '-gravity', 'center', '-fill', '#666', '-pointsize', '20', '-annotate', '0', 'YouTube', path.join(tDir, `${itemid}.webp`)]).catch(() => {});
|
||||
}
|
||||
|
||||
// Assign rating tag
|
||||
const ratingTagId = rating === 'sfw' ? 1 : (rating === 'nsfw' ? 2 : (cfg.nsfl_tag_id || 3));
|
||||
await db`insert into tags_assign ${db({ item_id: itemid, tag_id: ratingTagId, user_id: req.session.id })} on conflict do nothing`;
|
||||
if (rating === 'nsfw' || rating === 'nsfl') {
|
||||
await queue.genBlurredThumbnail(itemid, isApprovalRequired).catch(() => {});
|
||||
// Assign rating tag (only if a rating was selected)
|
||||
if (effectiveRating) {
|
||||
const ratingTagId = effectiveRating === 'sfw' ? 1 : (effectiveRating === 'nsfw' ? 2 : (cfg.nsfl_tag_id || 3));
|
||||
await db`insert into tags_assign ${db({ item_id: itemid, tag_id: ratingTagId, user_id: req.session.id })} on conflict do nothing`;
|
||||
if (effectiveRating === 'nsfw' || effectiveRating === 'nsfl') {
|
||||
await queue.genBlurredThumbnail(itemid, isApprovalRequired).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
// Assign user tags + auto-tags
|
||||
@@ -563,14 +570,17 @@ export default router => {
|
||||
|
||||
try {
|
||||
await queue.genThumbnail(filename, mime, itemid, url, isApprovalRequired);
|
||||
if (rating === 'nsfw' || rating === 'nsfl') await queue.genBlurredThumbnail(itemid, isApprovalRequired);
|
||||
if (effectiveRating === 'nsfw' || effectiveRating === 'nsfl') await queue.genBlurredThumbnail(itemid, isApprovalRequired);
|
||||
} catch (err) {
|
||||
const tDir = isApprovalRequired ? path.join(cfg.paths.pending, 't') : cfg.paths.t;
|
||||
await queue.spawn('magick', ['-size', '128x128', 'xc:#1a1a1a', path.join(tDir, `${itemid}.webp`)]).catch(() => {});
|
||||
}
|
||||
|
||||
const ratingTagId = rating === 'sfw' ? 1 : (rating === 'nsfw' ? 2 : (cfg.nsfl_tag_id || 3));
|
||||
await db`insert into tags_assign ${db({ item_id: itemid, tag_id: ratingTagId, user_id: session.id })}`;
|
||||
// Assign rating tag (only if a rating was selected)
|
||||
if (effectiveRating) {
|
||||
const ratingTagId = effectiveRating === 'sfw' ? 1 : (effectiveRating === 'nsfw' ? 2 : (cfg.nsfl_tag_id || 3));
|
||||
await db`insert into tags_assign ${db({ item_id: itemid, tag_id: ratingTagId, user_id: session.id })}`;
|
||||
}
|
||||
const autoTags = autoTagsFromUrl(url);
|
||||
const allTags = [...new Set([...tags, ...autoTags])];
|
||||
for (const tagName of allTags) {
|
||||
@@ -594,7 +604,7 @@ export default router => {
|
||||
mime: mime,
|
||||
username: session.user,
|
||||
display_name: session.display_name || null,
|
||||
tag_id: rating === 'sfw' ? 1 : (rating === 'nsfw' ? 2 : (cfg.nsfl_tag_id || 3)),
|
||||
tag_id: effectiveRating ? (effectiveRating === 'sfw' ? 1 : (effectiveRating === 'nsfw' ? 2 : (cfg.nsfl_tag_id || 3))) : 0,
|
||||
is_oc: !!is_oc
|
||||
})})`;
|
||||
} catch (err) {
|
||||
|
||||
@@ -40,10 +40,10 @@
|
||||
<div class="upload-mode-content" id="mode-url" style="display: none;">
|
||||
<div class="url-input-container">
|
||||
@if(shitpost_mode)
|
||||
<div class="url-shitpost-container">
|
||||
<textarea id="url-upload-input" name="url" placeholder="{{ t('upload.url_placeholder_shitpost') || 'Paste multiple URLs here (one per line)...' }}" autocomplete="off" style="width: 100%; min-height: 100px; background: rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.1); color: #fff; padding: 10px; border-radius: 4px; resize: vertical;"></textarea>
|
||||
<div class="url-shitpost-container" style="display: flex; flex-direction: column; gap: 6px;">
|
||||
<input type="url" id="url-upload-input" name="url" placeholder="Paste or type a URL..." autocomplete="off" style="width: 100%;">
|
||||
<button type="button" class="btn-add-urls">
|
||||
<i class="fa-solid fa-plus-circle"></i> {{ t('upload.btn_add_urls') }}
|
||||
<i class="fa-solid fa-plus-circle"></i> Add
|
||||
</button>
|
||||
</div>
|
||||
@else
|
||||
|
||||
Reference in New Issue
Block a user