[ overboard / sfw / alt / cytube] [ leftypol / siberia / hobby / tech / edu / games / anime / music ] [ meta / roulette ] [ GET / ref / booru]

/tech/ - Technology

"Technology reveals the active relation of man to nature"
Name
Email
Subject
Comment
Flag
File
Embed
Password (For file deletion.)

New Announcement: IRC<=>Matrix bridge #leftypol on Rizon
Please give feedback on proposals, new every Monday : /meta/


File: 1612129656526.gif (2.28 MB, 224x240, 1608608621350.gif)

 No.6724[View All]

This thread is only for feedback related to technical issues(bug reports, suggestions). Otherwise use >>>/leftypol/30356
Public Repo:
TBA
If you have any grievances you can make a PR.

Mobile Support:
https://github.com/PietroCarrara/Clover/releases/latest
Thread For Mobile Feedback: >>>/tech/6316

Onion Link:
76i2c3hn55fcj5nut3tqlboqqbbh23zvphv7lefk3vftpx6wketlanyd.onion

Cytube:
TBA

Matrix rooms:
https://matrix.to/#/#leftypolPublic:matrix.org

We 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/903
180 posts and 47 image replies omitted. Click reply to view.

 No.10728

I believe I have found the true cause of the auto-update issue after making a new post, a regression caused by an absolute hack of a commit from January.

 No.10738

>>10728
thanks devanon.

 No.10743

We're in a shortage of SEA communist flags (only Kampuchea, Vietnam). No Thai, no Pathet Lao, no Malay Communists, not even PKI is in the list currently.
Can you mods add those?

 No.10745

>>10414
>>10419
You 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.

 No.10747

>>10745
>Do you know what could cause them not to be found despite being generated immediately earlier?
This is explained in >>10407. 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 >>10393 js/inline-expanding.js >>10414 js/auto-scroll.js >>10419 and their friends, but it's placed too late in $config['additional_javascript'] >>10407.

>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.

 No.10749

This question is probably better asked here than /meta/, where should leftypol.org create its Git version management?
I'm sure we can all agree on 'fuck GitHub'. Personally I would prefer a site that has no external connections/trackers and allows use without enabling JavaScript.
What would be the pros and cons of various platforms?

Current suggestions:
>self-hosted - Gitea instance on leftypol.org
>0xacab.org (GitLab, explicitly leftist, has onion, requires JS)
>disroot.org (Gitea instance, explicitly leftist, no onion)
>codeberg.org (popular, no onion)

 No.10751

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.

>>10749
The 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.

 No.10752

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 >>10747 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 // >>10751
- 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/[email protected] js/options/[email protected] but config has js/[email protected] js/options/[email protected]
js/toggle-images.js has js/[email protected] js/options/[email protected] but config has js/[email protected] js/options/[email protected]
js/no-animated-gif.js has js/[email protected] js/options/[email protected] but config has js/[email protected] js/options/[email protected]
js/toggle-locked-threads.js has js/[email protected] js/options/[email protected] but config has js/[email protected] js/options/[email protected]
js/options/general.js has js/[email protected] js/options/[email protected] but config has js/[email protected] js/options/[email protected]
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 >>10747 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.

 No.10753

the sample invocation without clownflare interference

 No.10831

Iqdb links but only for thumbnails supported by iqdb.org, so no webps and no full images.
Array.from (document.querySelectorAll ("div.files > div.file")).map (e => [e.querySelector ("img.post-image"), e.querySelector ("span.details")]).filter (([img, details]) => img.hasAttribute ("src") && /^\/[^\/]+\/thumb\/[^\/.]+[.](jpe?g|png|gif)$/i.test (img.getAttribute ("src"))).forEach (([img, details]) => {
  const span = document.createElement ("span")
  span.setAttribute ("class", "iqdb")
  span.innerHTML = ' <a href="https://iqdb.org/?url=https://leftypol.org' + img.getAttribute ("src") + '" target="_blank">iqdb</a>'
  details.appendChild (span)
})

 No.10838

>>10831
Why not full images? They seem to support them.

 No.10845

>>10838
>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#L572
Using the full images when either a thumbnail is not available or is a webp will be in a future version of >>10831.

 No.10888

Upgrade of >>10831 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
)

 No.10935

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/10945

 No.10948

Some harmless fun with the original filenames. If the filename looks like a timestamp from a board download >>6724 the UTC date is provided. If it looks like an md5 hash >>6841 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 ()
    }
  ]
)

 No.10970

Let me get rid of this, I keep clicking it instead of the reply button

 No.10981

>>10970
Include enough context around it to show which one you mean.

 No.10982

File: 1630662239183.png (140.99 KB, 1086x450, ClipboardImage.png)

