update
This commit is contained in:
parent
a60608bdbc
commit
d6fabedb23
@ -33,6 +33,7 @@ import (
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/jwks"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/post"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/stream"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/user"
|
||||
)
|
||||
|
||||
// Injectors from wire.go:
|
||||
@ -52,7 +53,10 @@ func CreateApp() (*base.Application, error) {
|
||||
categoryService := category.NewService(query)
|
||||
postController := application_v1.NewPostController(authService, applicationService, postService, categoryService)
|
||||
categoryController := application_v1.NewCategoryController(authService, applicationService, postService, categoryService)
|
||||
handlers := http.NewHandler(applicationController, application_v1ApplicationController, postController, categoryController)
|
||||
userService := user.NewService(query, postService, loggerLogger)
|
||||
redisRedis := redis.NewRedis(config)
|
||||
userController := application_v1.NewUserController(authService, applicationService, userService, postService, loggerLogger, redisRedis)
|
||||
handlers := http.NewHandler(applicationController, application_v1ApplicationController, postController, categoryController, userController)
|
||||
api := router.NewApiRoute(handlers)
|
||||
swaggerRouter := router.NewSwaggerRoute()
|
||||
ginLoggerMiddleware := middleware.NewGinLoggerMiddleware(loggerLogger)
|
||||
@ -67,8 +71,7 @@ func CreateApp() (*base.Application, error) {
|
||||
grpcInterceptor := grpc.NewInterceptor(interceptorAuth, interceptorLogger)
|
||||
grpcHandlers := grpc.NewHandler(documentService, grpcInterceptor)
|
||||
handlerHandler := handler.NewHandler(grpcHandlers, handlers)
|
||||
serviceService := service.NewService(loggerLogger, jwksJWKS, streamService, authService, applicationService, postService, categoryService)
|
||||
redisRedis := redis.NewRedis(config)
|
||||
serviceService := service.NewService(loggerLogger, jwksJWKS, streamService, authService, applicationService, postService, categoryService, userService)
|
||||
batchBatch := batch.NewBatch(loggerLogger)
|
||||
s3S3 := s3.NewS3(config)
|
||||
baseApplication := base.NewApplication(config, httpServer, handlerHandler, loggerLogger, serviceService, httpMiddleware, redisRedis, batchBatch, s3S3, db, query)
|
||||
|
@ -22,6 +22,7 @@ redis:
|
||||
port: 6379
|
||||
password: ""
|
||||
db: 0
|
||||
prefix: "recommender_"
|
||||
|
||||
jwks:
|
||||
url: ""
|
||||
|
125
docs/docs.go
125
docs/docs.go
@ -697,6 +697,120 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/applications/v1/users/_dislike": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "从用户的标签喜好中移除内容",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"application_api"
|
||||
],
|
||||
"summary": "Dislike",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "UserLikePost",
|
||||
"name": "UserLikePost",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.UserLikePost"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.ResponseBody"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/entity.Category"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.ResponseBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/applications/v1/users/_like": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "将标签附加到用户名",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"application_api"
|
||||
],
|
||||
"summary": "Like",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "UserLikePost",
|
||||
"name": "UserLikePost",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.UserLikePost"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.ResponseBody"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/entity.Category"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.ResponseBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@ -900,6 +1014,17 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.UserLikePost": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external_user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"post_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"response.ResponseBody": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -688,6 +688,120 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/applications/v1/users/_dislike": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "从用户的标签喜好中移除内容",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"application_api"
|
||||
],
|
||||
"summary": "Dislike",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "UserLikePost",
|
||||
"name": "UserLikePost",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.UserLikePost"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.ResponseBody"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/entity.Category"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.ResponseBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/applications/v1/users/_like": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "将标签附加到用户名",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"application_api"
|
||||
],
|
||||
"summary": "Like",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "UserLikePost",
|
||||
"name": "UserLikePost",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.UserLikePost"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.ResponseBody"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/entity.Category"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.ResponseBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@ -891,6 +1005,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.UserLikePost": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external_user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"post_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"response.ResponseBody": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -133,6 +133,13 @@ definitions:
|
||||
- target_id
|
||||
- title
|
||||
type: object
|
||||
request.UserLikePost:
|
||||
properties:
|
||||
external_user_id:
|
||||
type: string
|
||||
post_id:
|
||||
type: integer
|
||||
type: object
|
||||
response.ResponseBody:
|
||||
properties:
|
||||
data: {}
|
||||
@ -541,6 +548,72 @@ paths:
|
||||
summary: 新建资源
|
||||
tags:
|
||||
- application_api
|
||||
/applications/v1/users/_dislike:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 从用户的标签喜好中移除内容
|
||||
parameters:
|
||||
- description: UserLikePost
|
||||
in: body
|
||||
name: UserLikePost
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.UserLikePost'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.ResponseBody'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/entity.Category'
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.ResponseBody'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Dislike
|
||||
tags:
|
||||
- application_api
|
||||
/applications/v1/users/_like:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 将标签附加到用户名
|
||||
parameters:
|
||||
- description: UserLikePost
|
||||
in: body
|
||||
name: UserLikePost
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.UserLikePost'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.ResponseBody'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/entity.Category'
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.ResponseBody'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Like
|
||||
tags:
|
||||
- application_api
|
||||
securityDefinitions:
|
||||
ApiKeyAuth:
|
||||
in: header
|
||||
|
@ -34,6 +34,7 @@ func main() {
|
||||
entity.ApplicationToken{},
|
||||
entity.UserTagScore{},
|
||||
entity.Category{},
|
||||
entity.ExternalUser{},
|
||||
)
|
||||
|
||||
// Generate Type Safe API with Dynamic SQL defined on Querier interface for `model.User` and `model.Company`
|
||||
|
@ -53,6 +53,7 @@ type Redis struct {
|
||||
Host string `yaml:"host"`
|
||||
Port int `yaml:"port"`
|
||||
Password string `yaml:"password"`
|
||||
Prefix string `yaml:"prefix"`
|
||||
DB int `yaml:"db"`
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
type Redis struct {
|
||||
Client *redis.Client
|
||||
Locker *redislock.Client
|
||||
config *conf.Config
|
||||
}
|
||||
|
||||
func NewRedis(c *conf.Config) *Redis {
|
||||
@ -32,7 +33,12 @@ func NewRedis(c *conf.Config) *Redis {
|
||||
var r = &Redis{
|
||||
Client: client,
|
||||
Locker: locker,
|
||||
config: c,
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Redis) Prefix(key string) string {
|
||||
return fmt.Sprintf("%s:%s", r.config.Redis.Prefix, key)
|
||||
}
|
||||
|
486
internal/dao/external_users.gen.go
Normal file
486
internal/dao/external_users.gen.go
Normal file
@ -0,0 +1,486 @@
|
||||
// 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 dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"gorm.io/gorm/schema"
|
||||
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
|
||||
"leafdev.top/Ecosystem/recommender/internal/entity"
|
||||
)
|
||||
|
||||
func newExternalUser(db *gorm.DB, opts ...gen.DOOption) externalUser {
|
||||
_externalUser := externalUser{}
|
||||
|
||||
_externalUser.externalUserDo.UseDB(db, opts...)
|
||||
_externalUser.externalUserDo.UseModel(&entity.ExternalUser{})
|
||||
|
||||
tableName := _externalUser.externalUserDo.TableName()
|
||||
_externalUser.ALL = field.NewAsterisk(tableName)
|
||||
_externalUser.Id = field.NewUint(tableName, "id")
|
||||
_externalUser.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_externalUser.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_externalUser.Name = field.NewString(tableName, "name")
|
||||
_externalUser.Email = field.NewString(tableName, "email")
|
||||
_externalUser.ExternalId = field.NewString(tableName, "external_id")
|
||||
_externalUser.Summary = field.NewString(tableName, "summary")
|
||||
_externalUser.ApplicationId = field.NewUint(tableName, "application_id")
|
||||
_externalUser.Application = externalUserBelongsToApplication{
|
||||
db: db.Session(&gorm.Session{}),
|
||||
|
||||
RelationField: field.NewRelation("Application", "entity.Application"),
|
||||
}
|
||||
|
||||
_externalUser.fillFieldMap()
|
||||
|
||||
return _externalUser
|
||||
}
|
||||
|
||||
type externalUser struct {
|
||||
externalUserDo
|
||||
|
||||
ALL field.Asterisk
|
||||
Id field.Uint
|
||||
CreatedAt field.Time
|
||||
UpdatedAt field.Time
|
||||
Name field.String
|
||||
Email field.String
|
||||
ExternalId field.String
|
||||
Summary field.String
|
||||
ApplicationId field.Uint
|
||||
Application externalUserBelongsToApplication
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (e externalUser) Table(newTableName string) *externalUser {
|
||||
e.externalUserDo.UseTable(newTableName)
|
||||
return e.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (e externalUser) As(alias string) *externalUser {
|
||||
e.externalUserDo.DO = *(e.externalUserDo.As(alias).(*gen.DO))
|
||||
return e.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (e *externalUser) updateTableName(table string) *externalUser {
|
||||
e.ALL = field.NewAsterisk(table)
|
||||
e.Id = field.NewUint(table, "id")
|
||||
e.CreatedAt = field.NewTime(table, "created_at")
|
||||
e.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
e.Name = field.NewString(table, "name")
|
||||
e.Email = field.NewString(table, "email")
|
||||
e.ExternalId = field.NewString(table, "external_id")
|
||||
e.Summary = field.NewString(table, "summary")
|
||||
e.ApplicationId = field.NewUint(table, "application_id")
|
||||
|
||||
e.fillFieldMap()
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *externalUser) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := e.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
_oe, ok := _f.(field.OrderExpr)
|
||||
return _oe, ok
|
||||
}
|
||||
|
||||
func (e *externalUser) fillFieldMap() {
|
||||
e.fieldMap = make(map[string]field.Expr, 9)
|
||||
e.fieldMap["id"] = e.Id
|
||||
e.fieldMap["created_at"] = e.CreatedAt
|
||||
e.fieldMap["updated_at"] = e.UpdatedAt
|
||||
e.fieldMap["name"] = e.Name
|
||||
e.fieldMap["email"] = e.Email
|
||||
e.fieldMap["external_id"] = e.ExternalId
|
||||
e.fieldMap["summary"] = e.Summary
|
||||
e.fieldMap["application_id"] = e.ApplicationId
|
||||
|
||||
}
|
||||
|
||||
func (e externalUser) clone(db *gorm.DB) externalUser {
|
||||
e.externalUserDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e externalUser) replaceDB(db *gorm.DB) externalUser {
|
||||
e.externalUserDo.ReplaceDB(db)
|
||||
return e
|
||||
}
|
||||
|
||||
type externalUserBelongsToApplication struct {
|
||||
db *gorm.DB
|
||||
|
||||
field.RelationField
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplication) Where(conds ...field.Expr) *externalUserBelongsToApplication {
|
||||
if len(conds) == 0 {
|
||||
return &a
|
||||
}
|
||||
|
||||
exprs := make([]clause.Expression, 0, len(conds))
|
||||
for _, cond := range conds {
|
||||
exprs = append(exprs, cond.BeCond().(clause.Expression))
|
||||
}
|
||||
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplication) WithContext(ctx context.Context) *externalUserBelongsToApplication {
|
||||
a.db = a.db.WithContext(ctx)
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplication) Session(session *gorm.Session) *externalUserBelongsToApplication {
|
||||
a.db = a.db.Session(session)
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplication) Model(m *entity.ExternalUser) *externalUserBelongsToApplicationTx {
|
||||
return &externalUserBelongsToApplicationTx{a.db.Model(m).Association(a.Name())}
|
||||
}
|
||||
|
||||
type externalUserBelongsToApplicationTx struct{ tx *gorm.Association }
|
||||
|
||||
func (a externalUserBelongsToApplicationTx) Find() (result *entity.Application, err error) {
|
||||
return result, a.tx.Find(&result)
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplicationTx) Append(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Append(targetValues...)
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplicationTx) Replace(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Replace(targetValues...)
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplicationTx) Delete(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Delete(targetValues...)
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplicationTx) Clear() error {
|
||||
return a.tx.Clear()
|
||||
}
|
||||
|
||||
func (a externalUserBelongsToApplicationTx) Count() int64 {
|
||||
return a.tx.Count()
|
||||
}
|
||||
|
||||
type externalUserDo struct{ gen.DO }
|
||||
|
||||
type IExternalUserDo interface {
|
||||
gen.SubQuery
|
||||
Debug() IExternalUserDo
|
||||
WithContext(ctx context.Context) IExternalUserDo
|
||||
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
|
||||
ReplaceDB(db *gorm.DB)
|
||||
ReadDB() IExternalUserDo
|
||||
WriteDB() IExternalUserDo
|
||||
As(alias string) gen.Dao
|
||||
Session(config *gorm.Session) IExternalUserDo
|
||||
Columns(cols ...field.Expr) gen.Columns
|
||||
Clauses(conds ...clause.Expression) IExternalUserDo
|
||||
Not(conds ...gen.Condition) IExternalUserDo
|
||||
Or(conds ...gen.Condition) IExternalUserDo
|
||||
Select(conds ...field.Expr) IExternalUserDo
|
||||
Where(conds ...gen.Condition) IExternalUserDo
|
||||
Order(conds ...field.Expr) IExternalUserDo
|
||||
Distinct(cols ...field.Expr) IExternalUserDo
|
||||
Omit(cols ...field.Expr) IExternalUserDo
|
||||
Join(table schema.Tabler, on ...field.Expr) IExternalUserDo
|
||||
LeftJoin(table schema.Tabler, on ...field.Expr) IExternalUserDo
|
||||
RightJoin(table schema.Tabler, on ...field.Expr) IExternalUserDo
|
||||
Group(cols ...field.Expr) IExternalUserDo
|
||||
Having(conds ...gen.Condition) IExternalUserDo
|
||||
Limit(limit int) IExternalUserDo
|
||||
Offset(offset int) IExternalUserDo
|
||||
Count() (count int64, err error)
|
||||
Scopes(funcs ...func(gen.Dao) gen.Dao) IExternalUserDo
|
||||
Unscoped() IExternalUserDo
|
||||
Create(values ...*entity.ExternalUser) error
|
||||
CreateInBatches(values []*entity.ExternalUser, batchSize int) error
|
||||
Save(values ...*entity.ExternalUser) error
|
||||
First() (*entity.ExternalUser, error)
|
||||
Take() (*entity.ExternalUser, error)
|
||||
Last() (*entity.ExternalUser, error)
|
||||
Find() ([]*entity.ExternalUser, error)
|
||||
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*entity.ExternalUser, err error)
|
||||
FindInBatches(result *[]*entity.ExternalUser, batchSize int, fc func(tx gen.Dao, batch int) error) error
|
||||
Pluck(column field.Expr, dest interface{}) error
|
||||
Delete(...*entity.ExternalUser) (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) IExternalUserDo
|
||||
Assign(attrs ...field.AssignExpr) IExternalUserDo
|
||||
Joins(fields ...field.RelationField) IExternalUserDo
|
||||
Preload(fields ...field.RelationField) IExternalUserDo
|
||||
FirstOrInit() (*entity.ExternalUser, error)
|
||||
FirstOrCreate() (*entity.ExternalUser, error)
|
||||
FindByPage(offset int, limit int) (result []*entity.ExternalUser, count int64, err error)
|
||||
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
|
||||
Scan(result interface{}) (err error)
|
||||
Returning(value interface{}, columns ...string) IExternalUserDo
|
||||
UnderlyingDB() *gorm.DB
|
||||
schema.Tabler
|
||||
}
|
||||
|
||||
func (e externalUserDo) Debug() IExternalUserDo {
|
||||
return e.withDO(e.DO.Debug())
|
||||
}
|
||||
|
||||
func (e externalUserDo) WithContext(ctx context.Context) IExternalUserDo {
|
||||
return e.withDO(e.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (e externalUserDo) ReadDB() IExternalUserDo {
|
||||
return e.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (e externalUserDo) WriteDB() IExternalUserDo {
|
||||
return e.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (e externalUserDo) Session(config *gorm.Session) IExternalUserDo {
|
||||
return e.withDO(e.DO.Session(config))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Clauses(conds ...clause.Expression) IExternalUserDo {
|
||||
return e.withDO(e.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Returning(value interface{}, columns ...string) IExternalUserDo {
|
||||
return e.withDO(e.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Not(conds ...gen.Condition) IExternalUserDo {
|
||||
return e.withDO(e.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Or(conds ...gen.Condition) IExternalUserDo {
|
||||
return e.withDO(e.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Select(conds ...field.Expr) IExternalUserDo {
|
||||
return e.withDO(e.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Where(conds ...gen.Condition) IExternalUserDo {
|
||||
return e.withDO(e.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Order(conds ...field.Expr) IExternalUserDo {
|
||||
return e.withDO(e.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Distinct(cols ...field.Expr) IExternalUserDo {
|
||||
return e.withDO(e.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Omit(cols ...field.Expr) IExternalUserDo {
|
||||
return e.withDO(e.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Join(table schema.Tabler, on ...field.Expr) IExternalUserDo {
|
||||
return e.withDO(e.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) LeftJoin(table schema.Tabler, on ...field.Expr) IExternalUserDo {
|
||||
return e.withDO(e.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) RightJoin(table schema.Tabler, on ...field.Expr) IExternalUserDo {
|
||||
return e.withDO(e.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Group(cols ...field.Expr) IExternalUserDo {
|
||||
return e.withDO(e.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Having(conds ...gen.Condition) IExternalUserDo {
|
||||
return e.withDO(e.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Limit(limit int) IExternalUserDo {
|
||||
return e.withDO(e.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Offset(offset int) IExternalUserDo {
|
||||
return e.withDO(e.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IExternalUserDo {
|
||||
return e.withDO(e.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Unscoped() IExternalUserDo {
|
||||
return e.withDO(e.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (e externalUserDo) Create(values ...*entity.ExternalUser) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return e.DO.Create(values)
|
||||
}
|
||||
|
||||
func (e externalUserDo) CreateInBatches(values []*entity.ExternalUser, batchSize int) error {
|
||||
return e.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 (e externalUserDo) Save(values ...*entity.ExternalUser) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return e.DO.Save(values)
|
||||
}
|
||||
|
||||
func (e externalUserDo) First() (*entity.ExternalUser, error) {
|
||||
if result, err := e.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.ExternalUser), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e externalUserDo) Take() (*entity.ExternalUser, error) {
|
||||
if result, err := e.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.ExternalUser), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e externalUserDo) Last() (*entity.ExternalUser, error) {
|
||||
if result, err := e.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.ExternalUser), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e externalUserDo) Find() ([]*entity.ExternalUser, error) {
|
||||
result, err := e.DO.Find()
|
||||
return result.([]*entity.ExternalUser), err
|
||||
}
|
||||
|
||||
func (e externalUserDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*entity.ExternalUser, err error) {
|
||||
buf := make([]*entity.ExternalUser, 0, batchSize)
|
||||
err = e.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 (e externalUserDo) FindInBatches(result *[]*entity.ExternalUser, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return e.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (e externalUserDo) Attrs(attrs ...field.AssignExpr) IExternalUserDo {
|
||||
return e.withDO(e.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Assign(attrs ...field.AssignExpr) IExternalUserDo {
|
||||
return e.withDO(e.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (e externalUserDo) Joins(fields ...field.RelationField) IExternalUserDo {
|
||||
for _, _f := range fields {
|
||||
e = *e.withDO(e.DO.Joins(_f))
|
||||
}
|
||||
return &e
|
||||
}
|
||||
|
||||
func (e externalUserDo) Preload(fields ...field.RelationField) IExternalUserDo {
|
||||
for _, _f := range fields {
|
||||
e = *e.withDO(e.DO.Preload(_f))
|
||||
}
|
||||
return &e
|
||||
}
|
||||
|
||||
func (e externalUserDo) FirstOrInit() (*entity.ExternalUser, error) {
|
||||
if result, err := e.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.ExternalUser), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e externalUserDo) FirstOrCreate() (*entity.ExternalUser, error) {
|
||||
if result, err := e.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.ExternalUser), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e externalUserDo) FindByPage(offset int, limit int) (result []*entity.ExternalUser, count int64, err error) {
|
||||
result, err = e.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 = e.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (e externalUserDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = e.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = e.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (e externalUserDo) Scan(result interface{}) (err error) {
|
||||
return e.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (e externalUserDo) Delete(models ...*entity.ExternalUser) (result gen.ResultInfo, err error) {
|
||||
return e.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (e *externalUserDo) withDO(do gen.Dao) *externalUserDo {
|
||||
e.DO = *do.(*gen.DO)
|
||||
return e
|
||||
}
|
@ -20,6 +20,7 @@ var (
|
||||
Application *application
|
||||
ApplicationToken *applicationToken
|
||||
Category *category
|
||||
ExternalUser *externalUser
|
||||
Post *post
|
||||
PostTag *postTag
|
||||
Tag *tag
|
||||
@ -33,6 +34,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
|
||||
Application = &Q.Application
|
||||
ApplicationToken = &Q.ApplicationToken
|
||||
Category = &Q.Category
|
||||
ExternalUser = &Q.ExternalUser
|
||||
Post = &Q.Post
|
||||
PostTag = &Q.PostTag
|
||||
Tag = &Q.Tag
|
||||
@ -47,6 +49,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
|
||||
Application: newApplication(db, opts...),
|
||||
ApplicationToken: newApplicationToken(db, opts...),
|
||||
Category: newCategory(db, opts...),
|
||||
ExternalUser: newExternalUser(db, opts...),
|
||||
Post: newPost(db, opts...),
|
||||
PostTag: newPostTag(db, opts...),
|
||||
Tag: newTag(db, opts...),
|
||||
@ -62,6 +65,7 @@ type Query struct {
|
||||
Application application
|
||||
ApplicationToken applicationToken
|
||||
Category category
|
||||
ExternalUser externalUser
|
||||
Post post
|
||||
PostTag postTag
|
||||
Tag tag
|
||||
@ -78,6 +82,7 @@ func (q *Query) clone(db *gorm.DB) *Query {
|
||||
Application: q.Application.clone(db),
|
||||
ApplicationToken: q.ApplicationToken.clone(db),
|
||||
Category: q.Category.clone(db),
|
||||
ExternalUser: q.ExternalUser.clone(db),
|
||||
Post: q.Post.clone(db),
|
||||
PostTag: q.PostTag.clone(db),
|
||||
Tag: q.Tag.clone(db),
|
||||
@ -101,6 +106,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query {
|
||||
Application: q.Application.replaceDB(db),
|
||||
ApplicationToken: q.ApplicationToken.replaceDB(db),
|
||||
Category: q.Category.replaceDB(db),
|
||||
ExternalUser: q.ExternalUser.replaceDB(db),
|
||||
Post: q.Post.replaceDB(db),
|
||||
PostTag: q.PostTag.replaceDB(db),
|
||||
Tag: q.Tag.replaceDB(db),
|
||||
@ -114,6 +120,7 @@ type queryCtx struct {
|
||||
Application IApplicationDo
|
||||
ApplicationToken IApplicationTokenDo
|
||||
Category ICategoryDo
|
||||
ExternalUser IExternalUserDo
|
||||
Post IPostDo
|
||||
PostTag IPostTagDo
|
||||
Tag ITagDo
|
||||
@ -127,6 +134,7 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx {
|
||||
Application: q.Application.WithContext(ctx),
|
||||
ApplicationToken: q.ApplicationToken.WithContext(ctx),
|
||||
Category: q.Category.WithContext(ctx),
|
||||
ExternalUser: q.ExternalUser.WithContext(ctx),
|
||||
Post: q.Post.WithContext(ctx),
|
||||
PostTag: q.PostTag.WithContext(ctx),
|
||||
Tag: q.Tag.WithContext(ctx),
|
||||
|
@ -27,9 +27,15 @@ func newUserLike(db *gorm.DB, opts ...gen.DOOption) userLike {
|
||||
|
||||
tableName := _userLike.userLikeDo.TableName()
|
||||
_userLike.ALL = field.NewAsterisk(tableName)
|
||||
_userLike.UserId = field.NewString(tableName, "user_id")
|
||||
_userLike.ExternalUserId = field.NewUint(tableName, "external_user_id")
|
||||
_userLike.PostId = field.NewUint(tableName, "post_id")
|
||||
_userLike.Type = field.NewString(tableName, "type")
|
||||
_userLike.ApplicationId = field.NewUint(tableName, "application_id")
|
||||
_userLike.Application = userLikeBelongsToApplication{
|
||||
db: db.Session(&gorm.Session{}),
|
||||
|
||||
RelationField: field.NewRelation("Application", "entity.Application"),
|
||||
}
|
||||
|
||||
_userLike.fillFieldMap()
|
||||
|
||||
@ -39,10 +45,12 @@ func newUserLike(db *gorm.DB, opts ...gen.DOOption) userLike {
|
||||
type userLike struct {
|
||||
userLikeDo
|
||||
|
||||
ALL field.Asterisk
|
||||
UserId field.String
|
||||
PostId field.Uint
|
||||
Type field.String
|
||||
ALL field.Asterisk
|
||||
ExternalUserId field.Uint
|
||||
PostId field.Uint
|
||||
Type field.String
|
||||
ApplicationId field.Uint
|
||||
Application userLikeBelongsToApplication
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
@ -59,9 +67,10 @@ func (u userLike) As(alias string) *userLike {
|
||||
|
||||
func (u *userLike) updateTableName(table string) *userLike {
|
||||
u.ALL = field.NewAsterisk(table)
|
||||
u.UserId = field.NewString(table, "user_id")
|
||||
u.ExternalUserId = field.NewUint(table, "external_user_id")
|
||||
u.PostId = field.NewUint(table, "post_id")
|
||||
u.Type = field.NewString(table, "type")
|
||||
u.ApplicationId = field.NewUint(table, "application_id")
|
||||
|
||||
u.fillFieldMap()
|
||||
|
||||
@ -78,10 +87,12 @@ func (u *userLike) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
}
|
||||
|
||||
func (u *userLike) fillFieldMap() {
|
||||
u.fieldMap = make(map[string]field.Expr, 3)
|
||||
u.fieldMap["user_id"] = u.UserId
|
||||
u.fieldMap = make(map[string]field.Expr, 5)
|
||||
u.fieldMap["external_user_id"] = u.ExternalUserId
|
||||
u.fieldMap["post_id"] = u.PostId
|
||||
u.fieldMap["type"] = u.Type
|
||||
u.fieldMap["application_id"] = u.ApplicationId
|
||||
|
||||
}
|
||||
|
||||
func (u userLike) clone(db *gorm.DB) userLike {
|
||||
@ -94,6 +105,77 @@ func (u userLike) replaceDB(db *gorm.DB) userLike {
|
||||
return u
|
||||
}
|
||||
|
||||
type userLikeBelongsToApplication struct {
|
||||
db *gorm.DB
|
||||
|
||||
field.RelationField
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplication) Where(conds ...field.Expr) *userLikeBelongsToApplication {
|
||||
if len(conds) == 0 {
|
||||
return &a
|
||||
}
|
||||
|
||||
exprs := make([]clause.Expression, 0, len(conds))
|
||||
for _, cond := range conds {
|
||||
exprs = append(exprs, cond.BeCond().(clause.Expression))
|
||||
}
|
||||
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplication) WithContext(ctx context.Context) *userLikeBelongsToApplication {
|
||||
a.db = a.db.WithContext(ctx)
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplication) Session(session *gorm.Session) *userLikeBelongsToApplication {
|
||||
a.db = a.db.Session(session)
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplication) Model(m *entity.UserLike) *userLikeBelongsToApplicationTx {
|
||||
return &userLikeBelongsToApplicationTx{a.db.Model(m).Association(a.Name())}
|
||||
}
|
||||
|
||||
type userLikeBelongsToApplicationTx struct{ tx *gorm.Association }
|
||||
|
||||
func (a userLikeBelongsToApplicationTx) Find() (result *entity.Application, err error) {
|
||||
return result, a.tx.Find(&result)
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplicationTx) Append(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Append(targetValues...)
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplicationTx) Replace(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Replace(targetValues...)
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplicationTx) Delete(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Delete(targetValues...)
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplicationTx) Clear() error {
|
||||
return a.tx.Clear()
|
||||
}
|
||||
|
||||
func (a userLikeBelongsToApplicationTx) Count() int64 {
|
||||
return a.tx.Count()
|
||||
}
|
||||
|
||||
type userLikeDo struct{ gen.DO }
|
||||
|
||||
type IUserLikeDo interface {
|
||||
|
@ -27,9 +27,10 @@ func newUserTagScore(db *gorm.DB, opts ...gen.DOOption) userTagScore {
|
||||
|
||||
tableName := _userTagScore.userTagScoreDo.TableName()
|
||||
_userTagScore.ALL = field.NewAsterisk(tableName)
|
||||
_userTagScore.UserId = field.NewString(tableName, "user_id")
|
||||
_userTagScore.ExternalUserId = field.NewUint(tableName, "external_user_id")
|
||||
_userTagScore.TagId = field.NewUint(tableName, "tag_id")
|
||||
_userTagScore.Score = field.NewInt(tableName, "score")
|
||||
_userTagScore.ApplicationId = field.NewUint(tableName, "application_id")
|
||||
_userTagScore.Tag = userTagScoreBelongsToTag{
|
||||
db: db.Session(&gorm.Session{}),
|
||||
|
||||
@ -41,6 +42,12 @@ func newUserTagScore(db *gorm.DB, opts ...gen.DOOption) userTagScore {
|
||||
},
|
||||
}
|
||||
|
||||
_userTagScore.Application = userTagScoreBelongsToApplication{
|
||||
db: db.Session(&gorm.Session{}),
|
||||
|
||||
RelationField: field.NewRelation("Application", "entity.Application"),
|
||||
}
|
||||
|
||||
_userTagScore.fillFieldMap()
|
||||
|
||||
return _userTagScore
|
||||
@ -49,11 +56,14 @@ func newUserTagScore(db *gorm.DB, opts ...gen.DOOption) userTagScore {
|
||||
type userTagScore struct {
|
||||
userTagScoreDo
|
||||
|
||||
ALL field.Asterisk
|
||||
UserId field.String
|
||||
TagId field.Uint
|
||||
Score field.Int
|
||||
Tag userTagScoreBelongsToTag
|
||||
ALL field.Asterisk
|
||||
ExternalUserId field.Uint
|
||||
TagId field.Uint
|
||||
Score field.Int
|
||||
ApplicationId field.Uint
|
||||
Tag userTagScoreBelongsToTag
|
||||
|
||||
Application userTagScoreBelongsToApplication
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
@ -70,9 +80,10 @@ func (u userTagScore) As(alias string) *userTagScore {
|
||||
|
||||
func (u *userTagScore) updateTableName(table string) *userTagScore {
|
||||
u.ALL = field.NewAsterisk(table)
|
||||
u.UserId = field.NewString(table, "user_id")
|
||||
u.ExternalUserId = field.NewUint(table, "external_user_id")
|
||||
u.TagId = field.NewUint(table, "tag_id")
|
||||
u.Score = field.NewInt(table, "score")
|
||||
u.ApplicationId = field.NewUint(table, "application_id")
|
||||
|
||||
u.fillFieldMap()
|
||||
|
||||
@ -89,10 +100,11 @@ func (u *userTagScore) GetFieldByName(fieldName string) (field.OrderExpr, bool)
|
||||
}
|
||||
|
||||
func (u *userTagScore) fillFieldMap() {
|
||||
u.fieldMap = make(map[string]field.Expr, 4)
|
||||
u.fieldMap["user_id"] = u.UserId
|
||||
u.fieldMap = make(map[string]field.Expr, 6)
|
||||
u.fieldMap["external_user_id"] = u.ExternalUserId
|
||||
u.fieldMap["tag_id"] = u.TagId
|
||||
u.fieldMap["score"] = u.Score
|
||||
u.fieldMap["application_id"] = u.ApplicationId
|
||||
|
||||
}
|
||||
|
||||
@ -181,6 +193,77 @@ func (a userTagScoreBelongsToTagTx) Count() int64 {
|
||||
return a.tx.Count()
|
||||
}
|
||||
|
||||
type userTagScoreBelongsToApplication struct {
|
||||
db *gorm.DB
|
||||
|
||||
field.RelationField
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplication) Where(conds ...field.Expr) *userTagScoreBelongsToApplication {
|
||||
if len(conds) == 0 {
|
||||
return &a
|
||||
}
|
||||
|
||||
exprs := make([]clause.Expression, 0, len(conds))
|
||||
for _, cond := range conds {
|
||||
exprs = append(exprs, cond.BeCond().(clause.Expression))
|
||||
}
|
||||
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplication) WithContext(ctx context.Context) *userTagScoreBelongsToApplication {
|
||||
a.db = a.db.WithContext(ctx)
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplication) Session(session *gorm.Session) *userTagScoreBelongsToApplication {
|
||||
a.db = a.db.Session(session)
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplication) Model(m *entity.UserTagScore) *userTagScoreBelongsToApplicationTx {
|
||||
return &userTagScoreBelongsToApplicationTx{a.db.Model(m).Association(a.Name())}
|
||||
}
|
||||
|
||||
type userTagScoreBelongsToApplicationTx struct{ tx *gorm.Association }
|
||||
|
||||
func (a userTagScoreBelongsToApplicationTx) Find() (result *entity.Application, err error) {
|
||||
return result, a.tx.Find(&result)
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplicationTx) Append(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Append(targetValues...)
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplicationTx) Replace(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Replace(targetValues...)
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplicationTx) Delete(values ...*entity.Application) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Delete(targetValues...)
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplicationTx) Clear() error {
|
||||
return a.tx.Clear()
|
||||
}
|
||||
|
||||
func (a userTagScoreBelongsToApplicationTx) Count() int64 {
|
||||
return a.tx.Count()
|
||||
}
|
||||
|
||||
type userTagScoreDo struct{ gen.DO }
|
||||
|
||||
type IUserTagScoreDo interface {
|
||||
|
@ -11,10 +11,27 @@ func (u *User) TableName() string {
|
||||
return "users"
|
||||
}
|
||||
|
||||
type ExternalUser struct {
|
||||
Model
|
||||
Id schema.EntityId `gorm:"primarykey" json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
ExternalId string `json:"external_id"`
|
||||
Summary string `json:"summary"`
|
||||
ApplicationId schema.EntityId `json:"application_id"`
|
||||
Application *Application
|
||||
}
|
||||
|
||||
func (u *ExternalUser) TableName() string {
|
||||
return "external_users"
|
||||
}
|
||||
|
||||
type UserLike struct {
|
||||
UserId schema.UserId `gorm:"primarykey" json:"user_id"`
|
||||
PostId schema.EntityId `gorm:"primarykey" json:"post_id"`
|
||||
Type schema.UserLikeType `json:"type"`
|
||||
ExternalUserId schema.EntityId `gorm:"primarykey" json:"external_user_id"`
|
||||
PostId schema.EntityId `gorm:"primarykey" json:"post_id"`
|
||||
Type schema.UserLikeType `json:"type"`
|
||||
Application *Application
|
||||
ApplicationId schema.EntityId `json:"application_id"`
|
||||
}
|
||||
|
||||
func (u *UserLike) TableName() string {
|
||||
@ -22,10 +39,12 @@ func (u *UserLike) TableName() string {
|
||||
}
|
||||
|
||||
type UserTagScore struct {
|
||||
UserId schema.UserId `gorm:"primarykey" json:"user_id"`
|
||||
TagId schema.EntityId `gorm:"primarykey" json:"tag_id"`
|
||||
Tag *Tag
|
||||
Score int `json:"score"`
|
||||
ExternalUserId schema.EntityId `gorm:"primarykey" json:"external_user_id"`
|
||||
TagId schema.EntityId `gorm:"primarykey" json:"tag_id"`
|
||||
Tag *Tag
|
||||
Score int `json:"score"`
|
||||
Application *Application
|
||||
ApplicationId schema.EntityId `json:"application_id"`
|
||||
}
|
||||
|
||||
func (u *UserTagScore) TableName() string {
|
||||
|
199
internal/handler/http/controller/application_v1/users.go
Normal file
199
internal/handler/http/controller/application_v1/users.go
Normal file
@ -0,0 +1,199 @@
|
||||
package application_v1
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"leafdev.top/Ecosystem/recommender/internal/base/logger"
|
||||
"leafdev.top/Ecosystem/recommender/internal/base/redis"
|
||||
"leafdev.top/Ecosystem/recommender/internal/handler/http/request"
|
||||
"leafdev.top/Ecosystem/recommender/internal/handler/http/response"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/application"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/auth"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/post"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/user"
|
||||
"leafdev.top/Ecosystem/recommender/pkg/consts"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const TaskProcessing = "user_likes"
|
||||
|
||||
var LockTTL = time.Minute * 10
|
||||
|
||||
type UserController struct {
|
||||
authService *auth.Service
|
||||
applicationService *application.Service
|
||||
userService *user.Service
|
||||
postService *post.Service
|
||||
logger *logger.Logger
|
||||
redis *redis.Redis
|
||||
}
|
||||
|
||||
func NewUserController(
|
||||
authService *auth.Service,
|
||||
applicationService *application.Service,
|
||||
userService *user.Service,
|
||||
postService *post.Service,
|
||||
logger *logger.Logger,
|
||||
redis *redis.Redis,
|
||||
|
||||
) *UserController {
|
||||
return &UserController{
|
||||
authService: authService,
|
||||
applicationService: applicationService,
|
||||
userService: userService,
|
||||
postService: postService,
|
||||
logger: logger,
|
||||
redis: redis,
|
||||
}
|
||||
}
|
||||
|
||||
// Like godoc
|
||||
// @Summary Like
|
||||
// @Description 将标签附加到用户名
|
||||
// @Tags application_api
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security ApiKeyAuth
|
||||
// @Param UserLikePost body request.UserLikePost true "UserLikePost"
|
||||
// @Success 200 {object} response.ResponseBody{data=entity.Category}
|
||||
// @Failure 400 {object} response.ResponseBody
|
||||
// @Router /applications/v1/users/_like [post]
|
||||
func (uc *UserController) Like(c *gin.Context) {
|
||||
app, err := uc.authService.GetApplication(c)
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
||||
return
|
||||
}
|
||||
|
||||
var userLikePostRequest = &request.UserLikePost{}
|
||||
|
||||
if err := c.ShouldBindJSON(userLikePostRequest); err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
||||
return
|
||||
}
|
||||
|
||||
externalUser, err := uc.userService.GetOrCreateExternalUser(c, userLikePostRequest.ExternalUserId, app)
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
||||
return
|
||||
}
|
||||
|
||||
// posts
|
||||
postEntity, err := uc.postService.GetPostById(c, userLikePostRequest.PostId)
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if postEntity.ApplicationId != app.Id {
|
||||
response.Ctx(c).Status(http.StatusNotFound).Send()
|
||||
return
|
||||
}
|
||||
|
||||
// 检测是否有
|
||||
var cacheKey = uc.redis.Prefix(TaskProcessing + ":" + userLikePostRequest.PostId.String())
|
||||
// if exists
|
||||
exists, err := uc.redis.Client.Exists(c, cacheKey).Result()
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if exists > 0 {
|
||||
response.Ctx(c).Status(http.StatusTooEarly).Error(consts.ErrAnotherOperationInProgress).Send()
|
||||
return
|
||||
}
|
||||
|
||||
_, err = uc.redis.Client.Set(c, cacheKey, userLikePostRequest.ExternalUserId, LockTTL).Result()
|
||||
|
||||
go func(prefix string) {
|
||||
err = uc.userService.LikePost(c, externalUser, app, postEntity)
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
||||
return
|
||||
}
|
||||
|
||||
_, err := uc.redis.Client.Del(c, prefix).Result()
|
||||
if err != nil {
|
||||
uc.logger.Sugar.Error(err)
|
||||
}
|
||||
}(cacheKey)
|
||||
|
||||
response.Ctx(c).Status(http.StatusNoContent).Send()
|
||||
return
|
||||
}
|
||||
|
||||
// Dislike godoc
|
||||
// @Summary Dislike
|
||||
// @Description 从用户的标签喜好中移除内容
|
||||
// @Tags application_api
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security ApiKeyAuth
|
||||
// @Param UserLikePost body request.UserLikePost true "UserLikePost"
|
||||
// @Success 200 {object} response.ResponseBody{data=entity.Category}
|
||||
// @Failure 400 {object} response.ResponseBody
|
||||
// @Router /applications/v1/users/_dislike [post]
|
||||
func (uc *UserController) Dislike(c *gin.Context) {
|
||||
app, err := uc.authService.GetApplication(c)
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
||||
return
|
||||
}
|
||||
|
||||
var userDislikePostRequest = &request.UserDislikePost{}
|
||||
|
||||
if err := c.ShouldBindJSON(userDislikePostRequest); err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusBadRequest).Send()
|
||||
return
|
||||
}
|
||||
|
||||
externalUser, err := uc.userService.GetOrCreateExternalUser(c, userDislikePostRequest.ExternalUserId, app)
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
||||
return
|
||||
}
|
||||
|
||||
// posts
|
||||
postEntity, err := uc.postService.GetPostById(c, userDislikePostRequest.PostId)
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if postEntity.ApplicationId != app.Id {
|
||||
response.Ctx(c).Status(http.StatusNotFound).Send()
|
||||
return
|
||||
}
|
||||
|
||||
// 检测是否有
|
||||
var cacheKey = uc.redis.Prefix(TaskProcessing + ":" + userDislikePostRequest.PostId.String())
|
||||
exists, err := uc.redis.Client.Exists(c, cacheKey).Result()
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if exists > 0 {
|
||||
response.Ctx(c).Status(http.StatusTooEarly).Error(consts.ErrAnotherOperationInProgress).Send()
|
||||
return
|
||||
}
|
||||
|
||||
_, err = uc.redis.Client.Set(c, cacheKey, userDislikePostRequest.ExternalUserId, LockTTL).Result()
|
||||
|
||||
go func(prefix string) {
|
||||
err = uc.userService.DislikePost(c, externalUser, app, postEntity)
|
||||
if err != nil {
|
||||
response.Ctx(c).Error(err).Status(http.StatusInternalServerError).Send()
|
||||
return
|
||||
}
|
||||
|
||||
_, err := uc.redis.Client.Del(c, prefix).Result()
|
||||
if err != nil {
|
||||
uc.logger.Sugar.Error(err)
|
||||
}
|
||||
}(cacheKey)
|
||||
|
||||
response.Ctx(c).Status(http.StatusNoContent).Send()
|
||||
return
|
||||
}
|
@ -17,6 +17,7 @@ var ProviderSet = wire.NewSet(
|
||||
application_v1.NewApplicationController,
|
||||
application_v1.NewPostController,
|
||||
application_v1.NewCategoryController,
|
||||
application_v1.NewUserController,
|
||||
NewHandler,
|
||||
)
|
||||
|
||||
@ -46,6 +47,7 @@ type Handlers struct {
|
||||
ApplicationApi *application_v1.ApplicationController
|
||||
ApplicationPostApi *application_v1.PostController
|
||||
ApplicationCategoryApi *application_v1.CategoryController
|
||||
ApplicationUserApi *application_v1.UserController
|
||||
}
|
||||
|
||||
func NewHandler(
|
||||
@ -53,11 +55,14 @@ func NewHandler(
|
||||
applicationApiController *application_v1.ApplicationController,
|
||||
applicationPostApi *application_v1.PostController,
|
||||
applicationCategoryApi *application_v1.CategoryController,
|
||||
applicationUserApi *application_v1.UserController,
|
||||
|
||||
) *Handlers {
|
||||
return &Handlers{
|
||||
ApplicationController: applicationController,
|
||||
ApplicationApi: applicationApiController,
|
||||
ApplicationPostApi: applicationPostApi,
|
||||
ApplicationCategoryApi: applicationCategoryApi,
|
||||
ApplicationUserApi: applicationUserApi,
|
||||
}
|
||||
}
|
||||
|
@ -9,3 +9,13 @@ type ApplicationId struct {
|
||||
type ApplicationCreateRequest struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type UserLikePost struct {
|
||||
PostId schema.EntityId `json:"post_id" uri:"post_id"`
|
||||
ExternalUserId string `json:"external_user_id"`
|
||||
}
|
||||
|
||||
type UserDislikePost struct {
|
||||
PostId schema.EntityId `json:"post_id" uri:"post_id"`
|
||||
ExternalUserId string `json:"external_user_id"`
|
||||
}
|
||||
|
@ -23,6 +23,22 @@ CREATE TABLE `application_tokens`
|
||||
foreign key (application_id) references applications (id) on delete cascade
|
||||
);
|
||||
|
||||
CREATE TABLE `external_users`
|
||||
(
|
||||
id serial NOT NULL,
|
||||
name varchar(255) DEFAULT NULL,
|
||||
email varchar(255) DEFAULT NULL,
|
||||
external_id varchar(255) NOT NULL,
|
||||
summary varchar(255) DEFAULT NULL,
|
||||
application_id bigint unsigned NOT NULL,
|
||||
created_at timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
primary key (id),
|
||||
index (external_id),
|
||||
foreign key (application_id) references applications (id) on delete cascade
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE `categories`
|
||||
(
|
||||
id serial NOT NULL,
|
||||
@ -88,27 +104,29 @@ CREATE TABLE `post_tags`
|
||||
-- user tag scores
|
||||
CREATE TABLE `user_tag_scores`
|
||||
(
|
||||
user_id varchar(255) NOT NULL,
|
||||
tag_id bigint unsigned NOT NULL,
|
||||
score int NOT NULL,
|
||||
application_id bigint unsigned NOT NULL,
|
||||
primary key (user_id, tag_id),
|
||||
external_user_id bigint unsigned NOT NULL,
|
||||
tag_id bigint unsigned NOT NULL,
|
||||
score int NOT NULL,
|
||||
application_id bigint unsigned NOT NULL,
|
||||
primary key (external_user_id, tag_id),
|
||||
index (score, application_id),
|
||||
foreign key (tag_id) references tags (id) on delete cascade,
|
||||
foreign key (application_id) references applications (id) on delete cascade
|
||||
foreign key (application_id) references applications (id) on delete cascade,
|
||||
foreign key (external_user_id) references external_users (id) on delete cascade
|
||||
);
|
||||
|
||||
-- user likes
|
||||
CREATE TABLE `user_likes`
|
||||
(
|
||||
user_id varchar(255) NOT NULL,
|
||||
post_id bigint unsigned NOT NULL,
|
||||
type enum ('like', 'dislike') NOT NULL,
|
||||
application_id bigint unsigned NOT NULL,
|
||||
primary key (user_id, post_id),
|
||||
external_user_id bigint unsigned NOT NULL,
|
||||
post_id bigint unsigned NOT NULL,
|
||||
type enum ('like', 'dislike') NOT NULL,
|
||||
application_id bigint unsigned NOT NULL,
|
||||
primary key (external_user_id, post_id),
|
||||
index (type, application_id),
|
||||
foreign key (post_id) references posts (id) on delete cascade,
|
||||
foreign key (application_id) references applications (id) on delete cascade
|
||||
foreign key (application_id) references applications (id) on delete cascade,
|
||||
foreign key (external_user_id) references external_users (id) on delete cascade
|
||||
);
|
||||
|
||||
|
||||
@ -122,3 +140,4 @@ DROP TABLE IF EXISTS `tags`;
|
||||
DROP TABLE IF EXISTS `categories`;
|
||||
DROP TABLE IF EXISTS `application_tokens`;
|
||||
DROP TABLE IF EXISTS `applications`;
|
||||
DROP TABLE IF EXISTS `external_users`;
|
||||
|
@ -45,4 +45,7 @@ func (a *Api) InitApplicationApi(r *gin.RouterGroup) {
|
||||
r.POST("/categories", a.h.ApplicationCategoryApi.Save)
|
||||
r.GET("/categories/:category_id", a.h.ApplicationCategoryApi.Get)
|
||||
r.DELETE("/categories/:category_id", a.h.ApplicationCategoryApi.Delete)
|
||||
|
||||
r.POST("/users/_like", a.h.ApplicationUserApi.Like)
|
||||
r.POST("/users/_dislike", a.h.ApplicationUserApi.Dislike)
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ type User struct {
|
||||
}
|
||||
|
||||
type UserId string
|
||||
type ExternalUserId uint
|
||||
|
||||
func (u UserId) String() string {
|
||||
return string(u)
|
||||
|
@ -51,3 +51,20 @@ func (s *Service) DeletePost(c context.Context, post *entity.Post) error {
|
||||
func (s *Service) GetPostById(c context.Context, postId schema.EntityId) (*entity.Post, error) {
|
||||
return s.dao.WithContext(c).Post.Preload(s.dao.Post.Application).Where(s.dao.Post.Id.Eq(postId.Uint())).First()
|
||||
}
|
||||
|
||||
func (s *Service) GetPostTags(c context.Context, postEntity *entity.Post) ([]*entity.Tag, error) {
|
||||
postTags, err := s.dao.WithContext(c).PostTag.Preload(s.dao.PostTag.Tag).
|
||||
Where(s.dao.PostTag.PostId.Eq(postEntity.Id.Uint())).Find()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tags []*entity.Tag
|
||||
|
||||
for _, postTag := range postTags {
|
||||
tags = append(tags, postTag.Tag)
|
||||
}
|
||||
|
||||
return tags, err
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ func (s *Service) GetTag(c context.Context, name string, applicationEntity *enti
|
||||
FirstOrCreate()
|
||||
}
|
||||
|
||||
// Has Bind
|
||||
func (s *Service) HasBindTag(c context.Context, post *entity.Post, tagName string) (bool, error) {
|
||||
tag, err := s.GetTag(c, tagName, post.Application)
|
||||
if err != nil {
|
||||
@ -46,12 +45,15 @@ func (s *Service) HasBindTag(c context.Context, post *entity.Post, tagName strin
|
||||
|
||||
func (s *Service) BindTag(c context.Context, post *entity.Post, tagName string) error {
|
||||
tag, err := s.GetTag(c, tagName, post.Application)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bind, err := s.HasBindTag(c, post, tag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !bind {
|
||||
err = s.dao.WithContext(c).PostTag.Create(&entity.PostTag{
|
||||
PostId: &post.Id,
|
||||
@ -59,7 +61,7 @@ func (s *Service) BindTag(c context.Context, post *entity.Post, tagName string)
|
||||
})
|
||||
}
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) MarkAsProcessed(c context.Context, post *entity.Post) error {
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/jwks"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/post"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/stream"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/user"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
@ -20,6 +21,7 @@ type Service struct {
|
||||
Application *application.Service
|
||||
Post *post.Service
|
||||
Category *category.Service
|
||||
User *user.Service
|
||||
}
|
||||
|
||||
var Provider = wire.NewSet(
|
||||
@ -29,6 +31,7 @@ var Provider = wire.NewSet(
|
||||
application.NewService,
|
||||
post.NewService,
|
||||
category.NewService,
|
||||
user.NewService,
|
||||
NewService,
|
||||
)
|
||||
|
||||
@ -40,6 +43,7 @@ func NewService(
|
||||
application *application.Service,
|
||||
post *post.Service,
|
||||
category *category.Service,
|
||||
user *user.Service,
|
||||
) *Service {
|
||||
return &Service{
|
||||
logger,
|
||||
@ -49,5 +53,6 @@ func NewService(
|
||||
application,
|
||||
post,
|
||||
category,
|
||||
user,
|
||||
}
|
||||
}
|
||||
|
35
internal/service/user/external.go
Normal file
35
internal/service/user/external.go
Normal file
@ -0,0 +1,35 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"leafdev.top/Ecosystem/recommender/internal/entity"
|
||||
)
|
||||
|
||||
func (s *Service) GetOrCreateExternalUser(c context.Context, externalUserId string, applicationEntity *entity.Application) (*entity.ExternalUser, error) {
|
||||
//Where(s.dao.UserTagScore.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
count, err := s.dao.WithContext(c).ExternalUser.
|
||||
Where(s.dao.ExternalUser.ApplicationId.Eq(applicationEntity.Id.Uint())).
|
||||
Where(s.dao.ExternalUser.ExternalId.Eq(externalUserId)).Count()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
eu, err := s.dao.WithContext(c).ExternalUser.
|
||||
Where(s.dao.ExternalUser.ApplicationId.Eq(applicationEntity.Id.Uint())).
|
||||
Where(s.dao.ExternalUser.ExternalId.Eq(externalUserId)).First()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return eu, nil
|
||||
}
|
||||
|
||||
eu := &entity.ExternalUser{
|
||||
ApplicationId: applicationEntity.Id,
|
||||
ExternalId: externalUserId,
|
||||
}
|
||||
|
||||
err = s.dao.WithContext(c).ExternalUser.Create(eu)
|
||||
|
||||
return eu, err
|
||||
}
|
148
internal/service/user/posts.go
Normal file
148
internal/service/user/posts.go
Normal file
@ -0,0 +1,148 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"leafdev.top/Ecosystem/recommender/internal/entity"
|
||||
"leafdev.top/Ecosystem/recommender/internal/schema"
|
||||
"time"
|
||||
)
|
||||
|
||||
const TaskProcessing = "user_likes"
|
||||
|
||||
var LockTTL = time.Minute * 10
|
||||
|
||||
func (s *Service) HasLiked(c context.Context, externalUserEntity *entity.ExternalUser, applicationEntity *entity.Application, postEntity *entity.Post) (bool, error) {
|
||||
count, err := s.dao.WithContext(c).UserLike.Where(s.dao.UserLike.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
Where(s.dao.UserLike.PostId.Eq(postEntity.Id.Uint())).
|
||||
Where(s.dao.UserLike.ApplicationId.Eq(applicationEntity.Id.Uint())).Count()
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateLike(c context.Context, externalUserEntity *entity.ExternalUser, applicationEntity *entity.Application, postEntity *entity.Post, likeType schema.UserLikeType) error {
|
||||
count, err := s.dao.WithContext(c).UserLike.Where(s.dao.UserLike.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
Where(s.dao.UserLike.PostId.Eq(postEntity.Id.Uint())).
|
||||
Where(s.dao.UserLike.ApplicationId.Eq(applicationEntity.Id.Uint())).Count()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
// update
|
||||
_, err = s.dao.WithContext(c).UserLike.Where(s.dao.UserLike.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
Where(s.dao.UserLike.PostId.Eq(postEntity.Id.Uint())).
|
||||
Where(s.dao.UserLike.ApplicationId.Eq(applicationEntity.Id.Uint())).
|
||||
Update(s.dao.UserLike.Type, likeType)
|
||||
return err
|
||||
}
|
||||
|
||||
var userLike = &entity.UserLike{
|
||||
ApplicationId: applicationEntity.Id,
|
||||
ExternalUserId: externalUserEntity.Id,
|
||||
PostId: postEntity.Id,
|
||||
Type: likeType,
|
||||
}
|
||||
|
||||
err = s.dao.WithContext(c).UserLike.Create(userLike)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Service) LikePost(c context.Context, externalUserEntity *entity.ExternalUser, applicationEntity *entity.Application, postEntity *entity.Post) error {
|
||||
//// 检测是否有
|
||||
//var cacheKey = s.redis.Prefix(TaskProcessing)
|
||||
//lock, err := s.redis.Locker.Obtain(c, cacheKey, LockTTL, nil)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
|
||||
//defer func(lock *redislock.Lock, ctx context.Context) {
|
||||
// err := lock.Release(ctx)
|
||||
// if err != nil {
|
||||
// s.logger.Sugar.Error(err)
|
||||
// }
|
||||
//}(lock, c)
|
||||
|
||||
// get tags
|
||||
postTags, err := s.postService.GetPostTags(c, postEntity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hasLike, err := s.HasLiked(c, externalUserEntity, applicationEntity, postEntity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if hasLike {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = s.UpdateLike(c, externalUserEntity, applicationEntity, postEntity, schema.UserLikeTypeLike)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.BindTags(context.Background(), externalUserEntity, applicationEntity, postTags)
|
||||
if err != nil {
|
||||
s.logger.Sugar.Error(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) DislikePost(c context.Context, externalUserEntity *entity.ExternalUser, applicationEntity *entity.Application, postEntity *entity.Post) error {
|
||||
// 检测是否有
|
||||
//var cacheKey = s.redis.Prefix(TaskProcessing)
|
||||
//lock, err := s.redis.Locker.Obtain(c, cacheKey, LockTTL, nil)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//
|
||||
//defer func(lock *redislock.Lock, ctx context.Context) {
|
||||
// err := lock.Release(ctx)
|
||||
// if err != nil {
|
||||
// s.logger.Sugar.Error(err)
|
||||
// }
|
||||
//}(lock, c)
|
||||
|
||||
// get tags
|
||||
postTags, err := s.postService.GetPostTags(c, postEntity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hasLike, err := s.HasLiked(c, externalUserEntity, applicationEntity, postEntity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !hasLike {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = s.UpdateLike(c, externalUserEntity, applicationEntity, postEntity, schema.UserLikeTypeDislike)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = s.dao.WithContext(c).UserLike.Where(s.dao.UserLike.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
Where(s.dao.UserLike.PostId.Eq(postEntity.Id.Uint())).
|
||||
Where(s.dao.UserLike.ApplicationId.Eq(applicationEntity.Id.Uint())).Count()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.RemoveTags(context.Background(), externalUserEntity, applicationEntity, postTags)
|
||||
if err != nil {
|
||||
s.logger.Sugar.Error(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
25
internal/service/user/provider.go
Normal file
25
internal/service/user/provider.go
Normal file
@ -0,0 +1,25 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"leafdev.top/Ecosystem/recommender/internal/base/logger"
|
||||
"leafdev.top/Ecosystem/recommender/internal/dao"
|
||||
"leafdev.top/Ecosystem/recommender/internal/service/post"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
dao *dao.Query
|
||||
postService *post.Service
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
func NewService(
|
||||
dao *dao.Query,
|
||||
postService *post.Service,
|
||||
logger *logger.Logger,
|
||||
) *Service {
|
||||
return &Service{
|
||||
dao: dao,
|
||||
postService: postService,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
114
internal/service/user/tags.go
Normal file
114
internal/service/user/tags.go
Normal file
@ -0,0 +1,114 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"leafdev.top/Ecosystem/recommender/internal/entity"
|
||||
)
|
||||
|
||||
func (s *Service) HasBindTag(c context.Context, externalUserEntity *entity.ExternalUser, applicationEntity *entity.Application, tagEntity *entity.Tag) (bool, error) {
|
||||
count, err := s.dao.WithContext(c).UserTagScore.
|
||||
Where(s.dao.UserTagScore.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
Where(s.dao.UserTagScore.TagId.Eq(tagEntity.Id.Uint())).
|
||||
Where(s.dao.UserTagScore.ApplicationId.Eq(applicationEntity.Id.Uint())).Count()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (s *Service) BindTags(c context.Context, externalUserEntity *entity.ExternalUser, applicationEntity *entity.Application, tags []*entity.Tag) error {
|
||||
// 检测用户是否绑定 Tag,如果绑定则更新,否则创建
|
||||
for _, tag := range tags {
|
||||
var uts *entity.UserTagScore
|
||||
|
||||
hasBind, err := s.HasBindTag(c, externalUserEntity, applicationEntity, tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if hasBind {
|
||||
// score + 1
|
||||
uts, err = s.dao.WithContext(c).UserTagScore.
|
||||
Where(s.dao.UserTagScore.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
Where(s.dao.UserTagScore.TagId.Eq(tag.Id.Uint())).
|
||||
Where(s.dao.UserTagScore.ApplicationId.Eq(applicationEntity.Id.Uint())).First()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uts.Score += 1
|
||||
|
||||
err = s.dao.WithContext(c).UserTagScore.Save(uts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
uts = &entity.UserTagScore{
|
||||
ApplicationId: applicationEntity.Id,
|
||||
TagId: tag.Id,
|
||||
ExternalUserId: externalUserEntity.Id,
|
||||
Score: 1,
|
||||
}
|
||||
|
||||
err = s.dao.WithContext(c).UserTagScore.Create(uts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) RemoveTags(c context.Context, externalUserEntity *entity.ExternalUser, applicationEntity *entity.Application, tags []*entity.Tag) error {
|
||||
for _, tag := range tags {
|
||||
var uts *entity.UserTagScore
|
||||
|
||||
hasBind, err := s.HasBindTag(c, externalUserEntity, applicationEntity, tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if hasBind {
|
||||
// score - 1
|
||||
uts, err = s.dao.WithContext(c).UserTagScore.
|
||||
Where(s.dao.UserTagScore.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
Where(s.dao.UserTagScore.TagId.Eq(tag.Id.Uint())).
|
||||
Where(s.dao.UserTagScore.ApplicationId.Eq(applicationEntity.Id.Uint())).First()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//if uts.Score-1 < 0 {
|
||||
// continue
|
||||
//}
|
||||
|
||||
uts.Score -= 1
|
||||
|
||||
_, err = s.dao.WithContext(c).UserTagScore.
|
||||
Where(s.dao.UserTagScore.ExternalUserId.Eq(externalUserEntity.Id.Uint())).
|
||||
Where(s.dao.UserTagScore.TagId.Eq(tag.Id.Uint())).
|
||||
Where(s.dao.UserTagScore.ApplicationId.Eq(applicationEntity.Id.Uint())).Update(s.dao.UserTagScore.Score, uts.Score)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
uts = &entity.UserTagScore{
|
||||
ApplicationId: applicationEntity.Id,
|
||||
TagId: tag.Id,
|
||||
ExternalUserId: externalUserEntity.Id,
|
||||
Score: -1,
|
||||
}
|
||||
|
||||
err = s.dao.WithContext(c).UserTagScore.Create(uts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
7
pkg/consts/posts.go
Normal file
7
pkg/consts/posts.go
Normal file
@ -0,0 +1,7 @@
|
||||
package consts
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrAnotherOperationInProgress = errors.New("another operation in progress")
|
||||
)
|
Loading…
Reference in New Issue
Block a user