Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Slack AI & Assistants Compatibility #1331

Merged
merged 13 commits into from
Nov 6, 2024
Merged
160 changes: 160 additions & 0 deletions assistant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package slack

import (
"context"
"encoding/json"
"net/url"
)

// AssistantThreadSetStatusParameters are the parameters for AssistantThreadSetStatus
type AssistantThreadsSetStatusParameters struct {
ChannelID string `json:"channel_id"`
Status string `json:"status"`
ThreadTS string `json:"thread_ts"`
}

// AssistantThreadSetTitleParameters are the parameters for AssistantThreadSetTitle
type AssistantThreadsSetTitleParameters struct {
ChannelID string `json:"channel_id"`
ThreadTS string `json:"thread_ts"`
Title string `json:"title"`
}

// AssistantThreadSetSuggestedPromptsParameters are the parameters for AssistantThreadSetSuggestedPrompts
type AssistantThreadsSetSuggestedPromptsParameters struct {
ChannelID string `json:"channel_id"`
ThreadTS string `json:"thread_ts"`
Prompts []AssistantThreadsPrompt `json:"prompts"`
}

// AssistantThreadPrompt is a suggested prompt for a thread
type AssistantThreadsPrompt struct {
Title string `json:"title"`
Message string `json:"message"`
}

// AssistantThreadSetSuggestedPrompts sets the suggested prompts for a thread
func (p *AssistantThreadsSetSuggestedPromptsParameters) AddPrompt(title, message string) {
p.Prompts = append(p.Prompts, AssistantThreadsPrompt{
Title: title,
Message: message,
})
}

// SetAssistantThreadsSugesstedPrompts sets the suggested prompts for a thread
// @see https://api.slack.com/methods/assistant.threads.setSuggestedPrompts
func (api *Client) SetAssistantThreadsSuggestedPrompts(params AssistantThreadsSetSuggestedPromptsParameters) (err error) {
return api.SetAssistantThreadsSuggestedPromptsContext(context.Background(), params)
}

// SetAssistantThreadSuggestedPromptsContext sets the suggested prompts for a thread with a custom context
// @see https://api.slack.com/methods/assistant.threads.setSuggestedPrompts
func (api *Client) SetAssistantThreadsSuggestedPromptsContext(ctx context.Context, params AssistantThreadsSetSuggestedPromptsParameters) (err error) {

values := url.Values{
"token": {api.token},
}

if params.ChannelID != "" {
values.Add("channel_id", params.ChannelID)
}

if params.ThreadTS != "" {
values.Add("thread_ts", params.ThreadTS)
}

// Send Prompts as JSON
prompts, err := json.Marshal(params.Prompts)
if err != nil {
return err
}

values.Add("prompts", string(prompts))

response := struct {
SlackResponse
}{}

err = api.postMethod(ctx, "assistant.threads.setSuggestedPrompts", values, &response)
if err != nil {
return
}

return response.Err()
}

// SetAssistantThreadStatus sets the status of a thread
// @see https://api.slack.com/methods/assistant.threads.setStatus
func (api *Client) SetAssistantThreadsStatus(params AssistantThreadsSetStatusParameters) (err error) {
return api.SetAssistantThreadsStatusContext(context.Background(), params)
}

// SetAssistantThreadStatusContext sets the status of a thread with a custom context
// @see https://api.slack.com/methods/assistant.threads.setStatus
func (api *Client) SetAssistantThreadsStatusContext(ctx context.Context, params AssistantThreadsSetStatusParameters) (err error) {

values := url.Values{
"token": {api.token},
}

if params.ChannelID != "" {
values.Add("channel_id", params.ChannelID)
}

if params.ThreadTS != "" {
values.Add("thread_ts", params.ThreadTS)
}

// Always send the status parameter, if empty, it will clear any existing status
values.Add("status", params.Status)

response := struct {
SlackResponse
}{}

err = api.postMethod(ctx, "assistant.threads.setStatus", values, &response)
if err != nil {
return
}

return response.Err()
}

// SetAssistantThreadsTitle sets the title of a thread
// @see https://api.slack.com/methods/assistant.threads.setTitle
func (api *Client) SetAssistantThreadsTitle(params AssistantThreadsSetTitleParameters) (err error) {
return api.SetAssistantThreadsTitleContext(context.Background(), params)
}

