Finding total contributions of a user from GitHub API - github

I am trying to extract the below info for any user from GitHub.
Is there a way/API exposed in GitHub REST API where we can get this information directly?

Answers for 2019, Use GitHub API V4.
First go to GitHub to apply for a token: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line. step 7, scopes select only read:user
cUrl
curl -H "Authorization: bearer token" -X POST -d '{"query":"query {\n user(login: \"MeiK2333\") {\n name\n contributionsCollection {\n contributionCalendar {\n colors\n totalContributions\n weeks {\n contributionDays {\n color\n contributionCount\n date\n weekday\n }\n firstDay\n }\n }\n }\n }\n}"}' https://api.github.com/graphql
JavaScript
async function getContributions(token, username) {
const headers = {
'Authorization': `bearer ${token}`,
}
const body = {
"query": `query {
user(login: "${username}") {
name
contributionsCollection {
contributionCalendar {
colors
totalContributions
weeks {
contributionDays {
color
contributionCount
date
weekday
}
firstDay
}
}
}
}
}`
}
const response = await fetch('https://api.github.com/graphql', { method: 'POST', body: JSON.stringify(body), headers: headers })
const data = await response.json()
return data
}
const data = await getContributions('token', 'MeiK2333')
console.log(data)

Yes, You can do this easily with the new graphql API
Check out the explorer: https://developer.github.com/v4/explorer/
There you can see the contributions collection which is an edge of the user. You can get all of the information necessary to rebuild the calendar.
I've included a full example, and the explorer documentation can guide you even further.
Specifically to answer your question, the query.user.contributionsCollection.contributionsCalendar.totalContributions
is what you are looking for
Go ahead and copy/paste the following into the explorer and you will see my contribution history for the last year
query {
user(login: "qhenkart") {
email
createdAt
contributionsCollection(from: "2019-09-28T23:05:23Z", to: "2020-09-28T23:05:23Z") {
contributionCalendar {
totalContributions
weeks {
contributionDays {
weekday
date
contributionCount
color
}
}
months {
name
year
firstDay
totalWeeks
}
}
}
}
}

To load the svg with all contributions you can use this code in your html page
<img src="https://ghchart.rshah.org/username" alt="Name Your Github chart">
To customize color you can just do that
<img src="https://ghchart.rshah.org/HEXCOLORCODE/username" alt="Name Your Github chart">
HEXCOLORCODE = 17A2B8

You can use the github events api for that:
Example (node.js)
const got = require('got')
async function getEvents(username) {
const events = []
let page = 1
do {
const url = `https://api.github.com/users/${username}/events?page=${page}`
var { body } = await got(url, {
json: true
})
page++
events.push(...body)
} while(!body.length)
return events
}
(async () => {
const events = await getEvents('handtrix')
console.log('Overall Events', events.length)
console.log('PullRequests', events.filter(event => event.type === 'PullRequestEvent').length)
console.log('Forks', events.filter(event => event.type === 'ForkEvent').length)
console.log('Issues', events.filter(event => event.type === 'IssuesEvent').length)
console.log('Reviews', events.filter(event => event.type === 'PullRequestReviewEvent').length)
})()
Example (javascript)
async function getEvents(username) {
const events = []
let page = 1
do {
const url = `https://api.github.com/users/${username}/events?page=${page}`
var body = await fetch(url).then(res => res.json())
page++
events.push(...body)
} while(!body.length)
return events
}
(async () => {
const events = await getEvents('handtrix')
console.log('Overall Events', events.length)
console.log('PullRequests', events.filter(event => event.type === 'PullRequestEvent').length)
console.log('Forks', events.filter(event => event.type === 'ForkEvent').length)
console.log('Issues', events.filter(event => event.type === 'IssuesEvent').length)
console.log('Reviews', events.filter(event => event.type === 'PullRequestReviewEvent').length)
})()
Documentation
https://developer.github.com/v3/activity/events/
https://developer.github.com/v3/activity/events/types/
https://www.npmjs.com/package/got

You can get the svg calendar from https://github.com/users/<USER>/contributions with to URL parameter like :
https://github.com/users/bertrandmartel/contributions?to=2016-12-31
You can use a basic xml parser to sum all the contributions from the svg.
An example with curl & xmlstarlet for year 2016:
curl -s "https://github.com/users/bertrandmartel/contributions?to=2016-12-31" | \
xmlstarlet sel -t -v "sum(//svg/g/g/rect/#data-count)"

I believe you can see count of contributions in a timeframe as well as other individual contributor analytics within Code Climate’s Velocity git analytics, which you may request access to here: https://go.codeclimate.com/velocity-free-for-teams

You could use this function to extract the contributions from the last year (client):
function getContributions(){
const svgGraph = document.getElementsByClassName('js-calendar-graph')[0];
const daysRects = svgGraph.getElementsByClassName('day');
const days = [];
for (let d of daysRects){
days.push({
date: d.getAttribute('data-date'),
count: d.getAttribute('data-count')
});
}
return days;
}
I've also written a small node module which can 'extract' the contributions
#simonwep/github-contributions
Maybe this will help you (even I'm 4 years to late)

If you would prefer a npm package, you can try this.
https://github.com/SammyRobensParadise/github-contributions-counter#readme
You can get all time contributions or contributions by each year.

Related

Using POST in terminal for MongoDB returns ObjectParameterError

I just started learning about MongoDB and Node.js and was confused about this error. I created this app through the next.js template.
The error I am getting is
error - ObjectParameterError: Parameter "obj" to Document() must be an object, got {"title":"X","content":"XXX"}
Where I tried inserting the data through this line on my terminal
curl -X POST -d '{"title":"X","content":"XXX"}' -H 'Content-Type: application/json' localhost:3000/api/blogs/articles
Here is the code...
import { connect, model, models, Schema } from "mongoose"
const connectionString = 'mongodb+srv://user1:2bhEHe22GdtH1idX#cluster0.t27tcax.mongodb.net/blogs'
export default async function handler(req, res) {
await connect(connectionString);
console.log("req.method: ", req.method)
if (req.method === 'GET') {
const docs = await Article.find()
res.status(200).json(docs)
} else if (req.method === 'POST') {
console.log(req.body)
res.status(200).json(req.body)
// const doc = await Article.create(req.body)
// res.status(201).json(doc)
} else {
res.setHeader('Allow', ['GET', 'POST'])
res.status(405).end(`Method ${req.method} Not Allowed`)
}
}
const articleSchema = new Schema({
title: String,
content: String,
});
console.log("Mongoose Models", models)
const Article = models?.article || model('article', articleSchema);
I've took a look at a similar post (Saving data into MongoDb returns an ObjectParameterError) and it seems that all I've already implemented their fixes. Thank you for any help you can give.

Cannot read property 'Authorization' of undefined with Nuxt Auth & Axios

I have been using nuxt/auth-next and axios modules with nuxt project since last 3-4 months, everything was working fine since yesterday but now whenever I try to send axios request to public APIs without passing Authorization in headers, I get this error
Cannot read property 'Authorization' of undefined with Nuxt Auth & Axios
Attached is a screenshot of the page
below is my code in index.js store file
export const actions = {
async nuxtServerInit({ commit }, context) {
// Public profile
if (context.route.params && context.route.params.subdomain) {
context.$axios.onRequest((config) => {
config.progress = false
})
let { data } = await context.$axios.get(
`users/get_user_data_using_subdomain/${context.route.params.subdomain}`,
{
headers: {
'Content-Type': 'multipart/form-data',
},
}
)
await context.store.dispatch('artists/setPublicProfile', data.user_data)
}
},
}
This happend to me to when I was using context.app.$axios instead of context.$axios within a injection
Nuxt server is looking for config.headers.common.Authorization.
The example below is a quick win for you:
let { data } = await context.$axios.get(
`users/get_user_data_using_subdomain/${context.route.params.subdomain}`,
{
headers: {
common: null, // or something like this: context.$axios.defaults.headers?.common
'Content-Type': 'multipart/form-data',
},
}
)

Facebook photo upload date timestamp

I've downloaded all my Facebook data and wish to upload some of the images that I've sent via Messenger to Google Photos. I wish to have them to have the correct metadata so they are uploaded under the correct day, not under today. Unfortunately, they have the date of download for Date created.
I tried parsing the title, but it doesn't seem to be a timestamp.
My question is: is there a way to create a script that adds the correct metadata to a photo downloaded from Facebook (via Download your information archive)? An example title is: 142666616_209126620919024_535058535265435125_n.jpg. This photo should have the date Jan 27, 2021, 10:53 AM.
After some digging I found a solution.
The archive that Facebook gives you has folders for each friend with the following structure:
\friend_name_a1b2c3
\photos
12345678_123456788996_123124421.jpg
\gifs
\audio
messages_1.json
messages_1.json has all your messages with that friend and here is an example how a message looks like:
{
"sender_name": "Your Name",
"timestamp_ms": 1562647443588,
"photos": [
{
"uri": "messages/inbox/friend_name_a1b2c3/photos/12345678_123456788996_123124421.jpg",
"creation_timestamp": 1562647443
}
],
"type": "Generic",
"is_unsent": false
},
So, using glob and utimes I came up with the following script:
var glob = require("glob")
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require("fs"));
var { utimes } = require("utimes");
const readJSONFiles = async () => {
const messagesFiles = glob.sync(`**/message_*.json`)
const promises = [];
messagesFiles.forEach(mFile => {
promises.push(fs.readFileAsync(mFile, 'utf8'));
})
return Promise.all(promises);
}
readJSONFiles().then(result => {
const map = {};
result.forEach(data => {
const messagesContents = JSON.parse(data);
messagesContents.messages
.filter(m => m.photos)
.forEach(m => {
m.photos.filter(p => {
const splitted = p.uri.split("/")
const messagePhotoFileName = splitted[splitted.length - 1];
map[messagePhotoFileName] = m.timestamp_ms;
})
})
})
fs.writeFileSync("./map.json", JSON.stringify(map))
}).then(() => {
fs.readFileAsync("./map.json", 'utf8').then(data => {
const map = JSON.parse(data);
glob("**/*.jpg", function (er, files) {
files.forEach(file => {
const [, , photo] = file.split("/");
utimes(file, {
btime: map[photo],
atime: map[photo],
mtime: map[photo]
});
})
})
})
});
It creates a map of file-name:date-taken then loops over all .jpg files and changes its metadata. It definitely is a little rough around the edges but gets the job done, after all.

facebook messenger bot encoding error

I have written sample echo message bot using facebook messenger api and wit.ai actions.
My message from facebook page is received and the proper action function defined using wit api's is also getting called. However
while returning the response, i am getting followin error as -
Oops! An error occurred while forwarding the response to : Error: (#100) Param message[text] must be a UTF-8 encoded string
at fetch.then.then.json (/app/index.js:106:13)
at process._tickCallback (internal/process/next_tick.js:103:7)
Here is the function which is used to return the response -
const fbMessage = (id, text) => {
const body = JSON.stringify({
recipient: { id },
message: { text },
});
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_ACCESS_TOKEN);
return fetch('https://graph.facebook.com/v2.6/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json; charset=UTF-8'},
body
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);`enter code here`
}
return json;
});
};
I have copied this function from the messenger.js file from the documentation since i am just trying the POC.
I checked the values for text and id in this function and verified using console.log statements and those are coming properly.
Can some experts help me to solve this error?
Note - I tried encoding the text using text.toString("utf8"); but it returns the encoding string as [object object] and thats the
response i get from bot. so it doesnt work.
Get the latest code from node-wit, there is a change in facebook id usage,
According to Facebook:
On Tue May 17 format of user and page ids delivered via webhooks will
change from an int to a string to better support default json encoder
in js (that trims long ints). Please make sure your app works with
string ids returned from webhooks as well as with ints.
Still you are getting issue with the api try to add if(event.message && !event.message.is_echo) condition as shown in below code.
// Message handler
app.post('/webhook', (req, res) => {
const data = req.body;
if (data.object === 'page') {
data.entry.forEach(entry => {
entry.messaging.forEach(event => {
if (event.message && !event.message.is_echo) {
const sender = event.sender.id;
const sessionId = findOrCreateSession(sender);
const {text, attachments} = event.message;
if (attachments) {
fbMessage(sender, 'Sorry I can only process text messages for now.')
.catch(console.error);
} else if (text) {
wit.runActions(
sessionId, // the user's current session
text, // the user's message
sessions[sessionId].context // the user's current session state
).then((context) => {
console.log('Waiting for next user messages');
sessions[sessionId].context = context;
})
.catch((err) => {
console.error('Oops! Got an error from Wit: ', err.stack || err);
})
}
} else {
console.log('received event', JSON.stringify(event));
}
});
});
}
res.sendStatus(200);
});
Reference:
no matching user bug
no matching user fix

How to make remote REST call inside Node.js? any CURL?

In Node.js, other than using child process to make CURL call, is there a way to make CURL call to remote server REST API and get the return data?
I also need to set up the request header to the remote REST call, and also query string as well in GET (or POST).
I find this one: http://blog.nodejitsu.com/jsdom-jquery-in-5-lines-on-nodejs
but it doesn't show any way to POST query string.
Look at http.request
var options = {
host: url,
port: 80,
path: '/resource?id=foo&bar=baz',
method: 'POST'
};
http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
}).end();
How about using Request — Simplified HTTP client.
Edit February 2020: Request has been deprecated so you probably shouldn't use it any more.
Here's a GET:
var request = require('request');
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body) // Print the google web page.
}
})
OP also wanted a POST:
request.post('http://service.com/upload', {form:{key:'value'}})
I use node-fetch because it uses the familiar (if you are a web developer) fetch() API. fetch() is the new way to make arbitrary HTTP requests from the browser.
Yes I know this is a node js question, but don't we want to reduce the number of API's developers have to memorize and understand, and improve re-useability of our javascript code? Fetch is a standard so how about we converge on that?
The other nice thing about fetch() is that it returns a javascript Promise, so you can write async code like this:
let fetch = require('node-fetch');
fetch('http://localhost', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: '{}'
}).then(response => {
return response.json();
}).catch(err => {console.log(err);});
Fetch superseeds XMLHTTPRequest. Here's some more info.
Look at http://isolasoftware.it/2012/05/28/call-rest-api-with-node-js/
var https = require('https');
/**
* HOW TO Make an HTTP Call - GET
*/
// options for GET
var optionsget = {
host : 'graph.facebook.com', // here only the domain name
// (no http/https !)
port : 443,
path : '/youscada', // the rest of the url with parameters if needed
method : 'GET' // do GET
};
console.info('Options prepared:');
console.info(optionsget);
console.info('Do the GET call');
// do the GET request
var reqGet = https.request(optionsget, function(res) {
console.log("statusCode: ", res.statusCode);
// uncomment it for header details
// console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('GET result:\n');
process.stdout.write(d);
console.info('\n\nCall completed');
});
});
reqGet.end();
reqGet.on('error', function(e) {
console.error(e);
});
/**
* HOW TO Make an HTTP Call - POST
*/
// do a POST request
// create the JSON object
jsonObject = JSON.stringify({
"message" : "The web of things is approaching, let do some tests to be ready!",
"name" : "Test message posted with node.js",
"caption" : "Some tests with node.js",
"link" : "http://www.youscada.com",
"description" : "this is a description",
"picture" : "http://youscada.com/wp-content/uploads/2012/05/logo2.png",
"actions" : [ {
"name" : "youSCADA",
"link" : "http://www.youscada.com"
} ]
});
// prepare the header
var postheaders = {
'Content-Type' : 'application/json',
'Content-Length' : Buffer.byteLength(jsonObject, 'utf8')
};
// the post options
var optionspost = {
host : 'graph.facebook.com',
port : 443,
path : '/youscada/feed?access_token=your_api_key',
method : 'POST',
headers : postheaders
};
console.info('Options prepared:');
console.info(optionspost);
console.info('Do the POST call');
// do the POST call
var reqPost = https.request(optionspost, function(res) {
console.log("statusCode: ", res.statusCode);
// uncomment it for header details
// console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('POST result:\n');
process.stdout.write(d);
console.info('\n\nPOST completed');
});
});
// write the json data
reqPost.write(jsonObject);
reqPost.end();
reqPost.on('error', function(e) {
console.error(e);
});
/**
* Get Message - GET
*/
// options for GET
var optionsgetmsg = {
host : 'graph.facebook.com', // here only the domain name
// (no http/https !)
port : 443,
path : '/youscada/feed?access_token=you_api_key', // the rest of the url with parameters if needed
method : 'GET' // do GET
};
console.info('Options prepared:');
console.info(optionsgetmsg);
console.info('Do the GET call');
// do the GET request
var reqGet = https.request(optionsgetmsg, function(res) {
console.log("statusCode: ", res.statusCode);
// uncomment it for header details
// console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('GET result after POST:\n');
process.stdout.write(d);
console.info('\n\nCall completed');
});
});
reqGet.end();
reqGet.on('error', function(e) {
console.error(e);
});
Axios
An example (axios_example.js) using Axios in Node.js:
const axios = require('axios');
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
app.get('/search', function(req, res) {
let query = req.query.queryStr;
let url = `https://your.service.org?query=${query}`;
axios({
method:'get',
url,
auth: {
username: 'the_username',
password: 'the_password'
}
})
.then(function (response) {
res.send(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
});
var server = app.listen(port);
Be sure in your project directory you do:
npm init
npm install express
npm install axios
node axios_example.js
You can then test the Node.js REST API using your browser at: http://localhost:5000/search?queryStr=xxxxxxxxx
Similarly you can do post, such as:
axios({
method: 'post',
url: 'https://your.service.org/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
SuperAgent
Similarly you can use SuperAgent.
superagent.get('https://your.service.org?query=xxxx')
.end((err, response) => {
if (err) { return console.log(err); }
res.send(JSON.stringify(response.body));
});
And if you want to do basic authentication:
superagent.get('https://your.service.org?query=xxxx')
.auth('the_username', 'the_password')
.end((err, response) => {
if (err) { return console.log(err); }
res.send(JSON.stringify(response.body));
});
Ref:
https://github.com/axios/axios
https://www.twilio.com/blog/2017/08/http-requests-in-node-js.html
I have been using restler for making webservices call, works like charm and is pretty neat.
To use latest Async/Await features
https://www.npmjs.com/package/request-promise-native
npm install --save request
npm install --save request-promise-native
//code
async function getData (){
try{
var rp = require ('request-promise-native');
var options = {
uri:'https://reqres.in/api/users/2',
json:true
};
var response = await rp(options);
return response;
}catch(error){
throw error;
}
}
try{
console.log(getData());
}catch(error){
console.log(error);
}
Warning: As of Feb 11th 2020, request is fully deprecated.
One another example - you need to install request module for that
var request = require('request');
function get_trustyou(trust_you_id, callback) {
var options = {
uri : 'https://api.trustyou.com/hotels/'+trust_you_id+'/seal.json',
method : 'GET'
};
var res = '';
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
res = body;
}
else {
res = 'Not Found';
}
callback(res);
});
}
get_trustyou("674fa44c-1fbd-4275-aa72-a20f262372cd", function(resp){
console.log(resp);
});
const http = require('http');
const url = process.argv[2];
http.get(url, function(response) {
let finalData = "";
response.on("data", function (data) {
finalData += data.toString();
});
response.on("end", function() {
console.log(finalData.length);
console.log(finalData.toString());
});
});
I didn't find any with cURL so I wrote a wrapper around node-libcurl and can be found at https://www.npmjs.com/package/vps-rest-client.
To make a POST is like so:
var host = 'https://api.budgetvm.com/v2/dns/record';
var key = 'some___key';
var domain_id = 'some___id';
var rest = require('vps-rest-client');
var client = rest.createClient(key, {
verbose: false
});
var post = {
domain: domain_id,
record: 'test.example.net',
type: 'A',
content: '111.111.111.111'
};
client.post(host, post).then(function(resp) {
console.info(resp);
if (resp.success === true) {
// some action
}
client.close();
}).catch((err) => console.info(err));
If you have Node.js 4.4+, take a look at reqclient, it allows you to make calls and log the requests in cURL style, so you can easily check and reproduce the calls outside the application.
Returns Promise objects instead of pass simple callbacks, so you can handle the result in a more "fashion" way, chain the result easily, and handle errors in a standard way. Also removes a lot of boilerplate configurations on each request: base URL, time out, content type format, default headers, parameters and query binding in the URL, and basic cache features.
This is an example of how to initialize it, make a call and log the operation with curl style:
var RequestClient = require("reqclient").RequestClient;
var client = new RequestClient({
baseUrl:"http://baseurl.com/api/", debugRequest:true, debugResponse:true});
client.post("client/orders", {"client": 1234, "ref_id": "A987"},{"x-token": "AFF01XX"});
This will log in the console...
[Requesting client/orders]-> -X POST http://baseurl.com/api/client/orders -d '{"client": 1234, "ref_id": "A987"}' -H '{"x-token": "AFF01XX"}' -H Content-Type:application/json
And when the response is returned ...
[Response client/orders]<- Status 200 - {"orderId": 1320934}
This is an example of how to handle the response with the promise object:
client.get("reports/clients")
.then(function(response) {
// Do something with the result
}).catch(console.error); // In case of error ...
Of course, it can be installed with: npm install reqclient.
You can use curlrequest to easily set what time of request you want to do... you can even set headers in the options to "fake" a browser call.
Warning: As of Feb 11th 2020, request is fully deprecated.
If you implement with form-data, for more info (https://tanaikech.github.io/2017/07/27/multipart-post-request-using-node.js):
var fs = require('fs');
var request = require('request');
request.post({
url: 'https://slack.com/api/files.upload',
formData: {
file: fs.createReadStream('sample.zip'),
token: '### access token ###',
filetype: 'zip',
filename: 'samplefilename',
channels: 'sample',
title: 'sampletitle',
},
}, function (error, response, body) {
console.log(body);
});
I found superagent to be really useful,
it is very simple
for example
const superagent=require('superagent')
superagent
.get('google.com')
.set('Authorization','Authorization object')
.set('Accept','application/json')
Update from 2022:
from node.js version v18 on you can use the globally available fetch API (see https://nodejs.org/en/blog/announcements/v18-release-announce/)
There is also an example usage included on their announcement page:
const res = await fetch('https://nodejs.org/api/documentation.json');
if (res.ok) {
const data = await res.json();
console.log(data);
}