>>10981
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.

 No.10983

>>10982
If 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.

 No.10984

>>10983
>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

 No.11029

>>10984
Here'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 ()
}) ()

 No.11046

There's no div.banner in the post form in index pages so >>11029 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 ()
}) ()

 No.11066

File: 1630855709885.png (3.05 KB, 449x67, ClipboardImage.png)

m8 who tf extended the already annoying as fuck FLOOD DETECTED box to two minutes? Can we have something slightly more sophisticated like kicking in on the third post so I don't have to sit like a retard pressing New Reply to correct a mistake in the previous post?

 No.11074

Upgrade of >>10948 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)
)

 No.11079

>>11066
Two 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.

 No.11081

>>11079
Lainchan 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.

 No.11091

>>11079
/leftypol/, non-shared private IP. The time between the two posts was 2 minutes when it finally allowed me to post. Sometimes it feels like pressing it resets the count.

 No.11093

>>11081
>adding a postcontainer div
The alternative solution with keeping postcontainer is in >>>/leftypol_archive/1822 2021-01-29.

 No.11094

>>11093
I'm happy to implement either solution, which do you think is better? It looked to me as if the postcontainer didn't offer anything and broke scripts.

 No.11097

>>11094
>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.

 No.11107

Upgrade of >>11074 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)
    }
  }
)

 No.11115

File: 1631011636594.png (232.27 KB, 707x615, ClipboardImage.png)

Why did the date format on the posts change from a beautiful ISO8601 to a horrible and confusing burger date format?

 No.11124

>>11115
Are 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.

 No.11137

>>11124
Sorry it's just 4chanX messing up with the format.

 No.11141

Okay lads I have a feature suggestion I have never seen on any imageboard, I am quite pleased to say it is a genius idea and quite simple.
In the reply box, when you start a line with > or <, it will greentext or orangetext the line as it would appear in the reply.

 No.11147

>>11141
>In the reply box
Textarea is a plain text element without subrange styling.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea
The comment line quoter which avoids >>10984 is in >>11046.

 No.11561

i might be the only affected person but i can't upload images via tor browser on android

 No.11636

File: 1632148454808.png (83.52 KB, 972x609, ClipboardImage.png)

There's now a dark solarized theme.

 No.11641

>>11561
It's not just you, I usually don't post images via mobile but I tried and they wouldn't attach (both with and without JS). I'm not sure how it would be fixed.

 No.11642

YouTube now blocks every Tor exit node. Can you change the URLs of YouTube videos so instead of YouTube links, it gives you Invidious links like this? That way we can all watch easily.

https://iteroni.com/watch?v=r65hqtFSoBY

 No.11643

>>11641
that makes two of us

 No.11644

>>11642
i type in watch?v= all the time. making it automatic would probably require an add-on? which is unadvisable with tor borwser

 No.11646

The best part about leftychan is that they reverted your shitty fucking webp thumbnail bullshit and suddenly the site became 10x more usable again because I can actually see post thumbnails on a fucking image board. Do the same here and maybe I'll think about posting again. The mods have otherwise done next to nothing constructive to end the split.

 No.11649

>>11642
Array.from (document.querySelectorAll ('a[href^="https://youtu.be/"]')).map (e => [e, e.getAttribute ("href").match (/^https:\/\/youtu\.be\/(watch\?v=)?([^?\/]+)$/)]).filter (p => p [1] != null).forEach (([e, m]) => { e.setAttribute ("href", "https://iteroni.com/watch?v=" + m [2]); })


>>11644
Array.from (document.querySelectorAll ('a[href^="https://youtu.be/"]')).map (e => [e, e.getAttribute ("href").match (/^https:\/\/youtu\.be\/([^?\/]+)$/)]).filter (p => p [1] != null).forEach (([e, m]) => { e.setAttribute ("href", "https://youtu.be/watch?v=" + m [1]); })


>>11641
If you can upload on other sites with the same procedure look at a var_dump of $_FILES early in post.php:handle_post.

 No.11650

>>11642
How 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?

 No.11651

>>11650
That 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.

>>11646
If your computer can't show .webp in a browser by now, I think you should look into fixing it.

 No.11652

>>11651
Do you know of a good proxy?

 No.11654

File: 1632225263176.png (358.88 KB, 950x681, ClipboardImage.png)

>>11652
I 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

 No.11658


 No.11660

>>11654
>….onion
This 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?


Unique IPs: 11

[Return][Go to top] [Catalog] | [Home][Post a Reply]
Delete Post [ ]
[ overboard / sfw / alt / cytube] [ leftypol / siberia / hobby / tech / edu / games / anime / music ] [ meta / roulette ] [ GET / ref / booru]