// SetAssistantThreadsTitleContext sets the title of a thread with a custom context
// @see https://api.slack.com/methods/assistant.threads.setTitle
func (api *Client) SetAssistantThreadsTitleContext(ctx context.Context, params AssistantThreadsSetTitleParameters) (err error) {

values := url.Values{
"token": {api.token},
}

if params.ChannelID != "" {
values.Add("channel_id", params.ChannelID)
}

if params.ThreadTS != "" {
values.Add("thread_ts", params.ThreadTS)
}

if params.Title != "" {
values.Add("title", params.Title)
}

response := struct {
SlackResponse
}{}

err = api.postMethod(ctx, "assistant.threads.setTitle", values, &response)
if err != nil {
return
}

return response.Err()

}
135 changes: 135 additions & 0 deletions assistant_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package slack

import (
"encoding/json"
"net/http"
"testing"
)

func assistantThreadsSuggestedPromptsHandler(rw http.ResponseWriter, r *http.Request) {

channelID := r.FormValue("channel_id")
threadTS := r.FormValue("thread_ts")
promptStr := r.FormValue("prompts")

var prompts []AssistantThreadsPrompt
err := json.Unmarshal([]byte(promptStr), &prompts)
if err != nil {
rw.Write([]byte(`{ "ok": false, "error": "errored" }`))
return
}

rw.Header().Set("Content-Type", "application/json")

if channelID != "" && threadTS != "" && len(prompts) == 2 {

resp, _ := json.Marshal(&addBookmarkResponse{
SlackResponse: SlackResponse{Ok: true},
})
rw.Write(resp)

} else {
rw.Write([]byte(`{ "ok": false, "error": "errored" }`))
}

}

func TestAssistantThreadsSuggestedPrompts(t *testing.T) {

http.HandleFunc("/assistant.threads.setSuggestedPrompts", assistantThreadsSuggestedPromptsHandler)
once.Do(startServer)
api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))

params := AssistantThreadsSetSuggestedPromptsParameters{
ChannelID: "CXXXXXXXX",
ThreadTS: "1234567890.123456",
}

params.AddPrompt("title1", "message1")
params.AddPrompt("title2", "message2")

err := api.SetAssistantThreadsSuggestedPrompts(params)
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}

}

func setAssistantThreadsStatusHandler(rw http.ResponseWriter, r *http.Request) {

channelID := r.FormValue("channel_id")
threadTS := r.FormValue("thread_ts")
status := r.FormValue("status")

rw.Header().Set("Content-Type", "application/json")

if channelID != "" && threadTS != "" && status != "" {

resp, _ := json.Marshal(&addBookmarkResponse{
SlackResponse: SlackResponse{Ok: true},
})
rw.Write(resp)

} else {
rw.Write([]byte(`{ "ok": false, "error": "errored" }`))
}

}

func TestSetAssistantThreadsStatus(t *testing.T) {

http.HandleFunc("/assistant.threads.setStatus", setAssistantThreadsStatusHandler)
once.Do(startServer)
api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))

params := AssistantThreadsSetStatusParameters{
ChannelID: "CXXXXXXXX",
ThreadTS: "1234567890.123456",
Status: "updated status",
}

err := api.SetAssistantThreadsStatus(params)
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}

}

func assistantThreadsTitleHandler(rw http.ResponseWriter, r *http.Request) {

channelID := r.FormValue("channel_id")
threadTS := r.FormValue("thread_ts")
title := r.FormValue("title")

rw.Header().Set("Content-Type", "application/json")

if channelID != "" && threadTS != "" && title != "" {

resp, _ := json.Marshal(&addBookmarkResponse{
SlackResponse: SlackResponse{Ok: true},
})
rw.Write(resp)
} else {
rw.Write([]byte(`{ "ok": false, "error": "errored" }`))
}

}

func TestSetAssistantThreadsTitle(t *testing.T) {

http.HandleFunc("/assistant.threads.setTitle", assistantThreadsTitleHandler)
once.Do(startServer)
api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))

params := AssistantThreadsSetTitleParameters{
ChannelID: "CXXXXXXXX",
ThreadTS: "1234567890.123456",
Title: "updated title",
}

err := api.SetAssistantThreadsTitle(params)
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}

}
Loading