Showing preview only (1,540K chars total). Download the full file or copy to clipboard to get everything.
Repository: sentrionic/Valkyrie
Branch: main
Commit: 5daec722cd19
Files: 291
Total size: 1.4 MB
Directory structure:
gitextract_j1xfpjp2/
├── .github/
│ └── workflows/
│ ├── release_build.yml
│ ├── server_ci.yml
│ ├── server_deploy.yml
│ ├── web_ci.yml
│ ├── website-e2e.yml
│ └── website_deploy.yml
├── .gitignore
├── LICENSE
├── README.md
├── server/
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .idea/
│ │ ├── .gitignore
│ │ ├── ValkyrieGo.iml
│ │ ├── dataSources.xml
│ │ ├── modules.xml
│ │ └── vcs.xml
│ ├── Makefile
│ ├── config/
│ │ └── config.go
│ ├── data_sources.go
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── e2e_test.go
│ ├── go.mod
│ ├── go.sum
│ ├── handler/
│ │ ├── account_handler.go
│ │ ├── account_handler_test.go
│ │ ├── auth_handler.go
│ │ ├── auth_handler_test.go
│ │ ├── bind_data.go
│ │ ├── channel_handler.go
│ │ ├── channel_handler_test.go
│ │ ├── friend_handler.go
│ │ ├── friend_handler_test.go
│ │ ├── guild_handler.go
│ │ ├── guild_handler_test.go
│ │ ├── handler.go
│ │ ├── member_handler.go
│ │ ├── member_handler_test.go
│ │ ├── message_handler.go
│ │ ├── message_handler_test.go
│ │ ├── middleware/
│ │ │ ├── auth_user.go
│ │ │ ├── auth_user_test.go
│ │ │ └── timeout.go
│ │ ├── mime_type.go
│ │ └── test_helpers.go
│ ├── injection.go
│ ├── main.go
│ ├── mocks/
│ │ ├── ChannelRepository.go
│ │ ├── ChannelService.go
│ │ ├── FileRepository.go
│ │ ├── FriendRepository.go
│ │ ├── FriendService.go
│ │ ├── GuildRepository.go
│ │ ├── GuildService.go
│ │ ├── MailRepository.go
│ │ ├── MessageRepository.go
│ │ ├── MessageService.go
│ │ ├── RedisRepository.go
│ │ ├── Request.go
│ │ ├── SocketService.go
│ │ ├── UserRepository.go
│ │ └── UserService.go
│ ├── model/
│ │ ├── app_constants.go
│ │ ├── apperrors/
│ │ │ ├── apperrors.go
│ │ │ └── httperrors.go
│ │ ├── base_model.go
│ │ ├── channel.go
│ │ ├── direct_message.go
│ │ ├── dm_member.go
│ │ ├── field_error.go
│ │ ├── fixture/
│ │ │ ├── channel.go
│ │ │ ├── faker.go
│ │ │ ├── guild.go
│ │ │ ├── message.go
│ │ │ ├── multipart.go
│ │ │ └── user.go
│ │ ├── friend.go
│ │ ├── friend_request.go
│ │ ├── guild.go
│ │ ├── interfaces.go
│ │ ├── invite.go
│ │ ├── member.go
│ │ ├── message.go
│ │ ├── user.go
│ │ └── ws_message.go
│ ├── repository/
│ │ ├── channel_repository.go
│ │ ├── file_repository.go
│ │ ├── friend_repository.go
│ │ ├── guild_repository.go
│ │ ├── mail_repository.go
│ │ ├── message_repository.go
│ │ ├── redis_repository.go
│ │ └── user_repository.go
│ ├── service/
│ │ ├── channel_service.go
│ │ ├── channel_service_test.go
│ │ ├── friend_service.go
│ │ ├── guild_service.go
│ │ ├── guild_service_test.go
│ │ ├── id_generator.go
│ │ ├── message_service.go
│ │ ├── message_service_test.go
│ │ ├── password.go
│ │ ├── password_test.go
│ │ ├── socket_service.go
│ │ ├── user_service.go
│ │ └── user_service_test.go
│ ├── static/
│ │ ├── asyncapi.yml
│ │ ├── index.html
│ │ └── js/
│ │ └── main.js
│ └── ws/
│ ├── actions.go
│ ├── client.go
│ ├── hub.go
│ └── room.go
└── web/
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── cypress/
│ ├── e2e/
│ │ ├── account.cy.ts
│ │ ├── channel.cy.ts
│ │ ├── friend.cy.ts
│ │ ├── guild.cy.ts
│ │ ├── member.cy.ts
│ │ └── message.cy.ts
│ ├── fixtures/
│ │ └── example.json
│ ├── plugins/
│ │ └── index.js
│ ├── support/
│ │ ├── commands.ts
│ │ ├── e2e.js
│ │ ├── index.d.ts
│ │ └── utils.ts
│ └── tsconfig.json
├── cypress.config.ts
├── package.json
├── public/
│ ├── _redirects
│ ├── index.html
│ ├── manifest.json
│ └── robots.txt
├── src/
│ ├── App.tsx
│ ├── components/
│ │ ├── common/
│ │ │ ├── GuildPills.tsx
│ │ │ ├── InputField.tsx
│ │ │ ├── Logo.tsx
│ │ │ └── NotificationIcon.tsx
│ │ ├── items/
│ │ │ ├── ChannelListItem.tsx
│ │ │ ├── DMListItem.tsx
│ │ │ ├── FriendsListItem.tsx
│ │ │ ├── GuildListItem.tsx
│ │ │ ├── MemberListItem.tsx
│ │ │ ├── NotificationListItem.tsx
│ │ │ ├── RequestListItem.tsx
│ │ │ ├── VoiceChannelItem.tsx
│ │ │ ├── css/
│ │ │ │ └── ContextMenu.css
│ │ │ └── message/
│ │ │ ├── Message.tsx
│ │ │ └── MessageContent.tsx
│ │ ├── layouts/
│ │ │ ├── AccountBar.tsx
│ │ │ ├── AppLayout.tsx
│ │ │ ├── LandingLayout.tsx
│ │ │ ├── VoiceBar.tsx
│ │ │ ├── guild/
│ │ │ │ ├── ChannelHeader.tsx
│ │ │ │ ├── Channels.tsx
│ │ │ │ ├── GuildList.tsx
│ │ │ │ ├── MemberList.tsx
│ │ │ │ ├── VoiceChat.tsx
│ │ │ │ ├── chat/
│ │ │ │ │ ├── ChatGrid.tsx
│ │ │ │ │ ├── ChatScreen.tsx
│ │ │ │ │ ├── FileUploadButton.tsx
│ │ │ │ │ └── MessageInput.tsx
│ │ │ │ └── css/
│ │ │ │ ├── ChannelScrollerCSS.ts
│ │ │ │ ├── GuildScrollerCSS.ts
│ │ │ │ ├── MemberScrollerCSS.ts
│ │ │ │ └── MessageInput.css
│ │ │ └── home/
│ │ │ ├── DMHeader.tsx
│ │ │ ├── DMSidebar.tsx
│ │ │ ├── css/
│ │ │ │ └── dmScrollerCSS.ts
│ │ │ └── dashboard/
│ │ │ ├── FriendsDashboard.tsx
│ │ │ ├── FriendsList.tsx
│ │ │ ├── FriendsListHeader.tsx
│ │ │ └── PendingList.tsx
│ │ ├── menus/
│ │ │ ├── GuildMenu.tsx
│ │ │ ├── MemberContextMenu.tsx
│ │ │ ├── StyledMenuItem.tsx
│ │ │ └── StyledMenuList.tsx
│ │ ├── modals/
│ │ │ ├── AddFriendModal.tsx
│ │ │ ├── AddGuildModal.tsx
│ │ │ ├── ChangePasswordModal.tsx
│ │ │ ├── ChannelSettingsModal.tsx
│ │ │ ├── CreateChannelModal.tsx
│ │ │ ├── CropImageModal.tsx
│ │ │ ├── DeleteMessageModal.tsx
│ │ │ ├── EditMemberModal.tsx
│ │ │ ├── EditMessageModal.tsx
│ │ │ ├── GuildSettingsModal.tsx
│ │ │ ├── InviteModal.tsx
│ │ │ ├── ModActionModal.tsx
│ │ │ └── RemoveFriendModal.tsx
│ │ └── sections/
│ │ ├── AddGuildIcon.tsx
│ │ ├── DMPlaceholder.tsx
│ │ ├── DateDivider.tsx
│ │ ├── Footer.tsx
│ │ ├── FriendsListButton.tsx
│ │ ├── GlobalState.tsx
│ │ ├── Hero.tsx
│ │ ├── HomeIcon.tsx
│ │ ├── NavBar.tsx
│ │ ├── OnlineLabel.tsx
│ │ ├── StartMessages.tsx
│ │ ├── StyledTooltip.tsx
│ │ └── UserPopover.tsx
│ ├── index.tsx
│ ├── lib/
│ │ ├── api/
│ │ │ ├── dtos/
│ │ │ │ ├── AuthInput.ts
│ │ │ │ ├── ChannelInput.ts
│ │ │ │ ├── GuildInput.ts
│ │ │ │ ├── GuildMemberInput.ts
│ │ │ │ ├── InviteInput.ts
│ │ │ │ └── UserInput.ts
│ │ │ ├── getSocket.ts
│ │ │ ├── handler/
│ │ │ │ ├── account.ts
│ │ │ │ ├── auth.ts
│ │ │ │ ├── channel.ts
│ │ │ │ ├── dm.ts
│ │ │ │ ├── guilds.ts
│ │ │ │ ├── members.ts
│ │ │ │ └── messages.ts
│ │ │ ├── setupAxios.ts
│ │ │ └── ws/
│ │ │ ├── useChannelSocket.ts
│ │ │ ├── useDMSocket.ts
│ │ │ ├── useFriendSocket.ts
│ │ │ ├── useGuildSocket.ts
│ │ │ ├── useMemberSocket.ts
│ │ │ ├── useMessageSocket.ts
│ │ │ ├── useRequestSocket.ts
│ │ │ └── useVoiceSocket.ts
│ │ ├── models/
│ │ │ ├── account.ts
│ │ │ ├── channel.ts
│ │ │ ├── dm.ts
│ │ │ ├── fieldError.ts
│ │ │ ├── friend.ts
│ │ │ ├── guild.ts
│ │ │ ├── member.ts
│ │ │ ├── message.ts
│ │ │ ├── routerProps.ts
│ │ │ └── voice.ts
│ │ ├── stores/
│ │ │ ├── channelStore.ts
│ │ │ ├── homeStore.ts
│ │ │ ├── settingsStore.ts
│ │ │ ├── userStore.ts
│ │ │ └── voiceStore.ts
│ │ └── utils/
│ │ ├── cropImage.ts
│ │ ├── dateUtils.ts
│ │ ├── hooks/
│ │ │ ├── useGetCurrentChannel.ts
│ │ │ ├── useGetCurrentDM.ts
│ │ │ ├── useGetCurrentGuild.ts
│ │ │ ├── useGetFriend.ts
│ │ │ └── useVoiceChat.ts
│ │ ├── querykeys.ts
│ │ ├── theme.ts
│ │ ├── toErrorMap.ts
│ │ └── validation/
│ │ ├── auth.schema.ts
│ │ ├── channel.schema.ts
│ │ ├── guild.schema.ts
│ │ ├── member.schema.ts
│ │ └── message.schema.ts
│ ├── react-app-env.d.ts
│ ├── routes/
│ │ ├── AuthRoute.tsx
│ │ ├── ForgotPassword.tsx
│ │ ├── Home.tsx
│ │ ├── Invite.tsx
│ │ ├── Landing.tsx
│ │ ├── Login.tsx
│ │ ├── Register.tsx
│ │ ├── ResetPassword.tsx
│ │ ├── Routes.tsx
│ │ ├── Settings.tsx
│ │ └── ViewGuild.tsx
│ ├── setupTests.ts
│ └── tests/
│ ├── fixture/
│ │ ├── accountFixture.ts
│ │ ├── channelFixtures.ts
│ │ ├── dmFixtures.ts
│ │ ├── friendFixture.ts
│ │ ├── guildFixtures.ts
│ │ ├── memberFixtures.ts
│ │ ├── messageFixtures.ts
│ │ └── requestFixtures.ts
│ ├── queries/
│ │ ├── account.test.tsx
│ │ ├── channel.test.tsx
│ │ ├── dm.test.tsx
│ │ ├── friend.test.tsx
│ │ ├── guild.test.tsx
│ │ ├── member.test.tsx
│ │ ├── message.test.tsx
│ │ └── request.test.tsx
│ └── testUtils.tsx
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/release_build.yml
================================================
name: Release Server Binary
on:
release:
types: [created]
jobs:
releases-matrix:
name: Release Go Binary
runs-on: ubuntu-latest
strategy:
matrix:
goos: [linux, windows, darwin]
goarch: ['386', amd64]
exclude:
- goarch: '386'
goos: darwin
steps:
- uses: actions/checkout@v3
- uses: wangyoucao577/go-release-action@v1.38
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
project_path: './server'
binary_name: 'valkyrie-server'
md5sum: false
extra_files: ./server/.env.example README.md
================================================
FILE: .github/workflows/server_ci.yml
================================================
name: Test & Lint
on:
push:
paths:
- 'server/**'
pull_request:
paths:
- 'server/**'
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v4
with:
go-version: 1.20
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: latest
args: --timeout=5m
working-directory: ./server
test:
name: Test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:alpine
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: secret
POSTGRES_DB: valkyrie
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: 'redis:alpine'
ports:
- '6379:6379'
volumes:
- 'redisdata:/data'
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.20
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Run Unit Tests
working-directory: ./server
run: make test
- name: Run E2E
run: make e2e
working-directory: ./server
env:
DATABASE_URL: postgresql://root:secret@localhost:5432/valkyrie?sslmode=disable
HANDLER_TIMEOUT: 5
MAX_BODY_BYTES: 4194304
REDIS_URL: redis://localhost:6379
SECRET: jmaijopspahisodphiasdhiahiopsdhoiasdg8a89sdta08sdtg8aosdou
CORS_ORIGIN: origin
================================================
FILE: .github/workflows/server_deploy.yml
================================================
# name: Deploy [API]
# on:
# workflow_run:
# workflows: ['Test & Lint']
# branches: [main]
# types: [completed]
# jobs:
# on-success:
# runs-on: ubuntu-latest
# if: ${{ github.event.workflow_run.conclusion == 'success' }}
# steps:
# - uses: actions/checkout@v3
# - uses: akhileshns/heroku-deploy@v3.12.12
# with:
# heroku_api_key: ${{secrets.HEROKU_API_KEY}}
# heroku_app_name: ${{secrets.HEROKU_APP_NAME}}
# heroku_email: ${{secrets.HEROKU_EMAIL}}
# appdir: 'server'
================================================
FILE: .github/workflows/web_ci.yml
================================================
name: Test & Lint - Web
on:
push:
paths:
- 'web/**'
pull_request:
paths:
- 'web/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js 20.x
uses: actions/setup-node@v3
with:
node-version: '20.x'
cache: 'yarn'
cache-dependency-path: web/yarn.lock
- run: cd web && yarn install
- run: cd web && yarn compile
- run: cd web && yarn lint
- run: cd web && yarn test --watchAll=false
================================================
FILE: .github/workflows/website-e2e.yml
================================================
name: Website E2E
on:
workflow_run:
workflows: ['Test & Lint - Web']
branches: [main]
types: [completed]
jobs:
cypress-run:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:alpine
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: secret
POSTGRES_DB: valkyrie
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: 'redis:alpine'
ports:
- '6379:6379'
volumes:
- 'redisdata:/data'
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.20
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Run Server
run: go run github.com/sentrionic/valkyrie &
working-directory: ./server
env:
DATABASE_URL: postgresql://root:secret@localhost:5432/valkyrie?sslmode=disable
HANDLER_TIMEOUT: 5
MAX_BODY_BYTES: 4194304
REDIS_URL: redis://localhost:6379
SECRET: jmaijopspahisodphiasdhiahiopsdhoiasdg8a89sdta08sdtg8aosdou
PORT: 4000
CORS_ORIGIN: http://localhost:3000
GIN_MODE: release
- name: Cypress run
uses: cypress-io/github-action@v4
with:
install-command: yarn
start: yarn start
wait-on: http://localhost:3000
browser: chrome
working-directory: ./web
headless: true
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REACT_APP_API: http://localhost:4000
REACT_APP_WS: ws://http://localhost:4000/ws
================================================
FILE: .github/workflows/website_deploy.yml
================================================
# name: Website Deploy
# on:
# workflow_run:
# workflows: ['Website E2E']
# branches: [main]
# types: [completed]
# jobs:
# on-success:
# runs-on: ubuntu-latest
# if: ${{ github.event.workflow_run.conclusion == 'success' }}
# steps:
# - name: Checkout code
# uses: actions/checkout@v3
# - name: Use Node.js 18.x
# uses: actions/setup-node@v3
# with:
# node-version: '18.x'
# cache: 'yarn'
# cache-dependency-path: web/yarn.lock
# - run: yarn install
# working-directory: ./web
# - run: yarn build --if-present
# working-directory: ./web
# - name: Deploy to netlify
# uses: netlify/actions/cli@master
# env:
# NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
# NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
# with:
# args: deploy --dir=web/build --prod
# secrets: '["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]'
================================================
FILE: .gitignore
================================================
# Created by https://www.toptal.com/developers/gitignore/api/webstorm
# Edit at https://www.toptal.com/developers/gitignore?templates=webstorm
### WebStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### WebStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
.idea/**/sonarlint/
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/$CACHE_FILE$
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
.idea/codestream.xml
# End of https://www.toptal.com/developers/gitignore/api/webstorm
# Local Netlify folder
.netlify
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 sentrionic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
[](https://goreportcard.com/report/github.com/sentrionic/Valkyrie)
# Valkyrie
<p align="center">
<img src="https://harmony-cdn.s3.eu-central-1.amazonaws.com/logo.png">
</p>
A [Discord](https://discord.com) clone using [React](https://reactjs.org/) and [Go](https://golang.org/).
**Notes:**
- The design does not fully match the current design of Discord anymore.
- For the old [Socket.io](https://socket.io/) stack using [NestJS](https://nestjs.com/) check out the [v1](https://github.com/sentrionic/Valkyrie/tree/v1) branch.
## Video
https://user-images.githubusercontent.com/38354571/137365365-a7fe91d6-51d7-4739-8742-f68517223f8f.mp4
## Features
- Message, Channel, Server CRUD
- Authentication using Express Sessions
- Channel / Websocket Member Protection
- Realtime Events
- File Upload (Avatar, Icon, Messages) to S3
- Direct Messaging
- Private Channels
- Friend System
- Notification System
- Basic Moderation for the guild owner (delete messages, kick & ban members)
- Basic Voice Chat (one voice channel per guild + mute & deafen)
## Stack
### Server
- [Gin](https://gin-gonic.com/) for the HTTP server
- [Gorilla Websockets](https://github.com/gorilla/websocket) for WS communication
- [Gorm](https://gorm.io/) as the database ORM
- PostgreSQL to save all data
- Redis for storing sessions and reset tokens
- S3 for storing files and Gmail for sending emails
### Web
- React with [Chakra UI](https://chakra-ui.com/)
- [React Query](https://react-query.tanstack.com/) & [Zustand](https://github.com/pmndrs/zustand) for state management
- [Typescript](https://www.typescriptlang.org/)
For the mobile app using Flutter check out [ValkyrieApp](https://github.com/sentrionic/ValkyrieApp)
---
## Installation
### Server
If you are familiar with `make`, take a look at the `Makefile` to quickly setup the following steps
or alternatively copy the commands into your CLI.
1. Install Docker and get the Postgresql and Redis containers (`make postgres` && `make redis`)
2. Start both containers (`make start`) and create a DB (`make createdb`)
3. Install the latest version of Go and get all the dependencies (`go mod tidy`)
4. Rename `.env.example` to `.env` and fill in the values
- `Required`
PORT=4000
DATABASE_URL=postgresql://<username>:<password>@localhost:5432/valkyrie
REDIS_URL=redis://localhost:6379
CORS_ORIGIN=http://localhost:3000
SECRET=SUPERSECRET
HANDLER_TIMEOUT=5
MAX_BODY_BYTES=4194304 # 4MB in Bytes = 4 * 1024 * 1024
- `Optional: Not needed to run the app, but you won't be able to upload files or send emails.`
AWS_ACCESS_KEY=ACCESS_KEY
AWS_SECRET_ACCESS_KEY=SECRET_ACCESS_KEY
AWS_STORAGE_BUCKET_NAME=STORAGE_BUCKET_NAME
AWS_S3_REGION=S3_REGION
GMAIL_USER=GMAIL_USER
GMAIL_PASSWORD=GMAIL_PASSWORD
5. Run `go run github.com/sentrionic/valkyrie` to run the server
**Alternatively**: If you only want to run the backend without installing Go and all dependencies, you can download the pre compiled server from the [Release tab](https://github.com/sentrionic/Valkyrie/releases) instead. You will still need to follow the above steps 1, 2 and 4.
### Web
1. Install Node 20 or the LTS version of Node.
2. Install [yarn](https://classic.yarnpkg.com/lang/en/)
3. Run `yarn` to install the dependencies
4. Run `yarn start` to start the client
5. Go to `localhost:3000`
## Endpoints
Once the server is running go to `localhost:<PORT>/swagger/index.html` to see all the HTTP endpoints
and `localhost:<PORT>` for all the websockets events.
## Tests
All tests are run on all push and pull requests. Only if they are successful it will run the other Github Actions to automatically deploy the updates.
### Server
All routes in `handler` have tests written for them.
Function calls in the `service` directory that do not just delegate work to the repository have tests written for them.
Run `go test -v -cover ./service/... ./handler/...` (`make test`) to run all tests
Additionally this repository includes E2E tests for all successful requests. To run them you
have to have Postgres and Redis running in Docker and then run `go test github.com/sentrionic/valkyrie` (`make e2e`).
### Web
Most `useQuery` hooks have tests written for them.
To run them use `yarn test`.
Additionally [Cypress](https://www.cypress.io/) is used for E2E testing.
To run them you need to have the server and the client running.
After that run `yarn cypress` to open the test window.
**Note**: For unkown reasons websockets connection only randomly work during Cypress runs, which makes testing them impossible.
## Credits
[Ben Awad](https://github.com/benawad): The inital project is based on his Slack tutorial series and I always look at his repositories for inspiration.
[Jacob Goodwin](https://github.com/JacobSNGoodwin/memrizr): This backend is built upon his tutorial series and uses his backend structure.
[Jeroen de Kok](https://dev.to/jeroendk/building-a-simple-chat-application-with-websockets-in-go-and-vue-js-gao): The websockets structure is based on his tutorial.
[ericellb](https://github.com/ericellb/React-Discord-Clone): His repository helped me implement voice chat.
================================================
FILE: server/.gitattributes
================================================
*.html -linguist-detectable
*.css -linguist-detectable
*.js -linguist-detectable
================================================
FILE: server/.gitignore
================================================
# Created by https://www.toptal.com/developers/gitignore/api/go
# Edit at https://www.toptal.com/developers/gitignore?templates=go
.env
### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
### Go Patch ###
/vendor/
/Godeps/
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# End of https://www.toptal.com/developers/gitignore/api/go
================================================
FILE: server/.idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
================================================
FILE: server/.idea/ValkyrieGo.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
================================================
FILE: server/.idea/dataSources.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="DB" uuid="c44e306a-81ee-4f6d-bb8b-be5992634d17">
<driver-ref>postgresql</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
<jdbc-url>jdbc:postgresql://localhost:5432/valkyrie</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>
================================================
FILE: server/.idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/ValkyrieGo.iml" filepath="$PROJECT_DIR$/.idea/ValkyrieGo.iml" />
</modules>
</component>
</project>
================================================
FILE: server/.idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
================================================
FILE: server/Makefile
================================================
postgres:
docker run --name postgres -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=password -d postgres:alpine
redis:
docker run --name redis -d -p 6379:6379 redis:alpine redis-server --save 60 1
createdb:
docker exec -it postgres createdb --username=root --owner=root valkyrie
dropdb:
docker exec -it postgres dropdb valkyrie
recreate:
make dropdb && make createdb
start:
docker start postgres && docker start redis
test:
go test -v -cover ./service/... ./handler/...
e2e:
go test github.com/sentrionic/valkyrie
lint:
golangci-lint run
mock:
mockery --all
build:
go build github.com/sentrionic/valkyrie
fmt:
go fmt github.com/sentrionic/...
swag:
swag init
workflow:
make fmt && make lint && make test
================================================
FILE: server/config/config.go
================================================
package config
import (
"context"
"github.com/sethvargo/go-envconfig"
)
type Config struct {
DatabaseUrl string `env:"DATABASE_URL,required"`
RedisUrl string `env:"REDIS_URL,required"`
Port string `env:"PORT,default=4000"`
SessionSecret string `env:"SECRET,required"`
Domain string `env:"DOMAIN"`
CorsOrigin string `env:"CORS_ORIGIN,required"`
AccessKey string `env:"AWS_ACCESS_KEY"`
SecretKey string `env:"SECRET_KEY"`
BucketName string `env:"BUCKET_NAME"`
Region string `env:"REGION"`
GmailUser string `env:"GMAIL_USER"`
GmailPassword string `env:"GMAIL_PASSWORD"`
HandlerTimeOut int64 `env:"HANDLER_TIMEOUT,default=5"`
MaxBodyBytes int64 `env:"MAX_BODY_BYTES,default=4194304"`
}
func LoadConfig(ctx context.Context) (config Config, err error) {
err = envconfig.Process(ctx, &config)
if err != nil {
return
}
return
}
================================================
FILE: server/data_sources.go
================================================
package main
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/redis/go-redis/v9"
"github.com/sentrionic/valkyrie/config"
"github.com/sentrionic/valkyrie/model"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"log"
)
type dataSources struct {
DB *gorm.DB
RedisClient *redis.Client
S3Session *session.Session
}
// InitDS establishes connections to fields in dataSources
func initDS(ctx context.Context, cfg config.Config) (*dataSources, error) {
log.Printf("Initializing data sources\n")
log.Printf("Connecting to Postgresql\n")
db, err := gorm.Open(postgres.Open(cfg.DatabaseUrl))
if err != nil {
return nil, fmt.Errorf("error opening db: %w", err)
}
// Migrate models and setup join tables
if err = db.AutoMigrate(
&model.User{},
&model.Guild{},
&model.Member{},
&model.Channel{},
&model.DMMember{},
&model.Message{},
&model.Attachment{},
&model.VCMember{},
); err != nil {
return nil, fmt.Errorf("error migrating models: %w", err)
}
if err = db.SetupJoinTable(&model.Guild{}, "Members", &model.Member{}); err != nil {
return nil, fmt.Errorf("error creating join table: %w", err)
}
if err = db.SetupJoinTable(&model.Guild{}, "VCMembers", &model.VCMember{}); err != nil {
return nil, fmt.Errorf("error creating join table: %w", err)
}
// Initialize redis connection
opt, err := redis.ParseURL(cfg.RedisUrl)
if err != nil {
return nil, fmt.Errorf("error parsing the redis url: %w", err)
}
log.Println("Connecting to Redis")
rdb := redis.NewClient(opt)
// verify redis connection
_, err = rdb.Ping(ctx).Result()
if err != nil {
return nil, fmt.Errorf("error connecting to redis: %w", err)
}
// Initialize S3 Session
sess, err := session.NewSession(
&aws.Config{
Credentials: credentials.NewStaticCredentials(
cfg.AccessKey,
cfg.SessionSecret,
"",
),
Region: aws.String(cfg.Region),
},
)
if err != nil {
return nil, fmt.Errorf("error creating s3 session: %w", err)
}
return &dataSources{
DB: db,
RedisClient: rdb,
S3Session: sess,
}, nil
}
// close to be used in graceful server shutdown
func (d *dataSources) close() error {
if err := d.RedisClient.Close(); err != nil {
return fmt.Errorf("error closing Redis Client: %w", err)
}
return nil
}
================================================
FILE: server/docs/docs.go
================================================
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag
package docs
import (
"bytes"
"encoding/json"
"strings"
"github.com/alecthomas/template"
"github.com/swaggo/swag"
)
var doc = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
"description": "{{.Description}}",
"title": "{{.Title}}",
"contact": {},
"license": {
"name": "Apache 2.0"
},
"version": "{{.Version}}"
},
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/account": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Get Current User",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/User"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"put": {
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Update Current User",
"parameters": [
{
"description": "Update Account",
"name": "account",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/EditUser"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/change-password": {
"put": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Change Current User's Password",
"parameters": [
{
"description": "Change Password",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ChangePasswordRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/forgot-password": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Forgot Password Request",
"parameters": [
{
"description": "Forgot Password",
"name": "email",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ForgotPasswordRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/login": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "User Login",
"parameters": [
{
"description": "Login account",
"name": "account",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/LoginRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/logout": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "User Logout",
"parameters": [
{
"description": "Login account",
"name": "account",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/LoginRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
}
}
}
},
"/account/me/friends": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Get Current User's Friends",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Friend"
}
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/me/pending": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Get Current User's Friend Requests",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/FriendRequest"
}
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/register": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Create an Account",
"parameters": [
{
"description": "Create account",
"name": "account",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/RegisterRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/reset-password": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Reset Password",
"parameters": [
{
"description": "Reset Password",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ResetPasswordRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/{memberId}/friend": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Send Friend Request",
"parameters": [
{
"type": "string",
"description": "User ID",
"name": "memberId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Remove Friend",
"parameters": [
{
"type": "string",
"description": "User ID",
"name": "memberId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/{memberId}/friend/accept": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Accept Friend's Request",
"parameters": [
{
"type": "string",
"description": "User ID",
"name": "memberId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/{memberId}/friend/cancel": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Cancel Friend's Request",
"parameters": [
{
"type": "string",
"description": "User ID",
"name": "memberId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/me/dm": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Get User's DMs",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/DirectMessage"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{channelId}": {
"put": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Edit Channel",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "channelId",
"in": "path",
"required": true
},
{
"description": "Edit Channel",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ChannelRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{channelId}/dm": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Get or Create DM",
"parameters": [
{
"type": "string",
"description": "Member ID",
"name": "channelId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/DirectMessage"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{channelId}/members": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Get Members of the given Channel",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "channelId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{guildId}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Get Guild Channels",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Channel"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Create Channel",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Channel"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{id}": {
"delete": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Delete Channel",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{id}/dm": {
"delete": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Close DM",
"parameters": [
{
"type": "string",
"description": "DM Channel ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Get Current User's Guilds",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/GuildResponse"
}
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/create": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Create Guild",
"parameters": [
{
"description": "Create Guild",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/CreateGuildRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/GuildResponse"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/join": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Join Guild",
"parameters": [
{
"description": "Join Guild",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/JoinRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/GuildResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}": {
"put": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Edit Guild",
"parameters": [
{
"description": "Edit Guild",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/EditGuildRequest"
}
},
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Leave Guild",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/bans": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Get Guild Ban list",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/BanResponse"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Ban Member",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
},
{
"description": "Member ID",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MemberRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/SuccessResponse"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Unban Member",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
},
{
"description": "Member ID",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MemberRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/SuccessResponse"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/delete": {
"delete": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Delete Guild",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/invite": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Get Guild Invite",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
},
{
"type": "boolean",
"description": "Is Permanent",
"name": "isPermanent",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Delete all permanent invite links",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/kick": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Kick Member",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
},
{
"description": "Member ID",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MemberRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/SuccessResponse"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/member": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Get Member Settings",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/MemberSettings"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"put": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Edit Member Settings",
"parameters": [
{
"description": "Edit Member",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MemberSettingsRequest"
}
},
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/members": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Get Guild Members",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Member"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/messages/{channelId}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Messages"
],
"summary": "Get Channel Messages",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "channelId",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Cursor Pagination using the createdAt field",
"name": "cursor",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Message"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"Messages"
],
"summary": "Create Messages",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "channelId",
"in": "path",
"required": true
},
{
"description": "Create Message",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MessageRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/messages/{messageId}": {
"put": {
"produces": [
"application/json"
],
"tags": [
"Messages"
],
"summary": "Edit Messages",
"parameters": [
{
"type": "string",
"description": "Message ID",
"name": "messageId",
"in": "path",
"required": true
},
{
"description": "Edit Message",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MessageRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Messages"
],
"summary": "Delete Messages",
"parameters": [
{
"type": "string",
"description": "Message ID",
"name": "messageId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
}
},
"definitions": {
"Attachment": {
"type": "object",
"properties": {
"filename": {
"type": "string"
},
"filetype": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"BanResponse": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
"ChangePasswordRequest": {
"type": "object",
"properties": {
"confirmNewPassword": {
"description": "Must be the same as the newPassword value.",
"type": "string"
},
"currentPassword": {
"type": "string"
},
"newPassword": {
"description": "Min 6, max 150 characters.",
"type": "string"
}
}
},
"Channel": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"hasNotification": {
"type": "boolean"
},
"id": {
"type": "string"
},
"isPublic": {
"type": "boolean"
},
"name": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
},
"ChannelRequest": {
"type": "object",
"properties": {
"isPublic": {
"description": "Default is true",
"type": "boolean"
},
"members": {
"description": "Array of memberIds",
"type": "array",
"items": {
"type": "string"
}
},
"name": {
"description": "Channel Name. 3 to 30 character",
"type": "string"
}
}
},
"CreateGuildRequest": {
"type": "object",
"properties": {
"name": {
"description": "Guild Name. 3 to 30 characters",
"type": "string"
}
}
},
"DMUser": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"isFriend": {
"type": "boolean"
},
"isOnline": {
"type": "boolean"
},
"username": {
"type": "string"
}
}
},
"DirectMessage": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"user": {
"$ref": "#/definitions/DMUser"
}
}
},
"EditGuildRequest": {
"type": "object",
"properties": {
"icon": {
"description": "The old guild icon url if no new image is selected. Set to null to reset the guild icon",
"type": "string"
},
"image": {
"description": "image/png or image/jpeg",
"type": "string",
"format": "binary"
},
"name": {
"description": "Guild Name. 3 to 30 characters",
"type": "string"
}
}
},
"EditUser": {
"type": "object",
"properties": {
"email": {
"description": "Must be unique",
"type": "string"
},
"image": {
"description": "image/png or image/jpeg",
"type": "string",
"format": "binary"
},
"username": {
"description": "Min 3, max 30 characters.",
"type": "string"
}
}
},
"ErrorResponse": {
"type": "object",
"properties": {
"error": {
"$ref": "#/definitions/HttpError"
}
}
},
"ErrorsResponse": {
"type": "object",
"properties": {
"errors": {
"type": "array",
"items": {
"$ref": "#/definitions/FieldError"
}
}
}
},
"FieldError": {
"type": "object",
"properties": {
"field": {
"description": "The property containing the error",
"type": "string"
},
"message": {
"description": "The specific error message",
"type": "string"
}
}
},
"ForgotPasswordRequest": {
"type": "object",
"properties": {
"email": {
"type": "string"
}
}
},
"Friend": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"isOnline": {
"type": "boolean"
},
"username": {
"type": "string"
}
}
},
"FriendRequest": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"type": {
"description": "1: Incoming, 0: Outgoing",
"type": "integer",
"enum": [
0,
1
]
},
"username": {
"type": "string"
}
}
},
"GuildResponse": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"default_channel_id": {
"type": "string"
},
"hasNotification": {
"type": "boolean"
},
"icon": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"ownerId": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
},
"HttpError": {
"type": "object",
"properties": {
"message": {
"description": "The specific error message",
"type": "string"
},
"type": {
"description": "The Http Response as a string",
"type": "string"
}
}
},
"JoinRequest": {
"type": "object",
"properties": {
"link": {
"type": "string"
}
}
},
"LoginRequest": {
"type": "object",
"properties": {
"email": {
"description": "Must be unique",
"type": "string"
},
"password": {
"description": "Min 6, max 150 characters.",
"type": "string"
}
}
},
"Member": {
"type": "object",
"properties": {
"color": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"isFriend": {
"type": "boolean"
},
"isOnline": {
"type": "boolean"
},
"nickname": {
"type": "string"
},
"updatedAt": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
"MemberRequest": {
"type": "object",
"properties": {
"memberId": {
"type": "string"
}
}
},
"MemberSettings": {
"type": "object",
"properties": {
"color": {
"type": "string"
},
"nickname": {
"type": "string"
}
}
},
"MemberSettingsRequest": {
"type": "object",
"properties": {
"color": {
"type": "string"
},
"nickname": {
"type": "string"
}
}
},
"Message": {
"type": "object",
"properties": {
"attachment": {
"$ref": "#/definitions/Attachment"
},
"createdAt": {
"type": "string"
},
"id": {
"type": "string"
},
"text": {
"type": "string"
},
"updatedAt": {
"type": "string"
},
"user": {
"$ref": "#/definitions/Member"
}
}
},
"MessageRequest": {
"type": "object",
"properties": {
"file": {
"description": "image/* or audio/*",
"type": "string",
"format": "binary"
},
"text": {
"description": "Maximum 2000 characters",
"type": "string"
}
}
},
"RegisterRequest": {
"type": "object",
"properties": {
"email": {
"description": "Must be unique",
"type": "string"
},
"password": {
"description": "Min 6, max 150 characters.",
"type": "string"
},
"username": {
"description": "Min 3, max 30 characters.",
"type": "string"
}
}
},
"ResetPasswordRequest": {
"type": "object",
"properties": {
"confirmNewPassword": {
"description": "Must be the same as the password value.",
"type": "string"
},
"newPassword": {
"description": "Min 6, max 150 characters.",
"type": "string"
},
"token": {
"description": "The token the user got from the email.",
"type": "string"
}
}
},
"SuccessResponse": {
"type": "object",
"properties": {
"success": {
"description": "Only returns true, not a json object",
"type": "boolean"
}
}
},
"User": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"email": {
"type": "string"
},
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"isOnline": {
"type": "boolean"
},
"updatedAt": {
"type": "string"
},
"username": {
"type": "string"
}
}
}
}
}`
type swaggerInfo struct {
Version string
Host string
BasePath string
Schemes []string
Title string
Description string
}
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = swaggerInfo{
Version: "1.0",
Host: "localhost:<PORT>",
BasePath: "/api",
Schemes: []string{},
Title: "Valkyrie API",
Description: "Valkyrie REST API Specs. This service uses sessions for authentication",
}
type s struct{}
func (s *s) ReadDoc() string {
sInfo := SwaggerInfo
sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
t, err := template.New("swagger_info").Funcs(template.FuncMap{
"marshal": func(v any) string {
a, _ := json.Marshal(v)
return string(a)
},
}).Parse(doc)
if err != nil {
return doc
}
var tpl bytes.Buffer
if err := t.Execute(&tpl, sInfo); err != nil {
return doc
}
return tpl.String()
}
func init() {
swag.Register(swag.Name, &s{})
}
================================================
FILE: server/docs/swagger.json
================================================
{
"swagger": "2.0",
"info": {
"description": "Valkyrie REST API Specs. This service uses sessions for authentication",
"title": "Valkyrie API",
"contact": {},
"license": {
"name": "Apache 2.0"
},
"version": "1.0"
},
"host": "localhost:\u003cPORT\u003e",
"basePath": "/api",
"paths": {
"/account": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Get Current User",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/User"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"put": {
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Update Current User",
"parameters": [
{
"description": "Update Account",
"name": "account",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/EditUser"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/change-password": {
"put": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Change Current User's Password",
"parameters": [
{
"description": "Change Password",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ChangePasswordRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/forgot-password": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Forgot Password Request",
"parameters": [
{
"description": "Forgot Password",
"name": "email",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ForgotPasswordRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/login": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "User Login",
"parameters": [
{
"description": "Login account",
"name": "account",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/LoginRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/logout": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "User Logout",
"parameters": [
{
"description": "Login account",
"name": "account",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/LoginRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
}
}
}
},
"/account/me/friends": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Get Current User's Friends",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Friend"
}
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/me/pending": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Get Current User's Friend Requests",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/FriendRequest"
}
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/register": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Create an Account",
"parameters": [
{
"description": "Create account",
"name": "account",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/RegisterRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/reset-password": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Account"
],
"summary": "Reset Password",
"parameters": [
{
"description": "Reset Password",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ResetPasswordRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/User"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/{memberId}/friend": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Send Friend Request",
"parameters": [
{
"type": "string",
"description": "User ID",
"name": "memberId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Remove Friend",
"parameters": [
{
"type": "string",
"description": "User ID",
"name": "memberId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/{memberId}/friend/accept": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Accept Friend's Request",
"parameters": [
{
"type": "string",
"description": "User ID",
"name": "memberId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/account/{memberId}/friend/cancel": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Friends"
],
"summary": "Cancel Friend's Request",
"parameters": [
{
"type": "string",
"description": "User ID",
"name": "memberId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/me/dm": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Get User's DMs",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/DirectMessage"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{channelId}": {
"put": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Edit Channel",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "channelId",
"in": "path",
"required": true
},
{
"description": "Edit Channel",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/ChannelRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{channelId}/dm": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Get or Create DM",
"parameters": [
{
"type": "string",
"description": "Member ID",
"name": "channelId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/DirectMessage"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{channelId}/members": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Get Members of the given Channel",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "channelId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{guildId}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Get Guild Channels",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Channel"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Create Channel",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Channel"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{id}": {
"delete": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Delete Channel",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/channels/{id}/dm": {
"delete": {
"produces": [
"application/json"
],
"tags": [
"Channels"
],
"summary": "Close DM",
"parameters": [
{
"type": "string",
"description": "DM Channel ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Get Current User's Guilds",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/GuildResponse"
}
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/create": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Create Guild",
"parameters": [
{
"description": "Create Guild",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/CreateGuildRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/GuildResponse"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/join": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Join Guild",
"parameters": [
{
"description": "Join Guild",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/JoinRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/GuildResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}": {
"put": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Edit Guild",
"parameters": [
{
"description": "Edit Guild",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/EditGuildRequest"
}
},
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Leave Guild",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/bans": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Get Guild Ban list",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/BanResponse"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Ban Member",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
},
{
"description": "Member ID",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MemberRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/SuccessResponse"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Unban Member",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
},
{
"description": "Member ID",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MemberRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/SuccessResponse"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/delete": {
"delete": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Delete Guild",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/invite": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Get Guild Invite",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
},
{
"type": "boolean",
"description": "Is Permanent",
"name": "isPermanent",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Delete all permanent invite links",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/kick": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Kick Member",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
},
{
"description": "Member ID",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MemberRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/SuccessResponse"
}
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/member": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Get Member Settings",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/MemberSettings"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"put": {
"produces": [
"application/json"
],
"tags": [
"Members"
],
"summary": "Edit Member Settings",
"parameters": [
{
"description": "Edit Member",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MemberSettingsRequest"
}
},
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/guilds/{guildId}/members": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Guilds"
],
"summary": "Get Guild Members",
"parameters": [
{
"type": "string",
"description": "Guild ID",
"name": "guildId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Member"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/messages/{channelId}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Messages"
],
"summary": "Get Channel Messages",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "channelId",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Cursor Pagination using the createdAt field",
"name": "cursor",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Message"
}
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"Messages"
],
"summary": "Create Messages",
"parameters": [
{
"type": "string",
"description": "Channel ID",
"name": "channelId",
"in": "path",
"required": true
},
{
"description": "Create Message",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MessageRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/messages/{messageId}": {
"put": {
"produces": [
"application/json"
],
"tags": [
"Messages"
],
"summary": "Edit Messages",
"parameters": [
{
"type": "string",
"description": "Message ID",
"name": "messageId",
"in": "path",
"required": true
},
{
"description": "Edit Message",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/MessageRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/ErrorsResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"Messages"
],
"summary": "Delete Messages",
"parameters": [
{
"type": "string",
"description": "Message ID",
"name": "messageId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/SuccessResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
}
},
"definitions": {
"Attachment": {
"type": "object",
"properties": {
"filename": {
"type": "string"
},
"filetype": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"BanResponse": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
"ChangePasswordRequest": {
"type": "object",
"properties": {
"confirmNewPassword": {
"description": "Must be the same as the newPassword value.",
"type": "string"
},
"currentPassword": {
"type": "string"
},
"newPassword": {
"description": "Min 6, max 150 characters.",
"type": "string"
}
}
},
"Channel": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"hasNotification": {
"type": "boolean"
},
"id": {
"type": "string"
},
"isPublic": {
"type": "boolean"
},
"name": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
},
"ChannelRequest": {
"type": "object",
"properties": {
"isPublic": {
"description": "Default is true",
"type": "boolean"
},
"members": {
"description": "Array of memberIds",
"type": "array",
"items": {
"type": "string"
}
},
"name": {
"description": "Channel Name. 3 to 30 character",
"type": "string"
}
}
},
"CreateGuildRequest": {
"type": "object",
"properties": {
"name": {
"description": "Guild Name. 3 to 30 characters",
"type": "string"
}
}
},
"DMUser": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"isFriend": {
"type": "boolean"
},
"isOnline": {
"type": "boolean"
},
"username": {
"type": "string"
}
}
},
"DirectMessage": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"user": {
"$ref": "#/definitions/DMUser"
}
}
},
"EditGuildRequest": {
"type": "object",
"properties": {
"icon": {
"description": "The old guild icon url if no new image is selected. Set to null to reset the guild icon",
"type": "string"
},
"image": {
"description": "image/png or image/jpeg",
"type": "string",
"format": "binary"
},
"name": {
"description": "Guild Name. 3 to 30 characters",
"type": "string"
}
}
},
"EditUser": {
"type": "object",
"properties": {
"email": {
"description": "Must be unique",
"type": "string"
},
"image": {
"description": "image/png or image/jpeg",
"type": "string",
"format": "binary"
},
"username": {
"description": "Min 3, max 30 characters.",
"type": "string"
}
}
},
"ErrorResponse": {
"type": "object",
"properties": {
"error": {
"$ref": "#/definitions/HttpError"
}
}
},
"ErrorsResponse": {
"type": "object",
"properties": {
"errors": {
"type": "array",
"items": {
"$ref": "#/definitions/FieldError"
}
}
}
},
"FieldError": {
"type": "object",
"properties": {
"field": {
"description": "The property containing the error",
"type": "string"
},
"message": {
"description": "The specific error message",
"type": "string"
}
}
},
"ForgotPasswordRequest": {
"type": "object",
"properties": {
"email": {
"type": "string"
}
}
},
"Friend": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"isOnline": {
"type": "boolean"
},
"username": {
"type": "string"
}
}
},
"FriendRequest": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"type": {
"description": "1: Incoming, 0: Outgoing",
"type": "integer",
"enum": [
0,
1
]
},
"username": {
"type": "string"
}
}
},
"GuildResponse": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"default_channel_id": {
"type": "string"
},
"hasNotification": {
"type": "boolean"
},
"icon": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"ownerId": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
},
"HttpError": {
"type": "object",
"properties": {
"message": {
"description": "The specific error message",
"type": "string"
},
"type": {
"description": "The Http Response as a string",
"type": "string"
}
}
},
"JoinRequest": {
"type": "object",
"properties": {
"link": {
"type": "string"
}
}
},
"LoginRequest": {
"type": "object",
"properties": {
"email": {
"description": "Must be unique",
"type": "string"
},
"password": {
"description": "Min 6, max 150 characters.",
"type": "string"
}
}
},
"Member": {
"type": "object",
"properties": {
"color": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"isFriend": {
"type": "boolean"
},
"isOnline": {
"type": "boolean"
},
"nickname": {
"type": "string"
},
"updatedAt": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
"MemberRequest": {
"type": "object",
"properties": {
"memberId": {
"type": "string"
}
}
},
"MemberSettings": {
"type": "object",
"properties": {
"color": {
"type": "string"
},
"nickname": {
"type": "string"
}
}
},
"MemberSettingsRequest": {
"type": "object",
"properties": {
"color": {
"type": "string"
},
"nickname": {
"type": "string"
}
}
},
"Message": {
"type": "object",
"properties": {
"attachment": {
"$ref": "#/definitions/Attachment"
},
"createdAt": {
"type": "string"
},
"id": {
"type": "string"
},
"text": {
"type": "string"
},
"updatedAt": {
"type": "string"
},
"user": {
"$ref": "#/definitions/Member"
}
}
},
"MessageRequest": {
"type": "object",
"properties": {
"file": {
"description": "image/* or audio/*",
"type": "string",
"format": "binary"
},
"text": {
"description": "Maximum 2000 characters",
"type": "string"
}
}
},
"RegisterRequest": {
"type": "object",
"properties": {
"email": {
"description": "Must be unique",
"type": "string"
},
"password": {
"description": "Min 6, max 150 characters.",
"type": "string"
},
"username": {
"description": "Min 3, max 30 characters.",
"type": "string"
}
}
},
"ResetPasswordRequest": {
"type": "object",
"properties": {
"confirmNewPassword": {
"description": "Must be the same as the password value.",
"type": "string"
},
"newPassword": {
"description": "Min 6, max 150 characters.",
"type": "string"
},
"token": {
"description": "The token the user got from the email.",
"type": "string"
}
}
},
"SuccessResponse": {
"type": "object",
"properties": {
"success": {
"description": "Only returns true, not a json object",
"type": "boolean"
}
}
},
"User": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"email": {
"type": "string"
},
"id": {
"type": "string"
},
"image": {
"type": "string"
},
"isOnline": {
"type": "boolean"
},
"updatedAt": {
"type": "string"
},
"username": {
"type": "string"
}
}
}
}
}
================================================
FILE: server/docs/swagger.yaml
================================================
basePath: /api
definitions:
Attachment:
properties:
filename:
type: string
filetype:
type: string
url:
type: string
type: object
BanResponse:
properties:
id:
type: string
image:
type: string
username:
type: string
type: object
ChangePasswordRequest:
properties:
confirmNewPassword:
description: Must be the same as the newPassword value.
type: string
currentPassword:
type: string
newPassword:
description: Min 6, max 150 characters.
type: string
type: object
Channel:
properties:
createdAt:
type: string
hasNotification:
type: boolean
id:
type: string
isPublic:
type: boolean
name:
type: string
updatedAt:
type: string
type: object
ChannelRequest:
properties:
isPublic:
description: Default is true
type: boolean
members:
description: Array of memberIds
items:
type: string
type: array
name:
description: Channel Name. 3 to 30 character
type: string
type: object
CreateGuildRequest:
properties:
name:
description: Guild Name. 3 to 30 characters
type: string
type: object
DMUser:
properties:
id:
type: string
image:
type: string
isFriend:
type: boolean
isOnline:
type: boolean
username:
type: string
type: object
DirectMessage:
properties:
id:
type: string
user:
$ref: '#/definitions/DMUser'
type: object
EditGuildRequest:
properties:
icon:
description: The old guild icon url if no new image is selected. Set to null
to reset the guild icon
type: string
image:
description: image/png or image/jpeg
format: binary
type: string
name:
description: Guild Name. 3 to 30 characters
type: string
type: object
EditUser:
properties:
email:
description: Must be unique
type: string
image:
description: image/png or image/jpeg
format: binary
type: string
username:
description: Min 3, max 30 characters.
type: string
type: object
ErrorResponse:
properties:
error:
$ref: '#/definitions/HttpError'
type: object
ErrorsResponse:
properties:
errors:
items:
$ref: '#/definitions/FieldError'
type: array
type: object
FieldError:
properties:
field:
description: The property containing the error
type: string
message:
description: The specific error message
type: string
type: object
ForgotPasswordRequest:
properties:
email:
type: string
type: object
Friend:
properties:
id:
type: string
image:
type: string
isOnline:
type: boolean
username:
type: string
type: object
FriendRequest:
properties:
id:
type: string
image:
type: string
type:
description: '1: Incoming, 0: Outgoing'
enum:
- 0
- 1
type: integer
username:
type: string
type: object
GuildResponse:
properties:
createdAt:
type: string
default_channel_id:
type: string
hasNotification:
type: boolean
icon:
type: string
id:
type: string
name:
type: string
ownerId:
type: string
updatedAt:
type: string
type: object
HttpError:
properties:
message:
description: The specific error message
type: string
type:
description: The Http Response as a string
type: string
type: object
JoinRequest:
properties:
link:
type: string
type: object
LoginRequest:
properties:
email:
description: Must be unique
type: string
password:
description: Min 6, max 150 characters.
type: string
type: object
Member:
properties:
color:
type: string
createdAt:
type: string
id:
type: string
image:
type: string
isFriend:
type: boolean
isOnline:
type: boolean
nickname:
type: string
updatedAt:
type: string
username:
type: string
type: object
MemberRequest:
properties:
memberId:
type: string
type: object
MemberSettings:
properties:
color:
type: string
nickname:
type: string
type: object
MemberSettingsRequest:
properties:
color:
type: string
nickname:
type: string
type: object
Message:
properties:
attachment:
$ref: '#/definitions/Attachment'
createdAt:
type: string
id:
type: string
text:
type: string
updatedAt:
type: string
user:
$ref: '#/definitions/Member'
type: object
MessageRequest:
properties:
file:
description: image/* or audio/*
format: binary
type: string
text:
description: Maximum 2000 characters
type: string
type: object
RegisterRequest:
properties:
email:
description: Must be unique
type: string
password:
description: Min 6, max 150 characters.
type: string
username:
description: Min 3, max 30 characters.
type: string
type: object
ResetPasswordRequest:
properties:
confirmNewPassword:
description: Must be the same as the password value.
type: string
newPassword:
description: Min 6, max 150 characters.
type: string
token:
description: The token the user got from the email.
type: string
type: object
SuccessResponse:
properties:
success:
description: Only returns true, not a json object
type: boolean
type: object
User:
properties:
createdAt:
type: string
email:
type: string
id:
type: string
image:
type: string
isOnline:
type: boolean
updatedAt:
type: string
username:
type: string
type: object
host: localhost:<PORT>
info:
contact: {}
description: Valkyrie REST API Specs. This service uses sessions for authentication
license:
name: Apache 2.0
title: Valkyrie API
version: "1.0"
paths:
/account:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/User'
"404":
description: Not Found
schema:
$ref: '#/definitions/ErrorResponse'
summary: Get Current User
tags:
- Account
put:
consumes:
- multipart/form-data
parameters:
- description: Update Account
in: body
name: account
required: true
schema:
$ref: '#/definitions/EditUser'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/User'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorsResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ErrorResponse'
summary: Update Current User
tags:
- Account
/account/{memberId}/friend:
delete:
parameters:
- description: User ID
in: path
name: memberId
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/SuccessResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/ErrorResponse'
summary: Remove Friend
tags:
- Friends
post:
parameters:
- description: User ID
in: path
name: memberId
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/SuccessResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/ErrorResponse'
summary: Send Friend Request
tags:
- Friends
/account/{memberId}/friend/accept:
post:
parameters:
- description: User ID
in: path
name: memberId
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/SuccessResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/ErrorResponse'
summary: Accept Friend's Request
tags:
- Friends
/account/{memberId}/friend/cancel:
post:
parameters:
- description: User ID
in: path
name: memberId
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/SuccessResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/ErrorResponse'
summary: Cancel Friend's Request
tags:
- Friends
/account/change-password:
put:
consumes:
- application/json
parameters:
- description: Change Password
in: body
name: request
required: true
schema:
$ref: '#/definitions/ChangePasswordRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/SuccessResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorsResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ErrorResponse'
summary: Change Current User's Password
tags:
- Account
/account/forgot-password:
post:
consumes:
- application/json
parameters:
- description: Forgot Password
in: body
name: email
required: true
schema:
$ref: '#/definitions/ForgotPasswordRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/SuccessResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorsResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ErrorResponse'
summary: Forgot Password Request
tags:
- Account
/account/login:
post:
consumes:
- application/json
parameters:
- description: Login account
in: body
name: account
required: true
schema:
$ref: '#/definitions/LoginRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/User'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorsResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ErrorResponse'
summary: User Login
tags:
- Account
/account/logout:
post:
consumes:
- application/json
parameters:
- description: Login account
in: body
name: account
required: true
schema:
$ref: '#/definitions/LoginRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/SuccessResponse'
summary: User Logout
tags:
- Account
/account/me/friends:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/Friend'
type: array
"404":
description: Not Found
schema:
$ref: '#/definitions/ErrorResponse'
summary: Get Current User's Friends
tags:
- Friends
/account/me/pending:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/FriendRequest'
type: array
"404":
description: Not Found
schema:
$ref: '#/definitions/ErrorResponse'
summary: Get Current User's Friend Requests
tags:
- Friends
/account/register:
post:
consumes:
- application/json
parameters:
- description: Create account
in: body
name: account
required: true
schema:
$ref: '#/definitions/RegisterRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/User'
"400":
description: Bad Request
schema:
$ref: '#/definitions/ErrorsResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ErrorResponse'
summary: Create an Account
tags:
- Account
/account/reset-password:
post:
consumes:
- application/json
parameters:
- description: Reset Password
in: body
name: request
required: true
schema:
$ref: '#/definitions/ResetPasswordRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/User'
"400":
description: Bad Reques
gitextract_j1xfpjp2/
├── .github/
│ └── workflows/
│ ├── release_build.yml
│ ├── server_ci.yml
│ ├── server_deploy.yml
│ ├── web_ci.yml
│ ├── website-e2e.yml
│ └── website_deploy.yml
├── .gitignore
├── LICENSE
├── README.md
├── server/
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .idea/
│ │ ├── .gitignore
│ │ ├── ValkyrieGo.iml
│ │ ├── dataSources.xml
│ │ ├── modules.xml
│ │ └── vcs.xml
│ ├── Makefile
│ ├── config/
│ │ └── config.go
│ ├── data_sources.go
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── e2e_test.go
│ ├── go.mod
│ ├── go.sum
│ ├── handler/
│ │ ├── account_handler.go
│ │ ├── account_handler_test.go
│ │ ├── auth_handler.go
│ │ ├── auth_handler_test.go
│ │ ├── bind_data.go
│ │ ├── channel_handler.go
│ │ ├── channel_handler_test.go
│ │ ├── friend_handler.go
│ │ ├── friend_handler_test.go
│ │ ├── guild_handler.go
│ │ ├── guild_handler_test.go
│ │ ├── handler.go
│ │ ├── member_handler.go
│ │ ├── member_handler_test.go
│ │ ├── message_handler.go
│ │ ├── message_handler_test.go
│ │ ├── middleware/
│ │ │ ├── auth_user.go
│ │ │ ├── auth_user_test.go
│ │ │ └── timeout.go
│ │ ├── mime_type.go
│ │ └── test_helpers.go
│ ├── injection.go
│ ├── main.go
│ ├── mocks/
│ │ ├── ChannelRepository.go
│ │ ├── ChannelService.go
│ │ ├── FileRepository.go
│ │ ├── FriendRepository.go
│ │ ├── FriendService.go
│ │ ├── GuildRepository.go
│ │ ├── GuildService.go
│ │ ├── MailRepository.go
│ │ ├── MessageRepository.go
│ │ ├── MessageService.go
│ │ ├── RedisRepository.go
│ │ ├── Request.go
│ │ ├── SocketService.go
│ │ ├── UserRepository.go
│ │ └── UserService.go
│ ├── model/
│ │ ├── app_constants.go
│ │ ├── apperrors/
│ │ │ ├── apperrors.go
│ │ │ └── httperrors.go
│ │ ├── base_model.go
│ │ ├── channel.go
│ │ ├── direct_message.go
│ │ ├── dm_member.go
│ │ ├── field_error.go
│ │ ├── fixture/
│ │ │ ├── channel.go
│ │ │ ├── faker.go
│ │ │ ├── guild.go
│ │ │ ├── message.go
│ │ │ ├── multipart.go
│ │ │ └── user.go
│ │ ├── friend.go
│ │ ├── friend_request.go
│ │ ├── guild.go
│ │ ├── interfaces.go
│ │ ├── invite.go
│ │ ├── member.go
│ │ ├── message.go
│ │ ├── user.go
│ │ └── ws_message.go
│ ├── repository/
│ │ ├── channel_repository.go
│ │ ├── file_repository.go
│ │ ├── friend_repository.go
│ │ ├── guild_repository.go
│ │ ├── mail_repository.go
│ │ ├── message_repository.go
│ │ ├── redis_repository.go
│ │ └── user_repository.go
│ ├── service/
│ │ ├── channel_service.go
│ │ ├── channel_service_test.go
│ │ ├── friend_service.go
│ │ ├── guild_service.go
│ │ ├── guild_service_test.go
│ │ ├── id_generator.go
│ │ ├── message_service.go
│ │ ├── message_service_test.go
│ │ ├── password.go
│ │ ├── password_test.go
│ │ ├── socket_service.go
│ │ ├── user_service.go
│ │ └── user_service_test.go
│ ├── static/
│ │ ├── asyncapi.yml
│ │ ├── index.html
│ │ └── js/
│ │ └── main.js
│ └── ws/
│ ├── actions.go
│ ├── client.go
│ ├── hub.go
│ └── room.go
└── web/
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── cypress/
│ ├── e2e/
│ │ ├── account.cy.ts
│ │ ├── channel.cy.ts
│ │ ├── friend.cy.ts
│ │ ├── guild.cy.ts
│ │ ├── member.cy.ts
│ │ └── message.cy.ts
│ ├── fixtures/
│ │ └── example.json
│ ├── plugins/
│ │ └── index.js
│ ├── support/
│ │ ├── commands.ts
│ │ ├── e2e.js
│ │ ├── index.d.ts
│ │ └── utils.ts
│ └── tsconfig.json
├── cypress.config.ts
├── package.json
├── public/
│ ├── _redirects
│ ├── index.html
│ ├── manifest.json
│ └── robots.txt
├── src/
│ ├── App.tsx
│ ├── components/
│ │ ├── common/
│ │ │ ├── GuildPills.tsx
│ │ │ ├── InputField.tsx
│ │ │ ├── Logo.tsx
│ │ │ └── NotificationIcon.tsx
│ │ ├── items/
│ │ │ ├── ChannelListItem.tsx
│ │ │ ├── DMListItem.tsx
│ │ │ ├── FriendsListItem.tsx
│ │ │ ├── GuildListItem.tsx
│ │ │ ├── MemberListItem.tsx
│ │ │ ├── NotificationListItem.tsx
│ │ │ ├── RequestListItem.tsx
│ │ │ ├── VoiceChannelItem.tsx
│ │ │ ├── css/
│ │ │ │ └── ContextMenu.css
│ │ │ └── message/
│ │ │ ├── Message.tsx
│ │ │ └── MessageContent.tsx
│ │ ├── layouts/
│ │ │ ├── AccountBar.tsx
│ │ │ ├── AppLayout.tsx
│ │ │ ├── LandingLayout.tsx
│ │ │ ├── VoiceBar.tsx
│ │ │ ├── guild/
│ │ │ │ ├── ChannelHeader.tsx
│ │ │ │ ├── Channels.tsx
│ │ │ │ ├── GuildList.tsx
│ │ │ │ ├── MemberList.tsx
│ │ │ │ ├── VoiceChat.tsx
│ │ │ │ ├── chat/
│ │ │ │ │ ├── ChatGrid.tsx
│ │ │ │ │ ├── ChatScreen.tsx
│ │ │ │ │ ├── FileUploadButton.tsx
│ │ │ │ │ └── MessageInput.tsx
│ │ │ │ └── css/
│ │ │ │ ├── ChannelScrollerCSS.ts
│ │ │ │ ├── GuildScrollerCSS.ts
│ │ │ │ ├── MemberScrollerCSS.ts
│ │ │ │ └── MessageInput.css
│ │ │ └── home/
│ │ │ ├── DMHeader.tsx
│ │ │ ├── DMSidebar.tsx
│ │ │ ├── css/
│ │ │ │ └── dmScrollerCSS.ts
│ │ │ └── dashboard/
│ │ │ ├── FriendsDashboard.tsx
│ │ │ ├── FriendsList.tsx
│ │ │ ├── FriendsListHeader.tsx
│ │ │ └── PendingList.tsx
│ │ ├── menus/
│ │ │ ├── GuildMenu.tsx
│ │ │ ├── MemberContextMenu.tsx
│ │ │ ├── StyledMenuItem.tsx
│ │ │ └── StyledMenuList.tsx
│ │ ├── modals/
│ │ │ ├── AddFriendModal.tsx
│ │ │ ├── AddGuildModal.tsx
│ │ │ ├── ChangePasswordModal.tsx
│ │ │ ├── ChannelSettingsModal.tsx
│ │ │ ├── CreateChannelModal.tsx
│ │ │ ├── CropImageModal.tsx
│ │ │ ├── DeleteMessageModal.tsx
│ │ │ ├── EditMemberModal.tsx
│ │ │ ├── EditMessageModal.tsx
│ │ │ ├── GuildSettingsModal.tsx
│ │ │ ├── InviteModal.tsx
│ │ │ ├── ModActionModal.tsx
│ │ │ └── RemoveFriendModal.tsx
│ │ └── sections/
│ │ ├── AddGuildIcon.tsx
│ │ ├── DMPlaceholder.tsx
│ │ ├── DateDivider.tsx
│ │ ├── Footer.tsx
│ │ ├── FriendsListButton.tsx
│ │ ├── GlobalState.tsx
│ │ ├── Hero.tsx
│ │ ├── HomeIcon.tsx
│ │ ├── NavBar.tsx
│ │ ├── OnlineLabel.tsx
│ │ ├── StartMessages.tsx
│ │ ├── StyledTooltip.tsx
│ │ └── UserPopover.tsx
│ ├── index.tsx
│ ├── lib/
│ │ ├── api/
│ │ │ ├── dtos/
│ │ │ │ ├── AuthInput.ts
│ │ │ │ ├── ChannelInput.ts
│ │ │ │ ├── GuildInput.ts
│ │ │ │ ├── GuildMemberInput.ts
│ │ │ │ ├── InviteInput.ts
│ │ │ │ └── UserInput.ts
│ │ │ ├── getSocket.ts
│ │ │ ├── handler/
│ │ │ │ ├── account.ts
│ │ │ │ ├── auth.ts
│ │ │ │ ├── channel.ts
│ │ │ │ ├── dm.ts
│ │ │ │ ├── guilds.ts
│ │ │ │ ├── members.ts
│ │ │ │ └── messages.ts
│ │ │ ├── setupAxios.ts
│ │ │ └── ws/
│ │ │ ├── useChannelSocket.ts
│ │ │ ├── useDMSocket.ts
│ │ │ ├── useFriendSocket.ts
│ │ │ ├── useGuildSocket.ts
│ │ │ ├── useMemberSocket.ts
│ │ │ ├── useMessageSocket.ts
│ │ │ ├── useRequestSocket.ts
│ │ │ └── useVoiceSocket.ts
│ │ ├── models/
│ │ │ ├── account.ts
│ │ │ ├── channel.ts
│ │ │ ├── dm.ts
│ │ │ ├── fieldError.ts
│ │ │ ├── friend.ts
│ │ │ ├── guild.ts
│ │ │ ├── member.ts
│ │ │ ├── message.ts
│ │ │ ├── routerProps.ts
│ │ │ └── voice.ts
│ │ ├── stores/
│ │ │ ├── channelStore.ts
│ │ │ ├── homeStore.ts
│ │ │ ├── settingsStore.ts
│ │ │ ├── userStore.ts
│ │ │ └── voiceStore.ts
│ │ └── utils/
│ │ ├── cropImage.ts
│ │ ├── dateUtils.ts
│ │ ├── hooks/
│ │ │ ├── useGetCurrentChannel.ts
│ │ │ ├── useGetCurrentDM.ts
│ │ │ ├── useGetCurrentGuild.ts
│ │ │ ├── useGetFriend.ts
│ │ │ └── useVoiceChat.ts
│ │ ├── querykeys.ts
│ │ ├── theme.ts
│ │ ├── toErrorMap.ts
│ │ └── validation/
│ │ ├── auth.schema.ts
│ │ ├── channel.schema.ts
│ │ ├── guild.schema.ts
│ │ ├── member.schema.ts
│ │ └── message.schema.ts
│ ├── react-app-env.d.ts
│ ├── routes/
│ │ ├── AuthRoute.tsx
│ │ ├── ForgotPassword.tsx
│ │ ├── Home.tsx
│ │ ├── Invite.tsx
│ │ ├── Landing.tsx
│ │ ├── Login.tsx
│ │ ├── Register.tsx
│ │ ├── ResetPassword.tsx
│ │ ├── Routes.tsx
│ │ ├── Settings.tsx
│ │ └── ViewGuild.tsx
│ ├── setupTests.ts
│ └── tests/
│ ├── fixture/
│ │ ├── accountFixture.ts
│ │ ├── channelFixtures.ts
│ │ ├── dmFixtures.ts
│ │ ├── friendFixture.ts
│ │ ├── guildFixtures.ts
│ │ ├── memberFixtures.ts
│ │ ├── messageFixtures.ts
│ │ └── requestFixtures.ts
│ ├── queries/
│ │ ├── account.test.tsx
│ │ ├── channel.test.tsx
│ │ ├── dm.test.tsx
│ │ ├── friend.test.tsx
│ │ ├── guild.test.tsx
│ │ ├── member.test.tsx
│ │ ├── message.test.tsx
│ │ └── request.test.tsx
│ └── testUtils.tsx
└── tsconfig.json
SYMBOL INDEX (888 symbols across 172 files)
FILE: server/config/config.go
type Config (line 8) | type Config struct
function LoadConfig (line 25) | func LoadConfig(ctx context.Context) (config Config, err error) {
FILE: server/data_sources.go
type dataSources (line 17) | type dataSources struct
method close (line 96) | func (d *dataSources) close() error {
function initDS (line 24) | func initDS(ctx context.Context, cfg config.Config) (*dataSources, error) {
FILE: server/docs/docs.go
type swaggerInfo (line 2392) | type swaggerInfo struct
type s (line 2411) | type s struct
method ReadDoc (line 2413) | func (s *s) ReadDoc() string {
function init (line 2435) | func init() {
FILE: server/e2e_test.go
function setupTest (line 21) | func setupTest(t *testing.T) *gin.Engine {
function TestMain_AccountE2E (line 41) | func TestMain_AccountE2E(t *testing.T) {
function TestMain_FriendsE2E (line 293) | func TestMain_FriendsE2E(t *testing.T) {
function TestMain_GuildsE2E (line 610) | func TestMain_GuildsE2E(t *testing.T) {
function TestMain_MembersE2E (line 1006) | func TestMain_MembersE2E(t *testing.T) {
function TestMain_ChannelsE2E (line 1509) | func TestMain_ChannelsE2E(t *testing.T) {
function TestMain_DMsE2E (line 1803) | func TestMain_DMsE2E(t *testing.T) {
function TestMain_MessagesE2E (line 2033) | func TestMain_MessagesE2E(t *testing.T) {
FILE: server/handler/account_handler.go
method GetCurrent (line 29) | func (h *Handler) GetCurrent(c *gin.Context) {
type editReq (line 46) | type editReq struct
method validate (line 55) | func (r editReq) validate() error {
method sanitize (line 62) | func (r *editReq) sanitize() {
method Edit (line 80) | func (h *Handler) Edit(c *gin.Context) {
type changeRequest (line 155) | type changeRequest struct
method validate (line 163) | func (r changeRequest) validate() error {
method sanitize (line 171) | func (r *changeRequest) sanitize() {
method ChangePassword (line 189) | func (h *Handler) ChangePassword(c *gin.Context) {
FILE: server/handler/account_handler_test.go
function TestHandler_GetCurrent (line 23) | func TestHandler_GetCurrent(t *testing.T) {
function TestHandler_EditAccount (line 115) | func TestHandler_EditAccount(t *testing.T) {
function TestHandler_ChangePassword (line 306) | func TestHandler_ChangePassword(t *testing.T) {
function TestHandler_ChangePassword_BadRequest (line 438) | func TestHandler_ChangePassword_BadRequest(t *testing.T) {
FILE: server/handler/auth_handler.go
type registerReq (line 19) | type registerReq struct
method validate (line 28) | func (r registerReq) validate() error {
method sanitize (line 36) | func (r *registerReq) sanitize() {
method Register (line 55) | func (h *Handler) Register(c *gin.Context) {
type loginReq (line 89) | type loginReq struct
method validate (line 96) | func (r loginReq) validate() error {
method sanitize (line 103) | func (r *loginReq) sanitize() {
method Login (line 121) | func (h *Handler) Login(c *gin.Context) {
method Logout (line 153) | func (h *Handler) Logout(c *gin.Context) {
type forgotRequest (line 169) | type forgotRequest struct
method validate (line 173) | func (r forgotRequest) validate() error {
method sanitize (line 179) | func (r *forgotRequest) sanitize() {
method ForgotPassword (line 195) | func (h *Handler) ForgotPassword(c *gin.Context) {
type resetRequest (line 233) | type resetRequest struct
method validate (line 242) | func (r resetRequest) validate() error {
method sanitize (line 250) | func (r *resetRequest) sanitize() {
method ResetPassword (line 267) | func (h *Handler) ResetPassword(c *gin.Context) {
FILE: server/handler/auth_handler_test.go
function TestHandler_Register (line 20) | func TestHandler_Register(t *testing.T) {
function TestHandler_Login (line 300) | func TestHandler_Login(t *testing.T) {
function TestHandler_Logout (line 404) | func TestHandler_Logout(t *testing.T) {
function TestHandler_ForgotPassword (line 439) | func TestHandler_ForgotPassword(t *testing.T) {
function TestHandler_ForgotPassword_BadRequest (line 571) | func TestHandler_ForgotPassword_BadRequest(t *testing.T) {
function TestHandler_ResetPassword (line 627) | func TestHandler_ResetPassword(t *testing.T) {
function TestHandler_ResetPassword_BadRequest (line 722) | func TestHandler_ResetPassword_BadRequest(t *testing.T) {
FILE: server/handler/bind_data.go
type Request (line 13) | type Request interface
function bindData (line 18) | func bindData(c *gin.Context, req Request) bool {
FILE: server/handler/channel_handler.go
method GuildChannels (line 28) | func (h *Handler) GuildChannels(c *gin.Context) {
type channelReq (line 71) | type channelReq struct
method validate (line 80) | func (r channelReq) validate() error {
method sanitize (line 86) | func (r *channelReq) sanitize() {
method CreateChannel (line 103) | func (h *Handler) CreateChannel(c *gin.Context) {
method PrivateChannelMembers (line 218) | func (h *Handler) PrivateChannelMembers(c *gin.Context) {
method DirectMessages (line 292) | func (h *Handler) DirectMessages(c *gin.Context) {
method GetOrCreateDM (line 329) | func (h *Handler) GetOrCreateDM(c *gin.Context) {
function toDMChannel (line 408) | func toDMChannel(member *model.User, channelId string, userId string) mo...
method EditChannel (line 435) | func (h *Handler) EditChannel(c *gin.Context) {
function difference (line 544) | func difference(a, b []string) []string {
method DeleteChannel (line 570) | func (h *Handler) DeleteChannel(c *gin.Context) {
method CloseDM (line 636) | func (h *Handler) CloseDM(c *gin.Context) {
function containsUser (line 658) | func containsUser(members []string, userId string) bool {
FILE: server/handler/channel_handler_test.go
function TestHandler_GuildChannels (line 19) | func TestHandler_GuildChannels(t *testing.T) {
function TestHandler_CreateChannel (line 213) | func TestHandler_CreateChannel(t *testing.T) {
function TestHandler_CreateChannel_BadRequest (line 591) | func TestHandler_CreateChannel_BadRequest(t *testing.T) {
function TestHandler_PrivateChannelMembers (line 654) | func TestHandler_PrivateChannelMembers(t *testing.T) {
function TestHandler_DirectMessages (line 900) | func TestHandler_DirectMessages(t *testing.T) {
function TestHandler_GetOrCreateDM (line 1001) | func TestHandler_GetOrCreateDM(t *testing.T) {
function TestHandler_EditChannel (line 1263) | func TestHandler_EditChannel(t *testing.T) {
function TestHandler_EditChannel_BadRequest (line 1685) | func TestHandler_EditChannel_BadRequest(t *testing.T) {
function TestHandler_DeleteChannel (line 1748) | func TestHandler_DeleteChannel(t *testing.T) {
function TestHandler_CloseDM (line 2066) | func TestHandler_CloseDM(t *testing.T) {
FILE: server/handler/friend_handler.go
method GetUserFriends (line 23) | func (h *Handler) GetUserFriends(c *gin.Context) {
method GetUserRequests (line 49) | func (h *Handler) GetUserRequests(c *gin.Context) {
method SendFriendRequest (line 77) | func (h *Handler) SendFriendRequest(c *gin.Context) {
method RemoveFriend (line 152) | func (h *Handler) RemoveFriend(c *gin.Context) {
method AcceptFriendRequest (line 218) | func (h *Handler) AcceptFriendRequest(c *gin.Context) {
method CancelFriendRequest (line 313) | func (h *Handler) CancelFriendRequest(c *gin.Context) {
function isFriend (line 368) | func isFriend(user *model.User, userId string) bool {
function containsRequest (line 378) | func containsRequest(user *model.User, current *model.User) bool {
FILE: server/handler/friend_handler_test.go
function TestHandler_GetUserFriends (line 18) | func TestHandler_GetUserFriends(t *testing.T) {
function TestHandler_GetUserRequests (line 119) | func TestHandler_GetUserRequests(t *testing.T) {
function TestHandler_AcceptFriendRequest (line 220) | func TestHandler_AcceptFriendRequest(t *testing.T) {
function TestHandler_SendFriendRequest (line 459) | func TestHandler_SendFriendRequest(t *testing.T) {
function TestHandler_RemoveFriend (line 731) | func TestHandler_RemoveFriend(t *testing.T) {
function TestHandler_CancelFriendRequest (line 961) | func TestHandler_CancelFriendRequest(t *testing.T) {
FILE: server/handler/guild_handler.go
method GetUserGuilds (line 31) | func (h *Handler) GetUserGuilds(c *gin.Context) {
method GetGuildMembers (line 59) | func (h *Handler) GetGuildMembers(c *gin.Context) {
method GetVCMembers (line 110) | func (h *Handler) GetVCMembers(c *gin.Context) {
type createGuildRequest (line 151) | type createGuildRequest struct
method validate (line 156) | func (r createGuildRequest) validate() error {
method sanitize (line 162) | func (r *createGuildRequest) sanitize() {
method CreateGuild (line 178) | func (h *Handler) CreateGuild(c *gin.Context) {
type editGuildRequest (line 253) | type editGuildRequest struct
method validate (line 262) | func (r editGuildRequest) validate() error {
method sanitize (line 268) | func (r *editGuildRequest) sanitize() {
method EditGuild (line 286) | func (h *Handler) EditGuild(c *gin.Context) {
method GetInvite (line 382) | func (h *Handler) GetInvite(c *gin.Context) {
method DeleteGuildInvites (line 453) | func (h *Handler) DeleteGuildInvites(c *gin.Context) {
type joinReq (line 491) | type joinReq struct
method validate (line 495) | func (r joinReq) validate() error {
method sanitize (line 501) | func (r *joinReq) sanitize() {
method JoinGuild (line 515) | func (h *Handler) JoinGuild(c *gin.Context) {
method LeaveGuild (line 624) | func (h *Handler) LeaveGuild(c *gin.Context) {
method DeleteGuild (line 671) | func (h *Handler) DeleteGuild(c *gin.Context) {
function isMember (line 715) | func isMember(guild *model.Guild, userId string) bool {
function isBanned (line 725) | func isBanned(guild *model.Guild, userId string) bool {
FILE: server/handler/guild_handler_test.go
function TestHandler_GetUserGuilds (line 22) | func TestHandler_GetUserGuilds(t *testing.T) {
function TestHandler_GetGuildMembers (line 117) | func TestHandler_GetGuildMembers(t *testing.T) {
function TestHandler_GetVCMembers (line 315) | func TestHandler_GetVCMembers(t *testing.T) {
function TestHandler_CreateGuild (line 512) | func TestHandler_CreateGuild(t *testing.T) {
function TestHandler_CreateGuild_BadRequest (line 716) | func TestHandler_CreateGuild_BadRequest(t *testing.T) {
function TestHandler_UpdateGuild (line 776) | func TestHandler_UpdateGuild(t *testing.T) {
function TestHandler_UpdateGuild_BadRequest (line 991) | func TestHandler_UpdateGuild_BadRequest(t *testing.T) {
function TestHandler_GetInvite (line 1048) | func TestHandler_GetInvite(t *testing.T) {
function TestHandler_DeleteGuildInvites (line 1323) | func TestHandler_DeleteGuildInvites(t *testing.T) {
function TestHandler_JoinGuild (line 1507) | func TestHandler_JoinGuild(t *testing.T) {
function TestHandler_LeaveGuild (line 1901) | func TestHandler_LeaveGuild(t *testing.T) {
function TestHandler_DeleteGuild (line 2098) | func TestHandler_DeleteGuild(t *testing.T) {
FILE: server/handler/handler.go
type Handler (line 21) | type Handler struct
type Config (line 33) | type Config struct
function NewHandler (line 47) | func NewHandler(c *Config) {
function setUserSession (line 141) | func setUserSession(c *gin.Context, id string) {
function toFieldErrorResponse (line 149) | func toFieldErrorResponse(c *gin.Context, field, message string) {
FILE: server/handler/member_handler.go
type memberReq (line 20) | type memberReq struct
method validate (line 24) | func (r memberReq) validate() error {
method GetMemberSettings (line 40) | func (h *Handler) GetMemberSettings(c *gin.Context) {
type memberSettingsReq (line 69) | type memberSettingsReq struct
method validate (line 74) | func (r memberSettingsReq) validate() error {
method sanitize (line 81) | func (r *memberSettingsReq) sanitize() {
method EditMemberSettings (line 102) | func (h *Handler) EditMemberSettings(c *gin.Context) {
method GetBanList (line 166) | func (h *Handler) GetBanList(c *gin.Context) {
method BanMember (line 221) | func (h *Handler) BanMember(c *gin.Context) {
method UnbanMember (line 309) | func (h *Handler) UnbanMember(c *gin.Context) {
method KickMember (line 370) | func (h *Handler) KickMember(c *gin.Context) {
FILE: server/handler/member_handler_test.go
function TestHandler_GetMemberSettings (line 19) | func TestHandler_GetMemberSettings(t *testing.T) {
function TestHandler_EditMemberSettings (line 170) | func TestHandler_EditMemberSettings(t *testing.T) {
function TestHandler_EditMemberSettings_BadRequest (line 438) | func TestHandler_EditMemberSettings_BadRequest(t *testing.T) {
function TestHandler_GetBanList (line 500) | func TestHandler_GetBanList(t *testing.T) {
function TestHandler_BanMember (line 646) | func TestHandler_BanMember(t *testing.T) {
function TestHandler_KickMember (line 1029) | func TestHandler_KickMember(t *testing.T) {
function TestHandler_UnbanMember (line 1405) | func TestHandler_UnbanMember(t *testing.T) {
FILE: server/handler/message_handler.go
method GetMessages (line 33) | func (h *Handler) GetMessages(c *gin.Context) {
type messageRequest (line 84) | type messageRequest struct
method validate (line 91) | func (r messageRequest) validate() error {
method sanitize (line 102) | func (r *messageRequest) sanitize() {
method CreateMessage (line 123) | func (h *Handler) CreateMessage(c *gin.Context) {
method EditMessage (line 274) | func (h *Handler) EditMessage(c *gin.Context) {
method DeleteMessage (line 341) | func (h *Handler) DeleteMessage(c *gin.Context) {
FILE: server/handler/message_handler_test.go
function TestHandler_GetMessages (line 21) | func TestHandler_GetMessages(t *testing.T) {
function TestHandler_CreateMessage (line 228) | func TestHandler_CreateMessage(t *testing.T) {
function TestHandler_CreateMessage_BadRequest (line 745) | func TestHandler_CreateMessage_BadRequest(t *testing.T) {
function TestHandler_UpdateMessage (line 801) | func TestHandler_UpdateMessage(t *testing.T) {
function TestHandler_UpdateMessage_BadRequest (line 1036) | func TestHandler_UpdateMessage_BadRequest(t *testing.T) {
function TestHandler_Delete_Message (line 1092) | func TestHandler_Delete_Message(t *testing.T) {
FILE: server/handler/middleware/auth_user.go
function AuthUser (line 12) | func AuthUser() gin.HandlerFunc {
FILE: server/handler/middleware/auth_user_test.go
function TestAuthUser (line 16) | func TestAuthUser(t *testing.T) {
FILE: server/handler/middleware/timeout.go
function Timeout (line 22) | func Timeout(timeout time.Duration, errTimeout *apperrors.Error) gin.Han...
type timeoutWriter (line 95) | type timeoutWriter struct
method Write (line 109) | func (tw *timeoutWriter) Write(b []byte) (int, error) {
method WriteHeader (line 120) | func (tw *timeoutWriter) WriteHeader(code int) {
method writeHeader (line 132) | func (tw *timeoutWriter) writeHeader(code int) {
method Header (line 139) | func (tw *timeoutWriter) Header() http.Header {
method SetTimedOut (line 144) | func (tw *timeoutWriter) SetTimedOut() {
function checkWriteHeaderCode (line 148) | func checkWriteHeaderCode(code int) {
FILE: server/handler/mime_type.go
function isAllowedImageType (line 10) | func isAllowedImageType(mimeType string) bool {
function isAllowedFileType (line 25) | func isAllowedFileType(mimeType string) bool {
FILE: server/handler/test_helpers.go
function getAuthenticatedTestRouter (line 10) | func getAuthenticatedTestRouter(uid string) *gin.Engine {
function getTestRouter (line 24) | func getTestRouter() *gin.Engine {
function getTestFieldErrorResponse (line 31) | func getTestFieldErrorResponse(field, message string) gin.H {
FILE: server/injection.go
function inject (line 24) | func inject(d *dataSources, cfg config.Config) (*gin.Engine, error) {
FILE: server/main.go
function main (line 26) | func main() {
FILE: server/mocks/ChannelRepository.go
type ChannelRepository (line 13) | type ChannelRepository struct
method AddDMChannelMembers (line 18) | func (_m *ChannelRepository) AddDMChannelMembers(members []model.DMMem...
method AddPrivateChannelMembers (line 32) | func (_m *ChannelRepository) AddPrivateChannelMembers(memberIds []stri...
method CleanPCMembers (line 46) | func (_m *ChannelRepository) CleanPCMembers(channelId string) error {
method Create (line 60) | func (_m *ChannelRepository) Create(channel *model.Channel) (*model.Ch...
method DeleteChannel (line 83) | func (_m *ChannelRepository) DeleteChannel(channel *model.Channel) err...
method FindDMByUserAndChannelId (line 97) | func (_m *ChannelRepository) FindDMByUserAndChannelId(channelId string...
method Get (line 118) | func (_m *ChannelRepository) Get(userId string, guildId string) (*[]mo...
method GetById (line 141) | func (_m *ChannelRepository) GetById(channelId string) (*model.Channel...
method GetDMMemberIds (line 164) | func (_m *ChannelRepository) GetDMMemberIds(channelId string) (*[]stri...
method GetDirectMessageChannel (line 187) | func (_m *ChannelRepository) GetDirectMessageChannel(userId string, me...
method GetDirectMessages (line 210) | func (_m *ChannelRepository) GetDirectMessages(userId string) (*[]mode...
method GetGuildDefault (line 233) | func (_m *ChannelRepository) GetGuildDefault(guildId string) (*model.C...
method GetPrivateChannelMembers (line 256) | func (_m *ChannelRepository) GetPrivateChannelMembers(channelId string...
method OpenDMForAll (line 279) | func (_m *ChannelRepository) OpenDMForAll(dmId string) error {
method RemovePrivateChannelMembers (line 293) | func (_m *ChannelRepository) RemovePrivateChannelMembers(memberIds []s...
method SetDirectMessageStatus (line 307) | func (_m *ChannelRepository) SetDirectMessageStatus(dmId string, userI...
method UpdateChannel (line 321) | func (_m *ChannelRepository) UpdateChannel(channel *model.Channel) err...
function NewChannelRepository (line 335) | func NewChannelRepository(t testing.TB) *ChannelRepository {
FILE: server/mocks/ChannelService.go
type ChannelService (line 13) | type ChannelService struct
method AddDMChannelMembers (line 18) | func (_m *ChannelService) AddDMChannelMembers(memberIds []string, chan...
method AddPrivateChannelMembers (line 32) | func (_m *ChannelService) AddPrivateChannelMembers(memberIds []string,...
method CleanPCMembers (line 46) | func (_m *ChannelService) CleanPCMembers(channelId string) error {
method CreateChannel (line 60) | func (_m *ChannelService) CreateChannel(channel *model.Channel) (*mode...
method DeleteChannel (line 83) | func (_m *ChannelService) DeleteChannel(channel *model.Channel) error {
method Get (line 97) | func (_m *ChannelService) Get(channelId string) (*model.Channel, error) {
method GetChannels (line 120) | func (_m *ChannelService) GetChannels(userId string, guildId string) (...
method GetDMByUserAndChannel (line 143) | func (_m *ChannelService) GetDMByUserAndChannel(userId string, channel...
method GetDirectMessageChannel (line 164) | func (_m *ChannelService) GetDirectMessageChannel(userId string, membe...
method GetDirectMessages (line 187) | func (_m *ChannelService) GetDirectMessages(userId string) (*[]model.D...
method GetPrivateChannelMembers (line 210) | func (_m *ChannelService) GetPrivateChannelMembers(channelId string) (...
method IsChannelMember (line 233) | func (_m *ChannelService) IsChannelMember(channel *model.Channel, user...
method OpenDMForAll (line 247) | func (_m *ChannelService) OpenDMForAll(dmId string) error {
method RemovePrivateChannelMembers (line 261) | func (_m *ChannelService) RemovePrivateChannelMembers(memberIds []stri...
method SetDirectMessageStatus (line 275) | func (_m *ChannelService) SetDirectMessageStatus(dmId string, userId s...
method UpdateChannel (line 289) | func (_m *ChannelService) UpdateChannel(channel *model.Channel) error {
function NewChannelService (line 303) | func NewChannelService(t testing.TB) *ChannelService {
FILE: server/mocks/FileRepository.go
type FileRepository (line 14) | type FileRepository struct
method DeleteImage (line 19) | func (_m *FileRepository) DeleteImage(key string) error {
method UploadAvatar (line 33) | func (_m *FileRepository) UploadAvatar(header *multipart.FileHeader, d...
method UploadFile (line 54) | func (_m *FileRepository) UploadFile(header *multipart.FileHeader, dir...
function NewFileRepository (line 75) | func NewFileRepository(t testing.TB) *FileRepository {
FILE: server/mocks/FriendRepository.go
type FriendRepository (line 13) | type FriendRepository struct
method DeleteRequest (line 18) | func (_m *FriendRepository) DeleteRequest(memberId string, userId stri...
method FindByID (line 32) | func (_m *FriendRepository) FindByID(id string) (*model.User, error) {
method FriendsList (line 55) | func (_m *FriendRepository) FriendsList(id string) (*[]model.Friend, e...
method RemoveFriend (line 78) | func (_m *FriendRepository) RemoveFriend(memberId string, userId strin...
method RequestList (line 92) | func (_m *FriendRepository) RequestList(id string) (*[]model.FriendReq...
method Save (line 115) | func (_m *FriendRepository) Save(user *model.User) error {
function NewFriendRepository (line 129) | func NewFriendRepository(t testing.TB) *FriendRepository {
FILE: server/mocks/FriendService.go
type FriendService (line 13) | type FriendService struct
method DeleteRequest (line 18) | func (_m *FriendService) DeleteRequest(memberId string, userId string)...
method GetFriends (line 32) | func (_m *FriendService) GetFriends(id string) (*[]model.Friend, error) {
method GetMemberById (line 55) | func (_m *FriendService) GetMemberById(id string) (*model.User, error) {
method GetRequests (line 78) | func (_m *FriendService) GetRequests(id string) (*[]model.FriendReques...
method RemoveFriend (line 101) | func (_m *FriendService) RemoveFriend(memberId string, userId string) ...
method SaveRequests (line 115) | func (_m *FriendService) SaveRequests(user *model.User) error {
function NewFriendService (line 129) | func NewFriendService(t testing.TB) *FriendService {
FILE: server/mocks/GuildRepository.go
type GuildRepository (line 13) | type GuildRepository struct
method Create (line 18) | func (_m *GuildRepository) Create(guild *model.Guild) (*model.Guild, e...
method Delete (line 41) | func (_m *GuildRepository) Delete(guildId string) error {
method FindByID (line 55) | func (_m *GuildRepository) FindByID(id string) (*model.Guild, error) {
method FindUserByID (line 78) | func (_m *GuildRepository) FindUserByID(uid string) (*model.User, erro...
method FindUsersByIds (line 101) | func (_m *GuildRepository) FindUsersByIds(ids []string, guildId string...
method GetBanList (line 124) | func (_m *GuildRepository) GetBanList(guildId string) (*[]model.BanRes...
method GetMember (line 147) | func (_m *GuildRepository) GetMember(userId string, guildId string) (*...
method GetMemberIds (line 170) | func (_m *GuildRepository) GetMemberIds(guildId string) (*[]string, er...
method GetMemberSettings (line 193) | func (_m *GuildRepository) GetMemberSettings(userId string, guildId st...
method GetVCMember (line 216) | func (_m *GuildRepository) GetVCMember(userId string, guildId string) ...
method GuildMembers (line 239) | func (_m *GuildRepository) GuildMembers(userId string, guildId string)...
method List (line 262) | func (_m *GuildRepository) List(uid string) (*[]model.GuildResponse, e...
method RemoveMember (line 285) | func (_m *GuildRepository) RemoveMember(userId string, guildId string)...
method RemoveVCMember (line 299) | func (_m *GuildRepository) RemoveVCMember(userId string, guildId strin...
method Save (line 313) | func (_m *GuildRepository) Save(guild *model.Guild) error {
method UnbanMember (line 327) | func (_m *GuildRepository) UnbanMember(userId string, guildId string) ...
method UpdateMemberLastSeen (line 341) | func (_m *GuildRepository) UpdateMemberLastSeen(userId string, guildId...
method UpdateMemberSettings (line 355) | func (_m *GuildRepository) UpdateMemberSettings(settings *model.Member...
method UpdateVCMember (line 369) | func (_m *GuildRepository) UpdateVCMember(isMuted bool, isDeafened boo...
method VCMembers (line 383) | func (_m *GuildRepository) VCMembers(guildId string) (*[]model.VCMembe...
function NewGuildRepository (line 406) | func NewGuildRepository(t testing.TB) *GuildRepository {
FILE: server/mocks/GuildService.go
type GuildService (line 15) | type GuildService struct
method CreateGuild (line 20) | func (_m *GuildService) CreateGuild(guild *model.Guild) (*model.Guild,...
method DeleteGuild (line 43) | func (_m *GuildService) DeleteGuild(guildId string) error {
method FindUsersByIds (line 57) | func (_m *GuildService) FindUsersByIds(ids []string, guildId string) (...
method GenerateInviteLink (line 80) | func (_m *GuildService) GenerateInviteLink(ctx context.Context, guildI...
method GetBanList (line 101) | func (_m *GuildService) GetBanList(guildId string) (*[]model.BanRespon...
method GetDefaultChannel (line 124) | func (_m *GuildService) GetDefaultChannel(guildId string) (*model.Chan...
method GetGuild (line 147) | func (_m *GuildService) GetGuild(id string) (*model.Guild, error) {
method GetGuildIdFromInvite (line 170) | func (_m *GuildService) GetGuildIdFromInvite(ctx context.Context, toke...
method GetGuildMembers (line 191) | func (_m *GuildService) GetGuildMembers(userId string, guildId string)...
method GetMemberSettings (line 214) | func (_m *GuildService) GetMemberSettings(userId string, guildId strin...
method GetUser (line 237) | func (_m *GuildService) GetUser(uid string) (*model.User, error) {
method GetUserGuilds (line 260) | func (_m *GuildService) GetUserGuilds(uid string) (*[]model.GuildRespo...
method GetVCMember (line 283) | func (_m *GuildService) GetVCMember(userId string, guildId string) (*m...
method GetVCMembers (line 306) | func (_m *GuildService) GetVCMembers(guildId string) (*[]model.VCMembe...
method InvalidateInvites (line 329) | func (_m *GuildService) InvalidateInvites(ctx context.Context, guild *...
method RemoveMember (line 334) | func (_m *GuildService) RemoveMember(userId string, guildId string) er...
method RemoveVCMember (line 348) | func (_m *GuildService) RemoveVCMember(userId string, guildId string) ...
method UnbanMember (line 362) | func (_m *GuildService) UnbanMember(userId string, guildId string) err...
method UpdateGuild (line 376) | func (_m *GuildService) UpdateGuild(guild *model.Guild) error {
method UpdateMemberLastSeen (line 390) | func (_m *GuildService) UpdateMemberLastSeen(userId string, guildId st...
method UpdateMemberSettings (line 404) | func (_m *GuildService) UpdateMemberSettings(settings *model.MemberSet...
method UpdateVCMember (line 418) | func (_m *GuildService) UpdateVCMember(isMuted bool, isDeafened bool, ...
function NewGuildService (line 432) | func NewGuildService(t testing.TB) *GuildService {
FILE: server/mocks/MailRepository.go
type MailRepository (line 12) | type MailRepository struct
method SendResetMail (line 17) | func (_m *MailRepository) SendResetMail(email string, html string) err...
function NewMailRepository (line 31) | func NewMailRepository(t testing.TB) *MailRepository {
FILE: server/mocks/MessageRepository.go
type MessageRepository (line 13) | type MessageRepository struct
method CreateMessage (line 18) | func (_m *MessageRepository) CreateMessage(params *model.Message) (*mo...
method DeleteMessage (line 41) | func (_m *MessageRepository) DeleteMessage(message *model.Message) err...
method GetById (line 55) | func (_m *MessageRepository) GetById(messageId string) (*model.Message...
method GetMessages (line 78) | func (_m *MessageRepository) GetMessages(userId string, channel *model...
method UpdateMessage (line 101) | func (_m *MessageRepository) UpdateMessage(message *model.Message) err...
function NewMessageRepository (line 115) | func NewMessageRepository(t testing.TB) *MessageRepository {
FILE: server/mocks/MessageService.go
type MessageService (line 15) | type MessageService struct
method CreateMessage (line 20) | func (_m *MessageService) CreateMessage(params *model.Message) (*model...
method DeleteMessage (line 43) | func (_m *MessageService) DeleteMessage(message *model.Message) error {
method Get (line 57) | func (_m *MessageService) Get(messageId string) (*model.Message, error) {
method GetMessages (line 80) | func (_m *MessageService) GetMessages(userId string, channel *model.Ch...
method UpdateMessage (line 103) | func (_m *MessageService) UpdateMessage(message *model.Message) error {
method UploadFile (line 117) | func (_m *MessageService) UploadFile(header *multipart.FileHeader, cha...
function NewMessageService (line 140) | func NewMessageService(t testing.TB) *MessageService {
FILE: server/mocks/RedisRepository.go
type RedisRepository (line 15) | type RedisRepository struct
method GetIdFromToken (line 20) | func (_m *RedisRepository) GetIdFromToken(ctx context.Context, token s...
method GetInvite (line 41) | func (_m *RedisRepository) GetInvite(ctx context.Context, token string...
method InvalidateInvites (line 62) | func (_m *RedisRepository) InvalidateInvites(ctx context.Context, guil...
method SaveInvite (line 67) | func (_m *RedisRepository) SaveInvite(ctx context.Context, guildId str...
method SetResetToken (line 81) | func (_m *RedisRepository) SetResetToken(ctx context.Context, id strin...
function NewRedisRepository (line 102) | func NewRedisRepository(t testing.TB) *RedisRepository {
FILE: server/mocks/Request.go
type Request (line 12) | type Request struct
method validate (line 17) | func (_m *Request) validate() error {
function NewRequest (line 31) | func NewRequest(t testing.TB) *Request {
FILE: server/mocks/SocketService.go
type SocketService (line 13) | type SocketService struct
method EmitAddFriend (line 18) | func (_m *SocketService) EmitAddFriend(user *model.User, member *model...
method EmitAddFriendRequest (line 23) | func (_m *SocketService) EmitAddFriendRequest(room string, request *mo...
method EmitAddMember (line 28) | func (_m *SocketService) EmitAddMember(room string, member *model.User) {
method EmitDeleteChannel (line 33) | func (_m *SocketService) EmitDeleteChannel(channel *model.Channel) {
method EmitDeleteGuild (line 38) | func (_m *SocketService) EmitDeleteGuild(guildId string, members []str...
method EmitDeleteMessage (line 43) | func (_m *SocketService) EmitDeleteMessage(room string, messageId stri...
method EmitEditChannel (line 48) | func (_m *SocketService) EmitEditChannel(room string, channel *model.C...
method EmitEditGuild (line 53) | func (_m *SocketService) EmitEditGuild(guild *model.Guild) {
method EmitEditMessage (line 58) | func (_m *SocketService) EmitEditMessage(room string, message *model.M...
method EmitNewChannel (line 63) | func (_m *SocketService) EmitNewChannel(room string, channel *model.Ch...
method EmitNewDMNotification (line 68) | func (_m *SocketService) EmitNewDMNotification(channelId string, user ...
method EmitNewMessage (line 73) | func (_m *SocketService) EmitNewMessage(room string, message *model.Me...
method EmitNewNotification (line 78) | func (_m *SocketService) EmitNewNotification(guildId string, channelId...
method EmitNewPrivateChannel (line 83) | func (_m *SocketService) EmitNewPrivateChannel(members []string, chann...
method EmitRemoveFriend (line 88) | func (_m *SocketService) EmitRemoveFriend(userId string, memberId stri...
method EmitRemoveFromGuild (line 93) | func (_m *SocketService) EmitRemoveFromGuild(memberId string, guildId ...
method EmitRemoveMember (line 98) | func (_m *SocketService) EmitRemoveMember(room string, memberId string) {
method EmitSendRequest (line 103) | func (_m *SocketService) EmitSendRequest(room string) {
function NewSocketService (line 108) | func NewSocketService(t testing.TB) *SocketService {
FILE: server/mocks/UserRepository.go
type UserRepository (line 13) | type UserRepository struct
method Create (line 18) | func (_m *UserRepository) Create(user *model.User) (*model.User, error) {
method FindByEmail (line 41) | func (_m *UserRepository) FindByEmail(email string) (*model.User, erro...
method FindByID (line 64) | func (_m *UserRepository) FindByID(id string) (*model.User, error) {
method GetFriendAndGuildIds (line 87) | func (_m *UserRepository) GetFriendAndGuildIds(userId string) (*[]stri...
method GetRequestCount (line 110) | func (_m *UserRepository) GetRequestCount(userId string) (*int64, erro...
method Update (line 133) | func (_m *UserRepository) Update(user *model.User) error {
function NewUserRepository (line 147) | func NewUserRepository(t testing.TB) *UserRepository {
FILE: server/mocks/UserService.go
type UserService (line 17) | type UserService struct
method ChangeAvatar (line 22) | func (_m *UserService) ChangeAvatar(header *multipart.FileHeader, dire...
method ChangePassword (line 43) | func (_m *UserService) ChangePassword(currentPassword string, newPassw...
method DeleteImage (line 57) | func (_m *UserService) DeleteImage(key string) error {
method ForgotPassword (line 71) | func (_m *UserService) ForgotPassword(ctx context.Context, user *model...
method Get (line 85) | func (_m *UserService) Get(id string) (*model.User, error) {
method GetByEmail (line 108) | func (_m *UserService) GetByEmail(email string) (*model.User, error) {
method GetFriendAndGuildIds (line 131) | func (_m *UserService) GetFriendAndGuildIds(userId string) (*[]string,...
method GetRequestCount (line 154) | func (_m *UserService) GetRequestCount(userId string) (*int64, error) {
method IsEmailAlreadyInUse (line 177) | func (_m *UserService) IsEmailAlreadyInUse(email string) bool {
method Login (line 191) | func (_m *UserService) Login(email string, password string) (*model.Us...
method Register (line 214) | func (_m *UserService) Register(user *model.User) (*model.User, error) {
method ResetPassword (line 237) | func (_m *UserService) ResetPassword(ctx context.Context, password str...
method UpdateAccount (line 260) | func (_m *UserService) UpdateAccount(user *model.User) error {
function NewUserService (line 274) | func NewUserService(t testing.TB) *UserService {
FILE: server/model/app_constants.go
constant MinimumChannels (line 5) | MinimumChannels = 1
constant MaximumChannels (line 6) | MaximumChannels = 50
constant MaximumGuilds (line 7) | MaximumGuilds = 100
constant CookieName (line 8) | CookieName = "vlk"
FILE: server/model/apperrors/apperrors.go
constant NotAMember (line 5) | NotAMember = "Not a member of the guild"
constant AlreadyMember (line 6) | AlreadyMember = "Already a member of the guild"
constant GuildLimitReached (line 7) | GuildLimitReached = "The guild limit is 100"
constant MustBeOwner (line 8) | MustBeOwner = "Must be the owner for that"
constant InvalidImageType (line 9) | InvalidImageType = "imageFile must be 'image/jpeg' or 'image/png'"
constant MustBeMemberInvite (line 10) | MustBeMemberInvite = "Must be a member to fetch an invite"
constant IsPermanentError (line 11) | IsPermanentError = "isPermanent is not a boolean"
constant InvalidateInvitesError (line 12) | InvalidateInvitesError = "Only the owner can invalidate invites"
constant InvalidInviteError (line 13) | InvalidInviteError = "Invalid Link or the server got deleted"
constant BannedFromServer (line 14) | BannedFromServer = "You are banned from this server"
constant DeleteGuildError (line 15) | DeleteGuildError = "Only the owner can delete their server"
constant OwnerCantLeave (line 16) | OwnerCantLeave = "The owner cannot leave their server"
constant BanYourselfError (line 17) | BanYourselfError = "You cannot ban yourself"
constant KickYourselfError (line 18) | KickYourselfError = "You cannot kick yourself"
constant UnbanYourselfError (line 19) | UnbanYourselfError = "You cannot unban yourself"
constant OneChannelRequired (line 20) | OneChannelRequired = "A server needs at least one channel"
constant ChannelLimitError (line 21) | ChannelLimitError = "The channel limit is 50"
constant DMYourselfError (line 22) | DMYourselfError = "You cannot dm yourself"
constant InvalidOldPassword (line 27) | InvalidOldPassword = "Invalid old password"
constant InvalidCredentials (line 28) | InvalidCredentials = "Invalid email and password combination"
constant DuplicateEmail (line 29) | DuplicateEmail = "An account with that email already exists"
constant PasswordsDoNotMatch (line 30) | PasswordsDoNotMatch = "Passwords do not match"
constant InvalidResetToken (line 31) | InvalidResetToken = "Invalid reset token"
constant AddYourselfError (line 36) | AddYourselfError = "You cannot add yourself"
constant RemoveYourselfError (line 37) | RemoveYourselfError = "You cannot remove yourself"
constant AcceptYourselfError (line 38) | AcceptYourselfError = "You cannot accept yourself"
constant CancelYourselfError (line 39) | CancelYourselfError = "You cannot cancel yourself"
constant UnableAddError (line 40) | UnableAddError = "Unable to add user as friend. Try again later"
constant UnableRemoveError (line 41) | UnableRemoveError = "Unable to remove the user. Try again later"
constant UnableAcceptError (line 42) | UnableAcceptError = "Unable to accept the request. Try again later"
constant InvalidSession (line 47) | InvalidSession = "Provided session is invalid"
constant ServerError (line 48) | ServerError = "Something went wrong. Try again later"
constant Unauthorized (line 49) | Unauthorized = "Not Authorized"
constant MessageOrFileRequired (line 54) | MessageOrFileRequired = "Either a message or a file is required"
constant EditMessageError (line 55) | EditMessageError = "Only the author can edit the message"
constant DeleteMessageError (line 56) | DeleteMessageError = "Only the author or owner can delete the message"
constant DeleteDMMessageError (line 57) | DeleteDMMessageError = "Only the author can delete the message"
FILE: server/model/apperrors/httperrors.go
type Type (line 10) | type Type
constant Authorization (line 14) | Authorization Type = "AUTHORIZATION"
constant BadRequest (line 15) | BadRequest Type = "BADREQUEST"
constant Conflict (line 16) | Conflict Type = "CONFLICT"
constant Internal (line 17) | Internal Type = "INTERNAL"
constant NotFound (line 18) | NotFound Type = "NOTFOUND"
constant PayloadTooLarge (line 19) | PayloadTooLarge Type = "PAYLOADTOOLARGE"
constant ServiceUnavailable (line 20) | ServiceUnavailable Type = "SERVICE_UNAVAILABLE"
constant UnsupportedMediaType (line 21) | UnsupportedMediaType Type = "UNSUPPORTEDMEDIATYPE"
type Error (line 27) | type Error struct
method Error (line 35) | func (e *Error) Error() string {
method Status (line 42) | func (e *Error) Status() int {
function Status (line 68) | func Status(err error) int {
function NewAuthorization (line 81) | func NewAuthorization(reason string) *Error {
function NewBadRequest (line 89) | func NewBadRequest(reason string) *Error {
function NewConflict (line 97) | func NewConflict(name string, value string) *Error {
function NewInternal (line 105) | func NewInternal() *Error {
function NewNotFound (line 113) | func NewNotFound(name string, value string) *Error {
function NewPayloadTooLarge (line 121) | func NewPayloadTooLarge(maxBodySize int64, contentLength int64) *Error {
function NewServiceUnavailable (line 129) | func NewServiceUnavailable() *Error {
function NewUnsupportedMediaType (line 137) | func NewUnsupportedMediaType(reason string) *Error {
FILE: server/model/base_model.go
type BaseModel (line 9) | type BaseModel struct
type Success (line 17) | type Success struct
FILE: server/model/channel.go
type Channel (line 9) | type Channel struct
method SerializeChannel (line 31) | func (c Channel) SerializeChannel() ChannelResponse {
type ChannelResponse (line 21) | type ChannelResponse struct
type ChannelService (line 44) | type ChannelService interface
type ChannelRepository (line 65) | type ChannelRepository interface
FILE: server/model/direct_message.go
type DirectMessage (line 5) | type DirectMessage struct
type DMUser (line 11) | type DMUser struct
FILE: server/model/dm_member.go
type DMMember (line 7) | type DMMember struct
FILE: server/model/field_error.go
type ErrorsResponse (line 4) | type ErrorsResponse struct
type FieldError (line 9) | type FieldError struct
type ErrorResponse (line 17) | type ErrorResponse struct
type HttpError (line 22) | type HttpError struct
FILE: server/model/fixture/channel.go
function GetMockChannel (line 9) | func GetMockChannel(guildId string) *model.Channel {
function GetMockDMChannel (line 30) | func GetMockDMChannel() *model.Channel {
FILE: server/model/fixture/faker.go
function RandStringRunes (line 15) | func RandStringRunes(n int) string {
function randNumberRunes (line 24) | func randNumberRunes(n int) string {
function randStringLowerRunes (line 33) | func randStringLowerRunes(n int) string {
function RandInt (line 43) | func RandInt(min, max int) int {
function RandID (line 48) | func RandID() string {
function Username (line 53) | func Username() string {
function Email (line 58) | func Email() string {
function RandStr (line 64) | func RandStr(n int) string {
function generateAvatar (line 69) | func generateAvatar(email string) string {
FILE: server/model/fixture/guild.go
function GetMockGuild (line 9) | func GetMockGuild(uid string) *model.Guild {
FILE: server/model/fixture/message.go
function GetMockMessage (line 9) | func GetMockMessage(uid, cid string) *model.Message {
function GetMockMessageResponse (line 31) | func GetMockMessageResponse(uid, cid string) *model.MessageResponse {
FILE: server/model/fixture/multipart.go
type MultipartImage (line 19) | type MultipartImage struct
method GetFormFile (line 70) | func (m *MultipartImage) GetFormFile() *multipart.FileHeader {
method Close (line 80) | func (m *MultipartImage) Close() {
function NewMultipartImage (line 29) | func NewMultipartImage(fileName string, contentType string) *MultipartIm...
function createImage (line 87) | func createImage(imagePath string) *os.File {
FILE: server/model/fixture/user.go
function GetMockUser (line 9) | func GetMockUser() *model.User {
FILE: server/model/friend.go
type Friend (line 4) | type Friend struct
type FriendService (line 13) | type FriendService interface
type FriendRepository (line 24) | type FriendRepository interface
FILE: server/model/friend_request.go
type RequestType (line 4) | type RequestType
constant Outgoing (line 8) | Outgoing RequestType = iota
constant Incoming (line 9) | Incoming
type FriendRequest (line 16) | type FriendRequest struct
FILE: server/model/guild.go
type Guild (line 10) | type Guild struct
method SerializeGuild (line 38) | func (g Guild) SerializeGuild(channelId string) GuildResponse {
type GuildResponse (line 25) | type GuildResponse struct
type GuildService (line 53) | type GuildService interface
type GuildRepository (line 80) | type GuildRepository interface
FILE: server/model/interfaces.go
type FileRepository (line 10) | type FileRepository interface
type MailRepository (line 18) | type MailRepository interface
type RedisRepository (line 24) | type RedisRepository interface
FILE: server/model/invite.go
type Invite (line 5) | type Invite struct
FILE: server/model/member.go
type Member (line 7) | type Member struct
type VCMember (line 17) | type VCMember struct
type MemberResponse (line 25) | type MemberResponse struct
type BanResponse (line 38) | type BanResponse struct
type MemberSettings (line 45) | type MemberSettings struct
type VCMemberResponse (line 51) | type VCMemberResponse struct
FILE: server/model/message.go
type Message (line 10) | type Message struct
type MessageResponse (line 19) | type MessageResponse struct
type Attachment (line 30) | type Attachment struct
type MessageService (line 42) | type MessageService interface
type MessageRepository (line 53) | type MessageRepository interface
FILE: server/model/user.go
type User (line 9) | type User struct
type UserService (line 24) | type UserService interface
type UserRepository (line 42) | type UserRepository interface
FILE: server/model/ws_message.go
type ReceivedMessage (line 9) | type ReceivedMessage struct
type WebsocketMessage (line 16) | type WebsocketMessage struct
method Encode (line 22) | func (message *WebsocketMessage) Encode() []byte {
type SocketService (line 33) | type SocketService interface
FILE: server/repository/channel_repository.go
type channelRepository (line 14) | type channelRepository struct
method Create (line 26) | func (r *channelRepository) Create(channel *model.Channel) (*model.Cha...
method GetGuildDefault (line 36) | func (r *channelRepository) GetGuildDefault(guildId string) (*model.Ch...
method Get (line 48) | func (r *channelRepository) Get(userId string, guildId string) (*[]mod...
method GetDirectMessages (line 80) | func (r *channelRepository) GetDirectMessages(userId string) (*[]model...
method GetDirectMessageChannel (line 126) | func (r *channelRepository) GetDirectMessageChannel(userId string, mem...
method GetById (line 144) | func (r *channelRepository) GetById(channelId string) (*model.Channel,...
method GetPrivateChannelMembers (line 152) | func (r *channelRepository) GetPrivateChannelMembers(channelId string)...
method AddDMChannelMembers (line 161) | func (r *channelRepository) AddDMChannelMembers(members []model.DMMemb...
method SetDirectMessageStatus (line 171) | func (r *channelRepository) SetDirectMessageStatus(dmId string, userId...
method OpenDMForAll (line 184) | func (r *channelRepository) OpenDMForAll(dmId string) error {
method DeleteChannel (line 197) | func (r *channelRepository) DeleteChannel(channel *model.Channel) error {
method UpdateChannel (line 206) | func (r *channelRepository) UpdateChannel(channel *model.Channel) error {
method CleanPCMembers (line 215) | func (r *channelRepository) CleanPCMembers(channelId string) error {
method AddPrivateChannelMembers (line 224) | func (r *channelRepository) AddPrivateChannelMembers(memberIds []strin...
method RemovePrivateChannelMembers (line 238) | func (r *channelRepository) RemovePrivateChannelMembers(memberIds []st...
method FindDMByUserAndChannelId (line 249) | func (r *channelRepository) FindDMByUserAndChannelId(channelId, userId...
method GetDMMemberIds (line 258) | func (r *channelRepository) GetDMMemberIds(channelId string) (*[]strin...
function NewChannelRepository (line 19) | func NewChannelRepository(db *gorm.DB) model.ChannelRepository {
type dmQuery (line 70) | type dmQuery struct
FILE: server/repository/file_repository.go
type s3FileRepository (line 26) | type s3FileRepository struct
method UploadAvatar (line 43) | func (s *s3FileRepository) UploadAvatar(header *multipart.FileHeader, ...
method UploadFile (line 95) | func (s *s3FileRepository) UploadFile(header *multipart.FileHeader, di...
method DeleteImage (line 128) | func (s *s3FileRepository) DeleteImage(key string) error {
function NewFileRepository (line 32) | func NewFileRepository(session *session.Session, bucketName string) mode...
FILE: server/repository/friend_repository.go
type friendRepository (line 13) | type friendRepository struct
method FriendsList (line 25) | func (r *friendRepository) FriendsList(id string) (*[]model.Friend, er...
method RequestList (line 38) | func (r *friendRepository) RequestList(id string) (*[]model.FriendRequ...
method FindByID (line 58) | func (r *friendRepository) FindByID(id string) (*model.User, error) {
method DeleteRequest (line 76) | func (r *friendRepository) DeleteRequest(memberId string, userId strin...
method RemoveFriend (line 86) | func (r *friendRepository) RemoveFriend(memberId string, userId string...
method Save (line 94) | func (r *friendRepository) Save(user *model.User) error {
function NewFriendRepository (line 18) | func NewFriendRepository(db *gorm.DB) model.FriendRepository {
FILE: server/repository/guild_repository.go
type guildRepository (line 15) | type guildRepository struct
method List (line 27) | func (r *guildRepository) List(uid string) (*[]model.GuildResponse, er...
method GuildMembers (line 60) | func (r *guildRepository) GuildMembers(userId string, guildId string) ...
method Create (line 88) | func (r *guildRepository) Create(guild *model.Guild) (*model.Guild, er...
method FindUserByID (line 98) | func (r *guildRepository) FindUserByID(uid string) (*model.User, error) {
method FindByID (line 116) | func (r *guildRepository) FindByID(id string) (*model.Guild, error) {
method Save (line 133) | func (r *guildRepository) Save(guild *model.Guild) error {
method RemoveMember (line 143) | func (r *guildRepository) RemoveMember(userId string, guildId string) ...
method Delete (line 154) | func (r *guildRepository) Delete(guildId string) error {
method UnbanMember (line 167) | func (r *guildRepository) UnbanMember(userId string, guildId string) e...
method GetBanList (line 176) | func (r *guildRepository) GetBanList(guildId string) (*[]model.BanResp...
method GetMemberSettings (line 192) | func (r *guildRepository) GetMemberSettings(userId string, guildId str...
method UpdateMemberSettings (line 202) | func (r *guildRepository) UpdateMemberSettings(settings *model.MemberS...
method FindUsersByIds (line 216) | func (r *guildRepository) FindUsersByIds(ids []string, guildId string)...
method GetMember (line 230) | func (r *guildRepository) GetMember(userId, guildId string) (*model.Us...
method UpdateMemberLastSeen (line 244) | func (r *guildRepository) UpdateMemberLastSeen(userId, guildId string)...
method GetMemberIds (line 256) | func (r *guildRepository) GetMemberIds(guildId string) (*[]string, err...
method RemoveVCMember (line 268) | func (r *guildRepository) RemoveVCMember(userId, guildId string) error {
method VCMembers (line 276) | func (r *guildRepository) VCMembers(guildId string) (*[]model.VCMember...
method UpdateVCMember (line 295) | func (r *guildRepository) UpdateVCMember(isMuted, isDeafened bool, use...
method GetVCMember (line 307) | func (r *guildRepository) GetVCMember(userId, guildId string) (*model....
function NewGuildRepository (line 20) | func NewGuildRepository(db *gorm.DB) model.GuildRepository {
FILE: server/repository/mail_repository.go
type mailRepository (line 11) | type mailRepository struct
method SendResetMail (line 27) | func (m *mailRepository) SendResetMail(email string, token string) err...
function NewMailRepository (line 18) | func NewMailRepository(username string, password string, origin string) ...
FILE: server/repository/message_repository.go
type messageRepository (line 16) | type messageRepository struct
method GetMessages (line 50) | func (r *messageRepository) GetMessages(userId string, channel *model....
method CreateMessage (line 149) | func (r *messageRepository) CreateMessage(message *model.Message) (*mo...
method UpdateMessage (line 159) | func (r *messageRepository) UpdateMessage(message *model.Message) error {
method DeleteMessage (line 168) | func (r *messageRepository) DeleteMessage(message *model.Message) error {
method GetById (line 177) | func (r *messageRepository) GetById(messageId string) (*model.Message,...
function NewMessageRepository (line 21) | func NewMessageRepository(db *gorm.DB) model.MessageRepository {
type messageQuery (line 28) | type messageQuery struct
FILE: server/repository/redis_repository.go
type redisRepository (line 15) | type redisRepository struct
method SetResetToken (line 33) | func (r *redisRepository) SetResetToken(ctx context.Context, id string...
method GetIdFromToken (line 50) | func (r *redisRepository) GetIdFromToken(ctx context.Context, token st...
method SaveInvite (line 69) | func (r *redisRepository) SaveInvite(ctx context.Context, guildId stri...
method GetInvite (line 94) | func (r *redisRepository) GetInvite(ctx context.Context, token string)...
method InvalidateInvites (line 119) | func (r *redisRepository) InvalidateInvites(ctx context.Context, guild...
function NewRedisRepository (line 20) | func NewRedisRepository(rds *redis.Client) model.RedisRepository {
constant InviteLinkPrefix (line 28) | InviteLinkPrefix = "inviteLink"
constant ForgotPasswordPrefix (line 29) | ForgotPasswordPrefix = "forgot-password"
FILE: server/repository/user_repository.go
type userRepository (line 15) | type userRepository struct
method FindByID (line 27) | func (r *userRepository) FindByID(id string) (*model.User, error) {
method Create (line 42) | func (r *userRepository) Create(user *model.User) (*model.User, error) {
method FindByEmail (line 57) | func (r *userRepository) FindByEmail(email string) (*model.User, error) {
method Update (line 72) | func (r *userRepository) Update(user *model.User) error {
method GetFriendAndGuildIds (line 77) | func (r *userRepository) GetFriendAndGuildIds(userId string) (*[]strin...
method GetRequestCount (line 95) | func (r *userRepository) GetRequestCount(userId string) (*int64, error) {
function NewUserRepository (line 20) | func NewUserRepository(db *gorm.DB) model.UserRepository {
function isDuplicateKeyError (line 108) | func isDuplicateKeyError(err error) bool {
FILE: server/service/channel_service.go
type channelService (line 10) | type channelService struct
method CreateChannel (line 31) | func (c *channelService) CreateChannel(channel *model.Channel) (*model...
method GetChannels (line 37) | func (c *channelService) GetChannels(userId string, guildId string) (*...
method Get (line 41) | func (c *channelService) Get(channelId string) (*model.Channel, error) {
method GetPrivateChannelMembers (line 45) | func (c *channelService) GetPrivateChannelMembers(channelId string) (*...
method GetDirectMessages (line 49) | func (c *channelService) GetDirectMessages(userId string) (*[]model.Di...
method GetDirectMessageChannel (line 53) | func (c *channelService) GetDirectMessageChannel(userId string, member...
method AddDMChannelMembers (line 57) | func (c *channelService) AddDMChannelMembers(memberIds []string, chann...
method SetDirectMessageStatus (line 72) | func (c *channelService) SetDirectMessageStatus(dmId string, userId st...
method DeleteChannel (line 76) | func (c *channelService) DeleteChannel(channel *model.Channel) error {
method UpdateChannel (line 80) | func (c *channelService) UpdateChannel(channel *model.Channel) error {
method CleanPCMembers (line 84) | func (c *channelService) CleanPCMembers(channelId string) error {
method AddPrivateChannelMembers (line 88) | func (c *channelService) AddPrivateChannelMembers(memberIds []string, ...
method RemovePrivateChannelMembers (line 92) | func (c *channelService) RemovePrivateChannelMembers(memberIds []strin...
method OpenDMForAll (line 96) | func (c *channelService) OpenDMForAll(dmId string) error {
method GetDMByUserAndChannel (line 100) | func (c *channelService) GetDMByUserAndChannel(userId string, channelI...
method IsChannelMember (line 106) | func (c *channelService) IsChannelMember(channel *model.Channel, userI...
type CSConfig (line 17) | type CSConfig struct
function NewChannelService (line 24) | func NewChannelService(c *CSConfig) model.ChannelService {
FILE: server/service/channel_service_test.go
function TestChannelService_CreateChannel (line 13) | func TestChannelService_CreateChannel(t *testing.T) {
function TestChannelService_AddDMChannelMembers (line 75) | func TestChannelService_AddDMChannelMembers(t *testing.T) {
function TestChannelService_IsChannelMember (line 116) | func TestChannelService_IsChannelMember(t *testing.T) {
FILE: server/service/friend_service.go
type friendService (line 9) | type friendService struct
method GetFriends (line 30) | func (f *friendService) GetFriends(id string) (*[]model.Friend, error) {
method GetRequests (line 34) | func (f *friendService) GetRequests(id string) (*[]model.FriendRequest...
method GetMemberById (line 38) | func (f *friendService) GetMemberById(id string) (*model.User, error) {
method DeleteRequest (line 42) | func (f *friendService) DeleteRequest(memberId string, userId string) ...
method RemoveFriend (line 46) | func (f *friendService) RemoveFriend(memberId string, userId string) e...
method SaveRequests (line 50) | func (f *friendService) SaveRequests(user *model.User) error {
type FSConfig (line 16) | type FSConfig struct
function NewFriendService (line 23) | func NewFriendService(c *FSConfig) model.FriendService {
FILE: server/service/guild_service.go
type guildService (line 11) | type guildService struct
method GetUserGuilds (line 41) | func (g *guildService) GetUserGuilds(uid string) (*[]model.GuildRespon...
method GetGuildMembers (line 45) | func (g *guildService) GetGuildMembers(userId string, guildId string) ...
method CreateGuild (line 49) | func (g *guildService) CreateGuild(guild *model.Guild) (*model.Guild, ...
method GetUser (line 55) | func (g *guildService) GetUser(uid string) (*model.User, error) {
method GetGuild (line 59) | func (g *guildService) GetGuild(id string) (*model.Guild, error) {
method GenerateInviteLink (line 63) | func (g *guildService) GenerateInviteLink(ctx context.Context, guildId...
method UpdateGuild (line 77) | func (g *guildService) UpdateGuild(guild *model.Guild) error {
method GetGuildIdFromInvite (line 81) | func (g *guildService) GetGuildIdFromInvite(ctx context.Context, token...
method GetDefaultChannel (line 85) | func (g *guildService) GetDefaultChannel(guildId string) (*model.Chann...
method InvalidateInvites (line 89) | func (g *guildService) InvalidateInvites(ctx context.Context, guild *m...
method RemoveMember (line 93) | func (g *guildService) RemoveMember(userId string, guildId string) err...
method DeleteGuild (line 97) | func (g *guildService) DeleteGuild(guildId string) error {
method UnbanMember (line 101) | func (g *guildService) UnbanMember(userId string, guildId string) error {
method GetBanList (line 105) | func (g *guildService) GetBanList(guildId string) (*[]model.BanRespons...
method GetMemberSettings (line 109) | func (g *guildService) GetMemberSettings(userId string, guildId string...
method UpdateMemberSettings (line 113) | func (g *guildService) UpdateMemberSettings(settings *model.MemberSett...
method FindUsersByIds (line 117) | func (g *guildService) FindUsersByIds(ids []string, guildId string) (*...
method UpdateMemberLastSeen (line 121) | func (g *guildService) UpdateMemberLastSeen(userId, guildId string) er...
method RemoveVCMember (line 125) | func (g *guildService) RemoveVCMember(userId, guildId string) error {
method GetVCMembers (line 129) | func (g *guildService) GetVCMembers(guildId string) (*[]model.VCMember...
method UpdateVCMember (line 133) | func (g *guildService) UpdateVCMember(isMuted, isDeafened bool, userId...
method GetVCMember (line 137) | func (g *guildService) GetVCMember(userId, guildId string) (*model.VCM...
type GSConfig (line 21) | type GSConfig struct
function NewGuildService (line 31) | func NewGuildService(c *GSConfig) model.GuildService {
FILE: server/service/guild_service_test.go
function TestGuildService_CreateGuild (line 14) | func TestGuildService_CreateGuild(t *testing.T) {
function TestGuildService_GenerateInviteLink (line 72) | func TestGuildService_GenerateInviteLink(t *testing.T) {
FILE: server/service/id_generator.go
function init (line 10) | func init() {
function GenerateId (line 21) | func GenerateId() string {
FILE: server/service/message_service.go
type messageService (line 17) | type messageService struct
method GetMessages (line 38) | func (m *messageService) GetMessages(userId string, channel *model.Cha...
method CreateMessage (line 42) | func (m *messageService) CreateMessage(params *model.Message) (*model....
method UpdateMessage (line 48) | func (m *messageService) UpdateMessage(message *model.Message) error {
method DeleteMessage (line 52) | func (m *messageService) DeleteMessage(message *model.Message) error {
method UploadFile (line 62) | func (m *messageService) UploadFile(header *multipart.FileHeader, chan...
method Get (line 86) | func (m *messageService) Get(messageId string) (*model.Message, error) {
type MSConfig (line 24) | type MSConfig struct
function NewMessageService (line 31) | func NewMessageService(c *MSConfig) model.MessageService {
function formatName (line 92) | func formatName(filename string) string {
FILE: server/service/message_service_test.go
function TestGuildService_CreateMessage (line 14) | func TestGuildService_CreateMessage(t *testing.T) {
function TestGuildService_DeleteMessage (line 72) | func TestGuildService_DeleteMessage(t *testing.T) {
function TestMessageService_UploadFile (line 141) | func TestMessageService_UploadFile(t *testing.T) {
FILE: server/service/password.go
function hashPassword (line 13) | func hashPassword(password string) (string, error) {
function comparePasswords (line 33) | func comparePasswords(storedPassword string, suppliedPassword string) (b...
FILE: server/service/password_test.go
function TestPassword (line 10) | func TestPassword(t *testing.T) {
FILE: server/service/socket_service.go
type socketService (line 10) | type socketService struct
method EmitNewMessage (line 34) | func (s *socketService) EmitNewMessage(room string, message *model.Mes...
method EmitEditMessage (line 47) | func (s *socketService) EmitEditMessage(room string, message *model.Me...
method EmitDeleteMessage (line 60) | func (s *socketService) EmitDeleteMessage(room, messageId string) {
method EmitNewChannel (line 73) | func (s *socketService) EmitNewChannel(room string, channel *model.Cha...
method EmitNewPrivateChannel (line 86) | func (s *socketService) EmitNewPrivateChannel(members []string, channe...
method EmitEditChannel (line 101) | func (s *socketService) EmitEditChannel(room string, channel *model.Ch...
method EmitDeleteChannel (line 114) | func (s *socketService) EmitDeleteChannel(channel *model.Channel) {
method EmitEditGuild (line 127) | func (s *socketService) EmitEditGuild(guild *model.Guild) {
method EmitDeleteGuild (line 151) | func (s *socketService) EmitDeleteGuild(guildId string, members []stri...
method EmitRemoveFromGuild (line 166) | func (s *socketService) EmitRemoveFromGuild(memberId, guildId string) {
method EmitAddMember (line 179) | func (s *socketService) EmitAddMember(room string, member *model.User) {
method EmitRemoveMember (line 203) | func (s *socketService) EmitRemoveMember(room, memberId string) {
method EmitNewDMNotification (line 216) | func (s *socketService) EmitNewDMNotification(channelId string, user *...
method EmitNewNotification (line 261) | func (s *socketService) EmitNewNotification(guildId, channelId string) {
method EmitSendRequest (line 293) | func (s *socketService) EmitSendRequest(room string) {
method EmitAddFriendRequest (line 306) | func (s *socketService) EmitAddFriendRequest(room string, request *mod...
method EmitAddFriend (line 320) | func (s *socketService) EmitAddFriend(user, member *model.User) {
method EmitRemoveFriend (line 359) | func (s *socketService) EmitRemoveFriend(userId, memberId string) {
type SSConfig (line 18) | type SSConfig struct
function NewSocketService (line 26) | func NewSocketService(c *SSConfig) model.SocketService {
FILE: server/service/user_service.go
type userService (line 17) | type userService struct
method Get (line 45) | func (s *userService) Get(uid string) (*model.User, error) {
method GetByEmail (line 50) | func (s *userService) GetByEmail(email string) (*model.User, error) {
method Register (line 60) | func (s *userService) Register(user *model.User) (*model.User, error) {
method Login (line 79) | func (s *userService) Login(email, password string) (*model.User, erro...
method UpdateAccount (line 101) | func (s *userService) UpdateAccount(u *model.User) error {
method IsEmailAlreadyInUse (line 105) | func (s *userService) IsEmailAlreadyInUse(email string) bool {
method ChangeAvatar (line 115) | func (s *userService) ChangeAvatar(header *multipart.FileHeader, direc...
method DeleteImage (line 119) | func (s *userService) DeleteImage(key string) error {
method ChangePassword (line 123) | func (s *userService) ChangePassword(currentPassword, newPassword stri...
method ForgotPassword (line 147) | func (s *userService) ForgotPassword(ctx context.Context, user *model....
method ResetPassword (line 157) | func (s *userService) ResetPassword(ctx context.Context, password stri...
method GetFriendAndGuildIds (line 186) | func (s *userService) GetFriendAndGuildIds(userId string) (*[]string, ...
method GetRequestCount (line 190) | func (s *userService) GetRequestCount(userId string) (*int64, error) {
type USConfig (line 26) | type USConfig struct
function NewUserService (line 35) | func NewUserService(c *USConfig) model.UserService {
function generateAvatar (line 195) | func generateAvatar(email string) string {
FILE: server/service/user_service_test.go
function TestGet (line 15) | func TestGet(t *testing.T) {
function TestUserService_GetByEmail (line 52) | func TestUserService_GetByEmail(t *testing.T) {
function TestRegister (line 87) | func TestRegister(t *testing.T) {
function TestLogin (line 152) | func TestLogin(t *testing.T) {
function TestUpdateDetails (line 203) | func TestUpdateDetails(t *testing.T) {
function TestUserService_ChangeAvatar (line 254) | func TestUserService_ChangeAvatar(t *testing.T) {
function TestUserService_ChangePassword (line 464) | func TestUserService_ChangePassword(t *testing.T) {
function TestUserService_ForgotPassword (line 546) | func TestUserService_ForgotPassword(t *testing.T) {
function TestUserService_ResetPassword (line 589) | func TestUserService_ResetPassword(t *testing.T) {
FILE: server/static/js/main.js
function bindExpanders (line 3) | function bindExpanders() {
function highlightCode (line 14) | function highlightCode() {
function bindMenuItems (line 22) | function bindMenuItems() {
FILE: server/ws/actions.go
constant JoinUserAction (line 5) | JoinUserAction = "joinUser"
constant JoinGuildAction (line 6) | JoinGuildAction = "joinGuild"
constant JoinChannelAction (line 7) | JoinChannelAction = "joinChannel"
constant JoinVoiceAction (line 8) | JoinVoiceAction = "joinVoice"
constant LeaveGuildAction (line 9) | LeaveGuildAction = "leaveGuild"
constant LeaveRoomAction (line 10) | LeaveRoomAction = "leaveRoom"
constant LeaveVoiceAction (line 11) | LeaveVoiceAction = "leaveVoice"
constant StartTypingAction (line 12) | StartTypingAction = "startTyping"
constant StopTypingAction (line 13) | StopTypingAction = "stopTyping"
constant ToggleOnlineAction (line 14) | ToggleOnlineAction = "toggleOnline"
constant ToggleOfflineAction (line 15) | ToggleOfflineAction = "toggleOffline"
constant GetRequestCountAction (line 16) | GetRequestCountAction = "getRequestCount"
constant NewMessageAction (line 21) | NewMessageAction = "new_message"
constant EditMessageAction (line 22) | EditMessageAction = "edit_message"
constant DeleteMessageAction (line 23) | DeleteMessageAction = "delete_message"
constant AddChannelAction (line 24) | AddChannelAction = "add_channel"
constant AddPrivateChannelAction (line 25) | AddPrivateChannelAction = "add_private_channel"
constant EditChannelAction (line 26) | EditChannelAction = "edit_channel"
constant DeleteChannelAction (line 27) | DeleteChannelAction = "delete_channel"
constant EditGuildAction (line 28) | EditGuildAction = "edit_guild"
constant DeleteGuildAction (line 29) | DeleteGuildAction = "delete_guild"
constant RemoveFromGuildAction (line 30) | RemoveFromGuildAction = "remove_from_guild"
constant AddMemberAction (line 31) | AddMemberAction = "add_member"
constant RemoveMemberAction (line 32) | RemoveMemberAction = "remove_member"
constant NewDMNotificationAction (line 33) | NewDMNotificationAction = "new_dm_notification"
constant NewNotificationAction (line 34) | NewNotificationAction = "new_notification"
constant ToggleOnlineEmission (line 35) | ToggleOnlineEmission = "toggle_online"
constant ToggleOfflineEmission (line 36) | ToggleOfflineEmission = "toggle_offline"
constant AddToTypingAction (line 37) | AddToTypingAction = "addToTyping"
constant RemoveFromTypingAction (line 38) | RemoveFromTypingAction = "removeFromTyping"
constant SendRequestAction (line 39) | SendRequestAction = "send_request"
constant AddRequestAction (line 40) | AddRequestAction = "add_request"
constant AddFriendAction (line 41) | AddFriendAction = "add_friend"
constant RemoveFriendAction (line 42) | RemoveFriendAction = "remove_friend"
constant PushToTopAction (line 43) | PushToTopAction = "push_to_top"
constant RequestCountEmission (line 44) | RequestCountEmission = "requestCount"
constant VoiceSignal (line 45) | VoiceSignal = "voice-signal"
constant ToggleMute (line 46) | ToggleMute = "toggle-mute"
constant ToggleDeafen (line 47) | ToggleDeafen = "toggle-deafen"
FILE: server/ws/client.go
constant writeWait (line 16) | writeWait = 10 * time.Second
constant pongWait (line 19) | pongWait = 60 * time.Second
constant pingPeriod (line 22) | pingPeriod = (pongWait * 9) / 10
constant maxMessageSize (line 25) | maxMessageSize = 10000
type Client (line 39) | type Client struct
method readPump (line 58) | func (client *Client) readPump() {
method writePump (line 83) | func (client *Client) writePump() {
method disconnect (line 124) | func (client *Client) disconnect() {
method handleNewMessage (line 151) | func (client *Client) handleNewMessage(jsonMessage []byte) {
method handleJoinChannelMessage (line 205) | func (client *Client) handleJoinChannelMessage(message model.ReceivedM...
method handleJoinGuildMessage (line 224) | func (client *Client) handleJoinGuildMessage(message model.ReceivedMes...
method handleJoinRoomMessage (line 243) | func (client *Client) handleJoinRoomMessage(message model.ReceivedMess...
method handleLeaveGuildMessage (line 257) | func (client *Client) handleLeaveGuildMessage(message model.ReceivedMe...
method handleLeaveRoomMessage (line 263) | func (client *Client) handleLeaveRoomMessage(message model.ReceivedMes...
method handleGetRequestCount (line 273) | func (client *Client) handleGetRequestCount() {
method handleTypingEvent (line 290) | func (client *Client) handleTypingEvent(message model.ReceivedMessage,...
method toggleOnlineStatus (line 303) | func (client *Client) toggleOnlineStatus(isOnline bool) {
method handleJoinVoiceMessage (line 345) | func (client *Client) handleJoinVoiceMessage(message model.ReceivedMes...
method handleVoiceSignal (line 401) | func (client *Client) handleVoiceSignal(message model.ReceivedMessage) {
method handleLeaveVoiceMessage (line 426) | func (client *Client) handleLeaveVoiceMessage(message model.ReceivedMe...
method updateVCMember (line 461) | func (client *Client) updateVCMember(message model.ReceivedMessage) {
function newClient (line 48) | func newClient(conn *websocket.Conn, hub *Hub, id string) *Client {
function ServeWs (line 134) | func ServeWs(hub *Hub, ctx *gin.Context) {
function isMember (line 495) | func isMember(guild *model.Guild, userId string) bool {
FILE: server/ws/hub.go
type Hub (line 9) | type Hub struct
method Run (line 46) | func (hub *Hub) Run() {
method registerClient (line 62) | func (hub *Hub) registerClient(client *Client) {
method unregisterClient (line 66) | func (hub *Hub) unregisterClient(client *Client) {
method broadcastToClients (line 70) | func (hub *Hub) broadcastToClients(message []byte) {
method BroadcastToRoom (line 77) | func (hub *Hub) BroadcastToRoom(message []byte, roomId string) {
method findRoomById (line 83) | func (hub *Hub) findRoomById(id string) *Room {
method createRoom (line 95) | func (hub *Hub) createRoom(id string) *Room {
type Config (line 23) | type Config struct
function NewWebsocketHub (line 31) | func NewWebsocketHub(c *Config) *Hub {
FILE: server/ws/room.go
type Room (line 11) | type Room struct
method RunRoom (line 35) | func (room *Room) RunRoom() {
method registerClientInRoom (line 55) | func (room *Room) registerClientInRoom(client *Client) {
method unregisterClientInRoom (line 60) | func (room *Room) unregisterClientInRoom(client *Client) {
method broadcastToClientsInRoom (line 65) | func (room *Room) broadcastToClientsInRoom(message []byte) {
method GetId (line 72) | func (room *Room) GetId() string {
method publishRoomMessage (line 77) | func (room *Room) publishRoomMessage(message []byte) {
method subscribeToRoomMessages (line 86) | func (room *Room) subscribeToRoomMessages() {
function NewRoom (line 23) | func NewRoom(id string, rds *redis.Client) *Room {
FILE: web/cypress/support/index.d.ts
type Chainable (line 6) | interface Chainable {
FILE: web/src/components/common/InputField.tsx
type InputFieldProps (line 6) | type InputFieldProps = InputHTMLAttributes<HTMLInputElement> & {
FILE: web/src/components/common/NotificationIcon.tsx
type NotificationIconProps (line 4) | interface NotificationIconProps {
FILE: web/src/components/items/ChannelListItem.tsx
type ChannelListItemProps (line 14) | interface ChannelListItemProps {
FILE: web/src/components/items/DMListItem.tsx
type DMListItemProps (line 10) | interface DMListItemProps {
FILE: web/src/components/items/FriendsListItem.tsx
type FriendsListItemProp (line 12) | interface FriendsListItemProp {
FILE: web/src/components/items/GuildListItem.tsx
type GuildListItemProps (line 10) | interface GuildListItemProps {
FILE: web/src/components/items/MemberListItem.tsx
type MemberListItemProps (line 11) | interface MemberListItemProps {
FILE: web/src/components/items/NotificationListItem.tsx
type NotificationListItemProps (line 11) | interface NotificationListItemProps {
FILE: web/src/components/items/RequestListItem.tsx
type RequestListItemProps (line 11) | interface RequestListItemProps {
FILE: web/src/components/items/VoiceChannelItem.tsx
type VoiceUserVisualProps (line 5) | interface VoiceUserVisualProps {
type VoiceUserProps (line 40) | interface VoiceUserProps extends VoiceUserVisualProps {
FILE: web/src/components/items/message/Message.tsx
type MessageProps (line 20) | interface MessageProps {
FILE: web/src/components/items/message/MessageContent.tsx
type MessageProps (line 5) | interface MessageProps {
FILE: web/src/components/layouts/AppLayout.tsx
type AppLayoutProps (line 4) | interface AppLayoutProps {
FILE: web/src/components/layouts/LandingLayout.tsx
type IProps (line 6) | interface IProps {
FILE: web/src/components/layouts/guild/chat/ChatGrid.tsx
type IProps (line 5) | interface IProps {
FILE: web/src/components/menus/GuildMenu.tsx
type GuildMenuProps (line 21) | interface GuildMenuProps {
FILE: web/src/components/menus/MemberContextMenu.tsx
type MemberContextMenuProps (line 11) | interface MemberContextMenuProps {
FILE: web/src/components/menus/StyledMenuItem.tsx
type StyledMenuItemProps (line 5) | interface StyledMenuItemProps {
FILE: web/src/components/menus/StyledMenuList.tsx
type IProps (line 4) | interface IProps {
FILE: web/src/components/modals/AddFriendModal.tsx
type AddFriendModalProps (line 25) | interface AddFriendModalProps {
FILE: web/src/components/modals/AddGuildModal.tsx
type IProps (line 26) | interface IProps {
type AddGuildScreen (line 31) | enum AddGuildScreen {
type IScreenProps (line 102) | interface IScreenProps {
FILE: web/src/components/modals/ChangePasswordModal.tsx
type IProps (line 20) | interface IProps {
FILE: web/src/components/modals/ChannelSettingsModal.tsx
type IProps (line 34) | interface IProps {
type Item (line 41) | interface Item {
type ChannelScreen (line 48) | enum ChannelScreen {
type IScreenProps (line 229) | interface IScreenProps {
FILE: web/src/components/modals/CreateChannelModal.tsx
type IProps (line 31) | interface IProps {
type Item (line 37) | interface Item {
FILE: web/src/components/modals/CropImageModal.tsx
type IProps (line 20) | interface IProps {
FILE: web/src/components/modals/DeleteMessageModal.tsx
type IProps (line 20) | interface IProps {
FILE: web/src/components/modals/EditMemberModal.tsx
type IProps (line 23) | interface IProps {
FILE: web/src/components/modals/EditMessageModal.tsx
type IProps (line 21) | interface IProps {
FILE: web/src/components/modals/GuildSettingsModal.tsx
type IProps (line 37) | interface IProps {
type SettingsScreen (line 43) | enum SettingsScreen {
type IScreenProps (line 253) | interface IScreenProps {
type IBanScreenProps (line 307) | interface IBanScreenProps {
FILE: web/src/components/modals/InviteModal.tsx
type InviteModalProps (line 22) | interface InviteModalProps {
FILE: web/src/components/modals/ModActionModal.tsx
type IProps (line 20) | interface IProps {
FILE: web/src/components/modals/RemoveFriendModal.tsx
type IProps (line 18) | interface IProps {
FILE: web/src/components/sections/AddGuildIcon.tsx
type AddGuildIconProps (line 7) | interface AddGuildIconProps {
FILE: web/src/components/sections/DateDivider.tsx
type DateDividerProps (line 5) | interface DateDividerProps {
FILE: web/src/components/sections/Footer.tsx
type FooterLinkProps (line 8) | type FooterLinkProps = {
FILE: web/src/components/sections/GlobalState.tsx
type WSMessage (line 9) | type WSMessage = { action: 'new_dm_notification'; data: DMChannel } | { ...
type IProps (line 11) | interface IProps {
FILE: web/src/components/sections/Hero.tsx
type HeroProps (line 6) | interface HeroProps {
FILE: web/src/components/sections/OnlineLabel.tsx
type LabelProps (line 4) | interface LabelProps {
FILE: web/src/components/sections/StyledTooltip.tsx
type Placement (line 4) | type Placement = 'top' | 'right';
type StyledTooltipProps (line 6) | interface StyledTooltipProps {
FILE: web/src/components/sections/UserPopover.tsx
type UserPopoverProps (line 16) | interface UserPopoverProps {
FILE: web/src/lib/api/dtos/AuthInput.ts
type LoginDTO (line 2) | interface LoginDTO {
type RegisterDTO (line 9) | interface RegisterDTO extends LoginDTO {
class ChangePasswordInput (line 13) | class ChangePasswordInput {
class ResetPasswordInput (line 21) | class ResetPasswordInput {
FILE: web/src/lib/api/dtos/ChannelInput.ts
type ChannelInput (line 1) | type ChannelInput = {
FILE: web/src/lib/api/dtos/GuildInput.ts
type GuildInput (line 1) | type GuildInput = {
FILE: web/src/lib/api/dtos/GuildMemberInput.ts
type GuildMemberInput (line 1) | type GuildMemberInput = {
FILE: web/src/lib/api/dtos/InviteInput.ts
type InviteInput (line 1) | type InviteInput = {
FILE: web/src/lib/api/dtos/UserInput.ts
type UpdateInput (line 1) | type UpdateInput = Partial<{
FILE: web/src/lib/api/ws/useChannelSocket.ts
type WSMessage (line 11) | type WSMessage =
function useChannelSocket (line 16) | function useChannelSocket(guildId: string): void {
FILE: web/src/lib/api/ws/useDMSocket.ts
type WSMessage (line 8) | type WSMessage = { action: 'push_to_top'; data: string };
function useDMSocket (line 10) | function useDMSocket(): void {
FILE: web/src/lib/api/ws/useFriendSocket.ts
type WSMessage (line 9) | type WSMessage =
function useFriendSocket (line 14) | function useFriendSocket(): void {
FILE: web/src/lib/api/ws/useGuildSocket.ts
type WSMessage (line 9) | type WSMessage =
function useGuildSocket (line 13) | function useGuildSocket(): void {
FILE: web/src/lib/api/ws/useMemberSocket.ts
type WSMessage (line 7) | type WSMessage =
function useMemberSocket (line 11) | function useMemberSocket(guildId: string): void {
FILE: web/src/lib/api/ws/useMessageSocket.ts
type WSMessage (line 9) | type WSMessage =
function useMessageSocket (line 13) | function useMessageSocket(channelId: string): void {
FILE: web/src/lib/api/ws/useRequestSocket.ts
type WSMessage (line 9) | type WSMessage = { action: 'add_request'; data: FriendRequest };
function useRequestSocket (line 11) | function useRequestSocket(): void {
FILE: web/src/lib/api/ws/useVoiceSocket.ts
type WSMessage (line 11) | type WSMessage =
function useVoiceSocket (line 16) | function useVoiceSocket(): void {
FILE: web/src/lib/models/account.ts
type Account (line 1) | interface Account {
FILE: web/src/lib/models/channel.ts
type Channel (line 1) | interface Channel {
FILE: web/src/lib/models/dm.ts
type DMChannel (line 1) | interface DMChannel {
type DMNotification (line 6) | interface DMNotification extends DMChannel {
type DMMember (line 10) | interface DMMember {
FILE: web/src/lib/models/fieldError.ts
type FieldError (line 1) | interface FieldError {
FILE: web/src/lib/models/friend.ts
type Friend (line 1) | interface Friend {
type RequestType (line 8) | enum RequestType {
type FriendRequest (line 13) | interface FriendRequest {
FILE: web/src/lib/models/guild.ts
type Guild (line 1) | interface Guild {
FILE: web/src/lib/models/member.ts
type Member (line 1) | interface Member {
FILE: web/src/lib/models/message.ts
type Message (line 3) | interface Message {
type Attachment (line 12) | interface Attachment {
FILE: web/src/lib/models/routerProps.ts
type RouterProps (line 1) | type RouterProps = {
FILE: web/src/lib/models/voice.ts
type VoiceSignal (line 1) | interface VoiceSignal {
type VoiceResponse (line 7) | interface VoiceResponse {
type VCMember (line 12) | interface VCMember {
FILE: web/src/lib/stores/channelStore.ts
type ChannelState (line 3) | type ChannelState = {
FILE: web/src/lib/stores/homeStore.ts
type HomeStoreType (line 3) | type HomeStoreType = {
FILE: web/src/lib/stores/settingsStore.ts
type SettingsState (line 4) | type SettingsState = {
FILE: web/src/lib/stores/userStore.ts
type AccountState (line 5) | type AccountState = {
FILE: web/src/lib/stores/voiceStore.ts
type VoiceState (line 4) | type VoiceState = {
FILE: web/src/lib/utils/cropImage.ts
function getCroppedImg (line 16) | async function getCroppedImg(imageSrc: string, pixelCrop: any): Promise<...
FILE: web/src/lib/utils/hooks/useGetCurrentChannel.ts
function useGetCurrentChannel (line 5) | function useGetCurrentChannel(channelId: string, guildId: string): Chann...
FILE: web/src/lib/utils/hooks/useGetCurrentDM.ts
function useGetCurrentDM (line 5) | function useGetCurrentDM(channelId: string): DMChannel | undefined {
FILE: web/src/lib/utils/hooks/useGetCurrentGuild.ts
function useGetCurrentGuild (line 5) | function useGetCurrentGuild(guildId: string): Guild | undefined {
FILE: web/src/lib/utils/hooks/useGetFriend.ts
function useGetFriend (line 5) | function useGetFriend(id: string): Friend | undefined {
FILE: web/src/lib/utils/hooks/useVoiceChat.ts
function useSetupVoiceChat (line 9) | function useSetupVoiceChat(guildId: string): void {
FILE: web/src/lib/utils/validation/message.schema.ts
constant SUPPORTED_FORMATS (line 3) | const SUPPORTED_FORMATS = ['image/jpg', 'image/jpeg', 'audio/mp3', 'audi...
FILE: web/src/routes/AuthRoute.tsx
type IProps (line 6) | interface IProps {
FILE: web/src/routes/Invite.tsx
type InviteRouter (line 6) | interface InviteRouter {
FILE: web/src/routes/ResetPassword.tsx
type TokenProps (line 11) | type TokenProps = {
FILE: web/src/tests/testUtils.tsx
type IQueryWrapperProps (line 49) | interface IQueryWrapperProps {
Condensed preview — 291 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,622K chars).
[
{
"path": ".github/workflows/release_build.yml",
"chars": 704,
"preview": "name: Release Server Binary\n\non:\n release:\n types: [created]\n\njobs:\n releases-matrix:\n name: Release Go Binary\n "
},
{
"path": ".github/workflows/server_ci.yml",
"chars": 1712,
"preview": "name: Test & Lint\n\non:\n push:\n paths:\n - 'server/**'\n pull_request:\n paths:\n - 'server/**'\n\njobs:\n go"
},
{
"path": ".github/workflows/server_deploy.yml",
"chars": 558,
"preview": "# name: Deploy [API]\n\n# on:\n# workflow_run:\n# workflows: ['Test & Lint']\n# branches: [main]\n# types: [comp"
},
{
"path": ".github/workflows/web_ci.yml",
"chars": 534,
"preview": "name: Test & Lint - Web\n\non:\n push:\n paths:\n - 'web/**'\n pull_request:\n paths:\n - 'web/**'\n\njobs:\n te"
},
{
"path": ".github/workflows/website-e2e.yml",
"chars": 1865,
"preview": "name: Website E2E\non:\n workflow_run:\n workflows: ['Test & Lint - Web']\n branches: [main]\n types: [completed]\n\n"
},
{
"path": ".github/workflows/website_deploy.yml",
"chars": 1008,
"preview": "# name: Website Deploy\n\n# on:\n# workflow_run:\n# workflows: ['Website E2E']\n# branches: [main]\n# types: [co"
},
{
"path": ".gitignore",
"chars": 2546,
"preview": "\n# Created by https://www.toptal.com/developers/gitignore/api/webstorm\n# Edit at https://www.toptal.com/developers/gitig"
},
{
"path": "LICENSE",
"chars": 1067,
"preview": "MIT License\n\nCopyright (c) 2021 sentrionic\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "README.md",
"chars": 5307,
"preview": "[](https://goreportcard.com/report/githu"
},
{
"path": "server/.gitattributes",
"chars": 80,
"preview": "*.html -linguist-detectable\n*.css -linguist-detectable\n*.js -linguist-detectable"
},
{
"path": "server/.gitignore",
"chars": 949,
"preview": "# Created by https://www.toptal.com/developers/gitignore/api/go\n# Edit at https://www.toptal.com/developers/gitignore?te"
},
{
"path": "server/.idea/.gitignore",
"chars": 176,
"preview": "# Default ignored files\n/shelf/\n/workspace.xml\n# Datasource local storage ignored files\n/dataSources/\n/dataSources.local"
},
{
"path": "server/.idea/ValkyrieGo.iml",
"chars": 322,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"WEB_MODULE\" version=\"4\">\n <component name=\"Go\" enabled=\"true\" />\n "
},
{
"path": "server/.idea/dataSources.xml",
"chars": 525,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"DataSourceManagerImpl\" format=\"xml\" mult"
},
{
"path": "server/.idea/modules.xml",
"chars": 272,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectModuleManager\">\n <modules>\n "
},
{
"path": "server/.idea/vcs.xml",
"chars": 183,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": "server/Makefile",
"chars": 739,
"preview": "postgres:\n\tdocker run --name postgres -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=password -d postgres:alpin"
},
{
"path": "server/config/config.go",
"chars": 911,
"preview": "package config\n\nimport (\n\t\"context\"\n\t\"github.com/sethvargo/go-envconfig\"\n)\n\ntype Config struct {\n\tDatabaseUrl string "
},
{
"path": "server/data_sources.go",
"chars": 2386,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/aws/aws-sdk-go/aws\"\n\t\"github.com/aws/aws-sdk-go/aws/credentials\"\n\t"
},
{
"path": "server/docs/docs.go",
"chars": 80496,
"preview": "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n// This file was generated by swaggo/swag\n\npackage docs\n\nimport (\n\t\"bytes"
},
{
"path": "server/docs/swagger.json",
"chars": 79308,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"description\": \"Valkyrie REST API Specs. This service uses sessions for au"
},
{
"path": "server/docs/swagger.yaml",
"chars": 37267,
"preview": "basePath: /api\ndefinitions:\n Attachment:\n properties:\n filename:\n type: string\n filetype:\n t"
},
{
"path": "server/e2e_test.go",
"chars": 72896,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/joho/godoten"
},
{
"path": "server/go.mod",
"chars": 3746,
"preview": "module github.com/sentrionic/valkyrie\n\ngo 1.20\n\n// +heroku goVersion go1.20\n\nrequire (\n\tgithub.com/alecthomas/template v"
},
{
"path": "server/go.sum",
"chars": 22864,
"preview": "github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=\ngithub.com/KyleBanks/depth v1.2.1/go.m"
},
{
"path": "server/handler/account_handler.go",
"chars": 5588,
"preview": "package handler\n\nimport (\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\tvalidation \"github.com/go-ozzo/ozzo-validation/v4\"\n\t\"githu"
},
{
"path": "server/handler/account_handler_test.go",
"chars": 13838,
"preview": "package handler\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valkyrie/"
},
{
"path": "server/handler/auth_handler.go",
"chars": 7404,
"preview": "package handler\n\nimport (\n\t\"github.com/gin-contrib/sessions\"\n\t\"github.com/gin-gonic/gin\"\n\tvalidation \"github.com/go-ozzo"
},
{
"path": "server/handler/auth_handler_test.go",
"chars": 21300,
"preview": "package handler\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"github.com/gin-contrib/sessions\"\n\t\"github.com/gin-gonic/gin\"\n\t\"git"
},
{
"path": "server/handler/bind_data.go",
"chars": 1048,
"preview": "package handler\n\nimport (\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentrionic/valkyrie/model/apperrors\"\n\t\"ne"
},
{
"path": "server/handler/channel_handler.go",
"chars": 15660,
"preview": "package handler\n\nimport (\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\tvalidation \"github.com/go-ozzo/ozzo-validation/v4\"\n\t\"githu"
},
{
"path": "server/handler/channel_handler_test.go",
"chars": 64350,
"preview": "package handler\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valkyrie/"
},
{
"path": "server/handler/friend_handler.go",
"chars": 9488,
"preview": "package handler\n\nimport (\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentrionic/va"
},
{
"path": "server/handler/friend_handler_test.go",
"chars": 33101,
"preview": "package handler\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valkyrie/mocks\"\n\t\""
},
{
"path": "server/handler/guild_handler.go",
"chars": 17265,
"preview": "package handler\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\tvalidation \"github.com/go-ozzo/ozzo-validation/"
},
{
"path": "server/handler/guild_handler_test.go",
"chars": 64310,
"preview": "package handler\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valkyrie/"
},
{
"path": "server/handler/handler.go",
"chars": 5080,
"preview": "package handler\n\nimport (\n\t\"github.com/gin-contrib/sessions\"\n\t\"github.com/gin-gonic/contrib/static\"\n\t\"github.com/gin-gon"
},
{
"path": "server/handler/member_handler.go",
"chars": 9999,
"preview": "package handler\n\nimport (\n\t\"github.com/gin-gonic/gin\"\n\tvalidation \"github.com/go-ozzo/ozzo-validation/v4\"\n\t\"github.com/g"
},
{
"path": "server/handler/member_handler_test.go",
"chars": 47036,
"preview": "package handler\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valkyrie/"
},
{
"path": "server/handler/message_handler.go",
"chars": 9951,
"preview": "package handler\n\nimport (\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\tvalidation \"github.com/go-ozzo/ozzo-validation/v4\"\n\tgonano"
},
{
"path": "server/handler/message_handler_test.go",
"chars": 46345,
"preview": "package handler\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valkyrie/mocks\"\n"
},
{
"path": "server/handler/middleware/auth_user.go",
"chars": 797,
"preview": "package middleware\n\nimport (\n\t\"github.com/gin-contrib/sessions\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valk"
},
{
"path": "server/handler/middleware/auth_user_test.go",
"chars": 1543,
"preview": "package middleware\n\nimport (\n\t\"github.com/gin-contrib/sessions\"\n\t\"github.com/gin-contrib/sessions/cookie\"\n\t\"github.com/s"
},
{
"path": "server/handler/middleware/timeout.go",
"chars": 4010,
"preview": "package middleware\n\n/*\n * Inspired by Golang's TimeoutHandler: https://golang.org/src/net/http/server.go?s=101514:101582"
},
{
"path": "server/handler/mime_type.go",
"chars": 629,
"preview": "package handler\n\nvar validImageTypes = map[string]bool{\n\t\"image/jpeg\": true,\n\t\"image/png\": true,\n}\n\n// IsAllowedImageTy"
},
{
"path": "server/handler/test_helpers.go",
"chars": 851,
"preview": "package handler\n\nimport (\n\t\"github.com/gin-contrib/sessions\"\n\t\"github.com/gin-contrib/sessions/cookie\"\n\t\"github.com/gin-"
},
{
"path": "server/injection.go",
"chars": 4158,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"github.com/gin-contrib/sessions\"\n\t\"github.com/gin-contrib/sessions/redis\"\n\t\"github.com/g"
},
{
"path": "server/main.go",
"chars": 2110,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/sentrionic/valk"
},
{
"path": "server/mocks/ChannelRepository.go",
"chars": 8132,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/ChannelService.go",
"chars": 7540,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/FileRepository.go",
"chars": 2151,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmock \"github.com/stretchr/testify/mock\"\n\n\tm"
},
{
"path": "server/mocks/FriendRepository.go",
"chars": 3063,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/FriendService.go",
"chars": 3045,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/GuildRepository.go",
"chars": 9764,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/GuildService.go",
"chars": 10546,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tcontext \"context\"\n\n\tmodel \"github.com/sentr"
},
{
"path": "server/mocks/MailRepository.go",
"chars": 927,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmock \"github.com/stretchr/testify/mock\"\n\n\tt"
},
{
"path": "server/mocks/MessageRepository.go",
"chars": 3004,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/MessageService.go",
"chars": 3608,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/RedisRepository.go",
"chars": 2787,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tcontext \"context\"\n\n\tmodel \"github.com/sentr"
},
{
"path": "server/mocks/Request.go",
"chars": 781,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\ttesting \"testing\"\n\n\tmock \"github.com/stretc"
},
{
"path": "server/mocks/SocketService.go",
"chars": 3995,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/UserRepository.go",
"chars": 3273,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tmodel \"github.com/sentrionic/valkyrie/model"
},
{
"path": "server/mocks/UserService.go",
"chars": 6339,
"preview": "// Code generated by mockery v2.12.1. DO NOT EDIT.\n\npackage mocks\n\nimport (\n\tcontext \"context\"\n\n\tmodel \"github.com/sentr"
},
{
"path": "server/model/app_constants.go",
"chars": 141,
"preview": "package model\n\n// Application Constants\nconst (\n\tMinimumChannels = 1\n\tMaximumChannels = 50\n\tMaximumGuilds = 100\n\tCooki"
},
{
"path": "server/model/apperrors/apperrors.go",
"chars": 2320,
"preview": "package apperrors\n\n// Guild Errors\nconst (\n\tNotAMember = \"Not a member of the guild\"\n\tAlreadyMember "
},
{
"path": "server/model/apperrors/httperrors.go",
"chars": 3873,
"preview": "package apperrors\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\n// Type holds a type string and integer code for the error\nt"
},
{
"path": "server/model/base_model.go",
"chars": 531,
"preview": "package model\n\nimport (\n\t\"time\"\n)\n\n// BaseModel is similar to the gorm.Model and it includes the\n// ID as a string, Crea"
},
{
"path": "server/model/channel.go",
"chars": 3523,
"preview": "package model\n\nimport \"time\"\n\n// Channel represents a text channel in a guild\n// or a text channel for DMs between users"
},
{
"path": "server/model/direct_message.go",
"chars": 454,
"preview": "package model\n\n// DirectMessage is the json response of the channel ID\n// and the other user of the DM.\ntype DirectMessa"
},
{
"path": "server/model/dm_member.go",
"chars": 345,
"preview": "package model\n\nimport \"time\"\n\n// DMMember represents a member of a DM channel.\n// IsOpen indicates if the DM is open on "
},
{
"path": "server/model/field_error.go",
"chars": 767,
"preview": "package model\n\n// ErrorsResponse contains a list of FieldError\ntype ErrorsResponse struct {\n\tErrors []FieldError `json:\""
},
{
"path": "server/model/fixture/channel.go",
"chars": 897,
"preview": "package fixture\n\nimport (\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"time\"\n)\n\n// GetMockChannel returns a mock channel. I"
},
{
"path": "server/model/fixture/faker.go",
"chars": 1670,
"preview": "package fixture\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"strings\"\n)\n\nvar letterRunes = []rune(\"abcd"
},
{
"path": "server/model/fixture/guild.go",
"chars": 430,
"preview": "package fixture\n\nimport (\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"time\"\n)\n\n// GetMockGuild returns a mock guild with t"
},
{
"path": "server/model/fixture/message.go",
"chars": 1246,
"preview": "package fixture\n\nimport (\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"time\"\n)\n\n// GetMockMessage returns a mock message wi"
},
{
"path": "server/model/fixture/multipart.go",
"chars": 2212,
"preview": "package fixture\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"image\"\n\t\"image/png\"\n\t\"io\"\n\t\"mime\"\n\t\"mime/multipart\"\n\t\"net/textproto\"\n\t\"os\"\n\t"
},
{
"path": "server/model/fixture/user.go",
"chars": 402,
"preview": "package fixture\n\nimport (\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"time\"\n)\n\n// GetMockUser returns a mock user\nfunc Get"
},
{
"path": "server/model/friend.go",
"chars": 1118,
"preview": "package model\n\n// Friend represents the api response of a user's friend.\ntype Friend struct {\n\tId string `json:\"id"
},
{
"path": "server/model/friend_request.go",
"chars": 525,
"preview": "package model\n\n// RequestType stands for the type of friend request\ntype RequestType int\n\n// FriendRequest RequestType e"
},
{
"path": "server/model/guild.go",
"chars": 4302,
"preview": "package model\n\nimport (\n\t\"context\"\n\t\"github.com/lib/pq\"\n\t\"time\"\n)\n\n// Guild represents the server many users can chat in"
},
{
"path": "server/model/interfaces.go",
"chars": 1146,
"preview": "package model\n\nimport (\n\t\"context\"\n\t\"mime/multipart\"\n)\n\n// FileRepository defines methods related to file upload the ser"
},
{
"path": "server/model/invite.go",
"chars": 223,
"preview": "package model\n\n// Invite represents an invite link for a guild\n// IsPermanent indicates if the invite should not expire\n"
},
{
"path": "server/model/member.go",
"chars": 1835,
"preview": "package model\n\nimport \"time\"\n\n// Member represents a user in a guild and is the join table between\n// User and Guild.\nty"
},
{
"path": "server/model/message.go",
"chars": 2171,
"preview": "package model\n\nimport (\n\t\"mime/multipart\"\n\t\"time\"\n)\n\n// Message represents a text message in a channel.\n// It may contai"
},
{
"path": "server/model/user.go",
"chars": 1903,
"preview": "package model\n\nimport (\n\t\"context\"\n\t\"mime/multipart\"\n)\n\n// User represents the user of the website.\ntype User struct {\n\t"
},
{
"path": "server/model/ws_message.go",
"chars": 1607,
"preview": "package model\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n)\n\n// ReceivedMessage represents a received websocket message\ntype Recei"
},
{
"path": "server/repository/channel_repository.go",
"chars": 8274,
"preview": "package repository\n\nimport (\n\t\"database/sql\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentrionic/valkyrie/mo"
},
{
"path": "server/repository/file_repository.go",
"chars": 3704,
"preview": "package repository\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"github.com/aws/aws-sdk-go/aws\"\n\t\"github.com/aws/aws-sdk-go/aws/session\"\n\t"
},
{
"path": "server/repository/friend_repository.go",
"chars": 2785,
"preview": "package repository\n\nimport (\n\t\"database/sql\"\n\t\"errors\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentrionic/v"
},
{
"path": "server/repository/guild_repository.go",
"chars": 9425,
"preview": "package repository\n\nimport (\n\t\"errors\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentrionic/valkyrie/model/ap"
},
{
"path": "server/repository/mail_repository.go",
"chars": 1026,
"preview": "package repository\n\nimport (\n\t\"fmt\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"net/smtp\"\n)\n\n// mailRepository contains th"
},
{
"path": "server/repository/message_repository.go",
"chars": 5085,
"preview": "package repository\n\nimport (\n\t\"database/sql\"\n\t\"errors\"\n\t\"fmt\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentr"
},
{
"path": "server/repository/redis_repository.go",
"chars": 3339,
"preview": "package repository\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\tgonanoid \"github.com/matoous/go-nanoid/v2\"\n\t\"github.com"
},
{
"path": "server/repository/user_repository.go",
"chars": 3341,
"preview": "package repository\n\nimport (\n\t\"database/sql\"\n\t\"errors\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentrionic/v"
},
{
"path": "server/service/channel_service.go",
"chars": 4325,
"preview": "package service\n\nimport (\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentrionic/valkyrie/model/apperrors\"\n)\n\n/"
},
{
"path": "server/service/channel_service_test.go",
"chars": 5970,
"preview": "package service\n\nimport (\n\t\"github.com/sentrionic/valkyrie/mocks\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/s"
},
{
"path": "server/service/friend_service.go",
"chars": 1540,
"preview": "package service\n\nimport (\n\t\"github.com/sentrionic/valkyrie/model\"\n)\n\n// friendService acts as a struct for injecting an "
},
{
"path": "server/service/guild_service.go",
"chars": 4432,
"preview": "package service\n\nimport (\n\t\"context\"\n\tgonanoid \"github.com/matoous/go-nanoid\"\n\t\"github.com/sentrionic/valkyrie/model\"\n)\n"
},
{
"path": "server/service/guild_service_test.go",
"chars": 2826,
"preview": "package service\n\nimport (\n\t\"context\"\n\t\"github.com/sentrionic/valkyrie/mocks\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"g"
},
{
"path": "server/service/id_generator.go",
"chars": 415,
"preview": "package service\n\nimport (\n\t\"github.com/bwmarrin/snowflake\"\n\t\"log\"\n)\n\nvar node *snowflake.Node\n\nfunc init() {\n\tconst node"
},
{
"path": "server/service/message_service.go",
"chars": 2709,
"preview": "package service\n\nimport (\n\t\"fmt\"\n\tgonanoid \"github.com/matoous/go-nanoid\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"log\""
},
{
"path": "server/service/message_service_test.go",
"chars": 5543,
"preview": "package service\n\nimport (\n\t\"fmt\"\n\t\"github.com/sentrionic/valkyrie/mocks\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"githu"
},
{
"path": "server/service/password.go",
"chars": 1348,
"preview": "package service\n\nimport (\n\t\"crypto/rand\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/crypto/scrypt\"\n)\n\n// hashPass"
},
{
"path": "server/service/password_test.go",
"chars": 920,
"preview": "package service\n\nimport (\n\t\"github.com/sentrionic/valkyrie/model/fixture\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/requ"
},
{
"path": "server/service/socket_service.go",
"chars": 8499,
"preview": "package service\n\nimport (\n\t\"encoding/json\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"github.com/sentrionic/valkyrie/ws\"\n"
},
{
"path": "server/service/user_service.go",
"chars": 5081,
"preview": "package service\n\nimport (\n\t\"context\"\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"gith"
},
{
"path": "server/service/user_service_test.go",
"chars": 18472,
"preview": "package service\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/sentrionic/valkyrie/mocks\"\n\t\"github.com/sentrionic/valkyrie/mod"
},
{
"path": "server/static/asyncapi.yml",
"chars": 10656,
"preview": "asyncapi: '2.4.0'\ninfo:\n title: Valkyrie Websockets\n version: '1.0.0'\n description: >\n This service is in charge o"
},
{
"path": "server/static/index.html",
"chars": 210826,
"preview": "<!DOCTYPE html>\n\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n \n\n <title>Valkyrie Websockets \n \n \n \n <"
},
{
"path": "server/static/js/main.js",
"chars": 922,
"preview": "/* eslint-disable */\n\nfunction bindExpanders() {\n var props = document.querySelectorAll('.js-prop');\n for (let index ="
},
{
"path": "server/ws/actions.go",
"chars": 1698,
"preview": "package ws\n\n// Subscribed Messages\nconst (\n\tJoinUserAction = \"joinUser\"\n\tJoinGuildAction = \"joinGuild\"\n\tJoi"
},
{
"path": "server/ws/client.go",
"chars": 11243,
"preview": "package ws\n\nimport (\n\t\"encoding/json\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"log\"\n\t\"net/h"
},
{
"path": "server/ws/hub.go",
"chars": 2275,
"preview": "package ws\n\nimport (\n\t\"github.com/redis/go-redis/v9\"\n\t\"github.com/sentrionic/valkyrie/model\"\n)\n\n// Hub contains all room"
},
{
"path": "server/ws/room.go",
"chars": 2140,
"preview": "package ws\n\nimport (\n\t\"context\"\n\t\"github.com/redis/go-redis/v9\"\n\t\"github.com/sentrionic/valkyrie/model\"\n\t\"log\"\n)\n\n// Roo"
},
{
"path": "web/.eslintrc.json",
"chars": 1805,
"preview": "{\n \"env\": {\n \"browser\": true,\n \"es2021\": true\n },\n \"extends\": [\"plugin:react/recommended\", \"airbnb\", \"airbnb-ty"
},
{
"path": "web/.gitignore",
"chars": 350,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
},
{
"path": "web/.prettierrc",
"chars": 80,
"preview": "{\n \"printWidth\": 120,\n \"semi\": true,\n \"tabWidth\": 2,\n \"singleQuote\": true\n}\n"
},
{
"path": "web/cypress/e2e/account.cy.ts",
"chars": 2231,
"preview": "import { uuid } from '../support/utils';\n\n// Covers the account routes\ndescribe('Account related pages', () => {\n const"
},
{
"path": "web/cypress/e2e/channel.cy.ts",
"chars": 3279,
"preview": "import { uuid } from '../support/utils';\n\ndescribe('Channels related actions', () => {\n // The user's values\n const id"
},
{
"path": "web/cypress/e2e/friend.cy.ts",
"chars": 5203,
"preview": "import { uuid } from '../support/utils';\n\ndescribe('Friends related actions', () => {\n // Friend values\n const friendN"
},
{
"path": "web/cypress/e2e/guild.cy.ts",
"chars": 5327,
"preview": "import { uuid } from '../support/utils';\n\ndescribe('Guild related actions', () => {\n // The user's values\n const id = "
},
{
"path": "web/cypress/e2e/member.cy.ts",
"chars": 5647,
"preview": "import { uuid } from '../support/utils';\n\ndescribe('Members related actions', () => {\n // Member values\n const memberN"
},
{
"path": "web/cypress/e2e/message.cy.ts",
"chars": 6907,
"preview": "import { uuid } from '../support/utils';\n\nconst waitTime = 1000;\n\ndescribe('Message related actions', () => {\n // The u"
},
{
"path": "web/cypress/fixtures/example.json",
"chars": 155,
"preview": "{\n \"name\": \"Using fixtures to represent data\",\n \"email\": \"hello@cypress.io\",\n \"body\": \"Fixtures are a great way to mo"
},
{
"path": "web/cypress/plugins/index.js",
"chars": 762,
"preview": "/// <reference types=\"cypress\" />\n// ***********************************************************\n// This example plugins"
},
{
"path": "web/cypress/support/commands.ts",
"chars": 2072,
"preview": "Cypress.Commands.add('registerUser', (email, id) => {\n cy.visit('/');\n cy.contains('Valkyrie');\n cy.contains('Registe"
},
{
"path": "web/cypress/support/e2e.js",
"chars": 671,
"preview": "// ***********************************************************\n// This example support/index.js is processed and\n// load"
},
{
"path": "web/cypress/support/index.d.ts",
"chars": 634,
"preview": "// load type definitions that come with Cypress module\n// eslint-disable-next-line spaced-comment\n/// <reference types=\""
},
{
"path": "web/cypress/support/utils.ts",
"chars": 71,
"preview": "export const uuid = (): string => Cypress._.random(0, 1e6).toString();\n"
},
{
"path": "web/cypress/tsconfig.json",
"chars": 150,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"es5\",\n \"lib\": [\"es5\", \"dom\"],\n \"types\": [\"cypress\"]\n },\n \"include\": [\"**"
},
{
"path": "web/cypress.config.ts",
"chars": 221,
"preview": "import { defineConfig } from 'cypress';\n\nexport default defineConfig({\n video: false,\n screenshotOnRunFailure: false,\n"
},
{
"path": "web/package.json",
"chars": 2735,
"preview": "{\n \"name\": \"valkyrie\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"start\": \"react-scripts start\",\n "
},
{
"path": "web/public/_redirects",
"chars": 23,
"preview": "/* /index.html 200"
},
{
"path": "web/public/index.html",
"chars": 862,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <link rel=\"icon\" href=\"%PUBLIC_URL%/favicon.i"
},
{
"path": "web/public/manifest.json",
"chars": 492,
"preview": "{\n \"short_name\": \"React App\",\n \"name\": \"Create React App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n "
},
{
"path": "web/public/robots.txt",
"chars": 67,
"preview": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
},
{
"path": "web/src/App.tsx",
"chars": 546,
"preview": "import * as React from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { AppRo"
},
{
"path": "web/src/components/common/GuildPills.tsx",
"chars": 753,
"preview": "import { Box } from '@chakra-ui/react';\nimport React from 'react';\n\nexport const NotificationIndicator: React.FC = () =>"
},
{
"path": "web/src/components/common/InputField.tsx",
"chars": 979,
"preview": "/* eslint-disable react/jsx-props-no-spreading */\nimport React, { InputHTMLAttributes } from 'react';\nimport { useField "
},
{
"path": "web/src/components/common/Logo.tsx",
"chars": 319,
"preview": "import { Box, Image, Text } from '@chakra-ui/react';\nimport React from 'react';\n\nexport const Logo: React.FC = () => (\n "
},
{
"path": "web/src/components/common/NotificationIcon.tsx",
"chars": 846,
"preview": "import { Flex, Text } from '@chakra-ui/react';\nimport React from 'react';\n\ninterface NotificationIconProps {\n count: nu"
},
{
"path": "web/src/components/items/ChannelListItem.tsx",
"chars": 3155,
"preview": "import React, { useEffect, useState } from 'react';\nimport { Flex, Icon, ListItem, Text, useDisclosure } from '@chakra-u"
},
{
"path": "web/src/components/items/DMListItem.tsx",
"chars": 2318,
"preview": "import React, { useState } from 'react';\nimport { Avatar, AvatarBadge, Flex, Icon, ListItem, Text } from '@chakra-ui/rea"
},
{
"path": "web/src/components/items/FriendsListItem.tsx",
"chars": 2168,
"preview": "import { Avatar, AvatarBadge, Flex, IconButton, ListItem, Text, useDisclosure } from '@chakra-ui/react';\nimport React fr"
},
{
"path": "web/src/components/items/GuildListItem.tsx",
"chars": 2449,
"preview": "import React, { useEffect, useState } from 'react';\nimport { Avatar, Flex } from '@chakra-ui/react';\nimport { Link, useL"
},
{
"path": "web/src/components/items/MemberListItem.tsx",
"chars": 1753,
"preview": "import React from 'react';\nimport { Avatar, AvatarBadge, Flex, ListItem, Text } from '@chakra-ui/react';\nimport { useCon"
},
{
"path": "web/src/components/items/NotificationListItem.tsx",
"chars": 2347,
"preview": "import React, { useEffect, useState } from 'react';\nimport { Avatar, Flex } from '@chakra-ui/react';\nimport { Link, useL"
},
{
"path": "web/src/components/items/RequestListItem.tsx",
"chars": 2644,
"preview": "import { Avatar, Box, Flex, IconButton, ListItem, Text } from '@chakra-ui/react';\nimport React from 'react';\nimport { Bi"
},
{
"path": "web/src/components/items/VoiceChannelItem.tsx",
"chars": 1791,
"preview": "import { Avatar, Flex, Icon, Text } from '@chakra-ui/react';\nimport React, { useCallback } from 'react';\nimport { MdHead"
},
{
"path": "web/src/components/items/css/ContextMenu.css",
"chars": 5163,
"preview": ".react-contexify {\n position: fixed;\n opacity: 0;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-se"
},
{
"path": "web/src/components/items/message/Message.tsx",
"chars": 6212,
"preview": "import React, { useState } from 'react';\nimport { Avatar, Box, Flex, Icon, Text, useDisclosure } from '@chakra-ui/react'"
},
{
"path": "web/src/components/items/message/MessageContent.tsx",
"chars": 1067,
"preview": "import React from 'react';\nimport { Box, Flex, Image, Text } from '@chakra-ui/react';\nimport { Message } from '../../../"
},
{
"path": "web/src/components/layouts/AccountBar.tsx",
"chars": 3253,
"preview": "import { Avatar, Flex, IconButton, Text, Tooltip, useClipboard } from '@chakra-ui/react';\nimport React from 'react';\nimp"
},
{
"path": "web/src/components/layouts/AppLayout.tsx",
"chars": 552,
"preview": "import { Grid } from '@chakra-ui/react';\nimport React from 'react';\n\ninterface AppLayoutProps {\n showLastColumn?: boole"
},
{
"path": "web/src/components/layouts/LandingLayout.tsx",
"chars": 413,
"preview": "import React from 'react';\nimport { Flex } from '@chakra-ui/react';\nimport { NavBar } from '../sections/NavBar';\nimport "
},
{
"path": "web/src/components/layouts/VoiceBar.tsx",
"chars": 1406,
"preview": "import { Box, Flex, Icon, IconButton, Text, Tooltip } from '@chakra-ui/react';\nimport React from 'react';\nimport { AiFil"
},
{
"path": "web/src/components/layouts/guild/ChannelHeader.tsx",
"chars": 1293,
"preview": "import React from 'react';\nimport { Flex, GridItem, Icon, Text } from '@chakra-ui/react';\nimport { FaHashtag } from 'rea"
},
{
"path": "web/src/components/layouts/guild/Channels.tsx",
"chars": 2147,
"preview": "import React from 'react';\nimport { Box, GridItem, UnorderedList, useDisclosure } from '@chakra-ui/react';\nimport { useP"
},
{
"path": "web/src/components/layouts/guild/GuildList.tsx",
"chars": 1902,
"preview": "import React from 'react';\nimport { Box, Divider, Flex, GridItem, UnorderedList, useDisclosure } from '@chakra-ui/react'"
},
{
"path": "web/src/components/layouts/guild/MemberList.tsx",
"chars": 1776,
"preview": "import React from 'react';\nimport { GridItem, UnorderedList } from '@chakra-ui/react';\nimport { useParams } from 'react-"
},
{
"path": "web/src/components/layouts/guild/VoiceChat.tsx",
"chars": 4158,
"preview": "import { Box, Flex, Icon, ListItem, Text } from '@chakra-ui/react';\nimport React from 'react';\nimport { FaVolumeUp } fro"
},
{
"path": "web/src/components/layouts/guild/chat/ChatGrid.tsx",
"chars": 483,
"preview": "import React from 'react';\nimport { GridItem } from '@chakra-ui/react';\nimport { scrollbarCss } from '../../../../lib/ut"
},
{
"path": "web/src/components/layouts/guild/chat/ChatScreen.tsx",
"chars": 3280,
"preview": "import React, { useState } from 'react';\nimport { Box, Flex, Spinner } from '@chakra-ui/react';\nimport InfiniteScroll fr"
},
{
"path": "web/src/components/layouts/guild/chat/FileUploadButton.tsx",
"chars": 3538,
"preview": "import {\n Icon,\n InputLeftElement,\n Modal,\n ModalBody,\n ModalCloseButton,\n ModalContent,\n ModalHeader,\n ModalOve"
},
{
"path": "web/src/components/layouts/guild/chat/MessageInput.tsx",
"chars": 4582,
"preview": "import React, { useRef, useState } from 'react';\nimport { Flex, GridItem, InputGroup, Text, Textarea } from '@chakra-ui/"
},
{
"path": "web/src/components/layouts/guild/css/ChannelScrollerCSS.ts",
"chars": 249,
"preview": "export const channelScrollbarCss = {\n '&::-webkit-scrollbar': {\n width: '4px',\n },\n '&::-webkit-scrollbar-track': "
},
{
"path": "web/src/components/layouts/guild/css/GuildScrollerCSS.ts",
"chars": 87,
"preview": "export const guildScrollbarCss = {\n '&::-webkit-scrollbar': {\n width: '0',\n },\n};\n"
},
{
"path": "web/src/components/layouts/guild/css/MemberScrollerCSS.ts",
"chars": 248,
"preview": "export const memberScrollbarCss = {\n '&::-webkit-scrollbar': {\n width: '4px',\n },\n '&::-webkit-scrollbar-track': {"
},
{
"path": "web/src/components/layouts/guild/css/MessageInput.css",
"chars": 1046,
"preview": ".typing-indicator {\n border-radius: 50px;\n display: table;\n position: relative;\n -webkit-animation: 2s bulge infinit"
},
{
"path": "web/src/components/layouts/home/DMHeader.tsx",
"chars": 946,
"preview": "import React from 'react';\nimport { Box, Flex, GridItem, Icon, Text } from '@chakra-ui/react';\nimport { FaAt } from 'rea"
},
{
"path": "web/src/components/layouts/home/DMSidebar.tsx",
"chars": 1570,
"preview": "import React from 'react';\nimport { GridItem, Box, Text, UnorderedList } from '@chakra-ui/react';\nimport { useQuery } fr"
},
{
"path": "web/src/components/layouts/home/css/dmScrollerCSS.ts",
"chars": 243,
"preview": "export const dmScrollerCss = {\n '&::-webkit-scrollbar': {\n width: '4px',\n },\n '&::-webkit-scrollbar-track': {\n "
},
{
"path": "web/src/components/layouts/home/dashboard/FriendsDashboard.tsx",
"chars": 776,
"preview": "import React from 'react';\nimport { GridItem } from '@chakra-ui/react';\nimport { FriendsListHeader } from './FriendsList"
},
{
"path": "web/src/components/layouts/home/dashboard/FriendsList.tsx",
"chars": 1104,
"preview": "import React from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { Flex, Text, UnorderedList } from '"
},
{
"path": "web/src/components/layouts/home/dashboard/FriendsListHeader.tsx",
"chars": 2183,
"preview": "import React from 'react';\nimport { Button, Flex, GridItem, Icon, LightMode, Text, useDisclosure } from '@chakra-ui/reac"
},
{
"path": "web/src/components/layouts/home/dashboard/PendingList.tsx",
"chars": 1329,
"preview": "import React, { useEffect } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { Flex, UnorderedList"
},
{
"path": "web/src/components/menus/GuildMenu.tsx",
"chars": 3539,
"preview": "import React from 'react';\nimport { Flex, GridItem, Heading, Icon, Menu, MenuButton, MenuDivider, useDisclosure } from '"
},
{
"path": "web/src/components/menus/MemberContextMenu.tsx",
"chars": 2984,
"preview": "import React, { useState } from 'react';\nimport { Divider, Flex, Text, useDisclosure } from '@chakra-ui/react';\nimport {"
},
{
"path": "web/src/components/menus/StyledMenuItem.tsx",
"chars": 898,
"preview": "import React from 'react';\nimport { Flex, Icon, MenuItem, Text } from '@chakra-ui/react';\nimport { IconType } from 'reac"
},
{
"path": "web/src/components/menus/StyledMenuList.tsx",
"chars": 267,
"preview": "import { MenuList } from '@chakra-ui/react';\nimport React from 'react';\n\ninterface IProps {\n children: React.ReactNode;"
},
{
"path": "web/src/components/modals/AddFriendModal.tsx",
"chars": 4140,
"preview": "import React from 'react';\nimport {\n Button,\n Input,\n InputGroup,\n InputLeftAddon,\n InputRightElement,\n Modal,\n M"
},
{
"path": "web/src/components/modals/AddGuildModal.tsx",
"chars": 8029,
"preview": "import {\n Button,\n Divider,\n Modal,\n ModalBody,\n ModalCloseButton,\n ModalContent,\n ModalFooter,\n ModalHeader,\n "
},
{
"path": "web/src/components/modals/ChangePasswordModal.tsx",
"chars": 3547,
"preview": "import {\n Button,\n Modal,\n ModalBody,\n ModalCloseButton,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalOverla"
},
{
"path": "web/src/components/modals/ChannelSettingsModal.tsx",
"chars": 8837,
"preview": "import {\n Avatar,\n Box,\n Button,\n Divider,\n Flex,\n FormControl,\n FormLabel,\n LightMode,\n Modal,\n ModalBody,\n "
},
{
"path": "web/src/components/modals/CreateChannelModal.tsx",
"chars": 5875,
"preview": "import {\n Avatar,\n Box,\n Button,\n Flex,\n FormControl,\n FormLabel,\n Modal,\n ModalBody,\n ModalCloseButton,\n Moda"
},
{
"path": "web/src/components/modals/CropImageModal.tsx",
"chars": 2813,
"preview": "import {\n Box,\n Button,\n Modal,\n ModalBody,\n ModalCloseButton,\n ModalContent,\n ModalFooter,\n ModalHeader,\n Moda"
},
{
"path": "web/src/components/modals/DeleteMessageModal.tsx",
"chars": 2420,
"preview": "import {\n Avatar,\n Box,\n Button,\n Flex,\n LightMode,\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHea"
},
{
"path": "web/src/components/modals/EditMemberModal.tsx",
"chars": 4822,
"preview": "import {\n Button,\n Divider,\n Modal,\n ModalBody,\n ModalCloseButton,\n ModalContent,\n ModalFooter,\n ModalHeader,\n "
},
{
"path": "web/src/components/modals/EditMessageModal.tsx",
"chars": 2652,
"preview": "import {\n Avatar,\n Box,\n Button,\n Flex,\n Input,\n LightMode,\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n "
},
{
"path": "web/src/components/modals/GuildSettingsModal.tsx",
"chars": 12063,
"preview": "import {\n Avatar,\n Box,\n Button,\n Divider,\n Flex,\n IconButton,\n LightMode,\n Modal,\n ModalBody,\n ModalCloseButt"
},
{
"path": "web/src/components/modals/InviteModal.tsx",
"chars": 2988,
"preview": "import {\n Button,\n Checkbox,\n Input,\n InputGroup,\n InputRightElement,\n Modal,\n ModalBody,\n ModalCloseButton,\n M"
},
{
"path": "web/src/components/modals/ModActionModal.tsx",
"chars": 2260,
"preview": "import {\n Button,\n LightMode,\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalOverlay,\n Te"
},
{
"path": "web/src/components/modals/RemoveFriendModal.tsx",
"chars": 1873,
"preview": "import {\n Button,\n LightMode,\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalOverlay,\n Te"
},
{
"path": "web/src/components/sections/AddGuildIcon.tsx",
"chars": 1155,
"preview": "import React, { useState } from 'react';\nimport { Flex } from '@chakra-ui/react';\nimport { AiOutlinePlus } from 'react-i"
},
{
"path": "web/src/components/sections/DMPlaceholder.tsx",
"chars": 318,
"preview": "import React from 'react';\nimport { Box, Flex } from '@chakra-ui/react';\n\nexport const DMPlaceholder: React.FC = () => ("
},
{
"path": "web/src/components/sections/DateDivider.tsx",
"chars": 507,
"preview": "import { Divider, Flex, Text } from '@chakra-ui/react';\nimport React from 'react';\nimport { formatDivider } from '../../"
},
{
"path": "web/src/components/sections/Footer.tsx",
"chars": 1604,
"preview": "import React from 'react';\nimport { Box, Flex, Link, Stack, Text } from '@chakra-ui/react';\nimport { AiOutlineApi, AiOut"
},
{
"path": "web/src/components/sections/FriendsListButton.tsx",
"chars": 1211,
"preview": "import React from 'react';\nimport { Flex, Icon, Text } from '@chakra-ui/react';\nimport { FiUsers } from 'react-icons/fi'"
},
{
"path": "web/src/components/sections/GlobalState.tsx",
"chars": 2783,
"preview": "import React, { useEffect } from 'react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { userStore } f"
},
{
"path": "web/src/components/sections/Hero.tsx",
"chars": 1891,
"preview": "/* eslint-disable react/jsx-props-no-spreading */\nimport React from 'react';\nimport { Link } from 'react-router-dom';\nim"
}
]
// ... and 91 more files (download for full content)
About this extraction
This page contains the full source code of the sentrionic/Valkyrie GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 291 files (1.4 MB), approximately 391.0k tokens, and a symbol index with 888 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.