Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat add: GUI #3

Draft
wants to merge 41 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
0529e3c
feat: selectable cubes
virus-rpi Feb 8, 2024
b0692ff
feat: better cube arrangement
virus-rpi Feb 8, 2024
830e81e
chore: restructure
virus-rpi Feb 19, 2024
cf757a5
feat: centering cubes works
virus-rpi May 7, 2024
d3bb040
feat: text is now visible
virus-rpi May 7, 2024
258094b
fix: no crash at spam click
virus-rpi May 7, 2024
aeb3bcd
chore: added lots of TODOs
virus-rpi May 7, 2024
8003301
fix: fixed a typo
virus-rpi May 7, 2024
26dab7e
Merge branch 'refs/heads/master' into gui
virus-rpi May 7, 2024
31893ea
<upload. no finished features>
virus-rpi May 16, 2024
9337189
feat: translator.go (script no fully working yet
virus-rpi May 16, 2024
e81f106
feat: extractor script for translator
virus-rpi May 16, 2024
0876905
fix: removed temporary function removal
virus-rpi May 16, 2024
87d758b
Feat: added some translations
May 18, 2024
a301472
chore: add .venv to gitignore
May 22, 2024
ef2499e
feat: add form system
virus-rpi May 22, 2024
9227cf5
feat: add form to gui translator (not fully working)
virus-rpi May 22, 2024
13a1e46
feat: better form
virus-rpi May 23, 2024
0e0b47f
feat: faster form refresh
virus-rpi May 23, 2024
b9defda
fix: validation
virus-rpi May 23, 2024
2d1be38
feat: add callback
virus-rpi May 23, 2024
4f90589
feat: better form
virus-rpi May 23, 2024
764c2e3
chore: refactor
virus-rpi May 30, 2024
40a2dc6
fix: visals work now "as expected"
virus-rpi May 30, 2024
a3bff86
fix: removed print statements
virus-rpi May 30, 2024
ef23c71
feat: added type to cube info
virus-rpi May 30, 2024
78bd506
feat: import / export cube config
virus-rpi May 30, 2024
da0543d
chore: updated todos
virus-rpi May 30, 2024
b364493
chore: updated todos
virus-rpi May 30, 2024
d7b5cea
feat: bump up version
virus-rpi May 31, 2024
de53999
feat: add uwu language
virus-rpi Jul 3, 2024
0ff3eaf
feat: resizabel ui
virus-rpi Jul 3, 2024
1f54733
feat: add language setting
virus-rpi Aug 1, 2024
c312d2a
chore: add missing translation
virus-rpi Aug 1, 2024
af16729
feat: added way to add on language change listeners
virus-rpi Aug 1, 2024
2df4f1a
chore: defined structure for orchestrator
virus-rpi Aug 1, 2024
c8ed737
feat: save cubes on server via sqlite db
virus-rpi Oct 9, 2024
1c3e4cf
feat: query all cubes from all servers cubes were added
virus-rpi Oct 10, 2024
f913384
chore: remove api type and update gitignore
virus-rpi Oct 10, 2024
7fc35fa
feat: intigrate queen into core
virus-rpi Oct 10, 2024
1c50fff
feat: switch to gRPC
virus-rpi Nov 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .air.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
args_bin = []
bin = "tmp\\main.exe"
cmd = "go build -o ./tmp/main.exe ."
delay = 500
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = true
follow_symlink = true
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false

[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"

[log]
main_only = false
time = false

[misc]
clean_on_exit = true

[screen]
clear_on_rebuild = false
keep_scroll = true
8 changes: 1 addition & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,4 @@ go.work
.idea/*
config.json

queen
security
drone
database
api
website
discord-bot
.venv
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ This is the core of cubus. It will be a platform to create, configure and manage
2. Create a fork
3. Checkout the correct branch / create one
4. Implement the feature or help by doing todos in the code (marked by `// TODO: `)
5. Create a PR or a Stacked PR depending if there is already a PR for the feature
5. Create a PR or a Stacked PR depending on if there is already a PR for the feature

and if you have any ideas how to improve something or have a feature idea, please post it in the discussion tab.
30 changes: 30 additions & 0 deletions cubes/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cubes

import "CUBUS-core/shared/types"

type Base interface {
InitMessageChannel()
SendMessage(message types.Message)
GetMessageChannel() chan types.Message
GetConfig() types.CubeConfig
}

type BaseStruct struct {
messageChannel chan types.Message
}

func (b *BaseStruct) InitMessageChannel() {
b.messageChannel = make(chan types.Message)
}

func (b *BaseStruct) SendMessage(message types.Message) {
b.messageChannel <- message
}

func (b *BaseStruct) GetMessageChannel() chan types.Message {
return b.messageChannel
}

func (b *BaseStruct) GetConfig() types.CubeConfig {
return types.CubeConfig{}
}
156 changes: 156 additions & 0 deletions cubes/queen/queen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package queen

import (
"CUBUS-core/cubes"
"CUBUS-core/shared/tasks"
"CUBUS-core/shared/types"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"github.com/hibiken/asynq"
"log"
"os"
"time"
)

type Queen struct {
cubes.BaseStruct
config types.QueenConfig
privateKey crypto.PrivateKey
asynqClient *asynq.Client
logger *log.Logger
}

func New(config types.QueenConfig) *Queen {
logger := log.New(os.Stdout, "Cube (type: "+config.CubeType.Value+", id: "+config.Id+"): ", log.LstdFlags)
q := Queen{config: config, logger: logger}
q.InitMessageChannel()
if q.config.PublicKey == nil || q.config.PublicKey == "" {
q.generateKeyPair()
} else {
q.loadPrivateKey()
}
go q.start()
return &q
}

func (q *Queen) generateKeyPair() {
q.logger.Println("Generating new key pair")
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
q.logger.Fatalln("Failed to generate key pair: ", err)
}
q.logger.Println("Key pair generated")
q.privateKey = privateKey
q.config.PublicKey = &privateKey.PublicKey

privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
})
err = os.WriteFile(q.config.Id+".pem", privateKeyPEM, 0600)
if err != nil {
q.logger.Fatalln("Failed to write private key to file: ", err)
}
go q.SendMessage(types.Message{
MessageType: "UPDATE PUBLIC KEY",
Message: q.config.PublicKey,
})
q.logger.Println("Key pair saved to file")
}

func (q *Queen) loadPrivateKey() {
q.logger.Println("Loading private key")
privateKeyPEM, err := os.ReadFile(q.config.Id + ".pem")
if err != nil {
q.logger.Fatalln("Failed to read private key from file: ", err)
}

block, _ := pem.Decode(privateKeyPEM)
if block == nil || block.Type != "RSA PRIVATE KEY" {
q.logger.Fatalln("Failed to decode private key")
}

privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
q.logger.Fatalln("Failed to parse private key: ", err)
}
q.privateKey = privateKey
q.logger.Println("Private key loaded")
}

func (q *Queen) startServer() {
q.logger.Println("Starting asynq server")
srv := asynq.NewServer(
asynq.RedisClientOpt{
Addr: q.config.RedisAddress,
Password: q.config.RedisPassword,
DB: q.config.RedisDB,
},
asynq.Config{
Concurrency: 1<<31 - 1,
Queues: map[string]int{
"critical": 6,
"default": 3,
"low": 1,
},
},
)

mux := asynq.NewServeMux()

q.logger.Println("Registering tasks")
for _, task := range q.config.Tasks {
mux.HandleFunc(task.Type, task.Handler)
q.logger.Println("Registered task: ", task.Type)
}

go func() {
err := srv.Run(mux)
if err != nil {

}
}()
}

func (q *Queen) startClient() {
q.logger.Println("Starting asynq client")
client := asynq.NewClient(asynq.RedisClientOpt{Addr: q.config.RedisAddress, Password: q.config.RedisPassword, DB: q.config.RedisDB})
defer func(client *asynq.Client) {
err := client.Close()
if err != nil {
q.logger.Println("Failed to close asynq client: ", err)
}
}(client)
q.asynqClient = client
q.logger.Println("Asynq client started")
}

func (q *Queen) start() {
q.startServer()
time.Sleep(1 * time.Second)
q.startClient()
}

func (q *Queen) Enqueue(task *asynq.Task, options ...asynq.Option) (*asynq.TaskInfo, error) {
for q.asynqClient == nil {
}
return q.asynqClient.Enqueue(task, options...)
}

func (q *Queen) GetConfig() types.CubeConfig {
return q.config.CubeConfig
}

func (q *Queen) Ping() {
task, _ := tasks.NewPingTask(q.config.Id)
info, err := q.Enqueue(task)
if err != nil {
q.logger.Println("Failed to enqueue ping task: ", err)
return
}
q.logger.Println("Ping task enqueued: ", info.ID)
}
52 changes: 0 additions & 52 deletions customComponents.go

This file was deleted.

60 changes: 60 additions & 0 deletions extract_i18n.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import re
import toml
import os
import glob
import logging

def load_existing_strings(directory):
strings = set()
for filename in glob.glob(os.path.join(directory, '*.toml')):
with open(filename, 'r', encoding='utf-8') as f:
data = toml.load(f)
strings.update(data.keys())
return strings

def extract_strings_from_go_files(directory, existing_strings):
strings = set()
unfiltered_strings = set()
constants = {}
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(".go"):
logging.info(f"Checking file: {os.path.join(root, file)}")
with open(os.path.join(root, file), 'r') as f:
content = f.read()
const_matches = re.findall(r'(\w+)\s+:=\s+"([^"]*)"', content)
for match in const_matches:
constants[match[0]] = match[1]
matches = re.findall(r'T\(([^)]*)\)', content)
for match in matches:
if match.startswith("\"") and match.endswith("\""):
match_string = match[1:-1]
elif match in constants:
match_string = constants[match]
if match_string not in existing_strings:
strings.add(match_string)
unfiltered_strings.add(match_string)
warn_unused_translations(existing_strings, unfiltered_strings)
return strings

def write_strings_to_toml(strings, directory):
if len(strings) == 0:
logging.info(f"No new strings to add to {directory}")
return
for filename in glob.glob(os.path.join(directory, '*.toml')):
with open(filename, 'r', encoding='utf-8') as f:
data = toml.load(f)
data.update({f'{s}': s for s in strings})
with open(filename, 'w', encoding='utf-8') as f:
toml.dump(data, f)
logging.info(f"Added {len(strings)} new strings to {directory} (keys: {strings})")

def warn_unused_translations(existing_strings, extracted_strings):
unused_translations = existing_strings - extracted_strings
for unused in unused_translations:
logging.warning(f"Unused translation: {unused}")

logging.basicConfig(level=logging.INFO)
existing_strings = load_existing_strings('./shared/translation/locals')
extracted_strings = extract_strings_from_go_files('./', existing_strings)
write_strings_to_toml(extracted_strings, './shared/translation/locals')
Loading