🎉 Initial Commit of Ring
This commit is contained in:
130
pkg/ring/clients/email.go
Normal file
130
pkg/ring/clients/email.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package clients
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type SMTPSettings struct {
|
||||
Host string
|
||||
Port int
|
||||
Username string
|
||||
Password string
|
||||
Encryption string // "tls", "ssl", "none"
|
||||
FromAddress string
|
||||
FromName string
|
||||
}
|
||||
|
||||
var smtpSettings SMTPSettings
|
||||
|
||||
func InitSMTPSettings() {
|
||||
smtpSettings = SMTPSettings{
|
||||
Host: viper.GetString("smtp.host"),
|
||||
Port: viper.GetInt("smtp.port"),
|
||||
Username: viper.GetString("smtp.username"),
|
||||
Password: viper.GetString("smtp.password"),
|
||||
Encryption: viper.GetString("smtp.encryption"),
|
||||
FromAddress: viper.GetString("smtp.from_address"),
|
||||
FromName: viper.GetString("smtp.from_name"),
|
||||
}
|
||||
|
||||
if smtpSettings.Host == "" || smtpSettings.Port == 0 || smtpSettings.FromAddress == "" {
|
||||
log.Warn().Msg("SMTP configuration incomplete. Email sending may not work.")
|
||||
} else {
|
||||
log.Info().Msgf("SMTP client initialized for %s:%d", smtpSettings.Host, smtpSettings.Port)
|
||||
}
|
||||
}
|
||||
|
||||
func GetSMTPSettings() SMTPSettings {
|
||||
return smtpSettings
|
||||
}
|
||||
|
||||
// SendEmail sends an email using the configured SMTP settings.
|
||||
func SendEmail(toAddress, subject, body string) error {
|
||||
if smtpSettings.Host == "" {
|
||||
return fmt.Errorf("SMTP client not initialized or host is empty")
|
||||
}
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", smtpSettings.Host, smtpSettings.Port)
|
||||
|
||||
// Setup authentication
|
||||
auth := smtp.PlainAuth("", smtpSettings.Username, smtpSettings.Password, smtpSettings.Host)
|
||||
|
||||
// Construct the email message
|
||||
mime := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n"
|
||||
msg := []byte("From: " + smtpSettings.FromName + " <" + smtpSettings.FromAddress + ">\r\n" +
|
||||
"To: " + toAddress + "\r\n" +
|
||||
"Subject: " + subject + "\r\n" +
|
||||
mime + "\r\n" +
|
||||
body + "\r\n")
|
||||
|
||||
var err error
|
||||
switch smtpSettings.Encryption {
|
||||
case "tls":
|
||||
// TLS encryption
|
||||
err = sendMailTLS(addr, auth, smtpSettings.FromAddress, []string{toAddress}, msg)
|
||||
case "ssl":
|
||||
// SSL encryption (usually port 465)
|
||||
err = smtp.SendMail(addr, auth, smtpSettings.FromAddress, []string{toAddress}, msg)
|
||||
case "none":
|
||||
// No encryption (usually port 25 or 587 without STARTTLS)
|
||||
err = smtp.SendMail(addr, auth, smtpSettings.FromAddress, []string{toAddress}, msg)
|
||||
default:
|
||||
return fmt.Errorf("unsupported SMTP encryption type: %s", smtpSettings.Encryption)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send email: %w", err)
|
||||
}
|
||||
log.Info().Msgf("Email sent successfully to %s", toAddress)
|
||||
return nil
|
||||
}
|
||||
|
||||
// sendMailTLS sends an email over a TLS connection.
|
||||
func sendMailTLS(addr string, auth smtp.Auth, from string, to []string, msg []byte) error {
|
||||
conn, err := tls.Dial("tcp", addr, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
client, err := smtp.NewClient(conn, smtpSettings.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
if auth != nil {
|
||||
if ok, _ := client.Extension("AUTH"); ok {
|
||||
if err = client.Auth(auth); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err = client.Mail(from); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, addr := range to {
|
||||
if err = client.Rcpt(addr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
w, err := client.Data()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.Quit()
|
||||
}
|
||||
29
pkg/ring/clients/nats.go
Normal file
29
pkg/ring/clients/nats.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package clients
|
||||
|
||||
import (
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var natsConn *nats.Conn
|
||||
|
||||
// InitNATSClient initializes the NATS client connection.
|
||||
func InitNATSClient() {
|
||||
natsURL := viper.GetString("nats.url")
|
||||
if natsURL == "" {
|
||||
log.Fatal().Msg("NATS URL not configured in viper (nats.url)")
|
||||
}
|
||||
|
||||
var err error
|
||||
natsConn, err = nats.Connect(natsURL)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to connect to NATS server")
|
||||
}
|
||||
log.Info().Msgf("Connected to NATS server: %s", natsURL)
|
||||
}
|
||||
|
||||
// GetNATSClient returns the initialized NATS client connection.
|
||||
func GetNATSClient() *nats.Conn {
|
||||
return natsConn
|
||||
}
|
||||
67
pkg/ring/clients/push.go
Normal file
67
pkg/ring/clients/push.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package clients
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
firebase "firebase.google.com/go/v4"
|
||||
"firebase.google.com/go/v4/messaging"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/sideshow/apns2"
|
||||
"github.com/sideshow/apns2/token"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
var (
|
||||
apnsClient *apns2.Client
|
||||
firebaseClient *messaging.Client
|
||||
)
|
||||
|
||||
func InitPushClients() {
|
||||
// Initialize APNs Client
|
||||
apnsCertPath := viper.GetString("apns.certificate_path")
|
||||
apnsKeyID := viper.GetString("apns.key_id")
|
||||
apnsTeamID := viper.GetString("apns.team_id")
|
||||
|
||||
if apnsCertPath != "" && apnsKeyID != "" && apnsTeamID != "" {
|
||||
authKey, err := token.AuthKeyFromFile(apnsCertPath)
|
||||
token := &token.Token{
|
||||
AuthKey: authKey,
|
||||
KeyID: apnsKeyID,
|
||||
TeamID: apnsTeamID,
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to create APNs auth key")
|
||||
}
|
||||
apnsClient = apns2.NewTokenClient(token)
|
||||
apnsClient.Production() // Use Production environment
|
||||
log.Info().Msg("APNs client initialized in production mode")
|
||||
} else {
|
||||
log.Warn().Msg("APNs configuration missing. Skipping APNs client initialization.")
|
||||
}
|
||||
|
||||
// Initialize Firebase Client
|
||||
firebaseServiceAccountPath := viper.GetString("firebase.service_account_path")
|
||||
if firebaseServiceAccountPath != "" {
|
||||
opt := option.WithCredentialsFile(firebaseServiceAccountPath)
|
||||
app, err := firebase.NewApp(context.Background(), nil, opt)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to create Firebase app")
|
||||
}
|
||||
firebaseClient, err = app.Messaging(context.Background())
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to create Firebase Messaging client")
|
||||
}
|
||||
log.Info().Msg("Firebase Messaging client initialized")
|
||||
} else {
|
||||
log.Warn().Msg("Firebase service account path missing. Skipping Firebase client initialization.")
|
||||
}
|
||||
}
|
||||
|
||||
func GetAPNsClient() *apns2.Client {
|
||||
return apnsClient
|
||||
}
|
||||
|
||||
func GetFirebaseClient() *messaging.Client {
|
||||
return firebaseClient
|
||||
}
|
||||
Reference in New Issue
Block a user