Using GitHub list-issues-for-a-repository API - github

When you go to GitHub, under Issues, it pulls up all the open issues as an HTML page. We'd like to implement a dashboard showing all the issues in a repository, grouped by labels, including those issues which are not correctly labelled.
This is the corresponding list-issues-for-a-repository API.
While I was initially using jQuery and Javascript, am now using PHP for a proof-of-concept because its built-in session handling lets me use the same page to login, have GitHub authenticate & callback, and continue. But it doesn't matter to me, any language is okay.
I've managed to get access to the GitHub API via OAUTH2, but when I get the list of repositories via https://api.github.com/orgs/{org}/repos it comes up as an empty array.
Because the /orgs/{org}/repos API returns an empty array, of course the corresponding /repos/{org}/{repo}/issues API will return an error.
Edit: See this followup for a solution! Glad I finally got it working!

It is a rest API. You need to call some endpoints using an Http request.
I don't know what language you are trying to use so I can't give you a good example on how to acheive this.
If you don't know which language to use yet, use postman to create REST API call to the github API.
Let's say you want to retreive the issues of the microsoft's typescript repo, You would need to call this API endpoint :
https://api.github.com/repos/microsoft/typescript/issues
Notice here that i have replace the :owner and :repo value of documentation for the one i'm trying to get.
You can then pass some parameters to the call to filter your data, for example, the API label.
https://api.github.com/repos/microsoft/typescript/issues?labels=API
This will only return issues that are labelled as API.
This is the basics of how to use an API.

