Skip to content

Instantly share code, notes, and snippets.

@johnnyreilly
Created November 17, 2023 07:30
Show Gist options
  • Save johnnyreilly/3e962ac5e97098c12526f9942f22d4a9 to your computer and use it in GitHub Desktop.
Save johnnyreilly/3e962ac5e97098c12526f9942f22d4a9 to your computer and use it in GitHub Desktop.
Get your MVP data for your records

MVP Application

Get your data from the API and write it to a file.

Read index.js for more information.

To run this:

  • Get a token from https://mvp.microsoft.com/en-US/mvp/apply
    • log in and then open the dev tools and look for the Authorization request header which will contain a token in the network tab
  • Run the following command to set the token in the environment variable
    • export TOKEN=token-goes-here (different syntax for Windows)
  • Install Node.js, update index.js with your email address
  • Run npm i && npm start and look for the mvp-application-full.json.
{
"name": "mvp-application-data",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"@types/node": "^20.9.0",
"axios": "^1.6.2",
"typescript": "^5.2.2"
}
}
const crypto = require("crypto");
const https = require("https");
const fs = require("fs");
const axios = require("axios");
/**
* Handle this problem with Node 18
* write EPROTO B8150000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled
* see https://stackoverflow.com/questions/74324019/allow-legacy-renegotiation-for-nodejs/74600467#74600467
**/
const allowLegacyRenegotiationforNodeJsOptions = {
httpsAgent: new https.Agent({
// for self signed you could also add
// rejectUnauthorized: false,
// allow legacy server
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
}),
};
// Get a token from https://mvp.microsoft.com/en-US/mvp/apply
// - log in and then open the dev tools and look for the Authorization request header which will contain a token in the network tab
//
// Run the following command to set the token in the environment variable
// export TOKEN=token-goes-here
const token = process.env.TOKEN;
// https://mavenapi-prod.azurewebsites.net/api/mvp/ApplicationForm/johnny_reilly@hotmail.com
// applicationForm.id = 316008
// https://mavenapi-prod.azurewebsites.net/api/ApplicationForm/ActivitiesEvents/316008
// https://mavenapi-prod.azurewebsites.net/api/Activities/154327
// https://mavenapi-prod.azurewebsites.net/api/Events/GetEvent/20971
const primedAxios = axios.default.create({
...allowLegacyRenegotiationforNodeJsOptions,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
authorization: `Bearer ${token}`,
},
});
/**
* @param {string} email - eg johnny_reilly@hotmail.com
*/
async function getMvpApplication(email) {
console.log(`Getting application for ${email}`);
const applicationFormResponse = await primedAxios({
url: `https://mavenapi-prod.azurewebsites.net/api/mvp/ApplicationForm/${email}`,
});
const applicationForm = applicationFormResponse.data;
console.log(`Getting activities and events for ${email}`);
const activitiesEventsResponse = await primedAxios({
url: `https://mavenapi-prod.azurewebsites.net/api/ApplicationForm/ActivitiesEvents/${applicationForm.applicationForm.id}`,
});
/**
* @type {{mappedEvents: import("./types").MvpEvent[], mappedActivities: import("./types").MvpActivity[]}}
*/
const { mappedEvents, mappedActivities } = activitiesEventsResponse.data;
/** @type{import("./types").MvpEvent[]} */
const events = [];
for (const mappedEvent of mappedEvents) {
console.log(`Getting event ${mappedEvent.eventId}`);
const eventResponse = await primedAxios({
url: `https://mavenapi-prod.azurewebsites.net/api/Events/GetEvent/${mappedEvent.eventId}`,
});
const event = eventResponse.data;
events.push(event);
}
/** @type{import("./types").MvpActivity[]} */
const activities = [];
for (const mappedActivity of mappedActivities) {
console.log(`Getting activity ${mappedActivity.activityId}`);
const activityResponse = await primedAxios({
url: `https://mavenapi-prod.azurewebsites.net/api/Activities/${mappedActivity.activityId}`,
});
const activity = activityResponse.data;
activities.push(activity);
}
const fullData = {
applicationForm,
activities,
events,
};
// Save file to disk
fs.writeFileSync("mvp-application-full.json", JSON.stringify(fullData, null, 2));
}
getMvpApplication("johnny_reilly@hotmail.com");
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
/* JavaScript Support */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
"checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
"allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
export interface MvpEvent {
id: number;
eventId: number;
eventIdentifier: string;
questionId: number;
applicationId: number;
title: string;
}
export interface MvpActivity {
id: number;
activityId: number;
questionId: number;
applicationId: number;
title: string;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment