.
This commit is contained in:
parent
334550cef9
commit
c143311608
5
Makefile
5
Makefile
@ -12,6 +12,7 @@ confirm:
|
|||||||
|
|
||||||
current_time = $(shell date -Iseconds)
|
current_time = $(shell date -Iseconds)
|
||||||
git_description = $(shell git describe --always --dirty)
|
git_description = $(shell git describe --always --dirty)
|
||||||
|
git_commit_count = $(shell git rev-list --count HEAD)
|
||||||
linker_flags = '-s -X main.buildTime=${current_time} -X main.version=${git_description}'
|
linker_flags = '-s -X main.buildTime=${current_time} -X main.version=${git_description}'
|
||||||
|
|
||||||
production_host = 152.53.236.243
|
production_host = 152.53.236.243
|
||||||
@ -46,8 +47,8 @@ build/package:
|
|||||||
cp ./deploy/DEBIAN/prerm /tmp/party-pkg/DEBIAN/prerm
|
cp ./deploy/DEBIAN/prerm /tmp/party-pkg/DEBIAN/prerm
|
||||||
cp ./deploy/DEBIAN/postrm /tmp/party-pkg/DEBIAN/postrm
|
cp ./deploy/DEBIAN/postrm /tmp/party-pkg/DEBIAN/postrm
|
||||||
chmod 755 /tmp/party-pkg/DEBIAN/postinst /tmp/party-pkg/DEBIAN/prerm /tmp/party-pkg/DEBIAN/postrm
|
chmod 755 /tmp/party-pkg/DEBIAN/postinst /tmp/party-pkg/DEBIAN/prerm /tmp/party-pkg/DEBIAN/postrm
|
||||||
printf 'Package: party\nVersion: 0+%s\nArchitecture: amd64\nMaintainer: Vicente Ferrari Smith <vicenteferrarismith@gmail.com>\nDescription: Party\n' \
|
printf 'Package: party\nVersion: 0+%s.%s\nArchitecture: amd64\nMaintainer: Vicente Ferrari Smith <vicenteferrarismith@gmail.com>\nDescription: Party\n' \
|
||||||
'${git_description}' > /tmp/party-pkg/DEBIAN/control
|
'${git_commit_count}' '${git_description}' > /tmp/party-pkg/DEBIAN/control
|
||||||
dpkg-deb --build --root-owner-group /tmp/party-pkg ./party.deb
|
dpkg-deb --build --root-owner-group /tmp/party-pkg ./party.deb
|
||||||
@echo 'Package ready: ./party.deb'
|
@echo 'Package ready: ./party.deb'
|
||||||
|
|
||||||
|
|||||||
@ -2,29 +2,47 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (api *Api) RegisterDeviceToken(w http.ResponseWriter, r *http.Request) {
|
func (api *Api) RegisterDeviceToken(w http.ResponseWriter, r *http.Request) {
|
||||||
user := GetUser(r)
|
user := GetUser(r)
|
||||||
|
|
||||||
|
api.App.Logger.PrintInfo("register device token: request", map[string]string{
|
||||||
|
"user_id": fmt.Sprint(user.ID),
|
||||||
|
})
|
||||||
|
|
||||||
var input struct {
|
var input struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
if err := api.readJSON(w, r, &input); err != nil {
|
if err := api.readJSON(w, r, &input); err != nil {
|
||||||
|
api.App.Logger.PrintInfo("register device token: bad request", map[string]string{
|
||||||
|
"user_id": fmt.Sprint(user.ID),
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
api.BadRequestResponse(w, r, err)
|
api.BadRequestResponse(w, r, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if input.Token == "" {
|
if input.Token == "" {
|
||||||
|
api.App.Logger.PrintInfo("register device token: empty token", map[string]string{
|
||||||
|
"user_id": fmt.Sprint(user.ID),
|
||||||
|
})
|
||||||
api.BadRequestResponse(w, r, errors.New("token must be provided"))
|
api.BadRequestResponse(w, r, errors.New("token must be provided"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := api.App.Models.DeviceTokens.Insert(user.ID, input.Token); err != nil {
|
if err := api.App.Models.DeviceTokens.Insert(user.ID, input.Token); err != nil {
|
||||||
|
api.App.Logger.PrintError(err, map[string]string{
|
||||||
|
"user_id": fmt.Sprint(user.ID),
|
||||||
|
})
|
||||||
api.ServerErrorResponse(w, r, err)
|
api.ServerErrorResponse(w, r, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
api.App.Logger.PrintInfo("register device token: ok", map[string]string{
|
||||||
|
"user_id": fmt.Sprint(user.ID),
|
||||||
|
})
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,6 +45,10 @@ func main() {
|
|||||||
runCreateAdmin(os.Args[2:])
|
runCreateAdmin(os.Args[2:])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if len(os.Args) > 1 && os.Args[1] == "send-test-notification" {
|
||||||
|
runSendTestNotification(os.Args[2:])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var cfg common.Config
|
var cfg common.Config
|
||||||
|
|
||||||
|
|||||||
100
cmd/party/send_test_notification.go
Normal file
100
cmd/party/send_test_notification.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
apns "github.com/sideshow/apns2"
|
||||||
|
"github.com/sideshow/apns2/token"
|
||||||
|
"party.at/party/cmd/party/common"
|
||||||
|
"party.at/party/internal/data"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runSendTestNotification(args []string) {
|
||||||
|
fs := flag.NewFlagSet("send-test-notification", flag.ExitOnError)
|
||||||
|
email := fs.String("email", "", "Send to all device tokens for this user")
|
||||||
|
deviceToken := fs.String("token", "", "Send to this specific device token")
|
||||||
|
message := fs.String("message", "Test notification", "Notification body")
|
||||||
|
fs.Parse(args)
|
||||||
|
|
||||||
|
if *email == "" && *deviceToken == "" {
|
||||||
|
fmt.Fprintln(os.Stderr, "usage: party send-test-notification [-email EMAIL | -token TOKEN] [-message TEXT]")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
keyPath := os.Getenv("APNS_KEY_PATH")
|
||||||
|
keyID := os.Getenv("APNS_KEY_ID")
|
||||||
|
teamID := os.Getenv("APNS_TEAM_ID")
|
||||||
|
bundleID := os.Getenv("APNS_BUNDLE_ID")
|
||||||
|
|
||||||
|
if keyPath == "" || keyID == "" || teamID == "" || bundleID == "" {
|
||||||
|
fmt.Fprintln(os.Stderr, "missing APNS_KEY_PATH, APNS_KEY_ID, APNS_TEAM_ID or APNS_BUNDLE_ID")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
authKey, err := token.AuthKeyFromFile(keyPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "apns key: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
client := apns.NewTokenClient(&token.Token{
|
||||||
|
AuthKey: authKey,
|
||||||
|
KeyID: keyID,
|
||||||
|
TeamID: teamID,
|
||||||
|
}).Production()
|
||||||
|
|
||||||
|
var targets []string
|
||||||
|
|
||||||
|
if *deviceToken != "" {
|
||||||
|
targets = []string{*deviceToken}
|
||||||
|
} else {
|
||||||
|
var cfg common.Config
|
||||||
|
cfg.DB.DSN = os.Getenv("PARTY_DB_DSN")
|
||||||
|
cfg.DB.MaxOpenConns = 5
|
||||||
|
cfg.DB.MaxIdleConns = 5
|
||||||
|
cfg.DB.MaxIdleTime = "15m"
|
||||||
|
|
||||||
|
db, err := openDB(cfg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "db: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
models := data.NewModels(db)
|
||||||
|
user, err := models.Users.GetByEmail(*email)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "user: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
deviceTokens, err := models.DeviceTokens.GetForUser(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "device tokens: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if len(deviceTokens) == 0 {
|
||||||
|
fmt.Fprintln(os.Stderr, "no device tokens registered for this user")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
for _, dt := range deviceTokens {
|
||||||
|
targets = append(targets, dt.Token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := fmt.Sprintf(`{"aps":{"alert":%q,"sound":"default"}}`, *message)
|
||||||
|
|
||||||
|
for _, t := range targets {
|
||||||
|
notification := &apns.Notification{
|
||||||
|
DeviceToken: t,
|
||||||
|
Topic: bundleID,
|
||||||
|
Payload: []byte(payload),
|
||||||
|
}
|
||||||
|
resp, err := client.Push(notification)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "push failed for %s: %v\n", t, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("token=%s status=%d apns_id=%s\n", t, resp.StatusCode, resp.ApnsID)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user