Advertisement
Guest User

Untitled

a guest
May 4th, 2018
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.09 KB | None | 0 0
  1. const fetch = require("node-fetch");
  2. const prompt = require("prompt");
  3. const puppeteer = require("puppeteer");
  4. const createToken = require("github-create-token");
  5.  
  6. // Tools used to create the .csv with the datas that we recuperate from the several git projects (name of projects and number of issues)
  7. const fs = require("fs");
  8. const csvWriter = require("csv-write-stream");
  9. const writer = csvWriter({ headers: ["PROJECT", "ISSUES"] });
  10. writer.pipe(fs.createWriteStream("issues.csv"));
  11.  
  12. // Urls used to recuperate the name of the projects on waffle.
  13. const urls = {
  14. login:
  15. "https://github.com/login?client_id=b68f04bdff231220a275&return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3Db68f04bdff231220a275%26redirect_uri%3Dhttps%253A%252F%252Fwaffle.io%252Fgithub-callback%26response_type%3Dcode%26scope%3Dread%253Aorg%252Cuser%253Aemail%252Crepo%26state%3DyLWJntH29IyHBDMZFgcoPom4",
  16. projectsPage:
  17. "https://waffle.io/inextensodigital/emeabridge.eu/settings/sources"
  18. };
  19.  
  20. // Same use as the urls above.
  21. const selectors = {
  22. login: "#login_field",
  23. password: "#password",
  24. submit: '[name="commit"]',
  25. openMenu: ".buttons > li > a",
  26. goToWaffleInextensodigital: ".button.private.js-private-login",
  27. projects:
  28. ".well.project-source.settings-list-item.ng-scope.ng-isolate-scope > div > span",
  29. errorConnectionMessage: ".flash.flash-full.flash-error"
  30. };
  31.  
  32. /*
  33. Access token permitting the authentication to the account with the following mail : 'vincent.mazel@etu.univ-amu.fr'.
  34. However, this token shouldn't be here and should be generated each type the program is launched or stocked in a database for a security question.
  35.  
  36. Solution --> stocker dans une base de données. Quand on lance le programme, on rentre id et password. On va check dans la bd pour voir si ya un token.
  37. Si oui c'est cool, sinon on en crée un tj avec le même nom (genre graphql_dashboard). Et hop, le tour est joué : pas de compte ni de token en dur dans le code.
  38. */
  39. let accessToken = "5ba612b28a01387c9e6f81cf2740b4b92b370844"; // a35c660cf1a14131057e7047384908c924c6b5aa
  40.  
  41. // Options used for the generation of a github token.
  42. let opts = {
  43. username: "",
  44. password: "",
  45. scopes: ["repo"],
  46. note: "dashboard_token"
  47. };
  48.  
  49. // Labels of the several issues that we recuperate.
  50. const labels = [
  51. '"ideas"',
  52. '"backlog"',
  53. '"priorisation"',
  54. '"definition"',
  55. '"proposal"',
  56. '"acceptance"',
  57. '"in progress"'
  58. ];
  59.  
  60. // A variable that will be useful later when we'll have to make a graphql request to recuperate the number of issues done.
  61. let query = `query {`;
  62.  
  63. // The configuration of the prompt.
  64. const schema = {
  65. properties: {
  66. email: {
  67. description: "Enter your email",
  68. type: "string",
  69. required: true
  70. },
  71. password: {
  72. description: "Enter your password",
  73. type: "string",
  74. required: true,
  75. hidden: true,
  76. replace: "*"
  77. }
  78. }
  79. };
  80.  
  81. /*
  82. Asking here the email and password in order to connect on waffle and recuperate the name of
  83. the several ongoing projects.
  84. */
  85.  
  86. prompt.start();
  87.  
  88. console.log(
  89. "\n" +
  90. "Enter your github email and password to automaticaly recuperate the projects on waffle : " +
  91. "\n"
  92. );
  93.  
  94. prompt.get(schema, function(err, result) {
  95. (async () => {
  96. const browser = await puppeteer.launch({
  97. headless: false,
  98. args: [
  99. "--no-sandbox",
  100. "--disable-setuid-sandbox",
  101. "--disable-dev-shm-usage"
  102. ]
  103. });
  104.  
  105. // Init page
  106. const page = await browser.newPage();
  107. await page.setViewport({ width: 1200, height: 900 });
  108.  
  109. await page.goto(urls.login, {
  110. waitUntil: "networkidle0"
  111. });
  112.  
  113. await page.type(selectors.login, "vincent.mazel@etu.univ-amu.fr"); // result.email
  114. await page.type(selectors.password, "newyorkciti17"); // result.password
  115. await page.click(selectors.submit);
  116.  
  117. await page.waitForNavigation({ waitUntil: "networkidle0" });
  118. await page.waitFor(2000);
  119.  
  120. /* if (
  121. await page.evaluate(async s => {
  122. console.log(
  123. document.body.contains(
  124. document.querySelector(s.errorConnectionMessage)
  125. )
  126. );
  127. return document.body.contains(
  128. document.querySelector(s.errorConnectionMessage)
  129. );
  130. }, selectors)
  131. ) */
  132.  
  133. if (
  134. await page.evaluate(async s => {
  135. console.log(
  136. document.body.contains(
  137. document.querySelector(s.errorConnectionMessage)
  138. )
  139. );
  140. return document.body.contains(
  141. document.querySelector(s.errorConnectionMessage)
  142. );
  143. }, selectors)
  144. ) {
  145. console.log("\n" + "Wrong username or password, be careful !" + "\n");
  146. } else {
  147. console.log("1");
  148. await page.waitForSelector(selectors.openMenu);
  149. console.log("2");
  150. await page.click(selectors.openMenu);
  151. console.log("3");
  152. await page.waitForSelector(selectors.goToWaffleInextensodigital);
  153. await page.waitFor(3000);
  154.  
  155. await page.click(selectors.goToWaffleInextensodigital);
  156.  
  157. await page.waitForNavigation({ waitUntil: "networkidle2" });
  158.  
  159. await page.goto(urls.projectsPage, { waitUntil: "networkidle2" });
  160. await page.waitFor(1500);
  161.  
  162. // Recuperation of the name of the several ongoing projects.
  163. const projects = await page.evaluate(async s => {
  164. const projectsName = [];
  165. const projectsReq = document.querySelectorAll(s.projects);
  166.  
  167. projectsReq.forEach(function(thisArg) {
  168. projectsName.push(
  169. thisArg.innerHTML.substring("inextensodigital/".length)
  170. );
  171. });
  172. return projectsName;
  173. }, selectors);
  174.  
  175. // Projects are recuperated, closing of the browser.
  176. await browser.close();
  177.  
  178. // Generation of a github token.
  179. /* opts.username = result.email;
  180. opts.password = result.password;
  181.  
  182. createToken(opts, clbk);
  183.  
  184. function clbk(error, results, info) {
  185. if (info) {
  186. console.error(info);
  187. }
  188. if (error) {
  189. throw new Error(error.message);
  190. }
  191. console.log("Token : " + results.token);
  192. accessToken = results.token;
  193. } */
  194.  
  195. /*
  196. Generation of the graphql request using the query variable initialized earlier.
  197. However, it's quite important to notice here that this is quite a dirty way to recuperate our issues.
  198. Indeed, factorizing code by using fragments and variables would have been better, but I didn't manage to do it,
  199. so this solution is for the moment the best one that I can give.
  200. */
  201. for (let i = 1; i < projects.length; i += 1) {
  202. query +=
  203. `repo` +
  204. i +
  205. `: repository(owner:"inextensodigital", name:"` +
  206. projects[i] +
  207. `") {
  208. name
  209. issues(labels:[` +
  210. labels +
  211. `], first:100, states:[OPEN]) {
  212. edges {
  213. node {
  214. title
  215. }
  216. }
  217. }
  218. }`;
  219. }
  220. query += `}`;
  221.  
  222. // Sending the graphql request.
  223. fetch("https://api.github.com/graphql", {
  224. method: "POST",
  225. body: JSON.stringify({ query }),
  226. headers: {
  227. Authorization: `Bearer ${accessToken}`
  228. }
  229. })
  230. .then(res => res.text())
  231. .then(body => {
  232. const jsonObj = JSON.parse(body);
  233. let tabNameNbIssues = [];
  234. let nbIssues = 0;
  235.  
  236. Object.entries(jsonObj.data).forEach(([key, value]) => {
  237. nbIssues += value.issues.edges.length;
  238. // tabNameNbIssues[value.name] = value.issues.edges.length;
  239. writer.write([value.name, value.issues.edges.length]);
  240. tabNameNbIssues.push({
  241. projectName: value.name,
  242. nbIssues: value.issues.edges.length
  243. });
  244. });
  245. writer.end();
  246. console.log("\n" + "Number total of issues : " + nbIssues + "\n");
  247. })
  248. .catch(error => console.error(error));
  249. }
  250. })();
  251. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement