This thread is only for feedback related to technical issues (bug reports, suggestions).
Mobile Support:https://github.com/PietroCarrara/Clover/releases/latest Thread For Mobile Feedback:
>>>/tech/6316 Matrix rooms:
https://matrix.to/#/#leftypolPublic:matrix.orgWe are currently working on improvements to the site, subject to the need of the tech team to sleep and go to their day jobs. If you need more immediate feedback please join the matrix room[s] and ask around. Feel free to leave comments, concerns, and suggestions about the tech side of the site here and we will try to get to it as soon as possible
Archived thread:
>>>/leftypol_archive/903To fix <a href="/meta/res/979.html#7789">>>>/meta/7789</a> stripped file sizes for the current strip_exif+use_exiftool case:<br/><a href="
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/e0ff3ea33ba2c81acdeb6bbc1b72ecd15a734be2/post.php#L1094" rel="nofollow" target="_blank">
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/e0ff3ea33ba2c81acdeb6bbc1b72ecd15a734be2/post.php#L1094</a><br/><pre class='code lang-'>if($error = shell_exec_error('exiftool -overwrite_original -ignoreMinorErrors -q -q -all= ' . escapeshellarg($file['tmp_name']))) { error(_('Could not strip EXIF metadata!'), null, $error); } else { clearstatcache(true, $file['tmp_name']); if (($newfilesize = filesize($file['tmp_name'])) !== false) $file['size'] = $newfilesize; }</pre><br/>More generally, operations that modify an uploaded file should reread its size.<br/><br/><a href="
https://www.php.net/manual/en/function.filesize.php" rel="nofollow" target="_blank">
https://www.php.net/manual/en/function.filesize.php</a><br/><a href="
https://www.php.net/manual/en/function.clearstatcache.php" rel="nofollow" target="_blank">
https://www.php.net/manual/en/function.clearstatcache.php</a>When the reply count drops and a recent version of the thread is available, the ids can be diffed:<br/><pre class='code lang-'>>> Array.from (document.querySelectorAll ("div.post.reply")).map (e => e.getAttribute ('id').replace (/^reply_/, '')).join (' ') "6727 …" $ diffids () { diff <(echo "$1" | tr ' ' '\n') <(echo "$2" | tr ' ' '\n'); } $ diffids "6727 …" "6727 …" 140d139 < 9986 151a151 > 10226</pre><br/>In this case the logs <a href="
https://leftypol.org/log.php?board=tech" rel="nofollow" target="_blank">
https://leftypol.org/log.php?board=tech</a> suggest 9986 was probably in "Deleted all posts by IP address".
Duplicate scripts:<br/><pre class='code lang-'>>> console.log (Object.entries (Array.from (document.getElementsByTagName ("script")).filter (e => e.hasAttribute ("src")).map (e => e.getAttribute ("src")).reduce ((acc, name, idx) => { if (name in acc) { acc [name].push (idx) } else { acc [name] = [idx] } return acc }, {})).filter (([name, indices]) => indices.length > 1).sort ((a, b) => a [1] [0] - b [1] [0]).map (([name, indices]) => name + ' ' + indices.toString ()).join ('\n')) /js/jquery.min.js 1,3 /js/inline-expanding.js 2,5</pre><br/>The source of the problem is this duplication:<br/><a href="
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/5faa622303f7a3d9568a7c89728c3095a664b5c7/inc/config.php#L1039" rel="nofollow" target="_blank">
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/5faa622303f7a3d9568a7c89728c3095a664b5c7/inc/config.php#L1039</a><br/><a href="
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/5faa622303f7a3d9568a7c89728c3095a664b5c7/inc/instance-config.php#L375" rel="nofollow" target="_blank">
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/5faa622303f7a3d9568a7c89728c3095a664b5c7/inc/instance-config.php#L375</a><br/><br/>While two jquery.min only slow page loads, the two inline-expanding cause double registration of listeners and duplicate options gui spans.
<a href="https://github.com/towards-a-new-leftypol/leftypol_lainchan/issues/318" rel="nofollow" target="_blank">https://github.com/towards-a-new-leftypol/leftypol_lainchan/issues/318</a><br/><span class="quote">> Syncronize spoiler button state on quick reply and main post form #318 </span><br/><br/>While looking into this the synchronization section of js/quick-reply.js turns out to be quite peculiar.<br/><a href="https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/dcf92dfef5f5ab900dc879d7dc4c3f04fab0aed8/js/quick-reply.js#L296" rel="nofollow" target="_blank">https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/dcf92dfef5f5ab900dc879d7dc4c3f04fab0aed8/js/quick-reply.js#L296</a><br/>Every time the quick reply form is manually closed and reopened, new listeners are installed on the forms and the window, but the old listeners are never cleared in the .close-btn click handler.<br/><a href="https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/dcf92dfef5f5ab900dc879d7dc4c3f04fab0aed8/js/quick-reply.js#L348" rel="nofollow" target="_blank">https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/dcf92dfef5f5ab900dc879d7dc4c3f04fab0aed8/js/quick-reply.js#L348</a><br/><br/>The effect can be observed on elements of the top form, such as the textarea, for which the inspector shows an ever increasing number of listeners. These keep the closed quick reply forms reachable and therefore uncollectable, leaking memory. They also transfer the top form text to each closed quick reply form, and after a sufficient number typing becomes sluggish. The .close-btn click handler should deregister all listeners that only served the closed quick reply form.<br/><br/>Keeping in mind that the current way of doing things leaks memory with abandon, the spoiler checkboxes can be synced by extending the synchronization section:<br/><pre class='code lang-'>const cbsync = (form1, form2, name) => { const sel = 'input[type="checkbox"][name="' + name + '"]' const cb1 = form1.find (sel) const cb2 = form2.find (sel) cb1.on ('change', () => { cb2.prop ('checked', cb1.prop ('checked')) }) cb2.on ('change', () => { cb1.prop ('checked', cb2.prop ('checked')) }) } cbsync ($origPostForm, $postForm, 'spoiler')</pre> Here's a cleanup_jquery_listeners utility function:<br/><pre class='code lang-'>const cleanup_jquery_listeners = cleanupspec => { // cleanupspec is a list of triples of // [jquery sets, selector or null, event string] // example: [ // [[$origPostForm, $postForm], 'input[type="text"],select', '.quickreply'], // [[$(window)], null, 'scroll.quickreply'] // ] for (const [sets, sel, events] of cleanupspec) { for (let oneset of sets) { if (sel != null) { oneset = oneset.find (sel) } oneset.off (events) } } }</pre><br/>Then in .close-btn click:<br/><pre class='code lang-'>const spec = [ [[$origPostForm, $postForm], 'textarea[name="body"]', '.quickreply'], [[$origPostForm, $postForm], 'input[type="text"],select', '.quickreply'], [[$(window)], null, 'scroll.quickreply'], [[$postForm], 'th .close-btn', 'click.quickreply'], ] cleanup_jquery_listeners (spec)</pre><br/>The $postForm is cleaned up for completeness. When spoilers are synced <a onclick="highlightReply('10441', event);" href="/tech/res/6724.html#10441">>>10441</a> they can be added to the spec list in the obvious way. All <em>on</em> calls need .quickreply on their events. The click, focus and scroll calls become .on('click.quickreply', …) and equivalent. The exceptions are the last two listeners of <a onclick="highlightReply('10455', event);" href="/tech/res/6724.html#10455">>>10455</a> which can be dealt with using callonce_factory <a onclick="highlightReply('10109', event);" href="/tech/res/6724.html#10109">>>10109</a>.
For the last two listeners of <a onclick="highlightReply('10455', event);" href="/tech/res/6724.html#10455">>>10455</a>, inside the outermost function of js/quick-reply.js:<br/><pre class='code lang-'>const stylesheet_handler_once = callonce_factory (() => { $(window).on('stylesheet', function() { do_css(); if ($('link#stylesheet').attr('href')) { $('link#stylesheet')[0].onload = do_css; } }); }) const qr_handler_once = callonce_factory (() => { $(window).on('quick-reply', function() { $('.quick-reply-btn').remove(); }); })</pre><br/>Then replace<br/><a href="
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/dcf92dfef5f5ab900dc879d7dc4c3f04fab0aed8/js/quick-reply.js#L375" rel="nofollow" target="_blank">
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/dcf92dfef5f5ab900dc879d7dc4c3f04fab0aed8/js/quick-reply.js#L375</a><br/>with<br/><span class="orangeQuote">< stylesheet_handler_once ()</span><br/>and replace<br/><a href="
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/dcf92dfef5f5ab900dc879d7dc4c3f04fab0aed8/js/quick-reply.js#L414" rel="nofollow" target="_blank">
https://github.com/towards-a-new-leftypol/leftypol_lainchan/blob/dcf92dfef5f5ab900dc879d7dc4c3f04fab0aed8/js/quick-reply.js#L414</a><br/>with<br/><span class="orangeQuote">< qr_handler_once ()</span><br/><br/><a onclick="highlightReply('10486', event);" href="/tech/res/6724.html#10486">>>10486</a><br/>Either templates/main.js or a new js/functools.js, entirely at the techs' option.
Temporary fix for spoiler sync #318 in Options -> User JS until the backend is fixed <a onclick="highlightReply('10441', event);" href="/tech/res/6724.html#10441">>>10441</a>.<br/><pre class='code lang-'>(() => { const cbsync = (form1, form2, name) => { const sel = 'input[type="checkbox"][name="' + name + '"]' const cb1 = form1.find (sel) const cb2 = form2.find (sel) cb1.on ('change', () => { cb2.prop ('checked', cb1.prop ('checked')) }) cb2.on ('change', () => { cb1.prop ('checked', cb2.prop ('checked')) }) } const spoilersync = () => { const ftop = $('form[name="post"]:first') const fquick = $('#quick-reply') if ((ftop.length != 1) || (fquick.length != 1)) { return; } if (fquick.attr ('data-userjs-spoilersync') == 'spoilersync') { return; } cbsync (ftop, fquick, 'spoiler') fquick.attr ('data-userjs-spoilersync', 'spoilersync') } spoilersync () $(window).on('quick-reply', spoilersync) })()</pre>
Updated Options -> User JS <a onclick="highlightReply('10101', event);" href="/tech/res/6724.html#10101">>>10101</a> with the current fixes.<br/>① catalog links in div.boardlist <a onclick="highlightReply('9483', event);" href="/tech/res/6724.html#9483">>>9483</a><br/>② thread stats and Unique IPs <a onclick="highlightReply('6744', event);" href="/tech/res/6724.html#6744">>>6744</a><br/>③ individual post hiding <a onclick="highlightReply('6753', event);" href="/tech/res/6724.html#6753">>>6753</a><br/>④ batch loop/once WebM setting <a onclick="highlightReply('6819', event);" href="/tech/res/6724.html#6819">>>6819</a><br/>⑤ top/bottom navlinks in the top bar <a onclick="highlightReply('6835', event);" href="/tech/res/6724.html#6835">>>6835</a><br/>⑥ generic file thumbs in catalog <a onclick="highlightReply('6843', event);" href="/tech/res/6724.html#6843">>>6843</a><br/>⑦ catalog link above OP <a onclick="highlightReply('6916', event);" href="/tech/res/6724.html#6916">>>6916</a><br/>⑧ quick reply spoiler sync <a onclick="highlightReply('10493', event);" href="/tech/res/6724.html#10493">>>10493</a><br/>⑨ quick reply before init_file_selector <a onclick="highlightReply('10494', event);" href="/tech/res/6724.html#10494">>>10494</a>
links like <a href="
https://leftychan.net/leftypol" rel="nofollow" target="_blank">
https://leftychan.net/leftypol</a> don't work anymore
>>34666Now that we have more active devs and most of the basic necessities are set up, I'll request to the dev team that this become a priority fix.
btw filename download should now be fixed.
>>34649auto-update.js is no longer deferred or tardy. This appears to have fixed the reliability issues with that script in normal use.
Thank you, once again.
>> console.log ((lines => lines.join ('\n') + '\nentries: ' + lines.length) (Object.entries (Array.from (document.getElementsByTagName ("script")).filter (e => e.hasAttribute ("src")).map (e => e.getAttribute ("src")).reduce ((acc, name, idx) => {
if (name in acc) {
acc [name].push (idx)
} else {
acc [name] = [idx]
}
return acc
}, {})).filter (([name, indices]) => indices.length > 1).sort ((a, b) => a [1] [0] - b [1] [0]).map (([name, indices]) => name + ' ' + indices.toString ())))
entries: 0
👍
>>34645 👍
>>34670That is strange, I'm not exactly sure what caused that.
The transfer method was a very rushed effort (for another example, flags were mistakenly added to 'body' instead of 'body_nomarkup').
>>34668Update: this appears to be false, only part of the problem has been fixed. Work on this is continuing.
>>34648>>34649You mention $('#inline-expand-max-input') and $('#autoScroll') as being empty and I've seen this issue in a few other cases (leading to things like a broken filter tab). Do you know what could cause them not to be found despite being generated immediately earlier? It feels like there must be something we messed up that causes them all not to work any more.
Otherwise I can patch the issue per-case with that 'find' fix you suggested.
>>34676>Do you know what could cause them not to be found despite being generated immediately earlier?This is explained in
>>34647. The options gui elements are only added to the global document in the $(document).ready of js/options.js. Prior to that they cannot be retrieved from the global document because they are only in the tabs, which go into options_div, which goes into options_handler, which is not yet in the global document. Js/options.js is effectively an undeclared order dependency of js/local-time.js
>>34646 js/inline-expanding.js
>>34648 js/auto-scroll.js
>>34649 and their friends, but it's placed too late in $config['additional_javascript']
>>34647.
>Otherwise I can patch the issue per-case with that 'find' fix you suggested.The main advantage of retrieving the options gui elements from the tabs instead of the document is to remove the undeclared order dependence on js/options.js, which if preserved may come back to bite you in the future.
Scripts usually declare their optional dependencies with //.
$ head -n 14 js/local-time.js
/*
* local-time.js
* https://github.com/savetheinternet/Tinyboard/blob/master/js/local-time.js
*
* Released under the MIT license
* Copyright (c) 2012 Michael Save <[email protected]>
* Copyright (c) 2013-2014 Marcin Łabanowski <[email protected]>
*
* Usage:
* // $config['additional_javascript'][] = 'js/jquery.min.js';
* // $config['additional_javascript'][] = 'js/strftime.min.js';
* $config['additional_javascript'][] = 'js/local-time.js';
*
*/
But jquery-ui.custom in quick-reply uses verbiage instead.
$ grep -F -ne "\$config['additional_javascript'][]" -r js | grep -e ';.\+'
js/quick-reply.js:11: * $config['additional_javascript'][] = 'js/jquery-ui.custom.min.js'; // Optional; if you want the form to be draggable.
js/show-backlinks.js:11: * // $config['additional_javascript'][] = 'js/post-hover'; (optional; must come first)
It should be switched to // for consistency and automation.
>>34678The sources can be seen from anywhere by cloning and pulling, but if the site requires JS then I won't be able to see ancillary features like issues and PRs. Currently GitHub has the best feature set available without JS, so by this specific criterion it's the best option, regardless of our feelings about Microsoft.
Here's an alpha version of a tool that checks the consistency of the ordering restrictions declared by individual scripts against the order in instance-config.php's $config['additional_javascript']. Ideally individual scripts would declare complete and correct ordering restrictions, but this doesn't hold
>>34677 in practice, so this tool can only provide a hint. It currently checks for:
- duplicates in $config['additional_javascript']
- unsatisfied dependencies that are not marked optional with //
>>34679- order reversals in individual scripts versus $config['additional_javascript']
- satisfiability of the full ordering restriction graph if all scripts were to be included
Here's a wrapper that sets up the grep calls:
$ cat addjs.sh
#!/bin/sh
SRC="$1"
grep -F -ne "\$config['additional_javascript'][]" -r "$SRC"/js > scripts.txt
grep -F -ne "\$config['additional_javascript'][]" "$SRC"/inc/instance-config.php > config.txt
python3 addjs.py scripts.txt config.txt
Sample invocation:
$ sh addjs.sh ~/Documents/leftypol_lainchan
js/forced-anon.js has js/style-select.js@12 js/options/general.js@13 but config has js/style-select.js@400 js/options/general.js@397
js/toggle-images.js has js/style-select.js@11 js/options/general.js@12 but config has js/style-select.js@400 js/options/general.js@397
js/no-animated-gif.js has js/style-select.js@10 js/options/general.js@11 but config has js/style-select.js@400 js/options/general.js@397
js/toggle-locked-threads.js has js/style-select.js@11 js/options/general.js@12 but config has js/style-select.js@400 js/options/general.js@397
js/options/general.js has js/style-select.js@9 js/options/general.js@10 but config has js/style-select.js@400 js/options/general.js@397
problems: 5
Currently, on the public sources, the only problem is style-select versus options/general, which is declared five times in the opposite order from $config['additional_javascript']. But this is the only
declared >>34677 ordering problem. The style selector has been moved around recently, piggybacking on its sorted fix, but its placement in $config['additional_javascript'] and its attempted transfer at the end of options/general haven't been kept consistent. This can be fixed in either direction once the long-term placement of the style selector is decided.
>>34683>Why not full images? They seem to support them.The first thing iqdb.org and friends do is shrink the image, so transferring full images is a waste of bandwidth on both ends when thumbnails are available. Unfortunately, not creating a retrievable thumbnail at all for spoilered images is a problem that goes all the way back to Tinyboard:
https://github.com/savetheinternet/Tinyboard/blob/master/post.php#L572Using the full images when either a thumbnail is not available or is a webp will be in a future version of
>>34682.
Upgrade of
>>34682 to use the full images when either thumbnails are not available or in an unsupported format. A failed iqdb search will provide a saucenao link using a thumbnail generated by iqdb. This hasn't been tested with image hiders, expanders and similar scripts that mutate the div.file subtree.
((getthumb, getfull, getdest, getthumb2, getfull2, realthumb, formatok, speclist, showft) => Array.from (document.querySelectorAll ("div.files > div.file")).map (e => [getthumb (e), getfull (e), getdest (e)]).map (([ethumb, efull, edest]) => [ethumb ? getthumb2 (ethumb) : null, efull ? getfull2 (efull) : null, edest]).map (([thumb, full, edest]) => [thumb, full, edest, thumb && realthumb (thumb) && formatok (thumb), full && formatok (full)]).filter (([thumb, full, edest, thumbok, fullok]) => thumbok || fullok).forEach (([thumb, full, edest, thumbok, fullok]) => {
const url = "https://leftypol.org" + (thumbok ? thumb : full)
const span = document.createElement ("span")
span.setAttribute ("class", "iqdb")
span.innerHTML = ' ' + (showft ? ((thumbok ? 'T' : 'F') + ':') : "") + speclist.map (([label, urlfun]) => '<a href="' + urlfun (url) + '" target="_blank">' + label + '</a>').join (' ')
edest.appendChild (span)
})) (
e => e.querySelector ("img.post-image"),
e => e.querySelector ('p.fileinfo a[target="_blank"][href*="/src/"]'),
e => e.querySelector ("span.details"),
e => e.getAttribute ("src"),
e => e.getAttribute ("href"),
s => /^\/[^\/]+\/thumb\//.test (s),
s => /[.](jpe?g|png|gif)$/i.test (s),
[
["iqdb", s => "https://iqdb.org/?url=" + s],
// ["nao", s => "https://saucenao.com/search.php?db=999&dbmaski=32768&url=" + s]
],
false
)
Multiupload with the site's scripts disabled but JS enabled in the dev tools console:
(count => {
const dest = document.querySelector ("tr#upload > td.upload-area")
if (dest == null) { return; }
const have = dest.querySelectorAll ('input[type="file"]').length
if (have >= count) { return; }
const make = n => '<br class="file_separator"/><input type="file" name="file' + n + '" id="upload_file' + n + '">'
const add = []
for (let k = 2; k <= count; k++) {
add.push (make (k))
}
dest.innerHTML += add.join ("")
}) (5)
test:
>>>/meta/10945Some harmless fun with the original filenames. If the filename looks like a timestamp from a board download
>>34492 the UTC date is provided. If it looks like an md5 hash
>>34524 an md5 search link is provided to r34. Other matchers might be added later. This is merely a demo, not anything serious.
((getfilesbody, getorig, decorate, providers) => getfilesbody ().forEach (([files, body]) => {
const infolist = Array.from (files.querySelectorAll ("div.file")).map ((f, index) => [getorig (f), index + 1]).filter (p => p [0] != null).map (([name, index]) => providers.map (p => p (name, index)).filter (s => s != null)).flat (1)
if (infolist.length > 0) {
decorate (body, infolist)
}
})) (
() => Array.from (document.querySelectorAll ("div.thread > div.files")).map (f => [f, f.parentNode.querySelector ("div.post.op > div.body")]).concat (Array.from (document.querySelectorAll ("div.post.reply")).map (r => [r.querySelector ("div.files"), r.querySelector ("div.body")]).filter (p => p [0] != null)),
f => {
const a = f.querySelector ('span.details > a[download][title^="Save as original filename"]')
return a == null ? null : a.getAttribute ("download")
},
(body, infolist) => {
const p = document.createElement ("p")
p.setAttribute ("class", "miscfilesbodyinfo")
p.innerHTML = infolist.join ("<br/>")
if (body.firstChild) {
body.insertBefore (p, body.firstChild)
const hr = document.createElement ("hr")
hr.setAttribute ("style", "clear: none;")
body.insertBefore (hr, p.nextSibling)
} else {
body.appendChild (p)
}
},
[
// (name, index) => "file " + index + " name " + name,
(name, index) => {
const m = name.match (/^([0-9a-fA-F]{32})[.]/)
if (m == null) { return null; }
const hash = m [1]
return "file " + index + " md5 " + hash + ' search <a href="https://rule34.xxx/index.php?page=post&s=list&tags=md5%3a' + hash + '" target="_blank">r34</a>'
},
(name, index) => {
const m = name.match (/^([0-9]{13})[.]/)
if (m == null) { return null; }
const time = parseInt (m [1], 10)
return "file " + index + " timestamp " + time + " date " + new Date (time).toUTCString ()
}
]
)
>>34690If you want that button gone right now without waiting for anything fancy you can go to Options → User CSS and enter:
div.post.op > p.intro > a.watchThread { display: none; }
Adding a button to quote every line in the comment field can be done from User JS, I'll post that tomorrow. Recovering missing line breaks from another site can only be done after you specify precise and complete rules for doing so.
>>34691>Recovering missing line breaks from another site can only be done after you specify precise and complete rules for doing so.No I mean it will avoid quoting text like
>Oh also I had another niche feature idea that I think would actually be used quite a bit but sounds silly.
>A "greentext/quote all text" button so you can copy and paste an article without having to manually add > to every line and inevitably miss a break in the middle of a paragraph due to the site it being copied from having weird formatting.
Because line breaks aren't always visible when adding the quotes manually, it will just keep it all green
>div.post.op > p.intro > a.watchThread { display: none; }Based, thanks
>>34692Here's some Options → User JS code to add a quote link to the post forms that quotes the lines of the comment field. To change the link's text modify the value of the a.innerText assignment. Empty lines and lines that look like post links are exempt from quoting. To modify the exemptions adjust the
untouched function.
(() => {
const empty = s => /^\s*$/.test (s)
const untouched = s => /^\s*>>(\d+|>\/\w+\/\d*)\s*$/.test (s)
const prefix = "> "
const oneline = s => (empty (s) || untouched (s)) ? s : (prefix + s)
const edit = s => s.split ("\n").map (oneline).join ("\n")
const perform = area => {
const vold = area.value
const vnew = edit (vold)
if (vold != vnew) {
area.focus ()
area.setRangeText (vnew, 0, vold.length, "end")
}
}
const install = form => {
const dest = form.querySelector ("div.banner")
const have = dest.querySelector ("a.quotecommentlines")
const area = form.querySelector ('textarea[name="body"]')
if (have == null) {
const a = document.createElement ("a")
a.setAttribute ("class", "quotecommentlines")
a.setAttribute ("href", "javascript:void(0)")
a.setAttribute ("title", "quote comment lines")
a.innerText = "> "
a.addEventListener ('click', event => {
perform (area)
})
dest.insertBefore (a, dest.firstChild)
} else if (form.getAttribute ("id") == "quick-reply") {
have.addEventListener ('click', event => {
perform (area)
})
}
}
const setup = () => {
const form = document.querySelector ('form[name="post"]')
if (form == null) { return; }
install (form)
const doquick = () => {
const q = document.querySelector ('form#quick-reply')
if (q != null) { install (q); }
}
doquick ()
$(window).on ('quick-reply', doquick)
}
setup ()
}) ()
There's no div.banner in the post form in index pages so
>>34693 only works in thread pages. Here's the fix to the
install function to make it work in both thread pages and index pages.
(() => {
const empty = s => /^\s*$/.test (s)
const untouched = s => /^\s*>>(\d+|>\/\w+\/\d*)\s*$/.test (s)
const prefix = "> "
const oneline = s => (empty (s) || untouched (s)) ? s : (prefix + s)
const edit = s => s.split ("\n").map (oneline).join ("\n")
const perform = area => {
const vold = area.value
const vnew = edit (vold)
if (vold != vnew) {
area.focus ()
area.setRangeText (vnew, 0, vold.length, "end")
}
}
const install = form => {
const area = form.querySelector ('textarea[name="body"]')
const listen = e => {
e.addEventListener ('click', event => {
perform (area)
})
}
const quick = form.getAttribute ("id") == "quick-reply"
const build = () => {
const a = document.createElement ("a")
a.setAttribute ("class", "quotecommentlines")
a.setAttribute ("href", "javascript:void(0)")
a.setAttribute ("title", "quote comment lines")
a.innerText = "> "
return a
}
const have = form.querySelector ("a.quotecommentlines")
const insert = e => {
if (quick) {
const dest = form.querySelector ("div.banner")
if (dest == null) { return; }
dest.insertBefore (e, dest.firstChild)
} else {
const dest = area.parentNode.previousSibling
if (dest == null) { return; }
dest.insertBefore (document.createElement ("br"), dest.firstChild)
dest.insertBefore (e, dest.firstChild)
}
}
if (have == null) {
const e = build ()
insert (e)
listen (e)
} else if (quick) {
insert (have)
listen (have)
}
}
const setup = () => {
const form = document.querySelector ('form[name="post"]')
if (form == null) { return; }
install (form)
const doquick = () => {
const q = document.querySelector ('form#quick-reply')
if (q != null) { install (q); }
}
doquick ()
$(window).on ('quick-reply', doquick)
}
setup ()
}) ()
Upgrade of
>>34687 to unify handling of the two sites. It'll work on some other vichan-based boards as well if their URLs are added.
(regexlisttest => ((sitespec, providers) => {
const site = sitespec.find (spec => spec ["test"] ())
if (!site) { return; }
const postfiles = site ["postfiles"]
const original = site ["original" ]
const decorate = site ["decorate" ]
site ["filesbody"] ().forEach (([files, body]) => {
const infolist = postfiles (files).map ((f, index) => [original (f), index + 1]).filter (p => p [0] != null).map (([name, index]) => providers.map (p => p (name, index)).filter (s => s != null)).flat (1)
if (infolist.length > 0) {
decorate (body, infolist)
}
})
}) (
[
{
test: regexlisttest ([
// /^https?:\/\//,
/^https?:\/\/leftychan\.net\//,
/^https?:\/\/leftypol\.org\//,
]),
filesbody: () => Array.from (document.querySelectorAll ("div.thread > div.files")).map (f => [f, f.parentNode.querySelector ("div.post.op > div.body")]).concat (Array.from (document.querySelectorAll ("div.post.reply")).map (r => [r.querySelector ("div.files"), r.querySelector ("div.body")]).filter (p => p [0] != null)),
postfiles: files => Array.from (files.querySelectorAll ("div.file")),
original: f => {
let e = f.querySelector ('span.postfilename')
if (e != null) { return e.hasAttribute ("title") ? e.getAttribute ("title") : e.innerText; }
e = f.querySelector ('span.details > a[download][title*="original filename"]')
if (e != null) { return e.getAttribute ("download"); }
return null
},
decorate: (body, infolist) => {
const p = document.createElement ("p")
p.setAttribute ("class", "miscfilesbodyinfo")
p.innerHTML = infolist.join ("<br/>")
if (body.firstChild) {
body.insertBefore (p, body.firstChild)
const hr = document.createElement ("hr")
hr.setAttribute ("style", "clear: none;")
body.insertBefore (hr, p.nextSibling)
} else {
body.appendChild (p)
}
}
}
], [
// (name, index) => "file " + index + " name " + name,
((link, speclist) => (name, index) => {
const m = name.match (/^([0-9a-fA-F]{32})[.]/)
if (m == null) { return null; }
const hash = m [1]
return "file " + index + " md5 " + hash + ' search ' + speclist.map (e => link (e ["href"] (hash), e ["name"])).join (" ")
}) (
(h, t) => '<a href="' + h + '" target="_blank">' + t + '</a>',
[
{
name: "r3",
href: s => "https://rule34.xxx/index.php?page=post&s=list&tags=md5%3a" + s,
}
]
),
(name, index) => {
const m = name.match (/^([0-9]{13})[-.]/)
if (m == null) { return null; }
const time = parseInt (m [1], 10)
return "file " + index + " timestamp " + time + " date " + new Date (time).toUTCString ()
}
]
)) (
regexlist => () => (url => regexlist.some (rx => rx.test (url))) (document.location.href)
)
>>34695Two minutes? Which board is this? It shouldn't ever be that high unless you're on a shared IP during high traffic (such as the Tor node) or making new threads (different message).
I can look into making a more lenient filter, we're currently just using the default basic one.
>>34697Lainchan was a mistake.Turns out the long-tern post filtering bug (cannot hide/filter individual posts in threads) was due to them adding a postcontainer div, apparently just so that they could add '>>' to the left of each reply. Since they don't use
bloat many of the additional Javascripts, they didn't realize it broke some.
As a side affect, I believe reverting that change fixed the issue where short posts are occasionally stacked to the right instead of below.
Filters appear to work fine now which opens up a lot of opportunities. Shout out if anything seems to have broken.
>>34698>adding a postcontainer divThe alternative solution with keeping postcontainer is in
>>>/leftypol_archive/1822 2021-01-29.
>>34701>which do you think is better?I have no opinion to offer on the costs/benefits of keeping versus removing div.postcontainer, so I trust your judgement that "the postcontainer didn't offer anything and broke scripts" and should therefore be removed. Regardless of the fate of postcontainer I also recommend the change
>>>/leftypol_archive/1822 from .parent() to .parents('.thread') simply because it makes the id retrieval more resilient by causing it to work both in the presence and absence of postcontainer.
Upgrade of
>>34696 to add support for lynx-based boards.
((regexlisttest, prefixhr) => ((sitespec, providers) => {
const site = sitespec.find (spec => spec ["test"] ())
if (!site) { return; }
const postfiles = site ["postfiles"]
const original = site ["original" ]
const decorate = site ["decorate" ]
site ["filesbody"] ().forEach (([files, body]) => {
const infolist = postfiles (files).map ((f, index) => [original (f), index + 1]).filter (p => p [0] != null).map (([name, index]) => providers.map (p => p (name, index)).filter (s => s != null)).flat (1)
if (infolist.length > 0) {
decorate (body, infolist)
}
})
}) (
[
{
test: regexlisttest ([
/^https?:\/\/someoldchan\.live\//,
]),
filesbody: () => Array.from (document.querySelectorAll ("div.innerOP, div.innerPost")).map (i => [i.querySelector ("div.panelUploads"), i.querySelector ("div.divMessage")]).filter (p => p [0] != null),
postfiles: files => Array.from (files.querySelectorAll ("figure.uploadCell")),
original: f => {
const e = f.querySelector ('a.originalNameLink[download]')
return e == null ? null : e.getAttribute ("download")
},
decorate: prefixhr ({join: '<br style="display: initial;"/>'})
}, {
test: regexlisttest ([
// /^https?:\/\//,
/^https?:\/\/leftychan\.net\//,
/^https?:\/\/leftypol\.org\//,
]),
filesbody: () => Array.from (document.querySelectorAll ("div.thread > div.files")).map (f => [f, f.parentNode.querySelector ("div.post.op > div.body")]).concat (Array.from (document.querySelectorAll ("div.post.reply")).map (r => [r.querySelector ("div.files"), r.querySelector ("div.body")]).filter (p => p [0] != null)),
postfiles: files => Array.from (files.querySelectorAll ("div.file")),
original: f => {
let e = f.querySelector ('span.postfilename')
if (e != null) { return e.hasAttribute ("title") ? e.getAttribute ("title") : e.innerText; }
e = f.querySelector ('span.details > a[download][title*="original filename"]')
if (e != null) { return e.getAttribute ("download"); }
return null
},
decorate: prefixhr ({join: "<br/>"})
}
], [
// (name, index) => "file " + index + " name " + name,
((link, speclist) => (name, index) => {
const m = name.match (/^([0-9a-fA-F]{32})[.]/)
if (m == null) { return null; }
const hash = m [1]
return "file " + index + " md5 " + hash + ' search ' + speclist.map (e => link (e ["href"] (hash), e ["name"])).join (" ")
}) (
(h, t) => '<a href="' + h + '" target="_blank">' + t + '</a>',
[
{
name: "r3",
href: s => "https://rule34.xxx/index.php?page=post&s=list&tags=md5%3a" + s,
}
]
),
(name, index) => {
const m = name.match (/^([0-9]{13})[-.]/)
if (m == null) { return null; }
const time = parseInt (m [1], 10)
return "file " + index + " timestamp " + time + " date " + new Date (time).toUTCString ()
}
]
)) (
regexlist => () => (url => regexlist.some (rx => rx.test (url))) (document.location.href),
config => (body, infolist) => {
const p = document.createElement ("p")
p.setAttribute ("class", "miscfilesbodyinfo")
p.innerHTML = infolist.join (config ["join"])
if (body.firstChild) {
body.insertBefore (p, body.firstChild)
const hr = document.createElement ("hr")
hr.setAttribute ("style", "clear: none;")
body.insertBefore (hr, p.nextSibling)
} else {
body.appendChild (p)
}
}
)
>>34704Are those posts still like that? Can you link them?
All the posts look like ISO8601 to me. The one I'm replying to is fine.
>>34707>In the reply boxTextarea is a plain text element without subrange styling.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textareaThe comment line quoter which avoids
>>34692 is in
>>34694.
>>34712How about having a separate button for embedding with a mirror?
Eg:
[Embed] [Mirror]
?
Ive had issues with some invidious instances. How can we choose a reliable one?
>>34717That would be cool, They could probably allow us to enter a custom instance in the options menu, so long as the default is a sane choice that proxies.
>>34715If your computer can't show .webp in a browser by now, I think you should look into fixing it.
>>34719I never really looked into it properly, but I have confirmed
https://incogtube.com proxies the videos instead of direct linking, and they also have Tor, I2P and Yggdrasil services.
aka.
http://tuberyps2pn6dor6h47brof3w2asmauahhk4ei42krugybzzzo55klad.onion/feed/trending >>34720>….onionThis works well. Ok, I'll put it in the backlog.
Maybe if you're on tor, it embeds the .onion, if you're on clearnet, it embeds the clearnet site. That makes the most sense, right? Or is clearnet preferred for both situations?
>>34717>Ive had issues with some invidious instances. How can we choose a reliable one?How about the [Mirror] button links to
https://redirect.invidious.io/watch?v={youtube_video_id}?
>>34722It's not just Tor users that want to use invidious instead of YouTube, so I'd rather link both Youtube and an invidious instance on clearnet as well.
Here's a radical idea though: how about we embed an invidious instance by default and provide the original Youtube link as secondary? Like this: [Embed] [YouTube]
>>34722If it's not difficult, Tor->Tor makes sense.
>>34724I support this.
>>34730(NTA) I guess the issue is:
- adding the instance-config so that it has convenient version control
- preventing sensitive information from being added
I wonder if using an 'include' at the bottom of the instance-config to store sensitive values in another config file is an appropriate solution.
Sorry for the unreasonable delays on many of these old issues. Hopefully we can get through them quicker now that we have more active devs with code access and a stable set-up.
File-thumbing on catalogs should now be fixed. Tested it on file uploads and deleting the first image of two in an OP.
Catalog posting without javascript now works, added an inline "list-style: none" to remove the drop-down triangle.
Fixed a few of the themes and added Midnight from
>>>/leftypol_archive/1541Let us know about any outstanding issues that aren't in the Gitea tracker.
>>34734 >>34729>I doubt they replace the password. It is much more likely that they don't actually use one.I have no way of knowing that, but we know a password was formerly in use:
> https://git.leftypol.org/leftypol/leftypol/commit/80dc724738310b5c86ff43a7b3c6977ccd74e965> lots of print statements> - $config['db']['password'] = 'oijrljqqwjr242kjn';> + $config['db']['password'] = '';Here's a generator for
>>34729 an instance-config-nosecrets.php:
$ cat instance-config-nosecrets.sh
#!/bin/sh
set -e
keylist ()
{
# in: cookies salt
# out: \['cookies'\]\['salt'\]
echo "$1" | sed -r -e 's/([^ ]+)( +|$)/\\['"'"'\1'"'"'\\]/g'
}
wipeone ()
{
# in: cookies salt
# out: s/^(\$config\['cookies'\]\['salt'\] *= *')[^']+('.+)$/\1\2/
env echo 's/^(\$config'"$(keylist "$1") *= *')[^']+('.+)\$/\1\2/"
}
nosecrets ()
{
sed -r \
-e "$(wipeone 'cookies salt')" \
-e "$(wipeone secure_trip_salt)" \
"$1" > "$2"
}
main ()
{
nosecrets inc/instance-config.php inc/instance-config-nosecrets.php
}
main
It can be rerun whenever instance-config.php is modified, and instance-config-nosecrets.php can be put into git. To verify:
$ diff inc/instance-config.php inc/instance-config-nosecrets.php
>>34733>File-thumbing on catalogs should now be fixed. Tested it on file uploads and deleting the first image of two in an OP.>Catalog posting without javascript now works, added an inline "list-style: none" to remove the drop-down triangle.👍
>Let us know about any outstanding issues that aren't in the Gitea tracker.I'll make a list, but it takes a bit.
Trimmed Options → User JS
>>34663 for the new backend fixes.
① catalog links in div.boardlist
>>34604② thread stats and Unique IPs
>>34497③ batch loop/once WebM setting
>>34519④ top/bottom navlinks in the top bar
>>34522⑤ catalog link above OP
>>34544⑥ quick reply spoiler sync
>>34661⑦ quick reply before init_file_selector
>>34662> outstanding issues that aren't in the Gitea tracker >>34733+ Unique IPs on the right | requested by
>>>/leftypol_archive/1601 >>>/leftypol_archive/1624 >>>/leftypol_archive/1756 | fix
>>34497+ batch loop/once WebM setting | requested by
>>>/leftypol_archive/1521 | frontend-only hack
>>34519+ update of old #229 sticky catalog for the new overboards | fix
>>34605+ catalog links in boardlist; as phrased #22 is distinct | requested by
>>>/leftypol_archive/1449 | fix
>>>/leftypol_archive/1807+ up/down buttons floating | requested by
>>>/leftypol_archive/1832 | frontend-only hack
>>34522+ per-file spoiler | requested by
>>34570 | see this thread on the other site #10799 #10800
+ leftover memory leaks from quick-reply sync
>>34655 >>34657 >>34658 >>34660+ restore instance-config.php to git without salts
>>34729 >>34735 >>34738Thank you very much for this.
Also, we might revert the deferring code, at least for things like the file-selector.js where it should be loaded timely to avoid complication.
>>34739>we might revert the deferring code, at least for things like the file-selector.js where it should be loaded timely to avoid complicationThat's for you to decide. On the same theme:
>>34641 >>34642 >>34651 >>34652 >>34654.
A backend version of
>>34522 >>34738.
The thread view's top/bottom targets are #top and #bottom:
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/templates/thread.html#L61> <span class="threadlink"><a href="#bottom" style="padding-left: 10px"> {% trans %}Go to bottom{% endtrans %}</a> ]</span>https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/templates/thread.html#L73> <a id="thread-top" href="#top">[{% trans %}Go to top{% endtrans %}]</a>The corresponding anchors are placed just after the boardlist and just before the end of the body:
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/templates/thread.html#L32> <a name="top"></a>https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/templates/thread.html#L116> <a href="#" id="bottom"></a>The boardlist assembly:
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/inc/display.php#L80> 'top' => '<div class="boardlist">' . $body . '</div>' . $top,This could host a span with two links with titles, some classes and some default styling such as floating in style.css. Inclusion could be controlled by a new optional boolean passed to createBoardlist that defaults to false.
// after trim
if ($topbottomlinks) {
$body .= ' <span class="topbottomlinks"><a href="#top" title="' . _('Go to top') . '">▲</a> <a href="#bottom" title="' . _('Go to bottom') . '">▼</a></span>';
}
// in style.css
.topbottomlinks {
... style to taste ...
}
.topbottomlinks a {
... style to taste ...
}
The createBoardlist invocations that would need the new boolean set to true:
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/inc/functions.php#L1405https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/inc/functions.php#L2331https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/inc/functions.php#L2434https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/templates/themes/catalog/theme.php#L486https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/templates/themes/overboards/theme.php#L216Plenty of views have boardlists, most of them lacking top/bottom anchors:
$ grep -e '{{ *boardlist\.top *}}' -r .
Out of those the ones that matter and need top/bottom anchors are:
templates/index.html
templates/themes/catalog/catalog.html
The unicode arrows used above:
▲=▲
▼=▼
Since the sources can now be referenced, here are the per-file spoiler
>>34738 posts.
To move towards per-file spoilers
>>34570 >>34573 exemptions for spoiler1 through spoiler9 should be added to $config['spam']['valid_inputs'], to allow per-file booleans to pass through the post form. Their number is simply for consistency with the existing file_url9.
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/inc/config.php#L279The names of the file fields of the post form are file, file2, file3 and so on.
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/js/file-selector.js#L73Those names can be used to select corresponding booleans sent by checkboxes, and are available as $_FILES keys when processing uploads. The $key can be temporarily stored in $file, for example as $file['formparametername'].
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/post.php#L793https://www.php.net/manual/en/features.file-upload.post-method.phpThe spoiler test
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/post.php#L1064can then be modified to check per-file booleans:
< if ($config['spoiler_images'] && isset($_POST[str_replace('file', 'spoiler', $file['formparametername'])])) {For per-file spoilers for the non-JS case the way to have multiple file controls can be found in multi-image.js:
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/js/multi-image.js#L21> var new_file = '<br class="file_separator"/><input type="file" name="file'+(images_len+1)+'" id="upload_file'+(images_len+1)+'">';The original spoiler checkbox is in post_form.html:
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/templates/post_form.html#L51> {% if config.spoiler_images %}<div id="spoilercontainer"> <input id="spoiler" name="spoiler" type="checkbox"> <label for="spoiler">{% trans %}Spoiler Image{% endtrans %}</label></div>{% endif %}as is the file input:
https://git.leftypol.org/leftypol/leftypol/src/commit/2d16e747a18ba900ec220a4303249402c19dcd37/templates/post_form.html#L149> <input type="file" name="file" id="upload_file">The div#spoilercontainer can be dropped and the file input replaced with:
{% for counter in 1..config.max_images %}
{% if counter > 1 %}<br class="file_separator"/>{% endif %}
{% set countersuffix = counter == 1 ? '' : counter %}
{% if config.spoiler_images %}<span class="spoilercontainer"><input id="spoiler{{ countersuffix }}" name="spoiler{{ countersuffix }}" type="checkbox"><label for="spoiler{{ countersuffix }}">S{{ counter }}</label></span>{% endif %}
<input type="file" name="file{{ countersuffix }}" id="upload_file{{ countersuffix }}">
{% endfor %}
A sample result is attached. This will enable per-file spoilers for the non-JS case. I'll leave the necessary frontend changes for the JS case to those who regularly browse with remote code execution enabled.
>>34712>YouTube now blocks every Tor exit node. When you browse via tor, embeds now use an invidious hidden service by default.
In an ideal world, the embed would choose a random proxy from a list of good proxies
>>34558 (
https://github.com/iv-org/documentation/blob/master/Invidious-Instances.md ).
My wish is something that helps with twitter links to automatically link to a random nitter instance. I absolutely detest the twitter front end. So much so that I avoid clicking twitter links.
Maybe it could look like this:
www.twitter.com/something/something [nitter]
Where [nitter] is a button that takes you to the same link, but on nitter.
>>34741>>34742Done. Please test and report.
https://git.leftypol.org/leftypol/leftypol/commit/af8b645b2395cf0d3ac0e6202d2fe1793f74e140> Adds bar | to unique IP counterIf you want a vertical bar but place it there, you'll get a dangling bar on the right in the non-JS case. By contrast, if you want a vertical bar but place it on the left in
https://git.leftypol.org/leftypol/leftypol/src/commit/2a506d8dec5b9cb10686c8509ec73f112069bd07/js/thread-stats.js#L25you'll get essentially the same effect but without dangling bars.
Here's a graph of relative PPD for the last 30 days for thread views.
((pagetest, install, getdata, draw) => {
const back = 'rgba( 0, 0, 60, 1)'
const bars = 'rgba( 0, 0, 255, 1)'
const grid = 'rgba(128, 128, 128, 1)'
const count = 30, step = 15
const width = count * step
const height = 100
if (!pagetest ()) { return; }
context = install ({
width: width,
height: height,
})
if (!context.ok) { return; }
context.back = back
context.bars = bars
context.grid = grid
context.count = count
context.step = step
context.width = width
context.height = height
context.data = getdata (count)
draw (context)
}) (
() => (document.getElementById ('uniqueip') != null) && (document.querySelectorAll ('div.post.op').length == 1),
config => {
const holder = document.createElement ("div")
holder.innerHTML = '<div style="text-align: center;"><canvas id="canvasid" width="' + config.width + '" height="' + config.height + '" style="border: 1px solid; z-index: 100; position: relative;">canvas</canvas></div>'
const target = document.getElementById ('thread-interactions')
if (target == null) { return { ok: false }; }
target.parentNode.insertBefore (holder, target)
const canvas = document.getElementById ('canvasid')
if (canvas.getContext) {
const ctx = canvas.getContext ('2d')
return {
ok: true,
holder: holder,
canvas: canvas,
context: ctx,
}
} else {
holder.remove ()
return { ok: false }
}
},
count => {
const all = Array.from (document.querySelectorAll ('p.intro time')).map (e => e.innerText.match (/^\d{4}-\d{2}-\d{2}/)).filter (m => m != null).reduce ((acc, m) => {
const key = m [0]
if (key in acc) {
acc [key] += 1
} else {
acc [key] = 1
}
return acc
}, {})
const now = new Date ()
const key = k => {
const when = new Date (now)
when.setUTCDate (now.getUTCDate () - k)
return when.getUTCFullYear ().toString ().padStart (4, '0') + '-' + (when.getUTCMonth () + 1).toString ().padStart (2, '0') + '-' + when.getUTCDate ().toString ().padStart (2, '0')
}
const ret = Array.from ({length: count}, (x, k) => all [key (k)] ?? 0)
return ret
},
context => {
const ctx = context.context
const data = context.data
const max = data.reduce ((a, b) => Math.max (a, b), 0) || 1
const w = context.width
const h = context.height
const count = context.count
const step = context.step
ctx.fillStyle = context.back
ctx.fillRect (0, 0, w, h)
ctx.strokeStyle = context.grid
for (let k = 0; k < count; k++) {
ctx.beginPath ()
ctx.moveTo (step * k, 0)
ctx.lineTo (step * k, h)
ctx.stroke ()
}
ctx.fillStyle = context.bars
for (let k = 0; k < count; k++) {
const y = data [k] * h / max
ctx.fillRect (w - step - k * step, h - y, step, y)
}
}
)
Just a demo.
Here's a plot for catalog views that shows the relative age of threads, growing to the right, the relative reply counts, growing to the top, and the relative bump freshness, active in red, dormant in blue. The sample images are for /tech/, /leftypol/ and /siberia/.
(tools => ((install, sitespec) => {
const site = sitespec.find (spec => spec.pagetest ())
if (!site) { return; }
const config = site.getconfig ()
if (!config.ok) { return; }
install (config)
if (!config.ok) { return; }
site.getdata (config)
if (!config.ok) {
config.holder.remove ()
return
}
site.draw (config)
}) (
config => {
// > width height insertmode inserttarget
// < holder canvas context
const modes = {
after: (holder, target) => { target.parentNode.insertBefore (holder, target.nextSibling); },
before: (holder, target) => { target.parentNode.insertBefore (holder, target); },
first: (holder, target) => { target.insertBefore (holder, target.firstChild); },
last: (holder, target) => { target.appendChild (holder); },
}
const holder = document.createElement ("div")
holder.innerHTML = '<div style="text-align: center;"><canvas id="canvasid" width="' + config.width + '" height="' + config.height + '" style="border: 1px solid; z-index: 100; position: relative;">canvas</canvas></div>'
modes [config.insertmode] (holder, config.inserttarget)
const canvas = document.getElementById ('canvasid')
if (canvas.getContext) {
config.holder = holder
config.canvas = canvas
config.context = canvas.getContext ('2d')
} else {
holder.remove ()
config.ok = false
}
}, [{
pagetest: () => /^https?:\/\/(leftypol\.org|leftychan\.net)\//.test (document.location.href) && (document.getElementById ('uniqueip') != null) && (document.querySelectorAll ('div.post.op').length == 1),
getconfig: () => {
const target = document.getElementById ('thread-interactions')
if (target == null) { return { ok: false }; }
const count = 60, step = 10
return {
ok: true,
width: count * step,
height: 100,
count: count,
step: step,
back: 'rgba( 0, 0, 60, 1)',
bars: 'rgba( 0, 0, 255, 1)',
grid: 'rgba(128, 128, 128, 1)',
insertmode: 'before',
inserttarget: target,
}
},
getdata: config => {
const dates = Array.from (document.querySelectorAll ('p.intro time')).map (e => e.innerText.match (/^\d{4}-\d{2}-\d{2}/)).filter (m => m != null).map (m => m [0])
tools.getdatadatecount (config, dates)
},
draw: tools.drawrelative
}, {
pagetest: () => /^https?:\/\/(leftypol\.org|leftychan\.net)\//.test (document.location.href) && (document.getElementById ('Grid') != null),
getconfig: () => {
const target = document.getElementById ('Grid')
if (target == null) { return { ok: false }; }
return {
ok: true,
width: 400,
height: 400,
radius: 8,
insertmode: 'after',
inserttarget: target,
}
},
getdata: config => {
const now = Date.now () / 1000
const data = Array.from (document.querySelectorAll ('div.mix[data-bump][data-reply][data-time]')).map (e => ["data-bump", "data-reply", "data-time"].map (s => parseInt (e.getAttribute (s), 10))).map (([b, r, t]) => [now - b, r, now - t])
config.data = data
},
draw: config => {
const ctx = config.context
const w = config.width
const h = config.height
const radius = config.radius
const data = config.data
const [maxb, maxr, maxt] = Array.from ({length: 3}, (x, k) => data.reduce ((a, b) => Math.max (a, b [k]), 0) || 1)
data.reverse ()
for (const [b, r, t] of data) {
const x = t * w / maxt
const y = h - r * h / maxr
const c = Math.floor (b * 255 / maxb)
const f = 'rgba(' + (255 - c) + ', 0, ' + c + ', 1)'
ctx.fillStyle = f
ctx.beginPath ()
ctx.arc (x, y, radius, 0, 2 * Math.PI, true)
ctx.fill ()
}
}
}]
)) ({
drawrelative: config => {
const ctx = config.context
const data = config.data
const max = data.reduce ((a, b) => Math.max (a, b), 0) || 1
const w = config.width
const h = config.height
const count = config.count
const step = config.step
ctx.fillStyle = config.back
ctx.fillRect (0, 0, w, h)
ctx.strokeStyle = config.grid
for (let k = 0; k < count; k++) {
ctx.beginPath ()
ctx.moveTo (step * k, 0)
ctx.lineTo (step * k, h)
ctx.stroke ()
}
ctx.fillStyle = config.bars
for (let k = 0; k < count; k++) {
const y = data [k] * h / max
ctx.fillRect (w - step - k * step, h - y, step, y)
}
},
getdatadatecount: (config, datestrings) => {
// YYYY-MM-DD
const all = datestrings.reduce ((acc, key) => {
if (key in acc) {
acc [key] += 1
} else {
acc [key] = 1
}
return acc
}, {})
const now = new Date ()
const key = k => {
const when = new Date (now)
when.setUTCDate (now.getUTCDate () - k)
return when.getUTCFullYear ().toString ().padStart (4, '0') + '-' + (when.getUTCMonth () + 1).toString ().padStart (2, '0') + '-' + when.getUTCDate ().toString ().padStart (2, '0')
}
const ret = Array.from ({length: config.count}, (x, k) => all [key (k)] ?? 0)
config.data = ret
}
})
Just a demo.
Trimmed Options → User JS
>>34737 for the recent backend fixes.
① catalog links in div.boardlist
>>34604② batch loop/once WebM setting
>>34519③ top/bottom navlinks in the top bar
>>34522④ catalog link above OP
>>34544⑤ quick reply spoiler sync
>>34661Last50 links on catalog pages:
((count, min) => Array.from (document.querySelectorAll ("div#Grid div.thread")).map (t => [t.querySelector ('a[href*="/res/"]'), t.querySelector ("div.replies > strong")]).filter (([a, s]) => parseInt (s.innerText.replace (/^R: (\d+) .+$/, "$1"), 10) >= min).forEach (([a, s]) => { s.innerHTML += ' <a href="' + a.getAttribute ("href").replace (/^(.+)([.]html)$/, "$1+50$2") + '">L' + count + '</a>'; })) (50, 100)
This can be made more resilient by exposing $config['noko50_count'] and $config['noko50_min'] in something like status.php.
>>34757I did something like this in my imageboard:
{% if post.reply_count >= config.noko50_min %}
<a href="{{ post.root }}{{ config.dir.res }}{{ link_for(post, true) }}">[50]</a>
{% endif %}
Still have to figure out a solution for ukko tho.
>>34760> Still have to figure out a solution for ukko tho.My recommendation for the backend, for the general case rather than merely for the ukko family, is to only use the template to check if a last50 href and count have been sent in and if so construct the anchor, but to perform the actual last50 href and count computations in generateRecentPosts where you have more freedom and power. This way you can properly handle per-board $config['noko50_*'] settings due to the openBoard call, which you would be hard pressed to account for in the twig template.
https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/templates/themes/catalog/theme.php#L428https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/templates/post_thread.html#L56https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/inc/display.php#L412
> >[50]<You might want the interface to display the actual config.noko50_count here for that post's board.
>>34761>but to perform the actual last50 href and count computations in generateRecentPosts where you have more freedom and power.The ukko problem I face it right it now, is that the href points it to ukko link itself instead of the board, eg: /ukko/res/6+50.html.
Tried messing around with "link" in inc/display.php but without luck so far.
>This way you can properly handle per-board $config['noko50_*'] settings due to the openBoard callOh, I see it now. What do you have in mind? The only thing I could think of was to make a query to count every reply and check against noko50 but this seems a little too much.
>You might want the interface to display the actual config.noko50_count here for that post's board.Done, forgot about it.
>>34762 >>34763>The ukko problem I face it right it now, is that the href points it to ukko link itself instead of the board, eg: /ukko/res/6+50.html.If you follow
>>34761 you will get the right board and settings due to the openBoard call. Notice how on the overboard index the thread fragments, which include last50 links, are built inside openBoard calls.
https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/templates/themes/overboards/theme.php#L144
>Oh, I see it now. What do you have in mind?Quite simply move the last50 href and count determination out of the catalog template and into generateRecentPosts
>>34761.
https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/templates/themes/catalog/theme.php#L428
>Done, forgot about it.>Got it right by doing this:Putting the retrieval and use of config.noko50_* values
>>34763 >>34760 inside the catalog template is wrong because that template is also used for heterogeneous boards like the overboards and you'd be ignoring the per-board config values of each post's board. This is why the thread fragments of the overboard index are built separately inside their own openBoard calls, before being handed to the index template.
>>34764>Notice how on the overboard index the thread fragments, which include last50 links, are built inside openBoard calls.With this example I was able to see clearly now.
I'm going to try modify my theme with these instructions.
Also, I was looking at the issues of your fork and saw "Post Editing feature", some time ago the lainchan fork received a PR to enable edit mode for users, it works, I was able to test under NPFchan, there is only a problem with spaces that I couldn't solve and didn't want to be bother since the Administrator didn't like it the ideia.
https://github.com/lainchan/lainchan/pull/127/commits/e7213d974952b1d1e8e180b3f1c747c51fc18538
>Embedding can only be done at the top of the page #34The embed in quick reply is managed by the settings.js default, unless you change these line to work without or set to true "show_embed"
https://git.leftypol.org/leftypol/leftypol/src/branch/config/js/quick-reply.js#L243https://git.leftypol.org/leftypol/leftypol/src/branch/config/js/settings.js#L38
>Option for automatically archiving threads #1Its not 100% finished but may give you an idea of an archive system.
https://github.com/Circlepuller/Tinyboard/commit/ff4cd3d041677c46e4eeabc3781aa90d58a1f983https://github.com/Circlepuller/Tinyboard/commit/de6944710b54e38660ab5ba5827a8e07ef0e4fc6 >>34765 >>34766>I was looking at the issues of your forkIt's not my fork and I'm not even one of the techs, mate. I'm just a run-of-the-mill prole.
>The embed in quick reply is managed by the settings.js defaultSee
>>34572
>private function countRepliesMy friend, do you honestly think it likely that the posts would be missing their reply count information when the catalog template already shows reply counts for every thread?
https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/templates/themes/catalog/catalog.html#L78< <strong>R: {{ post.replies }} /https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/templates/themes/catalog/theme.php#L334< (SELECT COUNT(`id`) FROM ``posts_$board`` WHERE `thread` = `thread_id`) AS `replies`
>private function generateRecentPostsThis is correct in spirit, although my opinion is that using a plain
if statement like a sane person instead of an assignment inside a ternary branch would make for more maintainable code.
>{{ post.noko }}Doing it this way instead of
>>34761 is also fine.
>>34767>My friend, do you honestly think it likely that the posts would be missing their reply count information when the catalog template already shows reply counts for every thread?Kek. You're right, just doing:
$post['reply'] >= $config['noko50_min'] was enough.
The href links are fixed now without workaround in the templates, thanks.
>>34769Title: `Unexpected char ' ' at line 1, column 1 (JSON::ParseException)`
Date: `2021-11-25T05:45:19Z`
Route: `/embed/N9o1X_TNXWA?autoplay=1&html5=1`
Version: `2021.11.18-b5a96b17 @ master`
<details><summary>Backtrace</summary><p> ```
Unexpected char ' ' at line 1, column 1 (JSON::ParseException)
from /usr/share/crystal/src/json/lexer.cr:331:7 in 'raise'
from /usr/share/crystal/src/json/lexer.cr:327:5 in 'unexpected_char'
from /usr/share/crystal/src/json/lexer.cr:326:11 in 'unexpected_char'
from /usr/share/crystal/src/slice.cr:213:5 in 'next_token'
from /usr/share/crystal/src/json/parser.cr:13:12 in '_post_json'
from src/invidious/yt_backend/youtube_api.cr:317:12 in 'extract_video_info:video_id'
from src/invidious/videos.cr:972:10 in 'get_video:region'
from src/invidious/routes/embed.cr:122:15 in 'show'
from lib/kemal/src/kemal/route.cr:13:9 in '->'
from /usr/share/crystal/src/primitives.cr:266:3 in 'call'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call_next'
from lib/kemal/src/kemal/filter_handler.cr:21:7 in 'call'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call_next'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call_next'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call_next'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call_next'
from src/invidious/helpers/static_file_handler.cr:167:15 in 'call'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call'
from /usr/share/crystal/src/http/server/handler.cr:28:7 in 'call_next'
from lib/kemal/src/kemal/init_handler.cr:12:7 in 'process'
from /usr/share/crystal/src/http/server.cr:500:5 in '->'
from /usr/share/crystal/src/primitives.cr:266:3 in 'run'
from ???
```
</p></details> >>34769 >>34770The first script of
>>34716 continues to work.
>>34769 >>34770The issue is an indirect invidious bug caused by the crystal-lang upstrem:
https://github.com/iv-org/invidious/issues/2612The invidious workaround with manual decompression is in testing:
https://github.com/iv-org/invidious/pull/2623When it's merged and the instances update or when crystal-lang fixes the HTTP::Client, whichever comes sooner, the issue will go away.
>>34774>Would it be possible to have an option to search for posts based on filename too?Sure, but the non-body field test would have to be loosened from always using equality.
https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/search.php#L124> $like .= '`' . $name . '` = '. $pdo->quote($value); A new filter type can be added here:
https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/search.php#L60> if(!in_array($name, array('id', 'thread', 'subject', 'name'))) { The file names are inside a json_encode in the 'files' field of posts.
https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/templates/posts.sql#L13> `files` text DEFAULT NULL, https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/inc/functions.php#L1075> $query->bindValue(':files', json_encode($post['files'])); The 'files' structure is an array of objects with a 'filename' field holding the upload file name.
https://git.leftypol.org/leftypol/leftypol/src/commit/199f9f5fd077e3beb9a7091295e390ac75345de1/post.php#L797> $file['filename'] = urldecode($file['name']); So as a trial version a LIKE test can be applied to a new files:value filter in search.php. After that with a little more effort the test can be targeted at the 'filename' field with a json path query like:
'$[*] ? (@.filename like_regex ".*valuegoeshere.*" flag "i").size()'
but this will depend on the quality of the SQL/JSON support available in the exact database type and version in use.
https://www.postgresql.org/docs/12/functions-json.html >>34777Luckily I have done this before for 8chan, I had to fiddle with it a bit but now it seems to work. Add this to your User JS and it will automatically rename the files just to their index like with this post:
function getFiles(t) {
return jQuery(t).children('.tmb-container').map(function (i, e) {
return $(e).data('file-ref');
});
}
function changeName(i, file) {
var name = i + '.' + file.name.split('.').pop();
var newFile = new File([file], name, { type: file.type });
return newFile;
}
function renameFiles(files) {
return files.map(changeName);
}
function removeFiles(t) {
jQuery('.dropzone .remove-btn').each(function (i, e) {
$(e).trigger('click');
});
}
function addFiles(t, files) {
transfer = new DataTransfer();
for (i = 0; i < files.length; i++) {
transfer.items.add(files[i]);
}
jQuery(t).parents('.dropzone').trigger(
$.Event('drop', {
originalEvent: new DragEvent(
'drop',
{ dataTransfer : transfer})}));
}
function stripFilenames(t) {
var files = getFiles(t);
removeFiles(t);
addFiles(t, renameFiles(files));
}
function observer(e) {
// You have to remove it first to avoid recursion.
jQuery('.file-thumbs').unbind("DOMSubtreeModified", observer);
// Always do it on the main form
stripFilenames(jQuery('.file-thumbs').first()[0]);
jQuery('.file-thumbs').bind("DOMSubtreeModified", observer);
}
// Initialize
jQuery('.file-thumbs').bind("DOMSubtreeModified", observer);
For a backend version of Anon's
>>34778 code a checkbox can be added to the post form wherever convenient
https://git.leftypol.org/leftypol/leftypol/src/commit/0e98c35dc59f42db891ce680f0995ec40cbb782c/templates/post_form.html#L51then the $file['filename'] can be suppressed between $file['extension'] and $config['filename_func']
https://git.leftypol.org/leftypol/leftypol/src/commit/0e98c35dc59f42db891ce680f0995ec40cbb782c/post.php#L797if ($config['suppress_filenames'] && isset($_POST['suppressfilenames'])) $file['filename'] = "$i." . $file['extension'];
Checkbox sync is in
>>34655 and memory leak cleanup in
>>34657 and
>>34658.
>>34781>the replied to postYou might reply to several posts, with only one of them having been deleted. You might mean some of the post references in your reply as part of the substance of your reply, rather than as posts being replied to.
What are your thoughts on auto update applying some visual marking to those posts that are still present in your view of the thread but would go away if you were to press F5?
>>34783Good idea, NPFchan faced a lot of abuse so it has some good moderation stuff that we can sample. Hash filters currently can't be done through the moderation interface.
There were plans for a vichan-NPFchan uplift (getting all the stuff lainchan never pulled), but unfortunately most of the development manpower is on hold for a while and (as one may have noticed) available time is mostly focused on maintenance and easy wins rather than new features and infrastructure improvement. People getting involved in the git repo would help this massively.
I haven't implemented phashes yet but it's always an option and possible with existing tools. I feel that most people able to intentionally evade a hash ban should be motivated and able to evade a phash, so it might be a wasted and computationally expensive effort.
Concerning >>>/meta/15307
>How the hell do you turn it off?the current snow test is
https://git.leftypol.org/leftypol/leftypol/src/commit/b3db9c52b70f0f7103b96b61891f752791e996ab/js/winter-snow.js#L3> var snow = localStorage['snow'] ? false : true; while the current option uncheck handler is
https://git.leftypol.org/leftypol/leftypol/src/commit/b3db9c52b70f0f7103b96b61891f752791e996ab/js/winter-snow.js#L17> localStorage.snow = false; which causes snow to remain true regardless of the checkbox state.
To disable the effect without waiting for a backend fix use the dev tools console to set localStorage.snow to a value that evaluates to true in a conditional, such as
localStorage.snow = "nothanks";
then check in dev tools storage that your browser stored the new value, then reload the page.
>>34789>The text missing from the aboveThe text is present:
<div class="post reply" id="reply_12587" data-board="tech"><p class="intro"><a id="12587" class="post_anchor"></a><input type="checkbox" class="delete" name="delete_12587" id="delete_12587"><label for="delete_12587"><span class="name">Anonymous</span> <time datetime="2021-12-20T14:45:22Z">2021-12-20 (Mon) 14:45:22</time></label> <a class="post_no" id="post_no_12587" onclick="highlightReply(12587)" href="/tech/res/6724.html#12587">No.</a><a class="post_no" onclick="citeReply(12587)" href="/tech/res/6724.html#q12587">12587</a></p> <div class="video-container" data-video="NLpPyuzxSf4"><a href="https://youtu.be/NLpPyuzxSf4" target="_blank" class="file"><img style="width:255px;height:190px;" src="/vi/NLpPyuzxSf4/0.jpg" class="post-image"></a></div> <div class="body"><pre class="code lang-">text</pre><br><pre class="code lang-">textblabla</pre><br><pre class="code lang-">textan bloo blee blouf</pre></div></div>
You can apply this CSS workaround:
pre { clear: both; }
>>34788For me (desktop), this text shows a scroll bar.
I assume the issue is that it's invisible on your device so it looks like it's just cut off.
>>34792Very strange. It is indeed invisible on my end, still.
I'm on desktop using Tor Browser, latest version, which is based on Firefox ESR, with javascript disabled (highest security setting).
Is [code] a javascript function? It doesn't seem like it. Another strange thing is that sometimes it works and I can see the [code] text like regular (leading me to speculate if it's to do with the number of lines). I did a similar test post on /siberia/ with typed in another way with an embed and it showed up normal, which made me think you had just disabled [code] on /leftypol/ as a board specifically. This was all without JS too (I always post without JS).
>>34798APNG upload works in principle.
>>>/meta/15840 The error is "benign" but for separate reasons shell_exec_error considers any stderr output an error.
>>>/leftypol_archive/1787 The workaround is the same as for the iCCP family of errors.
>>34564 The error means that your image has too many sPLT, tEXt, zTXt, iTXt or unknown chunks for libpng's taste.
https://github.com/glennrp/libpng/blob/a37d4836519517bdce6cb9d956092321eca3e73b/pngrutil.c#L3070png_chunk_benign_error(png_ptr, "no space in chunk cache");
https://github.com/glennrp/libpng/blob/a37d4836519517bdce6cb9d956092321eca3e73b/pngstruct.h#L440 /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown
* chunks that can be stored (0 means unlimited).
*/
png_uint_32 user_chunk_cache_max;
In practice this most likely means that your animation has more frames than leftypol->gm->libpng is currently willing to quietly accept. I assume that your image was good faith but it's also possible that you were attempting a resource consumption attack. I cannot check this as you have not provided a link to an external upload of your image.
>>34563 For future reference, uploading your file to
http://0x0.st/ or similar and including a link will improve your bug reports.
>>34800Your image is legitimate
>>>/meta/15862 but it has 6228 frames and 12462 chunks.
< In practice this most likely means that your animation has more frames than leftypol->gm->libpng is currently willing to quietly accept. >>34799You have the option of uploading it spoilered, which bypasses thumbnailing.
>>34684 Since the image is a type 3 8-bit PLTE with single-index transparency (tRNS=0x00) which was converted from a gif using gif2apng.sf.net, you also have the option of uploading the source gif, or losslessly reobtaining it with apng2gif.
>>>/meta/15864 The techs can try adding [0] to the first %s of $config['convert_args'] to explicitly request only the first source frame, which may or may not fix the problem.
https://git.leftypol.org/leftypol/leftypol/src/commit/c5814178aee666b34902665a0bd0b4667758a875/inc/config.php#L773 // Command-line options passed to ImageMagick when using `convert` for thumbnailing. Don't touch the
// placement of "%s" and "%d".
$config['convert_args'] = '-size %dx%d %s -thumbnail %dx%d -auto-orient +profile "*" %s';
Another option is the general workaround shared with the iCCP family of errors.
>>34799 >>34564 >>>/leftypol_archive/1787 Viewing the post history of an IP
>>34804 for site administration didn't originate with lefty, lain or vichan, in this family it goes all the way back to Tinyboard.
https://github.com/savetheinternet/Tinyboard/commit/78f3ea783394dba14b51b27f7f2db3974ce8b8b3#diff-e7c25d7d73eaa99b1564b025926e24d835d4322fdb65f4b9473b357f0ef64f44Reusing the same functionality to allow users to access a read-only view of their own post history might be reasonable on a site that doesn't allow VPNs or Tor, but on a site that does allow them it's probably not a good idea.
https://git.leftypol.org/leftypol/leftypol/src/commit/c5814178aee666b34902665a0bd0b4667758a875/inc/mod/pages.php#L892https://git.leftypol.org/leftypol/leftypol/src/commit/c5814178aee666b34902665a0bd0b4667758a875/templates/mod/view_ip.html#L204Here's some harmless fun with localStorage.own_posts:
((sortkeys, link, divide, cites, install, slice, groups) => {
const own = JSON.parse (localStorage.own_posts || '{}')
const boards = sortkeys (Object.keys (own))
const count = boards.reduce ((acc, item) => acc + own [item].length, 0)
const html = ['own posts: ' + count + ' boards: ' + boards.length]
boards.forEach (b => {
const ownb = own [b].reverse ()
const have = ownb.length
const [div, mod, left] = divide (have, slice, groups)
html.push ('board: ' + link ('/' + b + '/index.html', '/' + b + '/') + ' ' + link ('/' + b + '/catalog.html', '©') + ' count: ' + have + ' = ' + div + ' * ' + slice + ' + ' + mod + ' + ' + left)
for (let k = 0; k < div; k++) {
html.push (cites (b, ownb, slice, k, slice))
}
if (mod) {
html.push (cites (b, ownb, slice, div, mod))
}
})
install (html)
}) (
arr => arr.map (s => [s, s.toUpperCase ()]).sort ((a, b) => a [1] < b [1] ? -1 : a [1] > b [1] ? 1 : 0).map (p => p [0]),
(href, text) => '<a href="' + href + '">' + text + '</a>',
(have, slice, groups) => {
const take = Math.min (have, slice * groups)
const mod = take % slice
return [(take - mod) / slice, mod, have - take]
},
(board, arr, slice, skip, now) => arr.slice (skip * slice, skip * slice + now).map (s => '>>>/' + board + '/' + s).join (' '),
html => {
const old = document.getElementById ("ownposts-report")
if (old) { old.remove (); }
const node = document.createElement ("div")
node.setAttribute ("id", "ownposts-report")
node.setAttribute ("style", "border: thin solid;")
node.innerHTML = html.map (s => '<p>' + s + '</p>').join ("")
const foot = document.querySelector ('footer')
if (foot) {
foot.parentNode.insertBefore (node, foot)
} else {
document.body.appendChild (node)
}
},
45, 2
)
>>34806A page history for a user it's quite simple to make in php, it's just a gimp mod_view_ip and template as well.
I got this ideia from wizchan and works quite good. But that leaves you with one problem, vpn, since tor is easily blocked. But again, in my imageboard vpn and tor isn't allowed.
https://wizchan.org/history.php >>34807If you have some influence on the wizchan admin tell him to fix the double escaping in his code tags:
https://wizchan.org/meta/res/60390.html#60449 08/24/21.
>>34796Thank you writing for the code. It has been tested and is now added to the site. (I made a minor change to put them in a frameset labeled (You)s ).
https://git.leftypol.org/leftypol/leftypol/issues/66Do you have any issue with me trying to upstream this to vichan and lainchan?
>>34811>Do you have any issue with me trying to upstream this to vichan and lainchan?None at all. Use it freely and in good health. Same for the other fixes I post here.
Separately, I'd like to point out that you need to treat show-own-posts.js.txt
>>34796 as UTF-8 to get Marcin's last name right.
The database has been changed to a different engine (MyISAM -> InnoDB). Reverted lmao, vichan isn't concurrency-safe so a couple of people got deadlocks so we noped out. If you notice anything weird/slow/broken, let me know.
We've also upgraded the caching, which will hopefully provide major speed improvements.
I think one of the biggest issues we should focus on for now (high impact, possible easy win) is the large delay between a post appearing on the website and the poster being told their post is successful.
>>34812Fixed, thanks.
>>34813https://git.leftypol.org/leftypol/leftypol/commit/e906ac74514a415c73593edfad5b540df9d67ac5?style=split&whitespace=You are ignoring the state of $noko, which if false, such as by manual nonoko, causes:
https://git.leftypol.org/leftypol/leftypol/src/commit/e906ac74514a415c73593edfad5b540df9d67ac5/post.php#L1429$redirect = $root . $board['dir'] . $config['file_index'];
so you might want the same buildIndex before fastcgi_finish_request order when $noko is false as for "if ($post['op'])".
>>34820My guess is preventing overlap when uploading multiple images.
>>34821Nice.
>>34818Great to hear! Now that things have settled down and I have a bit of extra time, I'm focusing on a new effort to rebase the site software from vichan(2015)->lainchan(2017)->leftypol_lainchan onto current vichan, with functional patches from lainchan and NPFchan cherry-picked (excluding broken or unneeded patches like lainchan's broken overboard posting and Slack notification support, NPF's cookie tools and forced flags).
If there's any other vichan-based IBs with features you think we should cherry-pick, let me know.
What this means is a few more features, a far less broken base, and no loss of features.
The functional part (styling ignored) is about a third of the way done but it should always remain stable and working.
https://git.leftypol.org/leftypol/leftypol_vichan/(The reasons I'm doing this rebase as opposed to moving to another imageboard software entirely is the relative ease, the guarantee of feature parity, and the assurance of migrating without data loss. That said, it could easily happen in the long-term if one is considered objectively better at this scale)
>>34822To enable overboard post, I this way (using ukko2 from lainchan):
$isukko = true; // only here for exclude somethings because the condition 'no_post_form' will be always false
return Element('index.html', array(
'config' => $config,
'board' => $board,
'no_post_form' => false,
'isukko' => $isukko,
'body' => $body,
'mod' => $mod,
'boardlist' => createBoardlist($mod),
'boards' => $boardsforukko2,
'antibot' => $antibot
));
then, in the post_form.html:
<table>
{% if isukko %}
<tr>
<th>
{% trans %}Board{% endtrans %}
</th>
<td>
<select id="boardsUkko" name="board">
<option value=""></option>
{% for board in boards %}
<option value="{{ board.uri }}">{{ board.uri }} - {{ board.title }}</option>
{% endfor %}
</select>
{{ antibot.html() }}
</td>
</tr>
{% endif %}
at this stage is working and need minor modifications in templates because of the widely used 'no_post_form' condition.
>>34823I'm aware of that, but unless I am mistaken it's incompatible with the antispam function because it requires the antispam to be generated for that page, for the correct board that the post ends up on, which is impossible to predict.
I tried using lainchan.org's /mega/ ukko and it kept telling me my post looked automated.
>>34830>Are the hidden threads being duplicated (like, hidden on the first page, then when loading more it's showing up a second time, unhidden) No
>or is it just forgetting to hide ones that are loading up after the first page?Yes exactly
>>34827I've make a quick fix.
https://git.leftypol.org/leftypol/leftypol/commit/0950d4d09d18da30fd0a1d02085e5b8e2782fa49If anyone wants to look in further, it seems that filter() in post-filter.js doesn't get an up-to-date locallist, so anything after the initial page isn't searched. That trigger above prompts locallist to be regenerated.
>>34833 (me)
I've also noticed another pre-existing (issue?) where hidden threads on the overboard won't have any posts when unhidden. I'm considering that a wontfix because I have more important things to do than making sure there's posts in threads we explicitly choose not to see.
>>34826Nice goggles.
>>34822It's 75% complete, excluding theming.
The last quarter will be easier since it's leftypol code and most will just be config changes and unneeded patches. After that, it's just fixing 30 small bugs I noticed along the way, bug checking and porting the CSS themes.
>NPFchan features complete>lainchan (vanilla) features complete(excluding rejected features)
>>34833I think this was only a partial fix (for "hide threads from this board", which now works on scroll), but
individual hidden threads still are subject to the original bug in question, namely that they generate on overboard scroll unhidden when they're not supposed to be.
>>34849Fair enough. Fortunately this transition
>>34822 should bring them all in, when it eventually happens.
Do you use any of them?
>>34847>Palemoonuse IceCat
>>34850no, just thought it'd be nice to have more themes
Update of
>>34686 for the new file_multiple[].
((count, spoilers) => {
const dest = document.querySelector ("tr#upload > td.upload-area")
if (dest == null) { return; }
let have = dest.querySelectorAll ('input[type="file"]').length
if (have >= count) { return; }
const sepa = '<br class="file_separator"/>'
const file = n => (suf => '<input type="file" name="file' + suf + '" id="upload_file' + suf + '">') (n == 1 ? "" : ("" + n))
const spoi = n => (suf => '<span class="spoilercontainer"><input id="spoiler' + suf + '" name="spoiler' + suf + '" type="checkbox"><label for="spoiler' + suf + '">S' + n + '</label></span>') (n == 1 ? "" : ("" + n))
const add = []
const cleanmulti = dest => {
const multi = dest.querySelector ('input[type="file"][multiple]')
if (multi == null) { return false; }
multi.remove ()
return true
}
if (spoilers) {
(e => { e.nextSibling.remove (); e.remove (); }) (document.querySelector ("input#spoiler"))
for (let k = 1; k <= count; k++) {
add.push (spoi (k) + file (k))
}
dest.innerHTML = add.join (sepa)
} else {
if (cleanmulti (dest)) { have--; }
for (let k = have + 1; k <= count; k++) {
add.push (sepa)
add.push (file (k))
}
dest.innerHTML += add.join ("")
}
}) (5, false)
This allows files from different directories and shows file order and names for potential per-file spoilers.
>>34570 >>34744test:
>>>/meta/16815>>34853Not invidious, but Piped seems pretty good. I think this is kavin.rocks 's instance. There seem to be multiple video feeds that need to be allowed in NoScript but they are all v3 tor proxies
piped2bbch4xslbl2ckr6k62q56kon56ffowxaqzy42ai22a4sash3ad.onion/
>>34822Update: There were delays due to other priorities and burnout, but the functionality is essentially complete and now it just needs some styling changes.
After that I might open an instance to public testing, but I don't think the ultimate switch-over will happen for a while, at least until site activity stabilizes and thread migration is tested.
A member of staff can perform the following test with impunity. Pick a random post, inspect its checkbox, edit the number in id and name "delete_NNN" to some higher number that has not yet been reached by post ids on that board, and report that post with a test message. This simulates reporting a post that has been deleted immediately before submitting the report, but without having to actually delete anything. This should result in a false fetch
https://git.leftypol.org/leftypol/leftypol/src/commit/985d6f4dd66bfead158c2be016024347073f8864/post.php#L340https://www.php.net/manual/en/pdostatement.fetch.php#refsect1-pdostatement.fetch-returnvalueswhich causes the link_for in the subsequent event call argument list to attempt false['id'], resulting in >>>/meta/18331. In that case something similar to
// check if post was deleted before the report arrived
if ($thread === false) continue;
could be added just after the fetch.
>>34868If your statement is true within the context of a correctly performed
>>34865 test, then simply provide us with a var_dump($thread)
for the non-existent post id, so that we can see what $query->fetch returned while obeying the restrictions;
> WHERE `id` = :id> $query->bindValue(':id', $id, PDO::PARAM_INT); Can the /tech/ team try and implement optional spoilers, at least for /siberia/? It's a real pain in the ass because a bunch of OPs are arbitrarily spoilered by the mods for being porn…. on a /b/ board. I get that overboard has all boards on it but making it optional ought to at least give non-prudes less of a headache searching catalog.
An example of such a script
https://pastebin.com/R5G1JvFy (
https://archive.ph/WOccP) by the late Bell.
>>34881This has been brought up previously
>>34781 but there wasn't enough interest from the bug reporter to answer a follow-up
>>34782 question.
>>34883I guess
>>34782 sounds like a good solution too. But I still think not counting deleted posts as posts in the anti-spam mechanism is still a good addition too.
>>34881>>34882lmao
fuck, why didn't I think of that
Here's a patch to implement the first option from
>>34881 and
>>34782 to make auto-reload.js mark deleted posts. Theme maintainers can customize the marking using the
div.post.reply.auto-reload-removed selector. JS users can do the same in User CSS. Deleted posts are not considered important enough to reset the update timer, but if this is desired the removed_posts counter is available for this purpose. To test, inspect and edit a reply id to a non-existent one. Keep in mind that this is narrowly aimed at marking deleted posts, and auto-reload.js has other bugs
>>>/leftypol_archive/1759 with which this patch does not concern itself.
>>34885Is this not being implemented by default?
Also I tried copy-pasting the contents of the .txt into first User CSS and User JS and neither seemed to have any result on thread. Or does it require browser restart / clearing cookies and cache?
>>34886That is a patch for files served to you by the backend. So first we wait patiently until the techs apply the patch on the backend. After that, if you don't like the default visual marking for deleted posts, you put
div.post.reply.auto-reload-removed {
border: ...;
...
}
into User CSS and replace the ellipses with your own rules.
https://developer.mozilla.org/en-US/docs/Web/CSS/border#syntax you made a mistake in
https://leftypol.org/robots.txtremove the last "Allow: /" line because A) it overrides all your preceding disallow rules, and B) is redundant/unnecessary, since anything not disallowed is already allowed by default
read
https://www.robotstxt.org/robotstxt.htmlyour rotating banner system (/banners.php) is inefficient because it's impossible for users to cache these images in their browsers. everyone is constantly re-downloading previously-seen banners.
you can see if a file is already cached or is downloaded by refreshing a page (e.g.
https://leftypol.org/banners.php ) by checking http responses in firefox in the Network tab in Firefox Developer Tools (ctrl+shift+i) and seeing if it says "cached" under the "Transferred" column for the file
you can instead make it so twig serves the direct path to a random image from your banners folder instead of sending it to your inlined banners.php image file stream so that browsers can actually cache these images. this can speed up frequent visitors' page loads and reduce a bit of bandwidth per frequent visitor.
1. go to /inc/lib/Twig/Extensions/Extension/Tinyboard.php
2. add this line in that list of Twig extension functions:
new Twig_SimpleFunction('random_banner_url', 'twig_random_banner_url'),
(don't forget to put a comma at the end of that previous item or you'll get php error / blank page)
3. at the end of the file add this function definition:
function twig_random_banner_url() {
$path = dirname(__DIR__, 5) . '/banners/';
$isDirEmpty = true;
if (!file_exists($path)) {
return '/static/blank.gif';
}
$handle = opendir($path);
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$isDirEmpty = false;
break;
}
}
closedir($handle);
if (!$isDirEmpty) {
$files = scandir($path);
$files = array_diff($files, array('.', '..'));
return '/banners/' . $files[array_rand($files)];
}
return '/static/blank.gif';
}
4. go to /templates/index.html, and change
<img class="board_image" src="{{ config.url_banner }}"
to
<img class="board_image" src="{{ random_banner_url() }}"
5. do the exact same thing in #4 for /templates/thread.html, /templates/generic_page.html, and /templates/themes/index/index.html
6. rebuild all boards/threads in mod.php and test new banner system
obviously you need to test this in a dev environment first, i did this on vichan but it looks like it's identical on lainchan. the only minor drawback is that the banner changes on each thread/index based on user actions (a new reply, thread, delete, mod action, etc.) instead of refreshing the browser due to twig's caching system, but because leftypol has high enough traffic this will not be a problem, it will change frequently enough and it's worth it for the improved page load times and minor bandwidth savings of frequent visitors not having to constantly re-download previously-seen banner images. also in theory this may reduce cpu usage a bit because the banners.php opcode is no longer executed each time any user refreshes his browser or goes to a different page, whereas this new twig function would execute only on user actions which are obviously far less frequent than refreshes / page loads. the other minor issue is it will ignore whatever you set $config['url_banner'] in instance-config.php, it will only pull images from a "/banners" folder if it exists, can't think of a way right now to have this twig function work together with that, you can put a TODO comment on this function to change it later, i don't think it's a real priority.
>>34889> $isDirEmptyIf the directory is not empty, you call scandir on it. If the directory is empty, scandir would do no more work than your while loop. What is the purpose of prescanning the directory instead of testing whether the result of array_diff is empty?
> the other minor issue is it will ignore whatever you set $config['url_banner'] in instance-config.php, it will only pull images from a "/banners" folder if it exists, can't think of a way right now to have this twig function work together with thatThe twig_* functions can take parameters from the calling templates. The templates can take parameters in their Element(template_source, array) invocations. The invokers of Element(template_source, array) will pass in config values for whichever openBoard call is in effect at the time.
>>34761 >>34890>>34889function in step 3 is now:
function twig_random_banner_url($path) {
if (substr($path, -1) !== "/") {
$path = $path . '/';
}
$path_twig_relative = dirname(__DIR__, 5) . $path;
if (!file_exists($path_twig_relative)) {
return '/static/blank.gif';
}
$files = scandir($path_twig_relative);
$files = array_diff($files, array('.', '..'));
if ($files) {
return $path . $files[array_rand($files)];
}
return '/static/blank.gif';
}
in step 4 & 5 it is now:
<img class="board_image" src="{{ random_banner_url(config.url_banner) }}"
and now there's a new step between 5 and 6:
5.5. in instance-config.php set $config['url_banner'] to "/banners/" or "/banners" (either will work)
A note about Anon's
>>34891 updated code. While it will pick up the correct
config.url_banner in single-board template calls, on the overboard index pages, which feature banners, it will pick up the
config.url_banner of whichever board had the last thread in the
$top_threads, because that board had the last
openBoard call in
buildOne.
https://git.leftypol.org/leftypol/leftypol/src/commit/631a5b5fc705252697734c74a69e9edffbd55bec/templates/themes/overboards/theme.php#L172If this random pick by the last
$top_threads item is not desired,
config.url_banner can be remembered before the first
buildOne call and sent into the index template separately in the
Element invocation.
>>34890https://git.leftypol.org/leftypol/leftypol/src/commit/631a5b5fc705252697734c74a69e9edffbd55bec/templates/themes/overboards/theme.php#L204This way the overboard index pages would use the
config.url_banner setting from the global
instance-config.php. On the other hand, the random pick of the banner folder by the last item in
$top_threads might be considered a feature.
this commit for checking report length is incorrect it will give an error saying strlen is expecting a string not an array if someone bypasses the input maxlength set in html
https://github.com/towards-a-new-leftypol/leftypol_lainchan/commit/bb0b7007fd5e27bd29c76235cf7a1b8148995f99if (strlen($report)
should be
if (strlen($_POST['reason'])
Flag list for >>>/meta/20864. This version uses the git repo static/flags folder
https://git.leftypol.org/leftypol/leftypol/src/commit/631a5b5fc705252697734c74a69e9edffbd55bec/static/flags which is out of sync with the live site and the hidden
>>34728 >>34729 >>34735 instance-config.php, so it will not match the live post form. Adjust the 80px height in the img tag's style to taste. Rerun when a new flag shows up in the git repo.
$ cd leftypol/static/flags
$ { echo '<div style="text-align: justify">'; for f in $(ls | grep -e '[.]png$' | grep -ve '^flags[.]png$'); do echo '<span style="display: inline-block; border: 1px dashed; text-align: center">'; echo '<img style="height: 80px; image-rendering: crisp-edges" src="'$f'">'; echo '<br>'; echo '<span style="font-size: 20px">'${f%.png}'</span>'; echo '</span>'; done; echo '</div>'; } > test.html
Flag list for >>>/meta/20864. This version uses the live post form. It has to use the live static/flags folder because the git repo is out of sync
>>34897. Mobile app users get their flags through
https://leftypol.org/status.php which automatically syncs
https://git.leftypol.org/leftypol/leftypol/src/commit/631a5b5fc705252697734c74a69e9edffbd55bec/status.php#L55 with the live post form, so it will match this version. Adjust the 80px height in the img tag's style to taste. Rerun when a new flag shows up in the live post form.
$ { echo '<div style="text-align: justify">'; wget -q -O - 'https://leftypol.org/meta/res/20864.html' | grep -E -oe '<option value="[^"]+">[^<]+</option>' | sed -r -e 's#^<option value="([^"]+)">([^<]+)</option>#<span style="display: inline-block; border: 1px dashed; text-align: center"><img style="height: 80px; image-rendering: crisp-edges" src="https://leftypol.org/static/flags/\1.png"><br><span style="font-size: 20px">\2</span><br><span style="font-size: 20px">\1</span></span>#'; echo '</div>'; } > test.html
https://leftypol.org/search.php?search=Grace&board=siberia1. Why doesn't this find anything at all?
2. Why do I have to select /siberia/ again in the search form?
About
>>34901> 2. Why do I have to select /siberia/ again in the search form?The board parameter sent from search.php to search_form.html is called 'board':
https://git.leftypol.org/leftypol/leftypol/src/commit/631a5b5fc705252697734c74a69e9edffbd55bec/search.php#L18> $body = Element('search_form.html', Array('boards' => $boards, 'board' => isset($_GET['board']) ? $_GET['board'] : false, 'search' => isset($_GET['search']) ? str_replace('"', '"', utf8tohtml($_GET['search'])) : false));But search_form.html tests for equality with 'b':
https://git.leftypol.org/leftypol/leftypol/src/commit/631a5b5fc705252697734c74a69e9edffbd55bec/templates/search_form.html#L10{% for b2 in boards %}
{% if b2 == b %}
<option value="{{ b2 }}" selected>/{{ b2 }}/</option>
{% else %}
<option value="{{ b2 }}">/{{ b2 }}/</option>
{% endif %}
{% endfor %}
If either the board parameter sent from search.php to search_form.html is renamed to 'b', or the equality test is switched to 'board', the search form should pick up the correct board as its initial selection.
>>34906Maybe the global $board interferes with the twig template, although I can't see why it would, and we should just switch both the loop variable equality test target and the Element parameter to
searchboard.
> BenjaminThis is the same Southall guy who adds parens around &&, which took precedence anyway, instead of
>>>/leftypol_archive/1691 around the || chain:
https://git.leftypol.org/leftypol/leftypol/commit/1792bf48eec755ee9a07aa5bef5fbf1e27d406c4 >>34907It's Appleman1234 of Lainchan fame.
I would just revert b89fe3046bfbc0d7db8e7e8773e92c0536417450.
> the Rules and FAQ pages look atrocious / almost unreadable >>34912> Dark Bunker Red >>34914The relevant property of dark_bunker_red.css is that it lacks ban class styling.
>>34913https://git.leftypol.org/leftypol/leftypol/src/commit/858a501b1f652831feafd9b51c6f06c3b92e30a0/stylesheets/dark_bunker_red.cssThe default dark_red.css has three div.ban sections.
https://git.leftypol.org/leftypol/leftypol/src/commit/858a501b1f652831feafd9b51c6f06c3b92e30a0/stylesheets/dark_red.css#L157To fix add
div.ban { … } and
div.ban h2 { … } sections to
Dev Tools → Style Editor → New Stylesheet while on the Dark Bunker Red theme, adjust the foreground and background colors as well as any other desired properties until the faq and rules pages are no longer "atrocious / almost unreadable", then once satisfied post the changes for inclusion into dark_bunker_red.css.
https://developer.mozilla.org/en-US/docs/Web/CSS/color#syntax User JS snippet for twitter → nitter conversion
>>>/meta/22665Array.from (document.querySelectorAll ('a[href^="https://twitter.com/"]')).forEach (e => { e.outerHTML = e.outerHTML + ' <a target="_blank" href="' + e.getAttribute ("href").replace (/^https:\/\/twitter\.com\//, "https://nitter.net/") + '">[nitter]</a>'; })
test link:
>>>/meta/22666>>34927(Sorry for late reply, I've been away from /tech/)
Looks like it's a local thing if you're not seeing the page list at the bottom of the board index.
>>34926Has anyone asked you if you want to be part of the dev team yet? We've been pretty slow for a couple of months due to other obligations.
>>34934 NTA but probably.
Also IMO .webp is shit
Hey could we add .jxl support? It's supported by default on librewolf, and I think the only reason chrome is holding off on it is because it competes with .webp, but chrome still supports it via about:flags.
We could make some absurdly storage efficient memes with it, like sub-kilobyte file sizes, and even double digit byte sizes.
https://jpegxl.info/art/>>34933>>34937I'm not sure it's a good idea to at the moment.
The reason we only added webp for thumbnails is because all the common-enough browsers and forks worked fine.
Only issue was apparently one guy whose browser version did support it but his setup was broken. We didn't add support for uploading them, because they're still considered an annoying non-default format on many operating systems. Well, unless that's changed in the past year. I haven't kept up with formats/compatibility for a while so I'm open to counterpoints.
Until .jxl and av1 formats get more mainstream support, I don't think it's wise to allow either of them to be uploaded. Especially if Chrome doesn't support them (out of the box). The average griller user shouldn't be expected to dig into their most-common-in-the-world browser just to make images show up.
>>34936I don't see why not. I'll try and add this when I get home.
Heads up for codemonkey and admin vols
https://youtu.be/eUPJ9zFV5IEMatrix 2.0 go vroom
The RSS feed for the overboard seems to be broken, all the links point to /leftypol/, even if they're on other boards like /siberia/. So 404 since there's no threads on /leftypol/ with that number.
https://leftypol.org/overboard/index.rssWorks fine for board specific feeds tho, just the overboards are having this issue.
>>34956JESUS FUCKING CHRIST. WHAT THE FUCK IS WRONG WITH YOU PEOPLE??? WHEN WILL IT BE ENOUGH FUCKING SURVEILLANCE, AND SECRET LISTS, AND POST HISTORIES. FUCKING BROWSER FINGERPRINTING???
an IP + browser fingerprint gets you someone's identity. I hope anons here are switching user agents and/or using VPN/TOR.
>>34960leftypol.org does use Cloudflare, check the HTTP headers returned
>server: cloudflare>cf-cache-status: …>report-to: …also see
https://developers.cloudflare.com/ssl/reference/certificate-authorities/#universal-ssl and
https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/>By default, Cloudflare issues — and renews — free, unshared, publicly trusted SSL certificates to all domains added to and activated on Cloudflare.>Universal certificates issued by Let’s Encrypt or Google Trust Services have a 90 day validity period.this means that Cloudflare is MITM-ing everything you do here, you should use the Onion Service which ofc doesn't use Cloudflare
Not sure if this is a mod question or a /tech/ question so I'm reposting it in both
Say mods, why are so many of the image files and video files in
>>>/leftypol_archive/ and dead or gone? Like they're not deleted by mods, they just no longer exist. There's so many .webms that are non functional it's not even funny and the number of threads missing all of the images in them is annoying as hell. It's Desuarchive's filedeaths all over again.
Just as an example
https://leftypol.org/leftypol_archive/res/489758.html has all images dead. Why and how? Or the /edu/ checkpoint thread
https://leftypol.org/leftypol_archive/res/580500.htmlSo is there a reason why I can't embed certian youtube links? like for example I cant embed this
https://youtu.be/nbafT2w0cCQ?si=U42ECuZj_eus4Z82But I can embed this one
https://www.youtube.com/watch?v=nbafT2w0cCQBut they both go and go to the same video, this first one I coped off of YouTube's share feature and the second one I just directly copied from the browser.
>>34982Glad to hear. I hope you post more on tech then. Spread the word about leftypol.
>>34989Booru is its own website. You can reach the staff by their forum. They're slow to respond though, like a few weeks sometimes.
>>34990Maybe a hiccup, saw this post on the overboard.
>>34991/overboard/ works as it should but /overboard/catalog isn't updating for me. tried on several devices
same with the sfw and alt catalog
the catalogs for the individual boards work like normal
pic is what the overboard catalog looks like for me
It was brought to my attention that
https://boards.plus4chan.org/baw/ was having a Red Alert Day for April Fools and it was rather well done with musical theme an interactive musical background with the Red Alert Theme and moving Zepplins, and different Red Alert cut-scene video clips when you clicked Reply.
I was thinking it would be fucking metal as hell if the dev team took a look at this, maybe replicate it. We're leftypol and honestly the whole Red Alert aesthetic would be fun to have as a CSS option.
Anyone have advice for converting .swf to mp4 or webm? I have 2 swf files that obstinately fail to convert because of a frame error.
For example these files
https://files.catbox.moe/f5ueyb.swf https://files.catbox.moe/fc1w1v.swf>>34492>>35002Also Zankaria, as the most active Dev-Mod can you please take a look at
>>>/meta/31895 Thank you very kindly.
>>35005I am already on it and off it.
I have my hands quite full, and that slipped in the lower priority list.
With that said I finally managed to deploy a feature that had been stuck in a limbo for the past month
>>35009Spam. Unfortunately Gitea really lacks good moderation tools.
I was thinking of turning off registrations, but I have no channel set up to accept legit newcomers
>>35010Mate, if you need any help figuring out the backup system or anything else, need credentials for gitea or whatever let pask know and he'll tell me.
Cheers.
>>35017Ok, for whatever reason it seems like making a reply triggers the JavaScript, which makes it insert the
position: initial
CSS
https://git.leftypol.org/leftypol/leftypol/issues/133#issuecomment-686 >>35018That's weird. It always autocompleted with a password for me, even when I created an anonymous session
> what're ur thoughts on autocompletin the password box to "password"You're asking to use "password" as a default password for all posts?
>>35023What if you change
https://git.leftypol.org/leftypol/leftypol/src/branch/config/js/hud-pinning.js#L45 to
setHudPinning(localStorage.hud_pinning !== 'false');
In my case `localStorage.hud_pinning' is undefined, this makes the check produce "true" as it should. With the current code I get false. I guess the alternative is to initialize `localStorage.hud_pinning' to true on first running the JavaScript. But I like this better.
That aside, is anyone else here trouble with cloning our repos? I've been trying to onboard a couple of new devs, but they're both unable to clone
https://git.leftypol.org/leftypol/leftypol/ or their own forks, failing with 403.
The thing is that I can't even reproduce on any of my machines
Oi Zankaria, when you have the time soon, please repair the archives
>>>/meta/33396 Thanks
>>35040Can confirm.
Got the same when I responded with
ok retard to whatever illiterate idiot banned me.
Somebody fetch that mod their smelling salts.
>>35037Having reproducible issues is too much to ask these days
>>35038> when you have the timepicrel
>>35040I should have fixed it
>>35043Not even sure what to check tbh. We have a daemon that does it's proxy thing and that's basically it.
Are RSS for boards not working correctly for anyone else?
I'm attempting to feed these two URLs into newsboat:
https://leftypol.org/leftypol/index.rsshttps://leftypol.org/tech/index.rssBut neither of them populate in the reader. Am I missing something?
>>35467I mean ddmmyy.
Year first is clumsy and unsuited for everyday purposes… In my opinion.
>>35804Should have been fixed now
>>35830Noted
>>35831(Sadly) known heisenbug. It appears and disappears randomly, and no dev team member with iOS has been able to reproduce it. I deployed an fix attempt but I am not sure if it's effective
>>36065Now you never will
>>36037Filters on the overboard do not work because they were never implemented. Right now the only workaround is to use some user-supplied JS. You can check the [Options] button for the textfield to load the javascript in.
crossposted from
>>>/meta/35453Proposition for increasing legibility and reducing whitespace:
div.body {
text-indent: .25em each-line hanging;
}
This would make paragraphs easier to tell apart without needing an additional line break, and would only effect lines long enough to wrap.
Additionally, for the Jungle theme:
span.orangeQuote {
color: #FF8C00;
text-shadow: 0.05em 0.05em orange;
}
.quote {
color: #789922;
text-shadow: 0.05em 0.05em green;
}
This makes the green and orange pop from the banana background.
Mods,
Have or are any of you using the Tor Browser and the onion service? I.e. are you testing your "solutions" before you launch them?
Rhetorical question.
>Want to post
>Type full text out, fill everything out before hand, have a copy-paste saved, attached file, dropped kids off, filed tax returns, raise negotiated. Finally, it's time to solve the leftypol captcha.
>Solve it, ok browser froze, guess this is to be expected at this point
>Post reply. "Error". Damn, I guess the two-headed bird constituted as a single animal. Guess I'll have to solve it again.
>Another puzzle, okay. 57 second load time (no browser freeze this time!) Great. Oh seems like I missed a comma there on the last paragraph…
>Oh look the captcha expired.
Why do you hate anonymous posters?
>>36365>>36366I think I'm one of the only mods who uses the onion service. Shit definitely sucks, but some form of moderation is definitely necessary, since we've been getting a bombpartment of raids this month alone from the TOR node. I personally like the idea of
>>>/meta/36319. TL;DR during times of raids, it puts each TOR post on a waitlist, and Mods either approve/deny
Papers Please style. But as Zankaria notes, the development team already has a shitton of problems piling up, and creating this feature would involve a whole revamp of the vichan. I'll try to work on the patch, but if you can find any good wailist .php files those could be dope.
>>36365Occasionally I do use, and so far I squashed all the bugs I found
>Post reply. "Error". Damn, I guess the two-headed bird constituted as a single animal.Which error? You mean "you seem to have mistyped the captcha"?
>Oh look the captcha expired. I'll see if I can alter the timeout
>>36353Deployed the jungle theme changes.
The indentation is being discussed with staff
>>36593>>36532Ok I'll talk to the devs, but if they seem overwhelmed I'll try a crack at designing it.
>>36591I don't really know what you're talking about, since I only use TOR to accsess the site and the videos for me are always fucked
(can't have shit in Oniontown), but the reason for this is because under [Options] in the top right of the screen, and under the setting MediaProxy, its default configed to some weird onion link I never took the time to troubleshoot. Could this be the source of your issue?
>>36613You now should be able to post. It's a new antispam feature requested by staff.
IPs are now required to have made at least one another post before creating a thread.
>>36615>>36616Yeah this guy is IPV6, we might have to see if we can tune the system to work on the /64 range for IPV6 IPs - it *should* cover the possibility of dynamic IPs since they are usually only dynamic on that range.
Perchance, anon, could you post some of your other posts so I can check the IP range?
>>36617Only ones I can think of right now are some of the /USApol/ threads:
>>>/leftypol/2027089>>>/leftypol/2022471>>>/leftypol/2021616Some of them might have been over LTE, not 100% sure.
>>36688Could not reproduce
>>36676Noted
>>36904Couldn't reproduce this on my side. Also, you can also search through the site using your webbrowser: "[pattern] site:leftypol.org"
>>36986I experience the same issue. I imagine it has to do with the media-proxy setting that the website sets for all TOR connections, tuberyps2pn6dor6h47brof3w2asmauahhk4ei42krugybzzzo55klad.onion. I actually have never tried to fix it kek, kinda just gave up on watching videos. But poking around through the site when I accsess it with javascript enabled, I found you can navigate to the "[Options]" bar, and at the bottom you can change the proxy you use.
>>36988Do you have any alternatives in mind?
>>36996As
>>37002 says, they are handled in a chronological order. I reported your post and dismissed the report, see picrel.
>>36994As a TOR-user, I don't like the captcha either. Found this repository that's more or less the code they use:
https://github.com/Gregwar/Captcha. I'll write a ticket for it on our repo and talk to Zank to see if they'd be okay with implenting it.
>>37003Reading through our repo now. Looks like lainchan devs
(to whom we kneel and bow before) already made a captcha, which is the one I imagine lainchain actually uses. My apologies.
>>37042Stupid faggot.
make Anonymous comments invisible by default, and make users opt-in to view Anonymous posts.
Also kill yourself for having the most dogshit idea of the year.
Sorry I did not see
>>37012It seems to happen with every mp3
>>37073Ok that was really weird. Basically it seems like the thumbnail file got corrupted, and since it was in a folder that git doesn't track it never noticed the file being broken.
And with the file being broken, the code that was trying to calculate the width and height of the image failed.
>>37074Hi dev, can you look at this
>>37055 ?
It's a better captcha (the hCaptcha one is a resource hog and is very buggy on Tor Browser)
>>37151https://gitlab.leftypol.org/leftypol/leftypol/-/issues/54#note_145The lainchan one is just secureimage.
As for bus: which? The few times I used tor I haven't noticed anything that I haven't already fixed (or fixed in my tests?)
>>37178>>37158Makes it virtually impossible to post on the tor node unless you happen to get a very lucky or want to sit cycling for a long time.
It's ending torposting by the back door and only further proof to show the degradation of /leftypol/ in the last couple of years.
>>37253Conversation quality has substantially fallen, to the extent that /leftypol/ is resembling a /pol2/ overflow board with more leftists.
The change being requested is a small aesthetic change; it won't stop "glow" "anti-campists" from posting, but it will make it slightly less obvious.
Because as is, we're experiencing a Gresham's Law of bad posting displacing good posting, as good posters leave (Gay Nazi, of all people, is one of the last quality posters here) and bad posters proliferate.
>>37294>Let them do it and expose themselves.I hope the message is clear to all non-Whites. If Russians can be lowered to the Mongoloid Zigger Orc hordes, how do you think these people feel about you?
Either you're team Zigger or your team Cracker. If you're not a cracker, they won't let you on the team, and if you're not a cracker, you're all the same to them whether you're Black Brown Yellow Green whatever.
>>37295It's just easier to appropriate Zyghur than Zigger, mind you.
But you folks make a valid point about them alienating non-white non-burgers about how trying to set up a race war is suicidal.
>>37338Define a non-Western phenotype. Hottentot (Khosan) have huge t&a, Japanese women have small or no breasts, etc…
The point might be more that the women are geared toward notions of male gynosexual attractiveness.
Unique IPs: 180