wip
All checks were successful
docker / build-docker (push) Successful in 2m20s

This commit is contained in:
royalcat 2024-12-23 15:54:51 +03:00
commit 530c24b019
35 changed files with 3601 additions and 0 deletions

59
.github/workflows/docker.yaml vendored Normal file
View file

@ -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 }}

15
.vscode/launch.json vendored Normal file
View file

@ -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",
}
]
}

8
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,8 @@
{
"protoc": {
"path": "protoc",
"options": [
"--proto_path=proto",
]
}
}

25
Dockerfile Normal file
View file

@ -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" ]

26
buf.gen.yaml Normal file
View file

@ -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

12
buf.yaml Normal file
View file

@ -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

88
cmd/main.go Normal file
View file

@ -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
}

13
dev.compose.yaml Normal file
View file

@ -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:

61
go.mod Normal file
View file

@ -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
)

191
go.sum Normal file
View file

@ -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=

View file

@ -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
}
}

View file

@ -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
}
})
}

View file

@ -0,0 +1 @@
package broadcast

161
pkg/uuid/uuid.go Normal file
View file

@ -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
}

View file

@ -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;
}

View file

@ -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; }

View file

@ -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;
}

44
src/konfa/channel.go Normal file
View file

@ -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
}

93
src/konfa/message.go Normal file
View file

@ -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
}

45
src/konfa/server.go Normal file
View file

@ -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
}

23
src/konfa/service.go Normal file
View file

@ -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),
}
}

97
src/proto/auth.go Normal file
View file

@ -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)
}

123
src/proto/chat.go Normal file
View file

@ -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
}
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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",
}

View file

@ -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
}

View file

@ -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",
}

49
src/proto/mappers.go Normal file
View file

@ -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,
}
}

48
src/proto/servers.go Normal file
View file

@ -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
}

34
src/proto/util.go Normal file
View file

@ -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
}

103
src/store/connect_pg.go Normal file
View file

@ -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
}

42
src/store/models.go Normal file
View file

@ -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"`
}

View file

@ -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

50
src/store/utils.go Normal file
View file

@ -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
}