initial commit

This commit is contained in:
zyachel 2022-04-17 17:54:23 +05:30
commit bf4ee2c3cf
54 changed files with 7101 additions and 0 deletions

51
fetchers/fetcher.js Normal file
View file

@ -0,0 +1,51 @@
/* eslint-disable no-useless-catch */
////////////////////////////////////////////////////////
// IMPORTS
////////////////////////////////////////////////////////
import * as cheerio from 'cheerio';
import axiosInstance from '../utils/axiosInstance.js';
import AppError from '../utils/AppError.js';
////////////////////////////////////////////////////////
// FUNCTION
////////////////////////////////////////////////////////
/**
*
* @param {string} resourceStr a string after the baseURL
* @returns JSON containing the result
* @description makes a call to quora.com(with the resourceStr appended) and returns parsed JSON containing the data about the resource requested.
* @example await fetcher('What-is-free-and-open-software'); // will return object containing answers
* await fetcher('topic/Space-Physics'); // will return 'space physics' topic object
* await fetcher('profile/Charlie-Cheever'); // will return object containing information about charlie cheever
*/
const fetcher = async resourceStr => {
try {
// as url might contain unescaped chars. so, encodeing it right away
const res = await axiosInstance.get(encodeURIComponent(resourceStr));
const $ = cheerio.load(res.data);
let rawData;
$('body')
.children('script')
.each((i, el) => {
if ($(el).html() === 'window.installSettings();')
rawData = $(el)
.next()
.html()
?.match(/"\{.*\}"/m)?.[0];
});
if (!rawData) throw new Error("couldn't retrieve data");
const data = JSON.parse(rawData);
return data;
} catch (err) {
if (err.response.status === 404) throw new AppError('Not found', 404);
else throw err;
}
};
////////////////////////////////////////////////////////
// EXPORTS
////////////////////////////////////////////////////////
export default fetcher;

84
fetchers/getAnswers.js Normal file
View file

@ -0,0 +1,84 @@
////////////////////////////////////////////////////////
// IMPORTS
////////////////////////////////////////////////////////
// import log from '../utils/log.js';
import fetcher from './fetcher.js';
////////////////////////////////////////////////////////
// FUNCTION
////////////////////////////////////////////////////////
const getAnswers = async slug => {
// getting data and destructuring it in case it exists
const res = await fetcher(slug);
if (!Object.entries(res).length) throw new Error('no data received!');
const {
data: { question: rawData },
} = JSON.parse(res);
// array containing all the answers with metadata
const ansArr = rawData.pagedListDataConnection.edges
.filter(ansObj => ansObj.node.answer !== undefined)
.map(ansObj => ({
text: JSON.parse(ansObj.node.answer.content).sections,
isViewable: !!ansObj.node.answer.viewerHasAccess,
creationTime: ansObj.node.answer.creationTime,
updatedTime: ansObj.node.answer.updatedTime,
numComments: ansObj.node.answer.numDisplayComments,
numUpvotes: ansObj.node.answer.numUpvotes,
numViews: ansObj.node.answer.numViews,
numShares: ansObj.node.answer.numSharers,
numAnswerRequests: ansObj.node.answer.numRequesters,
aid: ansObj.node.answer.aid,
isBusinessAnswer: ansObj.node.answer.businessAnswer,
author: {
uid: ansObj.node.answer.author.uid,
isAnon: ansObj.node.answer.author.isAnon,
avatar: ansObj.node.answer.author.profileImageUrl,
isVerified: ansObj.node.answer.author.isVerified,
profile: ansObj.node.answer.author.profileUrl,
name: `${ansObj.node.answer.author.names[0].givenName} ${ansObj.node.answer.author.names[0].familyName}`,
credential: ansObj.node.answer.authorCredential?.translatedString,
// additionalCredentials: ansObj.node.answer?.credibilityFacts.map(),
},
OriginalQuestion: {
text: JSON.parse(ansObj.node.answer.question.title).sections[0],
url: ansObj.node.answer.question.url,
qid: ansObj.node.answer.question.qid,
isDeleted: ansObj.node.answer.question.isDeleted,
},
}));
// main data object to be returned
const data = {
question: {
text: JSON.parse(rawData.title).sections[0],
url: rawData.url,
qid: rawData.qid,
idDeleted: rawData.isDeleted,
isViewable: rawData.isVisibleToViewer,
askerUid: rawData.asker.uid,
},
numAnswers: rawData.answerCount,
answers: ansArr,
topics: rawData.topics.map(topicObj => ({
tid: topicObj.tid,
name: topicObj.name,
url: topicObj.url,
})),
relatedQuestions: rawData.bottomRelatedQuestionsInfo.relatedQuestions.map(
questionObj => ({
qid: questionObj.qid,
url: questionObj.url,
text: JSON.parse(questionObj.title).sections[0],
})
),
};
return data;
};
////////////////////////////////////////////////////////
// EXPORTS
////////////////////////////////////////////////////////
export default getAnswers;