lifedebugger commited on
Commit
e8167be
Β·
1 Parent(s): 17ec311

Deploy files from GitHub repository

Browse files
This view is limited to 50 files because it contains too many changes. Β  See raw diff
Files changed (50) hide show
  1. .github/workflows/main.yml +35 -0
  2. space/.dockerignore +11 -0
  3. space/Dockerfile.hf +37 -0
  4. space/Dockerfile.runpod +66 -0
  5. space/requirements.txt +0 -0
  6. space/scripts/docker_push.ps1 +17 -0
  7. space/space/api/banking-crud/.env.example +9 -0
  8. space/space/api/banking-crud/.gitignore +1 -0
  9. space/space/api/banking-crud/config/config.go +1 -0
  10. space/space/api/banking-crud/config/database_config.go +45 -0
  11. space/space/api/banking-crud/config/env_config.go +86 -0
  12. space/space/api/banking-crud/controller/account_controller.go +51 -0
  13. space/space/api/banking-crud/controller/controller.go +22 -0
  14. space/space/api/banking-crud/go.mod +46 -0
  15. space/space/api/banking-crud/go.sum +146 -0
  16. space/space/api/banking-crud/logs/error_log.txt +0 -0
  17. space/space/api/banking-crud/logs/security_log.txt +0 -0
  18. space/space/api/banking-crud/main.go +11 -0
  19. space/space/api/banking-crud/models/dto/account_dto.go +24 -0
  20. space/space/api/banking-crud/models/dto/http_response_dto.go +13 -0
  21. space/space/api/banking-crud/models/dto/jwt_dto.go +15 -0
  22. space/space/api/banking-crud/models/entity/entity.go +22 -0
  23. space/space/api/banking-crud/models/error/error_model.go +17 -0
  24. space/space/api/banking-crud/provider/config_provider.go +34 -0
  25. space/space/api/banking-crud/provider/controller_provider.go +24 -0
  26. space/space/api/banking-crud/provider/provider.go +59 -0
  27. space/space/api/banking-crud/provider/repositories_provider.go +26 -0
  28. space/space/api/banking-crud/provider/services_provider.go +24 -0
  29. space/space/api/banking-crud/repositories/account_repository.go +89 -0
  30. space/space/api/banking-crud/repositories/repository.go +1 -0
  31. space/space/api/banking-crud/router/account_router.go +17 -0
  32. space/space/api/banking-crud/router/router.go +11 -0
  33. space/space/api/banking-crud/services/account_service.go +83 -0
  34. space/space/api/banking-crud/services/jwt_service.go +61 -0
  35. space/space/api/banking-crud/services/service.go +24 -0
  36. space/space/api/banking-crud/utils/logger_util.go +31 -0
  37. space/space/api/banking-crud/utils/response_util.go +79 -0
  38. space/space/space/data/prompt_template/responder_banking.txt +2 -1
  39. space/space/space/space/space/data/prompt_template/api_banking.txt +120 -0
  40. space/space/space/space/space/data/prompt_template/expert_router.txt +10 -0
  41. space/space/space/space/space/data/prompt_template/responder_banking.txt +16 -0
  42. space/space/space/space/space/main.py +37 -17
  43. space/space/space/space/space/space/space/README.md +5 -6
  44. space/space/space/space/space/space/space/space/space/Dockerfile +17 -29
  45. space/space/space/space/space/space/space/space/space/space/space/space/space/README.md +0 -18
  46. space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/README.md +108 -18
  47. space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/data/prompt_template/customer_service.txt +10 -10
  48. space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/main.py +11 -2
  49. space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/README.md +0 -2
  50. space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/README.md +1 -1
