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

Update session token via command and manual_auth config variable #66

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ After you download the file, extract it into a folder and open the `env.example`
- Multiple IDs can be provided, separated by commas.
- `EDIT_WAIT_SECONDS` (Optional): Amount of seconds to wait between edits
- This is set to `1` by default, but you can increase if you start getting a lot of `Too Many Requests` errors.
- `MANUAL_AUTH` (Optional): Setting to true will disable the browser authentication
- Requires setting OpenAI Session Token manually, use `/setToken <token>` bot command
- See [auth section](#Authentication) for info on how to get your session token
- Save the file, and rename it to `.env`.
> **Note** Make sure you rename the file to _exactly_ `.env`! The program won't work otherwise.

Expand Down
1 change: 1 addition & 0 deletions env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
TELEGRAM_ID=
TELEGRAM_TOKEN=
EDIT_WAIT_SECONDS=1
MANUAL_AUTH=false
39 changes: 28 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,27 @@ import (
"github.com/m1guelpf/chatgpt-telegram/src/tgbot"
)

const (
messageStart = "Send a message to start talking with ChatGPT. You can use /reload at any point to clear the conversation history and start from scratch (don't worry, it won't delete the Telegram messages)."
messageHelp = `/reload - clear chatGPT conversation history (Telegram messages will not be deleted)
/setToken <token> - set the openAI session token`
)

func main() {
envConfig, err := config.LoadEnvConfig(".env")
if err != nil {
log.Fatalf("Couldn't load .env config: %v", err)
}
if err := envConfig.ValidateWithDefaults(); err != nil {
log.Fatalf("Invalid .env config: %v", err)
}

persistentConfig, err := config.LoadOrCreatePersistentConfig()
if err != nil {
log.Fatalf("Couldn't load config: %v", err)
}

if persistentConfig.OpenAISession == "" {
if persistentConfig.OpenAISession == "" && !envConfig.ManualAuth {
token, err := session.GetSession()
if err != nil {
log.Fatalf("Couldn't get OpenAI session: %v", err)
Expand All @@ -34,14 +48,6 @@ func main() {
chatGPT := chatgpt.Init(persistentConfig)
log.Println("Started ChatGPT")

envConfig, err := config.LoadEnvConfig(".env")
if err != nil {
log.Fatalf("Couldn't load .env config: %v", err)
}
if err := envConfig.ValidateWithDefaults(); err != nil {
log.Fatalf("Invalid .env config: %v", err)
}

bot, err := tgbot.New(envConfig.TelegramToken, time.Duration(envConfig.EditWaitSeconds))
if err != nil {
log.Fatalf("Couldn't start Telegram bot: %v", err)
Expand Down Expand Up @@ -90,9 +96,20 @@ func main() {
var text string
switch update.Message.Command() {
case "help":
text = "Send a message to start talking with ChatGPT. You can use /reload at any point to clear the conversation history and start from scratch (don't worry, it won't delete the Telegram messages)."
text = messageHelp
case "start":
text = "Send a message to start talking with ChatGPT. You can use /reload at any point to clear the conversation history and start from scratch (don't worry, it won't delete the Telegram messages)."
text = messageStart
case "setToken":
token := update.Message.CommandArguments()
if token == "" {
text = "Please provide a token. Example: /setToken eyJhB..."
break
}
if err := persistentConfig.SetSessionToken(token); err != nil {
text = fmt.Sprintf("Error: %v", err)
break
}
text = "Token set successfully."
case "reload":
chatGPT.ResetConversation(updateChatID)
text = "Started a new conversation. Enjoy!"
Expand Down
18 changes: 13 additions & 5 deletions src/chatgpt/chatgpt.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"net/http"
"time"

"github.com/m1guelpf/chatgpt-telegram/src/config"
"github.com/m1guelpf/chatgpt-telegram/src/expirymap"
"github.com/m1guelpf/chatgpt-telegram/src/sse"
)
Expand All @@ -21,8 +20,12 @@ type Conversation struct {
LastMessageID string
}

type Config interface {
GetSessionToken() string
}

type ChatGPT struct {
SessionToken string
cfg Config
AccessTokenMap expirymap.ExpiryMap
conversations map[int64]Conversation
}
Expand All @@ -48,10 +51,10 @@ type ChatResponse struct {
Message string
}

func Init(config *config.Config) *ChatGPT {
func Init(config Config) *ChatGPT {
return &ChatGPT{
cfg: config,
AccessTokenMap: expirymap.New(),
SessionToken: config.OpenAISession,
conversations: make(map[int64]Conversation),
}
}
Expand Down Expand Up @@ -123,6 +126,11 @@ func (c *ChatGPT) SendMessage(message string, tgChatID int64) (chan ChatResponse
}

func (c *ChatGPT) refreshAccessToken() (string, error) {
sessionToken := c.cfg.GetSessionToken()
if sessionToken == "" {
return "", errors.New("no session token, use /setToken command to set")
}

cachedAccessToken, ok := c.AccessTokenMap.Get(KEY_ACCESS_TOKEN)
if ok {
return cachedAccessToken, nil
Expand All @@ -134,7 +142,7 @@ func (c *ChatGPT) refreshAccessToken() (string, error) {
}

req.Header.Set("User-Agent", USER_AGENT)
req.Header.Set("Cookie", fmt.Sprintf("__Secure-next-auth.session-token=%s", c.SessionToken))
req.Header.Set("Cookie", fmt.Sprintf("__Secure-next-auth.session-token=%s", sessionToken))

res, err := http.DefaultClient.Do(req)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ type Config struct {
OpenAISession string
}

func (cfg *Config) GetSessionToken() string {
return cfg.OpenAISession
}

// LoadOrCreatePersistentConfig uses the default config directory for the current OS
// to load or create a config file named "chatgpt.json"
func LoadOrCreatePersistentConfig() (*Config, error) {
Expand Down
16 changes: 11 additions & 5 deletions src/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,35 +44,38 @@ func TestLoadEnvConfig(t *testing.T) {
want *EnvConfig
}{
"all values empty in file and env": {
fileContent: `TELEGRAM_ID=
TELEGRAM_TOKEN=
EDIT_WAIT_SECONDS=`,
fileContent: emptyConfig,
want: &EnvConfig{
TelegramID: []int64{},
TelegramToken: "",
EditWaitSeconds: 0,
ManualAuth: false,
},
},
"no file, all values through env": {
envVars: map[string]string{
"TELEGRAM_ID": "123,456",
"TELEGRAM_TOKEN": "token",
"EDIT_WAIT_SECONDS": "10",
"MANUAL_AUTH": "true",
},
want: &EnvConfig{
TelegramID: []int64{123, 456},
TelegramToken: "token",
EditWaitSeconds: 10,
ManualAuth: true,
},
},
"all values provided in file, single TELEGRAM_ID": {
fileContent: `TELEGRAM_ID=123
TELEGRAM_TOKEN=abc
EDIT_WAIT_SECONDS=10`,
EDIT_WAIT_SECONDS=10
MANUAL_AUTH=true`,
want: &EnvConfig{
TelegramID: []int64{123},
TelegramToken: "abc",
EditWaitSeconds: 10,
ManualAuth: true,
},
},
"multiple TELEGRAM_IDs provided in file": {
Expand All @@ -89,16 +92,19 @@ EDIT_WAIT_SECONDS=10`,
"env variables should override file values": {
fileContent: `TELEGRAM_ID=123
TELEGRAM_TOKEN=abc
EDIT_WAIT_SECONDS=10`,
EDIT_WAIT_SECONDS=10
MANUAL_AUTH=false`,
envVars: map[string]string{
"TELEGRAM_ID": "456",
"TELEGRAM_TOKEN": "def",
"EDIT_WAIT_SECONDS": "20",
"MANUAL_AUTH": "true",
},
want: &EnvConfig{
TelegramID: []int64{456},
TelegramToken: "def",
EditWaitSeconds: 20,
ManualAuth: true,
},
},
"multiple TELEGRAM_IDs provided in env": {
Expand Down
8 changes: 5 additions & 3 deletions src/config/env_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ type EnvConfig struct {
TelegramID []int64 `mapstructure:"TELEGRAM_ID"`
TelegramToken string `mapstructure:"TELEGRAM_TOKEN"`
EditWaitSeconds int `mapstructure:"EDIT_WAIT_SECONDS"`
ManualAuth bool `mapstructure:"MANUAL_AUTH"`
}

// emptyConfig is used to initialize viper.
// It is required to register config keys with viper when in case no config file is provided.
const emptyConfig = `TELEGRAM_ID=
TELEGRAM_TOKEN=
EDIT_WAIT_SECONDS=`
EDIT_WAIT_SECONDS=
MANUAL_AUTH=`

func (e *EnvConfig) HasTelegramID(id int64) bool {
for _, v := range e.TelegramID {
Expand All @@ -46,7 +48,7 @@ func LoadEnvConfig(path string) (*EnvConfig, error) {
}
if fileExists {
v.SetConfigFile(path)
if err := v.ReadInConfig(); err != nil {
if err := v.MergeInConfig(); err != nil {
return nil, err
}
}
Expand All @@ -72,7 +74,7 @@ func (e *EnvConfig) ValidateWithDefaults() error {
if len(e.TelegramID) == 0 {
log.Printf("TELEGRAM_ID is not set, all users will be able to use the bot")
}
if e.EditWaitSeconds < 0 {
if e.EditWaitSeconds <= 0 {
log.Printf("EDIT_WAIT_SECONDS not set, defaulting to 1")
e.EditWaitSeconds = 1
}
Expand Down