devunt / make-gis-great-again

This web extension adds back "View Image" button to Google Image Search results.
MIT License
768 stars 55 forks source link

View image button leads to encrypted-tbn0.gstatic.com #97

Open psonnosp opened 4 years ago

psonnosp commented 4 years ago

This doesn't happen on every image but on a lot of them. Instead of the image URL, in this case https://metro.co.uk/wp-content/uploads/2019/08/PRI_79508760.jpg?quality=90&strip=all, the 'View Image' button links to a tiny version of the image located at encrypted-tbn0.gstatic.com and in this case https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcRsvV0GQHomPdrBiS0zUTbv5j8v-BmZlae56Q&usqp=CAU And sometimes you just get a tiny data:image/jpeg;base64 instead.

Can this be fixed?

Procyon-b commented 4 years ago

That's something I noticed when the current layout appeared. When you open a new tab with a link that shows the page with the side panel visible, the image's url in the panel is always the "gstatic" copy. There is nothing that can be done about it. The real url is not part of the code of the page at that point (IIRC). If you want the real image, the solution is to use the right and left arrows on the image in the side panel. Click right to display the next image, and then left to go back to the desired image. The url will be fixed.

Edit Upon verification, in this particular example, the image in the side panel is the full-size image. But It's not always the case. Very big images are not loaded in the side panel. I'll have to test to find what is actually happening in that situation, but I remember that it was a problem when I updated the script. I even mentionned the problem in a comment.

psonnosp commented 4 years ago

Thanks for the work around, better than nothing :)

Procyon-b commented 4 years ago

I've made a comment yesterday, but apparently forgot to hit "comment". So here it is...

After more testing it appears that the "gstatic" version of the image is used all the time when opening the side panel. Google must have modified something recently. I'll try to fix this as soon as possible.

Procyon-b commented 4 years ago

@psonnosp can you try this version?

In TM, create a new script and paste this code. Disable the normal script, and enable this one ("BETA" is in its name). This version should reduce the "bad" images ("data:" and "gstatic" URLs) occurences as much as possible.

// ==UserScript==
// @name            Google Search "View Image" Button BETA
// @name:ru         Google Search кнопка "Показать в полном размере"
// @name:sl         Gumb "Ogled slike" na Google Slikah
// @name:uk         Google Search кнопка "Показати зображення"
// @name:lt         Google paieškos mygtukas "Rodyti vaizdą"
// @name:pl         Przycisk "Pokaż obraz" w wyszukiwarce obrazów Google
// @name:ja         Google 検索「画像を表示」ボタン
// @name:ko         Google 검색 ‘이미지 보기’ 버튼
// @name:nl         Google zoeken "Afbeelding bekijken" knop
// @name:sk         Tlačidlo "Zobraziť obrázok" pre Google Search
// @name:tr         Google Görseller "Resmi Görüntüle" butonu
// @namespace       https://github.com/devunt/make-gis-great-again
// @icon            https://raw.githubusercontent.com/devunt/make-gis-great-again/master/icons/icon.png
// @version         1.5.0.13
// @description     This userscript adds "View Image" button to Google Image Search results.
// @description:ru  Этот скрипт добавляет кнопку "Показать в полном размере" к результатам Google Image Search.
// @description:sl  Ponovno prikaže gumb "Ogled slike" na Google Slikah.
// @description:uk  Цей скрипт додає кнопку "Показати зображення" до результатів Google Image Search.
// @description:lt  Šis vartotojo skriptas prideda mygtuką "Rodyti vaizdą" į Google vaizdo paieškos rezultatus.
// @description:pl  Ten skrypt przywraca przycisk "Pokaż obraz" do wyszukiwarki obrazów Google.
// @description:ja  この UserScript は Google 画像検索結果に「画像を表示」ボタンを追加します。
// @description:ko  이 유저스크립트는 Google 이미지 검색 결과에 ‘이미지 보기’ 버튼을 추가합니다.
// @description:nl  Voegt de "Afbeelding bekijken" knop aan toe aan Google Afbeeldingen.
// @description:sk  Toto rozšírenie pridáva tlačidlo "Zobraziť obrázok" do výsledkov vyhľadávania Google Search.
// @description:tr  Bu betik Google Görseller arama sonuçlarına "Resmi Görüntüle" düğmesini ekler.
// @author          Bae Junehyeon
// @run-at          document-end
// @include         http*://*.google.tld/search*tbm=isch*
// @include         http*://*.google.tld/imgres*
// ==/UserScript==

const lang = {
    ar: 'عرض الصورة',
    cs: 'Zobrazit obrázek',
    da: 'Vis billede',
    de: 'Bild ansehen',
    en: 'View image',
    es: 'Ver imagen',
    fi: 'Näytä kuva',
    fr: 'Voir l\'image',
    he: 'הצג תמונה',  // also 'iw'
    hu: 'Kép megtekintése',
    it: 'Apri immagine',
    iw: 'הצג תמונה',  // same as 'he'
    ja: '画像を表示',
    ko: '이미지 보기',
    lt: 'Rodyti vaizdą',
    nl: 'Afbeelding bekijken',
    no: 'Se bilde',
    pl: 'Pokaż obraz',
    pt: 'Ver imagem',
    ru: 'Показать в полном размере',
    se: 'Visa bild',  // also 'sv'
    sk: 'Zobraziť obrázok',
    sl: 'Ogled slike',
    sv: 'Visa bild',  // same as 'se'
    tr: 'Resmi Görüntüle',
    uk: 'Показати зображення',
    zh: '查看原图',
    'zh-CN': '查看原图',  // also 'zh'
    },
  srch = {
    cs: 'Vyhledat podle obrázku',
    da: 'Søg efter billede',
    de: 'Zur "Bildersuche"',
    en: 'Search by image',
    es: 'Buscar por imagen',
    fr: 'Recherche par image',
    he: 'חפש לפי תמונה',  // also 'iw'
    hu: 'Keresés kép alapján',
    it: 'Ricerca tramite immagine',
    iw: 'חפש לפי תמונה',  // same as 'he'
    ja: '画像を検索',
    ko: '이미지로 검색',
    nl: 'Afbeelding zoeken',
    no: 'Søk med bilde',
    pl: 'Wyszukiwanie obrazem',
    pt: 'Pesquisar por imagem',
    ru: 'Поиск по картинке',
    se: 'Fler storlekar',  // also 'sv'
    sk: 'Vyhľadať podľa obrázku',
    sl: 'Iskanje s sliko',
    sv: 'Fler storlekar',  // same as 'se'
    tr: 'Görselle Ara',
    zh: '以图搜图',
    };

const pgL=document.documentElement.lang;
const localizedViewImage = lang[pgL] || lang[pgL.split('-')[0]] || lang[navigator.language] || lang[navigator.language.split('-')[0]] || lang['en'];
const SBItxt = srch[pgL] || srch[pgL.split('-')[0]] || srch[navigator.language] || srch[navigator.language.split('-')[0]] || srch['en'];

var Btn_1, Btn_2;
var RE=new RegExp('^(?:'+location.origin+')?\/imgres[\?&]imgurl=([^&]*)');

var dataN;
document.querySelectorAll('script').forEach((s)=>{
  let c=s.innerText;
  if (c.startsWith('AF_initDataCallback') && c.length>100) {
    dataN=s;
    }
  })

function addButton(node) {
  if (node.nodeType === Node.ELEMENT_NODE) {
    if (node.classList.contains('irc_ris') || node.classList.contains('Y6heUd') || node.classList.contains('irc_mi')) {
      let container;
      if (node.classList.contains('Y6heUd')) container = node;
      else container = node.closest('.irc_c');

      let inView = container.parentNode.style.display !== "none";

      let similarImages = node.querySelectorAll('.rg_l');

      if (!similarImages.length) {
        let block = container.querySelector('div[jsname="ofUehf"]');
        if (block) block.addEventListener('click', function(ev){
          if (ev.target.classList.contains('rg_i')) updateLinkAfterClickOnSimilar(ev);
          });
        }

      [].forEach.call(similarImages, (image) => {
        image.addEventListener('click', updateLinkAfterClickOnSimilar);
      });

      let findSrc, focus, tbnID, t;
      try{
        findSrc=((t=container.querySelector(':scope .irc_t .irc_mi, :scope .n3VNCb')) && t.src) || ((t=container.querySelector(':scope .irc_t .irc_mut')) && t.src);
        focus=document.querySelector('.irc-s');
        if (!focus) {
          tbnID=container.parentNode.dataset['tbnid'];
          if (tbnID) focus=document.querySelector('div[data-tbnid="'+tbnID+'"]');
          }
        if (badImg(findSrc)) if (focus) {
          for (let k of focus.querySelectorAll('a')) {
            if (RE.test(k.href)) {
              findSrc=unescape(RegExp.$1);
              break;
              }
            }
          }

        if (badImg(findSrc) && dataN) {
          let u= new RegExp('"'+tbnID+'".*?\\[.*?\\[(".*?"),','s').exec(dataN.innerText);
          if (u && u[1]) findSrc=unescape(JSON.parse(u[1]));
          }

      /**/}catch(e){}

if (focus && inView && badImg(findSrc)) {
  obsFocus.observe(focus,{
    childList: false,
    subtree: true,
    attributes: true,
    attributeFilter: [ "href", "src" ]
    });
  }

      let thumbnail = node.querySelector('.irc_rimask.irc_rist');
      let src = bigSrc[findSrc] || findSrc || unescape(thumbnail.querySelector('.rg_l').href.match(/imgurl=([^&]+)/)[1]);

      let buttons = container.querySelector('.irc_but_r tr');
      // new version
      let nv=false;
      if (!buttons) {
        buttons = container.querySelector('.Qc8zh > .irc_ab');
        nv=1;
        }
      if (!buttons) {
        buttons = container.querySelector('.fwCBrd');
        nv=2;
        }

      let button = buttons.querySelector(nv? 'a.mgisga' : 'td.mgisga');
      if (button === null) {
        let openButton = buttons.querySelector(nv ? 'a' : 'td');

        button = openButton.cloneNode(true);
        let sp=button.querySelector(nv ? 'div span:nth-child(2)' : 'a span:nth-child(2)');
        sp.innerText = localizedViewImage;
        // remove icon and style
        sp.parentNode.removeChild(sp.previousElementSibling);
        if (nv==1) sp.className='';

        let link = nv ? button : button.querySelector('a');
        link.href = src;
        if (!nv) link.className = '';
        link.removeAttribute('data-cthref');
        link.removeAttribute('jsaction');
        link.removeAttribute('data-ved');

        button.classList.remove('irc_lth');
        button.classList.add('mgisga');
        if (nv && button.classList.contains('irc_hol')) button.style='margin-left: 8px;';

        openButton.after(button);

        // adding "Search by image"
        let lnks = container.querySelector('.irc_b .irc_hd .irc_dsh');
        let style = 'margin-left:1em', cls = 'o5rIVb SBIlnk dPO1Qe';

        if (!lnks) {
          lnks = (lnks=container.querySelector('.irc_ft, .yKbIbb, .Beeb4e')) && lnks.parentNode;
          cls = cls.replace(/dPO1Qe/,'');
          cls += ' irc_help PvkmDc So4Urb';
          style = '';
          }

        if (lnks) {
          let lnkSBI = document.createElement('a');
          let RE=/.*[\?&](hl=[^&]+)/.exec(location.search); // catch last &hl=xx parameter
          lnkSBI.setAttribute('hrefbase','/searchbyimage?'+(RE?RE[1]+'&':'')+'image_url=');
          lnkSBI.setAttribute('target','_blank');
          lnkSBI.setAttribute('class',cls);
          lnkSBI.setAttribute('style',style);
          lnkSBI.innerText= SBItxt;
          lnks.appendChild(lnkSBI);
          }
      }

      let link = nv ? button : button.querySelector('a');
      link.href = src;
      link = container.querySelector('.SBIlnk');
      link.href = link.attributes.hrefbase.value + encodeURIComponent(src);
      if (inView) {
        Btn_1=button;
        Btn_2=link;
        }
    }
  }
}

