Skip to content

Commit

Permalink
fix: initial login flow bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
transitive-bullshit committed Dec 3, 2022
1 parent ddd9545 commit eaa4357
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 50 deletions.
16 changes: 8 additions & 8 deletions docs/classes/ChatGPTAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

#### Defined in

[chatgpt-api.ts:20](https://github.com/transitive-bullshit/chatgpt-api/blob/82a5232/src/chatgpt-api.ts#L20)
[chatgpt-api.ts:20](https://github.com/transitive-bullshit/chatgpt-api/blob/ddd9545/src/chatgpt-api.ts#L20)

## Methods

Expand All @@ -50,7 +50,7 @@

#### Defined in

[chatgpt-api.ts:175](https://github.com/transitive-bullshit/chatgpt-api/blob/82a5232/src/chatgpt-api.ts#L175)
[chatgpt-api.ts:186](https://github.com/transitive-bullshit/chatgpt-api/blob/ddd9545/src/chatgpt-api.ts#L186)

___

Expand All @@ -64,7 +64,7 @@ ___

#### Defined in

[chatgpt-api.ts:88](https://github.com/transitive-bullshit/chatgpt-api/blob/82a5232/src/chatgpt-api.ts#L88)
[chatgpt-api.ts:94](https://github.com/transitive-bullshit/chatgpt-api/blob/ddd9545/src/chatgpt-api.ts#L94)

___

Expand All @@ -78,7 +78,7 @@ ___

#### Defined in

[chatgpt-api.ts:93](https://github.com/transitive-bullshit/chatgpt-api/blob/82a5232/src/chatgpt-api.ts#L93)
[chatgpt-api.ts:104](https://github.com/transitive-bullshit/chatgpt-api/blob/ddd9545/src/chatgpt-api.ts#L104)

___

Expand All @@ -92,7 +92,7 @@ ___

#### Defined in

[chatgpt-api.ts:113](https://github.com/transitive-bullshit/chatgpt-api/blob/82a5232/src/chatgpt-api.ts#L113)
[chatgpt-api.ts:124](https://github.com/transitive-bullshit/chatgpt-api/blob/ddd9545/src/chatgpt-api.ts#L124)

___

Expand All @@ -106,7 +106,7 @@ ___

#### Defined in

[chatgpt-api.ts:103](https://github.com/transitive-bullshit/chatgpt-api/blob/82a5232/src/chatgpt-api.ts#L103)
[chatgpt-api.ts:114](https://github.com/transitive-bullshit/chatgpt-api/blob/ddd9545/src/chatgpt-api.ts#L114)

___

Expand All @@ -127,7 +127,7 @@ ___

#### Defined in

[chatgpt-api.ts:48](https://github.com/transitive-bullshit/chatgpt-api/blob/82a5232/src/chatgpt-api.ts#L48)
[chatgpt-api.ts:48](https://github.com/transitive-bullshit/chatgpt-api/blob/ddd9545/src/chatgpt-api.ts#L48)

___

Expand All @@ -147,4 +147,4 @@ ___

#### Defined in

[chatgpt-api.ts:151](https://github.com/transitive-bullshit/chatgpt-api/blob/82a5232/src/chatgpt-api.ts#L151)
[chatgpt-api.ts:162](https://github.com/transitive-bullshit/chatgpt-api/blob/ddd9545/src/chatgpt-api.ts#L162)
52 changes: 30 additions & 22 deletions docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,42 @@ chatgpt / [Exports](modules.md)

# ChatGPT API <!-- omit in toc -->

> Node.js TS wrapper around [ChatGPT](https://openai.com/blog/chatgpt/). Uses headless Chrome until the official API is released.
> Node.js wrapper around [ChatGPT](https://openai.com/blog/chatgpt/). Uses headless Chrome until the official API is released.
[![NPM](https://img.shields.io/npm/v/chatgpt.svg)](https://www.npmjs.com/package/chatgpt) [![Build Status](https://github.com/transitive-bullshit/chatgpt-api/actions/workflows/test.yml/badge.svg)](https://github.com/transitive-bullshit/chatgpt-api/actions/workflows/test.yml) [![MIT License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/transitive-bullshit/chatgpt-api/blob/main/license) [![Prettier Code Formatting](https://img.shields.io/badge/code_style-prettier-brightgreen.svg)](https://prettier.io)

- [Intro](#intro)
- [Auth](#auth)
- [How it works](#how-it-works)
- [Install](#install)
- [Usage](#usage)
- [Example](#example)
- [Docs](#docs)
- [Todo](#todo)
- [Related](#related)
- [License](#license)

## Intro

This package is a Node.js TypeScript wrapper around [ChatGPT](https://openai.com/blog/chatgpt) by [OpenAI](https://openai.com).
This package is a Node.js wrapper around [ChatGPT](https://openai.com/blog/chatgpt) by [OpenAI](https://openai.com). TS batteries included. ✨

You can use it to start experimenting with ChatGPT by integrating it into websites, chatbots, etc...
You can use it to start building projects powered by ChatGPT like chatbots, websites, etc...

## Auth
## How it works

It uses headless Chromium via [Playwright](https://playwright.dev) under the hood, so **you still need to have access to ChatGPT**, but it makes it much easier to access programatically.
We use headless Chromium via [Playwright](https://playwright.dev) to automate the webapp, so **you still need to have access to ChatGPT**. It just makes building API-like integrations much easier.

Chromium is opened in non-headless mode by default, which is important because the first time you run `ChatGPTAPI`.init, you'll need to log in manually. Chromium is launched with a persistent context, so you shouldn't need to keep re-logging in after the first time.
Chromium will be opened in non-headless mode by default, which is important because the first time you run `ChatGPTAPI.init()`, you'll need to log in manually. We launch Chromium with a persistent context, however, so you shouldn't need to keep re-logging in after the first time. When you log in the first time, _make sure that you also dismiss the welcome modal_.

> **Note**
> We'll replace headless chrome with the official API once it's released.
## Install

```bash
npm install --save chatgpt
# or
yarn add chatgpt
# or
pnpm add chatgpt
```

## Usage

Expand All @@ -35,10 +47,10 @@ import { ChatGPTAPI } from 'chatgpt'
async function example() {
const api = new ChatGPTAPI()

// open chromium and wait until the user has logged in
// open chromium and wait until you've logged in
await api.init({ auth: 'blocking' })

// send a message and wait for a complete response, then parse it as markdown
// send a message and wait for the response
const response = await api.sendMessage(
'Write a python version of bubble sort. Do not include example usage.'
)
Expand Down Expand Up @@ -70,33 +82,29 @@ def bubble_sort(lst):
return lst
```

The default functionality is to parse ChatGPT responses as markdown using [html-to-md](https://github.com/stonehank/html-to-md). I've found the markdown parsing to work really well during my testing, but if you'd rather output plaintext, you can use:
By default, ChatGPT responses are parsed as markdown using [html-to-md](https://github.com/stonehank/html-to-md). I've found that this works really well during my testing, but if you'd rather output plaintext, you can use:

```ts
const api = new ChatGPTAPI({ markdown: false })
```

## Example
A full [example](./src/example.ts) is included for testing purposes:

A full example is included for testing purposes:

```
```bash
# clone repo
# install node deps
# then run
npx tsx src/example.ts
```

## Docs

See the [auto-generated docs](./docs/classes/ChatGPTAPI.md) for more info on methods parameters.

## Todo

- [ ] Add message and conversation IDs
- [ ] Add support for streaming responses
- [ ] Add basic unit tests

## Related

- Inspired by this [Go module](https://github.com/danielgross/whatsapp-gpt) by [Daniel Gross](https://github.com/danielgross)
- [Python port](https://github.com/taranjeet/chatgpt-api)

## License

Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ You can use it to start building projects powered by ChatGPT like chatbots, webs

We use headless Chromium via [Playwright](https://playwright.dev) to automate the webapp, so **you still need to have access to ChatGPT**. It just makes building API-like integrations much easier.

Chromium will be opened in non-headless mode by default, which is important because the first time you run `ChatGPTAPI.init()`, you'll need to log in manually. We launch Chromium with a persistent context, however, so you shouldn't need to keep re-logging in after the first time.
Chromium will be opened in non-headless mode by default, which is important because the first time you run `ChatGPTAPI.init()`, you'll need to log in manually. We launch Chromium with a persistent context, however, so you shouldn't need to keep re-logging in after the first time. When you log in the first time, _make sure that you also dismiss the welcome modal_.

> **Note**
> We'll replace headless chrome with the official API once it's released.
Expand Down
31 changes: 21 additions & 10 deletions src/chatgpt-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,17 @@ export class ChatGPTAPI {
// dismiss welcome modal
do {
const modalSelector = '[data-headlessui-state="open"]'
if (!(await this._page.isVisible(modalSelector, { timeout: 500 }))) {

if (!(await this._page.$(modalSelector))) {
break
}

const modal = await this._page.locator(modalSelector)
if (modal) {
await modal.locator('button').last().click()
} else {
try {
await this._page.click(`${modalSelector} button:last-child`, {
timeout: 1000
})
} catch (err) {
// "next" button not found in welcome modal
break
}
} while (true)
Expand All @@ -77,7 +80,10 @@ export class ChatGPTAPI {
break
}

console.log('Please sign in to ChatGPT')
console.log(
'Please sign in to ChatGPT using the Chromium browser window and dismiss the welcome modal...'
)

await delay(1000)
} while (true)
}
Expand All @@ -86,8 +92,13 @@ export class ChatGPTAPI {
}

async getIsSignedIn() {
const inputBox = await this._getInputBox()
return !!inputBox
try {
const inputBox = await this._getInputBox()
return !!inputBox
} catch (err) {
// can happen when navigating during login
return false
}
}

async getLastMessage(): Promise<string | null> {
Expand Down Expand Up @@ -154,8 +165,8 @@ export class ChatGPTAPI {

const lastMessage = await this.getLastMessage()

await inputBox.click()
await inputBox.fill(message)
await inputBox.click({ force: true })
await inputBox.fill(message, { force: true })
await inputBox.press('Enter')

do {
Expand Down
22 changes: 13 additions & 9 deletions src/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@ async function main() {
// Wait until the user signs in via the chromium browser
await oraPromise(
new Promise<void>(async (resolve, reject) => {
try {
await delay(1000)
const isSignedIn = await api.getIsSignedIn()
if (isSignedIn) {
return resolve()
do {
try {
await delay(1000)

const isSignedIn = await api.getIsSignedIn()

if (isSignedIn) {
return resolve()
}
} catch (err) {
return reject(err)
}
} catch (err) {
return reject(err)
}
} while (true)
}),
'Please sign in to ChatGPT'
'Please sign in to ChatGPT and dismiss the welcome modal'
)
}

Expand Down

0 comments on commit eaa4357

Please sign in to comment.