implement a bit of the register.php call (and the DB schema)
This commit is contained in:
parent
0e58a5c5f0
commit
1671490485
12
server/.idea/dataSources.xml
generated
Normal file
12
server/.idea/dataSources.xml
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
|
<data-source source="LOCAL" name="DB" uuid="9efcb84c-0b66-4a1f-9c98-f11a17482c42">
|
||||||
|
<driver-ref>sqlite.xerial</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:sqlite:identifier.sqlite</jdbc-url>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
</component>
|
||||||
|
</project>
|
7
server/.idea/sqldialects.xml
generated
Normal file
7
server/.idea/sqldialects.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="SqlDialectMappings">
|
||||||
|
<file url="file://$PROJECT_DIR$/db/schema_2.0.sql" dialect="SQLite" />
|
||||||
|
<file url="PROJECT" dialect="SQLite" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -5,7 +5,13 @@ import (
|
|||||||
"blackforestbytes.com/simplecloudnotifier/api/models"
|
"blackforestbytes.com/simplecloudnotifier/api/models"
|
||||||
"blackforestbytes.com/simplecloudnotifier/common/ginresp"
|
"blackforestbytes.com/simplecloudnotifier/common/ginresp"
|
||||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CompatHandler struct {
|
type CompatHandler struct {
|
||||||
@ -21,6 +27,7 @@ func NewCompatHandler(app *logic.Application) CompatHandler {
|
|||||||
// Register swaggerdoc
|
// Register swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Register a new account
|
// @Summary Register a new account
|
||||||
|
// @ID compat-register
|
||||||
// @Param fcm_token query string true "the (android) fcm token"
|
// @Param fcm_token query string true "the (android) fcm token"
|
||||||
// @Param pro query string true "if the user is a paid account" Enums(true, false)
|
// @Param pro query string true "if the user is a paid account" Enums(true, false)
|
||||||
// @Param pro_token query string true "the (android) IAP token"
|
// @Param pro_token query string true "the (android) IAP token"
|
||||||
@ -29,28 +36,101 @@ func NewCompatHandler(app *logic.Application) CompatHandler {
|
|||||||
// @Router /register.php [get]
|
// @Router /register.php [get]
|
||||||
func (h CompatHandler) Register(g *gin.Context) ginresp.HTTPResponse {
|
func (h CompatHandler) Register(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type query struct {
|
type query struct {
|
||||||
FCMToken string `form:"fcm_token"`
|
FCMToken *string `form:"fcm_token"`
|
||||||
Pro string `form:"pro"`
|
Pro *string `form:"pro"`
|
||||||
ProToken string `form:"pro_token"`
|
ProToken *string `form:"pro_token"`
|
||||||
}
|
}
|
||||||
type response struct {
|
type response struct {
|
||||||
Success string `json:"success"`
|
Success bool `json:"success"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
UserID string `json:"user_id"`
|
UserID string `json:"user_id"`
|
||||||
UserKey string `json:"user_key"`
|
UserKey string `json:"user_key"`
|
||||||
QuotaUsed string `json:"quota"`
|
QuotaUsed int `json:"quota"`
|
||||||
QuotaMax string `json:"quota_max"`
|
QuotaMax int `json:"quota_max"`
|
||||||
IsPro string `json:"is_pro"`
|
IsPro int `json:"is_pro"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
return ginresp.NotImplemented(0)
|
var q query
|
||||||
|
if err := g.ShouldBindQuery(&q); err != nil {
|
||||||
|
return ginresp.InternAPIError(0, "Failed to read arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.FCMToken == nil {
|
||||||
|
return ginresp.InternAPIError(0, "Missing parameter [[fcm_token]]")
|
||||||
|
}
|
||||||
|
if q.Pro == nil {
|
||||||
|
return ginresp.InternAPIError(0, "Missing parameter [[pro]]")
|
||||||
|
}
|
||||||
|
if q.ProToken == nil {
|
||||||
|
return ginresp.InternAPIError(0, "Missing parameter [[pro_token]]")
|
||||||
|
}
|
||||||
|
|
||||||
|
isProInt := 0
|
||||||
|
isProBool := false
|
||||||
|
if *q.Pro == "true" {
|
||||||
|
isProInt = 1
|
||||||
|
isProBool = true
|
||||||
|
} else {
|
||||||
|
q.ProToken = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if isProBool {
|
||||||
|
ptok, err := h.app.VerifyProToken(*q.ProToken)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.InternAPIError(0, fmt.Sprintf("Failed to query purchaste status: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ptok {
|
||||||
|
return ginresp.InternAPIError(0, "Purchase token could not be verified")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userKey := h.app.GenerateRandomAuthKey()
|
||||||
|
|
||||||
|
return h.app.RunTransaction(ctx, nil, func(tx *sql.Tx) (ginresp.HTTPResponse, bool) {
|
||||||
|
|
||||||
|
res, err := tx.ExecContext(ctx, "INSERT INTO users (user_key, fcm_token, is_pro, pro_token, timestamp_accessed) VALUES (?, ?, ?, ?, NOW())", userKey, *q.FCMToken, isProInt, q.ProToken)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.InternAPIError(0, fmt.Sprintf("Failed to create user: %v", err)), false
|
||||||
|
}
|
||||||
|
|
||||||
|
userId, err := res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.InternAPIError(0, fmt.Sprintf("Failed to get user_id: %v", err)), false
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "UPDATE users SET fcm_token=NULL WHERE user_id <> ? AND fcm_token=?", userId, q.FCMToken)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.InternAPIError(0, fmt.Sprintf("Failed to update fcm: %v", err)), false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isProInt == 1 {
|
||||||
|
_, err := tx.ExecContext(ctx, "UPDATE users SET is_pro=0, pro_token=NULL WHERE user_id <> ? AND pro_token = ?", userId, q.ProToken)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.InternAPIError(0, fmt.Sprintf("Failed to update ispro: %v", err)), false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ginresp.JSON(http.StatusOK, response{
|
||||||
|
Success: true,
|
||||||
|
Message: "New user registered",
|
||||||
|
UserID: strconv.FormatInt(userId, 10),
|
||||||
|
UserKey: userKey,
|
||||||
|
QuotaUsed: 0,
|
||||||
|
QuotaMax: h.app.QuotaMax(isProBool),
|
||||||
|
IsPro: isProInt,
|
||||||
|
}), true
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info swaggerdoc
|
// Info swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Get information about the current user
|
// @Summary Get information about the current user
|
||||||
|
// @ID compat-info
|
||||||
// @Param user_id query string true "the user_id"
|
// @Param user_id query string true "the user_id"
|
||||||
// @Param user_key query string true "the user_key"
|
// @Param user_key query string true "the user_key"
|
||||||
// @Success 200 {object} handler.Info.response
|
// @Success 200 {object} handler.Info.response
|
||||||
@ -75,12 +155,13 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
return ginresp.NotImplemented(0)
|
return ginresp.InternAPIError(0, "NotImplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ack swaggerdoc
|
// Ack swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Acknowledge that a message was received
|
// @Summary Acknowledge that a message was received
|
||||||
|
// @ID compat-ack
|
||||||
// @Param user_id query string true "the user_id"
|
// @Param user_id query string true "the user_id"
|
||||||
// @Param user_key query string true "the user_key"
|
// @Param user_key query string true "the user_key"
|
||||||
// @Param scn_msg_id query string true "the message id"
|
// @Param scn_msg_id query string true "the message id"
|
||||||
@ -102,12 +183,13 @@ func (h CompatHandler) Ack(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
return ginresp.NotImplemented(0)
|
return ginresp.InternAPIError(0, "NotImplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Requery swaggerdoc
|
// Requery swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Return all not-acknowledged messages
|
// @Summary Return all not-acknowledged messages
|
||||||
|
// @ID compat-requery
|
||||||
// @Param user_id query string true "the user_id"
|
// @Param user_id query string true "the user_id"
|
||||||
// @Param user_key query string true "the user_key"
|
// @Param user_key query string true "the user_key"
|
||||||
// @Success 200 {object} handler.Requery.response
|
// @Success 200 {object} handler.Requery.response
|
||||||
@ -127,12 +209,13 @@ func (h CompatHandler) Requery(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
return ginresp.NotImplemented(0)
|
return ginresp.InternAPIError(0, "NotImplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update swaggerdoc
|
// Update swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Set the fcm-token (android)
|
// @Summary Set the fcm-token (android)
|
||||||
|
// @ID compat-update
|
||||||
// @Param user_id query string true "the user_id"
|
// @Param user_id query string true "the user_id"
|
||||||
// @Param user_key query string true "the user_key"
|
// @Param user_key query string true "the user_key"
|
||||||
// @Param fcm_token query string true "the (android) fcm token"
|
// @Param fcm_token query string true "the (android) fcm token"
|
||||||
@ -157,12 +240,13 @@ func (h CompatHandler) Update(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
return ginresp.NotImplemented(0)
|
return ginresp.InternAPIError(0, "NotImplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand swaggerdoc
|
// Expand swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Get a whole (potentially truncated) message
|
// @Summary Get a whole (potentially truncated) message
|
||||||
|
// @ID compat-expand
|
||||||
// @Success 200 {object} handler.Expand.response
|
// @Success 200 {object} handler.Expand.response
|
||||||
// @Failure 500 {object} ginresp.internAPIError
|
// @Failure 500 {object} ginresp.internAPIError
|
||||||
// @Router /expand.php [get]
|
// @Router /expand.php [get]
|
||||||
@ -180,12 +264,13 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
return ginresp.NotImplemented(0)
|
return ginresp.InternAPIError(0, "NotImplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade swaggerdoc
|
// Upgrade swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Upgrade a free account to a paid account
|
// @Summary Upgrade a free account to a paid account
|
||||||
|
// @ID compat-upgrade
|
||||||
// @Param user_id query string true "the user_id"
|
// @Param user_id query string true "the user_id"
|
||||||
// @Param user_key query string true "the user_key"
|
// @Param user_key query string true "the user_key"
|
||||||
// @Param pro query string true "if the user is a paid account" Enums(true, false)
|
// @Param pro query string true "if the user is a paid account" Enums(true, false)
|
||||||
@ -208,33 +293,39 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
return ginresp.NotImplemented(0)
|
return ginresp.InternAPIError(0, "NotImplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send swaggerdoc
|
// Send swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Send a message
|
// @Summary Send a message
|
||||||
// @Description all aeguments can either be supplied in the query or in the json body
|
// @Description (all arguments can either be supplied in the query or in the json body)
|
||||||
// @Param user_id query string true "the user_id"
|
// @ID compat-send
|
||||||
// @Param user_key query string true "the user_key"
|
// @Accept json
|
||||||
// @Param title query string true "The message title"
|
// @Produce json
|
||||||
// @Param content query string false "The message content"
|
// @Param _ query handler.Send.query false " "
|
||||||
// @Param priority query string false "The message priority" Enum(0, 1, 2)
|
// @Param post_body body handler.Send.body false " "
|
||||||
// @Param msg_id query string false "The message idempotency id"
|
|
||||||
// @Param timestamp query string false "The message timestamp"
|
|
||||||
// @Param user_id body string true "the user_id"
|
|
||||||
// @Param user_key body string true "the user_key"
|
|
||||||
// @Param title body string true "The message title"
|
|
||||||
// @Param content body string false "The message content"
|
|
||||||
// @Param priority body string false "The message priority" Enum(0, 1, 2)
|
|
||||||
// @Param msg_id body string false "The message idempotency id"
|
|
||||||
// @Param timestamp body string false "The message timestamp"
|
|
||||||
// @Success 200 {object} handler.Send.response
|
// @Success 200 {object} handler.Send.response
|
||||||
// @Failure 500 {object} ginresp.sendAPIError
|
// @Failure 500 {object} ginresp.sendAPIError
|
||||||
// @Router /send.php [post]
|
// @Router /send.php [post]
|
||||||
func (h CompatHandler) Send(g *gin.Context) ginresp.HTTPResponse {
|
func (h CompatHandler) Send(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type query struct {
|
type query struct {
|
||||||
//TODO
|
UserID string `form:"user_id" required:"true"`
|
||||||
|
UserKey string `form:"user_key" required:"true"`
|
||||||
|
Title string `form:"title" required:"true"`
|
||||||
|
Content *string `form:"content"`
|
||||||
|
Priority *string `form:"priority"`
|
||||||
|
MessageID *string `form:"msg_id"`
|
||||||
|
Timestamp *string `form:"timestamp"`
|
||||||
|
}
|
||||||
|
type body struct {
|
||||||
|
UserID string `json:"user_id" required:"true"`
|
||||||
|
UserKey string `json:"user_key" required:"true"`
|
||||||
|
Title string `json:"title" required:"true"`
|
||||||
|
Content *string `json:"content"`
|
||||||
|
Priority *string `json:"priority"`
|
||||||
|
MessageID *string `json:"msg_id"`
|
||||||
|
Timestamp *string `json:"timestamp"`
|
||||||
}
|
}
|
||||||
type response struct {
|
type response struct {
|
||||||
Success string `json:"success"`
|
Success string `json:"success"`
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"blackforestbytes.com/simplecloudnotifier/common/ginext"
|
"blackforestbytes.com/simplecloudnotifier/common/ginext"
|
||||||
"blackforestbytes.com/simplecloudnotifier/db"
|
"blackforestbytes.com/simplecloudnotifier/db"
|
||||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
@ -18,7 +19,7 @@ func main() {
|
|||||||
|
|
||||||
log.Info().Msg(fmt.Sprintf("Starting with config-namespace <%s>", conf.Namespace))
|
log.Info().Msg(fmt.Sprintf("Starting with config-namespace <%s>", conf.Namespace))
|
||||||
|
|
||||||
sqlite, err := db.NewDatabase(conf)
|
sqlite, err := db.NewDatabase(context.Background(), conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -76,8 +76,8 @@ func InternalError(e error) HTTPResponse {
|
|||||||
return &errHTTPResponse{statusCode: http.StatusInternalServerError, data: errBody{Success: false, Message: e.Error()}}
|
return &errHTTPResponse{statusCode: http.StatusInternalServerError, data: errBody{Success: false, Message: e.Error()}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotImplemented(errid int) HTTPResponse {
|
func InternAPIError(errid int, msg string) HTTPResponse {
|
||||||
return &errHTTPResponse{statusCode: http.StatusInternalServerError, data: internAPIError{Success: false, ErrorID: errid, Message: "NotImplemented"}}
|
return &errHTTPResponse{statusCode: http.StatusInternalServerError, data: internAPIError{Success: false, ErrorID: errid, Message: msg}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendAPIError(errorid apierr.APIError, highlight int, msg string) HTTPResponse {
|
func SendAPIError(errorid apierr.APIError, highlight int, msg string) HTTPResponse {
|
||||||
|
@ -2,10 +2,70 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
scn "blackforestbytes.com/simplecloudnotifier"
|
scn "blackforestbytes.com/simplecloudnotifier"
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
_ "embed"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDatabase(conf scn.Config) (*sql.DB, error) {
|
//go:embed schema_1.0.sql
|
||||||
return sql.Open("sqlite3", conf.DBFile)
|
var schema_1_0 string
|
||||||
|
|
||||||
|
//go:embed schema_2.0.sql
|
||||||
|
var schema_2_0 string
|
||||||
|
|
||||||
|
func NewDatabase(ctx context.Context, conf scn.Config) (*sql.DB, error) {
|
||||||
|
db, err := sql.Open("sqlite3", conf.DBFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
schema, err := getSchemaFromDB(ctx, db)
|
||||||
|
if schema == 0 {
|
||||||
|
|
||||||
|
_, err = db.ExecContext(ctx, schema_1_0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db, nil
|
||||||
|
|
||||||
|
} else if schema == 1 {
|
||||||
|
return nil, errors.New("cannot autom. upgrade schema 1")
|
||||||
|
} else if schema == 2 {
|
||||||
|
return db, nil
|
||||||
|
} else {
|
||||||
|
return nil, errors.New(fmt.Sprintf("Unknown DB schema: %d", schema))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSchemaFromDB(ctx context.Context, db *sql.DB) (int, error) {
|
||||||
|
|
||||||
|
r1, err := db.QueryContext(ctx, "SELECT name FROM sqlite_master WHERE type='table' AND name='meta'")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !r1.Next() {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r2, err := db.QueryContext(ctx, "SELECT value_int FROM meta WHERE key='schema'")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if !r2.Next() {
|
||||||
|
return 0, errors.New("no schema entry in meta table")
|
||||||
|
}
|
||||||
|
|
||||||
|
var schema int
|
||||||
|
err = r2.Scan(&schema)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema, nil
|
||||||
}
|
}
|
||||||
|
38
server/db/schema_1.0.sql
Normal file
38
server/db/schema_1.0.sql
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
DROP TABLE IF EXISTS `users`;
|
||||||
|
CREATE TABLE `users`
|
||||||
|
(
|
||||||
|
`user_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_key` VARCHAR(64) NOT NULL,
|
||||||
|
`fcm_token` VARCHAR(256) NULL DEFAULT NULL,
|
||||||
|
`messages_sent` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`timestamp_created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`timestamp_accessed` DATETIME NULL DEFAULT NULL,
|
||||||
|
|
||||||
|
`quota_today` INT(11) NOT NULL DEFAULT '0',
|
||||||
|
`quota_day` DATE NULL DEFAULT NULL,
|
||||||
|
|
||||||
|
`is_pro` BIT NOT NULL DEFAULT 0,
|
||||||
|
`pro_token` VARCHAR(256) NULL DEFAULT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `messages`;
|
||||||
|
CREATE TABLE `messages`
|
||||||
|
(
|
||||||
|
`scn_message_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`sender_user_id` INT(11) NOT NULL,
|
||||||
|
|
||||||
|
`timestamp_real` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`ack` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
`title` VARCHAR(256) NOT NULL,
|
||||||
|
`content` LONGTEXT NULL,
|
||||||
|
`priority` INT(11) NOT NULL,
|
||||||
|
`sendtime` BIGINT UNSIGNED NOT NULL,
|
||||||
|
|
||||||
|
`fcm_message_id` VARCHAR(256) NULL,
|
||||||
|
`usr_message_id` VARCHAR(256) NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`scn_message_id`)
|
||||||
|
);
|
47
server/db/schema_2.0.sql
Normal file
47
server/db/schema_2.0.sql
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
CREATE TABLE `users`
|
||||||
|
(
|
||||||
|
`user_id` INTEGER AUTO_INCREMENT,
|
||||||
|
`user_key` TEXT NOT NULL,
|
||||||
|
`fcm_token` TEXT NULL DEFAULT NULL,
|
||||||
|
`messages_sent` INTEGER NOT NULL DEFAULT '0',
|
||||||
|
`timestamp_created` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`timestamp_accessed` TEXT NULL DEFAULT NULL,
|
||||||
|
|
||||||
|
`quota_today` INTEGER NOT NULL DEFAULT '0',
|
||||||
|
`quota_day` TEXT NULL DEFAULT NULL,
|
||||||
|
|
||||||
|
`is_pro` INTEGER NOT NULL DEFAULT 0,
|
||||||
|
`pro_token` TEXT NULL DEFAULT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `messages`
|
||||||
|
(
|
||||||
|
`scn_message_id` INTEGER AUTO_INCREMENT,
|
||||||
|
`sender_user_id` INTEGER NOT NULL,
|
||||||
|
|
||||||
|
`timestamp_real` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`ack` INTEGER NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
`title` TEXT NOT NULL,
|
||||||
|
`content` TEXT NULL,
|
||||||
|
`priority` INTEGER NOT NULL,
|
||||||
|
`sendtime` INTEGER NOT NULL,
|
||||||
|
|
||||||
|
`fcm_message_id` TEXT NULL,
|
||||||
|
`usr_message_id` TEXT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`scn_message_id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `meta`
|
||||||
|
(
|
||||||
|
`key` TEXT NOT NULL,
|
||||||
|
`value_int` INTEGER NULL,
|
||||||
|
`value_txt` TEXT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`key`)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO meta (key, value_int) VALUES ('schema', 2)
|
@ -32,6 +32,7 @@ require (
|
|||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||||
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.17 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
||||||
golang.org/x/sys v0.1.0 // indirect
|
golang.org/x/sys v0.1.0 // indirect
|
||||||
|
@ -90,6 +90,8 @@ github.com/swaggo/swag v1.8.7/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9e
|
|||||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.17 h1:jsfbvII7aa0SH9qY0fnXBdtNnQe1YY3DgXDThEwLICc=
|
||||||
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.17/go.mod h1:TMBOjo3FRFh/GiTT0z3nwLmgcFJB87oSF2VMs4XUCTQ=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
|
@ -2,10 +2,13 @@ package logic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
scn "blackforestbytes.com/simplecloudnotifier"
|
scn "blackforestbytes.com/simplecloudnotifier"
|
||||||
|
"blackforestbytes.com/simplecloudnotifier/common/ginresp"
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -61,3 +64,48 @@ func (app *Application) Run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *Application) GenerateRandomAuthKey() string {
|
||||||
|
charset := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
k := ""
|
||||||
|
for i := 0; i < 64; i++ {
|
||||||
|
k += string(charset[rand.Int()%len(charset)])
|
||||||
|
}
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *Application) RunTransaction(ctx context.Context, opt *sql.TxOptions, fn func(tx *sql.Tx) (ginresp.HTTPResponse, bool)) ginresp.HTTPResponse {
|
||||||
|
|
||||||
|
tx, err := app.Database.BeginTx(ctx, opt)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.InternAPIError(0, fmt.Sprintf("Failed to create transaction: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
res, commit := fn(tx)
|
||||||
|
|
||||||
|
if commit {
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.InternAPIError(0, fmt.Sprintf("Failed to commit transaction: %v", err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = tx.Rollback()
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.InternAPIError(0, fmt.Sprintf("Failed to rollback transaction: %v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *Application) QuotaMax(ispro bool) int {
|
||||||
|
if ispro {
|
||||||
|
return 1000
|
||||||
|
} else {
|
||||||
|
return 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *Application) VerifyProToken(token string) (bool, error) {
|
||||||
|
return false, nil //TODO implement pro verification
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"/ack.php": {
|
"/ack.php": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Acknowledge that a message was received",
|
"summary": "Acknowledge that a message was received",
|
||||||
|
"operationId": "compat-ack",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -72,6 +73,7 @@
|
|||||||
"/expand.php": {
|
"/expand.php": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Get a whole (potentially truncated) message",
|
"summary": "Get a whole (potentially truncated) message",
|
||||||
|
"operationId": "compat-expand",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@ -109,6 +111,7 @@
|
|||||||
"/info.php": {
|
"/info.php": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Get information about the current user",
|
"summary": "Get information about the current user",
|
||||||
|
"operationId": "compat-info",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -226,6 +229,7 @@
|
|||||||
"/register.php": {
|
"/register.php": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Register a new account",
|
"summary": "Register a new account",
|
||||||
|
"operationId": "compat-register",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -272,6 +276,7 @@
|
|||||||
"/requery.php": {
|
"/requery.php": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Return all not-acknowledged messages",
|
"summary": "Return all not-acknowledged messages",
|
||||||
|
"operationId": "compat-requery",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -306,111 +311,57 @@
|
|||||||
},
|
},
|
||||||
"/send.php": {
|
"/send.php": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "all aeguments can either be supplied in the query or in the json body",
|
"description": "(all arguments can either be supplied in the query or in the json body)",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
"summary": "Send a message",
|
"summary": "Send a message",
|
||||||
|
"operationId": "compat-send",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "the user_id",
|
|
||||||
"name": "user_id",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "the user_key",
|
|
||||||
"name": "user_key",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "The message title",
|
|
||||||
"name": "title",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "The message content",
|
|
||||||
"name": "content",
|
"name": "content",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The message priority",
|
"name": "messageID",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
"name": "priority",
|
"name": "priority",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The message idempotency id",
|
|
||||||
"name": "msg_id",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "The message timestamp",
|
|
||||||
"name": "timestamp",
|
"name": "timestamp",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "the user_id",
|
"type": "string",
|
||||||
"name": "user_id",
|
|
||||||
"in": "body",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "the user_key",
|
|
||||||
"name": "user_key",
|
|
||||||
"in": "body",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "The message title",
|
|
||||||
"name": "title",
|
"name": "title",
|
||||||
"in": "body",
|
"in": "query"
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "The message content",
|
"type": "string",
|
||||||
"name": "content",
|
"name": "userID",
|
||||||
"in": "body",
|
"in": "query"
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "The message priority",
|
"type": "string",
|
||||||
"name": "priority",
|
"name": "userKey",
|
||||||
"in": "body",
|
"in": "query"
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "The message idempotency id",
|
"description": " ",
|
||||||
"name": "msg_id",
|
"name": "post_body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"$ref": "#/definitions/handler.Send.body"
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "The message timestamp",
|
|
||||||
"name": "timestamp",
|
|
||||||
"in": "body",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -433,6 +384,7 @@
|
|||||||
"/update.php": {
|
"/update.php": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Set the fcm-token (android)",
|
"summary": "Set the fcm-token (android)",
|
||||||
|
"operationId": "compat-update",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -475,6 +427,7 @@
|
|||||||
"/upgrade.php": {
|
"/upgrade.php": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Upgrade a free account to a paid account",
|
"summary": "Upgrade a free account to a paid account",
|
||||||
|
"operationId": "compat-upgrade",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -661,19 +614,19 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"is_pro": {
|
"is_pro": {
|
||||||
"type": "string"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"quota": {
|
"quota": {
|
||||||
"type": "string"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"quota_max": {
|
"quota_max": {
|
||||||
"type": "string"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
"type": "string"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"user_id": {
|
"user_id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -703,6 +656,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"handler.Send.body": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"content": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"msg_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"priority": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"user_key": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"handler.Send.response": {
|
"handler.Send.response": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -87,15 +87,15 @@ definitions:
|
|||||||
handler.Register.response:
|
handler.Register.response:
|
||||||
properties:
|
properties:
|
||||||
is_pro:
|
is_pro:
|
||||||
type: string
|
type: integer
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
quota:
|
quota:
|
||||||
type: string
|
type: integer
|
||||||
quota_max:
|
quota_max:
|
||||||
type: string
|
type: integer
|
||||||
success:
|
success:
|
||||||
type: string
|
type: boolean
|
||||||
user_id:
|
user_id:
|
||||||
type: string
|
type: string
|
||||||
user_key:
|
user_key:
|
||||||
@ -114,6 +114,23 @@ definitions:
|
|||||||
success:
|
success:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
handler.Send.body:
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
type: string
|
||||||
|
msg_id:
|
||||||
|
type: string
|
||||||
|
priority:
|
||||||
|
type: string
|
||||||
|
timestamp:
|
||||||
|
type: string
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
user_id:
|
||||||
|
type: string
|
||||||
|
user_key:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
handler.Send.response:
|
handler.Send.response:
|
||||||
properties:
|
properties:
|
||||||
message:
|
message:
|
||||||
@ -212,6 +229,7 @@ info:
|
|||||||
paths:
|
paths:
|
||||||
/ack.php:
|
/ack.php:
|
||||||
get:
|
get:
|
||||||
|
operationId: compat-ack
|
||||||
parameters:
|
parameters:
|
||||||
- description: the user_id
|
- description: the user_id
|
||||||
in: query
|
in: query
|
||||||
@ -251,6 +269,7 @@ paths:
|
|||||||
$ref: '#/definitions/ginresp.errBody'
|
$ref: '#/definitions/ginresp.errBody'
|
||||||
/expand.php:
|
/expand.php:
|
||||||
get:
|
get:
|
||||||
|
operationId: compat-expand
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
@ -274,6 +293,7 @@ paths:
|
|||||||
$ref: '#/definitions/ginresp.errBody'
|
$ref: '#/definitions/ginresp.errBody'
|
||||||
/info.php:
|
/info.php:
|
||||||
get:
|
get:
|
||||||
|
operationId: compat-info
|
||||||
parameters:
|
parameters:
|
||||||
- description: the user_id
|
- description: the user_id
|
||||||
in: query
|
in: query
|
||||||
@ -348,6 +368,7 @@ paths:
|
|||||||
$ref: '#/definitions/ginresp.errBody'
|
$ref: '#/definitions/ginresp.errBody'
|
||||||
/register.php:
|
/register.php:
|
||||||
get:
|
get:
|
||||||
|
operationId: compat-register
|
||||||
parameters:
|
parameters:
|
||||||
- description: the (android) fcm token
|
- description: the (android) fcm token
|
||||||
in: query
|
in: query
|
||||||
@ -379,6 +400,7 @@ paths:
|
|||||||
summary: Register a new account
|
summary: Register a new account
|
||||||
/requery.php:
|
/requery.php:
|
||||||
get:
|
get:
|
||||||
|
operationId: compat-requery
|
||||||
parameters:
|
parameters:
|
||||||
- description: the user_id
|
- description: the user_id
|
||||||
in: query
|
in: query
|
||||||
@ -402,78 +424,40 @@ paths:
|
|||||||
summary: Return all not-acknowledged messages
|
summary: Return all not-acknowledged messages
|
||||||
/send.php:
|
/send.php:
|
||||||
post:
|
post:
|
||||||
description: all aeguments can either be supplied in the query or in the json
|
consumes:
|
||||||
body
|
- application/json
|
||||||
|
description: (all arguments can either be supplied in the query or in the json
|
||||||
|
body)
|
||||||
|
operationId: compat-send
|
||||||
parameters:
|
parameters:
|
||||||
- description: the user_id
|
- in: query
|
||||||
in: query
|
|
||||||
name: user_id
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
- description: the user_key
|
|
||||||
in: query
|
|
||||||
name: user_key
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
- description: The message title
|
|
||||||
in: query
|
|
||||||
name: title
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
- description: The message content
|
|
||||||
in: query
|
|
||||||
name: content
|
name: content
|
||||||
type: string
|
type: string
|
||||||
- description: The message priority
|
- in: query
|
||||||
in: query
|
name: messageID
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
name: priority
|
name: priority
|
||||||
type: string
|
type: string
|
||||||
- description: The message idempotency id
|
- in: query
|
||||||
in: query
|
|
||||||
name: msg_id
|
|
||||||
type: string
|
|
||||||
- description: The message timestamp
|
|
||||||
in: query
|
|
||||||
name: timestamp
|
name: timestamp
|
||||||
type: string
|
type: string
|
||||||
- description: the user_id
|
- in: query
|
||||||
in: body
|
|
||||||
name: user_id
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- description: the user_key
|
|
||||||
in: body
|
|
||||||
name: user_key
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- description: The message title
|
|
||||||
in: body
|
|
||||||
name: title
|
name: title
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
type: string
|
||||||
- description: The message content
|
- in: query
|
||||||
|
name: userID
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: userKey
|
||||||
|
type: string
|
||||||
|
- description: ' '
|
||||||
in: body
|
in: body
|
||||||
name: content
|
name: post_body
|
||||||
schema:
|
schema:
|
||||||
type: string
|
$ref: '#/definitions/handler.Send.body'
|
||||||
- description: The message priority
|
produces:
|
||||||
in: body
|
- application/json
|
||||||
name: priority
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- description: The message idempotency id
|
|
||||||
in: body
|
|
||||||
name: msg_id
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- description: The message timestamp
|
|
||||||
in: body
|
|
||||||
name: timestamp
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
@ -486,6 +470,7 @@ paths:
|
|||||||
summary: Send a message
|
summary: Send a message
|
||||||
/update.php:
|
/update.php:
|
||||||
get:
|
get:
|
||||||
|
operationId: compat-update
|
||||||
parameters:
|
parameters:
|
||||||
- description: the user_id
|
- description: the user_id
|
||||||
in: query
|
in: query
|
||||||
@ -514,6 +499,7 @@ paths:
|
|||||||
summary: Set the fcm-token (android)
|
summary: Set the fcm-token (android)
|
||||||
/upgrade.php:
|
/upgrade.php:
|
||||||
get:
|
get:
|
||||||
|
operationId: compat-upgrade
|
||||||
parameters:
|
parameters:
|
||||||
- description: the user_id
|
- description: the user_id
|
||||||
in: query
|
in: query
|
||||||
|
Loading…
x
Reference in New Issue
Block a user