diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4cfedc8..009b3f7 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -16,4 +16,4 @@ jobs: go-version: '1.20' - name: Test - run: go test + run: go test -v ./... diff --git a/README.md b/README.md index c353823..14a7c13 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,30 @@ The official Go library for the Chat Nio API ```shell go get -u github.com/deeptrain-community/chatnio-api-go ``` + +## Usage + +- Authentication +```go +instance := chatnio.NewInstance("sk-...") +// or load from env +instance := chatnio.NewInstanceFromEnv("CHATNIO_TOKEN") +``` + +- Chat +```go +``` + + +## Test +To run the tests, you need to set the environment variable CHATNIO_TOKEN to your secret key. + +```shell +export CHATNIO_TOKEN=sk-... +``` + +Then run the tests: + +```shell +go test -v ./... +``` diff --git a/chat.go b/chat.go index 1a8c427..4be9d04 100644 --- a/chat.go +++ b/chat.go @@ -44,6 +44,10 @@ func (c *Chat) Close() error { return c.Conn.Close() } +func (c *Chat) DeferClose() { + c.Conn.DeferClose() +} + func (c *Chat) SendAuthRequest() bool { return c.Send(ChatAuthForm{ Id: c.Id, @@ -72,7 +76,13 @@ func (c *Chat) AskStream(form *ChatRequestForm, callback func(ChatPartialRespons } func (c *Chat) Ask(form *ChatRequestForm, channel chan ChatPartialResponse) { - c.AskStream(form, func(res ChatPartialResponse) { - channel <- res - }) + worker := func() { + c.AskStream(form, func(res ChatPartialResponse) { + channel <- res + }) + + close(channel) + } + + go worker() } diff --git a/chat_test.go b/chat_test.go new file mode 100644 index 0000000..3ef7728 --- /dev/null +++ b/chat_test.go @@ -0,0 +1,42 @@ +package chatnio + +import ( + "fmt" + "github.com/Deeptrain-Community/chatnio-api-go/utils" + "testing" +) + +func TestChat_AskStream(t *testing.T) { + if !instance.IsAuthenticated() { + return + } + + chat := instance.NewChat(-1) + defer chat.DeferClose() + + chat.AskStream(&ChatRequestForm{ + Message: "hello", + Model: "gpt-3.5-turbo", + }, func(resp ChatPartialResponse) { + fmt.Println(fmt.Sprintf("[chat] ask stream: %s", utils.MarshalForm(resp))) + }) +} + +func TestChat_Ask(t *testing.T) { + if !instance.IsAuthenticated() { + return + } + + chat := instance.NewChat(-1) + defer chat.DeferClose() + + channel := make(chan ChatPartialResponse) + chat.Ask(&ChatRequestForm{ + Message: "hello", + Model: "gpt-3.5-turbo", + }, channel) + + for resp := range channel { + fmt.Println(fmt.Sprintf("[chat] ask: %s", utils.MarshalForm(resp))) + } +} diff --git a/conversation_test.go b/conversation_test.go new file mode 100644 index 0000000..b098751 --- /dev/null +++ b/conversation_test.go @@ -0,0 +1,48 @@ +package chatnio + +import ( + "fmt" + "testing" +) + +func TestInstance_GetConversationList(t *testing.T) { + if !instance.IsAuthenticated() { + return + } + + list, err := instance.GetConversationList() + if err != nil { + t.Error(err) + } + + fmt.Println(fmt.Sprintf("[conversation] list: %v", list)) +} + +func TestInstance_GetConversation(t *testing.T) { + if !instance.IsAuthenticated() { + return + } + + conv, err := instance.GetConversation(2) + if err != nil { + t.Error(err) + } + + fmt.Println(fmt.Sprintf("[conversation] load: %v", conv)) +} + +func TestInstance_DeleteConversation(t *testing.T) { + if true { + return + } // // delete conversation is disabled because it's unsafe (it will delete conversation and then the test will fail) + if !instance.IsAuthenticated() { + return + } + + err := instance.DeleteConversation(2) + if err != nil { + t.Error(err) + } + + fmt.Println(fmt.Sprintf("[conversation] delete: %v", err)) +} diff --git a/quota_test.go b/quota_test.go new file mode 100644 index 0000000..27fa3a7 --- /dev/null +++ b/quota_test.go @@ -0,0 +1,79 @@ +package chatnio + +import ( + "fmt" + "github.com/Deeptrain-Community/chatnio-api-go/utils" + "testing" +) + +func TestInstance_GetQuota(t *testing.T) { + if !instance.IsAuthenticated() { + return + } + + quota, err := instance.GetQuota() + if err != nil { + t.Error(err) + } + + fmt.Println(fmt.Sprintf("[quota] get quota: %f", quota)) +} + +func TestInstance_BuyQuota(t *testing.T) { + if true { + return + } // buy quota is disabled because it's not free + + if !instance.IsAuthenticated() { + return + } + + err := instance.BuyQuota(1) + if err != nil { + t.Error(err) + } + + fmt.Println(fmt.Sprintf("[quota] buy quota: status %t", err == nil)) +} + +func TestInstance_GetPackage(t *testing.T) { + if !instance.IsAuthenticated() { + return + } + + pkg, err := instance.GetPackage() + if err != nil { + t.Error(err) + } + + fmt.Println(fmt.Sprintf("[quota] get package: %s", utils.MarshalForm(*pkg))) +} + +func TestInstance_GetSubscription(t *testing.T) { + if !instance.IsAuthenticated() { + return + } + + sub, err := instance.GetSubscription() + if err != nil { + t.Error(err) + } + + fmt.Println(fmt.Sprintf("[quota] get subscription: %s", utils.MarshalForm(*sub))) +} + +func TestInstance_Subscribe(t *testing.T) { + if true { + return + } // subscribe is disabled because it's not free + if !instance.IsAuthenticated() { + return + } + + err := instance.Subscribe(1) + if err != nil { + t.Error(err) + } + + fmt.Println(fmt.Sprintf("[quota] subscribe: status %t", err == nil)) +} diff --git a/utils/request_test.go b/utils/request_test.go new file mode 100644 index 0000000..32af28c --- /dev/null +++ b/utils/request_test.go @@ -0,0 +1,25 @@ +package utils + +import "testing" + +func TestGet(t *testing.T) { + _, err := Get("https://example.com", Headers{}) + if err != nil { + t.Error(err) + } +} + +func TestGetForm(t *testing.T) { + TestGet(t) +} + +func TestPost(t *testing.T) { + _, err := Post("https://example.com", Headers{}, "") + if err != nil { + t.Error(err) + } +} + +func TestPostForm(t *testing.T) { + TestPost(t) +} diff --git a/utils/websocket_test.go b/utils/websocket_test.go new file mode 100644 index 0000000..0b74fb5 --- /dev/null +++ b/utils/websocket_test.go @@ -0,0 +1,12 @@ +package utils + +import ( + "testing" +) + +func TestNewWebsocket(t *testing.T) { + ws := NewWebsocket("wss://api.chatnio.net/chat") + if ws == nil { + t.Error("websocket is nil") + } +}