6

I want to review questions I have posted bounties on across the Stack Exchange network. I'd like to do this so I can check for active bounties with answers I need to review.

I can view my offered bounties for a specific site by appending ?tab=bounties to my user profile, but this isn't an option on my Network Profile.

Is there any way to view my offered bounties across Stack Exchange?

Related: How can I view all my unaccepted questions across SE?

  • Sounds like a job for SEDE, the API or a user script – Helmar Jul 23 '17 at 15:04
  • 1
    @Helmar SEDE is possible but it is only refreshed once a week, on Sunday. For bounties that period is just a bit too long to be useful. The API which uses live data is a better choice here. – rene Jul 23 '17 at 20:31
3

Here is a stacksnippet that given an accountid (found in the url of your network profile) will list all your active bounties. It uses the questions/featured StackAPI endpoint.

The scripts start with fetching for a given account all associated users. With that info we can iterate over the result and call for each site the info endpoint so we have the site icon and name. Then we proceed to call questions/featured for a user to get the questions that are bountied for that specific site user.

Once we have that result all that is needed is adding elements to the DOM so you can click on the links.

(function () {
  var api = {
    url: 'https://api.stackexchange.com/2.2/',
    endpoint: 'questions/featured',
    params: { 
      site: 'stackoverflow',
      pagesize: 100,
      order: 'desc',
      sort: 'activity',
      Filter: '!iCF4LsDYJt6oT_Y1qKBCOv',
      key: 'JBN9WXWxwrcnAj7WEEytmQ(('
      }
    },
    sites = {};
    
  function createUrl(ap) {
    var ep = ap.url + ap.endpoint +'?',
       nv = [];
    if (ap.params) {
      for(var p in ap.params) {
        if (ap.params.hasOwnProperty(p)) {
             nv.push(p + '=' + ap.params[p]);
        }
      }
    }
    console.log(ep + nv.join('&'));
    return ep + nv.join('&');
  }
  
  function createSitesUrl() {
    return createUrl( 
      { url: api.url, 
        endpoint: 'sites', 
        params: { 
          pagesize: 500, 
          key: api.params.key, 
          filter: '!*l7_tSmzy1mF3bw9odQw*8ur' } 
       });
  }
  
  function createUserFeaturedUrl(userid, site) {
    return createUrl( 
      { url: api.url, 
        endpoint: 'users/'+ userid + '/questions/featured', 
        params: { 
          site: site,
          pagesize: 100, 
          key: api.params.key, 
          filter: '!*7PmgCF3rY3WihzNKHz4jURFN9X6' } 
       });
  }
  
  function createInfoUrl(site) {
    return createUrl( 
      { url: api.url, 
        endpoint: 'info', 
        params: { 
          site: site,
          key: api.params.key, 
          filter: '!39qVOEzAjeqnKS5bl7_puf_.GSZJG' } 
       });
  }
  
  function createAccountsUrl(accountid) {
    return createUrl( 
      { url: api.url, 
        endpoint: 'users/'+ accountid + '/associated', 
        params: { 
          pagesize: 100, 
          key: api.params.key, 
          filter: '!w*vp4lVBIX453e.b5Y' } 
       });
  }
  
  
  function find(id) {
    return document.getElementById(id);
  }
   
  function buildSite(site) {
     var img = document.createElement('img');
     img.setAttribute('src', site.icon_url);
     img.setAttribute('title', site.name);
     return img;
  }
  
  function buildLink(post, site) {
    var link = document.createElement('a');
    link.setAttribute('href', site.site_url +'/q/' + post.question_id);
    link.setAttribute('title', new Date(post.last_activity_date * 1000));
    link.textContent = post.title 
      + ' ('
      + 'score:'
      + post.score
      + ', ans:'
      + post.answer_count
      + ' )' ;
    return link;
  }
   
  function buildQuestion(site, item) {
     var cont = document.createElement('div');
     cont.appendChild(buildSite(site));
     cont.appendChild(buildLink(item, site));
     return cont;
  }
 
  var queue = [];
  var get = realget;  // function delegate void (url, callack)
  var backoffTimer;
  
  // used when we have received a backoff
  function backoffget(url, calback) {
     queue.push(function() { get(url, callback); });
  }
  
  function processQueue() {
    if (queue.length > 0 && get === realget) {
       var action = queue.shift();
       if (action != null) action();
    }
  }
  
  // used when we are good to call
  function realget(url, callback) {
     var xhr = new XMLHttpRequest();
     xhr.open('GET', url);
     xhr.addEventListener('load', function() {
       var data;
       if (xhr.readyState === 4 && xhr.status === 200) {
         data = JSON.parse(xhr.responseText);
         if (data.backoff) {
            // switch to backoff mode
            get = backoffget;
            clearTimeout(backoffTimer);
            backoffTimer = setTimeout(function () {
              get = realget;
              processQueue();
            }, data.backoff * 1000); 
         }
         processQueue();
         callback(JSON.parse(xhr.responseText));
      }
    });
    xhr.send();
  }

  function loadUserFeatured(userid, site) {
     get(createUserFeaturedUrl(userid, site.api_site_parameter), function(data) {
       console.log(site);
       data.items.forEach( function(item) {
           console.log(item);
           find('fav').appendChild(buildQuestion(site, item));
       });    
    });
  }
  
  function loadUserFromAccount(item) {
    var uid = item.user_id;
    var site = item.site_url.replace('https://','');
    if (sites[site]) {
      loadUserFeatured(uid, sites[site]);
    } else {
      get(createInfoUrl(site), function(data) {
        sites[site] = data.items[0].site;
        loadUserFeatured(uid, sites[site]);
      });
    }
  }
  
  function loadAccounts(accountId) {
    get(createAccountsUrl(accountId), function(data) {
      var fav = find('fav');
      while (fav.firstChild) {
        fav.removeChild(fav.firstChild);
      }
      data.items.forEach( function(item) {
         loadUserFromAccount(item);
      });
    });
  }
    
  find('go').addEventListener(
    'click', 
    function() {
        loadAccounts(find('accountid').value);
    });
  
}());
img {
  height: 1em;
  }
<div id="error" style="display:none">
</div>
<div>
<label>Account id:</label><input type="text" id="accountid" />
</div>
<div>
<button id="go">Search</button>
</div> 
<div id="fav">
  
</div>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .