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)

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

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

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;
```

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.

## 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`:

1. In a room make sure your transport is connected and your browser is supported (a warning will show up if it isn't)

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

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

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
================================================
[](https://www.npmjs.com/package/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 = {
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 └── 🐕.🏠
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 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": "[](https://www.npmjs.com/package/globalkey)  => 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.