Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Go

on:
push:
branches: [master]
paths:
- "**.go"
- "go.mod"
- "go.sum"
pull_request:
branches: [master]
paths:
- "**.go"
- "go.mod"
- "go.sum"

jobs:
golangci:
name: Lint
runs-on: ubuntu-latest
steps:
# step 1: checkout repository code
- name: Checkout code into workspace directory
uses: actions/checkout@v4

# step 2: set up go
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable

# step 3: run golangci-lint
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
args: --timeout=5m

test:
name: Test
runs-on: ubuntu-latest
steps:
# step 1: checkout repository code
- name: Checkout code into workspace directory
uses: actions/checkout@v4

# step 2: set up go
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable

# step 3: install dependencies
- name: Install all Go dependencies
run: go mod download

# step 4: run test
- name: Run coverage
run: go test -race -coverprofile=coverage.out -covermode=atomic ./...
18 changes: 0 additions & 18 deletions .github/workflows/test.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,4 @@ $RECYCLE.BIN/

# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)

go.work*
34 changes: 7 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# SMS Gateway for Android™ CLI

A command-line interface for working with SMS Gateway for Android.
A command-line interface for interacting with the SMS Gateway for Android API.

## Table of Contents

Expand All @@ -16,8 +16,6 @@ A command-line interface for working with SMS Gateway for Android.
- [Output Formats](#output-formats)
- [Usage](#usage)
- [Commands](#commands)
- [Send a message](#send-a-message)
- [Get the status of a sent message](#get-the-status-of-a-sent-message)
- [Exit codes](#exit-codes)
- [Examples](#examples)
- [Output formats](#output-formats-1)
Expand Down Expand Up @@ -91,32 +89,14 @@ smsgate [global options] command [command options] [arguments...]

### Commands

The CLI supports the following commands:
The CLI offers two main groups of commands:

- `send` - send a message with single or multiple recipients
- `status` - get the status of a sent message by message ID
- **Messages**: Commands for sending messages and checking their status.
- **Webhooks**: Commands for managing webhooks, including creating, updating, and deleting them.

#### Send a message

Syntax:
```bash
smsgate send [options] 'Message content'
```

| Option | Description | Default value | Example |
| --------------------------- | ------------------------------------------------------------------------------------------ | ------------- | ----------------------- |
| `--id` | Message ID, will be generated if not provided | empty | `zXDYfTmTVf3iMd16zzdBj` |
| `--phone`, `--phones`, `-p` | Phone number, can be used multiple times or with comma-separated values, E.164 format | **required** | `+19162255887` |
| `--sim`, `--simNumber` | One-based SIM card slot number, if empty, the default SIM card will be used | empty | `2` |
| `--ttl` | Time-to-live (TTL), if empty, the message will not expire<br>Conflicts with `--validUntil` | empty | `1h30m` |
| `--validUntil` | Valid until, if empty, the message will not expire<br>Conflicts with `--ttl` | empty | `2024-12-31T23:59:59Z` |

#### Get the status of a sent message

Syntax:
```bash
smsgate status 'Message ID'
```
For a complete list of available commands, you can:
- Run `smsgate help` or `smsgate --help` in your terminal.
- Visit the official documentation at [docs.sms-gate.app](https://docs.sms-gate.app/integration/cli/#commands).

### Exit codes

Expand Down
2 changes: 1 addition & 1 deletion cmd/smsgate/smsgate.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func main() {
}

app.Commands = append(app.Commands, messages.Commands...)
// app.Commands = append(app.Commands, webhooks.Commands...)
app.Commands = append(app.Commands, webhooks.Commands...)

if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module github.com/android-sms-gateway/cli
go 1.23.2

require (
github.com/android-sms-gateway/client-go v1.1.0
github.com/android-sms-gateway/client-go v1.4.0
github.com/capcom6/go-helpers v0.0.0-20240521035631-865ee2879fa3
github.com/joho/godotenv v1.5.1
github.com/urfave/cli/v2 v2.27.5
)
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
github.com/android-sms-gateway/client-go v1.1.0 h1:mAPsueRrY/qOdQAU5yO3uLQAb7Po+3jBxB1tiqyClvg=
github.com/android-sms-gateway/client-go v1.1.0/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.3.1-0.20250129225754-59c34aa9d1c0 h1:OQgfNIUB32Ui1plEtfjjRAP85fpW8gBQgc69g5IAimI=
github.com/android-sms-gateway/client-go v1.3.1-0.20250129225754-59c34aa9d1c0/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.4.0 h1:yc6VqbiF1p/a0Ygw49VrKYHwcBJQIidcBz4C30jb27Q=
github.com/android-sms-gateway/client-go v1.4.0/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/capcom6/go-helpers v0.0.0-20240521035631-865ee2879fa3 h1:mq9rmBMCCzqGnZtbQqFSd+Ua3fahqUOYaTf26YFhWJc=
github.com/capcom6/go-helpers v0.0.0-20240521035631-865ee2879fa3/go.mod h1:WDqc7HZNqHxUTisArkYIBZtqUfJBVyPWeQI+FMwEzAw=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
Expand Down
19 changes: 16 additions & 3 deletions internal/commands/webhooks/delete.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package webhooks

import (
"fmt"

"github.com/android-sms-gateway/cli/internal/core/codes"
"github.com/android-sms-gateway/cli/internal/utils/metadata"
"github.com/urfave/cli/v2"
)

Expand All @@ -18,9 +21,19 @@ var delete = &cli.Command{
return cli.Exit("ID is empty", codes.ParamsError)
}

// client := metadata.GetClient(c.App.Metadata)
// renderer := metadata.GetRenderer(c.App.Metadata)
client := metadata.GetClient(c.App.Metadata)
renderer := metadata.GetRenderer(c.App.Metadata)

err := client.DeleteWebhook(c.Context, id)
if err != nil {
return cli.Exit(err.Error(), codes.ClientError)
}

return cli.Exit("Not implemented", codes.ParamsError)
b, err := renderer.Success()
if err != nil {
return cli.Exit(err.Error(), codes.OutputError)
}
fmt.Println(b)
return nil
},
}
20 changes: 17 additions & 3 deletions internal/commands/webhooks/list.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package webhooks

import (
"fmt"

"github.com/android-sms-gateway/cli/internal/core/codes"
"github.com/android-sms-gateway/cli/internal/utils/metadata"
"github.com/urfave/cli/v2"
)

Expand All @@ -11,9 +14,20 @@ var list = &cli.Command{
Aliases: []string{"l", "ls"},
Usage: "List webhooks",
Action: func(c *cli.Context) error {
// client := metadata.GetClient(c.App.Metadata)
// renderer := metadata.GetRenderer(c.App.Metadata)
client := metadata.GetClient(c.App.Metadata)
renderer := metadata.GetRenderer(c.App.Metadata)

res, err := client.ListWebhooks(c.Context)
if err != nil {
return cli.Exit(err.Error(), codes.ClientError)
}

b, err := renderer.Webhooks(res)
if err != nil {
return cli.Exit(err.Error(), codes.OutputError)
}
fmt.Println(b)

return cli.Exit("Not implemented", codes.ParamsError)
return nil
},
}
43 changes: 31 additions & 12 deletions internal/commands/webhooks/register.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package webhooks

import (
"fmt"
"strings"

"github.com/android-sms-gateway/cli/internal/core/codes"
"github.com/android-sms-gateway/cli/internal/utils/metadata"
"github.com/android-sms-gateway/client-go/smsgateway"
"github.com/capcom6/go-helpers/slices"
"github.com/urfave/cli/v2"
)

Expand All @@ -15,13 +20,16 @@ var register = &cli.Command{
Flags: []cli.Flag{
&cli.StringFlag{
Name: "id",
Usage: "ID",
Usage: "ID, optional",
Required: false,
},
&cli.StringFlag{
Name: "event",
Aliases: []string{"e"},
Usage: "Event",
Name: "event",
Aliases: []string{"e"},
Usage: "Event, one of: " + strings.Join(
slices.Map(smsgateway.WebhookEventTypes(), func(e smsgateway.WebhookEvent) string { return string(e) }),
", ",
),
Required: true,
Action: func(c *cli.Context, event string) error {
if !smsgateway.IsValidWebhookEvent(event) {
Expand All @@ -38,15 +46,26 @@ var register = &cli.Command{
return cli.Exit("URL is empty", codes.ParamsError)
}

// client := metadata.GetClient(c.App.Metadata)
// renderer := metadata.GetRenderer(c.App.Metadata)
client := metadata.GetClient(c.App.Metadata)
renderer := metadata.GetRenderer(c.App.Metadata)

req := smsgateway.Webhook{
ID: c.String("id"),
URL: url,
Event: c.String("event"),
}

res, err := client.RegisterWebhook(c.Context, req)
if err != nil {
return cli.Exit(err.Error(), codes.ClientError)
}

// req := smsgateway.Webhook{
// ID: c.String("id"),
// URL: url,
// Event: c.String("event"),
// }
b, err := renderer.Webhook(res)
if err != nil {
return cli.Exit(err.Error(), codes.OutputError)
}
fmt.Println(b)

return cli.Exit("Not implemented", codes.ParamsError)
return nil
},
}
14 changes: 14 additions & 0 deletions internal/core/output/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,17 @@ func NewJSONOutput() *JSONOutput {
func (o *JSONOutput) MessageState(src smsgateway.MessageState) (string, error) {
return o.marshaler(src)
}

func (o *JSONOutput) Webhook(src smsgateway.Webhook) (string, error) {
return o.marshaler(src)
}

func (o *JSONOutput) Webhooks(src []smsgateway.Webhook) (string, error) {
return o.marshaler(src)
}

func (o *JSONOutput) Success() (string, error) {
return "", nil
}

var _ Renderer = (*JSONOutput)(nil)
3 changes: 3 additions & 0 deletions internal/core/output/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const (

type Renderer interface {
MessageState(src smsgateway.MessageState) (string, error)
Webhook(src smsgateway.Webhook) (string, error)
Webhooks(src []smsgateway.Webhook) (string, error)
Success() (string, error)
}

var ErrUnsupportedFormat = errors.New("unsupported format")
Expand Down
48 changes: 48 additions & 0 deletions internal/core/output/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,51 @@ func (*TextOutput) MessageState(src smsgateway.MessageState) (string, error) {

return builder.String(), nil
}

// Webhook formats a single smsgateway.Webhook into a string representation.
// The output includes the ID, Event, and URL of the webhook.
func (*TextOutput) Webhook(src smsgateway.Webhook) (string, error) {
builder := strings.Builder{}
builder.WriteString("ID: ")
builder.WriteString(src.ID)
builder.WriteString("\nEvent: ")
builder.WriteString(src.Event)
builder.WriteString("\nURL: ")
builder.WriteString(src.URL)

return builder.String(), nil
}

// Webhooks formats a slice of smsgateway.Webhook into a single string representation.
// Each webhook's string representation is separated by "---".
// Returns the formatted string and any error encountered during formatting.
func (o *TextOutput) Webhooks(src []smsgateway.Webhook) (string, error) {
if len(src) == 0 {
return "Empty result", nil
}

builder := strings.Builder{}

for i, w := range src {
b, err := o.Webhook(w)
if err != nil {
return "", err
}
builder.WriteString(b)

if i == len(src)-1 {
continue
}

builder.WriteString("\n---\n")
}

return builder.String(), nil
}

// Success returns a string indicating success.
func (*TextOutput) Success() (string, error) {
return "Success", nil
}

var _ Renderer = (*TextOutput)(nil)