Upwork: Hide jobs with hires

Hide the jobs where someone has already been hired

目前為 2021-09-06 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        Upwork: Hide jobs with hires
// @namespace   https://www.stardecimal.com/
// @version     1
// @description Hide the jobs where someone has already been hired
// @author      lifeweaver
// @grant       none
// @include     https://www.upwork.com/ab/jobs/search/*
// ==/UserScript==

/* jshint esversion: 6 */

(function (_undefined) {
  
	// ===================================================================
	// Tried of clicking on the jobs with hires already?
  //
	// Script style and some functions from YouTube: Hide Watched Videos - https://github.com/EvHaus/youtube-hide-watched

	// ====================================================================

	// Enable for debugging
	const __DEV__ = false;

	const logDebug = (msg) => {
		// eslint-disable-next-line no-console
		if (__DEV__) console.log(msg);
	};

	// ===========================================================

	const debounce = function (func, wait, immediate) {
		let timeout;
		return (...args) => {
			const later = () => {
				timeout = null;
				if (!immediate) func.apply(this, args);
			};
			const callNow = immediate && !timeout;
			clearTimeout(timeout);
			timeout = setTimeout(later, wait);
			if (callNow) func.apply(this, args);
		};
	};
  
  // ===========================================================
  
  // There is probably some normal way to get these, but I don't know how so...
  const getCookie = function (name) {
      var value = '';
      document.cookie.split(';').forEach(function(item, index) {
          if(item.includes(name)) {
              value = item.split('=').pop()
          }
      });
      return value;
  }
  
  // ===========================================================

  // Called after getting the details for each job
  const reqListener = function () {
      var jobDetails = JSON.parse(this.responseText);
      logDebug('[UW-JHH] totalHired: ', jobDetails.job.clientActivity.totalHired);
      if(jobDetails.job.clientActivity.totalHired > 0) {
          //Drop the first one
          var responseUrlArray = this.responseURL.split('/');
          responseUrlArray.pop()

          //JobId is the second to last
          var jobId = responseUrlArray.pop();

          document.querySelector('a[href*="' + jobId + '"]').closest('section').remove();
      }
  }

  // ===========================================================
  
  const lookForJobs = function () {
    document.querySelectorAll('.job-title-link').forEach(function(item, index) {
        var jobId = item.href.split('_').pop();
        jobId = jobId.slice(0, jobId.length -1);
        var detailsUrl = "https://www.upwork.com/job-details/jobdetails/api/job/" + jobId + "/summary";

        var xhr = new XMLHttpRequest();
        xhr.addEventListener("load", reqListener);
        xhr.open("GET", detailsUrl);
        xhr.setRequestHeader('Authorization', "Bearer " + getCookie('oauth2_global_js_token'));
        xhr.setRequestHeader('X-Odesk-Csrf-Token', getCookie('XSRF-TOKEN'));
        xhr.setRequestHeader('x-odesk-user-agent', 'oDesk LM');
        xhr.setRequestHeader('x-requested-with', 'XMLHttpRequest');
        xhr.send();
    });
  }
  
	const run = debounce((mutations) => {
		logDebug('[UW-JHH] Running check for jobs with hires');
		lookForJobs();
	}, 250);

	// ===========================================================
  
	const observeDOM = (function () {
		const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
		const eventListenerSupported = window.addEventListener;

		return function (obj, callback) {
			logDebug('[UW-JHH] Attaching DOM listener');

			// Invalid `obj` given
			if (!obj) return;

			if (MutationObserver) {
				const obs = new MutationObserver(((mutations, _observer) => {
					if (mutations[0].addedNodes.length || mutations[0].removedNodes.length) {
						// eslint-disable-next-line callback-return
						callback(mutations);
					}
				}));

				obs.observe(obj, {childList: true, subtree: true});
			} else if (eventListenerSupported) {
				obj.addEventListener('DOMNodeInserted', callback, false);
				obj.addEventListener('DOMNodeRemoved', callback, false);
			}
		};
	}());

  
	logDebug('[UW-JHH] Starting Script');
  
	// Listen for ANY DOM change event, and re-run the script.
	observeDOM(document.body, run);
  
  // Initial run
  run();
  
}());