Skip to content

Instantly share code, notes, and snippets.

@offirgolan
Created August 2, 2017 05:57
Show Gist options
  • Star 72 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save offirgolan/9b12a2a170f70d0d70e2238e8661e382 to your computer and use it in GitHub Desktop.
Save offirgolan/9b12a2a170f70d0d70e2238e8661e382 to your computer and use it in GitHub Desktop.
Unwatch All Org Repos
// Navigate to https://github.com/watching and then run:
// Taken from: https://stackoverflow.com/questions/11043374/how-to-unwatch-multiple-repos-easily-on-github
Array.prototype
.slice.apply(document.querySelectorAll('.js-subscription-row'))
.forEach(el => { const org = el.querySelector('a[href^="/YOUR_ORG"]'); if (org) el.querySelector('button').click()});
@stgarf
Copy link

stgarf commented Apr 1, 2019

GitHub UI has changed a bit since two years ago. This should get you a bit closer and also click the "Next" button.

Array.prototype
  .slice.apply(document.querySelectorAll('.Box-row'))
  .forEach(el => {
    const org = el.querySelector('a[href^="/YOUR_ORG"]');
    if (org) el.querySelector('button').click()
  });
var xpath = "//a[text()='Next']";
var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
matchingElement.click();

@pjmartorell
Copy link

Not working for me on https://github.com/watching. I don't know the reason

@cooperaj
Copy link

cooperaj commented Apr 5, 2019

I had to amend

if (org) el.querySelector('button').click()

to read

if (org) el.querySelector('button[value="included"]').click()

@DesignByOnyx
Copy link

If you have multiple organizations you wish to unwatch, you can use this:

Array.prototype
  .slice.apply(document.querySelectorAll('.Box-row'))
  .forEach(el => {
    ['ORG1', 'ORG2', 'ORG3' /** ADD MORE HERE, SEPARATED BY COMMA **/].forEach(o => {
      const org = el.querySelector(`a[href^="/${o}"]`);
      if (org) el.querySelector('button').click()
    });
  });
var xpath = "//a[text()='Next']";
var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
matchingElement.click();

@jaraco
Copy link

jaraco commented May 28, 2019

Did not work for me, either with button or button[value="included"] as the selector.

@voronianski
Copy link

try this one if you don't care about filtering by org:

(function () {
  const nodes = document.querySelectorAll('button.select-menu-item[value="included');
  const arr = [ ...nodes ];

  arr.forEach(button => {
    setTimeout(() => {
      button.click();
    }, 500);
  });
})();

https://gist.github.com/voronianski/b0bd4ecffc0919000ec7146bd5d7e4dd

@justin-edwards
Copy link

justin-edwards commented Jul 31, 2019

Working as of today with org filtering:

(function () {
  const org = 'ORG'
  
  const nodes = document.querySelectorAll('.Box-row');
  const rows = [ ...nodes ];
  const orgRows = rows.filter((e) => e.innerText.startsWith(` ${org}/`));
  const orgUnsubButtons = orgRows.map(row => row.querySelector('button.select-menu-item[value="included'));
  
  orgUnsubButtons.forEach(button => console.log(button.click()));
    
})();

@andreineculau
Copy link

fixed a typo in @justin-edwards snippet
row.querySelector('button.select-menu-item[value="included')); -> row.querySelector('button.select-menu-item[value="included"]'));

and added pagination support

(function() {
let qx = $x;
let unwatch = function(org) {
  let nodes = document.querySelectorAll('.Box-row');
  let rows = [ ...nodes ];
  let orgRows = rows.filter(e => e.innerText.startsWith(` ${org}/`));
  let orgUnsubButtons = orgRows.map(row => row.querySelector('button.select-menu-item[value="included"]'));
  orgUnsubButtons.forEach(button => console.log(button.click()));
  setTimeout(function() {
    qx("//a[text()='Next']")[0].click();
  }, 1000);
};

let org = 'ORG'; // <--- change ORG to desired organization, and repeat for all pages
unwatch(org);
})();

@jportella93
Copy link

To set it to Releases only using @andreineculau snippet

(function() {
let qx = $x;
let unwatch = function(org) {
  let nodes = document.querySelectorAll('.Box-row');
  let rows = [ ...nodes ];
  let orgRows = rows.filter(e => e.innerText.startsWith(` ${org}/`));
  let orgUnsubButtons = orgRows.map(row => row.querySelector('button.select-menu-item[value="release_only"]'));
  orgUnsubButtons.forEach(button => console.log(button.click()));
  setTimeout(function() {
    qx("//a[text()='Next']")[0].click();
  }, 1000);
};

let org = 'ORG'; // <--- change ORG to desired organization, and repeat for all pages
unwatch(org);
})();

@jdcanas
Copy link

jdcanas commented Dec 9, 2019

I found this page, which also seems to accomplish the same thing with an 'Unwatch All' button https://github.com/watching

@mindplay-dk
Copy link

I found this page, which also seems to accomplish the same thing with an 'Unwatch All' button https://github.com/watching

Uhm, no? This thread is about unwatching repos for a specific org.

@ypcrts
Copy link

ypcrts commented Mar 18, 2020

Now it seems I had to comment out the Next click, or else I get a race where Page 2 loads Page 3 items.

modified from @andreineculau's version

(function() {
let qx = $x;
let unwatch = function(org) {
  let nodes = document.querySelectorAll('.Box-row');
  let rows = [ ...nodes ];
  let orgRows = rows.filter(e => e.innerText.startsWith(` ${org}/`));
  let orgUnsubButtons = orgRows.map(row => row.querySelector('button.select-menu-item[value="included"]'));
  orgUnsubButtons.forEach(button => console.log(button.click()));
  setTimeout(function() {
  }, 1000);
};

let org = 'ORG'; // <--- change ORG to desired organization, and repeat for all pages
unwatch(org);
})();

@gaqzi
Copy link

gaqzi commented Sep 4, 2020

the tiniest of changes that can break stuff… @ypcrts' version doesn't quite work anymore because of a leading space when looking up whether the repo starts with the org. 🤷

I also updated it to make it a little clearer how to change it to a different notification type if you want to.

(function() {
let qx = $x;
let unwatch = function(org, notificationType) {
  let nodes = document.querySelectorAll('.Box-row');
  let rows = [ ...nodes ];
  let orgRows = rows.filter(e => e.innerText.startsWith(`${org}/`));
  let orgUnsubButtons = orgRows.map(row => row.querySelector(`button.select-menu-item[value="${notificationType}"]`));
  orgUnsubButtons.forEach(button => console.log(button.click()));
  setTimeout(function() {
  }, 1000);
};

let org = 'ORG'; // <--- change ORG to desired organization, and repeat for all pages
let notificationType = 'included'; // 'included' = not watching, 'release_only' = releases only, 'subscribed' = watching, 'ignore' = ignoring
unwatch(org, notificationType);
})();

@ypcrts
Copy link

ypcrts commented Sep 8, 2020

hey @github PMs! notice me senpai. we struggle with autowatch, especially when added to teams with 1892731892379812739 repos.

@gaqzi
Copy link

gaqzi commented Sep 8, 2020

there is an option to not automatically watch repositories when you get added to a team, but sometimes it's just a bit too late to learn about that option… :P

https://github.com/settings/notifications

@ypcrts
Copy link

ypcrts commented Sep 12, 2020

I actually want autowatch. I want to watch all the things. But now if someone adds me to the wrong team. Then I want to mass unwatch.

😭

@edman
Copy link

edman commented Nov 23, 2020

Here's the latest working script, adapted from @gaqzi's

(function() {
let qx = $x;
let unwatch = function(org, notificationType) {
  let nodes = document.querySelectorAll('.Box-row');
  let rows = [ ...nodes ];
  let orgRows = rows.filter(e => e.innerText.startsWith(`${org}/`));
  let orgUnsubButtons = orgRows.map(row => row.querySelector(`button.SelectMenu-item[value="${notificationType}"]`));
  orgUnsubButtons.forEach(button => console.log(button.click()));
  setTimeout(function() {
  }, 1000);
};

let org = 'ORG'; // <--- change ORG to desired organization, and repeat for all pages
let notificationType = 'included'; // 'included' = participating and @mentions, 'subscribed' = all activity, 'ignore' = ignore
unwatch(org, notificationType);
})();

@stas00
Copy link

stas00 commented Jan 25, 2021

@edman's revision worked today - thank you!

just a note that one needs to continue to reload the page and re-run the script multiple times if there are multiple screens.

there is an option to not automatically watch repositories when you get added to a team, but sometimes it's just a bit too late to learn about that option… :P
https://github.com/settings/notifications

That's a great tip - thank you, @gaqzi!

@Mxrcon
Copy link

Mxrcon commented Jul 16, 2021

Thanks for the last revision @edman still working! This gist is amazing.

@TheYarin
Copy link

thank you guys, don't know what I would have done without you!

@fuhrmanator
Copy link

Thanks for the last revision @edman still working! This gist is amazing.

For me too -- thanks much!

@gander
Copy link

gander commented Oct 14, 2021

My quick implementation to only remove stuff I don't want to track.

setInterval(() => {
  let ignore = ['vite', 'vue', 'awesome', 'livewire'];
  document.querySelectorAll('.Box-row').forEach((row) => {
    let url = new URL(row.querySelector('a').href);
    if (new RegExp(ignore.join("|")).test(url.pathname.toLowerCase())) return;
    row.querySelector('button[value=included]').click();
  });
}, 250);

@Mehul
Copy link

Mehul commented Nov 10, 2021

Had to modify script from @edman / @gaqzi to get it work for me in FF/Chrome. Minor changes, thanks to @dwells:

(function() {
  let qx = $x;
  let unwatch = function(org, notificationType) {
    let nodes = document.querySelectorAll(".Box-row");
    let rows = [...nodes];
    let orgRows = rows.filter(e => e.innerText.startsWith(`${org}/`));
    let orgUnsubButtons = orgRows.map(row =>
      row.querySelector(`button.SelectMenu-item[value="${notificationType}"]`)
    );
    orgUnsubButtons.forEach(button => console.log(button.click()));
    //orgUnsubButtons.forEach(button => console.log(`click ${notificationType}`));
    setTimeout(function() {}, 1000);
  };
  let org = "ORG"; // <--- change ORG to desired organization, and repeat for all pages
  let notificationType = "included"; // 'included' = participating and @mentions, 'subscribed' = all activity, 'ignore' = ignore
  unwatch(org, notificationType);
})();

@Anigif
Copy link

Anigif commented Mar 21, 2022

This feature now seems to be integrated into https://github.com/watching. Just click "Unwatch all" and selected the organization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment