Skip to content

A multi-platform user support system with a single core engine (currently integrated with Telegram).

License

Notifications You must be signed in to change notification settings

Lar000ki/support-bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

12 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Support Platform

🌐 README Π½Π° русском

A multi-platform user support system with a single core engine (currently integrated with Telegram).

The project is built according to Hexagonal / Clean Architecture principles:

  • all business logic is in the core
  • platforms (Telegram, Discord, etc.) are connected via adapters
  • UI and configuration are separate

Content


Features

  • admin commands (/help to display all)
  • support tickets (one open ticket per user)
  • message rate limit
  • ban users
  • welcome message upon first contact
  • the ability to add a header and footer to support responses
  • attachments support
  • operator responses -> to user
  • web interface for editing config application.yml
  • architecture ready to connect new platforms

Requirements

  • Java 21
  • PostgreSQL or MySQL
  • Maven (for dev)

How to use

Download .jar + .yml from releases and put them in one directory

java -jar target/support-platform-<current version>.jar

Dev running

Running

mvn spring-boot:run

Building and running the jar (jar requires .yml in its directory)

mvn clean package
java -jar target/support-platform-<current version>.jar

Architecture

command tree -I 'target|.git|.idea|*.class|test' --dirsfirst
β”œβ”€β”€ src
β”‚Β Β  └── main
β”‚Β Β      β”œβ”€β”€ java
β”‚Β Β      β”‚Β Β  └── com
β”‚Β Β      β”‚Β Β      └── bob
β”‚Β Β      β”‚Β Β          └── support_platform
β”‚Β Β      β”‚Β Β              β”œβ”€β”€ config
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ SupportConfig.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  └── SupportProperties.java
β”‚Β Β      β”‚Β Β              β”œβ”€β”€ core
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ dto
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ AdminReplyContext.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  └── CoreCommand.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ interfaces
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ CoreResponse.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  └── PlatformMessage.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ model
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ CommandScope.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ PlatformType.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Ticket.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ TicketStatus.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  └── User.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ service
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ RateLimitExceededException.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ RateLimitService.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ SupportService.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ TextService.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ TicketService.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ UserBannedException.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”‚Β Β  └── UserService.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ CoreCommandProcessor.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ CoreCommandType.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ CoreSupportProcessor.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  └── PlatformConfigResolver.java
β”‚Β Β      β”‚Β Β              β”œβ”€β”€ platform
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ discord
β”‚Β Β      β”‚Β Β              β”‚Β Β  └── telegram
β”‚Β Β      β”‚Β Β              β”‚Β Β      β”œβ”€β”€ adapter
β”‚Β Β      β”‚Β Β              β”‚Β Β      β”‚Β Β  β”œβ”€β”€ TelegramCommandAdapter.java
β”‚Β Β      β”‚Β Β              β”‚Β Β      β”‚Β Β  β”œβ”€β”€ TelegramMessageAdapter.java
β”‚Β Β      β”‚Β Β              β”‚Β Β      β”‚Β Β  └── TelegramPlatformMessage.java
β”‚Β Β      β”‚Β Β              β”‚Β Β      β”œβ”€β”€ TelegramBot.java
β”‚Β Β      β”‚Β Β              β”‚Β Β      β”œβ”€β”€ TelegramBotConfig.java
β”‚Β Β      β”‚Β Β              β”‚Β Β      β”œβ”€β”€ TelegramProperties.java
β”‚Β Β      β”‚Β Β              β”‚Β Β      β”œβ”€β”€ TelegramSender.java
β”‚Β Β      β”‚Β Β              β”‚Β Β      └── TelegramUpdateHandler.java
β”‚Β Β      β”‚Β Β              β”œβ”€β”€ repository
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ TicketRepository.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  └── UserRepository.java
β”‚Β Β      β”‚Β Β              β”œβ”€β”€ web
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ ConfigController.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ SupportConfigDto.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ UiController.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  β”œβ”€β”€ WebSecurityConfig.java
β”‚Β Β      β”‚Β Β              β”‚Β Β  └── YamlConfigService.java
β”‚Β Β      β”‚Β Β              └── SupportPlatformApplication.java
β”‚Β Β      └── resources
β”‚Β Β          β”œβ”€β”€ static
β”‚Β Β          β”‚Β Β  └── app.js
β”‚Β Β          └── templates
β”‚Β Β              └── index.html
β”œβ”€β”€ application.yml
└── pom.xml

Main idea

Core knows nothing about platforms (telegram, discord, etc.)

Core:

  • accepts abstract messages (PlatformMessage)
  • returns intents (CoreResponse)
  • does not send messages itself

Platforms:

  • determine context (user / admin / command)
  • adapt native messages
  • execute CoreResponse

How to add a new platform

To add a new platform, the following elements need to be implemented:

1: PlatformMessage

Platform native message adapter:

public interface PlatformMessage {
    PlatformType platform();
    long chatId();
    long senderId();
    String text();
    boolean hasAttachments();
    Object nativeMessage();
}

nativeMessage() is the native platform SDK object Core doesn't use it, it just passes it back to CoreResponse.CopyMessage

2: MessageAdapter

Converts a native platform message to a PlatformMessage:

@Component
public class TelegramMessageAdapter {
    public PlatformMessage adapt(Message message) {
        return new TelegramPlatformMessage(message);
    }
}

3: CommandAdapter

Converts admin commands to CoreCommand:

public record CoreCommand(
    PlatformType platform,
    long adminId,
    String name,
    List<String> args
) {}

4: UpdateHandler (Router)

The platform itself determines the context of the message:

  • admin command
  • admin reply
  • user message

Example logic:

1. If the command - CoreCommandProcessor
2. If the reply is from an administrator - CoreSupportProcessor.handleAdminReply
3. If the message is from a user - CoreSupportProcessor.handleUserMessage

5: Executing CoreResponse

The Core returns intents, the platform is obliged to fulfill them:

public sealed interface CoreResponse {
    record SendText(long chatId, String text) implements CoreResponse {}
    record CopyMessage(long from, long to, Object nativeMsg) implements CoreResponse {}
    enum Ignore implements CoreResponse { INSTANCE }
}

The platform knows:

  • how to send a text
  • how to copy a message
  • how to ignore

Configuration and web panel

All settings are located in application.yml.

Editing is possible:

  • manually
  • via the web panel

Web Admin Panel

  • By default, it's located on port 8080
  • URL: http://localhost:8080/
  • HTTP Basic Auth
  • Allows editing the entire application.yml
  • Changes take effect after a restart

Roadmap

  • Core engine (tickets, rate-limit, ban)
  • Telegram platform
  • Web UI for configuration
  • Discord platform
  • Rate-limit storage in Redis