starting ssh client
This commit is contained in:
parent
314a403ed9
commit
488f733ab1
@ -1,3 +1,4 @@
|
|||||||
export BOT_TOKEN=
|
export BOT_TOKEN=
|
||||||
export CRYPTO_TOKEN=
|
export CRYPTO_TOKEN=
|
||||||
export OPENAI_TOKEN=
|
export OPENAI_TOKEN=
|
||||||
|
export ADMIN_DISCORD_ID=
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
.env
|
.env
|
||||||
pb_data
|
pb_data
|
||||||
|
*.pem
|
||||||
|
*.pub
|
||||||
68
bot/bot.go
68
bot/bot.go
@ -1,6 +1,7 @@
|
|||||||
package bot
|
package bot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bitbot/pb"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
@ -11,9 +12,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
BotToken string
|
BotToken string
|
||||||
OpenAIToken string
|
OpenAIToken string
|
||||||
CryptoToken string
|
CryptoToken string
|
||||||
|
AllowedUserID string
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run() {
|
func Run() {
|
||||||
@ -26,7 +28,7 @@ func Run() {
|
|||||||
|
|
||||||
discord.Open()
|
discord.Open()
|
||||||
defer discord.Close()
|
defer discord.Close()
|
||||||
|
pb.Run()
|
||||||
log.Info("BitBot is running...")
|
log.Info("BitBot is running...")
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
@ -56,11 +58,63 @@ func newMessage(discord *discordgo.Session, message *discordgo.MessageCreate) {
|
|||||||
|
|
||||||
conversationHistory = append(conversationHistory, userMessage)
|
conversationHistory = append(conversationHistory, userMessage)
|
||||||
|
|
||||||
if strings.Contains(message.Content, "!bit") || isPrivateChannel {
|
if strings.Contains(message.Content, "!cry") {
|
||||||
chatGPT(discord, message.ChannelID, message.Content, conversationHistory)
|
|
||||||
} else if strings.Contains(message.Content, "!cry") {
|
|
||||||
currentCryptoPrice := getCurrentCryptoPrice(message.Content)
|
currentCryptoPrice := getCurrentCryptoPrice(message.Content)
|
||||||
discord.ChannelMessageSendComplex(message.ChannelID, currentCryptoPrice)
|
discord.ChannelMessageSendComplex(message.ChannelID, currentCryptoPrice)
|
||||||
|
} else if strings.Contains(message.Content, "!bit") || isPrivateChannel {
|
||||||
|
chatGPT(discord, message.ChannelID, message.Content, conversationHistory)
|
||||||
|
} else if strings.Contains(message.Content, "!genkey") {
|
||||||
|
if message.Author.ID == AllowedUserID {
|
||||||
|
err := GenerateAndSaveSSHKeyPairIfNotExist()
|
||||||
|
if err != nil {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "Error generating or saving key pair.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "SSH key pair generated and saved successfully!")
|
||||||
|
} else {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "You are not authorized to use this command.")
|
||||||
|
}
|
||||||
|
} else if strings.Contains(message.Content, "!showkey") {
|
||||||
|
if message.Author.ID == AllowedUserID {
|
||||||
|
publicKey, err := GetPublicKey()
|
||||||
|
if err != nil {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "Error fetching public key.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, publicKey)
|
||||||
|
} else {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "You are not authorized to use this command.")
|
||||||
|
}
|
||||||
|
} else if strings.Contains(message.Content, "!regenkey") {
|
||||||
|
if message.Author.ID == AllowedUserID {
|
||||||
|
err := GenerateAndSaveSSHKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "Error regenerating and saving key pair.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "SSH key pair regenerated and saved successfully!")
|
||||||
|
} else {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "You are not authorized to use this command.")
|
||||||
|
}
|
||||||
|
} else if strings.Contains(message.Content, "!ssh") {
|
||||||
|
if message.Author.ID == AllowedUserID {
|
||||||
|
commandParts := strings.Fields(message.Content)
|
||||||
|
if len(commandParts) != 2 {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "Invalid command format. Use !ssh username@remote-host:port")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionDetails := commandParts[1]
|
||||||
|
err := SSHConnectToRemoteServer(connectionDetails)
|
||||||
|
if err != nil {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "Error connecting to remote server.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "Connected to remote server!")
|
||||||
|
} else {
|
||||||
|
discord.ChannelMessageSend(message.ChannelID, "You are not authorized to use this command.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conversationHistoryMap[userID] = conversationHistory
|
conversationHistoryMap[userID] = conversationHistory
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package bot
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -41,7 +41,7 @@ func getCurrentCryptoPrice(message string) *discordgo.MessageSend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(response.Body)
|
body, _ := io.ReadAll(response.Body)
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
|
|
||||||
var data CryptoData
|
var data CryptoData
|
||||||
|
|||||||
185
bot/sshclient.go
Normal file
185
bot/sshclient.go
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
package bot
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
privateKeyPath = "private_key.pem"
|
||||||
|
publicKeyPath = "public_key.pub"
|
||||||
|
bits = 2048
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenerateAndSaveSSHKeyPairIfNotExist() error {
|
||||||
|
if KeyFilesExist(privateKeyPath, publicKeyPath) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, publicKey, err := GenerateSSHKeyPair(bits)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = SavePrivateKeyToFile(privateKeyPath, privateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = SavePublicKeyToFile(publicKeyPath, publicKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateAndSaveSSHKeyPair() error {
|
||||||
|
privateKey, publicKey, err := GenerateSSHKeyPair(bits)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = SavePrivateKeyToFile(privateKeyPath, privateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = SavePublicKeyToFile(publicKeyPath, publicKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeyFilesExist(privateKeyPath, publicKeyPath string) bool {
|
||||||
|
_, privateKeyErr := os.Stat(privateKeyPath)
|
||||||
|
_, publicKeyErr := os.Stat(publicKeyPath)
|
||||||
|
return !os.IsNotExist(privateKeyErr) && !os.IsNotExist(publicKeyErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateSSHKeyPair(bits int) (*rsa.PrivateKey, ssh.PublicKey, error) {
|
||||||
|
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return privateKey, publicKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SavePrivateKeyToFile(filename string, privateKey *rsa.PrivateKey) error {
|
||||||
|
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
|
||||||
|
privateKeyPEM := &pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: privateKeyBytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
err = pem.Encode(file, privateKeyPEM)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SavePublicKeyToFile(filename string, publicKey ssh.PublicKey) error {
|
||||||
|
publicKeyBytes := ssh.MarshalAuthorizedKey(publicKey)
|
||||||
|
|
||||||
|
file, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
_, err = file.WriteString(string(publicKeyBytes))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SSHConnectToRemoteServer(connectionDetails string) error {
|
||||||
|
privateKey, err := LoadPrivateKey(privateKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &ssh.ClientConfig{
|
||||||
|
User: "username", // You will replace this with the actual username extracted from connectionDetails
|
||||||
|
Auth: []ssh.AuthMethod{
|
||||||
|
ssh.PublicKeys(privateKey),
|
||||||
|
},
|
||||||
|
// Other configuration options like HostKeyCallback, etc.
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract username, host, and port from connectionDetails
|
||||||
|
parts := strings.Split(connectionDetails, "@")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return errors.New("invalid connection format")
|
||||||
|
}
|
||||||
|
username := parts[0]
|
||||||
|
hostPort := parts[1]
|
||||||
|
|
||||||
|
config.User = username // Set the actual username
|
||||||
|
|
||||||
|
// Connect to the remote server
|
||||||
|
client, err := ssh.Dial("tcp", hostPort, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
// Now you have a connected SSH client to the remote server.
|
||||||
|
// You can use this client to perform remote commands or file transfers.
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadPrivateKey(path string) (ssh.Signer, error) {
|
||||||
|
keyBytes, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKeyBlock, _ := pem.Decode(keyBytes)
|
||||||
|
if privateKeyBlock == nil || privateKeyBlock.Type != "RSA PRIVATE KEY" {
|
||||||
|
return nil, errors.New("failed to decode valid private key")
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssh.NewSignerFromKey(privateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPublicKey() (string, error) {
|
||||||
|
publicKeyBytes, err := os.ReadFile(publicKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(publicKeyBytes), nil
|
||||||
|
}
|
||||||
5
main.go
5
main.go
@ -28,10 +28,15 @@ func main() {
|
|||||||
if !ok {
|
if !ok {
|
||||||
log.Fatal("Must set OpenAI token as env variable: OPENAI_TOKEN")
|
log.Fatal("Must set OpenAI token as env variable: OPENAI_TOKEN")
|
||||||
}
|
}
|
||||||
|
AllowedUserID, ok := os.LookupEnv("ADMIN_DISCORD_ID")
|
||||||
|
if !ok {
|
||||||
|
log.Fatal("Must set OpenAI token as env variable: ADMIN_DISCORD_ID")
|
||||||
|
}
|
||||||
|
|
||||||
bot.BotToken = botToken
|
bot.BotToken = botToken
|
||||||
bot.CryptoToken = cryptoToken
|
bot.CryptoToken = cryptoToken
|
||||||
bot.OpenAIToken = openAIToken
|
bot.OpenAIToken = openAIToken
|
||||||
|
bot.AllowedUserID = AllowedUserID
|
||||||
|
|
||||||
bot.Run()
|
bot.Run()
|
||||||
}
|
}
|
||||||
|
|||||||
1
pb/pb.go
1
pb/pb.go
@ -8,7 +8,6 @@ import (
|
|||||||
func Run() {
|
func Run() {
|
||||||
app := pocketbase.New()
|
app := pocketbase.New()
|
||||||
|
|
||||||
// Start the PocketBase server in a goroutine.
|
|
||||||
func() {
|
func() {
|
||||||
if err := app.Start(); err != nil {
|
if err := app.Start(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|||||||
BIN
pb_data/data.db
BIN
pb_data/data.db
Binary file not shown.
BIN
pb_data/logs.db
BIN
pb_data/logs.db
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user