Skip to content
This repository has been archived by the owner on Aug 18, 2023. It is now read-only.

Commit

Permalink
Merge pull request #5 from muharamdani/refactor/change-from-puppeteer…
Browse files Browse the repository at this point in the history
…-to-fetch

Refactor | Change from puppeteer to fetch
  • Loading branch information
muharamdani authored Mar 7, 2023
2 parents a5b8fcf + 808b7c9 commit 3499f6b
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 1,806 deletions.
2 changes: 0 additions & 2 deletions .env.example

This file was deleted.

16 changes: 4 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
This is a CLI tool to call the Quora Poe API through GraphQL. It is a work in progress, and currently supports the following:
- Auto login using temporary email, so you don't need to use your own email/phone number.
- Semi auto login using your own email/phone number, you need to enter the OTP manually.
- Manually login using formkey and cookie, set in the .env file on FORMKEY and COOKIE.
- Chat with 4 types of bots (Sage, Claude, ChatGPT, and Dragonfly).
- Clear the chat history.

## Requirements
- NodeJS 16.0.0 or higher
- NPM

## Installation
- Copy the .env.example file to .env and fill in the required fields
- Copy the config.example.json file to config.json
- Run the following command to install the dependencies:

Expand All @@ -23,16 +25,6 @@ To start, run:
npm start
```

## Requirements

[Only for manual login]
To use this API, you will need to have the following:
- Quora-Formkey: This is obtained by **logging in** to quora.com, and open https://www.quora.com/poe_api/settings, copy the value of the formkey field.
- Cookie: 'm-b=xxxx' - This is the value of the cookie with the key m-b, which is present in the list of cookies used on quora.com, you can simply inspect cookies in Chrome, open chrome dev tools-->Application tab-->Open Cookies dropdwon .
- Put the above two in a .env file in the root directory of the project

Note: Next plan is to add stream support, so you can get tha chat responses in real time.

## TODO List
- [ ] Add support for relogin after session expires
- [ ] Add stream support
Expand Down
14 changes: 14 additions & 0 deletions dist/credential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import fetch from 'cross-fetch';
export const scrape = async () => {
const _pb = await fetch("https://poe.com/login"), pbCookie = _pb.headers.get("set-cookie")?.split(";")[0];
const _setting = await fetch('https://poe.com/api/settings', { headers: { cookie: `${pbCookie}` } });
if (_setting.status !== 200)
throw new Error("Failed to fetch token");
const appSettings = await _setting.json(), { tchannelData: { channel: channelName } } = appSettings;
return {
pbCookie,
channelName,
appSettings,
};
};
export default scrape;
104 changes: 14 additions & 90 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import prompts from "prompts";
import ora from "ora";
import * as dotenv from "dotenv";
import { readFileSync, writeFile } from "fs";
import axios from 'axios';
import { JSDOM } from 'jsdom';
import scrape from "./puppet.js";
import scrape from "./credential.js";
import * as mail from "./mail.js";
dotenv.config();
const spinner = ora({
Expand Down Expand Up @@ -35,25 +33,15 @@ class ChatBot {
this.chatId = 0;
this.bot = "";
}
async setMode(mode) {
if (mode !== "manual") {
const isFormkeyAvailable = await this.getCredentials();
if (!isFormkeyAvailable) {
await this.setCredentials();
}
}
else {
this.headers["poe-formkey"] = process.env.FORMKEY || "";
this.headers["Quora-Formkey"] = process.env.FORMKEY || "";
this.headers["Cookie"] = process.env.COOKIE || "";
}
}
async getCredentials() {
const credentials = JSON.parse(readFileSync("config.json", "utf8"));
const { quora_formkey, quora_cookie } = credentials;
console.log("FROM GET CREDENTIALS");
console.log(quora_formkey);
console.log(quora_cookie);
if (quora_formkey.length > 0 && quora_cookie.length > 0) {
formkey = quora_formkey;
pbCookie = `p-b=${quora_cookie}`;
pbCookie = quora_cookie;
// For websocket later feature
channelName = credentials.channel_name;
appSettings = credentials.app_settings;
Expand All @@ -66,19 +54,21 @@ class ChatBot {
let result = await scrape();
const credentials = JSON.parse(readFileSync("config.json", "utf8"));
credentials.quora_formkey = result.appSettings.formkey;
;
credentials.quora_cookie = result.pbCookie;
// For websocket later feature
credentials.channel_name = result.channelName;
credentials.app_settings = result.appSettings;
// set value
formkey = result.appSettings.formkey;
pbCookie = result.pbCookie;
console.log("FROM SET CREDENTIALS");
console.log(formkey);
console.log(pbCookie);
// For websocket later feature
channelName = result.channelName;
appSettings = result.appSettings;
this.headers["poe-formkey"] = formkey;
this.headers["Cookie"] = `p-b=${pbCookie}`;
this.headers["Cookie"] = pbCookie;
writeFile("config.json", JSON.stringify(credentials), function (err) {
if (err) {
console.log(err);
Expand All @@ -95,14 +85,13 @@ class ChatBot {
choices: [
{ title: "Auto [This will use temp email to get Verification Code]", value: "auto" },
{ title: "Semi-Auto [Use you own email/phone number]", value: "semi" },
{ title: "Manual [Input FORMKEY and COOKIE in .env manually]", value: "manual" },
{ title: "exit", value: "exit" }
],
});
if (mode === "exit") {
return;
process.exit(0);
}
await this.setMode(mode);
await this.setCredentials();
await this.login(mode);
}
const { bot } = await prompts({
Expand Down Expand Up @@ -187,7 +176,7 @@ class ChatBot {
await this.signInOrUp(null, email, otp_code);
}
}
else if (mode === "semi") {
else {
const { type } = await prompts({
type: "select",
name: "type",
Expand All @@ -199,7 +188,7 @@ class ChatBot {
],
});
if (type === "exit") {
return;
process.exit(0);
}
const { credentials } = await prompts({
type: "text",
Expand Down Expand Up @@ -240,9 +229,6 @@ class ChatBot {
}
spinner.stop();
}
else {
console.log("Manual mode selected");
}
}
async signInOrUp(phoneNumber, email, verifyCode) {
console.log("Signing in/up...");
Expand Down Expand Up @@ -303,65 +289,6 @@ class ChatBot {
throw e;
}
}
// DEPRECATED
async getPhoneNumber() {
const freeSmsBaseUrl = 'https://www.receivesms.co';
const url = freeSmsBaseUrl + '/active-numbers/';
let smsCodeUrl = '';
let phoneNumber = '';
let code = '';
try {
const response = await axios.get(url);
const dom = new JSDOM(response.data);
const buttons = dom.window.document.querySelectorAll('a.btn');
const phoneNumbers = [];
buttons.forEach(button => {
const phoneNumber = button.getAttribute('data-clipboard-text');
phoneNumbers.push(phoneNumber);
});
const codes = dom.window.document.querySelectorAll('td a[target="_self"]');
const phoneCodes = [];
codes.forEach(code => {
const codeText = code.getAttribute('href');
phoneCodes.push(codeText);
});
const position = Math.floor(Math.random() * phoneNumbers.length);
phoneNumber = phoneNumbers[position];
code = phoneCodes[position];
smsCodeUrl = freeSmsBaseUrl + code;
}
catch (error) {
console.log(error);
}
console.log("Your phone number: " + phoneNumber);
console.log("Your SMS code URL: " + smsCodeUrl);
return { phoneNumber, smsCodeUrl };
}
// DEPRECATED
async getOTP(smsCodeUrl) {
let latestCode = [];
try {
const res = await fetch(smsCodeUrl);
const html = await res.text();
const dom = new JSDOM(html);
const elements = dom.window.document.querySelectorAll(".col-xs-12.col-md-8");
elements.forEach((element) => {
const text = element.textContent;
if (text && text.includes("Your Poe verification code is:")) {
const code = element.querySelector(".btn1")?.getAttribute("data-clipboard-text");
if (code) {
latestCode.push(code);
}
return;
}
});
}
catch (error) {
console.log("Error:", error);
}
return latestCode;
}
// Safe
async getChatId(bot) {
try {
const { data: { chatOfBot: { chatId } } } = await this.makeRequest({
Expand All @@ -374,10 +301,9 @@ class ChatBot {
this.bot = bot;
}
catch (e) {
throw new Error("Could not get chat id, invalid formkey or cookie");
throw new Error("Could not get chat id, invalid formkey or cookie! Please remove the quora_formkey value from the config.json file and try again.");
}
}
// Safe
async clearContext() {
try {
await this.makeRequest({
Expand All @@ -389,7 +315,6 @@ class ChatBot {
throw new Error("Could not clear context");
}
}
// Safe
async sendMsg(query) {
try {
await this.makeRequest({
Expand All @@ -407,7 +332,6 @@ class ChatBot {
throw new Error("Could not send message");
}
}
// Safe
async getResponse() {
let text;
let state;
Expand Down
36 changes: 0 additions & 36 deletions dist/puppet.js

This file was deleted.

Loading

0 comments on commit 3499f6b

Please sign in to comment.