Qo'shildi: Docker konfiguratsiyasi yangilandi, .env va .gitignore fayllari yaratildi, Redis va muhit o'zgaruvchilari qo'shildi.
This commit is contained in:
@@ -99,6 +99,8 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ./notification
|
context: ./notification
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
volumes:
|
||||||
|
- ./notification:/app
|
||||||
networks:
|
networks:
|
||||||
- lamenu
|
- lamenu
|
||||||
profiles:
|
profiles:
|
||||||
@@ -109,6 +111,8 @@ services:
|
|||||||
- lamenu
|
- lamenu
|
||||||
restart: always
|
restart: always
|
||||||
image: redis
|
image: redis
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
image: rabbitmq:management
|
image: rabbitmq:management
|
||||||
|
|||||||
15
notification/.env.example
Normal file
15
notification/.env.example
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
RABBITMQ_URL=amqp://guest:guest@127.0.0.1:5672/
|
||||||
|
|
||||||
|
|
||||||
|
REDIS_ADDRESS=127.0.0.1:6379
|
||||||
|
REDIS_PASSWORD=
|
||||||
|
REDIS_DB=0
|
||||||
|
|
||||||
|
ESKIZ_DOMAIN="https://notify.eskiz.uz/api"
|
||||||
|
ESKIZ_USER="admin@gmail.com"
|
||||||
|
ESKIZ_PASSWORD="password"
|
||||||
|
ESKIZ_FROM="4546"
|
||||||
|
|
||||||
|
PMB_DOMAIN=""
|
||||||
|
PMB_USER=""
|
||||||
|
PMB_PASSWORD=""
|
||||||
3
notification/.gitignore
vendored
Normal file
3
notification/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.env
|
||||||
|
./bin
|
||||||
|
./main
|
||||||
@@ -1,10 +1,20 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/JscorpTech/notification/internal/consumer"
|
"github.com/JscorpTech/notification/internal/consumer"
|
||||||
|
"github.com/JscorpTech/notification/internal/redis"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ctx = context.Background()
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
notification := consumer.NewNotificationConsumer()
|
if err := godotenv.Load(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
redis.InitRedis()
|
||||||
|
notification := consumer.NewNotificationConsumer(ctx)
|
||||||
notification.Start()
|
notification.Start()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,13 @@ module github.com/JscorpTech/notification
|
|||||||
go 1.24.0
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/joho/godotenv v1.5.1 // indirect
|
||||||
github.com/k0kubun/pp/v3 v3.4.1 // indirect
|
github.com/k0kubun/pp/v3 v3.4.1 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
|
github.com/redis/go-redis/v9 v9.7.3 // indirect
|
||||||
github.com/streadway/amqp v1.1.0 // indirect
|
github.com/streadway/amqp v1.1.0 // indirect
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
golang.org/x/text v0.19.0 // indirect
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/k0kubun/pp/v3 v3.4.1 h1:1WdFZDRRqe8UsR61N/2RoOZ3ziTEqgTPVqKrHeb779Y=
|
github.com/k0kubun/pp/v3 v3.4.1 h1:1WdFZDRRqe8UsR61N/2RoOZ3ziTEqgTPVqKrHeb779Y=
|
||||||
github.com/k0kubun/pp/v3 v3.4.1/go.mod h1:+SiNiqKnBfw1Nkj82Lh5bIeKQOAkPy6Xw9CAZUZ8npI=
|
github.com/k0kubun/pp/v3 v3.4.1/go.mod h1:+SiNiqKnBfw1Nkj82Lh5bIeKQOAkPy6Xw9CAZUZ8npI=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||||
|
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||||
github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM=
|
github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM=
|
||||||
github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg=
|
github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package consumer
|
package consumer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@@ -11,10 +12,14 @@ import (
|
|||||||
"github.com/streadway/amqp"
|
"github.com/streadway/amqp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type notificationConsumer struct{}
|
type notificationConsumer struct {
|
||||||
|
Ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
func NewNotificationConsumer() domain.NotificationConsumerPort {
|
func NewNotificationConsumer(ctx context.Context) domain.NotificationConsumerPort {
|
||||||
return ¬ificationConsumer{}
|
return ¬ificationConsumer{
|
||||||
|
Ctx: ctx,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *notificationConsumer) Start() {
|
func (n *notificationConsumer) Start() {
|
||||||
@@ -54,7 +59,7 @@ func (n *notificationConsumer) Handler(msg amqp.Delivery) {
|
|||||||
var ntf domain.NotifierPort
|
var ntf domain.NotifierPort
|
||||||
switch notification.Type {
|
switch notification.Type {
|
||||||
case "sms":
|
case "sms":
|
||||||
ntf = notifier.NewSmsNotifier()
|
ntf = notifier.NewSmsNotifier(n.Ctx)
|
||||||
case "email":
|
case "email":
|
||||||
ntf = notifier.NewEmailNotifier()
|
ntf = notifier.NewEmailNotifier()
|
||||||
}
|
}
|
||||||
|
|||||||
27
notification/internal/domain/eskiz.go
Normal file
27
notification/internal/domain/eskiz.go
Normal 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"`
|
||||||
|
}
|
||||||
@@ -7,6 +7,9 @@ type NotificationConsumerPort interface {
|
|||||||
Handler(amqp.Delivery)
|
Handler(amqp.Delivery)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SMSServicePort interface {
|
||||||
|
SendSMS(string, string) error
|
||||||
|
}
|
||||||
type NotifierPort interface {
|
type NotifierPort interface {
|
||||||
SendMessage([]string, string)
|
SendMessage([]string, string)
|
||||||
}
|
}
|
||||||
|
|||||||
20
notification/internal/domain/playmobile.go
Normal file
20
notification/internal/domain/playmobile.go
Normal 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
|
||||||
|
}
|
||||||
@@ -1,16 +1,25 @@
|
|||||||
package notifier
|
package notifier
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/JscorpTech/notification/internal/domain"
|
"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 {
|
func NewSmsNotifier(ctx context.Context) domain.NotifierPort {
|
||||||
return &smsNotifier{}
|
return &smsNotifier{
|
||||||
|
SMSServie: services.NewEskizSMSService(ctx),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *smsNotifier) SendMessage(to []string, body string) {
|
func (n *smsNotifier) SendMessage(to []string, body string) {
|
||||||
pp.Print(to, body)
|
for _, user := range to {
|
||||||
|
n.SMSServie.SendSMS(user, body)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package rabbitmq
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/streadway/amqp"
|
"github.com/streadway/amqp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Connect() (*amqp.Connection, *amqp.Channel, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
27
notification/internal/redis/client.go
Normal file
27
notification/internal/redis/client.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
89
notification/internal/services/eskiz.go
Normal file
89
notification/internal/services/eskiz.go
Normal 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
|
||||||
|
}
|
||||||
53
notification/internal/services/playmobile.go
Normal file
53
notification/internal/services/playmobile.go
Normal 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
|
||||||
|
}
|
||||||
1
notification/tmp/build-errors.log
Normal file
1
notification/tmp/build-errors.log
Normal file
@@ -0,0 +1 @@
|
|||||||
|
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
||||||
2
test.py
2
test.py
@@ -11,7 +11,7 @@ exchange = Exchange('notification', type='direct')
|
|||||||
producer = Producer(channel, exchange=exchange, routing_key="notification")
|
producer = Producer(channel, exchange=exchange, routing_key="notification")
|
||||||
|
|
||||||
# Xabar yuborish
|
# Xabar yuborish
|
||||||
message = {'type': 'email', 'message': 'Hello, Workers!', "to": ["+998888112309", "+998943990509"]}
|
message = {'type': 'sms', 'message': "classcom.uz sayti va mobil ilovasiga ro'yxatdan o'tishingingiz uchun tasdiqlash kodi: 1234", "to": ["+998888112309", "+998943990509"]}
|
||||||
producer.publish(message)
|
producer.publish(message)
|
||||||
|
|
||||||
print("Message sent to all workers!")
|
print("Message sent to all workers!")
|
||||||
|
|||||||
Reference in New Issue
Block a user