function badImg(u) {
  if (!u || u.startsWith('data:') || /^https?:\/\/[^\/]*?\.gstatic\.com\//.test(u)) return true;
}

function updButton(url,src) {
  let u;
  if ( ((u=RE.exec(url)) && (u=u[1])) || (u=src) ) {
    u=unescape(u);
    Btn_1.href=u;
    Btn_2.href=Btn_2.attributes.hrefbase.value + encodeURIComponent(u);
  }
}

var bigSrc={};
function updateLinkAfterClickOnSimilar({target:node}) {
  let src = unescape(node.closest('.rg_l, a').href.match(/imgurl=([^&]+)/)[1]);
  let i = node.src;
  if (i) bigSrc[i]=src;
  let container = node.closest('.irc_c');
  let button = container.querySelector('.mgisga');
  let link = button.querySelector('a');
  if (!link) link = button;
  link.href = src;
  link = container.querySelector('.SBIlnk');
  link.href = link.attributes.hrefbase.value + encodeURIComponent(src);
}

const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    const addedNodes = mutation.addedNodes || [];

    [].forEach.call(addedNodes, (newNode) => {
        addButton(newNode);
    });
  });
});

observer.observe(document.body, {
  childList: true,
  subtree: true
});

var obsFocus = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    updButton(mutation.target.href, mutation.target.src);
    });
  });

addButton(document.body);
psonnosp commented 4 years ago

Think that fixed the gstatic part, kind of hard to know for sure since it was a bit random when it appeared, but I still get a lot of data:image/jpeg;base64 links. Your workaround fixes it though so no worries if it's hard to fix permanently :)

Procyon-b commented 4 years ago

When you say that you get a lot of "data:", is it still true with this version ?

psonnosp commented 4 years ago

Yes, exactly as I wrote. The new version seem to have fixed the gstatic problem but I still get a lot of data:image/jpeg;base64 links.

Procyon-b commented 4 years ago

If you could get a couple of examples (if you can reproduce) I'll make a test version with another button to force a reparse of the page looking for the correct link.

Which browser+userJSextension are you using ?

psonnosp commented 4 years ago

You know how it is when you want something to happen... But here is one, they seem to appear more often when you click on a result from Related Images than when you click on a regular search result.

I'm using Waterfox Classic and Tampermonkey.

Procyon-b commented 4 years ago

I don't see "data:" links from the "related" panel. The problem could be linked to how waterfox runs the code (mutationObserver and querySelector). I'll try it and see why it behaves differently (if it is indeed the source of the problem).

psonnosp commented 4 years ago

The data link is in the View Image button in my provided url.

What I meant about the related part is that it seems to be more common to end up with a data link in View Image if you click a related image than if you click an image among the search results to the left.

Even the same image sometimes results in different outputs depending on where you click on it. In the provided link the same image is shown in the upper right in the left column and in the top left under the related images. Clicking it in related images gives me a data URL but clicking it to the left gives me the correct URL.

[Edit] Might be a good idea to update the script in Chrome before you compare how it works with another browser 😄 Chrome seems fine so maybe it's a Firefox/Waterfox issue as you say.

Procyon-b commented 4 years ago

The data link is in the View Image button in my provided url.

What I meant about the related part is that it seems to be more common to end up with a data link in View Image if you click a related image than if you click an image among the search results to the left.

That's what I understood. But this behaviour is fixed by the new code in my chrome profile. So the type of browser could be an explanation (js running differently), or something that crossed my mind last night, being identified (or not) to google search.

<snip>

