├── .github ├── FUNDING.yml └── workflows │ └── build-and-test.yml ├── .gitignore ├── CB.sln ├── LICENSE ├── PRIVACYPOLICY.md ├── README.md ├── TERMSOFUSE.md ├── docker-compose.yml └── src ├── CB.Accessors ├── CB.Accessors.csproj ├── Contracts │ ├── IAllowConfigurationAccessor.cs │ ├── IChannelAccessor.cs │ ├── IChannelConfigurationAccessor.cs │ ├── IClipEmbedAccessor.cs │ ├── ICreatorAccessor.cs │ ├── ICreatorChannelAccessor.cs │ ├── IDLiveAccessor.cs │ ├── IDiscordLiveConfigurationAccessor.cs │ ├── IDropdownPayloadAccessor.cs │ ├── IFilterAccessor.cs │ ├── IFunAccessor.cs │ ├── IGuildAccessor.cs │ ├── IGuildConfigurationAccessor.cs │ ├── ILiveEmbedAccessor.cs │ ├── IMessageConfigurationAccessor.cs │ ├── IPicartoAccessor.cs │ ├── IPiczelAccessor.cs │ ├── IRoleConfigurationAccessor.cs │ ├── ITrovoAccessor.cs │ ├── ITwitchAccessor.cs │ ├── IUserAccessor.cs │ ├── IVodEmbedAccessor.cs │ └── IYouTubeAccessor.cs └── Implementations │ ├── AllowConfigurationAccessor.cs │ ├── ChannelAccessor.cs │ ├── ChannelConfigurationAccessor.cs │ ├── ClipEmbedAccessor.cs │ ├── CreatorAccessor.cs │ ├── CreatorChannelAccessor.cs │ ├── DLiveAccessor.cs │ ├── DiscordLiveConfigurationAccessor.cs │ ├── DropdownPayloadAccessor.cs │ ├── FilterAccessor.cs │ ├── FunAccessor.cs │ ├── GuildAccessor.cs │ ├── GuildConfigurationAccessor.cs │ ├── LiveEmbedAccessor.cs │ ├── MessageConfigurationAccessor.cs │ ├── PicartoAccessor.cs │ ├── PiczelAccessor.cs │ ├── RoleConfigurationAccessor.cs │ ├── TrovoAccessor.cs │ ├── TwitchAccessor.cs │ ├── UserAccessor.cs │ ├── VodEmbedAccessor.cs │ └── YouTubeAccessor.cs ├── CB.Antenna ├── CB.Antenna.csproj ├── Dockerfile ├── Program.cs ├── Properties │ └── launchSettings.json ├── Worker.cs ├── appsettings.Development.json └── appsettings.json ├── CB.Api ├── CB.Api.csproj ├── CB.Api.http ├── Controllers │ └── GuildController.cs ├── Dockerfile ├── Program.cs ├── Properties │ └── launchSettings.json ├── appsettings.Development.json └── appsettings.json ├── CB.Bot ├── CB.Bot.csproj ├── Commands │ ├── Application │ │ ├── BaseSlashCommands.cs │ │ ├── ChannelSlashCommands.cs │ │ ├── ConfigurationSlashCommands.cs │ │ ├── CustomizationCommands.cs │ │ ├── DiscordLiveSlashCommands.cs │ │ ├── DiscoverySlashCommands.cs │ │ ├── FilterSlashCommands.cs │ │ ├── FunSlashCommands.cs │ │ ├── ListSlashCommands.cs │ │ ├── MessageSlashCommands.cs │ │ ├── RoleSlashCommands.cs │ │ └── UtilityApplicationCommands.cs │ └── Text │ │ └── UtilityTextCommands.cs ├── Dockerfile ├── Program.cs ├── Properties │ └── launchSettings.json ├── Services │ ├── DiscordBotService.cs │ ├── GuildInteractionService.cs │ └── MessageInteractionService.cs ├── appsettings.Development.json └── appsettings.json ├── CB.Data ├── CB.Data.csproj ├── CbContext.cs ├── Entities │ ├── AllowConfiguration.cs │ ├── Channel.cs │ ├── ChannelConfiguration.cs │ ├── ClipEmbed.cs │ ├── Creator.cs │ ├── CreatorChannel.cs │ ├── DiscordLiveConfiguration.cs │ ├── DropdownPayload.cs │ ├── Filter.cs │ ├── FilterType.cs │ ├── FunStuff.cs │ ├── Game.cs │ ├── GameChannel.cs │ ├── Guild.cs │ ├── GuildConfiguration.cs │ ├── LiveEmbed.cs │ ├── MessageConfiguration.cs │ ├── Platform.cs │ ├── RoleConfiguration.cs │ ├── Team.cs │ ├── TeamChannel.cs │ ├── User.cs │ └── VodEmbed.cs └── Migrations │ ├── 20250710194734_InitialCreate.Designer.cs │ ├── 20250710194734_InitialCreate.cs │ ├── 20250710201805_AddGuilds.Designer.cs │ ├── 20250710201805_AddGuilds.cs │ ├── 20250710203427_AddCreators.Designer.cs │ ├── 20250710203427_AddCreators.cs │ ├── 20250710220537_AddConfigsAndChannel.Designer.cs │ ├── 20250710220537_AddConfigsAndChannel.cs │ ├── 20250710235930_PendingMigration.Designer.cs │ ├── 20250710235930_PendingMigration.cs │ ├── 20250711023200_7102025-931p.Designer.cs │ ├── 20250711023200_7102025-931p.cs │ ├── 20250715022843_7142025-928p.Designer.cs │ ├── 20250715022843_7142025-928p.cs │ ├── 20250715022909_7142025-929p.Designer.cs │ ├── 20250715022909_7142025-929p.cs │ ├── 20250716021538_7152025-906p.Designer.cs │ ├── 20250716021538_7152025-906p.cs │ ├── 20250717022001_7162025-919p.Designer.cs │ ├── 20250717022001_7162025-919p.cs │ ├── 20250717225501_7172025-554p.Designer.cs │ ├── 20250717225501_7172025-554p.cs │ ├── 20250717225700_7172025-556p.Designer.cs │ ├── 20250717225700_7172025-556p.cs │ ├── 20250717225843_7172025-558p.Designer.cs │ ├── 20250717225843_7172025-558p.cs │ ├── 20250718013457_7172025-834p.Designer.cs │ ├── 20250718013457_7172025-834p.cs │ ├── 20250718014125_7172025-841p.Designer.cs │ ├── 20250718014125_7172025-841p.cs │ ├── 20250718015544_7172025-855p.Designer.cs │ ├── 20250718015544_7172025-855p.cs │ ├── 20250724033914_7232025-1036p.Designer.cs │ ├── 20250724033914_7232025-1036p.cs │ └── CbContextModelSnapshot.cs ├── CB.Engines ├── CB.Engines.csproj ├── Contracts │ └── ICreatorEngine.cs └── Implementations │ └── CreatorEngine.cs ├── CB.Shared ├── CB.Shared.csproj ├── Constants.cs ├── Dtos │ ├── AllowConfigurationDto.cs │ ├── CbProfile.cs │ ├── ChannelConfigurationDto.cs │ ├── ChannelConfigurationSummaryDto.cs │ ├── ChannelDto.cs │ ├── ClipEmbedDto.cs │ ├── CreatorChannelDto.cs │ ├── CreatorDto.cs │ ├── DiscordLiveConfigurationDto.cs │ ├── DropdownPayloadDto.cs │ ├── FilterDto.cs │ ├── FilterTypeDto.cs │ ├── GameChannelDto.cs │ ├── GameDto.cs │ ├── GuildConfigurationDto.cs │ ├── GuildConfigurationSummaryDto.cs │ ├── GuildDto.cs │ ├── LiveEmbedDto.cs │ ├── MessageConfigurationDto.cs │ ├── PlatformDto.cs │ ├── RoleConfigurationDto.cs │ ├── TeamChannelDto.cs │ ├── TeamDto.cs │ ├── UserDto.cs │ └── VodEmbedDto.cs ├── Enums │ ├── ChannelType.cs │ ├── ChannelTypeTwitch.cs │ ├── ChannelTypeYouTube.cs │ ├── ConfiguredChannelType.cs │ ├── DropdownType.cs │ ├── FilterType.cs │ ├── MessageType.cs │ └── Platform.cs ├── Models │ ├── Bot │ │ ├── GenericDropdownPayload.cs │ │ ├── ListViewModel.cs │ │ └── YouTubeCreatorDropdownPayload.cs │ ├── DLive │ │ └── DLiveUser.cs │ ├── Picarto │ │ ├── Channel.cs │ │ ├── ChannelDetails.cs │ │ ├── ChatSettings.cs │ │ ├── Language.cs │ │ ├── PicartoChannel.cs │ │ ├── PicartoUser.cs │ │ └── Thumbnails.cs │ ├── Piczel │ │ └── PiczelChannel.cs │ ├── Trovo │ │ ├── TrovoChannel.cs │ │ └── TrovoUser.cs │ ├── Twitch │ │ ├── TwitchClientCredentials.cs │ │ ├── TwitchClipsResponse.cs │ │ ├── TwitchGameChannel.cs │ │ ├── TwitchGameSearchResponse.cs │ │ ├── TwitchStreamResponse.cs │ │ ├── TwitchTeam.cs │ │ └── TwitchUserResponse.cs │ └── YouTube │ │ ├── LiveChatStatusResponse.cs │ │ ├── PageInfo.cs │ │ ├── YouTubeChannelByIdResponse.cs │ │ ├── YouTubeChannelSearchList.cs │ │ ├── YouTubeChannelStatistics.cs │ │ ├── YouTubePlaylist.cs │ │ ├── YouTubeSearchListChannel.cs │ │ └── YouTubeVideoListResponse.cs ├── Responses │ ├── ChannelValidityResponse.cs │ ├── GameValidityResponse.cs │ ├── TeamValidityResponse.cs │ └── ValidityResponse.cs └── Utilities │ ├── ApiUtilities.cs │ └── StringUtilities.cs └── tests ├── CB.Tests.Accessors ├── CB.Tests.Accessors.csproj └── GuildAccessorTests.cs └── CB.Tests.Api ├── CB.Tests.Api.csproj └── GuildsControllerTests.cs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: MattTheDev 4 | patreon: CouchBot 5 | ko_fi: MattTheDev 6 | custom: "https://paypal.me/dawgeth" 7 | -------------------------------------------------------------------------------- /.github/workflows/build-and-test.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a .NET project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net 3 | 4 | name: .NET 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Setup .NET 20 | uses: actions/setup-dotnet@v4 21 | with: 22 | dotnet-version: 8.0.x 23 | - name: Restore dependencies 24 | run: dotnet restore 25 | - name: Build 26 | run: dotnet build --no-restore 27 | - name: Test 28 | run: dotnet test --no-build --verbosity normal 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## user-generated files 3 | 4 | # Build results 5 | [Bb]in/ 6 | [Oo]bj/ 7 | [Ll]og/ 8 | TestResults/ 9 | out/ 10 | generated/ 11 | 12 | # User-specific files 13 | *.user 14 | *.userosscache 15 | *.suo 16 | *.sln.docstates 17 | *.VC.db 18 | *.vscode/ 19 | .vscode/ 20 | 21 | # Rider 22 | .idea/ 23 | 24 | # VS for Mac 25 | *.userprefs 26 | 27 | # Auto-generated files 28 | *.pidb 29 | *.svd 30 | 31 | # OS junk 32 | .DS_Store 33 | Thumbs.db 34 | ehthumbs.db 35 | Desktop.ini 36 | 37 | # ASP.NET Scaffolding 38 | ScaffoldingReadMe.txt 39 | 40 | # dotCover 41 | *.dotCover 42 | 43 | # NCrunch 44 | _NCrunch_* 45 | .*crunch*.local.xml 46 | 47 | # VS Code launch configs 48 | .vscode/launch.json 49 | .vscode/tasks.json 50 | 51 | # docker-compose override 52 | docker-compose.override.yml 53 | 54 | # dotenv / secrets 55 | .env 56 | *.env 57 | 58 | # local db 59 | *.mdf 60 | *.ldf 61 | *.sqlite 62 | *.db 63 | *.db-shm 64 | *.db-wal 65 | 66 | # Entity Framework 67 | Migrations/*Snapshot.cs 68 | 69 | # NuGet 70 | *.nupkg 71 | .nuget/ 72 | packages/ 73 | project.lock.json 74 | project.fragment.lock.json 75 | artifacts/ 76 | 77 | # Global.json SDK resolver caches 78 | global.json.sdk.* 79 | 80 | # Visual Studio Code settings 81 | .vscode/* 82 | 83 | # ReSharper 84 | _ReSharper*/ 85 | *.[Rr]e[Ss]harper 86 | *.DotSettings.user 87 | 88 | # dotnet watch 89 | dotnet-watch.json 90 | 91 | # Logs 92 | *.log 93 | 94 | # Tye 95 | .tye/ 96 | 97 | # Coverage reports 98 | coverage/ 99 | coverage.*.xml 100 | *.lcov 101 | 102 | # Reports 103 | reports/ 104 | 105 | # Publish artifacts 106 | publish/ 107 | dist/ 108 | 109 | # Binaries 110 | *.dll 111 | *.exe 112 | *.app 113 | *.appx 114 | *.apk 115 | *.so 116 | *.dylib 117 | *.a 118 | *.lib 119 | *.pdb 120 | 121 | # Docker files 122 | docker-compose.override.yml 123 | docker-compose.*.yml 124 | 125 | # Terraform / infra junk 126 | .terraform/ 127 | *.tfstate 128 | *.tfstate.backup 129 | 130 | # Local certs 131 | *.pfx 132 | *.cer 133 | *.key 134 | 135 | # IDE settings backups 136 | *.bak 137 | *.orig 138 | 139 | # Temporary files 140 | ~$* 141 | *.tmp 142 | 143 | # .vs folder 144 | .vs/ 145 | 146 | -------------------------------------------------------------------------------- /PRIVACYPOLICY.md: -------------------------------------------------------------------------------- 1 | # Privacy Policy of CouchBot 2 | *Last Updated: 10/23/2022* 3 | 4 | This document contains the privacy policy for CouchBot. 5 | 6 | **Owner Contact Information** 7 | 8 | Matthew Smith - me@mattthedev.codes 9 | 10 | **Types of Data Collected** 11 | 12 | * Discord Data 13 | * User, Channel, and Guild Ids 14 | * Platform Data 15 | * Platform Channel Id, Channel Name, and meta data required to announce new content. 16 | * Analytics for website 17 | * Google analytics is used for tracking website visits and geographic demographics of visitors. 18 | 19 | **Storage of Data** 20 | 21 | * Discord and Platform Data 22 | * CouchBot Database and data backups. 23 | * Analytics data 24 | * Handled by Google 25 | 26 | **Retention of Data** 27 | 28 | * Discord Channel and Guild Data 29 | * Stored for the duration of the user of bot. Upon removal, the bot cleans up this data - not archiving it - hard delete. 30 | * Platform Data 31 | * Platform Channel Ids often are used across various servers. This data is held to ensure proper announcement of creators across multiple guilds. 32 | 33 | **Collection Methods** 34 | 35 | * **Commands** - The following data may be collected and temporarily stored when intentionally provided by a User via usage of a function of a Bot, hence this data is not collected automatically. Should a User provide data in this manner, they forego any rights pertaining to the content of the data provided. 36 | * Server specific configuration settings 37 | * Data and content for the task called 38 | * **Automatically Collected** - When users join/leave a server, their Discord User Id and Username are collected for potential linking for CouchBot's Discovery service. This service allows anyone to link their Discord and Platform accounts for easy announcing. 39 | * **via Stripe** - On subscription creation, a customer ID is generated per user. This is linked to a users Discord User record in the CouchBot database. 40 | 41 | **Why is this data collected?** 42 | 43 | For bot functionality, betterment of the bot, and to facilitate tracking of payments to ensure the bot is allowed into servers where he's paid for. 44 | 45 | **Who is the data shared with?** 46 | 47 | Absolutely nobody. There is only 1 developer. I am him. 48 | 49 | **Requesting Your Data** 50 | 51 | No problem! Email me at me@mattthedev.codes OR DM me via Discord and the data will be provided within 30 days. 52 | 53 | **Agreement** 54 | 55 | By using the CouchBot service, you are in agreement with this document. If you wish to remove your data from any of the systems - don't hesitate to reach out! 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |
3 | CouchBot 4 |
5 | CouchBot 6 |
7 |

8 | 9 |

Streaming Announcements, Role Hoisting, Cross-Platform.

10 | 11 |

12 | 13 | Discord Server 14 | 15 | 16 | Support CouchBot on Patreon! 17 | 18 | 19 | CouchBot on readthedocs.org 20 | 21 |

22 | 23 |

24 | 25 | 26 | 27 |

28 | 29 |

30 | Overview 31 | • 32 | Platforms Supported 33 | • 34 | Documentation 35 |