You can use jQuery Ajax to access the Github API and add a basic authentication header to authenticate (see here), an example is shown below, this will pull the issues for a given repo and show the first 10 in an alert window.
See the documentation on pulling issues here: https://developer.github.com/v3/issues/ to see which parameters you can use to filter, sort etc.
For example you can get all issues labelled 'bug' using:
/issues?labels=bug
This can include multiple labels, e.g.
/issues?labels=enhancement,nicetohave
You could easily modify to list in a table etc.
const username = 'github_username'; // Set your username here
const password = 'github_password'; // Set your password here
const repoPath = "organization/repo" // Set your Repo path e.g. microsoft/typescript here
$(document).ready(function() {
$.ajax({
url: `https://api.github.com/repos/${repoPath}/issues`,
type: "GET",
crossDomain: true,
// Send basic authentication header.
beforeSend: function (xhr) {
xhr.setRequestHeader ("Authorization", "Basic " + btoa(username + ":" + password));
},
success: function (response) {
console.log("Response:", response);
alert(`${repoPath} issue list (first 10):\n - ` + response.slice(0,10).map(issue => issue.title).join("\n - "))
},
error: function (xhr, status) {
alert("error: " + JSON.stringify(xhr));
}
});
});
Below is a snippet listing issues for a (public) repo using jQuery and the Github API:
(Note we don't add an authentication header here!)
const repoPath = "leachim6/hello-world" //
$(document).ready(function() {
$.ajax({
url: `https://api.github.com/repos/${repoPath}/issues`,
type: "GET",
crossDomain: true,
success: function (response) {
tbody = "";
response.forEach(issue => {
tbody += `<tr><td>${issue.number}</td><td>${issue.title}</td><td>${issue.created_at}</td><td>${issue.state}</td></tr>`;
});
$('#output-element').html(tbody);
},
error: function (xhr, status) {
alert("error: " + JSON.stringify(xhr));
}
});
});
<head>
<meta charset="utf-8">
<title>Issue Example</title>
<link rel="stylesheet" href="css/styles.css?v=1.0">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>
<body style="margin:50px;padding:25px">
<h3>Issues in Repo</h3>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Issue #</th>
<th scope="col">Title</th>
<th scope="col">Created</th>
<th scope="col">State</th>
</tr>
</thead>
<tbody id="output-element">
</tbody>
</table>
</body>

Related

Mapbox GL: How can I handle invalid/expired access tokens?

I've implemented Mapbox GL:
script.src = 'https://api.mapbox.com/mapbox-gl-js/v2.8.2/mapbox-gl.js';
script.onload = function() {
mapboxgl.accessToken = 'invalid_token';
map = new mapboxgl.Map({
container: 'mapsection', // container ID
style: 'mapbox://styles/mapbox/streets-v11' // style URL
});
}
If the access token is invalid or expired then a message is shown in the console, but how can I handle this in my code? I've tried both try .. catch and map.on('error'), but neither acknowledge there is an error. Any operations on the map are performed without errors, but there is just nothing to see on the page.
Alternatively, is there an API to validate a given token?
I don't know for sure, but if you take one of the URLs that are being requested (by looking in developer tools), and using fetch to query that URL, you will probably get back either 200 for a correct token, or 401 or 403 for an invalid token (or other issue).
Looks like I was almost there, but just made a small mistake. It is indeed the map.on('error') event handler I need to use:
script.src = 'https://api.mapbox.com/mapbox-gl-js/v2.8.2/mapbox-gl.js';
script.onload = function() {
mapboxgl.accessToken = 'invalid_token';
map = new mapboxgl.Map({
container: 'mapsection', // container ID
style: 'mapbox://styles/mapbox/streets-v11' // style URL
});
map.on('error', (response) => {
alert(response.error.message)
});
}
Using map.on('error') results in Mapbox GL (v2.12.0) creating the full HTML DIV structure even when a Mapbox access token is invalid.
<div id="map-container" class="mapboxgl-map"><div class="mapboxgl-canary" style="visibility: hidden;"></div><div class="mapboxgl-canvas-container mapboxgl-interactive mapboxgl-touch-drag-pan mapboxgl-touch-zoom-rotate"><canvas class="mapboxgl-canvas" tabindex="0" aria-label="Map" role="region" width="780" height="724" style="width: 519.115px; height: 482.542px;"></canvas></div><div class="mapboxgl-control-container"><div class="mapboxgl-ctrl-top-left"></div><div class="mapboxgl-ctrl-top-right"><div class="mapboxgl-ctrl mapboxgl-ctrl-group"><button class="mapboxgl-ctrl-zoom-in" type="button" aria-label="Zoom in" aria-disabled="false"><span class="mapboxgl-ctrl-icon" aria-hidden="true" title="Zoom in"></span></button><button class="mapboxgl-ctrl-zoom-out" type="button" aria-label="Zoom out" aria-disabled="false"><span class="mapboxgl-ctrl-icon" aria-hidden="true" title="Zoom out"></span></button><button class="mapboxgl-ctrl-compass" type="button" aria-label="Reset bearing to north"><span class="mapboxgl-ctrl-icon" aria-hidden="true" title="Reset bearing to north" style="transform: rotate(0deg);"></span></button></div></div><div class="mapboxgl-ctrl-bottom-left"><div class="mapboxgl-ctrl" style="display: block;"><a class="mapboxgl-ctrl-logo" target="_blank" rel="noopener nofollow" href="https://www.mapbox.com/" aria-label="Mapbox logo"></a></div></div><div class="mapboxgl-ctrl-bottom-right"></div></div></div>
To avoid the unnecessary code execution by mapbox-gl.js, I used #Steve's suggestion of using a fetch query to a Mapbox API. A request to a map styles API URL results in an ~70KB response when the access token is valid. A request to the Mapbox geocoding API (version 5 is older; v6 is the most current version as of Feb 2023), using a non-existent place as the search string results in a 343 byte response.
const url = `https://api.mapbox.com/geocoding/v5/mapbox.places/rndstrasdf.json?access_token=${mapboxAccessToken}`;
This all seems unnecessary, however, as it would more efficient if Mapbox provided an access token verification API before executing any mapbox-gl in much the same way they provide a mapbox-gl-supported plugin.
For performance reasons, it is better to check that Mapbox GL JS is
supported before going to the trouble of loading the script and
initializing the map on your page.
document.addEventListener('DOMContentLoaded', function() {
loadMap()
.then(map => console.log("Map loaded successfully into element with ID: " + map._container.id))
.catch(error => console.error("Map load failed with the error: " + error.message));
});
function loadMap() {
return new Promise((resolve, reject) => {
const mapboxAccessToken = "ADD_YOUR_VALID_OR_INVALID_ACCESS_TOKEN";
// Using the following URL in a 'fetch' API results in a ~70KB response.
//const url = `https://api.mapbox.com/styles/v1/mapbox/streets-v11?access_token=${mapboxAccessToken}`;
//const url = `https://api.mapbox.com/styles/v1/mapbox/streets-v11?access_token=invalid`;
// A URL to Mapbox geocoding to validate a Mapbox access token
// results in a 343 byte response using a non-existent place name.
// Place search at https://www.mapbox.com/geocoding
// Temporary Geocoding API pricing https://www.mapbox.com/pricing#search
// A valid place name -> "Los Angeles"
//const url = `https://api.mapbox.com/geocoding/v5/mapbox.places/Los Angeles.json?access_token=${mapboxAccessToken}`;
const url = `https://api.mapbox.com/geocoding/v5/mapbox.places/rndstrasdf.json?access_token=${mapboxAccessToken}`;
fetch(url)
.then(response => {
if (!response.ok) {
response.message = "Connected to Mapbox service but with an invalid access token.";
reject(response);
return;
}
// Request succeeded. Response is an empty GeoJSON 'features' collection
// 343 bytes
/*
'{"type":"FeatureCollection","query":["rndstrasdf"],"features":[],
"attribution":"NOTICE: © 2023 Mapbox and its suppliers. All rights reserved.
Use of this data is subject to the Mapbox Terms of Service
(https://www.mapbox.com/about/maps/). This response and the information
it contains may not be retained. POI(s) provided by Foursquare."}'
*/
response.text().then(text => {
console.log(text);
});
mapboxgl.accessToken = mapboxAccessToken;
// stackoverflow.com/questions/72254578/how-to-solve-that-a-valid-mapbox-access-token-is-required-to-use-mapbox-gl-js
// github.com/mapbox/mapbox-gl-js/releases/tag/v2.0.0
// "Beginning with v2.0.0, a billable map load occurs whenever a
// Map object is initialized. Before updating an existing
// implementation from v1.x.x to v2.x.x, please review the
// pricing documentation to estimate expected costs."
const map = new mapboxgl.Map({
container: "map-container",
style: 'mapbox://styles/mapbox/streets-v11',
center: [12.79690, 47.32350], // Longitude, latitude
zoom: 5
});
// Add zoom and rotation controls to the map
// docs.mapbox.com/mapbox-gl-js/example/navigation
map.addControl(new mapboxgl.NavigationControl());
map.on('load', () => resolve(map));
map.on('error', error => reject(error));
})
.catch(error => {
reject(error);
});
});
}
<link href='https://api.mapbox.com/mapbox-gl-js/v2.12.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://api.mapbox.com/mapbox-gl-js/v2.12.0/mapbox-gl.js'></script>
<div id="map-container" style="width: 100%; height: 80vh;"></div>

How can i prevent User from directly accessing the HTML page

I have got a set 3 HTML Pages
I am using Apache Tomcat 7 server . I have got the following HTML pages (All are HTML pages only)
login.html
sales.html
index.html
The code for the login.html is when clicked on submit is
<input type="email" name="email" id="email" >
<input type="pin" name="email" id="pin" >
<button class="primary login-btn">Submit</button>
Once clicked on Submit button , i am calling a Jersey REST Webservce this way and will response either true OR false based on the values present in our Database
function submitLoginForm() {
var email_input = $.trim($("#email").val());
var pin_input = $.trim($("#pin").val());
var logininfo = {
'email': email_input,
'pin': pin_input
};
var login_information = JSON.stringify(logininfo);
$.ajax({
type: 'POST',
dataType: 'json',
data: login_information,
url: url + '/HEGS/orn/webchecklogin',
success: function(response) {
// if true , redirect to sales.html page
window.location = "index.html"
},
});
}
All this is working fine , my issue is , how can i stop the prevent the user from accessing the page directly
For example if he types the follwing URL
http:localhost:8080/HEGS/dealer/sales.html
You would want to redirect the url to one file, which would then load the correct file based on the criteria you set. I don't know much about Tomcat, but this article seems to explain it well under the "URL Rewriting" section.

Twitter Typeahead.js with Yahoo Finance in AJAX

I am trying to couple the new version of Typeahead.js and using it with JSON that needs to be pulled from AJAX and not from a JSON file like they have in their examples. I just can't get it to work, I don't want to cache the JSON result or anything, I want to pull it live from Yahoo.
My HTML input is <input type="text" id="symbol" name="symbol" autofocus autocomplete="off" placeholder="Symbol" onkeyup="onSymbolChange(this.value)" />
My AJAX/PHP file has this to retrieve data (this part work, I tested it with Firebug)
header('Content-type:text/html; charset=UTF-8;');
$action = (isset($_GET['action'])) ? $_GET['action'] : null;
$symbol = (isset($_GET['symbol'])) ? $_GET['symbol'] : null;
switch($action) {
case 'autocjson':
getYahooSymbolAutoComplete($symbol);
break;
}
function getYahooSymbolAutoCompleteJson($symbolChar) {
$data = #file_get_contents("http://d.yimg.com/aq/autoc?callback=YAHOO.util.ScriptNodeDataSource.callbacks&query=$symbolChar");
// parse yahoo data into a list of symbols
$result = [];
$json = json_decode(substr($data, strlen('YAHOO.util.ScriptNodeDataSource.callbacks('), -1));
foreach ($json->ResultSet->Result as $stock) {
$result[] = '('.$stock->symbol.') '.$stock->name;
}
echo json_encode(['symbols' => $result]);
}
The JS file (this is where I'm struggling)
function onSymbolChange(symbolChar) {
$.ajax({
url: 'yahoo_autocomplete_ajax.php',
type: 'GET',
dataType: 'json',
data: {
action: 'autocjson',
symbol: symbolChar
},
success: function(response) {
$('#symbol').typeahead({
name: 'symbol',
remote: response.symbols
});
}
});
}
I don't think that I'm suppose to attach a typeahead inside an AJAX success response, but I don't see much examples with AJAX (except for a previous version of typeahead)... I see the JSON response with Firebug after typing a character but the input doesn't react so good. Any guidance would really be appreciated, I'm working on a proof of concept at this point... It's also worth to know that I'm using AJAX because I am in HTTPS and using a direct http to Yahoo API is giving all kind of problems with Chrome and new Firefox for insecure page.
UPDATE
To make it to work, thanks to Hieu Nguyen, I had to modify the AJAX JSON response from this echo json_encode(['symbols' => $result]); to instead this echo json_encode($result); and modify the JS file to use the code as suggested here:
$('#symbol').typeahead({
name: 'symbol',
remote: 'yahoo_autocomplete_ajax.php?action=autocjson&symbol=%QUERY'
});
I have to do it in reverse, i.e: hook the ajax call inside typeahead remote handler. You can try:
$('#symbol').typeahead({
name: 'symbol',
remote: '/yahoo_autocomplete_ajax.php?action=autocjson&symbol=%QUERY'
});
You don't have to create onSymbolChange() function since typeahead will take care of that already.
You can also filter and debug the response from backend by using:
$('#symbol').typeahead({
name: 'symbol',
remote: {
url: '/yahoo_autocomplete_ajax.php?action=autocjson&symbol=%QUERY',
filter: function(resp) {
var dataset = [];
console.log(resp); // debug the response here
// do some filtering if needed with the response
return dataset;
}
}
});
Hope it helps!

Errors in IE 8 from connect.facebook.net/en_US/all.js caused by credits callback

Setup:
Got a working facebook app and am correctly setup for facebook credits transactions (i.e. everything on the serverside is working fine).
In Firefox and chrome transactions complete without issue, however in IE8 the callback upon completing/closing the purchase dialog throws the following errors:
Error 1:
Line: 52 Error: Object doesn't support this property or method
Object doesn't support this property or method JScript - script block, line 52 character 37
Where the function it points to is:
ui: function( params )
{
obj = FB.JSON.parse( params );
method = obj.method;
cb = function( response ) { FBAS.getSwf().uiResponse( FB.JSON.stringify( response ), method ); }
FB.ui( obj, cb );
},
Specifically highlighting this bit:
FBAS.getSwf().uiResponse( FB.JSON.stringify( response ), method )
in the http://connect.facebook.net/en_US/all.js file
Error 2:
Line: 65 Error: Object doesn't support this action
Object doesn't support this action all.js, line 65 character 2198
[The line it points to is a stupidly long unformatted unreadable mess so I'll omit it unless requested]
Specifically highlighting this bit:
delete d._old_visibility
again in the http://connect.facebook.net/en_US/all.js file
The html I'm using (with the app identifying stuffs removed) is as follows:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="https://www.facebook.com/2008/fbml">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<meta http-equiv="Expires" content ="0" />
<meta http-equiv="Pragma" content ="no-cache" />
<meta http-equiv="Cache-Control" content ="no-cache" />
<title>[ APP NAME ]</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
</head>
<body>
<div id="fb-root"></div>
<script type="text/javascript">
$(document).ready
(
function()
{
var appId = [ APP ID ];
var host = [ APP HOST ];
// If the user did not grant the app authorization go ahead and
// tell them that. Stop code execution.
if (0 <= window.location.href.indexOf ("error_reason"))
{
$(document.body).append ("<p>Authorization denied!</p>");
return;
}
// Loads the Facebook SDK script.
(function(d)
{
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));
// When the Facebook SDK script has finished loading init the
// SDK and then get the login status of the user. The status is
// reported in the handler.
window.fbAsyncInit = function()
{
//debugger;
FB.init(
{
appId : appId,
status : true,
cookie : true,
oauth : true,
});
FB.getLoginStatus (onCheckLoginStatus);
};
// Handles the response from getting the user's login status.
// If the user is logged in and the app is authorized go ahead
// and start running the application. If they are not logged in
// then redirect to the auth dialog.
function onCheckLoginStatus (response)
{
if (response.status != "connected")
{
top.location.href = "https://www.facebook.com/dialog/oauth?client_id=" + appId + "&redirect_uri=" + encodeURIComponent (host+"[ RELATIVE APP PATH ]") + "&scope=publish_stream,user_about_me,read_friendlists,user_photos";
}
else
{
// Start the application
loadGame();
}
}
}
);
function loadGame()
{
var flashvars = {};
var params = {};
var attributes = {};
params.allowscriptaccess = "always";
attributes.id = 'flashContent';
attributes.name = 'flashContent';
swfobject.embedSWF("[ APP SWF ]?"+Math.floor(Math.random()*10000), "flashContent", "100%", "99%", "10.0", null, flashvars, params, attributes);
}
</script>
<div id="flashContent" >
Loading...
</div>
</body>
This is just a problem for IE 8 but is stopping the app going live since a significant number of users transactions would fail (or rather would complete, be charged and not take effect due to the failed callback).
For the past few days I've been searching for others with this or a similar problem but to no avail.
I've seen some similar issues where people are warned about javascript variables being created globally and causing interfereance or variables being names using keywords reserved in IE but as far as I can tell neither is the case here. The facebook javascript code is fairly boilerplate stuff lifted from facebook dev pages and reliable sources. It may be JQuery (which I have little experience with), however, again, this is lifted from working examples and if there is a problem I can't see it.
Can anyone help?
SOLVED
I won't accept this answer because I honestly don't think the question was answerable/solvable with the info provided and feel it would be bad form. But I want to leave this here for anyone that might be looking for a solution.
Cause of the error
The problem is the result of the combination of facebook hiding the app during 'normal' facebook actions (in this case, displaying the pay prompt) and external interface calls not working in Internet explorer when the app is hidden/not visible.
Solution
Found at http://flassari.is/2012/02/external-interface-error-object-expected/#comment-1743
All of these steps may not be neccessary but in the end what I did was:
Stop facebook hiding the app by overriding the visibility using
<style>
#[ ID OF THE FLASH OBJECT]
{
visibility: visible !important;
}
</style>
Adding wmode = "opaque"; to the swfobject params
Using the optional flash_hide_callback by adding hideFlashCallback:"OnHideFlash" to the FB.init options in the actionscript to move/hide the app instead, where OnHideFlash is a javascript function:
function OnHideFlash(params)
{
if (params.state == 'opened')
{
getSwf().style.top = '-10000px';
} else
{
getSwf().style.top = '';
}
}
Where getSwf() is your prefered method of getting the flash app object.
Hopefully this will save some people the suffering of pouring through the endless 'reasons that XYXY doesn't work in IE' questions and solutions that has been my last few days.
I suggest putting your code through a JavaScript Lint tool and correcting any errors you find. IE8 is extremely picky about how JavaScript is coded, while Firefox and Chrome are ok with minor mistakes. If your code is error free (after linting), it should work properly.

Facebook API - User object returning strange values

I have a user object, but it's only properties are education, first_name, id, last_name, link, locale, location, name, timezone, updated_time, verified. Not only is this missing properties that should be public (like picture), but also these values are different from the documentation (updated_time vs last_updated). Finally, strangely, I get the same thing from the link on the documentation page (here). Ultimately, I'm trying to get user.feed.
Any ideas about what's going on will be greatly appreciated. Am I missing something obvious?
visiting https://graph.facebook.com/me/feed gives the following:
{ "error": {
"type": "OAuthException",
"message": "An active access token must be used to query
information about the current user."
} }
Why do I need an active access token? the docs say that picture and feed are public!
Here is the code. The user object is logged to Firebug.console:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<script src="http://connect.facebook.net/en_US/all.js" type="text/javascript"></script>
<script type="text/javascript">
function update_user_box() {
var user_box = document.getElementById("user");
FB.api('/me', function(user) {
user_box.innerHTML = "<fb:profile-pic uid=\"loggedinuser\" useyou=\"false\"></fb:profile-pic>"
+ "Hey " + user.first_name + "<br>";
FB.XFBML.parse();
console.log(user);
});
}
</script>
</head>
<body>
<div id='user'><fb:login-button onlogin="update_user_box();"></fb:login-button></div>
<br><br>
<div id="fb-root"></div>
<script>
FB.init({
appId : 'b07e858317c9069d450023b7500b4511',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
FB.getLoginStatus(function(response) {
if (response.session) {
update_user_box();
} else {
// no user session available, someone you dont know
}
});
</script>
</body>
</html>
There are a couple of things that you can try
check if the data is matching correctly with https://graph.facebook.com/{YOUR_FB_ID}
Is there any data (that are null) needs extended permission. See here
Are you using right auth_token and oAuth2.0
I hope these will help you debugging.
Edit:
We faced a problem where we were using old API (FB-connect) and trying to get data mentioned in extended permission. We were not able to -- for some reason. We switched to oAuth2.0, and it worked. #3 bullet was just to share my experience.
Also, for photos we just fetched data from http://graph.facebook.com/{user_id}/picture
Get permission from user for offline_access.
Feed https://graph.facebook.com/{ID#username}/feed/