mirror of
https://github.com/therootcompany/golib.git
synced 2026-03-02 23:57:59 +00:00
feat: add cmd/smsgwhookstocsv for smsapid (android sms gateway) jsonl to tsv
This commit is contained in:
parent
71eceb809f
commit
af6b0eb5a2
5
cmd/smsgwhookstocsv/go.mod
Normal file
5
cmd/smsgwhookstocsv/go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module github.com/therootcompany/golib/cmd/smsgwhookstocsv
|
||||||
|
|
||||||
|
go 1.25.0
|
||||||
|
|
||||||
|
require github.com/jszwec/csvutil v1.10.0
|
||||||
2
cmd/smsgwhookstocsv/go.sum
Normal file
2
cmd/smsgwhookstocsv/go.sum
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
github.com/jszwec/csvutil v1.10.0 h1:upMDUxhQKqZ5ZDCs/wy+8Kib8rZR8I8lOR34yJkdqhI=
|
||||||
|
github.com/jszwec/csvutil v1.10.0/go.mod h1:/E4ONrmGkwmWsk9ae9jpXnv9QT8pLHEPcCirMFhxG9I=
|
||||||
133
cmd/smsgwhookstocsv/main.go
Normal file
133
cmd/smsgwhookstocsv/main.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
// smsgwhooks-to-tsv - Converts messages.jsonl webhook events to TSV/CSV
|
||||||
|
//
|
||||||
|
// Authored in 2026 by AJ ONeal <aj@therootcompany.com>, assisted by Grok Ai.
|
||||||
|
// To the extent possible under law, the author(s) have dedicated all copyright
|
||||||
|
// and related and neighboring rights to this software to the public domain
|
||||||
|
// worldwide. This software is distributed without any warranty.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the CC0 Public Domain Dedication along with
|
||||||
|
// this software. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/jszwec/csvutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SmsReceivedPayload struct {
|
||||||
|
Message string `json:"message" csv:"message"`
|
||||||
|
MessageID string `json:"messageId" csv:"messageId"`
|
||||||
|
PhoneNumber string `json:"phoneNumber" csv:"phoneNumber"`
|
||||||
|
ReceivedAt string `json:"receivedAt" csv:"receivedAt"`
|
||||||
|
SimNumber int `json:"simNumber" csv:"simNumber"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebhookEvent struct {
|
||||||
|
DeviceID string `json:"deviceId" csv:"deviceId"`
|
||||||
|
Event string `json:"event" csv:"event"`
|
||||||
|
ID string `json:"id" csv:"id"`
|
||||||
|
Payload SmsReceivedPayload `json:"payload" csv:",inline"`
|
||||||
|
WebhookID string `json:"webhookId" csv:"webhookId"`
|
||||||
|
XSignature string `json:"x-signature" csv:"x-signature"`
|
||||||
|
XTimestamp int64 `json:"x-timestamp" csv:"x-timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MainConfig struct {
|
||||||
|
out string
|
||||||
|
comma string
|
||||||
|
in string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfg := MainConfig{}
|
||||||
|
|
||||||
|
fs := flag.NewFlagSet("smsgwhooks-to-tsv", flag.ExitOnError)
|
||||||
|
|
||||||
|
fs.StringVar(&cfg.out, "o", "-", "output file ('-' = stdout)")
|
||||||
|
fs.StringVar(&cfg.comma, "comma", "\t", "field separator (default: tab)")
|
||||||
|
|
||||||
|
fs.Usage = func() {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: jsonl-to-tsv [flags] [input.jsonl]\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Converts JSONL webhook events to TSV (or CSV with custom separator).\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Flags:\n")
|
||||||
|
fs.PrintDefaults()
|
||||||
|
fmt.Fprintf(os.Stderr, "\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Examples:\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " jsonl-to-tsv messages.jsonl\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " cat messages.jsonl | jsonl-to-tsv -\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " jsonl-to-tsv -o ./out.tsv messages.jsonl\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " jsonl-to-tsv --comma , -o ./out.csv messages.jsonl\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " jsonl-to-tsv -o - messages.jsonl # explicit stdout\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = fs.Parse(os.Args[1:])
|
||||||
|
|
||||||
|
fi, _ := os.Stdin.Stat()
|
||||||
|
isProbablyPipe := (fi.Mode() & os.ModeCharDevice) == 0
|
||||||
|
if fs.NArg() == 0 && !isProbablyPipe {
|
||||||
|
fs.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var in io.Reader = os.Stdin
|
||||||
|
if cfg.in = fs.Arg(0); cfg.in != "" && cfg.in != "-" {
|
||||||
|
f, err := os.Open(cfg.in)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("open input: %v", err)
|
||||||
|
}
|
||||||
|
defer func() { _ = f.Close() }()
|
||||||
|
in = f
|
||||||
|
}
|
||||||
|
|
||||||
|
var out io.Writer = os.Stdout
|
||||||
|
if cfg.out != "-" {
|
||||||
|
f, err := os.Create(cfg.out)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("create output: %v", err)
|
||||||
|
}
|
||||||
|
defer func() { _ = f.Close() }()
|
||||||
|
out = f
|
||||||
|
}
|
||||||
|
|
||||||
|
csvWriter := csv.NewWriter(out)
|
||||||
|
csvWriter.Comma = rune((cfg.comma)[0])
|
||||||
|
csvWriter.UseCRLF = false
|
||||||
|
|
||||||
|
enc := csvutil.NewEncoder(csvWriter)
|
||||||
|
|
||||||
|
// write header
|
||||||
|
_ = enc.EncodeHeader(WebhookEvent{})
|
||||||
|
|
||||||
|
dec := json.NewDecoder(in)
|
||||||
|
for dec.More() {
|
||||||
|
var evt WebhookEvent
|
||||||
|
if err := dec.Decode(&evt); err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
log.Printf("decode error, skipping: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if evt.Event != "sms:received" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := enc.Encode(evt); err != nil {
|
||||||
|
log.Fatalf("encode error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
csvWriter.Flush()
|
||||||
|
if err := csvWriter.Error(); err != nil {
|
||||||
|
log.Printf("flush error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user