Qo'shildi: Docker konfiguratsiyasi yangilandi, .env va .gitignore fayllari yaratildi, Redis va muhit o'zgaruvchilari qo'shildi.

This commit is contained in:
A'zamov Samandar
2025-04-21 13:08:09 +05:00
parent 9b61f2f37d
commit 09ea20b088
15 changed files with 286 additions and 11 deletions

View File

@@ -1,6 +1,7 @@
package consumer
import (
"context"
"encoding/json"
"fmt"
"log"
@@ -11,10 +12,14 @@ import (
"github.com/streadway/amqp"
)
type notificationConsumer struct{}
type notificationConsumer struct {
Ctx context.Context
}
func NewNotificationConsumer() domain.NotificationConsumerPort {
return &notificationConsumer{}
func NewNotificationConsumer(ctx context.Context) domain.NotificationConsumerPort {
return &notificationConsumer{
Ctx: ctx,
}
}
func (n *notificationConsumer) Start() {
@@ -54,7 +59,7 @@ func (n *notificationConsumer) Handler(msg amqp.Delivery) {
var ntf domain.NotifierPort
switch notification.Type {
case "sms":
ntf = notifier.NewSmsNotifier()
ntf = notifier.NewSmsNotifier(n.Ctx)
case "email":
ntf = notifier.NewEmailNotifier()
}

27
internal/domain/eskiz.go Normal file
View File

@@ -0,0 +1,27 @@
package domain
type EskizLogin struct {
Email string `json:"email"`
Password string `json:"password"`
}
type EskizLoginRes struct {
Message string
TokenType string
Data struct {
Token string
}
}
type EskizMessage struct {
Phone string `json:"mobile_phone"`
Message string `json:"message"`
From string `json:"from"`
CallbackURL string `json:"callback_url"`
}
type EskizMessageRes struct {
ID string `json:"id"`
Message string `json:"message"`
Status string `json:"status"`
}

View File

@@ -7,6 +7,9 @@ type NotificationConsumerPort interface {
Handler(amqp.Delivery)
}
type SMSServicePort interface {
SendSMS(string, string) error
}
type NotifierPort interface {
SendMessage([]string, string)
}

View File

@@ -0,0 +1,20 @@
package domain
type PmbContent struct {
Text string `json:"text"`
}
type PmbSMS struct {
Originator string `json:"originator"`
Content PmbContent `json:"content"`
}
type PmbMessage struct {
Recipient string `json:"recipient"`
MessageID string `json:"message-id"`
Sms PmbSMS `json:"sms"`
}
type PmbPayload struct {
Messages []PmbMessage
}

View File

@@ -1,16 +1,25 @@
package notifier
import (
"context"
"github.com/JscorpTech/notification/internal/domain"
"github.com/k0kubun/pp/v3"
"github.com/JscorpTech/notification/internal/services"
)
type smsNotifier struct{}
type smsNotifier struct {
SMSServie domain.SMSServicePort
Ctx context.Context
}
func NewSmsNotifier() domain.NotifierPort {
return &smsNotifier{}
func NewSmsNotifier(ctx context.Context) domain.NotifierPort {
return &smsNotifier{
SMSServie: services.NewEskizSMSService(ctx),
}
}
func (n *smsNotifier) SendMessage(to []string, body string) {
pp.Print(to, body)
for _, user := range to {
n.SMSServie.SendSMS(user, body)
}
}

View File

@@ -2,12 +2,13 @@ package rabbitmq
import (
"log"
"os"
"github.com/streadway/amqp"
)
func Connect() (*amqp.Connection, *amqp.Channel, error) {
conn, err := amqp.Dial("amqp://guest:guest@rabbitmq:5672/")
conn, err := amqp.Dial(os.Getenv("RABBITMQ_URL"))
if err != nil {
return nil, nil, err
}

27
internal/redis/client.go Normal file
View File

@@ -0,0 +1,27 @@
package redis
import (
"context"
"log"
"os"
"strconv"
"github.com/redis/go-redis/v9"
)
var RDB *redis.Client
func InitRedis() {
DB, _ := strconv.Atoi(os.Getenv("REDIS_DB"))
RDB = redis.NewClient(&redis.Options{
Addr: os.Getenv("REDIS_ADDRESS"),
Password: os.Getenv("REDIS_PASSWORD"),
DB: DB,
})
// Test connection
_, err := RDB.Ping(context.Background()).Result()
if err != nil {
log.Fatalf("Redisga ulanib bo'lmadi: %v", err)
}
}

View File

@@ -0,0 +1,89 @@
package services
import (
"bytes"
"context"
"encoding/json"
"net/http"
"os"
"time"
"github.com/JscorpTech/notification/internal/domain"
"github.com/JscorpTech/notification/internal/redis"
"github.com/k0kubun/pp/v3"
)
type eskizSMSService struct {
BaseURL string
Ctx context.Context
}
// /broker-api/send
func NewEskizSMSService(ctx context.Context) domain.SMSServicePort {
return &eskizSMSService{
Ctx: ctx,
BaseURL: os.Getenv("ESKIZ_DOMAIN"),
}
}
func (e *eskizSMSService) Request(payload any, path string, isAuth bool, retry bool) (*http.Response, error) {
var buf bytes.Buffer
_ = json.NewEncoder(&buf).Encode(payload)
client := http.Client{
Timeout: 60 * time.Second,
}
req, err := http.NewRequest("POST", e.BaseURL+path, &buf)
req.Header.Add("Content-Type", "application/json")
if isAuth {
req.Header.Add("Authorization", "Bearer "+e.GetToken(true))
}
if err != nil {
return nil, err
}
res, err := client.Do(req)
if res.StatusCode == http.StatusUnauthorized && retry {
pp.Print("Qayta urunish")
e.GetToken(false)
return e.Request(payload, path, isAuth, false)
}
return res, err
}
func (e *eskizSMSService) GetToken(cache bool) string {
token, err := redis.RDB.Get(e.Ctx, "eskiz_token").Result()
if err == nil && cache {
pp.Print("Eskiz token topildi 😁")
return token
}
payload := domain.EskizLogin{
Email: os.Getenv("ESKIZ_USER"),
Password: os.Getenv("ESKIZ_PASSWORD"),
}
res, err := e.Request(payload, "/auth/login", false, true)
if err != nil {
pp.Print(err.Error())
}
var data domain.EskizLoginRes
_ = json.NewDecoder(res.Body).Decode(&data)
token = data.Data.Token
redis.RDB.Set(e.Ctx, "eskiz_token", token, 30*24*time.Hour)
pp.Print("Eskiz yangi token olindi 😔")
return token
}
func (e *eskizSMSService) SendSMS(to, body string) error {
payload := domain.EskizMessage{
Phone: to,
Message: body,
From: os.Getenv("ESKIZ_FROM"),
}
res, err := e.Request(payload, "/message/sms/send", true, true)
if err != nil {
return err
}
var data domain.EskizMessageRes
json.NewDecoder(res.Body).Decode(&data)
pp.Print(data)
return nil
}

View File

@@ -0,0 +1,53 @@
package services
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/JscorpTech/notification/internal/domain"
)
type pmbSMSService struct {
BaseURL string
}
// /broker-api/send
func NewPmbSMSService() domain.SMSServicePort {
return &pmbSMSService{
BaseURL: "https://send.smsxabar.uz",
}
}
func (e *pmbSMSService) SendSMS(to, body string) error {
client := http.Client{
Timeout: 60 * time.Second,
}
payload := domain.PmbPayload{
Messages: []domain.PmbMessage{
{
Recipient: "+998888112309",
MessageID: "salomsdfs",
Sms: domain.PmbSMS{
Originator: "3600",
Content: domain.PmbContent{
Text: "salom",
},
},
},
},
}
var buf bytes.Buffer
_ = json.NewEncoder(&buf).Encode(payload)
req, _ := http.NewRequest("POST", e.BaseURL+"/broker-api/send", &buf)
res, err := client.Do(req)
if err != nil {
return err
}
var data map[string]interface{}
json.NewDecoder(res.Body).Decode(&data)
fmt.Print(data)
return nil
}