From e9417b0641dd077451e41eff935f165d39f85c67 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Sun, 8 Apr 2018 13:39:04 -0400 Subject: [PATCH 01/15] Uploader consistency fix * Updated so that the uploader attribute isn't provided during instances of API use. --- better-better-booru.user.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index f472f97..d1e6710 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -4795,7 +4795,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. function createThumbHTML(postInfo, query) { // Create a thumbnail HTML string. - return '
' + postInfo.tag_string + '
'; + return '
' + postInfo.tag_string + '
'; } function createThumb(postInfo, query) { @@ -9063,6 +9063,11 @@ function bbbScript() { // Wrapper for injecting the script into the document. return (getUserData("level") >= 30); } + function isModLevel() { + // Determine whether the user is at the moderator account level or higher. + return (getUserData("level") >= 40); + } + function accountSettingCheck(scriptSetting) { // Determine whether the script setting or account/anonymous setting should be used. var loggedIn = isLoggedIn(); From 69d9adde3a4e15725234d595bddea83ffefbfb92 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Thu, 12 Apr 2018 21:53:30 -0400 Subject: [PATCH 02/15] Post data updates * Updated to collect and provide the "top tagger", "uploader id", and "normalized source" information. --- better-better-booru.user.js | 133 ++++++++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 5 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index d1e6710..3ae00b0 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -55,6 +55,24 @@ function bbbScript() { // Wrapper for injecting the script into the document. return hash >>> 0; }; + Number.prototype.bbbEncode62 = function() { + // Encode a number to base62. + var encodeChars = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]; + var encoded = ""; + var num = this; + + if (num === 0) + encoded = encodeChars[0]; + else { + while (num > 0) { + encoded = encodeChars[num % 62] + encoded; + num = Math.floor(num / 62); + } + } + + return encoded; + }; + Element.prototype.bbbGetPadding = function() { // Get all the padding measurements of an element including the total width and height. if (window.getComputedStyle) { @@ -1424,6 +1442,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. has_children: (imgContainer.getAttribute("data-has-children") === "true"), has_active_children: (postTag === "IMG" || postTag === "CANVAS" ? postEl.getAttribute("data-has-active-children") === "true" : !!target.getElementsByClassName("notice-parent")[0]), fav_string: getMeta("favorites", docEl), + normalized_source: imgContainer.getAttribute("data-normalized-source") || "", parent_id: (imgContainer.getAttribute("data-parent-id") ? Number(imgContainer.getAttribute("data-parent-id")) : null), rating: imgContainer.getAttribute("data-rating") || "", score: Number(imgContainer.getAttribute("data-score")) || 0, @@ -1435,6 +1454,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. tag_string_general: scrapePostTags("general", target), pool_string: imgContainer.getAttribute("data-pools") || "", uploader_name: imgContainer.getAttribute("data-uploader") || "", + uploader_id: Number(imgContainer.getAttribute("data-uploader-id")) || 0, approver_id: imgContainer.getAttribute("data-approver-id") || null, is_deleted: (flags.indexOf("deleted") > -1), is_flagged: (flags.indexOf("flagged") > -1), @@ -1444,6 +1464,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. image_width: Number(imgContainer.getAttribute("data-width")) || null }; + imgInfo.keeper_data = {uid: Number(imgContainer.getAttribute("data-top-tagger")) || imgInfo.uploader_id || 0}; imgInfo.has_large = (imgInfo.large_file_url !== imgInfo.file_url); // Grab any available Ugoira data. @@ -1508,6 +1529,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. has_children: (post.getAttribute("data-has-children") === "true"), has_active_children: post.bbbHasClass("post-status-has-children"), // Assumption. Basically a flag for the children class. fav_string: (post.getAttribute("data-is-favorited") === "true" ? "fav:" + getMeta("current-user-id") : ""), // Faked since thumbnails don't provide the full list of favorites. + normalized_source: post.getAttribute("data-normalized-source") || "", parent_id: (post.getAttribute("data-parent-id") ? Number(post.getAttribute("data-parent-id")) : null), rating: post.getAttribute("data-rating") || "", score: Number(post.getAttribute("data-score")) || 0, @@ -1515,6 +1537,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. tag_string: post.getAttribute("data-tags") || "", pool_string: post.getAttribute("data-pools") || "", uploader_name: post.getAttribute("data-uploader") || "", + uploader_id: Number(post.getAttribute("data-uploader-id")) || 0, approver_id: post.getAttribute("data-approver-id") || null, is_deleted: (flags.indexOf("deleted") > -1), is_flagged: (flags.indexOf("flagged") > -1), @@ -1524,6 +1547,8 @@ function bbbScript() { // Wrapper for injecting the script into the document. image_width: Number(post.getAttribute("data-width")) || null }; + imgInfo.keeper_data = {uid: Number(post.getAttribute("data-top-tagger")) || imgInfo.uploader_id || 0}; + if (imgInfo.file_url) imgInfo.has_large = (imgInfo.file_url !== imgInfo.large_file_url); else { @@ -4795,7 +4820,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. function createThumbHTML(postInfo, query) { // Create a thumbnail HTML string. - return ''; + return ''; } function createThumb(postInfo, query) { @@ -6246,6 +6271,8 @@ function bbbScript() { // Wrapper for injecting the script into the document. postInfo.has_sound = /(?:^|\s)(?:video|flash)_with_sound(?:$|\s)/.test(postInfo.tag_string); postInfo.flags = postFlags(postInfo); postInfo.is_favorited = new RegExp("(?:^|\\s)fav:" + getMeta("current-user-id") + "(?:$|\\s)").test(postInfo.fav_string); + postInfo.normalized_source = postInfo.normalized_source || normalizedSource(postInfo); + postInfo.keeper_data = postInfo.keeper_data || {uid: postInfo.uploader_id}; // Custom BBB properties. postInfo.file_url_desc = postFileUrlDesc(postInfo); @@ -6276,6 +6303,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. delete postInfo.preview_img_src; delete postInfo.file_img_src; delete postInfo.large_file_img_src; + delete postInfo.normalized_source; return postInfo; } @@ -6398,6 +6426,103 @@ function bbbScript() { // Wrapper for injecting the script into the document. } } + function normalizedSource(postInfo) { + // Produce a normalized source from a post's source information. + var source = postInfo.source; + var urlReg, url, id, artist, title; // If/else variables. + + if (!!(urlReg = source.match(/^https?:\/\/img\d+\.pixiv\.net\/img\/[^\/]+\/(\d+)/i) || source.match(/^https?:\/\/i\d\.pixiv\.net\/img\d+\/img\/[^\/]+\/(\d+)/i))) + url = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/(?:i\d+\.pixiv\.net|i\.pximg\.net)\/img-(?:master|original)\/img\/(?:\d+\/)+(\d+)_p/i) || source.match(/^https?:\/\/(?:i\d+\.pixiv\.net|i\.pximg\.net)\/c\/\d+x\d+\/img-master\/img\/(?:\d+\/)+(\d+)_p/i) || source.match(/^https?:\/\/(?:i\d+\.pixiv\.net|i\.pximg\.net)\/img-zip-ugoira\/img\/(?:\d+\/)+(\d+)_ugoira\d+x\d+\.zip/i))) + url = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/lohas\.nicoseiga\.jp\/priv\/(\d+)\?e=\d+&h=[a-f0-9]+/i) || source.match(/^https?:\/\/lohas\.nicoseiga\.jp\/priv\/[a-f0-9]+\/\d+\/(\d+)/i))) + url = "http://seiga.nicovideo.jp/seiga/im" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/(?:d3j5vwomefv46c|dn3pm25xmtlyu)\.cloudfront\.net\/photos\/large\/(\d+)\./i))) { + id = parseInt(urlReg[1]).toString(36); + url = "http://twitpic.com/" + id; + } + else if (!!(urlReg = source.match(/^https?:\/\/(?:fc|th|pre|orig|img|prnt)\d{2}\.deviantart\.net\/.+\/([a-z0-9_]+)_by_([a-z0-9_]+)-d([a-z0-9]+)\./i))) { + title = urlReg[1].replace(/[^A-Za-z0-9]/g, " ").bbbSpaceClean().replace(/[ ]/g, "-"); + artist = urlReg[2].replace(/_/g, "-"); + id = parseInt(urlReg[3], 36); + url = "http://" + artist + ".deviantart.com/art/" + title + "-" + id; + } + else if (!!(urlReg = source.match(/^https?:\/\/(?:fc|th|pre|orig|img|prnt)\d{2}\.deviantart\.net\/.+\/[a-f0-9]{32}-d([a-z0-9]+)\./i))) { + id = parseInt(urlReg[1], 36); + url = "http://deviantart.com/deviation/" + id; + } + else if (!!(urlReg = source.match(/^http:\/\/www\.karabako\.net\/images(?:ub)?\/karabako_(\d+)(?:_\d+)?\./i))) + url = "http://www.karabako.net/post/view/" + urlReg[1]; + else if (!!(urlReg = source.match(/^http:\/\/p\.twpl\.jp\/show\/orig\/([a-z0-9]+)/i))) + url = "http://p.twipple.jp/" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/pictures\.hentai-foundry\.com\/\/?[^\/]\/([^\/]+)\/(\d+)/i))) + url = "http://www.hentai-foundry.com/pictures/user/" + urlReg[1] + "/" + urlReg[2]; + else if (!!(urlReg = source.match(/^http:\/\/blog(?:(?:-imgs-)?\d*(?:-origin)?)?\.fc2\.com\/(?:(?:[^\/]\/){3}|(?:[^\/]\/))([^\/]+)\/(?:file\/)?([^\.]+\.[^\?]+)/i))) + url = "http://" + urlReg[1] + ".blog.fc2.com/img/" + urlReg[2] + "/"; + else if (!!(urlReg = source.match(/^http:\/\/diary(\d?)\.fc2\.com\/user\/([^\/]+)\/img\/(\d+)_(\d+)\/(\d+)\./i))) + url = "http://diary" + urlReg[1] + ".fc2.com/cgi-sys/ed.cgi/" + urlReg[2] + "?Y=" + urlReg[3] + "&M=" + urlReg[4] + "&D=" + urlReg[5]; + else if (!!(urlReg = source.match(/^https?:\/\/(?:fbcdn-)?s(?:content|photos)-[^\/]+\.(?:fbcdn|akamaihd)\.net\/hphotos-.+\/\d+_(\d+)_(?:\d+_){1,3}[no]\./i))) + url = "https://www.facebook.com/photo.php?fbid=" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/c(?:s|han|[1-4])\.sankakucomplex\.com\/data(?:\/sample)?\/(?:[a-f0-9]{2}\/){2}(?:sample-|preview)?([a-f0-9]{32})/i))) + url = "http://chan.sankakucomplex.com/en/post/show?md5=" + urlReg[1]; + else if (!!(urlReg = source.match(/^http:\/\/s(?:tatic|[1-4])\.zerochan\.net\/.+(?:\.|\/)(\d+)\.(?:jpe?g?)$/i))) + url = "http://www.zerochan.net/" + urlReg[1] + "#full"; + else if (!!(urlReg = source.match(/^http:\/\/static[1-6]?\.minitokyo\.net\/(?:downloads|view)\/(?:\d{2}\/){2}(\d+)/i))) + url = "http://gallery.minitokyo.net/download/" + urlReg[1]; + else if (postInfo.md5 && !!(urlReg = source.match(/^https?:\/\/(?:(?:s?img|cdn|www)\d?\.)?gelbooru\.com\/{1,2}(?:images|samples)\/(?:\d+|[a-f0-9]{2}\/[a-f0-9]{2})\/(?:sample_)?(?:[a-f0-9]{32}|[a-f0-9]{40})\./i))) + url = "http://gelbooru.com/index.php?page=post&s=list&md5=" + postInfo.md5; + else if (!!(urlReg = source.match(/^https?:\/\/(?:slot\d*\.)?im(?:g|ages)\d*\.wikia\.(?:nocookie\.net|com)\/(?:_{2}cb\d{14}\/)?([^\/]+)(?:\/[a-z]{2})?\/images\/(?:(?:thumb|archive)?\/)?[a-f0-9]\/[a-f0-9]{2}\/(?:\d{14}(?:!|%21))?([^\/]+)/i))) + url = "http://" + urlReg[1] + ".wikia.com/wiki/File:" + urlReg[2]; + else if (!!(urlReg = source.match(/^https?:\/\/vignette(?:\d*)\.wikia\.nocookie\.net\/([^\/]+)\/images\/[a-f0-9]\/[a-f0-9]{2}\/([^\/]+)/i))) + url = "http://" + urlReg[1] + ".wikia.com/wiki/File:" + urlReg[2]; + else if (!!(urlReg = source.match(/^http:\/\/(?:(?:\d{1,3}\.){3}\d{1,3}):(?:\d{1,5})\/h\/([a-f0-9]{40})-(?:\d+-){3}(?:png|gif|(?:jpe?g?))\/keystamp=\d+-[a-f0-9]{10}\/([^\/]+)/i))) + url = "http://g.e-hentai.org/?f_shash=" + urlReg[1] + "&fs_from=" + urlReg[2]; + else if (!!(urlReg = source.match(/^http:\/\/e-shuushuu.net\/images\/\d{4}-(?:\d{2}-){2}(\d+)/i))) + url = "http://e-shuushuu.net/image/" + urlReg[1]; + else if (!!(urlReg = source.match(/^http:\/\/jpg\.nijigen-daiaru\.com\/(\d+)/i))) + url = "http://nijigen-daiaru.com/book.php?idb=" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/sozai\.doujinantena\.com\/contents_jpg\/([a-f0-9]{32})\//i))) + url = "http://doujinantena.com/page.php?id=" + urlReg[1]; + else if (!!(urlReg = source.match(/^http:\/\/rule34-(?:data-\d{3}|images)\.paheal\.net\/(?:_images\/)?([a-f0-9]{32})/i))) + url = "http://rule34.paheal.net/post/list/md5:" + urlReg[1] + "/1"; + else if (!!(urlReg = source.match(/^http:\/\/shimmie\.katawa-shoujo\.com\/image\/(\d+)/i))) + url = "http://shimmie.katawa-shoujo.com/post/view/" + urlReg[1]; + else if (postInfo.md5 && !!(urlReg = source.match(/^http:\/\/(?:(?:(?:img\d?|cdn)\.)?rule34\.xxx|img\.booru\.org\/(?:rule34|r34))(?:\/(?:img\/rule34|r34))?\/{1,2}images\/\d+\/(?:[a-f0-9]{32}|[a-f0-9]{40})\./i))) + url = "http://rule34.xxx/index.php?page=post&s=list&md5=" + postInfo.md5; + else if (!!(urlReg = source.match(/^https?:\/\/(?:s3\.amazonaws\.com\/imgly_production|img\.ly\/system\/uploads)\/((?:\d{3}\/){3}|\d+\/)/i))) { + id = parseInt((urlReg[1].replace(/[^0-9]/g, '')) || 0).bbbEncode62(); + url = "http://img.ly/" + id; + } + else if (!!(urlReg = source.match(/^(http:\/\/.+)\/diarypro\/d(?:ata\/upfile\/|iary\.cgi\?mode=image&upfile=)(\d+)/i))) + url = urlReg[1] + "/diarypro/diary.cgi?no=" + urlReg[2]; + else if (!!(urlReg = source.match(/^http:\/\/i(?:\d)?\.minus\.com\/(?:i|j)([^\.]{12,})/i))) + url = "http://minus.com/i/" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/pic0[1-4]\.nijie\.info\/nijie_picture\/(?:diff\/main\/)?\d+_(\d+)_(?:\d{10}|\d+_\d{14})/i))) + url = "http://nijie.info/view.php?id=" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/(?:ayase\.|yuno\.|files\.)?yande\.re\/(?:sample|image)\/[a-z0-9]{32}\/yande\.re%20([0-9]+)%20/i))) + url = "https://yande.re/post/show/" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/(?:ayase\.|yuno\.|files\.)?yande\.re\/(?:image|jpeg|sample)\/([a-z0-9]{32})(?:\/yande\.re.*|\/?\.(?:jpg|png))$/i))) + url = "https://yande.re/post?tags=md5:" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/\w+\.artstation.com\/(?:artwork|projects)\/([a-z0-9-]+)$/i))) + url = "https://www.artstation.com/artwork/" + urlReg[1]; + else if (!!(urlReg = source.match(/^https?:\/\/(?:o|image-proxy-origin)\.twimg\.com\/\d\/proxy\.jpg\?t=(\w+)&/i))) { + url = window.atob(urlReg[1]).match(/https?:\/\/[\x20-\x7e]+/i); + + if (url[0]) { + url = url[0]; + + if (url.match(/^https?:\/\/twitpic.com\/show\/large\/[a-z0-9]+/i)) + url = url.substring(0, url.lastIndexOf('.')).replace("show/large/", ""); + } + else + url = source; + } + else + url = source; + + return url; + } + function fixPaginator(target) { // Determine whether the paginator needs to be updated and request one as needed. var paginator = getPaginator(target); @@ -8945,10 +9070,8 @@ function bbbScript() { // Wrapper for injecting the script into the document. // Test a URL to find which section of Danbooru the script is running on. var target; // If/else variable. - if (url) { - target = document.createElement("a"); - target.href = url; - } + if (url) + target = new URL(url); else target = location; From 046358b08cac93952b6a0bd337caa8d58da11d59 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Thu, 12 Apr 2018 22:16:53 -0400 Subject: [PATCH 03/15] User metatag help update fix * Fixed the description of the user metatag to clarify that it can only be used by mod level users and higher. --- better-better-booru.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index 3ae00b0..178ea93 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -2031,7 +2031,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. helpPage.className = "bbb-page"; scrollDiv.appendChild(helpPage); - helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
  • tag1 - Match posts with tag1.
  • tag1 tag2 - Match posts with tag1 AND tag2.
  • -tag1 - Match posts without tag1.
  • tag1 -tag2 - Match posts with tag1 AND without tag2.
  • ~tag1 ~tag2 - Match posts with tag1 OR tag2.
  • ~tag1 ~-tag2 - Match posts with tag1 OR without tag2.
  • tag1 ~tag2 ~tag3 - Match posts with tag1 AND either tag2 OR tag3.

Wildcards can be used with any of the above methods:
  • ~tag1* ~-*tag2 - Match posts with tags starting with tag1 or posts without tags ending with tag2.

Multiple match rules can be specified by using commas or separate lines when possible:
  • tag1 tag2, tag3 tag4 - Match posts with tag1 AND tag2 or posts with tag3 AND tag4.
  • tag1 ~tag2 ~tag3, tag4 - Match posts with tag1 AND either tag2 OR tag3 or posts with tag4.

Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
  • ( ~tag1 ~tag2 ) ( ~tag3 ~tag3 ) - Match posts with either tag1 OR tag2 AND either tag3 OR tag4.
  • tag1 ( tag2, tag3 tag4 ) - Match posts with tag1 AND tag2 or posts with tag1 AND tag3 AND tag4.
  • tag1 -( tag2 tag3 ) - Match posts with tag1 AND without tag2 AND tag3.
  • tag1 ~tag2 ~( tag3 tag4 ) - Match posts with tag1 and either tag2 OR tag3 AND tag4.

The following metatags are supported:
  • rating:safe - Match posts rated safe. Accepted values include safe, explicit, and questionable.
  • status:pending - Match pending posts. Accepted values include active, pending, flagged, banned, and deleted. Note that flagged posts also count as active posts.
  • user:albert - Match posts made by the user Albert. Note that this tag will only work when viewing posts since Danbooru doesn\'t provide uploader information for thumbnail listings.
  • isfav:true - Match posts favorited under your current account. Accepted values include true and false.
  • group:hidden or g:hidden - Match posts that match the tags in your group named \"hidden\".
  • pool:1 - Match posts that are in the pool with an ID number of 1. Accepted values include pool ID numbers, "series" for posts in series category pools, "collection" for posts in collection category pools, "any" for posts in any pool, "none" for posts not in a pool, "active" for posts in an active (not deleted) pool, and "inactive" for posts only in an inactive (deleted) pool.
  • parent:1 - Match posts that have the post with an ID number of 1 as a parent. Accepted values include post ID numbers, "any" for any posts with a parent, and "none" for posts without a parent.
  • child:any - Match any posts that have children. Accepted values include "any" for any posts with children and "none" for posts without children.
  • id:1 - Match posts with an ID number of 1.
  • score:1 - Match posts with a score of 1.
  • favcount:1 - Match posts with a favorite count of 1.
  • height:1 - Match posts with a height of 1.
  • width:1 - Match posts with a width of 1.

The id, score, favcount, width, and height metatags can also use number ranges for matching:
  • score:<5 - Match posts with a score less than 5.
  • score:>5 - Match posts with a score greater than 5.
  • score:<=5 or score:..5 - Match posts with a score equal to OR less than 5.
  • score:>=5 or score:5.. - Match posts with a score equal to OR greater than 5.
  • score:1..5 - Match posts with a score equal to OR greater than 1 AND equal to OR less than 5.
'); + helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
  • tag1 - Match posts with tag1.
  • tag1 tag2 - Match posts with tag1 AND tag2.
  • -tag1 - Match posts without tag1.
  • tag1 -tag2 - Match posts with tag1 AND without tag2.
  • ~tag1 ~tag2 - Match posts with tag1 OR tag2.
  • ~tag1 ~-tag2 - Match posts with tag1 OR without tag2.
  • tag1 ~tag2 ~tag3 - Match posts with tag1 AND either tag2 OR tag3.

Wildcards can be used with any of the above methods:
  • ~tag1* ~-*tag2 - Match posts with tags starting with tag1 or posts without tags ending with tag2.

Multiple match rules can be specified by using commas or separate lines when possible:
  • tag1 tag2, tag3 tag4 - Match posts with tag1 AND tag2 or posts with tag3 AND tag4.
  • tag1 ~tag2 ~tag3, tag4 - Match posts with tag1 AND either tag2 OR tag3 or posts with tag4.

Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
  • ( ~tag1 ~tag2 ) ( ~tag3 ~tag3 ) - Match posts with either tag1 OR tag2 AND either tag3 OR tag4.
  • tag1 ( tag2, tag3 tag4 ) - Match posts with tag1 AND tag2 or posts with tag1 AND tag3 AND tag4.
  • tag1 -( tag2 tag3 ) - Match posts with tag1 AND without tag2 AND tag3.
  • tag1 ~tag2 ~( tag3 tag4 ) - Match posts with tag1 and either tag2 OR tag3 AND tag4.

The following metatags are supported:
  • rating:safe - Match posts rated safe. Accepted values include safe, explicit, and questionable.
  • status:pending - Match pending posts. Accepted values include active, pending, flagged, banned, and deleted. Note that flagged posts also count as active posts.
  • user:albert - Match posts made by the user Albert. Note that this tag will only work if you have a moderator level account or higher.
  • isfav:true - Match posts favorited under your current account. Accepted values include true and false.
  • group:hidden or g:hidden - Match posts that match the tags in your group named \"hidden\".
  • pool:1 - Match posts that are in the pool with an ID number of 1. Accepted values include pool ID numbers, "series" for posts in series category pools, "collection" for posts in collection category pools, "any" for posts in any pool, "none" for posts not in a pool, "active" for posts in an active (not deleted) pool, and "inactive" for posts only in an inactive (deleted) pool.
  • parent:1 - Match posts that have the post with an ID number of 1 as a parent. Accepted values include post ID numbers, "any" for any posts with a parent, and "none" for posts without a parent.
  • child:any - Match any posts that have children. Accepted values include "any" for any posts with children and "none" for posts without children.
  • id:1 - Match posts with an ID number of 1.
  • score:1 - Match posts with a score of 1.
  • favcount:1 - Match posts with a favorite count of 1.
  • height:1 - Match posts with a height of 1.
  • width:1 - Match posts with a width of 1.

The id, score, favcount, width, and height metatags can also use number ranges for matching:
  • score:<5 - Match posts with a score less than 5.
  • score:>5 - Match posts with a score greater than 5.
  • score:<=5 or score:..5 - Match posts with a score equal to OR less than 5.
  • score:>=5 or score:5.. - Match posts with a score equal to OR greater than 5.
  • score:1..5 - Match posts with a score equal to OR greater than 1 AND equal to OR less than 5.
'); helpPage.bbbTextSection('Hotkeys', 'Posts
  • B - Open BBB menu.
  • 1 - Resize to window.
  • 2 - Resize to window width.
  • 3 - Resize to window height.
  • 4 - Reset/remove resizing.
Note: Numbers refer to the main typing keypad and not the numeric keypad.

General
  • B - Open BBB menu.
  • E - Toggle endless pages.
  • F - Open quick search.
  • Shift + F - Reset quick search.
'); helpPage.bbbTextSection('Questions, Suggestions, or Bugs?', 'If you have any questions, please use the Greasy Fork feedback forums located here. If you\'d like to report a bug or make a suggestion, please create an issue on GitHub here.'); helpPage.bbbTocSection(); From ddbaffe9b1bffadd8ba3de14fc98e0ecf3918b05 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Thu, 12 Apr 2018 23:11:30 -0400 Subject: [PATCH 04/15] Backup page fix * Updated to support browser security changes for data URLs. --- better-better-booru.user.js | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index 178ea93..f763332 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -2697,17 +2697,12 @@ function bbbScript() { // Wrapper for injecting the script into the document. buttonDiv.appendChild(textBackup); var pageBackup = document.createElement("a"); - pageBackup.innerHTML = "Create Backup Page"; - pageBackup.href = "#"; + pageBackup.innerHTML = "Create Backup Text File"; + pageBackup.download = "Better Better Booru v" + bbb.user.bbb_version + " Backup (" + timestamp() + ").txt"; + pageBackup.target = "_blank"; + pageBackup.href = ('data:,Better Better Booru v' + bbb.user.bbb_version + ' Backup (' + timestamp() + '):%0D%0D' + JSON.stringify(bbb.user)).replace(/#/g, encodeURIComponent("#")); pageBackup.className = "bbb-button"; pageBackup.style.marginRight = "15px"; - pageBackup.addEventListener("click", function(event) { - if (event.button !== 0) - return; - - createBackupPage(); - event.preventDefault(); - }, false); buttonDiv.appendChild(pageBackup); var rightButtons = document.createElement("span"); @@ -2732,7 +2727,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. helpButton.innerHTML = "Help"; helpButton.href = "#"; helpButton.className = "bbb-button"; - helpButton.bbbSetTip("Create copies of your settings that can be used for recovering lost/corrupted settings or transferring settings.DirectionsThere are two options for creating a backup. Creating a text backup will provide a plain text format backup in the area provided that can be copied and saved where desired. Creating a backup page will open a new page that can be saved with the browser's \"save page\" or bookmark options.

To restore a backup, copy and paste the desired backup into the provided area and click \"restore backup\"."); + helpButton.bbbSetTip("Create copies of your settings that can be used for recovering lost/corrupted settings or transferring settings.DirectionsThere are two options for creating a backup. Creating backup text will provide a plain text format backup in the area provided that can be copied and saved where desired. Creating a backup text file will attempt to download a plain text copy of your settings or open a new tab containing the plain text copy.

To restore a backup, copy and paste the desired backup into the provided area and click \"restore backup\"."); rightButtons.appendChild(helpButton); return sectionFrag; @@ -3449,11 +3444,6 @@ function bbbScript() { // Wrapper for injecting the script into the document. textarea.setSelectionRange(0,0); } - function createBackupPage() { - // Open a new tab/window and place the setting text in it. - window.open(('data:text/html,Better Better Booru v' + bbb.user.bbb_version + ' Backup (' + timestamp() + ')' + JSON.stringify(bbb.user) + '').replace(/#/g, encodeURIComponent("#"))); - } - function restoreBackupText() { // Load the backup text provided into the script. var textarea = bbb.el.menu.backupTextarea; From 0f18465626fbd559766d2b9403ac5e791867b9b1 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Thu, 26 Apr 2018 00:36:53 -0400 Subject: [PATCH 05/15] New metatags & Autocomplete fix * Added metatags for "userid", "taggerid", and "source". * Fixed autocomplete behavior for some metatags. --- better-better-booru.user.js | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index f763332..531adad 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -2031,7 +2031,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. helpPage.className = "bbb-page"; scrollDiv.appendChild(helpPage); - helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
  • tag1 - Match posts with tag1.
  • tag1 tag2 - Match posts with tag1 AND tag2.
  • -tag1 - Match posts without tag1.
  • tag1 -tag2 - Match posts with tag1 AND without tag2.
  • ~tag1 ~tag2 - Match posts with tag1 OR tag2.
  • ~tag1 ~-tag2 - Match posts with tag1 OR without tag2.
  • tag1 ~tag2 ~tag3 - Match posts with tag1 AND either tag2 OR tag3.

Wildcards can be used with any of the above methods:
  • ~tag1* ~-*tag2 - Match posts with tags starting with tag1 or posts without tags ending with tag2.

Multiple match rules can be specified by using commas or separate lines when possible:
  • tag1 tag2, tag3 tag4 - Match posts with tag1 AND tag2 or posts with tag3 AND tag4.
  • tag1 ~tag2 ~tag3, tag4 - Match posts with tag1 AND either tag2 OR tag3 or posts with tag4.

Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
  • ( ~tag1 ~tag2 ) ( ~tag3 ~tag3 ) - Match posts with either tag1 OR tag2 AND either tag3 OR tag4.
  • tag1 ( tag2, tag3 tag4 ) - Match posts with tag1 AND tag2 or posts with tag1 AND tag3 AND tag4.
  • tag1 -( tag2 tag3 ) - Match posts with tag1 AND without tag2 AND tag3.
  • tag1 ~tag2 ~( tag3 tag4 ) - Match posts with tag1 and either tag2 OR tag3 AND tag4.

The following metatags are supported:
  • rating:safe - Match posts rated safe. Accepted values include safe, explicit, and questionable.
  • status:pending - Match pending posts. Accepted values include active, pending, flagged, banned, and deleted. Note that flagged posts also count as active posts.
  • user:albert - Match posts made by the user Albert. Note that this tag will only work if you have a moderator level account or higher.
  • isfav:true - Match posts favorited under your current account. Accepted values include true and false.
  • group:hidden or g:hidden - Match posts that match the tags in your group named \"hidden\".
  • pool:1 - Match posts that are in the pool with an ID number of 1. Accepted values include pool ID numbers, "series" for posts in series category pools, "collection" for posts in collection category pools, "any" for posts in any pool, "none" for posts not in a pool, "active" for posts in an active (not deleted) pool, and "inactive" for posts only in an inactive (deleted) pool.
  • parent:1 - Match posts that have the post with an ID number of 1 as a parent. Accepted values include post ID numbers, "any" for any posts with a parent, and "none" for posts without a parent.
  • child:any - Match any posts that have children. Accepted values include "any" for any posts with children and "none" for posts without children.
  • id:1 - Match posts with an ID number of 1.
  • score:1 - Match posts with a score of 1.
  • favcount:1 - Match posts with a favorite count of 1.
  • height:1 - Match posts with a height of 1.
  • width:1 - Match posts with a width of 1.

The id, score, favcount, width, and height metatags can also use number ranges for matching:
  • score:<5 - Match posts with a score less than 5.
  • score:>5 - Match posts with a score greater than 5.
  • score:<=5 or score:..5 - Match posts with a score equal to OR less than 5.
  • score:>=5 or score:5.. - Match posts with a score equal to OR greater than 5.
  • score:1..5 - Match posts with a score equal to OR greater than 1 AND equal to OR less than 5.
'); + helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
  • tag1 - Match posts with tag1.
  • tag1 tag2 - Match posts with tag1 AND tag2.
  • -tag1 - Match posts without tag1.
  • tag1 -tag2 - Match posts with tag1 AND without tag2.
  • ~tag1 ~tag2 - Match posts with tag1 OR tag2.
  • ~tag1 ~-tag2 - Match posts with tag1 OR without tag2.
  • tag1 ~tag2 ~tag3 - Match posts with tag1 AND either tag2 OR tag3.

Wildcards can be used with any of the above methods:
  • ~tag1* ~-*tag2 - Match posts with tags starting with tag1 or posts without tags ending with tag2.

Multiple match rules can be specified by using commas or separate lines when possible:
  • tag1 tag2, tag3 tag4 - Match posts with tag1 AND tag2 or posts with tag3 AND tag4.
  • tag1 ~tag2 ~tag3, tag4 - Match posts with tag1 AND either tag2 OR tag3 or posts with tag4.

Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
  • ( ~tag1 ~tag2 ) ( ~tag3 ~tag3 ) - Match posts with either tag1 OR tag2 AND either tag3 OR tag4.
  • tag1 ( tag2, tag3 tag4 ) - Match posts with tag1 AND tag2 or posts with tag1 AND tag3 AND tag4.
  • tag1 -( tag2 tag3 ) - Match posts with tag1 AND without tag2 AND tag3.
  • tag1 ~tag2 ~( tag3 tag4 ) - Match posts with tag1 and either tag2 OR tag3 AND tag4.

The following metatags are supported:
  • rating:safe - Match posts rated safe. Accepted values include safe, explicit, and questionable.
  • status:pending - Match pending posts. Accepted values include active, pending, flagged, banned, and deleted. Note that flagged posts also count as active posts.
  • user:albert - Match posts made by the user Albert. Note that this tag will only work if you have a moderator level account or higher.
  • userid:1 - Match posts made by the user with an ID number of 1.
  • taggerid:1 - Match posts mostly tagged by the user with an ID number of 1.
  • source:http://www.4chan.org/ - Match posts with a source starting with http://www.4chan.org/. Accepted values include "any" for all posts with sources, "none" for all posts without sources, wildcard searches such as "*pixiv.net*" for posts with sources that contain pixiv.net, and non-wildcard searches that start matching at the beginning of a source.
  • isfav:true - Match posts favorited under your current account. Accepted values include true and false.
  • group:hidden or g:hidden - Match posts that match the tags in your group named \"hidden\".
  • pool:1 - Match posts that are in the pool with an ID number of 1. Accepted values include pool ID numbers, "series" for posts in series category pools, "collection" for posts in collection category pools, "any" for posts in any pool, "none" for posts not in a pool, "active" for posts in an active (not deleted) pool, and "inactive" for posts only in an inactive (deleted) pool.
  • parent:1 - Match posts that have the post with an ID number of 1 as a parent. Accepted values include post ID numbers, "any" for any posts with a parent, and "none" for posts without a parent.
  • child:any - Match any posts that have children. Accepted values include "any" for any posts with children and "none" for posts without children.
  • id:1 - Match posts with an ID number of 1.
  • score:1 - Match posts with a score of 1.
  • favcount:1 - Match posts with a favorite count of 1.
  • height:1 - Match posts with a height of 1.
  • width:1 - Match posts with a width of 1.

The id, score, favcount, width, and height metatags can also use number ranges for matching:
  • score:<5 - Match posts with a score less than 5.
  • score:>5 - Match posts with a score greater than 5.
  • score:<=5 or score:..5 - Match posts with a score equal to OR less than 5.
  • score:>=5 or score:5.. - Match posts with a score equal to OR greater than 5.
  • score:1..5 - Match posts with a score equal to OR greater than 1 AND equal to OR less than 5.
'); helpPage.bbbTextSection('Hotkeys', 'Posts
  • B - Open BBB menu.
  • 1 - Resize to window.
  • 2 - Resize to window width.
  • 3 - Resize to window height.
  • 4 - Reset/remove resizing.
Note: Numbers refer to the main typing keypad and not the numeric keypad.

General
  • B - Open BBB menu.
  • E - Toggle endless pages.
  • F - Open quick search.
  • Shift + F - Reset quick search.
'); helpPage.bbbTextSection('Questions, Suggestions, or Bugs?', 'If you have any questions, please use the Greasy Fork feedback forums located here. If you\'d like to report a bug or make a suggestion, please create an issue on GitHub here.'); helpPage.bbbTocSection(); @@ -6913,6 +6913,9 @@ function bbbScript() { // Wrapper for injecting the script into the document. var rating = " rating:" + postInfo.rating; var status = " status:" + (flags === "flagged" ? flags + " active" : flags).replace(/\s/g, " status:"); var user = " user:" + postInfo.uploader_name.replace(/\s/g, "_").toLowerCase(); + var userId = " userid:" + postInfo.uploader_id; + var taggerId = " taggerid:" + postInfo.keeper_data.uid; + var source = (postInfo.source ? " source:" + postInfo.source + " source:" + postInfo.normalized_source : ""); var pools = " " + (/pool:\d+/.test(postInfo.pool_string) && !/pool:(collection|series)/.test(postInfo.pool_string) ? postInfo.pool_string + " pool:inactive" : postInfo.pool_string); var parent = (postInfo.parent_id ? " parent:" + postInfo.parent_id : ""); var child = (postInfo.has_children === true ? " child:true" : ""); @@ -6920,7 +6923,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. postSearchInfo = { tags: postInfo.tag_string.bbbSpacePad(), - metatags:(rating + status + user + pools + parent + child + isFav).bbbSpacePad(), + metatags:(rating + status + user + pools + parent + child + isFav + userId + taggerId + source).bbbSpacePad(), score: postInfo.score, favcount: postInfo.fav_count, id: postInfo.id, @@ -7186,9 +7189,9 @@ function bbbScript() { // Wrapper for injecting the script into the document. if (!tagValue) continue; - if (tagValue === "any" && (tagName === "pool" || tagName === "parent" || tagName === "child")) + if (tagValue === "any" && (tagName === "pool" || tagName === "parent" || tagName === "child" || tagName === "source")) mode.push(new RegExp((tagName + ":\\S*").bbbSpacePad())); - else if (tagValue === "none" && (tagName === "pool" || tagName === "parent" || tagName === "child")) { + else if (tagValue === "none" && (tagName === "pool" || tagName === "parent" || tagName === "child" || tagName === "source")) { secondaryMode = (secondaryMode === "includes" ? "excludes" : "includes"); // Flip the include/exclude mode. mode = searchObject[primaryMode][secondaryMode]; @@ -7196,6 +7199,8 @@ function bbbScript() { // Wrapper for injecting the script into the document. } else if (tagValue === "active" && tagName === "pool") mode.push(new RegExp((tagName + ":(collection|series)").bbbSpacePad())); + else if (tagName === "source") // Append a wildcard to the end of "sources starting with the given value" searches. + mode.push(new RegExp((escapeRegEx(searchTerm) + "\\S*").bbbSpacePad())); else // Allow all other values through (ex: parent:# & pool:series). mode.push(searchTerm.bbbSpacePad()); } @@ -10024,7 +10029,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. else { var tagName = tag.split(":", 1)[0].bbbSpaceClean(); - if (tagName === "pool" || tagName === "user" || tagName === "status" || tagName === "rating" || tagName === "parent" || tagName === "child" || tagName === "isfav") + if (tagName === "pool" || tagName === "user" || tagName === "status" || tagName === "rating" || tagName === "parent" || tagName === "child" || tagName === "isfav" || tagName === "userid" || tagName === "taggerid" || tagName === "source") return true; else return false; @@ -10176,6 +10181,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. Danbooru.Autocomplete.static_metatags.parent = ["any", "none"]; Danbooru.Autocomplete.static_metatags.isfav = ["true", "false"]; Danbooru.Autocomplete.static_metatags.pool = ["series", "collection", "any", "none", "active", "inactive"]; + Danbooru.Autocomplete.static_metatags.source = ["any", "none"]; // Counter normal autocomplete getting turned back on after submitting an input. document.body.addEventListener("focus", function(event) { @@ -10197,7 +10203,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. var $fields_multiple = $(searchInputs); var prefixes = "-~"; - var metatags = "status|rating|parent|child|user|pool|group|g|isfav"; + var metatags = "status|rating|parent|child|user|pool|group|g|isfav|userid|taggerid|source|id|score|favcount|height|width"; $fields_multiple.autocomplete({ delay: 100, @@ -10245,6 +10251,15 @@ function bbbScript() { // Wrapper for injecting the script into the document. } switch(metatag) { + case "userid": + case "taggerid": + case "id": + case "score": + case "favcount": + case "height": + case "width": + this.close(); + return; case "status": case "rating": case "parent": @@ -10253,6 +10268,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. case "g": case "isfav": case "pool": + case "source": Danbooru.Autocomplete.static_metatag_source(term, resp, metatag); return; } @@ -10376,4 +10392,4 @@ function bbbInit() { window.setTimeout(function() { document.body.removeChild(script); }, 0); } -bbbInit(); +bbbInit(); \ No newline at end of file From 31f7c7aee89895811894e4abe80b98f90eb9af36 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Thu, 26 Apr 2018 00:48:28 -0400 Subject: [PATCH 06/15] DeviantArt normalized source update * Added the origin-orig subdomain. --- better-better-booru.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index 531adad..faeafcf 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -6431,7 +6431,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. id = parseInt(urlReg[1]).toString(36); url = "http://twitpic.com/" + id; } - else if (!!(urlReg = source.match(/^https?:\/\/(?:fc|th|pre|orig|img|prnt)\d{2}\.deviantart\.net\/.+\/([a-z0-9_]+)_by_([a-z0-9_]+)-d([a-z0-9]+)\./i))) { + else if (!!(urlReg = source.match(/^https?:\/\/(?:(?:fc|th|pre|orig|img|prnt)\d{2}|origin-orig)\.deviantart\.net\/.+\/([a-z0-9_]+)_by_([a-z0-9_]+)-d([a-z0-9]+)\./i))) { title = urlReg[1].replace(/[^A-Za-z0-9]/g, " ").bbbSpaceClean().replace(/[ ]/g, "-"); artist = urlReg[2].replace(/_/g, "-"); id = parseInt(urlReg[3], 36); From 1da7aaca30bfaa4a440f4ec8872af8e979d5d046 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Thu, 26 Apr 2018 21:21:31 -0400 Subject: [PATCH 07/15] Cross-origin URL update * Updated to support server changes on Danbooru. --- better-better-booru.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index faeafcf..4ce2bdf 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -3892,7 +3892,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. var optionItem = optionItems[i]; if (downloadRegex.test(optionItem.textContent)) { - optionItem.innerHTML = 'Download'; + optionItem.innerHTML = 'Download'; break; } } From 19eb64353bafbcc1533f97e84ae32719dc086a10 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Sat, 28 Apr 2018 01:44:44 -0400 Subject: [PATCH 08/15] Favorites update * Removed the fav string information since it is now restricted to moderators and above. --- better-better-booru.user.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index 4ce2bdf..ad7e686 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -1441,7 +1441,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. fav_count: Number(imgContainer.getAttribute("data-fav-count")) || 0, has_children: (imgContainer.getAttribute("data-has-children") === "true"), has_active_children: (postTag === "IMG" || postTag === "CANVAS" ? postEl.getAttribute("data-has-active-children") === "true" : !!target.getElementsByClassName("notice-parent")[0]), - fav_string: getMeta("favorites", docEl), + is_favorited: (imgContainer.getAttribute("data-is-favorited") === "true"), normalized_source: imgContainer.getAttribute("data-normalized-source") || "", parent_id: (imgContainer.getAttribute("data-parent-id") ? Number(imgContainer.getAttribute("data-parent-id")) : null), rating: imgContainer.getAttribute("data-rating") || "", @@ -1528,7 +1528,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. fav_count: Number(post.getAttribute("data-fav-count")) || 0, has_children: (post.getAttribute("data-has-children") === "true"), has_active_children: post.bbbHasClass("post-status-has-children"), // Assumption. Basically a flag for the children class. - fav_string: (post.getAttribute("data-is-favorited") === "true" ? "fav:" + getMeta("current-user-id") : ""), // Faked since thumbnails don't provide the full list of favorites. + is_favorited: (post.getAttribute("data-is-favorited") === "true"), normalized_source: post.getAttribute("data-normalized-source") || "", parent_id: (post.getAttribute("data-parent-id") ? Number(post.getAttribute("data-parent-id")) : null), rating: post.getAttribute("data-rating") || "", @@ -6260,7 +6260,6 @@ function bbbScript() { // Wrapper for injecting the script into the document. // Missing API/data fixes. postInfo.has_sound = /(?:^|\s)(?:video|flash)_with_sound(?:$|\s)/.test(postInfo.tag_string); postInfo.flags = postFlags(postInfo); - postInfo.is_favorited = new RegExp("(?:^|\\s)fav:" + getMeta("current-user-id") + "(?:$|\\s)").test(postInfo.fav_string); postInfo.normalized_source = postInfo.normalized_source || normalizedSource(postInfo); postInfo.keeper_data = postInfo.keeper_data || {uid: postInfo.uploader_id}; From 65df2e39b8351aa8b5b667c9f135642e5ae80d1c Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Sun, 29 Apr 2018 12:38:28 -0400 Subject: [PATCH 09/15] Uploader name updates * Adjusted to make consistency easier to maintain across the script. * Removed the username area from the parseComments function since it would only be needed by users below the moderator level. --- better-better-booru.user.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index ad7e686..e61825a 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -1020,7 +1020,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. // Create the new post. var childSpan = document.createElement("span"); - childSpan.innerHTML = ''; + childSpan.innerHTML = ''; // Prepare thumbnails. prepThumbnails(childSpan); @@ -4810,7 +4810,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. function createThumbHTML(postInfo, query) { // Create a thumbnail HTML string. - return ''; + return ''; } function createThumb(postInfo, query) { @@ -6262,6 +6262,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. postInfo.flags = postFlags(postInfo); postInfo.normalized_source = postInfo.normalized_source || normalizedSource(postInfo); postInfo.keeper_data = postInfo.keeper_data || {uid: postInfo.uploader_id}; + postInfo.uploader_name = (isModLevel() ? postInfo.uploader_name : ""); // Custom BBB properties. postInfo.file_url_desc = postFileUrlDesc(postInfo); @@ -6911,7 +6912,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. var flags = postInfo.flags || "active"; var rating = " rating:" + postInfo.rating; var status = " status:" + (flags === "flagged" ? flags + " active" : flags).replace(/\s/g, " status:"); - var user = " user:" + postInfo.uploader_name.replace(/\s/g, "_").toLowerCase(); + var user = (postInfo.uploader_name ? " user:" + postInfo.uploader_name.replace(/\s/g, "_").toLowerCase() : ""); var userId = " userid:" + postInfo.uploader_id; var taggerId = " taggerid:" + postInfo.keeper_data.uid; var source = (postInfo.source ? " source:" + postInfo.source + " source:" + postInfo.normalized_source : ""); From 40bd934d853d5fd8b95dda460076a234873dbb59 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Sun, 29 Apr 2018 12:41:52 -0400 Subject: [PATCH 10/15] Comments date fix * Fixed the formatting of the date information in the parseComments function. --- better-better-booru.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index e61825a..7c65522 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -1020,7 +1020,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. // Create the new post. var childSpan = document.createElement("span"); - childSpan.innerHTML = ''; + childSpan.innerHTML = ''; // Prepare thumbnails. prepThumbnails(childSpan); From 0e11bed4ff65c0b2b0cb4caacdb9eb15a028482c Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Sun, 29 Apr 2018 12:47:05 -0400 Subject: [PATCH 11/15] Removed image titles * Removed the image titles since they've been replaced with a javascript tip. --- better-better-booru.user.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index 7c65522..e86da81 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -4712,11 +4712,6 @@ function bbbScript() { // Wrapper for injecting the script into the document. var postInfo = post.bbbInfo(); var link = img.parentNode; - var tagsStr = postInfo.tag_string || ""; - var userStr = (postInfo.uploader_name ? " user:" + postInfo.uploader_name : ""); - var ratingStr = (postInfo.rating ? " rating:" + postInfo.rating : ""); - var scoreStr = (postInfo.score ? " score:" + postInfo.score : ""); - var title = tagsStr + userStr + ratingStr + scoreStr; var secondary = []; var secondaryLength = 0; var styleList = bbb.custom_tag.style_list; @@ -4726,9 +4721,6 @@ function bbbScript() { // Wrapper for injecting the script into the document. if (link.bbbHasClass("bbb-thumb-link")) continue; - // Create title. - img.title = title; - // Add custom data attributes. post.bbbInfo("file-url-desc", postInfo.file_url_desc); @@ -6557,7 +6549,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. var thumb = document.createElement("a"); thumb.href = "/posts/" + postInfo.id; - thumb.innerHTML = '' + postInfo.md5 + ''; + thumb.innerHTML = '' + postInfo.md5 + ''; if (before) preview.insertBefore(thumb, before); From 7940c307dd52384e03f475be22fe1d299773fe3b Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Sun, 29 Apr 2018 15:40:16 -0400 Subject: [PATCH 12/15] Approverid metatag * Added a metatag for "approverid". --- better-better-booru.user.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index e86da81..c8309fa 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -2031,7 +2031,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. helpPage.className = "bbb-page"; scrollDiv.appendChild(helpPage); - helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
  • tag1 - Match posts with tag1.
  • tag1 tag2 - Match posts with tag1 AND tag2.
  • -tag1 - Match posts without tag1.
  • tag1 -tag2 - Match posts with tag1 AND without tag2.
  • ~tag1 ~tag2 - Match posts with tag1 OR tag2.
  • ~tag1 ~-tag2 - Match posts with tag1 OR without tag2.
  • tag1 ~tag2 ~tag3 - Match posts with tag1 AND either tag2 OR tag3.

Wildcards can be used with any of the above methods:
  • ~tag1* ~-*tag2 - Match posts with tags starting with tag1 or posts without tags ending with tag2.

Multiple match rules can be specified by using commas or separate lines when possible:
  • tag1 tag2, tag3 tag4 - Match posts with tag1 AND tag2 or posts with tag3 AND tag4.
  • tag1 ~tag2 ~tag3, tag4 - Match posts with tag1 AND either tag2 OR tag3 or posts with tag4.

Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
  • ( ~tag1 ~tag2 ) ( ~tag3 ~tag3 ) - Match posts with either tag1 OR tag2 AND either tag3 OR tag4.
  • tag1 ( tag2, tag3 tag4 ) - Match posts with tag1 AND tag2 or posts with tag1 AND tag3 AND tag4.
  • tag1 -( tag2 tag3 ) - Match posts with tag1 AND without tag2 AND tag3.
  • tag1 ~tag2 ~( tag3 tag4 ) - Match posts with tag1 and either tag2 OR tag3 AND tag4.

The following metatags are supported:
  • rating:safe - Match posts rated safe. Accepted values include safe, explicit, and questionable.
  • status:pending - Match pending posts. Accepted values include active, pending, flagged, banned, and deleted. Note that flagged posts also count as active posts.
  • user:albert - Match posts made by the user Albert. Note that this tag will only work if you have a moderator level account or higher.
  • userid:1 - Match posts made by the user with an ID number of 1.
  • taggerid:1 - Match posts mostly tagged by the user with an ID number of 1.
  • source:http://www.4chan.org/ - Match posts with a source starting with http://www.4chan.org/. Accepted values include "any" for all posts with sources, "none" for all posts without sources, wildcard searches such as "*pixiv.net*" for posts with sources that contain pixiv.net, and non-wildcard searches that start matching at the beginning of a source.
  • isfav:true - Match posts favorited under your current account. Accepted values include true and false.
  • group:hidden or g:hidden - Match posts that match the tags in your group named \"hidden\".
  • pool:1 - Match posts that are in the pool with an ID number of 1. Accepted values include pool ID numbers, "series" for posts in series category pools, "collection" for posts in collection category pools, "any" for posts in any pool, "none" for posts not in a pool, "active" for posts in an active (not deleted) pool, and "inactive" for posts only in an inactive (deleted) pool.
  • parent:1 - Match posts that have the post with an ID number of 1 as a parent. Accepted values include post ID numbers, "any" for any posts with a parent, and "none" for posts without a parent.
  • child:any - Match any posts that have children. Accepted values include "any" for any posts with children and "none" for posts without children.
  • id:1 - Match posts with an ID number of 1.
  • score:1 - Match posts with a score of 1.
  • favcount:1 - Match posts with a favorite count of 1.
  • height:1 - Match posts with a height of 1.
  • width:1 - Match posts with a width of 1.

The id, score, favcount, width, and height metatags can also use number ranges for matching:
  • score:<5 - Match posts with a score less than 5.
  • score:>5 - Match posts with a score greater than 5.
  • score:<=5 or score:..5 - Match posts with a score equal to OR less than 5.
  • score:>=5 or score:5.. - Match posts with a score equal to OR greater than 5.
  • score:1..5 - Match posts with a score equal to OR greater than 1 AND equal to OR less than 5.
'); + helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
  • tag1 - Match posts with tag1.
  • tag1 tag2 - Match posts with tag1 AND tag2.
  • -tag1 - Match posts without tag1.
  • tag1 -tag2 - Match posts with tag1 AND without tag2.
  • ~tag1 ~tag2 - Match posts with tag1 OR tag2.
  • ~tag1 ~-tag2 - Match posts with tag1 OR without tag2.
  • tag1 ~tag2 ~tag3 - Match posts with tag1 AND either tag2 OR tag3.

Wildcards can be used with any of the above methods:
  • ~tag1* ~-*tag2 - Match posts with tags starting with tag1 or posts without tags ending with tag2.

Multiple match rules can be specified by using commas or separate lines when possible:
  • tag1 tag2, tag3 tag4 - Match posts with tag1 AND tag2 or posts with tag3 AND tag4.
  • tag1 ~tag2 ~tag3, tag4 - Match posts with tag1 AND either tag2 OR tag3 or posts with tag4.

Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
  • ( ~tag1 ~tag2 ) ( ~tag3 ~tag3 ) - Match posts with either tag1 OR tag2 AND either tag3 OR tag4.
  • tag1 ( tag2, tag3 tag4 ) - Match posts with tag1 AND tag2 or posts with tag1 AND tag3 AND tag4.
  • tag1 -( tag2 tag3 ) - Match posts with tag1 AND without tag2 AND tag3.
  • tag1 ~tag2 ~( tag3 tag4 ) - Match posts with tag1 and either tag2 OR tag3 AND tag4.

The following metatags are supported:
  • rating:safe - Match posts rated safe. Accepted values include safe, explicit, and questionable.
  • status:pending - Match pending posts. Accepted values include active, pending, flagged, banned, and deleted. Note that flagged posts also count as active posts.
  • user:albert - Match posts made by the user Albert. Note that this tag will only work if you have a moderator level account or higher.
  • userid:1 - Match posts made by the user with an ID number of 1.
  • taggerid:1 - Match posts mostly tagged by the user with an ID number of 1.
  • approverid:1 - Match posts approved by the user with an ID number of 1.
  • source:http://www.4chan.org/ - Match posts with a source starting with http://www.4chan.org/. Accepted values include "any" for all posts with sources, "none" for all posts without sources, wildcard searches such as "*pixiv.net*" for posts with sources that contain pixiv.net, and non-wildcard searches that start matching at the beginning of a source.
  • isfav:true - Match posts favorited under your current account. Accepted values include true and false.
  • group:hidden or g:hidden - Match posts that match the tags in your group named \"hidden\".
  • pool:1 - Match posts that are in the pool with an ID number of 1. Accepted values include pool ID numbers, "series" for posts in series category pools, "collection" for posts in collection category pools, "any" for posts in any pool, "none" for posts not in a pool, "active" for posts in an active (not deleted) pool, and "inactive" for posts only in an inactive (deleted) pool.
  • parent:1 - Match posts that have the post with an ID number of 1 as a parent. Accepted values include post ID numbers, "any" for any posts with a parent, and "none" for posts without a parent.
  • child:any - Match any posts that have children. Accepted values include "any" for any posts with children and "none" for posts without children.
  • id:1 - Match posts with an ID number of 1.
  • score:1 - Match posts with a score of 1.
  • favcount:1 - Match posts with a favorite count of 1.
  • height:1 - Match posts with a height of 1.
  • width:1 - Match posts with a width of 1.

The id, score, favcount, width, and height metatags can also use number ranges for matching:
  • score:<5 - Match posts with a score less than 5.
  • score:>5 - Match posts with a score greater than 5.
  • score:<=5 or score:..5 - Match posts with a score equal to OR less than 5.
  • score:>=5 or score:5.. - Match posts with a score equal to OR greater than 5.
  • score:1..5 - Match posts with a score equal to OR greater than 1 AND equal to OR less than 5.
'); helpPage.bbbTextSection('Hotkeys', 'Posts
  • B - Open BBB menu.
  • 1 - Resize to window.
  • 2 - Resize to window width.
  • 3 - Resize to window height.
  • 4 - Reset/remove resizing.
Note: Numbers refer to the main typing keypad and not the numeric keypad.

General
  • B - Open BBB menu.
  • E - Toggle endless pages.
  • F - Open quick search.
  • Shift + F - Reset quick search.
'); helpPage.bbbTextSection('Questions, Suggestions, or Bugs?', 'If you have any questions, please use the Greasy Fork feedback forums located here. If you\'d like to report a bug or make a suggestion, please create an issue on GitHub here.'); helpPage.bbbTocSection(); @@ -6907,6 +6907,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. var user = (postInfo.uploader_name ? " user:" + postInfo.uploader_name.replace(/\s/g, "_").toLowerCase() : ""); var userId = " userid:" + postInfo.uploader_id; var taggerId = " taggerid:" + postInfo.keeper_data.uid; + var approverId = (postInfo.approver_id ? " approverid:" + postInfo.approver_id : ""); var source = (postInfo.source ? " source:" + postInfo.source + " source:" + postInfo.normalized_source : ""); var pools = " " + (/pool:\d+/.test(postInfo.pool_string) && !/pool:(collection|series)/.test(postInfo.pool_string) ? postInfo.pool_string + " pool:inactive" : postInfo.pool_string); var parent = (postInfo.parent_id ? " parent:" + postInfo.parent_id : ""); @@ -6915,7 +6916,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. postSearchInfo = { tags: postInfo.tag_string.bbbSpacePad(), - metatags:(rating + status + user + pools + parent + child + isFav + userId + taggerId + source).bbbSpacePad(), + metatags:(rating + status + user + pools + parent + child + isFav + userId + taggerId + source + approverId).bbbSpacePad(), score: postInfo.score, favcount: postInfo.fav_count, id: postInfo.id, @@ -10021,7 +10022,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. else { var tagName = tag.split(":", 1)[0].bbbSpaceClean(); - if (tagName === "pool" || tagName === "user" || tagName === "status" || tagName === "rating" || tagName === "parent" || tagName === "child" || tagName === "isfav" || tagName === "userid" || tagName === "taggerid" || tagName === "source") + if (tagName === "pool" || tagName === "user" || tagName === "status" || tagName === "rating" || tagName === "parent" || tagName === "child" || tagName === "isfav" || tagName === "userid" || tagName === "taggerid" || tagName === "source" || tagName === "approverid") return true; else return false; @@ -10195,7 +10196,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. var $fields_multiple = $(searchInputs); var prefixes = "-~"; - var metatags = "status|rating|parent|child|user|pool|group|g|isfav|userid|taggerid|source|id|score|favcount|height|width"; + var metatags = "status|rating|parent|child|user|pool|group|g|isfav|userid|taggerid|approverid|source|id|score|favcount|height|width"; $fields_multiple.autocomplete({ delay: 100, @@ -10245,6 +10246,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. switch(metatag) { case "userid": case "taggerid": + case "approverid": case "id": case "score": case "favcount": From a9ed0a1135732fb5f75b0fe3da8753b369875be5 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Tue, 1 May 2018 21:18:46 -0400 Subject: [PATCH 13/15] Updated thumb image titles * Added "qtip" tooltip compatible title information to thumbnails. * Moved the thumbInfo function to the thumbnail functions area. --- better-better-booru.user.js | 117 +++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index c8309fa..c0f08f4 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -4712,6 +4712,12 @@ function bbbScript() { // Wrapper for injecting the script into the document. var postInfo = post.bbbInfo(); var link = img.parentNode; + var tagsStr = postInfo.tag_string || ""; + var userStr = (postInfo.uploader_name ? " user:" + postInfo.uploader_name : ""); + var ratingStr = (postInfo.rating ? " rating:" + postInfo.rating : ""); + var scoreStr = (typeof(postInfo.score) === "number" ? " score:" + postInfo.score : ""); + var titleStr = tagsStr + userStr + ratingStr + scoreStr; + var titleAttr = (getMeta("disable-post-tooltips") === "false" ? "oldtitle" : "title"); var secondary = []; var secondaryLength = 0; var styleList = bbb.custom_tag.style_list; @@ -4721,6 +4727,9 @@ function bbbScript() { // Wrapper for injecting the script into the document. if (link.bbbHasClass("bbb-thumb-link")) continue; + // Create title information. + img.setAttribute(titleAttr, titleStr); + // Add custom data attributes. post.bbbInfo("file-url-desc", postInfo.file_url_desc); @@ -4962,6 +4971,60 @@ function bbbScript() { // Wrapper for injecting the script into the document. return idCache.join(" "); } + function thumbInfo(target) { + // Add score, favorite count, and rating info to thumbnails. + var posts = getPosts(target); + + if (thumb_info === "disabled") + return; + + for (var i = 0, il = posts.length; i < il; i++) { + var post = posts[i]; + + // Skip thumbnails that already have the info added. + if (post.getElementsByClassName("bbb-thumb-info")[0]) + continue; + + var postInfo = post.bbbInfo(); + var tooShort = (150 / postInfo.image_width * postInfo.image_height < 30); // Short thumbnails will need the info div position adjusted. + + if (gLoc === "comments") { // Add favorites info to the existing info in the comments listing. + var firstInfo = post.getElementsByClassName("info")[0]; + var infoParent = (firstInfo ? firstInfo.parentNode : undefined); + + if (infoParent) { + var favSpan = document.createElement("span"); + favSpan.className = "info bbb-thumb-info"; + favSpan.innerHTML = 'Favorites ' + postInfo.fav_count; + infoParent.appendChild(favSpan); + } + } + else { // Add extra information inside of the thumbnail's parent element. + var thumbImg = post.getElementsByTagName("img")[0]; + + // Don't add the info if there isn't a thumbnail. + if (!thumbImg) + continue; + + var thumbEl = post.getElementsByClassName("preview")[0] || post; + thumbEl.bbbAddClass("bbb-thumb-info-parent"); + + var postLink = thumbEl.getElementsByTagName("a")[0]; + var before = (postLink ? postLink.nextElementSibling : undefined); + var scoreStr = (postInfo.score < 0 ? '' + postInfo.score + '' : postInfo.score); + + var infoDiv = document.createElement("div"); + infoDiv.className = "bbb-thumb-info" + (tooShort ? " bbb-thumb-info-short" : ""); + infoDiv.innerHTML = "★" + scoreStr + "   ♥" + postInfo.fav_count + (location.host.indexOf("safebooru") < 0 ? "    " + postInfo.rating.toUpperCase() : ""); + + if (before) + thumbEl.insertBefore(infoDiv, before); + else + thumbEl.appendChild(infoDiv); + } + } + } + function postDDL(target) { // Add direct downloads to thumbnails. if (!direct_downloads || (gLoc !== "search" && gLoc !== "pool" && gLoc !== "popular" && gLoc !== "popular_view" && gLoc !== "favorites" && gLoc !== "favorite_group")) @@ -8372,60 +8435,6 @@ function bbbScript() { // Wrapper for injecting the script into the document. } } - function thumbInfo(target) { - // Add score, favorite count, and rating info to thumbnails. - var posts = getPosts(target); - - if (thumb_info === "disabled") - return; - - for (var i = 0, il = posts.length; i < il; i++) { - var post = posts[i]; - - // Skip thumbnails that already have the info added. - if (post.getElementsByClassName("bbb-thumb-info")[0]) - continue; - - var postInfo = post.bbbInfo(); - var tooShort = (150 / postInfo.image_width * postInfo.image_height < 30); // Short thumbnails will need the info div position adjusted. - - if (gLoc === "comments") { // Add favorites info to the existing info in the comments listing. - var firstInfo = post.getElementsByClassName("info")[0]; - var infoParent = (firstInfo ? firstInfo.parentNode : undefined); - - if (infoParent) { - var favSpan = document.createElement("span"); - favSpan.className = "info bbb-thumb-info"; - favSpan.innerHTML = 'Favorites ' + postInfo.fav_count; - infoParent.appendChild(favSpan); - } - } - else { // Add extra information inside of the thumbnail's parent element. - var thumbImg = post.getElementsByTagName("img")[0]; - - // Don't add the info if there isn't a thumbnail. - if (!thumbImg) - continue; - - var thumbEl = post.getElementsByClassName("preview")[0] || post; - thumbEl.bbbAddClass("bbb-thumb-info-parent"); - - var postLink = thumbEl.getElementsByTagName("a")[0]; - var before = (postLink ? postLink.nextElementSibling : undefined); - var scoreStr = (postInfo.score < 0 ? '' + postInfo.score + '' : postInfo.score); - - var infoDiv = document.createElement("div"); - infoDiv.className = "bbb-thumb-info" + (tooShort ? " bbb-thumb-info-short" : ""); - infoDiv.innerHTML = "★" + scoreStr + "   ♥" + postInfo.fav_count + (location.host.indexOf("safebooru") < 0 ? "    " + postInfo.rating.toUpperCase() : ""); - - if (before) - thumbEl.insertBefore(infoDiv, before); - else - thumbEl.appendChild(infoDiv); - } - } - } - function postLinkNewWindow() { // Make thumbnail clicks open in a new tab/window. if (post_link_new_window === "disabled" || (gLoc !== "search" && gLoc !== "pool" && gLoc !== "favorites" && gLoc !== "popular" && gLoc !== "popular_view" && gLoc !== "favorite_group")) From 2e2ce8e737073b79530e0c87343f7dcf0a46603b Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Tue, 1 May 2018 21:56:41 -0400 Subject: [PATCH 14/15] Approverid metatag "any" & "none" support * Updated the approverid metatag to support the "any" and "none" values. --- better-better-booru.user.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index c0f08f4..13bd67f 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -2031,7 +2031,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. helpPage.className = "bbb-page"; scrollDiv.appendChild(helpPage); - helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
  • tag1 - Match posts with tag1.
  • tag1 tag2 - Match posts with tag1 AND tag2.
  • -tag1 - Match posts without tag1.
  • tag1 -tag2 - Match posts with tag1 AND without tag2.
  • ~tag1 ~tag2 - Match posts with tag1 OR tag2.
  • ~tag1 ~-tag2 - Match posts with tag1 OR without tag2.
  • tag1 ~tag2 ~tag3 - Match posts with tag1 AND either tag2 OR tag3.

Wildcards can be used with any of the above methods:
  • ~tag1* ~-*tag2 - Match posts with tags starting with tag1 or posts without tags ending with tag2.

Multiple match rules can be specified by using commas or separate lines when possible:
  • tag1 tag2, tag3 tag4 - Match posts with tag1 AND tag2 or posts with tag3 AND tag4.
  • tag1 ~tag2 ~tag3, tag4 - Match posts with tag1 AND either tag2 OR tag3 or posts with tag4.

Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
  • ( ~tag1 ~tag2 ) ( ~tag3 ~tag3 ) - Match posts with either tag1 OR tag2 AND either tag3 OR tag4.
  • tag1 ( tag2, tag3 tag4 ) - Match posts with tag1 AND tag2 or posts with tag1 AND tag3 AND tag4.
  • tag1 -( tag2 tag3 ) - Match posts with tag1 AND without tag2 AND tag3.
  • tag1 ~tag2 ~( tag3 tag4 ) - Match posts with tag1 and either tag2 OR tag3 AND tag4.

The following metatags are supported:
  • rating:safe - Match posts rated safe. Accepted values include safe, explicit, and questionable.
  • status:pending - Match pending posts. Accepted values include active, pending, flagged, banned, and deleted. Note that flagged posts also count as active posts.
  • user:albert - Match posts made by the user Albert. Note that this tag will only work if you have a moderator level account or higher.
  • userid:1 - Match posts made by the user with an ID number of 1.
  • taggerid:1 - Match posts mostly tagged by the user with an ID number of 1.
  • approverid:1 - Match posts approved by the user with an ID number of 1.
  • source:http://www.4chan.org/ - Match posts with a source starting with http://www.4chan.org/. Accepted values include "any" for all posts with sources, "none" for all posts without sources, wildcard searches such as "*pixiv.net*" for posts with sources that contain pixiv.net, and non-wildcard searches that start matching at the beginning of a source.
  • isfav:true - Match posts favorited under your current account. Accepted values include true and false.
  • group:hidden or g:hidden - Match posts that match the tags in your group named \"hidden\".
  • pool:1 - Match posts that are in the pool with an ID number of 1. Accepted values include pool ID numbers, "series" for posts in series category pools, "collection" for posts in collection category pools, "any" for posts in any pool, "none" for posts not in a pool, "active" for posts in an active (not deleted) pool, and "inactive" for posts only in an inactive (deleted) pool.
  • parent:1 - Match posts that have the post with an ID number of 1 as a parent. Accepted values include post ID numbers, "any" for any posts with a parent, and "none" for posts without a parent.
  • child:any - Match any posts that have children. Accepted values include "any" for any posts with children and "none" for posts without children.
  • id:1 - Match posts with an ID number of 1.
  • score:1 - Match posts with a score of 1.
  • favcount:1 - Match posts with a favorite count of 1.
  • height:1 - Match posts with a height of 1.
  • width:1 - Match posts with a width of 1.

The id, score, favcount, width, and height metatags can also use number ranges for matching:
  • score:<5 - Match posts with a score less than 5.
  • score:>5 - Match posts with a score greater than 5.
  • score:<=5 or score:..5 - Match posts with a score equal to OR less than 5.
  • score:>=5 or score:5.. - Match posts with a score equal to OR greater than 5.
  • score:1..5 - Match posts with a score equal to OR greater than 1 AND equal to OR less than 5.
'); + helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
  • tag1 - Match posts with tag1.
  • tag1 tag2 - Match posts with tag1 AND tag2.
  • -tag1 - Match posts without tag1.
  • tag1 -tag2 - Match posts with tag1 AND without tag2.
  • ~tag1 ~tag2 - Match posts with tag1 OR tag2.
  • ~tag1 ~-tag2 - Match posts with tag1 OR without tag2.
  • tag1 ~tag2 ~tag3 - Match posts with tag1 AND either tag2 OR tag3.

Wildcards can be used with any of the above methods:
  • ~tag1* ~-*tag2 - Match posts with tags starting with tag1 or posts without tags ending with tag2.

Multiple match rules can be specified by using commas or separate lines when possible:
  • tag1 tag2, tag3 tag4 - Match posts with tag1 AND tag2 or posts with tag3 AND tag4.
  • tag1 ~tag2 ~tag3, tag4 - Match posts with tag1 AND either tag2 OR tag3 or posts with tag4.

Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
  • ( ~tag1 ~tag2 ) ( ~tag3 ~tag3 ) - Match posts with either tag1 OR tag2 AND either tag3 OR tag4.
  • tag1 ( tag2, tag3 tag4 ) - Match posts with tag1 AND tag2 or posts with tag1 AND tag3 AND tag4.
  • tag1 -( tag2 tag3 ) - Match posts with tag1 AND without tag2 AND tag3.
  • tag1 ~tag2 ~( tag3 tag4 ) - Match posts with tag1 and either tag2 OR tag3 AND tag4.

The following metatags are supported:
  • rating:safe - Match posts rated safe. Accepted values include safe, explicit, and questionable.
  • status:pending - Match pending posts. Accepted values include active, pending, flagged, banned, and deleted. Note that flagged posts also count as active posts.
  • user:albert - Match posts made by the user Albert. Note that this tag will only work if you have a moderator level account or higher.
  • userid:1 - Match posts made by the user with an ID number of 1.
  • taggerid:1 - Match posts mostly tagged by the user with an ID number of 1.
  • approverid:1 - Match posts approved by the user with an ID number of 1. Accepted values include numbers, "any" for all posts with an approver, and "none" for posts without an approver.
  • source:http://www.4chan.org/ - Match posts with a source starting with http://www.4chan.org/. Accepted values include "any" for all posts with sources, "none" for all posts without sources, wildcard searches such as "*pixiv.net*" for posts with sources that contain pixiv.net, and non-wildcard searches that start matching at the beginning of a source.
  • isfav:true - Match posts favorited under your current account. Accepted values include true and false.
  • group:hidden or g:hidden - Match posts that match the tags in your group named \"hidden\".
  • pool:1 - Match posts that are in the pool with an ID number of 1. Accepted values include pool ID numbers, "series" for posts in series category pools, "collection" for posts in collection category pools, "any" for posts in any pool, "none" for posts not in a pool, "active" for posts in an active (not deleted) pool, and "inactive" for posts only in an inactive (deleted) pool.
  • parent:1 - Match posts that have the post with an ID number of 1 as a parent. Accepted values include post ID numbers, "any" for any posts with a parent, and "none" for posts without a parent.
  • child:any - Match any posts that have children. Accepted values include "any" for any posts with children and "none" for posts without children.
  • id:1 - Match posts with an ID number of 1.
  • score:1 - Match posts with a score of 1.
  • favcount:1 - Match posts with a favorite count of 1.
  • height:1 - Match posts with a height of 1.
  • width:1 - Match posts with a width of 1.

The id, score, favcount, width, and height metatags can also use number ranges for matching:
  • score:<5 - Match posts with a score less than 5.
  • score:>5 - Match posts with a score greater than 5.
  • score:<=5 or score:..5 - Match posts with a score equal to OR less than 5.
  • score:>=5 or score:5.. - Match posts with a score equal to OR greater than 5.
  • score:1..5 - Match posts with a score equal to OR greater than 1 AND equal to OR less than 5.
'); helpPage.bbbTextSection('Hotkeys', 'Posts
  • B - Open BBB menu.
  • 1 - Resize to window.
  • 2 - Resize to window width.
  • 3 - Resize to window height.
  • 4 - Reset/remove resizing.
Note: Numbers refer to the main typing keypad and not the numeric keypad.

General
  • B - Open BBB menu.
  • E - Toggle endless pages.
  • F - Open quick search.
  • Shift + F - Reset quick search.
'); helpPage.bbbTextSection('Questions, Suggestions, or Bugs?', 'If you have any questions, please use the Greasy Fork feedback forums located here. If you\'d like to report a bug or make a suggestion, please create an issue on GitHub here.'); helpPage.bbbTocSection(); @@ -7245,9 +7245,9 @@ function bbbScript() { // Wrapper for injecting the script into the document. if (!tagValue) continue; - if (tagValue === "any" && (tagName === "pool" || tagName === "parent" || tagName === "child" || tagName === "source")) + if (tagValue === "any" && (tagName === "pool" || tagName === "parent" || tagName === "child" || tagName === "source" || tagName === "approverid")) mode.push(new RegExp((tagName + ":\\S*").bbbSpacePad())); - else if (tagValue === "none" && (tagName === "pool" || tagName === "parent" || tagName === "child" || tagName === "source")) { + else if (tagValue === "none" && (tagName === "pool" || tagName === "parent" || tagName === "child" || tagName === "source" || tagName === "approverid")) { secondaryMode = (secondaryMode === "includes" ? "excludes" : "includes"); // Flip the include/exclude mode. mode = searchObject[primaryMode][secondaryMode]; @@ -10184,6 +10184,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. Danbooru.Autocomplete.static_metatags.isfav = ["true", "false"]; Danbooru.Autocomplete.static_metatags.pool = ["series", "collection", "any", "none", "active", "inactive"]; Danbooru.Autocomplete.static_metatags.source = ["any", "none"]; + Danbooru.Autocomplete.static_metatags.approverid = ["any", "none"]; // Counter normal autocomplete getting turned back on after submitting an input. document.body.addEventListener("focus", function(event) { @@ -10255,7 +10256,6 @@ function bbbScript() { // Wrapper for injecting the script into the document. switch(metatag) { case "userid": case "taggerid": - case "approverid": case "id": case "score": case "favcount": @@ -10272,6 +10272,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. case "isfav": case "pool": case "source": + case "approverid": Danbooru.Autocomplete.static_metatag_source(term, resp, metatag); return; } From 6dc81f6cc8106ddac5c46b6009262b3a6de31cc2 Mon Sep 17 00:00:00 2001 From: Moebius-Strip Date: Tue, 1 May 2018 22:09:32 -0400 Subject: [PATCH 15/15] Version 8.2 --- better-better-booru.user.js | 5 +++-- changelog.md | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/better-better-booru.user.js b/better-better-booru.user.js index 13bd67f..57f6134 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -3,7 +3,7 @@ // @namespace https://greasyfork.org/scripts/3575-better-better-booru // @author otani, modified by Jawertae, A Pseudonymous Coder & Moebius Strip. // @description Several changes to make Danbooru much better. -// @version 8.1 +// @version 8.2 // @updateURL https://greasyfork.org/scripts/3575-better-better-booru/code/better_better_booru.meta.js // @downloadURL https://greasyfork.org/scripts/3575-better-better-booru/code/better_better_booru.user.js // @match *://*.donmai.us/* @@ -340,7 +340,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. swapped: false // Whether the post content has been changed between the original and sample versions. }, options: { // Setting options and data. - bbb_version: "8.1", + bbb_version: "8.2", add_popular_link: newOption("checkbox", false, "Add Popular Link", "Add a link to the popular listing to the \"posts\" submenu"), add_random_post_link: newOption("checkbox", false, "Add Random Link", "Add a link to a random post to the post sidebar options menu."), alternate_image_swap: newOption("checkbox", false, "Alternate Image Swap", "Switch between the sample and original image by clicking the image. NoteNotes can be toggled by using the link in the sidebar options section."), @@ -3387,6 +3387,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. case "8.0": case "8.0.1": case "8.0.2": + case "8.1": break; } diff --git a/changelog.md b/changelog.md index 865d3f5..a2cd60a 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ Changelog ---------- +* Version 8.2: + * Added "userid", "taggerid", "approverid", and "source" to the script metatags. + * Updated the "user" metatag help text to clarify it can only be used by users at or above the moderator level. + * Updated thumbnail image titles to support Danbooru's new tooltips. + * Updated download links to support server changes on Danbooru. + * Fixed autocomplete behavior for some metatags. + * Fixed the backup page option to make it compatible with browser security changes for data URLs. + * Fixed the date information for hidden posts in the comments section. * Version 8.1: * Added a "hide favorite button" layout option for hiding the button underneath post content. * Added an "add random link" layout option for placing a link to a random post in the sidebar options menu of posts.