I can explain how google search works, and how the script tries to work with it. When you click on an image, the side panel opens. The image displayed in this panel is not (or very very very vey rarely) the full image. It is either a "data:" or a "gstatic" url (with some exceptions when the original image's resolution is very small). To get the correct url, the script is using the link of the focused thumbnail (the one highlighted in the listing). If you move the mouse over it, you'll see the url. One of its parameters is the image url ("?imgurl="). This url is immediately available when you click on this image to open the side panel. It is not when you open the tab with the full search url that cause the side panel to be opened from the start, or if you use the "previous" and "next" buttons. In that particular case, the thumbnail link is updated after the side panel. To get this, the script attaches a "MutationObserver" to that element to catch the modification, and apply it to the buttons.

Clicking on a thumbnail in the side panel is different. The full url is not part to these thumbnails, and when the image is displayed, its thumbnail disappears. The focused element is then the top image block on the side panel, which is structured differently. It is also modified afterwards to update the image src (not the link in this case), and the script also gets it from there with a "MutationObserver". There is sometimes an error here, when google background update fails and the url is not updated. This is the last case (at least for me) when a "gstatic" url still appears.

To fix the behaviour for everyone, I'll have to check:

psonnosp commented 4 years ago

Sorry missed that you had made a post, thanks for the explanation. Seems like they've changed something again cause all(?) results, not just the occasional related image result, are now linking to encrypted-tbn0.gstatic.com again. Is it still possible to fix or have they ruined it for good this time?

Procyon-b commented 4 years ago

I have been running the test version successfully since then. And I forgot to update the stable version. My bad.

Can you ensure that your version of the script is updated? You can delete this beta version if you had one installed in July. Re-test and tell me if it still links to the wrong image. I've not experienced it since using this modification.

psonnosp commented 4 years ago

I've been running the version posted above in July since then and it has worked up until a few days ago and it has also auto updated itself yesterday but the problem is still there. Guess it's a change in Waterfox as you talked about earlier that has ruined it if it still works for you. Is it something you are able to fix or can you give me any info in what I should tell the devs of Waterfox when I try to report a bug cause I have no clue in where to begin.

Procyon-b commented 4 years ago

I'll look at it in WF. I've installed it on another laptop to debug another userscript (dismissing the "sign-in" dialog). There is probably a workaround for the problem. There is also the possibility that google is at it again with different layouts (at least on the HTML level). So far I have not encountered one (I'm testing on 20+ google.tld to catch variations).

Procyon-b commented 4 years ago

Follow-up I've tested with WF 2020.10 + TM 4.11.6117 + script 1.5.0.14 and it works as expected. windows7 1.8Ghz x2

If you haven't installed TM beta, you can use it to test while leaving you normal TM unmodified, in case TM is somehow faulty. (enable only the beta)

psonnosp commented 4 years ago

Is that Waterfox current or classic? Realized I forgot to mention that I'm on the classic version. Other than that I have the same versions of everything on Win10.

Procyon-b commented 4 years ago

waterfox classic

the url in the caption at the bottom is the url of the "view image" button

GIS-waterfox2

GIS-waterfox

psonnosp commented 4 years ago

OK, so something is F'ed up in my end then, lovely... Thanks for your time!

Procyon-b commented 4 years ago

I can prepare a beta version, based on what I test, with more console.info() statements. Maybe you get a variation of the HTML code that doesn't trigger correctly within the script.

You can also check the "settings" tab of the script in TM. See if something has changed there. If you don't have the button bar displayed on the "Editor" tab of the script, you have "Factory reset" in the "developper" menu of the tab. It'll reset the script as if it was just installed.

Procyon-b commented 4 years ago

As a last resort you can install TM beta (from https://www.tampermonkey.net/ link on the page) and run the script there. Or you can install violentmonkey. This can eliminate a problem with your installation of TM.

Procyon-b commented 4 years ago

Last idea that struck me right now: what is the url of a GI page where the script doesn't work? Maybe, in your case, it no longer matches the @include rules.

Procyon-b commented 3 years ago

@psonnosp , any news?

psonnosp commented 3 years ago

Sorry, crazy times and my life is upside down so not that much time to spend at the computer.

But it all seem to work again for some reason. Well not without the workaround switching images with left/right or hitting F5, but the URL is showing again. Maybe it was just Google messing around with something.

Once again, thanks for your time spent on this.