Full Code of benawad/dogehouse for AI

staging 584055ad407b cached
1345 files
3.1 MB
895.8k tokens
1734 symbols
1 requests
Download .txt
Showing preview only (3,549K chars total). Download the full file or copy to clipboard to get everything.
Repository: benawad/dogehouse
Branch: staging
Commit: 584055ad407b
Files: 1345
Total size: 3.1 MB

Directory structure:
gitextract_vaj6l7zt/

├── .devcontainer/
│   ├── Dockerfile
│   ├── devcontainer.json
│   ├── docker-compose.yml
│   └── scripts/
│       ├── environment.sh
│       ├── node.sh
│       └── user.sh
├── .dockerignore
├── .editorconfig
├── .eslintignore
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── labeler.yml
│   └── workflows/
│       ├── baklava-build_and_release.yaml
│       ├── dolma-npm_deploy.yaml
│       ├── global-label_pr.yml
│       ├── global-lint_commit_messages.yaml
│       ├── globalkey-npm_deploy.yaml
│       ├── kebab-npm_publish.yaml
│       ├── kibbeh-e2e_tests.yaml
│       ├── kibbeh-lint_and_test.yaml
│       ├── kousa-deploy_staging.yaml
│       ├── kousa-tests.yaml
│       └── shawarma-deploy_staging.yaml
├── .gitignore
├── .husky/
│   ├── .gitignore
│   ├── commit-msg
│   └── pre-commit
├── .prettierignore
├── .prettierrc.js
├── .vscode/
│   └── settings.json
├── .yarnrc.yml
├── CHANGELOG.md
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── CREATE_BOT_ACCOUNT.MD
├── DESIGN_GUIDELINES.md
├── FAQ.md
├── HOW_TO_DEBUG_AUDIO.md
├── HOW_TO_GET_PERMA_BANNED_FROM_DOGEHOUSE.md
├── LICENSE
├── README.md
├── SECURITY.md
├── baklava/
│   ├── .gitignore
│   ├── .yarnrc.yml
│   ├── README.md
│   ├── icons/
│   │   └── icon.icns
│   ├── locales/
│   │   └── en/
│   │       └── translate.json
│   ├── package.json
│   ├── resources/
│   │   ├── overlay/
│   │   │   ├── .gitignore
│   │   │   ├── .yarnrc.yml
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── public/
│   │   │   │   └── index.html
│   │   │   └── src/
│   │   │       ├── App.css
│   │   │       ├── App.js
│   │   │       ├── index.css
│   │   │       ├── index.js
│   │   │       └── reportWebVitals.js
│   │   └── splash/
│   │       └── splash-screen.html
│   ├── scripts/
│   │   ├── generateTranslationTypes.ts
│   │   ├── syncTranslations.ts
│   │   ├── traverseTranslations.ts
│   │   └── tsconfig.json
│   ├── settings/
│   │   └── entitlements.mac.plist
│   ├── src/
│   │   ├── constants.ts
│   │   ├── dev.ts
│   │   ├── electron.ts
│   │   ├── generated/
│   │   │   └── translationKeys.ts
│   │   ├── types.ts
│   │   └── utils/
│   │       ├── keybinds.ts
│   │       ├── notifications.ts
│   │       ├── overlay/
│   │       │   ├── index.ts
│   │       │   └── ipc.ts
│   │       ├── rpc/
│   │       │   ├── index.ts
│   │       │   └── ipc.ts
│   │       └── tray.ts
│   └── tsconfig.json
├── commitlint.config.js
├── dinner/
│   ├── .eslintrc.json
│   ├── .gitignore
│   ├── package.json
│   ├── src/
│   │   ├── create-accounts.ts
│   │   └── play-audio.ts
│   └── tsconfig.json
├── docker-compose.local.yml
├── docker-compose.prod.yml
├── docker-compose.yml
├── docs/
│   ├── Architecture/
│   │   └── README.md
│   ├── Directory/
│   │   └── README.md
│   ├── Elixir Api/
│   │   └── README.MD
│   ├── README.MD
│   ├── React Front End/
│   │   └── README.MD
│   └── Voice Server/
│       └── README.MD
├── dolma/
│   ├── .editorconfig
│   ├── .gitignore
│   ├── LICENSE
│   ├── README.md
│   ├── package.json
│   ├── src/
│   │   ├── index.ts
│   │   ├── lib/
│   │   │   ├── decode.ts
│   │   │   ├── encode.ts
│   │   │   ├── filterString.ts
│   │   │   ├── filterUnitoken.ts
│   │   │   └── msgToken.ts
│   │   ├── test/
│   │   │   ├── run.ts
│   │   │   └── tests/
│   │   │       └── encoding.ts
│   │   ├── tokens/
│   │   │   ├── index.ts
│   │   │   └── types/
│   │   │       ├── block.ts
│   │   │       ├── emoji.ts
│   │   │       ├── emote.ts
│   │   │       ├── link.ts
│   │   │       ├── mention.ts
│   │   │       └── text.ts
│   │   └── util/
│   │       ├── regex.ts
│   │       └── types/
│   │           └── tokenTypes.ts
│   └── tsconfig.json
├── globalkey/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── README.md
│   ├── index.d.ts
│   ├── package.json
│   ├── src/
│   │   ├── build.rs
│   │   └── lib.rs
│   └── test.js
├── kebab/
│   ├── .eslintrc.json
│   ├── .gitignore
│   ├── .prettierrc.js
│   ├── README.md
│   ├── examples/
│   │   ├── bot/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   └── index.ts
│   │   │   └── tsconfig.json
│   │   ├── chat/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   └── index.ts
│   │   │   └── tsconfig.json
│   │   ├── create-bot/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   └── index.ts
│   │   │   └── tsconfig.json
│   │   ├── mediasoup-audio/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── index.css
│   │   │   │   ├── index.html
│   │   │   │   └── index.ts
│   │   │   └── tsconfig.json
│   │   └── react-chat/
│   │       ├── README.md
│   │       ├── package.json
│   │       ├── public/
│   │       │   ├── index.html
│   │       │   ├── manifest.json
│   │       │   └── robots.txt
│   │       ├── src/
│   │       │   ├── App.css
│   │       │   ├── App.tsx
│   │       │   ├── index.css
│   │       │   ├── index.tsx
│   │       │   └── react-app-env.d.ts
│   │       └── tsconfig.json
│   ├── jest.config.js
│   ├── package.json
│   ├── src/
│   │   ├── README.md
│   │   ├── audio/
│   │   │   ├── audioWrapper.ts
│   │   │   ├── interface.ts
│   │   │   └── mediasoup-client.ts
│   │   ├── client/
│   │   │   ├── README.md
│   │   │   ├── http/
│   │   │   │   ├── bot.ts
│   │   │   │   ├── dev.ts
│   │   │   │   ├── endpoint.ts
│   │   │   │   └── index.ts
│   │   │   ├── index.ts
│   │   │   ├── requester/
│   │   │   │   ├── auth.ts
│   │   │   │   ├── chat.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── misc.ts
│   │   │   │   ├── room.ts
│   │   │   │   └── user.ts
│   │   │   ├── subscriber/
│   │   │   │   ├── index.ts
│   │   │   │   └── legacy.ts
│   │   │   └── type-util.ts
│   │   ├── entities.ts
│   │   ├── http/
│   │   │   ├── bot.ts
│   │   │   ├── index.ts
│   │   │   ├── raw.ts
│   │   │   └── wrapper.ts
│   │   ├── index.ts
│   │   ├── pagination.ts
│   │   ├── util/
│   │   │   ├── ast.test.ts
│   │   │   ├── ast.ts
│   │   │   └── index.ts
│   │   └── websocket/
│   │       ├── index.ts
│   │       ├── raw.ts
│   │       ├── responses.ts
│   │       └── wrapper.ts
│   └── tsconfig.json
├── kibbeh/
│   ├── .babelrc
│   ├── .eslintignore
│   ├── .eslintrc.json
│   ├── .gitignore
│   ├── .prettierignore
│   ├── .prettierrc.js
│   ├── .storybook/
│   │   ├── main.js
│   │   ├── manager.js
│   │   ├── preview-head.html
│   │   └── preview.js
│   ├── .stylelintrc.json
│   ├── README.md
│   ├── cypress/
│   │   ├── .gitignore
│   │   ├── fixtures/
│   │   │   └── example.json
│   │   ├── integration/
│   │   │   ├── create-scheduled-room.ts
│   │   │   ├── edit-profile.ts
│   │   │   ├── room-creator.ts
│   │   │   └── search.ts
│   │   ├── plugins/
│   │   │   ├── index.js
│   │   │   └── sample_spec.js
│   │   ├── support/
│   │   │   ├── commands.ts
│   │   │   ├── index.d.ts
│   │   │   ├── index.js
│   │   │   └── test-constants.ts
│   │   └── tsconfig.json
│   ├── cypress.json
│   ├── deploy.sh
│   ├── next-env.d.ts
│   ├── next.config.js
│   ├── package.json
│   ├── postcss.config.js
│   ├── public/
│   │   ├── locales/
│   │   │   ├── af/
│   │   │   │   └── translation.json
│   │   │   ├── am/
│   │   │   │   └── translation.json
│   │   │   ├── ar/
│   │   │   │   └── translation.json
│   │   │   ├── az/
│   │   │   │   └── translation.json
│   │   │   ├── bg/
│   │   │   │   └── translation.json
│   │   │   ├── bn/
│   │   │   │   └── translation.json
│   │   │   ├── bottom/
│   │   │   │   └── translation.json
│   │   │   ├── cs/
│   │   │   │   └── translation.json
│   │   │   ├── da/
│   │   │   │   └── translation.json
│   │   │   ├── de/
│   │   │   │   └── translation.json
│   │   │   ├── de-AT/
│   │   │   │   └── translation.json
│   │   │   ├── el/
│   │   │   │   └── translation.json
│   │   │   ├── en/
│   │   │   │   └── translation.json
│   │   │   ├── en-AU/
│   │   │   │   └── translation.json
│   │   │   ├── en-C/
│   │   │   │   ├── GUIDE.md
│   │   │   │   └── translation.json
│   │   │   ├── en-CODE/
│   │   │   │   └── translation.json
│   │   │   ├── en-LOLCAT/
│   │   │   │   └── translation.json
│   │   │   ├── en-OWO/
│   │   │   │   └── translation.json
│   │   │   ├── en-PIGLATIN/
│   │   │   │   └── translation.json
│   │   │   ├── en-PIRATE/
│   │   │   │   └── translation.json
│   │   │   ├── eo/
│   │   │   │   └── translation.json
│   │   │   ├── es/
│   │   │   │   └── translation.json
│   │   │   ├── et/
│   │   │   │   └── translation.json
│   │   │   ├── eu/
│   │   │   │   └── translation.json
│   │   │   ├── fa/
│   │   │   │   └── translation.json
│   │   │   ├── fi/
│   │   │   │   └── translation.json
│   │   │   ├── fr/
│   │   │   │   └── translation.json
│   │   │   ├── grc/
│   │   │   │   └── translation.json
│   │   │   ├── gsw/
│   │   │   │   └── translation.json
│   │   │   ├── he/
│   │   │   │   └── translation.json
│   │   │   ├── hi/
│   │   │   │   └── translation.json
│   │   │   ├── hr/
│   │   │   │   └── translation.json
│   │   │   ├── hu/
│   │   │   │   └── translation.json
│   │   │   ├── id/
│   │   │   │   └── translation.json
│   │   │   ├── is/
│   │   │   │   └── translation.json
│   │   │   ├── it/
│   │   │   │   └── translation.json
│   │   │   ├── ja/
│   │   │   │   └── translation.json
│   │   │   ├── kk/
│   │   │   │   └── translation.json
│   │   │   ├── ko/
│   │   │   │   └── translation.json
│   │   │   ├── ku/
│   │   │   │   └── translation.json
│   │   │   ├── li/
│   │   │   │   └── translation.json
│   │   │   ├── lld/
│   │   │   │   └── translation.json
│   │   │   ├── lt/
│   │   │   │   └── translation.json
│   │   │   ├── lv/
│   │   │   │   └── translation.json
│   │   │   ├── nb/
│   │   │   │   └── translation.json
│   │   │   ├── ne/
│   │   │   │   └── translation.json
│   │   │   ├── nl/
│   │   │   │   └── translation.json
│   │   │   ├── pl/
│   │   │   │   └── translation.json
│   │   │   ├── pt-BR/
│   │   │   │   └── translation.json
│   │   │   ├── pt-PT/
│   │   │   │   └── translation.json
│   │   │   ├── ro/
│   │   │   │   └── translation.json
│   │   │   ├── ru/
│   │   │   │   └── translation.json
│   │   │   ├── sa/
│   │   │   │   └── translation.json
│   │   │   ├── si/
│   │   │   │   └── translation.json
│   │   │   ├── sk/
│   │   │   │   └── translation.json
│   │   │   ├── sl/
│   │   │   │   └── translation.json
│   │   │   ├── so/
│   │   │   │   └── translation.json
│   │   │   ├── sq/
│   │   │   │   └── translation.json
│   │   │   ├── sr/
│   │   │   │   └── translation.json
│   │   │   ├── sr-LATIN/
│   │   │   │   └── translation.json
│   │   │   ├── sv/
│   │   │   │   └── translation.json
│   │   │   ├── ta/
│   │   │   │   └── translation.json
│   │   │   ├── te/
│   │   │   │   └── translation.json
│   │   │   ├── th/
│   │   │   │   └── translation.json
│   │   │   ├── tl/
│   │   │   │   └── translation.json
│   │   │   ├── tp/
│   │   │   │   └── translation.json
│   │   │   ├── tr/
│   │   │   │   └── translation.json
│   │   │   ├── uk/
│   │   │   │   └── translation.json
│   │   │   ├── ur/
│   │   │   │   └── translation.json
│   │   │   ├── uz/
│   │   │   │   └── translation.json
│   │   │   ├── vi/
│   │   │   │   └── translation.json
│   │   │   ├── zh-CN/
│   │   │   │   └── translation.json
│   │   │   └── zh-TW/
│   │   │       └── translation.json
│   │   ├── manifest.json
│   │   ├── privacy-policy.html
│   │   └── terms.html
│   ├── scripts/
│   │   ├── syncTranslations.ts
│   │   ├── traverseTranslations.ts
│   │   └── tsconfig.json
│   ├── src/
│   │   ├── form-fields/
│   │   │   ├── FieldSpacer.tsx
│   │   │   └── InputField.tsx
│   │   ├── global-stores/
│   │   │   ├── useAccountOverlay.ts
│   │   │   ├── useAskForMicStore.ts
│   │   │   ├── useAudioTracks.ts
│   │   │   ├── useCurrentRoomIdStore.ts
│   │   │   ├── useDeafStore.ts
│   │   │   ├── useDebugAudio.ts
│   │   │   ├── useDownloadAlertStore.ts
│   │   │   ├── useElectronMobileStore.ts
│   │   │   ├── useEmojiPickerStore.ts
│   │   │   ├── useGlobalVolumeStore.ts
│   │   │   ├── useHostStore.ts
│   │   │   ├── useKeyMapStore.ts
│   │   │   ├── useMicPermErrorStore.ts
│   │   │   ├── useMuteStore.ts
│   │   │   ├── useOverlayStore.ts
│   │   │   ├── useProducerStore.ts
│   │   │   ├── useRoomChatMentionStore.ts
│   │   │   ├── useSocketStatus.ts
│   │   │   └── useStatus.ts
│   │   ├── globals.d.ts
│   │   ├── icons/
│   │   │   ├── BotIcon.tsx
│   │   │   ├── DeveloperIcon.tsx
│   │   │   ├── LgLogo.tsx
│   │   │   ├── Link.tsx
│   │   │   ├── LogoIcon.tsx
│   │   │   ├── MacCloseIcon.tsx
│   │   │   ├── MacMaximizeIcon.tsx
│   │   │   ├── MacMinimizeIcon.tsx
│   │   │   ├── OutlineGlobe.tsx
│   │   │   ├── Share.tsx
│   │   │   ├── Smiley.tsx
│   │   │   ├── SolidBug.tsx
│   │   │   ├── SolidCalendar.tsx
│   │   │   ├── SolidCaretRight.tsx
│   │   │   ├── SolidChatBubble.tsx
│   │   │   ├── SolidCompass.tsx
│   │   │   ├── SolidContributor.tsx
│   │   │   ├── SolidDeafened.tsx
│   │   │   ├── SolidDeafenedOff.tsx
│   │   │   ├── SolidDiscord.tsx
│   │   │   ├── SolidDogenitro.tsx
│   │   │   ├── SolidDownload.tsx
│   │   │   ├── SolidFriends.tsx
│   │   │   ├── SolidFriendsAdd.tsx
│   │   │   ├── SolidFullscreen.tsx
│   │   │   ├── SolidGitHub.tsx
│   │   │   ├── SolidGoogle.tsx
│   │   │   ├── SolidHelp.tsx
│   │   │   ├── SolidHome.tsx
│   │   │   ├── SolidInstagram.tsx
│   │   │   ├── SolidKeyboard.tsx
│   │   │   ├── SolidLink.tsx
│   │   │   ├── SolidLogOut.tsx
│   │   │   ├── SolidMegaphone.tsx
│   │   │   ├── SolidMessages.tsx
│   │   │   ├── SolidMicrophone.tsx
│   │   │   ├── SolidMicrophoneOff.tsx
│   │   │   ├── SolidMoon.tsx
│   │   │   ├── SolidNew.tsx
│   │   │   ├── SolidNotification.tsx
│   │   │   ├── SolidPersonAdd.tsx
│   │   │   ├── SolidPlus.tsx
│   │   │   ├── SolidRocket.tsx
│   │   │   ├── SolidSearch.tsx
│   │   │   ├── SolidSettings.tsx
│   │   │   ├── SolidSimpleMegaphone.tsx
│   │   │   ├── SolidStaff.tsx
│   │   │   ├── SolidTime.tsx
│   │   │   ├── SolidTrash.tsx
│   │   │   ├── SolidTwitter.tsx
│   │   │   ├── SolidUser.tsx
│   │   │   ├── SolidVolume.tsx
│   │   │   ├── SolidVolumeOff.tsx
│   │   │   ├── SolidWarning.tsx
│   │   │   ├── WinCloseIcon.tsx
│   │   │   ├── WinMaximizeIcon.tsx
│   │   │   ├── WinMinimizeIcon.tsx
│   │   │   ├── badges/
│   │   │   │   ├── ContributorBadge.tsx
│   │   │   │   ├── StaffBadge.tsx
│   │   │   │   └── index.tsx
│   │   │   └── index.tsx
│   │   ├── jest.config.js
│   │   ├── lib/
│   │   │   ├── constants.ts
│   │   │   ├── createChatMessage.ts
│   │   │   ├── defaultQueryFn.ts
│   │   │   ├── i18n.ts
│   │   │   ├── isCurrentRoomId.ts
│   │   │   ├── isServer.ts
│   │   │   ├── isWebRTCEnabled.ts
│   │   │   ├── kFormatter.ts
│   │   │   ├── queryClient.ts
│   │   │   ├── roomToCurrentRoom.ts
│   │   │   ├── showErrorToast.ts
│   │   │   ├── tests/
│   │   │   │   ├── constants.test.ts
│   │   │   │   └── kFormatter.test.ts
│   │   │   └── validateStruct.ts
│   │   ├── modules/
│   │   │   ├── admin/
│   │   │   │   ├── AdminPage.tsx
│   │   │   │   └── AdminPageForm.tsx
│   │   │   ├── auth/
│   │   │   │   ├── WaitForWsAndAuth.tsx
│   │   │   │   ├── useSaveTokensFromQueryParams.ts
│   │   │   │   ├── useTokenStore.ts
│   │   │   │   └── useVerifyLoggedIn.ts
│   │   │   ├── dashboard/
│   │   │   │   ├── CreateRoomModal.tsx
│   │   │   │   ├── DashboardPage.tsx
│   │   │   │   ├── FeedController.tsx
│   │   │   │   ├── FollowingOnlineController.tsx
│   │   │   │   ├── MinimizedRoomCardController.tsx
│   │   │   │   └── ProfileBlockController.tsx
│   │   │   ├── debugging/
│   │   │   │   ├── AudioDebugAvatar.tsx
│   │   │   │   └── AudioDebugPanel.tsx
│   │   │   ├── developer/
│   │   │   │   ├── Bot.tsx
│   │   │   │   ├── BotCard.tsx
│   │   │   │   ├── BotIcon.tsx
│   │   │   │   ├── BotInfo.tsx
│   │   │   │   ├── BotsEditPage.tsx
│   │   │   │   ├── BotsPage.tsx
│   │   │   │   ├── CreateBotModal.tsx
│   │   │   │   ├── DeveloperNavButton.tsx
│   │   │   │   ├── DeveloperPanel.tsx
│   │   │   │   ├── EditBot.tsx
│   │   │   │   └── YourBots.tsx
│   │   │   ├── display/
│   │   │   │   ├── HeaderController.tsx
│   │   │   │   └── TextParser.tsx
│   │   │   ├── errors/
│   │   │   │   ├── ErrorToastController.tsx
│   │   │   │   └── useErrorToastStore.tsx
│   │   │   ├── keyboard-shortcuts/
│   │   │   │   ├── ChatKeybind.tsx
│   │   │   │   ├── DeafKeybind.tsx
│   │   │   │   ├── InviteKeybind.tsx
│   │   │   │   ├── KeybindListener.tsx
│   │   │   │   ├── MuteKeybind.tsx
│   │   │   │   ├── OverlayKeybind.tsx
│   │   │   │   ├── PTTKeybind.tsx
│   │   │   │   ├── RequestToSpeakKeybind.tsx
│   │   │   │   └── index.ts
│   │   │   ├── landing-page/
│   │   │   │   └── LoginPage.tsx
│   │   │   ├── language/
│   │   │   │   └── LanguagePage.tsx
│   │   │   ├── layouts/
│   │   │   │   ├── DefaultDesktopLayout.tsx
│   │   │   │   ├── ElectronHeader.tsx
│   │   │   │   ├── FloatingRoomInfo.tsx
│   │   │   │   ├── GridPanels.tsx
│   │   │   │   ├── MainLayout.tsx
│   │   │   │   └── TabletSidebar.tsx
│   │   │   ├── room/
│   │   │   │   ├── AudioDebugConsumerSection.tsx
│   │   │   │   ├── BlockedFromRoomUsers.tsx
│   │   │   │   ├── InviteRoomPage.tsx
│   │   │   │   ├── RoomChatController.tsx
│   │   │   │   ├── RoomOpenGraphPreview.tsx
│   │   │   │   ├── RoomPage.tsx
│   │   │   │   ├── RoomPanelController.tsx
│   │   │   │   ├── RoomPanelIconBarController.tsx
│   │   │   │   ├── RoomSettingModal.tsx
│   │   │   │   ├── RoomUsersPanel.tsx
│   │   │   │   ├── UserPreviewModal.tsx
│   │   │   │   ├── UserPreviewModalProvider.tsx
│   │   │   │   ├── ViewScheduledRoomPage.tsx
│   │   │   │   ├── VolumeSliderController.tsx
│   │   │   │   ├── chat/
│   │   │   │   │   ├── Emote.tsx
│   │   │   │   │   ├── EmoteData.ts
│   │   │   │   │   ├── RoomChat.tsx
│   │   │   │   │   ├── RoomChatInput.tsx
│   │   │   │   │   ├── RoomChatList.tsx
│   │   │   │   │   ├── RoomChatMentions.tsx
│   │   │   │   │   ├── navigateThroughQueriedEmojis.ts
│   │   │   │   │   ├── navigateThroughQueriedUsers.ts
│   │   │   │   │   ├── useRoomChatMentionStore.ts
│   │   │   │   │   └── useRoomChatStore.ts
│   │   │   │   ├── mobile/
│   │   │   │   │   └── RoomOverlay.tsx
│   │   │   │   ├── useGetRoomByQueryParam.ts
│   │   │   │   ├── useResize.ts
│   │   │   │   └── useSplitUsersIntoSections.tsx
│   │   │   ├── scheduled-rooms/
│   │   │   │   ├── AddToCalendar.tsx
│   │   │   │   ├── CopyScheduleRoomLinkButton.tsx
│   │   │   │   ├── CreateScheduledRoomModal.tsx
│   │   │   │   ├── EditScheduleRoomModalController.tsx
│   │   │   │   ├── ScheduledRoomCard.tsx
│   │   │   │   ├── ScheduledRoomsList.tsx
│   │   │   │   ├── ScheduledRoomsPage.tsx
│   │   │   │   ├── copyToClipboard.ts
│   │   │   │   └── makeUrls.ts
│   │   │   ├── search/
│   │   │   │   ├── SearchBarController.tsx
│   │   │   │   └── SearchPage.tsx
│   │   │   ├── settings/
│   │   │   │   ├── OverlaySettingsPage.tsx
│   │   │   │   ├── PrivacySettingForm.tsx
│   │   │   │   ├── PrivacySettingsPage.tsx
│   │   │   │   ├── SoundEffectSettingsPage.tsx
│   │   │   │   └── VoiceSettingsPage.tsx
│   │   │   ├── sound-effects/
│   │   │   │   ├── SoundEffectPlayer.tsx
│   │   │   │   └── useSoundEffectStore.ts
│   │   │   ├── user/
│   │   │   │   ├── EditProfileModal.tsx
│   │   │   │   ├── FollowingController.tsx
│   │   │   │   ├── FollowingOnlinePage.tsx
│   │   │   │   ├── FollowingPage.tsx
│   │   │   │   ├── UserPage.tsx
│   │   │   │   ├── UserProfileController.tsx
│   │   │   │   └── VerticalUserInfoWithFollowButton.tsx
│   │   │   ├── webrtc/
│   │   │   │   ├── WebRtcApp.tsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── ActiveSpeakerListener.tsx
│   │   │   │   │   ├── AudioRender.tsx
│   │   │   │   │   └── MicPicker.tsx
│   │   │   │   ├── stores/
│   │   │   │   │   ├── useAskForMicStore.ts
│   │   │   │   │   ├── useAudioTracks.ts
│   │   │   │   │   ├── useConsumerStore.ts
│   │   │   │   │   ├── useMicIdStore.ts
│   │   │   │   │   ├── useMicPermErrorStore.ts
│   │   │   │   │   ├── useProducerStore.ts
│   │   │   │   │   ├── useSocketStatus.ts
│   │   │   │   │   ├── useStatus.ts
│   │   │   │   │   └── useVoiceStore.ts
│   │   │   │   ├── types.ts
│   │   │   │   └── utils/
│   │   │   │       ├── consumeAudio.ts
│   │   │   │       ├── createTransport.ts
│   │   │   │       ├── joinRoom.ts
│   │   │   │       ├── mergeRoomPermission.ts
│   │   │   │       ├── receiveVoice.ts
│   │   │   │       └── sendVoice.ts
│   │   │   └── ws/
│   │   │       └── WebSocketProvider.tsx
│   │   ├── pages/
│   │   │   ├── 404.tsx
│   │   │   ├── _app.tsx
│   │   │   ├── admin.tsx
│   │   │   ├── connection-taken.tsx
│   │   │   ├── dash.tsx
│   │   │   ├── developer/
│   │   │   │   └── bots/
│   │   │   │       ├── edit/
│   │   │   │       │   └── [username]/
│   │   │   │       │       └── index.tsx
│   │   │   │       └── index.tsx
│   │   │   ├── download.tsx
│   │   │   ├── index.tsx
│   │   │   ├── language.tsx
│   │   │   ├── logout.tsx
│   │   │   ├── overlay-settings.tsx
│   │   │   ├── privacy-settings.tsx
│   │   │   ├── room/
│   │   │   │   └── [id]/
│   │   │   │       ├── index.tsx
│   │   │   │       └── invite.tsx
│   │   │   ├── scheduled-room/
│   │   │   │   └── [id].tsx
│   │   │   ├── scheduled-rooms.tsx
│   │   │   ├── search.tsx
│   │   │   ├── sound-effect-settings.tsx
│   │   │   ├── u/
│   │   │   │   └── [username]/
│   │   │   │       ├── followers.tsx
│   │   │   │       ├── following-online.tsx
│   │   │   │       ├── following.tsx
│   │   │   │       └── index.tsx
│   │   │   └── voice-settings.tsx
│   │   ├── shared-components/
│   │   │   ├── ApiPreloadLink.tsx
│   │   │   ├── ConfirmModal.tsx
│   │   │   └── InvitedToJoinRoomModal.tsx
│   │   ├── shared-hooks/
│   │   │   ├── useBoundingClientRect.ts
│   │   │   ├── useConn.ts
│   │   │   ├── useCurrentRoomFromCache.ts
│   │   │   ├── useCurrentRoomId.ts
│   │   │   ├── useCurrentRoomInfo.ts
│   │   │   ├── useDevices.ts
│   │   │   ├── useIntersectionObserver.ts
│   │   │   ├── useLeaveRoom.ts
│   │   │   ├── useMainWsHandler.tsx
│   │   │   ├── useOnClickOutside.tsx
│   │   │   ├── usePageVisibility.ts
│   │   │   ├── useScreenType.ts
│   │   │   ├── useScreenWakeLockStore.ts
│   │   │   ├── useSetDeaf.ts
│   │   │   ├── useSetMute.ts
│   │   │   ├── useTypeSafeMutation.ts
│   │   │   ├── useTypeSafePrefetch.ts
│   │   │   ├── useTypeSafeQuery.ts
│   │   │   ├── useTypeSafeTranslation.ts
│   │   │   ├── useTypeSafeUpdateQuery.ts
│   │   │   ├── useViewportSize.ts
│   │   │   └── useWindowSize.ts
│   │   ├── stories/
│   │   │   ├── AccountOverlay.story.tsx
│   │   │   ├── BaseDropdownSm.story.tsx
│   │   │   ├── BaseOverlay.story.tsx
│   │   │   ├── BaseSettingsItem.story.tsx
│   │   │   ├── BoxedIcon.story.tsx
│   │   │   ├── BubbleText.story.tsx
│   │   │   ├── Button.story.tsx
│   │   │   ├── ChangeAvatarCard.story.tsx
│   │   │   ├── ChangeBannerCard.story.tsx
│   │   │   ├── ErrorButtonItem.story.tsx
│   │   │   ├── ErrorToast.story.tsx
│   │   │   ├── FriendsOnline.story.tsx
│   │   │   ├── KeybindCard.story.tsx
│   │   │   ├── LeftHeader.story.tsx
│   │   │   ├── MessageElement.story.tsx
│   │   │   ├── MessagesDropdown.story.tsx
│   │   │   ├── MiddleHeader.story.tsx
│   │   │   ├── MinimizedRoomCard.story.tsx
│   │   │   ├── MobileHeader/
│   │   │   │   ├── PageHeader.story.tsx
│   │   │   │   ├── ProfileHeader.story.tsx
│   │   │   │   └── SearchHeader.story.tsx
│   │   │   ├── MobileNav.story.tsx
│   │   │   ├── NativeCheckbox.story.tsx
│   │   │   ├── NativeRadio.story.tsx
│   │   │   ├── NotificationElement/
│   │   │   │   ├── FollowNotification.story.tsx
│   │   │   │   ├── GenericNotification.story.tsx
│   │   │   │   ├── LiveNotification.story.tsx
│   │   │   │   └── NewRoomNotification.story.tsx
│   │   │   ├── NotificationsDropdown.story.tsx
│   │   │   ├── ProfileAbout.story.tsx
│   │   │   ├── ProfileBlock.story.tsx
│   │   │   ├── ProfileHeader.story.tsx
│   │   │   ├── ProfileHeaderWrapper.story.tsx
│   │   │   ├── ProfileTabs.story.tsx
│   │   │   ├── RightHeader.story.tsx
│   │   │   ├── RoomAvatar.story.tsx
│   │   │   ├── RoomCard.story.tsx
│   │   │   ├── RoomCardHeading.story.tsx
│   │   │   ├── RoomCardParticipants.story.tsx
│   │   │   ├── RoomHeader.story.tsx
│   │   │   ├── RoomPanelIconBar.story.tsx
│   │   │   ├── RoomSectionHeader.story.tsx
│   │   │   ├── Search/
│   │   │   │   ├── GlobalSearch.story.tsx
│   │   │   │   ├── SearchBar.story.tsx
│   │   │   │   ├── SearchHistory.story.tsx
│   │   │   │   ├── SearchOverlay.story.tsx
│   │   │   │   └── SearchResult/
│   │   │   │       ├── RoomSearchResult.story.tsx
│   │   │   │       └── UserSearchResult.story.tsx
│   │   │   ├── SettingsDropdown.story.tsx
│   │   │   ├── SettingsIcon.story.tsx
│   │   │   ├── SettingsItemButton.story.tsx
│   │   │   ├── SettingsWrapper.story.tsx
│   │   │   ├── Tag.story.tsx
│   │   │   ├── UpcomingRoomCardLg.story.tsx
│   │   │   ├── UpcomingRoomsCard.story.tsx
│   │   │   ├── UserAvatar/
│   │   │   │   ├── MultipleUsers.story.tsx
│   │   │   │   └── SingleUser.story.tsx
│   │   │   ├── UserBadge.story.tsx
│   │   │   ├── UserBadgeLg.story.tsx
│   │   │   ├── UserSummaryCard.story.tsx
│   │   │   ├── UserWideButton.story.tsx
│   │   │   ├── VerticalUserInfo.story.tsx
│   │   │   ├── VolumeIndicator.story.tsx
│   │   │   ├── data/
│   │   │   │   └── BaseUser.tsx
│   │   │   ├── mobile/
│   │   │   │   ├── FeaturedRoomCardAvatars.story.tsx
│   │   │   │   └── FeaturedRoomCardHosts.story.tsx
│   │   │   └── utils/
│   │   │       ├── GbFlagIcon.tsx
│   │   │       ├── toBoolean.ts
│   │   │       ├── toEnum.ts
│   │   │       └── toStr.ts
│   │   ├── styles/
│   │   │   ├── banner-button.css
│   │   │   ├── date-time-picker.css
│   │   │   ├── electron-header.css
│   │   │   └── globals.css
│   │   ├── types/
│   │   │   ├── PageComponent.ts
│   │   │   ├── index.d.ts
│   │   │   ├── overrides-mui.d.ts
│   │   │   ├── user.d.ts
│   │   │   ├── util-types.ts
│   │   │   └── wakeLock.d.ts
│   │   └── ui/
│   │       ├── Banner.tsx
│   │       ├── BannerButton.tsx
│   │       ├── BaseDropdownSm.tsx
│   │       ├── BaseOverlay.tsx
│   │       ├── BaseSettingsItem.tsx
│   │       ├── BoxedIcon.tsx
│   │       ├── BubbleText.tsx
│   │       ├── Button.tsx
│   │       ├── ButtonLink.tsx
│   │       ├── CenterLoader.tsx
│   │       ├── ChangeAvatarCard.tsx
│   │       ├── ChangeBannerCard.tsx
│   │       ├── DropdownController.tsx
│   │       ├── DurationTicker.tsx
│   │       ├── EmojiPicker.tsx
│   │       ├── ErrorButtonItem.tsx
│   │       ├── ErrorMessageButton.tsx
│   │       ├── ErrorToast.tsx
│   │       ├── FeedHeader.tsx
│   │       ├── FollowersOnline.tsx
│   │       ├── GridPanel.tsx
│   │       ├── InfoText.tsx
│   │       ├── Input.tsx
│   │       ├── InputErrorMsg.tsx
│   │       ├── KeybindCard.tsx
│   │       ├── LanguageSearch.tsx
│   │       ├── LanguageSelector.tsx
│   │       ├── MacButton.tsx
│   │       ├── MainGrid.tsx
│   │       ├── MessageElement.tsx
│   │       ├── MessagesDropdown.tsx
│   │       ├── MinimizedRoomCard.tsx
│   │       ├── Modal.tsx
│   │       ├── NativeCheckbox.tsx
│   │       ├── NativeRadio.tsx
│   │       ├── NativeSelect.tsx
│   │       ├── NotificationElement/
│   │       │   ├── FollowNotification.tsx
│   │       │   ├── GenericNotification.tsx
│   │       │   ├── LiveNotification.tsx
│   │       │   ├── NewRoomNotification.tsx
│   │       │   └── index.tsx
│   │       ├── NotificationsDropdown.tsx
│   │       ├── ProfileAbout.tsx
│   │       ├── ProfileAdmin.tsx
│   │       ├── ProfileBlock.tsx
│   │       ├── ProfileHeader.tsx
│   │       ├── ProfileHeaderWrapper.tsx
│   │       ├── ProfileScheduled.tsx
│   │       ├── ProfileTabs.tsx
│   │       ├── RoomAvatar.tsx
│   │       ├── RoomCard.tsx
│   │       ├── RoomCardHeading.tsx
│   │       ├── RoomCardParticipants.tsx
│   │       ├── RoomHeader.tsx
│   │       ├── RoomPanelIconBar.tsx
│   │       ├── RoomSectionHeader.tsx
│   │       ├── Search/
│   │       │   ├── GlobalSearch.tsx
│   │       │   ├── SearchBar.tsx
│   │       │   ├── SearchHistory.tsx
│   │       │   ├── SearchOverlay.tsx
│   │       │   └── SearchResult/
│   │       │       ├── RoomSearchResult.tsx
│   │       │       ├── UserSearchResult.tsx
│   │       │       └── index.ts
│   │       ├── SettingsDropdown.tsx
│   │       ├── SettingsIcon.tsx
│   │       ├── SettingsItemButton.tsx
│   │       ├── SettingsWrapper.tsx
│   │       ├── Spinner.tsx
│   │       ├── Tag.tsx
│   │       ├── Toast.tsx
│   │       ├── Twemoji.tsx
│   │       ├── UpcomingRoomCardLg.tsx
│   │       ├── UpcomingRoomsCard.tsx
│   │       ├── UserAvatar/
│   │       │   ├── MultipleUsers.tsx
│   │       │   ├── SingleUser.tsx
│   │       │   ├── index.ts
│   │       │   └── tests/
│   │       │       ├── MultipleUser.spec.tsx
│   │       │       ├── SingleUser.spec.tsx
│   │       │       └── __snapshots__/
│   │       │           ├── MultipleUser.spec.tsx.snap
│   │       │           └── SingleUser.spec.tsx.snap
│   │       ├── UserBadge.tsx
│   │       ├── UserBadgeLg.tsx
│   │       ├── UserProfile.tsx
│   │       ├── UserSummaryCard.tsx
│   │       ├── UserWideButton.tsx
│   │       ├── VerticalUserInfo.tsx
│   │       ├── VolumeIndicator.tsx
│   │       ├── VolumeSlider.tsx
│   │       ├── WinButton.tsx
│   │       ├── header/
│   │       │   ├── LeftHeader.tsx
│   │       │   ├── MiddleHeader.tsx
│   │       │   └── RightHeader.tsx
│   │       ├── mobile/
│   │       │   ├── AccountOverlay.tsx
│   │       │   ├── FeaturedRoomCardAvatars.tsx
│   │       │   ├── FeaturedRoomCardHosts.tsx
│   │       │   ├── MobileHeader/
│   │       │   │   ├── PageHeader.tsx
│   │       │   │   ├── ProfileHeader.tsx
│   │       │   │   ├── SearchHeader.tsx
│   │       │   │   └── index.tsx
│   │       │   └── MobileNav.tsx
│   │       └── tests/
│   │           ├── BaseOverlay.spec.tsx
│   │           ├── BoxedIcon.spec.tsx
│   │           ├── BubbleText.spec.tsx
│   │           ├── Button.spec.tsx
│   │           ├── ErrorMessageButton.spec.tsx
│   │           ├── ErrorToast.spec.tsx
│   │           ├── Input.spec.tsx
│   │           ├── InputErrorMsg.spec.tsx
│   │           ├── MainGrid.spec.tsx
│   │           ├── MessageElement.spec.tsx
│   │           ├── MessagesDropdown.spec.tsx
│   │           ├── MinimizedRoomCard.spec.tsx
│   │           └── __snapshots__/
│   │               ├── BaseOverlay.spec.tsx.snap
│   │               ├── BoxedIcon.spec.tsx.snap
│   │               ├── BubbleText.spec.tsx.snap
│   │               ├── Button.spec.tsx.snap
│   │               ├── ErrorMessageButton.spec.tsx.snap
│   │               ├── ErrorToast.spec.tsx.snap
│   │               ├── Input.spec.tsx.snap
│   │               ├── InputErrorMsg.spec.tsx.snap
│   │               ├── MainGrid.spec.tsx.snap
│   │               ├── MessageElement.spec.tsx.snap
│   │               └── MinimizedRoomCard.spec.tsx.snap
│   ├── tailwind.config.js
│   ├── test-utils.ts
│   └── tsconfig.json
├── kousa/
│   ├── .envrc
│   ├── .formatter.exs
│   ├── .gitignore
│   ├── ADDING_TO_MESSAGING_API.md
│   ├── ARCHITECTURE.md
│   ├── Dockerfile
│   ├── README.md
│   ├── ROADMAP.md
│   ├── config/
│   │   ├── config.exs
│   │   ├── dev.exs
│   │   ├── prod.exs
│   │   ├── releases.exs
│   │   └── test.exs
│   ├── deploy.sh
│   ├── lib/
│   │   ├── beef/
│   │   │   ├── _repo.ex
│   │   │   ├── access/
│   │   │   │   ├── rooms.ex
│   │   │   │   ├── user_blocks.ex
│   │   │   │   └── users.ex
│   │   │   ├── follows.ex
│   │   │   ├── mutations/
│   │   │   │   ├── rooms.ex
│   │   │   │   ├── user_blocks.ex
│   │   │   │   └── users.ex
│   │   │   ├── queries/
│   │   │   │   ├── rooms.ex
│   │   │   │   ├── user_blocks.ex
│   │   │   │   └── users.ex
│   │   │   ├── room_blocks.ex
│   │   │   ├── room_permissions.ex
│   │   │   ├── rooms.ex
│   │   │   ├── scheduled_rooms.ex
│   │   │   ├── schemas/
│   │   │   │   ├── attending_scheduled_room.ex
│   │   │   │   ├── follow.ex
│   │   │   │   ├── room.ex
│   │   │   │   ├── room_block.ex
│   │   │   │   ├── room_permission.ex
│   │   │   │   ├── scheduled_room.ex
│   │   │   │   ├── scheduled_room_cohost.ex
│   │   │   │   ├── user.ex
│   │   │   │   └── user_block.ex
│   │   │   ├── user_blocks.ex
│   │   │   └── users.ex
│   │   ├── broth/
│   │   │   ├── legacy_handler.ex
│   │   │   ├── message/
│   │   │   │   ├── _types/
│   │   │   │   │   ├── chat_token.ex
│   │   │   │   │   ├── chat_token_type.ex
│   │   │   │   │   ├── operator.ex
│   │   │   │   │   ├── relationship.ex
│   │   │   │   │   ├── room_auth.ex
│   │   │   │   │   └── room_role.ex
│   │   │   │   ├── auth/
│   │   │   │   │   └── request.ex
│   │   │   │   ├── call.ex
│   │   │   │   ├── cast.ex
│   │   │   │   ├── chat/
│   │   │   │   │   ├── ban.ex
│   │   │   │   │   ├── delete.ex
│   │   │   │   │   ├── send.ex
│   │   │   │   │   └── unban.ex
│   │   │   │   ├── manifest.ex
│   │   │   │   ├── misc/
│   │   │   │   │   └── search.ex
│   │   │   │   ├── push.ex
│   │   │   │   ├── room/
│   │   │   │   │   ├── ban.ex
│   │   │   │   │   ├── create.ex
│   │   │   │   │   ├── create_scheduled.ex
│   │   │   │   │   ├── deafen.ex
│   │   │   │   │   ├── delete_scheduled.ex
│   │   │   │   │   ├── get_banned_users.ex
│   │   │   │   │   ├── get_info.ex
│   │   │   │   │   ├── get_invite_list.ex
│   │   │   │   │   ├── get_scheduled.ex
│   │   │   │   │   ├── get_top.ex
│   │   │   │   │   ├── invite.ex
│   │   │   │   │   ├── join.ex
│   │   │   │   │   ├── leave.ex
│   │   │   │   │   ├── mute.ex
│   │   │   │   │   ├── set_active_speaker.ex
│   │   │   │   │   ├── set_auth.ex
│   │   │   │   │   ├── set_role.ex
│   │   │   │   │   ├── unban.ex
│   │   │   │   │   ├── update.ex
│   │   │   │   │   └── update_scheduled.ex
│   │   │   │   └── user/
│   │   │   │       ├── admin_update.ex
│   │   │   │       ├── ban.ex
│   │   │   │       ├── block.ex
│   │   │   │       ├── create_bot.ex
│   │   │   │       ├── follow.ex
│   │   │   │       ├── get_bots.ex
│   │   │   │       ├── get_followers.ex
│   │   │   │       ├── get_following.ex
│   │   │   │       ├── get_info.ex
│   │   │   │       ├── get_relationship.ex
│   │   │   │       ├── revoke_api_key.ex
│   │   │   │       ├── unblock.ex
│   │   │   │       ├── unfollow.ex
│   │   │   │       └── update.ex
│   │   │   ├── message.ex
│   │   │   ├── plugs/
│   │   │   │   ├── check_auth.ex
│   │   │   │   ├── cors.ex
│   │   │   │   └── redirect.ex
│   │   │   ├── routes/
│   │   │   │   ├── bot_auth.ex
│   │   │   │   ├── dev_only.ex
│   │   │   │   ├── discord_auth.ex
│   │   │   │   ├── github_auth.ex
│   │   │   │   ├── room.ex
│   │   │   │   ├── scheduled_room.ex
│   │   │   │   ├── stats.ex
│   │   │   │   ├── twitter_auth.ex
│   │   │   │   └── user.ex
│   │   │   ├── socket_handler.ex
│   │   │   ├── translator/
│   │   │   │   └── v0_1_0.ex
│   │   │   └── translator.ex
│   │   ├── broth.ex
│   │   ├── kousa/
│   │   │   ├── access_token.ex
│   │   │   ├── auth.ex
│   │   │   ├── chat.ex
│   │   │   ├── discord.ex
│   │   │   ├── follow_logic.ex
│   │   │   ├── github.ex
│   │   │   ├── metrics/
│   │   │   │   └── prometheus.ex
│   │   │   ├── refresh_token.ex
│   │   │   ├── release.ex
│   │   │   ├── room.ex
│   │   │   ├── room_block.ex
│   │   │   ├── scheduled_room.ex
│   │   │   ├── user.ex
│   │   │   ├── user_block.ex
│   │   │   └── utils/
│   │   │       ├── errors.ex
│   │   │       ├── pagination.ex
│   │   │       ├── random.ex
│   │   │       ├── reg_utils.ex
│   │   │       ├── token_utils.ex
│   │   │       ├── urls.ex
│   │   │       ├── uuid.ex
│   │   │       ├── version.ex
│   │   │       └── voice_server_utils.ex
│   │   ├── kousa.ex
│   │   └── onion/
│   │       ├── bot_auth_rate_limit.ex
│   │       ├── chat.ex
│   │       ├── pub_sub.ex
│   │       ├── room_session.ex
│   │       ├── stats_cache.ex
│   │       ├── supervisors/
│   │       │   ├── room_chat.ex
│   │       │   ├── room_session.ex
│   │       │   ├── user_session.ex
│   │       │   ├── voice_online_rabbit.ex
│   │       │   └── voice_rabbit.ex
│   │       ├── telemetry.ex
│   │       ├── user_session.ex
│   │       ├── voice_online_rabbit.ex
│   │       └── voice_rabbit.ex
│   ├── mix.exs
│   ├── priv/
│   │   └── repo/
│   │       └── migrations/
│   │           ├── 20210124203315_most_tables.exs
│   │           ├── 20210125155346_more_fields.exs
│   │           ├── 20210202143344_has_logged_in.exs
│   │           ├── 20210202162325_default_timestamps.exs
│   │           ├── 20210210005241_email.exs
│   │           ├── 20210210012609_access_token.exs
│   │           ├── 20210212141759_bans.exs
│   │           ├── 20210214140430_twitter_id.exs
│   │           ├── 20210214172930_github_id_nullable.exs
│   │           ├── 20210219173153_case_insensitive_unique_username_index.exs
│   │           ├── 20210221041850_room_permissions.exs
│   │           ├── 20210221233129_voice_server_id.exs
│   │           ├── 20210301151808_use_utc_datetime_usec.exs
│   │           ├── 20210301162635_last_online_utc_datetime_usec.exs
│   │           ├── 20210301200955_scheduled_room.exs
│   │           ├── 20210303204515_room_description.exs
│   │           ├── 20210304004945_set_timezone_for_now.exs
│   │           ├── 20210305031538_scheduled_room_started.exs
│   │           ├── 20210321141614_discord_login.exs
│   │           ├── 20210424191849_banner_url.exs
│   │           ├── 20210425000426_user_bot_api_key.exs
│   │           ├── 20210427180800_user_ip.exs
│   │           ├── 20210427192138_room_ban_ip.exs
│   │           ├── 20210501201857_emails_are_no_longer_unique.exs
│   │           ├── 20210504210047_whisper_privacy_setting.exs
│   │           ├── 20210504225546_chat_mode.exs
│   │           ├── 20210506000509_chat_throttle.exs
│   │           └── 20210509055314_admin_update.exs
│   └── test/
│       ├── _support/
│       │   ├── deprecations.ex
│       │   ├── ecto_sandbox.ex
│       │   ├── factory.ex
│       │   ├── http_request.ex
│       │   ├── message.ex
│       │   └── ws_client.ex
│       ├── ad_hoc_user_test.exs
│       ├── beef/
│       │   ├── follow_test.exs
│       │   ├── room_test.exs
│       │   ├── rooms_test.exs
│       │   ├── scheduled_room_test.exs
│       │   ├── user_block_test.exs
│       │   ├── user_blocks_test.exs
│       │   ├── user_test.exs
│       │   └── users_test.exs
│       ├── broth/
│       │   ├── _calls/
│       │   │   ├── _THIS DIRECTORY TO BE DEPRECATED
│       │   │   ├── create_room_from_scheduled_room_test.exs
│       │   │   ├── create_room_test.exs
│       │   │   ├── delete_scheduled_room_test.exs
│       │   │   ├── edit_profile_test.exs
│       │   │   ├── edit_room_test.exs
│       │   │   ├── edit_scheduled_room_test.exs
│       │   │   ├── fetch_follow_list_test.exs
│       │   │   ├── follow_info_test.exs
│       │   │   ├── get_blocked_from_room_users_test.exs
│       │   │   ├── get_my_following_test.exs
│       │   │   ├── get_my_scheduled_rooms_about_to_start_test.exs
│       │   │   ├── get_scheduled_rooms_test.exs
│       │   │   ├── get_top_public_rooms_test.exs
│       │   │   ├── get_user_profile_test.exs
│       │   │   ├── join_room_and_get_info_test.exs
│       │   │   ├── schedule_room_test.exs
│       │   │   ├── search_test.exs
│       │   │   └── unban_from_room_test.exs
│       │   ├── _casts/
│       │   │   ├── _THIS DIRECTORY TO BE DEPRECATED
│       │   │   ├── add_speaker_test.exs
│       │   │   ├── ask_to_speak_test.exs
│       │   │   ├── auth_test.exs
│       │   │   ├── ban_from_room_chat_test.exs
│       │   │   ├── ban_test.exs
│       │   │   ├── block_from_room_test.exs
│       │   │   ├── change_mod_status_test.exs
│       │   │   ├── change_room_creator_test.exs
│       │   │   ├── delete_room_chat_message_test.exs
│       │   │   ├── follow_test.exs
│       │   │   ├── invite_to_room_test.exs
│       │   │   ├── leave_room_test.exs
│       │   │   ├── make_room_public_test.exs
│       │   │   ├── mute_test.exs
│       │   │   ├── send_room_chat_msg_test.exs
│       │   │   ├── set_auto_speaker.exs
│       │   │   ├── set_listener_test.exs
│       │   │   ├── speaking_change_test.exs
│       │   │   └── unban_from_room_chat_test.exs
│       │   ├── _message/
│       │   │   ├── auth/
│       │   │   │   └── request_test.exs
│       │   │   ├── chat/
│       │   │   │   ├── ban_test.exs
│       │   │   │   ├── delete_msg_test.exs
│       │   │   │   ├── send_test.exs
│       │   │   │   └── unban_test.exs
│       │   │   ├── misc/
│       │   │   │   └── search_test.exs
│       │   │   ├── room/
│       │   │   │   ├── ban_test.exs
│       │   │   │   ├── create_scheduled_test.exs
│       │   │   │   ├── create_test.exs
│       │   │   │   ├── deafen_test.exs
│       │   │   │   ├── delete_scheduled_test.exs
│       │   │   │   ├── get_banned_users_test.exs
│       │   │   │   ├── get_info_test.exs
│       │   │   │   ├── get_invite_list_test.exs
│       │   │   │   ├── get_scheduled_test.exs
│       │   │   │   ├── get_top_test.exs
│       │   │   │   ├── invite_test.exs
│       │   │   │   ├── join_test.exs
│       │   │   │   ├── leave_test.exs
│       │   │   │   ├── mute_test.exs
│       │   │   │   ├── set_active_speaker_test.exs
│       │   │   │   ├── set_auth_test.exs
│       │   │   │   ├── set_role_test.exs
│       │   │   │   ├── unban_test.exs
│       │   │   │   ├── update_scheduled_test.exs
│       │   │   │   └── update_test.exs
│       │   │   └── user/
│       │   │       ├── admin_update_test.exs
│       │   │       ├── ban_test.exs
│       │   │       ├── block_test.exs
│       │   │       ├── create_bot_test.exs
│       │   │       ├── follow_test.exs
│       │   │       ├── get_bots_test.exs
│       │   │       ├── get_followers_test.exs
│       │   │       ├── get_following_test.exs
│       │   │       ├── get_info_test.exs
│       │   │       ├── get_relationship_test.exs
│       │   │       ├── revoke_api_key_test.exs
│       │   │       ├── unblock_test.exs
│       │   │       ├── unfollow_test.exs
│       │   │       └── update_test.exs
│       │   ├── _routes/
│       │   │   └── bot_auth_test.exs
│       │   ├── _types/
│       │   │   └── chat_token.exs
│       │   ├── auth/
│       │   │   └── request_test.exs
│       │   ├── chat/
│       │   │   ├── ban_test.exs
│       │   │   ├── delete_test.exs
│       │   │   ├── send_test.exs
│       │   │   └── unban_test.exs
│       │   ├── message_test.exs
│       │   ├── misc/
│       │   │   └── search_test.exs
│       │   ├── room/
│       │   │   ├── ban_test.exs
│       │   │   ├── create_scheduled_test.exs
│       │   │   ├── create_test.exs
│       │   │   ├── deafen_test.exs
│       │   │   ├── delete_scheduled_test.exs
│       │   │   ├── get_banned_users_test.exs
│       │   │   ├── get_info_test.exs
│       │   │   ├── get_invite_list_test.exs
│       │   │   ├── get_scheduled_test.exs
│       │   │   ├── get_top_test.exs
│       │   │   ├── invite_test.exs
│       │   │   ├── join_test.exs
│       │   │   ├── leave_test.exs
│       │   │   ├── mute_test.exs
│       │   │   ├── set_active_speaker_test.exs
│       │   │   ├── set_auth_test.exs
│       │   │   ├── set_role_test.exs
│       │   │   ├── unban_test.exs
│       │   │   ├── update_scheduled_test.exs
│       │   │   └── update_test.exs
│       │   └── user/
│       │       ├── admin_update_test.exs
│       │       ├── ban_test.exs
│       │       ├── block_test.exs
│       │       ├── create_bot_test.exs
│       │       ├── follow_test.exs
│       │       ├── get_bots_test.exs
│       │       ├── get_followers_test.exs
│       │       ├── get_following_test.exs
│       │       ├── get_info_test.exs
│       │       ├── get_relationship_test.exs
│       │       ├── revoke_api_key_test.exs
│       │       ├── unblock_test.exs
│       │       ├── unfollow_test.exs
│       │       └── update_test.exs
│       ├── kousa/
│       │   └── user.ex
│       └── test_helper.exs
├── package.json
├── pilaf/
│   ├── .buckconfig
│   ├── .eslintrc.js
│   ├── .flowconfig
│   ├── .gitattributes
│   ├── .gitignore
│   ├── .prettierrc.js
│   ├── .storybook/
│   │   ├── main.js
│   │   └── manager.js
│   ├── .watchmanconfig
│   ├── .yarnrc.yml
│   ├── App.tsx
│   ├── LICENSE
│   ├── README.md
│   ├── __tests__/
│   │   └── App-test.js
│   ├── android/
│   │   ├── app/
│   │   │   ├── BUCK
│   │   │   ├── build.gradle
│   │   │   ├── build_defs.bzl
│   │   │   ├── debug.keystore
│   │   │   ├── proguard-rules.pro
│   │   │   └── src/
│   │   │       ├── debug/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   └── java/
│   │   │       │       └── com/
│   │   │       │           └── rice/
│   │   │       │               └── ReactNativeFlipper.java
│   │   │       └── main/
│   │   │           ├── AndroidManifest.xml
│   │   │           ├── java/
│   │   │           │   └── com/
│   │   │           │       └── rice/
│   │   │           │           ├── MainActivity.java
│   │   │           │           ├── MainApplication.java
│   │   │           │           └── SplashActivity.java
│   │   │           └── res/
│   │   │               ├── drawable/
│   │   │               │   └── background_splash.xml
│   │   │               ├── layout/
│   │   │               │   └── launch_screen.xml
│   │   │               └── values/
│   │   │                   ├── colors.xml
│   │   │                   ├── strings.xml
│   │   │                   └── styles.xml
│   │   ├── build.gradle
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       ├── gradle-wrapper.jar
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   ├── gradlew
│   │   ├── gradlew.bat
│   │   └── settings.gradle
│   ├── app.json
│   ├── babel.config.js
│   ├── index.js
│   ├── ios/
│   │   ├── Podfile
│   │   ├── rice/
│   │   │   ├── AppDelegate.h
│   │   │   ├── AppDelegate.m
│   │   │   ├── Images.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── Contents.json
│   │   │   │   └── SplashIcon.imageset/
│   │   │   │       └── Contents.json
│   │   │   ├── Info.plist
│   │   │   ├── LaunchScreen.storyboard
│   │   │   ├── main.m
│   │   │   └── rice.entitlements
│   │   ├── rice-tvOS/
│   │   │   └── Info.plist
│   │   ├── rice-tvOSTests/
│   │   │   └── Info.plist
│   │   ├── rice.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           ├── rice-tvOS.xcscheme
│   │   │           └── rice.xcscheme
│   │   ├── rice.xcworkspace/
│   │   │   ├── contents.xcworkspacedata
│   │   │   └── xcshareddata/
│   │   │       └── IDEWorkspaceChecks.plist
│   │   └── riceTests/
│   │       ├── Info.plist
│   │       └── riceTests.m
│   ├── metro.config.js
│   ├── package.json
│   ├── react-native.config.js
│   ├── src/
│   │   ├── assets/
│   │   │   └── images/
│   │   │       ├── logo.svg~Add font + constant for dogehouse theme colors
│   │   │       └── logo.svg~refs/
│   │   │           └── remotes/
│   │   │               └── ben/
│   │   │                   └── staging
│   │   ├── components/
│   │   │   ├── BaseOverlay.tsx
│   │   │   ├── BubbleText.tsx
│   │   │   ├── ErrorToast.tsx
│   │   │   ├── FeaturedRoomCard.tsx
│   │   │   ├── MessageElement.tsx
│   │   │   ├── RoomCard.tsx
│   │   │   ├── RoomCardHeading.tsx
│   │   │   ├── ScrollViewLoadMore.tsx
│   │   │   ├── Spinner.tsx
│   │   │   ├── Tag.tsx
│   │   │   ├── UpcomingRoomCard.tsx
│   │   │   ├── UserBadge.tsx
│   │   │   ├── UserPreview.tsx
│   │   │   ├── accountModal/
│   │   │   │   ├── AccountModalContent.tsx
│   │   │   │   └── AccountModalRow.tsx
│   │   │   ├── avatars/
│   │   │   │   ├── MultipleUserAvatar.tsx
│   │   │   │   ├── RoomAvatar.tsx
│   │   │   │   └── SingleUserAvatar.tsx
│   │   │   ├── bottomBar/
│   │   │   │   └── CreateRoomButton.tsx
│   │   │   ├── buttons/
│   │   │   │   ├── Button.tsx
│   │   │   │   ├── IconButton.tsx
│   │   │   │   ├── SignInButton.tsx
│   │   │   │   └── SigninWithGithub.tsx
│   │   │   ├── header/
│   │   │   │   ├── Header.tsx
│   │   │   │   ├── HeaderBase.tsx
│   │   │   │   ├── ProfileButton.tsx
│   │   │   │   ├── RoomHeader.tsx
│   │   │   │   ├── SearchHeader.tsx
│   │   │   │   └── TitledHeader.tsx
│   │   │   ├── minimizedRoomCard/
│   │   │   │   ├── BoxedIcon.tsx
│   │   │   │   └── MinimizedRoomCard.tsx
│   │   │   ├── notifications/
│   │   │   │   ├── FollowNotification.tsx
│   │   │   │   ├── GenericNotification.tsx
│   │   │   │   ├── LiveNotification.tsx
│   │   │   │   └── NewRoomNotification.tsx
│   │   │   ├── report/
│   │   │   │   └── Report.tsx
│   │   │   └── search/
│   │   │       ├── RoomSearchResult.tsx
│   │   │       ├── SearchHistoryResult.tsx
│   │   │       ├── SearchHistoryResultList.tsx
│   │   │       ├── SearchResultList.tsx
│   │   │       └── UserSearchResult.tsx
│   │   ├── constants/
│   │   │   ├── dogeStyle.ts
│   │   │   ├── env.ts
│   │   │   └── regex.ts
│   │   ├── global-stores/
│   │   │   ├── useCurrentRoomIdStore.ts
│   │   │   ├── useMicPermErrorStore.ts
│   │   │   ├── useMuteStore.ts
│   │   │   ├── useProducerStore.ts
│   │   │   └── useRoomChatMentionStore.ts
│   │   ├── lib/
│   │   │   ├── createChatMessage.ts
│   │   │   ├── inCallManagerCenter.ts
│   │   │   ├── notificationCenter.ts
│   │   │   └── queryClient.ts
│   │   ├── modules/
│   │   │   ├── auth/
│   │   │   │   ├── WaitForWsAndAuth.tsx
│   │   │   │   ├── useSaveTokensFromQueryParams.ts
│   │   │   │   ├── useTokenStore.ts
│   │   │   │   └── useVerifyLoggedIn.ts
│   │   │   ├── explore/
│   │   │   │   └── ExploreController.tsx
│   │   │   ├── feed/
│   │   │   │   └── FeedController.tsx
│   │   │   ├── following/
│   │   │   │   ├── FollowersOnline.tsx
│   │   │   │   └── FollowingOnlineController.tsx
│   │   │   ├── help/
│   │   │   │   └── HelpController.tsx
│   │   │   ├── landing/
│   │   │   │   └── LandingController.tsx
│   │   │   ├── languages/
│   │   │   │   └── LanguagesController.tsx
│   │   │   ├── main/
│   │   │   │   └── MainController.tsx
│   │   │   ├── messages/
│   │   │   │   └── MessagesController.tsx
│   │   │   ├── notifications/
│   │   │   │   └── NotificationsController.tsx
│   │   │   ├── profile/
│   │   │   │   └── ProfileController.tsx
│   │   │   ├── reportBug/
│   │   │   │   └── ReportBugController.tsx
│   │   │   ├── room/
│   │   │   │   ├── InviteRoomController.tsx
│   │   │   │   ├── MinimizedRoomCardController.tsx
│   │   │   │   ├── RoomController.tsx
│   │   │   │   ├── RoomDescriptionController.tsx
│   │   │   │   ├── RoomPanelController.tsx
│   │   │   │   ├── RoomUsersPanel.tsx
│   │   │   │   ├── UserPreviewModalProvider.tsx
│   │   │   │   ├── chat/
│   │   │   │   │   ├── EmoteData.ts
│   │   │   │   │   ├── EmotePicker.tsx
│   │   │   │   │   ├── RoomChat.tsx
│   │   │   │   │   ├── RoomChatControls.tsx
│   │   │   │   │   ├── RoomChatInput.tsx
│   │   │   │   │   ├── RoomChatList.tsx
│   │   │   │   │   ├── RoomChatMentions.tsx
│   │   │   │   │   ├── RoomMessage.tsx
│   │   │   │   │   ├── useRoomChatMentionStore.ts
│   │   │   │   │   └── useRoomChatStore.ts
│   │   │   │   ├── useOnRoomPage.tsx
│   │   │   │   └── useSplitUsersIntoSections.tsx
│   │   │   ├── schedule/
│   │   │   │   └── ScheduleController.tsx
│   │   │   ├── search/
│   │   │   │   └── SearchController.tsx
│   │   │   ├── settings/
│   │   │   │   └── SettingsController.tsx
│   │   │   ├── sound-effect/
│   │   │   │   └── useSoundEffectStore.ts
│   │   │   ├── wallet/
│   │   │   │   └── WalletController.tsx
│   │   │   ├── webrtc/
│   │   │   │   ├── WebRtcApp.tsx
│   │   │   │   ├── components/
│   │   │   │   │   └── MicPicker.tsx
│   │   │   │   ├── stores/
│   │   │   │   │   ├── useAskForMicStore.ts
│   │   │   │   │   ├── useAudioTracks.ts
│   │   │   │   │   ├── useConsumerStore.ts
│   │   │   │   │   ├── useMicIdStore.ts
│   │   │   │   │   ├── useMicPermErrorStore.ts
│   │   │   │   │   ├── useProducerStore.ts
│   │   │   │   │   ├── useSocketStatus.ts
│   │   │   │   │   ├── useStatus.ts
│   │   │   │   │   └── useVoiceStore.ts
│   │   │   │   ├── types.ts
│   │   │   │   └── utils/
│   │   │   │       ├── consumeAudio.ts
│   │   │   │       ├── createTransport.ts
│   │   │   │       ├── joinRoom.ts
│   │   │   │       ├── mergeRoomPermission.ts
│   │   │   │       ├── receiveVoice.ts
│   │   │   │       └── sendVoice.ts
│   │   │   └── ws/
│   │   │       └── WebSocketProvider.tsx
│   │   ├── navigation/
│   │   │   ├── AuthenticationSwitch.tsx
│   │   │   ├── LandingPage.tsx
│   │   │   ├── MainNavigator.tsx
│   │   │   ├── RootNavigation.ts
│   │   │   └── mainNavigator/
│   │   │       ├── BottomNavigator.tsx
│   │   │       ├── HelpPage.tsx
│   │   │       ├── InviteRoomPage.tsx
│   │   │       ├── LanguagesPage.tsx
│   │   │       ├── MainPage.tsx
│   │   │       ├── MessagesPage.tsx
│   │   │       ├── NotificationsPage.tsx
│   │   │       ├── ProfilePage.tsx
│   │   │       ├── ReportBugPage.tsx
│   │   │       ├── RoomDescriptionPage.tsx
│   │   │       ├── RoomNavigator.tsx
│   │   │       ├── RoomPage.tsx
│   │   │       ├── SearchPage.tsx
│   │   │       ├── SettingsPage.tsx
│   │   │       ├── WalletPage.tsx
│   │   │       └── bottomNavigator/
│   │   │           ├── ExplorePage.tsx
│   │   │           ├── FeedPage.tsx
│   │   │           ├── FollowingPage.tsx
│   │   │           └── SchedulePage.tsx
│   │   ├── pages/
│   │   │   └── CreateRoomPage.tsx
│   │   ├── shared-components/
│   │   │   └── ApiPreloadLink.tsx
│   │   ├── shared-hooks/
│   │   │   ├── useConn.ts
│   │   │   ├── useCurrentRoomInfo.ts
│   │   │   ├── useMainWsHandler.tsx
│   │   │   ├── useSetMute.ts
│   │   │   ├── useTypeSafeMutation.ts
│   │   │   ├── useTypeSafePrefetch.ts
│   │   │   ├── useTypeSafeQuery.ts
│   │   │   └── useTypeSafeUpdateQuery.ts
│   │   ├── stories/
│   │   │   └── index.ts
│   │   └── types/
│   │       └── util-types.ts
│   ├── storybook/
│   │   ├── addons.ts
│   │   ├── index.ts
│   │   ├── rn-addons.ts
│   │   └── stories/
│   │       ├── Button.stories.tsx
│   │       ├── CenterView/
│   │       │   └── index.tsx
│   │       ├── FeaturedRoomCard.stories.tsx
│   │       ├── FollowNotification.stories.tsx
│   │       ├── GenericNotification.stories.tsx
│   │       ├── LiveNotification.stories.tsx
│   │       ├── Message.stories.tsx
│   │       ├── MultipleUserAvatar.stories.tsx
│   │       ├── NewRoomNotification.stories.tsx
│   │       ├── SingleUserAvatar.stories.tsx
│   │       └── index.ts
│   ├── template.config.js
│   └── tokens.ts
├── run.ps1
├── run.sh
├── scripts/
│   └── trigger-electron-deploy.sh
├── shawarma/
│   ├── .dockerignore
│   ├── .eslintrc.json
│   ├── Dockerfile
│   ├── README.md
│   ├── deploy.sh
│   ├── package.json
│   ├── src/
│   │   ├── MyPeer.ts
│   │   ├── MyRoomState.ts
│   │   ├── config.ts
│   │   ├── constants.ts
│   │   ├── index.ts
│   │   ├── main.ts
│   │   ├── types/
│   │   │   ├── env.d.ts
│   │   │   └── index.ts
│   │   └── utils/
│   │       ├── closePeer.ts
│   │       ├── createConsumer.ts
│   │       ├── createTransport.ts
│   │       ├── deleteRoom.ts
│   │       ├── startMediasoup.ts
│   │       └── startRabbit.ts
│   └── tsconfig.json
└── 🐕.🏠

================================================
FILE CONTENTS
================================================

================================================
FILE: .devcontainer/Dockerfile
================================================
# Update to pick an Elixir version: 1.9, 1.10, 1.10.4
ARG VARIANT=latest
FROM elixir:${VARIANT}

ENV USERNAME=doge
ENV USER_UID=1000
ENV USER_GID=$USER_UID

COPY scripts/*.sh /tmp/scripts/

# Create non-root doge user
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    && bash /tmp/scripts/user.sh "$USERNAME" "$USER_UID" "$USER_GID" \
    # Clean up
    && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /root/.gnupg

# Install Node.js
ENV NVM_DIR=/home/$USERNAME/.nvm
ENV NODE_VERSION="lts/*"

RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    # Install common packages, non-root user, update yarn and install nvm
    && bash /tmp/scripts/node.sh "$NVM_DIR" "$NODE_VERSION" "$USERNAME" \
    # Clean up
    && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /root/.gnupg

# Cleanup scripts
RUN rm -rf /tmp/scripts

CMD ["sleep", "infinity"]

================================================
FILE: .devcontainer/devcontainer.json
================================================
{
    "name": "Dogehouse",
    "dockerComposeFile": "docker-compose.yml",
    "service": "workspace",
    "workspaceFolder": "/workspace",
    "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "jakebecker.elixir-ls",
        "bradlc.vscode-tailwindcss"
    ],
    "forwardPorts": [
        80,
        3000,
        4001,
        8080,
        5432,
        5672,
        15672 // rabbit.mq management interface 
    ],
    "postCreateCommand": ["bash", ".devcontainer/scripts/environment.sh"],
    "remoteUser": "doge"
}

================================================
FILE: .devcontainer/docker-compose.yml
================================================
version: "3"

services:
  workspace:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ..:/workspace:cached

  db:
    image: postgres:latest
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: kousa_repo2 # Initial schema name
    network_mode: service:workspace

  rabbitmq:
    image: rabbitmq:management
    restart: unless-stopped
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq/data
    environment:
      RABBITMQ_DEFAULT_USER: guest
      RABBITMQ_DEFAULT_PASS: guest
    network_mode: service:workspace

volumes:
  postgres-data:
  rabbitmq-data:


================================================
FILE: .devcontainer/scripts/environment.sh
================================================
# kousa
cat >> "/home/$USERNAME/.bashrc" << EOL

# Kousa environment variables 
export DATABASE_URL=postgres://postgres:postgres@localhost/kousa_repo2
export BEN_GITHUB_ID=7872329
export RABBITMQ_URL=amqp://guest:guest@localhost:5672
export ACCESS_TOKEN_SECRET=
export REFRESH_TOKEN_SECRET=
export GITHUB_CLIENT_ID=
export TWITTER_API_KEY=
export TWITTER_SECRET_KEY=
export TWITTER_BEARER_TOKEN=
export GITHUB_CLIENT_SECRET=
export DISCORD_CLIENT_ID=
export DISCORD_CLIENT_SECRET=
export GOOGLE_CLIENT_ID=
export GOOGLE_CLIENT_SECRET=
export SENTRY_DNS=
export API_URL=http://localhost:4001
export WEB_URL=http://localhost:3000
export PORT=4001
EOL

# shawarma
echo "WEBRTC_LISTEN_IP=127.0.0.1" > shawarma/.env

# kibbeh
cp kibbeh/.env.example kibbeh/.env


================================================
FILE: .devcontainer/scripts/node.sh
================================================
#!/usr/bin/env bash

USERNAME=${3:-"doge"}
export NVM_DIR=${1:-"/home/$USERNAME/.nvm"}
export NODE_VERSION=${2:-"lts/*"}

set -e

# install all dependencies
apt-get update \
    && apt-get install -y curl ca-certificates tar gnupg2 \
    && apt-get -y autoclean

# install yarn
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | (OUT=$(apt-key add - 2>&1) || echo $OUT)
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt-get update
apt-get -y install --no-install-recommends yarn

# install nvm
su ${USERNAME} -c "mkdir $NVM_DIR"
su ${USERNAME} -c "curl --silent -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.36.0/install.sh | bash"

# install node and npm
su ${USERNAME} -c "source $NVM_DIR/nvm.sh \
    && nvm install $NODE_VERSION \
    && nvm alias default $NODE_VERSION \
    && nvm use default"

================================================
FILE: .devcontainer/scripts/user.sh
================================================
#!/usr/bin/env bash

USERNAME=${1:-"doge"}
USER_UID=${2:-1000}
USER_GID=${3:-$USER_UID}

PACKAGE_LIST="apt-utils \
        git \
        htop \
        curl \
        wget \
        unzip \
        zip \
        vim \
        less \
        sudo \
        man-db"

# install packages
apt-get -y install --no-install-recommends ${PACKAGE_LIST}

# add non-root user
groupadd --gid $USER_GID $USERNAME
useradd -s /bin/bash --uid $USER_UID --gid $USERNAME -m $USERNAME
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
chmod 0440 /etc/sudoers.d/$USERNAME
chown ${USERNAME}:${USERNAME} "/home/${USERNAME}/.bashrc"

================================================
FILE: .dockerignore
================================================
docker/
.docker/

================================================
FILE: .editorconfig
================================================
# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true


================================================
FILE: .eslintignore
================================================
node_modules/

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**What device are you on?**

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/labeler.yml
================================================
kibbeh:
  - kibbeh/**/*
baklava:
  - baklava/**/*
kebab:
  - kebab/**/*
kousa:
  - kousa/**/*
pilaf:
  - pilaf/**/*
shawarma:
  - shawarma/**/*
dolma:
  - dolma/**/*
emote:
  - kibbeh/public/emotes/**/*
translation:
  - kibbeh/public/locales/**/*


================================================
FILE: .github/workflows/baklava-build_and_release.yaml
================================================
name: baklava:build_and_release

on:
  push:
    paths:
      - "baklava/**"
    branches:
      - staging

jobs:
  release:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]
    steps:
      - name: Check out Git repository
        uses: actions/checkout@v1
      - name: Install Node.js, NPM and Yarn
        uses: actions/setup-node@v1
        with:
          node-version: 14
      - name: Yarn cache
        uses: actions/cache@v2
        id: yarn-cache
        with:
          path: |
            baklava/.yarn/cache
            baklava/resources/overlay/.yarn/cache
          key: ${{ runner.os }}-yarn-${{ hashFiles('baklava/**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Install deps
        working-directory: baklava
        run: yarn
      - name: Save env vars
        working-directory: baklava/src
        run: echo "export const DISCORD_CLIENT_ID = '${{ secrets.DISCORD_CLIENT_ID }}'" >> constants.ts
      - name: Compile Typescript
        working-directory: baklava
        run: yarn compile
      - name: Install Overlay Deps
        working-directory: baklava/resources/overlay
        run: yarn
      - name: Build overlay
        working-directory: baklava/resources/overlay
        run: yarn build
      - name: Install rust
        uses: hecrj/setup-rust-action@v1
        with:
          rust-version: stable
      - name: Install nj-cli
        run: cargo install nj-cli
      - name: Build globalkey
        working-directory: baklava
        run: yarn build:globalkey
      - name: Prepare for app notarization
        if: startsWith(matrix.os, 'macos')
        # Import Apple API key for app notarization on macOS
        # this get skipped for some reason
        run: |
          mkdir -p ~/private_keys/
          echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8
      - name: Install Snapcraft
        uses: samuelmeuli/action-snapcraft@v1
        if: startsWith(matrix.os, 'ubuntu')
        with:
          # Log in to Snap Store
          snapcraft_token: ${{ secrets.snapcraft_token }}
      - name: Install RPM
        if: startsWith(matrix.os, 'ubuntu')
        run: |
          sudo apt install rpm
      - name: Build/release Electron app
        uses: samuelmeuli/action-electron-builder@v1
        with:
          mac_certs: ${{ secrets.mac_certs }}
          mac_certs_password: ${{ secrets.mac_certs_password }}
          # this is executed before the default `electron-builder` script
          build_script_name: delete:artifacts
          package_root: baklava
          github_token: ${{ secrets.github_token }}
          release: true
        env:
          # macOS notarization API key
          API_KEY_ID: ${{ secrets.api_key_id }}
          API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id }}


================================================
FILE: .github/workflows/dolma-npm_deploy.yaml
================================================
name: dolma:npm_publish
on:
  push:
    paths:
      - "dolma/**"
    branches:
      - staging
jobs:
  npm-publish:
    name: npm-publish
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
      - name: Install Node.js, NPM and Yarn
        uses: actions/setup-node@v1
        with:
          node-version: 14
      - name: Yarn cache
        uses: actions/cache@v2
        id: yarn-cache
        with:
          path: |
            .yarn/cache
          key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Install deps
        working-directory: ./dolma
        run: yarn
      - name: Build
        working-directory: ./dolma
        run: yarn build
      - name: Publish if version has been updated
        uses: pascalgn/npm-publish-action@1.3.7
        with: # All of theses inputs are optional
          tag_name: "v%s"
          tag_message: "v%s"
          create_tag: "false"
          commit_pattern: "^feat\\(dolma\\)\\: release (\\S+)"
          workspace: "dolma"
          publish_command: "yarn"
          publish_args: "--non-interactive --verbose"
        env: # More info about the environment variables in the README
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Leave this as is, it's automatically generated
          NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} # You need to set this in your repo settings


================================================
FILE: .github/workflows/global-label_pr.yml
================================================
name: global:label_pr

on:
  - pull_request_target

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/labeler@main
        with:
          repo-token: "${{ secrets.GITHUB_TOKEN }}"


================================================
FILE: .github/workflows/global-lint_commit_messages.yaml
================================================
name: global:lint_commit_messages

on: [push, pull_request]

jobs:
  commitlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - uses: wagoid/commitlint-github-action@v3

================================================
FILE: .github/workflows/globalkey-npm_deploy.yaml
================================================
name: globalkey:npm_publish
on:
  push:
    paths:
      - "globalkey/**"
    branches:
      - staging
jobs:
  npm-publish:
    name: npm-publish
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
      - name: Install Node.js, NPM and Yarn
        uses: actions/setup-node@v1
        with:
          node-version: 14
      - name: Install deps
        working-directory: ./globalkey
        run: yarn
      - name: Build
        working-directory: ./globalkey
        run: yarn build
      - name: Publish if version has been updated
        uses: pascalgn/npm-publish-action@1.3.7
        with: # All of theses inputs are optional
          tag_name: "v%s"
          tag_message: "v%s"
          create_tag: "false"
          commit_pattern: "^feat\\(globalkey\\)\\: release (\\S+)"
          workspace: "globalkey"
          publish_command: "yarn"
          publish_args: "--non-interactive --verbose"
        env: # More info about the environment variables in the README
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Leave this as is, it's automatically generated
          NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} # You need to set this in your repo settings


================================================
FILE: .github/workflows/kebab-npm_publish.yaml
================================================
name: kebab:npm_publish
on:
  push:
    paths:
      - "kebab/**"
    branches:
      - staging
jobs:
  npm-publish:
    name: npm-publish
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
      - name: Install Node.js, NPM and Yarn
        uses: actions/setup-node@v1
        with:
          node-version: 14
      - name: Yarn cache
        uses: actions/cache@v2
        id: yarn-cache
        with:
          path: |
            .yarn/cache
          key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Install deps
        working-directory: kebab
        run: yarn
      - name: Build
        working-directory: kebab
        run: yarn build
      - name: Publish if version has been updated
        uses: pascalgn/npm-publish-action@1.3.7
        with: # All of theses inputs are optional
          tag_name: "v%s"
          tag_message: "v%s"
          create_tag: "false"
          commit_pattern: "^feat\\(kebab\\)\\: release (\\S+)"
          workspace: "kebab"
          publish_command: "yarn"
          publish_args: "--non-interactive"
        env: # More info about the environment variables in the README
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Leave this as is, it's automatically generated
          NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} # You need to set this in your repo settings


================================================
FILE: .github/workflows/kibbeh-e2e_tests.yaml
================================================
name: kibbeh:e2e_tests
on:
  push:
    branches:
      - staging
    paths:
      - '.github/workflows/kibbeh-e2e_tests.yaml'
      - 'kousa/lib/**'
      - 'kibbeh/src/**'
  pull_request:
    branches:
      - staging
    paths:
      - 'kousa/lib/**'
      - 'kibbeh/src/**'
jobs:
  end-to-end-tests:
    name: end-to-end-tests
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./kousa
    services:
      db:
        image: postgres:11
        ports: ['5432:5432']
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: kousa_repo2
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
    - uses: actions/checkout@v2
    - uses: erlef/setup-elixir@v1
      with:
        otp-version: '22.2'
        elixir-version: '1.11'
    - name: fetch deps
      run: mix deps.get
      env:
          MIX_ENV: test
    - run: source .envrc && mix ecto.migrate
    - run: source .envrc && iex -S mix
    - name: Use Node.js
      uses: actions/setup-node@v1
    - run: yarn install
    - run: cd ../kebab && yarn build
    - run: cd ../kibbeh && yarn test:e2e:ci

================================================
FILE: .github/workflows/kibbeh-lint_and_test.yaml
================================================
name: kibbeh:lint_and_test

on:
  push:
    branches:
      - staging
    paths:
      - "kibbeh/**"
  pull_request:
    branches:
      - staging
    paths:
      - "kibbeh/**"

jobs:
  test:
    name: lint-and-test-kibbeh
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Use Node.js
        uses: actions/setup-node@v1
      - name: Yarn cache
        uses: actions/cache@v2
        id: yarn-cache
        with:
          path: |
            .yarn/cache
          key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - run: yarn install
      - run: cd kebab && yarn build
      - run: cd dolma && yarn build
      - run: cd kibbeh && yarn compile
      - run: cd kibbeh && yarn lint
      - run: cd kibbeh && yarn test:ci
        id: test


================================================
FILE: .github/workflows/kousa-deploy_staging.yaml
================================================
name: kousa:deploy_staging
on:
  push:
    paths:
      - 'kousa/lib/**'
    branches:
      - staging

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: executing remote ssh commands using password
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          password: ${{ secrets.SSH_PASSWORD }}
          script: cd dogehouse/kousa && git pull origin staging && docker build -t benawad/kousa:0.0.1 . && docker tag benawad/kousa:0.0.1 dokku/doge-staging:latest && dokku tags:deploy doge-staging latest


================================================
FILE: .github/workflows/kousa-tests.yaml
================================================
name: kousa:tests
on:
  push:
    branches:
      - staging
    paths:
      - 'kousa/lib/**'
  pull_request:
    branches:
      - staging
    paths:
      - 'kousa/lib/**'
jobs:
  test:
    name: test-elixir
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./kousa
    services:
      db:
        image: postgres:11
        ports: ['5432:5432']
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
    - uses: actions/checkout@v2
    - uses: erlef/setup-elixir@v1
      with:
        otp-version: '22.2'
        elixir-version: '1.11'
    - name: fetch deps
      run: mix deps.get
      env:
          MIX_ENV: test
    - run: mix test
      id: test

================================================
FILE: .github/workflows/shawarma-deploy_staging.yaml
================================================
name: shawarma:deploy_staging
on:
  push:
    paths:
      - 'shawarma/src/**'
    branches:
      - staging

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: executing remote ssh commands using password
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          password: ${{ secrets.SSH_PASSWORD }}
          script: cd dogehouse/kousa && git pull origin staging && source ~/.nvm/nvm.sh && nvm use 14 && cd ../shawarma && yarn install && npm run build && pm2 restart dist/index.js


================================================
FILE: .gitignore
================================================
.DS_Store
node_modules

# Local Netlify folder
.netlify

.idea/
*/.idea/
.docker
.env
.next
storybook-static
_
.env.local
kebab/lib
yarn-error.log

dist
.yarn
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*


================================================
FILE: .husky/.gitignore
================================================
_


================================================
FILE: .husky/commit-msg
================================================
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# @todo uncomment when new-design hits
# thats when we will start enforcing commit style
# npx --no-install commitlint --edit


================================================
FILE: .husky/pre-commit
================================================
#!/bin/sh
# . "$(dirname "$0")/_/husky.sh"

# cd kibbeh
# npm run format
# npm run lint

================================================
FILE: .prettierignore
================================================
node_modules/

================================================
FILE: .prettierrc.js
================================================
module.exports = {
  trailingComma: "es5",
  tabWidth: 2,
  semi: true,
  singleQuote: false,
  arrowParens: "always",
  useTabs: false,
};


================================================
FILE: .vscode/settings.json
================================================
{
    "elixirLS.projectDir": "kousa",
    "elixir.projectPath": "kousa",
    "git.ignoreLimitWarning": true,
}

================================================
FILE: .yarnrc.yml
================================================
nodeLinker: node-modules

plugins:
  - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
    spec: "@yarnpkg/plugin-workspace-tools"
  - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
    spec: "@yarnpkg/plugin-interactive-tools"

yarnPath: .yarn/releases/yarn-berry.cjs


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## 4/16/2021

- Switched to a new UI

## 2/20/2021

- Added changelog


================================================
FILE: CODEOWNERS
================================================
/kebab/ @overlisted
/baklava/ @amitojsingh366
/dolma/ @HoloPanio
/globalkey/ @willdoescode


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
 advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
 address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
 professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at benawadapps@gmail.com  or on <a href="https://discord.gg/wCbKBZF9cV">Discord</a> . All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to DogeHouse
> Please read the [PRIORITY LIST](https://github.com/benawad/dogehouse/issues/1969) before contributing.

We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
- Reporting an issue
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer

## Code of Conduct
The code of conduct is described in [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md).

## Our Development Process
All changes happen through pull requests. Pull requests are the best way to propose changes. We actively welcome your pull requests and invite you to submit pull requests directly [here](https://github.com/benawad/dogehouse/pulls), and after review, these can be merged into the project.

## Using the Project's Standard Commit Messages
This project is using the [conventional commits](https://www.conventionalcommits.org/en/v1.0.0-beta.2/) standard. Please follow these steps to ensure your
commit messages are standardized:
1. Make sure your shell path is in the root of the project (not inside any of the packages).
2. Run `yarn`.
3. Stage the files you are committing with `git add [files]`.
4. Run `yarn commit`. This will start an interactive prompt that generates your commit message:
    1. Select the type of change.
    2. Type the scope. This is either `global` for project-wide changes or one of the packages (kibbeh, shawarma etc.).
    3. Write a short, imperative tense description of the change.
    4. If the above was not sufficient, you may now write a longer description of your change (otherwise press enter to leave blank).
    5. y or n for whether there are any breaking changes (e.g. changing the props of a component, changing the JSON structure of an API response).
    6. y or n for whether this change affects an open issue, if positive you will be prompted to enter the issue number.
5. Your commit message has now been created, you may push to your fork and open a pull request (read below for further instructions).

## Pull Requests
1. Fork the repo and create your branch (usually named `patch-%the number of PRs you've already made%`) from `staging`.
2. If you've added code that should be tested, add some test examples.
3. Ensure to describe your pull request.

## Adding Emojis
Emojis need to be 28x28px. To add an emoji, add the png/gif image to public/emojis and add the emoji to the `kofta/src/app/modules/room-chat/EmoteData.ts`.

To avoid conflicts please add the emojis to the top of the file.
> **NOTE:** We are not accepting new emojis atm


## Quickstart Local Frontend Development
Do this if you only want to do React stuff and don't want to touch Elixir:

### UI *(react + next.js)*:
Navigate to `/kibbeh`

- Run `yarn`
- Run `yarn staging` (this tells React to connect to a hosted version of the backend for development purposes).
- Read `kibbeh/README.md` for more information and fixes for known development issues.
> **NOTE:** Please follow the [design guidelines](https://github.com/benawad/dogehouse/blob/staging/DESIGN_GUIDELINES.md) and [figma mockups](https://www.figma.com/file/CS01VVLR7ArQl0afYFkNj3/Web-App) and if what you're trying to do isn't in there, consult [@ajmnz](https://github.com/ajmnz)/[@benawad](https://github.com/benawad) beforehand.

## Translating
1. Fork the [repository](https://github.com/benawad/dogehouse "benawad/dogehouse") (click on `fork` in the top right corner of the screen)
![image](https://i.ibb.co/RB4FVS0/Screenshot-2021-05-07-152827.jpg)

2. In the forked repository, navigate to `kibbeh/public/locales` and then choose your language and open the `translation.json` file
3. Click on `edit` in the top right corner of the window

![image](https://i.ibb.co/vZjt4jD/Screenshot-2021-05-07-153427.jpg)

4. Make the changes in the translation(make sure you are using the correct json syntax)
5. click `commit changes` in the bottom of the page and add `fix(kibbeh): update {my language} Translation` as the commit message(`fix` if you are fixing tranlsations and `feat` if you are adding a language)(leave the description empty!)
![image](https://user-images.githubusercontent.com/68110106/117442435-6e1b1080-af3f-11eb-990f-9a1a270fef29.png)
6. Go to the [main page of the repository](https://github.com/benawad/dogehouse) and under `Contribute`, click on `Open Pull Request`

## Supporting translation in new components
1. Add your translation key into the English `translation.json` located in `kibbeh/public/locales/en/translation.json`. Make sure it is put in an appropriate section that makes sense.
2. Run `yarn i18`. This will sync all fields in all languages, if field doesn't exist it will copy it over from `en`.
3. Use your translation key in your code. This is done by using `useTypeSafeTranslation` like this: `const { t } = useTypeSafeTranslation();`. You can now call `t` and get your desired translation key.

## Devcontainer Full Local Development
For VSCode users, we're able to use devcontainers which allows you to create development environments that already have all the tools and services configured and ready to go.

### Usage

_Prerequisite: [Install Docker](https://docs.docker.com/install) on your local environment._

To get started, read and follow the instructions in [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers). The [.devcontainer/](./.devcontainer) directory contains pre-configured `devcontainer.json`, `docker-compose.yml` and `Dockerfile` files, which you can use to set up remote development within a docker container.

- Install the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
- Open VSCode and bring up the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
- Type `Remote-Containers: Open Folder in Container`, this will build the container with Elixir and Node installed, this will also start Postgres and RabbitMQ instances.

> If you need to modify environment variables for kousa, you need to modify them inside `/home/doge/.bashrc` and restart your terminal.

### Run
#### `kousa`
```shell
$ mix deps.get
$ mix ecto.migrate
$ iex -S mix
```
#### `shawarma`
```shell
$ yarn
$ yarn build
$ yarn start
```
#### `kibbeh`
```shell
$ yarn
$ yarn dev
```

## Manual Full Local Development
How to run locally:

### Backend
#### RabbitMQ
Install RabbitMQ:
- **macOS**: Run `brew install rabbitmq`.
- **Windows**: Run `choco install rabbitmq`.
- **Linux**: Follow their installation guide [here](https://www.rabbitmq.com/download.html).

Start RabbitMQ
- **macOS**: Run `brew services start rabbitmq`.
- **Windows**: Setup guide [here](https://www.rabbitmq.com/install-windows.html).
- **Linux**: Setup guide [here](https://www.rabbitmq.com/install-debian.html).

#### PostgreSQL
Install PostgreSQL:
- **macOS**: Run `brew install postgresql`.
- **Windows**: Follow [this](https://www.postgresqltutorial.com/install-postgresql/) guide.
- **Linux**: Follow [this](https://www.postgresqltutorial.com/install-postgresql-linux/) guide.

Start PostgreSQL:
- **macOS**: Run `brew services start postgresql`.
- **Windows**: Start PostgreSQL through the control panel or run `net start postgresql-{version}`.
- **Linux**: Run `/etc/rc.d/init.d/postgresql start`.

Create a DB named `kousa_repo2`:

```shell
$ psql postgres

$ CREATE DATABASE kousa_repo2;
```

#### Elixir
Elixir installation guide [here](https://elixir-lang.org/install.html).

#### `kousa`
Navigate to `/kousa` and set the following environment variables:
```
export DATABASE_URL=postgres://user:password@localhost/kousa_repo2
export BEN_GITHUB_ID=7872329
export RABBITMQ_URL=amqp://user:password@yourinternalip:5672
export ACCESS_TOKEN_SECRET=
export REFRESH_TOKEN_SECRET=
export GITHUB_CLIENT_ID=
export TWITTER_API_KEY=
export TWITTER_SECRET_KEY=
export TWITTER_BEARER_TOKEN=
export GITHUB_CLIENT_SECRET=
export SENTRY_DNS=
export API_URL=http://localhost:4001
export WEB_URL=http://localhost:3000
export PORT=4001
export DISCORD_CLIENT_ID=
export DISCORD_CLIENT_SECRET=
```

> You can save these variables in a `.txt` and run `source path/to/file.txt`

Run the following commands:
```shell
$ mix deps.get
$ mix ecto.migrate
```

Start the server
```shell
$ iex -S mix
```

#### `shawarma`
Navigate to `/shawarma` and run `yarn`.

> Mediasoup requires `node >=0.8 <=14` and has [specific requirements](https://mediasoup.org/documentation/v3/mediasoup/installation/#windows) on Windows.

Create an `.env` file and set the following environment variable:

```
WEBRTC_LISTEN_IP=127.0.0.1
```

Then run `yarn build` and `yarn start`.

## Issues
> NOTE: If your bug is a **security vulnerability**, please instead see the [security policy](https://github.com/benawad/dogehouse/security/policy)

We use GitHub issues to track public bugs. Please ensure your description is
clear and has sufficient instructions to be able to reproduce the issue. Report a bug by <a href="https://github.com/benawad/dogehouse/issues">opening a new issue</a>; it's that easy!

## Frequently Asked Questions (FAQs)
<!--- I thought it would be great to have a list of FAQs for the project to help save time for new contributors--->
    - Q: [The Question?]
    - A: [The Answer!]

## Feature Request
Great Feature Requests tend to have:

- A quick idea summary.
- What & why you wanted to add the specific feature.
- Additional context like images, links to resources to implement the feature etc, etc.

## License
By contributing to DogeHouse, you agree that your contributions will be licensed
under the [LICENSE file](LICENSE).


================================================
FILE: CREATE_BOT_ACCOUNT.MD
================================================
0. Sign in to your account
1. Head to [developer settings](https://dogehouse.tv/developer/bots)
2. Click `Create bot`
3. Enter the name of your bot
4. Click create bot
5. Go to the bot and click `Copy` to copy your API key
6. You now have a bot account! Use the API key to authenticate your bot


================================================
FILE: DESIGN_GUIDELINES.md
================================================
# Design Guidelines

This document aims to specify and define the rules and patterns to follow when implementing and developing new features and components for DogeHouse.

>This is a summary. For a more extensive version, components and UI Design, visit the publically available **[Figma file](https://www.figma.com/file/CS01VVLR7ArQl0afYFkNj3/Web-App?node-id=201%3A1979)**.

## Table of contents
- [Design Guidelines](#design-guidelines)
  - [Table of contents](#table-of-contents)
  - [Color scheme](#color-scheme)
      - [Gray shades](#gray-shades)
  - [Typography](#typography)
      - [Web Embed](#web-embed)
    - [Desktop](#desktop)
  - [Spacing](#spacing)
  - [Doubts and questions](#doubts-and-questions)

## Color scheme

- **Accent**: `#FD4D4D`
- **Pure White**: `#FFFFFF`

#### Gray shades
- **Gray 100**: `#DEE3EA`
- **Gray 200**: `#B2BDCD`
- **Gray 300**: `#5D7290`
- **~~Gray 400~~**: `#4F617A`
- **~~Gray 500~~**: `#404F64`
- **~~Gray 600~~**: `#323D4D`
- **Gray 700**: `#242C37`
- **Gray 800**: `#151A21`
- **Gray 900**: `#0B0E11`

## Typography

The font chosen for this project is `Inter`.

Inter is a free font available on Google Fonts. Clean and bold headings, readable paragraph text and an overall versatile font.

We'll be using two of its styles:
- Inter Bold (`700`)
- Inter Medium (`500`)

#### Web Embed

HTML's `link` method

```html
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@500;700&display=swap" rel="stylesheet">
```

CSS/SCSS `@import`

```css
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;700&display=swap');
```

CSS Rules

```scss
font-family: 'Inter', sans-serif;

// Regular
font-weight: 500;

// Bold
font-weight: 700;
```

![DogeHouse typography](https://i.imgur.com/A1pz7UD.png)

Tag | Font Size | Line Height | Weight
--- | --------- | ----------- | ------
**H1** | 56px | 90 | 700
**H2** | 40px | 64 | 700
**H3** | 28px | 45 | 700
**H4** | 20px | 32 | 700
**P** | 14px | 22 | 500 - 700
**P (small)** | 12px | 22 | 500 - 700

## Spacing

This is an approximation. On some circumstances other values will be used to ensure readability, consistency and visual balance, so make sure to also check the UI Design and the spacing used there.

![DogeHouse spacing](https://i.imgur.com/gRIJAXA.png)

## Doubts and questions
If you have any doubts or concerns when developing components or other UI elements, you can open an issue and tag @ajmnz or leave a message in `#design` or `#kibbeh` in [our Discord](https://discord.gg/82HzQCJCDg).


================================================
FILE: FAQ.md
================================================
# FAQ

## Why did you choose Elixir?

It's fun to program in. The error messages are awful and there's no static typing, but other than that it's great.

## How will DogeHouse make money?

- DogeNitro
- DogeSubscriptions
- DogeAds

## Will open source contributors get paid?

After DogeHouse adds monetization and it makes enough to pay server costs, there will be bounties.

## How will you market this?

Once the core product is solid, I will be doing events with the community and other influencers.

## Are you working on this full-time?

yes

## Discord Stages?

https://www.youtube.com/watch?v=FmAL5qvJkaI

## Are you ever doing video?

Not for a long time, maybe never.


================================================
FILE: HOW_TO_DEBUG_AUDIO.md
================================================
0. Turn on audio debugging mode by clicking on your avatar in the top right and click `Debug Audio`:
![image](https://user-images.githubusercontent.com/7872329/116554048-5d73f600-a8c0-11eb-9f0c-bfae58530f75.png)
1. In a room make sure your transport is connected and your browser is supported (a warning will show up if it isn't)
![image](https://user-images.githubusercontent.com/7872329/116554680-1803f880-a8c1-11eb-9535-aa89d2f424ca.png)
2. Avatars will be tinted red if the audio consumer doesn't exist or orange if it's closed (this means something is wrong if other people can hear them, skip to step 6)
3. Green will come from the bottom of the avatar if everything is working based on how loud they are speaking
![image](https://user-images.githubusercontent.com/7872329/116556759-6e723680-a8c3-11eb-913c-7506d875ac30.png)

4. If you see green but can't hear them, make sure your speakers work then click on the profile image of a speaker you can't hear and screen shot the debug info
![image](https://user-images.githubusercontent.com/7872329/116554578-f86cd000-a8c0-11eb-883c-3a66a94eb61e.png)
5. Then click `Force Play Audio` once
6. If all of these things don't work, right-click the page, click inspect, click console tab, and copy/paste all the text into a GitHub issue


================================================
FILE: HOW_TO_GET_PERMA_BANNED_FROM_DOGEHOUSE.md
================================================
# Things that will get you perma banned

0. Spam creating a ton of scheduled rooms
1. NSFW profile/banner image
2. Ban evading rooms
 - if you get banned from a room, don't create another DogeHouse account and join the same room


================================================
FILE: LICENSE
================================================
MIT License

Copyright (C) 2021 Ben Awad and the DogeHouse contributors

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
================================================
<a href="https://dogehouse.tv"><p align="center">
<img height=100 src="https://raw.githubusercontent.com/benawad/dogehouse/staging/.redesign-assets/dogehouse_logo.svg"/>

</p></a>
<p align="center">
  <strong>Taking voice conversations to the moon 🚀</strong>
</p>
<p align="center">
  <a href="https://discord.gg/wCbKBZF9cV">
    <img src="https://img.shields.io/discord/810571477316403233?style=for-the-badge" alt="discord - users online" />
  </a>
  <a href="https://dogehouse.tv">
    <img src="https://img.shields.io/endpoint?color=FD4D4D&style=for-the-badge&url=https%3A%2F%2Fapi.dogegarden.net%2Fv1%2Fshields" alt="dogehouse - users online" />
  </a>
</p>

<h3 align="center">
  <a href="https://github.com/benawad/dogehouse/blob/staging/CONTRIBUTING.md">Contribute</a>
  <span> · </span>
  <a href="https://discord.gg/82HzQCJCDg">Community</a>
  <span> · </span>
  <a href="https://github.com/FotieMConstant/dogehouse-docs">Documentation</a>
</h3>

---

## Important DogeHouse Notice

[I'm done with DogeHouse](https://www.youtube.com/watch?v=I8PkQgPiSq8)

## Structure

| Codebase              |      Description          |
| :-------------------- | :-----------------------: |
| [kousa](kousa)        |      Elixir API           |
| [shawarma](shawarma)  |     Voice Server          |
| [dinner](dinner)      | Puppeteer shenanigans     |
| [baklava](baklava)    |   Electron Wrapper        |
| [pilaf](pilaf)        |   React Native App        |
| [kibbeh](kibbeh)      |   Next.js frontend        |
| [kebab](kebab)        |      API Client           |
| [dolma](dolma)        | Chat Token Transcoder     |
| [globalkey](globalkey)| [Baklava](baklava)'s Global Keystroke Listener |


## Branches

- staging -> pr this branch for everything
- prod -> don't touch, this is what's running in prod

## Contributions

DogeHouse is open to contributions, but I recommend creating an issue or replying in a comment to let me know what you are working on first that way we don't overwrite each other.

Please read [CONTRIBUTING.md](https://github.com/benawad/dogehouse/blob/staging/CONTRIBUTING.md) for details on this project.

## DogeHouse Desktop

A desktop app built with [Electron](https://www.electronjs.org/) is available for Windows, Mac, and Linux.

There are different ways to get the Electron desktop app:

* Get the official builds from [here, in GitHub Releases][gh-releases]
for any platform.
* Get it from AUR (unofficial package) for Arch/Manjaro or other Arch-based distro with
`yay -S dogehouse`, using another AUR helper, or installing manually from the AUR.
* Get the desktop client for Debian-based distros (including Ubuntu)
from the official APT repo with these simple steps:
  * Add the repo with `echo "deb http://ppa.dogehouse.tv/ ./" | sudo tee -a /etc/apt/sources.list > /dev/null`
  * Add Ben Awad's GPG key with `$(command -v curl>>/dev/null && echo "curl -o-" || echo "wget -q0-") http://ppa.dogehouse.tv/KEY.gpg | sudo apt-key add -`.
  * Finally, update your local repository list and install DogeHouse
with `sudo apt update && sudo apt install dogehouse`.
* Get the snap for your systemd-powered Linux distro from either the
[Snap Store](https://snapcraft.io/dogehouse) or in an terminal with
`sudo snap install dogehouse`.
  * After installing the snap, you need to allow microphone access with
`sudo snap connect dogehouse:audio-record` to be able to speak in rooms.

[gh-releases]: https://github.com/benawad/dogehouse/releases/latest

**_Notes:_**

- If a warning message pops up on Windows, go to 'more info' and select 'Run Anyway'
- Currently, the snap package's available channels are only `edge` as
contributions for Baklava are merged almost on daily basis. Tested
versions that are stable will be promoted into `stable` in the future.

## DogeReviewers

Contributors helping to review/merge pull requests:

- [@HarrisonMayotte](https://github.com/HarrisonMayotte)
- [@TheOtterlord](https://github.com/TheOtterlord)
- [@amitojsingh366](https://github.com/amitojsingh366)
- [@dk-raw](https://github.com/dk-raw)
- [@ermalsh](https://github.com/ermalsh)
- [@goldyydev](https://github.com/goldyydev)
- [@jamesql](https://github.com/jamesql)
- [@nadirabbas](https://github.com/nadirabbas)
- [@ofsho](https://github.com/ofsho)
- [@overlisted](https://github.com/overlisted)

## Code of Conduct

Please read [CODE_OF_CONDUCT.md](https://github.com/benawad/dogehouse/blob/staging/CODE_OF_CONDUCT.md) for details on our code of conduct.

## How to run locally

Check <a href="https://github.com/benawad/dogehouse/blob/staging/CONTRIBUTING.md#quickstart-local-frontend-development">here</a> on how to run locally</a>

## Why did you make this?

https://www.youtube.com/watch?v=hy-EhJ_tTQo

## Attribution

For emojis, we use [Twemoji](https://twemoji.twitter.com/)


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Reporting a Vulnerability

DM me on https://twitter.com/benawad or https://discord.gg/wCbKBZF9cV


================================================
FILE: baklava/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/builds
/dist

#Builds
DogeHouse*

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
.eslintcache
.netlify

# yarn v2
.yarn/*
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions

================================================
FILE: baklava/.yarnrc.yml
================================================
nodeLinker: node-modules

plugins:
  - path: ../.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
    spec: "@yarnpkg/plugin-workspace-tools"
  - path: ../.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
    spec: "@yarnpkg/plugin-interactive-tools"

yarnPath: ../.yarn/releases/yarn-berry.cjs

================================================
FILE: baklava/README.md
================================================
# Dogehouse for Desktop (Baklava)

This is the desktop application for Dogehouse.
It uses ElectronJS as a wrapper for [dogehouse.tv](https://dogehouse.tv) and adds other native capabilities.

## Features

- Notifications
- System tray
- Global keybinds
- Splash screen
- Localization
- Discord RPC

## How to run

> NOTE: Windows users may have to install Visual Studio 2019 and the workload `Desktop Development with C++`.

- Run `yarn install`
- Ensure [Rust](https://www.rust-lang.org/learn/get-started) is installed
- Install `nj-cli` by running `cargo install nj-cli`
- Run `yarn build:globalkey`
- Run `yarn start`
- _(Optional)_ Run `yarn build:%YOUR_PLATFORM_CODE%` and install the app from the build _(located in `/builds`)_

If you encounter any errors while building please create a new issue for it or ask for help on the [Discord](https://discord.gg/wCbKBZF9cV0).

## Using hot reload

The electron wrapper has the capability for hot reloads during development.
You can run the app in hot reload mode using `yarn dev`.

While in hot reload mode, any time you save changes to a `ts` file, the electron app will recompile and relaunch itself.
To exit hot reload mode, use `Ctrl+C` in the console. This will however, leave the current app window open, so be sure to close that also, as it will no longer have access to hot reload.

## Translations

Translations are stored in `baklava/locales` and loaded using the `i18next` library.
You can add new languages by creating a folder with the correct [language code](https://www.electronjs.org/docs/api/locales) and adding the `translate.json` file.
All keys are present in `baklava/src/generated/translationKeys.ts`, so it's a good idea to use it for reference.

You can sync the files and generate missing keys using `yarn i18`.


================================================
FILE: baklava/locales/en/translate.json
================================================
{
  "common": {
    "title": "Dogehouse"
  },
  "splash": {
    "check": "Checking for updates...",
    "download": "Downloading Updates...",
    "relaunch": "Relaunching...",
    "launch": "Launching...",
    "skipCheck": "Skipping update checks...",
    "notfound": "No updates found..."
  }
}

================================================
FILE: baklava/package.json
================================================
{
    "name": "dogehouse",
    "version": "1.0.69",
    "description": "Taking voice conversations to the moon 🚀",
    "main": "./dist/electron.js",
    "scripts": {
        "compile": "tsc",
        "watch": "tsc -w",
        "dev": "yarn compile && node ./dist/dev.js",
        "start": "yarn compile && electron ./dist/electron.js",
        "gen:i18:keys": "ts-node --project scripts/tsconfig.json scripts/generateTranslationTypes.ts",
        "sync:i18": "ts-node --project scripts/tsconfig.json scripts/syncTranslations.ts",
        "i18": "npm run gen:i18:keys && npm run sync:i18",
        "build:all": "yarn compile && electron-builder -mwl",
        "build:mac": "yarn compile && electron-builder --mac",
        "build:win": "yarn compile && electron-builder --win",
        "build:linux": "yarn compile && electron-builder --linux",
        "build:overlay": "cd resources/overlay && yarn build && cd ../../",
        "build:globalkey": "yarn remove globalkey && yarn add globalkey && cd node_modules/globalkey && npx electron-build-env nj-cli build --release",
        "delete:artifacts": "yarn delete:globalkey_artifacts && yarn delete:overlay_yarn_cache",
        "delete:globalkey_artifacts": "cd node_modules/globalkey && del-cli target src && cd ../../",
        "delete:overlay_yarn_cache": "cd resources/overlay && del-cli .yarn && cd ../../"
    },
    "keywords": [
        "DogeHouse",
        "Electron",
        "voice-chat",
        "Doge"
    ],
    "author": "Ben Awad <benawadapps@gmail.com>",
    "homepage": "https://github.com/benawad/dogehouse/",
    "repository": {
        "type": "git",
        "url": "https://github.com/benawad/dogehouse"
    },
    "bugs": {
        "url": "https://github.com/benawad/dogehouse/issues"
    },
    "license": "MIT",
    "build": {
        "appId": "com.electron.dogehouse",
        "productName": "DogeHouse",
        "afterSign": "electron-builder-notarize",
        "mac": {
            "hardenedRuntime": true,
            "icon": "icons/icon.png",
            "category": "public.app-category.social-networking",
            "entitlements": "settings/entitlements.mac.plist",
            "extendInfo": {
                "NSMicrophoneUsageDescription": "Mic access for speech input in voice."
            },
            "target": [
                "dmg",
                "zip"
            ]
        },
        "win": {
            "icon": "icons/icon.png",
            "target": "nsis",
            "publish": [
                "github"
            ]
        },
        "linux": {
            "icon": "icons/icon.png",
            "target": [
                "deb",
                "AppImage",
                "snap",
                "tar.gz",
                "rpm"
            ],
            "category": "AudioVideo"
        },
        "snap": {
            "confinement": "strict",
            "plugs": [
                "default",
                "audio-playback",
                "audio-record",
                {
                    "browser-support": {
                        "interface": "browser-support",
                        "allow-sandbox": false
                    }
                }
            ]
        },
        "extraMetadata": {
            "main": "dist/electron.js"
        },
        "directories": {
            "output": "./builds"
        },
        "extends": null
    },
    "devDependencies": {
        "@types/discord-rpc": "^3.0.5",
        "@types/i18next-node-fs-backend": "^2.1.0",
        "@types/lodash": "^4.14.168",
        "@types/node": "^14.14.31",
        "@types/prettier": "^2.2.3",
        "builder-util": "^22.10.5",
        "del-cli": "^3.0.1",
        "electron": "^12.0.2",
        "electron-build-env": "^0.2.0",
        "electron-builder": "^22.10.5",
        "electron-builder-notarize": "^1.2.0",
        "lodash": "^4.17.21",
        "prettier": "^2.2.1",
        "pretty-quick": "^3.1.0",
        "ts-node": "^9.1.1",
        "typescript": "^4.2.2"
    },
    "dependencies": {
        "discord-rpc": "^3.2.0",
        "dotenv": "^8.2.0",
        "electron-log": "^4.3.2",
        "electron-overlay-window": "^1.0.4",
        "electron-updater": "^4.3.8",
        "globalkey": "^1.0.7",
        "i18next": "^20.0.0",
        "i18next-node-fs-backend": "^2.1.3"
    },
    "files": [
        "./icons/**/*",
        "./resources/**/*"
    ]
}

================================================
FILE: baklava/resources/overlay/.gitignore
================================================
/node_modules
/build

# yarn v2
.yarn/*
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions

================================================
FILE: baklava/resources/overlay/.yarnrc.yml
================================================
nodeLinker: node-modules

plugins:
  - path: ../../../.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
    spec: "@yarnpkg/plugin-workspace-tools"
  - path: ../../../.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
    spec: "@yarnpkg/plugin-interactive-tools"

yarnPath: ../../../.yarn/releases/yarn-berry.cjs

================================================
FILE: baklava/resources/overlay/README.md
================================================
# Getting Started with Create React App

This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).

## Available Scripts

In the project directory, you can run:

### `yarn start`

Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.\
You will also see any lint errors in the console.

### `yarn test`

Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.

### `yarn build`

Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.

### `yarn eject`

**Note: this is a one-way operation. Once you `eject`, you can’t go back!**

If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.

Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.

You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.

## Learn More

You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

To learn React, check out the [React documentation](https://reactjs.org/).

### Code Splitting

This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)

### Analyzing the Bundle Size

This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)

### Making a Progressive Web App

This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)

### Advanced Configuration

This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)

### Deployment

This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)

### `yarn build` fails to minify

This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)


================================================
FILE: baklava/resources/overlay/package.json
================================================
{
  "name": "dogehouse-baklava-overlay",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-icons": "^4.2.0",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.0.1"
  },
  "scripts": {
    "start": "set PORT=5000 && react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "homepage": "./"
}


================================================
FILE: baklava/resources/overlay/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>Dogehouse Overlay</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>


================================================
FILE: baklava/resources/overlay/src/App.css
================================================
.App {
  text-align: center;
  background: rgba(0, 0, 0, 0);
  /* background: #ffffff; */
}

img{
  border-radius: 50%;
  width: 40px;
  height: 40px;
}

.active-speaker{
  border: solid #60A5FA 3px;
  border-radius: 50%;
  width: 40px;
  float: left;
  height: 40px;
}

.img-div{
  display:inline;
}

.name-div{
  display:inline; 
  white-space:nowrap;
}

.active-speaker-cont {
  background: rgba(255, 255, 255, 0.2);
  white-space:nowrap;
  border-radius: 10%;
  width: max-content;
  margin: 5px;
  padding: 2px;
}

.speaker-muted{
  position: relative;
  bottom: 0;
  right: 0;
}

.left{
  float:left;
}

================================================
FILE: baklava/resources/overlay/src/App.js
================================================
import './App.css';
import { useEffect, useState } from 'react';
// import { FiMicOff } from "react-icons/fi";

const ipcRenderer = window.require("electron").ipcRenderer;

function App() {
  const [speakers, setSpeakers] = useState([]);
  useEffect(() => {
    ipcRenderer.send("@overlay/start_ipc", true);
    ipcRenderer.on("@overlay/overlayData", (event, data) => {
      if (data.currentRoom) {
        let s = [];
        data.currentRoom.users.forEach((u) => {
          if (u.roomPermissions) {
            if (
              u.roomPermissions.isSpeaker ||
              data.currentRoom.room.creatorId === u.id
            ) {
              u.isSpeaking = false;
              u.isMuted = false;
              if (data.currentRoom.activeSpeakerMap[u.id]) {
                u.isSpeaking = true;
              }
              if (data.currentRoom.muteMap[u.id]) {
                u.isMuted = true;
              }
              s.push(u);
            }
          } else {
            if (data.currentRoom.room.creatorId === u.id) {
              u.isSpeaking = false;
              u.isMuted = false;
              if (data.currentRoom.activeSpeakerMap[u.id]) {
                u.isSpeaking = true;
              }
              if (data.currentRoom.muteMap[u.id]) {
                u.isMuted = true;
              }
              s.push(u);
            }
          }

          console.log(u);
        });
        setSpeakers(s);
      }
    });
  }, []);

  return (
    <div className="App" width="100%">
      {speakers &&
        speakers.map((speaker) => (
          <SpeakerIcon speaker={speaker} key={speaker.id} />
        ))}
    </div>
  );
}

function SpeakerIcon(props) {
  return (
    <div>
      <div
        className={
          props.speaker.isSpeaking ? "active-speaker-cont left" : "left"
        }
      >
        <div className="img-div">
          <img
            alt="speaker bubble"
            width="50px"
            height="50px"
            className={props.speaker.isSpeaking ? "active-speaker" : ""}
            src={props.speaker.avatarUrl}
          />
          {/* {props.speaker.isMuted ?
          <div className="speaker-muted">
            <FiMicOff />
          </div>
          : null} */}
        </div>
        {/* {props.speaker.isSpeaking ? <div className="name-div"> <p>{props.speaker.displayName}</p> </div> : null} */}
      </div>
    </div>
  );
}

export default App;


================================================
FILE: baklava/resources/overlay/src/index.css
================================================
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}


================================================
FILE: baklava/resources/overlay/src/index.js
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();


================================================
FILE: baklava/resources/overlay/src/reportWebVitals.js
================================================
const reportWebVitals = onPerfEntry => {
  if (onPerfEntry && onPerfEntry instanceof Function) {
    import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(onPerfEntry);
      getFID(onPerfEntry);
      getFCP(onPerfEntry);
      getLCP(onPerfEntry);
      getTTFB(onPerfEntry);
    });
  }
};

export default reportWebVitals;


================================================
FILE: baklava/resources/splash/splash-screen.html
================================================
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DogeHouse</title>
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/inter-ui/3.18.0/inter.css" rel="stylesheet">
</head>

<body>
    <style>
        :root {
            user-select: none;
        }

        body {
            background-color: rgba(0, 0, 0, 0);
        }

        #progress {
            width: 75%;
            height: 10px;
            background-color: #242C37;
            border-radius: 10px;
        }

        #bar {
            height: 10px;
            width: 40%;
            background-color: #FD4D4D;
            border-radius: 10px;
            transition: width 2s;
        }
    </style>
    <div
        style="background-color: #0B0E11; border-radius: 5%; height: 400px; width: 300px; position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); -webkit-app-region: drag;">
        <img style="height:120px; position:fixed; top:35%; left:50%; transform:translate(-50%, -50%);"
            src="../../icons/icon.png" alt="DogeHouse Logo">
        <h4
            style="color: #B2BDCD; font-family: 'Inter'; position:fixed; top:68%; left:50%; transform:translate(-50%, -50%); width: 100%; text-align: center;">
        </h4>

        <div id="progress" style="position:fixed; top:83%; left:50%; transform:translate(-50%, -50%); display: none;">
            <div id="bar"></div>
        </div>

        <script>
            const { ipcRenderer } = require('electron');
            const header = document.querySelector('h4');
            let locale;
            ipcRenderer.on('@locale/text', (ev, text) => {
                locale = text;
                document.title = locale.title;
                header.textContent = locale.check;
            });
            ipcRenderer.on('download', () => {
                header.textContent = locale.download;
            });
            ipcRenderer.on('percentage', (event, percent) => {
                header.textContent = `${locale.download} ${JSON.stringify(percent)}%`;
                document.getElementById('progress').style.display = 'inherit';
                document.getElementById('bar').style.width = `${JSON.stringify(percent)}%`;
            });
            ipcRenderer.on('relaunch', () => {
                header.textContent = locale.relaunch;
            });
            ipcRenderer.on('launch', () => {
                header.textContent = locale.launch;
            });
            ipcRenderer.on('skipCheck', () => {
                header.textContent = locale.skipCheck;
            });
            ipcRenderer.on('notfound', () => {
                header.textContent = locale.notfound;
            });
        </script>
    </div>
</body>

</html>

================================================
FILE: baklava/scripts/generateTranslationTypes.ts
================================================
import fs from "fs";
import { join } from "path";
import prettier from "prettier";
import { traverseTranslations } from "./traverseTranslations";

const s = `
// this is autogenerated by running \`npm run gen:i18:keys\`
export type TranslationKeys =
${traverseTranslations()
	.map((k) => `  "${k}"`)
	.join("|\n")}
`;

fs.writeFileSync(
	join(__dirname, "../src/generated/translationKeys.ts"),
	prettier.format(s, { parser: "babel", useTabs: true })
);


================================================
FILE: baklava/scripts/syncTranslations.ts
================================================
// @ts-ignore
import config from "../../.prettierrc.js";
import english from "../locales/en/translate.json";
import * as fs from "fs";
import { join } from "path";
import prettier from "prettier";
import { traverseTranslations } from "./traverseTranslations";
import { get, set } from "lodash";

const paths = traverseTranslations();

fs.readdirSync(join(__dirname, "../locales")).forEach((locale) => {
  if (locale === "en") {
    return;
  }
  const filename = join(
    __dirname,
    "../public/locales",
    locale,
    "translation.json"
  );
  let data: any;
  try {
    data = JSON.parse(fs.readFileSync(filename, { encoding: "utf-8" }));
  } catch (err) {
    throw new Error(`${locale}: ${err.message}`);
  }
  paths.forEach((p) => {
    if (get(data, p, null) === null) {
      set(data, p, get(english, p));
    }
  });

  fs.writeFileSync(
    filename,
    prettier.format(JSON.stringify(data), {
      parser: "json",
      useTabs: true,
      ...config,
    })
  );
});


================================================
FILE: baklava/scripts/traverseTranslations.ts
================================================
import translations from "../locales/en/translate.json";

const keys: string[] = [];

type TranslationRecord = {
	[P in string]: string | TranslationRecord;
};

const _traverseTranslations = (obj: TranslationRecord, path: string[]) => {
	Object.keys(obj).forEach((key) => {
		if (key.startsWith("_")) {
			return;
		}
		const objOrString = obj[key];
		if (typeof objOrString === "string") {
			keys.push([...path, key].join("."));
		} else {
			_traverseTranslations(objOrString, [...path, key]);
		}
	});
};

export const traverseTranslations = () => {
	_traverseTranslations(translations, []);
	return keys;
};


================================================
FILE: baklava/scripts/tsconfig.json
================================================
{
	"compilerOptions": {
		"target": "es6",
		"module": "commonjs",
		"lib": ["dom", "es6", "es2017", "esnext.asynciterable"],
		"sourceMap": true,
		"outDir": "./dist",
		"moduleResolution": "node",
		"removeComments": true,
		"noImplicitAny": true,
		"strictNullChecks": true,
		"strictFunctionTypes": true,
		"noImplicitThis": true,
		"noUnusedLocals": true,
		"noUnusedParameters": true,
		"noImplicitReturns": true,
		"noFallthroughCasesInSwitch": true,
		"allowSyntheticDefaultImports": true,
		"esModuleInterop": true,
		"emitDecoratorMetadata": true,
		"experimentalDecorators": true,
		"resolveJsonModule": true,
		"baseUrl": "."
	},
	"exclude": ["node_modules"],
	"include": ["./*.ts"]
}


================================================
FILE: baklava/settings/entitlements.mac.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.device.audio-input</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
  </dict>
</plist>

================================================
FILE: baklava/src/constants.ts
================================================
import { app, shell } from "electron";
import { autoUpdater } from "electron-updater";

export const isMac = process.platform === "darwin";
export const isWin = process.platform === "win32";
export const isLinux =
  process.platform !== "darwin" && process.platform !== "win32";
export const REQUEST_TO_SPEAK_KEY = "@keybind/invite";
export const INVITE_KEY = "@keybind/invite";
export const MUTE_KEY = "@keybind/mute";
export const DEAF_KEY = "@keybind/deafen";
export const CHAT_KEY = "@keybind/chat";
export const PTT_KEY = "@keybind/ptt";
export const OVERLAY_KEY = "@keybind/overlay";

export const RPC_TRAY_OPTION_ID = "@tray/rpc";

const REPO_URL = "https://github.com/benawad/dogehouse/";
const DISCUSSION_URL = "https://github.com/benawad/dogehouse/discussions";
const ISSUES_URL = "https://github.com/benawad/dogehouse/issues";

export const ALLOWED_HOSTS = [
  "dogehouse.tv",
  "next.dogehouse.tv",
  "api.dogehouse.tv",
  "github.com",
  "localhost",
  "staging.dogehouse.tv",
  "doge-staging.stripcode.dev",
  "api.twitter.com",
  "twitter.com",
];

export const MENU_TEMPLATE: any = [
  ...(isMac
    ? [
      {
        label: app.name,
        submenu: [
          { role: "about" },
          { type: "separator" },
          { role: "services" },
          { type: "separator" },
          { role: "hide" },
          { role: "hideothers" },
          { role: "unhide" },
          { type: "separator" },
          { role: "quit" },
        ],
      },
    ]
    : []),
  {
    label: "File",
    submenu: [isMac ? { role: "close" } : { role: "quit" }],
  },
  {
    label: "Edit",
    submenu: [
      { role: "undo" },
      { role: "redo" },
      { type: "separator" },
      { role: "cut" },
      { role: "copy" },
      { role: "paste" },
      ...(isMac
        ? [
          { role: "pasteAndMatchStyle" },
          { role: "delete" },
          { role: "selectAll" },
          { type: "separator" },
          {
            label: "Speech",
            submenu: [{ role: "startSpeaking" }, { role: "stopSpeaking" }],
          },
        ]
        : [{ role: "delete" }, { type: "separator" }, { role: "selectAll" }]),
    ],
  },
  {
    label: "View",
    submenu: [
      { role: "reload" },
      { role: "forceReload" },
      { role: "toggleDevTools" },
      { type: "separator" },
      { role: "resetZoom" },
      { role: "zoomIn" },
      { role: "zoomOut" },
      { type: "separator" },
      { role: "togglefullscreen" },
    ],
  },
  {
    label: "Window",
    submenu: [
      { role: "minimize" },
      { role: "zoom" },
      ...(isMac
        ? [
          { type: "separator" },
          { role: "front" },
          { type: "separator" },
          { role: "window" },
        ]
        : [{ role: "close" }]),
    ],
  },
  {
    role: "help",
    submenu: [
      {
        label: "Learn More",
        click: async () => {
          await shell.openExternal(REPO_URL);
        },
      },
      {
        label: "Community Discussions",
        click: async () => {
          await shell.openExternal(DISCUSSION_URL);
        },
      },
      {
        label: "Search Issues",
        click: async () => {
          await shell.openExternal(ISSUES_URL);
        },
      },
      {
        label: "Check For Updates",
        click: async () => {
          autoUpdater.checkForUpdatesAndNotify();
        },
      },
    ],
  },
];


================================================
FILE: baklava/src/dev.ts
================================================
import { exec, ChildProcess } from 'child_process';

let compiler: ChildProcess;
let app: ChildProcess;

let env = process.env;
env.hotReload = 'true';

/**
 * Get a formatted timestamp for logging
 * @returns {string} A formatted timestamp (HH:MM:SS)
 */
function timestamp() {
  return new Date().toISOString().split('T')[1].split(".")[0];
}

/**
 * Start the hot reloader.
 * Creates a connection with the typescript compiler and listens for changes.
 * Once changes are compiled, the electron app is relaunched.
 */
function start() {
  console.log(`${timestamp()} - Starting hot reload`);
  compiler = exec('npm run watch');
  compiler.stdout?.on('data', data => {
    if (data.includes('Watching')) {
      if (app) console.log(`${timestamp()} - Detected changes`);
      app = exec('npm run start', {
        env
      });
      console.log(`${timestamp()} - Launching app`);
    }
  });
}

start();


================================================
FILE: baklava/src/electron.ts
================================================
import {
  BrowserWindow,
  app,
  systemPreferences,
  ipcMain,
  globalShortcut,
  shell,
  Tray,
  Menu,
} from "electron";
import i18n from "i18next";
import Backend from "i18next-node-fs-backend";
import { autoUpdater } from "electron-updater";
import { exitApp, RegisterKeybinds } from "./utils/keybinds";

import { HandleVoiceTray } from "./utils/tray";
import {
  ALLOWED_HOSTS,
  isLinux,
  isMac,
  isWin,
  MENU_TEMPLATE,
} from "./constants";
import path from "path";
import { StartNotificationHandler } from "./utils/notifications";
import { bWindowsType } from "./types";
import electronLogger from "electron-log";
import { startRPC } from "./utils/rpc";

let mainWindow: BrowserWindow;
let tray: Tray;
let menu: Menu;
let splash: BrowserWindow;

export let bWindows: bWindowsType;

export const __prod__ = app.isPackaged;
const instanceLock = app.requestSingleInstanceLock();
let shouldShowWindow = false;
let windowShowInterval: NodeJS.Timeout;
let skipUpdateTimeout: NodeJS.Timeout;

i18n.use(Backend);

electronLogger.transports.file.level = "debug";
autoUpdater.logger = electronLogger;
// just in case we have to revert to a build
autoUpdater.allowDowngrade = true;

if (isWin) app.setAppUserModelId("DogeHouse");

async function localize() {
  await i18n.init({
    lng: app.getLocale(),
    debug: false,
    backend: {
      // path where resources get loaded from
      loadPath: path.join(__dirname, "../locales/{{lng}}/translate.json"),
    },
    interpolation: {
      escapeValue: false,
    },
    saveMissing: true,
    fallbackLng: "en",
  });
}

function createMainWindow() {
  mainWindow = new BrowserWindow({
    width: 1500,
    height: 800,
    minWidth: 400,
    minHeight: 600,
    autoHideMenuBar: true,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
    frame: isLinux,
    show: false,
  });

  // applying custom menu
  menu = Menu.buildFromTemplate(MENU_TEMPLATE);
  Menu.setApplicationMenu(menu);

  // applying custom tray
  tray = new Tray(path.join(__dirname, `../icons/tray.png`));

  if (!__prod__) {
    mainWindow.webContents.openDevTools();
  }
  mainWindow.loadURL(
    __prod__ ? `https://dogehouse.tv/` : "http://localhost:3000"
  );

  bWindows = {
    main: mainWindow,
    overlay: undefined,
  };

  mainWindow.once("ready-to-show", () => {
    shouldShowWindow = true;
  });
  // crashes on mac only in dev
  // systemPreferences.askForMediaAccess("microphone");
  ipcMain.on("request-mic", async (event, _serviceName) => {
    const isAllowed: boolean = await systemPreferences.askForMediaAccess(
      "microphone"
    );
    event.returnValue = isAllowed;
  });
  if (isMac) {
    mainWindow.webContents.send("@alerts/permissions", true);
  }

  // start rpc
  startRPC();

  // registers global keybinds
  RegisterKeybinds(bWindows);

  // starting the custom voice menu handler
  HandleVoiceTray(mainWindow, tray);

  // starting the noti handler
  StartNotificationHandler();

  // graceful exiting
  mainWindow.on("closed", () => {
    globalShortcut.unregisterAll();
    if (bWindows.overlay) {
      bWindows.overlay.destroy();
    }
    mainWindow.destroy();
  });

  // handling external links
  const handleLinks = (event: any, url: string) => {
    let urlObj = new URL(url);
    let urlHost = urlObj.hostname;
    if (!ALLOWED_HOSTS.includes(urlHost)) {
      event.preventDefault();
      shell.openExternal(url);
    } else {
      if (
        (urlHost == ALLOWED_HOSTS[3] &&
          urlObj.pathname !== "/login" &&
          urlObj.pathname !== "/session" &&
          urlObj.pathname !== "/sessions/two-factor" &&
          urlObj.pathname !== "/sessions/two-factor/webauthn") ||
        (
          urlHost == ALLOWED_HOSTS[8] &&
          urlObj.pathname !== "/account/login_verification"
        )
      ) {
        event.preventDefault();
        shell.openExternal(url);
      }
    }
  };
  mainWindow.webContents.on("new-window", handleLinks);
  mainWindow.webContents.on("will-navigate", handleLinks);

  ipcMain.on("@dogehouse/loaded", (event, doge) => {
    if (isMac) mainWindow.maximize();
  });
  ipcMain.on("@app/quit", (event, args) => {
    mainWindow.close();
  });
  ipcMain.on("@app/maximize", (event, args) => {
    if (isMac) {
      if (mainWindow.isFullScreenable()) {
        mainWindow.setFullScreen(!mainWindow.isFullScreen());
      }
    } else {
      if (mainWindow.maximizable) {
        if (mainWindow.isMaximized()) {
          mainWindow.unmaximize();
        } else {
          mainWindow.maximize();
        }
      }
    }
  });
  ipcMain.on("@app/minimize", (event, args) => {
    if (mainWindow.minimizable) {
      mainWindow.minimize();
    }
  });

  ipcMain.on("@app/hostPlatform", (event, args) => {
    event.sender.send("@app/hostPlatform", {
      isLinux,
      isMac,
      isWin,
    });
  });
}

function createSplashWindow() {
  splash = new BrowserWindow({
    width: 300,
    height: 410,
    transparent: true,
    frame: false,
    resizable: false,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
  });
  splash.loadFile(
    path.join(__dirname, "../resources/splash/splash-screen.html")
  );
  splash.webContents.on("did-finish-load", () => {
    splash.webContents.send("@locale/text", {
      title: i18n.t("common.title"),
      check: i18n.t("splash.check"),
      download: i18n.t("splash.download"),
      relaunch: i18n.t("splash.relaunch"),
      launch: i18n.t("splash.launch"),
      skipCheck: i18n.t("splash.skipCheck"),
      notfound: i18n.t("splash.notfound"),
    });
  });
}

if (!instanceLock) {
  if (process.env.hotReload) {
    app.relaunch();
  }
  exitApp();
} else {
  app.on("ready", () => {
    localize().then(async () => {
      createSplashWindow();
      if (!__prod__) skipUpdateCheck(splash);
      if (__prod__ && !isLinux) await autoUpdater.checkForUpdates();
      if (isLinux && __prod__) {
        skipUpdateCheck(splash);
      }
    });
  });
  app.on("second-instance", (event, argv, workingDirectory) => {
    if (mainWindow) {
      if (process.env.hotReload) return mainWindow.close();
      if (mainWindow.isMinimized()) mainWindow.restore();
      mainWindow.focus();
    }
  });
}

autoUpdater.on("update-available", (info) => {
  splash.webContents.send("download", info);
  // skip the update if it takes more than 1 minute
  skipUpdateTimeout = setTimeout(() => {
    skipUpdateCheck(splash);
  }, 60000);
});
autoUpdater.on("download-progress", (progress) => {
  let prog = Math.floor(progress.percent);
  splash.webContents.send("percentage", prog);
  splash.setProgressBar(prog / 100);
  // stop timeout that skips the update
  if (skipUpdateTimeout) {
    clearTimeout(skipUpdateTimeout);
  }
});
autoUpdater.on("update-downloaded", () => {
  splash.webContents.send("relaunch");
  // stop timeout that skips the update
  if (skipUpdateTimeout) {
    clearTimeout(skipUpdateTimeout);
  }
  setTimeout(() => {
    autoUpdater.quitAndInstall();
  }, 1000);
});
autoUpdater.on("update-not-available", () => {
  skipUpdateCheck(splash);
});
app.on("window-all-closed", async () => {
  exitApp();
});
app.on("activate", () => {
  if (mainWindow === null) {
    localize().then(() => {
      createMainWindow();
    });
  }
});

function skipUpdateCheck(splash: BrowserWindow) {
  createMainWindow();
  splash.webContents.send("notfound");
  if (isLinux || !__prod__) {
    splash.webContents.send("skipCheck");
  }
  // stop timeout that skips the update
  if (skipUpdateTimeout) {
    clearTimeout(skipUpdateTimeout);
  }
  windowShowInterval = setInterval(() => {
    if (shouldShowWindow) {
      splash.webContents.send("launch");
      clearInterval(windowShowInterval);
      setTimeout(() => {
        splash.destroy();
        mainWindow.show();
      }, 800);
    }
  }, 1000);
}


================================================
FILE: baklava/src/generated/translationKeys.ts
================================================
// this is autogenerated by running `npm run gen:i18:keys`
export type TranslationKeys =
	| "common.title"
	| "splash.check"
	| "splash.download"
	| "splash.relaunch"
	| "splash.launch";


================================================
FILE: baklava/src/types.ts
================================================
import { BrowserWindow } from "electron"

export type bWindowsType = {
    main: BrowserWindow,
    overlay: BrowserWindow | undefined
}


================================================
FILE: baklava/src/utils/keybinds.ts
================================================
import {
    ipcMain,
    globalShortcut,
    app,
} from "electron";
import {
    CHAT_KEY,
    INVITE_KEY,
    MUTE_KEY,
    PTT_KEY,
    REQUEST_TO_SPEAK_KEY,
    OVERLAY_KEY,
    isMac,
    DEAF_KEY,
} from "../constants";
import { overlayWindow } from "electron-overlay-window";
import { createOverlay } from "./overlay";
import { startOverlayIPCHandler } from "./overlay/ipc";
import { bWindowsType } from "../types";

import globalkey from 'globalkey';
import { stopRPC } from "./rpc";

export let CURRENT_REQUEST_TO_SPEAK_KEY = "Control+8";
export let CURRENT_INVITE_KEY = "Control+7";
export let CURRENT_MUTE_KEY = "Control+m";
export let CURRENT_DEAF_KEY = "Control+1";
export let CURRENT_CHAT_KEY = "Control+9";
export let CURRENT_OVERLAY_KEY = "Control+2";
export let CURRENT_PTT_KEY = ["0", "Control"];
export let CURRENT_PTT_KEY_STRING = "0,control"

export let CURRENT_APP_TITLE = "";

let PREV_PTT_STATUS = false;

export let worker: Worker;

export async function RegisterKeybinds(bWindows: bWindowsType) {
    ipcMain.on(REQUEST_TO_SPEAK_KEY, (event, keyCode) => {
        if (globalShortcut.isRegistered(CURRENT_REQUEST_TO_SPEAK_KEY)) {
            globalShortcut.unregister(CURRENT_REQUEST_TO_SPEAK_KEY);
        }
        CURRENT_REQUEST_TO_SPEAK_KEY = keyCode;
        globalShortcut.register(keyCode, () => {
            bWindows.main.webContents.send(REQUEST_TO_SPEAK_KEY, keyCode);
        })
    });
    ipcMain.on(INVITE_KEY, (event, keyCode) => {
        if (globalShortcut.isRegistered(CURRENT_INVITE_KEY)) {
            globalShortcut.unregister(CURRENT_INVITE_KEY);
        }
        CURRENT_INVITE_KEY = keyCode;
        globalShortcut.register(keyCode, () => {
            bWindows.main.webContents.send(INVITE_KEY, keyCode);
        })
    });
    ipcMain.on(MUTE_KEY, (event, keyCode) => {
        if (globalShortcut.isRegistered(CURRENT_MUTE_KEY)) {
            globalShortcut.unregister(CURRENT_MUTE_KEY);
        }
        CURRENT_MUTE_KEY = keyCode
        globalShortcut.register(keyCode, () => {
            bWindows.main.webContents.send(MUTE_KEY, keyCode);
        })
    });
    ipcMain.on(DEAF_KEY, (event, keyCode) => {
        if (globalShortcut.isRegistered(CURRENT_DEAF_KEY)) {
            globalShortcut.unregister(CURRENT_DEAF_KEY);
        }
        CURRENT_DEAF_KEY = keyCode
        globalShortcut.register(keyCode, () => {
            bWindows.main.webContents.send(DEAF_KEY, keyCode);
        })
    });
    ipcMain.on(CHAT_KEY, (event, keyCode) => {
        if (globalShortcut.isRegistered(CURRENT_CHAT_KEY)) {
            globalShortcut.unregister(CURRENT_CHAT_KEY);
        }
        CURRENT_CHAT_KEY = keyCode;
        globalShortcut.register(keyCode, () => {
            bWindows.main.webContents.send(CHAT_KEY, keyCode);
        })
    });
    ipcMain.on(PTT_KEY, (event, keyCode: string) => {
        if (keyCode.includes("+")) {
            let keys = keyCode.split("+");
            CURRENT_PTT_KEY = keys;
        } else {
            CURRENT_PTT_KEY = [keyCode];
        }
        CURRENT_PTT_KEY = CURRENT_PTT_KEY.sort();
        CURRENT_PTT_KEY_STRING = CURRENT_PTT_KEY.join().toLowerCase();
    });

    ipcMain.on(OVERLAY_KEY, (event, keyCode) => {
        if (globalShortcut.isRegistered(CURRENT_OVERLAY_KEY)) {
            globalShortcut.unregister(CURRENT_OVERLAY_KEY);
        }
        CURRENT_OVERLAY_KEY = keyCode;
        globalShortcut.register(keyCode, () => {
            if (!isMac) {
                if (bWindows.overlay) {
                    if (!bWindows.overlay.isVisible()) {
                        bWindows.overlay.show();
                        bWindows.main.webContents.send("@overlay/start_ipc", true);
                    } else {
                        bWindows.overlay.hide();
                        bWindows.main.webContents.send("@overlay/start_ipc", true);
                    }
                } else {
                    bWindows.overlay = createOverlay(CURRENT_APP_TITLE, overlayWindow);
                    startOverlayIPCHandler(bWindows.main, bWindows.overlay);
                }
            }
        })
    });

    ipcMain.on("@overlay/app_title", (event, appTitle: string) => {
        CURRENT_APP_TITLE = appTitle;
    })

    globalkey.start(
        down => {
            down.forEach((key: any) => {
                let i = down.indexOf(key);
                down[i] = down[i].replace("L", "");
                down[i] = down[i].replace("R", "");
                down[i] = down[i].replace("Key", "");
            });
            down = down.sort()
            const keyString = down.join().toLowerCase();
            let PTT = keyString !== CURRENT_PTT_KEY_STRING;
            if (PREV_PTT_STATUS !== PTT) {
                bWindows.main.webContents.send("@voice/ptt_status_change", PTT);
                PREV_PTT_STATUS = PTT;
            }
        },
        up => { }
    );
}

export function exitApp() {
    globalkey.stop();
    stopRPC();
    app.quit();
}


================================================
FILE: baklava/src/utils/notifications.ts
================================================
import {
    ipcMain,
    Notification
} from "electron";

export async function StartNotificationHandler() {
    if (Notification.isSupported()) {
        ipcMain.on("@notification/mention", (event, msg) => {
            let body = "";
            msg.tokens.forEach((token) => {
                if (token.t == "mention") {
                    body += "@" + token.v + " "
                } else {
                    body += token.v + " "
                }
            });
            let notification = {
                title: msg.displayName,
                body,
            }
            new Notification(notification).show()
        })
        ipcMain.on("@notification/invitation", (event, invite) => {
            let notification = {
                title: "Room Invitation",
                body: `${invite.username} has invited you to ${invite.roomName}`,
            }
            new Notification(notification).show()
        })
        ipcMain.on("@notification/indirect_invitation", (event, invite) => {
            let notification = {
                title: "DogeHouse",
                body: `${invite.username} has just created ${invite.roomName}\nJoin them now!`,
            }
            new Notification(notification).show()
        })
        ipcMain.on("@notification/mod", (event, isMod: boolean) => {
            let notification = {
                title: "DogeHouse",
                body: `You are ${isMod ? "now" : "no longer"} a mod`,
            }
            new Notification(notification).show()
        })
    }
}


================================================
FILE: baklava/src/utils/overlay/index.ts
================================================
import { BrowserWindow } from 'electron';
import * as path from "path";
import { __prod__ } from '../../electron';

export function createOverlay(target: string, OW: any) {
    const overLay = new BrowserWindow({
        width: 400,
        height: 300,
        webPreferences: {
            nodeIntegration: true,
        },
        ...OW.WINDOW_OPTS,
    });
    overLay.loadFile(path.join(__dirname, "../../resources/overlay/build/index.html"));
    //overLay.loadURL("http://localhost:5000");
    OW.attachTo(overLay, target);
    return overLay;
}


================================================
FILE: baklava/src/utils/overlay/ipc.ts
================================================
import {
    ipcMain,
    BrowserWindow,
} from "electron";

export async function startOverlayIPCHandler(mainWindow: BrowserWindow, overlayWindow: BrowserWindow) {
    ipcMain.on("@overlay/start_ipc", (event, data) => {
        if (overlayWindow) {
            mainWindow.webContents.send("@overlay/start_ipc", true);
        }
    });
    ipcMain.on("@room/data", (event, data) => {
        if (overlayWindow) {
            overlayWindow.webContents.send("@overlay/overlayData", data);
        }
    });
}

================================================
FILE: baklava/src/utils/rpc/index.ts
================================================
import { Client, Presence } from "discord-rpc";
import logger from "electron-log";
import { startRPCIPCHandler, stopRPCIPCHandler } from "./ipc";
import dotenv from "dotenv";
// @ts-ignore
import { DISCORD_CLIENT_ID } from "../../constants";

dotenv.config();

const clientId = DISCORD_CLIENT_ID || process.env.DISCORD_CLIENT_ID;
let client: Client;

export let RPC_RUNNING = false;
const defaultData: Presence = {
  largeImageKey: "logo",
  largeImageText: "DogeHouse",
  instance: true,
};

export async function startRPC() {
  client = new Client({ transport: "ipc" });
  client.login({ clientId }).catch((e) => {
    logger.error(e);
  });

  client.on("ready", () => {
    RPC_RUNNING = true;
    startRPCIPCHandler();
    setPresence({ details: "Logging In..." });
  });
}

export async function setPresence(data: Presence) {
  if (RPC_RUNNING) {
    client.setActivity(Object.assign(data, defaultData));
  }
}

// added this for when there will be a electron settings page
export async function stopRPC() {
  stopRPCIPCHandler();
  client.destroy();
  RPC_RUNNING = false;
}


================================================
FILE: baklava/src/utils/rpc/ipc.ts
================================================
import { Presence } from "discord-rpc";
import { ipcMain } from "electron";
import { setPresence } from "./index";
let inRoom = false;
let PREV_PAGE_DATA: {
  page: string;
  opened: boolean;
  modal: boolean;
  data: any;
};
const START_TIME = Date.now();
const ROOM_DATA_UPDATE_FUNC = (event, data) => {
  if (inRoom) {
    let voiceState = "Muted";
    let isMuted = true;
    let isDeafened = false;
    let isSpeaker = false;
    if (data.currentRoom) {
      // kofta dosent send currentRoom.room
      if (!data.currentRoom.room) {
        data.currentRoom.room = data.currentRoom;
      }
      let isPrivate = data.currentRoom.room.isPrivate;
      let meInRoom = data.currentRoom.users.find((u) => u.id == data.me.id);
      if (meInRoom) {
        if (meInRoom.roomPermissions) {
          isSpeaker = meInRoom.roomPermissions.isSpeaker;
        } else if (data.currentRoom.room.creatorId === data.me.id) {
          isSpeaker = true;
        }
      }
      if (isSpeaker) {
        isMuted = data.muted;
        voiceState = isMuted ? "Muted" : "Unmuted";
      }
      if (data.deafened) {
        isDeafened = data.deafened;
        voiceState = isDeafened ? "Deafened" : voiceState;
      }
      let pdata: Presence = {
        state: isPrivate
          ? "In a private room"
          : `In ${data.currentRoom.room.name}`,
      };
      if (!isPrivate) {
        pdata.details = isSpeaker
          ? `Speaking (${data.currentRoom.users.length} of ထ)`
          : `Listening (${data.currentRoom.users.length} of ထ)`;
        pdata.partyId = data.currentRoom.room.id;
        pdata.startTimestamp = new Date(data.currentRoom.room.inserted_at).getTime();
        pdata.smallImageKey = !isDeafened ? isSpeaker && !isMuted ? "mic_on" : "mic_off" : "speaker_off";
        pdata.smallImageText = isSpeaker ? `Speaker - ${voiceState}` : isDeafened ? `Listener - ${voiceState}` : `Listener`;
        pdata.buttons = [
          {
            label: "Join Room",
            url: `https://dogehouse.tv/room/${data.currentRoom.room.id}`,
          },
        ];
      }
      setPresence(pdata);
    }
  }
};
const ROOM_JOINED_FUNC = (event, newinRoom) => {
  inRoom = newinRoom;
};

const PAGE_UPDATE_FUNC = (
  event,
  pageData: { page: string; opened: boolean; modal: boolean; data: any }
) => {
  if (!inRoom) {
    if (pageData.opened) {
      if (!pageData.modal) PREV_PAGE_DATA = pageData;
      let presence: Presence = {
        partyId: "dogehouse69funnyhaha",
        startTimestamp: START_TIME,
      };
      switch (pageData.page) {
        case "home":
          presence.details = "Browsing Rooms";
          presence.state = `${pageData.data} public rooms`;

          break;
        case "voice-settings":
          presence.details = "User Settings";
          presence.state = "Editing Voice Settings";
          break;
        case "overlay-settings":
          presence.details = "User Settings";
          presence.state = "Editing Overlay Settings";
          break;
        case "sound-effect-settings":
          presence.details = "User Settings";
          presence.state = "Editing Sound Effect Settings";
          break;
        case "profile":
          presence.details = "User Profile";
          presence.state = `Viewing @${pageData.data}`;
          break;
        case "edit-profile":
          presence.details = "User Settings";
          presence.state = "Editing Profile";
          break;
        default:
          presence.details = "Taking DogeHouse to the moon";
          break;
      }
      setPresence(presence);
    } else {
      if (PREV_PAGE_DATA) {
        PAGE_UPDATE_FUNC(event, PREV_PAGE_DATA);
      } else {
        setPresence({ details: "Taking DogeHouse to the moon" });
      }
    }
  }
};

export async function startRPCIPCHandler() {
  ipcMain.on("@rpc/page", PAGE_UPDATE_FUNC);
  ipcMain.on("@room/joined", ROOM_JOINED_FUNC);
  ipcMain.on("@room/data", ROOM_DATA_UPDATE_FUNC);
}

export async function stopRPCIPCHandler() {
  ipcMain.removeListener("@rpc/page", PAGE_UPDATE_FUNC);
  ipcMain.removeListener("@room/joined", ROOM_JOINED_FUNC);
  ipcMain.removeListener("@room/data", ROOM_DATA_UPDATE_FUNC);
}


================================================
FILE: baklava/src/utils/tray.ts
================================================
import {
    ipcMain,
    BrowserWindow,
    Menu,
    Tray,
    app
} from "electron";
import { autoUpdater } from "electron-updater";
import { MUTE_KEY } from "../constants";
import { RPC_RUNNING, startRPC, stopRPC } from "./rpc";

let voiceActive = false;

export async function HandleVoiceTray(mainWindow: BrowserWindow, tray: Tray) {
    let TRAY_MENU: any = [
        {
            label: "Quit Dogehouse",
            click: () => {
                mainWindow.close();
            },
        },
        {
            label: 'Toggle Mute',
            click: () => {
                mainWindow.webContents.send(MUTE_KEY, "Toggled mute from Menu");
            }
        },
        {
            label: "Check For Updates",
            click: () => {
                autoUpdater.checkForUpdatesAndNotify();
            },
        },
        {
            label: "Toggle Discord RPC",
            click: () => {
                if (RPC_RUNNING) {
                    stopRPC();
                } else {
                    startRPC()
                }
                TRAY_MENU[3].checked = RPC_RUNNING;
                let contextMenu = Menu.buildFromTemplate([TRAY_MENU[3], TRAY_MENU[2], seperator, TRAY_MENU[0]]);
                if (voiceActive) {
                    contextMenu = Menu.buildFromTemplate([TRAY_MENU[1], TRAY_MENU[3], TRAY_MENU[2], seperator, TRAY_MENU[0]]);
                } else {
                    contextMenu = Menu.buildFromTemplate([TRAY_MENU[3], TRAY_MENU[2], seperator, TRAY_MENU[0]]);
                }
                tray.setContextMenu(contextMenu);
                tray.setContextMenu(contextMenu)
            },
            checked: RPC_RUNNING
        },
    ];

    let seperator = { type: 'separator' };

    // create system tray
    tray.setToolTip("Taking voice conversations to the moon 🚀");
    tray.on("click", () => {
        mainWindow.focus();
    });

    let contextMenu = Menu.buildFromTemplate([TRAY_MENU[3], TRAY_MENU[2], seperator, TRAY_MENU[0]]);
    tray.setContextMenu(contextMenu);

    ipcMain.on("@room/joined", (event, isActive: boolean) => {
        voiceActive = isActive
        if (voiceActive) {
            contextMenu = Menu.buildFromTemplate([TRAY_MENU[1], TRAY_MENU[3], TRAY_MENU[2], seperator, TRAY_MENU[0]]);
        } else {
            contextMenu = Menu.buildFromTemplate([TRAY_MENU[3], TRAY_MENU[2], seperator, TRAY_MENU[0]]);
        }
        tray.setContextMenu(contextMenu);
    });
}


================================================
FILE: baklava/tsconfig.json
================================================
{
  "compilerOptions": {
    "outDir": "./dist",
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "baseUrl": ".",
    "rootDir": "src",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "noImplicitAny": false
  },
  "include": [
    "src/**/*.ts",
    "src/utils/overlay/*"
  ]
}

================================================
FILE: commitlint.config.js
================================================
module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    "scope-enum": [
      2,
      "always",
      [
        "global",
        "baklava",
        "dinner",
        "kibbeh",
        "kousa",
        "pilaf",
        "shawarma",
        "kebab",
        "dolma",
        "globalkey"
      ],
    ],
  },
};


================================================
FILE: dinner/.eslintrc.json
================================================
{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": ["eslint:recommended"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint/eslint-plugin"],
  "rules": {
    "no-unused-vars": "off",
    "no-empty": "off"
  }
}


================================================
FILE: dinner/.gitignore
================================================
node_modules

================================================
FILE: dinner/package.json
================================================
{
  "name": "dinner",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "ts-node src/create-accounts.ts",
    "audio": "ts-node src/play-audio.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@dogehouse/kebab": "workspace:kebab",
    "mediasoup-client": "^3.6.30",
    "mediasoup-client-aiortc": "^3.6.3"
  },
  "devDependencies": {
    "@types/node": "^14.14.22",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
  }
}


================================================
FILE: dinner/src/create-accounts.ts
================================================
import { http, raw, wrap } from "@dogehouse/kebab";
import { Connection } from "@dogehouse/kebab/lib/raw";

const main = async () => {
  const bot = http.wrap(http.create({ baseUrl: "http://localhost:4001" }));
  const tokens: Array<{ accessToken: string; refreshToken: string }> = [];

  for (let i = 0; i < 900; i++) {
    console.log(i);
    tokens.push(await bot.testUser("user" + i));
  }

  const conns: Connection[] = [];
  for (let i = 0; i < tokens.length; i++) {
    const { accessToken, refreshToken } = tokens[i];
    conns.push(
      await raw.connect(accessToken, refreshToken, {
        url: "ws://localhost:4001/socket",
      })
    );
  }

  for (const conn of conns) {
    await wrap(conn).query.joinRoomAndGetInfo("");
  }
};

main();


================================================
FILE: dinner/src/play-audio.ts
================================================
import { audioWrap, http, raw, wrap, Wrapper } from "@dogehouse/kebab";
import { connect as mediasoupConnect } from "@dogehouse/kebab/lib/audio/mediasoup-client";
import { Device } from "mediasoup-client";
import { createWorker, Worker } from "mediasoup-client-aiortc";
import path from "path";

async function makeMicTrack(
  worker: Worker,
  filepath = `../test-sounds/2sec.mp3`
) {
  const stream = await worker.getUserMedia({
    audio: {
      source: "file",
      file: path.join(__dirname, filepath),
    },
  });
  const audio = stream.getAudioTracks()[0];
  return audio as MediaStreamTrack;
}

let worker: Worker;
let device: Device;

export async function startAudio(wrapper: Wrapper) {
  worker = await createWorker({
    logLevel: "warn",
  });

  device = new Device({ handlerFactory: worker.createHandlerFactory() });

  wrapAudio(wrapper);
}

export async function wrapAudio(wrapper: Wrapper) {
  const audioWrapper = audioWrap(wrapper.connection);

  console.log("sub");
  const unsubYjap = audioWrapper.subscribe.youJoinedAsPeer(
    async ({ routerRtpCapabilities, recvTransportOptions }) => {
      unsubYjap();
      console.log("Yjap");
      await mediasoupConnect(
        wrapper.connection,
        routerRtpCapabilities,
        "output",
        recvTransportOptions,
        () => {}
      )(device);

      wrapper.connection.send("ask_to_speak", {});
      const unsubYbs = audioWrapper.subscribe.youBecameSpeaker(
        async ({ sendTransportOptions }) => {
          unsubYbs();
          console.log("Ybs");
          // OrouterRtpCapabilities = routerRtpCapabilities;
          // OsendTransportOptions = sendTransportOptions;
          let track = await makeMicTrack(worker, "../test-sounds/me.mp3");
          await mediasoupConnect(
            wrapper.connection,
            routerRtpCapabilities,
            "input",
            sendTransportOptions,
            track
          )(device);
        }
      );
    }
  );
}

const test = async () => {
  const bot = http.wrap(http.create({ baseUrl: "http://localhost:4001" }));
  const { accessToken, refreshToken } = await bot.testUser("user1");
  const conn = await raw.connect(accessToken, refreshToken, {
    url: "http://localhost:4001/socket",
    logger: (direction, opcode) => {
      if (opcode !== "ping") {
        console.log(direction, opcode);
      }
    },
  });
  const wrapper = wrap(conn);
  await startAudio(wrapper);
  await wrapper.query.joinRoomAndGetInfo(
    "d34c120e-3b76-49d7-b4a9-50be27f9e9af"
  );
};

test();


================================================
FILE: dinner/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "lib": [
      "dom",
      "es6",
      "es2017",
      "esnext.asynciterable"
    ],
    "sourceMap": true,
    "outDir": "./dist",
    "moduleResolution": "node",
    "removeComments": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "baseUrl": "."
  },
  "exclude": [
    "node_modules"
  ],
  "include": [
    "./src/**/*.tsx",
    "./src/**/*.ts"
  ]
}

================================================
FILE: docker-compose.local.yml
================================================
version: "3"

# service_name:
#   build: 
#     context: .
#     dockerfile: path/to/Dockerfile
#

services:
  # voice server
  shawarma:
    build: ./shawarma
    environment: 
      - WEBRTC_LISTEN_IP=127.0.0.1
      - RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
  kofta:
    build: ./kofta
    # # uncomment if you want your changes to kofta code to hot reload. you'll need to npm install.
    # volumes:
    #   - './kofta:/usr/src/frontend'
    labels:
      tv.dogehouse.description: "Frontend Service"
    environment: 
      - REACT_APP_API_BASE_URL=http://localhost:4001
    ports: 
      - 3000:3000
  # backend
  kousa:
    build: ./kousa
    environment: 
      - DATABASE_URL=postgresql://postgres:postgres@postgres/postgres
      - BEN_GITHUB_ID=benawad
      - RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
      - GITHUB_CLIENT_ID=5d5xxxxxxab70
      - GITHUB_CLIENT_SECRET=48xxxxxxxxxxxxd1cd5
      - TWITTER_SECRET_KEY=testtwittersecret
      - TWITER_BEARER_TOKEN=testtwitterbearer
      - TWITTER_API_KEY=testtwitterkey
      - ACCESS_TOKEN_SECRET=8f51exxxxxx7211dd
      - SENTRY_DSN=SIJHFIUSDHIF
      - SECRET_KEY_BASE=TESTING
      - REFRESH_TOKEN_SECRET=dbb85xxxxxx9ebde
      - WEB_URL=http://localhost:3000
      - API_URL=http://localhost:4001
      - PORT=4001
    ports: 
      - 4001:4001
  postgres:
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRE_DB=postgres
  rabbitmq:
    environment: 
      RABBITMQ_ERLANG_COOKIE: erlang_dev_only_cookie
      RABBITMQ_DEFAULT_USER: guest
      RABBITMQ_DEFAULT_PASS: guest
  adminer:

================================================
FILE: docker-compose.prod.yml
================================================
version: "3"

# service_name:
#   build: 
#     context: .
#     dockerfile: path/to/Dockerfile
#

# kofta is not here cause it's manually deployed.
services:
  shawarma:
    image: dogehouse/shawarma
    env_file: 
      - shawarma.env
  kousa:
    image: dogehouse/kousa
    env_file: 
      - kousa.env
  postgres:
    env_file: 
      - pg.env
  rabbitmq:
    env_file: 
      - rabbit.env
  adminer:


================================================
FILE: docker-compose.yml
================================================
version: "3"

# service_name:
#   build: 
#     context: .
#     dockerfile: path/to/Dockerfile
#   restart: unless-stopped
#   labels:
#     tv.dogehouse.description: "Service Description"
#   depends_on:
#     - deps
#

# We will be making use of docker-compose overloads, so be sure to check the other compose files before reporting a missing field
# On local the containers will be built locally and tagged, able to be published.
# On prod the compose file will pull from the docker registry
services:

  rabbitmq:
    image: rabbitmq:3-management-alpine
    restart: unless-stopped
    labels:
      tv.dogehouse.description: "RabbitMQ broker"
    volumes:
      - ./.docker/rabbitmq/data/:/var/lib/rabbitmq/
      - ./.docker/rabbitmq/logs/:/var/log/rabbitmq/
    ports:
      - 5672:5672
      - 15672:15672
    healthcheck:
      test: ['CMD', 'rabbitmq-diagnostics', '-q', 'ping']
      interval: 60s
      timeout: 5s

  shawarma:
    restart: unless-stopped
    labels:
      tv.dogehouse.description: "Voice Server Service"
    depends_on: 
      - kousa

  kousa:
    restart: unless-stopped
    labels:
      tv.dogehouse.description: "Backend Service"
    depends_on: 
      - postgres
      - rabbitmq
      
  postgres:
    image: postgres:13-alpine
    restart: unless-stopped
    labels:
      tv.dogehouse.description: "Postgres Database"
    volumes:
      - ./.docker/postgres:/var/lib/postgresql/data
    ports:
      - 5432:5432

  adminer:
    image: adminer
    restart: unless-stopped
    ports:
      - 8080:8080
    labels:
      tv.dogehouse.description: "Adminer Database"
    depends_on: 
      - postgres

================================================
FILE: docs/Architecture/README.md
================================================
# Architecture Of DogeHouse!

<img src= "https://github.com/RonaldColyar/dogehouse/blob/staging/docs/Architecture/Architecture.png"/>



# How does DogeHouse dish out communications?

Voice communications are routed directly to the node [voice server](https://github.com/benawad/dogehouse/tree/staging/shawarma) through the usage of [WebRTC](https://webrtc.org/) once the elixir API gathers credentials for connection to the node voice server through [RabbitMQ](https://www.rabbitmq.com/)!

<img src="https://github.com/RonaldColyar/dogehouse/blob/staging/docs/Architecture/ReactAndNode.png" />

# How is data fetched?

All of data is fetched from the Client([React Front-end](https://github.com/benawad/dogehouse/tree/staging/kofta)) to the server([Elixir Api](https://github.com/benawad/dogehouse/tree/staging/kousa)) directly through a websocket connection!

<img src= "https://github.com/RonaldColyar/dogehouse/blob/staging/docs/Architecture/clientandelixr.png" />

# How is data stored?
All data is stored using Postgresql that is directly managed using the [Elixir Api](https://github.com/benawad/dogehouse/tree/staging/kousa)!


<img src="https://github.com/RonaldColyar/dogehouse/blob/staging/docs/Architecture/ElixirAndPostgresql.png" />


================================================
FILE: docs/Directory/README.md
================================================
# DogeHouse Code Directory


1.Kofta(React Front End)
  - Components
    - [AlertModal](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/AlertModal.tsx)
    - [Backbar](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/Backbar.tsx)
    - [Blocked Users List](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/BlockedFromRoomUsers.tsx)
    - [Bottom Room Controls](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/BottomVoiceControl.tsx)
    - [Check Box](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/Checkbox.tsx)
    - [Circle Button](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/CircleButton.tsx)
    - [Button](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/Button.tsx)
    - [Center Layout](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/CenterLayout.tsx)
    - [Confirm Modal](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/ConfirmModal.tsx)
    - [Create Room Modal](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/CreateRoomModal.tsx)
    - [Create Profile Modal](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/EditProfileModal.tsx)
    - [Footer](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/Footer.tsx)
    - [Input](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/Input.tsx)
    - [Input error message](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/InputErrorMsg.tsx)
    - [Invite Button](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/InviteButton.tsx)
    - [Invited To Join Room Modal](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/InvitedToJoinRoomModal.tsx)
    - [Keybind Listener](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/KeybindListener.tsx)
    - [List Item](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/ListItem.tsx)
    - [Loading](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/Loading.tsx)
    - [Mic Permission Banner](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/MicPermissionBanner.tsx)
    - [Modal](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/Modal.tsx)
    - [Mute Title Updater](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/MuteTitleUpdater.tsx)
    - [Profile Button](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/ProfileButton.tsx)
    - [Profile Modal](https://github.com/benawad/dogehouse/blob/staging/kofta/src/vscode-webview/components/ProfileModal.tsx)
    - 


================================================
FILE: docs/Elixir Api/README.MD
================================================
# Authentication

Tokens:

- Refresh token -> lasts 30 days
- Access token -> 1 hour

Websocket connection:

- On initial connection if the client doesn't send an `auth` event with their refresh & access token within 8 seconds the connection will be closed by the server
- If access token is valid, the user id is extracted from the payload and the user is authenticated
- If the access token is invalid, the server will try to refresh both tokens

Refreshing tokens:

- A refresh token is invalid if
    - it is malformed
    - it has expired
    - the token version in the payload is different then what's in the db for that user
- If the refresh token is invalid, they are not authenticated and will need to log in again
- If the refresh token is valid they are considered authenticated and a new refresh & access token is created/sent back to the client with the `new_tokens` event
    
    
Invalidating tokens:

- You can invalidate all refresh tokens for a user by incrementing the token version in the db


================================================
FILE: docs/README.MD
================================================
## Home
<p align="center">
<img height=100 src="https://raw.githubusercontent.com/benawad/dogehouse/staging/.redesign-assets/dogehouse_logo.svg"/>
</p>
<p align="center">
 Taking voice conversations to the moon 🚀
</p>

## Welcome
Welcome to the DogeHouse Documentation, the next voice conversation social platform.

DogeHouse makes it easy to connect with friends and people over voice and chat message.

### Overview
- Dark Theme
- Open Sign-Ups (Twitter, GitHub, and Discord)
- Cross-Platform Support
- Open Source
- Text Chat
- Powered by Doge

### Basic Features
- Create account (Twitter, GitHub, and Discord for now)
- Create rooms and invite friends (Public/Private)
  - When you create a room, you are automatically a mod and have a doge with glasses.
  - You can also make people in room mod by clicking on their profile.
  - You can edit room name, edit room description and change room visibility by clicking on the room name.
- Schedule Room to take place at a future date
  - Add scheduled rooms to calender
    - Apple's Calendar
    - Google Calendar
    - Outlook
    - Outlook Web App
    - Yahoo! Calendar
- Join room, leave room, chat in room (chat now has emojis😋), mute/unmute, deafen room, and invite
- Mention someone in the chat with an @ (e.g. `@username`)
- Whisper to someone in the room by using `#@username`
- Write codeblocks using \`backticks\`
- Delete message. You can only delete messages if:
  - You wrote it
  - You are a mod
- Adjust volume of a speaker by clicking on their profile
- 60+ Translations
- Desktop App has Global Keybinds & Desktop Notifications
- Custom Emojis
- 🐕

### Why DogeHouse?
For more please watch here: https://www.youtube.com/watch?v=hy-EhJ_tTQo


================================================
FILE: docs/React Front End/README.MD
================================================


================================================
FILE: docs/Voice Server/README.MD
================================================


================================================
FILE: dolma/.editorconfig
================================================
# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true


================================================
FILE: dolma/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

.package-lock.json

wip.ts
.package-lock.json

/lib

================================================
FILE: dolma/LICENSE
================================================
MIT License

Copyright (c) 2021 HoloPanio

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: dolma/README.md
================================================
<h1 align=center>
Dolma Token Transcoder<br>
<a href="https://www.npmjs.com/package/@dogehouse/dolma"><img src="https://img.shields.io/npm/v/@dogehouse/dolma?style=for-the-badge"></a>
</h1>
This is a token transcoder that is used to encode and decode DogeHouse chat message token arrays.  This package is written for bot/bot library developers to be able to easily transcode dogehouse chat message tokens.  

## How to install

To install this, simply go to your project and run the following command:

```cmd
yarn add dolma
```

## How to use

This will show you how to encode and decode tokens

### Encoding Tokens

In this example, you will see multiple ways to encode your tokens. The first one is in plain text. You can pass any string into the encoder and it will convert it into an array of Message Tokens.

```ts
import { dolma } from "dolma";

const str = "I'm @HoloPanio, and I'd like to goto `Paris, France` one day :catJAM: Also, https://dogehouse.tv is epic!";

const tokens = dolma.encode(str);

console.log(tokens);

/**
Returns: 
[
  { t: 'text', v: "I'm" },
  { t: 'mention', v: 'HoloPanio' },
  { t: 'text', v: ',' },
  { t: 'text', v: 'and' },
  { t: 'text', v: "I'd" },
  { t: 'text', v: 'like' },
  { t: 'text', v: 'to' },
  { t: 'text', v: 'goto' },
  { t: 'block', v: 'Paris, France' },
  { t: 'text', v: 'one' },
  { t: 'text', v: 'day' },
  { t: 'emote', v: 'catJAM' },
  { t: 'text', v: 'Also,' },
  { t: 'link', v: 'https://dogehouse.tv' },
  { t: 'text', v: 'is' },
  { t: 'text', v: 'epic!' }
]
*/
```

In this example, you will see that you can have a mixed array with strings, and unitokens!  A unitoken is a token object where you define your object key as the token type, and the value as the value of the token, doing so would look like such: `{link: "https://google.com"}`, and this can be done for all token types.

```ts
import { dolma } from 'dolma';
const arr = ["I'm", {mention: "HoloPanio"},", and I'd like to goto", {block: "Paris, France"},"one day", {emote: "catJAM"}, "Also",{link: 'https://dogehouse.tv'}, "is epic!"];

const tokens = dolma.encode(arr);

console.log(tokens);

/**
Returns: 
[
  { t: 'text', v: "I'm" },
  { t: 'mention', v: 'HoloPanio' },
  { t: 'text', v: ',' },
  { t: 'text', v: 'and' },
  { t: 'text', v: "I'd" },
  { t: 'text', v: 'like' },
  { t: 'text', v: 'to' },
  { t: 'text', v: 'goto' },
  { t: 'block', v: 'Paris, France' },
  { t: 'text', v: 'one' },
  { t: 'text', v: 'day' },
  { t: 'emote', v: 'catJAM' },
  { t: 'text', v: 'Also,' },
  { t: 'link', v: 'https://dogehouse.tv' },
  { t: 'text', v: 'is' },
  { t: 'text', v: 'epic!' }
]
*/
```
You can also pass in message tokens like `{t: 'link', v: 'https://dogehouse.tv'}`, and it will work because the encoder checks for all possible methods that can be used.

### Decoding Tokens

When you get a payload from DogeHouse, you can use the decode method which will take the tokens, and turn it into a raw text string when you can use anywhere you please. The decode method will always encode the data sent to it to ensure that the data is parsed correctly, so that means you can also pass in un-encoded data, such as the array in the previous example, and will print out a plain text string. In this example, we will take the array from above, and return it to a plain text string using the decode method.

```ts
import { dolma } from "dolma";

const tokens = [
  { t: 'text', v: "I'm" },
  { t: 'mention', v: 'HoloPanio' },
  { t: 'text', v: ',' },
  { t: 'text', v: 'and' },
  { t: 'text', v: "I'd" },
  { t: 'text', v: 'like' },
  { t: 'text', v: 'to' },
  { t: 'text', v: 'goto' },
  { t: 'block', v: 'Paris, France' },
  { t: 'text', v: 'one' },
  { t: 'text', v: 'day' },
  { t: 'emote', v: 'catJAM' },
  { t: 'text', v: 'Also,' },
  { t: 'link', v: 'https://dogehouse.tv' },
  { t: 'text', v: 'is' },
  { t: 'text', v: 'epic!' }

];

const message = dolma.decode(tokens);

console.log(message);

/**
Returns: 

I'm @HoloPanio , and I'd like to goto `Paris, France` one day :catJAM: Also, https://google.com is epic!
*/
```

================================================
FILE: dolma/package.json
================================================
{
  "name": "@dogehouse/dolma",
  "author": "Jackson Roberts <jackson@holopanio.com>",
  "description": "A chat token transcoder for DogeHouse and associated projects.",
  "version": "1.2.1",
  "license": "MIT",
  "main": "lib/index.js",
  "scripts": {
    "test": "tsc && node lib/test/run.js && tsc -b . --clean",
    "clean": "tsc -b . --clean",
    "build": "tsc"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/HoloPanio/dolma.git"
  },
  "keywords": [
    "@dogehouse/dolma",
    "dogehouse",
    "doghouse-tokens"
  ],
  "bugs": {
    "url": "https://github.com/HoloPanio/dolma/issues"
  },
  "homepage": "https://github.com/HoloPanio/dolma#readme",
  "dependencies": {
    "@types/node": "^15.0.2",
    "emoji-regex": "^9.2.2"
  },
  "devDependencies": {
    "typescript": "^4.2.4"
  }
}


================================================
FILE: dolma/src/index.ts
================================================
import { decodeTokens } from "./lib/decode";
import { encodeTokens } from "./lib/encode";
import { Unitoken } from "./tokens";
import { MessageToken } from "./util/types/tokenTypes";

interface RootMethodResponse {
	encoded: MessageToken[],
	decoded: string
}

export * from './util/types/tokenTypes';

// export default function dolma(values?: Array<Unitoken | MessageToken | string> | string): RootMethodResponse {
// 	return {
// 		encoded: encodeTokens(values ?? ""),
// 		decoded: decodeTokens(values ?? "")
// 	}
// }

// dolma['encode'] = encodeTokens;
// dolma['decode'] = decodeTokens;

export default class dolma {
  public readonly emotes: {name: string}[];

  constructor(emotes: {name: string}[]) {
    this.emotes = emotes;
  }

  public decode = decodeTokens;
  public encode = encodeTokens;
}


================================================
FILE: dolma/src/lib/decode.ts
================================================
import dolma from "../index";
import { Unitoken } from "../tokens";
import { MessageToken } from "../util/types/tokenTypes";
import { encodeTokens } from "./encode";

export function decodeTokens(this: {emotes: {name: string}[]}, all: Array<Unitoken | MessageToken | string> | string): string {
	const tokens = new dolma(this.emotes).encode(all);
	let vals: string[] = [];

	tokens.tokens.map(tkn => {
		if (tkn.t == 'text') return vals.push(tkn.v);
		if (tkn.t == 'block') return vals.push(`\`${tkn.v}\``);
		if (tkn.t == 'emote') return vals.push(`:${tkn.v}:`);
		if (tkn.t == 'mention') return vals.push(`@${tkn.v}`);
		if (tkn.t == 'link') return vals.push(tkn.v);
	});

	let ret: string[] = [];
	const len = vals.length
	vals.forEach((val, index) => {
		const strayValues = [",", "."]
		if (strayValues.includes(val)) {
			ret[ret.length-1] += val;
		} else {
			ret.push(val);
		}
	});

	return ret.join(' ');
}


================================================
FILE: dolma/src/lib/encode.ts
================================================
import { Unitoken } from "../tokens";
import { MessageToken } from "../util/types/tokenTypes";
import { decodeTokens } from "./decode";
import { filterString } from "./filterString";
import { filterUnitoken } from "./filterUnitoken";

export function encodeTokens(this: {emotes: {name: string}[]},message: Array<Unitoken | MessageToken | string> | string) {
	const tokens: MessageToken[] = [];
	if (!message) return {tokens: tokens, whisperedTo: []};

	if (typeof message == 'string') {
		console.log(this.emotes);
		return filterString(this.emotes, message)
	}

	// if (typeof message == 'object') {
	// 	message.forEach((item: any, index) => {
	// 		const unitoken = filterUnitoken(item);
	// 		const isToken = Object.keys(item).includes('t') && Object.keys(item).includes('v');

	// 		if (typeof item == 'string') return filterString(item).map(tk => tokens.push(tk));
	// 		if (unitoken !== null) return tokens.push(unitoken);
	// 		if (isToken) return tokens.push(item);

	// 		return;
	// 	})
	// }

	return {tokens: tokens, whisperedTo: []};
}


================================================
FILE: dolma/src/lib/filterString.ts
================================================
import { validationRegex } from "../util/regex";
import { MessageToken, MessageTokenType } from "../util/types/tokenTypes";
import { msgToken } from "./msgToken";

export function filterString(emotes: { name: string }[], message: string) {
  const tokens: MessageToken[] = [];
  const vals = message
    .split(validationRegex.global)
    .filter((e) => e != undefined && e != "")
    .map((e) => e);
  const whispers = message.split(/^\#\@([A-z0-9_]{4,})/gi)[1];

  vals.map((e) => {
    let tkn = msgToken.getType(e);
    tokenSwitch:
      switch (tkn) {
        case "emote":
          for(const emote of emotes) {
            if(e.trim().toLowerCase() === `:${emote.name}:`) {
              e = emote.name;
              break tokenSwitch;
            }
          }
          tkn = "text";
          break;
        case "block":
          e = e.slice(1, -1);
          break;
        case "mention":
          e = e.substr(1);
          break;
      }

    const value = msgToken.getValue(tkn, e);

    return tokens.push(msgToken.newToken(tkn, value));
  });

  return { tokens, whisperedTo: whispers ? [whispers] : [] };
}


================================================
FILE: dolma/src/lib/filterUnitoken.ts
================================================
import { MessageToken, MessageTokenType } from "../util/types/tokenTypes";
import { msgToken } from "./msgToken";

const newToken = msgToken.newToken;

export function filterUnitoken(token: any): MessageToken | null {
	const keys = Object.keys(token);
	const tkn = msgToken.getUnitoken(token);
	if (keys.length > 1) return null;
	if (tkn == null) return null;
	
	return newToken(tkn, token[tkn]);
}

================================================
FILE: dolma/src/lib/msgToken.ts
================================================
import { validationRegex } from "../util/regex";
import { MessageToken, MessageTokenType } from "../util/types/tokenTypes";

import * as rawTokens from '../tokens';

//@ts-ignore
const tokenTypes: MessageTokenType[] = Object.keys(rawTokens.default);

export function msgToken() {

}

msgToken.tokens = rawTokens.default;
msgToken.types = tokenTypes;

msgToken.getUnitoken = (token: rawTokens.Unitoken): MessageTokenType | null => {
	const utKeys = Object.keys(token);
	let tkn: MessageTokenType = 'text';

	tokenTypes.map(tt => { if (tt == utKeys[0]) tkn = tt });

	return tkn;
}

msgToken.get = (tokenType: MessageTokenType) => {
	const tkn = rawTokens.default[tokenType];
	return tkn;
}

msgToken.getType = (raw: string): MessageTokenType => {
	let type: MessageTokenType = 'text';
	tokenTypes.forEach(tt => {
		if (msgToken.validate(tt, raw)) {
			type = tt;
		}
	});
	return type;
}

msgToken.getValue = (tkn: MessageTokenType, raw: string): string => {
	const regex = msgToken.get(tkn).regex;
	if (!regex) return raw;
	else return raw;
}

msgToken.newToken = (tk: MessageTokenType, value: string) => {
	const genToken = (t: MessageTokenType, v: string) => { return { t, v } }
	let val = msgToken.get(tk).format(value);
	return genToken(tk, val);
}

msgToken.validate = (token: MessageTokenType, str: string): string | false => {
	const tkn = msgToken.get(token);
	if (!tkn.regex) return str;

	if (str.match(tkn.regex)) return str.replace(tkn.regex, '$1');
	else return false;
}


================================================
FILE: dolma/src/test/run.ts
================================================
import * as encodingTests from './tests/encoding';
import dolma from '../';

interface CompletedTest {
  started: Date,
  finished: Date,
  type: string,
  passed?: boolean
}

const neutralPrefix = "\u001b[36m[ DOLMA ]\u001b[0m";
const successPrefix = "\u001b[32m[ SUCCESS ]\u001b[0m";
const failurePrefix = "\u001b[31m[ FAILURE ]\u001b[0m"

const testName = (name: string) => { return `\u001b[37;1m(${name})\u001b[0m` }

let failedTests: CompletedTest[] = [];
let successfulTests: CompletedTest[] = [];

let tests = {
  encoding: encodingTests.default
}

function testFinished(test: any, started: Date, successful?: boolean) {
  const finished = new Date();

  if (successful) {
    successfulTests.push({ started, finished, type: test.type, passed: true });

    const time = ((finished.getTime() - started.getTime()) / 1000) % 60;
    console.log(successPrefix, testName(test.name), "Test passed in", `${time}s!`);
  } else {
    failedTests.push({ started, finished, type: test.type, passed: false });

    const time = ((finished.getTime() - started.getTime()) / 1000) % 60;
    console.log(failurePrefix, testName(test.name), "Test failed in", `${time}s!`);
  }
}
async function main() {
  console.log(neutralPrefix, "Running tests on dolma...\n");

  tests.encoding.map(async test => {
    const started = new Date();
    const encodedValue = new dolma([]).encode(test.input);
    if (JSON.stringify(encodedValue) == JSON.stringify(test.expectedOutput)) testFinished(test, started, true);
    else testFinished(test, started, false);
  });

  console.log(`\n${neutralPrefix} Testing completed! \u001b[37;1m(${successfulTests.length} passed) (${failedTests.length} failed)`)
}

main();

================================================
FILE: dolma/src/test/tests/encoding.ts
================================================
export default [
	{
		name: "Single string type test 1 (text)",
		type: "encode",

		input: "Ben Awad",
		expectedOutput: [{ t: 'text', v: 'Ben Awad' }]
	},

	{
		name: "Single string type test 2 (link)",
		type: "encode",

		input: "https://dogehouse.tv",
		expectedOutput: [{ t: 'link', v: 'https://dogehouse.tv' }]
	},

	{
		name: "Single string type test 3 (mention)",
		type: "encode",

		input: "@benawad",
		expectedOutput: [{ t: 'mention', v: 'benawad' }]
	},

	{
		name: "Single string type test 4 (block)",
		type: "encode",

		input: "`Angular.JS is horrible`",
		expectedOutput: [{ t: 'block', v: 'Angular.JS is horrible' }]
	},

	{
		name: "Single string type test 5 (emote)",
		type: "encode",

		input: ":CryptoDOGE:",
		expectedOutput: [{ t: 'emote', v: 'CryptoDOGE' }]
	},

	{
		name: "Plain text encoding test 1",
		type: "encode",

		input: "This is a test to make sure that plain text tokens still work, also, https://dogehouse.tv is pretty great!",
		expectedOutput: [
			{
				t: 'text',
				v: 'This is a test to make sure that plain text tokens still work, also,'
			},
			{ t: 'link', v: 'https://dogehouse.tv' },
			{ t: 'text', v: 'is pretty great!' }
		]
	},

	{
		name: "Plain text encoding test 2",
		type: "encode",

		input: "I think Ben Awad being on simptok is super funny, but I think he would do better being a simp on dogehouse :reddogehouse:, but https://github.com/ is epic!",
		expectedOutput: [
			{
				t: 'text',
				v: 'I think Ben Awad being on simptok is super funny, but I think he would do better being a simp on dogehouse'
			},
			{ t: 'emote', v: 'reddogehouse' },
			{ t: 'text', v: ', but' },
			{ t: 'link', v: 'https://github.com/' },
			{ t: 'text', v: 'is epic!' }
		]
	},

	{
		name: "Mixed unitoken and strings encoding test 1",
		type: "encode",

		input: ["Dogecoin to the moon!!!", { emote: "CryptoDOGE" }],
		expectedOutput: [
			{ t: 'text', v: 'Dogecoin to the moon!!!' },
			{ t: 'emote', v: 'CryptoDOGE' }
		]
	}
];

================================================
FILE: dolma/src/tokens/index.ts
================================================
import * as text from './types/text';
import * as block from './types/block';
import * as mention from './types/mention';
import * as emote from './types/emote';
import * as link from './types/link';
import * as emoji from './types/emoji';

export interface Unitoken {
	text?: string
	block?: string
	mention?: string,
	emote?: string,
	link?: string,
}

export default {
	text: text.default,
	block: block.default,
	mention: mention.default,
	emote: emote.default,
	emoji: emoji.default,
	link: link.default
};


================================================
FILE: dolma/src/tokens/types/block.ts
================================================
import { Token } from "../../util/types/tokenTypes";

export default {
	name: "block",
	regex: /\`(.*?)\`/gi,

	format: (val) => val,
  validate: (raw, val) => true
} as Token;

================================================
FILE: dolma/src/tokens/types/emoji.ts
================================================
import { Token } from "../../util/types/tokenTypes";
import emojiRegex from "emoji-regex"

export default {
	name: "emoji",
	regex: emojiRegex(),

	format: (val) => val,
  validate: (raw, val) => true
} as Token;


================================================
FILE: dolma/src/tokens/types/emote.ts
================================================
import { Token } from "../../util/types/tokenTypes";

export default {
	name: "emote",
	regex: /\:([a-z0-9]+)\:/gi,

	format: (val) => val,
  validate: (raw, val) => true
} as Token;


================================================
FILE: dolma/src/tokens/types/link.ts
================================================
import { Token } from "../../util/types/tokenTypes";

export default {
	name: "link",
	regex: /(https?\:\/\/[^ ]+)/gi,

	format: (val) => val,
  validate: (raw, val) => true
} as Token;

================================================
FILE: dolma/src/tokens/types/mention.ts
================================================
import { Token } from "../../util/types/tokenTypes";

export default {
	name: "mention",
	regex: /\@([a-zA-Z0-9_]{4,})/gi,

	format: (val) => val,
  validate: (raw, val) => true
} as Token;

================================================
FILE: dolma/src/tokens/types/text.ts
================================================
import { Token } from "../../util/types/tokenTypes";

export default {
	name: "text",

	format: (val) => val,
  validate: (raw, val) => true 
} as Token;

================================================
FILE: dolma/src/util/regex.ts
================================================
export const validationRegex = {
	link: /(https?\:\/\/[^ ]+)/gi,
	mention: /\@([a-zA-Z0-9_]{4,})/gi,
	emote: /\:([a-z0-9]+)\:/gi,
	block: /\`(.*?)\`/gi,

	global: /(\`.*?\`)|(\@[a-zA-Z0-9_]{4,})|(\:[a-z0-9]+\:)|(https?\:\/\/[^ ]+)/gi,

	unicodeEmoji:  /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff])/gm
}


================================================
FILE: dolma/src/util/types/tokenTypes.ts
================================================
import * as rawTokens from '../../tokens';

export type MessageTokenType = keyof typeof rawTokens.default;

export interface MessageToken {
	t: MessageTokenType | string;
	v: string;
}

export interface Token {
	name: string,
	regex: RegExp,
	format: (value: string) => string;
	validate: (raw: string, value?: string) => boolean;
}


================================================
FILE: dolma/tsconfig.json
================================================
{
  "compilerOptions": {
    "outDir": "./lib",
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "baseUrl": ".",
    "rootDir": "src",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "declaration": true,
    "noImplicitAny": false
  },
  "include": ["src/**/*.ts"]
}


================================================
FILE: globalkey/.gitignore
================================================
/target
Cargo.lock
/.idea
/dist


================================================
FILE: globalkey/Cargo.toml
================================================
[package]
name = "globalkey"
description = "A rust node library for global key listeners in electron apps"
version = "0.1.0"
edition = "2018"
license = "MIT"
build = "src/build.rs"
authors = ["Will Lane <williamlane923@gmail.com>"]

[lib]
crate-type = ["cdylib"]

[dependencies]
device_query = "0.2.8"
lazy_static = "1.4.0"
node-bindgen = "4.3.0"
stoppable_thread = "0.2.1"

[build-dependencies]
node-bindgen = { version = "4.3.0", features = ["build"] }


================================================
FILE: globalkey/README.md
================================================
[![npm](https://img.shields.io/npm/v/globalkey)](https://www.npmjs.com/package/globalkey) ![downloads](https://img.shields.io/npm/dm/globalkey)

# GlobalKey

## Building

```shell
cargo install nj-cli

nj-cli build --release
```

## Calling from node

```shell
npm i globalkey

# or

yarn add globalkey
```

```node
const globalkey = require('globalkey');

globalkey
    .start(x => console.log(`Keydown ${x}`), y => console.log(`Keyup ${y}`));


setTimeout(() => globalkey.stop(), 5000)
```


================================================
FILE: globalkey/index.d.ts
================================================
declare module "globalkey" {
    export function start(keydown_callback: (keys: string[]) => void, keyup_callback: (keys: string[]) => void): void;
    export function stop(): void;
}

================================================
FILE: globalkey/package.json
================================================
{
  "name": "@dogehouse/globalkey",
  "version": "1.0.7",
  "main": "dist/index.node",
  "types": "index.d.ts",
  "repository": "https://github.com/willdoescode/globalkey.git",
  "author": "Will Lane <williamlane923@gmail.com>",
  "license": "MIT"
}


================================================
FILE: globalkey/src/build.rs
================================================
fn main() {
    node_bindgen::build::configure();
}


================================================
FILE: globalkey/src/lib.rs
================================================
use device_query::{DeviceQuery, DeviceState};
use node_bindgen::derive::node_bindgen;
use std::sync::Mutex;

#[macro_use]
extern crate lazy_static;

lazy_static! {
    static ref STOP: Mutex<Option<stoppable_thread::StoppableHandle<()>>> = Mutex::new(None);
}

#[node_bindgen(mt)]
fn start<F: Fn(Vec<String>) + Send + 'static, X: Fn(Vec<String>) + Send + 'static>(
    keydown_callback: F,
    keyup_callback: X,
) {
    *STOP.lock().unwrap() = Some(stoppable_thread::spawn(move |stop| {
        let state = DeviceState::new();

        let mut previous_keys = Vec::new();
        while !stop.get() {
            std::thread::sleep(std::time::Duration::new(0, 1000));
            let keys = state.get_keys();
            let state = keys != previous_keys;

            if !keys.is_empty() && state {
                keydown_callback(keys.clone().iter().map(|key| key.to_string()).collect());
            }

            if !previous_keys.is_empty() && state {
                keyup_callback(
                    previous_keys
                        .clone()
                        .iter()
                        .filter(|x| !keys.contains(x))
                        .map(|x| x.to_string())
                        .collect(),
                );
            }
            previous_keys = keys;
        }
    }));
}

#[node_bindgen]
fn stop() {
    STOP.lock().unwrap().take().unwrap().stop().join();
}


================================================
FILE: globalkey/test.js
================================================
const globalkey = require('./dist');

globalkey
    .start(x => console.log(`Keydown ${x}`), y => console.log(`Keyup ${y}`));


setTimeout(() => globalkey.stop(), 5000)


================================================
FILE: kebab/.eslintrc.json
================================================
{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint/eslint-plugin"],
  "rules": {
    "@typescript-eslint/no-empty-interface": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "@typescript-eslint/member-delimiter-style": "off",
    "no-empty": "off",
    "no-empty-pattern": "off",
    "react/prop-types": "off",
    "accessor-pairs": "error",
    "array-bracket-newline": "error",
    "array-bracket-spacing": "error",
    "array-callback-return": "error",
    "array-element-newline": ["error", "consistent"],
    "arrow-body-style": "off",
    "arrow-parens": "off",
    "arrow-spacing": "error",
    "block-scoped-var": "error",
    "block-spacing": "error",
    "brace-style": "error",
    "camelcase": "off",
    "comma-dangle": "off",
    "comma-spacing": "error",
    "comma-style": "error",
    "complexity": "error",
    "computed-property-spacing": "error",
    "consistent-this": "error",
    "default-case-last": "error",
    "default-param-last": "error",
    "dot-location": ["error", "property"],
    "dot-notation": "error",
    "eol-last": "error",
    "eqeqeq": "error",
    "func-call-spacing": "error",
    "func-name-matching": "error",
    "func-names": "error",
    "func-style": [
      "error",
      "declaration",
      {
        "allowArrowFunctions": true
      }
    ],
    "function-call-argument-newline": ["error", "consistent"],
    "function-paren-newline": "off",
    "generator-star-spacing": "error",
    "global-require": "error",
    "grouped-accessor-pairs": "error",
    "guard-for-in": "error",
    "handle-callback-err": "error",
    "id-blacklist": "error",
    "id-denylist": "error",
    "id-match": "error",
    "indent": [
      "error",
      2,
      {
        "offsetTernaryExpressions": true,
        "SwitchCase": 1
      }
    ],
    "init-declarations": "error",
    "jsx-quotes": "error",
    "key-spacing": ["error"],
    "keyword-spacing": "off",
    "line-comment-position": "error",
    "linebreak-style": "error",
    "lines-around-comment": "error",
    "lines-around-directive": "error",
    "lines-between-class-members": "error",
    "max-classes-per-file": "error",
    "max-depth": "error",
    "max-len": "off",
    "max-lines": "off",
    "max-lines-per-function": "off",
    "max-nested-callbacks": "error",
    "max-statements": "off",
    "max-statements-per-line": "error",
    "multiline-comment-style": "off",
    "multiline-ternary": "off",
    "new-cap": "error",
    "new-parens": "error",
    "newline-after-var": "error",
    "newline-before-return": "error",
    "newline-per-chained-call": "error",
    "no-alert": "error",
    "no-array-constructor": "error",
    "no-await-in-loop": "error",
    "no-bitwise": "error",
    "no-buffer-constructor": "error",
    "no-caller": "error",
    "no-catch-shadow": "error",
    "no-console": "error",
    "no-constructor-return": "error",
    "no-continue": "error",
    "no-div-regex": "error",
    "no-duplicate-imports": "error",
    "no-eq-null": "error",
    "no-eval": "error",
    "no-extend-native": "error",
    "no-extra-bind": "error",
    "no-extra-label": "error",
    "no-extra-parens": "off",
    "no-floating-decimal": "error",
    "no-implicit-coercion": "error",
    "no-implicit-globals": "error",
    "no-implied-eval": "error",
    "no-inline-comments": "error",
    "no-invalid-this": "error",
    "no-iterator": "error",
    "no-label-var": "error",
    "no-labels": "error",
    "no-lone-blocks": "error",
    "no-lonely-if": "error",
    "no-loop-func": "error",
    "no-loss-of-precision": "error",
    "@typescript-eslint/no-magic-numbers": "off",
    "no-mixed-operators": "off",
    "no-mixed-requires": "error",
    "no-multi-assign": "error",
    "no-multi-spaces": "error",
    "no-multi-str": "error",
    "no-multiple-empty-lines": "error",
    "no-native-reassign": "error",
    "no-negated-condition": "error",
    "no-negated-in-lhs": "error",
    "no-nested-ternary": "error",
    "no-new": "error",
    "no-new-func": "error",
    "no-new-object": "error",
    "no-new-require": "error",
    "no-new-wrappers": "error",
    "no-nonoctal-decimal-escape": "error",
    "no-octal-escape": "error",
    "no-param-reassign": "error",
    "no-path-concat": "error",
    "no-plusplus": "error",
    "no-process-env": "off",
    "no-process-exit": "error",
    "no-promise-executor-return": "error",
    "no-proto": "error",
    "no-restricted-exports": "error",
    "no-restricted-globals": "error",
    "no-restricted-imports": "error",
    "no-restricted-modules": "error",
    "no-restricted-properties": "error",
    "no-restricted-syntax": "error",
    "no-script-url": "error",
    "no-self-compare": "error",
    "no-sequences": "error",
    "@typescript-eslint/no-shadow": "error",
    "no-spaced-func": "error",
    "no-sync": "error",
    "no-tabs": "error",
    "no-template-curly-in-string": "error",
    "no-throw-literal": "error",
    "no-trailing-spaces": "error",
    "no-undef-init": "error",
    "no-undefined": "off",
    "no-underscore-dangle": "error",
    "no-unmodified-loop-condition": "error",
    "no-unneeded-ternary": "error",
    "no-unreachable-loop": "error",
    "no-unsafe-optional-chaining": "error",
    "no-unused-expressions": "error",
    "@typescript-eslint/no-use-before-define": "error",
    "no-useless-backreference": "error",
    "no-useless-call": "error",
    "no-useless-computed-key": "error",
    "no-useless-concat": "error",
    "no-useless-constructor": "error",
    "no-useless-rename": "error",
    "no-useless-return": "error",
    "no-var": "error",
    "no-void": "error",
    "no-warning-comments": "error",
    "no-whitespace-before-property": "error",
    "nonblock-statement-body-position": "error",
    "object-curly-newline": "error",
    "object-curly-spacing": ["error", "always"],
    "object-property-newline": [
      "error",
      {
        "allowAllPropertiesOnSameLine": true
      }
    ],
    "object-shorthand": "error",
    "one-var": ["error", "never"],
    "operator-assignment": "error",
    "operator-linebreak": "error",
    "padded-blocks": ["error", "never"],
    "padding-line-between-statements": "error",
    "prefer-arrow-callback": "error",
    "prefer-const": "error",
    "prefer-destructuring": "error",
    "prefer-exponentiation-operator": "error",
    "prefer-named-capture-group": "off",
    "prefer-numeric-literals": "error",
    "prefer-object-spread": "error",
    "prefer-promise-reject-errors": "error",
    "prefer-reflect": "error",
    "prefer-regex-literals": "error",
    "prefer-rest-params": "error",
    "prefer-spread": "error",
    "prefer-template": "off",
    "quote-props": "off",
    "quotes": "off",
    "radix": "error",
    "require-atomic-updates": "error",
    "require-await": "error",
    "require-unicode-regexp": "off",
    "rest-spread-spacing": "error",
    "@typescript-eslint/semi": [
      "error",
      "always",
      {
        "omitLastInOneLineBlock": true
      }
    ],
    "semi-spacing": "error",
    "semi-style": "error",
    "no-extra-semi": "error",
    "space-before-blocks": "error",
    "space-before-function-paren": [
      "error",
      {
        "anonymous": "never",
        "named": "never",
        "asyncArrow": "always"
      }
    ],
    "space-in-parens": ["error", "never"],
    "space-infix-ops": "error",
    "space-unary-ops": [
      "error",
      {
        "words": true,
        "nonwords": false
      }
    ],
    "spaced-comment": "error",
    "strict": "error",
    "switch-colon-spacing": "error",
    "symbol-description": "error",
    "template-curly-spacing": "error",
    "template-tag-spacing": "error",
    "unicode-bom": "error",
    "valid-jsdoc": "error",
    "vars-on-top": "error",
    "wrap-iife": "error",
    "wrap-regex": "error",
    "yield-star-spacing": "error",
    "yoda": "error",
    "@typescript-eslint/ban-types": "warn",
    "react/react-in-jsx-scope": "off",
    "@typescript-eslint/no-empty-function": "off",
    "@typescript-eslint/ban-ts-comment": "warn"
  }
}


================================================
FILE: kebab/.gitignore
================================================
.idea
examples/*/.env
examples/*/node_modules
examples/*/build
examples/*/.parcel-cache
examples/*/dist
node_modules
lib


================================================
FILE: kebab/.prettierrc.js
================================================
module.exports = {
  trailingComma: "es5",
  tabWidth: 2,
  semi: true,
  singleQuote: false,
  arrowParens: "always",
  useTabs: false,
};


================================================
FILE: kebab/README.md
================================================
# Kebab
The official DogeHouse API client.

## Usage
- **In web =>** see `examples/mediasoup-audio/` and `examples/react-chat/`
- **In Node =>** see `examples/chat/` and `examples/bot/` (note that you need to have DOM in tsc's libs)

### A simple bot
```typescript
import { raw, createClient, httpRequest, httpEndpoint, tokensToString, stringToToken } from "@dogehouse/kebab";

const commandRegex = /^\/([^ ]+) ?(.*)$/;
const main = async () => {
  try {
    const credentials = await httpRequest(httpEndpoint.bot.auth, { apiKey: process.env.DOGEHOUSE_API_KEY! });
    const client = createClient(await raw.connect(
      credentials.accessToken,
      credentials.refreshToken,
      {
        onConnectionTaken: () => {
          console.error("\nAnother client has taken the connection");
          process.exit();
        }
      }
    ));

    const sendMessage = (text: string) => client.request(
      "chat:send_msg",
      {
        tokens: stringToToken(text),
        whisperedTo: []
      }
    );

    const { rooms } = await client.request("room:get_top", { cursor: 0, limit: 1 });
    const theRoom = rooms[0];

    client.subscribe("new_chat_msg", async ({ userId, msg }) => {
      const text = tokensToString(msg.tokens);

      console.log(`${msg.displayName} > ${text}`);
      if (userId === client.user.id) return;

      const [, command, parameters] = commandRegex.exec(text) ?? ["", ""];

      switch (command) {
        case "help":
          await sendMessage("Commands: /help, /goto (owner only), /to_base64 <text>, /from_base64 <buffer>");
          break;
        case "goto":
          if (msg.username !== process.env.OWNER_USERRNAME || parameters.length == 0) break;

          await client.request("room:leave", {});
          await client.request("room:join", { roomId: parameters });
          break;
        case "to_base64":
          if (parameters.length == 0) break;

          await sendMessage(Buffer.from(parameters, "utf-8").toString("base64"));

          break;
        case "from_base64":
          if (parameters.length == 0) break;

          await sendMessage(Buffer.from(parameters, "base64").toString("utf-8"));

          break;
      }
    });

    console.info(`=> starting in room "${theRoom.name}" (${theRoom.numPeopleInside} people)`);
    await client.request("room:join", { roomId: theRoom.id });
  } catch (e) {
    if (e.code === 4001) console.error("invalid token!");
    console.error(e)
  }
};

main();
```


================================================
FILE: kebab/examples/bot/README.md
================================================
# An example bot

1. Put your bot's api key in `.env` as `DOGEHOUSE_API_KEY`
2. Build the API package: `$ yarn` and `$ yarn build` in kebab's root directory
3. Build the example: `$ yarn` and `$ yarn build`
4. `$ yarn start`


================================================
FILE: kebab/examples/bot/package.json
================================================
{
  "name": "example-bot",
  "private": true,
  "scripts": {
    "build": "tsc",
    "start": "node build/index.js"
  },
  "dependencies": {
    "@dogehouse/kebab": "file:../..",
    "@types/node": "^14.14.35"
  },
  "devDependencies": {
    "dotenv": "^8.2.0",
    "typescript": "^4.2.3"
  }
}


================================================
FILE: kebab/examples/bot/src/index.ts
================================================
require("dotenv").config();

import { raw, createClient, httpRequest, httpEndpoint, tokensToString, stringToToken } from "@dogehouse/kebab";

const commandRegex = /^\/([^ ]+) ?(.*)$/;
const main = async () => {
  try {
    const credentials = await httpRequest(httpEndpoint.bot.auth, { apiKey: process.env.DOGEHOUSE_API_KEY! });
    const client = createClient(await raw.connect(
      credentials.accessToken,
      credentials.refreshToken,
      {
        onConnectionTaken: () => {
          console.error("\nAnother client has taken the connection");
          process.exit();
        }
      }
    ));

    const sendMessage = (text: string) => client.request(
      "chat:send_msg",
      {
        tokens: stringToToken(text),
        whisperedTo: []
      }
    );

    const { rooms } = await client.request("room:get_top", { cursor: 0, limit: 1 });
    const theRoom = rooms[0];

    client.subscribe("new_chat_msg", async ({ userId, msg }) => {
      const text = tokensToString(msg.tokens);

      console.log(`${msg.displayName} > ${text}`);
      if (userId === client.user.id) return;

      const [, command, parameters] = commandRegex.exec(text) ?? ["", ""];

      switch (command) {
        case "help":
          await sendMessage("Commands: /help, /goto (owner only), /to_base64 <text>, /from_base64 <buffer>");
          break;
        case "goto":
          if (msg.username !== process.env.OWNER_USERRNAME || parameters.length == 0) break;

          await client.request("room:leave", {});
          await client.request("room:join", { roomId: parameters });
          break;
        case "to_base64":
          if (parameters.length == 0) break;

          await sendMessage(Buffer.from(parameters, "utf-8").toString("base64"));

          break;
        case "from_base64":
          if (parameters.length == 0) break;

          await sendMessage(Buffer.from(parameters, "base64").toString("utf-8"));

          break;
      }
    });

    console.info(`=> starting in room "${theRoom.name}" (${theRoom.numPeopleInside} people)`);
    await client.request("room:join", { roomId: theRoom.id });
  } catch (e) {
    if (e.code === 4001) console.error("invalid token!");
    console.error(e)
  }
};

main();


================================================
FILE: kebab/examples/bot/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "./build",
    "strict": true,
    "lib": ["DOM", "ES6"],
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}


================================================
FILE: kebab/examples/chat/README.md
================================================
# CLI chat (an example app)

1. Put your access- and refresh-token in `.env` (`DOGEHOUSE_TOKEN`, `DOGEHOUSE_REFRESH_TOKEN`)
2. Build the API package: `$ yarn` and `$ yarn build` in kebab's root directory
3. Build the example: `$ yarn` and `$ yarn build`
4. `$ yarn start`


================================================
FILE: kebab/examples/chat/package.json
================================================
{
  "name": "example-chat",
  "private": true,
  "scripts": {
    "build": "tsc",
    "start": "node build/index.js"
  },
  "dependencies": {
    "@dogehouse/kebab": "file:../..",
    "@types/node": "^14.14.35"
  },
  "devDependencies": {
    "dotenv": "^8.2.0",
    "typescript": "^4.2.3"
  }
}


================================================
FILE: kebab/examples/chat/src/index.ts
================================================
require("dotenv").config();

import readline from "readline";
import { raw, wrap, tokensToString, stringToToken } from "@dogehouse/kebab";

const logger: raw.Logger = (direction, opcode, data, fetchId, raw) => {
  const directionPadded = direction.toUpperCase().padEnd(3, " ");
  const fetchIdInfo = fetchId ? ` (fetch id ${fetchId})` : "";
  console.info(`${directionPadded} "${opcode}"${fetchIdInfo}: ${raw}`);
};

const main = async () => {
  try {
    const connection = await raw.connect(
      process.env.DOGEHOUSE_TOKEN!,
      process.env.DOGEHOUSE_REFRESH_TOKEN!,
      {
        onConnectionTaken: () => {
          console.error("\nAnother client has taken the connection");
          process.exit();
        }
      }
    );

    const wrapper = wrap(connection);

    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
      prompt: `${connection.user.displayName} > `
    })

    const { rooms } = await wrapper.query.getTopPublicRooms();
    const theRoom = rooms[0];

    console.log(`=> joining room "${theRoom.name}" (${theRoom.numPeopleInside} people)`);
    const extraInfo = await wrapper.query.joinRoomAndGetInfo(theRoom.id);

    const unsubscribe = wrapper.subscribe.newChatMsg(async ({ userId, msg }) => {
      const text = tokensToString(msg.tokens);
      if(userId !== connection.user.id) {
        process.stdout.cursorTo(0);
        console.log(`${msg.displayName} > ${text}`);
      }

      rl.prompt();
    });

    rl.prompt();
    rl.on("line", async input => {
      if(input === "/leave") {
        unsubscribe();
        await wrapper.mutation.leaveRoom();
        console.log("=> left the room");
      } else {
        await wrapper.mutation.sendRoomChatMsg(stringToToken(input));
      }
    })
  } catch(e) {
    if(e.code === 4001) console.error("invalid token!");
    console.error(e)
  }
};

main();


================================================
FILE: kebab/examples/chat/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "./build",
    "strict": true,
    "lib": ["DOM", "ES6"],
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}


================================================
FILE: kebab/examples/create-bot/README.md
================================================
# An script to create a bot account

1. Put your access and refresh-token in `.env` (`DOGEHOUSE_TOKEN`, `DOGEHOUSE_REFRESH_TOKEN`)
2. Choose your bot's username and place it in `.env` as `DOGEHOUSE_BOT_NAME`
3. Build the API package: `$ yarn` and `$ yarn build` in kebab's root directory
4. Build the example: `$ yarn` and `$ yarn build`
5. `$ yarn start`
6. Save the api key printed to the screen in a safe place to later use with your bot.


================================================
FILE: kebab/examples/create-bot/package.json
================================================
{
  "name": "create-bot",
  "private": true,
  "scripts": {
    "build": "tsc",
    "start": "node build/index.js"
  },
  "dependencies": {
    "@dogehouse/kebab": "file:../..",
    "@types/node": "^14.14.35"
  },
  "devDependencies": {
    "dotenv": "^8.2.0",
    "typescript": "^4.2.3"
  }
}


================================================
FILE: kebab/examples/create-bot/src/index.ts
================================================
require("dotenv").config();

import { raw, wrap } from "@dogehouse/kebab";

const main = async () => {
  try {
    const wrapper = wrap(await raw.connect(
      process.env.DOGEHOUSE_TOKEN!,
      process.env.DOGEHOUSE_REFRESH_TOKEN!,
      {
        onConnectionTaken: () => {
          console.error("\nAnother client has taken the connection");
          process.exit();
        }
      }
    ));

    wrapper.mutation.userCreateBot(process.env.DOGEHOUSE_BOT_NAME!).then(res => {
      console.log(res)
    }).catch(err => {
      console.error(err)
    })
  } catch (e) {
    if (e.code === 4001) console.error("invalid token!");
    console.error(e)
  }
};

main();


================================================
FILE: kebab/examples/create-bot/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "./build",
    "strict": true,
    "lib": ["DOM", "ES6"],
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}


================================================
FILE: kebab/examples/mediasoup-audio/README.md
================================================
# Audio-only client (an example app)

1. Put your access- and refresh-token in `.env` (`DOGEHOUSE_TOKEN`, `DOGEHOUSE_REFRESH_TOKEN`)
2. Build the API package: `$ yarn` and `$ yarn build` in kebab's root directory
3. Setup the example: `$ yarn`
4. `$ yarn start`


================================================
FILE: kebab/examples/mediasoup-audio/package.json
================================================
{
  "name": "mediasoup-audio",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@dogehouse/kebab": "../..",
    "mediasoup-client": "^3.6.29"
  },
  "browserslist": [
    "> 0.2%",
    "not dead"
  ],
  "scripts": {
    "start": "parcel serve ./src/index.html -p 3000",
    "build": "parcel build ./src/index.html"
  },
  "devDependencies": {
    "parcel": "^2.0.0-beta.2",
    "typescript": "^4.2.3"
  }
}


================================================
FILE: kebab/examples/mediasoup-audio/src/index.css
================================================
body {
  margin: 0;
}

.current-role {
  display: flex;
  gap: 10px;
}

.cant-use-mic {
  color: red;
}


================================================
FILE: kebab/examples/mediasoup-audio/src/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Kebab example</title>
    <link rel="stylesheet" href="./index.css">
  </head>
  <body>
    <h1 class="current-role">Loading...</h1>
    <h2 class="current-room">Loading...</h2>
    <script type="module" src="./index.ts"></script>
  </body>
</html>


================================================
FILE: kebab/examples/mediasoup-audio/src/index.ts
================================================
import { wrap, audioWrap, raw } from "@dogehouse/kebab";
import { connect as mediasoupConnect } from "@dogehouse/kebab/lib/audio/mediasoup-client";
import { Device } from "mediasoup-client";

const main = async () => {
  const wrapper = wrap(await raw.connect(process.env.DOGEHOUSE_TOKEN!, process.env.DOGEHOUSE_REFRESH_TOKEN!, {}));
  const audioWrapper = audioWrap(wrapper.connection);
  const { rooms } = await wrapper.query.getTopPublicRooms()
  const theRoom = rooms[0];
  const device = new Device();

  const currentRole = document.querySelector(".current-role")!;

  const makeMicTrack = async () => {
    try {
      const mic = await navigator.mediaDevices.getUserMedia({ audio: true });

      return mic.getAudioTracks()[0];
    } catch {
      const cantUseMic = document.createElement("span");

      cantUseMic.className = "cant-use-mic";
      cantUseMic.textContent = "- can't use mic";
      currentRole.appendChild(cantUseMic);
    }
  };

  const playOutput = (track: MediaStreamTrack) => {
    const audio = new Audio();

    audio.srcObject = new MediaStream([track]);
    audio.play();
  };

  const unsubYjap = audioWrapper.subscribe.youJoinedAsPeer(async ({ routerRtpCapabilities, recvTransportOptions }) => {
    unsubYjap();

    await mediasoupConnect(
      wrapper.connection,
      routerRtpCapabilities,
      "output",
      recvTransportOptions,
      playOutput
    )(device);
    currentRole.textContent = "Listener";

    const button = document.createElement("button");

    button.textContent = "Request to speak";
    button.addEventListener("click", () => wrapper.connection.send("ask_to_speak", {}));
    currentRole.appendChild(button);

    const unsubYbs = audioWrapper.subscribe.youBecameSpeaker(async ({ sendTransportOptions }) => {
      unsubYbs();

      await mediasoupConnect(
        wrapper.connection,
        routerRtpCapabilities,
        "input",
        sendTransportOptions,
        await makeMicTrack()
      )(device);

      currentRole.removeChild(button);
    });
  });

  const unsubYjas = audioWrapper.subscribe.youJoinedAsSpeaker(async ({
    routerRtpCapabilities,
    recvTransportOptions,
    sendTransportOptions
  }) => {
    unsubYjas();

    await mediasoupConnect(
      wrapper.connection,
      routerRtpCapabilities,
      "output",
      recvTransportOptions,
      playOutput
    )(device);

    await mediasoupConnect(
      wrapper.connection,
      routerRtpCapabilities,
      "input",
      sendTransportOptions,
      await makeMicTrack()
    )(device);
  });

  const extraInfo = await wrapper.query.joinRoomAndGetInfo(theRoom.id);
  document.querySelector(".current-room")!.textContent = theRoom.name;
}

main();


================================================
FILE: kebab/examples/mediasoup-audio/tsconfig.json
================================================
{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es6",
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "noEmitOnError": false,
    "resolveJsonModule": true,
    "importHelpers": true,
    "lib": [
      "ESNext",
      "DOM"
    ],
    "module": "commonjs",
    "esModuleInterop": true,
    "preserveSymlinks": true,
    "typeRoots": [
      "./node_modules/@types"
    ],
    "downlevelIteration": true,
    "skipLibCheck": true
  }
}


================================================
FILE: kebab/examples/react-chat/README.md
================================================
# Text-only chat (an example app)

1. Build the API package: `$ yarn` and `$ yarn build` in kebab's root directory
2. Setup the example: `$ yarn`
3. `$ yarn start` (put `SKIP_PREFLIGHT_CHECK=true` in your .env if it crashes)


================================================
FILE: kebab/examples/react-chat/package.json
================================================
{
  "name": "react-chat",
  "version": "0.1.0",
  "private": true,
  "homepage": ".",
  "dependencies": {
    "@dogehouse/kebab": "file:../..",
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "@types/jest": "^26.0.15",
    "@types/node": "^12.0.0",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-scripts": "4.0.3",
    "typescript": "^4.1.2",
    "web-vitals": "^1.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}


================================================
FILE: kebab/examples/react-chat/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>


================================================
FILE: kebab/examples/react-chat/public/manifest.json
================================================
{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}


================================================
FILE: kebab/examples/react-chat/public/robots.txt
================================================
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:


================================================
FILE: kebab/examples/react-chat/src/App.css
================================================
.chat-messages {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: visible;
  flex-grow: 1;
}

.chat-prompt {
  display: flex;
  gap: 10px;
}

.room-chat {
  display: flex;
  align-items: center;
  flex-direction: column;
  gap: 10px;
  height: 99%;
}

.login-form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 10px;
}


================================================
FILE: kebab/examples/react-chat/src/App.tsx
================================================
import React, { createContext, useContext, useEffect, useState } from "react";
import { Message, raw, Room, stringToToken, tokensToString, wrap, Wrapper } from "@dogehouse/kebab";
import "./App.css";

const APIWrapperContext = createContext<Wrapper>({} as Wrapper);

const MessageView = (props: { message: Message }) => (
  <span>
    <strong>{props.message.displayName}</strong>: {tokensToString(props.message.tokens)}
  </span>
);

const ChatMessages = () => {
  const wrapper = useContext(APIWrapperContext);
  const [messages, setMessages] = useState<Message[]>([]);

  useEffect(() => wrapper.subscribe.newChatMsg(({msg}) => setMessages(messages.concat(msg))));

  return (
    <div className="chat-messages">
      {messages.map(it => <MessageView message={it} key={it.sentAt}/>)}
    </div>
  );
};

const ChatPrompt = () => {
  const wrapper = useContext(APIWrapperContext);
  const [message, setMessage] = useState("");

  const sendMessage = async () => {
    if(message.length > 0) {
      await wrapper.mutation.sendRoomChatMsg(stringToToken(message));
      setMessage("");
    }
  };

  return (
    <div className="chat-prompt">
      <input value={message} onChange={e => setMessage(e.target.value)}/>
      <button onClick={sendMessage}>Send</button>
    </div>
  );
};

const RoomChat = (props: { room: Room }) => {
  const wrapper = useContext(APIWrapperContext);
  const [joined, setJoined] = useState(false);

  if(!joined) {
    wrapper.query.joinRoomAndGetInfo(props.room.id).then(() => setJoined(true));

    return <span>loading 3/3</span>;
  }

  return (
    <div className="room-chat">
      <h1>{props.room.name}</h1>
      <ChatMessages/>
      <ChatPrompt/>
    </div>
  );
};

const LoggedInPage = (props: { token: string, refreshToken: string }) => {
  const [connection, setConnection] = useState<raw.Connection | null>(null);
  const [publicRooms, setPublicRooms] = useState<Room[]>([]);

  useEffect(() => {
    raw.connect(props.token, props.refreshToken, {}).then(setConnection);
  }, [props.token, props.refreshToken]);

  if(!connection) {
    return <span>loading 1/3</span>;
  }

  const wrapper = wrap(connection);

  if(publicRooms.length === 0) {
    wrapper.query.getTopPublicRooms().then(({ rooms }) => setPublicRooms(rooms));

    return <span>loading 2/3</span>;
  }

  return (
    <APIWrapperContext.Provider value={wrapper}>
      <RoomChat room={publicRooms[0]}/>
    </APIWrapperContext.Provider>
  );
};

const LogInPage = (props: { logIn: (token: string, refreshToken: string) => void }) => {
  const [token, setToken] = useState("");
  const [refreshToken, setRefreshToken] = useState("");
  const submit = () => props.logIn(token, refreshToken);

  return (
    <form
      className="login-form"
      onSubmit={e => {
        e.preventDefault();
        submit();
      }}
    >
      <input
        type="password"
        placeholder="Token"
        minLength={24}
        value={token} onChange={({ target }) => setToken(target.value)}
      />
      <input
        type="password"
        placeholder="Refresh token"
        minLength={24}
        value={refreshToken} onChange={({ target }) => setRefreshToken(target.value)}
      />
      <input type="submit" value="Log in"/>
    </form>
  );
};

export const App = () => {
  const [creds, setCreds] = useState({ token: "", refreshToken: "" });
  const loggedIn = creds.token.length > 0 && creds.refreshToken.length > 0 // lmao

  return loggedIn
    ? <LoggedInPage token={creds.token} refreshToken={creds.refreshToken}/>
    : <LogInPage
        logIn={(newToken, newRefreshToken) =>
          setCreds({ token: newToken, refreshToken: newRefreshToken })
        }
      />;
};


================================================
FILE: kebab/examples/react-chat/src/index.css
================================================
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Ubuntu", sans-serif;
}

html, body, #root {
  height: 100%;
}

code {
  font-family: source-code-pro, Menlo, monospace;
}


================================================
FILE: kebab/examples/react-chat/src/index.tsx
================================================
import React from "react";
import { render } from "react-dom";
import "./index.css";
import { App } from "./App";

render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);


================================================
FILE: kebab/examples/react-chat/src/react-app-env.d.ts
================================================
/// <reference types="react-scripts" />


================================================
FILE: kebab/examples/react-chat/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}


================================================
FILE: kebab/jest.config.js
================================================
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};


================================================
FILE: kebab/package.json
================================================
{
  "name": "@dogehouse/kebab",
  "author": "Ilya Maximov <mail@overlisted.net> (https://overlisted.net)",
  "bugs": "https://github.com/benawad/dogehouse/issues",
  "version": "1.0.0",
  "license": "MIT",
  "keywords": [
    "dogehouse"
  ],
  "description": "The official DogeHouse API client.",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "lint": "eslint src/",
    "test": "jest"
  },
  "publishConfig": {
    "access": "public"
  },
  "dependencies": {
    "@types/uuid": "^8.3.0",
    "@types/ws": "^7.4.2",
    "isomorphic-unfetch": "^3.1.0",
    "isomorphic-ws": "^4.0.1",
    "mediasoup-client": "^3.6.30",
    "reconnecting-websocket": "^4.4.0",
    "uuid": "^8.3.2",
    "ws": "^7.4.5"
  },
  "devDependencies": {
    "@types/jest": "^26.0.23",
    "@typescript-eslint/eslint-plugin": "^4.22.0",
    "@typescript-eslint/parser": "^4.22.0",
    "eslint": "^7.25.0",
    "jest": "^26.6.3",
    "ts-jest": "^26.5.5",
    "typescript": "^4.2.4"
  }
}


================================================
FILE: kebab/src/README.md
================================================
http, websocket/wrapper.ts and websocket/responses.ts are deprecated and are only kept because of kibbeh


================================================
FILE: kebab/src/audio/audioWrapper.ts
================================================
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck because internet is unpredictable

import { raw } from "..";
import { RoomPeer, UUID } from "../entities";
import {
  TransportOptions,
  DtlsParameters,
  ConsumerOptions,
  RtpCapabilities,
  RtpParameters,
} from "mediasoup-client/lib/types";

/**
 * Allows you to handle custom logic on websocket voice events
 */
type Handler<Data> = (data: Data) => void;

/**
 * Creates a wrapper object that allows you to make websocket voice related calls using functions
 * @param {raw.Connection} connection - reference to the websocket connection
 * @returns {connection} Wrapper object
 */
export const wrap = (connection: raw.Connection) => ({
  connection,

  /**
   * Allows you to subscribe to various pre-defined websocket voice events
   */
  subscribe: {
    closeConsumer: (handler: Handler<{ producerId: UUID }>) =>
      connection.addListener("close_consumer", handler),
    newPeerSpeaker: (
      handler: Handler<{ peerId: UUID; consumerParameters: ConsumerOptions }>
    ) => connection.addListener("new-peer-speaker", handler),
    youJoinedAsPeer: (
      handler: Handler<{
        routerRtpCapabilities: RtpCapabilities;
        recvTransportOptions: TransportOptions;
      }>
    ) => connection.addListener("you-joined-as-peer", handler),
    youJoinedAsSpeaker: (
      handler: Handler<{
        routerRtpCapabilities: RtpCapabilities;
        recvTransportOptions: TransportOptions;
        sendTransportOptions: TransportOptions;
      }>
    ) => connection.addListener("you-joined-as-speaker", handler),
    youBecameSpeaker: (
      handler: Handler<{ sendTransportOptions: TransportOptions }>
    ) => connection.addListener("you-are-now-a-speaker", handler),
  },

  /**
   * Allows you to call functions that return information about the ws voice state
   */
  query: {
    getConsumersParameters: (
      rtpCapabilities: RtpCapabilities
    ): Promise<{ consumerParametersArr: RoomPeer[] }> =>
      connection.fetch(
        "@get-recv-tracks",
        { rtpCapabilities },
        "@get-recv-tracks-done"
      ),
  },

  /**
   * Allows you to call functions that mutate the ws voice state
   */
  mutation: {
    connectTransport: (
      transportId: UUID,
      direction: "send" | "recv",
      dtlsParameters: DtlsParameters
    ): Promise<{ error: string } | { roomId: UUID }> =>
      connection.fetch(
        "@connect-transport",
        { transportId, direction, dtlsParameters },
        `@connect-transport-${direction}-done`
      ),
    sendTrack: (
      transportId: UUID,
      kind: "audio",
      rtpParameters: RtpParameters,
      rtpCapabilities: RtpCapabilities,
      paused: false,
      appData: { mediaTag: "cam-audio" },
      direction: "send"
    ): Promise<{ id: UUID } | { error: string }> =>
      connection.fetch(
        "@send-track",
        {
          transportId,
          kind,
          rtpParameters,
          rtpCapabilities,
          paused,
          appData,
          direction,
        },
        `@send-track-${direction}-done`
      ),
  },
});


================================================
FILE: kebab/src/audio/interface.ts
================================================
import { raw, UUID } from "..";
import { RtpCapabilities, TransportOptions } from "mediasoup-client/lib/types";

export type ConsumerPlayer = (track: MediaStreamTrack, user: UUID) => void;
export type ConnectFunction<Return> = <Direction extends "input" | "output">(
  connection: raw.Connection,
  routerRtpCapabilities: RtpCapabilities,
  direction: Direction extends "input" ? "input" : "output",
  transportOptions: TransportOptions,
  track: Direction extends "input" ? MediaStreamTrack : ConsumerPlayer
) => Return;


================================================
FILE: kebab/src/audio/mediasoup-client.ts
================================================
import { Device, Transport } from "mediasoup-client/lib/types";
import { ConnectFunction, ConsumerPlayer } from "./interface";
import { RoomPeer } from "..";
import { wrap } from "./audioWrapper";

export const makeConsumer = (transport: Transport) => async (data: RoomPeer) => ({
  user: data.peerId,
  consumer: await transport.consume({
    ...data.consumerParameters,
    appData: {
      peerId: data.peerId,
      producerId: data.consumerParameters.producerId,
      mediaTag: "cam-audio"
    }
  })
});

export const connect: ConnectFunction<(device: Device) => Promise<void>> = (
  connection,
  routerRtpCapabilities,
  direction,
  transportOptions,
  track
) => async (device) => {
  if(!device.loaded) await device.load({ routerRtpCapabilities });

  const wrapper = wrap(connection);
  const simplerDirection = direction === "output" ? "recv" : "send";
  const transport = direction === "output"
    ? device.createRecvTransport(transportOptions)
    : device.createSendTransport(transportOptions);

  transport.on("connect", async ({ dtlsParameters }, resolve, reject) => {
    const result = await wrapper.mutation.connectTransport(transport.id, simplerDirection, dtlsParameters);

    if("error" in result) {
      console.error(result.error); // eslint-disable-line no-console
      reject();
    } else {
      resolve();
    }
  });

  if(direction === "input") {
    transport.on("produce", async ({ kind, rtpParameters, appData }, resolve, reject) => {
      const result = await wrapper.mutation.sendTrack(
        transportOptions.id,
        kind,
        rtpParameters,
        device.rtpCapabilities,
        false,
        appData,
        simplerDirection as "send"
      );

      if("error" in result) {
        console.error(result.error); // eslint-disable-line no-console
        reject();
      } else {
        resolve(result);
      }
    });

    await transport.produce({
      track: track as MediaStreamTrack,
      appData: { mediaTag: "cam-audio" }
    });
  } else {
    const { consumerParametersArr } = await wrapper.query.getConsumersParameters(device.rtpCapabilities);

    const consumers = await Promise.all(consumerParametersArr.map(makeConsumer(transport)));
    const unsubNps = wrapper.subscribe.newPeerSpeaker(async (peer) => {
      consumers.push(await makeConsumer(transport)(peer));
    });

    const unsubCc = wrapper.subscribe.closeConsumer(({ producerId }) => {
      const found = consumers.filter(it => it.consumer.producerId === producerId);

      if(found[0]) consumers.splice(consumers.indexOf(found[0]), 1);
    });

    const unsubYlr = connection.addListener("you_left_room", () => {
      unsubYlr();
      unsubNps();
      unsubCc();
    });

    const giveTrack = track as ConsumerPlayer;

    consumers.forEach(({ user, consumer }) => giveTrack(consumer.track, user));
  }
};


================================================
FILE: kebab/src/client/README.md
================================================
# Rewritten client
i felt like the current system isn't declarative enough so i rewrote it just using typescript

## How to add new stuff
ask me on discord


================================================
FILE: kebab/src/client/http/bot.ts
================================================
import { Endpoint } from "./endpoint";

export const auth: Endpoint<
  { apiKey: string },
  { username: string, accessToken: string, refreshToken: string }
> = ({ apiKey }) => [
  "/bot/auth",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: `{ "apiKey": "${apiKey}" }`
  }
];


================================================
FILE: kebab/src/client/http/dev.ts
================================================
import { Endpoint } from "./endpoint";

export const testInfo: Endpoint<
  { username: string },
  { accessToken: string, refreshToken: string }
> = ({ username }) => [`/dev/test-info?username=${username}`, {}];


================================================
FILE: kebab/src/client/http/endpoint.ts
================================================
export type Endpoint<O, R> = (options: O) => [string, RequestInit]; // eslint-disable-line @typescript-eslint/no-unused-vars

export * as dev from "./dev";
export * as bot from "./bot";


================================================
FILE: kebab/src/client/http/index.ts
================================================
import { Endpoint } from "./endpoint";
import fetch from "isomorphic-fetch";

export const apiUrl = "https://api.dogehouse.tv";

export type HTTPRequester = <O, R>(endpoint: Endpoint<O, R>, options: O) => Promise<R>;
export const httpRequest: HTTPRequester = async (endpoint, options) => {
  const [address, fetchOptions] = endpoint(options);

  const response = await fetch(apiUrl + address, fetchOptions);

  return await response.json() as any; // eslint-disable-line @typescript-eslint/no-explicit-any
};

export * as httpEndpoint from "./endpoint";



================================================
FILE: kebab/src/client/index.ts
================================================
import { request, Requester } from "./requester";
import { subscribe, Subscriber } from "./subscriber";
import { raw } from "../index";

export type Client = raw.Connection & {
  request: Requester,
  subscribe: Subscriber
};

export const createClient = (connection: raw.Connection): Client => ({
  ...connection,
  request: (name, data) => request(connection, name, data),
  subscribe: (name, handler, options = {}) => subscribe(connection, name, handler, options),
});

export * from "./http";
export * from "./requester";
export * from "./subscriber";


================================================
FILE: kebab/src/client/requester/auth.ts
================================================
import { EmptyObject } from "../type-util";

export default interface Requests {
  "request:but:you:dont:want:to:use:this": EmptyObject,
}


================================================
FILE: kebab/src/client/requester/chat.ts
================================================
import { MessageToken, UUID } from "../..";

export default interface Requests {
  ban: {
    request: { userId: UUID }
  },
  unban: {
    request: { userId: UUID }
  },
  send_msg: {
    request: {
      tokens: MessageToken[],
      whisperedTo: UUID[],
      isWhisper?: boolean
    }
  },
  delete: {
    request: { messageId: UUID }
  },
}


================================================
FILE: kebab/src/client/requester/index.ts
================================================
import { raw } from "../..";
import UserRequests from "./user";
import RoomRequests from "./room";
import ChatRequests from "./chat";
import MiscRequests from "./misc";
import AuthRequests from "./auth";
import { DefaultValues, EmptyObject, GroupMap, NormalObjectKey } from "../type-util";

type DefaultRequest = {
Download .txt
gitextract_vaj6l7zt/

├── .devcontainer/
│   ├── Dockerfile
│   ├── devcontainer.json
│   ├── docker-compose.yml
│   └── scripts/
│       ├── environment.sh
│       ├── node.sh
│       └── user.sh
├── .dockerignore
├── .editorconfig
├── .eslintignore
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── labeler.yml
│   └── workflows/
│       ├── baklava-build_and_release.yaml
│       ├── dolma-npm_deploy.yaml
│       ├── global-label_pr.yml
│       ├── global-lint_commit_messages.yaml
│       ├── globalkey-npm_deploy.yaml
│       ├── kebab-npm_publish.yaml
│       ├── kibbeh-e2e_tests.yaml
│       ├── kibbeh-lint_and_test.yaml
│       ├── kousa-deploy_staging.yaml
│       ├── kousa-tests.yaml
│       └── shawarma-deploy_staging.yaml
├── .gitignore
├── .husky/
│   ├── .gitignore
│   ├── commit-msg
│   └── pre-commit
├── .prettierignore
├── .prettierrc.js
├── .vscode/
│   └── settings.json
├── .yarnrc.yml
├── CHANGELOG.md
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── CREATE_BOT_ACCOUNT.MD
├── DESIGN_GUIDELINES.md
├── FAQ.md
├── HOW_TO_DEBUG_AUDIO.md
├── HOW_TO_GET_PERMA_BANNED_FROM_DOGEHOUSE.md
├── LICENSE
├── README.md
├── SECURITY.md
├── baklava/
│   ├── .gitignore
│   ├── .yarnrc.yml
│   ├── README.md
│   ├── icons/
│   │   └── icon.icns
│   ├── locales/
│   │   └── en/
│   │       └── translate.json
│   ├── package.json
│   ├── resources/
│   │   ├── overlay/
│   │   │   ├── .gitignore
│   │   │   ├── .yarnrc.yml
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── public/
│   │   │   │   └── index.html
│   │   │   └── src/
│   │   │       ├── App.css
│   │   │       ├── App.js
│   │   │       ├── index.css
│   │   │       ├── index.js
│   │   │       └── reportWebVitals.js
│   │   └── splash/
│   │       └── splash-screen.html
│   ├── scripts/
│   │   ├── generateTranslationTypes.ts
│   │   ├── syncTranslations.ts
│   │   ├── traverseTranslations.ts
│   │   └── tsconfig.json
│   ├── settings/
│   │   └── entitlements.mac.plist
│   ├── src/
│   │   ├── constants.ts
│   │   ├── dev.ts
│   │   ├── electron.ts
│   │   ├── generated/
│   │   │   └── translationKeys.ts
│   │   ├── types.ts
│   │   └── utils/
│   │       ├── keybinds.ts
│   │       ├── notifications.ts
│   │       ├── overlay/
│   │       │   ├── index.ts
│   │       │   └── ipc.ts
│   │       ├── rpc/
│   │       │   ├── index.ts
│   │       │   └── ipc.ts
│   │       └── tray.ts
│   └── tsconfig.json
├── commitlint.config.js
├── dinner/
│   ├── .eslintrc.json
│   ├── .gitignore
│   ├── package.json
│   ├── src/
│   │   ├── create-accounts.ts
│   │   └── play-audio.ts
│   └── tsconfig.json
├── docker-compose.local.yml
├── docker-compose.prod.yml
├── docker-compose.yml
├── docs/
│   ├── Architecture/
│   │   └── README.md
│   ├── Directory/
│   │   └── README.md
│   ├── Elixir Api/
│   │   └── README.MD
│   ├── README.MD
│   ├── React Front End/
│   │   └── README.MD
│   └── Voice Server/
│       └── README.MD
├── dolma/
│   ├── .editorconfig
│   ├── .gitignore
│   ├── LICENSE
│   ├── README.md
│   ├── package.json
│   ├── src/
│   │   ├── index.ts
│   │   ├── lib/
│   │   │   ├── decode.ts
│   │   │   ├── encode.ts
│   │   │   ├── filterString.ts
│   │   │   ├── filterUnitoken.ts
│   │   │   └── msgToken.ts
│   │   ├── test/
│   │   │   ├── run.ts
│   │   │   └── tests/
│   │   │       └── encoding.ts
│   │   ├── tokens/
│   │   │   ├── index.ts
│   │   │   └── types/
│   │   │       ├── block.ts
│   │   │       ├── emoji.ts
│   │   │       ├── emote.ts
│   │   │       ├── link.ts
│   │   │       ├── mention.ts
│   │   │       └── text.ts
│   │   └── util/
│   │       ├── regex.ts
│   │       └── types/
│   │           └── tokenTypes.ts
│   └── tsconfig.json
├── globalkey/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── README.md
│   ├── index.d.ts
│   ├── package.json
│   ├── src/
│   │   ├── build.rs
│   │   └── lib.rs
│   └── test.js
├── kebab/
│   ├── .eslintrc.json
│   ├── .gitignore
│   ├── .prettierrc.js
│   ├── README.md
│   ├── examples/
│   │   ├── bot/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   └── index.ts
│   │   │   └── tsconfig.json
│   │   ├── chat/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   └── index.ts
│   │   │   └── tsconfig.json
│   │   ├── create-bot/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   └── index.ts
│   │   │   └── tsconfig.json
│   │   ├── mediasoup-audio/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── index.css
│   │   │   │   ├── index.html
│   │   │   │   └── index.ts
│   │   │   └── tsconfig.json
│   │   └── react-chat/
│   │       ├── README.md
│   │       ├── package.json
│   │       ├── public/
│   │       │   ├── index.html
│   │       │   ├── manifest.json
│   │       │   └── robots.txt
│   │       ├── src/
│   │       │   ├── App.css
│   │       │   ├── App.tsx
│   │       │   ├── index.css
│   │       │   ├── index.tsx
│   │       │   └── react-app-env.d.ts
│   │       └── tsconfig.json
│   ├── jest.config.js
│   ├── package.json
│   ├── src/
│   │   ├── README.md
│   │   ├── audio/
│   │   │   ├── audioWrapper.ts
│   │   │   ├── interface.ts
│   │   │   └── mediasoup-client.ts
│   │   ├── client/
│   │   │   ├── README.md
│   │   │   ├── http/
│   │   │   │   ├── bot.ts
│   │   │   │   ├── dev.ts
│   │   │   │   ├── endpoint.ts
│   │   │   │   └── index.ts
│   │   │   ├── index.ts
│   │   │   ├── requester/
│   │   │   │   ├── auth.ts
│   │   │   │   ├── chat.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── misc.ts
│   │   │   │   ├── room.ts
│   │   │   │   └── user.ts
│   │   │   ├── subscriber/
│   │   │   │   ├── index.ts
│   │   │   │   └── legacy.ts
│   │   │   └── type-util.ts
│   │   ├── entities.ts
│   │   ├── http/
│   │   │   ├── bot.ts
│   │   │   ├── index.ts
│   │   │   ├── raw.ts
│   │   │   └── wrapper.ts
│   │   ├── index.ts
│   │   ├── pagination.ts
│   │   ├── util/
│   │   │   ├── ast.test.ts
│   │   │   ├── ast.ts
│   │   │   └── index.ts
│   │   └── websocket/
│   │       ├── index.ts
│   │       ├── raw.ts
│   │       ├── responses.ts
│   │       └── wrapper.ts
│   └── tsconfig.json
├── kibbeh/
│   ├── .babelrc
│   ├── .eslintignore
│   ├── .eslintrc.json
│   ├── .gitignore
│   ├── .prettierignore
│   ├── .prettierrc.js
│   ├── .storybook/
│   │   ├── main.js
│   │   ├── manager.js
│   │   ├── preview-head.html
│   │   └── preview.js
│   ├── .stylelintrc.json
│   ├── README.md
│   ├── cypress/
│   │   ├── .gitignore
│   │   ├── fixtures/
│   │   │   └── example.json
│   │   ├── integration/
│   │   │   ├── create-scheduled-room.ts
│   │   │   ├── edit-profile.ts
│   │   │   ├── room-creator.ts
│   │   │   └── search.ts
│   │   ├── plugins/
│   │   │   ├── index.js
│   │   │   └── sample_spec.js
│   │   ├── support/
│   │   │   ├── commands.ts
│   │   │   ├── index.d.ts
│   │   │   ├── index.js
│   │   │   └── test-constants.ts
│   │   └── tsconfig.json
│   ├── cypress.json
│   ├── deploy.sh
│   ├── next-env.d.ts
│   ├── next.config.js
│   ├── package.json
│   ├── postcss.config.js
│   ├── public/
│   │   ├── locales/
│   │   │   ├── af/
│   │   │   │   └── translation.json
│   │   │   ├── am/
│   │   │   │   └── translation.json
│   │   │   ├── ar/
│   │   │   │   └── translation.json
│   │   │   ├── az/
│   │   │   │   └── translation.json
│   │   │   ├── bg/
│   │   │   │   └── translation.json
│   │   │   ├── bn/
│   │   │   │   └── translation.json
│   │   │   ├── bottom/
│   │   │   │   └── translation.json
│   │   │   ├── cs/
│   │   │   │   └── translation.json
│   │   │   ├── da/
│   │   │   │   └── translation.json
│   │   │   ├── de/
│   │   │   │   └── translation.json
│   │   │   ├── de-AT/
│   │   │   │   └── translation.json
│   │   │   ├── el/
│   │   │   │   └── translation.json
│   │   │   ├── en/
│   │   │   │   └── translation.json
│   │   │   ├── en-AU/
│   │   │   │   └── translation.json
│   │   │   ├── en-C/
│   │   │   │   ├── GUIDE.md
│   │   │   │   └── translation.json
│   │   │   ├── en-CODE/
│   │   │   │   └── translation.json
│   │   │   ├── en-LOLCAT/
│   │   │   │   └── translation.json
│   │   │   ├── en-OWO/
│   │   │   │   └── translation.json
│   │   │   ├── en-PIGLATIN/
│   │   │   │   └── translation.json
│   │   │   ├── en-PIRATE/
│   │   │   │   └── translation.json
│   │   │   ├── eo/
│   │   │   │   └── translation.json
│   │   │   ├── es/
│   │   │   │   └── translation.json
│   │   │   ├── et/
│   │   │   │   └── translation.json
│   │   │   ├── eu/
│   │   │   │   └── translation.json
│   │   │   ├── fa/
│   │   │   │   └── translation.json
│   │   │   ├── fi/
│   │   │   │   └── translation.json
│   │   │   ├── fr/
│   │   │   │   └── translation.json
│   │   │   ├── grc/
│   │   │   │   └── translation.json
│   │   │   ├── gsw/
│   │   │   │   └── translation.json
│   │   │   ├── he/
│   │   │   │   └── translation.json
│   │   │   ├── hi/
│   │   │   │   └── translation.json
│   │   │   ├── hr/
│   │   │   │   └── translation.json
│   │   │   ├── hu/
│   │   │   │   └── translation.json
│   │   │   ├── id/
│   │   │   │   └── translation.json
│   │   │   ├── is/
│   │   │   │   └── translation.json
│   │   │   ├── it/
│   │   │   │   └── translation.json
│   │   │   ├── ja/
│   │   │   │   └── translation.json
│   │   │   ├── kk/
│   │   │   │   └── translation.json
│   │   │   ├── ko/
│   │   │   │   └── translation.json
│   │   │   ├── ku/
│   │   │   │   └── translation.json
│   │   │   ├── li/
│   │   │   │   └── translation.json
│   │   │   ├── lld/
│   │   │   │   └── translation.json
│   │   │   ├── lt/
│   │   │   │   └── translation.json
│   │   │   ├── lv/
│   │   │   │   └── translation.json
│   │   │   ├── nb/
│   │   │   │   └── translation.json
│   │   │   ├── ne/
│   │   │   │   └── translation.json
│   │   │   ├── nl/
│   │   │   │   └── translation.json
│   │   │   ├── pl/
│   │   │   │   └── translation.json
│   │   │   ├── pt-BR/
│   │   │   │   └── translation.json
│   │   │   ├── pt-PT/
│   │   │   │   └── translation.json
│   │   │   ├── ro/
│   │   │   │   └── translation.json
│   │   │   ├── ru/
│   │   │   │   └── translation.json
│   │   │   ├── sa/
│   │   │   │   └── translation.json
│   │   │   ├── si/
│   │   │   │   └── translation.json
│   │   │   ├── sk/
│   │   │   │   └── translation.json
│   │   │   ├── sl/
│   │   │   │   └── translation.json
│   │   │   ├── so/
│   │   │   │   └── translation.json
│   │   │   ├── sq/
│   │   │   │   └── translation.json
│   │   │   ├── sr/
│   │   │   │   └── translation.json
│   │   │   ├── sr-LATIN/
│   │   │   │   └── translation.json
│   │   │   ├── sv/
│   │   │   │   └── translation.json
│   │   │   ├── ta/
│   │   │   │   └── translation.json
│   │   │   ├── te/
│   │   │   │   └── translation.json
│   │   │   ├── th/
│   │   │   │   └── translation.json
│   │   │   ├── tl/
│   │   │   │   └── translation.json
│   │   │   ├── tp/
│   │   │   │   └── translation.json
│   │   │   ├── tr/
│   │   │   │   └── translation.json
│   │   │   ├── uk/
│   │   │   │   └── translation.json
│   │   │   ├── ur/
│   │   │   │   └── translation.json
│   │   │   ├── uz/
│   │   │   │   └── translation.json
│   │   │   ├── vi/
│   │   │   │   └── translation.json
│   │   │   ├── zh-CN/
│   │   │   │   └── translation.json
│   │   │   └── zh-TW/
│   │   │       └── translation.json
│   │   ├── manifest.json
│   │   ├── privacy-policy.html
│   │   └── terms.html
│   ├── scripts/
│   │   ├── syncTranslations.ts
│   │   ├── traverseTranslations.ts
│   │   └── tsconfig.json
│   ├── src/
│   │   ├── form-fields/
│   │   │   ├── FieldSpacer.tsx
│   │   │   └── InputField.tsx
│   │   ├── global-stores/
│   │   │   ├── useAccountOverlay.ts
│   │   │   ├── useAskForMicStore.ts
│   │   │   ├── useAudioTracks.ts
│   │   │   ├── useCurrentRoomIdStore.ts
│   │   │   ├── useDeafStore.ts
│   │   │   ├── useDebugAudio.ts
│   │   │   ├── useDownloadAlertStore.ts
│   │   │   ├── useElectronMobileStore.ts
│   │   │   ├── useEmojiPickerStore.ts
│   │   │   ├── useGlobalVolumeStore.ts
│   │   │   ├── useHostStore.ts
│   │   │   ├── useKeyMapStore.ts
│   │   │   ├── useMicPermErrorStore.ts
│   │   │   ├── useMuteStore.ts
│   │   │   ├── useOverlayStore.ts
│   │   │   ├── useProducerStore.ts
│   │   │   ├── useRoomChatMentionStore.ts
│   │   │   ├── useSocketStatus.ts
│   │   │   └── useStatus.ts
│   │   ├── globals.d.ts
│   │   ├── icons/
│   │   │   ├── BotIcon.tsx
│   │   │   ├── DeveloperIcon.tsx
│   │   │   ├── LgLogo.tsx
│   │   │   ├── Link.tsx
│   │   │   ├── LogoIcon.tsx
│   │   │   ├── MacCloseIcon.tsx
│   │   │   ├── MacMaximizeIcon.tsx
│   │   │   ├── MacMinimizeIcon.tsx
│   │   │   ├── OutlineGlobe.tsx
│   │   │   ├── Share.tsx
│   │   │   ├── Smiley.tsx
│   │   │   ├── SolidBug.tsx
│   │   │   ├── SolidCalendar.tsx
│   │   │   ├── SolidCaretRight.tsx
│   │   │   ├── SolidChatBubble.tsx
│   │   │   ├── SolidCompass.tsx
│   │   │   ├── SolidContributor.tsx
│   │   │   ├── SolidDeafened.tsx
│   │   │   ├── SolidDeafenedOff.tsx
│   │   │   ├── SolidDiscord.tsx
│   │   │   ├── SolidDogenitro.tsx
│   │   │   ├── SolidDownload.tsx
│   │   │   ├── SolidFriends.tsx
│   │   │   ├── SolidFriendsAdd.tsx
│   │   │   ├── SolidFullscreen.tsx
│   │   │   ├── SolidGitHub.tsx
│   │   │   ├── SolidGoogle.tsx
│   │   │   ├── SolidHelp.tsx
│   │   │   ├── SolidHome.tsx
│   │   │   ├── SolidInstagram.tsx
│   │   │   ├── SolidKeyboard.tsx
│   │   │   ├── SolidLink.tsx
│   │   │   ├── SolidLogOut.tsx
│   │   │   ├── SolidMegaphone.tsx
│   │   │   ├── SolidMessages.tsx
│   │   │   ├── SolidMicrophone.tsx
│   │   │   ├── SolidMicrophoneOff.tsx
│   │   │   ├── SolidMoon.tsx
│   │   │   ├── SolidNew.tsx
│   │   │   ├── SolidNotification.tsx
│   │   │   ├── SolidPersonAdd.tsx
│   │   │   ├── SolidPlus.tsx
│   │   │   ├── SolidRocket.tsx
│   │   │   ├── SolidSearch.tsx
│   │   │   ├── SolidSettings.tsx
│   │   │   ├── SolidSimpleMegaphone.tsx
│   │   │   ├── SolidStaff.tsx
│   │   │   ├── SolidTime.tsx
│   │   │   ├── SolidTrash.tsx
│   │   │   ├── SolidTwitter.tsx
│   │   │   ├── SolidUser.tsx
│   │   │   ├── SolidVolume.tsx
│   │   │   ├── SolidVolumeOff.tsx
│   │   │   ├── SolidWarning.tsx
│   │   │   ├── WinCloseIcon.tsx
│   │   │   ├── WinMaximizeIcon.tsx
│   │   │   ├── WinMinimizeIcon.tsx
│   │   │   ├── badges/
│   │   │   │   ├── ContributorBadge.tsx
│   │   │   │   ├── StaffBadge.tsx
│   │   │   │   └── index.tsx
│   │   │   └── index.tsx
│   │   ├── jest.config.js
│   │   ├── lib/
│   │   │   ├── constants.ts
│   │   │   ├── createChatMessage.ts
│   │   │   ├── defaultQueryFn.ts
│   │   │   ├── i18n.ts
│   │   │   ├── isCurrentRoomId.ts
│   │   │   ├── isServer.ts
│   │   │   ├── isWebRTCEnabled.ts
│   │   │   ├── kFormatter.ts
│   │   │   ├── queryClient.ts
│   │   │   ├── roomToCurrentRoom.ts
│   │   │   ├── showErrorToast.ts
│   │   │   ├── tests/
│   │   │   │   ├── constants.test.ts
│   │   │   │   └── kFormatter.test.ts
│   │   │   └── validateStruct.ts
│   │   ├── modules/
│   │   │   ├── admin/
│   │   │   │   ├── AdminPage.tsx
│   │   │   │   └── AdminPageForm.tsx
│   │   │   ├── auth/
│   │   │   │   ├── WaitForWsAndAuth.tsx
│   │   │   │   ├── useSaveTokensFromQueryParams.ts
│   │   │   │   ├── useTokenStore.ts
│   │   │   │   └── useVerifyLoggedIn.ts
│   │   │   ├── dashboard/
│   │   │   │   ├── CreateRoomModal.tsx
│   │   │   │   ├── DashboardPage.tsx
│   │   │   │   ├── FeedController.tsx
│   │   │   │   ├── FollowingOnlineController.tsx
│   │   │   │   ├── MinimizedRoomCardController.tsx
│   │   │   │   └── ProfileBlockController.tsx
│   │   │   ├── debugging/
│   │   │   │   ├── AudioDebugAvatar.tsx
│   │   │   │   └── AudioDebugPanel.tsx
│   │   │   ├── developer/
│   │   │   │   ├── Bot.tsx
│   │   │   │   ├── BotCard.tsx
│   │   │   │   ├── BotIcon.tsx
│   │   │   │   ├── BotInfo.tsx
│   │   │   │   ├── BotsEditPage.tsx
│   │   │   │   ├── BotsPage.tsx
│   │   │   │   ├── CreateBotModal.tsx
│   │   │   │   ├── DeveloperNavButton.tsx
│   │   │   │   ├── DeveloperPanel.tsx
│   │   │   │   ├── EditBot.tsx
│   │   │   │   └── YourBots.tsx
│   │   │   ├── display/
│   │   │   │   ├── HeaderController.tsx
│   │   │   │   └── TextParser.tsx
│   │   │   ├── errors/
│   │   │   │   ├── ErrorToastController.tsx
│   │   │   │   └── useErrorToastStore.tsx
│   │   │   ├── keyboard-shortcuts/
│   │   │   │   ├── ChatKeybind.tsx
│   │   │   │   ├── DeafKeybind.tsx
│   │   │   │   ├── InviteKeybind.tsx
│   │   │   │   ├── KeybindListener.tsx
│   │   │   │   ├── MuteKeybind.tsx
│   │   │   │   ├── OverlayKeybind.tsx
│   │   │   │   ├── PTTKeybind.tsx
│   │   │   │   ├── RequestToSpeakKeybind.tsx
│   │   │   │   └── index.ts
│   │   │   ├── landing-page/
│   │   │   │   └── LoginPage.tsx
│   │   │   ├── language/
│   │   │   │   └── LanguagePage.tsx
│   │   │   ├── layouts/
│   │   │   │   ├── DefaultDesktopLayout.tsx
│   │   │   │   ├── ElectronHeader.tsx
│   │   │   │   ├── FloatingRoomInfo.tsx
│   │   │   │   ├── GridPanels.tsx
│   │   │   │   ├── MainLayout.tsx
│   │   │   │   └── TabletSidebar.tsx
│   │   │   ├── room/
│   │   │   │   ├── AudioDebugConsumerSection.tsx
│   │   │   │   ├── BlockedFromRoomUsers.tsx
│   │   │   │   ├── InviteRoomPage.tsx
│   │   │   │   ├── RoomChatController.tsx
│   │   │   │   ├── RoomOpenGraphPreview.tsx
│   │   │   │   ├── RoomPage.tsx
│   │   │   │   ├── RoomPanelController.tsx
│   │   │   │   ├── RoomPanelIconBarController.tsx
│   │   │   │   ├── RoomSettingModal.tsx
│   │   │   │   ├── RoomUsersPanel.tsx
│   │   │   │   ├── UserPreviewModal.tsx
│   │   │   │   ├── UserPreviewModalProvider.tsx
│   │   │   │   ├── ViewScheduledRoomPage.tsx
│   │   │   │   ├── VolumeSliderController.tsx
│   │   │   │   ├── chat/
│   │   │   │   │   ├── Emote.tsx
│   │   │   │   │   ├── EmoteData.ts
│   │   │   │   │   ├── RoomChat.tsx
│   │   │   │   │   ├── RoomChatInput.tsx
│   │   │   │   │   ├── RoomChatList.tsx
│   │   │   │   │   ├── RoomChatMentions.tsx
│   │   │   │   │   ├── navigateThroughQueriedEmojis.ts
│   │   │   │   │   ├── navigateThroughQueriedUsers.ts
│   │   │   │   │   ├── useRoomChatMentionStore.ts
│   │   │   │   │   └── useRoomChatStore.ts
│   │   │   │   ├── mobile/
│   │   │   │   │   └── RoomOverlay.tsx
│   │   │   │   ├── useGetRoomByQueryParam.ts
│   │   │   │   ├── useResize.ts
│   │   │   │   └── useSplitUsersIntoSections.tsx
│   │   │   ├── scheduled-rooms/
│   │   │   │   ├── AddToCalendar.tsx
│   │   │   │   ├── CopyScheduleRoomLinkButton.tsx
│   │   │   │   ├── CreateScheduledRoomModal.tsx
│   │   │   │   ├── EditScheduleRoomModalController.tsx
│   │   │   │   ├── ScheduledRoomCard.tsx
│   │   │   │   ├── ScheduledRoomsList.tsx
│   │   │   │   ├── ScheduledRoomsPage.tsx
│   │   │   │   ├── copyToClipboard.ts
│   │   │   │   └── makeUrls.ts
│   │   │   ├── search/
│   │   │   │   ├── SearchBarController.tsx
│   │   │   │   └── SearchPage.tsx
│   │   │   ├── settings/
│   │   │   │   ├── OverlaySettingsPage.tsx
│   │   │   │   ├── PrivacySettingForm.tsx
│   │   │   │   ├── PrivacySettingsPage.tsx
│   │   │   │   ├── SoundEffectSettingsPage.tsx
│   │   │   │   └── VoiceSettingsPage.tsx
│   │   │   ├── sound-effects/
│   │   │   │   ├── SoundEffectPlayer.tsx
│   │   │   │   └── useSoundEffectStore.ts
│   │   │   ├── user/
│   │   │   │   ├── EditProfileModal.tsx
│   │   │   │   ├── FollowingController.tsx
│   │   │   │   ├── FollowingOnlinePage.tsx
│   │   │   │   ├── FollowingPage.tsx
│   │   │   │   ├── UserPage.tsx
│   │   │   │   ├── UserProfileController.tsx
│   │   │   │   └── VerticalUserInfoWithFollowButton.tsx
│   │   │   ├── webrtc/
│   │   │   │   ├── WebRtcApp.tsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── ActiveSpeakerListener.tsx
│   │   │   │   │   ├── AudioRender.tsx
│   │   │   │   │   └── MicPicker.tsx
│   │   │   │   ├── stores/
│   │   │   │   │   ├── useAskForMicStore.ts
│   │   │   │   │   ├── useAudioTracks.ts
│   │   │   │   │   ├── useConsumerStore.ts
│   │   │   │   │   ├── useMicIdStore.ts
│   │   │   │   │   ├── useMicPermErrorStore.ts
│   │   │   │   │   ├── useProducerStore.ts
│   │   │   │   │   ├── useSocketStatus.ts
│   │   │   │   │   ├── useStatus.ts
│   │   │   │   │   └── useVoiceStore.ts
│   │   │   │   ├── types.ts
│   │   │   │   └── utils/
│   │   │   │       ├── consumeAudio.ts
│   │   │   │       ├── createTransport.ts
│   │   │   │       ├── joinRoom.ts
│   │   │   │       ├── mergeRoomPermission.ts
│   │   │   │       ├── receiveVoice.ts
│   │   │   │       └── sendVoice.ts
│   │   │   └── ws/
│   │   │       └── WebSocketProvider.tsx
│   │   ├── pages/
│   │   │   ├── 404.tsx
│   │   │   ├── _app.tsx
│   │   │   ├── admin.tsx
│   │   │   ├── connection-taken.tsx
│   │   │   ├── dash.tsx
│   │   │   ├── developer/
│   │   │   │   └── bots/
│   │   │   │       ├── edit/
│   │   │   │       │   └── [username]/
│   │   │   │       │       └── index.tsx
│   │   │   │       └── index.tsx
│   │   │   ├── download.tsx
│   │   │   ├── index.tsx
│   │   │   ├── language.tsx
│   │   │   ├── logout.tsx
│   │   │   ├── overlay-settings.tsx
│   │   │   ├── privacy-settings.tsx
│   │   │   ├── room/
│   │   │   │   └── [id]/
│   │   │   │       ├── index.tsx
│   │   │   │       └── invite.tsx
│   │   │   ├── scheduled-room/
│   │   │   │   └── [id].tsx
│   │   │   ├── scheduled-rooms.tsx
│   │   │   ├── search.tsx
│   │   │   ├── sound-effect-settings.tsx
│   │   │   ├── u/
│   │   │   │   └── [username]/
│   │   │   │       ├── followers.tsx
│   │   │   │       ├── following-online.tsx
│   │   │   │       ├── following.tsx
│   │   │   │       └── index.tsx
│   │   │   └── voice-settings.tsx
│   │   ├── shared-components/
│   │   │   ├── ApiPreloadLink.tsx
│   │   │   ├── ConfirmModal.tsx
│   │   │   └── InvitedToJoinRoomModal.tsx
│   │   ├── shared-hooks/
│   │   │   ├── useBoundingClientRect.ts
│   │   │   ├── useConn.ts
│   │   │   ├── useCurrentRoomFromCache.ts
│   │   │   ├── useCurrentRoomId.ts
│   │   │   ├── useCurrentRoomInfo.ts
│   │   │   ├── useDevices.ts
│   │   │   ├── useIntersectionObserver.ts
│   │   │   ├── useLeaveRoom.ts
│   │   │   ├── useMainWsHandler.tsx
│   │   │   ├── useOnClickOutside.tsx
│   │   │   ├── usePageVisibility.ts
│   │   │   ├── useScreenType.ts
│   │   │   ├── useScreenWakeLockStore.ts
│   │   │   ├── useSetDeaf.ts
│   │   │   ├── useSetMute.ts
│   │   │   ├── useTypeSafeMutation.ts
│   │   │   ├── useTypeSafePrefetch.ts
│   │   │   ├── useTypeSafeQuery.ts
│   │   │   ├── useTypeSafeTranslation.ts
│   │   │   ├── useTypeSafeUpdateQuery.ts
│   │   │   ├── useViewportSize.ts
│   │   │   └── useWindowSize.ts
│   │   ├── stories/
│   │   │   ├── AccountOverlay.story.tsx
│   │   │   ├── BaseDropdownSm.story.tsx
│   │   │   ├── BaseOverlay.story.tsx
│   │   │   ├── BaseSettingsItem.story.tsx
│   │   │   ├── BoxedIcon.story.tsx
│   │   │   ├── BubbleText.story.tsx
│   │   │   ├── Button.story.tsx
│   │   │   ├── ChangeAvatarCard.story.tsx
│   │   │   ├── ChangeBannerCard.story.tsx
│   │   │   ├── ErrorButtonItem.story.tsx
│   │   │   ├── ErrorToast.story.tsx
│   │   │   ├── FriendsOnline.story.tsx
│   │   │   ├── KeybindCard.story.tsx
│   │   │   ├── LeftHeader.story.tsx
│   │   │   ├── MessageElement.story.tsx
│   │   │   ├── MessagesDropdown.story.tsx
│   │   │   ├── MiddleHeader.story.tsx
│   │   │   ├── MinimizedRoomCard.story.tsx
│   │   │   ├── MobileHeader/
│   │   │   │   ├── PageHeader.story.tsx
│   │   │   │   ├── ProfileHeader.story.tsx
│   │   │   │   └── SearchHeader.story.tsx
│   │   │   ├── MobileNav.story.tsx
│   │   │   ├── NativeCheckbox.story.tsx
│   │   │   ├── NativeRadio.story.tsx
│   │   │   ├── NotificationElement/
│   │   │   │   ├── FollowNotification.story.tsx
│   │   │   │   ├── GenericNotification.story.tsx
│   │   │   │   ├── LiveNotification.story.tsx
│   │   │   │   └── NewRoomNotification.story.tsx
│   │   │   ├── NotificationsDropdown.story.tsx
│   │   │   ├── ProfileAbout.story.tsx
│   │   │   ├── ProfileBlock.story.tsx
│   │   │   ├── ProfileHeader.story.tsx
│   │   │   ├── ProfileHeaderWrapper.story.tsx
│   │   │   ├── ProfileTabs.story.tsx
│   │   │   ├── RightHeader.story.tsx
│   │   │   ├── RoomAvatar.story.tsx
│   │   │   ├── RoomCard.story.tsx
│   │   │   ├── RoomCardHeading.story.tsx
│   │   │   ├── RoomCardParticipants.story.tsx
│   │   │   ├── RoomHeader.story.tsx
│   │   │   ├── RoomPanelIconBar.story.tsx
│   │   │   ├── RoomSectionHeader.story.tsx
│   │   │   ├── Search/
│   │   │   │   ├── GlobalSearch.story.tsx
│   │   │   │   ├── SearchBar.story.tsx
│   │   │   │   ├── SearchHistory.story.tsx
│   │   │   │   ├── SearchOverlay.story.tsx
│   │   │   │   └── SearchResult/
│   │   │   │       ├── RoomSearchResult.story.tsx
│   │   │   │       └── UserSearchResult.story.tsx
│   │   │   ├── SettingsDropdown.story.tsx
│   │   │   ├── SettingsIcon.story.tsx
│   │   │   ├── SettingsItemButton.story.tsx
│   │   │   ├── SettingsWrapper.story.tsx
│   │   │   ├── Tag.story.tsx
│   │   │   ├── UpcomingRoomCardLg.story.tsx
│   │   │   ├── UpcomingRoomsCard.story.tsx
│   │   │   ├── UserAvatar/
│   │   │   │   ├── MultipleUsers.story.tsx
│   │   │   │   └── SingleUser.story.tsx
│   │   │   ├── UserBadge.story.tsx
│   │   │   ├── UserBadgeLg.story.tsx
│   │   │   ├── UserSummaryCard.story.tsx
│   │   │   ├── UserWideButton.story.tsx
│   │   │   ├── VerticalUserInfo.story.tsx
│   │   │   ├── VolumeIndicator.story.tsx
│   │   │   ├── data/
│   │   │   │   └── BaseUser.tsx
│   │   │   ├── mobile/
│   │   │   │   ├── FeaturedRoomCardAvatars.story.tsx
│   │   │   │   └── FeaturedRoomCardHosts.story.tsx
│   │   │   └── utils/
│   │   │       ├── GbFlagIcon.tsx
│   │   │       ├── toBoolean.ts
│   │   │       ├── toEnum.ts
│   │   │       └── toStr.ts
│   │   ├── styles/
│   │   │   ├── banner-button.css
│   │   │   ├── date-time-picker.css
│   │   │   ├── electron-header.css
│   │   │   └── globals.css
│   │   ├── types/
│   │   │   ├── PageComponent.ts
│   │   │   ├── index.d.ts
│   │   │   ├── overrides-mui.d.ts
│   │   │   ├── user.d.ts
│   │   │   ├── util-types.ts
│   │   │   └── wakeLock.d.ts
│   │   └── ui/
│   │       ├── Banner.tsx
│   │       ├── BannerButton.tsx
│   │       ├── BaseDropdownSm.tsx
│   │       ├── BaseOverlay.tsx
│   │       ├── BaseSettingsItem.tsx
│   │       ├── BoxedIcon.tsx
│   │       ├── BubbleText.tsx
│   │       ├── Button.tsx
│   │       ├── ButtonLink.tsx
│   │       ├── CenterLoader.tsx
│   │       ├── ChangeAvatarCard.tsx
│   │       ├── ChangeBannerCard.tsx
│   │       ├── DropdownController.tsx
│   │       ├── DurationTicker.tsx
│   │       ├── EmojiPicker.tsx
│   │       ├── ErrorButtonItem.tsx
│   │       ├── ErrorMessageButton.tsx
│   │       ├── ErrorToast.tsx
│   │       ├── FeedHeader.tsx
│   │       ├── FollowersOnline.tsx
│   │       ├── GridPanel.tsx
│   │       ├── InfoText.tsx
│   │       ├── Input.tsx
│   │       ├── InputErrorMsg.tsx
│   │       ├── KeybindCard.tsx
│   │       ├── LanguageSearch.tsx
│   │       ├── LanguageSelector.tsx
│   │       ├── MacButton.tsx
│   │       ├── MainGrid.tsx
│   │       ├── MessageElement.tsx
│   │       ├── MessagesDropdown.tsx
│   │       ├── MinimizedRoomCard.tsx
│   │       ├── Modal.tsx
│   │       ├── NativeCheckbox.tsx
│   │       ├── NativeRadio.tsx
│   │       ├── NativeSelect.tsx
│   │       ├── NotificationElement/
│   │       │   ├── FollowNotification.tsx
│   │       │   ├── GenericNotification.tsx
│   │       │   ├── LiveNotification.tsx
│   │       │   ├── NewRoomNotification.tsx
│   │       │   └── index.tsx
│   │       ├── NotificationsDropdown.tsx
│   │       ├── ProfileAbout.tsx
│   │       ├── ProfileAdmin.tsx
│   │       ├── ProfileBlock.tsx
│   │       ├── ProfileHeader.tsx
│   │       ├── ProfileHeaderWrapper.tsx
│   │       ├── ProfileScheduled.tsx
│   │       ├── ProfileTabs.tsx
│   │       ├── RoomAvatar.tsx
│   │       ├── RoomCard.tsx
│   │       ├── RoomCardHeading.tsx
│   │       ├── RoomCardParticipants.tsx
│   │       ├── RoomHeader.tsx
│   │       ├── RoomPanelIconBar.tsx
│   │       ├── RoomSectionHeader.tsx
│   │       ├── Search/
│   │       │   ├── GlobalSearch.tsx
│   │       │   ├── SearchBar.tsx
│   │       │   ├── SearchHistory.tsx
│   │       │   ├── SearchOverlay.tsx
│   │       │   └── SearchResult/
│   │       │       ├── RoomSearchResult.tsx
│   │       │       ├── UserSearchResult.tsx
│   │       │       └── index.ts
│   │       ├── SettingsDropdown.tsx
│   │       ├── SettingsIcon.tsx
│   │       ├── SettingsItemButton.tsx
│   │       ├── SettingsWrapper.tsx
│   │       ├── Spinner.tsx
│   │       ├── Tag.tsx
│   │       ├── Toast.tsx
│   │       ├── Twemoji.tsx
│   │       ├── UpcomingRoomCardLg.tsx
│   │       ├── UpcomingRoomsCard.tsx
│   │       ├── UserAvatar/
│   │       │   ├── MultipleUsers.tsx
│   │       │   ├── SingleUser.tsx
│   │       │   ├── index.ts
│   │       │   └── tests/
│   │       │       ├── MultipleUser.spec.tsx
│   │       │       ├── SingleUser.spec.tsx
│   │       │       └── __snapshots__/
│   │       │           ├── MultipleUser.spec.tsx.snap
│   │       │           └── SingleUser.spec.tsx.snap
│   │       ├── UserBadge.tsx
│   │       ├── UserBadgeLg.tsx
│   │       ├── UserProfile.tsx
│   │       ├── UserSummaryCard.tsx
│   │       ├── UserWideButton.tsx
│   │       ├── VerticalUserInfo.tsx
│   │       ├── VolumeIndicator.tsx
│   │       ├── VolumeSlider.tsx
│   │       ├── WinButton.tsx
│   │       ├── header/
│   │       │   ├── LeftHeader.tsx
│   │       │   ├── MiddleHeader.tsx
│   │       │   └── RightHeader.tsx
│   │       ├── mobile/
│   │       │   ├── AccountOverlay.tsx
│   │       │   ├── FeaturedRoomCardAvatars.tsx
│   │       │   ├── FeaturedRoomCardHosts.tsx
│   │       │   ├── MobileHeader/
│   │       │   │   ├── PageHeader.tsx
│   │       │   │   ├── ProfileHeader.tsx
│   │       │   │   ├── SearchHeader.tsx
│   │       │   │   └── index.tsx
│   │       │   └── MobileNav.tsx
│   │       └── tests/
│   │           ├── BaseOverlay.spec.tsx
│   │           ├── BoxedIcon.spec.tsx
│   │           ├── BubbleText.spec.tsx
│   │           ├── Button.spec.tsx
│   │           ├── ErrorMessageButton.spec.tsx
│   │           ├── ErrorToast.spec.tsx
│   │           ├── Input.spec.tsx
│   │           ├── InputErrorMsg.spec.tsx
│   │           ├── MainGrid.spec.tsx
│   │           ├── MessageElement.spec.tsx
│   │           ├── MessagesDropdown.spec.tsx
│   │           ├── MinimizedRoomCard.spec.tsx
│   │           └── __snapshots__/
│   │               ├── BaseOverlay.spec.tsx.snap
│   │               ├── BoxedIcon.spec.tsx.snap
│   │               ├── BubbleText.spec.tsx.snap
│   │               ├── Button.spec.tsx.snap
│   │               ├── ErrorMessageButton.spec.tsx.snap
│   │               ├── ErrorToast.spec.tsx.snap
│   │               ├── Input.spec.tsx.snap
│   │               ├── InputErrorMsg.spec.tsx.snap
│   │               ├── MainGrid.spec.tsx.snap
│   │               ├── MessageElement.spec.tsx.snap
│   │               └── MinimizedRoomCard.spec.tsx.snap
│   ├── tailwind.config.js
│   ├── test-utils.ts
│   └── tsconfig.json
├── kousa/
│   ├── .envrc
│   ├── .formatter.exs
│   ├── .gitignore
│   ├── ADDING_TO_MESSAGING_API.md
│   ├── ARCHITECTURE.md
│   ├── Dockerfile
│   ├── README.md
│   ├── ROADMAP.md
│   ├── config/
│   │   ├── config.exs
│   │   ├── dev.exs
│   │   ├── prod.exs
│   │   ├── releases.exs
│   │   └── test.exs
│   ├── deploy.sh
│   ├── lib/
│   │   ├── beef/
│   │   │   ├── _repo.ex
│   │   │   ├── access/
│   │   │   │   ├── rooms.ex
│   │   │   │   ├── user_blocks.ex
│   │   │   │   └── users.ex
│   │   │   ├── follows.ex
│   │   │   ├── mutations/
│   │   │   │   ├── rooms.ex
│   │   │   │   ├── user_blocks.ex
│   │   │   │   └── users.ex
│   │   │   ├── queries/
│   │   │   │   ├── rooms.ex
│   │   │   │   ├── user_blocks.ex
│   │   │   │   └── users.ex
│   │   │   ├── room_blocks.ex
│   │   │   ├── room_permissions.ex
│   │   │   ├── rooms.ex
│   │   │   ├── scheduled_rooms.ex
│   │   │   ├── schemas/
│   │   │   │   ├── attending_scheduled_room.ex
│   │   │   │   ├── follow.ex
│   │   │   │   ├── room.ex
│   │   │   │   ├── room_block.ex
│   │   │   │   ├── room_permission.ex
│   │   │   │   ├── scheduled_room.ex
│   │   │   │   ├── scheduled_room_cohost.ex
│   │   │   │   ├── user.ex
│   │   │   │   └── user_block.ex
│   │   │   ├── user_blocks.ex
│   │   │   └── users.ex
│   │   ├── broth/
│   │   │   ├── legacy_handler.ex
│   │   │   ├── message/
│   │   │   │   ├── _types/
│   │   │   │   │   ├── chat_token.ex
│   │   │   │   │   ├── chat_token_type.ex
│   │   │   │   │   ├── operator.ex
│   │   │   │   │   ├── relationship.ex
│   │   │   │   │   ├── room_auth.ex
│   │   │   │   │   └── room_role.ex
│   │   │   │   ├── auth/
│   │   │   │   │   └── request.ex
│   │   │   │   ├── call.ex
│   │   │   │   ├── cast.ex
│   │   │   │   ├── chat/
│   │   │   │   │   ├── ban.ex
│   │   │   │   │   ├── delete.ex
│   │   │   │   │   ├── send.ex
│   │   │   │   │   └── unban.ex
│   │   │   │   ├── manifest.ex
│   │   │   │   ├── misc/
│   │   │   │   │   └── search.ex
│   │   │   │   ├── push.ex
│   │   │   │   ├── room/
│   │   │   │   │   ├── ban.ex
│   │   │   │   │   ├── create.ex
│   │   │   │   │   ├── create_scheduled.ex
│   │   │   │   │   ├── deafen.ex
│   │   │   │   │   ├── delete_scheduled.ex
│   │   │   │   │   ├── get_banned_users.ex
│   │   │   │   │   ├── get_info.ex
│   │   │   │   │   ├── get_invite_list.ex
│   │   │   │   │   ├── get_scheduled.ex
│   │   │   │   │   ├── get_top.ex
│   │   │   │   │   ├── invite.ex
│   │   │   │   │   ├── join.ex
│   │   │   │   │   ├── leave.ex
│   │   │   │   │   ├── mute.ex
│   │   │   │   │   ├── set_active_speaker.ex
│   │   │   │   │   ├── set_auth.ex
│   │   │   │   │   ├── set_role.ex
│   │   │   │   │   ├── unban.ex
│   │   │   │   │   ├── update.ex
│   │   │   │   │   └── update_scheduled.ex
│   │   │   │   └── user/
│   │   │   │       ├── admin_update.ex
│   │   │   │       ├── ban.ex
│   │   │   │       ├── block.ex
│   │   │   │       ├── create_bot.ex
│   │   │   │       ├── follow.ex
│   │   │   │       ├── get_bots.ex
│   │   │   │       ├── get_followers.ex
│   │   │   │       ├── get_following.ex
│   │   │   │       ├── get_info.ex
│   │   │   │       ├── get_relationship.ex
│   │   │   │       ├── revoke_api_key.ex
│   │   │   │       ├── unblock.ex
│   │   │   │       ├── unfollow.ex
│   │   │   │       └── update.ex
│   │   │   ├── message.ex
│   │   │   ├── plugs/
│   │   │   │   ├── check_auth.ex
│   │   │   │   ├── cors.ex
│   │   │   │   └── redirect.ex
│   │   │   ├── routes/
│   │   │   │   ├── bot_auth.ex
│   │   │   │   ├── dev_only.ex
│   │   │   │   ├── discord_auth.ex
│   │   │   │   ├── github_auth.ex
│   │   │   │   ├── room.ex
│   │   │   │   ├── scheduled_room.ex
│   │   │   │   ├── stats.ex
│   │   │   │   ├── twitter_auth.ex
│   │   │   │   └── user.ex
│   │   │   ├── socket_handler.ex
│   │   │   ├── translator/
│   │   │   │   └── v0_1_0.ex
│   │   │   └── translator.ex
│   │   ├── broth.ex
│   │   ├── kousa/
│   │   │   ├── access_token.ex
│   │   │   ├── auth.ex
│   │   │   ├── chat.ex
│   │   │   ├── discord.ex
│   │   │   ├── follow_logic.ex
│   │   │   ├── github.ex
│   │   │   ├── metrics/
│   │   │   │   └── prometheus.ex
│   │   │   ├── refresh_token.ex
│   │   │   ├── release.ex
│   │   │   ├── room.ex
│   │   │   ├── room_block.ex
│   │   │   ├── scheduled_room.ex
│   │   │   ├── user.ex
│   │   │   ├── user_block.ex
│   │   │   └── utils/
│   │   │       ├── errors.ex
│   │   │       ├── pagination.ex
│   │   │       ├── random.ex
│   │   │       ├── reg_utils.ex
│   │   │       ├── token_utils.ex
│   │   │       ├── urls.ex
│   │   │       ├── uuid.ex
│   │   │       ├── version.ex
│   │   │       └── voice_server_utils.ex
│   │   ├── kousa.ex
│   │   └── onion/
│   │       ├── bot_auth_rate_limit.ex
│   │       ├── chat.ex
│   │       ├── pub_sub.ex
│   │       ├── room_session.ex
│   │       ├── stats_cache.ex
│   │       ├── supervisors/
│   │       │   ├── room_chat.ex
│   │       │   ├── room_session.ex
│   │       │   ├── user_session.ex
│   │       │   ├── voice_online_rabbit.ex
│   │       │   └── voice_rabbit.ex
│   │       ├── telemetry.ex
│   │       ├── user_session.ex
│   │       ├── voice_online_rabbit.ex
│   │       └── voice_rabbit.ex
│   ├── mix.exs
│   ├── priv/
│   │   └── repo/
│   │       └── migrations/
│   │           ├── 20210124203315_most_tables.exs
│   │           ├── 20210125155346_more_fields.exs
│   │           ├── 20210202143344_has_logged_in.exs
│   │           ├── 20210202162325_default_timestamps.exs
│   │           ├── 20210210005241_email.exs
│   │           ├── 20210210012609_access_token.exs
│   │           ├── 20210212141759_bans.exs
│   │           ├── 20210214140430_twitter_id.exs
│   │           ├── 20210214172930_github_id_nullable.exs
│   │           ├── 20210219173153_case_insensitive_unique_username_index.exs
│   │           ├── 20210221041850_room_permissions.exs
│   │           ├── 20210221233129_voice_server_id.exs
│   │           ├── 20210301151808_use_utc_datetime_usec.exs
│   │           ├── 20210301162635_last_online_utc_datetime_usec.exs
│   │           ├── 20210301200955_scheduled_room.exs
│   │           ├── 20210303204515_room_description.exs
│   │           ├── 20210304004945_set_timezone_for_now.exs
│   │           ├── 20210305031538_scheduled_room_started.exs
│   │           ├── 20210321141614_discord_login.exs
│   │           ├── 20210424191849_banner_url.exs
│   │           ├── 20210425000426_user_bot_api_key.exs
│   │           ├── 20210427180800_user_ip.exs
│   │           ├── 20210427192138_room_ban_ip.exs
│   │           ├── 20210501201857_emails_are_no_longer_unique.exs
│   │           ├── 20210504210047_whisper_privacy_setting.exs
│   │           ├── 20210504225546_chat_mode.exs
│   │           ├── 20210506000509_chat_throttle.exs
│   │           └── 20210509055314_admin_update.exs
│   └── test/
│       ├── _support/
│       │   ├── deprecations.ex
│       │   ├── ecto_sandbox.ex
│       │   ├── factory.ex
│       │   ├── http_request.ex
│       │   ├── message.ex
│       │   └── ws_client.ex
│       ├── ad_hoc_user_test.exs
│       ├── beef/
│       │   ├── follow_test.exs
│       │   ├── room_test.exs
│       │   ├── rooms_test.exs
│       │   ├── scheduled_room_test.exs
│       │   ├── user_block_test.exs
│       │   ├── user_blocks_test.exs
│       │   ├── user_test.exs
│       │   └── users_test.exs
│       ├── broth/
│       │   ├── _calls/
│       │   │   ├── _THIS DIRECTORY TO BE DEPRECATED
│       │   │   ├── create_room_from_scheduled_room_test.exs
│       │   │   ├── create_room_test.exs
│       │   │   ├── delete_scheduled_room_test.exs
│       │   │   ├── edit_profile_test.exs
│       │   │   ├── edit_room_test.exs
│       │   │   ├── edit_scheduled_room_test.exs
│       │   │   ├── fetch_follow_list_test.exs
│       │   │   ├── follow_info_test.exs
│       │   │   ├── get_blocked_from_room_users_test.exs
│       │   │   ├── get_my_following_test.exs
│       │   │   ├── get_my_scheduled_rooms_about_to_start_test.exs
│       │   │   ├── get_scheduled_rooms_test.exs
│       │   │   ├── get_top_public_rooms_test.exs
│       │   │   ├── get_user_profile_test.exs
│       │   │   ├── join_room_and_get_info_test.exs
│       │   │   ├── schedule_room_test.exs
│       │   │   ├── search_test.exs
│       │   │   └── unban_from_room_test.exs
│       │   ├── _casts/
│       │   │   ├── _THIS DIRECTORY TO BE DEPRECATED
│       │   │   ├── add_speaker_test.exs
│       │   │   ├── ask_to_speak_test.exs
│       │   │   ├── auth_test.exs
│       │   │   ├── ban_from_room_chat_test.exs
│       │   │   ├── ban_test.exs
│       │   │   ├── block_from_room_test.exs
│       │   │   ├── change_mod_status_test.exs
│       │   │   ├── change_room_creator_test.exs
│       │   │   ├── delete_room_chat_message_test.exs
│       │   │   ├── follow_test.exs
│       │   │   ├── invite_to_room_test.exs
│       │   │   ├── leave_room_test.exs
│       │   │   ├── make_room_public_test.exs
│       │   │   ├── mute_test.exs
│       │   │   ├── send_room_chat_msg_test.exs
│       │   │   ├── set_auto_speaker.exs
│       │   │   ├── set_listener_test.exs
│       │   │   ├── speaking_change_test.exs
│       │   │   └── unban_from_room_chat_test.exs
│       │   ├── _message/
│       │   │   ├── auth/
│       │   │   │   └── request_test.exs
│       │   │   ├── chat/
│       │   │   │   ├── ban_test.exs
│       │   │   │   ├── delete_msg_test.exs
│       │   │   │   ├── send_test.exs
│       │   │   │   └── unban_test.exs
│       │   │   ├── misc/
│       │   │   │   └── search_test.exs
│       │   │   ├── room/
│       │   │   │   ├── ban_test.exs
│       │   │   │   ├── create_scheduled_test.exs
│       │   │   │   ├── create_test.exs
│       │   │   │   ├── deafen_test.exs
│       │   │   │   ├── delete_scheduled_test.exs
│       │   │   │   ├── get_banned_users_test.exs
│       │   │   │   ├── get_info_test.exs
│       │   │   │   ├── get_invite_list_test.exs
│       │   │   │   ├── get_scheduled_test.exs
│       │   │   │   ├── get_top_test.exs
│       │   │   │   ├── invite_test.exs
│       │   │   │   ├── join_test.exs
│       │   │   │   ├── leave_test.exs
│       │   │   │   ├── mute_test.exs
│       │   │   │   ├── set_active_speaker_test.exs
│       │   │   │   ├── set_auth_test.exs
│       │   │   │   ├── set_role_test.exs
│       │   │   │   ├── unban_test.exs
│       │   │   │   ├── update_scheduled_test.exs
│       │   │   │   └── update_test.exs
│       │   │   └── user/
│       │   │       ├── admin_update_test.exs
│       │   │       ├── ban_test.exs
│       │   │       ├── block_test.exs
│       │   │       ├── create_bot_test.exs
│       │   │       ├── follow_test.exs
│       │   │       ├── get_bots_test.exs
│       │   │       ├── get_followers_test.exs
│       │   │       ├── get_following_test.exs
│       │   │       ├── get_info_test.exs
│       │   │       ├── get_relationship_test.exs
│       │   │       ├── revoke_api_key_test.exs
│       │   │       ├── unblock_test.exs
│       │   │       ├── unfollow_test.exs
│       │   │       └── update_test.exs
│       │   ├── _routes/
│       │   │   └── bot_auth_test.exs
│       │   ├── _types/
│       │   │   └── chat_token.exs
│       │   ├── auth/
│       │   │   └── request_test.exs
│       │   ├── chat/
│       │   │   ├── ban_test.exs
│       │   │   ├── delete_test.exs
│       │   │   ├── send_test.exs
│       │   │   └── unban_test.exs
│       │   ├── message_test.exs
│       │   ├── misc/
│       │   │   └── search_test.exs
│       │   ├── room/
│       │   │   ├── ban_test.exs
│       │   │   ├── create_scheduled_test.exs
│       │   │   ├── create_test.exs
│       │   │   ├── deafen_test.exs
│       │   │   ├── delete_scheduled_test.exs
│       │   │   ├── get_banned_users_test.exs
│       │   │   ├── get_info_test.exs
│       │   │   ├── get_invite_list_test.exs
│       │   │   ├── get_scheduled_test.exs
│       │   │   ├── get_top_test.exs
│       │   │   ├── invite_test.exs
│       │   │   ├── join_test.exs
│       │   │   ├── leave_test.exs
│       │   │   ├── mute_test.exs
│       │   │   ├── set_active_speaker_test.exs
│       │   │   ├── set_auth_test.exs
│       │   │   ├── set_role_test.exs
│       │   │   ├── unban_test.exs
│       │   │   ├── update_scheduled_test.exs
│       │   │   └── update_test.exs
│       │   └── user/
│       │       ├── admin_update_test.exs
│       │       ├── ban_test.exs
│       │       ├── block_test.exs
│       │       ├── create_bot_test.exs
│       │       ├── follow_test.exs
│       │       ├── get_bots_test.exs
│       │       ├── get_followers_test.exs
│       │       ├── get_following_test.exs
│       │       ├── get_info_test.exs
│       │       ├── get_relationship_test.exs
│       │       ├── revoke_api_key_test.exs
│       │       ├── unblock_test.exs
│       │       ├── unfollow_test.exs
│       │       └── update_test.exs
│       ├── kousa/
│       │   └── user.ex
│       └── test_helper.exs
├── package.json
├── pilaf/
│   ├── .buckconfig
│   ├── .eslintrc.js
│   ├── .flowconfig
│   ├── .gitattributes
│   ├── .gitignore
│   ├── .prettierrc.js
│   ├── .storybook/
│   │   ├── main.js
│   │   └── manager.js
│   ├── .watchmanconfig
│   ├── .yarnrc.yml
│   ├── App.tsx
│   ├── LICENSE
│   ├── README.md
│   ├── __tests__/
│   │   └── App-test.js
│   ├── android/
│   │   ├── app/
│   │   │   ├── BUCK
│   │   │   ├── build.gradle
│   │   │   ├── build_defs.bzl
│   │   │   ├── debug.keystore
│   │   │   ├── proguard-rules.pro
│   │   │   └── src/
│   │   │       ├── debug/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   └── java/
│   │   │       │       └── com/
│   │   │       │           └── rice/
│   │   │       │               └── ReactNativeFlipper.java
│   │   │       └── main/
│   │   │           ├── AndroidManifest.xml
│   │   │           ├── java/
│   │   │           │   └── com/
│   │   │           │       └── rice/
│   │   │           │           ├── MainActivity.java
│   │   │           │           ├── MainApplication.java
│   │   │           │           └── SplashActivity.java
│   │   │           └── res/
│   │   │               ├── drawable/
│   │   │               │   └── background_splash.xml
│   │   │               ├── layout/
│   │   │               │   └── launch_screen.xml
│   │   │               └── values/
│   │   │                   ├── colors.xml
│   │   │                   ├── strings.xml
│   │   │                   └── styles.xml
│   │   ├── build.gradle
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       ├── gradle-wrapper.jar
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   ├── gradlew
│   │   ├── gradlew.bat
│   │   └── settings.gradle
│   ├── app.json
│   ├── babel.config.js
│   ├── index.js
│   ├── ios/
│   │   ├── Podfile
│   │   ├── rice/
│   │   │   ├── AppDelegate.h
│   │   │   ├── AppDelegate.m
│   │   │   ├── Images.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── Contents.json
│   │   │   │   └── SplashIcon.imageset/
│   │   │   │       └── Contents.json
│   │   │   ├── Info.plist
│   │   │   ├── LaunchScreen.storyboard
│   │   │   ├── main.m
│   │   │   └── rice.entitlements
│   │   ├── rice-tvOS/
│   │   │   └── Info.plist
│   │   ├── rice-tvOSTests/
│   │   │   └── Info.plist
│   │   ├── rice.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           ├── rice-tvOS.xcscheme
│   │   │           └── rice.xcscheme
│   │   ├── rice.xcworkspace/
│   │   │   ├── contents.xcworkspacedata
│   │   │   └── xcshareddata/
│   │   │       └── IDEWorkspaceChecks.plist
│   │   └── riceTests/
│   │       ├── Info.plist
│   │       └── riceTests.m
│   ├── metro.config.js
│   ├── package.json
│   ├── react-native.config.js
│   ├── src/
│   │   ├── assets/
│   │   │   └── images/
│   │   │       ├── logo.svg~Add font + constant for dogehouse theme colors
│   │   │       └── logo.svg~refs/
│   │   │           └── remotes/
│   │   │               └── ben/
│   │   │                   └── staging
│   │   ├── components/
│   │   │   ├── BaseOverlay.tsx
│   │   │   ├── BubbleText.tsx
│   │   │   ├── ErrorToast.tsx
│   │   │   ├── FeaturedRoomCard.tsx
│   │   │   ├── MessageElement.tsx
│   │   │   ├── RoomCard.tsx
│   │   │   ├── RoomCardHeading.tsx
│   │   │   ├── ScrollViewLoadMore.tsx
│   │   │   ├── Spinner.tsx
│   │   │   ├── Tag.tsx
│   │   │   ├── UpcomingRoomCard.tsx
│   │   │   ├── UserBadge.tsx
│   │   │   ├── UserPreview.tsx
│   │   │   ├── accountModal/
│   │   │   │   ├── AccountModalContent.tsx
│   │   │   │   └── AccountModalRow.tsx
│   │   │   ├── avatars/
│   │   │   │   ├── MultipleUserAvatar.tsx
│   │   │   │   ├── RoomAvatar.tsx
│   │   │   │   └── SingleUserAvatar.tsx
│   │   │   ├── bottomBar/
│   │   │   │   └── CreateRoomButton.tsx
│   │   │   ├── buttons/
│   │   │   │   ├── Button.tsx
│   │   │   │   ├── IconButton.tsx
│   │   │   │   ├── SignInButton.tsx
│   │   │   │   └── SigninWithGithub.tsx
│   │   │   ├── header/
│   │   │   │   ├── Header.tsx
│   │   │   │   ├── HeaderBase.tsx
│   │   │   │   ├── ProfileButton.tsx
│   │   │   │   ├── RoomHeader.tsx
│   │   │   │   ├── SearchHeader.tsx
│   │   │   │   └── TitledHeader.tsx
│   │   │   ├── minimizedRoomCard/
│   │   │   │   ├── BoxedIcon.tsx
│   │   │   │   └── MinimizedRoomCard.tsx
│   │   │   ├── notifications/
│   │   │   │   ├── FollowNotification.tsx
│   │   │   │   ├── GenericNotification.tsx
│   │   │   │   ├── LiveNotification.tsx
│   │   │   │   └── NewRoomNotification.tsx
│   │   │   ├── report/
│   │   │   │   └── Report.tsx
│   │   │   └── search/
│   │   │       ├── RoomSearchResult.tsx
│   │   │       ├── SearchHistoryResult.tsx
│   │   │       ├── SearchHistoryResultList.tsx
│   │   │       ├── SearchResultList.tsx
│   │   │       └── UserSearchResult.tsx
│   │   ├── constants/
│   │   │   ├── dogeStyle.ts
│   │   │   ├── env.ts
│   │   │   └── regex.ts
│   │   ├── global-stores/
│   │   │   ├── useCurrentRoomIdStore.ts
│   │   │   ├── useMicPermErrorStore.ts
│   │   │   ├── useMuteStore.ts
│   │   │   ├── useProducerStore.ts
│   │   │   └── useRoomChatMentionStore.ts
│   │   ├── lib/
│   │   │   ├── createChatMessage.ts
│   │   │   ├── inCallManagerCenter.ts
│   │   │   ├── notificationCenter.ts
│   │   │   └── queryClient.ts
│   │   ├── modules/
│   │   │   ├── auth/
│   │   │   │   ├── WaitForWsAndAuth.tsx
│   │   │   │   ├── useSaveTokensFromQueryParams.ts
│   │   │   │   ├── useTokenStore.ts
│   │   │   │   └── useVerifyLoggedIn.ts
│   │   │   ├── explore/
│   │   │   │   └── ExploreController.tsx
│   │   │   ├── feed/
│   │   │   │   └── FeedController.tsx
│   │   │   ├── following/
│   │   │   │   ├── FollowersOnline.tsx
│   │   │   │   └── FollowingOnlineController.tsx
│   │   │   ├── help/
│   │   │   │   └── HelpController.tsx
│   │   │   ├── landing/
│   │   │   │   └── LandingController.tsx
│   │   │   ├── languages/
│   │   │   │   └── LanguagesController.tsx
│   │   │   ├── main/
│   │   │   │   └── MainController.tsx
│   │   │   ├── messages/
│   │   │   │   └── MessagesController.tsx
│   │   │   ├── notifications/
│   │   │   │   └── NotificationsController.tsx
│   │   │   ├── profile/
│   │   │   │   └── ProfileController.tsx
│   │   │   ├── reportBug/
│   │   │   │   └── ReportBugController.tsx
│   │   │   ├── room/
│   │   │   │   ├── InviteRoomController.tsx
│   │   │   │   ├── MinimizedRoomCardController.tsx
│   │   │   │   ├── RoomController.tsx
│   │   │   │   ├── RoomDescriptionController.tsx
│   │   │   │   ├── RoomPanelController.tsx
│   │   │   │   ├── RoomUsersPanel.tsx
│   │   │   │   ├── UserPreviewModalProvider.tsx
│   │   │   │   ├── chat/
│   │   │   │   │   ├── EmoteData.ts
│   │   │   │   │   ├── EmotePicker.tsx
│   │   │   │   │   ├── RoomChat.tsx
│   │   │   │   │   ├── RoomChatControls.tsx
│   │   │   │   │   ├── RoomChatInput.tsx
│   │   │   │   │   ├── RoomChatList.tsx
│   │   │   │   │   ├── RoomChatMentions.tsx
│   │   │   │   │   ├── RoomMessage.tsx
│   │   │   │   │   ├── useRoomChatMentionStore.ts
│   │   │   │   │   └── useRoomChatStore.ts
│   │   │   │   ├── useOnRoomPage.tsx
│   │   │   │   └── useSplitUsersIntoSections.tsx
│   │   │   ├── schedule/
│   │   │   │   └── ScheduleController.tsx
│   │   │   ├── search/
│   │   │   │   └── SearchController.tsx
│   │   │   ├── settings/
│   │   │   │   └── SettingsController.tsx
│   │   │   ├── sound-effect/
│   │   │   │   └── useSoundEffectStore.ts
│   │   │   ├── wallet/
│   │   │   │   └── WalletController.tsx
│   │   │   ├── webrtc/
│   │   │   │   ├── WebRtcApp.tsx
│   │   │   │   ├── components/
│   │   │   │   │   └── MicPicker.tsx
│   │   │   │   ├── stores/
│   │   │   │   │   ├── useAskForMicStore.ts
│   │   │   │   │   ├── useAudioTracks.ts
│   │   │   │   │   ├── useConsumerStore.ts
│   │   │   │   │   ├── useMicIdStore.ts
│   │   │   │   │   ├── useMicPermErrorStore.ts
│   │   │   │   │   ├── useProducerStore.ts
│   │   │   │   │   ├── useSocketStatus.ts
│   │   │   │   │   ├── useStatus.ts
│   │   │   │   │   └── useVoiceStore.ts
│   │   │   │   ├── types.ts
│   │   │   │   └── utils/
│   │   │   │       ├── consumeAudio.ts
│   │   │   │       ├── createTransport.ts
│   │   │   │       ├── joinRoom.ts
│   │   │   │       ├── mergeRoomPermission.ts
│   │   │   │       ├── receiveVoice.ts
│   │   │   │       └── sendVoice.ts
│   │   │   └── ws/
│   │   │       └── WebSocketProvider.tsx
│   │   ├── navigation/
│   │   │   ├── AuthenticationSwitch.tsx
│   │   │   ├── LandingPage.tsx
│   │   │   ├── MainNavigator.tsx
│   │   │   ├── RootNavigation.ts
│   │   │   └── mainNavigator/
│   │   │       ├── BottomNavigator.tsx
│   │   │       ├── HelpPage.tsx
│   │   │       ├── InviteRoomPage.tsx
│   │   │       ├── LanguagesPage.tsx
│   │   │       ├── MainPage.tsx
│   │   │       ├── MessagesPage.tsx
│   │   │       ├── NotificationsPage.tsx
│   │   │       ├── ProfilePage.tsx
│   │   │       ├── ReportBugPage.tsx
│   │   │       ├── RoomDescriptionPage.tsx
│   │   │       ├── RoomNavigator.tsx
│   │   │       ├── RoomPage.tsx
│   │   │       ├── SearchPage.tsx
│   │   │       ├── SettingsPage.tsx
│   │   │       ├── WalletPage.tsx
│   │   │       └── bottomNavigator/
│   │   │           ├── ExplorePage.tsx
│   │   │           ├── FeedPage.tsx
│   │   │           ├── FollowingPage.tsx
│   │   │           └── SchedulePage.tsx
│   │   ├── pages/
│   │   │   └── CreateRoomPage.tsx
│   │   ├── shared-components/
│   │   │   └── ApiPreloadLink.tsx
│   │   ├── shared-hooks/
│   │   │   ├── useConn.ts
│   │   │   ├── useCurrentRoomInfo.ts
│   │   │   ├── useMainWsHandler.tsx
│   │   │   ├── useSetMute.ts
│   │   │   ├── useTypeSafeMutation.ts
│   │   │   ├── useTypeSafePrefetch.ts
│   │   │   ├── useTypeSafeQuery.ts
│   │   │   └── useTypeSafeUpdateQuery.ts
│   │   ├── stories/
│   │   │   └── index.ts
│   │   └── types/
│   │       └── util-types.ts
│   ├── storybook/
│   │   ├── addons.ts
│   │   ├── index.ts
│   │   ├── rn-addons.ts
│   │   └── stories/
│   │       ├── Button.stories.tsx
│   │       ├── CenterView/
│   │       │   └── index.tsx
│   │       ├── FeaturedRoomCard.stories.tsx
│   │       ├── FollowNotification.stories.tsx
│   │       ├── GenericNotification.stories.tsx
│   │       ├── LiveNotification.stories.tsx
│   │       ├── Message.stories.tsx
│   │       ├── MultipleUserAvatar.stories.tsx
│   │       ├── NewRoomNotification.stories.tsx
│   │       ├── SingleUserAvatar.stories.tsx
│   │       └── index.ts
│   ├── template.config.js
│   └── tokens.ts
├── run.ps1
├── run.sh
├── scripts/
│   └── trigger-electron-deploy.sh
├── shawarma/
│   ├── .dockerignore
│   ├── .eslintrc.json
│   ├── Dockerfile
│   ├── README.md
│   ├── deploy.sh
│   ├── package.json
│   ├── src/
│   │   ├── MyPeer.ts
│   │   ├── MyRoomState.ts
│   │   ├── config.ts
│   │   ├── constants.ts
│   │   ├── index.ts
│   │   ├── main.ts
│   │   ├── types/
│   │   │   ├── env.d.ts
│   │   │   └── index.ts
│   │   └── utils/
│   │       ├── closePeer.ts
│   │       ├── createConsumer.ts
│   │       ├── createTransport.ts
│   │       ├── deleteRoom.ts
│   │       ├── startMediasoup.ts
│   │       └── startRabbit.ts
│   └── tsconfig.json
└── 🐕.🏠
Download .txt
SYMBOL INDEX (1734 symbols across 695 files)

FILE: baklava/resources/overlay/src/App.js
  function App (line 7) | function App() {
  function SpeakerIcon (line 61) | function SpeakerIcon(props) {

FILE: baklava/scripts/traverseTranslations.ts
  type TranslationRecord (line 5) | type TranslationRecord = {

FILE: baklava/src/constants.ts
  constant REQUEST_TO_SPEAK_KEY (line 8) | const REQUEST_TO_SPEAK_KEY = "@keybind/invite";
  constant INVITE_KEY (line 9) | const INVITE_KEY = "@keybind/invite";
  constant MUTE_KEY (line 10) | const MUTE_KEY = "@keybind/mute";
  constant DEAF_KEY (line 11) | const DEAF_KEY = "@keybind/deafen";
  constant CHAT_KEY (line 12) | const CHAT_KEY = "@keybind/chat";
  constant PTT_KEY (line 13) | const PTT_KEY = "@keybind/ptt";
  constant OVERLAY_KEY (line 14) | const OVERLAY_KEY = "@keybind/overlay";
  constant RPC_TRAY_OPTION_ID (line 16) | const RPC_TRAY_OPTION_ID = "@tray/rpc";
  constant REPO_URL (line 18) | const REPO_URL = "https://github.com/benawad/dogehouse/";
  constant DISCUSSION_URL (line 19) | const DISCUSSION_URL = "https://github.com/benawad/dogehouse/discussions";
  constant ISSUES_URL (line 20) | const ISSUES_URL = "https://github.com/benawad/dogehouse/issues";
  constant ALLOWED_HOSTS (line 22) | const ALLOWED_HOSTS = [
  constant MENU_TEMPLATE (line 34) | const MENU_TEMPLATE: any = [

FILE: baklava/src/dev.ts
  function timestamp (line 13) | function timestamp() {
  function start (line 22) | function start() {

FILE: baklava/src/electron.ts
  function localize (line 52) | async function localize() {
  function createMainWindow (line 68) | function createMainWindow() {
  function createSplashWindow (line 201) | function createSplashWindow() {
  function skipUpdateCheck (line 294) | function skipUpdateCheck(splash: BrowserWindow) {

FILE: baklava/src/generated/translationKeys.ts
  type TranslationKeys (line 2) | type TranslationKeys =

FILE: baklava/src/types.ts
  type bWindowsType (line 3) | type bWindowsType = {

FILE: baklava/src/utils/keybinds.ts
  constant CURRENT_REQUEST_TO_SPEAK_KEY (line 24) | let CURRENT_REQUEST_TO_SPEAK_KEY = "Control+8";
  constant CURRENT_INVITE_KEY (line 25) | let CURRENT_INVITE_KEY = "Control+7";
  constant CURRENT_MUTE_KEY (line 26) | let CURRENT_MUTE_KEY = "Control+m";
  constant CURRENT_DEAF_KEY (line 27) | let CURRENT_DEAF_KEY = "Control+1";
  constant CURRENT_CHAT_KEY (line 28) | let CURRENT_CHAT_KEY = "Control+9";
  constant CURRENT_OVERLAY_KEY (line 29) | let CURRENT_OVERLAY_KEY = "Control+2";
  constant CURRENT_PTT_KEY (line 30) | let CURRENT_PTT_KEY = ["0", "Control"];
  constant CURRENT_PTT_KEY_STRING (line 31) | let CURRENT_PTT_KEY_STRING = "0,control"
  constant CURRENT_APP_TITLE (line 33) | let CURRENT_APP_TITLE = "";
  constant PREV_PTT_STATUS (line 35) | let PREV_PTT_STATUS = false;
  function RegisterKeybinds (line 39) | async function RegisterKeybinds(bWindows: bWindowsType) {
  function exitApp (line 143) | function exitApp() {

FILE: baklava/src/utils/notifications.ts
  function StartNotificationHandler (line 6) | async function StartNotificationHandler() {

FILE: baklava/src/utils/overlay/index.ts
  function createOverlay (line 5) | function createOverlay(target: string, OW: any) {

FILE: baklava/src/utils/overlay/ipc.ts
  function startOverlayIPCHandler (line 6) | async function startOverlayIPCHandler(mainWindow: BrowserWindow, overlay...

FILE: baklava/src/utils/rpc/index.ts
  constant RPC_RUNNING (line 13) | let RPC_RUNNING = false;
  function startRPC (line 20) | async function startRPC() {
  function setPresence (line 33) | async function setPresence(data: Presence) {
  function stopRPC (line 40) | async function stopRPC() {

FILE: baklava/src/utils/rpc/ipc.ts
  constant PREV_PAGE_DATA (line 5) | let PREV_PAGE_DATA: {
  constant START_TIME (line 11) | const START_TIME = Date.now();
  function startRPCIPCHandler (line 120) | async function startRPCIPCHandler() {
  function stopRPCIPCHandler (line 126) | async function stopRPCIPCHandler() {

FILE: baklava/src/utils/tray.ts
  function HandleVoiceTray (line 14) | async function HandleVoiceTray(mainWindow: BrowserWindow, tray: Tray) {

FILE: dinner/src/play-audio.ts
  function makeMicTrack (line 7) | async function makeMicTrack(
  function startAudio (line 24) | async function startAudio(wrapper: Wrapper) {
  function wrapAudio (line 34) | async function wrapAudio(wrapper: Wrapper) {

FILE: dolma/src/index.ts
  type RootMethodResponse (line 6) | interface RootMethodResponse {
  class dolma (line 23) | class dolma {
    method constructor (line 26) | constructor(emotes: {name: string}[]) {

FILE: dolma/src/lib/decode.ts
  function decodeTokens (line 6) | function decodeTokens(this: {emotes: {name: string}[]}, all: Array<Unito...

FILE: dolma/src/lib/encode.ts
  function encodeTokens (line 7) | function encodeTokens(this: {emotes: {name: string}[]},message: Array<Un...

FILE: dolma/src/lib/filterString.ts
  function filterString (line 5) | function filterString(emotes: { name: string }[], message: string) {

FILE: dolma/src/lib/filterUnitoken.ts
  function filterUnitoken (line 6) | function filterUnitoken(token: any): MessageToken | null {

FILE: dolma/src/lib/msgToken.ts
  function msgToken (line 9) | function msgToken() {

FILE: dolma/src/test/run.ts
  type CompletedTest (line 4) | interface CompletedTest {
  function testFinished (line 24) | function testFinished(test: any, started: Date, successful?: boolean) {
  function main (line 39) | async function main() {

FILE: dolma/src/tokens/index.ts
  type Unitoken (line 8) | interface Unitoken {

FILE: dolma/src/util/types/tokenTypes.ts
  type MessageTokenType (line 3) | type MessageTokenType = keyof typeof rawTokens.default;
  type MessageToken (line 5) | interface MessageToken {
  type Token (line 10) | interface Token {

FILE: globalkey/src/build.rs
  function main (line 1) | fn main() {

FILE: globalkey/src/lib.rs
  function start (line 13) | fn start<F: Fn(Vec<String>) + Send + 'static, X: Fn(Vec<String>) + Send ...
  function stop (line 46) | fn stop() {

FILE: kebab/src/audio/audioWrapper.ts
  type Handler (line 17) | type Handler<Data> = (data: Data) => void;

FILE: kebab/src/audio/interface.ts
  type ConsumerPlayer (line 4) | type ConsumerPlayer = (track: MediaStreamTrack, user: UUID) => void;
  type ConnectFunction (line 5) | type ConnectFunction<Return> = <Direction extends "input" | "output">(

FILE: kebab/src/client/http/endpoint.ts
  type Endpoint (line 1) | type Endpoint<O, R> = (options: O) => [string, RequestInit];

FILE: kebab/src/client/http/index.ts
  type HTTPRequester (line 6) | type HTTPRequester = <O, R>(endpoint: Endpoint<O, R>, options: O) => Pro...

FILE: kebab/src/client/index.ts
  type Client (line 5) | type Client = raw.Connection & {

FILE: kebab/src/client/requester/auth.ts
  type Requests (line 3) | interface Requests {

FILE: kebab/src/client/requester/chat.ts
  type Requests (line 3) | interface Requests {

FILE: kebab/src/client/requester/index.ts
  type DefaultRequest (line 9) | type DefaultRequest = {
  type RequestMap (line 15) | type RequestMap = DefaultValues<
  type Requester (line 25) | type Requester = <R extends NormalObjectKey<keyof RequestMap>>(
  type SimpleRequester (line 30) | type SimpleRequester = <R extends NormalObjectKey<keyof RequestMap>>(

FILE: kebab/src/client/requester/misc.ts
  type Requests (line 3) | interface Requests {

FILE: kebab/src/client/requester/room.ts
  type Requests (line 3) | interface Requests {

FILE: kebab/src/client/requester/user.ts
  type Requests (line 3) | interface Requests {

FILE: kebab/src/client/subscriber/index.ts
  type EventMap (line 5) | type EventMap = LegacyRequests;
  type EventHandler (line 7) | type EventHandler<D extends EventMap[keyof EventMap]> = (data: D) => void;
  type Unsubscriber (line 8) | type Unsubscriber = () => void;
  type Subscriber (line 10) | type Subscriber = <E extends NormalObjectKey<keyof EventMap>>(
  type SimpleSubscriber (line 16) | type SimpleSubscriber = <E extends NormalObjectKey<keyof EventMap>>(

FILE: kebab/src/client/subscriber/legacy.ts
  type Events (line 3) | interface Events {

FILE: kebab/src/client/type-util.ts
  type NormalObjectKey (line 1) | type NormalObjectKey<T> = Exclude<T, symbol | number>;
  type DefaultValues (line 3) | type DefaultValues<T, D> = {
  type GroupMap (line 7) | type GroupMap<Group, Separator extends string, GroupName extends string>...
  type EmptyObject (line 11) | type EmptyObject = Record<string | symbol | number, unknown>;

FILE: kebab/src/entities.ts
  type UUID (line 3) | type UUID = string;
  type RoomPeer (line 5) | type RoomPeer = {
  type UserPreview (line 10) | type UserPreview = {
  type ChatMode (line 17) | type ChatMode = "default" | "disabled" | "follower_only";
  type RoomDetails (line 19) | type RoomDetails = {
  type Room (line 26) | type Room = RoomDetails & {
  type ScheduledRoom (line 37) | interface ScheduledRoom {
  type User (line 48) | type User = {
  type MessageToken (line 69) | type MessageToken<T extends string = string, V = unknown> = {
  type TextToken (line 74) | type TextToken = MessageToken<"text", string>;
  type MentionToken (line 75) | type MentionToken = MessageToken<"mention", string>;
  type LinkToken (line 76) | type LinkToken = MessageToken<"link", string>;
  type EmoteToken (line 77) | type EmoteToken = MessageToken<"emote", string>;
  type CodeBlockToken (line 78) | type CodeBlockToken = MessageToken<"block", string>;
  type EmojiToken (line 79) | type EmojiToken = MessageToken<"emoji", string>;
  type Message (line 81) | type Message = {
  type BaseUser (line 95) | type BaseUser = {
  type RoomPermissions (line 112) | type RoomPermissions = {
  type UserWithFollowInfo (line 118) | type UserWithFollowInfo = BaseUser & {
  type RoomUser (line 124) | type RoomUser = {
  type CurrentRoom (line 128) | type CurrentRoom = Room & {
  type BooleanMap (line 136) | type BooleanMap = Record<UUID, boolean>;
  type Relationship (line 138) | enum Relationship {
  type RoomRole (line 146) | enum RoomRole {
  type RoomAuth (line 152) | enum RoomAuth {

FILE: kebab/src/http/bot.ts
  type AuthResponse (line 3) | type AuthResponse = {

FILE: kebab/src/http/raw.ts
  constant BASE_URL (line 3) | const BASE_URL = "https://api.dogehouse.tv";
  type Options (line 5) | interface Options {
  type Request (line 9) | type Request = (
  type Http (line 16) | type Http = {

FILE: kebab/src/http/wrapper.ts
  type AuthResponse (line 3) | type AuthResponse = {

FILE: kebab/src/pagination.ts
  type PaginatedRequest (line 1) | type PaginatedRequest<C extends number | string = number> = {
  type PaginatedReply (line 6) | type PaginatedReply<C extends number | string = number> = {

FILE: kebab/src/websocket/raw.ts
  type Token (line 11) | type Token = string;
  type FetchID (line 16) | type FetchID = UUID;
  type Ref (line 17) | type Ref = UUID;
  type Opcode (line 18) | type Opcode = string;
  type Logger (line 19) | type Logger = (
  type ListenerHandler (line 26) | type ListenerHandler<Data = unknown> = (
  type Listener (line 30) | type Listener<Data = unknown> = {
  type Connection (line 38) | type Connection = {

FILE: kebab/src/websocket/responses.ts
  type GetTopPublicRoomsResponse (line 3) | type GetTopPublicRoomsResponse = {
  type GetScheduledRoomsResponse (line 8) | type GetScheduledRoomsResponse = {
  type JoinRoomAndGetInfoResponse (line 13) | type JoinRoomAndGetInfoResponse = {
  type GetRoomUsersResponse (line 22) | type GetRoomUsersResponse = {
  type NewRoomDetailsResponse (line 32) | type NewRoomDetailsResponse = {
  type InvitationToRoomResponse (line 40) | type InvitationToRoomResponse = {
  type CreateBotResponse (line 50) | type CreateBotResponse = {

FILE: kebab/src/websocket/wrapper.ts
  type Handler (line 29) | type Handler<Data> = (data: Data) => void;
  type Wrapper (line 34) | type Wrapper = ReturnType<typeof wrap>;

FILE: kibbeh/cypress/support/commands.ts
  method onBeforeLoad (line 72) | onBeforeLoad(win) {

FILE: kibbeh/cypress/support/index.d.ts
  type Chainable (line 6) | interface Chainable {

FILE: kibbeh/scripts/traverseTranslations.ts
  type TranslationRecord (line 5) | type TranslationRecord = {

FILE: kibbeh/src/form-fields/FieldSpacer.tsx
  type FieldSpacerProps (line 3) | interface FieldSpacerProps {}

FILE: kibbeh/src/global-stores/useCurrentRoomIdStore.ts
  type Fn (line 5) | type Fn = (currentRoomId: string | null) => string | null;

FILE: kibbeh/src/global-stores/useKeyMapStore.ts
  constant REQUEST_TO_SPEAK_KEY (line 11) | const REQUEST_TO_SPEAK_KEY = "@keybind/invite";
  constant INVITE_KEY (line 12) | const INVITE_KEY = "@keybind/invite";
  constant MUTE_KEY (line 13) | const MUTE_KEY = "@keybind/mute";
  constant DEAF_KEY (line 14) | const DEAF_KEY = "@keybind/deafen";
  constant CHAT_KEY (line 15) | const CHAT_KEY = "@keybind/chat";
  constant PTT_KEY (line 16) | const PTT_KEY = "@keybind/ptt";
  constant OVERLAY_KEY (line 17) | const OVERLAY_KEY = "@keybind/overlay";
  function getKeybind (line 19) | function getKeybind(actionKey: string, defaultKeybind: string) {
  function getRequestToSpeakKeybind (line 30) | function getRequestToSpeakKeybind() {
  function getInviteKeybind (line 34) | function getInviteKeybind() {
  function getMuteKeybind (line 38) | function getMuteKeybind() {
  function getDeafKeybind (line 42) | function getDeafKeybind() {
  function getChatKeybind (line 46) | function getChatKeybind() {
  function getPTTKeybind (line 50) | function getPTTKeybind() {
  function getOverlayKeybind (line 54) | function getOverlayKeybind() {

FILE: kibbeh/src/global-stores/useSocketStatus.ts
  type State (line 4) | type State =

FILE: kibbeh/src/global-stores/useStatus.ts
  type State (line 4) | type State =

FILE: kibbeh/src/icons/BotIcon.tsx
  function BotIcon (line 3) | function BotIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/DeveloperIcon.tsx
  function DeveloperIcon (line 3) | function DeveloperIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/LgLogo.tsx
  function LgLogo (line 3) | function LgLogo(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/Link.tsx
  function LinkIcon (line 3) | function LinkIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/LogoIcon.tsx
  type SvgDogehouseIconProps (line 3) | interface SvgDogehouseIconProps extends React.SVGProps<SVGSVGElement> {
  function SvgDogehouseIcon (line 7) | function SvgDogehouseIcon(props: SvgDogehouseIconProps) {

FILE: kibbeh/src/icons/MacCloseIcon.tsx
  function MacCloseIcon (line 3) | function MacCloseIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/MacMaximizeIcon.tsx
  function MacMaximizeIcon (line 3) | function MacMaximizeIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/MacMinimizeIcon.tsx
  function MacMinimizeIcon (line 3) | function MacMinimizeIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/OutlineGlobe.tsx
  function SvgOutlineGlobe (line 3) | function SvgOutlineGlobe(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/Share.tsx
  function ShareIcon (line 3) | function ShareIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/Smiley.tsx
  function Smiley (line 3) | function Smiley(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidBug.tsx
  function SvgSolidBug (line 3) | function SvgSolidBug(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidCalendar.tsx
  function SvgSolidCalendar (line 3) | function SvgSolidCalendar(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidCaretRight.tsx
  function SvgSolidCaretRight (line 3) | function SvgSolidCaretRight(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidChatBubble.tsx
  function SolidChatBubble (line 3) | function SolidChatBubble(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidCompass.tsx
  function SvgSolidCompass (line 3) | function SvgSolidCompass(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidContributor.tsx
  type SolidContributorProps (line 3) | interface SolidContributorProps extends React.SVGProps<SVGSVGElement> {}
  function SolidContributor (line 5) | function SolidContributor(props: SolidContributorProps): JSX.Element {

FILE: kibbeh/src/icons/SolidDeafened.tsx
  function SvgSolidDeafened (line 3) | function SvgSolidDeafened(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidDeafenedOff.tsx
  function SvgSolidDeafenedOff (line 3) | function SvgSolidDeafenedOff(

FILE: kibbeh/src/icons/SolidDiscord.tsx
  function SvgSolidDiscord (line 3) | function SvgSolidDiscord(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidDogenitro.tsx
  function SvgSolidDogenitro (line 3) | function SvgSolidDogenitro(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidDownload.tsx
  function SvgSolidDownload (line 3) | function SvgSolidDownload(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidFriends.tsx
  function SvgSolidFriends (line 3) | function SvgSolidFriends(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidFriendsAdd.tsx
  function SvgSolidFriendsAdd (line 3) | function SvgSolidFriendsAdd(

FILE: kibbeh/src/icons/SolidFullscreen.tsx
  function SvgSolidFullscreen (line 3) | function SvgSolidFullscreen(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidGitHub.tsx
  function SvgSolidGitHub (line 3) | function SvgSolidGitHub(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidGoogle.tsx
  function SvgSolidGoogle (line 3) | function SvgSolidGoogle(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidHelp.tsx
  function SvgSolidHelp (line 3) | function SvgSolidHelp(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidHome.tsx
  function SvgSolidHome (line 3) | function SvgSolidHome(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidInstagram.tsx
  function SvgSolidInstagram (line 3) | function SvgSolidInstagram(

FILE: kibbeh/src/icons/SolidKeyboard.tsx
  function SvgSolidKeyboard (line 3) | function SvgSolidKeyboard(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidLink.tsx
  type SolidLinkProps (line 3) | interface SolidLinkProps extends React.SVGProps<SVGSVGElement> {}
  function SolidLink (line 5) | function SolidLink(props: SolidLinkProps): JSX.Element {

FILE: kibbeh/src/icons/SolidLogOut.tsx
  function SvgSolidLogOut (line 1) | function SvgSolidLogOut(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidMegaphone.tsx
  function SvgSolidMegaphone (line 3) | function SvgSolidMegaphone(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidMessages.tsx
  function SvgSolidMessages (line 3) | function SvgSolidMessages(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidMicrophone.tsx
  function SvgSolidMicrophone (line 3) | function SvgSolidMicrophone(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidMicrophoneOff.tsx
  function SvgSolidMicrophoneOff (line 3) | function SvgSolidMicrophoneOff(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidMoon.tsx
  function SvgSolidMoon (line 3) | function SvgSolidMoon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidNew.tsx
  function SvgSolidNew (line 3) | function SvgSolidNew(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidNotification.tsx
  function SvgSolidNotification (line 3) | function SvgSolidNotification(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidPersonAdd.tsx
  function SvgSolidPersonAdd (line 3) | function SvgSolidPersonAdd(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidPlus.tsx
  function SvgSolidMessages (line 3) | function SvgSolidMessages(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidRocket.tsx
  function SvgSolidRocket (line 3) | function SvgSolidRocket(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidSearch.tsx
  function SvgSolidSearch (line 3) | function SvgSolidSearch(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidSettings.tsx
  function SvgSolidSettings (line 3) | function SvgSolidSettings(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidSimpleMegaphone.tsx
  function SvgSolidSimpleMegaphone (line 3) | function SvgSolidSimpleMegaphone(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidStaff.tsx
  type SolidStaffProps (line 3) | interface SolidStaffProps extends React.SVGProps<SVGSVGElement> {}
  function SolidStaff (line 5) | function SolidStaff(props: SolidStaffProps): JSX.Element {

FILE: kibbeh/src/icons/SolidTime.tsx
  function SvgSolidTime (line 3) | function SvgSolidTime(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidTrash.tsx
  function SvgSolidTrash (line 3) | function SvgSolidTrash(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidTwitter.tsx
  function SvgSolidTwitter (line 3) | function SvgSolidTwitter(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidUser.tsx
  function SvgSolidUser (line 3) | function SvgSolidUser(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidVolume.tsx
  function SvgSolidVolume (line 3) | function SvgSolidVolume(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidVolumeOff.tsx
  function SvgSolidVolumeOff (line 3) | function SvgSolidVolumeOff(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/SolidWarning.tsx
  function SvgSolidWarning (line 3) | function SvgSolidWarning(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/WinCloseIcon.tsx
  function WinCloseIcon (line 3) | function WinCloseIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/WinMaximizeIcon.tsx
  function WinMaximizeIcon (line 3) | function WinMaximizeIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/WinMinimizeIcon.tsx
  function WinMinimizeIcon (line 3) | function WinMinimizeIcon(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/icons/badges/ContributorBadge.tsx
  type SvgSolidContributorBadgeProps (line 3) | interface SvgSolidContributorBadgeProps extends React.SVGProps<SVGSVGEle...
  function SvgSolidContributorBadge (line 7) | function SvgSolidContributorBadge(props: SvgSolidContributorBadgeProps) {

FILE: kibbeh/src/icons/badges/StaffBadge.tsx
  function SvgSolidStaffBadge (line 3) | function SvgSolidStaffBadge(props: React.SVGProps<SVGSVGElement>) {

FILE: kibbeh/src/lib/i18n.ts
  constant DETECTION_OPTIONS (line 8) | const DETECTION_OPTIONS = {
  function createDateFormatOptions (line 12) | function createDateFormatOptions(format: string): Intl.DateTimeFormatOpt...

FILE: kibbeh/src/modules/admin/AdminPage.tsx
  type Props (line 7) | interface Props {}

FILE: kibbeh/src/modules/admin/AdminPageForm.tsx
  type SearchUsersProps (line 11) | interface SearchUsersProps {}

FILE: kibbeh/src/modules/auth/WaitForWsAndAuth.tsx
  type WaitForWsAndAuthProps (line 5) | interface WaitForWsAndAuthProps {}

FILE: kibbeh/src/modules/dashboard/CreateRoomModal.tsx
  type CreateRoomModalProps (line 16) | interface CreateRoomModalProps {

FILE: kibbeh/src/modules/dashboard/DashboardPage.tsx
  type LoungePageProps (line 9) | interface LoungePageProps {}

FILE: kibbeh/src/modules/dashboard/FeedController.tsx
  type FeedControllerProps (line 23) | interface FeedControllerProps {}

FILE: kibbeh/src/modules/dashboard/FollowingOnlineController.tsx
  type FriendsOnlineControllerProps (line 12) | interface FriendsOnlineControllerProps {}

FILE: kibbeh/src/modules/dashboard/ProfileBlockController.tsx
  type ProfileBlockControllerProps (line 17) | interface ProfileBlockControllerProps {}

FILE: kibbeh/src/modules/debugging/AudioDebugAvatar.tsx
  type AudioDebugAvatarProps (line 5) | interface AudioDebugAvatarProps {

FILE: kibbeh/src/modules/debugging/AudioDebugPanel.tsx
  type AudioDebugPanelProps (line 5) | interface AudioDebugPanelProps {}

FILE: kibbeh/src/modules/developer/Bot.tsx
  type Bot (line 1) | interface Bot {

FILE: kibbeh/src/modules/developer/BotCard.tsx
  type BotCardProps (line 7) | interface BotCardProps {

FILE: kibbeh/src/modules/developer/BotIcon.tsx
  type BotIconProps (line 3) | interface BotIconProps {

FILE: kibbeh/src/modules/developer/BotInfo.tsx
  type BotInfoProps (line 5) | interface BotInfoProps {

FILE: kibbeh/src/modules/developer/BotsEditPage.tsx
  type BotsEditPageProps (line 12) | interface BotsEditPageProps {}

FILE: kibbeh/src/modules/developer/CreateBotModal.tsx
  type CreateBotModalProps (line 10) | interface CreateBotModalProps {

FILE: kibbeh/src/modules/display/HeaderController.tsx
  type HeaderControllerProps (line 5) | interface HeaderControllerProps {

FILE: kibbeh/src/modules/display/TextParser.tsx
  type TextParserProps (line 6) | interface TextParserProps {

FILE: kibbeh/src/modules/errors/ErrorToastController.tsx
  type ErrorToastControllerProps (line 6) | interface ErrorToastControllerProps {}

FILE: kibbeh/src/modules/errors/useErrorToastStore.tsx
  type Toast (line 7) | type Toast = {

FILE: kibbeh/src/modules/keyboard-shortcuts/ChatKeybind.tsx
  type ChatKeybindProps (line 7) | interface ChatKeybindProps {

FILE: kibbeh/src/modules/keyboard-shortcuts/DeafKeybind.tsx
  type DeafKeybindProps (line 7) | interface DeafKeybindProps {

FILE: kibbeh/src/modules/keyboard-shortcuts/InviteKeybind.tsx
  type InviteKeybindProps (line 7) | interface InviteKeybindProps {

FILE: kibbeh/src/modules/keyboard-shortcuts/KeybindListener.tsx
  type KeybindListenerProps (line 27) | interface KeybindListenerProps {}
  function ListenerElectron (line 29) | function ListenerElectron() {
  function ListenerBrowser (line 93) | function ListenerBrowser() {

FILE: kibbeh/src/modules/keyboard-shortcuts/MuteKeybind.tsx
  type MuteKeybindProps (line 7) | interface MuteKeybindProps {

FILE: kibbeh/src/modules/keyboard-shortcuts/OverlayKeybind.tsx
  type OverlayKeybindProps (line 7) | interface OverlayKeybindProps {

FILE: kibbeh/src/modules/keyboard-shortcuts/PTTKeybind.tsx
  type PTTKeybindProps (line 7) | interface PTTKeybindProps {

FILE: kibbeh/src/modules/keyboard-shortcuts/RequestToSpeakKeybind.tsx
  type RequestToSpeakKeybindProps (line 7) | interface RequestToSpeakKeybindProps {

FILE: kibbeh/src/modules/landing-page/LoginPage.tsx
  type LoginButtonProps (line 27) | interface LoginButtonProps {

FILE: kibbeh/src/modules/language/LanguagePage.tsx
  type LanguagePageProps (line 11) | interface LanguagePageProps {}

FILE: kibbeh/src/modules/layouts/DefaultDesktopLayout.tsx
  type DefaultDesktopLayoutProps (line 9) | interface DefaultDesktopLayoutProps {

FILE: kibbeh/src/modules/layouts/ElectronHeader.tsx
  function WinHeader (line 20) | function WinHeader() {
  function MacHeader (line 62) | function MacHeader() {
  function ElectronHeader (line 102) | function ElectronHeader() {

FILE: kibbeh/src/modules/layouts/GridPanels.tsx
  type LeftPanelProps (line 12) | interface LeftPanelProps {}

FILE: kibbeh/src/modules/layouts/MainLayout.tsx
  type MainLayoutProps (line 24) | interface MainLayoutProps {

FILE: kibbeh/src/modules/layouts/TabletSidebar.tsx
  type FriendsOnlineControllerProps (line 9) | interface FriendsOnlineControllerProps {}

FILE: kibbeh/src/modules/room/AudioDebugConsumerSection.tsx
  type AudioDebugConsumerSectionProps (line 5) | interface AudioDebugConsumerSectionProps {

FILE: kibbeh/src/modules/room/BlockedFromRoomUsers.tsx
  type BlockedFromRoomUsersProps (line 12) | interface BlockedFromRoomUsersProps {}
  constant GET_BLOCKED_FROM_ROOM_USERS (line 14) | const GET_BLOCKED_FROM_ROOM_USERS = "get_blocked_from_room_users";

FILE: kibbeh/src/modules/room/InviteRoomPage.tsx
  type InviteRoomPageProps (line 24) | interface InviteRoomPageProps {}

FILE: kibbeh/src/modules/room/RoomChatController.tsx
  type RoomChatControllerProps (line 5) | interface RoomChatControllerProps {}

FILE: kibbeh/src/modules/room/RoomOpenGraphPreview.tsx
  type RoomOpenGraphPreviewProps (line 6) | interface RoomOpenGraphPreviewProps {

FILE: kibbeh/src/modules/room/RoomPage.tsx
  type RoomPageProps (line 20) | interface RoomPageProps {

FILE: kibbeh/src/modules/room/RoomPanelController.tsx
  type RoomPanelControllerProps (line 17) | interface RoomPanelControllerProps {

FILE: kibbeh/src/modules/room/RoomSettingModal.tsx
  type RoomSettingsModalProps (line 13) | interface RoomSettingsModalProps {

FILE: kibbeh/src/modules/room/RoomUsersPanel.tsx
  type RoomUsersPanelProps (line 17) | interface RoomUsersPanelProps extends JoinRoomAndGetInfoResponse {}

FILE: kibbeh/src/modules/room/UserPreviewModalProvider.tsx
  type UserProfileOverlayProviderProps (line 4) | interface UserProfileOverlayProviderProps {}
  type Data (line 6) | type Data = { userId: string; message?: RoomChatMessage };

FILE: kibbeh/src/modules/room/ViewScheduledRoomPage.tsx
  type ViewScheduledRoomPageProps (line 14) | interface ViewScheduledRoomPageProps {}
  type GetScheduledRoomById (line 16) | type GetScheduledRoomById = { room: ScheduledRoom | null };

FILE: kibbeh/src/modules/room/VolumeSliderController.tsx
  type VolumeSliderControllerProps (line 6) | interface VolumeSliderControllerProps {

FILE: kibbeh/src/modules/room/chat/Emote.tsx
  type CustomEmojiProps (line 4) | interface CustomEmojiProps {

FILE: kibbeh/src/modules/room/chat/EmoteData.ts
  type EmoteList (line 1561) | type EmoteList = typeof customEmojis;
  type EmoteKeys (line 1562) | type EmoteKeys = EmoteList[number]["name"];
  type CustomEmote (line 1566) | type CustomEmote = {

FILE: kibbeh/src/modules/room/chat/RoomChat.tsx
  type ChatProps (line 7) | interface ChatProps {

FILE: kibbeh/src/modules/room/chat/RoomChatInput.tsx
  type ChatInputProps (line 22) | interface ChatInputProps {

FILE: kibbeh/src/modules/room/chat/RoomChatList.tsx
  type ChatListProps (line 16) | interface ChatListProps {
  type BadgeIconData (line 21) | interface BadgeIconData {

FILE: kibbeh/src/modules/room/chat/RoomChatMentions.tsx
  type RoomChatMentionsProps (line 9) | interface RoomChatMentionsProps {
  function addMention (line 27) | function addMention(m: BaseUser) {

FILE: kibbeh/src/modules/room/chat/useRoomChatStore.ts
  type TextToken (line 5) | interface TextToken {
  type MentionToken (line 9) | interface MentionToken {
  type LinkToken (line 13) | interface LinkToken {
  type BlockToken (line 18) | interface BlockToken {
  type EmoteToken (line 23) | interface EmoteToken {
  type EmojiToken (line 28) | interface EmojiToken {
  type RoomChatMessageToken (line 33) | type RoomChatMessageToken =
  function generateColorFromString (line 54) | function generateColorFromString(str: string) {
  type RoomChatMessage (line 60) | interface RoomChatMessage {

FILE: kibbeh/src/modules/room/mobile/RoomOverlay.tsx
  type RoomOverlayProps (line 19) | interface RoomOverlayProps {

FILE: kibbeh/src/modules/room/useResize.ts
  function getWindowsSize (line 3) | function getWindowsSize() {

FILE: kibbeh/src/modules/scheduled-rooms/AddToCalendar.tsx
  type CalendarURLs (line 7) | type CalendarURLs = ReturnType<typeof makeUrls>;
  type OpenStateToggle (line 30) | type OpenStateToggle = (event?: React.MouseEvent) => void;
  type CalendarRef (line 50) | type CalendarRef = HTMLAnchorElement;
  type CalendarProps (line 51) | type CalendarProps = {
  type DropdownProps (line 73) | type DropdownProps = {
  type AddToCalendarProps (line 118) | type AddToCalendarProps = {

FILE: kibbeh/src/modules/scheduled-rooms/CopyScheduleRoomLinkButton.tsx
  type CopyLinkButtonProps (line 7) | interface CopyLinkButtonProps {

FILE: kibbeh/src/modules/scheduled-rooms/CreateScheduledRoomModal.tsx
  type ScheduleRoomFormData (line 17) | interface ScheduleRoomFormData {
  type CreateRoomModalProps (line 24) | interface CreateRoomModalProps {

FILE: kibbeh/src/modules/scheduled-rooms/EditScheduleRoomModalController.tsx
  type State (line 8) | type State = {
  type EditScheduleRoomModalControllerProps (line 13) | interface EditScheduleRoomModalControllerProps {

FILE: kibbeh/src/modules/scheduled-rooms/ScheduledRoomCard.tsx
  type ScheduledRoomCardProps (line 17) | interface ScheduledRoomCardProps {

FILE: kibbeh/src/modules/scheduled-rooms/ScheduledRoomsList.tsx
  type ScheduledRoomsListProps (line 15) | interface ScheduledRoomsListProps {}

FILE: kibbeh/src/modules/scheduled-rooms/ScheduledRoomsPage.tsx
  type LoungePageProps (line 8) | interface LoungePageProps {}

FILE: kibbeh/src/modules/scheduled-rooms/copyToClipboard.ts
  function copyTextToClipboard (line 4) | function copyTextToClipboard(text: string) {

FILE: kibbeh/src/modules/scheduled-rooms/makeUrls.ts
  type CalendarEvent (line 1) | interface CalendarEvent {
  type Query (line 21) | type Query = { [key: string]: null | boolean | number | string };
  type URLSet (line 90) | type URLSet = { [key: string]: string };

FILE: kibbeh/src/modules/search/SearchBarController.tsx
  type SearchControllerProps (line 18) | interface SearchControllerProps {}

FILE: kibbeh/src/modules/search/SearchPage.tsx
  type LoungePageProps (line 17) | interface LoungePageProps {}

FILE: kibbeh/src/modules/settings/OverlaySettingsPage.tsx
  type OverlaySettingsProps (line 16) | interface OverlaySettingsProps {}

FILE: kibbeh/src/modules/settings/PrivacySettingForm.tsx
  type PrivacySettingFormProps (line 8) | interface PrivacySettingFormProps {}

FILE: kibbeh/src/modules/settings/PrivacySettingsPage.tsx
  type ChatSettingsProps (line 9) | interface ChatSettingsProps {}

FILE: kibbeh/src/modules/settings/SoundEffectSettingsPage.tsx
  type ChatSettingsProps (line 15) | interface ChatSettingsProps {}

FILE: kibbeh/src/modules/settings/VoiceSettingsPage.tsx
  type VoiceSettingsProps (line 23) | interface VoiceSettingsProps {}

FILE: kibbeh/src/modules/sound-effects/useSoundEffectStore.ts
  type PossibleSoundEffect (line 13) | type PossibleSoundEffect = keyof typeof soundEffects;
  function getInitialSettings (line 17) | function getInitialSettings() {

FILE: kibbeh/src/modules/user/EditProfileModal.tsx
  type EditProfileModalProps (line 31) | interface EditProfileModalProps {

FILE: kibbeh/src/modules/user/FollowingController.tsx
  type FollowingControllerProps (line 18) | interface FollowingControllerProps {}

FILE: kibbeh/src/modules/user/FollowingOnlinePage.tsx
  type UserPageProps (line 12) | interface UserPageProps {}

FILE: kibbeh/src/modules/user/FollowingPage.tsx
  type UserPageProps (line 13) | interface UserPageProps {}

FILE: kibbeh/src/modules/user/UserPage.tsx
  type UserPageProps (line 10) | interface UserPageProps {

FILE: kibbeh/src/modules/user/UserProfileController.tsx
  type UserProfileControllerProps (line 17) | interface UserProfileControllerProps {}

FILE: kibbeh/src/modules/user/VerticalUserInfoWithFollowButton.tsx
  type VerticalUserInfoControllerProps (line 11) | interface VerticalUserInfoControllerProps {

FILE: kibbeh/src/modules/webrtc/WebRtcApp.tsx
  type App2Props (line 17) | interface App2Props {}
  function closeVoiceConnections (line 19) | function closeVoiceConnections(_roomId: string | null) {
  function flushConsumerQueue (line 50) | function flushConsumerQueue(_roomId: string) {

FILE: kibbeh/src/modules/webrtc/components/ActiveSpeakerListener.tsx
  type ActiveSpeakerListenerProps (line 10) | interface ActiveSpeakerListenerProps {}

FILE: kibbeh/src/modules/webrtc/components/AudioRender.tsx
  type AudioRenderProps (line 6) | interface AudioRenderProps {}

FILE: kibbeh/src/modules/webrtc/components/MicPicker.tsx
  type MicPickerProps (line 4) | interface MicPickerProps {}

FILE: kibbeh/src/modules/webrtc/stores/useMicIdStore.ts
  constant MIC_KEY (line 4) | const MIC_KEY = "micId";

FILE: kibbeh/src/modules/webrtc/stores/useSocketStatus.ts
  type State (line 4) | type State =

FILE: kibbeh/src/modules/webrtc/stores/useStatus.ts
  type State (line 4) | type State =

FILE: kibbeh/src/modules/webrtc/types.ts
  type AddWsListenerOnce (line 1) | type AddWsListenerOnce = (op: string, fn: (d: any) => void) => void;

FILE: kibbeh/src/modules/webrtc/utils/createTransport.ts
  function createTransport (line 5) | async function createTransport(

FILE: kibbeh/src/modules/ws/WebSocketProvider.tsx
  type WebSocketProviderProps (line 13) | interface WebSocketProviderProps {
  type V (line 17) | type V = raw.Connection | null;

FILE: kibbeh/src/pages/404.tsx
  function Custom404 (line 4) | function Custom404() {

FILE: kibbeh/src/pages/_app.tsx
  function App (line 40) | function App({ Component, pageProps }: AppProps) {

FILE: kibbeh/src/pages/connection-taken.tsx
  type ConnectionTakenProps (line 7) | interface ConnectionTakenProps {}

FILE: kibbeh/src/pages/download.tsx
  function getOS (line 20) | function getOS() {
  function OtherPlatformButton (line 60) | function OtherPlatformButton(props: {
  function CurrentPlatformButton (line 88) | function CurrentPlatformButton(props: {
  function Download (line 112) | function Download() {

FILE: kibbeh/src/pages/logout.tsx
  type logoutProps (line 7) | interface logoutProps {}

FILE: kibbeh/src/shared-components/ApiPreloadLink.tsx
  type Prefetch (line 6) | type Prefetch = ReturnType<typeof useTypeSafePrefetch>;
  type Handler (line 33) | type Handler = typeof handlers;
  type ValueOf (line 35) | type ValueOf<T> = T[keyof T];
  type DifferentProps (line 36) | type DifferentProps = {

FILE: kibbeh/src/shared-components/ConfirmModal.tsx
  type Props (line 9) | interface Props {}
  type Fn (line 11) | type Fn = () => void;

FILE: kibbeh/src/shared-components/InvitedToJoinRoomModal.tsx
  type Props (line 12) | interface Props {}
  type Fn (line 14) | type Fn = () => void;
  type JoinRoomModalType (line 16) | type JoinRoomModalType = "invite" | "someone_you_follow_created_a_room";
  type UserPreviewInfo (line 18) | type UserPreviewInfo = {
  type Options (line 24) | type Options = {

FILE: kibbeh/src/shared-hooks/useBoundingClientRect.ts
  function getBoundingClientRect (line 3) | function getBoundingClientRect(
  function useBoundingClientRect (line 9) | function useBoundingClientRect(

FILE: kibbeh/src/shared-hooks/useTypeSafeMutation.ts
  type Keys (line 7) | type Keys = keyof ReturnType<typeof wrap>["mutation"];

FILE: kibbeh/src/shared-hooks/useTypeSafePrefetch.ts
  type Keys (line 6) | type Keys = keyof ReturnType<typeof wrap>["query"];
  type PaginatedKey (line 8) | type PaginatedKey<K extends Keys> = [K, string | number];

FILE: kibbeh/src/shared-hooks/useTypeSafeQuery.ts
  type Keys (line 9) | type Keys = keyof ReturnType<typeof wrap>["query"];
  type PaginatedKey (line 11) | type PaginatedKey<K extends Keys> = [K, ...(string | number | boolean)[]];

FILE: kibbeh/src/shared-hooks/useTypeSafeTranslation.ts
  type TranslationKeys (line 6) | type TranslationKeys = Paths<typeof translations>;
  type DateTranslationType (line 8) | interface DateTranslationType {

FILE: kibbeh/src/shared-hooks/useTypeSafeUpdateQuery.ts
  type Keys (line 8) | type Keys = keyof ReturnType<typeof wrap>["query"];
  type PaginatedKey (line 10) | type PaginatedKey<K extends Keys> = [K, ...(string | number | boolean)[]];

FILE: kibbeh/src/shared-hooks/useViewportSize.ts
  type WindowSize (line 4) | interface WindowSize {

FILE: kibbeh/src/shared-hooks/useWindowSize.ts
  type WindowSize (line 4) | interface WindowSize {

FILE: kibbeh/src/stories/BaseOverlay.story.tsx
  type IconWrapperProps (line 48) | interface IconWrapperProps {
  function IconWrapper (line 52) | function IconWrapper({ children }: IconWrapperProps) {

FILE: kibbeh/src/stories/ProfileBlock.story.tsx
  type MinimizedRoomCardProps (line 18) | interface MinimizedRoomCardProps {
  type ProfileBlockProps (line 33) | interface ProfileBlockProps {

FILE: kibbeh/src/types/PageComponent.ts
  type PageComponent (line 3) | type PageComponent<T> = NextPage<T> & { ws?: boolean };

FILE: kibbeh/src/types/overrides-mui.d.ts
  type overridesNameToClassKey (line 4) | type overridesNameToClassKey = {
  type ComponentNameToClassKey (line 9) | interface ComponentNameToClassKey extends overridesNameToClassKey {}

FILE: kibbeh/src/types/util-types.ts
  type Await (line 1) | type Await<T> = T extends Promise<infer U> ? U : T;
  type Join (line 3) | type Join<S1, S2> = S1 extends string
  type Paths (line 9) | type Paths<T> = {

FILE: kibbeh/src/types/wakeLock.d.ts
  type BaseWebLockSentinelEventMap (line 1) | interface BaseWebLockSentinelEventMap {
  type WakeLockSentinel (line 5) | type WakeLockSentinel = {
  type WakeLockRequestType (line 31) | type WakeLockRequestType = "screen";
  type Navigator (line 33) | interface Navigator {

FILE: kibbeh/src/ui/Banner.tsx
  type BannerDurations (line 4) | type BannerDurations = "default" | "sticky";
  type BannerProps (line 6) | interface BannerProps {

FILE: kibbeh/src/ui/BannerButton.tsx
  type ButtonProps (line 17) | type ButtonProps = DetailedHTMLProps<

FILE: kibbeh/src/ui/BaseDropdownSm.tsx
  type BaseDropdownSmItemProps (line 3) | type BaseDropdownSmItemProps = React.DetailedHTMLProps<
  type BaseDropdownSmProps (line 23) | type BaseDropdownSmProps = React.DetailedHTMLProps<

FILE: kibbeh/src/ui/BaseOverlay.tsx
  type BaseOverlayProps (line 4) | interface BaseOverlayProps

FILE: kibbeh/src/ui/BaseSettingsItem.tsx
  type BaseSettingsItemProps (line 3) | interface BaseSettingsItemProps {

FILE: kibbeh/src/ui/BoxedIcon.tsx
  type BoxedIconProps (line 8) | interface BoxedIconProps

FILE: kibbeh/src/ui/BubbleText.tsx
  type BubbleTextProps (line 3) | interface BubbleTextProps {

FILE: kibbeh/src/ui/Button.tsx
  type ButtonProps (line 28) | type ButtonProps = DetailedHTMLProps<

FILE: kibbeh/src/ui/CenterLoader.tsx
  type CenterLoaderProps (line 4) | interface CenterLoaderProps {}

FILE: kibbeh/src/ui/ChangeAvatarCard.tsx
  type ChangeAvatarCardProps (line 7) | interface ChangeAvatarCardProps {

FILE: kibbeh/src/ui/ChangeBannerCard.tsx
  type ChangeBannerCardProps (line 6) | interface ChangeBannerCardProps {

FILE: kibbeh/src/ui/DurationTicker.tsx
  type DurationTickerProps (line 4) | interface DurationTickerProps {

FILE: kibbeh/src/ui/EmojiPicker.tsx
  type EmojiPickerProps (line 5) | interface EmojiPickerProps {

FILE: kibbeh/src/ui/ErrorButtonItem.tsx
  type ErrorButtonItemProps (line 6) | interface ErrorButtonItemProps {

FILE: kibbeh/src/ui/ErrorToast.tsx
  type ToastDurations (line 4) | type ToastDurations = "default" | "sticky";
  type ErrorMessageProps (line 6) | interface ErrorMessageProps {

FILE: kibbeh/src/ui/FeedHeader.tsx
  type FeedProps (line 5) | interface FeedProps {
  type FeedHeaderProps (line 11) | interface FeedHeaderProps {

FILE: kibbeh/src/ui/FollowersOnline.tsx
  type FriendOnlineType (line 8) | interface FriendOnlineType {
  type FriendsOnlineProps (line 18) | interface FriendsOnlineProps {

FILE: kibbeh/src/ui/InfoText.tsx
  type InfoTextProps (line 3) | interface InfoTextProps {

FILE: kibbeh/src/ui/Input.tsx
  type InputProps (line 4) | interface InputProps extends React.ComponentPropsWithoutRef<"input"> {

FILE: kibbeh/src/ui/InputErrorMsg.tsx
  type InputErrorMsgProps (line 3) | interface InputErrorMsgProps {}

FILE: kibbeh/src/ui/KeybindCard.tsx
  type KeybindCardProps (line 12) | interface KeybindCardProps {

FILE: kibbeh/src/ui/LanguageSelector.tsx
  type LanguageSelectorProps (line 9) | interface LanguageSelectorProps {

FILE: kibbeh/src/ui/MacButton.tsx
  type ButtonProps (line 13) | type ButtonProps = DetailedHTMLProps<

FILE: kibbeh/src/ui/MainGrid.tsx
  type DashboardGridProps (line 4) | interface DashboardGridProps {

FILE: kibbeh/src/ui/MessageElement.tsx
  type MessageElementProps (line 6) | interface MessageElementProps {
  type MessageDateProps (line 18) | interface MessageDateProps {

FILE: kibbeh/src/ui/MessagesDropdown.tsx
  type MessagesDropdownProps (line 6) | interface MessagesDropdownProps {

FILE: kibbeh/src/ui/MinimizedRoomCard.tsx
  type MinimizedRoomCardProps (line 14) | interface MinimizedRoomCardProps {

FILE: kibbeh/src/ui/NativeCheckbox.tsx
  type SwitchProps (line 3) | interface SwitchProps {
  type NativeCheckboxProps (line 25) | interface NativeCheckboxProps {
  type NativeCheckboxControllerProps (line 64) | interface NativeCheckboxControllerProps {

FILE: kibbeh/src/ui/NativeRadio.tsx
  type NativeRadioProps (line 3) | interface NativeRadioProps {
  type NativeRadioControllerProps (line 60) | interface NativeRadioControllerProps {

FILE: kibbeh/src/ui/NativeSelect.tsx
  type NativeSelectProps (line 3) | interface NativeSelectProps {}

FILE: kibbeh/src/ui/NotificationElement/FollowNotification.tsx
  type FollowNotificationProps (line 6) | interface FollowNotificationProps {

FILE: kibbeh/src/ui/NotificationElement/GenericNotification.tsx
  type GenericNotificationProps (line 4) | interface GenericNotificationProps {

FILE: kibbeh/src/ui/NotificationElement/LiveNotification.tsx
  type LiveNotificationProps (line 6) | interface LiveNotificationProps {

FILE: kibbeh/src/ui/NotificationElement/NewRoomNotification.tsx
  type NewRoomNotificationProps (line 6) | interface NewRoomNotificationProps {

FILE: kibbeh/src/ui/NotificationsDropdown.tsx
  type NotificationsDropdownPropsData (line 11) | type NotificationsDropdownPropsData = {
  type NotificationsDropdownProps (line 24) | interface NotificationsDropdownProps {

FILE: kibbeh/src/ui/ProfileAbout.tsx
  type ProfileAboutProps (line 9) | interface ProfileAboutProps

FILE: kibbeh/src/ui/ProfileAdmin.tsx
  type ProfileAdminProps (line 7) | interface ProfileAdminProps

FILE: kibbeh/src/ui/ProfileBlock.tsx
  type ProfileBlockProps (line 3) | interface ProfileBlockProps {

FILE: kibbeh/src/ui/ProfileHeader.tsx
  type ProfileHeaderProps (line 20) | interface ProfileHeaderProps {

FILE: kibbeh/src/ui/ProfileHeaderWrapper.tsx
  type ProfileHeaderWrapperProps (line 3) | interface ProfileHeaderWrapperProps {

FILE: kibbeh/src/ui/ProfileScheduled.tsx
  type ProfileScheduledProps (line 11) | interface ProfileScheduledProps

FILE: kibbeh/src/ui/ProfileTabs.tsx
  type ProfileTabsProps (line 10) | interface ProfileTabsProps extends React.HTMLAttributes<HTMLDivElement> {

FILE: kibbeh/src/ui/RoomAvatar.tsx
  type RoomAvatarProps (line 7) | interface RoomAvatarProps {

FILE: kibbeh/src/ui/RoomCard.tsx
  function formatNumber (line 9) | function formatNumber(num: number): string {
  function useScheduleRerender (line 15) | function useScheduleRerender(scheduledFor?: Date) {
  type RoomCardProps (line 39) | type RoomCardProps = {

FILE: kibbeh/src/ui/RoomCardHeading.tsx
  type RoomCardHeadingProps (line 3) | interface RoomCardHeadingProps {

FILE: kibbeh/src/ui/RoomCardParticipants.tsx
  type RoomCardParticipantsProps (line 4) | interface RoomCardParticipantsProps {

FILE: kibbeh/src/ui/RoomHeader.tsx
  type RoomHeaderProps (line 7) | interface RoomHeaderProps {

FILE: kibbeh/src/ui/RoomPanelIconBar.tsx
  type RoomPanelIconBarProps (line 16) | interface RoomPanelIconBarProps {

FILE: kibbeh/src/ui/RoomSectionHeader.tsx
  type RoomSectionHeaderProps (line 3) | interface RoomSectionHeaderProps {

FILE: kibbeh/src/ui/Search/GlobalSearch.tsx
  type HistoryItem (line 8) | type HistoryItem = {
  type UserSearchResult (line 13) | type UserSearchResult = {
  type RoomSearchResult (line 21) | type RoomSearchResult = {
  type SearchResultItem (line 28) | type SearchResultItem = User | Room;
  type GlobalSearchProps (line 30) | interface GlobalSearchProps {
  type HistoryProps (line 35) | interface HistoryProps {
  type SearchResultProps (line 39) | interface SearchResultProps {

FILE: kibbeh/src/ui/Search/SearchBar.tsx
  type SearchBarProps (line 6) | interface SearchBarProps

FILE: kibbeh/src/ui/Search/SearchHistory.tsx
  type SearchHistoryProps (line 5) | interface SearchHistoryProps {

FILE: kibbeh/src/ui/Search/SearchOverlay.tsx
  type SearchOverlayProps (line 4) | interface SearchOverlayProps {

FILE: kibbeh/src/ui/Search/SearchResult/RoomSearchResult.tsx
  type RoomSearchResultProps (line 6) | interface RoomSearchResultProps {

FILE: kibbeh/src/ui/Search/SearchResult/UserSearchResult.tsx
  type UserSearchResultProps (line 5) | interface UserSearchResultProps {

FILE: kibbeh/src/ui/SettingsIcon.tsx
  type SettingsIconProps (line 3) | interface SettingsIconProps {

FILE: kibbeh/src/ui/SettingsItemButton.tsx
  type SettingsItemButtonProps (line 5) | type SettingsItemButtonProps = {

FILE: kibbeh/src/ui/SettingsWrapper.tsx
  type SettingsWrapperProps (line 3) | interface SettingsWrapperProps {

FILE: kibbeh/src/ui/Tag.tsx
  type TagProps (line 3) | interface TagProps {

FILE: kibbeh/src/ui/Toast.tsx
  type ToastDurations (line 4) | type ToastDurations = "default" | "sticky";
  type ErrorMessageProps (line 6) | interface ErrorMessageProps {

FILE: kibbeh/src/ui/Twemoji.tsx
  type TwemojiProps (line 6) | interface TwemojiProps extends React.ImgHTMLAttributes<HTMLImageElement> {
  type StaticTwemojiProps (line 44) | interface StaticTwemojiProps extends React.ImgHTMLAttributes<HTMLImageEl...

FILE: kibbeh/src/ui/UpcomingRoomCardLg.tsx
  type UpcomingRoomCardLgProps (line 18) | interface UpcomingRoomCardLgProps {
  type DropdownProps (line 26) | interface DropdownProps {}

FILE: kibbeh/src/ui/UpcomingRoomsCard.tsx
  type FormattedDateProps (line 10) | interface FormattedDateProps {
  type UserCardProps (line 25) | interface UserCardProps {
  type ScheduledRoomSummaryCardProps (line 30) | interface ScheduledRoomSummaryCardProps {
  type UpcomingRoomsCardProps (line 39) | interface UpcomingRoomsCardProps {

FILE: kibbeh/src/ui/UserAvatar/MultipleUsers.tsx
  type AvatarProps (line 5) | interface AvatarProps {

FILE: kibbeh/src/ui/UserAvatar/SingleUser.tsx
  type AvatarProps (line 59) | interface AvatarProps {

FILE: kibbeh/src/ui/UserBadge.tsx
  type UserBadgeProps (line 14) | interface UserBadgeProps {

FILE: kibbeh/src/ui/UserBadgeLg.tsx
  type UserBadgeLgProps (line 10) | interface UserBadgeLgProps extends React.HTMLProps<HTMLDivElement> {

FILE: kibbeh/src/ui/UserProfile.tsx
  type UserProfileProps (line 11) | interface UserProfileProps {

FILE: kibbeh/src/ui/UserSummaryCard.tsx
  type badge (line 9) | type badge = {
  type UserSummaryCardProps (line 18) | interface UserSummaryCardProps {
  type BadgesProps (line 32) | interface BadgesProps {
  type WebsiteProps (line 36) | interface WebsiteProps {

FILE: kibbeh/src/ui/UserWideButton.tsx
  type UserWideButtonInfoProps (line 6) | interface UserWideButtonInfoProps {

FILE: kibbeh/src/ui/VerticalUserInfo.tsx
  type VerticalUserInfoProps (line 14) | interface VerticalUserInfoProps {

FILE: kibbeh/src/ui/VolumeIndicator.tsx
  type VolumeIndicatorProps (line 3) | interface VolumeIndicatorProps

FILE: kibbeh/src/ui/VolumeSlider.tsx
  type VolumeSliderProps (line 5) | interface VolumeSliderProps

FILE: kibbeh/src/ui/WinButton.tsx
  type ButtonProps (line 7) | type ButtonProps = DetailedHTMLProps<

FILE: kibbeh/src/ui/header/LeftHeader.tsx
  type LeftHeaderProps (line 6) | interface LeftHeaderProps {}

FILE: kibbeh/src/ui/header/MiddleHeader.tsx
  type MiddleHeaderProps (line 7) | interface MiddleHeaderProps {}

FILE: kibbeh/src/ui/header/RightHeader.tsx
  type RightHeaderProps (line 15) | interface RightHeaderProps {

FILE: kibbeh/src/ui/mobile/AccountOverlay.tsx
  type AccountOverlyProps (line 24) | interface AccountOverlyProps {}

FILE: kibbeh/src/ui/mobile/FeaturedRoomCardAvatars.tsx
  type FeaturedRoomCardAvatarsProps (line 4) | type FeaturedRoomCardAvatarsProps = {

FILE: kibbeh/src/ui/mobile/FeaturedRoomCardHosts.tsx
  type FeaturedRoomCardHostsProps (line 4) | type FeaturedRoomCardHostsProps = {

FILE: kibbeh/src/ui/mobile/MobileHeader/PageHeader.tsx
  type PageHeaderProps (line 4) | interface PageHeaderProps {

FILE: kibbeh/src/ui/mobile/MobileHeader/ProfileHeader.tsx
  type ProfileHeaderProps (line 15) | interface ProfileHeaderProps extends HTMLProps<HTMLDivElement> {

FILE: kibbeh/src/ui/mobile/MobileHeader/SearchHeader.tsx
  type SearchHeaderProps (line 5) | interface SearchHeaderProps {

FILE: kibbeh/src/ui/mobile/MobileNav.tsx
  type MobileNavContainerProps (line 5) | interface MobileNavContainerProps {
  type MobileNavItemProps (line 22) | interface MobileNavItemProps {
  type NavItem (line 49) | interface NavItem {
  type MobileNavProps (line 54) | interface MobileNavProps {

FILE: kousa/lib/beef/_repo.ex
  class Beef.Repo (line 1) | defmodule Beef.Repo

FILE: kousa/lib/beef/access/rooms.ex
  class Beef.Access.Rooms (line 1) | defmodule Beef.Access.Rooms
    method get_room_status (line 16) | def get_room_status(user_id) do
    method can_join_room (line 36) | def can_join_room(room_id, user_id) do
    method get_top_public_rooms (line 62) | def get_top_public_rooms(user_id, offset \\ 0) do
    method get_room_by_id (line 87) | def get_room_by_id(room_id) do
    method get_next_creator_for_room (line 98) | def get_next_creator_for_room(room_id) do
    method get_a_user_for_room (line 111) | def get_a_user_for_room(room_id) do
    method get_room_by_creator_id (line 118) | def get_room_by_creator_id(creator_id) do
    method owner? (line 125) | def owner?(room_id, user_id) do
    method search_name (line 133) | def search_name(start_of_name) do
    method all_rooms (line 144) | def all_rooms() do

FILE: kousa/lib/beef/access/user_blocks.ex
  class Beef.Access.UserBlocks (line 1) | defmodule Beef.Access.UserBlocks
    method blocked? (line 10) | def blocked?(user_id, user_id_blocked) do
    method username_blocked? (line 19) | def username_blocked?(username, user_id_blocked) do

FILE: kousa/lib/beef/access/users.ex
  class Beef.Access.Users (line 1) | defmodule Beef.Access.Users
    method get (line 10) | def get(user_id) do
    method get (line 14) | def get(user_id, opts) do
    method find_by_github_ids (line 18) | def find_by_github_ids(ids) do
    method search_username (line 29) | def search_username(start_of_username) do
    method get_by_id_with_follow_info (line 41) | def get_by_id_with_follow_info(me_id, them_id) do
    method get_by_id (line 52) | def get_by_id(user_id) do
    method get_by_id_with_room_permissions (line 56) | def get_by_id_with_room_permissions(user_id) do
    method get_by_username (line 67) | def get_by_username(username) do
    method get_by_username_with_follow_info (line 73) | def get_by_username_with_follow_info(user_id, username) do
    method search (line 85) | def search(query, offset) do
    method get_users_in_current_room (line 105) | def get_users_in_current_room(user_id) do
    method tuple_get_current_room_id (line 128) | def tuple_get_current_room_id(user_id) do
    method get_by_id_with_current_room (line 140) | def get_by_id_with_current_room(user_id) do
    method get_current_room (line 152) | def get_current_room(user_id) do
    method get_current_room_id (line 161) | def get_current_room_id(user_id) do
    method get_ip (line 174) | def get_ip(user_id) do
    method bot? (line 187) | def bot?(user_id) do
    method get_by_api_key (line 200) | def get_by_api_key(api_key) do
    method count_bot_accounts (line 204) | def count_bot_accounts(user_id) do

FILE: kousa/lib/beef/follows.ex
  class Beef.Follows (line 1) | defmodule Beef.Follows
    method get_followers_online_and_not_in_a_room (line 18) | def get_followers_online_and_not_in_a_room(user_id) do
    method bulk_insert (line 28) | def bulk_insert(follows) do
    method following_me? (line 38) | def following_me?(user_id, user_id_to_check) do
    method get_my_following (line 49) | def get_my_following(user_id, offset \\ 0) do
    method fetch_invite_list (line 79) | def fetch_invite_list(user_id, offset \\ 0) do
    method get_followers (line 100) | def get_followers(user_id, user_id_to_get_followers_for, offset \\ 20) do
    method get_following (line 120) | def get_following(user_id, user_id_to_get_following_for, offset \\ 20) do
    method delete (line 140) | def delete(user_id, follower_id) do
    method insert (line 168) | def insert(data) do
    method get_follow (line 202) | def get_follow(me_id, other_user_id) do
    method get_info (line 210) | def get_info(me_id, other_user_id) do

FILE: kousa/lib/beef/mutations/rooms.ex
  class Beef.Mutations.Rooms (line 1) | defmodule Beef.Mutations.Rooms
    method set_room_privacy_by_creator_id (line 9) | def set_room_privacy_by_creator_id(user_id, isPrivate, new_name) do
    method join_room (line 23) | def join_room(room, user_id) do
    method increment_room_people_count (line 53) | def increment_room_people_count(room_id) do
    method increment_room_people_count (line 65) | def increment_room_people_count(room_id, new_people_list) do
    method delete_room_by_id (line 80) | def delete_room_by_id(room_id) do
    method decrement_room_people_count (line 84) | def decrement_room_people_count(room_id, new_people_list) do
    method set_room_owner_and_dec (line 99) | def set_room_owner_and_dec(room_id, user_id, new_people_list) do
    method replace_room_owner (line 115) | def replace_room_owner(user_id, new_creator_id) do
    method kick_from_room (line 128) | def kick_from_room(user_id, room_id) do
    method leave_room (line 140) | def leave_room(user_id, room_id) do
    method raw_insert (line 171) | def raw_insert(data, peoplePreviewList) do
    method update_name (line 177) | def update_name(user_id, name) do
    method create (line 190) | def create(data) do
    method edit (line 224) | def edit(room_id, data) do

FILE: kousa/lib/beef/mutations/user_blocks.ex
  class Beef.Mutations.UserBlocks (line 1) | defmodule Beef.Mutations.UserBlocks
    method insert (line 10) | def insert(data) do
    method delete (line 16) | def delete(user_id, user_id_to_block) do

FILE: kousa/lib/beef/mutations/users.ex
  class Beef.Mutations.Users (line 1) | defmodule Beef.Mutations.Users
    method edit_profile (line 9) | def edit_profile(user_id, data) do
    method delete (line 17) | def delete(user_id) do
    method bulk_insert (line 21) | def bulk_insert(users) do
    method inc_num_following (line 29) | def inc_num_following(user_id, n) do
    method set_reason_for_ban (line 36) | def set_reason_for_ban(user_id, reason_for_ban) do
    method set_ip (line 43) | def set_ip(user_id, ip) do
    method set_online (line 50) | def set_online(user_id) do
    method set_user_left_current_room (line 57) | def set_user_left_current_room(user_id) do
    method set_offline (line 66) | def set_offline(user_id) do
    method set_current_room (line 74) | def set_current_room(user_id, room_id, can_speak \\ false, returning \...
    method twitter_find_or_create (line 107) | def twitter_find_or_create(user) do
    method github_find_or_create (line 151) | def github_find_or_create(user, github_access_token) do
    method discord_find_or_create (line 199) | def discord_find_or_create(user, discord_access_token) do
    method create_bot (line 241) | def create_bot(owner_id, username) do

FILE: kousa/lib/beef/queries/rooms.ex
  class Beef.Queries.Rooms (line 1) | defmodule Beef.Queries.Rooms
    method start (line 6) | def start do
    method userStart (line 10) | def userStart do
    method filter_by_current_room_id (line 14) | def filter_by_current_room_id(query, room_id) do
    method filter_by_creator_id (line 18) | def filter_by_creator_id(query, creator_id) do
    method filter_by_room_id_and_creator_id (line 22) | def filter_by_room_id_and_creator_id(query, room_id, user_id) do
    method limit_one (line 26) | def limit_one(query) do

FILE: kousa/lib/beef/queries/user_blocks.ex
  class Beef.Queries.UserBlocks (line 1) | defmodule Beef.Queries.UserBlocks
    method start (line 10) | def start do
    method filter_by_id_and_blockedId (line 14) | def filter_by_id_and_blockedId(query, user_id, user_id_blockedId) do
    method filter_by_username_and_blockedId (line 18) | def filter_by_username_and_blockedId(query, username, user_id_blocked) do

FILE: kousa/lib/beef/queries/users.ex
  class Beef.Queries.Users (line 1) | defmodule Beef.Queries.Users
    method start (line 12) | def start do
    method limit_one (line 16) | def limit_one(query) do
    method they_blocked_me_info (line 20) | def they_blocked_me_info(query, me_id) do
    method i_blocked_them_info (line 31) | def i_blocked_them_info(query, me_id) do
    method follow_info (line 42) | def follow_info(query, me_id) do
    method filter_by_github_ids (line 58) | def filter_by_github_ids(query, github_ids) do
    method select_id (line 62) | def select_id(query) do
    method filter_by_id (line 66) | def filter_by_id(query, user_id) do
    method filter_by_username (line 70) | def filter_by_username(query, username) do
    method inc_num_following_by_n (line 74) | def inc_num_following_by_n(query, n) do
    method update_reason_for_ban (line 82) | def update_reason_for_ban(query, reason_for_ban) do
    method update_set_ip (line 90) | def update_set_ip(query, ip) do
    method update_set_online_true (line 98) | def update_set_online_true(query) do
    method update_set_online_false (line 106) | def update_set_online_false(query) do
    method update_set_last_online_to_now (line 114) | def update_set_last_online_to_now(query) do
    method update_set_current_room_nil (line 122) | def update_set_current_room_nil(query) do

FILE: kousa/lib/beef/room_blocks.ex
  class Beef.RoomBlocks (line 1) | defmodule Beef.RoomBlocks
    method unban (line 9) | def unban(room_id, user_id) do
    method blocked? (line 14) | def blocked?(room_id, user_id) do
    method get_blocked_users (line 28) | def get_blocked_users(room_id, offset) do
    method insert (line 41) | def insert(data) do
    method upsert (line 47) | def upsert(data = %{ip: ip}) do

FILE: kousa/lib/beef/room_permissions.ex
  class Beef.RoomPermissions (line 1) | defmodule Beef.RoomPermissions
    method insert (line 4) | def insert(data) do
    method upsert (line 10) | def upsert(data, set, returning \\ true) do
    method speaker? (line 20) | def speaker?(user_id, room_id) do
    method listener? (line 30) | def listener?(user_id, room_id) do
    method mod? (line 34) | def mod?(user_id, room_id) do
    method asked_to_speak? (line 44) | def asked_to_speak?(user_id, room_id) do
    method get (line 54) | def get(user_id, room_id) do
    method ask_to_speak (line 62) | def ask_to_speak(user_id, room_id) do
    method set_speaker (line 66) | def set_speaker(user_id, room_id, speaker?, returning \\ false) do
    method set_is_mod (line 74) | def set_is_mod(user_id, room_id, is_mod) do
    method make_listener (line 82) | def make_listener(user_id, room_id) do

FILE: kousa/lib/beef/rooms.ex
  class Beef.Rooms (line 1) | defmodule Beef.Rooms

FILE: kousa/lib/beef/scheduled_rooms.ex
  class Beef.ScheduledRooms (line 1) | defmodule Beef.ScheduledRooms
    method get_by_id (line 10) | def get_by_id(id) do
    method delete (line 21) | def delete(user_id, id) do
    method insert (line 26) | def insert(data) do
    method room_started (line 30) | def room_started(user_id, id, room_id) do
    method edit (line 48) | def edit(user_id, id, data) do
    method add_cursor (line 70) | def add_cursor(q, "") do
    method add_cursor (line 74) | def add_cursor(q, nil) do
    method add_cursor (line 78) | def add_cursor(q, cursor) do
    method get_my_scheduled_rooms_about_to_start (line 88) | def get_my_scheduled_rooms_about_to_start(user_id) do
    method get_feed (line 110) | def get_feed(user_id, get_only_my_scheduled_rooms, cursor) do
    method get_mine (line 141) | def get_mine(user_id) do

FILE: kousa/lib/beef/schemas/attending_scheduled_room.ex
  class Beef.Schemas.AttendingScheduledRoom (line 1) | defmodule Beef.Schemas.AttendingScheduledRoom
    method insert_changeset (line 22) | def insert_changeset(follow, attrs) do

FILE: kousa/lib/beef/schemas/follow.ex
  class Beef.Schemas.Follow (line 1) | defmodule Beef.Schemas.Follow
    method insert_changeset (line 24) | def insert_changeset(follow, attrs) do

FILE: kousa/lib/beef/schemas/room.ex
  class Beef.Schemas.Room (line 1) | defmodule Beef.Schemas.Room
    method insert_changeset (line 47) | def insert_changeset(room, attrs) do
    method edit_changeset (line 71) | def edit_changeset(room, attrs) do

FILE: kousa/lib/beef/schemas/room_block.ex
  class Beef.Schemas.RoomBlock (line 1) | defmodule Beef.Schemas.RoomBlock
    method insert_changeset (line 19) | def insert_changeset(roomBlock, attrs) do

FILE: kousa/lib/beef/schemas/room_permission.ex
  class Beef.Schemas.RoomPermission (line 1) | defmodule Beef.Schemas.RoomPermission
    method insert_changeset (line 31) | def insert_changeset(roomPerm, attrs) do

FILE: kousa/lib/beef/schemas/scheduled_room.ex
  class Beef.Schemas.ScheduledRoom (line 1) | defmodule Beef.Schemas.ScheduledRoom
    method validate_future_date (line 41) | def validate_future_date(%{changes: changes} = changeset, field) do
    method validate_not_too_far_into_future_date (line 54) | def validate_not_too_far_into_future_date(%{changes: changes} = change...
    method common_validation (line 70) | def common_validation(attrs) do
    method insert_changeset (line 79) | def insert_changeset(room, attrs) do
    method edit_changeset (line 86) | def edit_changeset(room, attrs) do

FILE: kousa/lib/beef/schemas/scheduled_room_cohost.ex
  class Beef.Schemas.ScheduledRoomCohost (line 1) | defmodule Beef.Schemas.ScheduledRoomCohost
    method insert_changeset (line 22) | def insert_changeset(follow, attrs) do

FILE: kousa/lib/beef/schemas/user.ex
  class Beef.Schemas.User (line 1) | defmodule Beef.Schemas.User
    method changeset (line 111) | def changeset(user, attrs) do
    method api_key_changeset (line 119) | def api_key_changeset(user, attrs) do
    method admin_update_changeset (line 126) | def admin_update_changeset(user, attrs) do
    method edit_changeset (line 134) | def edit_changeset(user, attrs) do
  class Preview (line 9) | defmodule Preview

FILE: kousa/lib/beef/schemas/user_block.ex
  class Beef.Schemas.UserBlock (line 1) | defmodule Beef.Schemas.UserBlock
    method insert_changeset (line 17) | def insert_changeset(userBlock, attrs) do

FILE: kousa/lib/beef/user_blocks.ex
  class Beef.UserBlocks (line 1) | defmodule Beef.UserBlocks

FILE: kousa/lib/beef/users.ex
  class Beef.Users (line 1) | defmodule Beef.Users

FILE: kousa/lib/broth.ex
  class Broth (line 1) | defmodule Broth

FILE: kousa/lib/broth/legacy_handler.ex
  class Broth.LegacyHandler (line 1) | defmodule Broth.LegacyHandler
    method process (line 15) | def process(%{"op" => "block_user_and_from_room", "d" => payload}, sta...
    method process (line 19) | def process(%{"op" => "fetch_follow_list", "d" => payload}, state) do
    method process (line 23) | def process(%{"op" => "join_room_and_get_info", "d" => payload, "fetch...
    method block_user_and_from_room (line 28) | defp block_user_and_from_room(%{"userId" => user_id_to_block}, state) do
    method fetch_follow_list (line 38) | defp fetch_follow_list(
    method join_room_and_get_info (line 60) | defp join_room_and_get_info(%{"roomId" => room_id_to_join}, fetch_id, ...

FILE: kousa/lib/broth/message.ex
  class Broth.Message (line 1) | defmodule Broth.Message
    method changeset (line 29) | def changeset(data, state) do
    method find (line 58) | defp find(changeset, field, optional \\ false)
    method find (line 59) | defp find(changeset = %{valid?: false}, _, _), do: changeset
    method find (line 72) | defp find(changeset, field, [_ | rest], optional), do: find(changeset,...
    method find (line 74) | defp find(changeset, field, [], optional) do
    method cast_operator (line 86) | defp cast_operator(changeset = %{valid?: false}), do: changeset
    method cast_operator (line 88) | defp cast_operator(changeset = %{params: %{"operator" => op}}) do
    method cast_reference (line 98) | defp cast_reference(changeset = %{valid?: false}), do: changeset
    method cast_reference (line 100) | defp cast_reference(changeset = %{params: %{"reference" => reference}}...
    method cast_reference (line 104) | defp cast_reference(changeset), do: changeset
    method cast_inbound_operator (line 106) | defp cast_inbound_operator(changeset) do
    method cast_payload (line 115) | defp cast_payload(changeset = %{valid?: false}, _), do: changeset
    method cast_payload (line 117) | defp cast_payload(changeset, state) do
    method cast_version (line 133) | defp cast_version(changeset = %{valid?: false}), do: changeset
    method cast_version (line 135) | defp cast_version(changeset = %{params: params}) do
    method validate_calls_have_references (line 143) | defp validate_calls_have_references(changeset = %{valid?: false}), do:...
    method validate_calls_have_references (line 145) | defp validate_calls_have_references(changeset) do

FILE: kousa/lib/broth/message/_types/chat_token.ex
  class Broth.Message.Types.ChatToken (line 1) | defmodule Broth.Message.Types.ChatToken
    method changeset (line 27) | def changeset(changeset, %{"t" => type, "v" => value}) do
    method changeset (line 31) | def changeset(changeset, data) do
    method validate_link (line 40) | defp validate_link(changeset) do
    method validate_link_uri (line 49) | defp validate_link_uri(changeset) do

FILE: kousa/lib/broth/message/auth/request.ex
  class Broth.Message.Auth.Request (line 1) | defmodule Broth.Message.Auth.Request
    method changeset (line 19) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 58) | def execute(changeset, state) do
  class Reply (line 26) | defmodule Reply

FILE: kousa/lib/broth/message/call.ex
  class Broth.Message.Call (line 1) | defmodule Broth.Message.Call
    method __after_compile__ (line 84) | def __after_compile__(%{module: module}, _bin) do

FILE: kousa/lib/broth/message/cast.ex
  class Broth.Message.Cast (line 1) | defmodule Broth.Message.Cast
    method __after_compile__ (line 54) | def __after_compile__(%{module: module}, _bin) do
    method auth_check (line 63) | def auth_check(true) do
    method auth_check (line 71) | def auth_check(false) do
    method schema_ast (line 78) | def schema_ast(opts) do
    method check_for_schema (line 92) | def check_for_schema(module, direction) do

FILE: kousa/lib/broth/message/chat/ban.ex
  class Broth.Message.Chat.Ban (line 1) | defmodule Broth.Message.Chat.Ban
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 15) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/chat/delete.ex
  class Broth.Message.Chat.Delete (line 1) | defmodule Broth.Message.Chat.Delete
    method initialize (line 21) | def initialize(state) do
    method changeset (line 25) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 33) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/chat/send.ex
  class Broth.Message.Chat.Send (line 1) | defmodule Broth.Message.Chat.Send
    method initialize (line 21) | def initialize(state) do
    method changeset (line 30) | def changeset(initializer \\ %__MODULE__{}, data) do
    method default_whispered_to (line 38) | defp default_whispered_to(changeset) do
    method put_tokens (line 46) | def put_tokens(changeset, []) do
    method put_tokens (line 67) | def put_tokens(changeset, _invalid_tokens) do
    method apply_changeset_accumulate_length (line 71) | defp apply_changeset_accumulate_length(token, length) do
    method text_size (line 91) | defp text_size(changeset) do
    method validate_whispered_to (line 99) | def validate_whispered_to(changeset) do
    method execute (line 126) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/chat/unban.ex
  class Broth.Message.Chat.Unban (line 1) | defmodule Broth.Message.Chat.Unban
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 15) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/manifest.ex
  class Broth.Message.Manifest (line 1) | defmodule Broth.Message.Manifest
    method actions (line 65) | def actions, do: @actions

FILE: kousa/lib/broth/message/misc/search.ex
  class Broth.Message.Misc.Search (line 1) | defmodule Broth.Message.Misc.Search
    method changeset (line 13) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 46) | def execute(changeset, state) do
  class Reply (line 20) | defmodule Reply

FILE: kousa/lib/broth/message/push.ex
  class Broth.Message.Push (line 1) | defmodule Broth.Message.Push
    method __after_compile__ (line 29) | def __after_compile__(%{module: module}, _bin) do

FILE: kousa/lib/broth/message/room/ban.ex
  class Broth.Message.Room.Ban (line 1) | defmodule Broth.Message.Room.Ban
    method changeset (line 12) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 19) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/room/create.ex
  class Broth.Message.Room.Create (line 1) | defmodule Broth.Message.Room.Create
    method changeset (line 27) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 42) | def execute(changeset!, state) do

FILE: kousa/lib/broth/message/room/create_scheduled.ex
  class Broth.Message.Room.CreateScheduled (line 1) | defmodule Broth.Message.Room.CreateScheduled
    method changeset (line 17) | def changeset(initializer \\ %__MODULE__{}, data) do
    method validate_future (line 24) | def validate_future(changeset = %{valid?: false}), do: changeset
    method validate_future (line 26) | def validate_future(changeset) do
    method execute (line 38) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/room/deafen.ex
  class Broth.Message.Room.Deafen (line 1) | defmodule Broth.Message.Room.Deafen
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 23) | def execute(changeset, state) do
  class Reply (line 15) | defmodule Reply

FILE: kousa/lib/broth/message/room/delete_scheduled.ex
  class Broth.Message.Room.DeleteScheduled (line 1) | defmodule Broth.Message.Room.DeleteScheduled
    method changeset (line 11) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 28) | def execute(changeset, state) do
  class Reply (line 18) | defmodule Reply

FILE: kousa/lib/broth/message/room/get_banned_users.ex
  class Broth.Message.Room.GetBannedUsers (line 1) | defmodule Broth.Message.Room.GetBannedUsers
    method changeset (line 10) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 31) | def execute(changeset, state) do
  class Reply (line 16) | defmodule Reply

FILE: kousa/lib/broth/message/room/get_info.ex
  class Broth.Message.Room.GetInfo (line 1) | defmodule Broth.Message.Room.GetInfo
    method changeset (line 14) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 33) | def execute(changeset, state) do
  class Reply (line 20) | defmodule Reply

FILE: kousa/lib/broth/message/room/get_invite_list.ex
  class Broth.Message.Room.GetInviteList (line 1) | defmodule Broth.Message.Room.GetInviteList
    method changeset (line 10) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 29) | def execute(changeset, state) do
  class Reply (line 16) | defmodule Reply

FILE: kousa/lib/broth/message/room/get_scheduled.ex
  class Broth.Message.Room.GetScheduled (line 1) | defmodule Broth.Message.Room.GetScheduled
    method changeset (line 13) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 35) | def execute(changeset, state = %{user: %{id: user_id}}) do
  class Reply (line 23) | defmodule Reply

FILE: kousa/lib/broth/message/room/get_top.ex
  class Broth.Message.Room.GetTop (line 1) | defmodule Broth.Message.Room.GetTop
    method changeset (line 10) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 31) | def execute(changeset, state) do
  class Reply (line 16) | defmodule Reply

FILE: kousa/lib/broth/message/room/invite.ex
  class Broth.Message.Room.Invite (line 1) | defmodule Broth.Message.Room.Invite
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 15) | def execute(data, state) do

FILE: kousa/lib/broth/message/room/join.ex
  class Broth.Message.Room.Join (line 1) | defmodule Broth.Message.Room.Join
    method changeset (line 12) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 32) | def execute(changeset, state) do
  class Reply (line 19) | defmodule Reply

FILE: kousa/lib/broth/message/room/leave.ex
  class Broth.Message.Room.Leave (line 1) | defmodule Broth.Message.Room.Leave
    method changeset (line 17) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 31) | def execute(_, state) do
  class Reply (line 21) | defmodule Reply

FILE: kousa/lib/broth/message/room/mute.ex
  class Broth.Message.Room.Mute (line 1) | defmodule Broth.Message.Room.Mute
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 23) | def execute(changeset, state) do
  class Reply (line 15) | defmodule Reply

FILE: kousa/lib/broth/message/room/set_active_speaker.ex
  class Broth.Message.Room.SetActiveSpeaker (line 1) | defmodule Broth.Message.Room.SetActiveSpeaker
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 15) | def execute(changeset, state = %{user: %{id: user_id}}) do

FILE: kousa/lib/broth/message/room/set_auth.ex
  class Broth.Message.Room.SetAuth (line 1) | defmodule Broth.Message.Room.SetAuth
    method changeset (line 12) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 19) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/room/set_role.ex
  class Broth.Message.Room.SetRole (line 1) | defmodule Broth.Message.Room.SetRole
    method initialize (line 12) | def initialize(state) do
    method changeset (line 17) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 25) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/room/unban.ex
  class Broth.Message.Room.Unban (line 1) | defmodule Broth.Message.Room.Unban
    method changeset (line 11) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 28) | def execute(changeset, state) do
  class Reply (line 18) | defmodule Reply

FILE: kousa/lib/broth/message/room/update.ex
  class Broth.Message.Room.Update (line 1) | defmodule Broth.Message.Room.Update
    method initialize (line 9) | def initialize(state) do
    method changeset (line 14) | def changeset(nil, _) do
    method changeset (line 21) | def changeset(initializer, data) do
    method execute (line 29) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/room/update_scheduled.ex
  class Broth.Message.Room.UpdateScheduled (line 1) | defmodule Broth.Message.Room.UpdateScheduled
    method changeset (line 17) | def changeset(initializer \\ %__MODULE__{}, data)
    method changeset (line 25) | def changeset(_, data) do
    method id_error (line 38) | def id_error(message) do
    method execute (line 44) | def execute(changeset, state) do

FILE: kousa/lib/broth/message/user/admin_update.ex
  class Broth.Message.User.AdminUpdate (line 1) | defmodule Broth.Message.User.AdminUpdate
    method user_admin_changeset (line 15) | def user_admin_changeset(_, data, user) do
    method changeset (line 21) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 41) | def execute(changeset, %SocketHandler{} = state) do

FILE: kousa/lib/broth/message/user/ban.ex
  class Broth.Message.User.Ban (line 1) | defmodule Broth.Message.User.Ban
    method changeset (line 10) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 26) | def execute(changeset, state) do
  class Reply (line 16) | defmodule Reply

FILE: kousa/lib/broth/message/user/block.ex
  class Broth.Message.User.Block (line 1) | defmodule Broth.Message.User.Block
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 33) | def execute(changeset, %SocketHandler{} = state) do
  class Reply (line 15) | defmodule Reply

FILE: kousa/lib/broth/message/user/create_bot.ex
  class Broth.Message.User.CreateBot (line 1) | defmodule Broth.Message.User.CreateBot
    method changeset (line 13) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 40) | def execute(changeset!, state) do
  class Reply (line 19) | defmodule Reply

FILE: kousa/lib/broth/message/user/follow.ex
  class Broth.Message.User.Follow (line 1) | defmodule Broth.Message.User.Follow
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 25) | def execute(changeset, state) do
  class Reply (line 15) | defmodule Reply

FILE: kousa/lib/broth/message/user/get_bots.ex
  class Broth.Message.User.GetBots (line 1) | defmodule Broth.Message.User.GetBots
    method changeset (line 10) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 40) | def execute(changeset, %SocketHandler{} = state) do
  class Reply (line 15) | defmodule Reply

FILE: kousa/lib/broth/message/user/get_followers.ex
  class Broth.Message.User.GetFollowers (line 1) | defmodule Broth.Message.User.GetFollowers
    method changeset (line 14) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 33) | def execute(changeset, state) do
  class Reply (line 21) | defmodule Reply

FILE: kousa/lib/broth/message/user/get_following.ex
  class Broth.Message.User.GetFollowing (line 1) | defmodule Broth.Message.User.GetFollowing
    method changeset (line 11) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 30) | def execute(changeset, state) do
  class Reply (line 17) | defmodule Reply

FILE: kousa/lib/broth/message/user/get_info.ex
  class Broth.Message.User.GetInfo (line 1) | defmodule Broth.Message.User.GetInfo
    method changeset (line 11) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 55) | def execute(changeset, state) do
  class Reply (line 17) | defmodule Reply

FILE: kousa/lib/broth/message/user/get_relationship.ex
  class Broth.Message.User.GetRelationship (line 1) | defmodule Broth.Message.User.GetRelationship
    method changeset (line 17) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 35) | def execute(changeset, state = %{user: %{id: user_id}}) do
  class Reply (line 24) | defmodule Reply

FILE: kousa/lib/broth/message/user/revoke_api_key.ex
  class Broth.Message.User.RevokeApiKey (line 1) | defmodule Broth.Message.User.RevokeApiKey
    method changeset (line 10) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 33) | def execute(changeset, %SocketHandler{} = state) do
  class Reply (line 17) | defmodule Reply

FILE: kousa/lib/broth/message/user/unblock.ex
  class Broth.Message.User.Unblock (line 1) | defmodule Broth.Message.User.Unblock
    method changeset (line 11) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 31) | def execute(changeset, %SocketHandler{} = state) do
  class Reply (line 18) | defmodule Reply

FILE: kousa/lib/broth/message/user/unfollow.ex
  class Broth.Message.User.Unfollow (line 1) | defmodule Broth.Message.User.Unfollow
    method changeset (line 9) | def changeset(initializer \\ %__MODULE__{}, data) do
    method execute (line 25) | def execute(changeset, state) do
  class Reply (line 15) | defmodule Reply

FILE: kousa/lib/broth/message/user/update.ex
  class Broth.Message.User.Update (line 1) | defmodule Broth.Message.User.Update
    method initialize (line 9) | def initialize(state) do
    method changeset (line 14) | def changeset(initializer \\ %User{}, data) do
    method execute (line 41) | def execute(changeset, state) do

FILE: kousa/lib/broth/plugs/check_auth.ex
  class Broth.Plugs.CheckAuth (line 1) | defmodule Broth.Plugs.CheckAuth
    method init (line 4) | def init(opts) do
    method call (line 8) | def call(conn = %{req_headers: req_headers}, opts) do
    method assign_tokens (line 19) | defp assign_tokens(conn, access_token, refresh_token, opts) do
    method auth_error (line 43) | defp auth_error(conn, opts) do

FILE: kousa/lib/broth/plugs/cors.ex
  class Broth.Plugs.Cors (line 1) | defmodule Broth.Plugs.Cors
    method init (line 4) | def init(_) do
    method call (line 7) | def call(conn, _opts) do

FILE: kousa/lib/broth/plugs/redirect.ex
  class Broth.Plugs.Redirect (line 1) | defmodule Broth.Plugs.Redirect
    method redirect (line 4) | def redirect(conn, url) do

FILE: kousa/lib/broth/routes/bot_auth.ex
  class Broth.Routes.BotAuth (line 1) | defmodule Broth.Routes.BotAuth

FILE: kousa/lib/broth/routes/dev_only.ex
  class Broth.Routes.DevOnly (line 1) | defmodule Broth.Routes.DevOnly

FILE: kousa/lib/broth/routes/discord_auth.ex
  class Broth.Routes.DiscordAuth (line 1) | defmodule Broth.Routes.DiscordAuth
    method get_base_url (line 44) | def get_base_url(conn) do
    method handle_callback (line 57) | def handle_callback(
    method handle_callback (line 69) | def handle_callback(%Plug.Conn{assigns: %{ueberauth_failure: failure}}...
    method handle_callback (line 83) | def handle_callback(

FILE: kousa/lib/broth/routes/github_auth.ex
  class Broth.Routes.GitHubAuth (line 1) | defmodule Broth.Routes.GitHubAuth
    method get_base_url (line 51) | def get_base_url(conn) do
    method handle_callback (line 74) | def handle_callback(
    method handle_callback (line 86) | def handle_callback(%Plug.Conn{assigns: %{ueberauth_failure: failure}}...
    method handle_callback (line 99) | def handle_callback(
    method handle_callback (line 143) | def handle_callback(conn) do

FILE: kousa/lib/broth/routes/room.ex
  class Broth.Routes.Room (line 1) | defmodule Broth.Routes.Room

FILE: kousa/lib/broth/routes/scheduled_room.ex
  class Broth.Routes.ScheduledRoom (line 1) | defmodule Broth.Routes.ScheduledRoom

FILE: kousa/lib/broth/routes/stats.ex
  class Broth.Routes.Stats (line 1) | defmodule Broth.Routes.Stats
    method getStats (line 16) | defp getStats do

FILE: kousa/lib/broth/routes/twitter_auth.ex
  class Broth.Routes.TwitterAuth (line 1) | defmodule Broth.Routes.TwitterAuth
    method put_secret_key_base (line 21) | def put_secret_key_base(conn, _) do
    method get_base_url (line 130) | def get_base_url(conn) do

FILE: kousa/lib/broth/routes/user.ex
  class Broth.Routes.User (line 1) | defmodule Broth.Routes.User

FILE: kousa/lib/broth/socket_handler.ex
  class Broth.SocketHandler (line 1) | defmodule Broth.SocketHandler
    method init (line 30) | def init(request, _state) do
    method websocket_init (line 62) | def websocket_init(state) do
    method exit (line 76) | def exit(pid), do: send(pid, :exit)
    method exit_impl (line 78) | defp exit_impl(state) do
    method auth_timeout_impl (line 88) | defp auth_timeout_impl(state) do
    method unsub (line 97) | def unsub(socket, topic), do: send(socket, {:unsub, topic})
    method unsub_impl (line 101) | defp unsub_impl(topic, state) do
    method remote_send (line 107) | def remote_send(socket, message), do: send(socket, {:remote_send, mess...
    method remote_send_impl (line 110) | defp remote_send_impl(message, state) do
    method user_update_impl (line 123) | def user_update_impl({"user:update:" <> user_id, user}, state = %{user...
    method user_update_impl (line 130) | def user_update_impl(_, state), do: ws_push(nil, state)
    method real_chat_impl (line 135) | defp real_chat_impl(
    method chat_impl (line 146) | def chat_impl(
    method chat_impl (line 160) | def chat_impl(
    method chat_impl (line 168) | def chat_impl(_, state), do: ws_push(nil, state)
    method websocket_handle (line 174) | def websocket_handle({:text, "ping"}, state), do: {[text: "pong"], state}
    method websocket_handle (line 178) | def websocket_handle({:ping, _}, state), do: {[text: "pong"], state}
    method websocket_handle (line 180) | def websocket_handle({:text, command_json}, state) do
    method validate (line 234) | def validate(message, state) do
    method auth_check (line 240) | def auth_check(%{operator: op}, state), do: op.auth_check(state)
    method dispatch (line 242) | def dispatch(message, state) do
    method wrap (line 270) | def wrap(message, payload = %{}) do
    method wrap_error (line 274) | defp wrap_error(message, error) do
    method to_map (line 291) | defp to_map(changeset = %Ecto.Changeset{}) do
    method to_map (line 299) | defp to_map(other) do
    method dispatch_mediasoup_message (line 303) | defp dispatch_mediasoup_message(msg, %{user: %{id: user_id}}) do
    method prepare_socket_msg (line 324) | def prepare_socket_msg(data, state) do
    method encode_data (line 330) | defp encode_data(data, %{encoding: :etf}) do
    method encode_data (line 336) | defp encode_data(data, %{encoding: :json}) do
    method prepare_data (line 340) | defp prepare_data(data, %{compression: :zlib}) do
    method prepare_data (line 350) | defp prepare_data(data, %{encoding: :etf}) do
    method prepare_data (line 354) | defp prepare_data(data, %{encoding: :json}) do
    method ws_push (line 358) | def ws_push(frame, state) do
    method adopt_version (line 362) | def adopt_version(target = %{version: _}, %{version: version}) do
    method websocket_info (line 388) | def websocket_info({:EXIT, _, _}, state), do: exit_impl(state)
    method websocket_info (line 389) | def websocket_info(:exit, state), do: exit_impl(state)
    method websocket_info (line 390) | def websocket_info(:auth_timeout, state), do: auth_timeout_impl(state)
    method websocket_info (line 391) | def websocket_info({:remote_send, message}, state), do: remote_send_im...
    method websocket_info (line 392) | def websocket_info({:unsub, topic}, state), do: unsub_impl(topic, state)
    method websocket_info (line 393) | def websocket_info(message = {"chat:" <> _, _}, state), do: chat_impl(...
    method websocket_info (line 395) | def websocket_info(message = {"user:update:" <> _, _}, state),
    method websocket_info (line 399) | def websocket_info(_, state) do

FILE: kousa/lib/broth/translator.ex
  class Broth.Translator (line 1) | defmodule Broth.Translator
    method translate_inbound (line 12) | def translate_inbound(message), do: message
    method translate_outbound (line 14) | def translate_outbound(message, original = %{version: ~v(0.1.0)}) do
    method translate_outbound (line 18) | def translate_outbound(message, _), do: message

FILE: kousa/lib/broth/translator/v0_1_0.ex
  class Broth.Translator.V0_1_0 (line 1) | defmodule Broth.Translator.V0_1_0
    method translate_inbound (line 61) | def translate_inbound(message = %{"op" => operator}) do
    method translate_operation (line 69) | def translate_operation(message = %{"op" => operator}) do
    method translate_in_body (line 73) | def translate_in_body(message, "edit_profile") do
    method translate_in_body (line 77) | def translate_in_body(message, "get_user_profile") do
    method translate_in_body (line 81) | def translate_in_body(message, "create_room_from_scheduled_room") do
    method translate_in_body (line 85) | def translate_in_body(message, "create_room") do
    method translate_in_body (line 90) | def translate_in_body(message, "ban") do
    method translate_in_body (line 99) | def translate_in_body(message, "set_listener") do
    method translate_in_body (line 103) | def translate_in_body(message, "add_speaker") do
    method translate_in_body (line 107) | def translate_in_body(message, "change_mod_status") do
    method translate_in_body (line 112) | def translate_in_body(message, "change_room_creator") do
    method translate_in_body (line 116) | def translate_in_body(message, "make_room_public") do
    method translate_in_body (line 125) | def translate_in_body(message, "edit_room") do
    method translate_in_body (line 130) | def translate_in_body(message, "ask_to_speak") do
    method translate_in_body (line 134) | def translate_in_body(message, "follow") do
    method translate_in_body (line 140) | def translate_in_body(message, "get_follow_list") do
    method translate_in_body (line 150) | def translate_in_body(message, "speaking_change") do
    method translate_in_body (line 155) | def translate_in_body(message, "mute") do
    method translate_in_body (line 160) | def translate_in_body(message, "deafen") do
    method translate_in_body (line 165) | def translate_in_body(message, "get_my_scheduled_rooms_about_to_start"...
    method translate_in_body (line 171) | def translate_in_body(message, "get_scheduled_rooms") do
    method translate_in_body (line 179) | def translate_in_body(message, "delete_scheduled_room") do
    method translate_in_body (line 184) | def translate_in_body(message, "edit_scheduled_room") do
    method translate_in_body (line 196) | def translate_in_body(message, _op), do: message
    method add_in_ref (line 206) | def add_in_ref(message, _op), do: message
    method add_version (line 208) | def add_version(message), do: Map.put(message, "version", ~v(0.1.0))
    method translate_outbound (line 213) | def translate_outbound(message, original) do
    method add_out_ref (line 220) | defp add_out_ref(message, %{ref: ref}), do: Map.put(message, :fetchId,...
    method add_out_ref (line 221) | defp add_out_ref(message, _), do: message
    method add_out_err (line 223) | defp add_out_err(message, %{e: err}), do: Map.put(message, :e, err)
    method add_out_err (line 224) | defp add_out_err(message, _), do: message
    method translate_out_body (line 226) | def translate_out_body(message, "auth:request") do
    method translate_out_body (line 230) | def translate_out_body(message, "user:ban") do
    method translate_out_body (line 234) | def translate_out_body(message, "room:create") do
    method translate_out_body (line 238) | def translate_out_body(message = %{e: errors}, "user:update") do
    method translate_out_body (line 242) | def translate_out_body(message, "user:get_relationship") do
    method translate_out_body (line 254) | def translate_out_body(message, "room:create_scheduled") do
    method translate_out_body (line 258) | def translate_out_body(message, "room:update") do
    method translate_out_body (line 262) | def translate_out_body(message, "room:get_invite_list") do
    method translate_out_body (line 267) | def translate_out_body(message, "user:get_following") do
    method translate_out_body (line 272) | def translate_out_body(message, "user:get_followers") do
    method translate_out_body (line 277) | def translate_out_body(message, "room:leave") do
    method translate_out_body (line 281) | def translate_out_body(message, "room:get_scheduled") do
    method translate_out_body (line 289) | def translate_out_body(message, "chat:send") do
    method translate_out_body (line 311) | def translate_out_body(message, "chat:delete") do
    method translate_out_body (line 318) | def translate_out_body(message, _), do: message

FILE: kousa/lib/kousa.ex
  class Kousa (line 1) | defmodule Kousa
    method start (line 4) | def start(_type, _args) do
    method dispatch (line 49) | defp dispatch do
    method start_rooms (line 59) | defp start_rooms() do
    method start_rabbits (line 73) | defp start_rabbits() do

FILE: kousa/lib/kousa/access_token.ex
  class Kousa.AccessToken (line 1) | defmodule Kousa.AccessToken
    method __default_signer__ (line 2) | def __default_signer__,
    method token_config (line 8) | def token_config, do: default_claims(default_exp: 60 * 60)

FILE: kousa/lib/kousa/auth.ex
  class Kousa.Auth (line 1) | defmodule Kousa.Auth
    method authenticate (line 8) | def authenticate(request, ip) do
    method do_auth (line 22) | defp do_auth(user, tokens, request, ip) do

FILE: kousa/lib/kousa/chat.ex
  class Kousa.Chat (line 1) | defmodule Kousa.Chat
    method send_msg (line 7) | def send_msg(payload) do
    method ban_user (line 22) | def ban_user(user_id, user_id_to_ban) do
    method unban_user (line 41) | def unban_user(user_id, user_id_to_unban) do
    method delete_msg (line 54) | def delete_msg(deletion, opts) do

FILE: kousa/lib/kousa/discord.ex
  class Kousa.Discord (line 1) | defmodule Kousa.Discord
    method get_avatar_url (line 2) | def get_avatar_url(user) do

FILE: kousa/lib/kousa/follow_logic.ex
  class Kousa.Follow (line 1) | defmodule Kousa.Follow
    method get_follow_list (line 8) | def get_follow_list(user_id, user_id_to_get_list_for, get_following_li...
    method get_follow_list_by_username (line 17) | def get_follow_list_by_username(user_id, username, get_following_list,...
    method follow (line 35) | def follow(user_id, user_you_want_to_follow_id, should_follow) do
    method sync_notify_followers_you_created_a_room (line 50) | def sync_notify_followers_you_created_a_room(user_id, room) do
    method notify_followers_you_created_a_room (line 77) | def notify_followers_you_created_a_room(user_id, room) do

FILE: kousa/lib/kousa/github.ex
  class Kousa.Github (line 1) | defmodule Kousa.Github
    method pick_primary_email (line 2) | def pick_primary_email([]) do
    method pick_primary_email (line 6) | def pick_primary_email(emails) do

FILE: kousa/lib/kousa/metrics/prometheus.ex
  class Kousa.Metric.PipelineInstrumenter (line 1) | defmodule Kousa.Metric.PipelineInstrumenter
    method label_value (line 4) | def label_value(:request_path, conn) do
  class Kousa.Metric.PrometheusExporter (line 9) | defmodule Kousa.Metric.PrometheusExporter
  class Kousa.Metric.UserSessions (line 13) | defmodule Kousa.Metric.UserSessions
    method setup (line 16) | def setup do
    method set (line 23) | def set(n) do

FILE: kousa/lib/kousa/refresh_token.ex
  class Kousa.RefreshToken (line 1) | defmodule Kousa.RefreshToken
    method __default_signer__ (line 2) | def __default_signer__,
    method token_config (line 8) | def token_config, do: default_claims(default_exp: 60 * 60 * 24 * 30)

FILE: kousa/lib/kousa/release.ex
  class Kousa.Release (line 1) | defmodule Kousa.Release
    method migrate (line 4) | def migrate do
    method rollback (line 12) | def rollback(repo, version) do
    method repos (line 17) | defp repos do
    method load_app (line 21) | defp load_app do

FILE: kousa/lib/kousa/room.ex
  class Kousa.Room (line 1) | defmodule Kousa.Room
    method set_auto_speaker (line 13) | def set_auto_speaker(user_id, value) do
    method make_room_public (line 20) | def make_room_public(user_id, new_name) do
    method make_room_private (line 35) | def make_room_private(user_id, new_name) do
    method invite_to_room (line 49) | def invite_to_room(user_id, user_id_to_invite) do
    method internal_kick_from_room (line 73) | defp internal_kick_from_room(user_id_to_kick, room_id) do
    method block_from_room (line 99) | def block_from_room(user_id, user_id_to_block_from_room, should_ban_ip...
    method set_auth (line 127) | def set_auth(user_id, auth, opts) do
    method set_owner (line 148) | def set_owner(room_id, user_id, setter_id) do
    method set_mod (line 167) | defp set_mod(room_id, user_id, setter_id) do
    method set_user (line 192) | defp set_user(room_id, user_id, user_id) do
    method set_user (line 211) | defp set_user(room_id, user_id, setter_id) do
    method set_role (line 239) | def set_role(user_id, role, opts) do
    method set_listener (line 260) | defp set_listener(nil, _, _), do: :noop
    method set_listener (line 262) | defp set_listener(room_id, user_id, user_id) do
    method set_listener (line 266) | defp set_listener(room_id, user_id, setter_id) do
    method internal_set_listener (line 277) | defp internal_set_listener(user_id, room_id) do
    method set_speaker (line 285) | defp set_speaker(nil, _, _), do: :noop
    method set_speaker (line 287) | defp set_speaker(room_id, user_id, setter_id) do
    method internal_set_speaker (line 308) | defp internal_set_speaker(user_id, room_id) do
    method set_raised_hand (line 330) | defp set_raised_hand(room_id, user_id, setter_id) do
    method update (line 355) | def update(user_id, data) do
    method join_vc_room (line 378) | def join_vc_room(user_id, room, speaker? \\ nil) do
    method create_room (line 408) | def create_room(
    method join_room (line 482) | def join_room(user_id, room_id) do
    method leave_room (line 533) | def leave_room(user_id, current_room_id \\ nil) do

FILE: kousa/lib/kousa/room_block.ex
  class Kousa.RoomBlock (line 1) | defmodule Kousa.RoomBlock
    method unban (line 6) | def unban(user_id, user_id_to_unban) do
    method get_blocked_users (line 17) | def get_blocked_users(user_id, offset) do

FILE: kousa/lib/kousa/scheduled_room.ex
  class Kousa.ScheduledRoom (line 1) | defmodule Kousa.ScheduledRoom
    method create_room_from_scheduled_room (line 6) | def create_room_from_scheduled_room(user_id, scheduled_room_id, name, ...
    method delete (line 17) | def delete(user_id, id) do
    method edit (line 21) | def edit(user_id, id, data) do
    method schedule (line 32) | def schedule(user_id, data) do
    method get_scheduled_rooms (line 46) | def get_scheduled_rooms(user_id, get_only_my_scheduled_rooms, cursor) do
    method get_my_scheduled_rooms_about_to_start (line 50) | def get_my_scheduled_rooms_about_to_start(user_id) do
    method get_my_scheduled_room (line 54) | def get_my_scheduled_room(user_id) do

FILE: kousa/lib/kousa/user.ex
  class Kousa.User (line 1) | defmodule Kousa.User
    method delete (line 6) | def delete(user_id) do
    method revoke_api_key (line 11) | def revoke_api_key(user_id, bot_id) do
    method update_with (line 31) | def update_with(changeset = %Ecto.Changeset{}) do
    method ban (line 65) | def ban(user_id_to_ban, reason_for_ban, opts) do
    method admin_update_with (line 79) | def admin_update_with(changeset, admin) do

FILE: kousa/lib/kousa/user_block.ex
  class Kousa.UserBlock (line 1) | defmodule Kousa.UserBlock
    method block (line 5) | def block(user_id, user_id_to_block) do

FILE: kousa/lib/kousa/utils/errors.ex
  class Kousa.Utils.Errors (line 1) | defmodule Kousa.Utils.Errors
    method changeset_errors (line 3) | def changeset_errors(%{errors: errors}) do
    method changeset_to_first_err_message (line 7) | def changeset_to_first_err_message(%{errors: [{_, {message, values}}]}...
    method changeset_to_first_err_message (line 13) | def changeset_to_first_err_message(changeset) do
    method changeset_to_first_err_message_with_field_name (line 17) | def changeset_to_first_err_message_with_field_name(%{errors: [{field, ...

FILE: kousa/lib/kousa/utils/pagination.ex
  class Kousa.Utils.Pagination (line 1) | defmodule Kousa.Utils.Pagination
    method items_to_offset_tuple (line 3) | def items_to_offset_tuple(items, offset, limit) do
    method items_to_cursor_tuple (line 8) | def items_to_cursor_tuple([], _limit, _item_to_cursor) do
    method items_to_cursor_tuple (line 13) | def items_to_cursor_tuple(items, limit, item_to_cursor) do

FILE: kousa/lib/kousa/utils/random.ex
  class Kousa.Utils.Random (line 1) | defmodule Kousa.Utils.Random
    method ascii_id (line 2) | def ascii_id() do
    method big_ascii_id (line 13) | def big_ascii_id() do

FILE: kousa/lib/kousa/utils/token_utils.ex
  class Kousa.Utils.TokenUtils (line 1) | defmodule Kousa.Utils.TokenUtils
    method tokens_to_user_id (line 26) | def tokens_to_user_id(access_token!, refresh_token) do
    method verify_refresh_token (line 39) | defp verify_refresh_token(refresh_token!) do
    method create_tokens (line 57) | def create_tokens(user) do

FILE: kousa/lib/kousa/utils/urls.ex
  class Kousa.Utils.Urls (line 1) | defmodule Kousa.Utils.Urls
    method next_site_url? (line 2) | def next_site_url?(url) do

FILE: kousa/lib/kousa/utils/uuid.ex
  class Kousa.Utils.UUID (line 1) | defmodule Kousa.Utils.UUID
    method normalize (line 28) | def normalize(nil), do: {:ok, nil}
    method normalize (line 30) | def normalize(_), do: :invalid
    method lower (line 33) | defp lower(char), do: char
    method normalize (line 38) | def normalize(changeset = %{valid?: false}, _), do: changeset
    method normalize (line 40) | def normalize(changeset, field) do

FILE: kousa/lib/kousa/utils/version.ex
  class Kousa.Utils.Version (line 1) | defmodule Kousa.Utils.Version
    method type (line 4) | def type, do: :string
    method cast (line 10) | def cast(v = %Version{}) do
    method cast (line 14) | def cast(_), do: :error
    method dump (line 16) | def dump(v = %Version{}) do
    method dump (line 20) | def dump(_), do: :error

FILE: kousa/lib/kousa/utils/voice_server_utils.ex
  class Kousa.Utils.VoiceServerUtils (line 1) | defmodule Kousa.Utils.VoiceServerUtils
    method idx_to_str_id (line 2) | def idx_to_str_id(n) do
    method get_next_voice_server_id (line 9) | def get_next_voice_server_id() do

FILE: kousa/lib/onion/bot_auth_rate_limit.ex
  class Onion.BotAuthRateLimit (line 1) | defmodule Onion.BotAuthRateLimit
    method start_link (line 3) | def start_link(_), do: GenServer.start_link(__MODULE__, nil, name: __M...
    method init (line 8) | def init(_) do
    method handle_info (line 18) | def handle_info(:sweep, state) do
    method schedule_sweep (line 24) | defp schedule_sweep do
    method get (line 28) | def get(key) do
    method set (line 38) | def set(key, value) do
    method delete (line 43) | def delete(key) do
    method reset (line 48) | def reset do
    method update_counter (line 56) | def update_counter(key, increment, default_value) do

FILE: kousa/lib/onion/chat.ex
  class Onion.Chat (line 1) | defmodule Onion.Chat
    method via (line 34) | defp via(user_id), do: {:via, Registry, {Onion.RoomChatRegistry, user_...
    method cast (line 36) | defp cast(user_id, params), do: GenServer.cast(via(user_id), params)
    method call (line 37) | defp call(user_id, params), do: GenServer.call(via(user_id), params)
    method start_link_supervised (line 39) | def start_link_supervised(initial_values) do
    method child_spec (line 64) | def child_spec(init), do: %{super(init) | id: Keyword.get(init, :room_...
    method count (line 66) | def count, do: Registry.count(Onion.RoomChatRegistry)
    method start_link (line 71) | def start_link(init) do
    method init (line 75) | def init(init) do
    method kill (line 81) | def kill(room_id) do
    method ws_fan (line 89) | def ws_fan(users, msg) do
    method set_room_creator_id (line 98) | def set_room_creator_id(room_id, id) do
    method set_room_creator_id_impl (line 102) | defp set_room_creator_id_impl(id, %__MODULE__{} = state) do
    method set_chat_throttle (line 106) | def set_chat_throttle(room_id, value) do
    method set_chat_throttle_impl (line 110) | defp set_chat_throttle_impl(value, %__MODULE__{} = state) do
    method banned? (line 114) | def banned?(room_id, who), do: call(room_id, {:banned?, who})
    method banned_impl (line 116) | defp banned_impl(who, _reply, state) do
    method user_banned? (line 120) | defp user_banned?(who, state) do
    method eligible_to_chat? (line 146) | defp eligible_to_chat?(
    method eligible_to_chat? (line 182) | defp eligible_to_chat?(_, state), do: {state, true}
    method unban_user (line 184) | def unban_user(room_id, user_id), do: cast(room_id, {:unban_user, user...
    method remove_user (line 186) | def remove_user(room_id, user_id), do: cast(room_id, {:remove_user, us...
    method remove_user_impl (line 188) | defp remove_user_impl(user_id, state) do
    method add_user (line 192) | def add_user(room_id, user_id), do: cast(room_id, {:add_user, user_id})
    method add_user_impl (line 194) | defp add_user_impl(user_id, state) do
    method ban_user (line 202) | def ban_user(room_id, user_id), do: cast(room_id, {:ban_user, user_id})
    method ban_user_impl (line 204) | defp ban_user_impl(user_id, state) do
    method unban_user_impl (line 215) | defp unban_user_impl(user_id, state) do
    method set_can_chat (line 226) | def set_can_chat(room_id, user_id), do: cast(room_id, {:set_can_chat, ...
    method set_can_chat_impl (line 228) | defp set_can_chat_impl(user_id, %__MODULE__{follow_at_map: follow_at_m...
    method set (line 232) | def set(room_id, key, value), do: cast(room_id, {:set, key, value})
    method set_impl (line 234) | defp set_impl(key, value, state) do
    method get (line 238) | def get(room_id, key), do: call(room_id, {:get, key})
    method get_impl (line 240) | defp get_impl(key, _reply, state) do
    method send_msg (line 248) | def send_msg(room_id, payload) do
    method send_msg_impl (line 252) | defp send_msg_impl(_, %__MODULE__{chat_mode: :disabled} = state) do
    method send_msg_impl (line 257) | defp send_msg_impl(payload = %{from: from}, %__MODULE__{} = state) do
    method should_throttle? (line 286) | defp should_throttle?(_, _), do: false
    method dispatch_message (line 288) | defp dispatch_message(payload, state) do
    method delete_message (line 322) | def delete_message(room_id, deletion = %Delete{}) do
    method delete_message_impl (line 326) | defp delete_message_impl(deletion, state) do
    method handle_call (line 338) | def handle_call({:banned?, who}, reply, state), do: banned_impl(who, r...
    method handle_call (line 340) | def handle_call({:get, key}, reply, state), do: get_impl(key, reply, s...
    method handle_cast (line 342) | def handle_cast({:set_can_chat, user_id}, state) do
    method handle_cast (line 346) | def handle_cast({:set_room_creator_id, id}, state) do
    method handle_cast (line 350) | def handle_cast({:set_chat_throttle, value}, state) do
    method handle_cast (line 354) | def handle_cast({:set, key, value}, state), do: set_impl(key, value, s...
    method handle_cast (line 356) | def handle_cast({:unban_user, user_id}, state), do: unban_user_impl(us...
    method handle_cast (line 358) | def handle_cast({:remove_user, user_id}, state), do: remove_user_impl(...
    method handle_cast (line 360) | def handle_cast({:add_user, user_id}, state), do: add_user_impl(user_i...
    method handle_cast (line 362) | def handle_cast({:send_msg, message}, state), do: send_msg_impl(messag...
    method handle_cast (line 364) | def handle_cast({:delete_message, payload}, state), do: delete_message...
    method handle_cast (line 366) | def handle_cast({:ban_user, user_id}, state), do: ban_user_impl(user_i...

FILE: kousa/lib/onion/pub_sub.ex
  class Onion.PubSub (line 1) | defmodule Onion.PubSub

FILE: kousa/lib/onion/room_session.ex
  class Onion.RoomSession (line 1) | defmodule Onion.RoomSession
    method via (line 32) | defp via(user_id), do: {:via, Registry, {Onion.RoomSessionRegistry, us...
    method cast (line 34) | defp cast(user_id, params), do: GenServer.cast(via(user_id), params)
    method call (line 35) | defp call(user_id, params), do: GenServer.call(via(user_id), params)
    method start_supervised (line 37) | def start_supervised(initial_values) do
    method child_spec (line 49) | def child_spec(init), do: %{super(init) | id: Keyword.get(init, :room_...
    method count (line 51) | def count, do: Registry.count(Onion.RoomSessionRegistry)
    method lookup (line 52) | def lookup(room_id), do: Registry.lookup(Onion.RoomSessionRegistry, ro...
    method start_link (line 57) | def start_link(init) do
    method init (line 61) | def init(init) do
    method ws_fan (line 73) | def ws_fan(users, msg) do
    method get (line 79) | def get(room_id, key), do: call(room_id, {:get, key})
    method get_impl (line 81) | defp get_impl(key, _reply, state) do
    method get_maps (line 85) | def get_maps(room_id), do: call(room_id, :get_maps)
    method get_maps_impl (line 87) | defp get_maps_impl(_reply, state) do
    method set (line 91) | def set(user_id, key, value), do: cast(user_id, {:set, key, value})
    method set_impl (line 93) | defp set_impl(key, value, state) do
    method redeem_invite (line 97) | def redeem_invite(room_id, user_id), do: call(room_id, {:redeem_invite...
    method redeem_invite_impl (line 99) | defp redeem_invite_impl(user_id, _reply, state) do
    method speaking_change (line 105) | def speaking_change(room_id, user_id, value) do
    method set_room_creator_id (line 131) | def set_room_creator_id(room_id, id) do
    method set_room_creator_id_impl (line 135) | defp set_room_creator_id_impl(id, %State{} = state) do
    method set_auto_speaker_impl (line 144) | defp set_auto_speaker_impl(value, state) do
    method broadcast_ws (line 148) | def broadcast_ws(room_id, msg), do: cast(room_id, {:broadcast_ws, msg})
    method broadcast_ws_impl (line 150) | defp broadcast_ws_impl(msg, state) do
    method create_invite (line 155) | def create_invite(room_id, user_id, user_info) do
    method create_invite_impl (line 159) | defp create_invite_impl(user_id, user_info, state) do
    method remove_speaker (line 180) | def remove_speaker(room_id, user_id), do: cast(room_id, {:remove_speak...
    method remove_speaker_impl (line 182) | defp remove_speaker_impl(user_id, state) do
    method add_speaker_impl (line 211) | def add_speaker_impl(user_id, muted?, deafened?, state) do
    method join_room (line 242) | def join_room(room_id, user_id, mute, deaf, opts \\ []) do
    method join_room_impl (line 246) | defp join_room_impl(user_id, mute, deaf, opts, state) do
    method mute (line 289) | def mute(room_id, user_id, value), do: cast(room_id, {:mute, user_id, ...
    method mute_impl (line 291) | defp mute_impl(user_id, value, state) do
    method deafen (line 315) | def deafen(room_id, user_id, value), do: cast(room_id, {:deafen, user_...
    method deafen_impl (line 317) | defp deafen_impl(user_id, value, state) do
    method destroy (line 341) | def destroy(room_id, user_id), do: cast(room_id, {:destroy, user_id})
    method destroy_impl (line 343) | defp destroy_impl(user_id, state) do
    method kick_from_room (line 354) | def kick_from_room(room_id, user_id), do: cast(room_id, {:kick_from_ro...
    method kick_from_room_impl (line 356) | defp kick_from_room_impl(user_id, state) do
    method leave_room (line 381) | def leave_room(room_id, user_id), do: cast(room_id, {:leave_room, user...
    method leave_room_impl (line 383) | defp leave_room_impl(user_id, state) do
    method handle_call (line 419) | def handle_call({:get, key}, reply, state), do: get_impl(key, reply, s...
    method handle_call (line 421) | def handle_call(:get_maps, reply, state), do: get_maps_impl(reply, state)
    method handle_call (line 423) | def handle_call({:redeem_invite, user_id}, reply, state) do
    method handle_cast (line 427) | def handle_cast({:set, key, value}, state), do: set_impl(key, value, s...
    method handle_cast (line 429) | def handle_cast({:kick_from_room, user_id}, state) do
    method handle_cast (line 433) | def handle_cast({:speaking_change, user_id, value}, state) do
    method handle_cast (line 437) | def handle_cast({:set_room_creator_id, id}, state) do
    method handle_cast (line 441) | def handle_cast({:set_auto_speaker, value}, state) do
    method handle_cast (line 445) | def handle_cast({:broadcast_ws, msg}, state) do
    method handle_cast (line 449) | def handle_cast({:create_invite, user_id, user_info}, state) do
    method handle_cast (line 453) | def handle_cast({:remove_speaker, user_id}, state) do
    method handle_cast (line 457) | def handle_cast({:add_speaker, user_id, muted?, deafened?}, state) do
    method handle_cast (line 461) | def handle_cast({:join_room, user_id, mute, deaf, opts}, state) do
    method handle_cast (line 465) | def handle_cast({:mute, user_id, value}, state) do
    method handle_cast (line 469) | def handle_cast({:deafen, user_id, value}, state) do
    method handle_cast (line 473) | def handle_cast({:destroy, user_id}, state) do
    method handle_cast (line 477) | def handle_cast({:leave_room, user_id}, state) do
  class State (line 5) | defmodule State

FILE: kousa/lib/onion/stats_cache.ex
  class Onion.StatsCache (line 1) | defmodule Onion.StatsCache
    method start_link (line 3) | def start_link(_), do: GenServer.start_link(__MODULE__, nil, name: __M...
    method init (line 6) | def init(_) do
    method get (line 15) | def get(key) do
    method set (line 25) | def set(key, value) do
    method delete (line 30) | def delete(key) do
    method reset (line 35) | def reset do
    method update_counter (line 43) | def update_counter(key, increment) do

FILE: kousa/lib/onion/supervisors/room_chat.ex
  class Onion.Supervisors.Chat (line 1) | defmodule Onion.Supervisors.Chat
    method start_link (line 4) | def start_link(init_arg) do
    method init (line 9) | def init(_init_arg) do

FILE: kousa/lib/onion/supervisors/room_session.ex
  class Onion.Supervisors.RoomSession (line 1) | defmodule Onion.Supervisors.RoomSession
    method start_link (line 4) | def start_link(init_arg) do
    method init (line 9) | def init(_init_arg) do

FILE: kousa/lib/onion/supervisors/user_session.ex
  class Onion.Supervisors.UserSession (line 1) | defmodule Onion.Supervisors.UserSession
    method start_link (line 4) | def start_link(init_arg) do
    method init (line 9) | def init(_init_arg) do

FILE: kousa/lib/onion/supervisors/voice_online_rabbit.ex
  class Onion.Supervisors.VoiceOnlineRabbit (line 1) | defmodule Onion.Supervisors.VoiceOnlineRabbit
    method start_link (line 4) | def start_link(init_arg) do
    method init (line 9) | def init(_init_arg) do

FILE: kousa/lib/onion/supervisors/voice_rabbit.ex
  class Onion.Supervisors.VoiceRabbit (line 1) | defmodule Onion.Supervisors.VoiceRabbit
    method start_link (line 4) | def start_link(init_arg) do
    method init (line 9) | def init(_init_arg) do

FILE: kousa/lib/onion/telemetry.ex
  class Onion.Telemetry (line 1) | defmodule Onion.Telemetry
    method start_link (line 4) | def start_link(_) do
    method init (line 8) | def init(_opts) do
    method handle_info (line 13) | def handle_info(:collect_metrics, state) do

FILE: kousa/lib/onion/user_session.ex
  class Onion.UserSession (line 1) | defmodule Onion.UserSession
    method via (line 37) | defp via(user_id), do: {:via, Registry, {Onion.UserSessionRegistry, us...
    method cast (line 39) | defp cast(user_id, params), do: GenServer.cast(via(user_id), params)
    method call (line 40) | defp call(user_id, params), do: GenServer.call(via(user_id), params)
    method start_supervised (line 42) | def start_supervised(initial_values) do
    method child_spec (line 54) | def child_spec(init), do: %{super(init) | id: Keyword.get(init, :user_...
    method count (line 56) | def count, do: Registry.count(Onion.UserSessionRegistry)
    method lookup (line 58) | def lookup(user_id), do: Registry.lookup(Onion.UserSessionRegistry, us...
    method start_link (line 63) | def start_link(init) do
    method init (line 67) | def init(init) do
    method set (line 77) | def set(user_id, key, value), do: cast(user_id, {:set, key, value})
    method set_impl (line 79) | defp set_impl(key, value, state) do
    method send_ws (line 83) | def send_ws(user_id, platform, msg), do: cast(user_id, {:send_ws, plat...
    method send_ws_impl (line 85) | defp send_ws_impl(_platform, msg, state = %{pid: pid}) do
    method set_mute_impl (line 94) | defp set_mute_impl(value, state = %{current_room_id: current_room_id}) do
    method set_deafen_impl (line 105) | defp set_deafen_impl(value, state = %{current_room_id: current_room_id...
    method new_tokens (line 113) | def new_tokens(user_id, tokens), do: cast(user_id, {:new_tokens, tokens})
    method new_tokens_impl (line 115) | defp new_tokens_impl(tokens, state = %{pid: pid}) do
    method set_state (line 121) | def set_state(user_id, info), do: cast(user_id, {:set_state, info})
    method set_state_impl (line 123) | defp set_state_impl(info, state) do
    method set_current_room_id (line 127) | def set_current_room_id(user_id, current_room_id) do
    method get_info_for_msg (line 131) | def get_info_for_msg(user_id), do: call(user_id, :get_info_for_msg)
    method get_info_for_msg_impl (line 133) | defp get_info_for_msg_impl(_reply, state) do
    method get_current_room_id (line 137) | def get_current_room_id(user_id) do
    method get (line 141) | def get(user_id, key), do: call(user_id, {:get, key})
    method get_impl (line 143) | defp get_impl(key, _reply, state) do
    method set_active_ws (line 149) | def set_active_ws(user_id, pid), do: call(user_id, {:set_active_ws, pid})
    method set_active_ws (line 151) | defp set_active_ws(pid, _reply, state) do
    method force_reconnects (line 165) | def force_reconnects(rabbit_id) do
    method reconnect (line 171) | def reconnect(user_pid, rabbit_id), do: GenServer.cast(user_pid, {:rec...
    method reconnect_impl (line 173) | defp reconnect_impl(voice_server_id, state) do
    method handle_disconnect (line 192) | defp handle_disconnect(pid, state = %{pid: pid}) do
    method handle_disconnect (line 202) | defp handle_disconnect(_, state), do: {:noreply, state}
    method handle_cast (line 207) | def handle_cast({:set, key, value}, state), do: set_impl(key, value, s...
    method handle_cast (line 209) | def handle_cast({:send_ws, platform, msg}, state),
    method handle_cast (line 212) | def handle_cast({:reconnect, voice_server_id}, state),
    method handle_cast (line 215) | def handle_cast({:set_mute, value}, state), do: set_mute_impl(value, s...
    method handle_cast (line 216) | def handle_cast({:set_deafen, value}, state), do: set_deafen_impl(valu...
    method handle_cast (line 217) | def handle_cast({:new_tokens, tokens}, state), do: new_tokens_impl(tok...
    method handle_cast (line 218) | def handle_cast({:set_state, info}, state), do: set_state_impl(info, s...
    method handle_call (line 220) | def handle_call(:get_info_for_msg, reply, state), do: get_info_for_msg...
    method handle_call (line 221) | def handle_call({:get, key}, reply, state), do: get_impl(key, reply, s...
    method handle_call (line 222) | def handle_call({:set_active_ws, pid}, reply, state), do: set_active_w...
    method handle_info (line 224) | def handle_info({:DOWN, _ref, :process, pid, _reason}, state), do: han...
  class State (line 6) | defmodule State

FILE: kousa/lib/onion/voice_online_rabbit.ex
  class Onion.VoiceOnlineRabbit (line 2) | defmodule Onion.VoiceOnlineRabbit
    method start_supervised (line 15) | def start_supervised(voice_id) do
    method start_link (line 22) | def start_link(voice_id) do
    method via (line 30) | defp via(voice_id), do: {:via, Registry, {Onion.VoiceOnlineRabbitRegis...
    method init (line 36) | def init(voice_id) do
    method handle_info (line 52) | def handle_info({:basic_consume_ok, %{consumer_tag: _consumer_tag}}, s...
    method handle_info (line 57) | def handle_info({:basic_cancel, %{consumer_tag: _consumer_tag}}, state...
    method handle_info (line 62) | def handle_info({:basic_cancel_ok, %{consumer_tag: _consumer_tag}}, st...
    method handle_info (line 66) | def handle_info(
    method setup_queue (line 83) | defp setup_queue(id, chan) do
  class State (line 6) | defmodule State

FILE: kousa/lib/onion/voice_rabbit.ex
  class Onion.VoiceRabbit (line 1) | defmodule Onion.VoiceRabbit
    method start_supervised (line 14) | def start_supervised(voice_id) do
    method start_link (line 21) | def start_link(voice_id) do
    method via (line 29) | defp via(voice_id), do: {:via, Registry, {Onion.VoiceRabbitRegistry, v...
    method init (line 36) | def init(voice_id) do
    method send (line 50) | def send(id, msg) do
    method handle_cast (line 54) | def handle_cast({:send, msg}, %State{chan: chan, id: id} = state) do
    method handle_info (line 59) | def handle_info({:basic_consume_ok, %{consumer_tag: _consumer_tag}}, s...
    method handle_info (line 64) | def handle_info({:basic_cancel, %{consumer_tag: _consumer_tag}}, state...
    method handle_info (line 69) | def handle_info({:basic_cancel_ok, %{consumer_tag: _consumer_tag}}, st...
    method handle_info (line 73) | def handle_info(
    method setup_queue (line 95) | defp setup_queue(id, chan) do
  class State (line 5) | defmodule State

FILE: kousa/mix.exs
  class Kousa.MixProject (line 1) | defmodule Kousa.MixProject
    method project (line 4) | def project do
    method application (line 21) | def application do
    method deps (line 35) | defp deps do
    method elixirc_paths (line 71) | defp elixirc_paths(:test), do: ["lib", "test/_support"]
    method elixirc_paths (line 72) | defp elixirc_paths(_), do: ["lib"]
    method aliases (line 74) | defp aliases do

FILE: kousa/priv/repo/migrations/20210124203315_most_tables.exs
  class Beef.Repo.Migrations.MostTables (line 1) | defmodule Beef.Repo.Migrations.MostTables
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210125155346_more_fields.exs
  class Beef.Repo.Migrations.MoreFields (line 1) | defmodule Beef.Repo.Migrations.MoreFields
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210202143344_has_logged_in.exs
  class Beef.Repo.Migrations.HasLoggedIn (line 1) | defmodule Beef.Repo.Migrations.HasLoggedIn
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210202162325_default_timestamps.exs
  class Beef.Repo.Migrations.DefaultTimestamps (line 1) | defmodule Beef.Repo.Migrations.DefaultTimestamps
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210210005241_email.exs
  class Beef.Repo.Migrations.Email (line 1) | defmodule Beef.Repo.Migrations.Email
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210210012609_access_token.exs
  class Beef.Repo.Migrations.AccessToken (line 1) | defmodule Beef.Repo.Migrations.AccessToken
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210212141759_bans.exs
  class Beef.Repo.Migrations.Bans (line 1) | defmodule Beef.Repo.Migrations.Bans
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210214140430_twitter_id.exs
  class Beef.Repo.Migrations.TwitterId (line 1) | defmodule Beef.Repo.Migrations.TwitterId
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210214172930_github_id_nullable.exs
  class Beef.Repo.Migrations.GithubIdNullable (line 1) | defmodule Beef.Repo.Migrations.GithubIdNullable
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210219173153_case_insensitive_unique_username_index.exs
  class Beef.Repo.Migrations.CaseInsensitiveUniqueUsernameIndex (line 1) | defmodule Beef.Repo.Migrations.CaseInsensitiveUniqueUsernameIndex
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210221041850_room_permissions.exs
  class Beef.Repo.Migrations.RoomPermissions (line 1) | defmodule Beef.Repo.Migrations.RoomPermissions
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210221233129_voice_server_id.exs
  class Beef.Repo.Migrations.VoiceServerId (line 1) | defmodule Beef.Repo.Migrations.VoiceServerId
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210301151808_use_utc_datetime_usec.exs
  class Beef.Repo.Migrations.UseUtcDatetimeUsec (line 1) | defmodule Beef.Repo.Migrations.UseUtcDatetimeUsec
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210301162635_last_online_utc_datetime_usec.exs
  class Beef.Repo.Migrations.LastOnlineUtcDatetimeUsec (line 1) | defmodule Beef.Repo.Migrations.LastOnlineUtcDatetimeUsec
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210301200955_scheduled_room.exs
  class Beef.Repo.Migrations.ScheduledRoom (line 1) | defmodule Beef.Repo.Migrations.ScheduledRoom
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210303204515_room_description.exs
  class Beef.Repo.Migrations.RoomDescription (line 1) | defmodule Beef.Repo.Migrations.RoomDescription
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210304004945_set_timezone_for_now.exs
  class Beef.Repo.Migrations.SetTimezoneForNow (line 1) | defmodule Beef.Repo.Migrations.SetTimezoneForNow
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210305031538_scheduled_room_started.exs
  class Beef.Repo.Migrations.ScheduledRoomStarted (line 1) | defmodule Beef.Repo.Migrations.ScheduledRoomStarted
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210321141614_discord_login.exs
  class Beef.Repo.Migrations.DiscordLogin (line 1) | defmodule Beef.Repo.Migrations.DiscordLogin
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210424191849_banner_url.exs
  class Beef.Repo.Migrations.BannerUrl (line 1) | defmodule Beef.Repo.Migrations.BannerUrl
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210425000426_user_bot_api_key.exs
  class Beef.Repo.Migrations.UserBotApiKey (line 1) | defmodule Beef.Repo.Migrations.UserBotApiKey
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210427180800_user_ip.exs
  class Beef.Repo.Migrations.UserIp (line 1) | defmodule Beef.Repo.Migrations.UserIp
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210427192138_room_ban_ip.exs
  class Beef.Repo.Migrations.RoomBanIp (line 1) | defmodule Beef.Repo.Migrations.RoomBanIp
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210501201857_emails_are_no_longer_unique.exs
  class Beef.Repo.Migrations.EmailsAreNoLongerUnique (line 1) | defmodule Beef.Repo.Migrations.EmailsAreNoLongerUnique
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210504210047_whisper_privacy_setting.exs
  class Beef.Repo.Migrations.WhisperPrivacySetting (line 1) | defmodule Beef.Repo.Migrations.WhisperPrivacySetting
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210504225546_chat_mode.exs
  class Beef.Repo.Migrations.ChatMode (line 1) | defmodule Beef.Repo.Migrations.ChatMode
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210506000509_chat_throttle.exs
  class Beef.Repo.Migrations.ChatThrottle (line 1) | defmodule Beef.Repo.Migrations.ChatThrottle
    method change (line 4) | def change do

FILE: kousa/priv/repo/migrations/20210509055314_admin_update.exs
  class Beef.Repo.Migrations.AdminUpdate (line 1) | defmodule Beef.Repo.Migrations.AdminUpdate
    method change (line 4) | def change do

FILE: kousa/test/_support/deprecations.ex
  class KousaTest.Support.Deprecations (line 1) | defmodule KousaTest.Support.Deprecations
    method capture_deprecation (line 6) | def capture_deprecation(fun) do

FILE: kousa/test/_support/ecto_sandbox.ex
  class KousaTest.Support.EctoSandbox (line 1) | defmodule KousaTest.Support.EctoSandbox

FILE: kousa/test/_support/factory.ex
  class KousaTest.Support.Factory (line 1) | defmodule KousaTest.Support.Factory
    method create (line 16) | def create(struct, data \\ [])
    method create (line 18) | def create(User, data) do
    method create (line 43) | def create(Room, data) do
    method create (line 69) | def create(ScheduledRoom, data) do

FILE: kousa/test/_support/http_request.ex
  class BrothTest.HttpRequest (line 1) | defmodule BrothTest.HttpRequest
    method post (line 2) | def post(path, body, opts \\ []) do

FILE: kousa/test/_support/message.ex
  class BrothTest.Support.Message (line 1) | defmodule BrothTest.Support.Message
    method validate (line 9) | def validate(message, state \\ @init) do

FILE: kousa/test/_support/ws_client.ex
  class BrothTest.WsClient (line 1) | defmodule BrothTest.WsClient
    method child_spec (line 6) | def child_spec(info) do
    method start_link (line 13) | def start_link(_opts) do
    method send_call (line 32) | def send_call(client_ws, op, payload) do
    method send_call_legacy (line 43) | def send_call_legacy(client_ws, op, payload) do
    method do_call (line 59) | def do_call(ws, op, payload) do
    method do_call_legacy (line 72) | def do_call_legacy(ws, op, payload) do
    method send_msg (line 84) | def send_msg(client_ws, op, payload),
    method send_msg_legacy (line 87) | def send_msg_legacy(client_ws, op, payload),
    method send_msg_impl (line 90) | defp send_msg_impl(map, test_pid) do
    method forward_frames (line 94) | def forward_frames(client_ws), do: WebSockex.cast(client_ws, {:forward...
    method forward_frames_impl (line 95) | defp forward_frames_impl(test_pid, _state), do: {:ok, test_pid}
    method handle_frame (line 235) | def handle_frame({type, data}, test_pid) do
    method handle_cast (line 241) | def handle_cast({:send, map}, test_pid), do: send_msg_impl(map, test_pid)
    method handle_cast (line 242) | def handle_cast({:forward_frames, test_pid}, state), do: forward_frame...
  class BrothTest.WsClientFactory (line 245) | defmodule BrothTest.WsClientFactory
    method create_client_for (line 254) | def create_client_for(user = %User{}, opts \\ []) do

FILE: kousa/test/ad_hoc_user_test.exs
  class KousaTest.AdHocUserTest (line 1) | defmodule KousaTest.AdHocUserTest

FILE: kousa/test/beef/follow_test.exs
  class Kousa.Beef.FollowTest (line 1) | defmodule Kousa.Beef.FollowTest

FILE: kousa/test/beef/room_test.exs
  class Kousa.Beef.RoomTest (line 1) | defmodule Kousa.Beef.RoomTest

FILE: kousa/test/beef/rooms_test.exs
  class Kousa.Beef.RoomsTest (line 1) | defmodule Kousa.Beef.RoomsTest

FILE: kousa/test/beef/scheduled_room_test.exs
  class Kousa.Beef.ScheduledRoomsTest (line 1) | defmodule Kousa.Beef.ScheduledRoomsTest
    method create_user (line 12) | defp create_user(_) do

FILE: kousa/test/beef/user_block_test.exs
  class Kousa.Beef.UserBlockTest (line 1) | defmodule Kousa.Beef.UserBlockTest

FILE: kousa/test/beef/user_blocks_test.exs
  class Kousa.Beef.UserBlocksTest (line 1) | defmodule Kousa.Beef.UserBlocksTest

FILE: kousa/test/beef/user_test.exs
  class Kousa.Beef.UserTest (line 1) | defmodule Kousa.Beef.UserTest
    method create_user (line 33) | defp create_user(_) do

FILE: kousa/test/beef/users_test.exs
  class Kousa.Beef.UsersTest (line 1) | defmodule Kousa.Beef.UsersTest

FILE: kousa/test/broth/_calls/create_room_from_scheduled_room_test.exs
  class BrothTest.CreateRoomFromScheduledRoomTest (line 1) | defmodule BrothTest.CreateRoomFromScheduledRoomTest

FILE: kousa/test/broth/_calls/create_room_test.exs
  class BrothTest.CreateRoomTest (line 1) | defmodule BrothTest.CreateRoomTest

FILE: kousa/test/broth/_calls/delete_scheduled_room_test.exs
  class BrothTest.DeleteScheduledRoomTest (line 1) | defmodule BrothTest.DeleteScheduledRoomTest

FILE: kousa/test/broth/_calls/edit_profile_test.exs
  class BrothTest.EditProfileTest (line 1) | defmodule BrothTest.EditProfileTest

FILE: kousa/test/broth/_calls/edit_room_test.exs
  class BrothTest.EditRoomTest (line 1) | defmodule BrothTest.EditRoomTest

FILE: kousa/test/broth/_calls/edit_scheduled_room_test.exs
  class BrothTest.EditScheduledRoomTest (line 1) | defmodule BrothTest.EditScheduledRoomTest

FILE: kousa/test/broth/_calls/fetch_follow_list_test.exs
  class BrothTest.FetchFollowListTest (line 1) | defmodule BrothTest.FetchFollowListTest

FILE: kousa/test/broth/_calls/follow_info_test.exs
  class BrothTest.FollowInfoTest (line 1) | defmodule BrothTest.FollowInfoTest

FILE: kousa/test/broth/_calls/get_blocked_from_room_users_test.exs
  class BrothTest.GetBlockedFromRoomUsersTest (line 1) | defmodule BrothTest.GetBlockedFromRoomUsersTest

FILE: kousa/test/broth/_calls/get_my_following_test.exs
  class BrothTest.GetMyFollowingTest (line 1) | defmodule BrothTest.GetMyFollowingTest

FILE: kousa/test/broth/_calls/get_my_scheduled_rooms_about_to_start_test.exs
  class BrothTest.GetMyScheduledRoomsAboutToStartTest (line 1) | defmodule BrothTest.GetMyScheduledRoomsAboutToStartTest

FILE: kousa/test/broth/_calls/get_scheduled_rooms_test.exs
  class BrothTest.GetScheduledRoomsTest (line 1) | defmodule BrothTest.GetScheduledRoomsTest

FILE: kousa/test/broth/_calls/get_top_public_rooms_test.exs
  class BrothTest.GetTopPublicRoomsTest (line 1) | defmodule BrothTest.GetTopPublicRoomsTest

FILE: kousa/test/broth/_calls/get_user_profile_test.exs
  class BrothTest.GetUserProfileTest (line 1) | defmodule BrothTest.GetUserProfileTest

FILE: kousa/test/broth/_calls/join_room_and_get_info_test.exs
  class BrothTest.JoinRoomAndGetInfoTest (line 1) | defmodule BrothTest.JoinRoomAndGetInfoTest

FILE: kousa/test/broth/_calls/schedule_room_test.exs
  class BrothTest.ScheduleRoomTest (line 1) | defmodule BrothTest.ScheduleRoomTest

FILE: kousa/test/broth/_calls/search_test.exs
  class BrothTest.SearchTest (line 1) | defmodule BrothTest.SearchTest

FILE: kousa/test/broth/_calls/unban_from_room_test.exs
  class BrothTest.UnbanFromRoomTest (line 1) | defmodule BrothTest.UnbanFromRoomTest

FILE: kousa/test/broth/_casts/add_speaker_test.exs
  class BrothTest.AddSpeakerTest (line 1) | defmodule BrothTest.AddSpeakerTest

FILE: kousa/test/broth/_casts/ask_to_speak_test.exs
  class BrothTest.AskToSpeakTest (line 1) | defmodule BrothTest.AskToSpeakTest

FILE: kousa/test/broth/_casts/auth_test.exs
  class BrothTest.AuthTest (line 1) | defmodule BrothTest.AuthTest

FILE: kousa/test/broth/_casts/ban_from_room_chat_test.exs
  class BrothTest.BanFromRoomChatTest (line 1) | defmodule BrothTest.BanFromRoomChatTest

FILE: kousa/test/broth/_casts/ban_test.exs
  class BrothTest.BanTest (line 1) | defmodule BrothTest.BanTest

FILE: kousa/test/broth/_casts/block_from_room_test.exs
  class BrothTest.BlockFromRoomTest (line 1) | defmodule BrothTest.BlockFromRoomTest

FILE: kousa/test/broth/_casts/change_mod_status_test.exs
  class BrothTest.ChangeModStatusTest (line 1) | defmodule BrothTest.ChangeModStatusTest

FILE: kousa/test/broth/_casts/change_room_creator_test.exs
  class BrothTest.ChangeRoomCreatorTest (line 1) | defmodule BrothTest.ChangeRoomCreatorTest

FILE: kousa/test/broth/_casts/delete_room_chat_message_test.exs
  class BrothTest.DeleteRoomChatMessageTest (line 1) | defmodule BrothTest.DeleteRoomChatMessageTest

FILE: kousa/test/broth/_casts/follow_test.exs
  class BrothTest.FollowTest (line 1) | defmodule BrothTest.FollowTest

FILE: kousa/test/broth/_casts/invite_to_room_test.exs
  class BrothTest.InviteToRoomTest (line 1) | defmodule BrothTest.InviteToRoomTest

FILE: kousa/test/broth/_casts/leave_room_test.exs
  class BrothTest.LeaveRoomTest (line 1) | defmodule BrothTest.LeaveRoomTest

FILE: kousa/test/broth/_casts/make_room_public_test.exs
  class BrothTest.MakeRoomPublicTest (line 1) | defmodule BrothTest.MakeRoomPublicTest

FILE: kousa/test/broth/_casts/mute_test.exs
  class BrothTest.MuteTest (line 1) | defmodule BrothTest.MuteTest

FILE: kousa/test/broth/_casts/send_room_chat_msg_test.exs
  class BrothTest.SendRoomChatMsgTest (line 1) | defmodule BrothTest.SendRoomChatMsgTest

FILE: kousa/test/broth/_casts/set_auto_speaker.exs
  class BrothTest.SetAutoSpeakerTest (line 1) | defmodule BrothTest.SetAutoSpeakerTest

FILE: kousa/test/broth/_casts/set_listener_test.exs
  class BrothTest.SetListenerTest (line 1) | defmodule BrothTest.SetListenerTest

FILE: kousa/test/broth/_casts/speaking_change_test.exs
  class BrothTest.SpeakingChangeTest (line 1) | defmodule BrothTest.SpeakingChangeTest

FILE: kousa/test/broth/_casts/unban_from_room_chat_test.exs
  class BrothTest.UnbanFromRoomChatTest (line 1) | defmodule BrothTest.UnbanFromRoomChatTest

FILE: kousa/test/broth/_message/auth/request_test.exs
  class BrothTest.Message.Auth.RequestTest (line 1) | defmodule BrothTest.Message.Auth.RequestTest

FILE: kousa/test/broth/_message/chat/ban_test.exs
  class BrothTest.Message.Chat.BanTest (line 1) | defmodule BrothTest.Message.Chat.BanTest

FILE: kousa/test/broth/_message/chat/delete_msg_test.exs
  class BrothTest.Message.Chat.DeleteTest (line 1) | defmodule BrothTest.Message.Chat.DeleteTest

FILE: kousa/test/broth/_message/chat/send_test.exs
  class BrothTest.Message.Chat.SendTest (line 1) | defmodule BrothTest.Message.Chat.SendTest

FILE: kousa/test/broth/_message/chat/unban_test.exs
  class BrothTest.Message.Chat.UnbanTest (line 1) | defmodule BrothTest.Message.Chat.UnbanTest

FILE: kousa/test/broth/_message/misc/search_test.exs
  class BrothTest.Message.Misc.SearchTest (line 1) | defmodule BrothTest.Message.Misc.SearchTest

FILE: kousa/test/broth/_message/room/ban_test.exs
  class BrothTest.Message.Room.BanTest (line 1) | defmodule BrothTest.Message.Room.BanTest

FILE: kousa/test/broth/_message/room/create_scheduled_test.exs
  class BrothTest.Message.Room.CreateScheduledTest (line 1) | defmodule BrothTest.Message.Room.CreateScheduledTest

FILE: kousa/test/broth/_message/room/create_test.exs
  class BrothTest.Message.Room.CreateTest (line 1) | defmodule BrothTest.Message.Room.CreateTest

FILE: kousa/test/broth/_message/room/deafen_test.exs
  class BrothTest.Message.Room.DeafenTest (line 1) | defmodule BrothTest.Message.Room.DeafenTest

FILE: kousa/test/broth/_message/room/delete_scheduled_test.exs
  class BrothTest.Message.Room.DeleteScheduledTest (line 1) | defmodule BrothTest.Message.Room.DeleteScheduledTest

FILE: kousa/test/broth/_message/room/get_banned_users_test.exs
  class BrothTest.Message.Room.GetBannedUsersTest (line 1) | defmodule BrothTest.Message.Room.GetBannedUsersTest
    method get_current_room_id (line 15) | def get_current_room_id(_), do: @room_id

FILE: kousa/test/broth/_message/room/get_info_test.exs
  class BrothTest.Message.Room.GetInfoTest (line 1) | defmodule BrothTest.Message.Room.GetInfoTest

FILE: kousa/test/broth/_message/room/get_invite_list_test.exs
  class BrothTest.Message.Room.GetInviteListTest (line 1) | defmodule BrothTest.Message.Room.GetInviteListTest

FILE: kousa/test/broth/_message/room/get_scheduled_test.exs
  class BrothTest.Message.Room.GetScheduledTest (line 1) | defmodule BrothTest.Message.Room.GetScheduledTest

FILE: kousa/test/broth/_message/room/get_top_test.exs
  class BrothTest.Message.Room.GetTopTest (line 1) | defmodule BrothTest.Message.Room.GetTopTest

FILE: kousa/test/broth/_message/room/invite_test.exs
  class BrothTest.Message.Room.InviteTest (line 1) | defmodule BrothTest.Message.Room.InviteTest

FILE: kousa/test/broth/_message/room/join_test.exs
  class BrothTest.Message.Room.JoinTest (line 1) | defmodule BrothTest.Message.Room.JoinTest

FILE: kousa/test/broth/_message/room/leave_test.exs
  class BrothTest.Message.Room.LeaveTest (line 1) | defmodule BrothTest.Message.Room.LeaveTest

FILE: kousa/test/broth/_message/room/mute_test.exs
  class BrothTest.Message.Room.MuteTest (line 1) | defmodule BrothTest.Message.Room.MuteTest

FILE: kousa/test/broth/_message/room/set_active_speaker_test.exs
  class BrothTest.Message.Room.SetActiveSpeakerTest (line 1) | defmodule BrothTest.Message.Room.SetActiveSpeakerTest

FILE: kousa/test/broth/_message/room/set_auth_test.exs
  class BrothTest.Message.Room.SetAuthTest (line 1) | defmodule BrothTest.Message.Room.SetAuthTest

FILE: kousa/test/broth/_message/room/set_role_test.exs
  class BrothTest.Message.Room.SetRoleTest (line 1) | defmodule BrothTest.Message.Room.SetRoleTest

FILE: kousa/test/broth/_message/room/unban_test.exs
  class BrothTest.Message.Room.UnbanTest (line 1) | defmodule BrothTest.Message.Room.UnbanTest

FILE: kousa/test/broth/_message/room/update_scheduled_test.exs
  class BrothTest.Message.Room.UpdateScheduledTest (line 1) | defmodule BrothTest.Message.Room.UpdateScheduledTest

FILE: kousa/test/broth/_message/room/update_test.exs
  class BrothTest.Message.Room.UpdateTest (line 1) | defmodule BrothTest.Message.Room.UpdateTest

FILE: kousa/test/broth/_message/user/admin_update_test.exs
  class BrothTest.Message.User.AdminUpdateTest (line 1) | defmodule BrothTest.Message.User.AdminUpdateTest

FILE: kousa/test/broth/_message/user/ban_test.exs
  class BrothTest.Message.User.BanTest (line 1) | defmodule BrothTest.Message.User.BanTest

FILE: kousa/test/broth/_message/user/block_test.exs
  class BrothTest.Message.User.BlockTest (line 1) | defmodule BrothTest.Message.User.BlockTest

FILE: kousa/test/broth/_message/user/create_bot_test.exs
  class BrothTest.Message.User.CreateBotTest (line 1) | defmodule BrothTest.Message.User.CreateBotTest

FILE: kousa/test/broth/_message/user/follow_test.exs
  class BrothTest.Message.User.FollowTest (line 1) | defmodule BrothTest.Message.User.FollowTest

FILE: kousa/test/broth/_message/user/get_bots_test.exs
  class BrothTest.Message.User.GetBotsTest (line 1) | defmodule BrothTest.Message.User.GetBotsTest

FILE: kousa/test/broth/_message/user/get_followers_test.exs
  class BrothTest.Message.User.GetFollowersTest (line 1) | defmodule BrothTest.Message.User.GetFollowersTest

FILE: kousa/test/broth/_message/user/get_following_test.exs
  class BrothTest.Message.User.GetFollowingTest (line 1) | defmodule BrothTest.Message.User.GetFollowingTest

FILE: kousa/test/broth/_message/user/get_info_test.exs
  class BrothTest.Message.User.GetInfoTest (line 1) | defmodule BrothTest.Message.User.GetInfoTest

FILE: kousa/test/broth/_message/user/get_relationship_test.exs
  class BrothTest.Message.User.GetRelationshipTest (line 1) | defmodule BrothTest.Message.User.GetRelationshipTest

FILE: kousa/test/broth/_message/user/revoke_api_key_test.exs
  class BrothTest.Message.User.RevokeApiKeyTest (line 1) | defmodule BrothTest.Message.User.RevokeApiKeyTest

FILE: kousa/test/broth/_message/user/unblock_test.exs
  class BrothTest.Message.User.UnblockTest (line 1) | defmodule BrothTest.Message.User.UnblockTest

FILE: kousa/test/broth/_message/user/unfollow_test.exs
  class BrothTest.Message.User.UnfollowTest (line 1) | defmodule BrothTest.Message.User.UnfollowTest

FILE: kousa/test/broth/_message/user/update_test.exs
  class BrothTest.Message.User.UpdateTest (line 1) | defmodule BrothTest.Message.User.UpdateTest

FILE: kousa/test/broth/_routes/bot_auth_test.exs
  class BrothTest.Routes.BotAuthTest (line 1) | defmodule BrothTest.Routes.BotAuthTest

FILE: kousa/test/broth/_types/chat_token.exs
  class BrothTest.Message.Types.ChatToken (line 1) | defmodule BrothTest.Message.Types.ChatToken
    method validate (line 7) | defp validate(map) do

FILE: kousa/test/broth/auth/request_test.exs
  class BrothTest.Auth.RequestTest (line 1) | defmodule BrothTest.Auth.RequestTest

FILE: kousa/test/broth/chat/ban_test.exs
  class BrothTest.Chat.BanTest (line 1) | defmodule BrothTest.Chat.BanTest

FILE: kousa/test/broth/chat/delete_test.exs
  class BrothTest.Chat.DeleteTest (line 1) | defmodule BrothTest.Chat.DeleteTest

FILE: kousa/test/broth/chat/send_test.exs
  class BrothTest.Chat.SendTest (line 1) | defmodule BrothTest.Chat.SendTest

FILE: kousa/test/broth/chat/unban_test.exs
  class BrothTest.Chat.UnbanTest (line 1) | defmodule BrothTest.Chat.UnbanTest

FILE: kousa/test/broth/message_test.exs
  class BrothTest.MessageTest (line 1) | defmodule BrothTest.MessageTest
    method validate (line 35) | defp validate(data) do
  class TestOperator (line 8) | defmodule TestOperator
    method changeset (line 19) | def changeset(changeset \\ %__MODULE__{}, data) do
    method execute (line 26) | def execute(_, state), do: {:reply, %__MODULE__{}, state}

FILE: kousa/test/broth/misc/search_test.exs
  class BrothTest.Misc.Search (line 1) | defmodule BrothTest.Misc.Search

FILE: kousa/test/broth/room/ban_test.exs
  class BrothTest.Room.BanTest (line 1) | defmodule BrothTest.Room.BanTest

FILE: kousa/test/broth/room/create_scheduled_test.exs
  class BrothTest.Room.CreateScheduledTest (line 1) | defmodule BrothTest.Room.CreateScheduledTest

FILE: kousa/test/broth/room/create_test.exs
  class BrothTest.Room.CreateTest (line 1) | defmodule BrothTest.Room.CreateTest

FILE: kousa/test/broth/room/deafen_test.exs
  class BrothTest.Room.DeafenTest (line 1) | defmodule BrothTest.Room.DeafenTest

FILE: kousa/test/broth/room/delete_scheduled_test.exs
  class BrothTest.Room.DeleteScheduledTest (line 1) | defmodule BrothTest.Room.DeleteScheduledTest

FILE: kousa/test/broth/room/get_banned_users_test.exs
  class BrothTest.Room.GetBannedUsersTest (line 1) | defmodule BrothTest.Room.GetBannedUsersTest

FILE: kousa/test/broth/room/get_info_test.exs
  class BrothTest.Room.GetInfoTest (line 1) | defmodule BrothTest.Room.GetInfoTest

FILE: kousa/test/broth/room/get_invite_list_test.exs
  class BrothTest.Room.GetInviteListTest (line 1) | defmodule BrothTest.Room.GetInviteListTest

FILE: kousa/test/broth/room/get_scheduled_test.exs
  class BrothTest.Room.GetScheduledTest (line 1) | defmodule BrothTest.Room.GetScheduledTest

FILE: kousa/test/broth/room/get_top_test.exs
  class BrothTest.Room.GetTopTest (line 1) | defmodule BrothTest.Room.GetTopTest

FILE: kousa/test/broth/room/invite_test.exs
  class BrothTest.Room.InviteTest (line 1) | defmodule BrothTest.Room.InviteTest

FILE: kousa/test/broth/room/join_test.exs
  class BrothTest.Room.JoinTest (line 1) | defmodule BrothTest.Room.JoinTest

FILE: kousa/test/broth/room/leave_test.exs
  class BrothTest.Room.LeaveTest (line 1) | defmodule BrothTest.Room.LeaveTest

FILE: kousa/test/broth/room/mute_test.exs
  class BrothTest.Room.MuteTest (line 1) | defmodule BrothTest.Room.MuteTest

FILE: kousa/test/broth/room/set_active_speaker_test.exs
  class BrothTest.Room.SetActiveSpeakerTest (line 1) | defmodule BrothTest.Room.SetActiveSpeakerTest

FILE: kousa/test/broth/room/set_auth_test.exs
  class BrothTest.Room.SetAuthTest (line 1) | defmodule BrothTest.Room.SetAuthTest

FILE: kousa/test/broth/room/set_role_test.exs
  class BrothTest.Room.SetRoleTest (line 1) | defmodule BrothTest.Room.SetRoleTest

FILE: kousa/test/broth/room/unban_test.exs
  class BrothTest.Room.UnbanTest (line 1) | defmodule BrothTest.Room.UnbanTest

FILE: kousa/test/broth/room/update_scheduled_test.exs
  class BrothTest.Room.UpdateScheduledTest (line 1) | defmodule BrothTest.Room.UpdateScheduledTest

FILE: kousa/test/broth/room/update_test.exs
  class BrothTest.Room.UpdateTest (line 1) | defmodule BrothTest.Room.UpdateTest

FILE: kousa/test/broth/user/admin_update_test.exs
  class BrothTest.User.AdminUpdateTest (line 1) | defmodule BrothTest.User.AdminUpdateTest

FILE: kousa/test/broth/user/ban_test.exs
  class BrothTest.User.BanTest (line 1) | defmodule BrothTest.User.BanTest

FILE: kousa/test/broth/user/block_test.exs
  class BrothTest.User.BlockTest (line 1) | defmodule BrothTest.User.BlockTest

FILE: kousa/test/broth/user/create_bot_test.exs
  class BrothTest.User.CreateBotTest (line 1) | defmodule BrothTest.User.CreateBotTest

FILE: kousa/test/broth/user/follow_test.exs
  class BrothTest.User.FollowTest (line 1) | defmodule BrothTest.User.FollowTest

FILE: kousa/test/broth/user/get_bots_test.exs
  class BrothTest.User.GetBotsTest (line 1) | defmodule BrothTest.User.GetBotsTest

FILE: kousa/test/broth/user/get_followers_test.exs
  class BrothTest.User.GetFollowersTest (line 1) | defmodule BrothTest.User.GetFollowersTest

FILE: kousa/test/broth/user/get_following_test.exs
  class BrothTest.User.GetFollowingTest (line 1) | defmodule BrothTest.User.GetFollowingTest

FILE: kousa/test/broth/user/get_info_test.exs
  class BrothTest.User.GetInfoTest (line 1) | defmodule BrothTest.User.GetInfoTest

FILE: kousa/test/broth/user/get_relationship_test.exs
  class BrothTest.User.GetRelationshipTest (line 1) | defmodule BrothTest.User.GetRelationshipTest

FILE: kousa/test/broth/user/revoke_api_key_test.exs
  class BrothTest.User.RevokeApiKeyTest (line 1) | defmodule BrothTest.User.RevokeApiKeyTest

FILE: kousa/test/broth/user/unblock_test.exs
  class BrothTest.User.UnblockTest (line 1) | defmodule BrothTest.User.UnblockTest

FILE: kousa/test/broth/user/unfollow_test.exs
  class BrothTest.User.UnfollowTest (line 1) | defmodule BrothTest.User.UnfollowTest

FILE: kousa/test/broth/user/update_test.exs
  class BrothTest.User.UpdateTest (line 1) | defmodule BrothTest.User.UpdateTest

FILE: kousa/test/kousa/user.ex
  class KousaTest.User (line 1) | defmodule KousaTest.User

FILE: kousa/test/test_helper.exs
  class KousaTest (line 8) | defmodule KousaTest
    method elixir_module? (line 9) | def elixir_module?(module) do
    method message_module? (line 16) | def message_module?(module) do
    method message_validation_module? (line 21) | def message_validation_module?(module) do
    method message_test_module? (line 26) | def message_test_module?(module) do
    method test_for (line 31) | def test_for(module) do
    method validation_for (line 36) | def validation_for(module) do

FILE: pilaf/android/app/src/debug/java/com/rice/ReactNativeFlipper.java
  class ReactNativeFlipper (line 27) | public class ReactNativeFlipper {
    method initializeFlipper (line 28) | public static void initializeFlipper(Context context, ReactInstanceMan...

FILE: pilaf/android/app/src/main/java/com/rice/MainActivity.java
  class MainActivity (line 9) | public class MainActivity extends ReactActivity {
    method getMainComponentName (line 15) | @Override
    method onCreate (line 20) | @Override

FILE: pilaf/android/app/src/main/java/com/rice/MainApplication.java
  class MainApplication (line 14) | public class MainApplication extends Application implements ReactApplica...
    method getUseDeveloperSupport (line 18) | @Override
    method getPackages (line 23) | @Override
    method getJSMainModuleName (line 32) | @Override
    method getReactNativeHost (line 38) | @Override
    method onCreate (line 43) | @Override
    method initializeFlipper (line 57) | private static void initializeFlipper(

FILE: pilaf/android/app/src/main/java/com/rice/SplashActivity.java
  class SplashActivity (line 7) | public class SplashActivity extends AppCompatActivity {
    method onCreate (line 8) | @Override

FILE: pilaf/src/components/BaseOverlay.tsx
  type BaseOverlayProps (line 12) | interface BaseOverlayProps {

FILE: pilaf/src/components/BubbleText.tsx
  type BubbleTextProps (line 5) | interface BubbleTextProps {

FILE: pilaf/src/components/FeaturedRoomCard.tsx
  function formatNumber (line 22) | function formatNumber(num: number): string {
  function useScheduleRerender (line 28) | function useScheduleRerender(scheduledFor?: Date) {
  type FeaturedRoomCardProps (line 52) | type FeaturedRoomCardProps = {

FILE: pilaf/src/components/MessageElement.tsx
  type MessageElementProps (line 15) | type MessageElementProps = ViewProps & {
  type MessageDateProps (line 27) | interface MessageDateProps {

FILE: pilaf/src/components/RoomCard.tsx
  function formatNumber (line 22) | function formatNumber(num: number): string {
  function useScheduleRerender (line 28) | function useScheduleRerender(scheduledFor?: Date) {
  type RoomCardProps (line 52) | type RoomCardProps = {

FILE: pilaf/src/components/RoomCardHeading.tsx
  type RoomCardHeadingProps (line 5) | interface RoomCardHeadingProps {

FILE: pilaf/src/components/ScrollViewLoadMore.tsx
  type ScrollViewLoadMoreProps (line 6) | type ScrollViewLoadMoreProps = {

FILE: pilaf/src/components/Spinner.tsx
  type SpinnerProps (line 5) | type SpinnerProps = ViewProps & {

FILE: pilaf/src/components/Tag.tsx
  type TagProps (line 5) | interface TagProps {

FILE: pilaf/src/components/UpcomingRoomCard.tsx
  type UserCardProps (line 24) | interface UserCardProps {
  type ScheduledRoomSummaryCardProps (line 29) | interface ScheduledRoomSummaryCardProps {
  type UpcomingRoomsCardProps (line 36) | type UpcomingRoomsCardProps = ViewProps & {

FILE: pilaf/src/components/UserBadge.tsx
  type UserBadgeProps (line 17) | type UserBadgeProps = ViewProps & {

FILE: pilaf/src/components/UserPreview.tsx
  type UserPreviewProps (line 29) | type UserPreviewProps = ViewProps & {
  type UserPreviewRoutePageProp (line 442) | type UserPreviewRoutePageProp = RouteProp<
  type UserPreviewRouteProp (line 447) | type UserPreviewRouteProp = {

FILE: pilaf/src/components/accountModal/AccountModalContent.tsx
  type AccountModalContentProps (line 11) | type AccountModalContentProps = {

FILE: pilaf/src/components/accountModal/AccountModalRow.tsx
  type AccountModalRowProps (line 11) | interface AccountModalRowProps {

FILE: pilaf/src/components/avatars/MultipleUserAvatar.tsx
  type MultipleUserAvatarProps (line 12) | interface MultipleUserAvatarProps {

FILE: pilaf/src/components/avatars/RoomAvatar.tsx
  type RoomAvatarProps (line 12) | interface RoomAvatarProps {

FILE: pilaf/src/components/avatars/SingleUserAvatar.tsx
  type SingleUserAvatarProps (line 12) | interface SingleUserAvatarProps {

FILE: pilaf/src/components/buttons/Button.tsx
  type ButtonProps (line 19) | type ButtonProps = ViewProps & {

FILE: pilaf/src/components/buttons/IconButton.tsx
  type IconButtonProps (line 12) | interface IconButtonProps {

FILE: pilaf/src/components/buttons/SignInButton.tsx
  type Provider (line 15) | type Provider = "google" | "twitter" | "github" | "apple";
  type SignInButtonProps (line 58) | type SignInButtonProps = ViewProps & {

FILE: pilaf/src/components/buttons/SigninWithGithub.tsx
  type SigninWithGithubButtonProps (line 53) | interface SigninWithGithubButtonProps {

FILE: pilaf/src/components/header/HeaderBase.tsx
  type HeaderBaseProps (line 13) | type HeaderBaseProps = ViewProps & {

FILE: pilaf/src/components/header/ProfileButton.tsx
  type ProfileButtonProps (line 14) | interface ProfileButtonProps {

FILE: pilaf/src/components/header/RoomHeader.tsx
  type RoomHeaderProps (line 13) | type RoomHeaderProps = {

FILE: pilaf/src/components/header/SearchHeader.tsx
  type SearchHeaderProps (line 6) | type SearchHeaderProps = {

FILE: pilaf/src/components/header/TitledHeader.tsx
  type TitledHeaderProps (line 6) | type TitledHeaderProps = {

FILE: pilaf/src/components/minimizedRoomCard/BoxedIcon.tsx
  type BoxedIconProps (line 12) | interface BoxedIconProps {

FILE: pilaf/src/components/minimizedRoomCard/MinimizedRoomCard.tsx
  type MinimizedRoomCardProps (line 15) | interface MinimizedRoomCardProps {

FILE: pilaf/src/components/notifications/FollowNotification.tsx
  type FollowNotificationProps (line 20) | interface FollowNotificationProps {

FILE: pilaf/src/components/notifications/GenericNotification.tsx
  type GenericNotificationProps (line 6) | interface GenericNotificationProps {

FILE: pilaf/src/components/notifications/LiveNotification.tsx
  type LiveNotificationProps (line 19) | interface LiveNotificationProps {

FILE: pilaf/src/components/notifications/NewRoomNotification.tsx
  type NewRoomNotificationProps (line 19) | interface NewRoomNotificationProps {

FILE: pilaf/src/components/report/Report.tsx
  type ReportProps (line 6) | type ReportProps = ViewProps & {

FILE: pilaf/src/components/search/RoomSearchResult.tsx
  function formatNumber (line 21) | function formatNumber(num: number): string {
  function useScheduleRerender (line 27) | function useScheduleRerender(scheduledFor?: Date) {
  type RoomSearchResultProps (line 49) | type RoomSearchResultProps = ViewProps & {

FILE: pilaf/src/components/search/SearchHistoryResult.tsx
  type SearchHistoryResultProps (line 12) | type SearchHistoryResultProps = ViewProps & {

FILE: pilaf/src/components/search/UserSearchResult.tsx
  type UserSearchResultProps (line 18) | type UserSearchResultProps = ViewProps & {

FILE: pilaf/src/global-stores/useCurrentRoomIdStore.ts
  type Fn (line 4) | type Fn = (currentRoomId: string | null) => string | null;

FILE: pilaf/src/modules/auth/WaitForWsAndAuth.tsx
  type WaitForWsAndAuthProps (line 7) | interface WaitForWsAndAuthProps {}

FILE: pilaf/src/modules/auth/useSaveTokensFromQueryParams.ts
  function getUrlParameter (line 5) | function getUrlParameter(url: string, name: string) {

FILE: pilaf/src/modules/feed/FeedController.tsx
  type FeedControllerProps (line 11) | interface FeedControllerProps {}

FILE: pilaf/src/modules/following/FollowersOnline.tsx
  type FriendOnlineType (line 18) | interface FriendOnlineType {
  type FriendsOnlineProps (line 28) | interface FriendsOnlineProps {

FILE: pilaf/src/modules/following/FollowingOnlineController.tsx
  type FriendsOnlineControllerProps (line 8) | type FriendsOnlineControllerProps = {

FILE: pilaf/src/modules/room/InviteRoomController.tsx
  type InviteRoomControllerPropse (line 108) | type InviteRoomControllerPropse = {

FILE: pilaf/src/modules/room/MinimizedRoomCardController.tsx
  type MinimizedRoomCardControllerProps (line 10) | interface MinimizedRoomCardControllerProps {}

FILE: pilaf/src/modules/room/RoomController.tsx
  type RoomControllerProps (line 32) | type RoomControllerProps = {

FILE: pilaf/src/modules/room/RoomDescriptionController.tsx
  type RoomDescriptionControllerProps (line 15) | type RoomDescriptionControllerProps = {

FILE: pilaf/src/modules/room/RoomPanelController.tsx
  type RoomPageRouteProp (line 15) | type RoomPageRouteProp = RouteProp<RoomStackParamList, "RoomMain">;
  type RoomPageProps (line 17) | type RoomPageProps = {

FILE: pilaf/src/modules/room/RoomUsersPanel.tsx
  type RoomUsersPanelProps (line 8) | interface RoomUsersPanelProps extends JoinRoomAndGetInfoResponse {}

FILE: pilaf/src/modules/room/UserPreviewModalProvider.tsx
  type UserProfileOverlayProviderProps (line 4) | interface UserProfileOverlayProviderProps {}
  type Data (line 6) | type Data = { userId: string; message?: RoomChatMessage };

FILE: pilaf/src/modules/room/chat/EmotePicker.tsx
  type EmotePickerProps (line 15) | type EmotePickerProps = ViewProps & {

FILE: pilaf/src/modules/room/chat/RoomChat.tsx
  type ChatProps (line 17) | interface ChatProps {

FILE: pilaf/src/modules/room/chat/RoomChatControls.tsx
  type RoomChatControlsProps (line 12) | interface RoomChatControlsProps {

FILE: pilaf/src/modules/room/chat/RoomChatInput.tsx
  type ChatInputProps (line 17) | interface ChatInputProps {

FILE: pilaf/src/modules/room/chat/RoomChatList.tsx
  type ChatListProps (line 9) | interface ChatListProps {

FILE: pilaf/src/modules/room/chat/RoomChatMentions.tsx
  type RoomChatMentionsProps (line 10) | interface RoomChatMentionsProps {
  function addMention (line 30) | function addMention(m: BaseUser) {

FILE: pilaf/src/modules/room/chat/useRoomChatStore.ts
  type TextToken (line 5) | interface TextToken {
  type MentionToken (line 9) | interface MentionToken {
  type LinkToken (line 13) | interface LinkToken {
  type BlockToken (line 18) | interface BlockToken {
  type EmoteToken (line 23) | interface EmoteToken {
  type RoomChatMessageToken (line 28) | type RoomChatMessageToken =
  function generateColorFromString (line 48) | function generateColorFromString(str: string) {
  type RoomChatMessage (line 54) | interface RoomChatMessage {

FILE: pilaf/src/modules/sound-effect/useSoundEffectStore.ts
  type PossibleSoundEffect (line 20) | type PossibleSoundEffect = keyof typeof soundEffects;
  function getInitialSettings (line 22) | function getInitialSettings() {

FILE: pilaf/src/modules/webrtc/WebRtcApp.tsx
  type App2Props (line 16) | interface App2Props {}
  function closeVoiceConnections (line 18) | function closeVoiceConnections(_roomId: string | null) {
  function flushConsumerQueue (line 47) | async function flushConsumerQueue(_roomId: string) {

FILE: pilaf/src/modules/webrtc/components/MicPicker.tsx
  type MicPickerProps (line 4) | interface MicPickerProps {}

FILE: pilaf/src/modules/webrtc/stores/useMicIdStore.ts
  constant MIC_KEY (line 4) | const MIC_KEY = "micId";

FILE: pilaf/src/modules/webrtc/stores/useSocketStatus.ts
  type State (line 4) | type State =

FILE: pilaf/src/modules/webrtc/stores/useStatus.ts
  type State (line 4) | type State =

FILE: pilaf/src/modules/webrtc/types.ts
  type AddWsListenerOnce (line 1) | type AddWsListenerOnce = (op: string, fn: (d: any) => void) => void;

FILE: pilaf/src/modules/webrtc/utils/createTransport.ts
  function createTransport (line 5) | async function createTransport(

FILE: pilaf/src/modules/ws/WebSocketProvider.tsx
  type WebSocketProviderProps (line 5) | interface WebSocketProviderProps {
  type V (line 9) | type V = raw.Connection | null;

FILE: pilaf/src/navigation/MainNavigator.tsx
  type RootStackParamList (line 18) | type RootStackParamList = {

FILE: pilaf/src/navigation/RootNavigation.ts
  type StackNavigationProps (line 12) | interface StackNavigationProps<
  function navigate (line 24) | function navigate(name, params = {}) {

FILE: pilaf/src/navigation/mainNavigator/InviteRoomPage.tsx
  type RoomPageRouteProp (line 6) | type RoomPageRouteProp = RouteProp<RoomStackParamList, "RoomInvitation">;
  type InviteRoomPageProps (line 8) | type InviteRoomPageProps = {

FILE: pilaf/src/navigation/mainNavigator/RoomDescriptionPage.tsx
  type RoomDescriptionPageRouteProp (line 6) | type RoomDescriptionPageRouteProp = RouteProp<
  type RoomDescriptionPageProps (line 11) | type RoomDescriptionPageProps = {

FILE: pilaf/src/navigation/mainNavigator/RoomNavigator.tsx
  type RoomStackParamList (line 12) | type RoomStackParamList = {
  type RoomNavigatorProps (line 25) | type RoomNavigatorProps = {

FILE: pilaf/src/pages/CreateRoomPage.tsx
  type CreateRoomModalProps (line 31) | interface CreateRoomModalProps {

FILE: pilaf/src/shared-components/ApiPreloadLink.tsx
  type Prefetch (line 4) | type Prefetch = ReturnType<typeof useTypeSafePrefetch>;
  type Handler (line 31) | type Handler = typeof handlers;
  type ValueOf (line 33) | type ValueOf<T> = T[keyof T];
  type DifferentProps (line 34) | type DifferentProps = {

FILE: pilaf/src/shared-hooks/useTypeSafeMutation.ts
  type Keys (line 7) | type Keys = keyof ReturnType<typeof wrap>["mutation"];

FILE: pilaf/src/shared-hooks/useTypeSafePrefetch.ts
  type Keys (line 6) | type Keys = keyof ReturnType<typeof wrap>["query"];
  type PaginatedKey (line 8) | type PaginatedKey<K extends Keys> = [K, string | number];

FILE: pilaf/src/shared-hooks/useTypeSafeQuery.ts
  type Keys (line 6) | type Keys = keyof ReturnType<typeof wrap>["query"];
  type PaginatedKey (line 8) | type PaginatedKey<K extends Keys> = [K, ...(string | number | boolean)[]];

FILE: pilaf/src/shared-hooks/useTypeSafeUpdateQuery.ts
  type Keys (line 6) | type Keys = keyof ReturnType<typeof wrap>["query"];
  type PaginatedKey (line 8) | type PaginatedKey<K extends Keys> = [K, string | number];

FILE: pilaf/src/types/util-types.ts
  type Await (line 1) | type Await<T> = T extends Promise<infer U> ? U : T;

FILE: pilaf/storybook/stories/CenterView/index.tsx
  function CenterView (line 6) | function CenterView({ children }) {

FILE: shawarma/src/MyPeer.ts
  type MyPeer (line 3) | type MyPeer = {

FILE: shawarma/src/MyRoomState.ts
  type Then (line 4) | type Then<T> = T extends PromiseLike<infer U> ? U : T;
  type MyRoomState (line 6) | type MyRoomState = Record<string, MyPeer>;
  type MyRooms (line 8) | type MyRooms = Record<

FILE: shawarma/src/main.ts
  function main (line 18) | async function main() {

FILE: shawarma/src/types/env.d.ts
  type ProcessEnv (line 2) | interface ProcessEnv {

FILE: shawarma/src/types/index.ts
  type VoiceSendDirection (line 1) | type VoiceSendDirection = "recv" | "send";

FILE: shawarma/src/utils/createConsumer.ts
  type Consumer (line 56) | interface Consumer {

FILE: shawarma/src/utils/createTransport.ts
  type TransportOptions (line 16) | type TransportOptions = ReturnType<typeof transportToOptions>;

FILE: shawarma/src/utils/startMediasoup.ts
  function startMediasoup (line 6) | async function startMediasoup() {

FILE: shawarma/src/utils/startRabbit.ts
  type HandlerDataMap (line 14) | interface HandlerDataMap {
  type HandlerMap (line 57) | type HandlerMap = {
  type SendTrackDoneOperationName (line 68) | type SendTrackDoneOperationName = `@send-track-${VoiceSendDirection}-done`;
  type ConnectTransportDoneOperationName (line 69) | type ConnectTransportDoneOperationName = `@connect-transport-${VoiceSend...
  type OutgoingMessageDataMap (line 71) | type OutgoingMessageDataMap = {
  type OutgoingMessage (line 122) | type OutgoingMessage<Key extends keyof OutgoingMessageDataMap> = {
  type IncomingChannelMessageData (line 126) | interface IncomingChannelMessageData<Key extends keyof HandlerMap> {
Condensed preview — 1345 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,634K chars).
[
  {
    "path": ".devcontainer/Dockerfile",
    "chars": 924,
    "preview": "# Update to pick an Elixir version: 1.9, 1.10, 1.10.4\nARG VARIANT=latest\nFROM elixir:${VARIANT}\n\nENV USERNAME=doge\nENV U"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 563,
    "preview": "{\n    \"name\": \"Dogehouse\",\n    \"dockerComposeFile\": \"docker-compose.yml\",\n    \"service\": \"workspace\",\n    \"workspaceFold"
  },
  {
    "path": ".devcontainer/docker-compose.yml",
    "chars": 725,
    "preview": "version: \"3\"\n\nservices:\n  workspace:\n    build:\n      context: .\n      dockerfile: Dockerfile\n    volumes:\n      - ..:/w"
  },
  {
    "path": ".devcontainer/scripts/environment.sh",
    "chars": 756,
    "preview": "# kousa\ncat >> \"/home/$USERNAME/.bashrc\" << EOL\n\n# Kousa environment variables \nexport DATABASE_URL=postgres://postgres:"
  },
  {
    "path": ".devcontainer/scripts/node.sh",
    "chars": 854,
    "preview": "#!/usr/bin/env bash\n\nUSERNAME=${3:-\"doge\"}\nexport NVM_DIR=${1:-\"/home/$USERNAME/.nvm\"}\nexport NODE_VERSION=${2:-\"lts/*\"}"
  },
  {
    "path": ".devcontainer/scripts/user.sh",
    "chars": 626,
    "preview": "#!/usr/bin/env bash\n\nUSERNAME=${1:-\"doge\"}\nUSER_UID=${2:-1000}\nUSER_GID=${3:-$USER_UID}\n\nPACKAGE_LIST=\"apt-utils \\\n     "
  },
  {
    "path": ".dockerignore",
    "chars": 16,
    "preview": "docker/\n.docker/"
  },
  {
    "path": ".editorconfig",
    "chars": 231,
    "preview": "# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with a newline ending every file\n[*]\ncharset = utf-8\nend"
  },
  {
    "path": ".eslintignore",
    "chars": 13,
    "preview": "node_modules/"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 565,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 604,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Is"
  },
  {
    "path": ".github/labeler.yml",
    "chars": 247,
    "preview": "kibbeh:\n  - kibbeh/**/*\nbaklava:\n  - baklava/**/*\nkebab:\n  - kebab/**/*\nkousa:\n  - kousa/**/*\npilaf:\n  - pilaf/**/*\nshaw"
  },
  {
    "path": ".github/workflows/baklava-build_and_release.yaml",
    "chars": 2895,
    "preview": "name: baklava:build_and_release\n\non:\n  push:\n    paths:\n      - \"baklava/**\"\n    branches:\n      - staging\n\njobs:\n  rele"
  },
  {
    "path": ".github/workflows/dolma-npm_deploy.yaml",
    "chars": 1474,
    "preview": "name: dolma:npm_publish\non:\n  push:\n    paths:\n      - \"dolma/**\"\n    branches:\n      - staging\njobs:\n  npm-publish:\n   "
  },
  {
    "path": ".github/workflows/global-label_pr.yml",
    "chars": 207,
    "preview": "name: global:label_pr\n\non:\n  - pull_request_target\n\njobs:\n  triage:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: "
  },
  {
    "path": ".github/workflows/global-lint_commit_messages.yaml",
    "chars": 240,
    "preview": "name: global:lint_commit_messages\n\non: [push, pull_request]\n\njobs:\n  commitlint:\n    runs-on: ubuntu-latest\n    steps:\n "
  },
  {
    "path": ".github/workflows/globalkey-npm_deploy.yaml",
    "chars": 1235,
    "preview": "name: globalkey:npm_publish\non:\n  push:\n    paths:\n      - \"globalkey/**\"\n    branches:\n      - staging\njobs:\n  npm-publ"
  },
  {
    "path": ".github/workflows/kebab-npm_publish.yaml",
    "chars": 1460,
    "preview": "name: kebab:npm_publish\non:\n  push:\n    paths:\n      - \"kebab/**\"\n    branches:\n      - staging\njobs:\n  npm-publish:\n   "
  },
  {
    "path": ".github/workflows/kibbeh-e2e_tests.yaml",
    "chars": 1204,
    "preview": "name: kibbeh:e2e_tests\non:\n  push:\n    branches:\n      - staging\n    paths:\n      - '.github/workflows/kibbeh-e2e_tests."
  },
  {
    "path": ".github/workflows/kibbeh-lint_and_test.yaml",
    "chars": 850,
    "preview": "name: kibbeh:lint_and_test\n\non:\n  push:\n    branches:\n      - staging\n    paths:\n      - \"kibbeh/**\"\n  pull_request:\n   "
  },
  {
    "path": ".github/workflows/kousa-deploy_staging.yaml",
    "chars": 629,
    "preview": "name: kousa:deploy_staging\non:\n  push:\n    paths:\n      - 'kousa/lib/**'\n    branches:\n      - staging\n\njobs:\n  build:\n "
  },
  {
    "path": ".github/workflows/kousa-tests.yaml",
    "chars": 837,
    "preview": "name: kousa:tests\non:\n  push:\n    branches:\n      - staging\n    paths:\n      - 'kousa/lib/**'\n  pull_request:\n    branch"
  },
  {
    "path": ".github/workflows/shawarma-deploy_staging.yaml",
    "chars": 611,
    "preview": "name: shawarma:deploy_staging\non:\n  push:\n    paths:\n      - 'shawarma/src/**'\n    branches:\n      - staging\n\njobs:\n  bu"
  },
  {
    "path": ".gitignore",
    "chars": 225,
    "preview": ".DS_Store\nnode_modules\n\n# Local Netlify folder\n.netlify\n\n.idea/\n*/.idea/\n.docker\n.env\n.next\nstorybook-static\n_\n.env.loca"
  },
  {
    "path": ".husky/.gitignore",
    "chars": 2,
    "preview": "_\n"
  },
  {
    "path": ".husky/commit-msg",
    "chars": 168,
    "preview": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\n# @todo uncomment when new-design hits\n# thats when we will start enforcing co"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 87,
    "preview": "#!/bin/sh\n# . \"$(dirname \"$0\")/_/husky.sh\"\n\n# cd kibbeh\n# npm run format\n# npm run lint"
  },
  {
    "path": ".prettierignore",
    "chars": 13,
    "preview": "node_modules/"
  },
  {
    "path": ".prettierrc.js",
    "chars": 140,
    "preview": "module.exports = {\n  trailingComma: \"es5\",\n  tabWidth: 2,\n  semi: true,\n  singleQuote: false,\n  arrowParens: \"always\",\n "
  },
  {
    "path": ".vscode/settings.json",
    "chars": 110,
    "preview": "{\n    \"elixirLS.projectDir\": \"kousa\",\n    \"elixir.projectPath\": \"kousa\",\n    \"git.ignoreLimitWarning\": true,\n}"
  },
  {
    "path": ".yarnrc.yml",
    "chars": 288,
    "preview": "nodeLinker: node-modules\n\nplugins:\n  - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs\n    spec: \"@yarnpkg/plugi"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 83,
    "preview": "# Changelog\n\n## 4/16/2021\n\n- Switched to a new UI\n\n## 2/20/2021\n\n- Added changelog\n"
  },
  {
    "path": "CODEOWNERS",
    "chars": 91,
    "preview": "/kebab/ @overlisted\n/baklava/ @amitojsingh366\n/dolma/ @HoloPanio\n/globalkey/ @willdoescode\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3411,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 9666,
    "preview": "# Contributing to DogeHouse\n> Please read the [PRIORITY LIST](https://github.com/benawad/dogehouse/issues/1969) before c"
  },
  {
    "path": "CREATE_BOT_ACCOUNT.MD",
    "chars": 295,
    "preview": "0. Sign in to your account\n1. Head to [developer settings](https://dogehouse.tv/developer/bots)\n2. Click `Create bot`\n3."
  },
  {
    "path": "DESIGN_GUIDELINES.md",
    "chars": 2577,
    "preview": "# Design Guidelines\n\nThis document aims to specify and define the rules and patterns to follow when implementing and dev"
  },
  {
    "path": "FAQ.md",
    "chars": 677,
    "preview": "# FAQ\n\n## Why did you choose Elixir?\n\nIt's fun to program in. The error messages are awful and there's no static typing,"
  },
  {
    "path": "HOW_TO_DEBUG_AUDIO.md",
    "chars": 1284,
    "preview": "0. Turn on audio debugging mode by clicking on your avatar in the top right and click `Debug Audio`:\n![image](https://us"
  },
  {
    "path": "HOW_TO_GET_PERMA_BANNED_FROM_DOGEHOUSE.md",
    "chars": 229,
    "preview": "# Things that will get you perma banned\n\n0. Spam creating a ton of scheduled rooms\n1. NSFW profile/banner image\n2. Ban e"
  },
  {
    "path": "LICENSE",
    "chars": 1096,
    "preview": "MIT License\n\nCopyright (C) 2021 Ben Awad and the DogeHouse contributors\n\nPermission is hereby granted, free of charge, t"
  },
  {
    "path": "README.md",
    "chars": 4802,
    "preview": "<a href=\"https://dogehouse.tv\"><p align=\"center\">\n<img height=100 src=\"https://raw.githubusercontent.com/benawad/dogehou"
  },
  {
    "path": "SECURITY.md",
    "chars": 119,
    "preview": "# Security Policy\n\n## Reporting a Vulnerability\n\nDM me on https://twitter.com/benawad or https://discord.gg/wCbKBZF9cV\n"
  },
  {
    "path": "baklava/.gitignore",
    "chars": 441,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": "baklava/.yarnrc.yml",
    "chars": 296,
    "preview": "nodeLinker: node-modules\n\nplugins:\n  - path: ../.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs\n    spec: \"@yarnpkg/pl"
  },
  {
    "path": "baklava/README.md",
    "chars": 1788,
    "preview": "# Dogehouse for Desktop (Baklava)\n\nThis is the desktop application for Dogehouse.\nIt uses ElectronJS as a wrapper for [d"
  },
  {
    "path": "baklava/locales/en/translate.json",
    "chars": 295,
    "preview": "{\n  \"common\": {\n    \"title\": \"Dogehouse\"\n  },\n  \"splash\": {\n    \"check\": \"Checking for updates...\",\n    \"download\": \"Dow"
  },
  {
    "path": "baklava/package.json",
    "chars": 4374,
    "preview": "{\n    \"name\": \"dogehouse\",\n    \"version\": \"1.0.69\",\n    \"description\": \"Taking voice conversations to the moon 🚀\",\n    \""
  },
  {
    "path": "baklava/resources/overlay/.gitignore",
    "chars": 98,
    "preview": "/node_modules\n/build\n\n# yarn v2\n.yarn/*\n!.yarn/releases\n!.yarn/plugins\n!.yarn/sdks\n!.yarn/versions"
  },
  {
    "path": "baklava/resources/overlay/.yarnrc.yml",
    "chars": 314,
    "preview": "nodeLinker: node-modules\n\nplugins:\n  - path: ../../../.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs\n    spec: \"@yarn"
  },
  {
    "path": "baklava/resources/overlay/README.md",
    "chars": 3348,
    "preview": "# Getting Started with Create React App\n\nThis project was bootstrapped with [Create React App](https://github.com/facebo"
  },
  {
    "path": "baklava/resources/overlay/package.json",
    "chars": 935,
    "preview": "{\r\n  \"name\": \"dogehouse-baklava-overlay\",\r\n  \"version\": \"0.1.0\",\r\n  \"private\": true,\r\n  \"dependencies\": {\r\n    \"@testing"
  },
  {
    "path": "baklava/resources/overlay/public/index.html",
    "chars": 1450,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-w"
  },
  {
    "path": "baklava/resources/overlay/src/App.css",
    "chars": 608,
    "preview": ".App {\n  text-align: center;\n  background: rgba(0, 0, 0, 0);\n  /* background: #ffffff; */\n}\n\nimg{\n  border-radius: 50%;\n"
  },
  {
    "path": "baklava/resources/overlay/src/App.js",
    "chars": 2518,
    "preview": "import './App.css';\r\nimport { useEffect, useState } from 'react';\r\n// import { FiMicOff } from \"react-icons/fi\";\r\n\r\ncons"
  },
  {
    "path": "baklava/resources/overlay/src/index.css",
    "chars": 366,
    "preview": "body {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n    'Ubuntu', 'Can"
  },
  {
    "path": "baklava/resources/overlay/src/index.js",
    "chars": 500,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport repor"
  },
  {
    "path": "baklava/resources/overlay/src/reportWebVitals.js",
    "chars": 362,
    "preview": "const reportWebVitals = onPerfEntry => {\n  if (onPerfEntry && onPerfEntry instanceof Function) {\n    import('web-vitals'"
  },
  {
    "path": "baklava/resources/splash/splash-screen.html",
    "chars": 2936,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=e"
  },
  {
    "path": "baklava/scripts/generateTranslationTypes.ts",
    "chars": 453,
    "preview": "import fs from \"fs\";\nimport { join } from \"path\";\nimport prettier from \"prettier\";\nimport { traverseTranslations } from "
  },
  {
    "path": "baklava/scripts/syncTranslations.ts",
    "chars": 987,
    "preview": "// @ts-ignore\nimport config from \"../../.prettierrc.js\";\nimport english from \"../locales/en/translate.json\";\nimport * as"
  },
  {
    "path": "baklava/scripts/traverseTranslations.ts",
    "chars": 613,
    "preview": "import translations from \"../locales/en/translate.json\";\n\nconst keys: string[] = [];\n\ntype TranslationRecord = {\n\t[P in "
  },
  {
    "path": "baklava/scripts/tsconfig.json",
    "chars": 697,
    "preview": "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"es6\",\n\t\t\"module\": \"commonjs\",\n\t\t\"lib\": [\"dom\", \"es6\", \"es2017\", \"esnext.asynciterab"
  },
  {
    "path": "baklava/settings/entitlements.mac.plist",
    "chars": 555,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "baklava/src/constants.ts",
    "chars": 3391,
    "preview": "import { app, shell } from \"electron\";\nimport { autoUpdater } from \"electron-updater\";\n\nexport const isMac = process.pla"
  },
  {
    "path": "baklava/src/dev.ts",
    "chars": 943,
    "preview": "import { exec, ChildProcess } from 'child_process';\r\n\r\nlet compiler: ChildProcess;\r\nlet app: ChildProcess;\r\n\r\nlet env = "
  },
  {
    "path": "baklava/src/electron.ts",
    "chars": 7861,
    "preview": "import {\n  BrowserWindow,\n  app,\n  systemPreferences,\n  ipcMain,\n  globalShortcut,\n  shell,\n  Tray,\n  Menu,\n} from \"elec"
  },
  {
    "path": "baklava/src/generated/translationKeys.ts",
    "chars": 187,
    "preview": "// this is autogenerated by running `npm run gen:i18:keys`\nexport type TranslationKeys =\n\t| \"common.title\"\n\t| \"splash.ch"
  },
  {
    "path": "baklava/src/types.ts",
    "chars": 143,
    "preview": "import { BrowserWindow } from \"electron\"\r\n\r\nexport type bWindowsType = {\r\n    main: BrowserWindow,\r\n    overlay: Browser"
  },
  {
    "path": "baklava/src/utils/keybinds.ts",
    "chars": 4982,
    "preview": "import {\n    ipcMain,\n    globalShortcut,\n    app,\n} from \"electron\";\nimport {\n    CHAT_KEY,\n    INVITE_KEY,\n    MUTE_KE"
  },
  {
    "path": "baklava/src/utils/notifications.ts",
    "chars": 1597,
    "preview": "import {\r\n    ipcMain,\r\n    Notification\r\n} from \"electron\";\r\n\r\nexport async function StartNotificationHandler() {\r\n    "
  },
  {
    "path": "baklava/src/utils/overlay/index.ts",
    "chars": 553,
    "preview": "import { BrowserWindow } from 'electron';\nimport * as path from \"path\";\nimport { __prod__ } from '../../electron';\n\nexpo"
  },
  {
    "path": "baklava/src/utils/overlay/ipc.ts",
    "chars": 507,
    "preview": "import {\n    ipcMain,\n    BrowserWindow,\n} from \"electron\";\n\nexport async function startOverlayIPCHandler(mainWindow: Br"
  },
  {
    "path": "baklava/src/utils/rpc/index.ts",
    "chars": 1082,
    "preview": "import { Client, Presence } from \"discord-rpc\";\nimport logger from \"electron-log\";\nimport { startRPCIPCHandler, stopRPCI"
  },
  {
    "path": "baklava/src/utils/rpc/ipc.ts",
    "chars": 4186,
    "preview": "import { Presence } from \"discord-rpc\";\nimport { ipcMain } from \"electron\";\nimport { setPresence } from \"./index\";\nlet i"
  },
  {
    "path": "baklava/src/utils/tray.ts",
    "chars": 2470,
    "preview": "import {\n    ipcMain,\n    BrowserWindow,\n    Menu,\n    Tray,\n    app\n} from \"electron\";\nimport { autoUpdater } from \"ele"
  },
  {
    "path": "baklava/tsconfig.json",
    "chars": 604,
    "preview": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"target\": \"es5\",\n    \"lib\": [\n      \"dom\",\n      \"dom.iterable\",\n  "
  },
  {
    "path": "commitlint.config.js",
    "chars": 336,
    "preview": "module.exports = {\n  extends: [\"@commitlint/config-conventional\"],\n  rules: {\n    \"scope-enum\": [\n      2,\n      \"always"
  },
  {
    "path": "dinner/.eslintrc.json",
    "chars": 398,
    "preview": "{\n  \"env\": {\n    \"browser\": true,\n    \"es2021\": true,\n    \"node\": true\n  },\n  \"extends\": [\"eslint:recommended\"],\n  \"pars"
  },
  {
    "path": "dinner/.gitignore",
    "chars": 12,
    "preview": "node_modules"
  },
  {
    "path": "dinner/package.json",
    "chars": 564,
    "preview": "{\n  \"name\": \"dinner\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"ts-n"
  },
  {
    "path": "dinner/src/create-accounts.ts",
    "chars": 756,
    "preview": "import { http, raw, wrap } from \"@dogehouse/kebab\";\nimport { Connection } from \"@dogehouse/kebab/lib/raw\";\n\nconst main ="
  },
  {
    "path": "dinner/src/play-audio.ts",
    "chars": 2534,
    "preview": "import { audioWrap, http, raw, wrap, Wrapper } from \"@dogehouse/kebab\";\nimport { connect as mediasoupConnect } from \"@do"
  },
  {
    "path": "dinner/tsconfig.json",
    "chars": 817,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"module\": \"commonjs\",\n    \"lib\": [\n      \"dom\",\n      \"es6\",\n      \"es"
  },
  {
    "path": "docker-compose.local.yml",
    "chars": 1608,
    "preview": "version: \"3\"\n\n# service_name:\n#   build: \n#     context: .\n#     dockerfile: path/to/Dockerfile\n#\n\nservices:\n  # voice s"
  },
  {
    "path": "docker-compose.prod.yml",
    "chars": 405,
    "preview": "version: \"3\"\n\n# service_name:\n#   build: \n#     context: .\n#     dockerfile: path/to/Dockerfile\n#\n\n# kofta is not here c"
  },
  {
    "path": "docker-compose.yml",
    "chars": 1637,
    "preview": "version: \"3\"\n\n# service_name:\n#   build: \n#     context: .\n#     dockerfile: path/to/Dockerfile\n#   restart: unless-stop"
  },
  {
    "path": "docs/Architecture/README.md",
    "chars": 1247,
    "preview": "# Architecture Of DogeHouse!\n\n<img src= \"https://github.com/RonaldColyar/dogehouse/blob/staging/docs/Architecture/Archit"
  },
  {
    "path": "docs/Directory/README.md",
    "chars": 3107,
    "preview": "# DogeHouse Code Directory\n\n\n1.Kofta(React Front End)\n  - Components\n    - [AlertModal](https://github.com/benawad/dogeh"
  },
  {
    "path": "docs/Elixir Api/README.MD",
    "chars": 1039,
    "preview": "# Authentication\r\n\r\nTokens:\r\n\r\n- Refresh token -> lasts 30 days\r\n- Access token -> 1 hour\r\n\r\nWebsocket connection:\r\n\r\n- "
  },
  {
    "path": "docs/README.MD",
    "chars": 1709,
    "preview": "## Home\n<p align=\"center\">\n<img height=100 src=\"https://raw.githubusercontent.com/benawad/dogehouse/staging/.redesign-as"
  },
  {
    "path": "docs/React Front End/README.MD",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/Voice Server/README.MD",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "dolma/.editorconfig",
    "chars": 231,
    "preview": "# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with a newline ending every file\n[*]\ncharset = utf-8\nend"
  },
  {
    "path": "dolma/.gitignore",
    "chars": 1662,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# Diagnostic reports (https://nodejs."
  },
  {
    "path": "dolma/LICENSE",
    "chars": 1066,
    "preview": "MIT License\n\nCopyright (c) 2021 HoloPanio\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": "dolma/README.md",
    "chars": 4058,
    "preview": "<h1 align=center>\nDolma Token Transcoder<br>\n<a href=\"https://www.npmjs.com/package/@dogehouse/dolma\"><img src=\"https://"
  },
  {
    "path": "dolma/package.json",
    "chars": 825,
    "preview": "{\n  \"name\": \"@dogehouse/dolma\",\n  \"author\": \"Jackson Roberts <jackson@holopanio.com>\",\n  \"description\": \"A chat token tr"
  },
  {
    "path": "dolma/src/index.ts",
    "chars": 809,
    "preview": "import { decodeTokens } from \"./lib/decode\";\nimport { encodeTokens } from \"./lib/encode\";\nimport { Unitoken } from \"./to"
  },
  {
    "path": "dolma/src/lib/decode.ts",
    "chars": 918,
    "preview": "import dolma from \"../index\";\nimport { Unitoken } from \"../tokens\";\nimport { MessageToken } from \"../util/types/tokenTyp"
  },
  {
    "path": "dolma/src/lib/encode.ts",
    "chars": 1050,
    "preview": "import { Unitoken } from \"../tokens\";\nimport { MessageToken } from \"../util/types/tokenTypes\";\nimport { decodeTokens } f"
  },
  {
    "path": "dolma/src/lib/filterString.ts",
    "chars": 1130,
    "preview": "import { validationRegex } from \"../util/regex\";\nimport { MessageToken, MessageTokenType } from \"../util/types/tokenType"
  },
  {
    "path": "dolma/src/lib/filterUnitoken.ts",
    "chars": 398,
    "preview": "import { MessageToken, MessageTokenType } from \"../util/types/tokenTypes\";\nimport { msgToken } from \"./msgToken\";\n\nconst"
  },
  {
    "path": "dolma/src/lib/msgToken.ts",
    "chars": 1484,
    "preview": "import { validationRegex } from \"../util/regex\";\nimport { MessageToken, MessageTokenType } from \"../util/types/tokenType"
  },
  {
    "path": "dolma/src/test/run.ts",
    "chars": 1691,
    "preview": "import * as encodingTests from './tests/encoding';\nimport dolma from '../';\n\ninterface CompletedTest {\n  started: Date,\n"
  },
  {
    "path": "dolma/src/test/tests/encoding.ts",
    "chars": 1982,
    "preview": "export default [\n\t{\n\t\tname: \"Single string type test 1 (text)\",\n\t\ttype: \"encode\",\n\n\t\tinput: \"Ben Awad\",\n\t\texpectedOutput"
  },
  {
    "path": "dolma/src/tokens/index.ts",
    "chars": 512,
    "preview": "import * as text from './types/text';\nimport * as block from './types/block';\nimport * as mention from './types/mention'"
  },
  {
    "path": "dolma/src/tokens/types/block.ts",
    "chars": 176,
    "preview": "import { Token } from \"../../util/types/tokenTypes\";\n\nexport default {\n\tname: \"block\",\n\tregex: /\\`(.*?)\\`/gi,\n\n\tformat: "
  },
  {
    "path": "dolma/src/tokens/types/emoji.ts",
    "chars": 213,
    "preview": "import { Token } from \"../../util/types/tokenTypes\";\nimport emojiRegex from \"emoji-regex\"\n\nexport default {\n\tname: \"emoj"
  },
  {
    "path": "dolma/src/tokens/types/emote.ts",
    "chars": 183,
    "preview": "import { Token } from \"../../util/types/tokenTypes\";\n\nexport default {\n\tname: \"emote\",\n\tregex: /\\:([a-z0-9]+)\\:/gi,\n\n\tfo"
  },
  {
    "path": "dolma/src/tokens/types/link.ts",
    "chars": 185,
    "preview": "import { Token } from \"../../util/types/tokenTypes\";\n\nexport default {\n\tname: \"link\",\n\tregex: /(https?\\:\\/\\/[^ ]+)/gi,\n\n"
  },
  {
    "path": "dolma/src/tokens/types/mention.ts",
    "chars": 189,
    "preview": "import { Token } from \"../../util/types/tokenTypes\";\n\nexport default {\n\tname: \"mention\",\n\tregex: /\\@([a-zA-Z0-9_]{4,})/g"
  },
  {
    "path": "dolma/src/tokens/types/text.ts",
    "chars": 153,
    "preview": "import { Token } from \"../../util/types/tokenTypes\";\n\nexport default {\n\tname: \"text\",\n\n\tformat: (val) => val,\n  validate"
  },
  {
    "path": "dolma/src/util/regex.ts",
    "chars": 338,
    "preview": "export const validationRegex = {\n\tlink: /(https?\\:\\/\\/[^ ]+)/gi,\n\tmention: /\\@([a-zA-Z0-9_]{4,})/gi,\n\temote: /\\:([a-z0-9"
  },
  {
    "path": "dolma/src/util/types/tokenTypes.ts",
    "chars": 333,
    "preview": "import * as rawTokens from '../../tokens';\n\nexport type MessageTokenType = keyof typeof rawTokens.default;\n\nexport inter"
  },
  {
    "path": "dolma/tsconfig.json",
    "chars": 547,
    "preview": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./lib\",\n    \"target\": \"es5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \""
  },
  {
    "path": "globalkey/.gitignore",
    "chars": 32,
    "preview": "/target\nCargo.lock\n/.idea\n/dist\n"
  },
  {
    "path": "globalkey/Cargo.toml",
    "chars": 455,
    "preview": "[package]\nname = \"globalkey\"\ndescription = \"A rust node library for global key listeners in electron apps\"\nversion = \"0."
  },
  {
    "path": "globalkey/README.md",
    "chars": 492,
    "preview": "[![npm](https://img.shields.io/npm/v/globalkey)](https://www.npmjs.com/package/globalkey) ![downloads](https://img.shiel"
  },
  {
    "path": "globalkey/index.d.ts",
    "chars": 183,
    "preview": "declare module \"globalkey\" {\n    export function start(keydown_callback: (keys: string[]) => void, keyup_callback: (keys"
  },
  {
    "path": "globalkey/package.json",
    "chars": 250,
    "preview": "{\n  \"name\": \"@dogehouse/globalkey\",\n  \"version\": \"1.0.7\",\n  \"main\": \"dist/index.node\",\n  \"types\": \"index.d.ts\",\n  \"repos"
  },
  {
    "path": "globalkey/src/build.rs",
    "chars": 52,
    "preview": "fn main() {\n    node_bindgen::build::configure();\n}\n"
  },
  {
    "path": "globalkey/src/lib.rs",
    "chars": 1404,
    "preview": "use device_query::{DeviceQuery, DeviceState};\nuse node_bindgen::derive::node_bindgen;\nuse std::sync::Mutex;\n\n#[macro_use"
  },
  {
    "path": "globalkey/test.js",
    "chars": 169,
    "preview": "const globalkey = require('./dist');\n\nglobalkey\n    .start(x => console.log(`Keydown ${x}`), y => console.log(`Keyup ${y"
  },
  {
    "path": "kebab/.eslintrc.json",
    "chars": 8346,
    "preview": "{\n  \"env\": {\n    \"browser\": true,\n    \"es2021\": true,\n    \"node\": true\n  },\n  \"extends\": [\"eslint:recommended\", \"plugin:"
  },
  {
    "path": "kebab/.gitignore",
    "chars": 121,
    "preview": ".idea\nexamples/*/.env\nexamples/*/node_modules\nexamples/*/build\nexamples/*/.parcel-cache\nexamples/*/dist\nnode_modules\nlib"
  },
  {
    "path": "kebab/.prettierrc.js",
    "chars": 140,
    "preview": "module.exports = {\n  trailingComma: \"es5\",\n  tabWidth: 2,\n  semi: true,\n  singleQuote: false,\n  arrowParens: \"always\",\n "
  },
  {
    "path": "kebab/README.md",
    "chars": 2474,
    "preview": "# Kebab\nThe official DogeHouse API client.\n\n## Usage\n- **In web =>** see `examples/mediasoup-audio/` and `examples/react"
  },
  {
    "path": "kebab/examples/bot/README.md",
    "chars": 225,
    "preview": "# An example bot\n\n1. Put your bot's api key in `.env` as `DOGEHOUSE_API_KEY`\n2. Build the API package: `$ yarn` and `$ y"
  },
  {
    "path": "kebab/examples/bot/package.json",
    "chars": 295,
    "preview": "{\n  \"name\": \"example-bot\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"start\": \"node build/index.js\"\n  },"
  },
  {
    "path": "kebab/examples/bot/src/index.ts",
    "chars": 2234,
    "preview": "require(\"dotenv\").config();\n\nimport { raw, createClient, httpRequest, httpEndpoint, tokensToString, stringToToken } from"
  },
  {
    "path": "kebab/examples/bot/tsconfig.json",
    "chars": 257,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"module\": \"commonjs\",\n    \"outDir\": \"./build\",\n    \"strict\": true,\n   "
  },
  {
    "path": "kebab/examples/chat/README.md",
    "chars": 272,
    "preview": "# CLI chat (an example app)\n\n1. Put your access- and refresh-token in `.env` (`DOGEHOUSE_TOKEN`, `DOGEHOUSE_REFRESH_TOKE"
  },
  {
    "path": "kebab/examples/chat/package.json",
    "chars": 296,
    "preview": "{\n  \"name\": \"example-chat\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"start\": \"node build/index.js\"\n  }"
  },
  {
    "path": "kebab/examples/chat/src/index.ts",
    "chars": 1892,
    "preview": "require(\"dotenv\").config();\n\nimport readline from \"readline\";\nimport { raw, wrap, tokensToString, stringToToken } from \""
  },
  {
    "path": "kebab/examples/chat/tsconfig.json",
    "chars": 257,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"module\": \"commonjs\",\n    \"outDir\": \"./build\",\n    \"strict\": true,\n   "
  },
  {
    "path": "kebab/examples/create-bot/README.md",
    "chars": 442,
    "preview": "# An script to create a bot account\n\n1. Put your access and refresh-token in `.env` (`DOGEHOUSE_TOKEN`, `DOGEHOUSE_REFRE"
  },
  {
    "path": "kebab/examples/create-bot/package.json",
    "chars": 294,
    "preview": "{\n  \"name\": \"create-bot\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"start\": \"node build/index.js\"\n  },\n"
  },
  {
    "path": "kebab/examples/create-bot/src/index.ts",
    "chars": 671,
    "preview": "require(\"dotenv\").config();\n\nimport { raw, wrap } from \"@dogehouse/kebab\";\n\nconst main = async () => {\n  try {\n    const"
  },
  {
    "path": "kebab/examples/create-bot/tsconfig.json",
    "chars": 257,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"module\": \"commonjs\",\n    \"outDir\": \"./build\",\n    \"strict\": true,\n   "
  },
  {
    "path": "kebab/examples/mediasoup-audio/README.md",
    "chars": 262,
    "preview": "# Audio-only client (an example app)\n\n1. Put your access- and refresh-token in `.env` (`DOGEHOUSE_TOKEN`, `DOGEHOUSE_REF"
  },
  {
    "path": "kebab/examples/mediasoup-audio/package.json",
    "chars": 424,
    "preview": "{\n  \"name\": \"mediasoup-audio\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@dogehouse/kebab\": \"../"
  },
  {
    "path": "kebab/examples/mediasoup-audio/src/index.css",
    "chars": 104,
    "preview": "body {\n  margin: 0;\n}\n\n.current-role {\n  display: flex;\n  gap: 10px;\n}\n\n.cant-use-mic {\n  color: red;\n}\n"
  },
  {
    "path": "kebab/examples/mediasoup-audio/src/index.html",
    "chars": 321,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Kebab example</title>\n    <link rel=\"stylesheet\""
  },
  {
    "path": "kebab/examples/mediasoup-audio/src/index.ts",
    "chars": 2702,
    "preview": "import { wrap, audioWrap, raw } from \"@dogehouse/kebab\";\nimport { connect as mediasoupConnect } from \"@dogehouse/kebab/l"
  },
  {
    "path": "kebab/examples/mediasoup-audio/tsconfig.json",
    "chars": 475,
    "preview": "{\n  \"compilerOptions\": {\n    \"sourceMap\": true,\n    \"target\": \"es6\",\n    \"moduleResolution\": \"node\",\n    \"experimentalDe"
  },
  {
    "path": "kebab/examples/react-chat/README.md",
    "chars": 225,
    "preview": "# Text-only chat (an example app)\n\n1. Build the API package: `$ yarn` and `$ yarn build` in kebab's root directory\n2. Se"
  },
  {
    "path": "kebab/examples/react-chat/package.json",
    "chars": 1026,
    "preview": "{\n  \"name\": \"react-chat\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"homepage\": \".\",\n  \"dependencies\": {\n    \"@dogehous"
  },
  {
    "path": "kebab/examples/react-chat/public/index.html",
    "chars": 1721,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%PUBLIC_URL%/favicon.i"
  },
  {
    "path": "kebab/examples/react-chat/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": "kebab/examples/react-chat/public/robots.txt",
    "chars": 67,
    "preview": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "kebab/examples/react-chat/src/App.css",
    "chars": 385,
    "preview": ".chat-messages {\n  display: flex;\n  flex-direction: column;\n  gap: 10px;\n  overflow-y: visible;\n  flex-grow: 1;\n}\n\n.chat"
  },
  {
    "path": "kebab/examples/react-chat/src/App.tsx",
    "chars": 3697,
    "preview": "import React, { createContext, useContext, useEffect, useState } from \"react\";\nimport { Message, raw, Room, stringToToke"
  },
  {
    "path": "kebab/examples/react-chat/src/index.css",
    "chars": 193,
    "preview": "body {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Ubuntu\", sans-serif;\n}\n\nhtml, body, #root {\n  hei"
  },
  {
    "path": "kebab/examples/react-chat/src/index.tsx",
    "chars": 216,
    "preview": "import React from \"react\";\nimport { render } from \"react-dom\";\nimport \"./index.css\";\nimport { App } from \"./App\";\n\nrende"
  },
  {
    "path": "kebab/examples/react-chat/src/react-app-env.d.ts",
    "chars": 40,
    "preview": "/// <reference types=\"react-scripts\" />\n"
  },
  {
    "path": "kebab/examples/react-chat/tsconfig.json",
    "chars": 535,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\n      \"dom\",\n      \"dom.iterable\",\n      \"esnext\"\n    ],\n    "
  },
  {
    "path": "kebab/jest.config.js",
    "chars": 70,
    "preview": "module.exports = {\n  preset: 'ts-jest',\n  testEnvironment: 'node',\n};\n"
  },
  {
    "path": "kebab/package.json",
    "chars": 1031,
    "preview": "{\n  \"name\": \"@dogehouse/kebab\",\n  \"author\": \"Ilya Maximov <mail@overlisted.net> (https://overlisted.net)\",\n  \"bugs\": \"ht"
  },
  {
    "path": "kebab/src/README.md",
    "chars": 105,
    "preview": "http, websocket/wrapper.ts and websocket/responses.ts are deprecated and are only kept because of kibbeh\n"
  },
  {
    "path": "kebab/src/audio/audioWrapper.ts",
    "chars": 3111,
    "preview": "// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck because internet is unpredictable\n\nimport {"
  },
  {
    "path": "kebab/src/audio/interface.ts",
    "chars": 522,
    "preview": "import { raw, UUID } from \"..\";\nimport { RtpCapabilities, TransportOptions } from \"mediasoup-client/lib/types\";\n\nexport "
  },
  {
    "path": "kebab/src/audio/mediasoup-client.ts",
    "chars": 2853,
    "preview": "import { Device, Transport } from \"mediasoup-client/lib/types\";\nimport { ConnectFunction, ConsumerPlayer } from \"./inter"
  },
  {
    "path": "kebab/src/client/README.md",
    "chars": 156,
    "preview": "# Rewritten client\ni felt like the current system isn't declarative enough so i rewrote it just using typescript\n\n## How"
  },
  {
    "path": "kebab/src/client/http/bot.ts",
    "chars": 316,
    "preview": "import { Endpoint } from \"./endpoint\";\n\nexport const auth: Endpoint<\n  { apiKey: string },\n  { username: string, accessT"
  },
  {
    "path": "kebab/src/client/http/dev.ts",
    "chars": 212,
    "preview": "import { Endpoint } from \"./endpoint\";\n\nexport const testInfo: Endpoint<\n  { username: string },\n  { accessToken: string"
  },
  {
    "path": "kebab/src/client/http/endpoint.ts",
    "chars": 186,
    "preview": "export type Endpoint<O, R> = (options: O) => [string, RequestInit]; // eslint-disable-line @typescript-eslint/no-unused-"
  },
  {
    "path": "kebab/src/client/http/index.ts",
    "chars": 555,
    "preview": "import { Endpoint } from \"./endpoint\";\nimport fetch from \"isomorphic-fetch\";\n\nexport const apiUrl = \"https://api.dogehou"
  },
  {
    "path": "kebab/src/client/index.ts",
    "chars": 556,
    "preview": "import { request, Requester } from \"./requester\";\nimport { subscribe, Subscriber } from \"./subscriber\";\nimport { raw } f"
  },
  {
    "path": "kebab/src/client/requester/auth.ts",
    "chars": 139,
    "preview": "import { EmptyObject } from \"../type-util\";\n\nexport default interface Requests {\n  \"request:but:you:dont:want:to:use:thi"
  },
  {
    "path": "kebab/src/client/requester/chat.ts",
    "chars": 346,
    "preview": "import { MessageToken, UUID } from \"../..\";\n\nexport default interface Requests {\n  ban: {\n    request: { userId: UUID }\n"
  },
  {
    "path": "kebab/src/client/requester/index.ts",
    "chars": 1245,
    "preview": "import { raw } from \"../..\";\nimport UserRequests from \"./user\";\nimport RoomRequests from \"./room\";\nimport ChatRequests f"
  },
  {
    "path": "kebab/src/client/requester/misc.ts",
    "chars": 195,
    "preview": "import { Room, User } from \"../..\";\n\nexport default interface Requests {\n  search: {\n    request: { query: string },\n   "
  },
  {
    "path": "kebab/src/client/requester/room.ts",
    "chars": 2047,
    "preview": "import { Room, RoomAuth, RoomRole, User, UUID, PaginatedReply, PaginatedRequest } from \"../..\";\n\nexport default interfac"
  },
  {
    "path": "kebab/src/client/requester/user.ts",
    "chars": 1498,
    "preview": "import { Relationship, User, UUID, PaginatedReply, PaginatedRequest } from \"../..\";\n\nexport default interface Requests {"
  },
  {
    "path": "kebab/src/client/subscriber/index.ts",
    "chars": 1061,
    "preview": "import { raw } from \"../..\";\nimport LegacyRequests from \"./legacy\";\nimport { NormalObjectKey } from \"../type-util\";\n\ntyp"
  },
  {
    "path": "kebab/src/client/subscriber/legacy.ts",
    "chars": 671,
    "preview": "import { BooleanMap, Message, RoomDetails, User, UUID } from \"../../entities\";\n\nexport default interface Events {\n  new_"
  },
  {
    "path": "kebab/src/client/type-util.ts",
    "chars": 401,
    "preview": "export type NormalObjectKey<T> = Exclude<T, symbol | number>;\n\nexport type DefaultValues<T, D> = {\n  [K in keyof T]: D &"
  },
  {
    "path": "kebab/src/entities.ts",
    "chars": 3131,
    "preview": "import { ConsumerOptions } from \"mediasoup-client/lib/types\";\n\nexport type UUID = string;\n\nexport type RoomPeer = {\n  pe"
  },
  {
    "path": "kebab/src/http/bot.ts",
    "chars": 414,
    "preview": "import { request } from \"./raw\";\n\nexport type AuthResponse = {\n  username: string;\n  accessToken: string;\n  refreshToken"
  },
  {
    "path": "kebab/src/http/index.ts",
    "chars": 80,
    "preview": "export * from \"./raw\";\nexport * from \"./wrapper\";\nexport * as bot from \"./bot\";\n"
  },
  {
    "path": "kebab/src/http/raw.ts",
    "chars": 923,
    "preview": "import fetch from \"isomorphic-unfetch\";\n\nconst BASE_URL = \"https://api.dogehouse.tv\";\n\ninterface Options {\n  baseUrl?: s"
  },
  {
    "path": "kebab/src/http/wrapper.ts",
    "chars": 479,
    "preview": "import { Http } from \"./raw\";\n\nexport type AuthResponse = {\n  username: string;\n  accessToken: string;\n  refreshToken: s"
  },
  {
    "path": "kebab/src/index.ts",
    "chars": 228,
    "preview": "export * from \"./websocket\";\nexport { wrap as audioWrap } from \"./audio/audioWrapper\";\nexport * as http from \"./http\";\n\n"
  },
  {
    "path": "kebab/src/pagination.ts",
    "chars": 208,
    "preview": "export type PaginatedRequest<C extends number | string = number> = {\n  cursor: C,\n  limit: number\n};\n\nexport type Pagina"
  },
  {
    "path": "kebab/src/util/ast.test.ts",
    "chars": 334,
    "preview": "import { tokensToString, stringToToken } from \"./ast\";\n\ntest(\"to tokens\", () => {\n  expect(stringToToken(\"abcd\")).toEqua"
  },
  {
    "path": "kebab/src/util/ast.ts",
    "chars": 745,
    "preview": "import { MessageToken, TextToken } from \"..\";\n\n/**\n *\n * @param {string} string The string you want to convert to TextTo"
  },
  {
    "path": "kebab/src/util/index.ts",
    "chars": 23,
    "preview": "export * from \"./ast\";\n"
  },
  {
    "path": "kebab/src/websocket/index.ts",
    "chars": 86,
    "preview": "export * as raw from \"./raw\";\nexport * from \"./wrapper\";\nexport * from \"./responses\";\n"
  },
  {
    "path": "kebab/src/websocket/raw.ts",
    "chars": 8982,
    "preview": "import WebSocket from \"isomorphic-ws\";\nimport ReconnectingWebSocket from \"reconnecting-websocket\";\nimport { v4 as genera"
  },
  {
    "path": "kebab/src/websocket/responses.ts",
    "chars": 1189,
    "preview": "import { Room, RoomUser, ScheduledRoom, User, UUID } from \"../entities\";\n\nexport type GetTopPublicRoomsResponse = {\n  ro"
  },
  {
    "path": "kebab/src/websocket/wrapper.ts",
    "chars": 9026,
    "preview": "// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck because internet is unpredictable\n\nimport {"
  },
  {
    "path": "kebab/tsconfig.json",
    "chars": 300,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"skipLibCheck\": tru"
  },
  {
    "path": "kibbeh/.babelrc",
    "chars": 32,
    "preview": "{\n  \"presets\": [\"next/babel\"]\n}\n"
  },
  {
    "path": "kibbeh/.eslintignore",
    "chars": 57,
    "preview": "node_modules/\n\n*.spec.tsx\n*.spec.tsx.snap\nsrc/generated/\n"
  },
  {
    "path": "kibbeh/.eslintrc.json",
    "chars": 8755,
    "preview": "{\n  \"env\": {\n    \"browser\": true,\n    \"es2021\": true,\n    \"node\": true\n  },\n  \"extends\": [\n    \"eslint:recommended\",\n   "
  },
  {
    "path": "kibbeh/.gitignore",
    "chars": 28,
    "preview": "_\n.env.local\n.idea\nsw.js.map"
  },
  {
    "path": "kibbeh/.prettierignore",
    "chars": 42,
    "preview": "*.spec.tsx\n*.spec.tsx.snap\nsrc/generated/\n"
  },
  {
    "path": "kibbeh/.prettierrc.js",
    "chars": 117,
    "preview": "module.exports = {\n\ttrailingComma: \"es5\",\n\ttabWidth: 2,\n\tsemi: true,\n\tsingleQuote: false,\n\tarrowParens: \"always\",\n};\n"
  },
  {
    "path": "kibbeh/.storybook/main.js",
    "chars": 2807,
    "preview": "const path = require(\"path\");\n\nconst toPath = (_path) => path.join(process.cwd(), _path);\n\nmodule.exports = {\n    storie"
  }
]

// ... and 1145 more files (download for full content)

About this extraction

This page contains the full source code of the benawad/dogehouse GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1345 files (3.1 MB), approximately 895.8k tokens, and a symbol index with 1734 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.

Copied to clipboard!