commit 530c24b019c1d4a5884a60f5a5cb16e9c1554018 Author: royalcat Date: Mon Dec 23 15:54:51 2024 +0300 wip diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 0000000..db1d809 --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,59 @@ +name: docker + +on: + push: + branches: + - master + tags: + - "v*" + +jobs: + build-docker: + permissions: + contents: read + packages: write + runs-on: ubuntu-latest + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Container Registry + uses: docker/login-action@v3 + with: + registry: git.kmsign.ru + username: ${{ github.actor }} + password: ${{ secrets.PACKAGE_TOKEN }} + + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Docker meta + id: meta + # uses: https://github.com/docker/metadata-action@v5 + uses: docker/metadata-action@v5 + with: + # list of Docker images to use as base name for tags + images: git.kmsign.ru/${{ github.repository }} + # generate Docker tags based on the following events/attributes + tags: | + type=schedule + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + pull: true + platforms: linux/amd64 #, linux/arm64 + labels: ${{ steps.meta.outputs.labels }} + sbom: true + provenance: true + # cache-from: type=gha + # cache-to: type=gha,mode=max + tags: ${{ steps.meta.outputs.tags }} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d3c530e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch file", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/cmd/main.go", + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..30646cb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "protoc": { + "path": "protoc", + "options": [ + "--proto_path=proto", + ] + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1e181c8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +FROM golang:1.23 AS build +RUN go build -v std + +WORKDIR /app + +COPY go.mod ./ +COPY go.sum ./ +RUN go mod download + +COPY ./cmd ./cmd +COPY ./pkg ./pkg +COPY ./src ./src + +RUN go build -tags timetzdata -o /server ./cmd/main.go + +# run container +FROM scratch + +#Adding root serts for ssl +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +COPY --from=build /server /app/konfa-server + +WORKDIR /app + +ENTRYPOINT [ "/app/konfa-server" ] \ No newline at end of file diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 0000000..6ad9980 --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,26 @@ +# version: v2 +# clean: true +# plugins: +# - local: protoc-gen-go +# out: internal/proto/gen +# opt: paths=source_relative + +version: v2 +managed: + enabled: true + override: + - file_option: go_package_prefix + value: github.com/royalcat/konfa-server/src/proto +plugins: + - remote: buf.build/grpc/go + out: src/proto + opt: + - paths=source_relative + - require_unimplemented_servers=false + - remote: buf.build/protocolbuffers/go + out: src/proto + opt: + - paths=source_relative + +inputs: + - directory: proto diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 0000000..2a85a61 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,12 @@ +# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml +version: v2 +deps: + - buf.build/protocolbuffers/wellknowntypes:v21.12 +modules: + - path: proto +lint: + use: + - STANDARD +breaking: + use: + - FILE diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..3cec285 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,88 @@ +package main + +import ( + "context" + "fmt" + "log" + "net" + + "github.com/royalcat/konfa-server/pkg/uuid" + "github.com/royalcat/konfa-server/src/konfa" + "github.com/royalcat/konfa-server/src/proto" + chatv1 "github.com/royalcat/konfa-server/src/proto/konfa/chat/v1" + serverv1 "github.com/royalcat/konfa-server/src/proto/konfa/server/v1" + "github.com/royalcat/konfa-server/src/store" + "google.golang.org/grpc" +) + +func main() { + ctx := context.Background() + db, dbpool, err := store.ConnectPostgres(ctx, "postgres://localhost:5432/konfa?sslmode=disable&user=konfa&password=konfa") + if err != nil { + panic(err) + } + + srv := konfa.NewService(db, dbpool) + + grpcServer := grpc.NewServer(grpc.UnaryInterceptor(proto.Authenticate)) + chatv1.RegisterChatServiceServer(grpcServer, proto.NewChatService(srv)) + serverv1.RegisterServerServiceServer(grpcServer, proto.NewServerService(srv)) + + serverID, chanID, err := createKonfach(ctx, srv) + if err != nil { + panic(err) + } + + println(serverID.String()) + println(chanID.String()) + + port := 38100 + + lis, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port)) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + + println("Server is running on port", port) + panic(grpcServer.Serve(lis)) +} + +func createKonfach(ctx context.Context, srv *konfa.Service) (uuid.UUID, uuid.UUID, error) { + var serverID uuid.UUID + + servers, err := srv.ListServers(ctx) + if err != nil { + return uuid.Nil, uuid.Nil, fmt.Errorf("failed to list servers: %w", err) + } + for _, serv := range servers { + if serv.Name == "konfach" { + serverID = serv.ID + } + } + if serverID == uuid.Nil { + serverID, err = srv.CreateServer(ctx, "konfach") + if err != nil { + return uuid.Nil, uuid.Nil, fmt.Errorf("failed to create server: %w", err) + } + } + + var chanID uuid.UUID + + channels, err := srv.ListChannelsOnServer(ctx, serverID) + if err != nil { + return uuid.Nil, uuid.Nil, err + } + for _, channel := range channels { + if channel.Name == "general" { + chanID = channel.ID + } + } + if chanID == uuid.Nil { + chanID, err = srv.CreateChannel(ctx, serverID, "general") + if err != nil { + return uuid.Nil, uuid.Nil, fmt.Errorf("failed to create channel: %w", err) + } + } + + return serverID, chanID, nil +} diff --git a/dev.compose.yaml b/dev.compose.yaml new file mode 100644 index 0000000..9bd9d41 --- /dev/null +++ b/dev.compose.yaml @@ -0,0 +1,13 @@ +services: + postgres: + image: postgres:16 + ports: + - 5432:5432 + volumes: + - data:/var/lib/postgresql/data + environment: + - POSTGRES_PASSWORD=konfa + - POSTGRES_USER=konfa + - POSTGRES_DB=konfa +volumes: + data: diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..af2b453 --- /dev/null +++ b/go.mod @@ -0,0 +1,61 @@ +module github.com/royalcat/konfa-server + +go 1.23.3 + +require ( + github.com/Masterminds/squirrel v1.5.4 + github.com/cskr/pubsub/v2 v2.0.2 + github.com/gofrs/uuid/v5 v5.3.0 + github.com/golang-migrate/migrate/v4 v4.18.1 + github.com/jackc/pgx/v5 v5.7.1 + github.com/pressly/goose/v3 v3.23.0 + github.com/uptrace/bun v1.2.6 + github.com/uptrace/bun/dialect/pgdialect v1.2.6 + github.com/uptrace/bun/extra/bundebug v1.2.6 + github.com/uptrace/bun/extra/bunotel v1.2.6 + go.mongodb.org/mongo-driver v1.17.1 + google.golang.org/grpc v1.68.1 + google.golang.org/protobuf v1.35.2 + gorm.io/gorm v1.25.10 +) + +require ( + github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/buger/jsonparser v1.1.1 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect + github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mfridman/interpolate v0.0.2 // indirect + github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect + github.com/sethvargo/go-retry v0.3.0 // indirect + github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.9-0.20240816141633-0a40785b4f41 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.19.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a29e9d9 --- /dev/null +++ b/go.sum @@ -0,0 +1,191 @@ +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= +github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/cskr/pubsub/v2 v2.0.2 h1:395hhPXEsyI1b+5nfj+s5Q3gdxpg0jsWd3t/QAdmU1Y= +github.com/cskr/pubsub/v2 v2.0.2/go.mod h1:XYuiN8dhcXTCzQDa5SH4+B3zLso94FTwAk0maAEGJJw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dhui/dktest v0.4.3 h1:wquqUxAFdcUgabAVLvSCOKOlag5cIZuaOjYIBOWdsR0= +github.com/dhui/dktest v0.4.3/go.mod h1:zNK8IwktWzQRm6I/l2Wjp7MakiyaFWv4G1hjmodmMTs= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= +github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= +github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y= +github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= +github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= +github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pressly/goose/v3 v3.23.0 h1:57hqKos8izGek4v6D5+OXBa+Y4Rq8MU//+MmnevdpVA= +github.com/pressly/goose/v3 v3.23.0/go.mod h1:rpx+D9GX/+stXmzKa+uh1DkjPnNVMdiOCV9iLdle4N8= +github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= +github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= +github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= +github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= +github.com/uptrace/bun v1.2.6 h1:lyGBQAhNiClchb97HA2cBnDeRxwTRLhSIgiFPXVisV8= +github.com/uptrace/bun v1.2.6/go.mod h1:xMgnVFf+/5xsrFBU34HjDJmzZnXbVuNEt/Ih56I8qBU= +github.com/uptrace/bun/dialect/pgdialect v1.2.6 h1:iNd1YLx619K+sZK+dRcWPzluurXYK1QwIkp9FEfNB/8= +github.com/uptrace/bun/dialect/pgdialect v1.2.6/go.mod h1:OL7d3qZLxKYP8kxNhMg3IheN1pDR3UScGjoUP+ivxJQ= +github.com/uptrace/bun/extra/bundebug v1.2.6 h1:5l61LXIR2YWk/gqGSq5esha+x/qPPyhtQKORAuTfV34= +github.com/uptrace/bun/extra/bundebug v1.2.6/go.mod h1:11C5ajtPrFcmIRo31TfQrmK5D2LgNIxxTQEZMz6lD2k= +github.com/uptrace/bun/extra/bunotel v1.2.6 h1:6m90acv9hsDuTYRo3oiKCWMatGPmi+feKAx8Y/GPj9A= +github.com/uptrace/bun/extra/bunotel v1.2.6/go.mod h1:QGqnFNJ2H88juh7DmgdPJZVN9bSTpj7UaGllSO9JDKk= +github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2 h1:ZjUj9BLYf9PEqBn8W/OapxhPjVRdC6CsXTdULHsyk5c= +github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2/go.mod h1:O8bHQfyinKwTXKkiKNGmLQS7vRsqRxIQTFZpYpHK3IQ= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/wk8/go-ordered-map/v2 v2.1.9-0.20240816141633-0a40785b4f41 h1:rnB8ZLMeAr3VcqjfRkAm27qb8y6zFKNfuHvy1Gfe7KI= +github.com/wk8/go-ordered-map/v2 v2.1.9-0.20240816141633-0a40785b4f41/go.mod h1:DbzwytT4g/odXquuOCqroKvtxxldI4nb3nuesHF/Exo= +go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM= +go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= +google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= +modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= +modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/sqlite v1.34.1 h1:u3Yi6M0N8t9yKRDwhXcyp1eS5/ErhPTBggxWFuR6Hfk= +modernc.org/sqlite v1.34.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/pkg/broadcast/broadcast.go b/pkg/broadcast/broadcast.go new file mode 100644 index 0000000..031cad2 --- /dev/null +++ b/pkg/broadcast/broadcast.go @@ -0,0 +1,91 @@ +/* +Package broadcast provides pubsub of messages over channels. + +A provider has a Broadcaster into which it Submits messages and into +which subscribers Register to pick up those messages. +*/ +package broadcast + +type Broadcaster[T any] struct { + input chan T + reg chan chan<- T + unreg chan chan<- T + + outputs map[chan<- T]bool +} + +func (b *Broadcaster[T]) broadcast(m T) { + for ch := range b.outputs { + ch <- m + } +} + +func (b *Broadcaster[T]) run() { + for { + select { + case m := <-b.input: + b.broadcast(m) + case ch, ok := <-b.reg: + if ok { + b.outputs[ch] = true + } else { + return + } + case ch := <-b.unreg: + delete(b.outputs, ch) + } + } +} + +// NewBroadcaster creates a new broadcaster with the given input +// channel buffer length. +func NewBroadcaster[T any](buflen int) *Broadcaster[T] { + b := &Broadcaster[T]{ + input: make(chan T, buflen), + reg: make(chan chan<- T), + unreg: make(chan chan<- T), + outputs: make(map[chan<- T]bool), + } + + go b.run() + + return b +} + +// Register a new channel to receive broadcasts +func (b *Broadcaster[T]) Register(newch chan<- T) { + b.reg <- newch +} + +// Unregister a channel so that it no longer receives broadcasts. +func (b *Broadcaster[T]) Unregister(newch chan<- T) { + b.unreg <- newch +} + +// Shut this broadcaster down. +func (b *Broadcaster[T]) Close() error { + close(b.reg) + close(b.unreg) + return nil +} + +// Submit an item to be broadcast to all listeners. +func (b *Broadcaster[T]) Submit(m T) { + if b != nil { + b.input <- m + } +} + +// TrySubmit attempts to submit an item to be broadcast, returning +// true iff it the item was broadcast, else false. +func (b *Broadcaster[T]) TrySubmit(m T) bool { + if b == nil { + return false + } + select { + case b.input <- m: + return true + default: + return false + } +} diff --git a/pkg/broadcast/broadcast_test.go b/pkg/broadcast/broadcast_test.go new file mode 100644 index 0000000..f35eb92 --- /dev/null +++ b/pkg/broadcast/broadcast_test.go @@ -0,0 +1,120 @@ +package broadcast + +import ( + "sync" + "testing" +) + +func TestBroadcast(t *testing.T) { + wg := sync.WaitGroup{} + + b := NewBroadcaster[int](100) + defer b.Close() + + for i := 0; i < 5; i++ { + wg.Add(1) + + cch := make(chan int) + + b.Register(cch) + + go func() { + defer wg.Done() + defer b.Unregister(cch) + <-cch + }() + + } + + b.Submit(1) + + wg.Wait() +} + +func TestBroadcastTrySubmit(t *testing.T) { + b := NewBroadcaster[int](1) + defer b.Close() + + if ok := b.TrySubmit(0); !ok { + t.Fatalf("1st TrySubmit assert error expect=true actual=%v", ok) + } + + if ok := b.TrySubmit(1); ok { + t.Fatalf("2nd TrySubmit assert error expect=false actual=%v", ok) + } + + cch := make(chan int) + b.Register(cch) + + if ok := b.TrySubmit(1); !ok { + t.Fatalf("3rd TrySubmit assert error expect=true actual=%v", ok) + } +} + +func TestBroadcastCleanup(t *testing.T) { + b := NewBroadcaster[int](100) + b.Register(make(chan int)) + b.Close() +} + +func echoer(chin, chout chan interface{}) { + for m := range chin { + chout <- m + } +} + +func BenchmarkDirectSend(b *testing.B) { + chout := make(chan interface{}) + chin := make(chan interface{}) + defer close(chin) + + go echoer(chin, chout) + + for i := 0; i < b.N; i++ { + chin <- nil + <-chout + } +} + +func BenchmarkBrodcast(b *testing.B) { + chout := make(chan int) + + bc := NewBroadcaster[int](0) + defer bc.Close() + bc.Register(chout) + + for i := 0; i < b.N; i++ { + bc.Submit(1) + <-chout + } +} + +func BenchmarkParallelDirectSend(b *testing.B) { + chout := make(chan interface{}) + chin := make(chan interface{}) + defer close(chin) + + go echoer(chin, chout) + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + chin <- nil + <-chout + } + }) +} + +func BenchmarkParallelBrodcast(b *testing.B) { + chout := make(chan int) + + bc := NewBroadcaster[int](0) + defer bc.Close() + bc.Register(chout) + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + bc.Submit(1) + <-chout + } + }) +} diff --git a/pkg/broadcast/subscription.go b/pkg/broadcast/subscription.go new file mode 100644 index 0000000..aa270f6 --- /dev/null +++ b/pkg/broadcast/subscription.go @@ -0,0 +1 @@ +package broadcast diff --git a/pkg/uuid/uuid.go b/pkg/uuid/uuid.go new file mode 100644 index 0000000..24294f8 --- /dev/null +++ b/pkg/uuid/uuid.go @@ -0,0 +1,161 @@ +package uuid + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "strconv" + "time" + + fuuid "github.com/gofrs/uuid/v5" + "github.com/jackc/pgx/v5/pgtype" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +var Nil = UUID{} + +type UUIDList = []UUID + +type UUID struct { + fuuid.UUID +} + +func New() UUID { + return UUID{fuuid.Must(fuuid.NewV7())} +} + +func NewFromTime(t time.Time) UUID { + gen := fuuid.NewGenWithOptions( + fuuid.WithEpochFunc(func() time.Time { return t }), + ) + return UUID{fuuid.Must(gen.NewV7())} +} + +func NewP() *UUID { + return &UUID{fuuid.Must(fuuid.NewV7())} +} + +func FromString(text string) (UUID, error) { + u, err := fuuid.FromString(text) + if err != nil { + return Nil, err + } + + return UUID{u}, nil +} + +func MustFromString(text string) UUID { + u, err := fuuid.FromString(text) + if err != nil { + panic(err) + } + + return UUID{u} +} + +func FromBytes(input []byte) (UUID, error) { + u, err := fuuid.FromBytes(input) + if err != nil { + return Nil, err + } + + return UUID{u}, nil +} + +func (a *UUID) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + if s == "" { + a.UUID = fuuid.Nil + return nil + } + + return a.UUID.Parse(s) +} + +func (a UUID) MarshalJSON() ([]byte, error) { + if a.IsNil() { + return json.Marshal("") + } + + return json.Marshal(a.UUID) +} + +// UnmarshalGQL implements the graphql.Unmarshaler interface +func (u *UUID) UnmarshalGQL(v interface{}) error { + id, ok := v.(string) + if !ok { + return fmt.Errorf("uuid must be a string") + } + + return u.Parse(id) +} + +// MarshalGQL implements the graphql.Marshaler interface +func (u UUID) MarshalGQL(w io.Writer) { + b := []byte(strconv.Quote(u.String())) + _, err := w.Write(b) + if err != nil { + panic(err) + } +} + +const uuidSubtype = 4 + +// MarshalBSONValue для официального mongo драйвера (go.mongodb.org/mongo-driver/mongo) +func (id UUID) MarshalBSONValue() (bsontype.Type, []byte, error) { + if id.IsNil() { + return bsontype.Null, nil, nil + } else { + bin := bsoncore.AppendBinary(nil, uuidSubtype, id.UUID.Bytes()) + return bson.TypeBinary, bin, nil + } +} + +// MarshalBSONValue для официального mongo драйвера (go.mongodb.org/mongo-driver/mongo) +func (id *UUID) UnmarshalBSONValue(t bsontype.Type, data []byte) error { + switch t { + case bsontype.Null, bsontype.Undefined: + id = &UUID{} // nil uuid value 00000000-0000-0000-0000-000000000000 + return nil + case bsontype.Binary: + subtype, bin, _, ok := bsoncore.ReadBinary(data) + if !ok { + return errors.New("invalid bson binary value") + } + if subtype != uuidSubtype && subtype != 3 { // 3 is a deprecated uuid subtype, used for compatibility + return fmt.Errorf("unsupported binary subtype for uuid: %d", subtype) + } + return id.UUID.UnmarshalBinary(bin) + default: + return fmt.Errorf("unsupported value type for uuid: %s", t.String()) + } +} + +var _ pgtype.UUIDValuer = UUID{} + +// UUIDValue implements pgtype.UUIDValuer. +func (a UUID) UUIDValue() (pgtype.UUID, error) { + return pgtype.UUID{ + Bytes: a.UUID, + Valid: true, + }, nil +} + +var _ pgtype.UUIDScanner = (*UUID)(nil) + +// ScanUUID implements pgtype.UUIDScanner. +func (a *UUID) ScanUUID(v pgtype.UUID) error { + if !v.Valid { + return fmt.Errorf("cannot scan NULL into *uuid.UUID") + } + + a.UUID = v.Bytes + return nil +} diff --git a/proto/konfa/channel/v1/channels.proto b/proto/konfa/channel/v1/channels.proto new file mode 100644 index 0000000..dd7c290 --- /dev/null +++ b/proto/konfa/channel/v1/channels.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +package konfa.channel.v1; + +option go_package = "/channelv1"; + +// import "google/protobuf/timestamp.proto"; + +message Channel { + oneof channel { + TextChannel text_channel = 1; + VoiceChannel voice_channel = 2; + } +} + +message TextChannel { + string server_id = 1; + string channel_id = 2; + string name = 3; +} + +message VoiceChannel { + string server_id = 1; + string channel_id = 2; + string name = 3; +} + diff --git a/proto/konfa/chat/v1/service.proto b/proto/konfa/chat/v1/service.proto new file mode 100644 index 0000000..73a6f4b --- /dev/null +++ b/proto/konfa/chat/v1/service.proto @@ -0,0 +1,69 @@ +syntax = "proto3"; + +package konfa.chat.v1; + +option go_package = "/chatv1"; + +import "google/protobuf/timestamp.proto"; + +service ChatService { + rpc SendMessage(SendMessageRequest) returns (SendMessageResponse) {} + rpc GetMessageHistory(GetMessageHistoryRequest) returns (GetMessageHistoryResponse) {} + rpc GetMessage(GetMessageRequest) returns (GetMessageResponse) {} + rpc StreamNewMessages(StreamNewMessagesRequest) + returns (stream StreamNewMessagesResponse) {} + rpc UploadAttachment(stream UploadAttachmentRequest) returns (UploadAttachmentResponse) {} +} + +message TextChannelRef { + string server_id = 1; + string channel_id = 2; +} + +message SendMessageRequest { + TextChannelRef channel = 1; + string content = 2; +} + +message SendMessageResponse { + string message_id = 1; +} + +message Message { + string message_id = 1; + string sender_id = 4; + string content = 5; + google.protobuf.Timestamp timestamp = 6; +} + +message GetMessageHistoryRequest { + TextChannelRef channel = 1; + google.protobuf.Timestamp from = 2; + int32 count = 3; + } + +message GetMessageHistoryResponse { repeated Message messages = 1; } + +message GetMessageRequest { + TextChannelRef channel = 1; + string message_id = 2; + } + + message GetMessageResponse { Message message = 1; } + +message StreamNewMessagesRequest { TextChannelRef channel = 1; } + +message StreamNewMessagesResponse { string message_id = 1; } + +message UploadAttachmentRequest { + oneof payload { + AttachmentUploadInfo info = 1; + bytes data = 2 ; + } +} + +message AttachmentUploadInfo { + string name = 1; +} + +message UploadAttachmentResponse { string attachmen_id = 1; } \ No newline at end of file diff --git a/proto/konfa/server/v1/service.proto b/proto/konfa/server/v1/service.proto new file mode 100644 index 0000000..130e9a8 --- /dev/null +++ b/proto/konfa/server/v1/service.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package konfa.server.v1; + +option go_package = "/serverv1"; + +// import "google/protobuf/timestamp.proto"; +import "konfa/channel/v1/channels.proto"; + +service ServerService { + rpc ListServerChannels(ListServerChannelsRequest) returns (ListServerChannelsResponse) {} +} + +message ListServerChannelsRequest { + string server_id = 1; +} + +message ListServerChannelsResponse { + repeated konfa.channel.v1.Channel channels = 1; +} \ No newline at end of file diff --git a/src/konfa/channel.go b/src/konfa/channel.go new file mode 100644 index 0000000..7bf43e8 --- /dev/null +++ b/src/konfa/channel.go @@ -0,0 +1,44 @@ +package konfa + +import ( + "context" + + "github.com/royalcat/konfa-server/pkg/uuid" + "github.com/royalcat/konfa-server/src/store" +) + +func (c *Service) CreateChannel(ctx context.Context, serverID uuid.UUID, name string) (uuid.UUID, error) { + channel := store.TextChannel{ + ID: uuid.New(), + ServerID: serverID, + Name: name, + } + + var idrow store.IDRow + _, err := c.db.NewInsert().Model(&channel).Returning("id").Exec(ctx, &idrow) + if err != nil { + return idrow.ID, err + } + + return idrow.ID, nil +} + +func (c *Service) GetChannel(ctx context.Context, serverID uuid.UUID, channelID uuid.UUID) (store.TextChannel, error) { + var channel store.TextChannel + err := c.db.NewSelect(). + Model(&channel). + // Where("server_id = ?", serverID). + Where("id = ?", channelID). + Scan(ctx) + + return channel, err +} + +func (c *Service) ListChannelsOnServer(ctx context.Context, serverID uuid.UUID) ([]store.TextChannel, error) { + var channels []store.TextChannel + err := c.db.NewSelect(). + Model(&channels). + Where("server_id = ?", serverID). + Scan(ctx) + return channels, err +} diff --git a/src/konfa/message.go b/src/konfa/message.go new file mode 100644 index 0000000..4cf0fa7 --- /dev/null +++ b/src/konfa/message.go @@ -0,0 +1,93 @@ +package konfa + +import ( + "context" + "time" + + "github.com/cskr/pubsub/v2" + "github.com/royalcat/konfa-server/pkg/uuid" + "github.com/royalcat/konfa-server/src/store" +) + +type ChannelSubscription struct { + ChannelID uuid.UUID + Msgs chan uuid.UUID + + msgBroker *pubsub.PubSub[uuid.UUID, uuid.UUID] +} + +func (c *ChannelSubscription) Close() { + c.msgBroker.Unsub(c.Msgs, c.ChannelID) + // Drain the channel + for range c.Msgs { + } +} + +func (c *Service) SubscribeNewMessages(ctx context.Context, channelID uuid.UUID) (*ChannelSubscription, error) { + sub := c.msgBroker.Sub(channelID) + + return &ChannelSubscription{ + ChannelID: channelID, + Msgs: sub, + msgBroker: c.msgBroker, + }, nil +} + +func (c *Service) GetMessagesHistory(ctx context.Context, serverID uuid.UUID, channelID uuid.UUID, from time.Time, count int) ([]store.Message, error) { + var messages []store.Message + err := c.db.NewSelect(). + Model(&messages). + // Where("server_id = ?", serverID). + Where("channel_id = ?", channelID). + Where("timestamp < ?", from). + Order("timestamp DESC"). + Limit(count). + Scan(ctx) + return messages, err +} + +func (c *Service) GetMessage(ctx context.Context, serverID, channelID, messageID uuid.UUID) (store.Message, error) { + var message store.Message + err := c.db.NewSelect(). + Model(&message). + // Where("server_id = ?", serverID). + // Where("channel_id = ?", channelID). + Where("id = ?", messageID). + Order("timestamp DESC"). + Scan(ctx) + return message, err +} + +func (c *Service) SendMessage(ctx context.Context, senderID, serverID, channelID uuid.UUID, content string) (uuid.UUID, error) { + msg := store.Message{ + ID: uuid.New(), + Timestamp: time.Now(), + ChannelID: channelID, + SenderID: senderID, + Content: content, + } + + _, err := c.db.NewInsert().Model(&msg).Exec(ctx) + + c.msgBroker.Pub(msg.ID, channelID) + + return msg.ID, err + + // sql, args, err := sq.Insert("channel"). + // Columns("id", "server_id", "channel_id", "sender_id", "content"). + // Values(id, serverID, channelID, senderID, content). + // Suffix("RETURNING id"). + // ToSql() + // if err != nil { + // return uuid.Nil, err + // } + + // id, err = store.PgxExecInsertReturningID(ctx, c.dbpool, sql, args) + // if err != nil { + // return uuid.Nil, err + // } + + // c.msgBroker.Pub(id, channelID) + + // return id, nil +} diff --git a/src/konfa/server.go b/src/konfa/server.go new file mode 100644 index 0000000..a621a6e --- /dev/null +++ b/src/konfa/server.go @@ -0,0 +1,45 @@ +package konfa + +import ( + "context" + + "github.com/royalcat/konfa-server/pkg/uuid" + "github.com/royalcat/konfa-server/src/store" +) + +func (c *Service) CreateServer(ctx context.Context, name string) (uuid.UUID, error) { + server := store.Server{ + ID: uuid.New(), + Name: name, + } + + var idrow store.IDRow + _, err := c.db.NewInsert().Model(&server).Returning("id").Exec(ctx, &idrow) + return idrow.ID, err +} + +func (c *Service) GetServer(ctx context.Context, serverID uuid.UUID) ([]store.Server, error) { + var servers []store.Server + err := c.db.NewSelect(). + Model(&servers). + Where("server_id = ?", serverID). + Scan(ctx) + return servers, err +} + +func (c *Service) ListServers(ctx context.Context) ([]store.Server, error) { + var servers []store.Server + err := c.db.NewSelect(). + Model(&servers). + Scan(ctx) + return servers, err +} + +func (c *Service) ListTextChannels(ctx context.Context, serverID uuid.UUID) ([]store.TextChannel, error) { + var channels []store.TextChannel + err := c.db.NewSelect(). + Model(&channels). + Where("server_id = ?", serverID). + Scan(ctx) + return channels, err +} diff --git a/src/konfa/service.go b/src/konfa/service.go new file mode 100644 index 0000000..17c62f1 --- /dev/null +++ b/src/konfa/service.go @@ -0,0 +1,23 @@ +package konfa + +import ( + "github.com/cskr/pubsub/v2" + "github.com/jackc/pgx/v5/pgxpool" + "github.com/royalcat/konfa-server/pkg/uuid" + "github.com/uptrace/bun" +) + +type Service struct { + db *bun.DB + dbpool *pgxpool.Pool + + msgBroker *pubsub.PubSub[uuid.UUID, uuid.UUID] +} + +func NewService(db *bun.DB, dbpool *pgxpool.Pool) *Service { + return &Service{ + db: db, + dbpool: dbpool, + msgBroker: pubsub.New[uuid.UUID, uuid.UUID](10), + } +} diff --git a/src/proto/auth.go b/src/proto/auth.go new file mode 100644 index 0000000..5ee2b3f --- /dev/null +++ b/src/proto/auth.go @@ -0,0 +1,97 @@ +package proto + +import ( + "context" + "flag" + "strings" + + "github.com/royalcat/konfa-server/pkg/uuid" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var ( + errMissingMetadata = status.Errorf(codes.InvalidArgument, "missing metadata") + errInvalidToken = status.Errorf(codes.Unauthenticated, "invalid token") +) + +var port = flag.Int("port", 50051, "the port to serve on") + +// func main() { +// flag.Parse() +// fmt.Printf("server starting on port %d...\n", *port) + +// cert, err := tls.LoadX509KeyPair(data.Path("x509/server_cert.pem"), data.Path("x509/server_key.pem")) +// if err != nil { +// log.Fatalf("failed to load key pair: %s", err) +// } +// opts := []grpc.ServerOption{ +// // The following grpc.ServerOption adds an interceptor for all unary +// // RPCs. To configure an interceptor for streaming RPCs, see: +// // https://godoc.org/google.golang.org/grpc#StreamInterceptor +// grpc.UnaryInterceptor(ensureValidToken), +// // Enable TLS for all incoming connections. +// grpc.Creds(credentials.NewServerTLSFromCert(&cert)), +// } +// s := grpc.NewServer(opts...) +// pb.RegisterEchoServer(s, &ecServer{}) +// lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) +// if err != nil { +// log.Fatalf("failed to listen: %v", err) +// } +// if err := s.Serve(lis); err != nil { +// log.Fatalf("failed to serve: %v", err) +// } +// } + +// valid validates the authorization. +func valid(authorization []string) bool { + if len(authorization) < 1 { + return false + } + token := strings.TrimPrefix(authorization[0], "Bearer ") + // Perform the token validation here. For the sake of this example, the code + // here forgoes any of the usual OAuth2 token validation and instead checks + // for a token matching an arbitrary string. + return token == "some-secret-token" +} + +type ctxKey string + +const ctxUserKey ctxKey = "user" + +// Authenticate ensures a valid token exists within a request's metadata. If +// the token is missing or invalid, the interceptor blocks execution of the +// handler and returns an error. Otherwise, the interceptor invokes the unary +// handler. +func Authenticate(ctx context.Context, req any, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { + // md, ok := metadata.FromIncomingContext(ctx) + // if !ok { + // return nil, errMissingMetadata + // } + // // The keys within metadata.MD are normalized to lowercase. + // // See: https://godoc.org/google.golang.org/grpc/metadata#New + // if !valid(md["authorization"]) { + // return nil, errInvalidToken + // } + + var user User + + user = User{ + ID: uuid.MustFromString("a903b474-26f4-4262-9ba7-97edaa76491f"), + } + + ctx = context.WithValue(ctx, ctxUserKey, &user) + + // Continue execution of handler after ensuring a valid token. + return handler(ctx, req) +} + +type User struct { + ID uuid.UUID +} + +func getCtxUser(ctx context.Context) *User { + return ctx.Value(ctxUserKey).(*User) +} diff --git a/src/proto/chat.go b/src/proto/chat.go new file mode 100644 index 0000000..6c99a14 --- /dev/null +++ b/src/proto/chat.go @@ -0,0 +1,123 @@ +package proto + +import ( + "context" + + "github.com/royalcat/konfa-server/pkg/uuid" + "github.com/royalcat/konfa-server/src/konfa" + chatv1 "github.com/royalcat/konfa-server/src/proto/konfa/chat/v1" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type ChatService struct { + srv *konfa.Service +} + +func NewChatService(srv *konfa.Service) *ChatService { + return &ChatService{ + srv: srv, + } +} + +var ErrUnauthenticated = status.Error(codes.Unauthenticated, "unauthenticated") + +var _ chatv1.ChatServiceServer = (*ChatService)(nil) + +// SendMessage implements chatv1.ChatServiceServer. +func (c *ChatService) SendMessage(ctx context.Context, req *chatv1.SendMessageRequest) (*chatv1.SendMessageResponse, error) { + user := getCtxUser(ctx) + if user == nil { + return nil, ErrUnauthenticated + } + ref, err := parseChannelRef(req.Channel) + if err != nil { + return nil, err + } + + id, err := c.srv.SendMessage(ctx, user.ID, ref.ServerID, ref.ChannelID, req.Content) + if err != nil { + return nil, err + } + + return &chatv1.SendMessageResponse{MessageId: id.String()}, nil +} + +// GetMessage implements chatv1.ChatServiceServer. +func (c *ChatService) GetMessage(ctx context.Context, req *chatv1.GetMessageRequest) (*chatv1.GetMessageResponse, error) { + ref, err := parseChannelRef(req.Channel) + if err != nil { + return nil, err + } + + messageID, err := uuid.FromString(req.MessageId) + if err != nil { + return nil, err + } + + msg, err := c.srv.GetMessage(ctx, ref.ServerID, ref.ChannelID, messageID) + if err != nil { + return nil, err + } + + return &chatv1.GetMessageResponse{ + Message: mapMessage(msg), + }, nil +} + +// GetMessageHistory implements chatv1.ChatServiceServer. +func (c *ChatService) GetMessageHistory(ctx context.Context, req *chatv1.GetMessageHistoryRequest) (*chatv1.GetMessageHistoryResponse, error) { + ref, err := parseChannelRef(req.Channel) + if err != nil { + return nil, err + } + + msgs, err := c.srv.GetMessagesHistory(ctx, ref.ServerID, ref.ChannelID, req.From.AsTime(), int(req.Count)) + if err != nil { + return nil, err + } + + return &chatv1.GetMessageHistoryResponse{ + Messages: apply(msgs, mapMessage), + }, nil +} + +// StreamNewMessages implements chatv1.ChatServiceServer. +func (c *ChatService) StreamNewMessages(req *chatv1.StreamNewMessagesRequest, out grpc.ServerStreamingServer[chatv1.StreamNewMessagesResponse]) error { + channelID, err := uuid.FromString(req.Channel.ChannelId) + if err != nil { + return err + } + + sub, err := c.srv.SubscribeNewMessages(out.Context(), channelID) + if err != nil { + return err + } + + defer sub.Close() + + for { + select { + case <-out.Context().Done(): + return nil + case msg := <-sub.Msgs: + err := out.Send(&chatv1.StreamNewMessagesResponse{MessageId: msg.String()}) + if err != nil { + return err + } + } + } + +} + +// UploadAttachment implements chatv1.ChatServiceServer. +func (c *ChatService) UploadAttachment(req grpc.ClientStreamingServer[chatv1.UploadAttachmentRequest, chatv1.UploadAttachmentResponse]) error { + for { + req, err := req.Recv() + if err != nil { + return err + } + _ = req + } +} diff --git a/src/proto/konfa/channel/v1/channels.pb.go b/src/proto/konfa/channel/v1/channels.pb.go new file mode 100644 index 0000000..d3abd61 --- /dev/null +++ b/src/proto/konfa/channel/v1/channels.pb.go @@ -0,0 +1,324 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.0 +// protoc (unknown) +// source: konfa/channel/v1/channels.proto + +package channelv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Channel struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Channel: + // + // *Channel_TextChannel + // *Channel_VoiceChannel + Channel isChannel_Channel `protobuf_oneof:"channel"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Channel) Reset() { + *x = Channel{} + mi := &file_konfa_channel_v1_channels_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Channel) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Channel) ProtoMessage() {} + +func (x *Channel) ProtoReflect() protoreflect.Message { + mi := &file_konfa_channel_v1_channels_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Channel.ProtoReflect.Descriptor instead. +func (*Channel) Descriptor() ([]byte, []int) { + return file_konfa_channel_v1_channels_proto_rawDescGZIP(), []int{0} +} + +func (x *Channel) GetChannel() isChannel_Channel { + if x != nil { + return x.Channel + } + return nil +} + +func (x *Channel) GetTextChannel() *TextChannel { + if x != nil { + if x, ok := x.Channel.(*Channel_TextChannel); ok { + return x.TextChannel + } + } + return nil +} + +func (x *Channel) GetVoiceChannel() *VoiceChannel { + if x != nil { + if x, ok := x.Channel.(*Channel_VoiceChannel); ok { + return x.VoiceChannel + } + } + return nil +} + +type isChannel_Channel interface { + isChannel_Channel() +} + +type Channel_TextChannel struct { + TextChannel *TextChannel `protobuf:"bytes,1,opt,name=text_channel,json=textChannel,proto3,oneof"` +} + +type Channel_VoiceChannel struct { + VoiceChannel *VoiceChannel `protobuf:"bytes,2,opt,name=voice_channel,json=voiceChannel,proto3,oneof"` +} + +func (*Channel_TextChannel) isChannel_Channel() {} + +func (*Channel_VoiceChannel) isChannel_Channel() {} + +type TextChannel struct { + state protoimpl.MessageState `protogen:"open.v1"` + ServerId string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty"` + ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TextChannel) Reset() { + *x = TextChannel{} + mi := &file_konfa_channel_v1_channels_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TextChannel) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TextChannel) ProtoMessage() {} + +func (x *TextChannel) ProtoReflect() protoreflect.Message { + mi := &file_konfa_channel_v1_channels_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TextChannel.ProtoReflect.Descriptor instead. +func (*TextChannel) Descriptor() ([]byte, []int) { + return file_konfa_channel_v1_channels_proto_rawDescGZIP(), []int{1} +} + +func (x *TextChannel) GetServerId() string { + if x != nil { + return x.ServerId + } + return "" +} + +func (x *TextChannel) GetChannelId() string { + if x != nil { + return x.ChannelId + } + return "" +} + +func (x *TextChannel) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type VoiceChannel struct { + state protoimpl.MessageState `protogen:"open.v1"` + ServerId string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty"` + ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VoiceChannel) Reset() { + *x = VoiceChannel{} + mi := &file_konfa_channel_v1_channels_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VoiceChannel) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VoiceChannel) ProtoMessage() {} + +func (x *VoiceChannel) ProtoReflect() protoreflect.Message { + mi := &file_konfa_channel_v1_channels_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VoiceChannel.ProtoReflect.Descriptor instead. +func (*VoiceChannel) Descriptor() ([]byte, []int) { + return file_konfa_channel_v1_channels_proto_rawDescGZIP(), []int{2} +} + +func (x *VoiceChannel) GetServerId() string { + if x != nil { + return x.ServerId + } + return "" +} + +func (x *VoiceChannel) GetChannelId() string { + if x != nil { + return x.ChannelId + } + return "" +} + +func (x *VoiceChannel) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +var File_konfa_channel_v1_channels_proto protoreflect.FileDescriptor + +var file_konfa_channel_v1_channels_proto_rawDesc = []byte{ + 0x0a, 0x1f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2f, + 0x76, 0x31, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x10, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x2e, 0x76, 0x31, 0x22, 0x9f, 0x01, 0x0a, 0x07, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, + 0x42, 0x0a, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x65, 0x78, 0x74, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x12, 0x45, 0x0a, 0x0d, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6b, 0x6f, 0x6e, + 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, + 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x0c, 0x76, 0x6f, + 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x5d, 0x0a, 0x0b, 0x54, 0x65, 0x78, 0x74, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x5e, 0x0a, 0x0c, 0x56, 0x6f, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x42, 0xce, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x6b, 0x6f, 0x6e, + 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6f, 0x79, 0x61, 0x6c, + 0x63, 0x61, 0x74, 0x2f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, + 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4b, 0x43, 0x58, 0xaa, 0x02, 0x10, 0x4b, 0x6f, + 0x6e, 0x66, 0x61, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x56, 0x31, 0xca, 0x02, + 0x10, 0x4b, 0x6f, 0x6e, 0x66, 0x61, 0x5c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5c, 0x56, + 0x31, 0xe2, 0x02, 0x1c, 0x4b, 0x6f, 0x6e, 0x66, 0x61, 0x5c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x12, 0x4b, 0x6f, 0x6e, 0x66, 0x61, 0x3a, 0x3a, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_konfa_channel_v1_channels_proto_rawDescOnce sync.Once + file_konfa_channel_v1_channels_proto_rawDescData = file_konfa_channel_v1_channels_proto_rawDesc +) + +func file_konfa_channel_v1_channels_proto_rawDescGZIP() []byte { + file_konfa_channel_v1_channels_proto_rawDescOnce.Do(func() { + file_konfa_channel_v1_channels_proto_rawDescData = protoimpl.X.CompressGZIP(file_konfa_channel_v1_channels_proto_rawDescData) + }) + return file_konfa_channel_v1_channels_proto_rawDescData +} + +var file_konfa_channel_v1_channels_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_konfa_channel_v1_channels_proto_goTypes = []any{ + (*Channel)(nil), // 0: konfa.channel.v1.Channel + (*TextChannel)(nil), // 1: konfa.channel.v1.TextChannel + (*VoiceChannel)(nil), // 2: konfa.channel.v1.VoiceChannel +} +var file_konfa_channel_v1_channels_proto_depIdxs = []int32{ + 1, // 0: konfa.channel.v1.Channel.text_channel:type_name -> konfa.channel.v1.TextChannel + 2, // 1: konfa.channel.v1.Channel.voice_channel:type_name -> konfa.channel.v1.VoiceChannel + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_konfa_channel_v1_channels_proto_init() } +func file_konfa_channel_v1_channels_proto_init() { + if File_konfa_channel_v1_channels_proto != nil { + return + } + file_konfa_channel_v1_channels_proto_msgTypes[0].OneofWrappers = []any{ + (*Channel_TextChannel)(nil), + (*Channel_VoiceChannel)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_konfa_channel_v1_channels_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_konfa_channel_v1_channels_proto_goTypes, + DependencyIndexes: file_konfa_channel_v1_channels_proto_depIdxs, + MessageInfos: file_konfa_channel_v1_channels_proto_msgTypes, + }.Build() + File_konfa_channel_v1_channels_proto = out.File + file_konfa_channel_v1_channels_proto_rawDesc = nil + file_konfa_channel_v1_channels_proto_goTypes = nil + file_konfa_channel_v1_channels_proto_depIdxs = nil +} diff --git a/src/proto/konfa/chat/v1/service.pb.go b/src/proto/konfa/chat/v1/service.pb.go new file mode 100644 index 0000000..b767052 --- /dev/null +++ b/src/proto/konfa/chat/v1/service.pb.go @@ -0,0 +1,909 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.0 +// protoc (unknown) +// source: konfa/chat/v1/service.proto + +package chatv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type TextChannelRef struct { + state protoimpl.MessageState `protogen:"open.v1"` + ServerId string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty"` + ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TextChannelRef) Reset() { + *x = TextChannelRef{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TextChannelRef) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TextChannelRef) ProtoMessage() {} + +func (x *TextChannelRef) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TextChannelRef.ProtoReflect.Descriptor instead. +func (*TextChannelRef) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{0} +} + +func (x *TextChannelRef) GetServerId() string { + if x != nil { + return x.ServerId + } + return "" +} + +func (x *TextChannelRef) GetChannelId() string { + if x != nil { + return x.ChannelId + } + return "" +} + +type SendMessageRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Channel *TextChannelRef `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` + Content string `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SendMessageRequest) Reset() { + *x = SendMessageRequest{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SendMessageRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendMessageRequest) ProtoMessage() {} + +func (x *SendMessageRequest) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendMessageRequest.ProtoReflect.Descriptor instead. +func (*SendMessageRequest) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{1} +} + +func (x *SendMessageRequest) GetChannel() *TextChannelRef { + if x != nil { + return x.Channel + } + return nil +} + +func (x *SendMessageRequest) GetContent() string { + if x != nil { + return x.Content + } + return "" +} + +type SendMessageResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + MessageId string `protobuf:"bytes,1,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SendMessageResponse) Reset() { + *x = SendMessageResponse{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SendMessageResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendMessageResponse) ProtoMessage() {} + +func (x *SendMessageResponse) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendMessageResponse.ProtoReflect.Descriptor instead. +func (*SendMessageResponse) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{2} +} + +func (x *SendMessageResponse) GetMessageId() string { + if x != nil { + return x.MessageId + } + return "" +} + +type Message struct { + state protoimpl.MessageState `protogen:"open.v1"` + MessageId string `protobuf:"bytes,1,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` + SenderId string `protobuf:"bytes,4,opt,name=sender_id,json=senderId,proto3" json:"sender_id,omitempty"` + Content string `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Message) Reset() { + *x = Message{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Message) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Message) ProtoMessage() {} + +func (x *Message) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Message.ProtoReflect.Descriptor instead. +func (*Message) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{3} +} + +func (x *Message) GetMessageId() string { + if x != nil { + return x.MessageId + } + return "" +} + +func (x *Message) GetSenderId() string { + if x != nil { + return x.SenderId + } + return "" +} + +func (x *Message) GetContent() string { + if x != nil { + return x.Content + } + return "" +} + +func (x *Message) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +type GetMessageHistoryRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Channel *TextChannelRef `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` + From *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=from,proto3" json:"from,omitempty"` + Count int32 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetMessageHistoryRequest) Reset() { + *x = GetMessageHistoryRequest{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMessageHistoryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMessageHistoryRequest) ProtoMessage() {} + +func (x *GetMessageHistoryRequest) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMessageHistoryRequest.ProtoReflect.Descriptor instead. +func (*GetMessageHistoryRequest) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{4} +} + +func (x *GetMessageHistoryRequest) GetChannel() *TextChannelRef { + if x != nil { + return x.Channel + } + return nil +} + +func (x *GetMessageHistoryRequest) GetFrom() *timestamppb.Timestamp { + if x != nil { + return x.From + } + return nil +} + +func (x *GetMessageHistoryRequest) GetCount() int32 { + if x != nil { + return x.Count + } + return 0 +} + +type GetMessageHistoryResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Messages []*Message `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetMessageHistoryResponse) Reset() { + *x = GetMessageHistoryResponse{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMessageHistoryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMessageHistoryResponse) ProtoMessage() {} + +func (x *GetMessageHistoryResponse) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMessageHistoryResponse.ProtoReflect.Descriptor instead. +func (*GetMessageHistoryResponse) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{5} +} + +func (x *GetMessageHistoryResponse) GetMessages() []*Message { + if x != nil { + return x.Messages + } + return nil +} + +type GetMessageRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Channel *TextChannelRef `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` + MessageId string `protobuf:"bytes,2,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetMessageRequest) Reset() { + *x = GetMessageRequest{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMessageRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMessageRequest) ProtoMessage() {} + +func (x *GetMessageRequest) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMessageRequest.ProtoReflect.Descriptor instead. +func (*GetMessageRequest) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{6} +} + +func (x *GetMessageRequest) GetChannel() *TextChannelRef { + if x != nil { + return x.Channel + } + return nil +} + +func (x *GetMessageRequest) GetMessageId() string { + if x != nil { + return x.MessageId + } + return "" +} + +type GetMessageResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Message *Message `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetMessageResponse) Reset() { + *x = GetMessageResponse{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMessageResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMessageResponse) ProtoMessage() {} + +func (x *GetMessageResponse) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMessageResponse.ProtoReflect.Descriptor instead. +func (*GetMessageResponse) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{7} +} + +func (x *GetMessageResponse) GetMessage() *Message { + if x != nil { + return x.Message + } + return nil +} + +type StreamNewMessagesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Channel *TextChannelRef `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamNewMessagesRequest) Reset() { + *x = StreamNewMessagesRequest{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamNewMessagesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamNewMessagesRequest) ProtoMessage() {} + +func (x *StreamNewMessagesRequest) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StreamNewMessagesRequest.ProtoReflect.Descriptor instead. +func (*StreamNewMessagesRequest) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{8} +} + +func (x *StreamNewMessagesRequest) GetChannel() *TextChannelRef { + if x != nil { + return x.Channel + } + return nil +} + +type StreamNewMessagesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + MessageId string `protobuf:"bytes,1,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamNewMessagesResponse) Reset() { + *x = StreamNewMessagesResponse{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamNewMessagesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamNewMessagesResponse) ProtoMessage() {} + +func (x *StreamNewMessagesResponse) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StreamNewMessagesResponse.ProtoReflect.Descriptor instead. +func (*StreamNewMessagesResponse) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{9} +} + +func (x *StreamNewMessagesResponse) GetMessageId() string { + if x != nil { + return x.MessageId + } + return "" +} + +type UploadAttachmentRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Payload: + // + // *UploadAttachmentRequest_Info + // *UploadAttachmentRequest_Data + Payload isUploadAttachmentRequest_Payload `protobuf_oneof:"payload"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UploadAttachmentRequest) Reset() { + *x = UploadAttachmentRequest{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UploadAttachmentRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadAttachmentRequest) ProtoMessage() {} + +func (x *UploadAttachmentRequest) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadAttachmentRequest.ProtoReflect.Descriptor instead. +func (*UploadAttachmentRequest) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{10} +} + +func (x *UploadAttachmentRequest) GetPayload() isUploadAttachmentRequest_Payload { + if x != nil { + return x.Payload + } + return nil +} + +func (x *UploadAttachmentRequest) GetInfo() *AttachmentUploadInfo { + if x != nil { + if x, ok := x.Payload.(*UploadAttachmentRequest_Info); ok { + return x.Info + } + } + return nil +} + +func (x *UploadAttachmentRequest) GetData() []byte { + if x != nil { + if x, ok := x.Payload.(*UploadAttachmentRequest_Data); ok { + return x.Data + } + } + return nil +} + +type isUploadAttachmentRequest_Payload interface { + isUploadAttachmentRequest_Payload() +} + +type UploadAttachmentRequest_Info struct { + Info *AttachmentUploadInfo `protobuf:"bytes,1,opt,name=info,proto3,oneof"` +} + +type UploadAttachmentRequest_Data struct { + Data []byte `protobuf:"bytes,2,opt,name=data,proto3,oneof"` +} + +func (*UploadAttachmentRequest_Info) isUploadAttachmentRequest_Payload() {} + +func (*UploadAttachmentRequest_Data) isUploadAttachmentRequest_Payload() {} + +type AttachmentUploadInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AttachmentUploadInfo) Reset() { + *x = AttachmentUploadInfo{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AttachmentUploadInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AttachmentUploadInfo) ProtoMessage() {} + +func (x *AttachmentUploadInfo) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AttachmentUploadInfo.ProtoReflect.Descriptor instead. +func (*AttachmentUploadInfo) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{11} +} + +func (x *AttachmentUploadInfo) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type UploadAttachmentResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + AttachmenId string `protobuf:"bytes,1,opt,name=attachmen_id,json=attachmenId,proto3" json:"attachmen_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UploadAttachmentResponse) Reset() { + *x = UploadAttachmentResponse{} + mi := &file_konfa_chat_v1_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UploadAttachmentResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadAttachmentResponse) ProtoMessage() {} + +func (x *UploadAttachmentResponse) ProtoReflect() protoreflect.Message { + mi := &file_konfa_chat_v1_service_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadAttachmentResponse.ProtoReflect.Descriptor instead. +func (*UploadAttachmentResponse) Descriptor() ([]byte, []int) { + return file_konfa_chat_v1_service_proto_rawDescGZIP(), []int{12} +} + +func (x *UploadAttachmentResponse) GetAttachmenId() string { + if x != nil { + return x.AttachmenId + } + return "" +} + +var File_konfa_chat_v1_service_proto protoreflect.FileDescriptor + +var file_konfa_chat_v1_service_proto_rawDesc = []byte{ + 0x0a, 0x1b, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2f, 0x63, 0x68, 0x61, 0x74, 0x2f, 0x76, 0x31, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x6b, + 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4c, 0x0a, + 0x0e, 0x54, 0x65, 0x78, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x66, 0x12, + 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x22, 0x67, 0x0a, 0x12, 0x53, + 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, + 0x66, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x22, 0x34, 0x0a, 0x13, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x99, 0x01, 0x0a, 0x07, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x99, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x52, 0x65, 0x66, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x2e, 0x0a, 0x04, + 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x14, 0x0a, 0x05, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x22, 0x4f, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x32, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x73, 0x22, 0x6b, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, + 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x66, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, + 0x22, 0x46, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, + 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x53, 0x0a, 0x18, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x4e, 0x65, 0x77, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, + 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x52, 0x65, 0x66, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x3a, 0x0a, + 0x19, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x65, 0x77, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x75, 0x0a, 0x17, 0x55, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, + 0x14, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x22, 0x2a, 0x0a, 0x14, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x70, + 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x18, + 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x61, + 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x49, 0x64, 0x32, 0xf9, 0x03, 0x0a, 0x0b, + 0x43, 0x68, 0x61, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x56, 0x0a, 0x0b, 0x53, + 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x6b, 0x6f, 0x6e, + 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, + 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x68, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x27, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, + 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, + 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x2e, 0x6b, 0x6f, + 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, + 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x11, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x65, 0x77, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, + 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x65, + 0x77, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x28, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x65, 0x77, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x67, + 0x0a, 0x10, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x26, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6b, 0x6f, 0x6e, + 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x42, 0xb8, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, + 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6f, 0x79, 0x61, 0x6c, 0x63, + 0x61, 0x74, 0x2f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, + 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2f, + 0x63, 0x68, 0x61, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x68, 0x61, 0x74, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x4b, 0x43, 0x58, 0xaa, 0x02, 0x0d, 0x4b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x43, 0x68, 0x61, + 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0d, 0x4b, 0x6f, 0x6e, 0x66, 0x61, 0x5c, 0x43, 0x68, 0x61, + 0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x19, 0x4b, 0x6f, 0x6e, 0x66, 0x61, 0x5c, 0x43, 0x68, 0x61, + 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x0f, 0x4b, 0x6f, 0x6e, 0x66, 0x61, 0x3a, 0x3a, 0x43, 0x68, 0x61, 0x74, 0x3a, 0x3a, + 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_konfa_chat_v1_service_proto_rawDescOnce sync.Once + file_konfa_chat_v1_service_proto_rawDescData = file_konfa_chat_v1_service_proto_rawDesc +) + +func file_konfa_chat_v1_service_proto_rawDescGZIP() []byte { + file_konfa_chat_v1_service_proto_rawDescOnce.Do(func() { + file_konfa_chat_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_konfa_chat_v1_service_proto_rawDescData) + }) + return file_konfa_chat_v1_service_proto_rawDescData +} + +var file_konfa_chat_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_konfa_chat_v1_service_proto_goTypes = []any{ + (*TextChannelRef)(nil), // 0: konfa.chat.v1.TextChannelRef + (*SendMessageRequest)(nil), // 1: konfa.chat.v1.SendMessageRequest + (*SendMessageResponse)(nil), // 2: konfa.chat.v1.SendMessageResponse + (*Message)(nil), // 3: konfa.chat.v1.Message + (*GetMessageHistoryRequest)(nil), // 4: konfa.chat.v1.GetMessageHistoryRequest + (*GetMessageHistoryResponse)(nil), // 5: konfa.chat.v1.GetMessageHistoryResponse + (*GetMessageRequest)(nil), // 6: konfa.chat.v1.GetMessageRequest + (*GetMessageResponse)(nil), // 7: konfa.chat.v1.GetMessageResponse + (*StreamNewMessagesRequest)(nil), // 8: konfa.chat.v1.StreamNewMessagesRequest + (*StreamNewMessagesResponse)(nil), // 9: konfa.chat.v1.StreamNewMessagesResponse + (*UploadAttachmentRequest)(nil), // 10: konfa.chat.v1.UploadAttachmentRequest + (*AttachmentUploadInfo)(nil), // 11: konfa.chat.v1.AttachmentUploadInfo + (*UploadAttachmentResponse)(nil), // 12: konfa.chat.v1.UploadAttachmentResponse + (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp +} +var file_konfa_chat_v1_service_proto_depIdxs = []int32{ + 0, // 0: konfa.chat.v1.SendMessageRequest.channel:type_name -> konfa.chat.v1.TextChannelRef + 13, // 1: konfa.chat.v1.Message.timestamp:type_name -> google.protobuf.Timestamp + 0, // 2: konfa.chat.v1.GetMessageHistoryRequest.channel:type_name -> konfa.chat.v1.TextChannelRef + 13, // 3: konfa.chat.v1.GetMessageHistoryRequest.from:type_name -> google.protobuf.Timestamp + 3, // 4: konfa.chat.v1.GetMessageHistoryResponse.messages:type_name -> konfa.chat.v1.Message + 0, // 5: konfa.chat.v1.GetMessageRequest.channel:type_name -> konfa.chat.v1.TextChannelRef + 3, // 6: konfa.chat.v1.GetMessageResponse.message:type_name -> konfa.chat.v1.Message + 0, // 7: konfa.chat.v1.StreamNewMessagesRequest.channel:type_name -> konfa.chat.v1.TextChannelRef + 11, // 8: konfa.chat.v1.UploadAttachmentRequest.info:type_name -> konfa.chat.v1.AttachmentUploadInfo + 1, // 9: konfa.chat.v1.ChatService.SendMessage:input_type -> konfa.chat.v1.SendMessageRequest + 4, // 10: konfa.chat.v1.ChatService.GetMessageHistory:input_type -> konfa.chat.v1.GetMessageHistoryRequest + 6, // 11: konfa.chat.v1.ChatService.GetMessage:input_type -> konfa.chat.v1.GetMessageRequest + 8, // 12: konfa.chat.v1.ChatService.StreamNewMessages:input_type -> konfa.chat.v1.StreamNewMessagesRequest + 10, // 13: konfa.chat.v1.ChatService.UploadAttachment:input_type -> konfa.chat.v1.UploadAttachmentRequest + 2, // 14: konfa.chat.v1.ChatService.SendMessage:output_type -> konfa.chat.v1.SendMessageResponse + 5, // 15: konfa.chat.v1.ChatService.GetMessageHistory:output_type -> konfa.chat.v1.GetMessageHistoryResponse + 7, // 16: konfa.chat.v1.ChatService.GetMessage:output_type -> konfa.chat.v1.GetMessageResponse + 9, // 17: konfa.chat.v1.ChatService.StreamNewMessages:output_type -> konfa.chat.v1.StreamNewMessagesResponse + 12, // 18: konfa.chat.v1.ChatService.UploadAttachment:output_type -> konfa.chat.v1.UploadAttachmentResponse + 14, // [14:19] is the sub-list for method output_type + 9, // [9:14] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name +} + +func init() { file_konfa_chat_v1_service_proto_init() } +func file_konfa_chat_v1_service_proto_init() { + if File_konfa_chat_v1_service_proto != nil { + return + } + file_konfa_chat_v1_service_proto_msgTypes[10].OneofWrappers = []any{ + (*UploadAttachmentRequest_Info)(nil), + (*UploadAttachmentRequest_Data)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_konfa_chat_v1_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 13, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_konfa_chat_v1_service_proto_goTypes, + DependencyIndexes: file_konfa_chat_v1_service_proto_depIdxs, + MessageInfos: file_konfa_chat_v1_service_proto_msgTypes, + }.Build() + File_konfa_chat_v1_service_proto = out.File + file_konfa_chat_v1_service_proto_rawDesc = nil + file_konfa_chat_v1_service_proto_goTypes = nil + file_konfa_chat_v1_service_proto_depIdxs = nil +} diff --git a/src/proto/konfa/chat/v1/service_grpc.pb.go b/src/proto/konfa/chat/v1/service_grpc.pb.go new file mode 100644 index 0000000..14b228e --- /dev/null +++ b/src/proto/konfa/chat/v1/service_grpc.pb.go @@ -0,0 +1,268 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc (unknown) +// source: konfa/chat/v1/service.proto + +package chatv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + ChatService_SendMessage_FullMethodName = "/konfa.chat.v1.ChatService/SendMessage" + ChatService_GetMessageHistory_FullMethodName = "/konfa.chat.v1.ChatService/GetMessageHistory" + ChatService_GetMessage_FullMethodName = "/konfa.chat.v1.ChatService/GetMessage" + ChatService_StreamNewMessages_FullMethodName = "/konfa.chat.v1.ChatService/StreamNewMessages" + ChatService_UploadAttachment_FullMethodName = "/konfa.chat.v1.ChatService/UploadAttachment" +) + +// ChatServiceClient is the client API for ChatService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ChatServiceClient interface { + SendMessage(ctx context.Context, in *SendMessageRequest, opts ...grpc.CallOption) (*SendMessageResponse, error) + GetMessageHistory(ctx context.Context, in *GetMessageHistoryRequest, opts ...grpc.CallOption) (*GetMessageHistoryResponse, error) + GetMessage(ctx context.Context, in *GetMessageRequest, opts ...grpc.CallOption) (*GetMessageResponse, error) + StreamNewMessages(ctx context.Context, in *StreamNewMessagesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StreamNewMessagesResponse], error) + UploadAttachment(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[UploadAttachmentRequest, UploadAttachmentResponse], error) +} + +type chatServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewChatServiceClient(cc grpc.ClientConnInterface) ChatServiceClient { + return &chatServiceClient{cc} +} + +func (c *chatServiceClient) SendMessage(ctx context.Context, in *SendMessageRequest, opts ...grpc.CallOption) (*SendMessageResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SendMessageResponse) + err := c.cc.Invoke(ctx, ChatService_SendMessage_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *chatServiceClient) GetMessageHistory(ctx context.Context, in *GetMessageHistoryRequest, opts ...grpc.CallOption) (*GetMessageHistoryResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetMessageHistoryResponse) + err := c.cc.Invoke(ctx, ChatService_GetMessageHistory_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *chatServiceClient) GetMessage(ctx context.Context, in *GetMessageRequest, opts ...grpc.CallOption) (*GetMessageResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetMessageResponse) + err := c.cc.Invoke(ctx, ChatService_GetMessage_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *chatServiceClient) StreamNewMessages(ctx context.Context, in *StreamNewMessagesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StreamNewMessagesResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &ChatService_ServiceDesc.Streams[0], ChatService_StreamNewMessages_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[StreamNewMessagesRequest, StreamNewMessagesResponse]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ChatService_StreamNewMessagesClient = grpc.ServerStreamingClient[StreamNewMessagesResponse] + +func (c *chatServiceClient) UploadAttachment(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[UploadAttachmentRequest, UploadAttachmentResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &ChatService_ServiceDesc.Streams[1], ChatService_UploadAttachment_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[UploadAttachmentRequest, UploadAttachmentResponse]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ChatService_UploadAttachmentClient = grpc.ClientStreamingClient[UploadAttachmentRequest, UploadAttachmentResponse] + +// ChatServiceServer is the server API for ChatService service. +// All implementations should embed UnimplementedChatServiceServer +// for forward compatibility. +type ChatServiceServer interface { + SendMessage(context.Context, *SendMessageRequest) (*SendMessageResponse, error) + GetMessageHistory(context.Context, *GetMessageHistoryRequest) (*GetMessageHistoryResponse, error) + GetMessage(context.Context, *GetMessageRequest) (*GetMessageResponse, error) + StreamNewMessages(*StreamNewMessagesRequest, grpc.ServerStreamingServer[StreamNewMessagesResponse]) error + UploadAttachment(grpc.ClientStreamingServer[UploadAttachmentRequest, UploadAttachmentResponse]) error +} + +// UnimplementedChatServiceServer should be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedChatServiceServer struct{} + +func (UnimplementedChatServiceServer) SendMessage(context.Context, *SendMessageRequest) (*SendMessageResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SendMessage not implemented") +} +func (UnimplementedChatServiceServer) GetMessageHistory(context.Context, *GetMessageHistoryRequest) (*GetMessageHistoryResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMessageHistory not implemented") +} +func (UnimplementedChatServiceServer) GetMessage(context.Context, *GetMessageRequest) (*GetMessageResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMessage not implemented") +} +func (UnimplementedChatServiceServer) StreamNewMessages(*StreamNewMessagesRequest, grpc.ServerStreamingServer[StreamNewMessagesResponse]) error { + return status.Errorf(codes.Unimplemented, "method StreamNewMessages not implemented") +} +func (UnimplementedChatServiceServer) UploadAttachment(grpc.ClientStreamingServer[UploadAttachmentRequest, UploadAttachmentResponse]) error { + return status.Errorf(codes.Unimplemented, "method UploadAttachment not implemented") +} +func (UnimplementedChatServiceServer) testEmbeddedByValue() {} + +// UnsafeChatServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ChatServiceServer will +// result in compilation errors. +type UnsafeChatServiceServer interface { + mustEmbedUnimplementedChatServiceServer() +} + +func RegisterChatServiceServer(s grpc.ServiceRegistrar, srv ChatServiceServer) { + // If the following call pancis, it indicates UnimplementedChatServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&ChatService_ServiceDesc, srv) +} + +func _ChatService_SendMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SendMessageRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ChatServiceServer).SendMessage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ChatService_SendMessage_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ChatServiceServer).SendMessage(ctx, req.(*SendMessageRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ChatService_GetMessageHistory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetMessageHistoryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ChatServiceServer).GetMessageHistory(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ChatService_GetMessageHistory_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ChatServiceServer).GetMessageHistory(ctx, req.(*GetMessageHistoryRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ChatService_GetMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetMessageRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ChatServiceServer).GetMessage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ChatService_GetMessage_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ChatServiceServer).GetMessage(ctx, req.(*GetMessageRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ChatService_StreamNewMessages_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(StreamNewMessagesRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ChatServiceServer).StreamNewMessages(m, &grpc.GenericServerStream[StreamNewMessagesRequest, StreamNewMessagesResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ChatService_StreamNewMessagesServer = grpc.ServerStreamingServer[StreamNewMessagesResponse] + +func _ChatService_UploadAttachment_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ChatServiceServer).UploadAttachment(&grpc.GenericServerStream[UploadAttachmentRequest, UploadAttachmentResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ChatService_UploadAttachmentServer = grpc.ClientStreamingServer[UploadAttachmentRequest, UploadAttachmentResponse] + +// ChatService_ServiceDesc is the grpc.ServiceDesc for ChatService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ChatService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "konfa.chat.v1.ChatService", + HandlerType: (*ChatServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SendMessage", + Handler: _ChatService_SendMessage_Handler, + }, + { + MethodName: "GetMessageHistory", + Handler: _ChatService_GetMessageHistory_Handler, + }, + { + MethodName: "GetMessage", + Handler: _ChatService_GetMessage_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamNewMessages", + Handler: _ChatService_StreamNewMessages_Handler, + ServerStreams: true, + }, + { + StreamName: "UploadAttachment", + Handler: _ChatService_UploadAttachment_Handler, + ClientStreams: true, + }, + }, + Metadata: "konfa/chat/v1/service.proto", +} diff --git a/src/proto/konfa/server/v1/service.pb.go b/src/proto/konfa/server/v1/service.pb.go new file mode 100644 index 0000000..88f918c --- /dev/null +++ b/src/proto/konfa/server/v1/service.pb.go @@ -0,0 +1,205 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.0 +// protoc (unknown) +// source: konfa/server/v1/service.proto + +package serverv1 + +import ( + v1 "github.com/royalcat/konfa-server/src/proto/konfa/channel/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ListServerChannelsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ServerId string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListServerChannelsRequest) Reset() { + *x = ListServerChannelsRequest{} + mi := &file_konfa_server_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListServerChannelsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServerChannelsRequest) ProtoMessage() {} + +func (x *ListServerChannelsRequest) ProtoReflect() protoreflect.Message { + mi := &file_konfa_server_v1_service_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServerChannelsRequest.ProtoReflect.Descriptor instead. +func (*ListServerChannelsRequest) Descriptor() ([]byte, []int) { + return file_konfa_server_v1_service_proto_rawDescGZIP(), []int{0} +} + +func (x *ListServerChannelsRequest) GetServerId() string { + if x != nil { + return x.ServerId + } + return "" +} + +type ListServerChannelsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Channels []*v1.Channel `protobuf:"bytes,1,rep,name=channels,proto3" json:"channels,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListServerChannelsResponse) Reset() { + *x = ListServerChannelsResponse{} + mi := &file_konfa_server_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListServerChannelsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServerChannelsResponse) ProtoMessage() {} + +func (x *ListServerChannelsResponse) ProtoReflect() protoreflect.Message { + mi := &file_konfa_server_v1_service_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServerChannelsResponse.ProtoReflect.Descriptor instead. +func (*ListServerChannelsResponse) Descriptor() ([]byte, []int) { + return file_konfa_server_v1_service_proto_rawDescGZIP(), []int{1} +} + +func (x *ListServerChannelsResponse) GetChannels() []*v1.Channel { + if x != nil { + return x.Channels + } + return nil +} + +var File_konfa_server_v1_service_proto protoreflect.FileDescriptor + +var file_konfa_server_v1_service_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x76, + 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x0f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x1a, 0x1f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2f, + 0x76, 0x31, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x38, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, + 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x22, 0x53, 0x0a, 0x1a, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x63, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6b, 0x6f, + 0x6e, 0x66, 0x61, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, + 0x32, 0x80, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x6f, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x2a, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x42, 0xc6, 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x6b, 0x6f, 0x6e, 0x66, + 0x61, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6f, 0x79, 0x61, 0x6c, 0x63, 0x61, 0x74, + 0x2f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x73, 0x72, + 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6b, 0x6f, 0x6e, 0x66, 0x61, 0x2f, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x76, 0x31, + 0xa2, 0x02, 0x03, 0x4b, 0x53, 0x58, 0xaa, 0x02, 0x0f, 0x4b, 0x6f, 0x6e, 0x66, 0x61, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x4b, 0x6f, 0x6e, 0x66, 0x61, + 0x5c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x4b, 0x6f, 0x6e, + 0x66, 0x61, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x4b, 0x6f, 0x6e, 0x66, 0x61, + 0x3a, 0x3a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_konfa_server_v1_service_proto_rawDescOnce sync.Once + file_konfa_server_v1_service_proto_rawDescData = file_konfa_server_v1_service_proto_rawDesc +) + +func file_konfa_server_v1_service_proto_rawDescGZIP() []byte { + file_konfa_server_v1_service_proto_rawDescOnce.Do(func() { + file_konfa_server_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_konfa_server_v1_service_proto_rawDescData) + }) + return file_konfa_server_v1_service_proto_rawDescData +} + +var file_konfa_server_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_konfa_server_v1_service_proto_goTypes = []any{ + (*ListServerChannelsRequest)(nil), // 0: konfa.server.v1.ListServerChannelsRequest + (*ListServerChannelsResponse)(nil), // 1: konfa.server.v1.ListServerChannelsResponse + (*v1.Channel)(nil), // 2: konfa.channel.v1.Channel +} +var file_konfa_server_v1_service_proto_depIdxs = []int32{ + 2, // 0: konfa.server.v1.ListServerChannelsResponse.channels:type_name -> konfa.channel.v1.Channel + 0, // 1: konfa.server.v1.ServerService.ListServerChannels:input_type -> konfa.server.v1.ListServerChannelsRequest + 1, // 2: konfa.server.v1.ServerService.ListServerChannels:output_type -> konfa.server.v1.ListServerChannelsResponse + 2, // [2:3] is the sub-list for method output_type + 1, // [1:2] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_konfa_server_v1_service_proto_init() } +func file_konfa_server_v1_service_proto_init() { + if File_konfa_server_v1_service_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_konfa_server_v1_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_konfa_server_v1_service_proto_goTypes, + DependencyIndexes: file_konfa_server_v1_service_proto_depIdxs, + MessageInfos: file_konfa_server_v1_service_proto_msgTypes, + }.Build() + File_konfa_server_v1_service_proto = out.File + file_konfa_server_v1_service_proto_rawDesc = nil + file_konfa_server_v1_service_proto_goTypes = nil + file_konfa_server_v1_service_proto_depIdxs = nil +} diff --git a/src/proto/konfa/server/v1/service_grpc.pb.go b/src/proto/konfa/server/v1/service_grpc.pb.go new file mode 100644 index 0000000..aa27d57 --- /dev/null +++ b/src/proto/konfa/server/v1/service_grpc.pb.go @@ -0,0 +1,119 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc (unknown) +// source: konfa/server/v1/service.proto + +package serverv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + ServerService_ListServerChannels_FullMethodName = "/konfa.server.v1.ServerService/ListServerChannels" +) + +// ServerServiceClient is the client API for ServerService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ServerServiceClient interface { + ListServerChannels(ctx context.Context, in *ListServerChannelsRequest, opts ...grpc.CallOption) (*ListServerChannelsResponse, error) +} + +type serverServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewServerServiceClient(cc grpc.ClientConnInterface) ServerServiceClient { + return &serverServiceClient{cc} +} + +func (c *serverServiceClient) ListServerChannels(ctx context.Context, in *ListServerChannelsRequest, opts ...grpc.CallOption) (*ListServerChannelsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListServerChannelsResponse) + err := c.cc.Invoke(ctx, ServerService_ListServerChannels_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ServerServiceServer is the server API for ServerService service. +// All implementations should embed UnimplementedServerServiceServer +// for forward compatibility. +type ServerServiceServer interface { + ListServerChannels(context.Context, *ListServerChannelsRequest) (*ListServerChannelsResponse, error) +} + +// UnimplementedServerServiceServer should be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedServerServiceServer struct{} + +func (UnimplementedServerServiceServer) ListServerChannels(context.Context, *ListServerChannelsRequest) (*ListServerChannelsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListServerChannels not implemented") +} +func (UnimplementedServerServiceServer) testEmbeddedByValue() {} + +// UnsafeServerServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ServerServiceServer will +// result in compilation errors. +type UnsafeServerServiceServer interface { + mustEmbedUnimplementedServerServiceServer() +} + +func RegisterServerServiceServer(s grpc.ServiceRegistrar, srv ServerServiceServer) { + // If the following call pancis, it indicates UnimplementedServerServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&ServerService_ServiceDesc, srv) +} + +func _ServerService_ListServerChannels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListServerChannelsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ServerServiceServer).ListServerChannels(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ServerService_ListServerChannels_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ServerServiceServer).ListServerChannels(ctx, req.(*ListServerChannelsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ServerService_ServiceDesc is the grpc.ServiceDesc for ServerService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ServerService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "konfa.server.v1.ServerService", + HandlerType: (*ServerServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListServerChannels", + Handler: _ServerService_ListServerChannels_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "konfa/server/v1/service.proto", +} diff --git a/src/proto/mappers.go b/src/proto/mappers.go new file mode 100644 index 0000000..d7e8a1c --- /dev/null +++ b/src/proto/mappers.go @@ -0,0 +1,49 @@ +package proto + +import ( + channelv1 "github.com/royalcat/konfa-server/src/proto/konfa/channel/v1" + chatv1 "github.com/royalcat/konfa-server/src/proto/konfa/chat/v1" + "github.com/royalcat/konfa-server/src/store" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func mapMessage(msg store.Message) *chatv1.Message { + return &chatv1.Message{ + MessageId: msg.ID.String(), + SenderId: msg.SenderID.String(), + Content: msg.Content, + Timestamp: timestamppb.New(msg.Timestamp), + } +} + +func mapTextChannelToChannel(c store.TextChannel) *channelv1.Channel { + return &channelv1.Channel{ + Channel: &channelv1.Channel_TextChannel{ + TextChannel: mapTextChannel(c), + }, + } +} + +func mapVoiceChannelToChannel(c store.VoiceChannel) *channelv1.Channel { + return &channelv1.Channel{ + Channel: &channelv1.Channel_VoiceChannel{ + VoiceChannel: mapVoiceChannel(c), + }, + } +} + +func mapTextChannel(c store.TextChannel) *channelv1.TextChannel { + return &channelv1.TextChannel{ + ServerId: c.ServerID.String(), + ChannelId: c.ID.String(), + Name: c.Name, + } +} + +func mapVoiceChannel(c store.VoiceChannel) *channelv1.VoiceChannel { + return &channelv1.VoiceChannel{ + ServerId: c.ServerID.String(), + ChannelId: c.ID.String(), + Name: c.Name, + } +} diff --git a/src/proto/servers.go b/src/proto/servers.go new file mode 100644 index 0000000..cb05530 --- /dev/null +++ b/src/proto/servers.go @@ -0,0 +1,48 @@ +package proto + +import ( + "context" + + "github.com/royalcat/konfa-server/pkg/uuid" + "github.com/royalcat/konfa-server/src/konfa" + channelv1 "github.com/royalcat/konfa-server/src/proto/konfa/channel/v1" + serverv1 "github.com/royalcat/konfa-server/src/proto/konfa/server/v1" + "github.com/royalcat/konfa-server/src/store" +) + +func NewServerService(srv *konfa.Service) *ServerService { + return &ServerService{srv: srv} +} + +type ServerService struct { + srv *konfa.Service +} + +var _ serverv1.ServerServiceServer = (*ServerService)(nil) + +// ListServerChannels implements serverv1.ServerServiceServer. +func (s *ServerService) ListServerChannels(ctx context.Context, req *serverv1.ListServerChannelsRequest) (*serverv1.ListServerChannelsResponse, error) { + serverID, err := uuid.FromString(req.ServerId) + if err != nil { + return nil, err + } + + textChannels, err := s.srv.ListTextChannels(ctx, serverID) + if err != nil { + return nil, err + } + + voiceChannels := []store.VoiceChannel{{ + ID: serverID, + ServerID: serverID, + Name: "general", + }} + + channels := make([]*channelv1.Channel, 0, len(textChannels)+len(voiceChannels)) + channels = append(channels, apply(textChannels, mapTextChannelToChannel)...) + channels = append(channels, apply(voiceChannels, mapVoiceChannelToChannel)...) + + return &serverv1.ListServerChannelsResponse{ + Channels: channels, + }, nil +} diff --git a/src/proto/util.go b/src/proto/util.go new file mode 100644 index 0000000..3ea6fdb --- /dev/null +++ b/src/proto/util.go @@ -0,0 +1,34 @@ +package proto + +import ( + "github.com/royalcat/konfa-server/pkg/uuid" + chatv1 "github.com/royalcat/konfa-server/src/proto/konfa/chat/v1" +) + +func apply[I any, O any](input []I, f func(I) O) []O { + res := make([]O, 0, len(input)) + for _, v := range input { + res = append(res, f(v)) + } + return res +} + +type channelRef struct { + ServerID uuid.UUID + ChannelID uuid.UUID +} + +func parseChannelRef(ref *chatv1.TextChannelRef) (channelRef, error) { + serverID, err := uuid.FromString(ref.ServerId) + if err != nil { + return channelRef{}, err + } + channelID, err := uuid.FromString(ref.ChannelId) + if err != nil { + return channelRef{}, err + } + return channelRef{ + ServerID: serverID, + ChannelID: channelID, + }, nil +} diff --git a/src/store/connect_pg.go b/src/store/connect_pg.go new file mode 100644 index 0000000..f6757e4 --- /dev/null +++ b/src/store/connect_pg.go @@ -0,0 +1,103 @@ +package store + +import ( + "context" + "database/sql" + "embed" + "fmt" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" + "github.com/jackc/pgx/v5/stdlib" + "github.com/pressly/goose/v3" + "github.com/uptrace/bun" + "github.com/uptrace/bun/dialect/pgdialect" + "github.com/uptrace/bun/extra/bundebug" + "github.com/uptrace/bun/extra/bunotel" + + sq "github.com/Masterminds/squirrel" + + _ "github.com/golang-migrate/migrate/v4/database/postgres" + + _ "github.com/jackc/pgx/v5/stdlib" +) + +//go:embed pg_migrations/*.sql +var pg_migrations embed.FS + +func ConnectPostgres(ctx context.Context, databaseURL string) (*bun.DB, *pgxpool.Pool, error) { + sq.StatementBuilder = sq.StatementBuilder.PlaceholderFormat(sq.Dollar) + + dbconfig, err := pgxpool.ParseConfig(databaseURL) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse database URL: %w", err) + } + // dbconfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error { + // pgxuuid.Register(conn.TypeMap()) + // return nil + // } + + if err := postgresMigrate(ctx, dbconfig.ConnConfig.Copy()); err != nil { + return nil, nil, fmt.Errorf("failed to apply migrations: %w", err) + } + + dbpool, err := pgxpool.NewWithConfig(ctx, dbconfig) + if err != nil { + return nil, nil, fmt.Errorf("failed to connect to database: %w", err) + } + + // db, err := gorm.Open( + // postgres.New(postgres.Config{ + // Conn: stdlib.OpenDBFromPool(dbpool), + // }), + // &gorm.Config{ + // Logger: logger.New( + // slog.NewWriter(), + // logger.Config{ + // SlowThreshold: time.Millisecond, + // LogLevel: logger.Warn, + // Colorful: false, + // }, + // ), + // NamingStrategy: schema.NamingStrategy{ + // SingularTable: true, + // }, + // }) + // if err != nil { + // return nil, nil, err + // } + + // err = db.Use(tracing.NewPlugin()) + // if err != nil { + // return nil, nil, fmt.Errorf("failed to use tracing plugin: %w", err) + // } + + sqldb := stdlib.OpenDBFromPool(dbpool) + db := bun.NewDB(sqldb, pgdialect.New()) + db.AddQueryHook(bunotel.NewQueryHook(bunotel.WithDBName("mydb"))) + db.AddQueryHook(bundebug.NewQueryHook( + bundebug.WithVerbose(true), // log everything + )) + + return db, dbpool, nil +} + +func postgresMigrate(ctx context.Context, dbconfig *pgx.ConnConfig) error { + goose.SetBaseFS(pg_migrations) + + if err := goose.SetDialect("postgres"); err != nil { + return fmt.Errorf("failed to set goose dialect: %w", err) + } + + db, err := sql.Open("pgx", dbconfig.ConnString()) + if err != nil { + return fmt.Errorf("failed to open database connection: %w", err) + } + + err = goose.UpContext(ctx, db, "pg_migrations") + if err != nil { + return fmt.Errorf("failed to apply migrations: %w", err) + } + + return nil +} diff --git a/src/store/models.go b/src/store/models.go new file mode 100644 index 0000000..67b558e --- /dev/null +++ b/src/store/models.go @@ -0,0 +1,42 @@ +package store + +import ( + "time" + + "github.com/royalcat/konfa-server/pkg/uuid" + "github.com/uptrace/bun" +) + +type Server struct { + bun.BaseModel `bun:"table:server"` + + ID uuid.UUID `bun:"id,pk"` + Name string `bun:"name"` +} + +type TextChannel struct { + bun.BaseModel `bun:"table:text_channel"` + + ID uuid.UUID `bun:"id,pk"` + ServerID uuid.UUID `bun:"server_id"` + Name string `bun:"name"` +} + +type Message struct { + bun.BaseModel `bun:"table:message"` + + ID uuid.UUID `bun:"id,pk"` + // ServerID uuid.UUID `bun:"server_id"` + ChannelID uuid.UUID `bun:"channel_id"` + SenderID uuid.UUID `bun:"sender_id"` + Content string `bun:"content"` + Timestamp time.Time `bun:"timestamp"` +} + +type VoiceChannel struct { + bun.BaseModel `bun:"table:voice_channel"` + + ID uuid.UUID `bun:"id,pk"` + ServerID uuid.UUID `bun:"server_id"` + Name string `bun:"name"` +} diff --git a/src/store/pg_migrations/1_initialize_schema.sql b/src/store/pg_migrations/1_initialize_schema.sql new file mode 100644 index 0000000..c6b5feb --- /dev/null +++ b/src/store/pg_migrations/1_initialize_schema.sql @@ -0,0 +1,38 @@ +-- +goose Up +-- +goose StatementBegin +-- User Table +CREATE TABLE "user" ( + id uuid PRIMARY KEY, + username VARCHAR(255) UNIQUE +); +-- Server Table +CREATE TABLE "server" (id uuid PRIMARY KEY, "name" VARCHAR(255)); +-- TextChannel Table +CREATE TABLE "text_channel" ( + id uuid PRIMARY KEY, + server_id uuid, + FOREIGN KEY (server_id) REFERENCES "server"(id), + "name" VARCHAR(255) +); +CREATE UNIQUE INDEX unique_text_channel_name ON "text_channel"(server_id, "name"); +-- VoiceChannel Table +CREATE TABLE "voice_channel" ( + id uuid PRIMARY KEY, + server_id uuid, + FOREIGN KEY (server_id) REFERENCES "server"(id), + "name" VARCHAR(255) +); +CREATE UNIQUE INDEX unique_text_channel_name ON "text_channel"(server_id, "name"); +-- Message Table +CREATE TABLE "message" ( + id uuid PRIMARY KEY, + channel_id uuid NOT NULL, + FOREIGN KEY (channel_id) REFERENCES "text_channel"(id), + sender_id uuid NOT NULL, + FOREIGN KEY (sender_id) REFERENCES "user"(id), + content TEXT NOT NULL, + "timestamp" TIMESTAMPTZ NOT NULL DEFAULT now() +); +CREATE INDEX message_channel ON "message" USING hash ("channel_id"); +CREATE INDEX message_timestamp ON "message" USING brin ("timestamp"); +-- +goose StatementEnd \ No newline at end of file diff --git a/src/store/utils.go b/src/store/utils.go new file mode 100644 index 0000000..999fd45 --- /dev/null +++ b/src/store/utils.go @@ -0,0 +1,50 @@ +package store + +import ( + "context" + "fmt" + + "github.com/jackc/pgx/v5/pgxpool" + "github.com/royalcat/konfa-server/pkg/uuid" + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +var ReturnIdClause = clause.Returning{Columns: []clause.Column{{Name: "id"}}} + +func PgxExecInsertReturningID(ctx context.Context, dbpool *pgxpool.Pool, sql string, args []interface{}) (uuid.UUID, error) { + rows, err := dbpool.Query(ctx, sql, args...) + if err != nil { + return uuid.Nil, err + } + + id := uuid.New() + if rows.Next() { + err := rows.Scan(&id) + if err != nil { + return uuid.Nil, err + } + } + + return id, nil +} + +type IDRow struct { + ID uuid.UUID `gorm:"column:id" bun:"id,pk"` +} + +func ScanReturnID(tx *gorm.DB) (uuid.UUID, error) { + if tx.Error != nil { + return uuid.Nil, fmt.Errorf("error in transaction: %w", tx.Error) + } + + out := IDRow{ + ID: uuid.Nil, + } + tx = tx.Scan(&out) + if tx.Error != nil { + return uuid.Nil, tx.Error + } + + return out.ID, nil +}