in progress

This commit is contained in:
2026-01-31 19:30:41 +03:00
parent c62ca01584
commit 69ec3a6050
7 changed files with 267 additions and 2 deletions

5
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"recommendations": [
"gigacode.gigacode-vscode"
]
}

112
README.md
View File

@@ -1,3 +1,111 @@
# smsc
# SMSc - Отправка SMS через smsc.ru
Отправка смс при помощи сервиса smsc.ru
Пакет `smsc` предоставляет простой способ отправки SMS через сервис [smsc.ru](https://smsc.ru) на языке Go.
## Установка
```bash
go get git.gm6.ru/icewind/smsc
```
## Использование
```go
package main
import (
"git.gm6.ru/icewind/smsc"
)
func main() {
// Создание запроса на отправку SMS
req := smsc.RequestSMS{
ApiKey: аш_api_ключ", // Замените на ваш реальный API-ключ
Phone: "+79991234567", // Номер получателя
Message: "Привет от Go!", // Текст сообщения
}
// Отправка SMS
resp := smsc.SendSMS(req)
// Проверка результата
if resp.Error != "" {
// Обработка ошибки
panic(resp.Error)
}
// Успешная отправка
fmt.Printf("SMS отправлена. ID: %d, Количество сообщений: %d\n", resp.ID, resp.Cnt)
}
```
## Функции
### `SendSMS(req RequestSMS) ResponseSMS`
Отправляет SMS через сервис smsc.ru.
**Параметры:**
- `req` — структура `RequestSMS` с данными для отправки.
**Возвращает:**
- `ResponseSMS` — ответ от сервера, включая `ID` и `Cnt`, или ошибку.
## Структуры
### `RequestSMS`
| Поле | Тип | Описание | JSON-тег |
|-----------|--------|------------------------------|--------------|
| `ApiKey` | string | API-ключ от smsc.ru | `apikey` |
| `Phone` | string | Номер телефона получателя | `phones` |
| `Message` | string | Текст сообщения | `mes` |
### `ResponseSMS`
| Поле | Тип | Описание | JSON-тег |
|-----------|-----|---------------------------------|----------|
| `ID` | int | Уникальный идентификатор SMS | `id` |
| `Cnt` | int | Количество отправленных SMS | `cnt` |
| `Error` | string | Описание ошибки (если есть) | `error` |
| `ErrorCode`| int | Код ошибки | `error_code` |
## Обработка ошибок
Если произошла ошибка при отправке, поле `Error` в `ResponseSMS` будет содержать описание ошибки.
```go
resp := smsc.SendSMS(req)
if resp.Error != "" {
log.Printf("Ошибка: %s (код: %d)\n", resp.Error, resp.ErrorCode)
}
```
## Тестирование
Для тестирования функции `SendSMS` можно использовать реальные вызовы (интеграционные тесты). Пример теста:
```go
func TestSendSMS(t *testing.T) {
req := RequestSMS{
ApiKey: аш_api_ключ",
Phone: "+79991234567",
Message: "Тестовое сообщение",
}
resp := SendSMS(req)
if resp.Error != "" {
t.Errorf("Ошибка при отправке SMS: %s", resp.Error)
}
if resp.ID == 0 {
t.Error("Ожидался ненулевой ID")
}
}
```
> **Внимание:** Не забудьте заменить `ваш_api_ключ` на реальный ключ и убедитесь, что номер телефона корректен.
## Лицензия
MIT

3
go.mod Normal file
View File

@@ -0,0 +1,3 @@
module git.gm6.ru/icewind/smsc
go 1.25.4

66
request.go Normal file
View File

@@ -0,0 +1,66 @@
package smsc
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
func httpRequest(req *http.Request, resp any) error {
client := &http.Client{}
httpResp, err := client.Do(req)
if err != nil {
return fmt.Errorf("http request error: %w", err)
}
defer httpResp.Body.Close()
body, err := io.ReadAll(httpResp.Body)
if err != nil {
return fmt.Errorf("http response read error: %w", err)
}
//log.Println(string(body))
if err = json.Unmarshal(body, resp); err != nil {
var rErr Response
if err = json.Unmarshal(body, &rErr); err == nil && rErr.ErrorCode != 0 {
return fmt.Errorf("error %d: %s", rErr.ErrorCode, rErr.Error)
}
err = fmt.Errorf("http response unmarshal error: %w", err)
}
return err
}
func requestPost(url string, req, resp any) error {
reqData, err := json.Marshal(req)
if err != nil {
return fmt.Errorf("request marshal error: %w", err)
}
httpReq, err := http.NewRequest("POST", url, bytes.NewReader(reqData))
if err != nil {
return fmt.Errorf("http request create error: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Accept", "application/json")
err = httpRequest(httpReq, resp)
return err
}
func requestGet(url, apiKey string, params url.Values, resp any) error {
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
return fmt.Errorf("http request create error: %w", err)
}
httpReq.URL.RawQuery = params.Encode()
httpReq.Header.Set("Accept", "application/json")
err = httpRequest(httpReq, resp)
return err
}

10
response.go Normal file
View File

@@ -0,0 +1,10 @@
package smsc
type Response struct {
Error string `json:"error"`
ErrorCode int `json:"error_code"`
}
func (s *Response) IsError() bool {
return s.Error == ""
}

24
sms.go Normal file
View File

@@ -0,0 +1,24 @@
package smsc
const (
UrlSMS = "https://smsc.ru/rest/send/"
)
type RequestSMS struct {
ApiKey string `json:"apikey"`
Phone string `json:"phones"`
Message string `json:"mes"`
}
type ResponseSMS struct {
Response
ID int `json:"id"`
Cnt int `json:"cnt"`
}
func SendSMS(req RequestSMS) (resp ResponseSMS) {
if err := requestPost(UrlSMS, req, &resp); err != nil {
resp.Error = err.Error()
}
return
}

49
sms_test.go Normal file
View File

@@ -0,0 +1,49 @@
package smsc
import (
"encoding/json"
"fmt"
"math/rand"
"testing"
)
func generateCode() string {
return fmt.Sprintf("%04d", rand.Intn(10000))
}
func TestSendSMS(t *testing.T) {
// Создаем тестовый запрос
req := RequestSMS{
ApiKey: "80g8w5-t4D5n2X5v2!8s1S3p5E2n2X68e", // Замените на реальный API-ключ для теста
Phone: "79397804368", // Замените на реальный номер телефона
Message: "Код подтверждения: " + generateCode(),
}
// Вызываем тестируемую функцию
resp := SendSMS(req)
// Проверяем, что нет ошибки
if resp.Error != "" {
t.Errorf("Ошибка при отправке SMS: %s", resp.Error)
}
// Проверяем, что ID и Cnt имеют ожидаемые значения (если применимо)
// Эти проверки могут быть опциональными, так как значения зависят от ответа сервера
if resp.ID == 0 {
t.Error("Ожидался ненулевой ID")
}
if resp.Cnt == 0 {
t.Error("Ожидался ненулевой Cnt")
}
printJSON(t, resp)
}
func printJSON(t *testing.T, data any) {
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
t.Errorf("Ошибка при преобразовании в JSON: %v", err)
return
}
fmt.Println(string(jsonData))
}