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

Commit

Permalink
Add cost command
Browse files Browse the repository at this point in the history
  • Loading branch information
Amaototi committed Apr 11, 2023
1 parent a399e6a commit 8a419e6
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 89 deletions.
1 change: 0 additions & 1 deletion config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ guild:
prefix: b.
lang: japanese
maxtoken: 4095
viewfees: true
timeout: 120
user_blacklist:
- "0000000000000000000"
1 change: 1 addition & 0 deletions data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
totaltokens: 0
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (

require (
github.com/gorilla/websocket v1.4.2 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4Ho
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
Expand Down
56 changes: 8 additions & 48 deletions lib/chat/gpt_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net"
"net/http"
"net/url"
"strconv"
"time"

"github.com/tpc3/Bocchi-Go/lib/config"
Expand All @@ -19,13 +18,13 @@ const openai = "https://api.openai.com/v1/chat/completions"

var timeout *url.Error

func GptRequest(guild *config.Guild, msg *[]Message, num *int) (response string, coststr string, err error) {
func GptRequest(guild *config.Guild, msg *[]Message, num *int, data *config.Data) (string, error) {
apikey := config.CurrentConfig.Chat.ChatToken
response, coststr, err = getOpenAIResponse(guild, &apikey, msg, num)
return
response, err := getOpenAIResponse(guild, &apikey, msg, num, data)
return response, err
}

func getOpenAIResponse(guild *config.Guild, apikey *string, messages *[]Message, num *int) (string, string, error) {
func getOpenAIResponse(guild *config.Guild, apikey *string, messages *[]Message, num *int, data *config.Data) (string, error) {
requestBody := OpenaiRequest{
Model: "gpt-3.5-turbo",
Messages: *messages,
Expand Down Expand Up @@ -59,7 +58,7 @@ func getOpenAIResponse(guild *config.Guild, apikey *string, messages *[]Message,
resp, err := client.Do(req)
if err != nil {
if errors.As(err, &timeout) && timeout.Timeout() {
return "", "", err
return "", err
} else {
log.Fatal("Sending http request error: ", err)
}
Expand All @@ -72,7 +71,7 @@ func getOpenAIResponse(guild *config.Guild, apikey *string, messages *[]Message,
log.Panic("Decoding error response failed: ", err)
}
log.Print("Service is unavailable: ", errorResponse.Error.Message)
return "", "", err
return "", err
}

body, err := io.ReadAll(resp.Body)
Expand All @@ -87,47 +86,8 @@ func getOpenAIResponse(guild *config.Guild, apikey *string, messages *[]Message,
}
result := response.Choices[0].Messages.Content
tokens := response.Usages.TotalTokens
cost := calculationCost(tokens, guild)

return result, cost, nil
}
config.SaveData(data, tokens)

func calculationCost(tokens int, guild *config.Guild) string {
rate := getRate(guild)
cost := (float64(tokens) / 1000) * 0.002 * rate
recost := strconv.FormatFloat(cost, 'f', 2, 64)
if recost == "0.00" {
i := 1
text := "0.00"
for {
recost = strconv.FormatFloat(cost, 'f', 2+i, 64)
text = text + "0"
if recost != text {
break
}
}
}
return recost
}

func getRate(guild *config.Guild) float64 {
if config.Lang[guild.Lang].Lang == "japanese" {
url := "https://api.excelapi.org/currency/rate?pair=usd-jpy"
resp, err := http.Get(url)
if err != nil {
log.Fatal("Sending http request error: ", err)
}
defer resp.Body.Close()
byteArray, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal("Reading body error: ", err)
}
rate, err := strconv.ParseFloat(string(byteArray), 64)
if err != nil {
log.Fatal("Parsing rate error: ", err)
}
return rate
} else {
return 1
}
return result, nil
}
14 changes: 4 additions & 10 deletions lib/cmds/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (

var timeout *url.Error

func ChatCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guild *config.Guild, msg *string) {
func ChatCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guild *config.Guild, msg *string, data *config.Data) {
if *msg == "" {
ErrorReply(session, orgMsg, config.Lang[config.CurrentConfig.Guild.Lang].Error.SubCmd)
return
Expand Down Expand Up @@ -92,7 +92,7 @@ func ChatCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guild

start := time.Now()
session.MessageReactionAdd(orgMsg.ChannelID, orgMsg.ID, "🤔")
response, coststr, err := chat.GptRequest(guild, &msgChain, &num)
response, err := chat.GptRequest(guild, &msgChain, &num, data)
if errors.As(err, &timeout) && timeout.Timeout() {
ErrorReply(session, orgMsg, config.Lang[guild.Lang].Error.TimeOut)
return
Expand All @@ -112,14 +112,8 @@ func ChatCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guild
embedMsg.Description = response
exectimetext := config.Lang[guild.Lang].Reply.ExecTime
second := config.Lang[guild.Lang].Reply.Second
if config.CurrentConfig.Guild.ViewFees {
embedMsg.Footer = &discordgo.MessageEmbedFooter{
Text: exectimetext + dulation + second + "\n" + config.Lang[guild.Lang].Reply.Cost + coststr,
}
} else {
embedMsg.Footer = &discordgo.MessageEmbedFooter{
Text: exectimetext + dulation + second,
}
embedMsg.Footer = &discordgo.MessageEmbedFooter{
Text: exectimetext + dulation + second,
}
session.MessageReactionRemove(orgMsg.ChannelID, orgMsg.ID, "🤔", session.State.User.ID)
GPTReplyEmbed(session, orgMsg, embedMsg)
Expand Down
16 changes: 0 additions & 16 deletions lib/cmds/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ func ConfigUsage(session *discordgo.Session, orgMsg *discordgo.MessageCreate, gu
Name: "maxtoken <int>",
Value: config.Lang[guild.Lang].Usage.Config.MaxToken,
})
msg.Fields = append(msg.Fields, &discordgo.MessageEmbedField{
Name: "viewfees <bool>",
Value: config.Lang[guild.Lang].Usage.Config.ViewFees,
})
msg.Fields = append(msg.Fields, &discordgo.MessageEmbedField{
Name: "timeout <int>",
Value: config.Lang[guild.Lang].Usage.Config.TimeOut,
Expand All @@ -63,10 +59,6 @@ func ConfigCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guil
Name: "maxtoken",
Value: strconv.Itoa(guild.MaxToken),
})
msg.Fields = append(msg.Fields, &discordgo.MessageEmbedField{
Name: "viewfees",
Value: strconv.FormatBool(guild.ViewFees),
})
msg.Fields = append(msg.Fields, &discordgo.MessageEmbedField{
Name: "timeout",
Value: strconv.Itoa(guild.Timeout),
Expand Down Expand Up @@ -104,14 +96,6 @@ func ConfigCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guil
}
key = config.Lang[guild.Lang].Config.Item.Maxtoken
item = maxtoken
case "viewfees":
viewfees := split[1]
if viewfees != "true" && viewfees != "false" {
ErrorReply(session, orgMsg, config.Lang[guild.Lang].Error.MustBoolean)
}
guild.ViewFees, _ = strconv.ParseBool(viewfees)
key = config.Lang[guild.Lang].Config.Item.ViewFees
item = viewfees
case "timeout":
timeout := split[1]
guild.Timeout, _ = strconv.Atoi(timeout)
Expand Down
59 changes: 59 additions & 0 deletions lib/cmds/cost.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmds

import (
"io"
"log"
"net/http"
"strconv"

"github.com/bwmarrin/discordgo"
"github.com/tpc3/Bocchi-Go/lib/config"
"github.com/tpc3/Bocchi-Go/lib/embed"
)

const (
Cost = "cost"
dataFile = "./data.yml"
)

func CostCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guild *config.Guild) {
embedMsg := embed.NewEmbed(session, orgMsg)
embedMsg.Title = "Cost"
embedMsg.Description = config.Lang[guild.Lang].Reply.Cost + calculationTokens(guild)
ReplyEmbed(session, orgMsg, embedMsg)
}

func calculationTokens(guild *config.Guild) string {

var rate float64
Tokens := float64(config.CurrentData.Totaltokens)

if config.Lang[guild.Lang].Lang == "japanese" {
url := "https://api.excelapi.org/currency/rate?pair=usd-jpy"
resp, err := http.Get(url)

if err != nil {
log.Fatal("Sending http request error: ", err)
}

defer resp.Body.Close()
byteArray, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal("Reading body error: ", err)
}

rate, err = strconv.ParseFloat(string(byteArray), 64)
if err != nil {
log.Fatal("Parsing rate error: ", err)
}
} else {
rate = 1
}

cost := (Tokens / 1000) * 0.002 * rate
coststr := strconv.FormatFloat(cost, 'f', 2, 64)
if coststr == "0.00" {
coststr = "0"
}
return coststr
}
6 changes: 4 additions & 2 deletions lib/cmds/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func UnknownError(session *discordgo.Session, orgMsg *discordgo.MessageCreate, l
ReplyEmbed(session, orgMsg, msgEmbed)
}

func HandleCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guild *config.Guild, message *string) {
func HandleCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guild *config.Guild, data *config.Data, message *string) {
splitMsg := strings.SplitN(*message, " ", 2)
var param string
if len(splitMsg) == 2 {
Expand All @@ -81,8 +81,10 @@ func HandleCmd(session *discordgo.Session, orgMsg *discordgo.MessageCreate, guil
HelpCmd(session, orgMsg)
case Config:
ConfigCmd(session, orgMsg, *guild, &param)
case Cost:
CostCmd(session, orgMsg, guild)
case Chat:
go ChatCmd(session, orgMsg, guild, &param)
go ChatCmd(session, orgMsg, guild, &param, data)
default:
ErrorReply(session, orgMsg, config.Lang[guild.Lang].Error.NoCmd)
}
Expand Down
4 changes: 1 addition & 3 deletions lib/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ type Guild struct {
Prefix string
Lang string
MaxToken int
ViewFees bool
Timeout int
}

Expand Down Expand Up @@ -84,11 +83,10 @@ func SaveGuild(guild *Guild) error {
return err
}

if guild.Prefix != CurrentConfig.Guild.Prefix || guild.Lang != CurrentConfig.Guild.Lang || guild.MaxToken != CurrentConfig.Guild.MaxToken || guild.ViewFees != CurrentConfig.Guild.ViewFees || guild.Timeout != CurrentConfig.Guild.Timeout {
if guild.Prefix != CurrentConfig.Guild.Prefix || guild.Lang != CurrentConfig.Guild.Lang || guild.MaxToken != CurrentConfig.Guild.MaxToken || guild.Timeout != CurrentConfig.Guild.Timeout {
CurrentConfig.Guild.Prefix = guild.Prefix
CurrentConfig.Guild.Lang = guild.Lang
CurrentConfig.Guild.MaxToken = guild.MaxToken
CurrentConfig.Guild.ViewFees = guild.ViewFees
CurrentConfig.Guild.Timeout = guild.Timeout
}

Expand Down
84 changes: 84 additions & 0 deletions lib/config/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package config

import (
"log"
"os"

"github.com/robfig/cron/v3"
"gopkg.in/yaml.v2"
)

type Data struct {
Totaltokens int
}

const dataFile = "./data.yml"

var CurrentData Data

func init() {
file, err := os.ReadFile(dataFile)
if err != nil {
log.Fatal("Data load failed: ", err)
}
err = yaml.Unmarshal(file, &CurrentData)
if err != nil {
log.Fatal("Data parse failed: ", err)
}
}

func SaveData(data *Data, tokens int) error {
file, err := os.ReadFile(dataFile)
if err != nil {
return err
}

err = yaml.Unmarshal(file, &data)
if err != nil {
return err
}

if CurrentData.Totaltokens != tokens {
CurrentData.Totaltokens = CurrentData.Totaltokens + tokens
}

newData := Data{
Totaltokens: CurrentData.Totaltokens,
}
writedata, err := yaml.Marshal(&newData)
if err != nil {
return nil
}

err = os.WriteFile(dataFile, writedata, 0666)
if err != nil {
return nil
}

return nil
}

func RunCron() {
c := cron.New()
c.AddFunc("0 0 1 * *", func() { ResetTokens() })
c.Start()
}

func ResetTokens() error {
CurrentData.Totaltokens = 0

newData := Data{
Totaltokens: CurrentData.Totaltokens,
}
data, err := yaml.Marshal(&newData)
if err != nil {
return nil
}

err = os.WriteFile(dataFile, data, 0666)
if err != nil {
return nil
}

return nil
}
Loading

0 comments on commit 8a419e6

Please sign in to comment.