init commit
This commit is contained in:
2
.env.example
Normal file
2
.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
# Copy this file to .env and set your real values.
|
||||
DISCORD_BOT_TOKEN=YOUR_DISCORD_BOT_TOKEN_HERE
|
||||
45
.github/copilot-instructions.md
vendored
Normal file
45
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
# TentacleBot - Discord .NET Bot
|
||||
|
||||
A Discord bot project built with Discord.Net and .NET 8+, featuring dependency injection and slash commands.
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
1. Verify .NET SDK is installed (version 8.0 or higher)
|
||||
2. Install project dependencies: `dotnet restore`
|
||||
3. Configure bot token in `appsettings.json`
|
||||
4. Build the project: `dotnet build`
|
||||
5. Run the bot: `dotnet run`
|
||||
|
||||
## Project Structure
|
||||
|
||||
- **Program.cs**: Bot initialization and dependency injection setup
|
||||
- **Services/BotService.cs**: Core bot service managing connection and event handlers
|
||||
- **Commands/GeneralCommands.cs**: Example slash command module
|
||||
- **appsettings.json**: Configuration file for bot token and prefix
|
||||
|
||||
## Key Features
|
||||
|
||||
- Dependency injection for services
|
||||
- Slash command support
|
||||
- Event handling for bot lifecycle
|
||||
- Discord.Net integration
|
||||
|
||||
## Configuration
|
||||
|
||||
Before running, update `appsettings.json` with your Discord bot token:
|
||||
|
||||
```json
|
||||
{
|
||||
"Discord": {
|
||||
"BotToken": "YOUR_BOT_TOKEN_HERE"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Running the Bot
|
||||
|
||||
```bash
|
||||
dotnet run
|
||||
```
|
||||
|
||||
The bot will connect to Discord and respond to slash commands.
|
||||
50
.gitignore
vendored
Normal file
50
.gitignore
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio cache/options
|
||||
.vs/
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/settings.json
|
||||
.vscode/launch.json
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Configuration files with sensitive data
|
||||
appsettings.json
|
||||
!appsettings.*.json
|
||||
|
||||
# NuGet
|
||||
.nuget/
|
||||
*.nupkg
|
||||
*.snupkg
|
||||
|
||||
# dotnet
|
||||
project.assets.json
|
||||
project.lock.json
|
||||
|
||||
# secrets
|
||||
.env
|
||||
|
||||
# OS generated files
|
||||
*.swp
|
||||
*.swo
|
||||
*.DS_Store
|
||||
44
.vscode/tasks.json
vendored
Normal file
44
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"build",
|
||||
"--configuration",
|
||||
"Debug"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "run",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"run",
|
||||
"--no-build"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"isBackground": false
|
||||
},
|
||||
{
|
||||
"label": "clean",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"clean"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
32
AGENTS.md
Normal file
32
AGENTS.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# TentacleBot - Agent Instructions
|
||||
|
||||
## Quick Commands
|
||||
|
||||
```bash
|
||||
dotnet restore && dotnet run # Run the bot locally
|
||||
docker compose up --build -d # Run with Docker
|
||||
docker compose logs -f # View Docker logs
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
1. Set `DISCORD_BOT_TOKEN` env var (preferred) or edit `appsettings.json`
|
||||
2. Copy `.env.example` to `.env` for Docker: `cp .env.example .env`
|
||||
3. `appsettings.json` is gitignored — never commit it
|
||||
|
||||
## Architecture
|
||||
|
||||
- **`Program.cs`** — Entry point, DI setup, registers command modules from the assembly
|
||||
- **`Services/BotService.cs`** — Core bot lifecycle (login, ready handler, interaction routing)
|
||||
- **`Commands/GeneralCommands.cs`** — Slash commands (`/general ping`, `/general hello`, `/botinfo`)
|
||||
|
||||
Add new commands by creating a class in `Commands/` that extends `InteractionModuleBase<SocketInteractionContext>`. Commands are auto-discovered via `AddModulesAsync(typeof(Program).Assembly)`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Two `DiscordSocketClient` instances** are created in `Program.cs` — one for the bot client and one passed into `InteractionService`. They are separate instances sharing the same config.
|
||||
- **Token priority**: `DISCORD_BOT_TOKEN` env var is checked first, then `appsettings.json` → `Discord:BotToken`.
|
||||
|
||||
## No tests, no lint config
|
||||
|
||||
This project has no test framework, no linting, and no CI. `dotnet build` is the only verification step.
|
||||
71
Commands/GeneralCommands.cs
Normal file
71
Commands/GeneralCommands.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
|
||||
namespace TentacleBot.Commands;
|
||||
|
||||
[Group("general", "General commands")]
|
||||
public class GeneralCommands : InteractionModuleBase<SocketInteractionContext>
|
||||
{
|
||||
/// <summary>
|
||||
/// Example ping command that responds with pong
|
||||
/// </summary>
|
||||
[SlashCommand("ping", "Responds with pong and latency")]
|
||||
public async Task HandlePingAsync()
|
||||
{
|
||||
await DeferAsync();
|
||||
|
||||
var latency = Context.Client.Latency;
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle("Pong!")
|
||||
.WithDescription($"Latency: {latency}ms")
|
||||
.WithColor(Color.Green)
|
||||
.WithTimestamp(DateTimeOffset.UtcNow)
|
||||
.Build();
|
||||
|
||||
await FollowupAsync(embed: embed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example hello command with a user parameter
|
||||
/// </summary>
|
||||
[SlashCommand("hello", "Greet a user")]
|
||||
public async Task HandleHelloAsync(
|
||||
[Summary("user", "The user to greet")] IUser? user = null)
|
||||
{
|
||||
await DeferAsync();
|
||||
|
||||
var targetUser = user ?? Context.User;
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle($"Hello, {targetUser.Username}!")
|
||||
.WithDescription($"Nice to meet you! ?")
|
||||
.WithThumbnailUrl(targetUser.GetAvatarUrl() ?? targetUser.GetDefaultAvatarUrl())
|
||||
.WithColor(Color.Blue)
|
||||
.WithTimestamp(DateTimeOffset.UtcNow)
|
||||
.Build();
|
||||
|
||||
await FollowupAsync(embed: embed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example command that shows bot information
|
||||
/// </summary>
|
||||
[SlashCommand("botinfo", "Display bot information")]
|
||||
public async Task HandleBotInfoAsync()
|
||||
{
|
||||
await DeferAsync();
|
||||
|
||||
var bot = Context.Client.CurrentUser;
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle("Bot Information")
|
||||
.AddField("Name", bot?.Username, true)
|
||||
.AddField("ID", bot?.Id, true)
|
||||
.AddField("Created", bot?.CreatedAt.ToString("g"), true)
|
||||
.AddField("Guilds", Context.Client.Guilds.Count, true)
|
||||
.WithColor(Color.Purple)
|
||||
.WithThumbnailUrl(bot?.GetAvatarUrl())
|
||||
.WithTimestamp(DateTimeOffset.UtcNow)
|
||||
.Build();
|
||||
|
||||
await FollowupAsync(embed: embed);
|
||||
}
|
||||
}
|
||||
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||
WORKDIR /src
|
||||
|
||||
COPY TentacleBot.csproj ./
|
||||
RUN dotnet restore
|
||||
|
||||
COPY . ./
|
||||
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS final
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=build /app/publish ./
|
||||
|
||||
ENV DOTNET_RUNNING_IN_CONTAINER=true
|
||||
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
|
||||
|
||||
ENTRYPOINT ["dotnet", "TentacleBot.dll"]
|
||||
50
Program.cs
Normal file
50
Program.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Discord.Interactions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TentacleBot.Services;
|
||||
using TentacleBot.Commands;
|
||||
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddJsonFile("appsettings.json")
|
||||
.Build();
|
||||
|
||||
var discordConfig = new DiscordSocketConfig
|
||||
{
|
||||
GatewayIntents = GatewayIntents.All,
|
||||
LogLevel = LogSeverity.Info,
|
||||
UseInteractionSnowflakeDate = false,
|
||||
};
|
||||
|
||||
var client = new DiscordSocketClient(discordConfig);
|
||||
|
||||
var services = new ServiceCollection()
|
||||
.AddLogging(builder => builder.AddConsole())
|
||||
.AddSingleton<IConfiguration>(configuration)
|
||||
.AddSingleton(client)
|
||||
.AddSingleton(new InteractionService(client, new InteractionServiceConfig
|
||||
{
|
||||
LogLevel = LogSeverity.Info,
|
||||
UseCompiledLambda = true,
|
||||
}))
|
||||
.AddSingleton<BotService>();
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var botService = serviceProvider.GetRequiredService<BotService>();
|
||||
var interactionService = serviceProvider.GetRequiredService<InteractionService>();
|
||||
|
||||
// Register command modules
|
||||
await interactionService.AddModulesAsync(
|
||||
typeof(Program).Assembly,
|
||||
serviceProvider);
|
||||
|
||||
// Initialize the bot
|
||||
await botService.InitializeAsync();
|
||||
|
||||
// Keep the bot running
|
||||
await Task.Delay(Timeout.Infinite);
|
||||
157
README.md
Normal file
157
README.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# TentacleBot - Discord .NET Bot
|
||||
|
||||
A Discord bot project built with Discord.Net and .NET 8+, featuring dependency injection and slash commands.
|
||||
|
||||
## Features
|
||||
|
||||
- ? Built with Discord.Net 3.14+
|
||||
- ? Dependency Injection for services
|
||||
- ? Slash commands support
|
||||
- ? Rich embed messages
|
||||
- ? Example commands included
|
||||
- ? .NET 8 or higher
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 8.0 or higher ([download here](https://dotnet.microsoft.com/download))
|
||||
- A Discord Bot Token (create one at [Discord Developer Portal](https://discord.com/developers/applications))
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Clone and Setup
|
||||
|
||||
```bash
|
||||
dotnet restore
|
||||
```
|
||||
|
||||
### 2. Configure Your Bot Token
|
||||
|
||||
Edit `appsettings.json` and replace `YOUR_BOT_TOKEN_HERE` with your actual Discord bot token:
|
||||
|
||||
```json
|
||||
{
|
||||
"Discord": {
|
||||
"BotToken": "YOUR_ACTUAL_TOKEN_HERE"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Run the Bot
|
||||
|
||||
```bash
|
||||
dotnet run
|
||||
```
|
||||
|
||||
The bot will connect to Discord and register its slash commands globally.
|
||||
|
||||
## Run With Docker Compose
|
||||
|
||||
1. Copy the example env file:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
2. Edit `.env` and set your Discord token:
|
||||
|
||||
```dotenv
|
||||
DISCORD_BOT_TOKEN=YOUR_ACTUAL_TOKEN_HERE
|
||||
```
|
||||
|
||||
3. Build and run with Docker Compose:
|
||||
|
||||
```bash
|
||||
docker compose up --build -d
|
||||
```
|
||||
|
||||
4. View logs:
|
||||
|
||||
```bash
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
5. Stop the bot:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
TentacleBot/
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Program.cs # Entry point and DI setup
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Services/
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BotService.cs # Core bot service
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Commands/
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GeneralCommands.cs # Example slash commands
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> appsettings.json # Configuration
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Dockerfile # Container image definition
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> docker-compose.yml # Local compose setup
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> .env.example # Environment variable template
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> TentacleBot.csproj # Project file
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> README.md # This file
|
||||
```
|
||||
|
||||
## Example Commands
|
||||
|
||||
The bot includes example slash commands:
|
||||
|
||||
- `/general ping` - Shows bot latency
|
||||
- `/general hello [user]` - Greet a user
|
||||
- `/general botinfo` - Display bot information
|
||||
|
||||
## Adding New Commands
|
||||
|
||||
Create a new class in the `Commands` folder that inherits from `InteractionModuleBase<SocketInteractionContext>`:
|
||||
|
||||
```csharp
|
||||
using Discord.Interactions;
|
||||
|
||||
namespace TentacleBot.Commands;
|
||||
|
||||
public class MyCommands : InteractionModuleBase<SocketInteractionContext>
|
||||
{
|
||||
[SlashCommand("mycommand", "My custom command")]
|
||||
public async Task HandleMyCommandAsync()
|
||||
{
|
||||
await RespondAsync("Hello from my command!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Commands are automatically discovered and registered when the bot starts.
|
||||
|
||||
## Configuration
|
||||
|
||||
### appsettings.json
|
||||
|
||||
```json
|
||||
{
|
||||
"Discord": {
|
||||
"BotToken": "YOUR_BOT_TOKEN_HERE"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **"Bot token not found"**: Set `DISCORD_BOT_TOKEN` in `.env` (Docker) or in your shell. The app falls back to `appsettings.json` if the env var is not set
|
||||
- **"Insufficient permissions"**: Ensure your bot has the necessary permissions in Discord Developer Portal
|
||||
- **Commands not appearing**: The bot needs to connect first. Wait a few seconds after starting, then try `/` in Discord
|
||||
|
||||
## Resources
|
||||
|
||||
- [Discord.Net Documentation](https://discordnet.dev/)
|
||||
- [Discord Developer Portal](https://discord.com/developers/applications)
|
||||
- [.NET Documentation](https://docs.microsoft.com/dotnet)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
102
Services/BotService.cs
Normal file
102
Services/BotService.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Discord.Interactions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace TentacleBot.Services;
|
||||
|
||||
public class BotService
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly InteractionService _interactionService;
|
||||
private readonly ILogger<BotService> _logger;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public BotService(
|
||||
DiscordSocketClient client,
|
||||
InteractionService interactionService,
|
||||
ILogger<BotService> logger,
|
||||
IConfiguration configuration,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
_client = client;
|
||||
_interactionService = interactionService;
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
_client.Log += LogAsync;
|
||||
_interactionService.Log += LogAsync;
|
||||
|
||||
_client.Ready += ClientReadyAsync;
|
||||
_client.InteractionCreated += InteractionCreatedAsync;
|
||||
|
||||
var token = Environment.GetEnvironmentVariable("DISCORD_BOT_TOKEN");
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
token = _configuration["Discord:BotToken"];
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(token))
|
||||
{
|
||||
throw new InvalidOperationException("Discord bot token not found. Set DISCORD_BOT_TOKEN or Discord:BotToken in appsettings.json");
|
||||
}
|
||||
|
||||
await _client.LoginAsync(TokenType.Bot, token);
|
||||
await _client.StartAsync();
|
||||
|
||||
_logger.LogInformation("Bot service initialized");
|
||||
}
|
||||
|
||||
private async Task ClientReadyAsync()
|
||||
{
|
||||
_logger.LogInformation("Bot connected as {BotName}#{Discriminator}", _client.CurrentUser?.Username, _client.CurrentUser?.Discriminator);
|
||||
|
||||
// Register slash commands
|
||||
await _interactionService.RegisterCommandsGloballyAsync();
|
||||
|
||||
_logger.LogInformation("Slash commands registered");
|
||||
}
|
||||
|
||||
private async Task InteractionCreatedAsync(SocketInteraction interaction)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ctx = new SocketInteractionContext(_client, interaction);
|
||||
await _interactionService.ExecuteCommandAsync(ctx, _serviceProvider);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error handling interaction");
|
||||
|
||||
if (interaction.Type == InteractionType.ApplicationCommand)
|
||||
{
|
||||
await interaction.GetOriginalResponseAsync().ContinueWith(async msg =>
|
||||
{
|
||||
if (msg.IsCompletedSuccessfully)
|
||||
{
|
||||
await interaction.FollowupAsync("An error occurred while executing the command.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Task LogAsync(LogMessage message)
|
||||
{
|
||||
Console.WriteLine($"[{message.Severity}] {message.Source}: {message.Message}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
await _client.StopAsync();
|
||||
_client.Dispose();
|
||||
_logger.LogInformation("Bot service stopped");
|
||||
}
|
||||
}
|
||||
27
TentacleBot.csproj
Normal file
27
TentacleBot.csproj
Normal file
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>TentacleBot</RootNamespace>
|
||||
<AssemblyName>TentacleBot</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Discord.Net" Version="3.14.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
9
docker-compose.yml
Normal file
9
docker-compose.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
services:
|
||||
tentaclebot:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: tentaclebot
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
Reference in New Issue
Block a user