36 | 37 | # Overview 38 | 39 | Looking for CouchBot Documentation? 40 | 41 | [https://docs.couch.bot](https://docs.couch.bot) 42 | 43 | 44 | # Welcome to the Couch! 45 | 46 | Looking to engage your communities, let your Twitch, and YouTube viewers know when you've got new content, or know when your favorite creators have gone live? Look no further. CouchBot has been running for over 4 years, has gone through a few rewrites, and we're one of the best at doing what we do. 47 | 48 | CouchBot is monetized to ensure people that use the bot are willing to invest in its day to day, its growth, and its future. 49 | 50 | ## Want the Bot?! 51 | 52 | TBD 53 | 54 | #### How do I get my server id? 55 | Discord Resource: https://dis.gd/findmyid 56 | 57 | GIF Example: 58 | 59 | ![ex](https://i.imgur.com/sSzb8sf.gif) 60 | -------------------------------------------------------------------------------- /TERMSOFUSE.md: -------------------------------------------------------------------------------- 1 | # Terms of Use for CouchBot 2 | *Last Updated: 10/23/2022* 3 | 4 | This document contains the terms of use for CouchBot. 5 | 6 | **Owner Contact Information** 7 | 8 | Matthew Smith - me@mattthedev.codes 9 | 10 | These things can get super stuffy and formal - and while I should probably provide something long and drawn out ... I want to make sure the main bullet points are hit. 11 | 12 | 1. The bot can be removed from servers when the service is abused. Refunds will not be provided. 13 | 2. I, Matt Smith / CouchBot, am not responsible for the content delivered by CouchBot. If you have any concerns, please reach out to me at the email above. 14 | 15 | If you have any questions, comments, or feedback - don't hesitate to reach out. 16 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | db: 3 | image: postgres:16 4 | environment: 5 | POSTGRES_USER: myuser 6 | POSTGRES_PASSWORD: mypassword 7 | POSTGRES_DB: myappdb 8 | ports: 9 | - "5432:5432" 10 | volumes: 11 | - pgdata:/var/lib/postgresql/data 12 | 13 | api: 14 | build: 15 | context: . 16 | dockerfile: src/CB.Api/Dockerfile 17 | depends_on: 18 | - db 19 | environment: 20 | - ConnectionStrings__DefaultConnection=Host=db;Database=myappdb;Username=myuser;Password=mypassword 21 | - ASPNETCORE_ENVIRONMENT=Development 22 | ports: 23 | - "5000:8080" 24 | 25 | bot: 26 | build: 27 | context: . 28 | dockerfile: src/CB.Bot/Dockerfile 29 | depends_on: 30 | - db 31 | environment: 32 | - ConnectionStrings__DefaultConnection=Host=db;Database=myappdb;Username=myuser;Password=mypassword 33 | - ASPNETCORE_ENVIRONMENT=Development 34 | - BOT_TOKEN=BOT_TOKEN_HERE 35 | 36 | antenna: 37 | build: 38 | context: . 39 | dockerfile: src/CB.Antenna/Dockerfile 40 | depends_on: 41 | - db 42 | environment: 43 | - ConnectionStrings__DefaultConnection=Host=db;Database=myappdb;Username=myuser;Password=mypassword 44 | - ASPNETCORE_ENVIRONMENT=Development 45 | 46 | volumes: 47 | pgdata: 48 | -------------------------------------------------------------------------------- /src/CB.Accessors/CB.Accessors.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IAllowConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IAllowConfigurationAccessor 7 | { 8 | Task> GetAllAsync(); 9 | 10 | Task GetByIdAsync(string id); 11 | 12 | Task CreateAsync(AllowConfiguration entity); 13 | 14 | Task UpdateAsync(AllowConfigurationDto entity); 15 | 16 | Task DeleteAsync(string id); 17 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IChannelAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IChannelAccessor 7 | { 8 | Task> GetAllAsync(); 9 | 10 | Task GetByIdAsync(string id); 11 | 12 | Task GetChannelConfigurationSummaryByIdAsync(string id); 13 | 14 | Task CreateAsync(Channel entity); 15 | 16 | Task UpdateAsync(ChannelDto entity); 17 | 18 | Task DeleteAsync(string id); 19 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IChannelConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IChannelConfigurationAccessor 7 | { 8 | Task> GetAllAsync(); 9 | 10 | Task GetByIdAsync(string id); 11 | 12 | Task CreateAsync(ChannelConfiguration entity); 13 | 14 | Task UpdateAsync(string id, 15 | ChannelConfigurationDto dto); 16 | 17 | Task DeleteAsync(string id); 18 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IClipEmbedAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Dtos; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface IClipEmbedAccessor 6 | { 7 | Task GetByIdAsync(string guildId); 8 | 9 | Task UpdateAsync(ClipEmbedDto entity); 10 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/ICreatorAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | using CB.Shared.Enums; 4 | using Platform = CB.Shared.Enums.Platform; 5 | 6 | namespace CB.Accessors.Contracts; 7 | 8 | public interface ICreatorAccessor 9 | { 10 | Task> GetAllAsync(); 11 | 12 | Task GetByIdAsync(long id); 13 | 14 | Task GetByChannelIdAndPlatformAsync(string channelId, Platform platform); 15 | 16 | Task CreateAsync(Creator entity); 17 | 18 | Task UpdateAsync(string id, 19 | Creator entity); 20 | 21 | Task DeleteAsync(string id); 22 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/ICreatorChannelAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | // ReSharper disable UnusedMember.Global 5 | 6 | namespace CB.Accessors.Contracts; 7 | 8 | public interface ICreatorChannelAccessor 9 | { 10 | Task> GetAllAsync(); 11 | 12 | Task GetAsync(long creatorId, 13 | string channelId, 14 | int channelTypeId); 15 | 16 | Task CreateAsync(CreatorChannel entity); 17 | 18 | Task UpdateAsync(string id, 19 | CreatorChannelDto entity); 20 | 21 | Task DeleteAsync(long creatorId, 22 | string channelId, 23 | int channelTypeId); 24 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IDLiveAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Models.DLive; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface IDLiveAccessor 6 | { 7 | Task GetUserByDisplayNameAsync(string displayName); 8 | 9 | Task GetUserByUsernameAsync(string username); 10 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IDiscordLiveConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IDiscordLiveConfigurationAccessor 7 | { 8 | Task CreateAsync(DiscordLiveConfiguration entity); 9 | Task GetByIdAsync(string guildId); 10 | Task UpdateAsync(DiscordLiveConfigurationDto updated); 11 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IDropdownPayloadAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IDropdownPayloadAccessor 7 | { 8 | Task> GetAllAsync(); 9 | 10 | Task GetByIdAsync(int id); 11 | 12 | Task CreateAsync(DropdownPayload entity); 13 | 14 | //Task UpdateAsync(string id, 15 | // DropdownPayload entity); 16 | 17 | Task DeleteAsync(string id); 18 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IFilterAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IFilterAccessor 7 | { 8 | Task CreateAsync(Filter entity); 9 | 10 | Task> GetAllAsync(); 11 | 12 | Task> GetAllAsync(string guildId); 13 | 14 | Task DeleteAsync(FilterDto filter); 15 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IFunAccessor.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Accessors.Contracts; 2 | 3 | public interface IFunAccessor 4 | { 5 | Task IncrementHaiBai(); 6 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IGuildAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IGuildAccessor 7 | { 8 | Task> GetAllAsync(); 9 | 10 | Task GetByIdAsync(string id); 11 | 12 | Task GetConfigurationSummaryByIdAsync(string id); 13 | 14 | Task CreateAsync(Guild entity); 15 | 16 | Task UpdateAsync(string id, 17 | Guild entity); 18 | 19 | Task DeleteAsync(string id); 20 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IGuildConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IGuildConfigurationAccessor 7 | { 8 | Task> GetAllAsync(); 9 | 10 | Task GetByIdAsync(string id); 11 | 12 | Task CreateAsync(GuildConfiguration entity); 13 | 14 | Task UpdateAsync(string id, 15 | GuildConfigurationDto entity); 16 | 17 | Task DeleteAsync(string id); 18 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/ILiveEmbedAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Dtos; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface ILiveEmbedAccessor 6 | { 7 | Task GetByIdAsync(string guildId); 8 | 9 | Task UpdateAsync(LiveEmbedDto entity); 10 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IMessageConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Dtos; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface IMessageConfigurationAccessor 6 | { 7 | Task UpdateAsync(MessageConfigurationDto updated); 8 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IPicartoAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Models.Picarto; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface IPicartoAccessor 6 | { 7 | Task RetrieveAsync(string accessToken); 8 | 9 | Task GetChannelByNameAsync(string name); 10 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IPiczelAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Models.Piczel; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface IPiczelAccessor 6 | { 7 | Task GetChannelByNameAsync(string name); 8 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IRoleConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IRoleConfigurationAccessor 7 | { 8 | Task> GetAllAsync(); 9 | 10 | Task GetByIdAsync(string id); 11 | 12 | Task CreateAsync(RoleConfiguration entity); 13 | 14 | Task UpdateAsync(RoleConfigurationDto entity); 15 | 16 | Task DeleteAsync(string id); 17 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/ITrovoAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Models.Trovo; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface ITrovoAccessor 6 | { 7 | Task GetUserByNameAsync(string name); 8 | 9 | Task GetChannelByIdAsync(int id); 10 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/ITwitchAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Models.Twitch; 2 | using CouchBot.Domain.Models.Twitch; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface ITwitchAccessor 7 | { 8 | Task GetStreamsAsync(string twitchIdList); 9 | 10 | Task GetUsersAsync(string twitchIdList); 11 | 12 | Task GetTwitchTeamByNameAsync(string name); 13 | 14 | Task GetStreamsByGameNameAsync(string gameName); 15 | 16 | Task SearchForGameByNameAsync(string gameName); 17 | 18 | Task GetClipsAsync(string channelId); 19 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IUserAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Data.Entities; 2 | using CB.Shared.Dtos; 3 | 4 | namespace CB.Accessors.Contracts; 5 | 6 | public interface IUserAccessor 7 | { 8 | Task> GetAllAsync(); 9 | 10 | Task GetByIdAsync(string id); 11 | 12 | Task CreateAsync(User entity); 13 | 14 | Task UpdateAsync(string id, 15 | User entity); 16 | 17 | Task DeleteAsync(string id); 18 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IVodEmbedAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Dtos; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface IVodEmbedAccessor 6 | { 7 | Task GetByIdAsync(string guildId); 8 | 9 | Task UpdateAsync(VodEmbedDto entity); 10 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Contracts/IYouTubeAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Models.YouTube; 2 | 3 | namespace CB.Accessors.Contracts; 4 | 5 | public interface IYouTubeAccessor 6 | { 7 | Task GetVideoByIdAsync(string id); 8 | 9 | Task GetChannelStatisticsByIdAsync(string id); 10 | 11 | Task GetPlaylistItemsByPlaylistIdAsync(string playlistId); 12 | 13 | Task GetYouTubeChannelByQueryAsync(string name); 14 | 15 | Task GetYouTubeChannelByIdAsync(string channelId); 16 | 17 | Task GetLiveChannelsAsync(string channelIds); 18 | 19 | Task GetVideoDetailsAsync(string videoId); 20 | 21 | Task> GetYouTubeChannelsByIdsAsync(string channelIds); 22 | 23 | Task GetYouTubeChannelByUsernameAsync(string username); 24 | 25 | Task IsYouTubeShortAsync(string videoId); 26 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/AllowConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class AllowConfigurationAccessor(CbContext context, 12 | IMapper mapper) 13 | : IAllowConfigurationAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .AllowConfigurations 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetByIdAsync(string id) => context.AllowConfigurations 22 | .AsNoTracking() 23 | .Where(g => g.GuildId == id) 24 | .ProjectTo(mapper.ConfigurationProvider) 25 | .FirstOrDefaultAsync(); 26 | 27 | public async Task CreateAsync(AllowConfiguration entity) 28 | { 29 | context.AllowConfigurations.Add(entity); 30 | await context 31 | .SaveChangesAsync() 32 | .ConfigureAwait(false); 33 | 34 | return mapper.Map(entity); 35 | } 36 | 37 | public async Task UpdateAsync(AllowConfigurationDto updated) 38 | { 39 | var allowConfiguration = await context 40 | .AllowConfigurations 41 | .FirstOrDefaultAsync( x => x.GuildId == updated.GuildId) 42 | .ConfigureAwait(false); 43 | 44 | if (allowConfiguration == null) 45 | { 46 | return null; 47 | } 48 | 49 | allowConfiguration.AllowCrosspost = updated.AllowCrosspost; 50 | allowConfiguration.AllowDiscordLive = updated.AllowDiscordLive; 51 | allowConfiguration.AllowFfa = updated.AllowFfa; 52 | allowConfiguration.AllowGoodbyes = updated.AllowGoodbyes; 53 | allowConfiguration.AllowGreetings = updated.AllowGreetings; 54 | allowConfiguration.AllowLive = updated.AllowLive; 55 | allowConfiguration.AllowLiveDiscovery = updated.AllowLiveDiscovery; 56 | allowConfiguration.AllowPublished = updated.AllowPublished; 57 | allowConfiguration.AllowStreamVod = updated.AllowStreamVod; 58 | allowConfiguration.AllowThumbnails = updated.AllowThumbnails; 59 | 60 | await context 61 | .SaveChangesAsync() 62 | .ConfigureAwait(false); 63 | 64 | return mapper.Map(allowConfiguration); 65 | } 66 | 67 | public async Task DeleteAsync(string id) 68 | { 69 | var allowConfiguration = await context 70 | .AllowConfigurations 71 | .FindAsync(id) 72 | .ConfigureAwait(false); 73 | 74 | if (allowConfiguration == null) 75 | { 76 | return false; 77 | } 78 | 79 | context.AllowConfigurations.Remove(allowConfiguration); 80 | await context 81 | .SaveChangesAsync() 82 | .ConfigureAwait(false); 83 | 84 | return true; 85 | } 86 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/ChannelAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class ChannelAccessor(CbContext context, 12 | IMapper mapper) 13 | : IChannelAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .Channels 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetByIdAsync(string id) => context.Channels 22 | .AsNoTracking() 23 | .Where(g => g.Id == id) 24 | .ProjectTo(mapper.ConfigurationProvider) 25 | .FirstOrDefaultAsync(); 26 | 27 | public Task GetChannelConfigurationSummaryByIdAsync(string id) => context.Channels 28 | .AsNoTracking() 29 | .Where(g => g.Id == id) 30 | .ProjectTo(mapper.ConfigurationProvider) 31 | .FirstOrDefaultAsync(); 32 | 33 | public async Task CreateAsync(Channel entity) 34 | { 35 | entity.CreatedDate = DateTime.UtcNow; 36 | entity.ModifiedDate = DateTime.UtcNow; 37 | 38 | context.Channels.Add(entity); 39 | await context 40 | .SaveChangesAsync() 41 | .ConfigureAwait(false); 42 | 43 | return mapper.Map(entity); 44 | } 45 | 46 | public async Task UpdateAsync(ChannelDto updated) 47 | { 48 | var channel = await context 49 | .Channels 50 | .FirstOrDefaultAsync(x => x.Id == updated.Id) 51 | .ConfigureAwait(false); 52 | 53 | if (channel == null) 54 | { 55 | return null; 56 | } 57 | 58 | channel.DisplayName = updated.DisplayName; 59 | channel.ModifiedDate = DateTime.UtcNow; 60 | 61 | await context 62 | .SaveChangesAsync() 63 | .ConfigureAwait(false); 64 | 65 | return mapper.Map(channel); 66 | } 67 | 68 | public async Task DeleteAsync(string id) 69 | { 70 | var channel = await context 71 | .Channels 72 | .FindAsync(id) 73 | .ConfigureAwait(false); 74 | 75 | if (channel == null) 76 | { 77 | return false; 78 | } 79 | 80 | context.Channels.Remove(channel); 81 | await context 82 | .SaveChangesAsync() 83 | .ConfigureAwait(false); 84 | 85 | return true; 86 | } 87 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/ChannelConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class ChannelConfigurationAccessor(CbContext context, 12 | IMapper mapper) 13 | : IChannelConfigurationAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .ChannelConfigurations 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetByIdAsync(string id) => context.ChannelConfigurations 22 | .AsNoTracking() 23 | .Where(g => g.GuildId == id) 24 | .ProjectTo(mapper.ConfigurationProvider) 25 | .FirstOrDefaultAsync(); 26 | 27 | public async Task CreateAsync(ChannelConfiguration entity) 28 | { 29 | context.ChannelConfigurations.Add(entity); 30 | await context 31 | .SaveChangesAsync() 32 | .ConfigureAwait(false); 33 | 34 | return mapper.Map(entity); 35 | } 36 | 37 | public async Task UpdateAsync(string id, 38 | ChannelConfigurationDto dto) 39 | { 40 | var channelConfiguration = await context 41 | .ChannelConfigurations 42 | .FindAsync(id) 43 | .ConfigureAwait(false); 44 | 45 | if (channelConfiguration == null) 46 | { 47 | return null; 48 | } 49 | 50 | channelConfiguration.GreetingChannelId = dto.GreetingChannelId; 51 | channelConfiguration.GoodbyeChannelId = dto.GoodbyeChannelId; 52 | channelConfiguration.LiveChannelId = dto.LiveChannelId; 53 | channelConfiguration.DiscordLiveChannelId = dto.DiscordLiveChannelId; 54 | 55 | await context 56 | .SaveChangesAsync() 57 | .ConfigureAwait(false); 58 | 59 | return mapper.Map(channelConfiguration); 60 | } 61 | 62 | public async Task DeleteAsync(string id) 63 | { 64 | var channelConfiguration = await context 65 | .ChannelConfigurations 66 | .FindAsync(id) 67 | .ConfigureAwait(false); 68 | 69 | if (channelConfiguration == null) 70 | { 71 | return false; 72 | } 73 | 74 | context.ChannelConfigurations.Remove(channelConfiguration); 75 | await context 76 | .SaveChangesAsync() 77 | .ConfigureAwait(false); 78 | 79 | return true; 80 | } 81 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/ClipEmbedAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using CB.Accessors.Contracts; 3 | using CB.Data; 4 | using CB.Shared.Dtos; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace CB.Accessors.Implementations; 8 | 9 | public class ClipEmbedAccessor(CbContext context, 10 | IMapper mapper) 11 | : IClipEmbedAccessor 12 | { 13 | public async Task GetByIdAsync(string guildId) 14 | { 15 | var entity = await context 16 | .ClipEmbeds 17 | .FirstOrDefaultAsync(x => x.GuildId == guildId); 18 | 19 | if (entity == null) 20 | { 21 | entity = new() 22 | { 23 | GuildId = guildId, 24 | Header = "New Clip @ %CHANNEL%", 25 | Description = "%DESCRIPTION%", 26 | Footer = "Powered by 100% Couch • Created by %CHANNEL%", 27 | WatchButton = "Watch this Clip!", 28 | MoreButton = "And More!", 29 | }; 30 | 31 | await context 32 | .ClipEmbeds 33 | .AddAsync(entity); 34 | await context 35 | .SaveChangesAsync(); 36 | } 37 | 38 | return mapper.Map(entity); 39 | } 40 | 41 | public async Task UpdateAsync(ClipEmbedDto entity) 42 | { 43 | var embed = await context 44 | .ClipEmbeds 45 | .FirstOrDefaultAsync(x => x.GuildId == entity.GuildId) 46 | .ConfigureAwait(false); 47 | 48 | if (embed == null) 49 | { 50 | return null; 51 | } 52 | 53 | embed.Description = entity.Description; 54 | embed.Footer = entity.Description; 55 | embed.Header = entity.Description; 56 | embed.MoreButton = entity.Description; 57 | embed.WatchButton = entity.WatchButton; 58 | 59 | await context 60 | .SaveChangesAsync() 61 | .ConfigureAwait(false); 62 | 63 | return mapper.Map(embed); 64 | } 65 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/CreatorAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using CB.Shared.Enums; 8 | using Microsoft.EntityFrameworkCore; 9 | using Platform = CB.Shared.Enums.Platform; 10 | 11 | namespace CB.Accessors.Implementations; 12 | 13 | public class CreatorAccessor(CbContext context, 14 | IMapper mapper) 15 | : ICreatorAccessor 16 | { 17 | public Task> GetAllAsync() => context 18 | .Creators 19 | .AsNoTracking() 20 | .ProjectTo(mapper.ConfigurationProvider) 21 | .ToListAsync(); 22 | 23 | public Task GetByIdAsync(long id) => context.Creators 24 | .AsNoTracking() 25 | .Where(g => g.Id == id) 26 | .ProjectTo(mapper.ConfigurationProvider) 27 | .FirstOrDefaultAsync(); 28 | 29 | public Task GetByChannelIdAndPlatformAsync(string channelId, Platform platform) => context.Creators 30 | .AsNoTracking() 31 | .Where(g => g.ChannelId == channelId && 32 | g.PlatformId == (int)platform) 33 | .ProjectTo(mapper.ConfigurationProvider) 34 | .FirstOrDefaultAsync(); 35 | 36 | public async Task CreateAsync(Creator entity) 37 | { 38 | entity.CreatedDate = DateTime.UtcNow; 39 | entity.ModifiedDate = DateTime.UtcNow; 40 | 41 | context.Creators.Add(entity); 42 | await context 43 | .SaveChangesAsync() 44 | .ConfigureAwait(false); 45 | 46 | return mapper.Map(entity); 47 | } 48 | 49 | public async Task UpdateAsync(string id, 50 | Creator updated) 51 | { 52 | var creator = await context 53 | .Creators 54 | .FindAsync(id) 55 | .ConfigureAwait(false); 56 | 57 | if (creator == null) 58 | { 59 | return null; 60 | } 61 | 62 | creator.DisplayName = updated.DisplayName; 63 | creator.ModifiedDate = DateTime.UtcNow; 64 | 65 | await context 66 | .SaveChangesAsync() 67 | .ConfigureAwait(false); 68 | 69 | return mapper.Map(creator); 70 | } 71 | 72 | public async Task DeleteAsync(string id) 73 | { 74 | var creator = await context 75 | .Creators 76 | .FindAsync(id) 77 | .ConfigureAwait(false); 78 | 79 | if (creator == null) 80 | { 81 | return false; 82 | } 83 | 84 | context.Creators.Remove(creator); 85 | await context 86 | .SaveChangesAsync() 87 | .ConfigureAwait(false); 88 | 89 | return true; 90 | } 91 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/CreatorChannelAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class CreatorChannelAccessor(CbContext context, 12 | IMapper mapper) 13 | : ICreatorChannelAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .CreatorChannels 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetAsync(long creatorId, 22 | string channelId, 23 | int channelTypeId) => context.CreatorChannels 24 | .AsNoTracking() 25 | .Where(g => g.CreatorId == creatorId && 26 | g.ChannelId == channelId && 27 | g.ChannelTypeId == channelTypeId) 28 | .ProjectTo(mapper.ConfigurationProvider) 29 | .FirstOrDefaultAsync(); 30 | 31 | public async Task CreateAsync(CreatorChannel entity) 32 | { 33 | context.CreatorChannels.Add(entity); 34 | await context 35 | .SaveChangesAsync() 36 | .ConfigureAwait(false); 37 | 38 | return mapper.Map(entity); 39 | } 40 | 41 | public async Task UpdateAsync(string id, 42 | CreatorChannelDto updated) 43 | { 44 | var creatorChannel = await context 45 | .CreatorChannels 46 | .FindAsync(id) 47 | .ConfigureAwait(false); 48 | 49 | if (creatorChannel == null) 50 | { 51 | return null; 52 | } 53 | 54 | creatorChannel.CustomMessage = updated.CustomMessage; 55 | creatorChannel.ChannelTypeId = updated.ChannelTypeId; 56 | 57 | await context 58 | .SaveChangesAsync() 59 | .ConfigureAwait(false); 60 | 61 | return mapper.Map(creatorChannel); 62 | } 63 | 64 | public async Task DeleteAsync(long creatorId, 65 | string channelId, 66 | int channelTypeId) 67 | { 68 | var creatorChannel = await context 69 | .CreatorChannels 70 | .FirstOrDefaultAsync(x => x.CreatorId == creatorId && 71 | x.ChannelId == channelId && 72 | x.ChannelTypeId == channelTypeId) 73 | .ConfigureAwait(false); 74 | 75 | if (creatorChannel == null) 76 | { 77 | return false; 78 | } 79 | 80 | context.CreatorChannels.Remove(creatorChannel); 81 | await context 82 | .SaveChangesAsync() 83 | .ConfigureAwait(false); 84 | 85 | return true; 86 | } 87 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/DLiveAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Shared.Models.DLive; 3 | using CB.Shared.Utilities; 4 | using Newtonsoft.Json; 5 | 6 | namespace CB.Accessors.Implementations; 7 | 8 | public class DLiveAccessor : IDLiveAccessor 9 | { 10 | private const string DLiveUrl = "https://graphigo.prd.dlive.tv/"; 11 | private const string GetUserByDisplayNameQuery = 12 | "query {" + 13 | "userByDisplayName(displayname:\"%DISPLAYNAME%\") {" + 14 | " id" + 15 | " username" + 16 | " displayname" + 17 | "}" + 18 | "}"; 19 | 20 | private const string GetUserByUsernameQuery = 21 | "query {" + 22 | "user(username:\"%USERNAME%\") { " + 23 | "displayname " + 24 | "avatar " + 25 | "followers {" + 26 | "totalCount " + 27 | "} " + 28 | "livestream { " + 29 | "thumbnailUrl " + 30 | "title " + 31 | "watchingCount " + 32 | "category " + 33 | "{ " + 34 | "title " + 35 | "} " + 36 | "} " + 37 | "} " + 38 | "}"; 39 | 40 | public async Task GetUserByDisplayNameAsync(string displayName) 41 | { 42 | var query = GetUserByDisplayNameQuery.Replace("%DISPLAYNAME%", displayName); 43 | 44 | var dliveQuery = new DLiveQuery 45 | { 46 | Query = query, 47 | OperationName = null, 48 | Variables = null 49 | }; 50 | 51 | return await ApiUtilities 52 | .PostApiHelper(DLiveUrl, 53 | payloadString: JsonConvert.SerializeObject(dliveQuery)) 54 | .ConfigureAwait(false); 55 | } 56 | 57 | public async Task GetUserByUsernameAsync(string username) 58 | { 59 | var query = GetUserByUsernameQuery.Replace("%USERNAME%", username); 60 | 61 | var dliveQuery = new DLiveQuery 62 | { 63 | Query = query, 64 | OperationName = null, 65 | Variables = null 66 | }; 67 | 68 | return await ApiUtilities 69 | .PostApiHelper(DLiveUrl, 70 | payloadString: JsonConvert.SerializeObject(dliveQuery)) 71 | .ConfigureAwait(false); 72 | } 73 | } 74 | 75 | public class DLiveQuery 76 | { 77 | public string Query { get; set; } 78 | 79 | public object Variables { get; set; } 80 | 81 | public object OperationName { get; set; } 82 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/DiscordLiveConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class DiscordLiveConfigurationAccessor(CbContext context, 12 | IMapper mapper) 13 | : IDiscordLiveConfigurationAccessor 14 | { 15 | public async Task CreateAsync(DiscordLiveConfiguration entity) 16 | { 17 | context.DiscordLiveConfigurations.Add(entity); 18 | await context 19 | .SaveChangesAsync() 20 | .ConfigureAwait(false); 21 | 22 | return mapper.Map(entity); 23 | } 24 | 25 | public Task GetByIdAsync(string guildId) => 26 | context.DiscordLiveConfigurations 27 | .AsNoTracking() 28 | .Where(g => g.GuildId == guildId) 29 | .ProjectTo(mapper.ConfigurationProvider) 30 | .FirstOrDefaultAsync(); 31 | 32 | 33 | public async Task UpdateAsync(DiscordLiveConfigurationDto updated) 34 | { 35 | var entity = await context 36 | .DiscordLiveConfigurations 37 | .FirstOrDefaultAsync(x => x.GuildId == updated.GuildId) 38 | .ConfigureAwait(false); 39 | 40 | if (entity == null) 41 | { 42 | return null; 43 | } 44 | 45 | entity.Description = updated.Description; 46 | entity.Footer = updated.Footer; 47 | entity.Header = updated.Header; 48 | entity.MentionRoleId = updated.MentionRoleId; 49 | entity.Message = updated.Message; 50 | 51 | await context 52 | .SaveChangesAsync() 53 | .ConfigureAwait(false); 54 | 55 | return mapper.Map(entity); 56 | } 57 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/DropdownPayloadAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class DropdownPayloadAccessor(CbContext context, 12 | IMapper mapper) 13 | : IDropdownPayloadAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .DropdownPayloads 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetByIdAsync(int id) => context.DropdownPayloads 22 | .AsNoTracking() 23 | .Where(g => g.Id == id) 24 | .ProjectTo(mapper.ConfigurationProvider) 25 | .FirstOrDefaultAsync(); 26 | 27 | public async Task CreateAsync(DropdownPayload entity) 28 | { 29 | context.DropdownPayloads.Add(entity); 30 | await context 31 | .SaveChangesAsync() 32 | .ConfigureAwait(false); 33 | 34 | return mapper.Map(entity); 35 | } 36 | 37 | public async Task DeleteAsync(string id) 38 | { 39 | var dropdownPayload = await context 40 | .DropdownPayloads 41 | .FindAsync(id) 42 | .ConfigureAwait(false); 43 | 44 | if (dropdownPayload == null) 45 | { 46 | return false; 47 | } 48 | 49 | context.DropdownPayloads.Remove(dropdownPayload); 50 | await context 51 | .SaveChangesAsync() 52 | .ConfigureAwait(false); 53 | 54 | return true; 55 | } 56 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/FilterAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class FilterAccessor(CbContext context, 12 | IMapper mapper) : IFilterAccessor 13 | { 14 | public async Task CreateAsync(Filter entity) 15 | { 16 | context.Filters.Add(entity); 17 | await context 18 | .SaveChangesAsync() 19 | .ConfigureAwait(false); 20 | 21 | return mapper.Map(entity); 22 | } 23 | 24 | public Task> GetAllAsync() => 25 | context 26 | .Filters 27 | .AsNoTracking() 28 | .ProjectTo(mapper.ConfigurationProvider) 29 | .ToListAsync(); 30 | 31 | public Task> GetAllAsync(string guildId) => 32 | context 33 | .Filters 34 | .AsNoTracking() 35 | .Where(x => x.GuildId == guildId) 36 | .ProjectTo(mapper.ConfigurationProvider) 37 | .ToListAsync(); 38 | 39 | public async Task DeleteAsync(FilterDto filter) 40 | { 41 | var entity = await context 42 | .Filters 43 | .FirstOrDefaultAsync(x => x.Id == filter.Id) 44 | .ConfigureAwait(false); 45 | 46 | if (entity == null) 47 | { 48 | return false; 49 | } 50 | 51 | context.Filters.Remove(entity); 52 | await context 53 | .SaveChangesAsync() 54 | .ConfigureAwait(false); 55 | 56 | return true; 57 | } 58 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/FunAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Data; 3 | using CB.Data.Entities; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace CB.Accessors.Implementations; 7 | 8 | public class FunAccessor(CbContext context) : IFunAccessor 9 | { 10 | public async Task IncrementHaiBai() 11 | { 12 | var result = await context 13 | .FunStuff 14 | .FromSqlRaw("UPDATE \"FunStuff\" SET \"HaiBaiCount\" = \"HaiBaiCount\" + 1 RETURNING \"HaiBaiCount\"") 15 | .ToListAsync(); 16 | 17 | return result.First().HaiBaiCount; 18 | } 19 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/GuildAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class GuildAccessor(CbContext context, 12 | IMapper mapper) 13 | : IGuildAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .Guilds 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetByIdAsync(string id) => context.Guilds 22 | .AsNoTracking() 23 | .Where(g => g.Id == id) 24 | .ProjectTo(mapper.ConfigurationProvider) 25 | .FirstOrDefaultAsync(); 26 | 27 | public Task GetConfigurationSummaryByIdAsync(string id) => context.Guilds 28 | .AsNoTracking() 29 | .Where(g => g.Id == id) 30 | .ProjectTo(mapper.ConfigurationProvider) 31 | .FirstOrDefaultAsync(); 32 | 33 | public async Task CreateAsync(Guild entity) 34 | { 35 | entity.CreatedDate = DateTime.UtcNow; 36 | entity.ModifiedDate = DateTime.UtcNow; 37 | 38 | context.Guilds.Add(entity); 39 | await context 40 | .SaveChangesAsync() 41 | .ConfigureAwait(false); 42 | 43 | return mapper.Map(entity); 44 | } 45 | 46 | public async Task UpdateAsync(string id, 47 | Guild updated) 48 | { 49 | var guild = await context 50 | .Guilds 51 | .FindAsync(id) 52 | .ConfigureAwait(false); 53 | 54 | if (guild == null) 55 | { 56 | return null; 57 | } 58 | 59 | guild.DisplayName = updated.DisplayName; 60 | guild.OwnerId = updated.OwnerId; 61 | guild.ModifiedDate = DateTime.UtcNow; 62 | 63 | await context 64 | .SaveChangesAsync() 65 | .ConfigureAwait(false); 66 | 67 | return mapper.Map(guild); 68 | } 69 | 70 | public async Task DeleteAsync(string id) 71 | { 72 | var guild = await context 73 | .Guilds 74 | .FindAsync(id) 75 | .ConfigureAwait(false); 76 | 77 | if (guild == null) 78 | { 79 | return false; 80 | } 81 | 82 | context.Guilds.Remove(guild); 83 | await context 84 | .SaveChangesAsync() 85 | .ConfigureAwait(false); 86 | 87 | return true; 88 | } 89 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/GuildConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class GuildConfigurationAccessor(CbContext context, 12 | IMapper mapper) 13 | : IGuildConfigurationAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .GuildConfigurations 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetByIdAsync(string id) => context.GuildConfigurations 22 | .AsNoTracking() 23 | .Where(g => g.GuildId == id) 24 | .ProjectTo(mapper.ConfigurationProvider) 25 | .FirstOrDefaultAsync(); 26 | 27 | public async Task CreateAsync(GuildConfiguration entity) 28 | { 29 | context.GuildConfigurations.Add(entity); 30 | await context 31 | .SaveChangesAsync() 32 | .ConfigureAwait(false); 33 | 34 | return mapper.Map(entity); 35 | } 36 | 37 | public async Task UpdateAsync(string id, 38 | GuildConfigurationDto updated) 39 | { 40 | var guildConfiguration = await context 41 | .GuildConfigurations 42 | .FindAsync(id) 43 | .ConfigureAwait(false); 44 | 45 | if (guildConfiguration == null) 46 | { 47 | return null; 48 | } 49 | 50 | guildConfiguration.DeleteOffline = updated.DeleteOffline; 51 | guildConfiguration.TextAnnouncements = updated.TextAnnouncements; 52 | 53 | await context 54 | .SaveChangesAsync() 55 | .ConfigureAwait(false); 56 | 57 | return mapper.Map(guildConfiguration); 58 | } 59 | 60 | public async Task DeleteAsync(string id) 61 | { 62 | var guildConfiguration = await context 63 | .GuildConfigurations 64 | .FindAsync(id) 65 | .ConfigureAwait(false); 66 | 67 | if (guildConfiguration == null) 68 | { 69 | return false; 70 | } 71 | 72 | context.GuildConfigurations.Remove(guildConfiguration); 73 | await context 74 | .SaveChangesAsync() 75 | .ConfigureAwait(false); 76 | 77 | return true; 78 | } 79 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/LiveEmbedAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using CB.Accessors.Contracts; 3 | using CB.Data; 4 | using CB.Shared.Dtos; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace CB.Accessors.Implementations; 8 | 9 | public class LiveEmbedAccessor(CbContext context, 10 | IMapper mapper) 11 | : ILiveEmbedAccessor 12 | { 13 | public async Task GetByIdAsync(string guildId) 14 | { 15 | var entity = await context 16 | .LiveEmbeds 17 | .FirstOrDefaultAsync(x => x.GuildId == guildId); 18 | 19 | if (entity == null) 20 | { 21 | entity = new() 22 | { 23 | GuildId = guildId, 24 | Header = "%CHANNEL% is now streaming!", 25 | DescriptionLabel = "Stream Description", 26 | Description = "%CHANNEL% is currently playing %GAME%", 27 | LastStreamed = "Last Streamed", 28 | AverageStream = "Average Stream", 29 | StreamDescription = "%DESCRIPTION%", 30 | FooterStopped = "Powered by 100% Couch • Stopped streaming", 31 | FooterStart = "Powered by 100% Couch • Started streaming", 32 | ChannelButton = "Creator Channel", 33 | }; 34 | 35 | await context 36 | .LiveEmbeds 37 | .AddAsync(entity); 38 | await context 39 | .SaveChangesAsync(); 40 | } 41 | 42 | return mapper.Map(entity); 43 | } 44 | 45 | public async Task UpdateAsync(LiveEmbedDto entity) 46 | { 47 | var embed = await context 48 | .LiveEmbeds 49 | .FirstOrDefaultAsync(x => x.GuildId == entity.GuildId) 50 | .ConfigureAwait(false); 51 | 52 | if (embed == null) 53 | { 54 | return null; 55 | } 56 | 57 | embed.AverageStream = entity.AverageStream; 58 | embed.ChannelButton = entity.ChannelButton; 59 | embed.Description = entity.Description; 60 | embed.DescriptionLabel = entity.DescriptionLabel; 61 | embed.FooterStart = entity.FooterStart; 62 | embed.FooterStopped = entity.FooterStopped; 63 | embed.Header = entity.Header; 64 | embed.LastStreamed = entity.LastStreamed; 65 | embed.StreamDescription = entity.StreamDescription; 66 | 67 | await context 68 | .SaveChangesAsync() 69 | .ConfigureAwait(false); 70 | 71 | return mapper.Map(embed); 72 | } 73 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/MessageConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using CB.Accessors.Contracts; 3 | using CB.Data; 4 | using CB.Shared.Dtos; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace CB.Accessors.Implementations; 8 | 9 | public class MessageConfigurationAccessor(CbContext context, 10 | IMapper mapper) 11 | : IMessageConfigurationAccessor 12 | { 13 | public async Task UpdateAsync(MessageConfigurationDto updated) 14 | { 15 | var messageConfiguration = await context 16 | .MessageConfigurations 17 | .FirstOrDefaultAsync(x => x.GuildId == updated.GuildId) 18 | .ConfigureAwait(false); 19 | 20 | if (messageConfiguration == null) 21 | { 22 | return null; 23 | } 24 | 25 | messageConfiguration.GoodbyeMessage = updated.GoodbyeMessage; 26 | messageConfiguration.GreetingMessage = updated.GreetingMessage; 27 | messageConfiguration.LiveMessage = updated.LiveMessage; 28 | messageConfiguration.PublishedMessage = updated.PublishedMessage; 29 | messageConfiguration.StreamOfflineMessage = updated.StreamOfflineMessage; 30 | 31 | await context 32 | .SaveChangesAsync() 33 | .ConfigureAwait(false); 34 | 35 | return mapper.Map(messageConfiguration); 36 | } 37 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/PicartoAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Shared.Models.Picarto; 3 | using CB.Shared.Utilities; 4 | 5 | namespace CB.Accessors.Implementations; 6 | 7 | public class PicartoAccessor : IPicartoAccessor 8 | { 9 | public async Task RetrieveAsync(string accessToken) 10 | { 11 | return await ApiUtilities 12 | .ApiHelper("https://api.picarto.tv/api/v1/user", 13 | [("Authorization", $"Bearer {accessToken}"), 14 | ("Content-Type", "application/json"), 15 | ("User-Agent", "PostmanRuntime/7.26.8")]) 16 | .ConfigureAwait(false); 17 | } 18 | 19 | public async Task GetChannelByNameAsync(string name) 20 | { 21 | return await ApiUtilities.ApiHelper($"https://ptvintern.picarto.tv/api/channel/detail/{name}", 22 | [("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0 - CouchBot - me@mattthedev.codes"), 23 | ("Accept", "*/*")]) 24 | .ConfigureAwait(false); 25 | } 26 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/PiczelAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Shared.Models.Piczel; 3 | using CB.Shared.Utilities; 4 | 5 | namespace CB.Accessors.Implementations; 6 | 7 | public class PiczelAccessor : IPiczelAccessor 8 | { 9 | public async Task GetChannelByNameAsync(string channelName) 10 | { 11 | return await ApiUtilities.ApiHelper($"https://piczel.tv/api/streams/{channelName}"); 12 | } 13 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/RoleConfigurationAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class RoleConfigurationAccessor(CbContext context, 12 | IMapper mapper) 13 | : IRoleConfigurationAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .RoleConfigurations 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetByIdAsync(string id) => context.RoleConfigurations 22 | .AsNoTracking() 23 | .Where(g => g.GuildId == id) 24 | .ProjectTo(mapper.ConfigurationProvider) 25 | .FirstOrDefaultAsync(); 26 | 27 | public async Task CreateAsync(RoleConfiguration entity) 28 | { 29 | context.RoleConfigurations.Add(entity); 30 | await context 31 | .SaveChangesAsync() 32 | .ConfigureAwait(false); 33 | 34 | return mapper.Map(entity); 35 | } 36 | 37 | public async Task UpdateAsync(RoleConfigurationDto updated) 38 | { 39 | var roleConfiguration = await context 40 | .RoleConfigurations 41 | .FirstOrDefaultAsync(x => x.GuildId == updated.GuildId) 42 | .ConfigureAwait(false); 43 | 44 | if (roleConfiguration == null) 45 | { 46 | return null; 47 | } 48 | 49 | roleConfiguration.DiscoveryRoleId = updated.DiscoveryRoleId; 50 | roleConfiguration.JoinRoleId = updated.JoinRoleId; 51 | roleConfiguration.LiveDiscoveryRoleId = updated.LiveDiscoveryRoleId; 52 | 53 | await context 54 | .SaveChangesAsync() 55 | .ConfigureAwait(false); 56 | 57 | return mapper.Map(roleConfiguration); 58 | } 59 | 60 | public async Task DeleteAsync(string id) 61 | { 62 | var roleConfiguration = await context 63 | .RoleConfigurations 64 | .FindAsync(id) 65 | .ConfigureAwait(false); 66 | 67 | if (roleConfiguration == null) 68 | { 69 | return false; 70 | } 71 | 72 | context.RoleConfigurations.Remove(roleConfiguration); 73 | await context 74 | .SaveChangesAsync() 75 | .ConfigureAwait(false); 76 | 77 | return true; 78 | } 79 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/TrovoAccessor.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Shared.Models.Trovo; 3 | using CB.Shared.Utilities; 4 | using Newtonsoft.Json; 5 | 6 | namespace CB.Accessors.Implementations; 7 | 8 | public class TrovoAccessor : ITrovoAccessor 9 | { 10 | private readonly string _trovoClientId; 11 | 12 | public TrovoAccessor() 13 | { 14 | _trovoClientId = Environment.GetEnvironmentVariable("TrovoClientId"); 15 | if (string.IsNullOrEmpty(_trovoClientId)) 16 | { 17 | throw new InvalidOperationException("TrovoClientId Configuration Missing."); 18 | } 19 | } 20 | 21 | public async Task GetUserByNameAsync(string name) 22 | { 23 | var query = new TrovoUserQuery 24 | { 25 | User = [name] 26 | }; 27 | 28 | return await ApiUtilities 29 | .PostApiHelper( 30 | "https://open-api.trovo.live/openplatform/getusers", 31 | [("Client-Id", _trovoClientId)], 32 | JsonConvert.SerializeObject(query)) 33 | .ConfigureAwait(false); 34 | } 35 | 36 | public async Task GetChannelByIdAsync(int id) 37 | { 38 | var query = new TrovoQuery 39 | { 40 | ChannelId = id 41 | }; 42 | 43 | return await ApiUtilities 44 | .PostApiHelper("https://open-api.trovo.live/openplatform/channels/id", 45 | [("Client-Id", _trovoClientId)], 46 | JsonConvert.SerializeObject(query)) 47 | .ConfigureAwait(false); 48 | } 49 | } 50 | 51 | public class TrovoQuery 52 | { 53 | [JsonProperty("channel_id")] 54 | public int ChannelId { get; set; } 55 | } 56 | 57 | public class TrovoUserQuery 58 | { 59 | [JsonProperty("user")] 60 | public List User { get; set; } 61 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/UserAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using CB.Accessors.Contracts; 4 | using CB.Data; 5 | using CB.Data.Entities; 6 | using CB.Shared.Dtos; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace CB.Accessors.Implementations; 10 | 11 | public class UserAccessor(CbContext context, 12 | IMapper mapper) 13 | : IUserAccessor 14 | { 15 | public Task> GetAllAsync() => context 16 | .Users 17 | .AsNoTracking() 18 | .ProjectTo(mapper.ConfigurationProvider) 19 | .ToListAsync(); 20 | 21 | public Task GetByIdAsync(string id) => context.Users 22 | .AsNoTracking() 23 | .Where(g => g.Id == id) 24 | .ProjectTo(mapper.ConfigurationProvider) 25 | .FirstOrDefaultAsync(); 26 | 27 | public async Task CreateAsync(User entity) 28 | { 29 | entity.CreatedDate = DateTime.UtcNow; 30 | entity.ModifiedDate = DateTime.UtcNow; 31 | 32 | context.Users.Add(entity); 33 | await context 34 | .SaveChangesAsync() 35 | .ConfigureAwait(false); 36 | 37 | return mapper.Map(entity); 38 | } 39 | 40 | public async Task UpdateAsync(string id, 41 | User updated) 42 | { 43 | var user = await context 44 | .Users 45 | .FindAsync(id) 46 | .ConfigureAwait(false); 47 | 48 | if (user == null) 49 | { 50 | return null; 51 | } 52 | 53 | user.DisplayName = updated.DisplayName; 54 | user.Id = updated.Id; 55 | user.ModifiedDate = DateTime.UtcNow; 56 | 57 | await context 58 | .SaveChangesAsync() 59 | .ConfigureAwait(false); 60 | 61 | return mapper.Map(user); 62 | } 63 | 64 | public async Task DeleteAsync(string id) 65 | { 66 | var user = await context.Users.FindAsync(id); 67 | if (user == null) 68 | { 69 | return false; 70 | } 71 | 72 | context.Users.Remove(user); 73 | await context 74 | .SaveChangesAsync() 75 | .ConfigureAwait(false); 76 | 77 | return true; 78 | } 79 | } -------------------------------------------------------------------------------- /src/CB.Accessors/Implementations/VodEmbedAccessor.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using CB.Accessors.Contracts; 3 | using CB.Data; 4 | using CB.Shared.Dtos; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace CB.Accessors.Implementations; 8 | 9 | public class VodEmbedAccessor(CbContext context, 10 | IMapper mapper) 11 | : IVodEmbedAccessor 12 | { 13 | public async Task GetByIdAsync(string guildId) 14 | { 15 | var entity = await context 16 | .VodEmbeds 17 | .FirstOrDefaultAsync(x => x.GuildId == guildId); 18 | 19 | if (entity == null) 20 | { 21 | entity = new() 22 | { 23 | GuildId = guildId, 24 | Header = "%CHANNEL% has published a new video!", 25 | Description = "%DESCRIPTION%", 26 | DescriptionLabel = "Video Description", 27 | Footer = "Powered by 100% Couch", 28 | ChannelButton = "Creator Channel!", 29 | }; 30 | 31 | await context 32 | .VodEmbeds 33 | .AddAsync(entity); 34 | await context 35 | .SaveChangesAsync(); 36 | } 37 | 38 | return mapper.Map(entity); 39 | } 40 | 41 | public async Task UpdateAsync(VodEmbedDto entity) 42 | { 43 | var embed = await context 44 | .VodEmbeds 45 | .FirstOrDefaultAsync(x => x.GuildId == entity.GuildId) 46 | .ConfigureAwait(false); 47 | 48 | if (embed == null) 49 | { 50 | return null; 51 | } 52 | 53 | embed.Header = entity.Header; 54 | embed.ChannelButton = entity.ChannelButton; 55 | embed.Description = entity.Description; 56 | embed.DescriptionLabel = entity.DescriptionLabel; 57 | embed.Footer = entity.Footer; 58 | 59 | await context 60 | .SaveChangesAsync() 61 | .ConfigureAwait(false); 62 | 63 | return mapper.Map(embed); 64 | } 65 | } -------------------------------------------------------------------------------- /src/CB.Antenna/CB.Antenna.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | dotnet-CB.Antenna-8011c496-f6b9-40f4-9d32-b5230132b68a 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/CB.Antenna/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | WORKDIR /src 7 | COPY . . 8 | RUN dotnet restore "src/CB.Antenna/CB.Antenna.csproj" 9 | RUN dotnet publish "src/CB.Antenna/CB.Antenna.csproj" -c Release -o /app/publish 10 | 11 | FROM base AS final 12 | WORKDIR /app 13 | COPY --from=build /app/publish . 14 | ENTRYPOINT ["dotnet", "CB.Antenna.dll"] 15 | -------------------------------------------------------------------------------- /src/CB.Antenna/Program.cs: -------------------------------------------------------------------------------- 1 | using CB.Antenna; 2 | 3 | var builder = Host.CreateApplicationBuilder(args); 4 | builder.Services.AddHostedService(); 5 | 6 | var host = builder.Build(); 7 | host.Run(); 8 | -------------------------------------------------------------------------------- /src/CB.Antenna/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "CB.Antenna": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "environmentVariables": { 8 | "DOTNET_ENVIRONMENT": "Development" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/CB.Antenna/Worker.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Antenna; 2 | 3 | public class Worker(ILogger logger) : BackgroundService 4 | { 5 | protected override async Task ExecuteAsync(CancellationToken stoppingToken) 6 | { 7 | while (!stoppingToken.IsCancellationRequested) 8 | { 9 | if (logger.IsEnabled(LogLevel.Information)) 10 | { 11 | logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); 12 | } 13 | await Task.Delay(1000, stoppingToken); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/CB.Antenna/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/CB.Antenna/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | }, 8 | "ConnectionStrings": { 9 | "DefaultConnection": "Host=db;Database=myappdb;Username=myuser;Password=mypassword" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/CB.Api/CB.Api.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | all 12 | runtime; build; native; contentfiles; analyzers; buildtransitive 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/CB.Api/CB.Api.http: -------------------------------------------------------------------------------- 1 | @CB.Api_HostAddress = http://localhost:5210 2 | 3 | GET {{CB.Api_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /src/CB.Api/Controllers/GuildController.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Data.Entities; 3 | using CB.Shared.Dtos; 4 | using Microsoft.AspNetCore.Mvc; 5 | 6 | namespace CB.Api.Controllers; 7 | 8 | [ApiController] 9 | [Route("api/[controller]")] 10 | public class GuildsController(IGuildAccessor guildAccessor) : ControllerBase 11 | { 12 | // GET api/guilds 13 | [HttpGet] 14 | public async Task>> GetAll() 15 | { 16 | var guilds = await guildAccessor 17 | .GetAllAsync() 18 | .ConfigureAwait(false); 19 | return Ok(guilds); 20 | } 21 | 22 | // GET api/guilds/{id} 23 | [HttpGet("{id}")] 24 | public async Task> GetById(string id) 25 | { 26 | var guild = await guildAccessor 27 | .GetByIdAsync(id) 28 | .ConfigureAwait(false); 29 | if (guild == null) 30 | { 31 | return NotFound(); 32 | } 33 | 34 | return Ok(guild); 35 | } 36 | 37 | // POST api/guilds 38 | [HttpPost] 39 | public async Task> Create([FromBody] Guild newGuild) 40 | { 41 | var created = await guildAccessor.CreateAsync(newGuild); 42 | 43 | // Return 201 Created with location header for the new resource 44 | return CreatedAtAction(nameof(GetById), new { id = created.Id }, created); 45 | } 46 | 47 | // PUT api/guilds/{id} 48 | [HttpPut("{id}")] 49 | public async Task> Update(string id, [FromBody] Guild updatedGuild) 50 | { 51 | var updated = await guildAccessor.UpdateAsync(id, updatedGuild); 52 | if (updated == null) 53 | { 54 | return NotFound(); 55 | } 56 | 57 | return Ok(updated); 58 | } 59 | 60 | // DELETE api/guilds/{id} 61 | [HttpDelete("{id}")] 62 | public async Task Delete(string id) 63 | { 64 | var deleted = await guildAccessor.DeleteAsync(id); 65 | if (!deleted) 66 | { 67 | return NotFound(); 68 | } 69 | 70 | return NoContent(); 71 | } 72 | } -------------------------------------------------------------------------------- /src/CB.Api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | WORKDIR /src 7 | COPY . . 8 | RUN dotnet restore "src/CB.Api/CB.Api.csproj" 9 | RUN dotnet publish "src/CB.Api/CB.Api.csproj" -c Release -o /app/publish 10 | 11 | FROM base AS final 12 | WORKDIR /app 13 | COPY --from=build /app/publish . 14 | ENTRYPOINT ["dotnet", "CB.Api.dll"] 15 | -------------------------------------------------------------------------------- /src/CB.Api/Program.cs: -------------------------------------------------------------------------------- 1 | using CB.Data; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | var builder = WebApplication.CreateBuilder(args); 5 | 6 | builder.Services.AddDbContext(options => 7 | options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); 8 | 9 | builder.Services.AddControllers(); 10 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 11 | builder.Services.AddEndpointsApiExplorer(); 12 | builder.Services.AddSwaggerGen(); 13 | 14 | var app = builder.Build(); 15 | 16 | using (var scope = app.Services.CreateScope()) 17 | { 18 | var db = scope.ServiceProvider.GetRequiredService(); 19 | db.Database.Migrate(); 20 | } 21 | 22 | // Configure the HTTP request pipeline. 23 | if (app.Environment.IsDevelopment()) 24 | { 25 | app.UseSwagger(); 26 | app.UseSwaggerUI(); 27 | } 28 | 29 | app.UseHttpsRedirection(); 30 | 31 | app.UseAuthorization(); 32 | 33 | app.MapControllers(); 34 | 35 | app.Run(); 36 | -------------------------------------------------------------------------------- /src/CB.Api/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:34225", 8 | "sslPort": 44387 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5210", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7274;http://localhost:5210", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/CB.Api/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/CB.Api/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "ConnectionStrings": { 10 | "DefaultConnection": "Host=db;Database=myappdb;Username=myuser;Password=mypassword" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/CB.Bot/CB.Bot.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | dotnet-CB.Bot-e32dd526-c97c-446a-816b-f4b92c67f026 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/CB.Bot/Commands/Application/BaseSlashCommands.cs: -------------------------------------------------------------------------------- 1 | using Discord; 2 | using Discord.Interactions; 3 | using Discord.WebSocket; 4 | 5 | namespace CB.Bot.Commands.Application; 6 | 7 | /// 8 | /// Base class to provide easier access to helper functions for our slash command implementations. 9 | /// 10 | public class BaseSlashCommands() : InteractionModuleBase 11 | { 12 | public IGuildUser GuildUser => (IGuildUser)Context.User; 13 | public IGuildChannel GuildChannel => (IGuildChannel)Context.Channel; 14 | public SocketInteraction SocketInteraction => (SocketInteraction)Context.Interaction; 15 | public SocketSlashCommand SocketSlashCommand => (SocketSlashCommand)SocketInteraction; 16 | 17 | /// 18 | /// Validate if the user executing the slash command is an approved admin, or not. 19 | /// 20 | /// Is user admin? true or false 21 | public async Task IsUserAdmin(bool sendResponse = true) 22 | { 23 | // TODO MS - We need to add ApprovedAdmin code. 24 | // This'll do for now. 25 | var isAdmin = GuildUser.GuildPermissions.ManageGuild; 26 | 27 | if (!isAdmin && sendResponse) 28 | { 29 | await SocketInteraction.FollowupAsync("Sorry, you have to be an admin to use that command.", 30 | ephemeral: true) 31 | .ConfigureAwait(false); 32 | } 33 | 34 | return isAdmin; 35 | } 36 | } -------------------------------------------------------------------------------- /src/CB.Bot/Commands/Application/ChannelSlashCommands.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Shared.Enums; 3 | using Discord; 4 | using Discord.Interactions; 5 | // ReSharper disable UnusedMember.Local 6 | // ReSharper disable UnusedMember.Global 7 | 8 | namespace CB.Bot.Commands.Application; 9 | 10 | [Group("channel", "Channel configuration")] 11 | public class ChannelSlashCommands(IGuildAccessor guildAccessor, 12 | IChannelAccessor channelAccessor, 13 | IChannelConfigurationAccessor channelConfigurationAccessor) : BaseSlashCommands 14 | { 15 | [SlashCommand( 16 | "live", 17 | "Configure server 'Channel' settings", 18 | false, 19 | RunMode.Async)] 20 | private async Task LiveChannelConfigurationAsync(IGuildChannel channel) 21 | { 22 | await ConfigureChannelAsync(ConfiguredChannelType.Live, 23 | channel); 24 | } 25 | 26 | [SlashCommand( 27 | "greetings", 28 | "Configure server 'Channel' settings", 29 | false, 30 | RunMode.Async)] 31 | private async Task GreetingChannelConfigurationAsync(IGuildChannel channel) 32 | { 33 | await ConfigureChannelAsync(ConfiguredChannelType.Greetings, 34 | channel); 35 | } 36 | 37 | [SlashCommand( 38 | "goodbyes", 39 | "Configure server 'Channel' settings", 40 | false, 41 | RunMode.Async)] 42 | private async Task GoodbyeChannelConfigurationAsync(IGuildChannel channel) 43 | { 44 | await ConfigureChannelAsync(ConfiguredChannelType.Goodbyes, 45 | channel); 46 | } 47 | 48 | [SlashCommand( 49 | "discordlive", 50 | "Configure server 'Discord Live Channel' setting", 51 | false, 52 | RunMode.Async)] 53 | private async Task DiscordLiveChannelConfigurationAsync(IGuildChannel channel) 54 | { 55 | await ConfigureChannelAsync(ConfiguredChannelType.DiscordLive, 56 | channel); 57 | } 58 | 59 | private async Task ConfigureChannelAsync(ConfiguredChannelType configuredChannelType, 60 | IGuildChannel discordChannel) 61 | { 62 | await SocketInteraction 63 | .DeferAsync(true) 64 | .ConfigureAwait(false); 65 | 66 | if (!await IsUserAdmin()) 67 | { 68 | return; 69 | } 70 | 71 | var guild = await guildAccessor 72 | .GetConfigurationSummaryByIdAsync(Context.Guild.Id.ToString()) 73 | .ConfigureAwait(false); 74 | 75 | if (guild == null) 76 | { 77 | await FollowupAsync("There was an issue retrieving your guild. Contact support.", ephemeral: true) 78 | .ConfigureAwait(false); 79 | return; 80 | } 81 | 82 | var existingChannel = await channelAccessor.GetChannelConfigurationSummaryByIdAsync(discordChannel.Id.ToString()).ConfigureAwait(false) 83 | ?? await channelAccessor.CreateAsync(new() 84 | { 85 | CreatedDate = DateTime.UtcNow, 86 | ModifiedDate = DateTime.UtcNow, 87 | DisplayName = discordChannel.Name, 88 | GuildId = guild.Id, 89 | Id = discordChannel.Id.ToString() 90 | }).ConfigureAwait(false); 91 | 92 | switch (configuredChannelType) 93 | { 94 | case ConfiguredChannelType.Greetings: 95 | guild.ChannelConfiguration.GreetingChannelId = existingChannel.Id; 96 | break; 97 | case ConfiguredChannelType.Goodbyes: 98 | guild.ChannelConfiguration.GoodbyeChannelId = existingChannel.Id; 99 | break; 100 | case ConfiguredChannelType.Live: 101 | guild.ChannelConfiguration.LiveChannelId = existingChannel.Id; 102 | break; 103 | case ConfiguredChannelType.DiscordLive: 104 | guild.ChannelConfiguration.DiscordLiveChannelId = existingChannel.Id; 105 | break; 106 | } 107 | 108 | await channelConfigurationAccessor.UpdateAsync(guild.ChannelConfiguration.GuildId, 109 | guild.ChannelConfiguration) 110 | .ConfigureAwait(false); 111 | 112 | await FollowupAsync($"Your '{configuredChannelType}' channel is now #{existingChannel.DisplayName}", 113 | ephemeral: true) 114 | .ConfigureAwait(false); 115 | } 116 | } -------------------------------------------------------------------------------- /src/CB.Bot/Commands/Application/DiscordLiveSlashCommands.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Data.Entities; 3 | using Discord; 4 | using Discord.Interactions; 5 | 6 | // ReSharper disable UnusedMember.Global 7 | // ReSharper disable UnusedMember.Local 8 | 9 | namespace CB.Bot.Commands.Application; 10 | 11 | public class DiscordLiveSlashCommands(IDiscordLiveConfigurationAccessor discordLiveConfigurationAccessor) 12 | : BaseSlashCommands 13 | { 14 | [SlashCommand("discordlive", 15 | "Configure the Discord Live notification.", 16 | false, 17 | RunMode.Async)] 18 | private async Task DiscordLiveAsync(string description, 19 | string footer, 20 | string header, 21 | string message, 22 | IRole mentionRole = null) 23 | { 24 | await SocketInteraction.DeferAsync(true); 25 | 26 | if (!await IsUserAdmin()) 27 | { 28 | return; 29 | } 30 | 31 | var config = await discordLiveConfigurationAccessor.GetByIdAsync(GuildUser.GuildId.ToString()) ?? await discordLiveConfigurationAccessor.CreateAsync(new DiscordLiveConfiguration 32 | { 33 | GuildId = GuildUser.GuildId.ToString() 34 | }); 35 | 36 | config.Description = description; 37 | config.Footer = footer; 38 | config.Header = header; 39 | config.Message = message; 40 | config.MentionRoleId = mentionRole?.Id.ToString(); 41 | 42 | await discordLiveConfigurationAccessor.UpdateAsync(config); 43 | await SocketInteraction.FollowupAsync("Your configuration for your Discord Live announcements has been set!"); 44 | } 45 | } -------------------------------------------------------------------------------- /src/CB.Bot/Commands/Application/DiscoverySlashCommands.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using Discord; 3 | using Discord.Interactions; 4 | 5 | // ReSharper disable UnusedMember.Local 6 | // ReSharper disable UnusedMember.Global 7 | 8 | namespace CB.Bot.Commands.Application; 9 | 10 | [Group("discovery", "Discovery commands")] 11 | public class DiscoverySlashCommands(IGuildAccessor guildAccessor, 12 | IRoleConfigurationAccessor roleConfigurationAccessor, 13 | IAllowConfigurationAccessor allowConfigurationAccessor) : BaseSlashCommands 14 | { 15 | [SlashCommand( 16 | "enable", 17 | "Configure server 'Discovery' setting", 18 | false, 19 | RunMode.Async)] 20 | private async Task DiscoveryEnableConfigurationAsync(IRole role = null) 21 | { 22 | await DoStuff(true, role); 23 | } 24 | 25 | [SlashCommand( 26 | "disable", 27 | "Configure server 'Discovery' setting", 28 | false, 29 | RunMode.Async)] 30 | private async Task DiscoveryDisableConfigurationAsync() 31 | { 32 | await DoStuff(false); 33 | } 34 | 35 | private async Task DoStuff(bool isEnabled, 36 | IRole role = null) 37 | { 38 | await SocketInteraction.DeferAsync(true); 39 | 40 | if (!await IsUserAdmin()) 41 | { 42 | return; 43 | } 44 | 45 | var guildChannel = (IGuildChannel)SocketInteraction.Channel; 46 | var guild = await guildAccessor.GetConfigurationSummaryByIdAsync(guildChannel.Guild.Id.ToString()); 47 | if (guild == null) 48 | { 49 | await SocketInteraction.FollowupAsync( 50 | "Sorry, unable to configure Discovery for this guild. Contact support.", ephemeral: true); 51 | return; 52 | } 53 | 54 | string message; 55 | if (!isEnabled) 56 | { 57 | guild.RoleConfiguration.DiscoveryRoleId = null; 58 | guild.AllowConfiguration.AllowLiveDiscovery = false; 59 | message = "Discovery has been set to `Disabled`."; 60 | } 61 | else 62 | { 63 | if (role != null) 64 | { 65 | guild.RoleConfiguration.DiscoveryRoleId = role.Id.ToString(); 66 | guild.AllowConfiguration.AllowLiveDiscovery = true; 67 | 68 | message = $"Discovery has been set to role {role.Name}."; 69 | } 70 | else 71 | { 72 | guild.RoleConfiguration.DiscoveryRoleId = null; 73 | guild.AllowConfiguration.AllowLiveDiscovery = true; 74 | 75 | message = "Discovery has been set to .. literally everyone!"; 76 | } 77 | } 78 | 79 | await roleConfigurationAccessor.UpdateAsync(guild.RoleConfiguration); 80 | await allowConfigurationAccessor.UpdateAsync(guild.AllowConfiguration); 81 | 82 | await SocketInteraction.FollowupAsync(message, ephemeral: true); 83 | } 84 | } -------------------------------------------------------------------------------- /src/CB.Bot/Commands/Application/FilterSlashCommands.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Data.Entities; 3 | using Discord.Interactions; 4 | using FilterType = CB.Shared.Enums.FilterType; 5 | using Platform = CB.Shared.Enums.Platform; 6 | 7 | // ReSharper disable UnusedMember.Global 8 | // ReSharper disable UnusedMember.Local 9 | 10 | namespace CB.Bot.Commands.Application; 11 | 12 | public class FilterSlashCommands(IFilterAccessor filterAccessor) 13 | : BaseSlashCommands 14 | { 15 | [SlashCommand( 16 | "filter", 17 | "Manage your filters.", 18 | false, 19 | RunMode.Async)] 20 | private async Task ToggleFilter(string filterText, 21 | FilterType filterType, 22 | Platform platform) 23 | { 24 | await SocketInteraction.DeferAsync(true); 25 | 26 | if (!await IsUserAdmin()) 27 | { 28 | return; 29 | } 30 | 31 | var t = (int)platform; 32 | filterText = filterText.TrimStart('"').TrimEnd('"'); 33 | var existingFilters = await filterAccessor.GetAllAsync(SocketInteraction.GuildId.ToString()); 34 | var existingFilter = existingFilters.FirstOrDefault( 35 | x => x.PlatformId == (int)platform && 36 | x.FilterTypeId == (int)filterType && 37 | x.Text.Equals(filterText, StringComparison.OrdinalIgnoreCase)); 38 | 39 | if (existingFilter == null) 40 | { 41 | await filterAccessor.CreateAsync(new Filter 42 | { 43 | Text = filterText, 44 | PlatformId = (int)platform, 45 | FilterTypeId = (int)filterType, 46 | GuildId = SocketInteraction.GuildId.ToString() 47 | }); 48 | 49 | await SocketInteraction.FollowupAsync($"{filterType} filter has been created."); 50 | } 51 | else 52 | { 53 | await filterAccessor.DeleteAsync(existingFilter); 54 | await SocketInteraction.FollowupAsync($"{filterType} filter has been removed."); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/CB.Bot/Commands/Application/FunSlashCommands.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | using CB.Accessors.Contracts; 3 | using Discord.Interactions; 4 | 5 | namespace CB.Bot.Commands.Application; 6 | 7 | public class FunSlashCommands(IFunAccessor funAccessor) : InteractionModuleBase 8 | { 9 | [SlashCommand("roll", "Roll a D20")] 10 | public async Task RollAsync() 11 | { 12 | var rollResult = RandomNumberGenerator.GetInt32(1, 21); 13 | await RespondAsync($"You rolled a {rollResult}!"); 14 | } 15 | 16 | [SlashCommand("haibai", "They comes .. they goes ..")] 17 | public async Task HaiBaiAsync() 18 | { 19 | var haiBaiCount = await funAccessor.IncrementHaiBai(); 20 | 21 | await RespondAsync( 22 | $"_ _" + 23 | $"[`HaiBai Count: {haiBaiCount}`](https://cdn.discordapp.com/attachments/313015271566868480/502228420881678336/couch.gif?ex=6882a2aa&is=6881512a&hm=8541f1b54df685b3ee50627db3c2c1fae730e371d3e4fd7d78eadb40a1d1102f&)"); 24 | } 25 | } -------------------------------------------------------------------------------- /src/CB.Bot/Commands/Application/UtilityApplicationCommands.cs: -------------------------------------------------------------------------------- 1 | using Discord.Interactions; 2 | // ReSharper disable UnusedMember.Local 3 | // ReSharper disable UnusedMember.Global 4 | 5 | namespace CB.Bot.Commands.Application; 6 | 7 | public class UtilityApplicationCommands : InteractionModuleBase 8 | { 9 | [SlashCommand("ping", 10 | "Test bot response.", 11 | true, 12 | RunMode.Async)] 13 | private async Task PingAsync() 14 | { 15 | await RespondAsync("Pong!") 16 | .ConfigureAwait(false); 17 | } 18 | } -------------------------------------------------------------------------------- /src/CB.Bot/Commands/Text/UtilityTextCommands.cs: -------------------------------------------------------------------------------- 1 | using Discord.Commands; 2 | 3 | namespace CB.Bot.Commands.Text; 4 | 5 | public class UtilityTextCommands : ModuleBase 6 | { 7 | [Command("ping", 8 | true, 9 | "Test bot response.", 10 | RunMode = RunMode.Async)] 11 | private async Task PingAsync() 12 | { 13 | await ReplyAsync("Pong!") 14 | .ConfigureAwait(false); 15 | } 16 | } -------------------------------------------------------------------------------- /src/CB.Bot/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 6 | WORKDIR /src 7 | COPY . . 8 | RUN dotnet restore "src/CB.Bot/CB.Bot.csproj" 9 | RUN dotnet publish "src/CB.Bot/CB.Bot.csproj" -c Release -o /app/publish 10 | 11 | FROM base AS final 12 | WORKDIR /app 13 | COPY --from=build /app/publish . 14 | ENTRYPOINT ["dotnet", "CB.Bot.dll"] 15 | -------------------------------------------------------------------------------- /src/CB.Bot/Program.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Accessors.Implementations; 3 | using CB.Bot.Services; 4 | using CB.Data; 5 | using CB.Engines.Contracts; 6 | using CB.Engines.Implementations; 7 | using CB.Shared.Dtos; 8 | using Discord; 9 | using Discord.Commands; 10 | using Discord.Interactions; 11 | using Discord.WebSocket; 12 | using Microsoft.EntityFrameworkCore; 13 | 14 | AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); 15 | 16 | var builder = Host.CreateApplicationBuilder(args); 17 | var socketConfig = new DiscordSocketConfig 18 | { 19 | LogLevel = LogSeverity.Verbose, 20 | GatewayIntents = 21 | GatewayIntents.GuildVoiceStates | 22 | GatewayIntents.GuildScheduledEvents | 23 | GatewayIntents.DirectMessages | 24 | GatewayIntents.GuildIntegrations | 25 | GatewayIntents.GuildMessageReactions | 26 | GatewayIntents.Guilds | 27 | GatewayIntents.GuildMessages, 28 | UseInteractionSnowflakeDate = false, 29 | AlwaysDownloadUsers = true, 30 | }; 31 | 32 | var client = new DiscordSocketClient(socketConfig); 33 | builder.Services.AddSingleton(client); 34 | builder.Services.AddSingleton(); 35 | builder.Services.AddSingleton(new InteractionService(client)); 36 | builder.Services.AddSingleton(); 37 | builder.Services.AddSingleton(); 38 | builder.Services.AddScoped(); 39 | builder.Services.AddScoped(); 40 | builder.Services.AddScoped(); 41 | builder.Services.AddScoped(); 42 | builder.Services.AddScoped(); 43 | builder.Services.AddScoped(); 44 | builder.Services.AddScoped(); 45 | builder.Services.AddScoped(); 46 | builder.Services.AddScoped(); 47 | builder.Services.AddScoped(); 48 | builder.Services.AddScoped(); 49 | builder.Services.AddScoped(); 50 | builder.Services.AddScoped(); 51 | builder.Services.AddScoped(); 52 | builder.Services.AddScoped(); 53 | builder.Services.AddScoped(); 54 | builder.Services.AddScoped(); 55 | builder.Services.AddScoped(); 56 | builder.Services.AddScoped(); 57 | 58 | builder.Services.AddDbContext(options => 59 | options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); 60 | builder.Services.AddAutoMapper(cfg => { }, typeof(CbProfile)); 61 | 62 | builder.Services.AddHostedService(); 63 | builder.Services.AddHttpClient(); 64 | var host = builder.Build(); 65 | host.Run(); 66 | -------------------------------------------------------------------------------- /src/CB.Bot/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "CB.Bot": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "environmentVariables": { 8 | "DOTNET_ENVIRONMENT": "Development" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/CB.Bot/Services/DiscordBotService.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Discord; 3 | using Discord.Commands; 4 | using Discord.Interactions; 5 | using Discord.WebSocket; 6 | 7 | namespace CB.Bot.Services; 8 | 9 | public class DiscordBotService(ILogger logger, 10 | DiscordSocketClient discordSocketClient, 11 | IServiceProvider serviceProvider, 12 | InteractionService interactionService, 13 | CommandService commandService, 14 | GuildInteractionService guildInteractionService, 15 | MessageInteractionService messageInteractionService) 16 | : IHostedService 17 | { 18 | public async Task StartAsync(CancellationToken cancellationToken) 19 | { 20 | await StartConnectionAsync() 21 | .ConfigureAwait(false); 22 | await ValidateBotConnection(cancellationToken) 23 | .ConfigureAwait(false); 24 | await InitializeCommands() 25 | .ConfigureAwait(false); 26 | InitializeEventListeners(); 27 | } 28 | 29 | public Task StopAsync(CancellationToken cancellationToken) 30 | { 31 | logger.LogInformation("Bot stopping"); 32 | return Task.CompletedTask; 33 | } 34 | 35 | private async Task ValidateBotConnection(CancellationToken cancellationToken) 36 | { 37 | while (discordSocketClient.CurrentUser == null) 38 | { 39 | logger.LogInformation("Discord user connection pending ..."); 40 | await Task.Delay(5000, cancellationToken) 41 | .ConfigureAwait(false); 42 | } 43 | 44 | while (discordSocketClient.ConnectionState != ConnectionState.Connected) 45 | { 46 | logger.LogInformation("Discord user connection pending ..."); 47 | await Task.Delay(5000, cancellationToken) 48 | .ConfigureAwait(false); 49 | } 50 | 51 | logger.LogInformation($"Discord user connected: {discordSocketClient.CurrentUser.Username}"); 52 | } 53 | 54 | private async Task StartConnectionAsync() 55 | { 56 | logger.LogInformation("Starting connection to Discord ..."); 57 | var discordToken = Environment.GetEnvironmentVariable("BOT_TOKEN"); 58 | 59 | if (string.IsNullOrWhiteSpace(discordToken)) 60 | { 61 | var error = "`BOT_TOKEN` environment variable missing."; 62 | logger.LogCritical(error); 63 | 64 | throw new Exception(error); 65 | } 66 | await discordSocketClient 67 | .LoginAsync(TokenType.Bot, discordToken) 68 | .ConfigureAwait(false); 69 | await discordSocketClient 70 | .StartAsync() 71 | .ConfigureAwait(false); 72 | 73 | logger.LogInformation("Connection to Discord Established ..."); 74 | } 75 | 76 | private async Task InitializeCommands() 77 | { 78 | await interactionService.AddModulesAsync(Assembly.GetEntryAssembly(), 79 | services: serviceProvider) 80 | .ConfigureAwait(false); 81 | await commandService.AddModulesAsync(assembly: Assembly.GetEntryAssembly(), 82 | services: serviceProvider) 83 | .ConfigureAwait(false); 84 | 85 | await interactionService 86 | .RegisterCommandsGloballyAsync() 87 | .ConfigureAwait(false); 88 | 89 | discordSocketClient.SlashCommandExecuted += async interaction => 90 | { 91 | var ctx = new SocketInteractionContext(discordSocketClient, interaction); 92 | await interactionService 93 | .ExecuteCommandAsync(ctx, serviceProvider) 94 | .ConfigureAwait(false); 95 | }; 96 | 97 | discordSocketClient.MessageReceived += async socketMessage => 98 | { 99 | if (socketMessage is not SocketUserMessage message) 100 | { 101 | return; 102 | } 103 | 104 | var argPos = 0; 105 | 106 | if (!(message.HasMentionPrefix(discordSocketClient.CurrentUser, ref argPos)) || message.Author.IsBot) 107 | { 108 | return; 109 | } 110 | 111 | var context = new SocketCommandContext(discordSocketClient, message); 112 | 113 | await commandService.ExecuteAsync( 114 | context: context, 115 | argPos: argPos, 116 | services: serviceProvider) 117 | .ConfigureAwait(false); 118 | }; 119 | } 120 | 121 | private void InitializeEventListeners() 122 | { 123 | guildInteractionService.Init(); 124 | messageInteractionService.Init(); 125 | } 126 | } -------------------------------------------------------------------------------- /src/CB.Bot/Services/GuildInteractionService.cs: -------------------------------------------------------------------------------- 1 | using CB.Accessors.Contracts; 2 | using CB.Data.Entities; 3 | using Discord.WebSocket; 4 | 5 | namespace CB.Bot.Services; 6 | 7 | public class GuildInteractionService(DiscordSocketClient discordSocketClient, 8 | IServiceScopeFactory serviceScopeFactory) 9 | { 10 | private IGuildAccessor _guildAccessor; 11 | private IUserAccessor _userAccessor; 12 | 13 | public void Init() 14 | { 15 | var scope = serviceScopeFactory.CreateScope(); 16 | _guildAccessor = scope.ServiceProvider.GetRequiredService(); 17 | _userAccessor = scope.ServiceProvider.GetRequiredService(); 18 | 19 | discordSocketClient.JoinedGuild += JoinedGuild; 20 | } 21 | 22 | private async Task JoinedGuild(SocketGuild arg) 23 | { 24 | var existingUser = await _userAccessor 25 | .GetByIdAsync(arg.OwnerId.ToString()) 26 | .ConfigureAwait(false); 27 | var existingGuild = await _guildAccessor 28 | .GetByIdAsync(arg.Id.ToString()) 29 | .ConfigureAwait(false); 30 | 31 | existingUser ??= await _userAccessor 32 | .CreateAsync(new() 33 | { 34 | CreatedDate = DateTime.UtcNow, 35 | ModifiedDate = DateTime.UtcNow, 36 | DisplayName = arg.Owner?.Username ?? "", 37 | Id = arg.OwnerId.ToString() 38 | }) 39 | .ConfigureAwait(false); 40 | 41 | if (existingGuild == null) 42 | { 43 | var newGuild = new Guild 44 | { 45 | AllowConfiguration = new() 46 | { 47 | AllowCrosspost = false, 48 | AllowDiscordLive = false, 49 | AllowFfa = false, 50 | AllowGoodbyes = false, 51 | AllowGreetings = false, 52 | AllowLive = true, 53 | AllowLiveDiscovery = false, 54 | AllowPublished = true, 55 | AllowStreamVod = false, 56 | AllowThumbnails = true, 57 | }, 58 | ChannelConfiguration = new() 59 | { 60 | DiscordLiveChannelId = null, 61 | GoodbyeChannelId = null, 62 | GreetingChannelId = null, 63 | LiveChannelId = null, 64 | }, 65 | GuildConfiguration = new() 66 | { 67 | DeleteOffline = true, 68 | TextAnnouncements = false, 69 | }, 70 | MessageConfiguration = new() 71 | { 72 | GoodbyeMessage = "Good bye, %USER%, thanks for hanging out!", 73 | GreetingMessage = "Welcome to the server, %USER%", 74 | LiveMessage = "%CHANNEL% just went live with %GAME% - %TITLE% - %URL%", 75 | PublishedMessage = "%CHANNEL% just published a new video - %TITLE% - %URL%", 76 | StreamOfflineMessage = "This stream is now offline.", 77 | }, 78 | CreatedDate = DateTime.UtcNow, 79 | ModifiedDate = DateTime.UtcNow, 80 | OwnerId = arg.OwnerId.ToString(), 81 | DisplayName = arg.Name, 82 | RoleConfiguration = new() 83 | { 84 | DiscoveryRoleId = null, 85 | JoinRoleId = null, 86 | LiveDiscoveryRoleId = null, 87 | }, 88 | Id = arg.Id.ToString() 89 | }; 90 | 91 | existingGuild = await _guildAccessor 92 | .CreateAsync(newGuild) 93 | .ConfigureAwait(false); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /src/CB.Bot/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/CB.Bot/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | }, 8 | "ConnectionStrings": { 9 | "DefaultConnection": "Host=db;Database=myappdb;Username=myuser;Password=mypassword" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/CB.Data/CB.Data.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/CB.Data/Entities/AllowConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class AllowConfiguration 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public bool AllowLive { get; set; } 11 | public bool AllowPublished { get; set; } 12 | public bool AllowThumbnails { get; set; } 13 | public bool AllowGreetings { get; set; } 14 | public bool AllowGoodbyes { get; set; } 15 | public bool AllowLiveDiscovery { get; set; } 16 | public bool AllowStreamVod { get; set; } 17 | public bool AllowFfa { get; set; } 18 | public bool AllowCrosspost { get; set; } 19 | public bool AllowDiscordLive { get; set; } 20 | 21 | public virtual Guild Guild { get; set; } 22 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/Channel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class Channel 6 | { 7 | [Key] 8 | public string Id { get; set; } 9 | 10 | public string DisplayName { get; set; } 11 | public string GuildId { get; set; } 12 | public DateTime CreatedDate { get; set; } 13 | public DateTime ModifiedDate { get; set; } 14 | 15 | public virtual Guild Guild { get; set; } 16 | 17 | public virtual ICollection CreatorChannels { get; set; } = new List(); 18 | public virtual ICollection GameChannels { get; set; } = new List(); 19 | public virtual ICollection TeamChannels { get; set; } = new List(); 20 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/ChannelConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class ChannelConfiguration 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public string? GreetingChannelId { get; set; } 11 | public string? GoodbyeChannelId { get; set; } 12 | public string? LiveChannelId { get; set; } 13 | public string? DiscordLiveChannelId { get; set; } 14 | 15 | public virtual Guild Guild { get; set; } 16 | public virtual Channel GreetingChannel { get; set; } 17 | public virtual Channel GoodbyeChannel { get; set; } 18 | public virtual Channel LiveChannel { get; set; } 19 | public virtual Channel DiscordLiveChannel { get; set; } 20 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/ClipEmbed.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class ClipEmbed 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public string Header { get; set; } 11 | 12 | public string Description { get; set; } 13 | 14 | public string Footer { get; set; } 15 | 16 | public string WatchButton { get; set; } 17 | 18 | public string MoreButton { get; set; } 19 | 20 | public virtual Guild Guild { get; set; } 21 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/Creator.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Data.Entities; 2 | 3 | public class Creator 4 | { 5 | public long Id { get; set; } 6 | 7 | public string ChannelId { get; set; } 8 | 9 | public string DisplayName { get; set; } 10 | 11 | public int PlatformId { get; set; } 12 | 13 | public string UserId { get; set; } 14 | 15 | public bool IsLive { get; set; } 16 | 17 | public DateTime CreatedDate { get; set; } 18 | 19 | public DateTime ModifiedDate { get; set; } 20 | 21 | public virtual User User { get; set; } 22 | 23 | public virtual ICollection CreatorChannels { get; set; } = new List(); 24 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/CreatorChannel.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Data.Entities; 2 | 3 | public class CreatorChannel 4 | { 5 | public long CreatorId { get; set; } 6 | public string ChannelId { get; set; } 7 | public int ChannelTypeId { get; set; } 8 | public string CustomMessage { get; set; } 9 | 10 | public virtual Creator Creator { get; set; } 11 | public virtual Channel Channel { get; set; } 12 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/DiscordLiveConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class DiscordLiveConfiguration 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public string Message { get; set; } 11 | public string Header { get; set; } 12 | public string Description { get; set; } 13 | public string Footer { get; set; } 14 | public string MentionRoleId { get; set; } 15 | 16 | public virtual Guild Guild { get; set; } 17 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/DropdownPayload.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class DropdownPayload 6 | { 7 | [Key] 8 | public int Id { get; set; } 9 | public string Payload { get; set; } 10 | public string DropdownType { get; set; } 11 | public string OriginalMessageId { get; set; } 12 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/Filter.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Data.Entities; 2 | 3 | public class Filter 4 | { 5 | public int Id { get; set; } 6 | public string Text { get; set; } 7 | public int? PlatformId { get; set; } 8 | public int FilterTypeId { get; set; } 9 | public string GuildId { get; set; } 10 | 11 | public Platform? Platform { get; set; } 12 | public FilterType FilterType { get; set; } 13 | public Guild Guild { get; set; } 14 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/FilterType.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Data.Entities; 2 | 3 | public class FilterType 4 | { 5 | public int Id { get; set; } 6 | public string DisplayName { get; set; } 7 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/FunStuff.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Data.Entities; 2 | 3 | public class FunStuff 4 | { 5 | public int HaiBaiCount { get; set; } = 0; 6 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/Game.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class Game 6 | { 7 | [Key] 8 | public int Id { get; set; } 9 | 10 | public string DisplayName { get; set; } 11 | public DateTime CreatedDate { get; set; } 12 | public DateTime ModifiedDate { get; set; } 13 | public int PlatformId { get; set; } 14 | public Platform Platform { get; set; } 15 | public string GameId { get; set; } 16 | 17 | public virtual ICollection GameChannels { get; set; } 18 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/GameChannel.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Data.Entities; 2 | 3 | public class GameChannel 4 | { 5 | public int GameId { get; set; } 6 | public string ChannelId { get; set; } 7 | 8 | public Game Game { get; set; } 9 | public Channel Channel { get; set; } 10 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/Guild.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class Guild 6 | { 7 | [Key] 8 | public string Id { get; set; } 9 | 10 | public string DisplayName { get; set; } 11 | 12 | public string OwnerId { get; set; } 13 | 14 | public DateTime CreatedDate { get; set; } 15 | 16 | public DateTime ModifiedDate { get; set; } 17 | 18 | public virtual User Owner { get; set; } 19 | public virtual ICollection Channels { get; set; } 20 | public virtual AllowConfiguration AllowConfiguration { get; set; } 21 | public virtual ChannelConfiguration ChannelConfiguration { get; set; } 22 | public virtual GuildConfiguration GuildConfiguration { get; set; } 23 | public virtual MessageConfiguration MessageConfiguration { get; set; } 24 | public virtual RoleConfiguration RoleConfiguration { get; set; } 25 | public virtual ClipEmbed ClipEmbed { get; set; } 26 | public virtual LiveEmbed LiveEmbed { get; set; } 27 | public virtual VodEmbed VodEmbed { get; set; } 28 | public virtual DiscordLiveConfiguration DiscordLiveConfiguration { get; set; } 29 | public virtual ICollection Filters { get; set; } 30 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/GuildConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class GuildConfiguration 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public bool TextAnnouncements { get; set; } 11 | public bool DeleteOffline { get; set; } 12 | 13 | public virtual Guild Guild { get; set; } 14 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/LiveEmbed.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class LiveEmbed 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public string Header { get; set; } 11 | 12 | public string Description { get; set; } 13 | 14 | public string LastStreamed { get; set; } 15 | 16 | public string AverageStream { get; set; } 17 | 18 | public string DescriptionLabel { get; set; } 19 | 20 | public string StreamDescription { get; set; } 21 | 22 | public string FooterStart { get; set; } 23 | 24 | public string FooterStopped { get; set; } 25 | 26 | public string ChannelButton { get; set; } 27 | 28 | public virtual Guild Guild { get; set; } 29 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/MessageConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class MessageConfiguration 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public string GreetingMessage { get; set; } 11 | public string GoodbyeMessage { get; set; } 12 | public string LiveMessage { get; set; } 13 | public string PublishedMessage { get; set; } 14 | public string StreamOfflineMessage { get; set; } 15 | 16 | public virtual Guild Guild { get; set; } 17 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/Platform.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class Platform 6 | { 7 | [Key] 8 | public int Id { get; set; } 9 | public string DisplayName { get; set; } 10 | public string SiteUrl { get; set; } 11 | public string LogoUrl { get; set; } 12 | public bool Enabled { get; set; } 13 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/RoleConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class RoleConfiguration 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public string JoinRoleId { get; set; } 11 | public string DiscoveryRoleId { get; set; } 12 | public string LiveDiscoveryRoleId { get; set; } 13 | 14 | public virtual Guild Guild { get; set; } 15 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/Team.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class Team 6 | { 7 | [Key] 8 | public int Id { get; set; } 9 | 10 | public string DisplayName { get; set; } 11 | public DateTime CreatedDate { get; set; } 12 | public DateTime ModifiedDate { get; set; } 13 | public int PlatformId { get; set; } 14 | public Platform Platform { get; set; } 15 | public string TeamId { get; set; } 16 | 17 | public ICollection TeamChannels { get; set; } 18 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/TeamChannel.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Data.Entities; 2 | 3 | public class TeamChannel 4 | { 5 | public int TeamId { get; set; } 6 | public string ChannelId { get; set; } 7 | 8 | public Team Team { get; set; } 9 | public Channel Channel { get; set; } 10 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/User.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace CB.Data.Entities; 5 | 6 | public class User 7 | { 8 | [Key] 9 | public string Id { get; set; } 10 | 11 | public string DisplayName { get; set; } 12 | 13 | [Column(TypeName = "timestamp without time zone")] 14 | public DateTime CreatedDate { get; set; } 15 | 16 | [Column(TypeName = "timestamp without time zone")] 17 | public DateTime ModifiedDate { get; set; } 18 | 19 | public virtual ICollection Guilds { get; set; } 20 | public virtual ICollection Creators { get; set; } 21 | } -------------------------------------------------------------------------------- /src/CB.Data/Entities/VodEmbed.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Data.Entities; 4 | 5 | public class VodEmbed 6 | { 7 | [Key] 8 | public string GuildId { get; set; } 9 | 10 | public string Header { get; set; } 11 | 12 | public string DescriptionLabel { get; set; } 13 | 14 | public string Description { get; set; } 15 | 16 | public string Footer { get; set; } 17 | 18 | public string ChannelButton { get; set; } 19 | 20 | public virtual Guild Guild { get; set; } 21 | } -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250710194734_InitialCreate.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using CB.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 9 | 10 | #nullable disable 11 | 12 | namespace CB.Data.Migrations 13 | { 14 | [DbContext(typeof(CbContext))] 15 | [Migration("20250710194734_InitialCreate")] 16 | partial class InitialCreate 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.6") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 25 | 26 | NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("CB.Data.Entities.User", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("text"); 32 | 33 | b.Property("CreatedDate") 34 | .HasColumnType("timestamp without time zone"); 35 | 36 | b.Property("DisplayName") 37 | .IsRequired() 38 | .HasColumnType("text"); 39 | 40 | b.Property("ModifiedDate") 41 | .HasColumnType("timestamp without time zone"); 42 | 43 | b.HasKey("Id"); 44 | 45 | b.ToTable("Users", (string)null); 46 | }); 47 | #pragma warning restore 612, 618 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250710194734_InitialCreate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace CB.Data.Migrations 7 | { 8 | /// 9 | public partial class InitialCreate : Migration 10 | { 11 | /// 12 | protected override void Up(MigrationBuilder migrationBuilder) 13 | { 14 | migrationBuilder.CreateTable( 15 | name: "Users", 16 | columns: table => new 17 | { 18 | Id = table.Column(type: "text", nullable: false), 19 | DisplayName = table.Column(type: "text", nullable: false), 20 | CreatedDate = table.Column(type: "timestamp without time zone", nullable: false), 21 | ModifiedDate = table.Column(type: "timestamp without time zone", nullable: false) 22 | }, 23 | constraints: table => 24 | { 25 | table.PrimaryKey("PK_Users", x => x.Id); 26 | }); 27 | } 28 | 29 | /// 30 | protected override void Down(MigrationBuilder migrationBuilder) 31 | { 32 | migrationBuilder.DropTable( 33 | name: "Users"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250710201805_AddGuilds.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using CB.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 9 | 10 | #nullable disable 11 | 12 | namespace CB.Data.Migrations 13 | { 14 | [DbContext(typeof(CbContext))] 15 | [Migration("20250710201805_AddGuilds")] 16 | partial class AddGuilds 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.6") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 25 | 26 | NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("CB.Data.Entities.Guild", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("text"); 32 | 33 | b.Property("CreatedDate") 34 | .HasColumnType("timestamp without time zone"); 35 | 36 | b.Property("DisplayName") 37 | .IsRequired() 38 | .HasColumnType("text"); 39 | 40 | b.Property("ModifiedDate") 41 | .HasColumnType("timestamp without time zone"); 42 | 43 | b.Property("UserId") 44 | .IsRequired() 45 | .HasColumnType("text"); 46 | 47 | b.HasKey("Id"); 48 | 49 | b.HasIndex("UserId"); 50 | 51 | b.ToTable("Guilds", (string)null); 52 | }); 53 | 54 | modelBuilder.Entity("CB.Data.Entities.User", b => 55 | { 56 | b.Property("Id") 57 | .HasColumnType("text"); 58 | 59 | b.Property("CreatedDate") 60 | .HasColumnType("timestamp without time zone"); 61 | 62 | b.Property("DisplayName") 63 | .IsRequired() 64 | .HasColumnType("text"); 65 | 66 | b.Property("ModifiedDate") 67 | .HasColumnType("timestamp without time zone"); 68 | 69 | b.HasKey("Id"); 70 | 71 | b.ToTable("Users", (string)null); 72 | }); 73 | 74 | modelBuilder.Entity("CB.Data.Entities.Guild", b => 75 | { 76 | b.HasOne("CB.Data.Entities.User", "User") 77 | .WithMany("Guilds") 78 | .HasForeignKey("UserId") 79 | .OnDelete(DeleteBehavior.NoAction) 80 | .IsRequired(); 81 | 82 | b.Navigation("User"); 83 | }); 84 | 85 | modelBuilder.Entity("CB.Data.Entities.User", b => 86 | { 87 | b.Navigation("Guilds"); 88 | }); 89 | #pragma warning restore 612, 618 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250710201805_AddGuilds.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace CB.Data.Migrations 7 | { 8 | /// 9 | public partial class AddGuilds : Migration 10 | { 11 | /// 12 | protected override void Up(MigrationBuilder migrationBuilder) 13 | { 14 | migrationBuilder.CreateTable( 15 | name: "Guilds", 16 | columns: table => new 17 | { 18 | Id = table.Column(type: "text", nullable: false), 19 | DisplayName = table.Column(type: "text", nullable: false), 20 | UserId = table.Column(type: "text", nullable: false), 21 | CreatedDate = table.Column(type: "timestamp without time zone", nullable: false), 22 | ModifiedDate = table.Column(type: "timestamp without time zone", nullable: false) 23 | }, 24 | constraints: table => 25 | { 26 | table.PrimaryKey("PK_Guilds", x => x.Id); 27 | table.ForeignKey( 28 | name: "FK_Guilds_Users_UserId", 29 | column: x => x.UserId, 30 | principalTable: "Users", 31 | principalColumn: "Id"); 32 | }); 33 | 34 | migrationBuilder.CreateIndex( 35 | name: "IX_Guilds_UserId", 36 | table: "Guilds", 37 | column: "UserId"); 38 | } 39 | 40 | /// 41 | protected override void Down(MigrationBuilder migrationBuilder) 42 | { 43 | migrationBuilder.DropTable( 44 | name: "Guilds"); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250710203427_AddCreators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 4 | 5 | #nullable disable 6 | 7 | namespace CB.Data.Migrations 8 | { 9 | /// 10 | public partial class AddCreators : Migration 11 | { 12 | /// 13 | protected override void Up(MigrationBuilder migrationBuilder) 14 | { 15 | migrationBuilder.DropForeignKey( 16 | name: "FK_Guilds_Users_UserId", 17 | table: "Guilds"); 18 | 19 | migrationBuilder.RenameColumn( 20 | name: "UserId", 21 | table: "Guilds", 22 | newName: "OwnerId"); 23 | 24 | migrationBuilder.RenameIndex( 25 | name: "IX_Guilds_UserId", 26 | table: "Guilds", 27 | newName: "IX_Guilds_OwnerId"); 28 | 29 | migrationBuilder.CreateTable( 30 | name: "Creators", 31 | columns: table => new 32 | { 33 | Id = table.Column(type: "bigint", nullable: false) 34 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 35 | ChannelId = table.Column(type: "text", nullable: false), 36 | DisplayName = table.Column(type: "text", nullable: false), 37 | PlatformId = table.Column(type: "integer", nullable: false), 38 | UserId = table.Column(type: "text", nullable: false), 39 | IsLive = table.Column(type: "boolean", nullable: false), 40 | CreatedDate = table.Column(type: "timestamp without time zone", nullable: false), 41 | ModifiedDate = table.Column(type: "timestamp without time zone", nullable: false) 42 | }, 43 | constraints: table => 44 | { 45 | table.PrimaryKey("PK_Creators", x => x.Id); 46 | table.ForeignKey( 47 | name: "FK_Creators_Users_UserId", 48 | column: x => x.UserId, 49 | principalTable: "Users", 50 | principalColumn: "Id"); 51 | }); 52 | 53 | migrationBuilder.CreateIndex( 54 | name: "IX_Creators_UserId", 55 | table: "Creators", 56 | column: "UserId"); 57 | 58 | migrationBuilder.AddForeignKey( 59 | name: "FK_Guilds_Users_OwnerId", 60 | table: "Guilds", 61 | column: "OwnerId", 62 | principalTable: "Users", 63 | principalColumn: "Id"); 64 | } 65 | 66 | /// 67 | protected override void Down(MigrationBuilder migrationBuilder) 68 | { 69 | migrationBuilder.DropForeignKey( 70 | name: "FK_Guilds_Users_OwnerId", 71 | table: "Guilds"); 72 | 73 | migrationBuilder.DropTable( 74 | name: "Creators"); 75 | 76 | migrationBuilder.RenameColumn( 77 | name: "OwnerId", 78 | table: "Guilds", 79 | newName: "UserId"); 80 | 81 | migrationBuilder.RenameIndex( 82 | name: "IX_Guilds_OwnerId", 83 | table: "Guilds", 84 | newName: "IX_Guilds_UserId"); 85 | 86 | migrationBuilder.AddForeignKey( 87 | name: "FK_Guilds_Users_UserId", 88 | table: "Guilds", 89 | column: "UserId", 90 | principalTable: "Users", 91 | principalColumn: "Id"); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250710235930_PendingMigration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace CB.Data.Migrations 6 | { 7 | /// 8 | public partial class PendingMigration : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.DropForeignKey( 14 | name: "FK_ChannelConfigurations_Channels_ChannelId", 15 | table: "ChannelConfigurations"); 16 | 17 | migrationBuilder.DropIndex( 18 | name: "IX_ChannelConfigurations_ChannelId", 19 | table: "ChannelConfigurations"); 20 | 21 | migrationBuilder.DropColumn( 22 | name: "ChannelId", 23 | table: "ChannelConfigurations"); 24 | } 25 | 26 | /// 27 | protected override void Down(MigrationBuilder migrationBuilder) 28 | { 29 | migrationBuilder.AddColumn( 30 | name: "ChannelId", 31 | table: "ChannelConfigurations", 32 | type: "text", 33 | nullable: true); 34 | 35 | migrationBuilder.CreateIndex( 36 | name: "IX_ChannelConfigurations_ChannelId", 37 | table: "ChannelConfigurations", 38 | column: "ChannelId"); 39 | 40 | migrationBuilder.AddForeignKey( 41 | name: "FK_ChannelConfigurations_Channels_ChannelId", 42 | table: "ChannelConfigurations", 43 | column: "ChannelId", 44 | principalTable: "Channels", 45 | principalColumn: "Id"); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250715022843_7142025-928p.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace CB.Data.Migrations 6 | { 7 | /// 8 | public partial class _7142025928p : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.DropForeignKey( 14 | name: "FK_Guilds_Users_UserId", 15 | table: "Guilds"); 16 | 17 | migrationBuilder.DropIndex( 18 | name: "IX_Guilds_UserId", 19 | table: "Guilds"); 20 | 21 | migrationBuilder.DropColumn( 22 | name: "UserId", 23 | table: "Guilds"); 24 | 25 | migrationBuilder.CreateIndex( 26 | name: "IX_Guilds_OwnerId", 27 | table: "Guilds", 28 | column: "OwnerId"); 29 | 30 | migrationBuilder.AddForeignKey( 31 | name: "FK_Guilds_Users_OwnerId", 32 | table: "Guilds", 33 | column: "OwnerId", 34 | principalTable: "Users", 35 | principalColumn: "Id"); 36 | } 37 | 38 | /// 39 | protected override void Down(MigrationBuilder migrationBuilder) 40 | { 41 | migrationBuilder.DropForeignKey( 42 | name: "FK_Guilds_Users_OwnerId", 43 | table: "Guilds"); 44 | 45 | migrationBuilder.DropIndex( 46 | name: "IX_Guilds_OwnerId", 47 | table: "Guilds"); 48 | 49 | migrationBuilder.AddColumn( 50 | name: "UserId", 51 | table: "Guilds", 52 | type: "text", 53 | nullable: true); 54 | 55 | migrationBuilder.CreateIndex( 56 | name: "IX_Guilds_UserId", 57 | table: "Guilds", 58 | column: "UserId"); 59 | 60 | migrationBuilder.AddForeignKey( 61 | name: "FK_Guilds_Users_UserId", 62 | table: "Guilds", 63 | column: "UserId", 64 | principalTable: "Users", 65 | principalColumn: "Id"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250715022909_7142025-929p.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace CB.Data.Migrations 6 | { 7 | /// 8 | public partial class _7142025929p : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | 14 | } 15 | 16 | /// 17 | protected override void Down(MigrationBuilder migrationBuilder) 18 | { 19 | 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250716021538_7152025-906p.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace CB.Data.Migrations 6 | { 7 | /// 8 | public partial class _7152025906p : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | 14 | } 15 | 16 | /// 17 | protected override void Down(MigrationBuilder migrationBuilder) 18 | { 19 | 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250717225700_7172025-556p.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace CB.Data.Migrations 6 | { 7 | /// 8 | public partial class _7172025556p : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | 14 | } 15 | 16 | /// 17 | protected override void Down(MigrationBuilder migrationBuilder) 18 | { 19 | 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250717225843_7172025-558p.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace CB.Data.Migrations 7 | { 8 | /// 9 | public partial class _7172025558p : Migration 10 | { 11 | /// 12 | protected override void Up(MigrationBuilder migrationBuilder) 13 | { 14 | migrationBuilder.AlterColumn( 15 | name: "ModifiedDate", 16 | table: "Team", 17 | type: "timestamp with time zone", 18 | nullable: false, 19 | oldClrType: typeof(DateTime), 20 | oldType: "timestamp without time zone"); 21 | 22 | migrationBuilder.AlterColumn( 23 | name: "CreatedDate", 24 | table: "Team", 25 | type: "timestamp with time zone", 26 | nullable: false, 27 | oldClrType: typeof(DateTime), 28 | oldType: "timestamp without time zone"); 29 | } 30 | 31 | /// 32 | protected override void Down(MigrationBuilder migrationBuilder) 33 | { 34 | migrationBuilder.AlterColumn( 35 | name: "ModifiedDate", 36 | table: "Team", 37 | type: "timestamp without time zone", 38 | nullable: false, 39 | oldClrType: typeof(DateTime), 40 | oldType: "timestamp with time zone"); 41 | 42 | migrationBuilder.AlterColumn( 43 | name: "CreatedDate", 44 | table: "Team", 45 | type: "timestamp without time zone", 46 | nullable: false, 47 | oldClrType: typeof(DateTime), 48 | oldType: "timestamp with time zone"); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250718013457_7172025-834p.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional 6 | 7 | namespace CB.Data.Migrations 8 | { 9 | /// 10 | public partial class _7172025834p : Migration 11 | { 12 | /// 13 | protected override void Up(MigrationBuilder migrationBuilder) 14 | { 15 | migrationBuilder.InsertData( 16 | table: "FilterType", 17 | columns: new[] { "Id", "DisplayName" }, 18 | values: new object[,] 19 | { 20 | { 1, "Game" }, 21 | { 2, "Title" } 22 | }); 23 | } 24 | 25 | /// 26 | protected override void Down(MigrationBuilder migrationBuilder) 27 | { 28 | migrationBuilder.DeleteData( 29 | table: "FilterType", 30 | keyColumn: "Id", 31 | keyValue: 1); 32 | 33 | migrationBuilder.DeleteData( 34 | table: "FilterType", 35 | keyColumn: "Id", 36 | keyValue: 2); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250718014125_7172025-841p.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional 6 | 7 | namespace CB.Data.Migrations 8 | { 9 | /// 10 | public partial class _7172025841p : Migration 11 | { 12 | /// 13 | protected override void Up(MigrationBuilder migrationBuilder) 14 | { 15 | migrationBuilder.InsertData( 16 | table: "Platform", 17 | columns: new[] { "Id", "DisplayName", "Enabled", "LogoUrl", "SiteUrl" }, 18 | values: new object[,] 19 | { 20 | { 3, "Picarto", false, null, null }, 21 | { 4, "Piczel", false, null, null }, 22 | { 6, "Twitch", false, null, null }, 23 | { 7, "YouTube", false, null, null }, 24 | { 10, "Trovo", false, null, null }, 25 | { 13, "DLive", false, null, null } 26 | }); 27 | } 28 | 29 | /// 30 | protected override void Down(MigrationBuilder migrationBuilder) 31 | { 32 | migrationBuilder.DeleteData( 33 | table: "Platform", 34 | keyColumn: "Id", 35 | keyValue: 3); 36 | 37 | migrationBuilder.DeleteData( 38 | table: "Platform", 39 | keyColumn: "Id", 40 | keyValue: 4); 41 | 42 | migrationBuilder.DeleteData( 43 | table: "Platform", 44 | keyColumn: "Id", 45 | keyValue: 6); 46 | 47 | migrationBuilder.DeleteData( 48 | table: "Platform", 49 | keyColumn: "Id", 50 | keyValue: 7); 51 | 52 | migrationBuilder.DeleteData( 53 | table: "Platform", 54 | keyColumn: "Id", 55 | keyValue: 10); 56 | 57 | migrationBuilder.DeleteData( 58 | table: "Platform", 59 | keyColumn: "Id", 60 | keyValue: 13); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250718015544_7172025-855p.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace CB.Data.Migrations 6 | { 7 | /// 8 | public partial class _7172025855p : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.DropForeignKey( 14 | name: "FK_Filters_Platform_PlatformId", 15 | table: "Filters"); 16 | 17 | migrationBuilder.AlterColumn( 18 | name: "PlatformId", 19 | table: "Filters", 20 | type: "integer", 21 | nullable: true, 22 | oldClrType: typeof(int), 23 | oldType: "integer"); 24 | 25 | migrationBuilder.InsertData( 26 | table: "Platform", 27 | columns: new[] { "Id", "DisplayName", "Enabled", "LogoUrl", "SiteUrl" }, 28 | values: new object[] { 1, "All", false, null, null }); 29 | 30 | migrationBuilder.AddForeignKey( 31 | name: "FK_Filters_Platform_PlatformId", 32 | table: "Filters", 33 | column: "PlatformId", 34 | principalTable: "Platform", 35 | principalColumn: "Id"); 36 | } 37 | 38 | /// 39 | protected override void Down(MigrationBuilder migrationBuilder) 40 | { 41 | migrationBuilder.DropForeignKey( 42 | name: "FK_Filters_Platform_PlatformId", 43 | table: "Filters"); 44 | 45 | migrationBuilder.DeleteData( 46 | table: "Platform", 47 | keyColumn: "Id", 48 | keyValue: 1); 49 | 50 | migrationBuilder.AlterColumn( 51 | name: "PlatformId", 52 | table: "Filters", 53 | type: "integer", 54 | nullable: false, 55 | defaultValue: 0, 56 | oldClrType: typeof(int), 57 | oldType: "integer", 58 | oldNullable: true); 59 | 60 | migrationBuilder.AddForeignKey( 61 | name: "FK_Filters_Platform_PlatformId", 62 | table: "Filters", 63 | column: "PlatformId", 64 | principalTable: "Platform", 65 | principalColumn: "Id", 66 | onDelete: ReferentialAction.Cascade); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/CB.Data/Migrations/20250724033914_7232025-1036p.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace CB.Data.Migrations 6 | { 7 | /// 8 | public partial class _72320251036p : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.CreateTable( 14 | name: "FunStuff", 15 | columns: table => new 16 | { 17 | HaiBaiCount = table.Column(type: "integer", nullable: false, defaultValue: 0) 18 | }, 19 | constraints: table => 20 | { 21 | }); 22 | } 23 | 24 | /// 25 | protected override void Down(MigrationBuilder migrationBuilder) 26 | { 27 | migrationBuilder.DropTable( 28 | name: "FunStuff"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/CB.Engines/CB.Engines.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/CB.Engines/Contracts/ICreatorEngine.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Dtos; 2 | using CB.Shared.Enums; 3 | using CB.Shared.Responses; 4 | using Discord; 5 | using Discord.WebSocket; 6 | using ChannelType = CB.Shared.Enums.ChannelType; 7 | 8 | namespace CB.Engines.Contracts; 9 | 10 | public interface ICreatorEngine 11 | { 12 | Task ToggleCreatorAsync(ChannelValidityResponse validChannel, 13 | Platform platform, 14 | GuildDto guild, 15 | string authorName, 16 | string creatorName, 17 | ChannelType channelType, 18 | string customMessage, 19 | // TODO This shouldnt be here. 20 | // Carrying this over for now .. just for ease ... 21 | // But all communication should be on the InteractionService layer. Just return 22 | // messaging ...? 23 | SocketInteraction socketInteraction, 24 | IGuildChannel announcementChannel 25 | ); 26 | } -------------------------------------------------------------------------------- /src/CB.Shared/CB.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/CB.Shared/Constants.cs: -------------------------------------------------------------------------------- 1 | using Discord; 2 | 3 | namespace CB.Shared; 4 | 5 | public static class Constants 6 | { 7 | public static class AllowOptions 8 | { 9 | public const string GreetingsOption = "greetings"; 10 | public const string GoodbyesOption = "goodbyes"; 11 | public const string LiveOption = "live"; 12 | public const string PublishedOption = "published"; 13 | public const string StreamVodOption = "stream vod"; 14 | public const string ThumbnailsOption = "thumbnails"; 15 | public const string FfaOption = "ffa"; 16 | public const string CrosspostOption = "crosspost"; 17 | public const string DeleteOfflineOption = "deleteoffline"; 18 | public const string TextAnnouncements = "textannouncements"; 19 | public const string DiscordLiveAnnouncements = "discordlive"; 20 | } 21 | 22 | public static class Colors 23 | { 24 | public static Color YouTubeRed = new(0xFF0000); 25 | public static Color PicartoWhite = new(0xFFFFFF); 26 | public static Color TwitchPurple = new(0x6441A5); 27 | } 28 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/AllowConfigurationDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class AllowConfigurationDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public bool AllowLive { get; set; } 8 | public bool AllowPublished { get; set; } 9 | public bool AllowThumbnails { get; set; } 10 | public bool AllowGreetings { get; set; } 11 | public bool AllowGoodbyes { get; set; } 12 | public bool AllowLiveDiscovery { get; set; } 13 | public bool AllowStreamVod { get; set; } 14 | public bool AllowFfa { get; set; } 15 | public bool AllowCrosspost { get; set; } 16 | public bool AllowDiscordLive { get; set; } 17 | 18 | //public virtual GuildDto Guild { get; set; } 19 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/CbProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using CB.Data.Entities; 3 | 4 | namespace CB.Shared.Dtos; 5 | 6 | public class CbProfile : Profile 7 | { 8 | public CbProfile() 9 | { 10 | CreateMap().ReverseMap(); 11 | CreateMap().ReverseMap(); 12 | CreateMap().ReverseMap(); 13 | CreateMap().ReverseMap(); 14 | CreateMap().ReverseMap(); 15 | CreateMap().ReverseMap(); 16 | CreateMap().ReverseMap(); 17 | CreateMap().ReverseMap(); 18 | CreateMap().ReverseMap(); 19 | CreateMap().ReverseMap(); 20 | CreateMap().ReverseMap(); 21 | CreateMap().ReverseMap(); 22 | CreateMap().ReverseMap(); 23 | CreateMap().ReverseMap(); 24 | CreateMap().ReverseMap(); 25 | CreateMap().ReverseMap(); 26 | CreateMap().ReverseMap(); 27 | CreateMap().ReverseMap(); 28 | CreateMap().ReverseMap(); 29 | CreateMap().ReverseMap(); 30 | CreateMap().ReverseMap(); 31 | CreateMap().ReverseMap(); 32 | CreateMap().ReverseMap(); 33 | CreateMap().ReverseMap(); 34 | } 35 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/ChannelConfigurationDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class ChannelConfigurationDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public string? GreetingChannelId { get; set; } 8 | public string? GoodbyeChannelId { get; set; } 9 | public string? LiveChannelId { get; set; } 10 | public string? DiscordLiveChannelId { get; set; } 11 | 12 | //public virtual GuildDto Guild { get; set; } 13 | //public virtual ChannelDto GreetingChannel { get; set; } 14 | //public virtual ChannelDto GoodbyeChannel { get; set; } 15 | //public virtual ChannelDto LiveChannel { get; set; } 16 | //public virtual ChannelDto DiscordLiveChannel { get; set; } 17 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/ChannelConfigurationSummaryDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class ChannelConfigurationSummaryDto 4 | { 5 | public string Id { get; set; } 6 | 7 | public string DisplayName { get; set; } 8 | public string GuildId { get; set; } 9 | public DateTime CreatedDate { get; set; } 10 | public DateTime ModifiedDate { get; set; } 11 | 12 | //public virtual GuildDto Guild { get; set; } 13 | 14 | //public virtual ICollection CreatorChannels { get; set; } = new List(); 15 | //public virtual ICollection GameChannels { get; set; } = new List(); 16 | //public virtual ICollection TeamChannels { get; set; } = new List(); 17 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/ChannelDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class ChannelDto 4 | { 5 | public string Id { get; set; } 6 | 7 | public string DisplayName { get; set; } 8 | public string GuildId { get; set; } 9 | public DateTime CreatedDate { get; set; } 10 | public DateTime ModifiedDate { get; set; } 11 | 12 | public virtual GuildDto Guild { get; set; } 13 | 14 | public virtual ICollection CreatorChannels { get; set; } = new List(); 15 | public virtual ICollection GameChannels { get; set; } = new List(); 16 | public virtual ICollection TeamChannels { get; set; } = new List(); 17 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/ClipEmbedDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class ClipEmbedDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public string Header { get; set; } 8 | 9 | public string Description { get; set; } 10 | 11 | public string Footer { get; set; } 12 | 13 | public string WatchButton { get; set; } 14 | 15 | public string MoreButton { get; set; } 16 | 17 | //public virtual GuildDto Guild { get; set; } 18 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/CreatorChannelDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class CreatorChannelDto 4 | { 5 | public long CreatorId { get; set; } 6 | public string ChannelId { get; set; } 7 | public int ChannelTypeId { get; set; } 8 | public string CustomMessage { get; set; } 9 | 10 | public CreatorDto Creator { get; set; } 11 | public ChannelDto Channel { get; set; } 12 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/CreatorDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class CreatorDto 4 | { 5 | public long Id { get; set; } 6 | 7 | public string ChannelId { get; set; } 8 | 9 | public string DisplayName { get; set; } 10 | 11 | public int PlatformId { get; set; } 12 | 13 | public string UserId { get; set; } 14 | 15 | public bool IsLive { get; set; } 16 | 17 | public DateTime CreatedDate { get; set; } 18 | 19 | public DateTime ModifiedDate { get; set; } 20 | 21 | public virtual UserDto User { get; set; } 22 | 23 | public virtual ICollection CreatorChannels { get; set; } = new List(); 24 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/DiscordLiveConfigurationDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class DiscordLiveConfigurationDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public string Message { get; set; } 8 | public string Header { get; set; } 9 | public string Description { get; set; } 10 | public string Footer { get; set; } 11 | public string MentionRoleId { get; set; } 12 | 13 | //public virtual GuildDto Guild { get; set; } 14 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/DropdownPayloadDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class DropdownPayloadDto 4 | { 5 | public int Id { get; set; } 6 | public string Payload { get; set; } 7 | public string DropdownType { get; set; } 8 | public string OriginalMessageId { get; set; } 9 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/FilterDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class FilterDto 4 | { 5 | public int Id { get; set; } 6 | public string Text { get; set; } 7 | public int? PlatformId { get; set; } 8 | public int FilterTypeId { get; set; } 9 | public string GuildId { get; set; } 10 | 11 | public PlatformDto? Platform { get; set; } 12 | public FilterTypeDto FilterType { get; set; } 13 | public GuildDto Guild { get; set; } 14 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/FilterTypeDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class FilterTypeDto 4 | { 5 | public int Id { get; set; } 6 | public string DisplayName { get; set; } 7 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/GameChannelDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class GameChannelDto 4 | { 5 | public int GameId { get; set; } 6 | public string ChannelId { get; set; } 7 | 8 | public GameDto Game { get; set; } 9 | public ChannelDto Channel { get; set; } 10 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/GameDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class GameDto 4 | { 5 | public int Id { get; set; } 6 | 7 | public string DisplayName { get; set; } 8 | public DateTime CreatedDate { get; set; } 9 | public DateTime ModifiedDate { get; set; } 10 | public int PlatformId { get; set; } 11 | public string GameId { get; set; } 12 | 13 | public virtual PlatformDto Platform { get; set; } 14 | public virtual ICollection GameChannels { get; set; } 15 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/GuildConfigurationDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class GuildConfigurationDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public bool TextAnnouncements { get; set; } 8 | public bool DeleteOffline { get; set; } 9 | 10 | //public virtual GuildDto Guild { get; set; } 11 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/GuildConfigurationSummaryDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Shared.Dtos; 4 | 5 | public class GuildConfigurationSummaryDto 6 | { 7 | public string Id { get; set; } 8 | 9 | public string DisplayName { get; set; } 10 | 11 | public string OwnerId { get; set; } 12 | 13 | public DateTime CreatedDate { get; set; } 14 | 15 | public DateTime ModifiedDate { get; set; } 16 | 17 | //public virtual UserDto Owner { get; set; } 18 | //public virtual ICollection Channels { get; set; } 19 | public virtual AllowConfigurationDto AllowConfiguration { get; set; } 20 | public virtual ChannelConfigurationDto ChannelConfiguration { get; set; } 21 | public virtual GuildConfigurationDto GuildConfiguration { get; set; } 22 | public virtual MessageConfigurationDto MessageConfiguration { get; set; } 23 | public virtual RoleConfigurationDto RoleConfiguration { get; set; } 24 | //public virtual ClipEmbedDto ClipEmbed { get; set; } 25 | //public virtual LiveEmbedDto LiveEmbed { get; set; } 26 | //public virtual VodEmbedDto VodEmbed { get; set; } 27 | //public virtual DiscordLiveConfigurationDto DiscordLiveConfiguration { get; set; } 28 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/GuildDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace CB.Shared.Dtos; 4 | 5 | public class GuildDto 6 | { 7 | public string Id { get; set; } 8 | 9 | public string DisplayName { get; set; } 10 | 11 | public string OwnerId { get; set; } 12 | 13 | public DateTime CreatedDate { get; set; } 14 | 15 | public DateTime ModifiedDate { get; set; } 16 | 17 | public virtual UserDto Owner { get; set; } 18 | public virtual ICollection Channels { get; set; } 19 | public virtual AllowConfigurationDto AllowConfiguration { get; set; } 20 | public virtual ChannelConfigurationDto ChannelConfiguration { get; set; } 21 | public virtual GuildConfigurationDto GuildConfiguration { get; set; } 22 | public virtual MessageConfigurationDto MessageConfiguration { get; set; } 23 | public virtual RoleConfigurationDto RoleConfiguration { get; set; } 24 | public virtual ClipEmbedDto ClipEmbed { get; set; } 25 | public virtual LiveEmbedDto LiveEmbed { get; set; } 26 | public virtual VodEmbedDto VodEmbed { get; set; } 27 | public virtual DiscordLiveConfigurationDto DiscordLiveConfiguration { get; set; } 28 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/LiveEmbedDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class LiveEmbedDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public string Header { get; set; } 8 | 9 | public string Description { get; set; } 10 | 11 | public string LastStreamed { get; set; } 12 | 13 | public string AverageStream { get; set; } 14 | 15 | public string DescriptionLabel { get; set; } 16 | 17 | public string StreamDescription { get; set; } 18 | 19 | public string FooterStart { get; set; } 20 | 21 | public string FooterStopped { get; set; } 22 | 23 | public string ChannelButton { get; set; } 24 | 25 | //public virtual GuildDto Guild { get; set; } 26 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/MessageConfigurationDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class MessageConfigurationDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public string GreetingMessage { get; set; } 8 | public string GoodbyeMessage { get; set; } 9 | public string LiveMessage { get; set; } 10 | public string PublishedMessage { get; set; } 11 | public string StreamOfflineMessage { get; set; } 12 | 13 | //public virtual GuildDto Guild { get; set; } 14 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/PlatformDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class PlatformDto 4 | { 5 | public int Id { get; set; } 6 | public string DisplayName { get; set; } 7 | public string SiteUrl { get; set; } 8 | public string LogoUrl { get; set; } 9 | public bool Enabled { get; set; } 10 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/RoleConfigurationDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class RoleConfigurationDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public string JoinRoleId { get; set; } 8 | public string DiscoveryRoleId { get; set; } 9 | public string LiveDiscoveryRoleId { get; set; } 10 | 11 | //public virtual GuildDto Guild { get; set; } 12 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/TeamChannelDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class TeamChannelDto 4 | { 5 | public int TeamId { get; set; } 6 | public string ChannelId { get; set; } 7 | 8 | public TeamDto Team { get; set; } 9 | public ChannelDto Channel { get; set; } 10 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/TeamDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class TeamDto 4 | { 5 | public int Id { get; set; } 6 | 7 | public string DisplayName { get; set; } 8 | public DateTime CreatedDate { get; set; } 9 | public DateTime ModifiedDate { get; set; } 10 | public int PlatformId { get; set; } 11 | public string TeamId { get; set; } 12 | 13 | public virtual PlatformDto Platform { get; set; } 14 | public ICollection TeamChannels { get; set; } 15 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/UserDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class UserDto 4 | { 5 | public string Id { get; set; } 6 | 7 | public string DisplayName { get; set; } 8 | 9 | public DateTime CreatedDate { get; set; } 10 | 11 | public DateTime ModifiedDate { get; set; } 12 | 13 | public virtual ICollection Guilds { get; set; } 14 | public virtual ICollection Creators { get; set; } 15 | } -------------------------------------------------------------------------------- /src/CB.Shared/Dtos/VodEmbedDto.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Dtos; 2 | 3 | public class VodEmbedDto 4 | { 5 | public string GuildId { get; set; } 6 | 7 | public string Header { get; set; } 8 | 9 | public string DescriptionLabel { get; set; } 10 | 11 | public string Description { get; set; } 12 | 13 | public string Footer { get; set; } 14 | 15 | public string ChannelButton { get; set; } 16 | 17 | //public virtual GuildDto Guild { get; set; } 18 | } -------------------------------------------------------------------------------- /src/CB.Shared/Enums/ChannelType.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Enums; 2 | 3 | public enum ChannelType 4 | { 5 | Live = 1, 6 | Vod = 2, 7 | All = 3, 8 | Clips = 4, 9 | Premieres = 5, 10 | Shorts = 6, 11 | Stories = 7, 12 | } 13 | 14 | public enum TwitchChannelType 15 | { 16 | Live = 1, 17 | Vod = 2, 18 | All = 3, 19 | Clips = 4, 20 | Stories = 7, 21 | } 22 | 23 | public enum YouTubeChannelType 24 | { 25 | Live = 1, 26 | Vod = 2, 27 | All = 3, 28 | Premieres = 5, 29 | Shorts = 6, 30 | } -------------------------------------------------------------------------------- /src/CB.Shared/Enums/ChannelTypeTwitch.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Enums; 2 | 3 | public enum ChannelTypeTwitch 4 | { 5 | Live = 1, 6 | //Vod = 2, 7 | All = 3, 8 | Clips = 4, 9 | //Premieres = 5, 10 | //Shorts = 6, 11 | } -------------------------------------------------------------------------------- /src/CB.Shared/Enums/ChannelTypeYouTube.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Enums; 2 | 3 | public enum ChannelTypeYouTube 4 | { 5 | Live = 1, 6 | Vod = 2, 7 | All = 3, 8 | //Clips = 4, 9 | //Premieres = 5, 10 | Shorts = 6, 11 | } -------------------------------------------------------------------------------- /src/CB.Shared/Enums/ConfiguredChannelType.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Enums; 2 | 3 | public enum ConfiguredChannelType 4 | { 5 | Greetings, 6 | Goodbyes, 7 | Live, 8 | DiscordLive, 9 | } -------------------------------------------------------------------------------- /src/CB.Shared/Enums/DropdownType.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Enums; 2 | 3 | public enum DropdownType 4 | { 5 | AllowConfiguration, 6 | YouTubeCreator 7 | } -------------------------------------------------------------------------------- /src/CB.Shared/Enums/FilterType.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Enums; 2 | 3 | public enum FilterType 4 | { 5 | Game = 1, 6 | Title = 2 7 | } -------------------------------------------------------------------------------- /src/CB.Shared/Enums/MessageType.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Enums; 2 | 3 | public enum MessageType 4 | { 5 | Live, 6 | Published, 7 | Offline, 8 | Greeting, 9 | Goodbye 10 | } -------------------------------------------------------------------------------- /src/CB.Shared/Enums/Platform.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Enums; 2 | 3 | public enum Platform 4 | { 5 | All = 1, 6 | Picarto = 3, 7 | Piczel = 4, 8 | Twitch = 6, 9 | YouTube = 7, 10 | Trovo = 10, 11 | DLive = 13 12 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Bot/GenericDropdownPayload.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.Bot; 2 | 3 | public class GenericDropdownPayload 4 | { 5 | public ulong AuthorId { get; set; } 6 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Bot/ListViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.Bot; 2 | 3 | public class ListViewModel 4 | { 5 | public string DisplayName { get; set; } 6 | 7 | public string CreatorChannelId { get; set; } 8 | 9 | public int PlatformId { get; set; } 10 | 11 | public string ChannelName { get; set; } 12 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Bot/YouTubeCreatorDropdownPayload.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.Bot; 2 | 3 | public class YouTubeCreatorDropdownPayload : GenericDropdownPayload 4 | { 5 | public ulong GuildId { get; set; } 6 | public ulong ChannelId { get; set; } 7 | public int ChannelType { get; set; } 8 | public string CustomMessage { get; set; } 9 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/DLive/DLiveUser.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.DLive; 2 | 3 | public class DLiveUser 4 | { 5 | public Data Data { get; set; } 6 | } 7 | 8 | public class UserByDisplayName 9 | { 10 | public string Id { get; set; } 11 | public string Username { get; set; } 12 | public string DisplayName { get; set; } 13 | } 14 | public class Followers 15 | { 16 | public int TotalCount { get; set; } 17 | } 18 | 19 | public class Category 20 | { 21 | public string Title { get; set; } 22 | } 23 | 24 | public class Livestream 25 | { 26 | public string ThumbnailUrl { get; set; } 27 | public string Title { get; set; } 28 | public int WatchingCount { get; set; } 29 | public Category Category { get; set; } 30 | } 31 | 32 | public class User 33 | { 34 | public string DisplayName { get; set; } 35 | public string Avatar { get; set; } 36 | public Followers Followers { get; set; } 37 | public Livestream Livestream { get; set; } 38 | } 39 | 40 | public class Data 41 | { 42 | public UserByDisplayName UserByDisplayName { get; set; } 43 | public User User { get; set; } 44 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Picarto/Channel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Picarto; 4 | 5 | public class Channel 6 | { 7 | public string Avatar { get; set; } 8 | 9 | public string Color { get; set; } 10 | 11 | [JsonProperty("created_at")] 12 | public string CreatedAt { get; set; } 13 | 14 | public string Name { get; set; } 15 | 16 | public bool Online { get; set; } 17 | 18 | public string Title { get; set; } 19 | 20 | [JsonProperty("total_views")] 21 | public int TotalViews { get; set; } 22 | 23 | public int Viewers { get; set; } 24 | 25 | [JsonProperty("followers_count")] 26 | public int FollowersCount { get; set; } 27 | 28 | [JsonProperty("subscribers_count")] 29 | public int SubscribersCount { get; set; } 30 | 31 | [JsonProperty("avatar_url")] 32 | public string AvatarUrl { get; set; } 33 | 34 | [JsonProperty("image_thumbnail")] 35 | public string ImageThumbnail { get; set; } 36 | 37 | public string DisplayName { get; set; } 38 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Picarto/ChannelDetails.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Picarto; 4 | 5 | public class ChannelDetails 6 | { 7 | [JsonProperty("user_id")] 8 | public int UserId { get; set; } 9 | 10 | public string Name { get; set; } 11 | 12 | public string Avatar { get; set; } 13 | 14 | public bool Online { get; set; } 15 | 16 | public int Viewers { get; set; } 17 | 18 | [JsonProperty("viewers_total")] 19 | public int ViewersTotal { get; set; } 20 | 21 | public Thumbnails Thumbnails { get; set; } 22 | 23 | public int Followers { get; set; } 24 | 25 | public int Subscribers { get; set; } 26 | 27 | public bool Adult { get; set; } 28 | 29 | public List Category { get; set; } 30 | 31 | [JsonProperty("account_type")] 32 | public string AccountType { get; set; } 33 | 34 | public bool Commissions { get; set; } 35 | 36 | public bool Recordings { get; set; } 37 | 38 | public string Title { get; set; } 39 | 40 | [JsonProperty("description_panels")] 41 | public List DescriptionPanels { get; set; } 42 | 43 | public bool Private { get; set; } 44 | 45 | [JsonProperty("private_message")] 46 | public string PrivateMessage { get; set; } 47 | 48 | public bool Gaming { get; set; } 49 | 50 | [JsonProperty("chat_settings")] 51 | public ChatSettings ChatSettings { get; set; } 52 | 53 | [JsonProperty("last_live")] 54 | public object LastLive { get; set; } 55 | 56 | public List Tags { get; set; } 57 | 58 | public object Multistream { get; set; } 59 | 60 | public List Languages { get; set; } 61 | 62 | public bool Following { get; set; } 63 | 64 | [JsonProperty("creation_date")] 65 | public string CreationDate { get; set; } 66 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Picarto/ChatSettings.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Picarto; 4 | 5 | public class ChatSettings 6 | { 7 | [JsonProperty("guest_chat")] 8 | public bool GuestChat { get; set; } 9 | 10 | public bool Links { get; set; } 11 | 12 | public bool Level { get; set; } 13 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Picarto/Language.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.Picarto; 2 | 3 | public class Language 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } 8 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Picarto/PicartoChannel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Picarto; 4 | 5 | public class PicartoChannel 6 | { 7 | [JsonProperty("channel")] 8 | public Channel ChannelData; 9 | 10 | [JsonProperty("getLoadBalancerUrl")] 11 | public GetLoadBalancerUrl GetLoadBalancerUrlData; 12 | 13 | [JsonProperty("getMultiStreams")] 14 | public GetMultiStreams GetMultiStreamsData; 15 | 16 | public class Category 17 | { 18 | public string Name; 19 | } 20 | 21 | public class Channel 22 | { 23 | public bool Online; 24 | 25 | public string Color; 26 | 27 | [JsonProperty("dm_setting")] 28 | public DmSetting DmSetting; 29 | 30 | [JsonProperty("created_at")] 31 | public string CreatedAt; 32 | 33 | public bool Notification; 34 | 35 | public bool Gifted; 36 | 37 | [JsonProperty("gifted_channel_name")] 38 | public object GiftedChannelName; 39 | 40 | public int Id; 41 | 42 | [JsonProperty("account_type")] 43 | public string AccountType; 44 | 45 | public bool Adult; 46 | 47 | public string Avatar; 48 | 49 | public string Bio; 50 | 51 | public int Columns; 52 | 53 | public bool Commissions; 54 | 55 | [JsonProperty("enable_subscription")] 56 | public bool EnableSubscription; 57 | 58 | public bool Gaming; 59 | 60 | public string Name; 61 | 62 | public bool Private; 63 | 64 | [JsonProperty("show_subscriber_count")] 65 | public bool ShowSubscriberCount; 66 | 67 | public string Title; 68 | 69 | public bool Verified; 70 | 71 | public bool Streaming; 72 | 73 | [JsonProperty("total_views")] 74 | public int TotalViews; 75 | 76 | public int Viewers; 77 | 78 | public List Descriptions; 79 | 80 | public List Banners; 81 | 82 | public List Categories; 83 | 84 | public List Languages; 85 | 86 | [JsonProperty("social_medias")] 87 | public List SocialMedias; 88 | 89 | public List Softwares; 90 | 91 | public List Tags; 92 | 93 | public List Tools; 94 | 95 | [JsonProperty("followers_count")] 96 | public int FollowersCount; 97 | 98 | [JsonProperty("videos_count")] 99 | public int VideosCount; 100 | } 101 | 102 | public class DmSetting 103 | { 104 | [JsonProperty("allow_message_every_one")] 105 | public bool AllowMessageEveryOne; 106 | } 107 | 108 | public class GetLoadBalancerUrl 109 | { 110 | public string Url; 111 | 112 | public string Origin; 113 | } 114 | 115 | public class GetMultiStreams 116 | { 117 | public string Name; 118 | 119 | public bool Streaming; 120 | 121 | public bool Online; 122 | 123 | public int Viewers; 124 | 125 | public bool Multistream; 126 | 127 | public List Streams; 128 | 129 | public string DisplayName; 130 | } 131 | 132 | public class Language 133 | { 134 | public int Id; 135 | 136 | public string Name; 137 | 138 | public string Code; 139 | 140 | public object Image; 141 | } 142 | 143 | public class Software 144 | { 145 | public int Id; 146 | 147 | public string Name; 148 | } 149 | 150 | public class Stream 151 | { 152 | public int Id; 153 | 154 | [JsonProperty("user_id")] 155 | public int UserId; 156 | 157 | public string Name; 158 | 159 | [JsonProperty("account_type")] 160 | public string AccountType; 161 | 162 | public string Avatar; 163 | 164 | [JsonProperty("offline_image")] 165 | public object OfflineImage; 166 | 167 | public bool Streaming; 168 | 169 | public bool Adult; 170 | 171 | public bool Multistream; 172 | 173 | public int Viewers; 174 | 175 | public bool Hosted; 176 | 177 | public bool Host; 178 | 179 | public bool Following; 180 | 181 | public bool Subscription; 182 | 183 | public bool Online; 184 | 185 | public int ChannelId; 186 | 187 | [JsonProperty("stream_name")] 188 | public string StreamName; 189 | 190 | public string Color; 191 | 192 | public bool Webrtc; 193 | 194 | [JsonProperty("subscription_enabled")] 195 | public bool SubscriptionEnabled; 196 | 197 | [JsonProperty("thumbnail_image")] 198 | public string ThumbnailImage; 199 | } 200 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Picarto/PicartoUser.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Picarto; 4 | 5 | public class PicartoUser 6 | { 7 | [JsonProperty("channel_details")] 8 | public ChannelDetails ChannelDetails { get; set; } 9 | 10 | public string Email { get; set; } 11 | 12 | [JsonProperty("creation_date")] 13 | public string CreationDate { get; set; } 14 | 15 | [JsonProperty("private_key")] 16 | public string PrivateKey { get; set; } 17 | 18 | [JsonProperty("nsfw_enabled")] 19 | public bool NsfwEnabled { get; set; } 20 | 21 | [JsonProperty("nsfw_app")] 22 | public bool NsfwApp { get; set; } 23 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Picarto/Thumbnails.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Picarto; 4 | 5 | public class Thumbnails 6 | { 7 | public string Web { get; set; } 8 | 9 | [JsonProperty("web_large")] 10 | public string WebLarge { get; set; } 11 | 12 | public string Mobile { get; set; } 13 | 14 | public string Tablet { get; set; } 15 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Piczel/PiczelChannel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Piczel; 4 | 5 | public class PiczelChannel 6 | { 7 | public string Type { get; set; } 8 | 9 | public List Data { get; set; } 10 | 11 | [JsonProperty("meta")] 12 | public Meta Meta_ { get; set; } 13 | 14 | public class OfflineImage 15 | { 16 | public object Url { get; set; } 17 | } 18 | 19 | public class Banner2 20 | { 21 | public object Url { get; set; } 22 | } 23 | 24 | public class Banner 25 | { 26 | [JsonProperty("banner")] 27 | public Banner2 Banner_ { get; set; } 28 | } 29 | 30 | public class Preview 31 | { 32 | public object Url { get; set; } 33 | } 34 | 35 | public class Basic 36 | { 37 | public bool Listed { get; set; } 38 | 39 | public bool AllowAnon { get; set; } 40 | 41 | public bool Notifications { get; set; } 42 | } 43 | 44 | public class Recording 45 | { 46 | public bool Enabled { get; set; } 47 | 48 | public bool Download { get; set; } 49 | 50 | [JsonProperty("timelapse_speed")] 51 | public int TimelapseSpeed { get; set; } 52 | 53 | [JsonProperty("watermark_timelapse")] 54 | public bool WatermarkTimelapse { get; set; } 55 | 56 | [JsonProperty("gen_timelapse")] 57 | public bool GenTimelapse { get; set; } 58 | } 59 | 60 | public class Private 61 | { 62 | public bool Enabled { get; set; } 63 | 64 | public bool Moderated { get; set; } 65 | } 66 | 67 | public class Emails 68 | { 69 | public bool Enabled { get; set; } 70 | } 71 | 72 | public class Settings 73 | { 74 | public Basic Basic { get; set; } 75 | 76 | public Recording Recording { get; set; } 77 | 78 | public Private Private { get; set; } 79 | 80 | public Emails Emails { get; set; } 81 | } 82 | 83 | public class Avatar 84 | { 85 | public string Url { get; set; } 86 | } 87 | 88 | public class Gallery 89 | { 90 | [JsonProperty("profile_description")] 91 | public string ProfileDescription { get; set; } 92 | } 93 | 94 | public class User 95 | { 96 | public int Id { get; set; } 97 | 98 | public string Username { get; set; } 99 | 100 | [JsonProperty("premium?")] 101 | public bool Premium { get; set; } 102 | 103 | public Avatar Avatar { get; set; } 104 | 105 | public string Role { get; set; } 106 | 107 | public Gallery Gallery { get; set; } 108 | 109 | [JsonProperty("follower_count")] 110 | public int FollowerCount { get; set; } 111 | } 112 | 113 | public class Datum 114 | { 115 | public int Id { get; set; } 116 | 117 | public string Title { get; set; } 118 | 119 | public object Description { get; set; } 120 | 121 | [JsonProperty("rendered_description")] 122 | public string RenderedDescription { get; set; } 123 | 124 | [JsonProperty("follower_count")] 125 | public int FollowerCount { get; set; } 126 | 127 | public bool Live { get; set; } 128 | 129 | [JsonProperty("live_since")] 130 | public DateTime? LiveSince { get; set; } 131 | 132 | [JsonProperty("isPrivate?")] 133 | public bool IsPrivate { get; set; } 134 | 135 | public string Slug { get; set; } 136 | 137 | [JsonProperty("offline_image")] 138 | public OfflineImage OfflineImage { get; set; } 139 | 140 | public Banner Banner { get; set; } 141 | 142 | [JsonProperty("banner_link")] 143 | public object BannerLink { get; set; } 144 | 145 | public Preview Preview { get; set; } 146 | 147 | public bool Adult { get; set; } 148 | 149 | [JsonProperty("in_multi")] 150 | public bool InMulti { get; set; } 151 | 152 | [JsonProperty("parent_streamer")] 153 | public object ParentStreamer { get; set; } 154 | 155 | public Settings Settings { get; set; } 156 | 157 | public string Viewers { get; set; } 158 | 159 | public string Username { get; set; } 160 | 161 | public List Tags { get; set; } 162 | 163 | public User User { get; set; } 164 | 165 | public List Recordings { get; set; } 166 | } 167 | 168 | public class Meta 169 | { 170 | [JsonProperty("limit_reached")] 171 | public bool LimitReached { get; set; } 172 | } 173 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Trovo/TrovoChannel.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.Trovo; 2 | 3 | public class TrovoChannel 4 | { 5 | public bool is_live { get; set; } 6 | public string category_id { get; set; } 7 | public string category_name { get; set; } 8 | public string live_title { get; set; } 9 | public string audi_type { get; set; } 10 | public string language_code { get; set; } 11 | public string thumbnail { get; set; } 12 | public int current_viewers { get; set; } 13 | public int followers { get; set; } 14 | public string streamer_info { get; set; } 15 | public string profile_pic { get; set; } 16 | public string channel_url { get; set; } 17 | public string created_at { get; set; } 18 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Trovo/TrovoUser.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Trovo; 4 | 5 | public class TrovoUser 6 | { 7 | public int Total { get; set; } 8 | public List Users { get; set; } 9 | 10 | public class User 11 | { 12 | [JsonProperty("user_id")] 13 | public string UserId { get; set; } 14 | public string Username { get; set; } 15 | public string Nickname { get; set; } 16 | [JsonProperty("channel_id")] 17 | public string ChannelId { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Twitch/TwitchClientCredentials.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Twitch; 4 | 5 | public class TwitchClientCredentials 6 | { 7 | [JsonProperty("access_token")] 8 | public string AccessToken { get; set; } 9 | 10 | [JsonProperty("expires_in")] 11 | public int ExpiresIn { get; set; } 12 | 13 | [JsonProperty("token_type")] 14 | public string TokenType { get; set; } 15 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Twitch/TwitchClipsResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Twitch; 4 | 5 | public class TwitchClipsResponse 6 | { 7 | [JsonProperty("data")] 8 | public List Clips { get; set; } 9 | 10 | public class Clip 11 | { 12 | public string Id { get; set; } 13 | 14 | public string Url { get; set; } 15 | 16 | [JsonProperty("embed_url")] 17 | public string EmbedUrl { get; set; } 18 | 19 | [JsonProperty("broadcaster_id")] 20 | public string BroadcasterId { get; set; } 21 | 22 | [JsonProperty("broadcaster_name")] 23 | public string BroadcasterName { get; set; } 24 | 25 | [JsonProperty("creator_id")] 26 | public string CreatorId { get; set; } 27 | 28 | [JsonProperty("creator_name")] 29 | public string CreatorName { get; set; } 30 | 31 | [JsonProperty("video_id")] 32 | public string VideoId { get; set; } 33 | 34 | [JsonProperty("game_id")] 35 | public string GameId { get; set; } 36 | 37 | public string Language { get; set; } 38 | public string Title { get; set; } 39 | 40 | [JsonProperty("view_count")] 41 | public int ViewCount { get; set; } 42 | 43 | [JsonProperty("created_at")] 44 | public DateTime CreatedAt { get; set; } 45 | 46 | [JsonProperty("thumbnail_url")] 47 | public string ThumbnailUrl { get; set; } 48 | 49 | public double Duration { get; set; } 50 | } 51 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Twitch/TwitchGameChannel.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.Twitch; 2 | 3 | public class TwitchGameChannel 4 | { 5 | public string GameId { get; set; } 6 | public string GameName { get; set; } 7 | public string ChannelId { get; set; } 8 | public string GuildId { get; set; } 9 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Twitch/TwitchGameSearchResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Twitch; 4 | 5 | public class TwitchGameSearchResponse 6 | { 7 | public List Data { get; set; } 8 | 9 | public class Datum 10 | { 11 | [JsonProperty("box_art_url")] 12 | public string BoxArtUrl { get; set; } 13 | 14 | public string Id { get; set; } 15 | 16 | public string Name { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Twitch/TwitchStreamResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Twitch; 4 | 5 | public class TwitchStreamResponse 6 | { 7 | public List Data { get; set; } 8 | 9 | public class Datum 10 | { 11 | public string Id { get; set; } 12 | 13 | [JsonProperty("user_id")] 14 | public string UserId { get; set; } 15 | 16 | [JsonProperty("user_login")] 17 | public string UserLogin { get; set; } 18 | 19 | [JsonProperty("user_name")] 20 | public string UserName { get; set; } 21 | 22 | [JsonProperty("game_id")] 23 | public string GameId { get; set; } 24 | 25 | [JsonProperty("game_name")] 26 | public string GameName { get; set; } 27 | 28 | public string Type { get; set; } 29 | 30 | public string Title { get; set; } 31 | 32 | [JsonProperty("viewer_count")] 33 | public int ViewerCount { get; set; } 34 | 35 | [JsonProperty("started_at")] 36 | public DateTime StartedAt { get; set; } 37 | 38 | public string Language { get; set; } 39 | 40 | [JsonProperty("thumbnail_url")] 41 | public string ThumbnailUrl { get; set; } 42 | 43 | [JsonProperty("tag_ids")] 44 | public List TagIds { get; set; } 45 | } 46 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Twitch/TwitchTeam.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.Twitch; 4 | 5 | public class TwitchTeam 6 | { 7 | public List Data { get; set; } 8 | 9 | public class User 10 | { 11 | [JsonProperty("user_id")] public string UserId { get; set; } 12 | 13 | [JsonProperty("user_name")] public string UserName { get; set; } 14 | 15 | [JsonProperty("user_login")] public string UserLogin { get; set; } 16 | } 17 | 18 | public class Datum 19 | { 20 | public List Users { get; set; } 21 | 22 | [JsonProperty("background_image_url")] public string BackgroundImageUrl { get; set; } 23 | 24 | public object Banner { get; set; } 25 | 26 | [JsonProperty("created_at")] public string CreatedAt { get; set; } 27 | 28 | [JsonProperty("updated_at")] public string UpdatedAt { get; set; } 29 | 30 | public string Info { get; set; } 31 | 32 | [JsonProperty("thumbnail_url")] public string ThumbnailUrl { get; set; } 33 | 34 | [JsonProperty("team_name")] public string TeamName { get; set; } 35 | 36 | [JsonProperty("team_display_name")] public string TeamDisplayName { get; set; } 37 | 38 | public string Id { get; set; } 39 | } 40 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/Twitch/TwitchUserResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CouchBot.Domain.Models.Twitch; 4 | 5 | public class TwitchUserResponse 6 | { 7 | public List Data { get; set; } 8 | 9 | public class Datum 10 | { 11 | public string Id { get; set; } 12 | 13 | public string Login { get; set; } 14 | 15 | [JsonProperty("display_name")] 16 | public string DisplayName { get; set; } 17 | 18 | public string Type { get; set; } 19 | 20 | [JsonProperty("broadcaster_type")] 21 | public string BroadcasterType { get; set; } 22 | 23 | public string Description { get; set; } 24 | 25 | [JsonProperty("profile_image_url")] 26 | public string ProfileImageUrl { get; set; } 27 | 28 | [JsonProperty("offline_image_url")] 29 | public string OfflineImageUrl { get; set; } 30 | 31 | [JsonProperty("view_count")] 32 | public int ViewCount { get; set; } 33 | 34 | public string Email { get; set; } 35 | 36 | [JsonProperty("created_at")] 37 | public DateTime CreatedAt { get; set; } 38 | } 39 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/YouTube/LiveChatStatusResponse.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.YouTube; 2 | 3 | public class LiveChatStatusResponse 4 | { 5 | public List Items { get; set; } 6 | 7 | public class Snippet 8 | { 9 | public string ChannelId { get; set; } 10 | 11 | public string CurrentVideoId { get; set; } 12 | } 13 | 14 | public class Item 15 | { 16 | public Snippet Snippet { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/YouTube/PageInfo.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.YouTube; 2 | 3 | public class PageInfo 4 | { 5 | public int TotalResults { get; set; } 6 | 7 | public int ResultsPerPage { get; set; } 8 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/YouTube/YouTubeChannelByIdResponse.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.YouTube; 2 | 3 | public class YouTubeChannelByIdResponse 4 | { 5 | public class Default 6 | { 7 | public string Url { get; set; } 8 | } 9 | 10 | public class Medium 11 | { 12 | public string Url { get; set; } 13 | } 14 | 15 | public class High 16 | { 17 | public string Url { get; set; } 18 | } 19 | 20 | public class Thumbnails 21 | { 22 | public Default Default { get; set; } 23 | public Medium Medium { get; set; } 24 | public High High { get; set; } 25 | } 26 | 27 | public class Localized 28 | { 29 | public string Title { get; set; } 30 | public string Description { get; set; } 31 | } 32 | 33 | public class Snippet 34 | { 35 | public string Title { get; set; } 36 | public string Description { get; set; } 37 | public string PublishedAt { get; set; } 38 | public Thumbnails Thumbnails { get; set; } 39 | public Localized Localized { get; set; } 40 | public string Country { get; set; } 41 | } 42 | 43 | public class Item 44 | { 45 | public string Kind { get; set; } 46 | public string Etag { get; set; } 47 | public string Id { get; set; } 48 | public Snippet Snippet { get; set; } 49 | public ContentDetails ContentDetails { get; set; } 50 | } 51 | 52 | public class ContentDetails 53 | { 54 | public RelatedPlaylists RelatedPlaylists { get; set; } 55 | } 56 | 57 | public class RelatedPlaylists 58 | { 59 | public string Likes { get; set; } 60 | public string Uploads { get; set; } 61 | public string WatchHistory { get; set; } 62 | public string WatchLater { get; set; } 63 | } 64 | 65 | public string Kind { get; set; } 66 | public string Etag { get; set; } 67 | public PageInfo PageInfo { get; set; } 68 | public List Items { get; set; } 69 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/YouTube/YouTubeChannelSearchList.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.YouTube; 2 | 3 | public class YouTubeChannelSearchList 4 | { 5 | public class Id 6 | { 7 | public string Kind { get; set; } 8 | public string ChannelId { get; set; } 9 | } 10 | 11 | public class Default 12 | { 13 | public string Url { get; set; } 14 | } 15 | 16 | public class Medium 17 | { 18 | public string Url { get; set; } 19 | } 20 | 21 | public class High 22 | { 23 | public string Url { get; set; } 24 | } 25 | 26 | public class Thumbnails 27 | { 28 | public Default Default { get; set; } 29 | public Medium Medium { get; set; } 30 | public High High { get; set; } 31 | } 32 | 33 | public class Snippet 34 | { 35 | public string PublishedAt { get; set; } 36 | public string ChannelId { get; set; } 37 | public string Title { get; set; } 38 | public string Description { get; set; } 39 | public Thumbnails Thumbnails { get; set; } 40 | public string ChannelTitle { get; set; } 41 | public string LiveBroadcastContent { get; set; } 42 | } 43 | 44 | public class Item 45 | { 46 | public string Kind { get; set; } 47 | public string Etag { get; set; } 48 | public Id Id { get; set; } 49 | public Snippet Snippet { get; set; } 50 | } 51 | 52 | public string Kind { get; set; } 53 | public string Etag { get; set; } 54 | public string NextPageToken { get; set; } 55 | public string RegionCode { get; set; } 56 | public PageInfo PageInfo { get; set; } 57 | public List Items { get; set; } 58 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/YouTube/YouTubeChannelStatistics.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.YouTube; 2 | 3 | public class YouTubeChannelStatistics 4 | { 5 | public class Statistics 6 | { 7 | public string ViewCount { get; set; } 8 | public string CommentCount { get; set; } 9 | public string SubscriberCount { get; set; } 10 | public bool HiddenSubscriberCount { get; set; } 11 | public string VideoCount { get; set; } 12 | } 13 | 14 | public class Item 15 | { 16 | public string Kind { get; set; } 17 | public string Etag { get; set; } 18 | public string Id { get; set; } 19 | public Statistics Statistics { get; set; } 20 | } 21 | 22 | public string Kind { get; set; } 23 | public string Etag { get; set; } 24 | public PageInfo PageInfo { get; set; } 25 | public List Items { get; set; } 26 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/YouTube/YouTubePlaylist.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace CB.Shared.Models.YouTube; 4 | 5 | public class YouTubePlaylist 6 | { 7 | public string Kind { get; set; } 8 | 9 | public string Etag { get; set; } 10 | 11 | public string NextPageToken { get; set; } 12 | 13 | public List Items { get; set; } 14 | 15 | [JsonProperty("pageInfo")] 16 | public PageInfo NextPageInfo { get; set; } 17 | 18 | public class Default 19 | { 20 | public string Url { get; set; } 21 | 22 | public int Width { get; set; } 23 | 24 | public int Height { get; set; } 25 | } 26 | 27 | public class Medium 28 | { 29 | public string Url { get; set; } 30 | 31 | public int Width { get; set; } 32 | 33 | public int Height { get; set; } 34 | } 35 | 36 | public class High 37 | { 38 | public string Url { get; set; } 39 | 40 | public int Width { get; set; } 41 | 42 | public int Height { get; set; } 43 | } 44 | 45 | public class Standard 46 | { 47 | public string Url { get; set; } 48 | 49 | public int Width { get; set; } 50 | 51 | public int Height { get; set; } 52 | } 53 | 54 | public class Maxres 55 | { 56 | public string Url { get; set; } 57 | 58 | public int Width { get; set; } 59 | 60 | public int Height { get; set; } 61 | } 62 | 63 | public class Thumbnails 64 | { 65 | public Default Default { get; set; } 66 | 67 | public Medium Medium { get; set; } 68 | 69 | public High High { get; set; } 70 | 71 | public Standard Standard { get; set; } 72 | 73 | public Maxres Maxres { get; set; } 74 | } 75 | 76 | public class ResourceId 77 | { 78 | public string Kind { get; set; } 79 | 80 | public string VideoId { get; set; } 81 | } 82 | 83 | public class Snippet 84 | { 85 | public DateTime PublishedAt { get; set; } 86 | 87 | public string ChannelId { get; set; } 88 | 89 | public string Title { get; set; } 90 | 91 | public string Description { get; set; } 92 | 93 | public Thumbnails Thumbnails { get; set; } 94 | 95 | public string ChannelTitle { get; set; } 96 | 97 | public string PlaylistId { get; set; } 98 | 99 | public int Position { get; set; } 100 | 101 | public ResourceId ResourceId { get; set; } 102 | 103 | public string VideoOwnerChannelTitle { get; set; } 104 | 105 | public string VideoOwnerChannelId { get; set; } 106 | } 107 | 108 | public class ContentDetails 109 | { 110 | public string VideoId { get; set; } 111 | 112 | public DateTime VideoPublishedAt { get; set; } 113 | } 114 | 115 | public class Status 116 | { 117 | public string PrivacyStatus { get; set; } 118 | } 119 | 120 | public class Item 121 | { 122 | public string Kind { get; set; } 123 | 124 | public string Etag { get; set; } 125 | 126 | public string Id { get; set; } 127 | 128 | public Snippet Snippet { get; set; } 129 | 130 | public ContentDetails ContentDetails { get; set; } 131 | 132 | public Status Status { get; set; } 133 | } 134 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/YouTube/YouTubeSearchListChannel.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.YouTube; 2 | 3 | public class YouTubeSearchListChannel 4 | { 5 | public List Items { get; set; } 6 | 7 | public class High 8 | { 9 | public string Url { get; set; } 10 | } 11 | 12 | public class Thumbnails 13 | { 14 | public High High { get; set; } 15 | } 16 | 17 | public class Snippet 18 | { 19 | public string Title { get; set; } 20 | public Thumbnails Thumbnails { get; set; } 21 | } 22 | 23 | public class Item 24 | { 25 | public string Id { get; set; } 26 | public Snippet Snippet { get; set; } 27 | public LiveStreamingDetails LiveStreamingDetails { get; set; } 28 | } 29 | 30 | public class LiveStreamingDetails 31 | { 32 | public DateTime? ActualStartTime { get; set; } 33 | public DateTime ScheduledStartTime { get; set; } 34 | public DateTime? ActualEndTime { get; set; } 35 | public string ConcurrentViewers { get; set; } 36 | public string ActiveLiveChatId { get; set; } 37 | } 38 | } -------------------------------------------------------------------------------- /src/CB.Shared/Models/YouTube/YouTubeVideoListResponse.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Models.YouTube; 2 | 3 | public class YouTubeVideoListResponse 4 | { 5 | public List Items { get; set; } 6 | 7 | public class Snippet 8 | { 9 | public string LiveBroadcastContent { get; set; } 10 | } 11 | 12 | public class Item 13 | { 14 | public Snippet Snippet { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/CB.Shared/Responses/ChannelValidityResponse.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Responses; 2 | 3 | public class ChannelValidityResponse : ValidityResponse 4 | { 5 | public string ChannelId { get; set; } 6 | } -------------------------------------------------------------------------------- /src/CB.Shared/Responses/GameValidityResponse.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Responses; 2 | 3 | public class GameValidityResponse : ValidityResponse 4 | { 5 | public string GameId { get; set; } 6 | } -------------------------------------------------------------------------------- /src/CB.Shared/Responses/TeamValidityResponse.cs: -------------------------------------------------------------------------------- 1 | using CB.Shared.Models.Twitch; 2 | 3 | namespace CB.Shared.Responses; 4 | 5 | public class TeamValidityResponse : ValidityResponse 6 | { 7 | public TwitchTeam.Datum TwitchTeam { get; set; } 8 | } -------------------------------------------------------------------------------- /src/CB.Shared/Responses/ValidityResponse.cs: -------------------------------------------------------------------------------- 1 | namespace CB.Shared.Responses; 2 | 3 | public class ValidityResponse 4 | { 5 | public string DisplayName { get; set; } 6 | public bool Valid { get; set; } 7 | } -------------------------------------------------------------------------------- /src/CB.Shared/Utilities/StringUtilities.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace CB.Shared.Utilities; 4 | 5 | public static class StringUtilities 6 | { 7 | public static string FirstLetterToUpper(this string str) 8 | { 9 | if (str == null) 10 | { 11 | return null; 12 | } 13 | 14 | if (str.Length > 1) 15 | { 16 | return char.ToUpper(str[0], CultureInfo.InvariantCulture) + str[1..]; 17 | } 18 | 19 | return str.ToUpper(CultureInfo.InvariantCulture); 20 | } 21 | } -------------------------------------------------------------------------------- /src/tests/CB.Tests.Accessors/CB.Tests.Accessors.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | 7 | false 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/tests/CB.Tests.Accessors/GuildAccessorTests.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using CB.Accessors.Implementations; 3 | using CB.Data; 4 | using CB.Data.Entities; 5 | using CB.Shared.Dtos; 6 | using Microsoft.EntityFrameworkCore; 7 | using Microsoft.Extensions.Logging.Abstractions; 8 | 9 | namespace CB.Tests.Accessors; 10 | 11 | public class GuildAccessorTests 12 | { 13 | private readonly IMapper _mapper; 14 | private readonly DbContextOptions _dbOptions; 15 | 16 | public GuildAccessorTests() 17 | { 18 | var loggerFactory = NullLoggerFactory.Instance; 19 | var config = new MapperConfiguration(cfg => { 20 | cfg.AddProfile(); 21 | }, loggerFactory); 22 | _mapper = config.CreateMapper(); 23 | 24 | // Setup InMemory DbContext options 25 | _dbOptions = new DbContextOptionsBuilder() 26 | .UseInMemoryDatabase(databaseName: "TestDb") 27 | .Options; 28 | } 29 | 30 | [Fact] 31 | public async Task CreateAsync_ShouldAddGuild() 32 | { 33 | await using var context = new CbContext(_dbOptions); 34 | 35 | var accessor = new GuildAccessor(context, _mapper); 36 | var guild = new Guild { Id = "guild1", DisplayName = "Test Guild" }; 37 | 38 | var result = await accessor.CreateAsync(guild); 39 | 40 | Assert.NotNull(result); 41 | Assert.Equal("Test Guild", result.DisplayName); 42 | Assert.NotEqual(default, guild.CreatedDate); 43 | Assert.NotEqual(default, guild.ModifiedDate); 44 | 45 | var dbGuild = await context.Guilds.FindAsync("guild1"); 46 | Assert.NotNull(dbGuild); 47 | } 48 | 49 | [Fact] 50 | public async Task GetByIdAsync_ReturnsGuild_WhenExists() 51 | { 52 | await using var context = new CbContext(_dbOptions); 53 | context.Guilds.Add(new Guild { Id = "guild2", DisplayName = "Guild 2" }); 54 | await context.SaveChangesAsync(); 55 | 56 | var accessor = new GuildAccessor(context, _mapper); 57 | 58 | var result = await accessor.GetByIdAsync("guild2"); 59 | 60 | Assert.NotNull(result); 61 | Assert.Equal("Guild 2", result.DisplayName); 62 | } 63 | } -------------------------------------------------------------------------------- /src/tests/CB.Tests.Api/CB.Tests.Api.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | 7 | false 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | --------------------------------------------------------------------------------