feat: add notification events handling and MQTT integration

- Implemented notification event publishing with a new NotificationEventPublisher interface.
- Created a noopNotificationEventPublisher for testing purposes.
- Added functionality to publish notification created events via MQTT.
- Introduced a new stream event publisher for handling job logs and updates.
- Added database migration for popup_ads table.
- Created tests for notification events and popup ads functionality.
- Established MQTT connection and publishing helpers for event messages.
This commit is contained in:
2026-03-29 15:47:09 +00:00
parent a910e6c624
commit 863a0ea2f6
42 changed files with 4606 additions and 576 deletions

23
go.mod
View File

@@ -13,7 +13,7 @@ require (
github.com/redis/go-redis/v9 v9.17.2 github.com/redis/go-redis/v9 v9.17.2
github.com/spf13/viper v1.21.0 github.com/spf13/viper v1.21.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
golang.org/x/crypto v0.47.0 golang.org/x/crypto v0.48.0
golang.org/x/oauth2 v0.34.0 golang.org/x/oauth2 v0.34.0
google.golang.org/grpc v1.79.2 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
@@ -22,6 +22,17 @@ require (
gorm.io/gen v0.3.27 gorm.io/gen v0.3.27
gorm.io/gorm v1.31.1 gorm.io/gorm v1.31.1
gorm.io/plugin/dbresolver v1.6.2 gorm.io/plugin/dbresolver v1.6.2
modernc.org/sqlite v1.47.0
)
require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
modernc.org/libc v1.70.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
) )
require ( require (
@@ -66,12 +77,12 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/multierr v1.10.0 // indirect go.uber.org/multierr v1.10.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/mod v0.32.0 // indirect golang.org/x/mod v0.33.0 // indirect
golang.org/x/net v0.49.0 // indirect golang.org/x/net v0.50.0 // indirect
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.40.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.33.0 // indirect golang.org/x/text v0.34.0 // indirect
golang.org/x/tools v0.41.0 // indirect golang.org/x/tools v0.42.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
gorm.io/datatypes v1.2.4 gorm.io/datatypes v1.2.4
gorm.io/driver/mysql v1.5.7 // indirect gorm.io/driver/mysql v1.5.7 // indirect

65
go.sum
View File

@@ -51,6 +51,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/eclipse/paho.mqtt.golang v1.5.1 h1:/VSOv3oDLlpqR2Epjn1Q7b2bSTplJIeV2ISgCl2W7nE= github.com/eclipse/paho.mqtt.golang v1.5.1 h1:/VSOv3oDLlpqR2Epjn1Q7b2bSTplJIeV2ISgCl2W7nE=
github.com/eclipse/paho.mqtt.golang v1.5.1/go.mod h1:1/yJCneuyOoCOzKSsOTUc0AJfpsItBGWvYpBLimhArU= github.com/eclipse/paho.mqtt.golang v1.5.1/go.mod h1:1/yJCneuyOoCOzKSsOTUc0AJfpsItBGWvYpBLimhArU=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
@@ -74,10 +76,14 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
@@ -97,17 +103,23 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=
github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI= github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI=
github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370= github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
@@ -151,22 +163,23 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=
@@ -203,3 +216,31 @@ gorm.io/hints v1.1.0 h1:Lp4z3rxREufSdxn4qmkK3TLDltrM10FLTHiuqwDPvXw=
gorm.io/hints v1.1.0/go.mod h1:lKQ0JjySsPBj3uslFzY3JhYDtqEwzm+G1hv8rWujB6Y= gorm.io/hints v1.1.0/go.mod h1:lKQ0JjySsPBj3uslFzY3JhYDtqEwzm+G1hv8rWujB6Y=
gorm.io/plugin/dbresolver v1.6.2 h1:F4b85TenghUeITqe3+epPSUtHH7RIk3fXr5l83DF8Pc= gorm.io/plugin/dbresolver v1.6.2 h1:F4b85TenghUeITqe3+epPSUtHH7RIk3fXr5l83DF8Pc=
gorm.io/plugin/dbresolver v1.6.2/go.mod h1:tctw63jdrOezFR9HmrKnPkmig3m5Edem9fdxk9bQSzM= gorm.io/plugin/dbresolver v1.6.2/go.mod h1:tctw63jdrOezFR9HmrKnPkmig3m5Edem9fdxk9bQSzM=
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.32.0 h1:hjG66bI/kqIPX1b2yT6fr/jt+QedtP2fqojG2VrFuVw=
modernc.org/ccgo/v4 v4.32.0/go.mod h1:6F08EBCx5uQc38kMGl+0Nm0oWczoo1c7cgpzEry7Uc0=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo=
modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.70.0 h1:U58NawXqXbgpZ/dcdS9kMshu08aiA6b7gusEusqzNkw=
modernc.org/libc v1.70.0/go.mod h1:OVmxFGP1CI/Z4L3E0Q3Mf1PDE0BucwMkcXjjLntvHJo=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.47.0 h1:R1XyaNpoW4Et9yly+I2EeX7pBza/w+pmYee/0HJDyKk=
modernc.org/sqlite v1.47.0/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,11 @@ const (
Admin_CreateAdminAdTemplate_FullMethodName = "/stream.app.v1.Admin/CreateAdminAdTemplate" Admin_CreateAdminAdTemplate_FullMethodName = "/stream.app.v1.Admin/CreateAdminAdTemplate"
Admin_UpdateAdminAdTemplate_FullMethodName = "/stream.app.v1.Admin/UpdateAdminAdTemplate" Admin_UpdateAdminAdTemplate_FullMethodName = "/stream.app.v1.Admin/UpdateAdminAdTemplate"
Admin_DeleteAdminAdTemplate_FullMethodName = "/stream.app.v1.Admin/DeleteAdminAdTemplate" Admin_DeleteAdminAdTemplate_FullMethodName = "/stream.app.v1.Admin/DeleteAdminAdTemplate"
Admin_ListAdminPopupAds_FullMethodName = "/stream.app.v1.Admin/ListAdminPopupAds"
Admin_GetAdminPopupAd_FullMethodName = "/stream.app.v1.Admin/GetAdminPopupAd"
Admin_CreateAdminPopupAd_FullMethodName = "/stream.app.v1.Admin/CreateAdminPopupAd"
Admin_UpdateAdminPopupAd_FullMethodName = "/stream.app.v1.Admin/UpdateAdminPopupAd"
Admin_DeleteAdminPopupAd_FullMethodName = "/stream.app.v1.Admin/DeleteAdminPopupAd"
Admin_ListAdminPlayerConfigs_FullMethodName = "/stream.app.v1.Admin/ListAdminPlayerConfigs" Admin_ListAdminPlayerConfigs_FullMethodName = "/stream.app.v1.Admin/ListAdminPlayerConfigs"
Admin_GetAdminPlayerConfig_FullMethodName = "/stream.app.v1.Admin/GetAdminPlayerConfig" Admin_GetAdminPlayerConfig_FullMethodName = "/stream.app.v1.Admin/GetAdminPlayerConfig"
Admin_CreateAdminPlayerConfig_FullMethodName = "/stream.app.v1.Admin/CreateAdminPlayerConfig" Admin_CreateAdminPlayerConfig_FullMethodName = "/stream.app.v1.Admin/CreateAdminPlayerConfig"
@@ -91,6 +96,11 @@ type AdminClient interface {
CreateAdminAdTemplate(ctx context.Context, in *CreateAdminAdTemplateRequest, opts ...grpc.CallOption) (*CreateAdminAdTemplateResponse, error) CreateAdminAdTemplate(ctx context.Context, in *CreateAdminAdTemplateRequest, opts ...grpc.CallOption) (*CreateAdminAdTemplateResponse, error)
UpdateAdminAdTemplate(ctx context.Context, in *UpdateAdminAdTemplateRequest, opts ...grpc.CallOption) (*UpdateAdminAdTemplateResponse, error) UpdateAdminAdTemplate(ctx context.Context, in *UpdateAdminAdTemplateRequest, opts ...grpc.CallOption) (*UpdateAdminAdTemplateResponse, error)
DeleteAdminAdTemplate(ctx context.Context, in *DeleteAdminAdTemplateRequest, opts ...grpc.CallOption) (*MessageResponse, error) DeleteAdminAdTemplate(ctx context.Context, in *DeleteAdminAdTemplateRequest, opts ...grpc.CallOption) (*MessageResponse, error)
ListAdminPopupAds(ctx context.Context, in *ListAdminPopupAdsRequest, opts ...grpc.CallOption) (*ListAdminPopupAdsResponse, error)
GetAdminPopupAd(ctx context.Context, in *GetAdminPopupAdRequest, opts ...grpc.CallOption) (*GetAdminPopupAdResponse, error)
CreateAdminPopupAd(ctx context.Context, in *CreateAdminPopupAdRequest, opts ...grpc.CallOption) (*CreateAdminPopupAdResponse, error)
UpdateAdminPopupAd(ctx context.Context, in *UpdateAdminPopupAdRequest, opts ...grpc.CallOption) (*UpdateAdminPopupAdResponse, error)
DeleteAdminPopupAd(ctx context.Context, in *DeleteAdminPopupAdRequest, opts ...grpc.CallOption) (*MessageResponse, error)
ListAdminPlayerConfigs(ctx context.Context, in *ListAdminPlayerConfigsRequest, opts ...grpc.CallOption) (*ListAdminPlayerConfigsResponse, error) ListAdminPlayerConfigs(ctx context.Context, in *ListAdminPlayerConfigsRequest, opts ...grpc.CallOption) (*ListAdminPlayerConfigsResponse, error)
GetAdminPlayerConfig(ctx context.Context, in *GetAdminPlayerConfigRequest, opts ...grpc.CallOption) (*GetAdminPlayerConfigResponse, error) GetAdminPlayerConfig(ctx context.Context, in *GetAdminPlayerConfigRequest, opts ...grpc.CallOption) (*GetAdminPlayerConfigResponse, error)
CreateAdminPlayerConfig(ctx context.Context, in *CreateAdminPlayerConfigRequest, opts ...grpc.CallOption) (*CreateAdminPlayerConfigResponse, error) CreateAdminPlayerConfig(ctx context.Context, in *CreateAdminPlayerConfigRequest, opts ...grpc.CallOption) (*CreateAdminPlayerConfigResponse, error)
@@ -375,6 +385,56 @@ func (c *adminClient) DeleteAdminAdTemplate(ctx context.Context, in *DeleteAdmin
return out, nil return out, nil
} }
func (c *adminClient) ListAdminPopupAds(ctx context.Context, in *ListAdminPopupAdsRequest, opts ...grpc.CallOption) (*ListAdminPopupAdsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListAdminPopupAdsResponse)
err := c.cc.Invoke(ctx, Admin_ListAdminPopupAds_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *adminClient) GetAdminPopupAd(ctx context.Context, in *GetAdminPopupAdRequest, opts ...grpc.CallOption) (*GetAdminPopupAdResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetAdminPopupAdResponse)
err := c.cc.Invoke(ctx, Admin_GetAdminPopupAd_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *adminClient) CreateAdminPopupAd(ctx context.Context, in *CreateAdminPopupAdRequest, opts ...grpc.CallOption) (*CreateAdminPopupAdResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CreateAdminPopupAdResponse)
err := c.cc.Invoke(ctx, Admin_CreateAdminPopupAd_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *adminClient) UpdateAdminPopupAd(ctx context.Context, in *UpdateAdminPopupAdRequest, opts ...grpc.CallOption) (*UpdateAdminPopupAdResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UpdateAdminPopupAdResponse)
err := c.cc.Invoke(ctx, Admin_UpdateAdminPopupAd_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *adminClient) DeleteAdminPopupAd(ctx context.Context, in *DeleteAdminPopupAdRequest, opts ...grpc.CallOption) (*MessageResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MessageResponse)
err := c.cc.Invoke(ctx, Admin_DeleteAdminPopupAd_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *adminClient) ListAdminPlayerConfigs(ctx context.Context, in *ListAdminPlayerConfigsRequest, opts ...grpc.CallOption) (*ListAdminPlayerConfigsResponse, error) { func (c *adminClient) ListAdminPlayerConfigs(ctx context.Context, in *ListAdminPlayerConfigsRequest, opts ...grpc.CallOption) (*ListAdminPlayerConfigsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListAdminPlayerConfigsResponse) out := new(ListAdminPlayerConfigsResponse)
@@ -545,6 +605,11 @@ type AdminServer interface {
CreateAdminAdTemplate(context.Context, *CreateAdminAdTemplateRequest) (*CreateAdminAdTemplateResponse, error) CreateAdminAdTemplate(context.Context, *CreateAdminAdTemplateRequest) (*CreateAdminAdTemplateResponse, error)
UpdateAdminAdTemplate(context.Context, *UpdateAdminAdTemplateRequest) (*UpdateAdminAdTemplateResponse, error) UpdateAdminAdTemplate(context.Context, *UpdateAdminAdTemplateRequest) (*UpdateAdminAdTemplateResponse, error)
DeleteAdminAdTemplate(context.Context, *DeleteAdminAdTemplateRequest) (*MessageResponse, error) DeleteAdminAdTemplate(context.Context, *DeleteAdminAdTemplateRequest) (*MessageResponse, error)
ListAdminPopupAds(context.Context, *ListAdminPopupAdsRequest) (*ListAdminPopupAdsResponse, error)
GetAdminPopupAd(context.Context, *GetAdminPopupAdRequest) (*GetAdminPopupAdResponse, error)
CreateAdminPopupAd(context.Context, *CreateAdminPopupAdRequest) (*CreateAdminPopupAdResponse, error)
UpdateAdminPopupAd(context.Context, *UpdateAdminPopupAdRequest) (*UpdateAdminPopupAdResponse, error)
DeleteAdminPopupAd(context.Context, *DeleteAdminPopupAdRequest) (*MessageResponse, error)
ListAdminPlayerConfigs(context.Context, *ListAdminPlayerConfigsRequest) (*ListAdminPlayerConfigsResponse, error) ListAdminPlayerConfigs(context.Context, *ListAdminPlayerConfigsRequest) (*ListAdminPlayerConfigsResponse, error)
GetAdminPlayerConfig(context.Context, *GetAdminPlayerConfigRequest) (*GetAdminPlayerConfigResponse, error) GetAdminPlayerConfig(context.Context, *GetAdminPlayerConfigRequest) (*GetAdminPlayerConfigResponse, error)
CreateAdminPlayerConfig(context.Context, *CreateAdminPlayerConfigRequest) (*CreateAdminPlayerConfigResponse, error) CreateAdminPlayerConfig(context.Context, *CreateAdminPlayerConfigRequest) (*CreateAdminPlayerConfigResponse, error)
@@ -647,6 +712,21 @@ func (UnimplementedAdminServer) UpdateAdminAdTemplate(context.Context, *UpdateAd
func (UnimplementedAdminServer) DeleteAdminAdTemplate(context.Context, *DeleteAdminAdTemplateRequest) (*MessageResponse, error) { func (UnimplementedAdminServer) DeleteAdminAdTemplate(context.Context, *DeleteAdminAdTemplateRequest) (*MessageResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeleteAdminAdTemplate not implemented") return nil, status.Error(codes.Unimplemented, "method DeleteAdminAdTemplate not implemented")
} }
func (UnimplementedAdminServer) ListAdminPopupAds(context.Context, *ListAdminPopupAdsRequest) (*ListAdminPopupAdsResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListAdminPopupAds not implemented")
}
func (UnimplementedAdminServer) GetAdminPopupAd(context.Context, *GetAdminPopupAdRequest) (*GetAdminPopupAdResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetAdminPopupAd not implemented")
}
func (UnimplementedAdminServer) CreateAdminPopupAd(context.Context, *CreateAdminPopupAdRequest) (*CreateAdminPopupAdResponse, error) {
return nil, status.Error(codes.Unimplemented, "method CreateAdminPopupAd not implemented")
}
func (UnimplementedAdminServer) UpdateAdminPopupAd(context.Context, *UpdateAdminPopupAdRequest) (*UpdateAdminPopupAdResponse, error) {
return nil, status.Error(codes.Unimplemented, "method UpdateAdminPopupAd not implemented")
}
func (UnimplementedAdminServer) DeleteAdminPopupAd(context.Context, *DeleteAdminPopupAdRequest) (*MessageResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeleteAdminPopupAd not implemented")
}
func (UnimplementedAdminServer) ListAdminPlayerConfigs(context.Context, *ListAdminPlayerConfigsRequest) (*ListAdminPlayerConfigsResponse, error) { func (UnimplementedAdminServer) ListAdminPlayerConfigs(context.Context, *ListAdminPlayerConfigsRequest) (*ListAdminPlayerConfigsResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListAdminPlayerConfigs not implemented") return nil, status.Error(codes.Unimplemented, "method ListAdminPlayerConfigs not implemented")
} }
@@ -1178,6 +1258,96 @@ func _Admin_DeleteAdminAdTemplate_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Admin_ListAdminPopupAds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListAdminPopupAdsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AdminServer).ListAdminPopupAds(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Admin_ListAdminPopupAds_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AdminServer).ListAdminPopupAds(ctx, req.(*ListAdminPopupAdsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Admin_GetAdminPopupAd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetAdminPopupAdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AdminServer).GetAdminPopupAd(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Admin_GetAdminPopupAd_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AdminServer).GetAdminPopupAd(ctx, req.(*GetAdminPopupAdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Admin_CreateAdminPopupAd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateAdminPopupAdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AdminServer).CreateAdminPopupAd(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Admin_CreateAdminPopupAd_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AdminServer).CreateAdminPopupAd(ctx, req.(*CreateAdminPopupAdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Admin_UpdateAdminPopupAd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateAdminPopupAdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AdminServer).UpdateAdminPopupAd(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Admin_UpdateAdminPopupAd_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AdminServer).UpdateAdminPopupAd(ctx, req.(*UpdateAdminPopupAdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Admin_DeleteAdminPopupAd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteAdminPopupAdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AdminServer).DeleteAdminPopupAd(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Admin_DeleteAdminPopupAd_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AdminServer).DeleteAdminPopupAd(ctx, req.(*DeleteAdminPopupAdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Admin_ListAdminPlayerConfigs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Admin_ListAdminPlayerConfigs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListAdminPlayerConfigsRequest) in := new(ListAdminPlayerConfigsRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@@ -1541,6 +1711,26 @@ var Admin_ServiceDesc = grpc.ServiceDesc{
MethodName: "DeleteAdminAdTemplate", MethodName: "DeleteAdminAdTemplate",
Handler: _Admin_DeleteAdminAdTemplate_Handler, Handler: _Admin_DeleteAdminAdTemplate_Handler,
}, },
{
MethodName: "ListAdminPopupAds",
Handler: _Admin_ListAdminPopupAds_Handler,
},
{
MethodName: "GetAdminPopupAd",
Handler: _Admin_GetAdminPopupAd_Handler,
},
{
MethodName: "CreateAdminPopupAd",
Handler: _Admin_CreateAdminPopupAd_Handler,
},
{
MethodName: "UpdateAdminPopupAd",
Handler: _Admin_UpdateAdminPopupAd_Handler,
},
{
MethodName: "DeleteAdminPopupAd",
Handler: _Admin_DeleteAdminPopupAd_Handler,
},
{ {
MethodName: "ListAdminPlayerConfigs", MethodName: "ListAdminPlayerConfigs",
Handler: _Admin_ListAdminPlayerConfigs_Handler, Handler: _Admin_ListAdminPlayerConfigs_Handler,

View File

@@ -637,6 +637,498 @@ func (x *DeleteAdTemplateRequest) GetId() string {
return "" return ""
} }
type ListPopupAdsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Page int32 `protobuf:"varint,1,opt,name=page,proto3" json:"page,omitempty"`
Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListPopupAdsRequest) Reset() {
*x = ListPopupAdsRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListPopupAdsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListPopupAdsRequest) ProtoMessage() {}
func (x *ListPopupAdsRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListPopupAdsRequest.ProtoReflect.Descriptor instead.
func (*ListPopupAdsRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{12}
}
func (x *ListPopupAdsRequest) GetPage() int32 {
if x != nil {
return x.Page
}
return 0
}
func (x *ListPopupAdsRequest) GetLimit() int32 {
if x != nil {
return x.Limit
}
return 0
}
type ListPopupAdsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Items []*PopupAd `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"`
Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"`
Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListPopupAdsResponse) Reset() {
*x = ListPopupAdsResponse{}
mi := &file_app_v1_catalog_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListPopupAdsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListPopupAdsResponse) ProtoMessage() {}
func (x *ListPopupAdsResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[13]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListPopupAdsResponse.ProtoReflect.Descriptor instead.
func (*ListPopupAdsResponse) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{13}
}
func (x *ListPopupAdsResponse) GetItems() []*PopupAd {
if x != nil {
return x.Items
}
return nil
}
func (x *ListPopupAdsResponse) GetTotal() int64 {
if x != nil {
return x.Total
}
return 0
}
func (x *ListPopupAdsResponse) GetPage() int32 {
if x != nil {
return x.Page
}
return 0
}
func (x *ListPopupAdsResponse) GetLimit() int32 {
if x != nil {
return x.Limit
}
return 0
}
type CreatePopupAdRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"`
Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
IsActive *bool `protobuf:"varint,4,opt,name=is_active,json=isActive,proto3,oneof" json:"is_active,omitempty"`
MaxTriggersPerSession *int32 `protobuf:"varint,5,opt,name=max_triggers_per_session,json=maxTriggersPerSession,proto3,oneof" json:"max_triggers_per_session,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreatePopupAdRequest) Reset() {
*x = CreatePopupAdRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreatePopupAdRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreatePopupAdRequest) ProtoMessage() {}
func (x *CreatePopupAdRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[14]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreatePopupAdRequest.ProtoReflect.Descriptor instead.
func (*CreatePopupAdRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{14}
}
func (x *CreatePopupAdRequest) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *CreatePopupAdRequest) GetLabel() string {
if x != nil {
return x.Label
}
return ""
}
func (x *CreatePopupAdRequest) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
func (x *CreatePopupAdRequest) GetIsActive() bool {
if x != nil && x.IsActive != nil {
return *x.IsActive
}
return false
}
func (x *CreatePopupAdRequest) GetMaxTriggersPerSession() int32 {
if x != nil && x.MaxTriggersPerSession != nil {
return *x.MaxTriggersPerSession
}
return 0
}
type CreatePopupAdResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Item *PopupAd `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreatePopupAdResponse) Reset() {
*x = CreatePopupAdResponse{}
mi := &file_app_v1_catalog_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreatePopupAdResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreatePopupAdResponse) ProtoMessage() {}
func (x *CreatePopupAdResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[15]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreatePopupAdResponse.ProtoReflect.Descriptor instead.
func (*CreatePopupAdResponse) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{15}
}
func (x *CreatePopupAdResponse) GetItem() *PopupAd {
if x != nil {
return x.Item
}
return nil
}
type UpdatePopupAdRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
Label string `protobuf:"bytes,3,opt,name=label,proto3" json:"label,omitempty"`
Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
IsActive *bool `protobuf:"varint,5,opt,name=is_active,json=isActive,proto3,oneof" json:"is_active,omitempty"`
MaxTriggersPerSession *int32 `protobuf:"varint,6,opt,name=max_triggers_per_session,json=maxTriggersPerSession,proto3,oneof" json:"max_triggers_per_session,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UpdatePopupAdRequest) Reset() {
*x = UpdatePopupAdRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdatePopupAdRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdatePopupAdRequest) ProtoMessage() {}
func (x *UpdatePopupAdRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[16]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UpdatePopupAdRequest.ProtoReflect.Descriptor instead.
func (*UpdatePopupAdRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{16}
}
func (x *UpdatePopupAdRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *UpdatePopupAdRequest) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *UpdatePopupAdRequest) GetLabel() string {
if x != nil {
return x.Label
}
return ""
}
func (x *UpdatePopupAdRequest) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
func (x *UpdatePopupAdRequest) GetIsActive() bool {
if x != nil && x.IsActive != nil {
return *x.IsActive
}
return false
}
func (x *UpdatePopupAdRequest) GetMaxTriggersPerSession() int32 {
if x != nil && x.MaxTriggersPerSession != nil {
return *x.MaxTriggersPerSession
}
return 0
}
type UpdatePopupAdResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Item *PopupAd `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UpdatePopupAdResponse) Reset() {
*x = UpdatePopupAdResponse{}
mi := &file_app_v1_catalog_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdatePopupAdResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdatePopupAdResponse) ProtoMessage() {}
func (x *UpdatePopupAdResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[17]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UpdatePopupAdResponse.ProtoReflect.Descriptor instead.
func (*UpdatePopupAdResponse) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{17}
}
func (x *UpdatePopupAdResponse) GetItem() *PopupAd {
if x != nil {
return x.Item
}
return nil
}
type DeletePopupAdRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeletePopupAdRequest) Reset() {
*x = DeletePopupAdRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeletePopupAdRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeletePopupAdRequest) ProtoMessage() {}
func (x *DeletePopupAdRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[18]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeletePopupAdRequest.ProtoReflect.Descriptor instead.
func (*DeletePopupAdRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{18}
}
func (x *DeletePopupAdRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type GetActivePopupAdRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetActivePopupAdRequest) Reset() {
*x = GetActivePopupAdRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetActivePopupAdRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetActivePopupAdRequest) ProtoMessage() {}
func (x *GetActivePopupAdRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[19]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetActivePopupAdRequest.ProtoReflect.Descriptor instead.
func (*GetActivePopupAdRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{19}
}
type GetActivePopupAdResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Item *PopupAd `protobuf:"bytes,1,opt,name=item,proto3,oneof" json:"item,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetActivePopupAdResponse) Reset() {
*x = GetActivePopupAdResponse{}
mi := &file_app_v1_catalog_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetActivePopupAdResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetActivePopupAdResponse) ProtoMessage() {}
func (x *GetActivePopupAdResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[20]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetActivePopupAdResponse.ProtoReflect.Descriptor instead.
func (*GetActivePopupAdResponse) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{20}
}
func (x *GetActivePopupAdResponse) GetItem() *PopupAd {
if x != nil {
return x.Item
}
return nil
}
type ListPlayerConfigsRequest struct { type ListPlayerConfigsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
@@ -645,7 +1137,7 @@ type ListPlayerConfigsRequest struct {
func (x *ListPlayerConfigsRequest) Reset() { func (x *ListPlayerConfigsRequest) Reset() {
*x = ListPlayerConfigsRequest{} *x = ListPlayerConfigsRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[12] mi := &file_app_v1_catalog_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -657,7 +1149,7 @@ func (x *ListPlayerConfigsRequest) String() string {
func (*ListPlayerConfigsRequest) ProtoMessage() {} func (*ListPlayerConfigsRequest) ProtoMessage() {}
func (x *ListPlayerConfigsRequest) ProtoReflect() protoreflect.Message { func (x *ListPlayerConfigsRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[12] mi := &file_app_v1_catalog_proto_msgTypes[21]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -670,7 +1162,7 @@ func (x *ListPlayerConfigsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListPlayerConfigsRequest.ProtoReflect.Descriptor instead. // Deprecated: Use ListPlayerConfigsRequest.ProtoReflect.Descriptor instead.
func (*ListPlayerConfigsRequest) Descriptor() ([]byte, []int) { func (*ListPlayerConfigsRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{12} return file_app_v1_catalog_proto_rawDescGZIP(), []int{21}
} }
type ListPlayerConfigsResponse struct { type ListPlayerConfigsResponse struct {
@@ -682,7 +1174,7 @@ type ListPlayerConfigsResponse struct {
func (x *ListPlayerConfigsResponse) Reset() { func (x *ListPlayerConfigsResponse) Reset() {
*x = ListPlayerConfigsResponse{} *x = ListPlayerConfigsResponse{}
mi := &file_app_v1_catalog_proto_msgTypes[13] mi := &file_app_v1_catalog_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -694,7 +1186,7 @@ func (x *ListPlayerConfigsResponse) String() string {
func (*ListPlayerConfigsResponse) ProtoMessage() {} func (*ListPlayerConfigsResponse) ProtoMessage() {}
func (x *ListPlayerConfigsResponse) ProtoReflect() protoreflect.Message { func (x *ListPlayerConfigsResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[13] mi := &file_app_v1_catalog_proto_msgTypes[22]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -707,7 +1199,7 @@ func (x *ListPlayerConfigsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListPlayerConfigsResponse.ProtoReflect.Descriptor instead. // Deprecated: Use ListPlayerConfigsResponse.ProtoReflect.Descriptor instead.
func (*ListPlayerConfigsResponse) Descriptor() ([]byte, []int) { func (*ListPlayerConfigsResponse) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{13} return file_app_v1_catalog_proto_rawDescGZIP(), []int{22}
} }
func (x *ListPlayerConfigsResponse) GetConfigs() []*PlayerConfig { func (x *ListPlayerConfigsResponse) GetConfigs() []*PlayerConfig {
@@ -738,7 +1230,7 @@ type CreatePlayerConfigRequest struct {
func (x *CreatePlayerConfigRequest) Reset() { func (x *CreatePlayerConfigRequest) Reset() {
*x = CreatePlayerConfigRequest{} *x = CreatePlayerConfigRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[14] mi := &file_app_v1_catalog_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -750,7 +1242,7 @@ func (x *CreatePlayerConfigRequest) String() string {
func (*CreatePlayerConfigRequest) ProtoMessage() {} func (*CreatePlayerConfigRequest) ProtoMessage() {}
func (x *CreatePlayerConfigRequest) ProtoReflect() protoreflect.Message { func (x *CreatePlayerConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[14] mi := &file_app_v1_catalog_proto_msgTypes[23]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -763,7 +1255,7 @@ func (x *CreatePlayerConfigRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use CreatePlayerConfigRequest.ProtoReflect.Descriptor instead. // Deprecated: Use CreatePlayerConfigRequest.ProtoReflect.Descriptor instead.
func (*CreatePlayerConfigRequest) Descriptor() ([]byte, []int) { func (*CreatePlayerConfigRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{14} return file_app_v1_catalog_proto_rawDescGZIP(), []int{23}
} }
func (x *CreatePlayerConfigRequest) GetName() string { func (x *CreatePlayerConfigRequest) GetName() string {
@@ -866,7 +1358,7 @@ type CreatePlayerConfigResponse struct {
func (x *CreatePlayerConfigResponse) Reset() { func (x *CreatePlayerConfigResponse) Reset() {
*x = CreatePlayerConfigResponse{} *x = CreatePlayerConfigResponse{}
mi := &file_app_v1_catalog_proto_msgTypes[15] mi := &file_app_v1_catalog_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -878,7 +1370,7 @@ func (x *CreatePlayerConfigResponse) String() string {
func (*CreatePlayerConfigResponse) ProtoMessage() {} func (*CreatePlayerConfigResponse) ProtoMessage() {}
func (x *CreatePlayerConfigResponse) ProtoReflect() protoreflect.Message { func (x *CreatePlayerConfigResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[15] mi := &file_app_v1_catalog_proto_msgTypes[24]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -891,7 +1383,7 @@ func (x *CreatePlayerConfigResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use CreatePlayerConfigResponse.ProtoReflect.Descriptor instead. // Deprecated: Use CreatePlayerConfigResponse.ProtoReflect.Descriptor instead.
func (*CreatePlayerConfigResponse) Descriptor() ([]byte, []int) { func (*CreatePlayerConfigResponse) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{15} return file_app_v1_catalog_proto_rawDescGZIP(), []int{24}
} }
func (x *CreatePlayerConfigResponse) GetConfig() *PlayerConfig { func (x *CreatePlayerConfigResponse) GetConfig() *PlayerConfig {
@@ -923,7 +1415,7 @@ type UpdatePlayerConfigRequest struct {
func (x *UpdatePlayerConfigRequest) Reset() { func (x *UpdatePlayerConfigRequest) Reset() {
*x = UpdatePlayerConfigRequest{} *x = UpdatePlayerConfigRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[16] mi := &file_app_v1_catalog_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -935,7 +1427,7 @@ func (x *UpdatePlayerConfigRequest) String() string {
func (*UpdatePlayerConfigRequest) ProtoMessage() {} func (*UpdatePlayerConfigRequest) ProtoMessage() {}
func (x *UpdatePlayerConfigRequest) ProtoReflect() protoreflect.Message { func (x *UpdatePlayerConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[16] mi := &file_app_v1_catalog_proto_msgTypes[25]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -948,7 +1440,7 @@ func (x *UpdatePlayerConfigRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdatePlayerConfigRequest.ProtoReflect.Descriptor instead. // Deprecated: Use UpdatePlayerConfigRequest.ProtoReflect.Descriptor instead.
func (*UpdatePlayerConfigRequest) Descriptor() ([]byte, []int) { func (*UpdatePlayerConfigRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{16} return file_app_v1_catalog_proto_rawDescGZIP(), []int{25}
} }
func (x *UpdatePlayerConfigRequest) GetId() string { func (x *UpdatePlayerConfigRequest) GetId() string {
@@ -1058,7 +1550,7 @@ type UpdatePlayerConfigResponse struct {
func (x *UpdatePlayerConfigResponse) Reset() { func (x *UpdatePlayerConfigResponse) Reset() {
*x = UpdatePlayerConfigResponse{} *x = UpdatePlayerConfigResponse{}
mi := &file_app_v1_catalog_proto_msgTypes[17] mi := &file_app_v1_catalog_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1070,7 +1562,7 @@ func (x *UpdatePlayerConfigResponse) String() string {
func (*UpdatePlayerConfigResponse) ProtoMessage() {} func (*UpdatePlayerConfigResponse) ProtoMessage() {}
func (x *UpdatePlayerConfigResponse) ProtoReflect() protoreflect.Message { func (x *UpdatePlayerConfigResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[17] mi := &file_app_v1_catalog_proto_msgTypes[26]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1083,7 +1575,7 @@ func (x *UpdatePlayerConfigResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdatePlayerConfigResponse.ProtoReflect.Descriptor instead. // Deprecated: Use UpdatePlayerConfigResponse.ProtoReflect.Descriptor instead.
func (*UpdatePlayerConfigResponse) Descriptor() ([]byte, []int) { func (*UpdatePlayerConfigResponse) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{17} return file_app_v1_catalog_proto_rawDescGZIP(), []int{26}
} }
func (x *UpdatePlayerConfigResponse) GetConfig() *PlayerConfig { func (x *UpdatePlayerConfigResponse) GetConfig() *PlayerConfig {
@@ -1102,7 +1594,7 @@ type DeletePlayerConfigRequest struct {
func (x *DeletePlayerConfigRequest) Reset() { func (x *DeletePlayerConfigRequest) Reset() {
*x = DeletePlayerConfigRequest{} *x = DeletePlayerConfigRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[18] mi := &file_app_v1_catalog_proto_msgTypes[27]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1114,7 +1606,7 @@ func (x *DeletePlayerConfigRequest) String() string {
func (*DeletePlayerConfigRequest) ProtoMessage() {} func (*DeletePlayerConfigRequest) ProtoMessage() {}
func (x *DeletePlayerConfigRequest) ProtoReflect() protoreflect.Message { func (x *DeletePlayerConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[18] mi := &file_app_v1_catalog_proto_msgTypes[27]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1127,7 +1619,7 @@ func (x *DeletePlayerConfigRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeletePlayerConfigRequest.ProtoReflect.Descriptor instead. // Deprecated: Use DeletePlayerConfigRequest.ProtoReflect.Descriptor instead.
func (*DeletePlayerConfigRequest) Descriptor() ([]byte, []int) { func (*DeletePlayerConfigRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{18} return file_app_v1_catalog_proto_rawDescGZIP(), []int{27}
} }
func (x *DeletePlayerConfigRequest) GetId() string { func (x *DeletePlayerConfigRequest) GetId() string {
@@ -1145,7 +1637,7 @@ type ListPlansRequest struct {
func (x *ListPlansRequest) Reset() { func (x *ListPlansRequest) Reset() {
*x = ListPlansRequest{} *x = ListPlansRequest{}
mi := &file_app_v1_catalog_proto_msgTypes[19] mi := &file_app_v1_catalog_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1157,7 +1649,7 @@ func (x *ListPlansRequest) String() string {
func (*ListPlansRequest) ProtoMessage() {} func (*ListPlansRequest) ProtoMessage() {}
func (x *ListPlansRequest) ProtoReflect() protoreflect.Message { func (x *ListPlansRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[19] mi := &file_app_v1_catalog_proto_msgTypes[28]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1170,7 +1662,7 @@ func (x *ListPlansRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListPlansRequest.ProtoReflect.Descriptor instead. // Deprecated: Use ListPlansRequest.ProtoReflect.Descriptor instead.
func (*ListPlansRequest) Descriptor() ([]byte, []int) { func (*ListPlansRequest) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{19} return file_app_v1_catalog_proto_rawDescGZIP(), []int{28}
} }
type ListPlansResponse struct { type ListPlansResponse struct {
@@ -1182,7 +1674,7 @@ type ListPlansResponse struct {
func (x *ListPlansResponse) Reset() { func (x *ListPlansResponse) Reset() {
*x = ListPlansResponse{} *x = ListPlansResponse{}
mi := &file_app_v1_catalog_proto_msgTypes[20] mi := &file_app_v1_catalog_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1194,7 +1686,7 @@ func (x *ListPlansResponse) String() string {
func (*ListPlansResponse) ProtoMessage() {} func (*ListPlansResponse) ProtoMessage() {}
func (x *ListPlansResponse) ProtoReflect() protoreflect.Message { func (x *ListPlansResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_catalog_proto_msgTypes[20] mi := &file_app_v1_catalog_proto_msgTypes[29]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1207,7 +1699,7 @@ func (x *ListPlansResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListPlansResponse.ProtoReflect.Descriptor instead. // Deprecated: Use ListPlansResponse.ProtoReflect.Descriptor instead.
func (*ListPlansResponse) Descriptor() ([]byte, []int) { func (*ListPlansResponse) Descriptor() ([]byte, []int) {
return file_app_v1_catalog_proto_rawDescGZIP(), []int{20} return file_app_v1_catalog_proto_rawDescGZIP(), []int{29}
} }
func (x *ListPlansResponse) GetPlans() []*Plan { func (x *ListPlansResponse) GetPlans() []*Plan {
@@ -1274,7 +1766,44 @@ const file_app_v1_catalog_proto_rawDesc = "" +
"\x18UpdateAdTemplateResponse\x125\n" + "\x18UpdateAdTemplateResponse\x125\n" +
"\btemplate\x18\x01 \x01(\v2\x19.stream.app.v1.AdTemplateR\btemplate\")\n" + "\btemplate\x18\x01 \x01(\v2\x19.stream.app.v1.AdTemplateR\btemplate\")\n" +
"\x17DeleteAdTemplateRequest\x12\x0e\n" + "\x17DeleteAdTemplateRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"\x1a\n" + "\x02id\x18\x01 \x01(\tR\x02id\"?\n" +
"\x13ListPopupAdsRequest\x12\x12\n" +
"\x04page\x18\x01 \x01(\x05R\x04page\x12\x14\n" +
"\x05limit\x18\x02 \x01(\x05R\x05limit\"\x84\x01\n" +
"\x14ListPopupAdsResponse\x12,\n" +
"\x05items\x18\x01 \x03(\v2\x16.stream.app.v1.PopupAdR\x05items\x12\x14\n" +
"\x05total\x18\x02 \x01(\x03R\x05total\x12\x12\n" +
"\x04page\x18\x03 \x01(\x05R\x04page\x12\x14\n" +
"\x05limit\x18\x04 \x01(\x05R\x05limit\"\xe1\x01\n" +
"\x14CreatePopupAdRequest\x12\x12\n" +
"\x04type\x18\x01 \x01(\tR\x04type\x12\x14\n" +
"\x05label\x18\x02 \x01(\tR\x05label\x12\x14\n" +
"\x05value\x18\x03 \x01(\tR\x05value\x12 \n" +
"\tis_active\x18\x04 \x01(\bH\x00R\bisActive\x88\x01\x01\x12<\n" +
"\x18max_triggers_per_session\x18\x05 \x01(\x05H\x01R\x15maxTriggersPerSession\x88\x01\x01B\f\n" +
"\n" +
"_is_activeB\x1b\n" +
"\x19_max_triggers_per_session\"C\n" +
"\x15CreatePopupAdResponse\x12*\n" +
"\x04item\x18\x01 \x01(\v2\x16.stream.app.v1.PopupAdR\x04item\"\xf1\x01\n" +
"\x14UpdatePopupAdRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
"\x04type\x18\x02 \x01(\tR\x04type\x12\x14\n" +
"\x05label\x18\x03 \x01(\tR\x05label\x12\x14\n" +
"\x05value\x18\x04 \x01(\tR\x05value\x12 \n" +
"\tis_active\x18\x05 \x01(\bH\x00R\bisActive\x88\x01\x01\x12<\n" +
"\x18max_triggers_per_session\x18\x06 \x01(\x05H\x01R\x15maxTriggersPerSession\x88\x01\x01B\f\n" +
"\n" +
"_is_activeB\x1b\n" +
"\x19_max_triggers_per_session\"C\n" +
"\x15UpdatePopupAdResponse\x12*\n" +
"\x04item\x18\x01 \x01(\v2\x16.stream.app.v1.PopupAdR\x04item\"&\n" +
"\x14DeletePopupAdRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"\x19\n" +
"\x17GetActivePopupAdRequest\"T\n" +
"\x18GetActivePopupAdResponse\x12/\n" +
"\x04item\x18\x01 \x01(\v2\x16.stream.app.v1.PopupAdH\x00R\x04item\x88\x01\x01B\a\n" +
"\x05_item\"\x1a\n" +
"\x18ListPlayerConfigsRequest\"R\n" + "\x18ListPlayerConfigsRequest\"R\n" +
"\x19ListPlayerConfigsResponse\x125\n" + "\x19ListPlayerConfigsResponse\x125\n" +
"\aconfigs\x18\x01 \x03(\v2\x1b.stream.app.v1.PlayerConfigR\aconfigs\"\xec\x03\n" + "\aconfigs\x18\x01 \x03(\v2\x1b.stream.app.v1.PlayerConfigR\aconfigs\"\xec\x03\n" +
@@ -1344,7 +1873,13 @@ const file_app_v1_catalog_proto_rawDesc = "" +
"\x0fListAdTemplates\x12%.stream.app.v1.ListAdTemplatesRequest\x1a&.stream.app.v1.ListAdTemplatesResponse\x12c\n" + "\x0fListAdTemplates\x12%.stream.app.v1.ListAdTemplatesRequest\x1a&.stream.app.v1.ListAdTemplatesResponse\x12c\n" +
"\x10CreateAdTemplate\x12&.stream.app.v1.CreateAdTemplateRequest\x1a'.stream.app.v1.CreateAdTemplateResponse\x12c\n" + "\x10CreateAdTemplate\x12&.stream.app.v1.CreateAdTemplateRequest\x1a'.stream.app.v1.CreateAdTemplateResponse\x12c\n" +
"\x10UpdateAdTemplate\x12&.stream.app.v1.UpdateAdTemplateRequest\x1a'.stream.app.v1.UpdateAdTemplateResponse\x12Z\n" + "\x10UpdateAdTemplate\x12&.stream.app.v1.UpdateAdTemplateRequest\x1a'.stream.app.v1.UpdateAdTemplateResponse\x12Z\n" +
"\x10DeleteAdTemplate\x12&.stream.app.v1.DeleteAdTemplateRequest\x1a\x1e.stream.app.v1.MessageResponse2\xad\x03\n" + "\x10DeleteAdTemplate\x12&.stream.app.v1.DeleteAdTemplateRequest\x1a\x1e.stream.app.v1.MessageResponse2\xd6\x03\n" +
"\bPopupAds\x12W\n" +
"\fListPopupAds\x12\".stream.app.v1.ListPopupAdsRequest\x1a#.stream.app.v1.ListPopupAdsResponse\x12Z\n" +
"\rCreatePopupAd\x12#.stream.app.v1.CreatePopupAdRequest\x1a$.stream.app.v1.CreatePopupAdResponse\x12Z\n" +
"\rUpdatePopupAd\x12#.stream.app.v1.UpdatePopupAdRequest\x1a$.stream.app.v1.UpdatePopupAdResponse\x12T\n" +
"\rDeletePopupAd\x12#.stream.app.v1.DeletePopupAdRequest\x1a\x1e.stream.app.v1.MessageResponse\x12c\n" +
"\x10GetActivePopupAd\x12&.stream.app.v1.GetActivePopupAdRequest\x1a'.stream.app.v1.GetActivePopupAdResponse2\xad\x03\n" +
"\rPlayerConfigs\x12f\n" + "\rPlayerConfigs\x12f\n" +
"\x11ListPlayerConfigs\x12'.stream.app.v1.ListPlayerConfigsRequest\x1a(.stream.app.v1.ListPlayerConfigsResponse\x12i\n" + "\x11ListPlayerConfigs\x12'.stream.app.v1.ListPlayerConfigsRequest\x1a(.stream.app.v1.ListPlayerConfigsResponse\x12i\n" +
"\x12CreatePlayerConfig\x12(.stream.app.v1.CreatePlayerConfigRequest\x1a).stream.app.v1.CreatePlayerConfigResponse\x12i\n" + "\x12CreatePlayerConfig\x12(.stream.app.v1.CreatePlayerConfigRequest\x1a).stream.app.v1.CreatePlayerConfigResponse\x12i\n" +
@@ -1365,7 +1900,7 @@ func file_app_v1_catalog_proto_rawDescGZIP() []byte {
return file_app_v1_catalog_proto_rawDescData return file_app_v1_catalog_proto_rawDescData
} }
var file_app_v1_catalog_proto_msgTypes = make([]protoimpl.MessageInfo, 21) var file_app_v1_catalog_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
var file_app_v1_catalog_proto_goTypes = []any{ var file_app_v1_catalog_proto_goTypes = []any{
(*ListDomainsRequest)(nil), // 0: stream.app.v1.ListDomainsRequest (*ListDomainsRequest)(nil), // 0: stream.app.v1.ListDomainsRequest
(*ListDomainsResponse)(nil), // 1: stream.app.v1.ListDomainsResponse (*ListDomainsResponse)(nil), // 1: stream.app.v1.ListDomainsResponse
@@ -1379,60 +1914,84 @@ var file_app_v1_catalog_proto_goTypes = []any{
(*UpdateAdTemplateRequest)(nil), // 9: stream.app.v1.UpdateAdTemplateRequest (*UpdateAdTemplateRequest)(nil), // 9: stream.app.v1.UpdateAdTemplateRequest
(*UpdateAdTemplateResponse)(nil), // 10: stream.app.v1.UpdateAdTemplateResponse (*UpdateAdTemplateResponse)(nil), // 10: stream.app.v1.UpdateAdTemplateResponse
(*DeleteAdTemplateRequest)(nil), // 11: stream.app.v1.DeleteAdTemplateRequest (*DeleteAdTemplateRequest)(nil), // 11: stream.app.v1.DeleteAdTemplateRequest
(*ListPlayerConfigsRequest)(nil), // 12: stream.app.v1.ListPlayerConfigsRequest (*ListPopupAdsRequest)(nil), // 12: stream.app.v1.ListPopupAdsRequest
(*ListPlayerConfigsResponse)(nil), // 13: stream.app.v1.ListPlayerConfigsResponse (*ListPopupAdsResponse)(nil), // 13: stream.app.v1.ListPopupAdsResponse
(*CreatePlayerConfigRequest)(nil), // 14: stream.app.v1.CreatePlayerConfigRequest (*CreatePopupAdRequest)(nil), // 14: stream.app.v1.CreatePopupAdRequest
(*CreatePlayerConfigResponse)(nil), // 15: stream.app.v1.CreatePlayerConfigResponse (*CreatePopupAdResponse)(nil), // 15: stream.app.v1.CreatePopupAdResponse
(*UpdatePlayerConfigRequest)(nil), // 16: stream.app.v1.UpdatePlayerConfigRequest (*UpdatePopupAdRequest)(nil), // 16: stream.app.v1.UpdatePopupAdRequest
(*UpdatePlayerConfigResponse)(nil), // 17: stream.app.v1.UpdatePlayerConfigResponse (*UpdatePopupAdResponse)(nil), // 17: stream.app.v1.UpdatePopupAdResponse
(*DeletePlayerConfigRequest)(nil), // 18: stream.app.v1.DeletePlayerConfigRequest (*DeletePopupAdRequest)(nil), // 18: stream.app.v1.DeletePopupAdRequest
(*ListPlansRequest)(nil), // 19: stream.app.v1.ListPlansRequest (*GetActivePopupAdRequest)(nil), // 19: stream.app.v1.GetActivePopupAdRequest
(*ListPlansResponse)(nil), // 20: stream.app.v1.ListPlansResponse (*GetActivePopupAdResponse)(nil), // 20: stream.app.v1.GetActivePopupAdResponse
(*Domain)(nil), // 21: stream.app.v1.Domain (*ListPlayerConfigsRequest)(nil), // 21: stream.app.v1.ListPlayerConfigsRequest
(*AdTemplate)(nil), // 22: stream.app.v1.AdTemplate (*ListPlayerConfigsResponse)(nil), // 22: stream.app.v1.ListPlayerConfigsResponse
(*PlayerConfig)(nil), // 23: stream.app.v1.PlayerConfig (*CreatePlayerConfigRequest)(nil), // 23: stream.app.v1.CreatePlayerConfigRequest
(*Plan)(nil), // 24: stream.app.v1.Plan (*CreatePlayerConfigResponse)(nil), // 24: stream.app.v1.CreatePlayerConfigResponse
(*MessageResponse)(nil), // 25: stream.app.v1.MessageResponse (*UpdatePlayerConfigRequest)(nil), // 25: stream.app.v1.UpdatePlayerConfigRequest
(*UpdatePlayerConfigResponse)(nil), // 26: stream.app.v1.UpdatePlayerConfigResponse
(*DeletePlayerConfigRequest)(nil), // 27: stream.app.v1.DeletePlayerConfigRequest
(*ListPlansRequest)(nil), // 28: stream.app.v1.ListPlansRequest
(*ListPlansResponse)(nil), // 29: stream.app.v1.ListPlansResponse
(*Domain)(nil), // 30: stream.app.v1.Domain
(*AdTemplate)(nil), // 31: stream.app.v1.AdTemplate
(*PopupAd)(nil), // 32: stream.app.v1.PopupAd
(*PlayerConfig)(nil), // 33: stream.app.v1.PlayerConfig
(*Plan)(nil), // 34: stream.app.v1.Plan
(*MessageResponse)(nil), // 35: stream.app.v1.MessageResponse
} }
var file_app_v1_catalog_proto_depIdxs = []int32{ var file_app_v1_catalog_proto_depIdxs = []int32{
21, // 0: stream.app.v1.ListDomainsResponse.domains:type_name -> stream.app.v1.Domain 30, // 0: stream.app.v1.ListDomainsResponse.domains:type_name -> stream.app.v1.Domain
21, // 1: stream.app.v1.CreateDomainResponse.domain:type_name -> stream.app.v1.Domain 30, // 1: stream.app.v1.CreateDomainResponse.domain:type_name -> stream.app.v1.Domain
22, // 2: stream.app.v1.ListAdTemplatesResponse.templates:type_name -> stream.app.v1.AdTemplate 31, // 2: stream.app.v1.ListAdTemplatesResponse.templates:type_name -> stream.app.v1.AdTemplate
22, // 3: stream.app.v1.CreateAdTemplateResponse.template:type_name -> stream.app.v1.AdTemplate 31, // 3: stream.app.v1.CreateAdTemplateResponse.template:type_name -> stream.app.v1.AdTemplate
22, // 4: stream.app.v1.UpdateAdTemplateResponse.template:type_name -> stream.app.v1.AdTemplate 31, // 4: stream.app.v1.UpdateAdTemplateResponse.template:type_name -> stream.app.v1.AdTemplate
23, // 5: stream.app.v1.ListPlayerConfigsResponse.configs:type_name -> stream.app.v1.PlayerConfig 32, // 5: stream.app.v1.ListPopupAdsResponse.items:type_name -> stream.app.v1.PopupAd
23, // 6: stream.app.v1.CreatePlayerConfigResponse.config:type_name -> stream.app.v1.PlayerConfig 32, // 6: stream.app.v1.CreatePopupAdResponse.item:type_name -> stream.app.v1.PopupAd
23, // 7: stream.app.v1.UpdatePlayerConfigResponse.config:type_name -> stream.app.v1.PlayerConfig 32, // 7: stream.app.v1.UpdatePopupAdResponse.item:type_name -> stream.app.v1.PopupAd
24, // 8: stream.app.v1.ListPlansResponse.plans:type_name -> stream.app.v1.Plan 32, // 8: stream.app.v1.GetActivePopupAdResponse.item:type_name -> stream.app.v1.PopupAd
0, // 9: stream.app.v1.Domains.ListDomains:input_type -> stream.app.v1.ListDomainsRequest 33, // 9: stream.app.v1.ListPlayerConfigsResponse.configs:type_name -> stream.app.v1.PlayerConfig
2, // 10: stream.app.v1.Domains.CreateDomain:input_type -> stream.app.v1.CreateDomainRequest 33, // 10: stream.app.v1.CreatePlayerConfigResponse.config:type_name -> stream.app.v1.PlayerConfig
4, // 11: stream.app.v1.Domains.DeleteDomain:input_type -> stream.app.v1.DeleteDomainRequest 33, // 11: stream.app.v1.UpdatePlayerConfigResponse.config:type_name -> stream.app.v1.PlayerConfig
5, // 12: stream.app.v1.AdTemplates.ListAdTemplates:input_type -> stream.app.v1.ListAdTemplatesRequest 34, // 12: stream.app.v1.ListPlansResponse.plans:type_name -> stream.app.v1.Plan
7, // 13: stream.app.v1.AdTemplates.CreateAdTemplate:input_type -> stream.app.v1.CreateAdTemplateRequest 0, // 13: stream.app.v1.Domains.ListDomains:input_type -> stream.app.v1.ListDomainsRequest
9, // 14: stream.app.v1.AdTemplates.UpdateAdTemplate:input_type -> stream.app.v1.UpdateAdTemplateRequest 2, // 14: stream.app.v1.Domains.CreateDomain:input_type -> stream.app.v1.CreateDomainRequest
11, // 15: stream.app.v1.AdTemplates.DeleteAdTemplate:input_type -> stream.app.v1.DeleteAdTemplateRequest 4, // 15: stream.app.v1.Domains.DeleteDomain:input_type -> stream.app.v1.DeleteDomainRequest
12, // 16: stream.app.v1.PlayerConfigs.ListPlayerConfigs:input_type -> stream.app.v1.ListPlayerConfigsRequest 5, // 16: stream.app.v1.AdTemplates.ListAdTemplates:input_type -> stream.app.v1.ListAdTemplatesRequest
14, // 17: stream.app.v1.PlayerConfigs.CreatePlayerConfig:input_type -> stream.app.v1.CreatePlayerConfigRequest 7, // 17: stream.app.v1.AdTemplates.CreateAdTemplate:input_type -> stream.app.v1.CreateAdTemplateRequest
16, // 18: stream.app.v1.PlayerConfigs.UpdatePlayerConfig:input_type -> stream.app.v1.UpdatePlayerConfigRequest 9, // 18: stream.app.v1.AdTemplates.UpdateAdTemplate:input_type -> stream.app.v1.UpdateAdTemplateRequest
18, // 19: stream.app.v1.PlayerConfigs.DeletePlayerConfig:input_type -> stream.app.v1.DeletePlayerConfigRequest 11, // 19: stream.app.v1.AdTemplates.DeleteAdTemplate:input_type -> stream.app.v1.DeleteAdTemplateRequest
19, // 20: stream.app.v1.Plans.ListPlans:input_type -> stream.app.v1.ListPlansRequest 12, // 20: stream.app.v1.PopupAds.ListPopupAds:input_type -> stream.app.v1.ListPopupAdsRequest
1, // 21: stream.app.v1.Domains.ListDomains:output_type -> stream.app.v1.ListDomainsResponse 14, // 21: stream.app.v1.PopupAds.CreatePopupAd:input_type -> stream.app.v1.CreatePopupAdRequest
3, // 22: stream.app.v1.Domains.CreateDomain:output_type -> stream.app.v1.CreateDomainResponse 16, // 22: stream.app.v1.PopupAds.UpdatePopupAd:input_type -> stream.app.v1.UpdatePopupAdRequest
25, // 23: stream.app.v1.Domains.DeleteDomain:output_type -> stream.app.v1.MessageResponse 18, // 23: stream.app.v1.PopupAds.DeletePopupAd:input_type -> stream.app.v1.DeletePopupAdRequest
6, // 24: stream.app.v1.AdTemplates.ListAdTemplates:output_type -> stream.app.v1.ListAdTemplatesResponse 19, // 24: stream.app.v1.PopupAds.GetActivePopupAd:input_type -> stream.app.v1.GetActivePopupAdRequest
8, // 25: stream.app.v1.AdTemplates.CreateAdTemplate:output_type -> stream.app.v1.CreateAdTemplateResponse 21, // 25: stream.app.v1.PlayerConfigs.ListPlayerConfigs:input_type -> stream.app.v1.ListPlayerConfigsRequest
10, // 26: stream.app.v1.AdTemplates.UpdateAdTemplate:output_type -> stream.app.v1.UpdateAdTemplateResponse 23, // 26: stream.app.v1.PlayerConfigs.CreatePlayerConfig:input_type -> stream.app.v1.CreatePlayerConfigRequest
25, // 27: stream.app.v1.AdTemplates.DeleteAdTemplate:output_type -> stream.app.v1.MessageResponse 25, // 27: stream.app.v1.PlayerConfigs.UpdatePlayerConfig:input_type -> stream.app.v1.UpdatePlayerConfigRequest
13, // 28: stream.app.v1.PlayerConfigs.ListPlayerConfigs:output_type -> stream.app.v1.ListPlayerConfigsResponse 27, // 28: stream.app.v1.PlayerConfigs.DeletePlayerConfig:input_type -> stream.app.v1.DeletePlayerConfigRequest
15, // 29: stream.app.v1.PlayerConfigs.CreatePlayerConfig:output_type -> stream.app.v1.CreatePlayerConfigResponse 28, // 29: stream.app.v1.Plans.ListPlans:input_type -> stream.app.v1.ListPlansRequest
17, // 30: stream.app.v1.PlayerConfigs.UpdatePlayerConfig:output_type -> stream.app.v1.UpdatePlayerConfigResponse 1, // 30: stream.app.v1.Domains.ListDomains:output_type -> stream.app.v1.ListDomainsResponse
25, // 31: stream.app.v1.PlayerConfigs.DeletePlayerConfig:output_type -> stream.app.v1.MessageResponse 3, // 31: stream.app.v1.Domains.CreateDomain:output_type -> stream.app.v1.CreateDomainResponse
20, // 32: stream.app.v1.Plans.ListPlans:output_type -> stream.app.v1.ListPlansResponse 35, // 32: stream.app.v1.Domains.DeleteDomain:output_type -> stream.app.v1.MessageResponse
21, // [21:33] is the sub-list for method output_type 6, // 33: stream.app.v1.AdTemplates.ListAdTemplates:output_type -> stream.app.v1.ListAdTemplatesResponse
9, // [9:21] is the sub-list for method input_type 8, // 34: stream.app.v1.AdTemplates.CreateAdTemplate:output_type -> stream.app.v1.CreateAdTemplateResponse
9, // [9:9] is the sub-list for extension type_name 10, // 35: stream.app.v1.AdTemplates.UpdateAdTemplate:output_type -> stream.app.v1.UpdateAdTemplateResponse
9, // [9:9] is the sub-list for extension extendee 35, // 36: stream.app.v1.AdTemplates.DeleteAdTemplate:output_type -> stream.app.v1.MessageResponse
0, // [0:9] is the sub-list for field type_name 13, // 37: stream.app.v1.PopupAds.ListPopupAds:output_type -> stream.app.v1.ListPopupAdsResponse
15, // 38: stream.app.v1.PopupAds.CreatePopupAd:output_type -> stream.app.v1.CreatePopupAdResponse
17, // 39: stream.app.v1.PopupAds.UpdatePopupAd:output_type -> stream.app.v1.UpdatePopupAdResponse
35, // 40: stream.app.v1.PopupAds.DeletePopupAd:output_type -> stream.app.v1.MessageResponse
20, // 41: stream.app.v1.PopupAds.GetActivePopupAd:output_type -> stream.app.v1.GetActivePopupAdResponse
22, // 42: stream.app.v1.PlayerConfigs.ListPlayerConfigs:output_type -> stream.app.v1.ListPlayerConfigsResponse
24, // 43: stream.app.v1.PlayerConfigs.CreatePlayerConfig:output_type -> stream.app.v1.CreatePlayerConfigResponse
26, // 44: stream.app.v1.PlayerConfigs.UpdatePlayerConfig:output_type -> stream.app.v1.UpdatePlayerConfigResponse
35, // 45: stream.app.v1.PlayerConfigs.DeletePlayerConfig:output_type -> stream.app.v1.MessageResponse
29, // 46: stream.app.v1.Plans.ListPlans:output_type -> stream.app.v1.ListPlansResponse
30, // [30:47] is the sub-list for method output_type
13, // [13:30] is the sub-list for method input_type
13, // [13:13] is the sub-list for extension type_name
13, // [13:13] is the sub-list for extension extendee
0, // [0:13] is the sub-list for field type_name
} }
func init() { file_app_v1_catalog_proto_init() } func init() { file_app_v1_catalog_proto_init() }
@@ -1445,15 +2004,18 @@ func file_app_v1_catalog_proto_init() {
file_app_v1_catalog_proto_msgTypes[9].OneofWrappers = []any{} file_app_v1_catalog_proto_msgTypes[9].OneofWrappers = []any{}
file_app_v1_catalog_proto_msgTypes[14].OneofWrappers = []any{} file_app_v1_catalog_proto_msgTypes[14].OneofWrappers = []any{}
file_app_v1_catalog_proto_msgTypes[16].OneofWrappers = []any{} file_app_v1_catalog_proto_msgTypes[16].OneofWrappers = []any{}
file_app_v1_catalog_proto_msgTypes[20].OneofWrappers = []any{}
file_app_v1_catalog_proto_msgTypes[23].OneofWrappers = []any{}
file_app_v1_catalog_proto_msgTypes[25].OneofWrappers = []any{}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_v1_catalog_proto_rawDesc), len(file_app_v1_catalog_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_v1_catalog_proto_rawDesc), len(file_app_v1_catalog_proto_rawDesc)),
NumEnums: 0, NumEnums: 0,
NumMessages: 21, NumMessages: 30,
NumExtensions: 0, NumExtensions: 0,
NumServices: 4, NumServices: 5,
}, },
GoTypes: file_app_v1_catalog_proto_goTypes, GoTypes: file_app_v1_catalog_proto_goTypes,
DependencyIndexes: file_app_v1_catalog_proto_depIdxs, DependencyIndexes: file_app_v1_catalog_proto_depIdxs,

View File

@@ -412,6 +412,260 @@ var AdTemplates_ServiceDesc = grpc.ServiceDesc{
Metadata: "app/v1/catalog.proto", Metadata: "app/v1/catalog.proto",
} }
const (
PopupAds_ListPopupAds_FullMethodName = "/stream.app.v1.PopupAds/ListPopupAds"
PopupAds_CreatePopupAd_FullMethodName = "/stream.app.v1.PopupAds/CreatePopupAd"
PopupAds_UpdatePopupAd_FullMethodName = "/stream.app.v1.PopupAds/UpdatePopupAd"
PopupAds_DeletePopupAd_FullMethodName = "/stream.app.v1.PopupAds/DeletePopupAd"
PopupAds_GetActivePopupAd_FullMethodName = "/stream.app.v1.PopupAds/GetActivePopupAd"
)
// PopupAdsClient is the client API for PopupAds service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type PopupAdsClient interface {
ListPopupAds(ctx context.Context, in *ListPopupAdsRequest, opts ...grpc.CallOption) (*ListPopupAdsResponse, error)
CreatePopupAd(ctx context.Context, in *CreatePopupAdRequest, opts ...grpc.CallOption) (*CreatePopupAdResponse, error)
UpdatePopupAd(ctx context.Context, in *UpdatePopupAdRequest, opts ...grpc.CallOption) (*UpdatePopupAdResponse, error)
DeletePopupAd(ctx context.Context, in *DeletePopupAdRequest, opts ...grpc.CallOption) (*MessageResponse, error)
GetActivePopupAd(ctx context.Context, in *GetActivePopupAdRequest, opts ...grpc.CallOption) (*GetActivePopupAdResponse, error)
}
type popupAdsClient struct {
cc grpc.ClientConnInterface
}
func NewPopupAdsClient(cc grpc.ClientConnInterface) PopupAdsClient {
return &popupAdsClient{cc}
}
func (c *popupAdsClient) ListPopupAds(ctx context.Context, in *ListPopupAdsRequest, opts ...grpc.CallOption) (*ListPopupAdsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListPopupAdsResponse)
err := c.cc.Invoke(ctx, PopupAds_ListPopupAds_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *popupAdsClient) CreatePopupAd(ctx context.Context, in *CreatePopupAdRequest, opts ...grpc.CallOption) (*CreatePopupAdResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CreatePopupAdResponse)
err := c.cc.Invoke(ctx, PopupAds_CreatePopupAd_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *popupAdsClient) UpdatePopupAd(ctx context.Context, in *UpdatePopupAdRequest, opts ...grpc.CallOption) (*UpdatePopupAdResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UpdatePopupAdResponse)
err := c.cc.Invoke(ctx, PopupAds_UpdatePopupAd_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *popupAdsClient) DeletePopupAd(ctx context.Context, in *DeletePopupAdRequest, opts ...grpc.CallOption) (*MessageResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MessageResponse)
err := c.cc.Invoke(ctx, PopupAds_DeletePopupAd_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *popupAdsClient) GetActivePopupAd(ctx context.Context, in *GetActivePopupAdRequest, opts ...grpc.CallOption) (*GetActivePopupAdResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetActivePopupAdResponse)
err := c.cc.Invoke(ctx, PopupAds_GetActivePopupAd_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// PopupAdsServer is the server API for PopupAds service.
// All implementations must embed UnimplementedPopupAdsServer
// for forward compatibility.
type PopupAdsServer interface {
ListPopupAds(context.Context, *ListPopupAdsRequest) (*ListPopupAdsResponse, error)
CreatePopupAd(context.Context, *CreatePopupAdRequest) (*CreatePopupAdResponse, error)
UpdatePopupAd(context.Context, *UpdatePopupAdRequest) (*UpdatePopupAdResponse, error)
DeletePopupAd(context.Context, *DeletePopupAdRequest) (*MessageResponse, error)
GetActivePopupAd(context.Context, *GetActivePopupAdRequest) (*GetActivePopupAdResponse, error)
mustEmbedUnimplementedPopupAdsServer()
}
// UnimplementedPopupAdsServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedPopupAdsServer struct{}
func (UnimplementedPopupAdsServer) ListPopupAds(context.Context, *ListPopupAdsRequest) (*ListPopupAdsResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListPopupAds not implemented")
}
func (UnimplementedPopupAdsServer) CreatePopupAd(context.Context, *CreatePopupAdRequest) (*CreatePopupAdResponse, error) {
return nil, status.Error(codes.Unimplemented, "method CreatePopupAd not implemented")
}
func (UnimplementedPopupAdsServer) UpdatePopupAd(context.Context, *UpdatePopupAdRequest) (*UpdatePopupAdResponse, error) {
return nil, status.Error(codes.Unimplemented, "method UpdatePopupAd not implemented")
}
func (UnimplementedPopupAdsServer) DeletePopupAd(context.Context, *DeletePopupAdRequest) (*MessageResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeletePopupAd not implemented")
}
func (UnimplementedPopupAdsServer) GetActivePopupAd(context.Context, *GetActivePopupAdRequest) (*GetActivePopupAdResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetActivePopupAd not implemented")
}
func (UnimplementedPopupAdsServer) mustEmbedUnimplementedPopupAdsServer() {}
func (UnimplementedPopupAdsServer) testEmbeddedByValue() {}
// UnsafePopupAdsServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to PopupAdsServer will
// result in compilation errors.
type UnsafePopupAdsServer interface {
mustEmbedUnimplementedPopupAdsServer()
}
func RegisterPopupAdsServer(s grpc.ServiceRegistrar, srv PopupAdsServer) {
// If the following call panics, it indicates UnimplementedPopupAdsServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&PopupAds_ServiceDesc, srv)
}
func _PopupAds_ListPopupAds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListPopupAdsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PopupAdsServer).ListPopupAds(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PopupAds_ListPopupAds_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PopupAdsServer).ListPopupAds(ctx, req.(*ListPopupAdsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PopupAds_CreatePopupAd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreatePopupAdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PopupAdsServer).CreatePopupAd(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PopupAds_CreatePopupAd_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PopupAdsServer).CreatePopupAd(ctx, req.(*CreatePopupAdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PopupAds_UpdatePopupAd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdatePopupAdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PopupAdsServer).UpdatePopupAd(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PopupAds_UpdatePopupAd_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PopupAdsServer).UpdatePopupAd(ctx, req.(*UpdatePopupAdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PopupAds_DeletePopupAd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeletePopupAdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PopupAdsServer).DeletePopupAd(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PopupAds_DeletePopupAd_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PopupAdsServer).DeletePopupAd(ctx, req.(*DeletePopupAdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PopupAds_GetActivePopupAd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetActivePopupAdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PopupAdsServer).GetActivePopupAd(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PopupAds_GetActivePopupAd_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PopupAdsServer).GetActivePopupAd(ctx, req.(*GetActivePopupAdRequest))
}
return interceptor(ctx, in, info, handler)
}
// PopupAds_ServiceDesc is the grpc.ServiceDesc for PopupAds service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var PopupAds_ServiceDesc = grpc.ServiceDesc{
ServiceName: "stream.app.v1.PopupAds",
HandlerType: (*PopupAdsServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListPopupAds",
Handler: _PopupAds_ListPopupAds_Handler,
},
{
MethodName: "CreatePopupAd",
Handler: _PopupAds_CreatePopupAd_Handler,
},
{
MethodName: "UpdatePopupAd",
Handler: _PopupAds_UpdatePopupAd_Handler,
},
{
MethodName: "DeletePopupAd",
Handler: _PopupAds_DeletePopupAd_Handler,
},
{
MethodName: "GetActivePopupAd",
Handler: _PopupAds_GetActivePopupAd_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "app/v1/catalog.proto",
}
const ( const (
PlayerConfigs_ListPlayerConfigs_FullMethodName = "/stream.app.v1.PlayerConfigs/ListPlayerConfigs" PlayerConfigs_ListPlayerConfigs_FullMethodName = "/stream.app.v1.PlayerConfigs/ListPlayerConfigs"
PlayerConfigs_CreatePlayerConfig_FullMethodName = "/stream.app.v1.PlayerConfigs/CreatePlayerConfig" PlayerConfigs_CreatePlayerConfig_FullMethodName = "/stream.app.v1.PlayerConfigs/CreatePlayerConfig"

View File

@@ -678,6 +678,106 @@ func (x *AdTemplate) GetUpdatedAt() *timestamppb.Timestamp {
return nil return nil
} }
type PopupAd struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
Label string `protobuf:"bytes,3,opt,name=label,proto3" json:"label,omitempty"`
Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
IsActive bool `protobuf:"varint,5,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"`
MaxTriggersPerSession int32 `protobuf:"varint,6,opt,name=max_triggers_per_session,json=maxTriggersPerSession,proto3" json:"max_triggers_per_session,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PopupAd) Reset() {
*x = PopupAd{}
mi := &file_app_v1_common_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PopupAd) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PopupAd) ProtoMessage() {}
func (x *PopupAd) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PopupAd.ProtoReflect.Descriptor instead.
func (*PopupAd) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{6}
}
func (x *PopupAd) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *PopupAd) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *PopupAd) GetLabel() string {
if x != nil {
return x.Label
}
return ""
}
func (x *PopupAd) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
func (x *PopupAd) GetIsActive() bool {
if x != nil {
return x.IsActive
}
return false
}
func (x *PopupAd) GetMaxTriggersPerSession() int32 {
if x != nil {
return x.MaxTriggersPerSession
}
return 0
}
func (x *PopupAd) GetCreatedAt() *timestamppb.Timestamp {
if x != nil {
return x.CreatedAt
}
return nil
}
func (x *PopupAd) GetUpdatedAt() *timestamppb.Timestamp {
if x != nil {
return x.UpdatedAt
}
return nil
}
type PlayerConfig struct { type PlayerConfig struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
@@ -702,7 +802,7 @@ type PlayerConfig struct {
func (x *PlayerConfig) Reset() { func (x *PlayerConfig) Reset() {
*x = PlayerConfig{} *x = PlayerConfig{}
mi := &file_app_v1_common_proto_msgTypes[6] mi := &file_app_v1_common_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -714,7 +814,7 @@ func (x *PlayerConfig) String() string {
func (*PlayerConfig) ProtoMessage() {} func (*PlayerConfig) ProtoMessage() {}
func (x *PlayerConfig) ProtoReflect() protoreflect.Message { func (x *PlayerConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[6] mi := &file_app_v1_common_proto_msgTypes[7]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -727,7 +827,7 @@ func (x *PlayerConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use PlayerConfig.ProtoReflect.Descriptor instead. // Deprecated: Use PlayerConfig.ProtoReflect.Descriptor instead.
func (*PlayerConfig) Descriptor() ([]byte, []int) { func (*PlayerConfig) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{6} return file_app_v1_common_proto_rawDescGZIP(), []int{7}
} }
func (x *PlayerConfig) GetId() string { func (x *PlayerConfig) GetId() string {
@@ -868,7 +968,7 @@ type AdminPlayerConfig struct {
func (x *AdminPlayerConfig) Reset() { func (x *AdminPlayerConfig) Reset() {
*x = AdminPlayerConfig{} *x = AdminPlayerConfig{}
mi := &file_app_v1_common_proto_msgTypes[7] mi := &file_app_v1_common_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -880,7 +980,7 @@ func (x *AdminPlayerConfig) String() string {
func (*AdminPlayerConfig) ProtoMessage() {} func (*AdminPlayerConfig) ProtoMessage() {}
func (x *AdminPlayerConfig) ProtoReflect() protoreflect.Message { func (x *AdminPlayerConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[7] mi := &file_app_v1_common_proto_msgTypes[8]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -893,7 +993,7 @@ func (x *AdminPlayerConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminPlayerConfig.ProtoReflect.Descriptor instead. // Deprecated: Use AdminPlayerConfig.ProtoReflect.Descriptor instead.
func (*AdminPlayerConfig) Descriptor() ([]byte, []int) { func (*AdminPlayerConfig) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{7} return file_app_v1_common_proto_rawDescGZIP(), []int{8}
} }
func (x *AdminPlayerConfig) GetId() string { func (x *AdminPlayerConfig) GetId() string {
@@ -1041,7 +1141,7 @@ type Plan struct {
func (x *Plan) Reset() { func (x *Plan) Reset() {
*x = Plan{} *x = Plan{}
mi := &file_app_v1_common_proto_msgTypes[8] mi := &file_app_v1_common_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1053,7 +1153,7 @@ func (x *Plan) String() string {
func (*Plan) ProtoMessage() {} func (*Plan) ProtoMessage() {}
func (x *Plan) ProtoReflect() protoreflect.Message { func (x *Plan) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[8] mi := &file_app_v1_common_proto_msgTypes[9]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1066,7 +1166,7 @@ func (x *Plan) ProtoReflect() protoreflect.Message {
// Deprecated: Use Plan.ProtoReflect.Descriptor instead. // Deprecated: Use Plan.ProtoReflect.Descriptor instead.
func (*Plan) Descriptor() ([]byte, []int) { func (*Plan) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{8} return file_app_v1_common_proto_rawDescGZIP(), []int{9}
} }
func (x *Plan) GetId() string { func (x *Plan) GetId() string {
@@ -1164,7 +1264,7 @@ type Payment struct {
func (x *Payment) Reset() { func (x *Payment) Reset() {
*x = Payment{} *x = Payment{}
mi := &file_app_v1_common_proto_msgTypes[9] mi := &file_app_v1_common_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1176,7 +1276,7 @@ func (x *Payment) String() string {
func (*Payment) ProtoMessage() {} func (*Payment) ProtoMessage() {}
func (x *Payment) ProtoReflect() protoreflect.Message { func (x *Payment) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[9] mi := &file_app_v1_common_proto_msgTypes[10]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1189,7 +1289,7 @@ func (x *Payment) ProtoReflect() protoreflect.Message {
// Deprecated: Use Payment.ProtoReflect.Descriptor instead. // Deprecated: Use Payment.ProtoReflect.Descriptor instead.
func (*Payment) Descriptor() ([]byte, []int) { func (*Payment) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{9} return file_app_v1_common_proto_rawDescGZIP(), []int{10}
} }
func (x *Payment) GetId() string { func (x *Payment) GetId() string {
@@ -1282,7 +1382,7 @@ type PlanSubscription struct {
func (x *PlanSubscription) Reset() { func (x *PlanSubscription) Reset() {
*x = PlanSubscription{} *x = PlanSubscription{}
mi := &file_app_v1_common_proto_msgTypes[10] mi := &file_app_v1_common_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1294,7 +1394,7 @@ func (x *PlanSubscription) String() string {
func (*PlanSubscription) ProtoMessage() {} func (*PlanSubscription) ProtoMessage() {}
func (x *PlanSubscription) ProtoReflect() protoreflect.Message { func (x *PlanSubscription) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[10] mi := &file_app_v1_common_proto_msgTypes[11]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1307,7 +1407,7 @@ func (x *PlanSubscription) ProtoReflect() protoreflect.Message {
// Deprecated: Use PlanSubscription.ProtoReflect.Descriptor instead. // Deprecated: Use PlanSubscription.ProtoReflect.Descriptor instead.
func (*PlanSubscription) Descriptor() ([]byte, []int) { func (*PlanSubscription) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{10} return file_app_v1_common_proto_rawDescGZIP(), []int{11}
} }
func (x *PlanSubscription) GetId() string { func (x *PlanSubscription) GetId() string {
@@ -1413,7 +1513,7 @@ type WalletTransaction struct {
func (x *WalletTransaction) Reset() { func (x *WalletTransaction) Reset() {
*x = WalletTransaction{} *x = WalletTransaction{}
mi := &file_app_v1_common_proto_msgTypes[11] mi := &file_app_v1_common_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1425,7 +1525,7 @@ func (x *WalletTransaction) String() string {
func (*WalletTransaction) ProtoMessage() {} func (*WalletTransaction) ProtoMessage() {}
func (x *WalletTransaction) ProtoReflect() protoreflect.Message { func (x *WalletTransaction) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[11] mi := &file_app_v1_common_proto_msgTypes[12]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1438,7 +1538,7 @@ func (x *WalletTransaction) ProtoReflect() protoreflect.Message {
// Deprecated: Use WalletTransaction.ProtoReflect.Descriptor instead. // Deprecated: Use WalletTransaction.ProtoReflect.Descriptor instead.
func (*WalletTransaction) Descriptor() ([]byte, []int) { func (*WalletTransaction) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{11} return file_app_v1_common_proto_rawDescGZIP(), []int{12}
} }
func (x *WalletTransaction) GetId() string { func (x *WalletTransaction) GetId() string {
@@ -1538,7 +1638,7 @@ type PaymentHistoryItem struct {
func (x *PaymentHistoryItem) Reset() { func (x *PaymentHistoryItem) Reset() {
*x = PaymentHistoryItem{} *x = PaymentHistoryItem{}
mi := &file_app_v1_common_proto_msgTypes[12] mi := &file_app_v1_common_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1550,7 +1650,7 @@ func (x *PaymentHistoryItem) String() string {
func (*PaymentHistoryItem) ProtoMessage() {} func (*PaymentHistoryItem) ProtoMessage() {}
func (x *PaymentHistoryItem) ProtoReflect() protoreflect.Message { func (x *PaymentHistoryItem) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[12] mi := &file_app_v1_common_proto_msgTypes[13]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1563,7 +1663,7 @@ func (x *PaymentHistoryItem) ProtoReflect() protoreflect.Message {
// Deprecated: Use PaymentHistoryItem.ProtoReflect.Descriptor instead. // Deprecated: Use PaymentHistoryItem.ProtoReflect.Descriptor instead.
func (*PaymentHistoryItem) Descriptor() ([]byte, []int) { func (*PaymentHistoryItem) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{12} return file_app_v1_common_proto_rawDescGZIP(), []int{13}
} }
func (x *PaymentHistoryItem) GetId() string { func (x *PaymentHistoryItem) GetId() string {
@@ -1673,7 +1773,7 @@ type Video struct {
func (x *Video) Reset() { func (x *Video) Reset() {
*x = Video{} *x = Video{}
mi := &file_app_v1_common_proto_msgTypes[13] mi := &file_app_v1_common_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1685,7 +1785,7 @@ func (x *Video) String() string {
func (*Video) ProtoMessage() {} func (*Video) ProtoMessage() {}
func (x *Video) ProtoReflect() protoreflect.Message { func (x *Video) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[13] mi := &file_app_v1_common_proto_msgTypes[14]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1698,7 +1798,7 @@ func (x *Video) ProtoReflect() protoreflect.Message {
// Deprecated: Use Video.ProtoReflect.Descriptor instead. // Deprecated: Use Video.ProtoReflect.Descriptor instead.
func (*Video) Descriptor() ([]byte, []int) { func (*Video) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{13} return file_app_v1_common_proto_rawDescGZIP(), []int{14}
} }
func (x *Video) GetId() string { func (x *Video) GetId() string {
@@ -1823,7 +1923,7 @@ type AdminDashboard struct {
func (x *AdminDashboard) Reset() { func (x *AdminDashboard) Reset() {
*x = AdminDashboard{} *x = AdminDashboard{}
mi := &file_app_v1_common_proto_msgTypes[14] mi := &file_app_v1_common_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1835,7 +1935,7 @@ func (x *AdminDashboard) String() string {
func (*AdminDashboard) ProtoMessage() {} func (*AdminDashboard) ProtoMessage() {}
func (x *AdminDashboard) ProtoReflect() protoreflect.Message { func (x *AdminDashboard) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[14] mi := &file_app_v1_common_proto_msgTypes[15]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1848,7 +1948,7 @@ func (x *AdminDashboard) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminDashboard.ProtoReflect.Descriptor instead. // Deprecated: Use AdminDashboard.ProtoReflect.Descriptor instead.
func (*AdminDashboard) Descriptor() ([]byte, []int) { func (*AdminDashboard) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{14} return file_app_v1_common_proto_rawDescGZIP(), []int{15}
} }
func (x *AdminDashboard) GetTotalUsers() int64 { func (x *AdminDashboard) GetTotalUsers() int64 {
@@ -1934,7 +2034,7 @@ type AdminUser struct {
func (x *AdminUser) Reset() { func (x *AdminUser) Reset() {
*x = AdminUser{} *x = AdminUser{}
mi := &file_app_v1_common_proto_msgTypes[15] mi := &file_app_v1_common_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1946,7 +2046,7 @@ func (x *AdminUser) String() string {
func (*AdminUser) ProtoMessage() {} func (*AdminUser) ProtoMessage() {}
func (x *AdminUser) ProtoReflect() protoreflect.Message { func (x *AdminUser) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[15] mi := &file_app_v1_common_proto_msgTypes[16]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1959,7 +2059,7 @@ func (x *AdminUser) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminUser.ProtoReflect.Descriptor instead. // Deprecated: Use AdminUser.ProtoReflect.Descriptor instead.
func (*AdminUser) Descriptor() ([]byte, []int) { func (*AdminUser) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{15} return file_app_v1_common_proto_rawDescGZIP(), []int{16}
} }
func (x *AdminUser) GetId() string { func (x *AdminUser) GetId() string {
@@ -2057,7 +2157,7 @@ type ReferralUserSummary struct {
func (x *ReferralUserSummary) Reset() { func (x *ReferralUserSummary) Reset() {
*x = ReferralUserSummary{} *x = ReferralUserSummary{}
mi := &file_app_v1_common_proto_msgTypes[16] mi := &file_app_v1_common_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -2069,7 +2169,7 @@ func (x *ReferralUserSummary) String() string {
func (*ReferralUserSummary) ProtoMessage() {} func (*ReferralUserSummary) ProtoMessage() {}
func (x *ReferralUserSummary) ProtoReflect() protoreflect.Message { func (x *ReferralUserSummary) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[16] mi := &file_app_v1_common_proto_msgTypes[17]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -2082,7 +2182,7 @@ func (x *ReferralUserSummary) ProtoReflect() protoreflect.Message {
// Deprecated: Use ReferralUserSummary.ProtoReflect.Descriptor instead. // Deprecated: Use ReferralUserSummary.ProtoReflect.Descriptor instead.
func (*ReferralUserSummary) Descriptor() ([]byte, []int) { func (*ReferralUserSummary) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{16} return file_app_v1_common_proto_rawDescGZIP(), []int{17}
} }
func (x *ReferralUserSummary) GetId() string { func (x *ReferralUserSummary) GetId() string {
@@ -2123,7 +2223,7 @@ type AdminUserReferralInfo struct {
func (x *AdminUserReferralInfo) Reset() { func (x *AdminUserReferralInfo) Reset() {
*x = AdminUserReferralInfo{} *x = AdminUserReferralInfo{}
mi := &file_app_v1_common_proto_msgTypes[17] mi := &file_app_v1_common_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -2135,7 +2235,7 @@ func (x *AdminUserReferralInfo) String() string {
func (*AdminUserReferralInfo) ProtoMessage() {} func (*AdminUserReferralInfo) ProtoMessage() {}
func (x *AdminUserReferralInfo) ProtoReflect() protoreflect.Message { func (x *AdminUserReferralInfo) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[17] mi := &file_app_v1_common_proto_msgTypes[18]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -2148,7 +2248,7 @@ func (x *AdminUserReferralInfo) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminUserReferralInfo.ProtoReflect.Descriptor instead. // Deprecated: Use AdminUserReferralInfo.ProtoReflect.Descriptor instead.
func (*AdminUserReferralInfo) Descriptor() ([]byte, []int) { func (*AdminUserReferralInfo) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{17} return file_app_v1_common_proto_rawDescGZIP(), []int{18}
} }
func (x *AdminUserReferralInfo) GetReferrer() *ReferralUserSummary { func (x *AdminUserReferralInfo) GetReferrer() *ReferralUserSummary {
@@ -2225,7 +2325,7 @@ type AdminUserDetail struct {
func (x *AdminUserDetail) Reset() { func (x *AdminUserDetail) Reset() {
*x = AdminUserDetail{} *x = AdminUserDetail{}
mi := &file_app_v1_common_proto_msgTypes[18] mi := &file_app_v1_common_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -2237,7 +2337,7 @@ func (x *AdminUserDetail) String() string {
func (*AdminUserDetail) ProtoMessage() {} func (*AdminUserDetail) ProtoMessage() {}
func (x *AdminUserDetail) ProtoReflect() protoreflect.Message { func (x *AdminUserDetail) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[18] mi := &file_app_v1_common_proto_msgTypes[19]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -2250,7 +2350,7 @@ func (x *AdminUserDetail) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminUserDetail.ProtoReflect.Descriptor instead. // Deprecated: Use AdminUserDetail.ProtoReflect.Descriptor instead.
func (*AdminUserDetail) Descriptor() ([]byte, []int) { func (*AdminUserDetail) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{18} return file_app_v1_common_proto_rawDescGZIP(), []int{19}
} }
func (x *AdminUserDetail) GetUser() *AdminUser { func (x *AdminUserDetail) GetUser() *AdminUser {
@@ -2298,7 +2398,7 @@ type AdminVideo struct {
func (x *AdminVideo) Reset() { func (x *AdminVideo) Reset() {
*x = AdminVideo{} *x = AdminVideo{}
mi := &file_app_v1_common_proto_msgTypes[19] mi := &file_app_v1_common_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -2310,7 +2410,7 @@ func (x *AdminVideo) String() string {
func (*AdminVideo) ProtoMessage() {} func (*AdminVideo) ProtoMessage() {}
func (x *AdminVideo) ProtoReflect() protoreflect.Message { func (x *AdminVideo) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[19] mi := &file_app_v1_common_proto_msgTypes[20]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -2323,7 +2423,7 @@ func (x *AdminVideo) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminVideo.ProtoReflect.Descriptor instead. // Deprecated: Use AdminVideo.ProtoReflect.Descriptor instead.
func (*AdminVideo) Descriptor() ([]byte, []int) { func (*AdminVideo) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{19} return file_app_v1_common_proto_rawDescGZIP(), []int{20}
} }
func (x *AdminVideo) GetId() string { func (x *AdminVideo) GetId() string {
@@ -2464,7 +2564,7 @@ type AdminPayment struct {
func (x *AdminPayment) Reset() { func (x *AdminPayment) Reset() {
*x = AdminPayment{} *x = AdminPayment{}
mi := &file_app_v1_common_proto_msgTypes[20] mi := &file_app_v1_common_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -2476,7 +2576,7 @@ func (x *AdminPayment) String() string {
func (*AdminPayment) ProtoMessage() {} func (*AdminPayment) ProtoMessage() {}
func (x *AdminPayment) ProtoReflect() protoreflect.Message { func (x *AdminPayment) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[20] mi := &file_app_v1_common_proto_msgTypes[21]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -2489,7 +2589,7 @@ func (x *AdminPayment) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminPayment.ProtoReflect.Descriptor instead. // Deprecated: Use AdminPayment.ProtoReflect.Descriptor instead.
func (*AdminPayment) Descriptor() ([]byte, []int) { func (*AdminPayment) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{20} return file_app_v1_common_proto_rawDescGZIP(), []int{21}
} }
func (x *AdminPayment) GetId() string { func (x *AdminPayment) GetId() string {
@@ -2640,7 +2740,7 @@ type AdminPlan struct {
func (x *AdminPlan) Reset() { func (x *AdminPlan) Reset() {
*x = AdminPlan{} *x = AdminPlan{}
mi := &file_app_v1_common_proto_msgTypes[21] mi := &file_app_v1_common_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -2652,7 +2752,7 @@ func (x *AdminPlan) String() string {
func (*AdminPlan) ProtoMessage() {} func (*AdminPlan) ProtoMessage() {}
func (x *AdminPlan) ProtoReflect() protoreflect.Message { func (x *AdminPlan) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[21] mi := &file_app_v1_common_proto_msgTypes[22]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -2665,7 +2765,7 @@ func (x *AdminPlan) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminPlan.ProtoReflect.Descriptor instead. // Deprecated: Use AdminPlan.ProtoReflect.Descriptor instead.
func (*AdminPlan) Descriptor() ([]byte, []int) { func (*AdminPlan) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{21} return file_app_v1_common_proto_rawDescGZIP(), []int{22}
} }
func (x *AdminPlan) GetId() string { func (x *AdminPlan) GetId() string {
@@ -2786,7 +2886,7 @@ type AdminAdTemplate struct {
func (x *AdminAdTemplate) Reset() { func (x *AdminAdTemplate) Reset() {
*x = AdminAdTemplate{} *x = AdminAdTemplate{}
mi := &file_app_v1_common_proto_msgTypes[22] mi := &file_app_v1_common_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -2798,7 +2898,7 @@ func (x *AdminAdTemplate) String() string {
func (*AdminAdTemplate) ProtoMessage() {} func (*AdminAdTemplate) ProtoMessage() {}
func (x *AdminAdTemplate) ProtoReflect() protoreflect.Message { func (x *AdminAdTemplate) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[22] mi := &file_app_v1_common_proto_msgTypes[23]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -2811,7 +2911,7 @@ func (x *AdminAdTemplate) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminAdTemplate.ProtoReflect.Descriptor instead. // Deprecated: Use AdminAdTemplate.ProtoReflect.Descriptor instead.
func (*AdminAdTemplate) Descriptor() ([]byte, []int) { func (*AdminAdTemplate) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{22} return file_app_v1_common_proto_rawDescGZIP(), []int{23}
} }
func (x *AdminAdTemplate) GetId() string { func (x *AdminAdTemplate) GetId() string {
@@ -2898,6 +2998,122 @@ func (x *AdminAdTemplate) GetUpdatedAt() *timestamppb.Timestamp {
return nil return nil
} }
type AdminPopupAd struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
Label string `protobuf:"bytes,4,opt,name=label,proto3" json:"label,omitempty"`
Value string `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"`
IsActive bool `protobuf:"varint,6,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"`
MaxTriggersPerSession int32 `protobuf:"varint,7,opt,name=max_triggers_per_session,json=maxTriggersPerSession,proto3" json:"max_triggers_per_session,omitempty"`
OwnerEmail *string `protobuf:"bytes,8,opt,name=owner_email,json=ownerEmail,proto3,oneof" json:"owner_email,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AdminPopupAd) Reset() {
*x = AdminPopupAd{}
mi := &file_app_v1_common_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AdminPopupAd) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AdminPopupAd) ProtoMessage() {}
func (x *AdminPopupAd) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[24]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AdminPopupAd.ProtoReflect.Descriptor instead.
func (*AdminPopupAd) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{24}
}
func (x *AdminPopupAd) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *AdminPopupAd) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *AdminPopupAd) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *AdminPopupAd) GetLabel() string {
if x != nil {
return x.Label
}
return ""
}
func (x *AdminPopupAd) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
func (x *AdminPopupAd) GetIsActive() bool {
if x != nil {
return x.IsActive
}
return false
}
func (x *AdminPopupAd) GetMaxTriggersPerSession() int32 {
if x != nil {
return x.MaxTriggersPerSession
}
return 0
}
func (x *AdminPopupAd) GetOwnerEmail() string {
if x != nil && x.OwnerEmail != nil {
return *x.OwnerEmail
}
return ""
}
func (x *AdminPopupAd) GetCreatedAt() *timestamppb.Timestamp {
if x != nil {
return x.CreatedAt
}
return nil
}
func (x *AdminPopupAd) GetUpdatedAt() *timestamppb.Timestamp {
if x != nil {
return x.UpdatedAt
}
return nil
}
type AdminJob struct { type AdminJob struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
@@ -2926,7 +3142,7 @@ type AdminJob struct {
func (x *AdminJob) Reset() { func (x *AdminJob) Reset() {
*x = AdminJob{} *x = AdminJob{}
mi := &file_app_v1_common_proto_msgTypes[23] mi := &file_app_v1_common_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -2938,7 +3154,7 @@ func (x *AdminJob) String() string {
func (*AdminJob) ProtoMessage() {} func (*AdminJob) ProtoMessage() {}
func (x *AdminJob) ProtoReflect() protoreflect.Message { func (x *AdminJob) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[23] mi := &file_app_v1_common_proto_msgTypes[25]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -2951,7 +3167,7 @@ func (x *AdminJob) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminJob.ProtoReflect.Descriptor instead. // Deprecated: Use AdminJob.ProtoReflect.Descriptor instead.
func (*AdminJob) Descriptor() ([]byte, []int) { func (*AdminJob) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{23} return file_app_v1_common_proto_rawDescGZIP(), []int{25}
} }
func (x *AdminJob) GetId() string { func (x *AdminJob) GetId() string {
@@ -3114,7 +3330,7 @@ type AdminAgent struct {
func (x *AdminAgent) Reset() { func (x *AdminAgent) Reset() {
*x = AdminAgent{} *x = AdminAgent{}
mi := &file_app_v1_common_proto_msgTypes[24] mi := &file_app_v1_common_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -3126,7 +3342,7 @@ func (x *AdminAgent) String() string {
func (*AdminAgent) ProtoMessage() {} func (*AdminAgent) ProtoMessage() {}
func (x *AdminAgent) ProtoReflect() protoreflect.Message { func (x *AdminAgent) ProtoReflect() protoreflect.Message {
mi := &file_app_v1_common_proto_msgTypes[24] mi := &file_app_v1_common_proto_msgTypes[26]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -3139,7 +3355,7 @@ func (x *AdminAgent) ProtoReflect() protoreflect.Message {
// Deprecated: Use AdminAgent.ProtoReflect.Descriptor instead. // Deprecated: Use AdminAgent.ProtoReflect.Descriptor instead.
func (*AdminAgent) Descriptor() ([]byte, []int) { func (*AdminAgent) Descriptor() ([]byte, []int) {
return file_app_v1_common_proto_rawDescGZIP(), []int{24} return file_app_v1_common_proto_rawDescGZIP(), []int{26}
} }
func (x *AdminAgent) GetId() string { func (x *AdminAgent) GetId() string {
@@ -3321,7 +3537,18 @@ const file_app_v1_common_proto_rawDesc = "" +
"updated_at\x18\n" + "updated_at\x18\n" +
" \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAtB\x0e\n" + " \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAtB\x0e\n" +
"\f_descriptionB\v\n" + "\f_descriptionB\v\n" +
"\t_duration\"\xa6\x04\n" + "\t_duration\"\xa5\x02\n" +
"\aPopupAd\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
"\x04type\x18\x02 \x01(\tR\x04type\x12\x14\n" +
"\x05label\x18\x03 \x01(\tR\x05label\x12\x14\n" +
"\x05value\x18\x04 \x01(\tR\x05value\x12\x1b\n" +
"\tis_active\x18\x05 \x01(\bR\bisActive\x127\n" +
"\x18max_triggers_per_session\x18\x06 \x01(\x05R\x15maxTriggersPerSession\x129\n" +
"\n" +
"created_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" +
"\n" +
"updated_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\"\xa6\x04\n" +
"\fPlayerConfig\x12\x0e\n" + "\fPlayerConfig\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
"\x04name\x18\x02 \x01(\tR\x04name\x12%\n" + "\x04name\x18\x02 \x01(\tR\x04name\x12%\n" +
@@ -3664,6 +3891,22 @@ const file_app_v1_common_proto_rawDesc = "" +
"updated_at\x18\f \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAtB\x0e\n" + "updated_at\x18\f \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAtB\x0e\n" +
"\f_descriptionB\v\n" + "\f_descriptionB\v\n" +
"\t_durationB\x0e\n" + "\t_durationB\x0e\n" +
"\f_owner_email\"\xf9\x02\n" +
"\fAdminPopupAd\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x17\n" +
"\auser_id\x18\x02 \x01(\tR\x06userId\x12\x12\n" +
"\x04type\x18\x03 \x01(\tR\x04type\x12\x14\n" +
"\x05label\x18\x04 \x01(\tR\x05label\x12\x14\n" +
"\x05value\x18\x05 \x01(\tR\x05value\x12\x1b\n" +
"\tis_active\x18\x06 \x01(\bR\bisActive\x127\n" +
"\x18max_triggers_per_session\x18\a \x01(\x05R\x15maxTriggersPerSession\x12$\n" +
"\vowner_email\x18\b \x01(\tH\x00R\n" +
"ownerEmail\x88\x01\x01\x129\n" +
"\n" +
"created_at\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" +
"\n" +
"updated_at\x18\n" +
" \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAtB\x0e\n" +
"\f_owner_email\"\x98\x05\n" + "\f_owner_email\"\x98\x05\n" +
"\bAdminJob\x12\x0e\n" + "\bAdminJob\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n" +
@@ -3725,7 +3968,7 @@ func file_app_v1_common_proto_rawDescGZIP() []byte {
return file_app_v1_common_proto_rawDescData return file_app_v1_common_proto_rawDescData
} }
var file_app_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_app_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
var file_app_v1_common_proto_goTypes = []any{ var file_app_v1_common_proto_goTypes = []any{
(*MessageResponse)(nil), // 0: stream.app.v1.MessageResponse (*MessageResponse)(nil), // 0: stream.app.v1.MessageResponse
(*User)(nil), // 1: stream.app.v1.User (*User)(nil), // 1: stream.app.v1.User
@@ -3733,76 +3976,82 @@ var file_app_v1_common_proto_goTypes = []any{
(*Notification)(nil), // 3: stream.app.v1.Notification (*Notification)(nil), // 3: stream.app.v1.Notification
(*Domain)(nil), // 4: stream.app.v1.Domain (*Domain)(nil), // 4: stream.app.v1.Domain
(*AdTemplate)(nil), // 5: stream.app.v1.AdTemplate (*AdTemplate)(nil), // 5: stream.app.v1.AdTemplate
(*PlayerConfig)(nil), // 6: stream.app.v1.PlayerConfig (*PopupAd)(nil), // 6: stream.app.v1.PopupAd
(*AdminPlayerConfig)(nil), // 7: stream.app.v1.AdminPlayerConfig (*PlayerConfig)(nil), // 7: stream.app.v1.PlayerConfig
(*Plan)(nil), // 8: stream.app.v1.Plan (*AdminPlayerConfig)(nil), // 8: stream.app.v1.AdminPlayerConfig
(*Payment)(nil), // 9: stream.app.v1.Payment (*Plan)(nil), // 9: stream.app.v1.Plan
(*PlanSubscription)(nil), // 10: stream.app.v1.PlanSubscription (*Payment)(nil), // 10: stream.app.v1.Payment
(*WalletTransaction)(nil), // 11: stream.app.v1.WalletTransaction (*PlanSubscription)(nil), // 11: stream.app.v1.PlanSubscription
(*PaymentHistoryItem)(nil), // 12: stream.app.v1.PaymentHistoryItem (*WalletTransaction)(nil), // 12: stream.app.v1.WalletTransaction
(*Video)(nil), // 13: stream.app.v1.Video (*PaymentHistoryItem)(nil), // 13: stream.app.v1.PaymentHistoryItem
(*AdminDashboard)(nil), // 14: stream.app.v1.AdminDashboard (*Video)(nil), // 14: stream.app.v1.Video
(*AdminUser)(nil), // 15: stream.app.v1.AdminUser (*AdminDashboard)(nil), // 15: stream.app.v1.AdminDashboard
(*ReferralUserSummary)(nil), // 16: stream.app.v1.ReferralUserSummary (*AdminUser)(nil), // 16: stream.app.v1.AdminUser
(*AdminUserReferralInfo)(nil), // 17: stream.app.v1.AdminUserReferralInfo (*ReferralUserSummary)(nil), // 17: stream.app.v1.ReferralUserSummary
(*AdminUserDetail)(nil), // 18: stream.app.v1.AdminUserDetail (*AdminUserReferralInfo)(nil), // 18: stream.app.v1.AdminUserReferralInfo
(*AdminVideo)(nil), // 19: stream.app.v1.AdminVideo (*AdminUserDetail)(nil), // 19: stream.app.v1.AdminUserDetail
(*AdminPayment)(nil), // 20: stream.app.v1.AdminPayment (*AdminVideo)(nil), // 20: stream.app.v1.AdminVideo
(*AdminPlan)(nil), // 21: stream.app.v1.AdminPlan (*AdminPayment)(nil), // 21: stream.app.v1.AdminPayment
(*AdminAdTemplate)(nil), // 22: stream.app.v1.AdminAdTemplate (*AdminPlan)(nil), // 22: stream.app.v1.AdminPlan
(*AdminJob)(nil), // 23: stream.app.v1.AdminJob (*AdminAdTemplate)(nil), // 23: stream.app.v1.AdminAdTemplate
(*AdminAgent)(nil), // 24: stream.app.v1.AdminAgent (*AdminPopupAd)(nil), // 24: stream.app.v1.AdminPopupAd
(*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp (*AdminJob)(nil), // 25: stream.app.v1.AdminJob
(*AdminAgent)(nil), // 26: stream.app.v1.AdminAgent
(*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp
} }
var file_app_v1_common_proto_depIdxs = []int32{ var file_app_v1_common_proto_depIdxs = []int32{
25, // 0: stream.app.v1.User.plan_started_at:type_name -> google.protobuf.Timestamp 27, // 0: stream.app.v1.User.plan_started_at:type_name -> google.protobuf.Timestamp
25, // 1: stream.app.v1.User.plan_expires_at:type_name -> google.protobuf.Timestamp 27, // 1: stream.app.v1.User.plan_expires_at:type_name -> google.protobuf.Timestamp
25, // 2: stream.app.v1.User.created_at:type_name -> google.protobuf.Timestamp 27, // 2: stream.app.v1.User.created_at:type_name -> google.protobuf.Timestamp
25, // 3: stream.app.v1.User.updated_at:type_name -> google.protobuf.Timestamp 27, // 3: stream.app.v1.User.updated_at:type_name -> google.protobuf.Timestamp
25, // 4: stream.app.v1.Notification.created_at:type_name -> google.protobuf.Timestamp 27, // 4: stream.app.v1.Notification.created_at:type_name -> google.protobuf.Timestamp
25, // 5: stream.app.v1.Domain.created_at:type_name -> google.protobuf.Timestamp 27, // 5: stream.app.v1.Domain.created_at:type_name -> google.protobuf.Timestamp
25, // 6: stream.app.v1.Domain.updated_at:type_name -> google.protobuf.Timestamp 27, // 6: stream.app.v1.Domain.updated_at:type_name -> google.protobuf.Timestamp
25, // 7: stream.app.v1.AdTemplate.created_at:type_name -> google.protobuf.Timestamp 27, // 7: stream.app.v1.AdTemplate.created_at:type_name -> google.protobuf.Timestamp
25, // 8: stream.app.v1.AdTemplate.updated_at:type_name -> google.protobuf.Timestamp 27, // 8: stream.app.v1.AdTemplate.updated_at:type_name -> google.protobuf.Timestamp
25, // 9: stream.app.v1.PlayerConfig.created_at:type_name -> google.protobuf.Timestamp 27, // 9: stream.app.v1.PopupAd.created_at:type_name -> google.protobuf.Timestamp
25, // 10: stream.app.v1.PlayerConfig.updated_at:type_name -> google.protobuf.Timestamp 27, // 10: stream.app.v1.PopupAd.updated_at:type_name -> google.protobuf.Timestamp
25, // 11: stream.app.v1.AdminPlayerConfig.created_at:type_name -> google.protobuf.Timestamp 27, // 11: stream.app.v1.PlayerConfig.created_at:type_name -> google.protobuf.Timestamp
25, // 12: stream.app.v1.AdminPlayerConfig.updated_at:type_name -> google.protobuf.Timestamp 27, // 12: stream.app.v1.PlayerConfig.updated_at:type_name -> google.protobuf.Timestamp
25, // 13: stream.app.v1.Payment.created_at:type_name -> google.protobuf.Timestamp 27, // 13: stream.app.v1.AdminPlayerConfig.created_at:type_name -> google.protobuf.Timestamp
25, // 14: stream.app.v1.Payment.updated_at:type_name -> google.protobuf.Timestamp 27, // 14: stream.app.v1.AdminPlayerConfig.updated_at:type_name -> google.protobuf.Timestamp
25, // 15: stream.app.v1.PlanSubscription.started_at:type_name -> google.protobuf.Timestamp 27, // 15: stream.app.v1.Payment.created_at:type_name -> google.protobuf.Timestamp
25, // 16: stream.app.v1.PlanSubscription.expires_at:type_name -> google.protobuf.Timestamp 27, // 16: stream.app.v1.Payment.updated_at:type_name -> google.protobuf.Timestamp
25, // 17: stream.app.v1.PlanSubscription.created_at:type_name -> google.protobuf.Timestamp 27, // 17: stream.app.v1.PlanSubscription.started_at:type_name -> google.protobuf.Timestamp
25, // 18: stream.app.v1.PlanSubscription.updated_at:type_name -> google.protobuf.Timestamp 27, // 18: stream.app.v1.PlanSubscription.expires_at:type_name -> google.protobuf.Timestamp
25, // 19: stream.app.v1.WalletTransaction.created_at:type_name -> google.protobuf.Timestamp 27, // 19: stream.app.v1.PlanSubscription.created_at:type_name -> google.protobuf.Timestamp
25, // 20: stream.app.v1.WalletTransaction.updated_at:type_name -> google.protobuf.Timestamp 27, // 20: stream.app.v1.PlanSubscription.updated_at:type_name -> google.protobuf.Timestamp
25, // 21: stream.app.v1.PaymentHistoryItem.expires_at:type_name -> google.protobuf.Timestamp 27, // 21: stream.app.v1.WalletTransaction.created_at:type_name -> google.protobuf.Timestamp
25, // 22: stream.app.v1.PaymentHistoryItem.created_at:type_name -> google.protobuf.Timestamp 27, // 22: stream.app.v1.WalletTransaction.updated_at:type_name -> google.protobuf.Timestamp
25, // 23: stream.app.v1.Video.created_at:type_name -> google.protobuf.Timestamp 27, // 23: stream.app.v1.PaymentHistoryItem.expires_at:type_name -> google.protobuf.Timestamp
25, // 24: stream.app.v1.Video.updated_at:type_name -> google.protobuf.Timestamp 27, // 24: stream.app.v1.PaymentHistoryItem.created_at:type_name -> google.protobuf.Timestamp
25, // 25: stream.app.v1.AdminUser.created_at:type_name -> google.protobuf.Timestamp 27, // 25: stream.app.v1.Video.created_at:type_name -> google.protobuf.Timestamp
25, // 26: stream.app.v1.AdminUser.updated_at:type_name -> google.protobuf.Timestamp 27, // 26: stream.app.v1.Video.updated_at:type_name -> google.protobuf.Timestamp
16, // 27: stream.app.v1.AdminUserReferralInfo.referrer:type_name -> stream.app.v1.ReferralUserSummary 27, // 27: stream.app.v1.AdminUser.created_at:type_name -> google.protobuf.Timestamp
25, // 28: stream.app.v1.AdminUserReferralInfo.reward_granted_at:type_name -> google.protobuf.Timestamp 27, // 28: stream.app.v1.AdminUser.updated_at:type_name -> google.protobuf.Timestamp
15, // 29: stream.app.v1.AdminUserDetail.user:type_name -> stream.app.v1.AdminUser 17, // 29: stream.app.v1.AdminUserReferralInfo.referrer:type_name -> stream.app.v1.ReferralUserSummary
10, // 30: stream.app.v1.AdminUserDetail.subscription:type_name -> stream.app.v1.PlanSubscription 27, // 30: stream.app.v1.AdminUserReferralInfo.reward_granted_at:type_name -> google.protobuf.Timestamp
17, // 31: stream.app.v1.AdminUserDetail.referral:type_name -> stream.app.v1.AdminUserReferralInfo 16, // 31: stream.app.v1.AdminUserDetail.user:type_name -> stream.app.v1.AdminUser
25, // 32: stream.app.v1.AdminVideo.created_at:type_name -> google.protobuf.Timestamp 11, // 32: stream.app.v1.AdminUserDetail.subscription:type_name -> stream.app.v1.PlanSubscription
25, // 33: stream.app.v1.AdminVideo.updated_at:type_name -> google.protobuf.Timestamp 18, // 33: stream.app.v1.AdminUserDetail.referral:type_name -> stream.app.v1.AdminUserReferralInfo
25, // 34: stream.app.v1.AdminPayment.created_at:type_name -> google.protobuf.Timestamp 27, // 34: stream.app.v1.AdminVideo.created_at:type_name -> google.protobuf.Timestamp
25, // 35: stream.app.v1.AdminPayment.updated_at:type_name -> google.protobuf.Timestamp 27, // 35: stream.app.v1.AdminVideo.updated_at:type_name -> google.protobuf.Timestamp
25, // 36: stream.app.v1.AdminAdTemplate.created_at:type_name -> google.protobuf.Timestamp 27, // 36: stream.app.v1.AdminPayment.created_at:type_name -> google.protobuf.Timestamp
25, // 37: stream.app.v1.AdminAdTemplate.updated_at:type_name -> google.protobuf.Timestamp 27, // 37: stream.app.v1.AdminPayment.updated_at:type_name -> google.protobuf.Timestamp
25, // 38: stream.app.v1.AdminJob.created_at:type_name -> google.protobuf.Timestamp 27, // 38: stream.app.v1.AdminAdTemplate.created_at:type_name -> google.protobuf.Timestamp
25, // 39: stream.app.v1.AdminJob.updated_at:type_name -> google.protobuf.Timestamp 27, // 39: stream.app.v1.AdminAdTemplate.updated_at:type_name -> google.protobuf.Timestamp
25, // 40: stream.app.v1.AdminAgent.last_heartbeat:type_name -> google.protobuf.Timestamp 27, // 40: stream.app.v1.AdminPopupAd.created_at:type_name -> google.protobuf.Timestamp
25, // 41: stream.app.v1.AdminAgent.created_at:type_name -> google.protobuf.Timestamp 27, // 41: stream.app.v1.AdminPopupAd.updated_at:type_name -> google.protobuf.Timestamp
25, // 42: stream.app.v1.AdminAgent.updated_at:type_name -> google.protobuf.Timestamp 27, // 42: stream.app.v1.AdminJob.created_at:type_name -> google.protobuf.Timestamp
43, // [43:43] is the sub-list for method output_type 27, // 43: stream.app.v1.AdminJob.updated_at:type_name -> google.protobuf.Timestamp
43, // [43:43] is the sub-list for method input_type 27, // 44: stream.app.v1.AdminAgent.last_heartbeat:type_name -> google.protobuf.Timestamp
43, // [43:43] is the sub-list for extension type_name 27, // 45: stream.app.v1.AdminAgent.created_at:type_name -> google.protobuf.Timestamp
43, // [43:43] is the sub-list for extension extendee 27, // 46: stream.app.v1.AdminAgent.updated_at:type_name -> google.protobuf.Timestamp
0, // [0:43] is the sub-list for field type_name 47, // [47:47] is the sub-list for method output_type
47, // [47:47] is the sub-list for method input_type
47, // [47:47] is the sub-list for extension type_name
47, // [47:47] is the sub-list for extension extendee
0, // [0:47] is the sub-list for field type_name
} }
func init() { file_app_v1_common_proto_init() } func init() { file_app_v1_common_proto_init() }
@@ -3813,14 +4062,13 @@ func file_app_v1_common_proto_init() {
file_app_v1_common_proto_msgTypes[1].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[1].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[3].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[3].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[5].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[5].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[6].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[7].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[7].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[8].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[8].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[9].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[9].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[11].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[10].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[12].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[12].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[13].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[13].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[15].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[14].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[16].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[16].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[17].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[17].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[18].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[18].OneofWrappers = []any{}
@@ -3829,13 +4077,15 @@ func file_app_v1_common_proto_init() {
file_app_v1_common_proto_msgTypes[21].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[21].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[22].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[22].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[23].OneofWrappers = []any{} file_app_v1_common_proto_msgTypes[23].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[24].OneofWrappers = []any{}
file_app_v1_common_proto_msgTypes[25].OneofWrappers = []any{}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_v1_common_proto_rawDesc), len(file_app_v1_common_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_v1_common_proto_rawDesc), len(file_app_v1_common_proto_rawDesc)),
NumEnums: 0, NumEnums: 0,
NumMessages: 25, NumMessages: 27,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@@ -24,7 +24,7 @@ type PlayerConfig struct {
Airplay *bool `gorm:"column:airplay;type:boolean;not null;default:true" json:"airplay"` Airplay *bool `gorm:"column:airplay;type:boolean;not null;default:true" json:"airplay"`
Chromecast *bool `gorm:"column:chromecast;type:boolean;not null;default:true" json:"chromecast"` Chromecast *bool `gorm:"column:chromecast;type:boolean;not null;default:true" json:"chromecast"`
IsActive *bool `gorm:"column:is_active;type:boolean;not null;default:true" json:"is_active"` IsActive *bool `gorm:"column:is_active;type:boolean;not null;default:true" json:"is_active"`
IsDefault bool `gorm:"column:is_default;type:boolean;not null;index:idx_player_configs_user_default,priority:1;index:idx_player_configs_is_default,priority:1" json:"is_default"` IsDefault bool `gorm:"column:is_default;type:boolean;not null;index:idx_player_configs_is_default,priority:1;index:idx_player_configs_user_default,priority:1" json:"is_default"`
CreatedAt *time.Time `gorm:"column:created_at;type:timestamp(3) without time zone;not null;default:CURRENT_TIMESTAMP" json:"created_at"` CreatedAt *time.Time `gorm:"column:created_at;type:timestamp(3) without time zone;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp(3) without time zone;not null" json:"updated_at"` UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp(3) without time zone;not null" json:"updated_at"`
Version *int64 `gorm:"column:version;type:bigint;not null;default:1;version" json:"-"` Version *int64 `gorm:"column:version;type:bigint;not null;default:1;version" json:"-"`

View File

@@ -0,0 +1,30 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package model
import (
"time"
)
const TableNamePopupAd = "popup_ads"
// PopupAd mapped from table <popup_ads>
type PopupAd struct {
ID string `gorm:"column:id;type:uuid;primaryKey" json:"id"`
UserID string `gorm:"column:user_id;type:uuid;not null;index:idx_popup_ads_user_id,priority:1;index:idx_popup_ads_user_active,priority:2" json:"user_id"`
Type string `gorm:"column:type;type:character varying(20);not null" json:"type"`
Label string `gorm:"column:label;type:text;not null" json:"label"`
Value string `gorm:"column:value;type:text;not null" json:"value"`
IsActive *bool `gorm:"column:is_active;type:boolean;not null;index:idx_popup_ads_user_active,priority:1;default:true" json:"is_active"`
MaxTriggersPerSession *int32 `gorm:"column:max_triggers_per_session;type:integer;not null;default:3" json:"max_triggers_per_session"`
CreatedAt *time.Time `gorm:"column:created_at;type:timestamp with time zone;default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt *time.Time `gorm:"column:updated_at;type:timestamp with time zone" json:"updated_at"`
Version *int64 `gorm:"column:version;type:bigint;not null;default:1;version" json:"-"`
}
// TableName PopupAd's table name
func (*PopupAd) TableName() string {
return TableNamePopupAd
}

View File

@@ -25,6 +25,7 @@ var (
Plan *plan Plan *plan
PlanSubscription *planSubscription PlanSubscription *planSubscription
PlayerConfig *playerConfig PlayerConfig *playerConfig
PopupAd *popupAd
User *user User *user
UserPreference *userPreference UserPreference *userPreference
Video *video Video *video
@@ -41,6 +42,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
Plan = &Q.Plan Plan = &Q.Plan
PlanSubscription = &Q.PlanSubscription PlanSubscription = &Q.PlanSubscription
PlayerConfig = &Q.PlayerConfig PlayerConfig = &Q.PlayerConfig
PopupAd = &Q.PopupAd
User = &Q.User User = &Q.User
UserPreference = &Q.UserPreference UserPreference = &Q.UserPreference
Video = &Q.Video Video = &Q.Video
@@ -58,6 +60,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
Plan: newPlan(db, opts...), Plan: newPlan(db, opts...),
PlanSubscription: newPlanSubscription(db, opts...), PlanSubscription: newPlanSubscription(db, opts...),
PlayerConfig: newPlayerConfig(db, opts...), PlayerConfig: newPlayerConfig(db, opts...),
PopupAd: newPopupAd(db, opts...),
User: newUser(db, opts...), User: newUser(db, opts...),
UserPreference: newUserPreference(db, opts...), UserPreference: newUserPreference(db, opts...),
Video: newVideo(db, opts...), Video: newVideo(db, opts...),
@@ -76,6 +79,7 @@ type Query struct {
Plan plan Plan plan
PlanSubscription planSubscription PlanSubscription planSubscription
PlayerConfig playerConfig PlayerConfig playerConfig
PopupAd popupAd
User user User user
UserPreference userPreference UserPreference userPreference
Video video Video video
@@ -95,6 +99,7 @@ func (q *Query) clone(db *gorm.DB) *Query {
Plan: q.Plan.clone(db), Plan: q.Plan.clone(db),
PlanSubscription: q.PlanSubscription.clone(db), PlanSubscription: q.PlanSubscription.clone(db),
PlayerConfig: q.PlayerConfig.clone(db), PlayerConfig: q.PlayerConfig.clone(db),
PopupAd: q.PopupAd.clone(db),
User: q.User.clone(db), User: q.User.clone(db),
UserPreference: q.UserPreference.clone(db), UserPreference: q.UserPreference.clone(db),
Video: q.Video.clone(db), Video: q.Video.clone(db),
@@ -121,6 +126,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query {
Plan: q.Plan.replaceDB(db), Plan: q.Plan.replaceDB(db),
PlanSubscription: q.PlanSubscription.replaceDB(db), PlanSubscription: q.PlanSubscription.replaceDB(db),
PlayerConfig: q.PlayerConfig.replaceDB(db), PlayerConfig: q.PlayerConfig.replaceDB(db),
PopupAd: q.PopupAd.replaceDB(db),
User: q.User.replaceDB(db), User: q.User.replaceDB(db),
UserPreference: q.UserPreference.replaceDB(db), UserPreference: q.UserPreference.replaceDB(db),
Video: q.Video.replaceDB(db), Video: q.Video.replaceDB(db),
@@ -137,6 +143,7 @@ type queryCtx struct {
Plan IPlanDo Plan IPlanDo
PlanSubscription IPlanSubscriptionDo PlanSubscription IPlanSubscriptionDo
PlayerConfig IPlayerConfigDo PlayerConfig IPlayerConfigDo
PopupAd IPopupAdDo
User IUserDo User IUserDo
UserPreference IUserPreferenceDo UserPreference IUserPreferenceDo
Video IVideoDo Video IVideoDo
@@ -153,6 +160,7 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx {
Plan: q.Plan.WithContext(ctx), Plan: q.Plan.WithContext(ctx),
PlanSubscription: q.PlanSubscription.WithContext(ctx), PlanSubscription: q.PlanSubscription.WithContext(ctx),
PlayerConfig: q.PlayerConfig.WithContext(ctx), PlayerConfig: q.PlayerConfig.WithContext(ctx),
PopupAd: q.PopupAd.WithContext(ctx),
User: q.User.WithContext(ctx), User: q.User.WithContext(ctx),
UserPreference: q.UserPreference.WithContext(ctx), UserPreference: q.UserPreference.WithContext(ctx),
Video: q.Video.WithContext(ctx), Video: q.Video.WithContext(ctx),

View File

@@ -0,0 +1,427 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package query
import (
"context"
"database/sql"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"gorm.io/gen"
"gorm.io/gen/field"
"gorm.io/plugin/dbresolver"
"stream.api/internal/database/model"
)
func newPopupAd(db *gorm.DB, opts ...gen.DOOption) popupAd {
_popupAd := popupAd{}
_popupAd.popupAdDo.UseDB(db, opts...)
_popupAd.popupAdDo.UseModel(&model.PopupAd{})
tableName := _popupAd.popupAdDo.TableName()
_popupAd.ALL = field.NewAsterisk(tableName)
_popupAd.ID = field.NewString(tableName, "id")
_popupAd.UserID = field.NewString(tableName, "user_id")
_popupAd.Type = field.NewString(tableName, "type")
_popupAd.Label = field.NewString(tableName, "label")
_popupAd.Value = field.NewString(tableName, "value")
_popupAd.IsActive = field.NewBool(tableName, "is_active")
_popupAd.MaxTriggersPerSession = field.NewInt32(tableName, "max_triggers_per_session")
_popupAd.CreatedAt = field.NewTime(tableName, "created_at")
_popupAd.UpdatedAt = field.NewTime(tableName, "updated_at")
_popupAd.Version = field.NewInt64(tableName, "version")
_popupAd.fillFieldMap()
return _popupAd
}
type popupAd struct {
popupAdDo popupAdDo
ALL field.Asterisk
ID field.String
UserID field.String
Type field.String
Label field.String
Value field.String
IsActive field.Bool
MaxTriggersPerSession field.Int32
CreatedAt field.Time
UpdatedAt field.Time
Version field.Int64
fieldMap map[string]field.Expr
}
func (p popupAd) Table(newTableName string) *popupAd {
p.popupAdDo.UseTable(newTableName)
return p.updateTableName(newTableName)
}
func (p popupAd) As(alias string) *popupAd {
p.popupAdDo.DO = *(p.popupAdDo.As(alias).(*gen.DO))
return p.updateTableName(alias)
}
func (p *popupAd) updateTableName(table string) *popupAd {
p.ALL = field.NewAsterisk(table)
p.ID = field.NewString(table, "id")
p.UserID = field.NewString(table, "user_id")
p.Type = field.NewString(table, "type")
p.Label = field.NewString(table, "label")
p.Value = field.NewString(table, "value")
p.IsActive = field.NewBool(table, "is_active")
p.MaxTriggersPerSession = field.NewInt32(table, "max_triggers_per_session")
p.CreatedAt = field.NewTime(table, "created_at")
p.UpdatedAt = field.NewTime(table, "updated_at")
p.Version = field.NewInt64(table, "version")
p.fillFieldMap()
return p
}
func (p *popupAd) WithContext(ctx context.Context) IPopupAdDo { return p.popupAdDo.WithContext(ctx) }
func (p popupAd) TableName() string { return p.popupAdDo.TableName() }
func (p popupAd) Alias() string { return p.popupAdDo.Alias() }
func (p popupAd) Columns(cols ...field.Expr) gen.Columns { return p.popupAdDo.Columns(cols...) }
func (p *popupAd) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := p.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (p *popupAd) fillFieldMap() {
p.fieldMap = make(map[string]field.Expr, 10)
p.fieldMap["id"] = p.ID
p.fieldMap["user_id"] = p.UserID
p.fieldMap["type"] = p.Type
p.fieldMap["label"] = p.Label
p.fieldMap["value"] = p.Value
p.fieldMap["is_active"] = p.IsActive
p.fieldMap["max_triggers_per_session"] = p.MaxTriggersPerSession
p.fieldMap["created_at"] = p.CreatedAt
p.fieldMap["updated_at"] = p.UpdatedAt
p.fieldMap["version"] = p.Version
}
func (p popupAd) clone(db *gorm.DB) popupAd {
p.popupAdDo.ReplaceConnPool(db.Statement.ConnPool)
return p
}
func (p popupAd) replaceDB(db *gorm.DB) popupAd {
p.popupAdDo.ReplaceDB(db)
return p
}
type popupAdDo struct{ gen.DO }
type IPopupAdDo interface {
gen.SubQuery
Debug() IPopupAdDo
WithContext(ctx context.Context) IPopupAdDo
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
ReplaceDB(db *gorm.DB)
ReadDB() IPopupAdDo
WriteDB() IPopupAdDo
As(alias string) gen.Dao
Session(config *gorm.Session) IPopupAdDo
Columns(cols ...field.Expr) gen.Columns
Clauses(conds ...clause.Expression) IPopupAdDo
Not(conds ...gen.Condition) IPopupAdDo
Or(conds ...gen.Condition) IPopupAdDo
Select(conds ...field.Expr) IPopupAdDo
Where(conds ...gen.Condition) IPopupAdDo
Order(conds ...field.Expr) IPopupAdDo
Distinct(cols ...field.Expr) IPopupAdDo
Omit(cols ...field.Expr) IPopupAdDo
Join(table schema.Tabler, on ...field.Expr) IPopupAdDo
LeftJoin(table schema.Tabler, on ...field.Expr) IPopupAdDo
RightJoin(table schema.Tabler, on ...field.Expr) IPopupAdDo
Group(cols ...field.Expr) IPopupAdDo
Having(conds ...gen.Condition) IPopupAdDo
Limit(limit int) IPopupAdDo
Offset(offset int) IPopupAdDo
Count() (count int64, err error)
Scopes(funcs ...func(gen.Dao) gen.Dao) IPopupAdDo
Unscoped() IPopupAdDo
Create(values ...*model.PopupAd) error
CreateInBatches(values []*model.PopupAd, batchSize int) error
Save(values ...*model.PopupAd) error
First() (*model.PopupAd, error)
Take() (*model.PopupAd, error)
Last() (*model.PopupAd, error)
Find() ([]*model.PopupAd, error)
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.PopupAd, err error)
FindInBatches(result *[]*model.PopupAd, batchSize int, fc func(tx gen.Dao, batch int) error) error
Pluck(column field.Expr, dest interface{}) error
Delete(...*model.PopupAd) (info gen.ResultInfo, err error)
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
Updates(value interface{}) (info gen.ResultInfo, err error)
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
UpdateFrom(q gen.SubQuery) gen.Dao
Attrs(attrs ...field.AssignExpr) IPopupAdDo
Assign(attrs ...field.AssignExpr) IPopupAdDo
Joins(fields ...field.RelationField) IPopupAdDo
Preload(fields ...field.RelationField) IPopupAdDo
FirstOrInit() (*model.PopupAd, error)
FirstOrCreate() (*model.PopupAd, error)
FindByPage(offset int, limit int) (result []*model.PopupAd, count int64, err error)
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
Rows() (*sql.Rows, error)
Row() *sql.Row
Scan(result interface{}) (err error)
Returning(value interface{}, columns ...string) IPopupAdDo
UnderlyingDB() *gorm.DB
schema.Tabler
}
func (p popupAdDo) Debug() IPopupAdDo {
return p.withDO(p.DO.Debug())
}
func (p popupAdDo) WithContext(ctx context.Context) IPopupAdDo {
return p.withDO(p.DO.WithContext(ctx))
}
func (p popupAdDo) ReadDB() IPopupAdDo {
return p.Clauses(dbresolver.Read)
}
func (p popupAdDo) WriteDB() IPopupAdDo {
return p.Clauses(dbresolver.Write)
}
func (p popupAdDo) Session(config *gorm.Session) IPopupAdDo {
return p.withDO(p.DO.Session(config))
}
func (p popupAdDo) Clauses(conds ...clause.Expression) IPopupAdDo {
return p.withDO(p.DO.Clauses(conds...))
}
func (p popupAdDo) Returning(value interface{}, columns ...string) IPopupAdDo {
return p.withDO(p.DO.Returning(value, columns...))
}
func (p popupAdDo) Not(conds ...gen.Condition) IPopupAdDo {
return p.withDO(p.DO.Not(conds...))
}
func (p popupAdDo) Or(conds ...gen.Condition) IPopupAdDo {
return p.withDO(p.DO.Or(conds...))
}
func (p popupAdDo) Select(conds ...field.Expr) IPopupAdDo {
return p.withDO(p.DO.Select(conds...))
}
func (p popupAdDo) Where(conds ...gen.Condition) IPopupAdDo {
return p.withDO(p.DO.Where(conds...))
}
func (p popupAdDo) Order(conds ...field.Expr) IPopupAdDo {
return p.withDO(p.DO.Order(conds...))
}
func (p popupAdDo) Distinct(cols ...field.Expr) IPopupAdDo {
return p.withDO(p.DO.Distinct(cols...))
}
func (p popupAdDo) Omit(cols ...field.Expr) IPopupAdDo {
return p.withDO(p.DO.Omit(cols...))
}
func (p popupAdDo) Join(table schema.Tabler, on ...field.Expr) IPopupAdDo {
return p.withDO(p.DO.Join(table, on...))
}
func (p popupAdDo) LeftJoin(table schema.Tabler, on ...field.Expr) IPopupAdDo {
return p.withDO(p.DO.LeftJoin(table, on...))
}
func (p popupAdDo) RightJoin(table schema.Tabler, on ...field.Expr) IPopupAdDo {
return p.withDO(p.DO.RightJoin(table, on...))
}
func (p popupAdDo) Group(cols ...field.Expr) IPopupAdDo {
return p.withDO(p.DO.Group(cols...))
}
func (p popupAdDo) Having(conds ...gen.Condition) IPopupAdDo {
return p.withDO(p.DO.Having(conds...))
}
func (p popupAdDo) Limit(limit int) IPopupAdDo {
return p.withDO(p.DO.Limit(limit))
}
func (p popupAdDo) Offset(offset int) IPopupAdDo {
return p.withDO(p.DO.Offset(offset))
}
func (p popupAdDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IPopupAdDo {
return p.withDO(p.DO.Scopes(funcs...))
}
func (p popupAdDo) Unscoped() IPopupAdDo {
return p.withDO(p.DO.Unscoped())
}
func (p popupAdDo) Create(values ...*model.PopupAd) error {
if len(values) == 0 {
return nil
}
return p.DO.Create(values)
}
func (p popupAdDo) CreateInBatches(values []*model.PopupAd, batchSize int) error {
return p.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (p popupAdDo) Save(values ...*model.PopupAd) error {
if len(values) == 0 {
return nil
}
return p.DO.Save(values)
}
func (p popupAdDo) First() (*model.PopupAd, error) {
if result, err := p.DO.First(); err != nil {
return nil, err
} else {
return result.(*model.PopupAd), nil
}
}
func (p popupAdDo) Take() (*model.PopupAd, error) {
if result, err := p.DO.Take(); err != nil {
return nil, err
} else {
return result.(*model.PopupAd), nil
}
}
func (p popupAdDo) Last() (*model.PopupAd, error) {
if result, err := p.DO.Last(); err != nil {
return nil, err
} else {
return result.(*model.PopupAd), nil
}
}
func (p popupAdDo) Find() ([]*model.PopupAd, error) {
result, err := p.DO.Find()
return result.([]*model.PopupAd), err
}
func (p popupAdDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.PopupAd, err error) {
buf := make([]*model.PopupAd, 0, batchSize)
err = p.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (p popupAdDo) FindInBatches(result *[]*model.PopupAd, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return p.DO.FindInBatches(result, batchSize, fc)
}
func (p popupAdDo) Attrs(attrs ...field.AssignExpr) IPopupAdDo {
return p.withDO(p.DO.Attrs(attrs...))
}
func (p popupAdDo) Assign(attrs ...field.AssignExpr) IPopupAdDo {
return p.withDO(p.DO.Assign(attrs...))
}
func (p popupAdDo) Joins(fields ...field.RelationField) IPopupAdDo {
for _, _f := range fields {
p = *p.withDO(p.DO.Joins(_f))
}
return &p
}
func (p popupAdDo) Preload(fields ...field.RelationField) IPopupAdDo {
for _, _f := range fields {
p = *p.withDO(p.DO.Preload(_f))
}
return &p
}
func (p popupAdDo) FirstOrInit() (*model.PopupAd, error) {
if result, err := p.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*model.PopupAd), nil
}
}
func (p popupAdDo) FirstOrCreate() (*model.PopupAd, error) {
if result, err := p.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*model.PopupAd), nil
}
}
func (p popupAdDo) FindByPage(offset int, limit int) (result []*model.PopupAd, count int64, err error) {
result, err = p.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = p.Offset(-1).Limit(-1).Count()
return
}
func (p popupAdDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = p.Count()
if err != nil {
return
}
err = p.Offset(offset).Limit(limit).Scan(result)
return
}
func (p popupAdDo) Scan(result interface{}) (err error) {
return p.DO.Scan(result)
}
func (p popupAdDo) Delete(models ...*model.PopupAd) (result gen.ResultInfo, err error) {
return p.DO.Delete(models)
}
func (p *popupAdDo) withDO(do gen.Dao) *popupAdDo {
p.DO = *do.(*gen.DO)
return p
}

View File

@@ -36,17 +36,23 @@ type Actor struct {
Role string Role string
} }
type Authenticator struct { type NotificationEventPublisher interface {
db *gorm.DB PublishNotificationCreated(ctx context.Context, notification *model.Notification) error
logger logger.Logger
trustedMarker string
} }
func NewAuthenticator(db *gorm.DB, l logger.Logger, trustedMarker string) *Authenticator { type Authenticator struct {
db *gorm.DB
logger logger.Logger
trustedMarker string
notificationEvents NotificationEventPublisher
}
func NewAuthenticator(db *gorm.DB, l logger.Logger, trustedMarker string, notificationEvents NotificationEventPublisher) *Authenticator {
return &Authenticator{ return &Authenticator{
db: db, db: db,
logger: l, logger: l,
trustedMarker: strings.TrimSpace(trustedMarker), trustedMarker: strings.TrimSpace(trustedMarker),
notificationEvents: notificationEvents,
} }
} }
@@ -210,6 +216,11 @@ func (a *Authenticator) maybeCreateSubscriptionReminderPostAuth(ctx context.Cont
if err := tx.WithContext(ctx).Create(notification).Error; err != nil { if err := tx.WithContext(ctx).Create(notification).Error; err != nil {
return err return err
} }
if a.notificationEvents != nil {
if err := a.notificationEvents.PublishNotificationCreated(ctx, notification); err != nil {
a.logger.Error("Failed to publish notification MQTT event", "error", err, "notification_id", notification.ID, "user_id", notification.UserID)
}
}
return tx.WithContext(ctx). return tx.WithContext(ctx).
Model(&model.PlanSubscription{}). Model(&model.PlanSubscription{}).
Where("id = ?", subscription.ID). Where("id = ?", subscription.ID).

View File

@@ -106,7 +106,7 @@ func newTrustedContext(userID, role string) context.Context {
func TestRequireActor(t *testing.T) { func TestRequireActor(t *testing.T) {
auth := NewAuthenticator(newAuthenticatorTestDB(t), testLogger{}, "trusted-marker") auth := NewAuthenticator(newAuthenticatorTestDB(t), testLogger{}, "trusted-marker", nil)
t.Run("thiếu metadata", func(t *testing.T) { t.Run("thiếu metadata", func(t *testing.T) {
_, err := auth.RequireActor(context.Background()) _, err := auth.RequireActor(context.Background())
@@ -146,7 +146,7 @@ func TestAuthenticate(t *testing.T) {
t.Run("user không tồn tại", func(t *testing.T) { t.Run("user không tồn tại", func(t *testing.T) {
db := newAuthenticatorTestDB(t) db := newAuthenticatorTestDB(t)
auth := NewAuthenticator(db, testLogger{}, "trusted-marker") auth := NewAuthenticator(db, testLogger{}, "trusted-marker", nil)
_, err := auth.Authenticate(newTrustedContext(uuid.NewString(), "USER")) _, err := auth.Authenticate(newTrustedContext(uuid.NewString(), "USER"))
if status.Code(err) != codes.Unauthenticated { if status.Code(err) != codes.Unauthenticated {
t.Fatalf("code = %v, want %v", status.Code(err), codes.Unauthenticated) t.Fatalf("code = %v, want %v", status.Code(err), codes.Unauthenticated)
@@ -159,7 +159,7 @@ func TestAuthenticate(t *testing.T) {
if err := db.Create(&blocked).Error; err != nil { if err := db.Create(&blocked).Error; err != nil {
t.Fatalf("create blocked user: %v", err) t.Fatalf("create blocked user: %v", err)
} }
auth := NewAuthenticator(db, testLogger{}, "trusted-marker") auth := NewAuthenticator(db, testLogger{}, "trusted-marker", nil)
_, err := auth.Authenticate(newTrustedContext(blocked.ID, "USER")) _, err := auth.Authenticate(newTrustedContext(blocked.ID, "USER"))
if status.Code(err) != codes.PermissionDenied { if status.Code(err) != codes.PermissionDenied {
t.Fatalf("code = %v, want %v", status.Code(err), codes.PermissionDenied) t.Fatalf("code = %v, want %v", status.Code(err), codes.PermissionDenied)
@@ -188,7 +188,7 @@ func TestAuthenticate(t *testing.T) {
if err := db.Create(&subscription).Error; err != nil { if err := db.Create(&subscription).Error; err != nil {
t.Fatalf("create subscription: %v", err) t.Fatalf("create subscription: %v", err)
} }
auth := NewAuthenticator(db, testLogger{}, "trusted-marker") auth := NewAuthenticator(db, testLogger{}, "trusted-marker", nil)
result, err := auth.Authenticate(newTrustedContext(user.ID, "USER")) result, err := auth.Authenticate(newTrustedContext(user.ID, "USER"))
if err != nil { if err != nil {
@@ -221,7 +221,7 @@ func TestAuthenticate(t *testing.T) {
if err := db.Create(&subscription).Error; err != nil { if err := db.Create(&subscription).Error; err != nil {
t.Fatalf("create subscription: %v", err) t.Fatalf("create subscription: %v", err)
} }
auth := NewAuthenticator(db, testLogger{}, "trusted-marker") auth := NewAuthenticator(db, testLogger{}, "trusted-marker", nil)
result, err := auth.Authenticate(newTrustedContext(user.ID, "USER")) result, err := auth.Authenticate(newTrustedContext(user.ID, "USER"))
if err != nil { if err != nil {
@@ -268,7 +268,7 @@ func TestAuthenticate(t *testing.T) {
t.Fatalf("create subscription: %v", err) t.Fatalf("create subscription: %v", err)
} }
auth := NewAuthenticator(db, testLogger{}, "trusted-marker") auth := NewAuthenticator(db, testLogger{}, "trusted-marker", nil)
for range 2 { for range 2 {
if _, err := auth.Authenticate(newTrustedContext(user.ID, "USER")); err != nil { if _, err := auth.Authenticate(newTrustedContext(user.ID, "USER")); err != nil {
t.Fatalf("Authenticate() error = %v", err) t.Fatalf("Authenticate() error = %v", err)

View File

@@ -0,0 +1,105 @@
package repository
import (
"context"
"strings"
"gorm.io/gorm"
"stream.api/internal/database/model"
)
type popupAdRepository struct {
db *gorm.DB
}
func NewPopupAdRepository(db *gorm.DB) *popupAdRepository {
return &popupAdRepository{db: db}
}
func (r *popupAdRepository) ListByUser(ctx context.Context, userID string, limit int32, offset int) ([]model.PopupAd, int64, error) {
db := r.baseQuery(ctx).Model(&model.PopupAd{}).Where("user_id = ?", strings.TrimSpace(userID))
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
var items []model.PopupAd
if err := db.Order("created_at DESC").Offset(offset).Limit(int(limit)).Find(&items).Error; err != nil {
return nil, 0, err
}
return items, total, nil
}
func (r *popupAdRepository) ListForAdmin(ctx context.Context, search string, userID string, limit int32, offset int) ([]model.PopupAd, int64, error) {
db := r.baseQuery(ctx).Model(&model.PopupAd{})
if trimmedSearch := strings.TrimSpace(search); trimmedSearch != "" {
like := "%" + trimmedSearch + "%"
db = db.Where("label ILIKE ?", like)
}
if trimmedUserID := strings.TrimSpace(userID); trimmedUserID != "" {
db = db.Where("user_id = ?", trimmedUserID)
}
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
var items []model.PopupAd
if err := db.Order("created_at DESC").Offset(offset).Limit(int(limit)).Find(&items).Error; err != nil {
return nil, 0, err
}
return items, total, nil
}
func (r *popupAdRepository) GetByID(ctx context.Context, id string) (*model.PopupAd, error) {
var item model.PopupAd
if err := r.baseQuery(ctx).Where("id = ?", strings.TrimSpace(id)).First(&item).Error; err != nil {
return nil, err
}
return &item, nil
}
func (r *popupAdRepository) GetByIDAndUser(ctx context.Context, id string, userID string) (*model.PopupAd, error) {
var item model.PopupAd
if err := r.baseQuery(ctx).Where("id = ? AND user_id = ?", strings.TrimSpace(id), strings.TrimSpace(userID)).First(&item).Error; err != nil {
return nil, err
}
return &item, nil
}
func (r *popupAdRepository) GetActiveByUser(ctx context.Context, userID string) (*model.PopupAd, error) {
var item model.PopupAd
err := r.baseQuery(ctx).
Where("user_id = ?", strings.TrimSpace(userID)).
Where("is_active = ?", true).
Order("created_at DESC").
First(&item).Error
if err != nil {
return nil, err
}
return &item, nil
}
func (r *popupAdRepository) Create(ctx context.Context, item *model.PopupAd) error {
return r.baseQuery(ctx).Create(item).Error
}
func (r *popupAdRepository) Save(ctx context.Context, item *model.PopupAd) error {
return r.baseQuery(ctx).Save(item).Error
}
func (r *popupAdRepository) DeleteByIDAndUser(ctx context.Context, id string, userID string) (int64, error) {
res := r.baseQuery(ctx).Where("id = ? AND user_id = ?", strings.TrimSpace(id), strings.TrimSpace(userID)).Delete(&model.PopupAd{})
return res.RowsAffected, res.Error
}
func (r *popupAdRepository) DeleteByID(ctx context.Context, id string) (int64, error) {
res := r.baseQuery(ctx).Where("id = ?", strings.TrimSpace(id)).Delete(&model.PopupAd{})
return res.RowsAffected, res.Error
}
func (r *popupAdRepository) baseQuery(ctx context.Context) *gorm.DB {
return r.db.WithContext(ctx)
}

View File

@@ -0,0 +1,96 @@
package service
import (
"context"
"testing"
"time"
"github.com/google/uuid"
appv1 "stream.api/internal/api/proto/app/v1"
"stream.api/internal/database/model"
)
type publishedNotificationEvent struct {
notification *model.Notification
}
type fakeNotificationEventPublisher struct {
events []publishedNotificationEvent
}
func (f *fakeNotificationEventPublisher) PublishNotificationCreated(_ context.Context, notification *model.Notification) error {
copyNotification := *notification
f.events = append(f.events, publishedNotificationEvent{notification: &copyNotification})
return nil
}
func TestExecutePaymentFlow_PublishesNotificationEvent(t *testing.T) {
db := newTestDB(t)
services := newTestAppServices(t, db)
publisher := &fakeNotificationEventPublisher{}
services.notificationEvents = publisher
user := seedTestUser(t, db, model.User{ID: uuid.NewString(), Email: "payer@example.com", Role: ptrString("USER")})
plan := seedTestPlan(t, db, model.Plan{ID: uuid.NewString(), Name: "Pro", Price: 10, Cycle: "monthly", StorageLimit: 100, UploadLimit: 10, QualityLimit: "1080p", IsActive: ptrBool(true)})
seedWalletTransaction(t, db, model.WalletTransaction{ID: uuid.NewString(), UserID: user.ID, Type: walletTransactionTypeTopup, Amount: 5, Currency: ptrString("USD")})
result, err := services.executePaymentFlow(context.Background(), paymentExecutionInput{
UserID: user.ID,
Plan: &plan,
TermMonths: 1,
PaymentMethod: paymentMethodTopup,
TopupAmount: ptrFloat64(5),
})
if err != nil {
t.Fatalf("executePaymentFlow() error = %v", err)
}
if result == nil {
t.Fatal("executePaymentFlow() result is nil")
}
if len(publisher.events) != 1 {
t.Fatalf("published events = %d, want 1", len(publisher.events))
}
if publisher.events[0].notification == nil || publisher.events[0].notification.Type != "billing.subscription" {
t.Fatalf("published notification = %#v", publisher.events[0].notification)
}
}
func TestTopupWallet_PublishesNotificationEvent(t *testing.T) {
db := newTestDB(t)
services := newTestAppServices(t, db)
publisher := &fakeNotificationEventPublisher{}
services.notificationEvents = publisher
user := seedTestUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: ptrString("USER")})
_, err := (&paymentsAppService{appServices: services}).TopupWallet(testActorIncomingContext(user.ID, "USER"), &appv1.TopupWalletRequest{Amount: 12})
if err != nil {
t.Fatalf("TopupWallet() error = %v", err)
}
if len(publisher.events) != 1 {
t.Fatalf("published events = %d, want 1", len(publisher.events))
}
if publisher.events[0].notification == nil || publisher.events[0].notification.Type != "billing.topup" {
t.Fatalf("published notification = %#v", publisher.events[0].notification)
}
}
func TestBuildNotificationCreatedPayload(t *testing.T) {
now := time.Now().UTC()
notification := &model.Notification{
ID: uuid.NewString(),
UserID: uuid.NewString(),
Type: "billing.subscription",
Title: "Subscription activated",
Message: "Your subscription is active.",
ActionURL: ptrString("/settings/billing"),
ActionLabel: ptrString("Renew plan"),
CreatedAt: &now,
}
payload := BuildNotificationCreatedPayload(notification)
if payload.ID != notification.ID || payload.UserID != notification.UserID || payload.Type != notification.Type {
t.Fatalf("payload = %#v", payload)
}
if payload.CreatedAt == "" {
t.Fatal("payload created_at should not be empty")
}
}

View File

@@ -0,0 +1,177 @@
package service
import (
"testing"
"time"
"github.com/google/uuid"
"google.golang.org/grpc/codes"
appv1 "stream.api/internal/api/proto/app/v1"
"stream.api/internal/database/model"
)
func TestPopupAdsUserFlow(t *testing.T) {
t.Run("create list update delete popup ad", func(t *testing.T) {
db := newTestDB(t)
services := newTestAppServices(t, db)
user := seedTestUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: ptrString("USER")})
startAt := time.Now().UTC().Add(-time.Hour)
endAt := time.Now().UTC().Add(2 * time.Hour)
createResp, err := services.CreatePopupAd(testActorIncomingContext(user.ID, "USER"), &appv1.CreatePopupAdRequest{
Title: "Homepage Campaign",
ImageUrl: "https://cdn.example.com/banner.jpg",
TargetUrl: "https://example.com/landing",
IsActive: ptrBool(true),
StartAt: timeToProto(&startAt),
EndAt: timeToProto(&endAt),
Priority: int32Ptr(5),
CloseCooldownMinutes: int32Ptr(90),
})
if err != nil {
t.Fatalf("CreatePopupAd() error = %v", err)
}
if createResp.Item == nil || createResp.Item.Title != "Homepage Campaign" {
t.Fatalf("CreatePopupAd() unexpected response: %#v", createResp)
}
listResp, err := services.ListPopupAds(testActorIncomingContext(user.ID, "USER"), &appv1.ListPopupAdsRequest{})
if err != nil {
t.Fatalf("ListPopupAds() error = %v", err)
}
if len(listResp.Items) != 1 {
t.Fatalf("ListPopupAds() count = %d, want 1", len(listResp.Items))
}
updateResp, err := services.UpdatePopupAd(testActorIncomingContext(user.ID, "USER"), &appv1.UpdatePopupAdRequest{
Id: createResp.Item.Id,
Title: "Homepage Campaign v2",
ImageUrl: "https://cdn.example.com/banner-v2.jpg",
TargetUrl: "https://example.com/landing-v2",
IsActive: ptrBool(false),
Priority: int32Ptr(8),
CloseCooldownMinutes: int32Ptr(30),
})
if err != nil {
t.Fatalf("UpdatePopupAd() error = %v", err)
}
if updateResp.Item == nil || updateResp.Item.Title != "Homepage Campaign v2" || updateResp.Item.IsActive {
t.Fatalf("UpdatePopupAd() unexpected response: %#v", updateResp)
}
items := mustListPopupAdsByUser(t, db, user.ID)
if len(items) != 1 {
t.Fatalf("popup ad count = %d, want 1", len(items))
}
if items[0].Priority != 8 || items[0].CloseCooldownMinutes != 30 {
t.Fatalf("popup ad values = %#v", items[0])
}
_, err = services.DeletePopupAd(testActorIncomingContext(user.ID, "USER"), &appv1.DeletePopupAdRequest{Id: createResp.Item.Id})
if err != nil {
t.Fatalf("DeletePopupAd() error = %v", err)
}
items = mustListPopupAdsByUser(t, db, user.ID)
if len(items) != 0 {
t.Fatalf("popup ad count after delete = %d, want 0", len(items))
}
})
t.Run("reject invalid schedule", func(t *testing.T) {
db := newTestDB(t)
services := newTestAppServices(t, db)
user := seedTestUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: ptrString("USER")})
startAt := time.Now().UTC().Add(time.Hour)
endAt := time.Now().UTC()
_, err := services.CreatePopupAd(testActorIncomingContext(user.ID, "USER"), &appv1.CreatePopupAdRequest{
Title: "Invalid",
ImageUrl: "https://cdn.example.com/banner.jpg",
TargetUrl: "https://example.com/landing",
StartAt: timeToProto(&startAt),
EndAt: timeToProto(&endAt),
})
assertGRPCCode(t, err, codes.InvalidArgument)
})
t.Run("get active popup ad picks highest priority valid item", func(t *testing.T) {
db := newTestDB(t)
services := newTestAppServices(t, db)
user := seedTestUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: ptrString("USER")})
now := time.Now().UTC()
seedTestPopupAd(t, db, model.PopupAd{ID: uuid.NewString(), UserID: user.ID, Title: "inactive", ImageURL: "https://cdn.example.com/1.jpg", TargetURL: "https://example.com/1", IsActive: ptrBool(false), Priority: 99})
seedTestPopupAd(t, db, model.PopupAd{ID: uuid.NewString(), UserID: user.ID, Title: "expired", ImageURL: "https://cdn.example.com/2.jpg", TargetURL: "https://example.com/2", IsActive: ptrBool(true), Priority: 50, StartAt: ptrTime(now.Add(-2 * time.Hour)), EndAt: ptrTime(now.Add(-time.Hour))})
seedTestPopupAd(t, db, model.PopupAd{ID: uuid.NewString(), UserID: user.ID, Title: "low", ImageURL: "https://cdn.example.com/3.jpg", TargetURL: "https://example.com/3", IsActive: ptrBool(true), Priority: 1, StartAt: ptrTime(now.Add(-time.Hour)), EndAt: ptrTime(now.Add(time.Hour))})
winner := seedTestPopupAd(t, db, model.PopupAd{ID: uuid.NewString(), UserID: user.ID, Title: "winner", ImageURL: "https://cdn.example.com/4.jpg", TargetURL: "https://example.com/4", IsActive: ptrBool(true), Priority: 10, StartAt: ptrTime(now.Add(-time.Hour)), EndAt: ptrTime(now.Add(time.Hour)), CloseCooldownMinutes: 15})
resp, err := services.GetActivePopupAd(testActorIncomingContext(user.ID, "USER"), &appv1.GetActivePopupAdRequest{})
if err != nil {
t.Fatalf("GetActivePopupAd() error = %v", err)
}
if resp.Item == nil || resp.Item.Id != winner.ID {
t.Fatalf("GetActivePopupAd() = %#v, want winner %q", resp.Item, winner.ID)
}
})
}
func TestPopupAdsAdminFlow(t *testing.T) {
t.Run("admin create list update delete popup ad", func(t *testing.T) {
db := newTestDB(t)
services := newTestAppServices(t, db)
admin := seedTestUser(t, db, model.User{ID: uuid.NewString(), Email: "admin@example.com", Role: ptrString("ADMIN")})
user := seedTestUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: ptrString("USER")})
conn, cleanup := newTestGRPCServer(t, services)
defer cleanup()
client := newAdminClient(conn)
createResp, err := client.CreateAdminPopupAd(testActorOutgoingContext(admin.ID, "ADMIN"), &appv1.CreateAdminPopupAdRequest{
UserId: user.ID,
Title: "Admin Campaign",
ImageUrl: "https://cdn.example.com/admin.jpg",
TargetUrl: "https://example.com/admin",
IsActive: ptrBool(true),
Priority: int32Ptr(7),
CloseCooldownMinutes: int32Ptr(45),
})
if err != nil {
t.Fatalf("CreateAdminPopupAd() error = %v", err)
}
if createResp.Item == nil || createResp.Item.UserId != user.ID {
t.Fatalf("CreateAdminPopupAd() unexpected response: %#v", createResp)
}
listResp, err := client.ListAdminPopupAds(testActorOutgoingContext(admin.ID, "ADMIN"), &appv1.ListAdminPopupAdsRequest{UserId: &user.ID})
if err != nil {
t.Fatalf("ListAdminPopupAds() error = %v", err)
}
if len(listResp.Items) != 1 {
t.Fatalf("ListAdminPopupAds() count = %d, want 1", len(listResp.Items))
}
updateResp, err := client.UpdateAdminPopupAd(testActorOutgoingContext(admin.ID, "ADMIN"), &appv1.UpdateAdminPopupAdRequest{
Id: createResp.Item.Id,
UserId: user.ID,
Title: "Admin Campaign v2",
ImageUrl: "https://cdn.example.com/admin-v2.jpg",
TargetUrl: "https://example.com/admin-v2",
IsActive: ptrBool(false),
Priority: int32Ptr(11),
CloseCooldownMinutes: int32Ptr(10),
})
if err != nil {
t.Fatalf("UpdateAdminPopupAd() error = %v", err)
}
if updateResp.Item == nil || updateResp.Item.Title != "Admin Campaign v2" || updateResp.Item.IsActive {
t.Fatalf("UpdateAdminPopupAd() unexpected response: %#v", updateResp)
}
_, err = client.DeleteAdminPopupAd(testActorOutgoingContext(admin.ID, "ADMIN"), &appv1.DeleteAdminPopupAdRequest{Id: createResp.Item.Id})
if err != nil {
t.Fatalf("DeleteAdminPopupAd() error = %v", err)
}
items := mustListPopupAdsByUser(t, db, user.ID)
if len(items) != 0 {
t.Fatalf("popup ad count after delete = %d, want 0", len(items))
}
})
}

View File

@@ -15,11 +15,12 @@ import (
"google.golang.org/grpc/test/bufconn" "google.golang.org/grpc/test/bufconn"
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
_ "modernc.org/sqlite" _ "github.com/mattn/go-sqlite3"
appv1 "stream.api/internal/api/proto/app/v1" appv1 "stream.api/internal/api/proto/app/v1"
"stream.api/internal/database/model" "stream.api/internal/database/model"
"stream.api/internal/database/query" "stream.api/internal/database/query"
"stream.api/internal/middleware" "stream.api/internal/middleware"
"stream.api/internal/repository"
"stream.api/pkg/logger" "stream.api/pkg/logger"
) )
@@ -74,7 +75,7 @@ func newTestDB(t *testing.T) *gorm.DB {
t.Helper() t.Helper()
dsn := fmt.Sprintf("file:%s?mode=memory&cache=shared", uuid.NewString()) dsn := fmt.Sprintf("file:%s?mode=memory&cache=shared", uuid.NewString())
db, err := gorm.Open(sqlite.Dialector{DriverName: "sqlite", DSN: dsn}, &gorm.Config{}) db, err := gorm.Open(sqlite.Dialector{DriverName: "sqlite3", DSN: dsn}, &gorm.Config{})
if err != nil { if err != nil {
t.Fatalf("open sqlite db: %v", err) t.Fatalf("open sqlite db: %v", err)
} }
@@ -206,6 +207,21 @@ func newTestDB(t *testing.T) *gorm.DB {
encrytion_m3u8 BOOLEAN NOT NULL DEFAULT 1, encrytion_m3u8 BOOLEAN NOT NULL DEFAULT 1,
logo_url TEXT logo_url TEXT
)`, )`,
`CREATE TABLE popup_ads (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
title TEXT NOT NULL,
image_url TEXT NOT NULL,
target_url TEXT NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT 1,
start_at DATETIME,
end_at DATETIME,
priority INTEGER NOT NULL DEFAULT 0,
close_cooldown_minutes INTEGER NOT NULL DEFAULT 60,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
version INTEGER NOT NULL DEFAULT 1
)`,
} { } {
if err := db.Exec(stmt).Error; err != nil { if err := db.Exec(stmt).Error; err != nil {
t.Fatalf("create test schema: %v", err) t.Fatalf("create test schema: %v", err)
@@ -226,9 +242,17 @@ func newTestAppServices(t *testing.T, db *gorm.DB) *appServices {
return &appServices{ return &appServices{
db: db, db: db,
logger: testLogger{}, logger: testLogger{},
authenticator: middleware.NewAuthenticator(db, testLogger{}, testTrustedMarker), authenticator: middleware.NewAuthenticator(db, testLogger{}, testTrustedMarker, nil),
// cache: &fakeCache{values: map[string]string{}}, // cache: &fakeCache{values: map[string]string{}},
googleUserInfoURL: defaultGoogleUserInfoURL, googleUserInfoURL: defaultGoogleUserInfoURL,
userRepository: repository.NewUserRepository(db),
planRepository: repository.NewPlanRepository(db),
paymentRepository: repository.NewPaymentRepository(db),
notificationRepo: repository.NewNotificationRepository(db),
domainRepository: repository.NewDomainRepository(db),
adTemplateRepository: repository.NewAdTemplateRepository(db),
popupAdRepository: repository.NewPopupAdRepository(db),
playerConfigRepo: repository.NewPlayerConfigRepository(db),
} }
} }
@@ -244,6 +268,7 @@ func newTestGRPCServer(t *testing.T, services *appServices) (*grpc.ClientConn, f
NotificationsServer: services, NotificationsServer: services,
DomainsServer: services, DomainsServer: services,
AdTemplatesServer: services, AdTemplatesServer: services,
PopupAdsServer: services,
PlayerConfigsServer: services, PlayerConfigsServer: services,
PlansServer: services, PlansServer: services,
PaymentsServer: services, PaymentsServer: services,
@@ -382,4 +407,33 @@ func newAdminClient(conn *grpc.ClientConn) appv1.AdminClient {
return appv1.NewAdminClient(conn) return appv1.NewAdminClient(conn)
} }
func ptrTime(v time.Time) *time.Time { return &v }
func seedTestPopupAd(t *testing.T, db *gorm.DB, item model.PopupAd) model.PopupAd {
t.Helper()
if item.IsActive == nil {
item.IsActive = ptrBool(true)
}
if item.CreatedAt == nil {
now := time.Now().UTC()
item.CreatedAt = &now
}
if item.CloseCooldownMinutes == 0 {
item.CloseCooldownMinutes = 60
}
if err := db.Create(&item).Error; err != nil {
t.Fatalf("create popup ad: %v", err)
}
return item
}
func mustListPopupAdsByUser(t *testing.T, db *gorm.DB, userID string) []model.PopupAd {
t.Helper()
var items []model.PopupAd
if err := db.Order("priority DESC, created_at DESC").Find(&items, "user_id = ?", userID).Error; err != nil {
t.Fatalf("list popup ads for user %s: %v", userID, err)
}
return items
}
var _ logger.Logger = testLogger{} var _ logger.Logger = testLogger{}

View File

@@ -464,6 +464,23 @@ func validateAdminAdTemplateInput(userID, name, vastTagURL, adFormat string, dur
return "" return ""
} }
func validateAdminPopupAdInput(userID, popupType, label, value string, maxTriggersPerSession *int32) string {
if strings.TrimSpace(userID) == "" {
return "User ID is required"
}
popupType = strings.ToLower(strings.TrimSpace(popupType))
if popupType != "url" && popupType != "script" {
return "Popup ad type must be url or script"
}
if strings.TrimSpace(label) == "" || strings.TrimSpace(value) == "" {
return "Label and value are required"
}
if maxTriggersPerSession != nil && *maxTriggersPerSession < 1 {
return "Max triggers per session must be greater than 0"
}
return ""
}
func validateAdminPlayerConfigInput(userID, name string) string { func validateAdminPlayerConfigInput(userID, name string) string {
if strings.TrimSpace(userID) == "" { if strings.TrimSpace(userID) == "" {
return "User ID is required" return "User ID is required"
@@ -503,6 +520,32 @@ func (s *appServices) buildAdminPlan(ctx context.Context, plan *model.Plan) (*ap
return payload, nil return payload, nil
} }
func (s *appServices) buildAdminPopupAd(ctx context.Context, item *model.PopupAd) (*appv1.AdminPopupAd, error) {
if item == nil {
return nil, nil
}
payload := &appv1.AdminPopupAd{
Id: item.ID,
UserId: item.UserID,
Type: item.Type,
Label: item.Label,
Value: item.Value,
IsActive: boolValue(item.IsActive),
MaxTriggersPerSession: func() int32 { if item.MaxTriggersPerSession != nil { return *item.MaxTriggersPerSession }; return 0 }(),
CreatedAt: timeToProto(item.CreatedAt),
UpdatedAt: timeToProto(item.UpdatedAt),
}
ownerEmail, err := s.loadAdminUserEmail(ctx, item.UserID)
if err != nil {
return nil, err
}
payload.OwnerEmail = ownerEmail
return payload, nil
}
func (s *appServices) buildAdminAdTemplate(ctx context.Context, item *model.AdTemplate) (*appv1.AdminAdTemplate, error) { func (s *appServices) buildAdminAdTemplate(ctx context.Context, item *model.AdTemplate) (*appv1.AdminAdTemplate, error) {
if item == nil { if item == nil {
return nil, nil return nil, nil

View File

@@ -1,7 +1,9 @@
package service package service
import appv1 "stream.api/internal/api/proto/app/v1" import (
import "stream.api/internal/database/model" appv1 "stream.api/internal/api/proto/app/v1"
"stream.api/internal/database/model"
)
func toProtoDomain(item *model.Domain) *appv1.Domain { func toProtoDomain(item *model.Domain) *appv1.Domain {
if item == nil { if item == nil {
@@ -33,6 +35,22 @@ func toProtoAdTemplate(item *model.AdTemplate) *appv1.AdTemplate {
} }
} }
func toProtoPopupAd(item *model.PopupAd) *appv1.PopupAd {
if item == nil {
return nil
}
return &appv1.PopupAd{
Id: item.ID,
Type: item.Type,
Label: item.Label,
Value: item.Value,
IsActive: boolValue(item.IsActive),
MaxTriggersPerSession: func() int32 { if item.MaxTriggersPerSession != nil { return *item.MaxTriggersPerSession }; return 0 }(),
CreatedAt: timeToProto(item.CreatedAt),
UpdatedAt: timeToProto(item.UpdatedAt),
}
}
func toProtoPlayerConfig(item *model.PlayerConfig) *appv1.PlayerConfig { func toProtoPlayerConfig(item *model.PlayerConfig) *appv1.PlayerConfig {
if item == nil { if item == nil {
return nil return nil

View File

@@ -43,6 +43,10 @@ type PaymentRepository interface {
ExecuteSubscriptionPayment(ctx context.Context, userID string, plan *model.Plan, termMonths int32, paymentMethod string, paymentRecord *model.Payment, invoiceID string, now time.Time, validateFunding func(currentWalletBalance float64) (float64, error)) (*model.PlanSubscription, float64, error) ExecuteSubscriptionPayment(ctx context.Context, userID string, plan *model.Plan, termMonths int32, paymentMethod string, paymentRecord *model.Payment, invoiceID string, now time.Time, validateFunding func(currentWalletBalance float64) (float64, error)) (*model.PlanSubscription, float64, error)
} }
type NotificationEventPublisher interface {
PublishNotificationCreated(ctx context.Context, notification *model.Notification) error
}
type AccountRepository interface { type AccountRepository interface {
DeleteUserAccount(ctx context.Context, userID string) error DeleteUserAccount(ctx context.Context, userID string) error
ClearUserData(ctx context.Context, userID string) error ClearUserData(ctx context.Context, userID string) error
@@ -76,6 +80,18 @@ type AdTemplateRepository interface {
DeleteByIDAndClearVideos(ctx context.Context, id string) error DeleteByIDAndClearVideos(ctx context.Context, id string) error
} }
type PopupAdRepository interface {
ListByUser(ctx context.Context, userID string, limit int32, offset int) ([]model.PopupAd, int64, error)
ListForAdmin(ctx context.Context, search string, userID string, limit int32, offset int) ([]model.PopupAd, int64, error)
GetByID(ctx context.Context, id string) (*model.PopupAd, error)
GetByIDAndUser(ctx context.Context, id string, userID string) (*model.PopupAd, error)
GetActiveByUser(ctx context.Context, userID string) (*model.PopupAd, error)
Create(ctx context.Context, item *model.PopupAd) error
Save(ctx context.Context, item *model.PopupAd) error
DeleteByIDAndUser(ctx context.Context, id string, userID string) (int64, error)
DeleteByID(ctx context.Context, id string) (int64, error)
}
type PlayerConfigRepository interface { type PlayerConfigRepository interface {
ListByUser(ctx context.Context, userID string) ([]model.PlayerConfig, error) ListByUser(ctx context.Context, userID string) ([]model.PlayerConfig, error)
ListForAdmin(ctx context.Context, search string, userID string, limit int32, offset int) ([]model.PlayerConfig, int64, error) ListForAdmin(ctx context.Context, search string, userID string, limit int32, offset int) ([]model.PlayerConfig, int64, error)

View File

@@ -0,0 +1,57 @@
package service
import (
"context"
"encoding/json"
"time"
"stream.api/internal/database/model"
)
type noopNotificationEventPublisher struct{}
func (noopNotificationEventPublisher) PublishNotificationCreated(context.Context, *model.Notification) error {
return nil
}
type NotificationCreatedPayload struct {
ID string `json:"id"`
UserID string `json:"user_id"`
Type string `json:"type"`
Title string `json:"title"`
Message string `json:"message"`
ActionURL *string `json:"action_url,omitempty"`
ActionLabel *string `json:"action_label,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
}
func (s *appServices) publishNotificationCreated(ctx context.Context, notification *model.Notification) {
if s == nil || s.notificationEvents == nil || notification == nil {
return
}
if err := s.notificationEvents.PublishNotificationCreated(ctx, notification); err != nil {
s.logger.Error("Failed to publish notification MQTT event", "error", err, "notification_id", notification.ID, "user_id", notification.UserID)
}
}
func BuildNotificationCreatedPayload(notification *model.Notification) NotificationCreatedPayload {
createdAt := ""
if notification != nil && notification.CreatedAt != nil {
createdAt = notification.CreatedAt.UTC().Format(time.RFC3339)
}
return NotificationCreatedPayload{
ID: notification.ID,
UserID: notification.UserID,
Type: notification.Type,
Title: notification.Title,
Message: notification.Message,
ActionURL: nullableTrimmedString(notification.ActionURL),
ActionLabel: nullableTrimmedString(notification.ActionLabel),
CreatedAt: createdAt,
}
}
func mustMarshalNotificationPayload(notification *model.Notification) []byte {
encoded, _ := json.Marshal(BuildNotificationCreatedPayload(notification))
return encoded
}

View File

@@ -0,0 +1,175 @@
package service
import (
"context"
"fmt"
"testing"
"time"
"github.com/google/uuid"
"google.golang.org/grpc/metadata"
_ "modernc.org/sqlite"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
appv1 "stream.api/internal/api/proto/app/v1"
"stream.api/internal/database/model"
"stream.api/internal/database/query"
"stream.api/internal/middleware"
"stream.api/internal/repository"
)
type serviceTestLogger struct{}
func (serviceTestLogger) Info(string, ...any) {}
func (serviceTestLogger) Error(string, ...any) {}
func (serviceTestLogger) Debug(string, ...any) {}
func (serviceTestLogger) Warn(string, ...any) {}
const notificationTestTrustedMarker = "trusted-notification-test-marker"
type publishedNotificationEvent struct {
notification *model.Notification
}
type fakeNotificationEventPublisher struct {
events []publishedNotificationEvent
}
func (f *fakeNotificationEventPublisher) PublishNotificationCreated(_ context.Context, notification *model.Notification) error {
copyNotification := *notification
f.events = append(f.events, publishedNotificationEvent{notification: &copyNotification})
return nil
}
func newNotificationTestDB(t *testing.T) *gorm.DB {
t.Helper()
dsn := fmt.Sprintf("file:%s?mode=memory&cache=shared", uuid.NewString())
db, err := gorm.Open(sqlite.Dialector{DriverName: "sqlite", DSN: dsn}, &gorm.Config{})
if err != nil {
t.Fatalf("open sqlite db: %v", err)
}
for _, stmt := range []string{
`CREATE TABLE user (id TEXT PRIMARY KEY,email TEXT NOT NULL,password TEXT,username TEXT,avatar TEXT,role TEXT NOT NULL,google_id TEXT,storage_used INTEGER NOT NULL DEFAULT 0,plan_id TEXT,referred_by_user_id TEXT,referral_eligible BOOLEAN NOT NULL DEFAULT 1,referral_reward_bps INTEGER,referral_reward_granted_at DATETIME,referral_reward_payment_id TEXT,referral_reward_amount REAL,created_at DATETIME DEFAULT CURRENT_TIMESTAMP,updated_at DATETIME,version INTEGER NOT NULL DEFAULT 1,telegram_id TEXT)`,
`CREATE TABLE plan (id TEXT PRIMARY KEY,name TEXT NOT NULL,description TEXT,price REAL NOT NULL,cycle TEXT NOT NULL,storage_limit INTEGER NOT NULL,upload_limit INTEGER NOT NULL,duration_limit INTEGER NOT NULL,quality_limit TEXT NOT NULL,features JSON,is_active BOOLEAN NOT NULL DEFAULT 1,version INTEGER NOT NULL DEFAULT 1)`,
`CREATE TABLE payment (id TEXT PRIMARY KEY,user_id TEXT NOT NULL,plan_id TEXT,amount REAL NOT NULL,currency TEXT,status TEXT,provider TEXT,transaction_id TEXT,created_at DATETIME DEFAULT CURRENT_TIMESTAMP,updated_at DATETIME,version INTEGER NOT NULL DEFAULT 1)`,
`CREATE TABLE plan_subscriptions (id TEXT PRIMARY KEY,user_id TEXT NOT NULL,payment_id TEXT NOT NULL,plan_id TEXT NOT NULL,term_months INTEGER NOT NULL,payment_method TEXT NOT NULL,wallet_amount REAL NOT NULL,topup_amount REAL NOT NULL,started_at DATETIME NOT NULL,expires_at DATETIME NOT NULL,reminder_7d_sent_at DATETIME,reminder_3d_sent_at DATETIME,reminder_1d_sent_at DATETIME,created_at DATETIME DEFAULT CURRENT_TIMESTAMP,updated_at DATETIME,version INTEGER NOT NULL DEFAULT 1)`,
`CREATE TABLE wallet_transactions (id TEXT PRIMARY KEY,user_id TEXT NOT NULL,type TEXT NOT NULL,amount REAL NOT NULL,currency TEXT,note TEXT,created_at DATETIME DEFAULT CURRENT_TIMESTAMP,updated_at DATETIME,payment_id TEXT,plan_id TEXT,term_months INTEGER,version INTEGER NOT NULL DEFAULT 1)`,
`CREATE TABLE notifications (id TEXT PRIMARY KEY,user_id TEXT NOT NULL,type TEXT NOT NULL,title TEXT NOT NULL,message TEXT NOT NULL,metadata TEXT,action_url TEXT,action_label TEXT,is_read BOOLEAN NOT NULL DEFAULT 0,created_at DATETIME DEFAULT CURRENT_TIMESTAMP,updated_at DATETIME,version INTEGER NOT NULL DEFAULT 1)`,
} {
if err := db.Exec(stmt).Error; err != nil {
t.Fatalf("create test schema: %v", err)
}
}
query.SetDefault(db)
return db
}
func newNotificationTestServices(t *testing.T, db *gorm.DB, publisher NotificationEventPublisher) *appServices {
t.Helper()
return &appServices{
db: db,
logger: serviceTestLogger{},
authenticator: middleware.NewAuthenticator(db, serviceTestLogger{}, notificationTestTrustedMarker, publisher),
googleUserInfoURL: defaultGoogleUserInfoURL,
userRepository: repository.NewUserRepository(db),
planRepository: repository.NewPlanRepository(db),
paymentRepository: repository.NewPaymentRepository(db),
billingRepository: repository.NewBillingRepository(db),
notificationRepo: repository.NewNotificationRepository(db),
notificationEvents: publisher,
}
}
func notificationTestContext(userID, role string) context.Context {
return metadata.NewIncomingContext(context.Background(), metadata.Pairs(
middleware.ActorMarkerMetadataKey, notificationTestTrustedMarker,
middleware.ActorIDMetadataKey, userID,
middleware.ActorRoleMetadataKey, role,
middleware.ActorEmailMetadataKey, "actor@example.com",
))
}
func notificationPtrString(v string) *string { return &v }
func notificationPtrBool(v bool) *bool { return &v }
func notificationPtrFloat64(v float64) *float64 { return &v }
func seedNotificationUser(t *testing.T, db *gorm.DB, user model.User) model.User {
t.Helper()
if user.Role == nil {
user.Role = notificationPtrString("USER")
}
if err := db.Create(&user).Error; err != nil {
t.Fatalf("create user: %v", err)
}
return user
}
func seedNotificationPlan(t *testing.T, db *gorm.DB, plan model.Plan) model.Plan {
t.Helper()
if plan.IsActive == nil {
plan.IsActive = notificationPtrBool(true)
}
if err := db.Create(&plan).Error; err != nil {
t.Fatalf("create plan: %v", err)
}
return plan
}
func seedNotificationWalletTransaction(t *testing.T, db *gorm.DB, tx model.WalletTransaction) model.WalletTransaction {
t.Helper()
if err := db.Create(&tx).Error; err != nil {
t.Fatalf("create wallet transaction: %v", err)
}
return tx
}
func TestExecutePaymentFlowPublishesNotificationEvent(t *testing.T) {
db := newNotificationTestDB(t)
publisher := &fakeNotificationEventPublisher{}
services := newNotificationTestServices(t, db, publisher)
user := seedNotificationUser(t, db, model.User{ID: uuid.NewString(), Email: "payer@example.com", Role: notificationPtrString("USER")})
plan := seedNotificationPlan(t, db, model.Plan{ID: uuid.NewString(), Name: "Pro", Price: 10, Cycle: "monthly", StorageLimit: 100, UploadLimit: 10, QualityLimit: "1080p", IsActive: notificationPtrBool(true)})
seedNotificationWalletTransaction(t, db, model.WalletTransaction{ID: uuid.NewString(), UserID: user.ID, Type: walletTransactionTypeTopup, Amount: 5, Currency: notificationPtrString("USD")})
_, err := services.executePaymentFlow(context.Background(), paymentExecutionInput{UserID: user.ID, Plan: &plan, TermMonths: 1, PaymentMethod: paymentMethodTopup, TopupAmount: notificationPtrFloat64(5)})
if err != nil {
t.Fatalf("executePaymentFlow() error = %v", err)
}
if len(publisher.events) != 1 {
t.Fatalf("published events = %d, want 1", len(publisher.events))
}
if publisher.events[0].notification == nil || publisher.events[0].notification.Type != "billing.subscription" {
t.Fatalf("published notification = %#v", publisher.events[0].notification)
}
}
func TestTopupWalletPublishesNotificationEvent(t *testing.T) {
db := newNotificationTestDB(t)
publisher := &fakeNotificationEventPublisher{}
services := newNotificationTestServices(t, db, publisher)
user := seedNotificationUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: notificationPtrString("USER")})
_, err := (&paymentsAppService{appServices: services}).TopupWallet(notificationTestContext(user.ID, "USER"), &appv1.TopupWalletRequest{Amount: 12})
if err != nil {
t.Fatalf("TopupWallet() error = %v", err)
}
if len(publisher.events) != 1 {
t.Fatalf("published events = %d, want 1", len(publisher.events))
}
if publisher.events[0].notification == nil || publisher.events[0].notification.Type != "billing.topup" {
t.Fatalf("published notification = %#v", publisher.events[0].notification)
}
}
func TestBuildNotificationCreatedPayload(t *testing.T) {
now := time.Now().UTC()
notification := &model.Notification{ID: uuid.NewString(), UserID: uuid.NewString(), Type: "billing.subscription", Title: "Subscription activated", Message: "Your subscription is active.", ActionURL: notificationPtrString("/settings/billing"), ActionLabel: notificationPtrString("Renew plan"), CreatedAt: &now}
payload := BuildNotificationCreatedPayload(notification)
if payload.ID != notification.ID || payload.UserID != notification.UserID || payload.Type != notification.Type {
t.Fatalf("payload = %#v", payload)
}
if payload.CreatedAt == "" {
t.Fatal("payload created_at should not be empty")
}
}

View File

@@ -118,6 +118,9 @@ func (s *appServices) executePaymentFlow(ctx context.Context, input paymentExecu
} }
result.Subscription = subscription result.Subscription = subscription
result.WalletBalance = walletBalance result.WalletBalance = walletBalance
if notification := latestNotificationForPayment(result.Payment, subscription, input.Plan, invoiceID); notification != nil {
s.publishNotificationCreated(ctx, notification)
}
return result, nil return result, nil
} }

View File

@@ -0,0 +1,31 @@
package service
import (
"fmt"
"time"
"stream.api/internal/database/model"
)
func latestNotificationForPayment(paymentRecord *model.Payment, subscription *model.PlanSubscription, plan *model.Plan, invoiceID string) *model.Notification {
if paymentRecord == nil || subscription == nil || plan == nil {
return nil
}
return &model.Notification{
ID: "",
UserID: paymentRecord.UserID,
Type: "billing.subscription",
Title: "Subscription activated",
Message: fmt.Sprintf("Your subscription to %s is active until %s.", plan.Name, subscription.ExpiresAt.UTC().Format("2006-01-02")),
Metadata: model.StringPtr(mustMarshalJSON(map[string]any{
"payment_id": paymentRecord.ID,
"invoice_id": invoiceID,
"plan_id": plan.ID,
"term_months": subscription.TermMonths,
"payment_method": subscription.PaymentMethod,
"wallet_amount": subscription.WalletAmount,
"topup_amount": subscription.TopupAmount,
"plan_expires_at": subscription.ExpiresAt.UTC().Format(time.RFC3339),
})),
}
}

View File

@@ -205,9 +205,11 @@ func (s *appServices) maybeGrantReferralReward(ctx context.Context, tx *gorm.DB,
if err := s.paymentRepository.CreateWalletTransactionTx(tx, ctx, rewardTransaction); err != nil { if err := s.paymentRepository.CreateWalletTransactionTx(tx, ctx, rewardTransaction); err != nil {
return nil, err return nil, err
} }
if err := s.paymentRepository.CreateNotificationTx(tx, ctx, buildReferralRewardNotification(referrer.ID, rewardAmount, referee, paymentRecord)); err != nil { rewardNotification := buildReferralRewardNotification(referrer.ID, rewardAmount, referee, paymentRecord)
if err := s.paymentRepository.CreateNotificationTx(tx, ctx, rewardNotification); err != nil {
return nil, err return nil, err
} }
s.publishNotificationCreated(ctx, rewardNotification)
now := time.Now().UTC() now := time.Now().UTC()
updates := map[string]any{ updates := map[string]any{

View File

@@ -11,6 +11,7 @@ func Register(server grpc.ServiceRegistrar, services *Services) {
appv1.RegisterNotificationsServer(server, services.NotificationsServer) appv1.RegisterNotificationsServer(server, services.NotificationsServer)
appv1.RegisterDomainsServer(server, services.DomainsServer) appv1.RegisterDomainsServer(server, services.DomainsServer)
appv1.RegisterAdTemplatesServer(server, services.AdTemplatesServer) appv1.RegisterAdTemplatesServer(server, services.AdTemplatesServer)
appv1.RegisterPopupAdsServer(server, services.PopupAdsServer)
appv1.RegisterPlayerConfigsServer(server, services.PlayerConfigsServer) appv1.RegisterPlayerConfigsServer(server, services.PlayerConfigsServer)
appv1.RegisterPlansServer(server, services.PlansServer) appv1.RegisterPlansServer(server, services.PlansServer)
appv1.RegisterPaymentsServer(server, services.PaymentsServer) appv1.RegisterPaymentsServer(server, services.PaymentsServer)

View File

@@ -461,6 +461,150 @@ func (s *appServices) DeleteAdminAdTemplate(ctx context.Context, req *appv1.Dele
return &appv1.MessageResponse{Message: "Ad template deleted"}, nil return &appv1.MessageResponse{Message: "Ad template deleted"}, nil
} }
func (s *appServices) ListAdminPopupAds(ctx context.Context, req *appv1.ListAdminPopupAdsRequest) (*appv1.ListAdminPopupAdsResponse, error) {
if _, err := s.requireAdmin(ctx); err != nil {
return nil, err
}
page, limit, offset := adminPageLimitOffset(req.GetPage(), req.GetLimit())
search := strings.TrimSpace(protoStringValue(req.Search))
userID := strings.TrimSpace(protoStringValue(req.UserId))
items, total, err := s.popupAdRepository.ListForAdmin(ctx, search, userID, limit, offset)
if err != nil {
return nil, status.Error(codes.Internal, "Failed to list popup ads")
}
payload := make([]*appv1.AdminPopupAd, 0, len(items))
for i := range items {
mapped, err := s.buildAdminPopupAd(ctx, &items[i])
if err != nil {
return nil, status.Error(codes.Internal, "Failed to list popup ads")
}
payload = append(payload, mapped)
}
return &appv1.ListAdminPopupAdsResponse{Items: payload, Total: total, Page: page, Limit: limit}, nil
}
func (s *appServices) GetAdminPopupAd(ctx context.Context, req *appv1.GetAdminPopupAdRequest) (*appv1.GetAdminPopupAdResponse, error) {
if _, err := s.requireAdmin(ctx); err != nil {
return nil, err
}
id := strings.TrimSpace(req.GetId())
if id == "" {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
item, err := s.popupAdRepository.GetByID(ctx, id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
return nil, status.Error(codes.Internal, "Failed to load popup ad")
}
payload, err := s.buildAdminPopupAd(ctx, item)
if err != nil {
return nil, status.Error(codes.Internal, "Failed to load popup ad")
}
return &appv1.GetAdminPopupAdResponse{Item: payload}, nil
}
func (s *appServices) CreateAdminPopupAd(ctx context.Context, req *appv1.CreateAdminPopupAdRequest) (*appv1.CreateAdminPopupAdResponse, error) {
if _, err := s.requireAdmin(ctx); err != nil {
return nil, err
}
if msg := validateAdminPopupAdInput(req.GetUserId(), req.GetType(), req.GetLabel(), req.GetValue(), req.MaxTriggersPerSession); msg != "" {
return nil, status.Error(codes.InvalidArgument, msg)
}
user, err := s.userRepository.GetByID(ctx, strings.TrimSpace(req.GetUserId()))
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.InvalidArgument, "User not found")
}
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
maxTriggers := int32(3)
if req.MaxTriggersPerSession != nil {
maxTriggers = *req.MaxTriggersPerSession
}
item := &model.PopupAd{
ID: uuid.New().String(),
UserID: user.ID,
Type: strings.ToLower(strings.TrimSpace(req.GetType())),
Label: strings.TrimSpace(req.GetLabel()),
Value: strings.TrimSpace(req.GetValue()),
IsActive: model.BoolPtr(req.IsActive == nil || *req.IsActive),
MaxTriggersPerSession: int32Ptr(maxTriggers),
}
if err := s.popupAdRepository.Create(ctx, item); err != nil {
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
payload, err := s.buildAdminPopupAd(ctx, item)
if err != nil {
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
return &appv1.CreateAdminPopupAdResponse{Item: payload}, nil
}
func (s *appServices) UpdateAdminPopupAd(ctx context.Context, req *appv1.UpdateAdminPopupAdRequest) (*appv1.UpdateAdminPopupAdResponse, error) {
if _, err := s.requireAdmin(ctx); err != nil {
return nil, err
}
id := strings.TrimSpace(req.GetId())
if id == "" {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
if msg := validateAdminPopupAdInput(req.GetUserId(), req.GetType(), req.GetLabel(), req.GetValue(), req.MaxTriggersPerSession); msg != "" {
return nil, status.Error(codes.InvalidArgument, msg)
}
user, err := s.userRepository.GetByID(ctx, strings.TrimSpace(req.GetUserId()))
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.InvalidArgument, "User not found")
}
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
item, err := s.popupAdRepository.GetByID(ctx, id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
item.UserID = user.ID
item.Type = strings.ToLower(strings.TrimSpace(req.GetType()))
item.Label = strings.TrimSpace(req.GetLabel())
item.Value = strings.TrimSpace(req.GetValue())
if req.IsActive != nil {
item.IsActive = model.BoolPtr(*req.IsActive)
}
if req.MaxTriggersPerSession != nil {
item.MaxTriggersPerSession = int32Ptr(*req.MaxTriggersPerSession)
}
if err := s.popupAdRepository.Save(ctx, item); err != nil {
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
payload, err := s.buildAdminPopupAd(ctx, item)
if err != nil {
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
return &appv1.UpdateAdminPopupAdResponse{Item: payload}, nil
}
func (s *appServices) DeleteAdminPopupAd(ctx context.Context, req *appv1.DeleteAdminPopupAdRequest) (*appv1.MessageResponse, error) {
if _, err := s.requireAdmin(ctx); err != nil {
return nil, err
}
id := strings.TrimSpace(req.GetId())
if id == "" {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
rowsAffected, err := s.popupAdRepository.DeleteByID(ctx, id)
if err != nil {
return nil, status.Error(codes.Internal, "Failed to delete popup ad")
}
if rowsAffected == 0 {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
return &appv1.MessageResponse{Message: "Popup ad deleted"}, nil
}
func (s *appServices) ListAdminPlayerConfigs(ctx context.Context, req *appv1.ListAdminPlayerConfigsRequest) (*appv1.ListAdminPlayerConfigsResponse, error) { func (s *appServices) ListAdminPlayerConfigs(ctx context.Context, req *appv1.ListAdminPlayerConfigsRequest) (*appv1.ListAdminPlayerConfigsResponse, error) {
if _, err := s.requireAdmin(ctx); err != nil { if _, err := s.requireAdmin(ctx); err != nil {
return nil, err return nil, err

View File

@@ -48,6 +48,7 @@ type Services struct {
appv1.NotificationsServer appv1.NotificationsServer
appv1.DomainsServer appv1.DomainsServer
appv1.AdTemplatesServer appv1.AdTemplatesServer
appv1.PopupAdsServer
appv1.PlayerConfigsServer appv1.PlayerConfigsServer
appv1.PlansServer appv1.PlansServer
appv1.PaymentsServer appv1.PaymentsServer
@@ -60,6 +61,7 @@ type accountAppService struct{ *appServices }
type notificationsAppService struct{ *appServices } type notificationsAppService struct{ *appServices }
type domainsAppService struct{ *appServices } type domainsAppService struct{ *appServices }
type adTemplatesAppService struct{ *appServices } type adTemplatesAppService struct{ *appServices }
type popupAdsAppService struct{ *appServices }
type playerConfigsAppService struct{ *appServices } type playerConfigsAppService struct{ *appServices }
type plansAppService struct{ *appServices } type plansAppService struct{ *appServices }
type paymentsAppService struct{ *appServices } type paymentsAppService struct{ *appServices }
@@ -72,6 +74,7 @@ type appServices struct {
appv1.UnimplementedNotificationsServer appv1.UnimplementedNotificationsServer
appv1.UnimplementedDomainsServer appv1.UnimplementedDomainsServer
appv1.UnimplementedAdTemplatesServer appv1.UnimplementedAdTemplatesServer
appv1.UnimplementedPopupAdsServer
appv1.UnimplementedPlayerConfigsServer appv1.UnimplementedPlayerConfigsServer
appv1.UnimplementedPlansServer appv1.UnimplementedPlansServer
appv1.UnimplementedPaymentsServer appv1.UnimplementedPaymentsServer
@@ -92,8 +95,10 @@ type appServices struct {
paymentRepository PaymentRepository paymentRepository PaymentRepository
accountRepository AccountRepository accountRepository AccountRepository
notificationRepo NotificationRepository notificationRepo NotificationRepository
notificationEvents NotificationEventPublisher
domainRepository DomainRepository domainRepository DomainRepository
adTemplateRepository AdTemplateRepository adTemplateRepository AdTemplateRepository
popupAdRepository PopupAdRepository
playerConfigRepo PlayerConfigRepository playerConfigRepo PlayerConfigRepository
agentRuntime AgentRuntime agentRuntime AgentRuntime
googleOauth *oauth2.Config googleOauth *oauth2.Config
@@ -138,7 +143,7 @@ type apiErrorBody struct {
Data any `json:"data,omitempty"` Data any `json:"data,omitempty"`
} }
func NewServices(c *redis.RedisAdapter, db *gorm.DB, l logger.Logger, cfg *config.Config, videoWorkflowService VideoWorkflow, agentRuntime AgentRuntime) *Services { func NewServices(c *redis.RedisAdapter, db *gorm.DB, l logger.Logger, cfg *config.Config, videoWorkflowService VideoWorkflow, agentRuntime AgentRuntime, notificationEvents NotificationEventPublisher) *Services {
var storageProvider storage.Provider var storageProvider storage.Provider
if cfg != nil { if cfg != nil {
provider, err := storage.NewS3Provider(cfg) provider, err := storage.NewS3Provider(cfg)
@@ -175,7 +180,7 @@ func NewServices(c *redis.RedisAdapter, db *gorm.DB, l logger.Logger, cfg *confi
service := &appServices{ service := &appServices{
db: db, db: db,
logger: l, logger: l,
authenticator: middleware.NewAuthenticator(db, l, cfg.Internal.Marker), authenticator: middleware.NewAuthenticator(db, l, cfg.Internal.Marker, notificationEvents),
cache: c, cache: c,
storageProvider: storageProvider, storageProvider: storageProvider,
videoWorkflowService: videoWorkflowService, videoWorkflowService: videoWorkflowService,
@@ -187,8 +192,10 @@ func NewServices(c *redis.RedisAdapter, db *gorm.DB, l logger.Logger, cfg *confi
paymentRepository: repository.NewPaymentRepository(db), paymentRepository: repository.NewPaymentRepository(db),
accountRepository: repository.NewAccountRepository(db), accountRepository: repository.NewAccountRepository(db),
notificationRepo: repository.NewNotificationRepository(db), notificationRepo: repository.NewNotificationRepository(db),
notificationEvents: notificationEvents,
domainRepository: repository.NewDomainRepository(db), domainRepository: repository.NewDomainRepository(db),
adTemplateRepository: repository.NewAdTemplateRepository(db), adTemplateRepository: repository.NewAdTemplateRepository(db),
popupAdRepository: repository.NewPopupAdRepository(db),
playerConfigRepo: repository.NewPlayerConfigRepository(db), playerConfigRepo: repository.NewPlayerConfigRepository(db),
jobRepository: repository.NewJobRepository(db), jobRepository: repository.NewJobRepository(db),
agentRuntime: agentRuntime, agentRuntime: agentRuntime,
@@ -203,6 +210,7 @@ func NewServices(c *redis.RedisAdapter, db *gorm.DB, l logger.Logger, cfg *confi
NotificationsServer: &notificationsAppService{appServices: service}, NotificationsServer: &notificationsAppService{appServices: service},
DomainsServer: &domainsAppService{appServices: service}, DomainsServer: &domainsAppService{appServices: service},
AdTemplatesServer: &adTemplatesAppService{appServices: service}, AdTemplatesServer: &adTemplatesAppService{appServices: service},
PopupAdsServer: &popupAdsAppService{appServices: service},
PlayerConfigsServer: &playerConfigsAppService{appServices: service}, PlayerConfigsServer: &playerConfigsAppService{appServices: service},
PlansServer: &plansAppService{appServices: service}, PlansServer: &plansAppService{appServices: service},
PaymentsServer: &paymentsAppService{appServices: service}, PaymentsServer: &paymentsAppService{appServices: service},

View File

@@ -141,6 +141,7 @@ func (s *paymentsAppService) TopupWallet(ctx context.Context, req *appv1.TopupWa
s.logger.Error("Failed to top up wallet", "error", err) s.logger.Error("Failed to top up wallet", "error", err)
return nil, status.Error(codes.Internal, "Failed to top up wallet") return nil, status.Error(codes.Internal, "Failed to top up wallet")
} }
s.publishNotificationCreated(ctx, notification)
balance, err := s.billingRepository.GetWalletBalance(ctx, result.UserID) balance, err := s.billingRepository.GetWalletBalance(ctx, result.UserID)
if err != nil { if err != nil {

View File

@@ -0,0 +1,354 @@
package service
import (
"context"
"fmt"
"testing"
"time"
"github.com/google/uuid"
_ "modernc.org/sqlite"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
appv1 "stream.api/internal/api/proto/app/v1"
"stream.api/internal/database/model"
"stream.api/internal/database/query"
"stream.api/internal/middleware"
"stream.api/internal/repository"
"stream.api/pkg/logger"
)
const popupTestTrustedMarker = "trusted-popup-test-marker"
type popupTestLogger struct{}
func (popupTestLogger) Info(string, ...any) {}
func (popupTestLogger) Error(string, ...any) {}
func (popupTestLogger) Debug(string, ...any) {}
func (popupTestLogger) Warn(string, ...any) {}
func newPopupTestDB(t *testing.T) *gorm.DB {
t.Helper()
dsn := fmt.Sprintf("file:%s?mode=memory&cache=shared", uuid.NewString())
db, err := gorm.Open(sqlite.Dialector{DriverName: "sqlite", DSN: dsn}, &gorm.Config{})
if err != nil {
t.Fatalf("open sqlite db: %v", err)
}
for _, stmt := range []string{
`CREATE TABLE user (
id TEXT PRIMARY KEY,
email TEXT NOT NULL,
password TEXT,
username TEXT,
avatar TEXT,
role TEXT NOT NULL,
google_id TEXT,
storage_used INTEGER NOT NULL DEFAULT 0,
plan_id TEXT,
referred_by_user_id TEXT,
referral_eligible BOOLEAN NOT NULL DEFAULT 1,
referral_reward_bps INTEGER,
referral_reward_granted_at DATETIME,
referral_reward_payment_id TEXT,
referral_reward_amount REAL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
version INTEGER NOT NULL DEFAULT 1,
telegram_id TEXT
)`,
`CREATE TABLE plan (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
price REAL NOT NULL,
cycle TEXT NOT NULL,
storage_limit INTEGER NOT NULL,
upload_limit INTEGER NOT NULL,
duration_limit INTEGER NOT NULL,
quality_limit TEXT NOT NULL,
features JSON,
is_active BOOLEAN NOT NULL DEFAULT 1,
version INTEGER NOT NULL DEFAULT 1
)`,
`CREATE TABLE plan_subscriptions (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
payment_id TEXT NOT NULL,
plan_id TEXT NOT NULL,
term_months INTEGER NOT NULL,
payment_method TEXT NOT NULL,
wallet_amount REAL NOT NULL,
topup_amount REAL NOT NULL,
started_at DATETIME NOT NULL,
expires_at DATETIME NOT NULL,
reminder_7d_sent_at DATETIME,
reminder_3d_sent_at DATETIME,
reminder_1d_sent_at DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
version INTEGER NOT NULL DEFAULT 1
)`,
`CREATE TABLE notifications (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
type TEXT NOT NULL,
title TEXT NOT NULL,
message TEXT NOT NULL,
metadata TEXT,
action_url TEXT,
action_label TEXT,
is_read BOOLEAN NOT NULL DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
version INTEGER NOT NULL DEFAULT 1
)`,
`CREATE TABLE popup_ads (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
type TEXT NOT NULL,
label TEXT NOT NULL,
value TEXT NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT 1,
max_triggers_per_session INTEGER NOT NULL DEFAULT 3,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
version INTEGER NOT NULL DEFAULT 1
)`,
} {
if err := db.Exec(stmt).Error; err != nil {
t.Fatalf("create test schema: %v", err)
}
}
query.SetDefault(db)
return db
}
func newPopupTestServices(t *testing.T, db *gorm.DB) *appServices {
t.Helper()
return &appServices{
db: db,
logger: popupTestLogger{},
authenticator: middleware.NewAuthenticator(db, popupTestLogger{}, popupTestTrustedMarker, nil),
userRepository: repository.NewUserRepository(db),
planRepository: repository.NewPlanRepository(db),
notificationRepo: repository.NewNotificationRepository(db),
popupAdRepository: repository.NewPopupAdRepository(db),
googleUserInfoURL: defaultGoogleUserInfoURL,
}
}
func popupTestContext(userID, role string) context.Context {
return metadata.NewIncomingContext(context.Background(), metadata.Pairs(
middleware.ActorMarkerMetadataKey, popupTestTrustedMarker,
middleware.ActorIDMetadataKey, userID,
middleware.ActorRoleMetadataKey, role,
middleware.ActorEmailMetadataKey, "actor@example.com",
))
}
func popupPtrString(v string) *string { return &v }
func popupPtrBool(v bool) *bool { return &v }
func popupPtrInt32(v int32) *int32 { return &v }
func popupPtrTime(v time.Time) *time.Time { return &v }
func popupSeedUser(t *testing.T, db *gorm.DB, user model.User) model.User {
t.Helper()
if user.Role == nil {
user.Role = popupPtrString("USER")
}
if err := db.Create(&user).Error; err != nil {
t.Fatalf("create user: %v", err)
}
return user
}
func popupSeedAd(t *testing.T, db *gorm.DB, item model.PopupAd) model.PopupAd {
t.Helper()
if item.IsActive == nil {
item.IsActive = popupPtrBool(true)
}
if *item.MaxTriggersPerSession == 0 {
*item.MaxTriggersPerSession = 60
}
if item.CreatedAt == nil {
now := time.Now().UTC()
item.CreatedAt = &now
}
if err := db.Create(&item).Error; err != nil {
t.Fatalf("create popup ad: %v", err)
}
return item
}
func popupMustListAds(t *testing.T, db *gorm.DB, userID string) []model.PopupAd {
t.Helper()
var items []model.PopupAd
if err := db.Order("created_at DESC").Find(&items, "user_id = ?", userID).Error; err != nil {
t.Fatalf("list popup ads: %v", err)
}
return items
}
func popupAssertGRPCCode(t *testing.T, err error, code codes.Code) {
t.Helper()
if status.Code(err) != code {
t.Fatalf("grpc code = %v, want %v (err=%v)", status.Code(err), code, err)
}
}
func TestPopupAdsUserFlow(t *testing.T) {
t.Run("create list update delete popup ad", func(t *testing.T) {
db := newPopupTestDB(t)
services := newPopupTestServices(t, db)
user := popupSeedUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: popupPtrString("USER")})
createResp, err := (&popupAdsAppService{appServices: services}).CreatePopupAd(popupTestContext(user.ID, "USER"), &appv1.CreatePopupAdRequest{
Type: "url",
Label: "Homepage Campaign",
Value: "https://example.com/landing",
IsActive: popupPtrBool(true),
MaxTriggersPerSession: popupPtrInt32(5),
})
if err != nil {
t.Fatalf("CreatePopupAd() error = %v", err)
}
if createResp.Item == nil || createResp.Item.Label != "Homepage Campaign" {
t.Fatalf("CreatePopupAd() unexpected response: %#v", createResp)
}
listResp, err := (&popupAdsAppService{appServices: services}).ListPopupAds(popupTestContext(user.ID, "USER"), &appv1.ListPopupAdsRequest{})
if err != nil {
t.Fatalf("ListPopupAds() error = %v", err)
}
if len(listResp.Items) != 1 {
t.Fatalf("ListPopupAds() count = %d, want 1", len(listResp.Items))
}
updateResp, err := (&popupAdsAppService{appServices: services}).UpdatePopupAd(popupTestContext(user.ID, "USER"), &appv1.UpdatePopupAdRequest{
Id: createResp.Item.Id,
Type: "script",
Label: "Homepage Campaign v2",
Value: `<script async src="//example.com/ad.js"></script>`,
IsActive: popupPtrBool(false),
MaxTriggersPerSession: popupPtrInt32(8),
})
if err != nil {
t.Fatalf("UpdatePopupAd() error = %v", err)
}
if updateResp.Item == nil || updateResp.Item.Label != "Homepage Campaign v2" || updateResp.Item.IsActive {
t.Fatalf("UpdatePopupAd() unexpected response: %#v", updateResp)
}
items := popupMustListAds(t, db, user.ID)
if len(items) != 1 {
t.Fatalf("popup ad count = %d, want 1", len(items))
}
if items[0].Type != "script" || items[0].Label != "Homepage Campaign v2" || *items[0].MaxTriggersPerSession != 8 {
t.Fatalf("popup ad values = %#v", items[0])
}
_, err = (&popupAdsAppService{appServices: services}).DeletePopupAd(popupTestContext(user.ID, "USER"), &appv1.DeletePopupAdRequest{Id: createResp.Item.Id})
if err != nil {
t.Fatalf("DeletePopupAd() error = %v", err)
}
items = popupMustListAds(t, db, user.ID)
if len(items) != 0 {
t.Fatalf("popup ad count after delete = %d, want 0", len(items))
}
})
t.Run("reject invalid type", func(t *testing.T) {
db := newPopupTestDB(t)
services := newPopupTestServices(t, db)
user := popupSeedUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: popupPtrString("USER")})
_, err := (&popupAdsAppService{appServices: services}).CreatePopupAd(popupTestContext(user.ID, "USER"), &appv1.CreatePopupAdRequest{
Type: "image",
Label: "Invalid",
Value: "https://example.com/landing",
})
popupAssertGRPCCode(t, err, codes.InvalidArgument)
})
t.Run("get active popup ad returns newest active item", func(t *testing.T) {
db := newPopupTestDB(t)
services := newPopupTestServices(t, db)
user := popupSeedUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: popupPtrString("USER")})
popupSeedAd(t, db, model.PopupAd{ID: uuid.NewString(), UserID: user.ID, Type: "url", Label: "inactive", Value: "https://example.com/1", IsActive: popupPtrBool(false), MaxTriggersPerSession: popupPtrInt32(2)})
popupSeedAd(t, db, model.PopupAd{ID: uuid.NewString(), UserID: user.ID, Type: "url", Label: "older", Value: "https://example.com/3", IsActive: popupPtrBool(true), MaxTriggersPerSession: popupPtrInt32(1), CreatedAt: popupPtrTime(time.Now().UTC().Add(-time.Minute))})
winner := popupSeedAd(t, db, model.PopupAd{ID: uuid.NewString(), UserID: user.ID, Type: "script", Label: "winner", Value: `<script async src="//example.com/win.js"></script>`, IsActive: popupPtrBool(true), MaxTriggersPerSession: popupPtrInt32(3), CreatedAt: popupPtrTime(time.Now().UTC())})
resp, err := (&popupAdsAppService{appServices: services}).GetActivePopupAd(popupTestContext(user.ID, "USER"), &appv1.GetActivePopupAdRequest{})
if err != nil {
t.Fatalf("GetActivePopupAd() error = %v", err)
}
if resp.Item == nil || resp.Item.Id != winner.ID {
t.Fatalf("GetActivePopupAd() = %#v, want winner %q", resp.Item, winner.ID)
}
})
}
func TestPopupAdsAdminFlow(t *testing.T) {
t.Run("admin create list update delete popup ad", func(t *testing.T) {
db := newPopupTestDB(t)
services := newPopupTestServices(t, db)
admin := popupSeedUser(t, db, model.User{ID: uuid.NewString(), Email: "admin@example.com", Role: popupPtrString("ADMIN")})
user := popupSeedUser(t, db, model.User{ID: uuid.NewString(), Email: "user@example.com", Role: popupPtrString("USER")})
createResp, err := services.CreateAdminPopupAd(popupTestContext(admin.ID, "ADMIN"), &appv1.CreateAdminPopupAdRequest{
UserId: user.ID,
Type: "url",
Label: "Admin Campaign",
Value: "https://example.com/admin",
IsActive: popupPtrBool(true),
MaxTriggersPerSession: popupPtrInt32(7),
})
if err != nil {
t.Fatalf("CreateAdminPopupAd() error = %v", err)
}
if createResp.Item == nil || createResp.Item.UserId != user.ID {
t.Fatalf("CreateAdminPopupAd() unexpected response: %#v", createResp)
}
listResp, err := services.ListAdminPopupAds(popupTestContext(admin.ID, "ADMIN"), &appv1.ListAdminPopupAdsRequest{UserId: &user.ID})
if err != nil {
t.Fatalf("ListAdminPopupAds() error = %v", err)
}
if len(listResp.Items) != 1 {
t.Fatalf("ListAdminPopupAds() count = %d, want 1", len(listResp.Items))
}
updateResp, err := services.UpdateAdminPopupAd(popupTestContext(admin.ID, "ADMIN"), &appv1.UpdateAdminPopupAdRequest{
Id: createResp.Item.Id,
UserId: user.ID,
Type: "script",
Label: "Admin Campaign v2",
Value: `<script async src="//example.com/admin-v2.js"></script>`,
IsActive: popupPtrBool(false),
MaxTriggersPerSession: popupPtrInt32(11),
})
if err != nil {
t.Fatalf("UpdateAdminPopupAd() error = %v", err)
}
if updateResp.Item == nil || updateResp.Item.Label != "Admin Campaign v2" || updateResp.Item.IsActive {
t.Fatalf("UpdateAdminPopupAd() unexpected response: %#v", updateResp)
}
_, err = services.DeleteAdminPopupAd(popupTestContext(admin.ID, "ADMIN"), &appv1.DeleteAdminPopupAdRequest{Id: createResp.Item.Id})
if err != nil {
t.Fatalf("DeleteAdminPopupAd() error = %v", err)
}
items := popupMustListAds(t, db, user.ID)
if len(items) != 0 {
t.Fatalf("popup ad count after delete = %d, want 0", len(items))
}
})
}
var _ logger.Logger = popupTestLogger{}

View File

@@ -318,6 +318,150 @@ func (s *adTemplatesAppService) DeleteAdTemplate(ctx context.Context, req *appv1
return messageResponse("Ad template deleted"), nil return messageResponse("Ad template deleted"), nil
} }
func (s *popupAdsAppService) ListPopupAds(ctx context.Context, req *appv1.ListPopupAdsRequest) (*appv1.ListPopupAdsResponse, error) {
result, err := s.authenticate(ctx)
if err != nil {
return nil, err
}
page, limit, offset := adminPageLimitOffset(req.GetPage(), req.GetLimit())
items, total, err := s.popupAdRepository.ListByUser(ctx, result.UserID, limit, offset)
if err != nil {
s.logger.Error("Failed to list popup ads", "error", err)
return nil, status.Error(codes.Internal, "Failed to load popup ads")
}
payload := make([]*appv1.PopupAd, 0, len(items))
for _, item := range items {
copyItem := item
payload = append(payload, toProtoPopupAd(&copyItem))
}
return &appv1.ListPopupAdsResponse{Items: payload, Total: total, Page: page, Limit: limit}, nil
}
func (s *popupAdsAppService) CreatePopupAd(ctx context.Context, req *appv1.CreatePopupAdRequest) (*appv1.CreatePopupAdResponse, error) {
result, err := s.authenticate(ctx)
if err != nil {
return nil, err
}
popupType := strings.ToLower(strings.TrimSpace(req.GetType()))
label := strings.TrimSpace(req.GetLabel())
value := strings.TrimSpace(req.GetValue())
maxTriggers := int32(3)
if req.MaxTriggersPerSession != nil {
maxTriggers = *req.MaxTriggersPerSession
}
if popupType != "url" && popupType != "script" {
return nil, status.Error(codes.InvalidArgument, "Popup ad type must be url or script")
}
if label == "" || value == "" {
return nil, status.Error(codes.InvalidArgument, "Label and value are required")
}
if maxTriggers < 1 {
return nil, status.Error(codes.InvalidArgument, "Max triggers per session must be greater than 0")
}
item := &model.PopupAd{
ID: uuid.New().String(),
UserID: result.UserID,
Type: popupType,
Label: label,
Value: value,
IsActive: model.BoolPtr(req.IsActive == nil || *req.IsActive),
MaxTriggersPerSession: int32Ptr(maxTriggers),
}
if err := s.popupAdRepository.Create(ctx, item); err != nil {
s.logger.Error("Failed to create popup ad", "error", err)
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
return &appv1.CreatePopupAdResponse{Item: toProtoPopupAd(item)}, nil
}
func (s *popupAdsAppService) UpdatePopupAd(ctx context.Context, req *appv1.UpdatePopupAdRequest) (*appv1.UpdatePopupAdResponse, error) {
result, err := s.authenticate(ctx)
if err != nil {
return nil, err
}
id := strings.TrimSpace(req.GetId())
if id == "" {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
popupType := strings.ToLower(strings.TrimSpace(req.GetType()))
label := strings.TrimSpace(req.GetLabel())
value := strings.TrimSpace(req.GetValue())
if popupType != "url" && popupType != "script" {
return nil, status.Error(codes.InvalidArgument, "Popup ad type must be url or script")
}
if label == "" || value == "" {
return nil, status.Error(codes.InvalidArgument, "Label and value are required")
}
if req.MaxTriggersPerSession != nil && *req.MaxTriggersPerSession < 1 {
return nil, status.Error(codes.InvalidArgument, "Max triggers per session must be greater than 0")
}
item, err := s.popupAdRepository.GetByIDAndUser(ctx, id, result.UserID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
s.logger.Error("Failed to load popup ad", "error", err)
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
item.Type = popupType
item.Label = label
item.Value = value
if req.IsActive != nil {
item.IsActive = model.BoolPtr(*req.IsActive)
}
if req.MaxTriggersPerSession != nil {
item.MaxTriggersPerSession = int32Ptr(*req.MaxTriggersPerSession)
}
if err := s.popupAdRepository.Save(ctx, item); err != nil {
s.logger.Error("Failed to update popup ad", "error", err)
return nil, status.Error(codes.Internal, "Failed to save popup ad")
}
return &appv1.UpdatePopupAdResponse{Item: toProtoPopupAd(item)}, nil
}
func (s *popupAdsAppService) DeletePopupAd(ctx context.Context, req *appv1.DeletePopupAdRequest) (*appv1.MessageResponse, error) {
result, err := s.authenticate(ctx)
if err != nil {
return nil, err
}
id := strings.TrimSpace(req.GetId())
if id == "" {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
rowsAffected, err := s.popupAdRepository.DeleteByIDAndUser(ctx, id, result.UserID)
if err != nil {
s.logger.Error("Failed to delete popup ad", "error", err)
return nil, status.Error(codes.Internal, "Failed to delete popup ad")
}
if rowsAffected == 0 {
return nil, status.Error(codes.NotFound, "Popup ad not found")
}
return messageResponse("Popup ad deleted"), nil
}
func (s *popupAdsAppService) GetActivePopupAd(ctx context.Context, _ *appv1.GetActivePopupAdRequest) (*appv1.GetActivePopupAdResponse, error) {
result, err := s.authenticate(ctx)
if err != nil {
return nil, err
}
item, err := s.popupAdRepository.GetActiveByUser(ctx, result.UserID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return &appv1.GetActivePopupAdResponse{}, nil
}
s.logger.Error("Failed to load active popup ad", "error", err)
return nil, status.Error(codes.Internal, "Failed to load popup ad")
}
return &appv1.GetActivePopupAdResponse{Item: toProtoPopupAd(item)}, nil
}
func (s *plansAppService) ListPlans(ctx context.Context, _ *appv1.ListPlansRequest) (*appv1.ListPlansResponse, error) { func (s *plansAppService) ListPlans(ctx context.Context, _ *appv1.ListPlansRequest) (*appv1.ListPlansResponse, error) {
if _, err := s.authenticate(ctx); err != nil { if _, err := s.authenticate(ctx); err != nil {
return nil, err return nil, err

View File

@@ -53,6 +53,14 @@ func int32Ptr(value int32) *int32 {
return &value return &value
} }
func protoTimestampToTime(value *timestamppb.Timestamp) *time.Time {
if value == nil {
return nil
}
timeValue := value.AsTime().UTC()
return &timeValue
}
func protoStringValue(value *string) string { func protoStringValue(value *string) string {
if value == nil { if value == nil {
return "" return ""

View File

@@ -36,17 +36,19 @@ func NewGRPCModule(ctx context.Context, cfg *config.Config, db *gorm.DB, rds *re
cfg: cfg, cfg: cfg,
} }
var notificationPublisher service.NotificationEventPublisher = nil
if publisher, err := mqtt.NewMQTTBootstrap(jobService, agentRuntime, appLogger); err != nil { if publisher, err := mqtt.NewMQTTBootstrap(jobService, agentRuntime, appLogger); err != nil {
appLogger.Error("Failed to initialize MQTT publisher", "error", err) appLogger.Error("Failed to initialize MQTT publisher", "error", err)
} else { } else {
module.mqttPublisher = publisher module.mqttPublisher = publisher
notificationPublisher = mqtt.NewNotificationPublisher(publisher.Client(), appLogger)
agentRuntime.SetAgentEventHandler(func(eventType string, agent *dto.AgentWithStats) { agentRuntime.SetAgentEventHandler(func(eventType string, agent *dto.AgentWithStats) {
mqtt.PublishAgentMQTTEvent(publisher.Client(), appLogger, eventType, agent) mqtt.PublishAgentMQTTEvent(publisher.Client(), appLogger, eventType, agent)
}) })
} }
agentRuntime.Register(grpcServer) agentRuntime.Register(grpcServer)
service.Register(grpcServer, service.NewServices(rds, db, appLogger, cfg, videoService, agentRuntime)) service.Register(grpcServer, service.NewServices(rds, db, appLogger, cfg, videoService, agentRuntime, notificationPublisher))
if module.mqttPublisher != nil { if module.mqttPublisher != nil {
module.mqttPublisher.Start(ctx) module.mqttPublisher.Start(ctx)
} }

View File

@@ -0,0 +1,41 @@
package mqtt
import (
"context"
pahomqtt "github.com/eclipse/paho.mqtt.golang"
"stream.api/internal/dto"
"stream.api/internal/service"
"stream.api/pkg/logger"
)
type MQTTBootstrap struct{ *streamEventPublisher }
func NewMQTTBootstrap(jobService *service.JobService, agentRT agentRuntime, appLogger logger.Logger) (*MQTTBootstrap, error) {
publisher, err := newStreamEventPublisher(jobService, agentRT, appLogger)
if err != nil {
return nil, err
}
return &MQTTBootstrap{streamEventPublisher: publisher}, nil
}
func (b *MQTTBootstrap) Start(ctx context.Context) {
if b == nil || b.streamEventPublisher == nil {
return
}
b.streamEventPublisher.start(ctx)
}
func (b *MQTTBootstrap) Client() pahomqtt.Client {
if b == nil || b.streamEventPublisher == nil {
return nil
}
return b.client
}
func PublishAgentMQTTEvent(client pahomqtt.Client, appLogger logger.Logger, eventType string, agent *dto.AgentWithStats) {
publishMQTTEvent(client, appLogger, defaultMQTTPrefix, mqttEvent{
Type: eventType,
Payload: mapAgentPayload(agent),
})
}

View File

@@ -0,0 +1,14 @@
package mqtt
import "time"
const (
defaultMQTTBrokerURL = "tcp://broker.mqtt-dashboard.com:1883"
defaultMQTTPrefix = "picpic"
defaultPublishWait = 5 * time.Second
)
type mqttEvent struct {
Type string `json:"type"`
Payload any `json:"payload"`
}

View File

@@ -0,0 +1,44 @@
package mqtt
import (
"context"
"fmt"
pahomqtt "github.com/eclipse/paho.mqtt.golang"
"stream.api/internal/database/model"
"stream.api/internal/service"
"stream.api/pkg/logger"
)
type notificationPublisher struct {
client pahomqtt.Client
logger logger.Logger
prefix string
}
func NewNotificationPublisher(client pahomqtt.Client, appLogger logger.Logger) service.NotificationEventPublisher {
if client == nil {
return service.NotificationEventPublisher(serviceNotificationNoop{})
}
return &notificationPublisher{client: client, logger: appLogger, prefix: defaultMQTTPrefix}
}
type serviceNotificationNoop struct{}
func (serviceNotificationNoop) PublishNotificationCreated(context.Context, *model.Notification) error { return nil }
func (p *notificationPublisher) PublishNotificationCreated(_ context.Context, notification *model.Notification) error {
if p == nil || notification == nil {
return nil
}
message := mqttEvent{
Type: "notification.created",
Payload: service.BuildNotificationCreatedPayload(notification),
}
return publishMQTTJSON(p.client, p.notificationTopic(notification.UserID), message)
}
func (p *notificationPublisher) notificationTopic(userID string) string {
return fmt.Sprintf("%s/notifications/%s", p.prefix, userID)
}

View File

@@ -36,17 +36,22 @@ func publishMQTTEvent(client pahomqtt.Client, appLogger logger.Logger, prefix st
return return
} }
encoded, err := json.Marshal(event) if err := publishMQTTJSON(client, fmt.Sprintf("%s/events", prefix), event); err != nil {
if err != nil {
appLogger.Error("Failed to marshal MQTT event", "error", err, "type", event.Type)
return
}
if err := publishPahoMessage(client, fmt.Sprintf("%s/events", prefix), encoded); err != nil {
appLogger.Error("Failed to publish MQTT event", "error", err, "type", event.Type) appLogger.Error("Failed to publish MQTT event", "error", err, "type", event.Type)
} }
} }
func publishMQTTJSON(client pahomqtt.Client, topic string, payload any) error {
if client == nil {
return nil
}
encoded, err := json.Marshal(payload)
if err != nil {
return err
}
return publishPahoMessage(client, topic, encoded)
}
func publishPahoMessage(client pahomqtt.Client, topic string, payload []byte) error { func publishPahoMessage(client pahomqtt.Client, topic string, payload []byte) error {
if client == nil { if client == nil {
return nil return nil

View File

@@ -12,17 +12,11 @@ import (
"stream.api/pkg/logger" "stream.api/pkg/logger"
) )
const (
defaultMQTTBrokerURL = "tcp://broker.mqtt-dashboard.com:1883"
defaultMQTTPrefix = "picpic"
defaultPublishWait = 5 * time.Second
)
type agentRuntime interface { type agentRuntime interface {
ListAgentsWithStats() []*dto.AgentWithStats ListAgentsWithStats() []*dto.AgentWithStats
} }
type mqttPublisher struct { type streamEventPublisher struct {
client pahomqtt.Client client pahomqtt.Client
jobService *service.JobService jobService *service.JobService
agentRT agentRuntime agentRT agentRuntime
@@ -30,13 +24,13 @@ type mqttPublisher struct {
prefix string prefix string
} }
func newMQTTPublisher(jobService *service.JobService, agentRT agentRuntime, appLogger logger.Logger) (*mqttPublisher, error) { func newStreamEventPublisher(jobService *service.JobService, agentRT agentRuntime, appLogger logger.Logger) (*streamEventPublisher, error) {
client, err := connectPahoClient(defaultMQTTBrokerURL, fmt.Sprintf("stream-api-%d", time.Now().UnixNano())) client, err := connectPahoClient(defaultMQTTBrokerURL, fmt.Sprintf("stream-api-%d", time.Now().UnixNano()))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &mqttPublisher{ return &streamEventPublisher{
client: client, client: client,
jobService: jobService, jobService: jobService,
agentRT: agentRT, agentRT: agentRT,
@@ -45,7 +39,7 @@ func newMQTTPublisher(jobService *service.JobService, agentRT agentRuntime, appL
}, nil }, nil
} }
func (p *mqttPublisher) start(ctx context.Context) { func (p *streamEventPublisher) start(ctx context.Context) {
if p == nil || p.jobService == nil { if p == nil || p.jobService == nil {
return return
} }
@@ -54,7 +48,7 @@ func (p *mqttPublisher) start(ctx context.Context) {
go p.consumeResources(ctx) go p.consumeResources(ctx)
} }
func (p *mqttPublisher) consumeLogs(ctx context.Context) { func (p *streamEventPublisher) consumeLogs(ctx context.Context) {
ch, err := p.jobService.SubscribeJobLogs(ctx, "") ch, err := p.jobService.SubscribeJobLogs(ctx, "")
if err != nil { if err != nil {
p.logger.Error("Failed to subscribe job logs for MQTT", "error", err) p.logger.Error("Failed to subscribe job logs for MQTT", "error", err)
@@ -69,14 +63,14 @@ func (p *mqttPublisher) consumeLogs(ctx context.Context) {
if !ok { if !ok {
return return
} }
if err := p.publishJSON(p.logTopic(entry.JobID), entry); err != nil { if err := publishMQTTJSON(p.client, p.logTopic(entry.JobID), entry); err != nil {
p.logger.Error("Failed to publish MQTT job log", "error", err, "job_id", entry.JobID) p.logger.Error("Failed to publish MQTT job log", "error", err, "job_id", entry.JobID)
} }
} }
} }
} }
func (p *mqttPublisher) consumeJobUpdates(ctx context.Context) { func (p *streamEventPublisher) consumeJobUpdates(ctx context.Context) {
ch, err := p.jobService.SubscribeJobUpdates(ctx) ch, err := p.jobService.SubscribeJobUpdates(ctx)
if err != nil { if err != nil {
p.logger.Error("Failed to subscribe job updates for MQTT", "error", err) p.logger.Error("Failed to subscribe job updates for MQTT", "error", err)
@@ -106,7 +100,7 @@ func (p *mqttPublisher) consumeJobUpdates(ctx context.Context) {
} }
} }
func (p *mqttPublisher) consumeResources(ctx context.Context) { func (p *streamEventPublisher) consumeResources(ctx context.Context) {
ch, err := p.jobService.SubscribeSystemResources(ctx) ch, err := p.jobService.SubscribeSystemResources(ctx)
if err != nil { if err != nil {
p.logger.Error("Failed to subscribe resources for MQTT", "error", err) p.logger.Error("Failed to subscribe resources for MQTT", "error", err)
@@ -137,7 +131,7 @@ func (p *mqttPublisher) consumeResources(ctx context.Context) {
} }
} }
func (p *mqttPublisher) findAgent(agentID string) *dto.AgentWithStats { func (p *streamEventPublisher) findAgent(agentID string) *dto.AgentWithStats {
if p == nil || p.agentRT == nil { if p == nil || p.agentRT == nil {
return nil return nil
} }
@@ -149,40 +143,25 @@ func (p *mqttPublisher) findAgent(agentID string) *dto.AgentWithStats {
return nil return nil
} }
func (p *mqttPublisher) publishEvent(eventType string, payload any, jobID string) error { func (p *streamEventPublisher) publishEvent(eventType string, payload any, jobID string) error {
message := mqttEvent{Type: eventType, Payload: payload} message := mqttEvent{Type: eventType, Payload: payload}
if jobID != "" { if jobID != "" {
if err := p.publishJSON(p.jobTopic(jobID), message); err != nil { if err := publishMQTTJSON(p.client, p.jobTopic(jobID), message); err != nil {
return err return err
} }
} }
return p.publishJSON(p.eventsTopic(), message) return publishMQTTJSON(p.client, p.eventsTopic(), message)
} }
func (p *mqttPublisher) publishJSON(topic string, payload any) error { func (p *streamEventPublisher) logTopic(jobID string) string {
encoded, err := json.Marshal(payload)
if err != nil {
return err
}
return p.publish(topic, encoded)
}
func (p *mqttPublisher) publish(topic string, payload []byte) error {
if p == nil {
return nil
}
return publishPahoMessage(p.client, topic, payload)
}
func (p *mqttPublisher) logTopic(jobID string) string {
return fmt.Sprintf("%s/logs/%s", p.prefix, jobID) return fmt.Sprintf("%s/logs/%s", p.prefix, jobID)
} }
func (p *mqttPublisher) jobTopic(jobID string) string { func (p *streamEventPublisher) jobTopic(jobID string) string {
return fmt.Sprintf("%s/job/%s", p.prefix, jobID) return fmt.Sprintf("%s/job/%s", p.prefix, jobID)
} }
func (p *mqttPublisher) eventsTopic() string { func (p *streamEventPublisher) eventsTopic() string {
return fmt.Sprintf("%s/events", p.prefix) return fmt.Sprintf("%s/events", p.prefix)
} }
@@ -206,39 +185,3 @@ func mapAgentPayload(agent *dto.AgentWithStats) map[string]any {
"active_job_count": agent.ActiveJobCount, "active_job_count": agent.ActiveJobCount,
} }
} }
type mqttEvent struct {
Type string `json:"type"`
Payload any `json:"payload"`
}
type MQTTBootstrap struct{ *mqttPublisher }
func NewMQTTBootstrap(jobService *service.JobService, agentRT agentRuntime, appLogger logger.Logger) (*MQTTBootstrap, error) {
publisher, err := newMQTTPublisher(jobService, agentRT, appLogger)
if err != nil {
return nil, err
}
return &MQTTBootstrap{mqttPublisher: publisher}, nil
}
func (b *MQTTBootstrap) Start(ctx context.Context) {
if b == nil || b.mqttPublisher == nil {
return
}
b.mqttPublisher.start(ctx)
}
func (b *MQTTBootstrap) Client() pahomqtt.Client {
if b == nil || b.mqttPublisher == nil {
return nil
}
return b.client
}
func PublishAgentMQTTEvent(client pahomqtt.Client, appLogger logger.Logger, eventType string, agent *dto.AgentWithStats) {
publishMQTTEvent(client, appLogger, defaultMQTTPrefix, mqttEvent{
Type: eventType,
Payload: mapAgentPayload(agent),
})
}

View File

@@ -0,0 +1,15 @@
CREATE TABLE IF NOT EXISTS popup_ads (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
type VARCHAR(20) NOT NULL,
label TEXT NOT NULL,
value TEXT NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
max_triggers_per_session INTEGER NOT NULL DEFAULT 3,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ,
version BIGINT NOT NULL DEFAULT 1
);
CREATE INDEX IF NOT EXISTS idx_popup_ads_user_id ON popup_ads(user_id);
CREATE INDEX IF NOT EXISTS idx_popup_ads_user_active ON popup_ads(user_id, is_active);

View File

@@ -33,6 +33,11 @@ service Admin {
rpc CreateAdminAdTemplate(CreateAdminAdTemplateRequest) returns (CreateAdminAdTemplateResponse); rpc CreateAdminAdTemplate(CreateAdminAdTemplateRequest) returns (CreateAdminAdTemplateResponse);
rpc UpdateAdminAdTemplate(UpdateAdminAdTemplateRequest) returns (UpdateAdminAdTemplateResponse); rpc UpdateAdminAdTemplate(UpdateAdminAdTemplateRequest) returns (UpdateAdminAdTemplateResponse);
rpc DeleteAdminAdTemplate(DeleteAdminAdTemplateRequest) returns (MessageResponse); rpc DeleteAdminAdTemplate(DeleteAdminAdTemplateRequest) returns (MessageResponse);
rpc ListAdminPopupAds(ListAdminPopupAdsRequest) returns (ListAdminPopupAdsResponse);
rpc GetAdminPopupAd(GetAdminPopupAdRequest) returns (GetAdminPopupAdResponse);
rpc CreateAdminPopupAd(CreateAdminPopupAdRequest) returns (CreateAdminPopupAdResponse);
rpc UpdateAdminPopupAd(UpdateAdminPopupAdRequest) returns (UpdateAdminPopupAdResponse);
rpc DeleteAdminPopupAd(DeleteAdminPopupAdRequest) returns (MessageResponse);
rpc ListAdminPlayerConfigs(ListAdminPlayerConfigsRequest) returns (ListAdminPlayerConfigsResponse); rpc ListAdminPlayerConfigs(ListAdminPlayerConfigsRequest) returns (ListAdminPlayerConfigsResponse);
rpc GetAdminPlayerConfig(GetAdminPlayerConfigRequest) returns (GetAdminPlayerConfigResponse); rpc GetAdminPlayerConfig(GetAdminPlayerConfigRequest) returns (GetAdminPlayerConfigResponse);
rpc CreateAdminPlayerConfig(CreateAdminPlayerConfigRequest) returns (CreateAdminPlayerConfigResponse); rpc CreateAdminPlayerConfig(CreateAdminPlayerConfigRequest) returns (CreateAdminPlayerConfigResponse);
@@ -338,6 +343,59 @@ message DeleteAdminAdTemplateRequest {
string id = 1; string id = 1;
} }
message ListAdminPopupAdsRequest {
int32 page = 1;
int32 limit = 2;
optional string user_id = 3;
optional string search = 4;
}
message ListAdminPopupAdsResponse {
repeated AdminPopupAd items = 1;
int64 total = 2;
int32 page = 3;
int32 limit = 4;
}
message GetAdminPopupAdRequest {
string id = 1;
}
message GetAdminPopupAdResponse {
AdminPopupAd item = 1;
}
message CreateAdminPopupAdRequest {
string user_id = 1;
string type = 2;
string label = 3;
string value = 4;
optional bool is_active = 5;
optional int32 max_triggers_per_session = 6;
}
message CreateAdminPopupAdResponse {
AdminPopupAd item = 1;
}
message UpdateAdminPopupAdRequest {
string id = 1;
string user_id = 2;
string type = 3;
string label = 4;
string value = 5;
optional bool is_active = 6;
optional int32 max_triggers_per_session = 7;
}
message UpdateAdminPopupAdResponse {
AdminPopupAd item = 1;
}
message DeleteAdminPopupAdRequest {
string id = 1;
}
message ListAdminPlayerConfigsRequest { message ListAdminPlayerConfigsRequest {
int32 page = 1; int32 page = 1;
int32 limit = 2; int32 limit = 2;

View File

@@ -19,6 +19,14 @@ service AdTemplates {
rpc DeleteAdTemplate(DeleteAdTemplateRequest) returns (MessageResponse); rpc DeleteAdTemplate(DeleteAdTemplateRequest) returns (MessageResponse);
} }
service PopupAds {
rpc ListPopupAds(ListPopupAdsRequest) returns (ListPopupAdsResponse);
rpc CreatePopupAd(CreatePopupAdRequest) returns (CreatePopupAdResponse);
rpc UpdatePopupAd(UpdatePopupAdRequest) returns (UpdatePopupAdResponse);
rpc DeletePopupAd(DeletePopupAdRequest) returns (MessageResponse);
rpc GetActivePopupAd(GetActivePopupAdRequest) returns (GetActivePopupAdResponse);
}
service PlayerConfigs { service PlayerConfigs {
rpc ListPlayerConfigs(ListPlayerConfigsRequest) returns (ListPlayerConfigsResponse); rpc ListPlayerConfigs(ListPlayerConfigsRequest) returns (ListPlayerConfigsResponse);
rpc CreatePlayerConfig(CreatePlayerConfigRequest) returns (CreatePlayerConfigResponse); rpc CreatePlayerConfig(CreatePlayerConfigRequest) returns (CreatePlayerConfigResponse);
@@ -87,6 +95,53 @@ message DeleteAdTemplateRequest {
string id = 1; string id = 1;
} }
message ListPopupAdsRequest {
int32 page = 1;
int32 limit = 2;
}
message ListPopupAdsResponse {
repeated PopupAd items = 1;
int64 total = 2;
int32 page = 3;
int32 limit = 4;
}
message CreatePopupAdRequest {
string type = 1;
string label = 2;
string value = 3;
optional bool is_active = 4;
optional int32 max_triggers_per_session = 5;
}
message CreatePopupAdResponse {
PopupAd item = 1;
}
message UpdatePopupAdRequest {
string id = 1;
string type = 2;
string label = 3;
string value = 4;
optional bool is_active = 5;
optional int32 max_triggers_per_session = 6;
}
message UpdatePopupAdResponse {
PopupAd item = 1;
}
message DeletePopupAdRequest {
string id = 1;
}
message GetActivePopupAdRequest {}
message GetActivePopupAdResponse {
optional PopupAd item = 1;
}
message ListPlayerConfigsRequest {} message ListPlayerConfigsRequest {}
message ListPlayerConfigsResponse { message ListPlayerConfigsResponse {

View File

@@ -79,6 +79,17 @@ message AdTemplate {
google.protobuf.Timestamp updated_at = 10; google.protobuf.Timestamp updated_at = 10;
} }
message PopupAd {
string id = 1;
string type = 2;
string label = 3;
string value = 4;
bool is_active = 5;
int32 max_triggers_per_session = 6;
google.protobuf.Timestamp created_at = 7;
google.protobuf.Timestamp updated_at = 8;
}
message PlayerConfig { message PlayerConfig {
string id = 1; string id = 1;
string name = 2; string name = 2;
@@ -331,6 +342,19 @@ message AdminAdTemplate {
google.protobuf.Timestamp updated_at = 12; google.protobuf.Timestamp updated_at = 12;
} }
message AdminPopupAd {
string id = 1;
string user_id = 2;
string type = 3;
string label = 4;
string value = 5;
bool is_active = 6;
int32 max_triggers_per_session = 7;
optional string owner_email = 8;
google.protobuf.Timestamp created_at = 9;
google.protobuf.Timestamp updated_at = 10;
}
message AdminJob { message AdminJob {
string id = 1; string id = 1;
string status = 2; string status = 2;