//Setup export default async function({login, q, imports, data, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met if ((!enabled) || (!q.stackoverflow)) return null //Load inputs let {sections, user, limit, lines, "lines.snippet": codelines} = imports.metadata.plugins.stackoverflow.inputs({data, account, q}) if (!user) throw {error: {message: "You must provide a stackoverflow user id"}} //Initialization //See https://api.stackexchange.com/docs const api = {base: "https://api.stackexchange.com/2.2", user: `https://api.stackexchange.com/2.2/users/${user}`} const filters = {user: "!0Z-LvgkLYnTCu1858)*D0lcx2", answer: "!7goY5TLWwCz.BaGpe)tv5C6Bks2q8siMH6", question: "!)EhwvzgX*hrClxjLzqxiZHHbTPRE5Pb3B9vvRaqCx5-ZY.vPr"} const result = {sections, lines} //Stackoverflow user metrics { //Account metrics console.debug(`metrics/compute/${login}/plugins > stackoverflow > querying api for user ${user}`) const {data: {items: [{reputation, badge_counts: {bronze, silver, gold}, answer_count: answers, question_count: questions, view_count: views}]}} = await imports.axios.get(`${api.user}?site=stackoverflow&filter=${filters.user}`) const {data: {total: comments}} = await imports.axios.get(`${api.user}/comments?site=stackoverflow&filter=total`) //Save result result.user = {id: user, reputation, badges: bronze + silver + gold, questions, answers, comments, views} } //Answers for (const {key, sort} of [{key: "answers-recent", sort: "sort=activity&order=desc"}, {key: "answers-top", sort: "sort=votes&order=desc"}].filter(({key}) => sections.includes(key))) { //Load and format answers console.debug(`metrics/compute/${login}/plugins > stackoverflow > querying api for ${key}`) const {data: {items}} = await imports.axios.get(`${api.user}/answers?site=stackoverflow&pagesize=${limit}&filter=${filters.answer}&${sort}`) result[key] = await Promise.all(items.map(item => format.answer(item, {imports, codelines}))) console.debug(`metrics/compute/${login}/plugins > stackoverflow > loaded ${result[key].length} items`) //Load related questions const ids = result[key].map(({question_id}) => question_id).filter(id => id) if (ids) { console.debug(`metrics/compute/${login}/plugins > stackoverflow > loading ${ids.length} related items`) const {data: {items}} = await imports.axios.get(`${api.base}/questions/${ids.join(";")}?site=stackoverflow&filter=${filters.question}`) await Promise.all(items.map(item => format.question(item, {imports, codelines}))) } } //Questions for (const {key, sort} of [{key: "questions-recent", sort: "sort=activity&order=desc"}, {key: "questions-top", sort: "sort=votes&order=desc"}].filter(({key}) => sections.includes(key))) { //Load and format questions console.debug(`metrics/compute/${login}/plugins > stackoverflow > querying api for ${key}`) const {data: {items}} = await imports.axios.get(`${api.user}/questions?site=stackoverflow&pagesize=${limit}&filter=${filters.question}&${sort}`) result[key] = await Promise.all(items.map(item => format.question(item, {imports, codelines}))) console.debug(`metrics/compute/${login}/plugins > stackoverflow > loaded ${result[key].length} items`) //Load related answers const ids = result[key].map(({accepted_answer_id}) => accepted_answer_id).filter(id => id) if (ids) { console.debug(`metrics/compute/${login}/plugins > stackoverflow > loading ${ids.length} related items`) const {data: {items}} = await imports.axios.get(`${api.base}/answers/${ids.join(";")}?site=stackoverflow&filter=${filters.answer}`) await Promise.all(items.map(item => format.answer(item, {imports, codelines}))) } } //Results return result } //Handle errors catch (error) { if (error.error?.message) throw error throw {error: {message: "An error occured", instance: error}} } } //Formatters const format = { /**Cached */ cached: new Map(), /**Format stackoverflow code snippets */ code(text) { return text.replace(/\s*(? {4}[\s\S]+?)(?=(?:)|(?: