Skip to content

The personal assistant with both dialogue and command interface.

Notifications You must be signed in to change notification settings

YukinaMochizuki/DCDos

Repository files navigation

DCDos

Don't want to read so many words? Jump to Demo.

This is personal assistant with both dialogue and command interface.

Strictly speaking, DCDos is a combination of framework and application. In the near future, I will release part of the framework separately as spring-boot-starter to make its functions easier to use.

What is DCDos?

Disk Control And Decision Operating System.

When working and living, I very much hope that I can have a personal assistant to help me organize notes and to-dos. Although Notion is powerful, it is still difficult to operate this complex and huge machine efficiently during meetings or busy times.

DCDos will act as a controller between the brain and the notes, just like the hard disk controller processes data from the disk to the memory.

General Information

  • Project status: Active, major side project
  • Not currently recommended for use: Before I refactored the code of the framework into spring-boot-starter, there are many functions tailored for myself, and most of these functions cannot be used directly in other environments

Table of Contents

Technologies Used

Development environment

  • AdoptOpenJDK 11 with HotSpot JVM
  • Software Development Kit Manager: SDKMAN!
  • Build System: Gradle 6.8.3
  • Database: MariaDB
  • CI/CD:
    • gitlab-ci.yml - This GitHub repository is actually a mirror from my GitLab
    • Dockerfile - The gitlab-ci will package the application into an image

Dependencies

  • Spring Boot 2.4.5
    • Spring Boot Starter Web
    • Spring Boot Starter Security
    • Spring Boot Starter Data JPA
  • JSch - A pure Java implementation of SSH2. Used to control the unofficial API server
  • Apache Commons Validator - A powerful and customized data verification framework. Used to verify whether the request sent to the API server conforms to the format
  • Picocli - Used to build rich command line applications then connect to communication software
  • TelegramBots - Java library to create bots using Telegram Bots API
  • Project Lombok - Getter, Setter, ToString, AllArgsConstructor and more..

Features

Portability

Program doesn’t know where the message it sends will go, also doesn’t know where the message it receives comes from. All operations are dependent on the abstract class AbstractSession.

So as long as any class extends AbstractSession and implements the above method, then it can assume the responsibility of message transmission like TelegramSession.

Setup

Build

To Jar

git clone https://github.com/YukinaMochizuki/DCDos.git
./gradlew assemble

To Docker image

After gradlew assemble

docker build --tag dcdos .

Configuration

application.properties

Put it in src/main/resources, or in /app/config in the container.

dcdos.debug=false
telegram.username=Your_Bot_Username
telegram.token=12345:ABCDEF
telegram.permission.master=123456789
notion.api.baseurl=http://your-dcdos-notion-api-url

Deploy

You may need to modify these commands for your own environment.

In my case

docker pull registry.lan.yukina.tw/shuvi/dcdos:latest
docker start dcdos-notion-api
docker run -d \
   -v /path/DCDos/config:/app/config \
   -v /path/DCDos/ssh:/app/ssh \
   --link dcdos-notion-api \
   --name dcdos \
   registry.lan.yukina.tw/shuvi/dcdos:latest

Usage

Command

In theory, most functions of Picocli are supported. The implementation of the execution command is in the TelegramManager. You can adjust according to your needs.

@Component
public class TelegramManager {
   public void messageInput(Update update){
   
   ...other code
   
   // find all of the command, assistantCommands is initialized at constructor injection
      Optional<AbstractAssistantCommand> assistantCommandOptional =
         assistantCommands.stream()
         .filter(command -> parameter.get(0).equals(command.getCommandName())).findAny();

   
   ...other code
   
   // execute command
      if(assistantCommandOptional.isPresent()) {
         new CommandLine(assistantCommand).setOut(writer).setErr(writer)
            .setCaseInsensitiveEnumValuesAllowed(true)
            .setUsageHelpWidth(100).execute(args);
      }
   }
}

Full code

So you can simply extend AbstractAssistantCommand and implements Runnable to create a command.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import picocli.CommandLine.Command;
import tw.yukina.dcdos.command.AbstractAssistantCommand;
import tw.yukina.dcdos.constants.Role;
import tw.yukina.dcdos.manager.telegram.TelegramUserInfoManager;

@Component
@Command(name = "start", description = "Say Hello")
public class Start extends AbstractAssistantCommand implements Runnable {

    @Override
    public void run() {
        sendMessageToChatId("Your telegram user id is " + getChatId());
        sendMessageToChatId("If you want to get some help, please send /help for me");
    }

    @Override
    public String getCommandName() {
        return "start";
    }

    @Override
    public Role[] getPermissions() {
        return new Role[]{Role.GUEST};
    }
}

drawing

Program

Just like creating a command, you can create a program by extends AbstractProgramCode.

package tw.yukina.dcdos.program.test;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import tw.yukina.dcdos.program.AbstractProgramCode;
import tw.yukina.dcdos.util.ReplyKeyboard;

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TestProgram extends AbstractProgramCode {

    @Override
    public String[] getKeyword() {
        return new String[]{"測試軟體1"};
    }

    @Override
    public void run() {
        stdout("HelloWorld");
        stdout(getInput());
        stdout("HelloWorld after HelloWorld2");
    }
}

Notice getInput() is synchronous, so blocking occurs in stdout(programController.getInput());.

drawing

Edit sent message

Only need to provide the id when sending the message, and then you can use that id to edit the message.

 @Override
 public void run() {
     stdout("testMessage", "uuid1");
     stdout("testMessage2", "uuid2");

     try {
         Thread.sleep(1000);
         stdout("after");
         updateStdout("after edit", "uuid1");
         updateStdout("after edit2", "uuid2");
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
 }

Full code

drawing

Examples

Create a note using dialogue

Create a note using dialogue instead of commands

Full code

Asynchronous create multiple notes

Create multiple notes in a row

Full code

Roadmap

Some implementation details

About

The personal assistant with both dialogue and command interface.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published