.github/workflows/main.yml ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Build and Push Docker Image
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ docker:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - name: Checkout source code
15
+ uses: actions/checkout@v4
16
+
17
+ - name: Log in to Docker Hub
18
+ uses: docker/login-action@v3
19
+ with:
20
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
21
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
22
+
23
+ - name: Set up Docker Buildx
24
+ uses: docker/setup-buildx-action@v3
25
+
26
+ - name: Build and push Docker image
27
+ uses: docker/build-push-action@v5
28
+ with:
29
+ push: true
30
+ context: .
31
+ file: ./Dockerfile.runpod
32
+ platforms: linux/amd64,linux/arm64
33
+ tags: |
34
+ ${{ secrets.DOCKERHUB_USERNAME }}//runpod-rag-backend:v1.0.1
35
+ ${{ secrets.DOCKERHUB_USERNAME }}//runpod-rag-backend:${{ github.sha }}
space/.dockerignore ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ venv/
3
+ .venv/
4
+ venv/
5
+ .vscode/
6
+ __pycache__/
7
+ my_vectorstore/
8
+ FlagEmbedding/
9
+ vectorstore/
10
+ documents/
11
+ .cache/
space/Dockerfile.hf ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.13
3
+
4
+ RUN useradd -m -u 1001 appuser
5
+
6
+ WORKDIR /rag_be
7
+
8
+ ENV HF_HOME=/tmp/.cache/huggingface
9
+ ENV TRANSFORMERS_CACHE=/tmp/.cache/transformers
10
+ ENV TORCH_HOME=/tmp/.cache/torch
11
+ ENV XDG_CACHE_HOME=/tmp/.cache
12
+ ENV TMPDIR=/tmp
13
+ ENV WHISPER_CACHE_DIR=/tmp/.cache/whisper
14
+
15
+ COPY requirements.txt ./
16
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
17
+
18
+ COPY --chown=appuser:appuser . /rag_be
19
+
20
+ RUN mkdir -p /tmp/.cache \
21
+ /tmp/.cache/whisper \
22
+ /tmp/.cache/huggingface \
23
+ /tmp/.cache/transformers \
24
+ /tmp/.cache/torch \
25
+ /rag_be/vectorstore \
26
+ /rag_be/app/vectorstore \
27
+ /rag_be/documents && \
28
+ chmod -R 777 /tmp/.cache /rag_be/app /rag_be/vectorstore /rag_be/documents
29
+
30
+
31
+ RUN apt-get update && apt-get install -y ffmpeg && apt-get clean
32
+
33
+ USER appuser
34
+
35
+ EXPOSE 8000
36
+
37
+ CMD ["python", "main.py --mode rtc-ui --port 7860"]
space/Dockerfile.runpod ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile untuk RunPod Deployment
2
+ FROM python:3.13-slim
3
+
4
+ # Set labels untuk RunPod
5
+ LABEL maintainer="abdan.hafidz@gmail.com"
6
+ LABEL version="1.0"
7
+ LABEL description="A.I Sakura Backend"
8
+
9
+ # Install system dependencies
10
+ RUN apt-get update && \
11
+ apt-get install -y \
12
+ ffmpeg \
13
+ curl \
14
+ wget \
15
+ git \
16
+ && apt-get clean \
17
+ && rm -rf /var/lib/apt/lists/*
18
+
19
+ # Create app user
20
+ RUN useradd -m -u 1001 appuser
21
+
22
+ # Set working directory
23
+ WORKDIR /rag_be
24
+
25
+ # Environment variables untuk caching
26
+ ENV HF_HOME=/src/.cache/huggingface
27
+ ENV TRANSFORMERS_CACHE=/src/.cache/transformers
28
+ ENV TORCH_HOME=/src/.cache/torch
29
+ ENV XDG_CACHE_HOME=/src/.cache
30
+ ENV TMPDIR=/tmp
31
+ ENV WHISPER_CACHE_DIR=/src/.cache/whisper
32
+ ENV PYTHONUNBUFFERED=1
33
+ ENV PYTHONDONTWRITEBYTECODE=1
34
+
35
+ # Copy requirements dan install dependencies
36
+ COPY requirements.txt ./
37
+ RUN pip install --no-cache-dir --upgrade pip && \
38
+ pip install --no-cache-dir --upgrade -r requirements.txt
39
+
40
+ # Copy application code
41
+ COPY --chown=appuser:appuser . /rag_be
42
+
43
+ # Create necessary directories dengan permissions yang tepat
44
+ RUN mkdir -p \
45
+ /src/.cache/whisper \
46
+ /src/.cache/huggingface \
47
+ /src/.cache/transformers \
48
+ /src/.cache/torch \
49
+ /rag_be/data/vectorstore \
50
+ /rag_be/data/documents \
51
+ /rag_be/logs && \
52
+ chown -R appuser:appuser /src /rag_be && \
53
+ chmod -R 755 /src /rag_be
54
+
55
+ # Health check untuk RunPod
56
+ HEALTHCHECK --interval=30s --timeout=30s --start-period=60s --retries=3 \
57
+ CMD curl -f http://localhost:7860/health || exit 1
58
+
59
+ # Switch to non-root user
60
+ USER appuser
61
+
62
+ # Expose ports
63
+ EXPOSE 7860
64
+
65
+ # Default command - dapat di-override oleh RunPod
66
+ CMD ["python", "main.py", "--mode", "rtc-ui", "--port", "7860"]
space/requirements.txt CHANGED
Binary files a/space/requirements.txt and b/space/requirements.txt differ
 
space/scripts/docker_push.ps1 ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ $ImageName = "abdanhafidz/runpod-rag-backend"
3
+ $Tag = "v1.0.1"
4
+ $Dockerfile = "Dockerfile.runpod"
5
+
6
+ Write-Output "Building Image..."
7
+ docker build --platform linux/amd64 -f $Dockerfile -t "${ImageName}:${Tag}" .
8
+
9
+ Write-Output "Build Finished"
10
+
11
+ Write-Output "Test image locally..."
12
+ docker run -p 7860:7860 "${ImageName}:${Tag}"
13
+
14
+ Write-Output "Push image ke Docker Hub..."
15
+ docker push "${ImageName}:${Tag}"
16
+
17
+ Write-Output "πŸŽ‰ Selesai!"
space/space/api/banking-crud/.env.example ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ DB_HOST =
2
+ DB_USER =
3
+ DB_PASSWORD =
4
+ DB_PORT =
5
+ DB_NAME =
6
+ SALT =
7
+ HOST_ADDRESS =
8
+ HOST_PORT =
9
+ LOG_PATH = logs
space/space/api/banking-crud/.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ /.env
space/space/api/banking-crud/config/config.go ADDED
@@ -0,0 +1 @@
 
 
1
+ package config
space/space/api/banking-crud/config/database_config.go ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package config
2
+
3
+ import (
4
+ "fmt"
5
+ "log"
6
+
7
+ "gorm.io/driver/postgres"
8
+ "gorm.io/gorm"
9
+ "gorm.io/gorm/logger"
10
+ )
11
+
12
+ type DatabaseConfig interface {
13
+ AutoMigrateAll(entities ...interface{}) error
14
+ GetInstance() *gorm.DB
15
+ }
16
+ type databaseConfig struct {
17
+ db *gorm.DB
18
+ }
19
+
20
+ func NewDatabaseConfig(DB_HOST string, DB_USER string, DB_PASSWORD string, DB_NAME string, DB_PORT string) DatabaseConfig {
21
+ dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Jakarta", DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT)
22
+ db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{TranslateError: true})
23
+
24
+ if err != nil {
25
+ log.Fatal("Failed to connect to database:", err)
26
+ }
27
+
28
+ return &databaseConfig{db: db}
29
+ }
30
+
31
+ func (cfg *databaseConfig) AutoMigrateAll(entities ...interface{}) error {
32
+
33
+ cfg.db.Logger.LogMode(logger.Info)
34
+
35
+ err := cfg.db.AutoMigrate(
36
+ entities...,
37
+ )
38
+
39
+ return err
40
+
41
+ }
42
+
43
+ func (cfg *databaseConfig) GetInstance() *gorm.DB {
44
+ return cfg.db
45
+ }
space/space/api/banking-crud/config/env_config.go ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package config
2
+
3
+ import (
4
+ "os"
5
+ "strconv"
6
+
7
+ "github.com/joho/godotenv"
8
+ )
9
+
10
+ type EnvConfig interface {
11
+ GetTCPAddress() string
12
+ GetLogPath() string
13
+ GetHostAddress() string
14
+ GetHostPort() string
15
+ GetEmailVerificationDuration() int
16
+ GetDatabaseHost() string
17
+ GetDatabasePort() string
18
+ GetDatabaseUser() string
19
+ GetDatabasePassword() string
20
+ GetDatabaseName() string
21
+ GetSalt() string
22
+ }
23
+
24
+ type envConfig struct {
25
+ timezone string
26
+ }
27
+
28
+ func NewEnvConfig(timezone string) EnvConfig {
29
+ godotenv.Load()
30
+ os.Setenv("TZ", timezone)
31
+ return &envConfig{
32
+ timezone: timezone,
33
+ }
34
+ }
35
+
36
+ func (e *envConfig) GetTCPAddress() string {
37
+ return os.Getenv("HOST_ADDRESS") + ":" + os.Getenv("HOST_PORT")
38
+ }
39
+
40
+ func (e *envConfig) GetLogPath() string {
41
+ return os.Getenv("LOG_PATH")
42
+ }
43
+
44
+ func (e *envConfig) GetHostAddress() string {
45
+ return os.Getenv("HOST_ADDRESS")
46
+ }
47
+
48
+ func (e *envConfig) GetHostPort() string {
49
+ return os.Getenv("HOST_PORT")
50
+ }
51
+
52
+ func (e *envConfig) GetEmailVerificationDuration() int {
53
+ duration, err := strconv.Atoi(os.Getenv("EMAIL_VERIFICATION_DURATION"))
54
+ if err != nil {
55
+ return 0 // Default value if parsing fails
56
+ }
57
+ return duration
58
+ }
59
+
60
+ func (e *envConfig) GetDatabaseHost() string {
61
+ return os.Getenv("DB_HOST")
62
+ }
63
+
64
+ func (e *envConfig) GetDatabasePort() string {
65
+ return os.Getenv("DB_PORT")
66
+ }
67
+
68
+ func (e *envConfig) GetDatabaseUser() string {
69
+ return os.Getenv("DB_USER")
70
+ }
71
+
72
+ func (e *envConfig) GetDatabasePassword() string {
73
+ return os.Getenv("DB_PASSWORD")
74
+ }
75
+
76
+ func (e *envConfig) GetDatabaseName() string {
77
+ return os.Getenv("DB_NAME")
78
+ }
79
+
80
+ func (e *envConfig) GetSalt() string {
81
+ salt := os.Getenv("SALT")
82
+ if salt == "" {
83
+ return "Def4u|7" // Default salt value
84
+ }
85
+ return salt
86
+ }
space/space/api/banking-crud/controller/account_controller.go ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package controller
2
+
3
+ import (
4
+ "fmt"
5
+
6
+ "abdanhafidz.com/go-boilerplate/models/dto"
7
+ "abdanhafidz.com/go-boilerplate/services"
8
+ "github.com/gin-gonic/gin"
9
+ )
10
+
11
+ type AccountController interface {
12
+ CreateAccount(ctx *gin.Context)
13
+ VerifyAccount(ctx *gin.Context)
14
+ ResetPIN(ctx *gin.Context)
15
+ BlockAccount(ctx *gin.Context)
16
+ }
17
+
18
+ type accountController struct {
19
+ accountService services.AccountService
20
+ }
21
+
22
+ func NewAccountController(accountService services.AccountService) AccountController {
23
+ return &accountController{
24
+ accountService: accountService,
25
+ }
26
+ }
27
+
28
+ func (c *accountController) CreateAccount(ctx *gin.Context) {
29
+ req := RequestJSON[dto.AccountRequest](ctx)
30
+ fmt.Println(req)
31
+ res, err := c.accountService.CreateAccount(ctx.Request.Context(), req.Name, req.Dateofbirth)
32
+ ResponseJSON(ctx, req, res, err)
33
+ }
34
+ func (c *accountController) VerifyAccount(ctx *gin.Context) {
35
+ req := RequestJSON[dto.VerifyAccountRequest](ctx)
36
+ fmt.Println(req)
37
+ res, err := c.accountService.VerifyAccount(ctx.Request.Context(), req)
38
+ ResponseJSON(ctx, req, res, err)
39
+ }
40
+
41
+ func (c *accountController) ResetPIN(ctx *gin.Context) {
42
+ req := RequestJSON[dto.VerifyAccountRequest](ctx)
43
+ res, err := c.accountService.ResetPIN(ctx.Request.Context(), req)
44
+ ResponseJSON(ctx, req, res, err)
45
+ }
46
+
47
+ func (c *accountController) BlockAccount(ctx *gin.Context) {
48
+ req := RequestJSON[dto.VerifyAccountRequest](ctx)
49
+ res, err := c.accountService.BlockAccount(ctx.Request.Context(), req)
50
+ ResponseJSON(ctx, req, res, err)
51
+ }
space/space/api/banking-crud/controller/controller.go ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package controller
2
+
3
+ import (
4
+ http_error "abdanhafidz.com/go-boilerplate/models/error"
5
+ "abdanhafidz.com/go-boilerplate/utils"
6
+ "github.com/gin-gonic/gin"
7
+ )
8
+
9
+ func RequestJSON[TRequest any](ctx *gin.Context) TRequest {
10
+ var request TRequest
11
+ if err := ctx.ShouldBindJSON(&request); err != nil {
12
+ utils.ResponseFAILED(ctx, request, http_error.BAD_REQUEST_ERROR)
13
+ ctx.Abort()
14
+ return request
15
+ } else {
16
+ return request
17
+ }
18
+ }
19
+
20
+ func ResponseJSON[TResponse any, TMetaData any](ctx *gin.Context, metaData TMetaData, res TResponse, err error) {
21
+ utils.SendResponse(ctx, metaData, res, err)
22
+ }
space/space/api/banking-crud/go.mod ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module abdanhafidz.com/go-boilerplate
2
+
3
+ go 1.24.5
4
+
5
+ require (
6
+ github.com/bytedance/sonic v1.14.0 // indirect
7
+ github.com/bytedance/sonic/loader v0.3.0 // indirect
8
+ github.com/cloudwego/base64x v0.1.6 // indirect
9
+ github.com/cloudwego/iasm v0.2.0 // indirect
10
+ github.com/gabriel-vasile/mimetype v1.4.9 // indirect
11
+ github.com/gin-contrib/sse v1.1.0 // indirect
12
+ github.com/gin-gonic/gin v1.10.1 // indirect
13
+ github.com/go-playground/locales v0.14.1 // indirect
14
+ github.com/go-playground/universal-translator v0.18.1 // indirect
15
+ github.com/go-playground/validator/v10 v10.27.0 // indirect
16
+ github.com/goccy/go-json v0.10.5 // indirect
17
+ github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
18
+ github.com/jackc/pgpassfile v1.0.0 // indirect
19
+ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
20
+ github.com/jackc/pgx/v5 v5.7.5 // indirect
21
+ github.com/jackc/puddle/v2 v2.2.2 // indirect
22
+ github.com/jinzhu/inflection v1.0.0 // indirect
23
+ github.com/jinzhu/now v1.1.5 // indirect
24
+ github.com/joho/godotenv v1.5.1 // indirect
25
+ github.com/json-iterator/go v1.1.12 // indirect
26
+ github.com/klauspost/cpuid/v2 v2.3.0 // indirect
27
+ github.com/knz/go-libedit v1.10.1 // indirect
28
+ github.com/leodido/go-urn v1.4.0 // indirect
29
+ github.com/mattn/go-isatty v0.0.20 // indirect
30
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
31
+ github.com/modern-go/reflect2 v1.0.2 // indirect
32
+ github.com/pelletier/go-toml/v2 v2.2.4 // indirect
33
+ github.com/satori/go.uuid v1.2.0 // indirect
34
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
35
+ github.com/ugorji/go/codec v1.3.0 // indirect
36
+ golang.org/x/arch v0.20.0 // indirect
37
+ golang.org/x/crypto v0.41.0 // indirect
38
+ golang.org/x/net v0.43.0 // indirect
39
+ golang.org/x/sync v0.16.0 // indirect
40
+ golang.org/x/sys v0.35.0 // indirect
41
+ golang.org/x/text v0.28.0 // indirect
42
+ google.golang.org/protobuf v1.36.7 // indirect
43
+ gopkg.in/yaml.v3 v3.0.1 // indirect
44
+ gorm.io/driver/postgres v1.6.0 // indirect
45
+ gorm.io/gorm v1.30.1 // indirect
46
+ )
space/space/api/banking-crud/go.sum ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
2
+ github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
3
+ github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
4
+ github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
5
+ github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
6
+ github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
7
+ github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
8
+ github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
9
+ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
10
+ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
11
+ github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
12
+ github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
13
+ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
14
+ github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
15
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
16
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
17
+ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
18
+ github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
19
+ github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
20
+ github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
21
+ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
22
+ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
23
+ github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
24
+ github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
25
+ github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
26
+ github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
27
+ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
28
+ github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
29
+ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
30
+ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
31
+ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
32
+ github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
33
+ github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
34
+ github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
35
+ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
36
+ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
37
+ github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
38
+ github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
39
+ github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
40
+ github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
41
+ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
42
+ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
43
+ github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
44
+ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
45
+ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
46
+ github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
47
+ github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
48
+ github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
49
+ github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
50
+ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
51
+ github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
52
+ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
53
+ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
54
+ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
55
+ github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
56
+ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
57
+ github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
58
+ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
59
+ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
60
+ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
61
+ github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
62
+ github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
63
+ github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
64
+ github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
65
+ github.com/knz/go-libedit v1.10.1 h1:0pHpWtx9vcvC0xGZqEQlQdfSQs7WRlAjuPvk3fOZDCo=
66
+ github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
67
+ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
68
+ github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
69
+ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
70
+ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
71
+ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
72
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
73
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
74
+ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
75
+ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
76
+ github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
77
+ github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
78
+ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
79
+ github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
80
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
81
+ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
82
+ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
83
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
84
+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
85
+ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
86
+ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
87
+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
88
+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
89
+ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
90
+ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
91
+ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
92
+ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
93
+ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
94
+ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
95
+ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
96
+ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
97
+ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
98
+ github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
99
+ github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
100
+ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
101
+ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
102
+ golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
103
+ golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
104
+ golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
105
+ golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
106
+ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
107
+ golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
108
+ golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
109
+ golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
110
+ golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
111
+ golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
112
+ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
113
+ golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
114
+ golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
115
+ golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
116
+ golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
117
+ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
118
+ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
119
+ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
120
+ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
121
+ golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
122
+ golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
123
+ golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
124
+ golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
125
+ golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
126
+ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
127
+ golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
128
+ golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
129
+ golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
130
+ golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
131
+ google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
132
+ google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
133
+ google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
134
+ google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
135
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
136
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
137
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
138
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
139
+ gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
140
+ gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
141
+ gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
142
+ gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
143
+ gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4=
144
+ gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
145
+ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
146
+ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
space/space/api/banking-crud/logs/error_log.txt ADDED
File without changes
space/space/api/banking-crud/logs/security_log.txt ADDED
File without changes
space/space/api/banking-crud/main.go ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package main
2
+
3
+ import (
4
+ "abdanhafidz.com/go-boilerplate/provider"
5
+ "abdanhafidz.com/go-boilerplate/router"
6
+ )
7
+
8
+ func main() {
9
+ appProvider := provider.NewAppProvider()
10
+ router.RunRouter(appProvider)
11
+ }
space/space/api/banking-crud/models/dto/account_dto.go ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package dto
2
+
3
+ import "time"
4
+
5
+ type AccountRequest struct {
6
+ Dateofbirth time.Time `json:"dob" binding:"required"`
7
+ Name string `json:"name" binding:"required"`
8
+ }
9
+
10
+ type VerifyAccountRequest struct {
11
+ Dateofbirth time.Time `json:"dob" binding:"required"`
12
+ Name string `json:"name" binding:"required"`
13
+ LastDigit string `json:"account_3_digits" binding:"required"`
14
+ }
15
+
16
+ type AccountInfoRequest struct {
17
+ VerifyAccountRequest
18
+ }
19
+
20
+ type AccountInfoResponse struct {
21
+ Name string `json:"name" binding:"required"`
22
+ AccountNumber uint `gorm:"uniqueIndex" json:"account_number"`
23
+ Balance uint `gorm:"type:number" json:"balance"`
24
+ }
space/space/api/banking-crud/models/dto/http_response_dto.go ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package dto
2
+
3
+ type SuccessResponse[TResponse any] struct {
4
+ Data TResponse `json:"data"`
5
+ Message any `json:"message"`
6
+ MetaData any `json:"meta_data"`
7
+ }
8
+
9
+ type ErrorResponse struct {
10
+ Error error `json:"errors"`
11
+ Message any `json:"message"`
12
+ MetaData any `json:"meta_data"`
13
+ }
space/space/api/banking-crud/models/dto/jwt_dto.go ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package dto
2
+
3
+ import (
4
+ "github.com/golang-jwt/jwt/v4"
5
+ uuid "github.com/satori/go.uuid"
6
+ )
7
+
8
+ type JWTCustomClaims struct {
9
+ IdUser uuid.UUID `json:"user_id" binding:"required"`
10
+ jwt.RegisteredClaims
11
+ }
12
+
13
+ type AccountData struct {
14
+ IdUser uuid.UUID `json:"user_id" binding:"required"`
15
+ }
space/space/api/banking-crud/models/entity/entity.go ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package entity
2
+
3
+ import (
4
+ "time"
5
+
6
+ uuid "github.com/satori/go.uuid"
7
+ )
8
+
9
+ type Account struct {
10
+ Id uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4();primaryKey" json:"id"`
11
+ Name string `gorm:"uniqueIndex" json:"name"`
12
+ DateOfBirth time.Time `gorm:"type:date" json:"date_of_birth"`
13
+ AccountNumber uint `gorm:"uniqueIndex" json:"account_number"`
14
+ Balance uint `gorm:"column:balance" json:"balance"`
15
+ PIN int `gorm:"column:pin" json:"-"`
16
+ IsActive bool `gorm:"type:boolean; column:is_active" json:"is_active"`
17
+ CreatedAt time.Time `json:"created_at"`
18
+ DeletedAt *time.Time `json:"deleted_at" gorm:"default:null"`
19
+ }
20
+
21
+ // Gorm table name settings
22
+ func (Account) TableName() string { return "account" }
space/space/api/banking-crud/models/error/error_model.go ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package http_error
2
+
3
+ import "errors"
4
+
5
+ var (
6
+ BAD_REQUEST_ERROR = errors.New("Invalid Request Format !")
7
+ INTERNAL_SERVER_ERROR = errors.New("Internal Server Error!")
8
+ UNAUTHORIZED = errors.New("Unauthorized, you don't have permission to access this service!")
9
+ DATA_NOT_FOUND = errors.New("There is not data with given credential / given parameter!")
10
+ TIMEOUT = errors.New("Server took to long respond!")
11
+ EXISTING_ACCOUNT = errors.New("There is existing account!")
12
+ INVALID_TOKEN = errors.New("Invalid Authentication Payload!")
13
+ DUPLICATE_DATA = errors.New("Duplicate data !")
14
+ ACCOUNT_NOT_FOUND = errors.New("There is no account with given credential!")
15
+ WRONG_PASSWORD = errors.New("Your password is wrong for given account credential, please recheck!")
16
+ INVALID_ACCOUNT_DIGITS = errors.New("Your account 3 digits is not found in account number data")
17
+ )
space/space/api/banking-crud/provider/config_provider.go ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package provider
2
+
3
+ import "abdanhafidz.com/go-boilerplate/config"
4
+
5
+ type ConfigProvider interface {
6
+ ProvideEnvConfig() config.EnvConfig
7
+ ProvideDatabaseConfig() config.DatabaseConfig
8
+ }
9
+
10
+ type configProvider struct {
11
+ envConfig config.EnvConfig
12
+ databaseConfig config.DatabaseConfig
13
+ }
14
+
15
+ func NewConfigProvider() ConfigProvider {
16
+ envConfig := config.NewEnvConfig("Asia/Jakarta")
17
+ return &configProvider{
18
+ envConfig: envConfig,
19
+ databaseConfig: config.NewDatabaseConfig(
20
+ envConfig.GetDatabaseHost(),
21
+ envConfig.GetDatabaseUser(),
22
+ envConfig.GetDatabasePassword(),
23
+ envConfig.GetDatabaseName(),
24
+ envConfig.GetDatabasePort(),
25
+ ),
26
+ }
27
+ }
28
+
29
+ func (c *configProvider) ProvideEnvConfig() config.EnvConfig {
30
+ return c.envConfig
31
+ }
32
+ func (c *configProvider) ProvideDatabaseConfig() config.DatabaseConfig {
33
+ return c.databaseConfig
34
+ }
space/space/api/banking-crud/provider/controller_provider.go ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package provider
2
+
3
+ import "abdanhafidz.com/go-boilerplate/controller"
4
+
5
+ type ControllerProvider interface {
6
+ ProvideAccountController() controller.AccountController
7
+ }
8
+
9
+ type controllerProvider struct {
10
+ accountController controller.AccountController
11
+ }
12
+
13
+ func NewControllerProvider(servicesProvider ServicesProvider) ControllerProvider {
14
+
15
+ accountController := controller.NewAccountController(servicesProvider.ProvideAccountService())
16
+
17
+ return &controllerProvider{
18
+ accountController: accountController,
19
+ }
20
+ }
21
+
22
+ func (c *controllerProvider) ProvideAccountController() controller.AccountController {
23
+ return c.accountController
24
+ }
space/space/api/banking-crud/provider/provider.go ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package provider
2
+
3
+ import (
4
+ "abdanhafidz.com/go-boilerplate/models/entity"
5
+ "github.com/gin-gonic/gin"
6
+ )
7
+
8
+ type AppProvider interface {
9
+ ProvideRouter() *gin.Engine
10
+ ProvideConfig() ConfigProvider
11
+ ProvideRepositories() RepositoriesProvider
12
+ ProvideServices() ServicesProvider
13
+ ProvideControllers() ControllerProvider
14
+ }
15
+ type appProvider struct {
16
+ ginRouter *gin.Engine
17
+ configProvider ConfigProvider
18
+ repositoriesProvider RepositoriesProvider
19
+ servicesProvider ServicesProvider
20
+ controllerProvider ControllerProvider
21
+ }
22
+
23
+ func NewAppProvider() AppProvider {
24
+ ginRouter := gin.Default()
25
+ configProvider := NewConfigProvider()
26
+ repositoriesProvider := NewRepositoriesProvider(configProvider)
27
+ servicesProvider := NewServicesProvider(repositoriesProvider, configProvider)
28
+ controllerProvider := NewControllerProvider(servicesProvider)
29
+
30
+ configProvider.ProvideDatabaseConfig().AutoMigrateAll(
31
+ &entity.Account{},
32
+ )
33
+
34
+ return &appProvider{
35
+ ginRouter: ginRouter,
36
+ configProvider: configProvider,
37
+ repositoriesProvider: repositoriesProvider,
38
+ servicesProvider: servicesProvider,
39
+ controllerProvider: controllerProvider,
40
+ }
41
+ }
42
+ func (a *appProvider) ProvideRouter() *gin.Engine {
43
+ return a.ginRouter
44
+ }
45
+ func (a *appProvider) ProvideConfig() ConfigProvider {
46
+ return a.configProvider
47
+ }
48
+
49
+ func (a *appProvider) ProvideRepositories() RepositoriesProvider {
50
+ return a.repositoriesProvider
51
+ }
52
+
53
+ func (a *appProvider) ProvideServices() ServicesProvider {
54
+ return a.servicesProvider
55
+ }
56
+
57
+ func (a *appProvider) ProvideControllers() ControllerProvider {
58
+ return a.controllerProvider
59
+ }
space/space/api/banking-crud/provider/repositories_provider.go ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package provider
2
+
3
+ import (
4
+ "abdanhafidz.com/go-boilerplate/repositories"
5
+ )
6
+
7
+ type RepositoriesProvider interface {
8
+ ProvideAccountRepository() repositories.AccountRepository
9
+ }
10
+ type repositoriesProvider struct {
11
+ accountRepository repositories.AccountRepository
12
+ }
13
+
14
+ func NewRepositoriesProvider(cfg ConfigProvider) RepositoriesProvider {
15
+ dbConfig := cfg.ProvideDatabaseConfig()
16
+ accountRepository := repositories.NewAccountRepository(dbConfig.GetInstance())
17
+
18
+ return &repositoriesProvider{
19
+ accountRepository: accountRepository,
20
+ }
21
+
22
+ }
23
+
24
+ func (r *repositoriesProvider) ProvideAccountRepository() repositories.AccountRepository {
25
+ return r.accountRepository
26
+ }
space/space/api/banking-crud/provider/services_provider.go ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package provider
2
+
3
+ import (
4
+ "abdanhafidz.com/go-boilerplate/services"
5
+ )
6
+
7
+ type ServicesProvider interface {
8
+ ProvideAccountService() services.AccountService
9
+ }
10
+ type servicesProvider struct {
11
+ accountService services.AccountService
12
+ }
13
+
14
+ func NewServicesProvider(repoProvider RepositoriesProvider, configProvider ConfigProvider) ServicesProvider {
15
+ accountService := services.NewAccountService(repoProvider.ProvideAccountRepository())
16
+
17
+ return &servicesProvider{
18
+ accountService: accountService,
19
+ }
20
+ }
21
+
22
+ func (s *servicesProvider) ProvideAccountService() services.AccountService {
23
+ return s.accountService
24
+ }
space/space/api/banking-crud/repositories/account_repository.go ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package repositories
2
+
3
+ import (
4
+ "context"
5
+ "strconv"
6
+ "time"
7
+
8
+ "abdanhafidz.com/go-boilerplate/models/entity"
9
+ uuid "github.com/satori/go.uuid"
10
+ "gorm.io/gorm"
11
+ )
12
+
13
+ type AccountRepository interface {
14
+ CreateAccount(ctx context.Context, name string, date_of_birth time.Time, account_number uint) (res entity.Account, err error)
15
+ GetAccount(ctx context.Context, name string, date_of_birth time.Time, digits_account_number string) (res entity.Account, err error)
16
+ ResetPIN(ctx context.Context, account_id uuid.UUID, newPin int) (res entity.Account, err error)
17
+ UpdateAccountStatus(ctx context.Context, account_id uuid.UUID, status bool) (res entity.Account, err error)
18
+ }
19
+ type accountRepository struct {
20
+ db *gorm.DB
21
+ }
22
+
23
+ func NewAccountRepository(db *gorm.DB) AccountRepository {
24
+ return &accountRepository{
25
+ db: db,
26
+ }
27
+ }
28
+
29
+ func (r *accountRepository) CreateAccount(ctx context.Context, name string, date_of_birth time.Time, account_number uint) (res entity.Account, err error) {
30
+
31
+ res = entity.Account{
32
+ Name: name,
33
+ DateOfBirth: date_of_birth,
34
+ AccountNumber: account_number,
35
+ IsActive: true,
36
+ }
37
+
38
+ tx := r.db.WithContext(ctx).Create(&res)
39
+
40
+ err = tx.Error
41
+
42
+ return res, err
43
+ }
44
+
45
+ func (r *accountRepository) GetAccount(ctx context.Context, name string, date_of_birth time.Time, digits_account_number string) (res entity.Account, err error) {
46
+ // Cari account dengan filter nama & tanggal lahir
47
+ tx := r.db.WithContext(ctx).Where("name = ? AND date_of_birth = ?", name, date_of_birth).Find(&res)
48
+
49
+ if tx.Error != nil {
50
+ return res, tx.Error
51
+ }
52
+
53
+ if tx.RowsAffected == 0 {
54
+ return res, gorm.ErrRecordNotFound
55
+ }
56
+
57
+ if strconv.Itoa(int(res.AccountNumber%1000)) != digits_account_number {
58
+ return res, gorm.ErrInvalidValue
59
+ }
60
+ return res, tx.Error
61
+ }
62
+
63
+ func (r *accountRepository) ResetPIN(ctx context.Context, account_id uuid.UUID, newPin int) (res entity.Account, err error) {
64
+ tx := r.db.WithContext(ctx).Model(&entity.Account{Id: account_id}).Update("pin", newPin).First(&res)
65
+
66
+ if tx.Error != nil {
67
+ return res, tx.Error
68
+ }
69
+
70
+ if tx.RowsAffected == 0 {
71
+ return res, gorm.ErrRecordNotFound
72
+ }
73
+
74
+ return res, tx.Error
75
+ }
76
+
77
+ func (r *accountRepository) UpdateAccountStatus(ctx context.Context, account_id uuid.UUID, status bool) (res entity.Account, err error) {
78
+ tx := r.db.WithContext(ctx).Model(&entity.Account{Id: account_id}).Update("is_active", status).First(&res)
79
+
80
+ if tx.Error != nil {
81
+ return res, tx.Error
82
+ }
83
+
84
+ if tx.RowsAffected == 0 {
85
+ return res, gorm.ErrRecordNotFound
86
+ }
87
+
88
+ return res, tx.Error
89
+ }
space/space/api/banking-crud/repositories/repository.go ADDED
@@ -0,0 +1 @@
 
 
1
+ package repositories
space/space/api/banking-crud/router/account_router.go ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package router
2
+
3
+ import (
4
+ "abdanhafidz.com/go-boilerplate/provider"
5
+ "github.com/gin-gonic/gin"
6
+ )
7
+
8
+ func AuthenticationRouter(router *gin.Engine, controller provider.ControllerProvider) {
9
+ routerGroup := router.Group("/api/v1/account")
10
+ accountController := controller.ProvideAccountController()
11
+ {
12
+ routerGroup.POST("/create", accountController.CreateAccount)
13
+ routerGroup.POST("/verify", accountController.VerifyAccount)
14
+ routerGroup.POST("/reset-pin", accountController.ResetPIN)
15
+ routerGroup.POST("/block-account", accountController.BlockAccount)
16
+ }
17
+ }
space/space/api/banking-crud/router/router.go ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package router
2
+
3
+ import (
4
+ "abdanhafidz.com/go-boilerplate/provider"
5
+ )
6
+
7
+ func RunRouter(appProvider provider.AppProvider) {
8
+ router, controller, config := appProvider.ProvideRouter(), appProvider.ProvideControllers(), appProvider.ProvideConfig()
9
+ AuthenticationRouter(router, controller)
10
+ router.Run(config.ProvideEnvConfig().GetTCPAddress())
11
+ }
space/space/api/banking-crud/services/account_service.go ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package services
2
+
3
+ import (
4
+ "context"
5
+ "errors"
6
+ "fmt"
7
+ "math/rand"
8
+ "time"
9
+
10
+ "abdanhafidz.com/go-boilerplate/models/dto"
11
+ "abdanhafidz.com/go-boilerplate/models/entity"
12
+ http_error "abdanhafidz.com/go-boilerplate/models/error"
13
+ "abdanhafidz.com/go-boilerplate/repositories"
14
+ "gorm.io/gorm"
15
+ )
16
+
17
+ type AccountService interface {
18
+ CreateAccount(ctx context.Context, name string, date_of_birth time.Time) (res entity.Account, err error)
19
+ VerifyAccount(ctx context.Context, req dto.VerifyAccountRequest) (res entity.Account, err error)
20
+ ResetPIN(ctx context.Context, req dto.VerifyAccountRequest) (res entity.Account, err error)
21
+ BlockAccount(ctx context.Context, req dto.VerifyAccountRequest) (res entity.Account, err error)
22
+ }
23
+
24
+ type accountService struct {
25
+ accountRepo repositories.AccountRepository
26
+ }
27
+
28
+ func NewAccountService(accountRepo repositories.AccountRepository) AccountService {
29
+ return &accountService{
30
+ accountRepo: accountRepo,
31
+ }
32
+ }
33
+ func (s *accountService) CreateAccount(ctx context.Context, name string, date_of_birth time.Time) (res entity.Account, err error) {
34
+ account_number := uint(rand.Intn(90_000_000) + 10_000_000)
35
+ if name == "" || date_of_birth.IsZero() {
36
+ return res, http_error.BAD_REQUEST_ERROR
37
+ }
38
+ res, err = s.accountRepo.CreateAccount(ctx, name, date_of_birth, account_number)
39
+ if err != nil {
40
+ return res, err
41
+ }
42
+ return res, err
43
+ }
44
+
45
+ func (s *accountService) VerifyAccount(ctx context.Context, req dto.VerifyAccountRequest) (res entity.Account, err error) {
46
+ res, err = s.accountRepo.GetAccount(ctx, req.Name, req.Dateofbirth, req.LastDigit)
47
+
48
+ if errors.Is(err, gorm.ErrRecordNotFound) {
49
+ return res, http_error.DATA_NOT_FOUND
50
+ }
51
+
52
+ if errors.Is(err, gorm.ErrInvalidValue) {
53
+ return res, http_error.INVALID_ACCOUNT_DIGITS
54
+ }
55
+
56
+ return res, err
57
+ }
58
+
59
+ func (s *accountService) ResetPIN(ctx context.Context, req dto.VerifyAccountRequest) (res entity.Account, err error) {
60
+ res_verify, err_verify := s.VerifyAccount(ctx, req)
61
+
62
+ if err_verify != nil {
63
+ return res, http_error.UNAUTHORIZED
64
+ }
65
+
66
+ newPIN := int(rand.Intn(90_000) + 10_000)
67
+
68
+ res, err = s.accountRepo.ResetPIN(ctx, res_verify.Id, newPIN)
69
+
70
+ return res, err
71
+ }
72
+
73
+ func (s *accountService) BlockAccount(ctx context.Context, req dto.VerifyAccountRequest) (res entity.Account, err error) {
74
+ res_verify, err_verify := s.VerifyAccount(ctx, req)
75
+
76
+ if err_verify != nil {
77
+ return res, http_error.UNAUTHORIZED
78
+ }
79
+ fmt.Println(res_verify)
80
+ res, err = s.accountRepo.UpdateAccountStatus(ctx, res_verify.Id, false)
81
+
82
+ return res, err
83
+ }
space/space/api/banking-crud/services/jwt_service.go ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package services
2
+
3
+ import (
4
+ "context"
5
+
6
+ "abdanhafidz.com/go-boilerplate/models/dto"
7
+ http_error "abdanhafidz.com/go-boilerplate/models/error"
8
+ "github.com/golang-jwt/jwt/v4"
9
+ uuid "github.com/satori/go.uuid"
10
+ )
11
+
12
+ type JWTService interface {
13
+ GenerateToken(ctx context.Context, payload dto.JWTCustomClaims) (token string, err error)
14
+ ValidateToken(ctx context.Context, tokenStr string) (claim *dto.JWTCustomClaims, err error)
15
+ }
16
+
17
+ type jwtService struct {
18
+ secretKey string
19
+ }
20
+
21
+ func NewJWTService(secretKey string) JWTService {
22
+ return &jwtService{
23
+ secretKey: secretKey,
24
+ }
25
+ }
26
+ func (s *jwtService) GenerateToken(ctx context.Context, payload dto.JWTCustomClaims) (token string, err error) {
27
+ claims := jwt.MapClaims{
28
+ "user_id": payload.IdUser,
29
+ }
30
+
31
+ jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
32
+ token, err_convertion := jwtToken.SignedString([]byte(s.secretKey))
33
+
34
+ if err_convertion != nil {
35
+ return "", http_error.INTERNAL_SERVER_ERROR
36
+ }
37
+
38
+ return token, nil
39
+ }
40
+
41
+ func (s *jwtService) ValidateToken(ctx context.Context, tokenStr string) (claim *dto.JWTCustomClaims, err error) {
42
+ token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
43
+ if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
44
+ return "", http_error.INTERNAL_SERVER_ERROR
45
+ }
46
+ return []byte(s.secretKey), nil
47
+ })
48
+
49
+ if err != nil || !token.Valid {
50
+ return nil, http_error.INVALID_TOKEN
51
+ }
52
+
53
+ claims, ok := token.Claims.(jwt.MapClaims)
54
+ if !ok {
55
+ return nil, http_error.INVALID_TOKEN
56
+ }
57
+
58
+ return &dto.JWTCustomClaims{
59
+ IdUser: claims["user_id"].(uuid.UUID),
60
+ }, nil
61
+ }
space/space/api/banking-crud/services/service.go ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package services
2
+
3
+ import (
4
+ "errors"
5
+
6
+ http_error "abdanhafidz.com/go-boilerplate/models/error"
7
+ "abdanhafidz.com/go-boilerplate/utils"
8
+ "gorm.io/gorm"
9
+ )
10
+
11
+ func RepoError(repo_err error) (err error) {
12
+ if repo_err != nil {
13
+ if errors.Is(repo_err, gorm.ErrDuplicatedKey) {
14
+ return http_error.DUPLICATE_DATA
15
+
16
+ } else if errors.Is(repo_err, gorm.ErrRecordNotFound) {
17
+ return http_error.DATA_NOT_FOUND
18
+ } else {
19
+ utils.InternalErrorLog(repo_err)
20
+ return http_error.INTERNAL_SERVER_ERROR
21
+ }
22
+ }
23
+ return nil
24
+ }
space/space/api/banking-crud/utils/logger_util.go ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package utils
2
+
3
+ import (
4
+ "fmt"
5
+ "log"
6
+ "os"
7
+ )
8
+
9
+ func InternalErrorLog(err_log error) {
10
+ fmt.Println("There is an error!")
11
+
12
+ file, err := os.OpenFile("logs/error_log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
13
+
14
+ if err != nil {
15
+ log.Fatal(err)
16
+ }
17
+ log.Println("Error Log :", err_log)
18
+ log.SetOutput(file)
19
+ }
20
+
21
+ func SecurityLog(security_log string) {
22
+ fmt.Println("There is an error!")
23
+
24
+ file, err := os.OpenFile("logs/security_log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
25
+
26
+ if err != nil {
27
+ log.Fatal(err)
28
+ }
29
+ log.Println("Security Log :", security_log)
30
+ log.SetOutput(file)
31
+ }
space/space/api/banking-crud/utils/response_util.go ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package utils
2
+
3
+ import (
4
+ "errors"
5
+
6
+ "abdanhafidz.com/go-boilerplate/models/dto"
7
+ http_error "abdanhafidz.com/go-boilerplate/models/error"
8
+ "github.com/gin-gonic/gin"
9
+ )
10
+
11
+ func ResponseOK[Tdata any, TMetaData any](c *gin.Context, metaData TMetaData, data Tdata) {
12
+ c.JSON(200, dto.SuccessResponse[Tdata]{
13
+ Data: data,
14
+ Message: "Data retrieved Successfully!",
15
+ MetaData: metaData,
16
+ })
17
+ }
18
+
19
+ func ResponseFAILED[TMetaData any](c *gin.Context, metaData TMetaData, err error) {
20
+ if errors.Is(err, http_error.BAD_REQUEST_ERROR) {
21
+ c.JSON(200, dto.ErrorResponse{
22
+ Error: err,
23
+ Message: "Invalid request format!",
24
+ MetaData: metaData,
25
+ })
26
+ return
27
+ } else if errors.Is(err, http_error.INTERNAL_SERVER_ERROR) {
28
+ c.JSON(200, dto.ErrorResponse{
29
+ Error: err,
30
+ Message: "Internal Server Error!",
31
+ MetaData: metaData,
32
+ })
33
+ return
34
+ } else if errors.Is(err, http_error.UNAUTHORIZED) {
35
+ c.JSON(401, dto.ErrorResponse{
36
+ Error: err,
37
+ Message: "Unauthorized, you don't have permission to access this service!",
38
+ MetaData: metaData,
39
+ })
40
+ return
41
+ } else if errors.Is(err, http_error.DATA_NOT_FOUND) {
42
+ c.JSON(404, dto.ErrorResponse{
43
+ Error: err,
44
+ Message: "There is not data with given credential / given parameter!",
45
+ MetaData: metaData,
46
+ })
47
+ return
48
+ } else if errors.Is(err, http_error.TIMEOUT) {
49
+ c.JSON(504, dto.ErrorResponse{
50
+ Error: err,
51
+ Message: "Server took to long to respond!",
52
+ MetaData: metaData,
53
+ })
54
+ return
55
+ } else {
56
+ c.JSON(405, dto.ErrorResponse{
57
+ Error: err,
58
+ Message: err.Error(),
59
+ MetaData: metaData,
60
+ })
61
+ return
62
+ }
63
+
64
+ }
65
+
66
+ func SendResponse[Tdata any, TMetaData any](c *gin.Context, metaData TMetaData, data Tdata, err error) {
67
+ if !c.IsAborted() {
68
+ if err != nil {
69
+ ResponseFAILED(c, metaData, err)
70
+ c.Abort()
71
+ return
72
+ } else {
73
+ ResponseOK(c, metaData, data)
74
+ c.Abort()
75
+ return
76
+ }
77
+ }
78
+
79
+ }
space/space/space/data/prompt_template/responder_banking.txt CHANGED
@@ -13,4 +13,5 @@ Menjaga kepatuhan standar keamanan perbankan dengan tidak membocorkan atau memin
13
  - Layanan Gagal : Dari Response API akan ada keterangan bahwa proses API error / gagal, berikan penjelasan secara umum jika kesalahan memang dari user, berikan keterangan kesalahan internal jika ternyata kategori error bukan dari user
14
  - Pertanyaan tidak jelas: ajukan pertanyaan klarifikasi.
15
 
16
- TOLONG PENYAMPAIAN RESPON AGAR LEBIH SANTAI DAN MUDAH DIPAHAMI, PEMBAWAAN SANTAI DAN FRIENDLY, JANGAN TERLALU TEKNIKAL
 
 
13
  - Layanan Gagal : Dari Response API akan ada keterangan bahwa proses API error / gagal, berikan penjelasan secara umum jika kesalahan memang dari user, berikan keterangan kesalahan internal jika ternyata kategori error bukan dari user
14
  - Pertanyaan tidak jelas: ajukan pertanyaan klarifikasi.
15
 
16
+ TOLONG PENYAMPAIAN RESPON AGAR LEBIH SANTAI DAN MUDAH DIPAHAMI, PEMBAWAAN SANTAI DAN FRIENDLY, JANGAN TERLALU TEKNIKAL
17
+ ANDA ADALAH CUSTOMER SERVICE YANG FRIENDLY.
space/space/space/space/space/data/prompt_template/api_banking.txt ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ Anda adalah **Agen Fetcher API**.
4
+
5
+ TOLONG JADI STRICT, BENAR BENAR MENGIKUTI SYSTEM PROMPT YANG SAYA TETAPKAN!
6
+
7
+ Tugas Anda adalah membaca input pengguna, mendeteksi kategori permintaan, dan mengembalikan spesifikasi permintaan API.
8
+
9
+ Output **selalu** berupa objek JSON dengan skema berikut:
10
+
11
+ "endpoint": string,
12
+ "method": string,
13
+ "request": object
14
+
15
+
16
+ ## 1. Pembuatan Rekening
17
+
18
+ **DISCLAIMER** : Jika pengguna tidak memberikan data yang dibutuhkan, mohon tanyakan kembali dengan sopan untuk melengkapinya. Jangan tampilkan format request JSON, cukup tampilkan pesan error saja!
19
+ **Endpoint**: `"account/create"`
20
+ **Kategori**: 🟒 Onboarding / Registrasi Rekening
21
+ **Kata Kunci Prompt dari User**: Buka Rekening, Daftar Rekening, Buka Tabungan, Membuat Tabungan, Membuat Rekening
22
+ **Input Wajib**:
23
+
24
+ * dob β†’ Tanggal lahir nasabah
25
+ * name β†’ Nama lengkap nasabah
26
+
27
+ **Penjelasan**:
28
+ Digunakan untuk membuat atau Rekening baru di sistem perbankan. Nasabah wajib memberikan nama lengkap dan tanggal lahir dengan format apapun.
29
+ Dari tanggal lahir yang diterima oleh user tolong lakukan format ulang agar mengikuti **time.Time RFC3339 (ISO8601)**, contoh: `11 Agustus 2005 β†’ 2005-08-11T00:00:00Z`
30
+ **Format Output (jika data lengkap)**:
31
+
32
+ "endpoint": "account/create",
33
+ "method": "POST",
34
+ "request":
35
+ "dob": "<TANGGAL_LAHIR_PENGGUNA>",
36
+ "name": "<NAMA_PENGGUNA>"
37
+
38
+
39
+ ## 2. Verifikasi Rekening
40
+
41
+ **DISCLAIMER** : Jika pengguna tidak memberikan data yang dibutuhkan, mohon tanyakan kembali dengan sopan untuk melengkapinya. Jangan tampilkan format request JSON, cukup tampilkan pesan error saja!
42
+ **Endpoint**: `"account/verify"`
43
+ **Kategori**: Verifikasi Identitas Rekening
44
+ **Kata Kunci Prompt User** : Informasi rekening, Verifikasi Rekening, Cek Saldo, Informasi Saldo, Informasi Tabungan, Detail Rekening
45
+ **Input Wajib**:
46
+
47
+ * dob β†’ Tanggal lahir nasabah
48
+ * name β†’ Nama lengkap nasabah
49
+ * account\_3\_digits β†’ 3 digit terakhir nomor rekening
50
+
51
+ **Penjelasan**:
52
+ Digunakan untuk memverifikasi kepemilikan Rekening atau nasabah ingin mengecek informasi Rekening, saldo, nomor rekening, dll. Proses ini memastikan data identitas sesuai dengan sistem.
53
+ Dari tanggal lahir yang diterima oleh user tolong lakukan format ulang agar mengikuti **time.Time RFC3339 (ISO8601)**, contoh: `11 Agustus 2005 β†’ 2005-08-11T00:00:00Z`
54
+ **Format Output (jika data lengkap)**:
55
+
56
+ "endpoint": "account/verify",
57
+ "method": "POST",
58
+ "request":
59
+ "dob": "<TANGGAL_LAHIR_PENGGUNA>",
60
+ "name": "<NAMA_PENGGUNA>",
61
+ "account_3_digits": "<3_DIGIT_TERAKHIR_REKENING>"
62
+
63
+ ## 3. Reset PIN
64
+
65
+ **DISCLAIMER** : Jika pengguna tidak memberikan data yang dibutuhkan, mohon tanyakan kembali dengan sopan untuk melengkapinya. Jangan tampilkan format request JSON, cukup tampilkan pesan error saja!
66
+ **Endpoint**: `"account/reset-pin"`
67
+ **Kategori**: 🟠 Manajemen Keamanan Rekening
68
+ **Kata Kunci Prompt User** : Reset PIN, Mengubah PIN, mengubah kata kunci
69
+ **Input Wajib**:
70
+
71
+ * dob β†’ Tanggal lahir nasabah
72
+ * name β†’ Nama lengkap nasabah
73
+ * account\_3\_digits β†’ 3 digit terakhir nomor rekening
74
+
75
+ **Penjelasan**:
76
+ Digunakan untuk mereset PIN jika nasabah lupa atau ingin mengganti PIN lama. Validasi data pribadi diperlukan untuk keamanan.
77
+ Dari tanggal lahir yang diterima oleh user tolong lakukan format ulang agar mengikuti **time.Time RFC3339 (ISO8601)**, contoh: `11 Agustus 2005 β†’ 2005-08-11T00:00:00Z`
78
+ **Format Output (jika data lengkap)**:
79
+
80
+ "endpoint": "account/reset-pin",
81
+ "method": "POST",
82
+ "request":
83
+ "dob": "<TANGGAL_LAHIR_PENGGUNA>",
84
+ "name": "<NAMA_PENGGUNA>",
85
+ "account_3_digits": "<3_DIGIT_TERAKHIR_REKENING>"
86
+
87
+
88
+ ## 4. Blokir Rekening
89
+
90
+ **DISCLAIMER** : Jika pengguna tidak memberikan data yang dibutuhkan, mohon tanyakan kembali dengan sopan untuk melengkapinya. Jangan tampilkan format request JSON, cukup tampilkan pesan error saja!
91
+ **Endpoint**: `"account/block-account"`
92
+ **Kategori**: Penutupan Rekening
93
+ **Kata Kunci Prompt User** : Memblokir Rekening, Menutup Rekening, Mengamankan Rekening, menonaktifkan rekening, nonaktivasi rekening
94
+ **Input Wajib**:
95
+
96
+ * dob β†’ Tanggal lahir nasabah
97
+ * name β†’ Nama lengkap nasabah
98
+ * account\_3\_digits β†’ 3 digit terakhir nomor rekening
99
+
100
+ **Penjelasan**:
101
+ Digunakan untuk memblokir Rekening nasabah, biasanya pada situasi darurat (misalnya aktivitas mencurigakan atau kehilangan akses Rekening).
102
+ Dari tanggal lahir yang diterima oleh user tolong lakukan format ulang agar mengikuti **time.Time RFC3339 (ISO8601)**, contoh: `11 Agustus 2005 β†’ 2005-08-11T00:00:00Z`
103
+
104
+ **Format Output (jika data lengkap)**:
105
+
106
+ "endpoint": "account/block-account",
107
+ "method": "POST",
108
+ "request":
109
+ "dob": "<TANGGAL_LAHIR_PENGGUNA>",
110
+ "name": "<NAMA_PENGGUNA>",
111
+ "account_3_digits": "<3_DIGIT_TERAKHIR_REKENING>"
112
+
113
+
114
+ **Aturan Utama**:
115
+
116
+ * Hanya kembalikan objek JSON final sebagai output. **Tidak boleh ada penjelasan tambahan atau teks ekstra.**
117
+ * Kunci dan nilai harus mengikuti skema persis seperti di atas.
118
+ * Jika informasi kurang, **jangan menebak atau mengarang** β†’ cukup minta data yang hilang dari pengguna dengan sopan.
119
+
120
+
space/space/space/space/space/data/prompt_template/expert_router.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ You are a classification agent.
2
+ Your task is to analyze a user's question and decide if it belongs to one of the following categories:
3
+
4
+ 1. "customer_service" β†’ General customer support, help requests, complaints, product/service inquiries, FAQs, or guidance.
5
+ 2. "bank_crud" β†’ Operations related to banking CRUD (Create, Read, Update, Delete), such as account creation, balance check, transactions, updating details, deleting / blocking an account, reset PIN.
6
+
7
+ Rules:
8
+ - Respond with only one label: "customer_service" or "bank_crud". ONLY STRING PLEASE DON'T ADD EXTRA FORMATTING PLAIN TEXT ONLY, remove character like (", *, `) please!
9
+ - Do not provide explanations or any other text.
10
+ - If unsure, choose the closest match.
space/space/space/space/space/data/prompt_template/responder_banking.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Anda adalah **Agen Penjawab Perbankan**, asisten perbankan yang sangat andal dan profesional.
2
+ Tujuan Anda adalah membantu nasabah menyelesaikan pertanyaan terkait perbankan mereka dengan akurat, jelas, dan aman.
3
+ Selalu pastikan kepatuhan terhadap etika asisten perbankan standar.
4
+ Anda juga akan
5
+
6
+ Menerjemahkan response API backend ke dalam bahasa yang mudah dipahami nasabah.
7
+
8
+ Memberikan konfirmasi atau penjelasan atas hasil layanan perbankan.
9
+ Menjaga kepatuhan standar keamanan perbankan dengan tidak membocorkan atau meminta informasi sensitif.
10
+ 1. Selalu tanggapi dengan cara yang **profesional, sopan, dan ringkas**.
11
+ 2. Ada 3 kategori tanggapan yang akan disampaikan secara implisit (disajikan ke bahasa yang user friendly dan mudah dipahami)
12
+ - Tanggapan berhasil: Dari Response API akan ada keterangan bahwa proses API berhasil, berikan respons positif serta hasilnya namun dalam bentuk eksplanatif singkat padat dan jelas.
13
+ - Layanan Gagal : Dari Response API akan ada keterangan bahwa proses API error / gagal, berikan penjelasan secara umum jika kesalahan memang dari user, berikan keterangan kesalahan internal jika ternyata kategori error bukan dari user
14
+ - Pertanyaan tidak jelas: ajukan pertanyaan klarifikasi.
15
+
16
+ TOLONG PENYAMPAIAN RESPON AGAR LEBIH SANTAI DAN MUDAH DIPAHAMI, PEMBAWAAN SANTAI DAN FRIENDLY, JANGAN TERLALU TEKNIKAL
space/space/space/space/space/main.py CHANGED
@@ -4,8 +4,28 @@ from src.config import OPENAI_API_KEY
4
  from openai import OpenAI
5
 
6
  openai_client = OpenAI(api_key = OPENAI_API_KEY)
 
7
  app = AppProvider(openai_client)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  chatbot_ui = app.provide_chatbot().provide_chatbot_ui()
 
9
  rtc = app.provide_rtc()
10
  rtc_handler = rtc.provide_rtc_handler()
11
  rtc_gpt_handler = rtc.provide_rtc_gpt_handler()
@@ -21,21 +41,21 @@ parser.add_argument("--mode", choices=[
21
 
22
  parser.add_argument("--port", default=7861, required=True)
23
  args = parser.parse_args()
24
-
25
- if(args.mode == "chatbot"):
26
- print("Launching Chabot UI :))))))")
27
- chatbot_ui.launch(port = int(args.port))
28
- elif(args.mode == "rtc-server"):
29
- print("launching RTC Server Mode ... ")
30
- rtc_handler.start_server(port = int(args.port))
31
- elif(args.mode == "rtc-ui"):
32
- print("launching RTC UI Mode ... ")
33
- rtc_handler.launch_ui(port = int(args.port))
34
- elif(args.mode == "rtc-gpt-ui"):
35
- print("RTC GPT UI mode ...")
36
- rtc_gpt_handler.launch_ui(port = int(args.port))
37
- elif(args.mode == "rtc-gpt-server"):
38
- rtc_gpt_handler.start_server(port = int(args.port))
39
- else:
40
- print("ERROR : INVALID ARGUMENT | PLEASE CHOOSE ONE BETWEEN chatbot / rtc-server/ rtc-ui / rtc-gpt-server / rtc-gpt-ui mode ")
41
 
 
4
  from openai import OpenAI
5
 
6
  openai_client = OpenAI(api_key = OPENAI_API_KEY)
7
+
8
  app = AppProvider(openai_client)
9
+ agents = app.provide_agents()
10
+
11
+ routing_expert = {
12
+ "customer_service" : {
13
+ "instance": agents.provide_cs_agent(),
14
+ "chat_template" : app.provide_chat_template("customer_service")
15
+ },
16
+ "bank_crud": {
17
+ "instance": agents.provide_banking_crud_agent(),
18
+ "chat_template" : {
19
+ "api_banking_template" : app.provide_chat_template("api_banking"),
20
+ "responder_template" : app.provide_chat_template("responder_banking")
21
+ }
22
+ }
23
+ }
24
+
25
+ agents.set_routing_expert(routing_expert)
26
+
27
  chatbot_ui = app.provide_chatbot().provide_chatbot_ui()
28
+
29
  rtc = app.provide_rtc()
30
  rtc_handler = rtc.provide_rtc_handler()
31
  rtc_gpt_handler = rtc.provide_rtc_gpt_handler()
 
41
 
42
  parser.add_argument("--port", default=7861, required=True)
43
  args = parser.parse_args()
44
+ match args.mode:
45
+ case "chatbot":
46
+ print("Launching Chabot UI :))))))")
47
+ chatbot_ui.launch(port = int(args.port))
48
+ case "rtc-server":
49
+ print("launching RTC Server Mode ... ")
50
+ rtc_handler.start_server(port = int(args.port))
51
+ case "rtc-ui":
52
+ print("launching RTC UI Mode ... ")
53
+ rtc_handler.launch_ui(port = int(args.port))
54
+ case "rtc-gpt-ui":
55
+ print("RTC GPT UI mode ...")
56
+ rtc_gpt_handler.launch_ui(port = int(args.port))
57
+ case "rtc-gpt-server":
58
+ rtc_gpt_handler.start_server(port = int(args.port))
59
+ case _:
60
+ print("ERROR : INVALID ARGUMENT | PLEASE CHOOSE ONE BETWEEN chatbot / rtc-server/ rtc-ui / rtc-gpt-server / rtc-gpt-ui mode ")
61
 
space/space/space/space/space/space/space/README.md CHANGED
@@ -48,30 +48,29 @@ OPENAI_API_KEY=your_openai_api_key_here
48
 
49
  #### Non-GPT Based UI
50
  ```bash
51
- python main.py --mode rtc-ui --port 8080
52
  ```
53
 
54
  #### GPT-Powered UI
55
  ```bash
56
- python main.py --mode rtc-gpt-ui --port 8080
57
  ```
58
 
59
  ### API Server
60
 
61
  #### Non-GPT Based Server
62
  ```bash
63
- python main.py --mode rtc-server --port 8080
64
  ```
65
 
66
  #### GPT-Powered Server
67
  ```bash
68
- python main.py --mode rtc-gpt-server --port 8080
69
  ```
70
 
71
  ### Chatbot Interface
72
  ```bash
73
- cd app
74
- python main.py --mode chatbot --port 8080
75
  ```
76
 
77
  ## 🐳 Docker Deployment
 
48
 
49
  #### Non-GPT Based UI
50
  ```bash
51
+ python main.py --mode rtc-ui --port 7860
52
  ```
53
 
54
  #### GPT-Powered UI
55
  ```bash
56
+ python main.py --mode rtc-gpt-ui --port 7860
57
  ```
58
 
59
  ### API Server
60
 
61
  #### Non-GPT Based Server
62
  ```bash
63
+ python main.py --mode rtc-server --port 7862
64
  ```
65
 
66
  #### GPT-Powered Server
67
  ```bash
68
+ python main.py --mode rtc-gpt-server --port 7862
69
  ```
70
 
71
  ### Chatbot Interface
72
  ```bash
73
+ python main.py --mode chatbot --port 7861
 
74
  ```
75
 
76
  ## 🐳 Docker Deployment
space/space/space/space/space/space/space/space/space/Dockerfile CHANGED
@@ -1,13 +1,10 @@
1
- # Gunakan image dasar Python versi 3.13
2
  FROM python:3.13
3
 
4
- # Tambahkan user non-root untuk keamanan
5
  RUN useradd -m -u 1001 appuser
6
 
7
- # Set working directory
8
  WORKDIR /rag_be
9
 
10
- # Set cache directories ke writable location
11
  ENV HF_HOME=/tmp/.cache/huggingface
12
  ENV TRANSFORMERS_CACHE=/tmp/.cache/transformers
13
  ENV TORCH_HOME=/tmp/.cache/torch
@@ -15,35 +12,26 @@ ENV XDG_CACHE_HOME=/tmp/.cache
15
  ENV TMPDIR=/tmp
16
  ENV WHISPER_CACHE_DIR=/tmp/.cache/whisper
17
 
18
- # Copy requirements dan install dependencies
19
- COPY requirements.txt ./
20
  RUN pip install --no-cache-dir --upgrade -r requirements.txt
21
 
22
- # Copy aplikasi dengan ownership ke appuser
23
  COPY --chown=appuser:appuser . /rag_be
24
 
25
- # Buat file .env dengan variabel environment menggunakan Hugging Face secrets
26
- RUN --mount=type=secret,id=OPENAI_API_KEY,mode=0444,required=false \
27
- --mount=type=secret,id=HF_TOKEN,mode=0444,required=false \
28
- --mount=type=secret,id=ELEVENLABS_API_KEY,mode=0444,required=false \
29
- echo "OPENAI_API_KEY=$(cat /run/secrets/OPENAI_API_KEY 2>/dev/null || echo '')" >> .env && \
30
- echo "HF_TOKEN=$(cat /run/secrets/HF_TOKEN 2>/dev/null || echo '')" >> .env && \
31
- echo "ELEVENLABS_API_KEY=$(cat /run/secrets/ELEVENLABS_API_KEY 2>/dev/null || echo '')" >> .env
32
-
33
- RUN ls -l /rag_be/app && whoami && id
34
-
35
- # Buat directories yang diperlukan dengan permissions yang tepat
36
- RUN mkdir -p /tmp/.cache /tmp/.cache/whisper /tmp/.cache/huggingface /rag_be/vectorstore /tmp/.cache/transformers /tmp/.cache/torch \
37
- /rag_be/app/vectorstore /rag_be/documents && \
38
- chmod -R 777 /tmp/.cache /rag_be/app /rag_be/app/vectorstore /rag_be/vectorstore /rag_be/documents && \
39
- chown -R appuser:appuser /tmp/.cache /rag_be/app /rag_be/app/vectorstore /rag_be/vectorstore /rag_be/documents /rag_be/.env
40
-
41
- RUN apt-get update && apt-get install -y ffmpeg
42
- # Beralih ke user non-root
43
  USER appuser
44
 
45
- # Expose port untuk Hugging Face Spaces
46
- EXPOSE 7860
47
 
48
- # Jalankan aplikasi
49
- CMD ["python", "app/__test__.py"]
 
1
+
2
  FROM python:3.13
3
 
 
4
  RUN useradd -m -u 1001 appuser
5
 
 
6
  WORKDIR /rag_be
7
 
 
8
  ENV HF_HOME=/tmp/.cache/huggingface
9
  ENV TRANSFORMERS_CACHE=/tmp/.cache/transformers
10
  ENV TORCH_HOME=/tmp/.cache/torch
 
12
  ENV TMPDIR=/tmp
13
  ENV WHISPER_CACHE_DIR=/tmp/.cache/whisper
14
 
15
+ COPY requirements.txt ./
 
16
  RUN pip install --no-cache-dir --upgrade -r requirements.txt
17
 
 
18
  COPY --chown=appuser:appuser . /rag_be
19
 
20
+ RUN mkdir -p /tmp/.cache \
21
+ /tmp/.cache/whisper \
22
+ /tmp/.cache/huggingface \
23
+ /tmp/.cache/transformers \
24
+ /tmp/.cache/torch \
25
+ /rag_be/vectorstore \
26
+ /rag_be/app/vectorstore \
27
+ /rag_be/documents && \
28
+ chmod -R 777 /tmp/.cache /rag_be/app /rag_be/vectorstore /rag_be/documents
29
+
30
+
31
+ RUN apt-get update && apt-get install -y ffmpeg && apt-get clean
32
+
 
 
 
 
 
33
  USER appuser
34
 
35
+ EXPOSE 8000
 
36
 
37
+ CMD ["python", "main.py --mode rtc-ui --port 7860"]
 
space/space/space/space/space/space/space/space/space/space/space/space/space/README.md CHANGED
@@ -104,21 +104,3 @@ docker run -p 8080:8080 cs-ai-sakura-dev
104
  Once the server is running, you can access the API documentation at:
105
  - `http://localhost:{port}/docs` (if using FastAPI)
106
  - `http://localhost:{port}` (for Gradio interface)
107
-
108
-
109
- ## πŸ—οΈ Project Structure
110
-
111
- ```
112
- cs-ai-sakura-dev/
113
- β”œβ”€β”€ app/
114
- β”‚ └── main.py # Chatbot application
115
- β”œβ”€β”€ main.py # Main application entry point
116
- β”œβ”€β”€ requirements.txt # Python dependencies
117
- β”œβ”€β”€ .env # Environment variables (create this)
118
- β”œβ”€β”€ Dockerfile # Docker configuration
119
- └── README.md # Project documentation
120
- ```
121
-
122
- ---
123
-
124
- **Happy coding! 🌸**
 
104
  Once the server is running, you can access the API documentation at:
105
  - `http://localhost:{port}/docs` (if using FastAPI)
106
  - `http://localhost:{port}` (for Gradio interface)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/README.md CHANGED
@@ -1,34 +1,124 @@
1
- ---
2
- title: Cs Ai Sakura Dev
3
- emoji: 🏒
4
- colorFrom: indigo
5
- colorTo: indigo
6
- sdk: docker
7
- pinned: false
8
- ---
 
 
 
 
9
 
10
- **Install The Requirements**
11
 
12
- 1.Create a virtual environment and install the dependencies
 
 
 
 
 
 
 
 
 
13
  ```
 
 
 
14
  python3 -m venv env
15
- source env/bin/activate
 
 
 
 
16
  pip install -r requirements.txt
17
  ```
18
 
19
- 2. Set your OPENAI_API_KEY in .env file
 
 
 
 
 
 
 
 
20
 
21
- 3. **TO LAUNCH THE GRADIO UI** Run the command below :
 
 
22
  ```
23
- python main.py --mode rtc-ui --port {your_port}
 
 
 
24
  ```
25
 
26
- 4. **TO LAUNCH THE API ENDPOINT (SERVER)** Run the command below :
 
 
 
 
27
  ```
28
- python main.py --mode rtc-server --port {your_port}
 
 
 
29
  ```
30
 
31
- 5. **TO LAUNCH THE CHATBOT UI** Run the command below :
 
 
 
32
  ```
33
- python main.py --mode chatbot --port {your_port}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CS AI Sakura Dev 🏒
2
+
3
+ A comprehensive AI-powered application with multiple modes including RTC (Real-Time Communication), GPT integration, and chatbot functionality.
4
+
5
+ ## πŸš€ Features
6
+
7
+ - **RTC Mode**: Real-time communication interface
8
+ - **GPT Integration**: Enhanced AI capabilities with OpenAI GPT models
9
+ - **Chatbot Interface**: Interactive chat functionality
10
+ - **Gradio UI**: User-friendly web interface
11
+ - **API Server**: RESTful API endpoints
12
+ - **Docker Support**: Containerized deployment
13
 
14
+ ## πŸ“‹ Prerequisites
15
 
16
+ - Python 3.8 or higher
17
+ - OpenAI API Key
18
+ - Docker (optional)
19
+
20
+ ## βš™οΈ Installation
21
+
22
+ ### 1. Clone the Repository
23
+ ```bash
24
+ git clone <repository-url>
25
+ cd cs-ai-sakura-dev
26
  ```
27
+
28
+ ### 2. Create Virtual Environment
29
+ ```bash
30
  python3 -m venv env
31
+ source env/bin/activate # On Windows: env\Scripts\activate
32
+ ```
33
+
34
+ ### 3. Install Dependencies
35
+ ```bash
36
  pip install -r requirements.txt
37
  ```
38
 
39
+ ### 4. Environment Configuration
40
+ Create a `.env` file in the root directory and add your OpenAI API key:
41
+ ```bash
42
+ OPENAI_API_KEY=your_openai_api_key_here
43
+ ```
44
+
45
+ ## πŸ–₯️ Usage
46
+
47
+ ### Gradio Web Interface
48
 
49
+ #### Non-GPT Based UI
50
+ ```bash
51
+ python main.py --mode rtc-ui --port 8080
52
  ```
53
+
54
+ #### GPT-Powered UI
55
+ ```bash
56
+ python main.py --mode rtc-gpt-ui --port 8080
57
  ```
58
 
59
+ ### API Server
60
+
61
+ #### Non-GPT Based Server
62
+ ```bash
63
+ python main.py --mode rtc-server --port 8080
64
  ```
65
+
66
+ #### GPT-Powered Server
67
+ ```bash
68
+ python main.py --mode rtc-gpt-server --port 8080
69
  ```
70
 
71
+ ### Chatbot Interface
72
+ ```bash
73
+ cd app
74
+ python main.py --mode chatbot --port 8080
75
  ```
76
+
77
+ ## 🐳 Docker Deployment
78
+
79
+ The application supports Docker deployment. Build and run the container:
80
+
81
+ ```bash
82
+ docker build -t cs-ai-sakura-dev .
83
+ docker run -p 8080:8080 cs-ai-sakura-dev
84
+ ```
85
+
86
+ ## πŸ“š Available Modes
87
+
88
+ | Mode | Description | Command |
89
+ |------|-------------|---------|
90
+ | `rtc-ui` | Real-time communication web interface | `python main.py --mode rtc-ui --port {port}` |
91
+ | `rtc-gpt-ui` | GPT-powered real-time communication UI | `python main.py --mode rtc-gpt-ui --port {port}` |
92
+ | `rtc-server` | Real-time communication API server | `python main.py --mode rtc-server --port {port}` |
93
+ | `rtc-gpt-server` | GPT-powered API server | `python main.py --mode rtc-gpt-server --port {port}` |
94
+ | `chatbot` | Interactive chatbot interface | `cd app && python main.py --mode chatbot --port {port}` |
95
+
96
+ ## πŸ”§ Configuration
97
+
98
+ ### Environment Variables
99
+ - `OPENAI_API_KEY`: Your OpenAI API key (required for GPT modes)
100
+ - `PORT`: Application port (default: 8080)
101
+
102
+ ## πŸ“– API Documentation
103
+
104
+ Once the server is running, you can access the API documentation at:
105
+ - `http://localhost:{port}/docs` (if using FastAPI)
106
+ - `http://localhost:{port}` (for Gradio interface)
107
+
108
+
109
+ ## πŸ—οΈ Project Structure
110
+
111
  ```
112
+ cs-ai-sakura-dev/
113
+ β”œβ”€β”€ app/
114
+ β”‚ └── main.py # Chatbot application
115
+ β”œβ”€β”€ main.py # Main application entry point
116
+ β”œβ”€β”€ requirements.txt # Python dependencies
117
+ β”œβ”€β”€ .env # Environment variables (create this)
118
+ β”œβ”€β”€ Dockerfile # Docker configuration
119
+ └── README.md # Project documentation
120
+ ```
121
+
122
+ ---
123
+
124
+ **Happy coding! 🌸**
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/data/prompt_template/customer_service.txt CHANGED
@@ -1,12 +1,12 @@
1
- You are a friendly and professional Customer Service for Human Resource Information System (HRIS) field,
2
- representative, fluent in Indonesian. Your job is to assist customers with accurate information based on your company's basic knowledge. Follow these guidelines:
3
 
4
- - Always greet customers in a friendly and professional manner.
5
- - Your answers are contextual and objective.
6
- - Provide clear, easy-to-understand, and structured answers based on the context provided by the user.
7
- - If information is not available, offer alternative assistance or direct them to the appropriate channel.
8
- - Use polite language and empathize with the customer's needs.
9
- - Conclude by offering further assistance.
10
- - You are highly skilled in the area relevant to the given context.
11
 
12
- Please use the given context to answer accurately.
 
1
+ Anda adalah seorang Customer Service yang ramah dan profesional di bidang Human Resource Information System (HRIS),
2
+ fasih berbahasa Indonesia. Tugas Anda adalah membantu pelanggan dengan informasi yang akurat berdasarkan pengetahuan dasar perusahaan Anda. Ikuti panduan berikut:
3
 
4
+ - Selalu menyapa pelanggan dengan ramah dan profesional.
5
+ - Jawaban Anda kontekstual dan objektif.
6
+ - Berikan jawaban yang jelas, mudah dipahami, dan terstruktur berdasarkan konteks yang diberikan oleh pengguna.
7
+ - Jika informasi tidak tersedia, tawarkan bantuan alternatif atau arahkan mereka ke saluran yang tepat.
8
+ - Gunakan bahasa yang sopan dan berempati terhadap kebutuhan pelanggan.
9
+ - Akhiri dengan menawarkan bantuan lebih lanjut.
10
+ - Anda sangat terampil di bidang yang relevan dengan konteks yang diberikan.
11
 
12
+ Harap gunakan konteks yang diberikan untuk menjawab dengan akurat.
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/main.py CHANGED
@@ -1,10 +1,14 @@
1
  import argparse
2
  from src.provider import AppProvider
 
 
3
 
4
- app = AppProvider()
 
5
  chatbot_ui = app.provide_chatbot().provide_chatbot_ui()
6
  rtc = app.provide_rtc()
7
  rtc_handler = rtc.provide_rtc_handler()
 
8
 
9
  parser = argparse.ArgumentParser()
10
  parser.add_argument("--mode", choices=[
@@ -27,6 +31,11 @@ elif(args.mode == "rtc-server"):
27
  elif(args.mode == "rtc-ui"):
28
  print("launching RTC UI Mode ... ")
29
  rtc_handler.launch_ui(port = int(args.port))
 
 
 
 
 
30
  else:
31
- print("ERROR : INVALID ARGUMENT | PLEASE CHOOSE ONE BETWEEN chatbot/rtc-server/rtc-ui mode ")
32
 
 
1
  import argparse
2
  from src.provider import AppProvider
3
+ from src.config import OPENAI_API_KEY
4
+ from openai import OpenAI
5
 
6
+ openai_client = OpenAI(api_key = OPENAI_API_KEY)
7
+ app = AppProvider(openai_client)
8
  chatbot_ui = app.provide_chatbot().provide_chatbot_ui()
9
  rtc = app.provide_rtc()
10
  rtc_handler = rtc.provide_rtc_handler()
11
+ rtc_gpt_handler = rtc.provide_rtc_gpt_handler()
12
 
13
  parser = argparse.ArgumentParser()
14
  parser.add_argument("--mode", choices=[
 
31
  elif(args.mode == "rtc-ui"):
32
  print("launching RTC UI Mode ... ")
33
  rtc_handler.launch_ui(port = int(args.port))
34
+ elif(args.mode == "rtc-gpt-ui"):
35
+ print("RTC GPT UI mode ...")
36
+ rtc_gpt_handler.launch_ui(port = int(args.port))
37
+ elif(args.mode == "rtc-gpt-server"):
38
+ rtc_gpt_handler.start_server(port = int(args.port))
39
  else:
40
+ print("ERROR : INVALID ARGUMENT | PLEASE CHOOSE ONE BETWEEN chatbot / rtc-server/ rtc-ui / rtc-gpt-server / rtc-gpt-ui mode ")
41
 
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/README.md CHANGED
@@ -25,12 +25,10 @@ python main.py --mode rtc-ui --port {your_port}
25
 
26
  4. **TO LAUNCH THE API ENDPOINT (SERVER)** Run the command below :
27
  ```
28
- cd app
29
  python main.py --mode rtc-server --port {your_port}
30
  ```
31
 
32
  5. **TO LAUNCH THE CHATBOT UI** Run the command below :
33
  ```
34
- cd app
35
  python main.py --mode chatbot --port {your_port}
36
  ```
 
25
 
26
  4. **TO LAUNCH THE API ENDPOINT (SERVER)** Run the command below :
27
  ```
 
28
  python main.py --mode rtc-server --port {your_port}
29
  ```
30
 
31
  5. **TO LAUNCH THE CHATBOT UI** Run the command below :
32
  ```
 
33
  python main.py --mode chatbot --port {your_port}
34
  ```
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/README.md CHANGED
@@ -29,7 +29,7 @@ cd app
29
  python main.py --mode rtc-server --port {your_port}
30
  ```
31
 
32
- 54. **TO LAUNCH THE CHATBOT UI** Run the command below :
33
  ```
34
  cd app
35
  python main.py --mode chatbot --port {your_port}
 
29
  python main.py --mode rtc-server --port {your_port}
30
  ```
31
 
32
+ 5. **TO LAUNCH THE CHATBOT UI** Run the command below :
33
  ```
34
  cd app
35
  python main.py --mode chatbot --port {your_port}