{"id":26367650,"url":"https://github.com/jwizard-bot/jwizard-core","last_synced_at":"2025-03-16T21:18:10.538Z","repository":{"id":45897284,"uuid":"512298084","full_name":"jwizard-bot/jwizard-core","owner":"jwizard-bot","description":"Command interactions handler, Lavalink client and web interface message broker events receiver.","archived":false,"fork":false,"pushed_at":"2024-10-23T16:47:20.000Z","size":3065,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-23T21:47:29.845Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://jwizard.pl","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jwizard-bot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-09T22:34:13.000Z","updated_at":"2024-10-23T03:07:00.000Z","dependencies_parsed_at":"2024-05-12T23:26:00.968Z","dependency_job_id":"cea6a06b-7cb6-47dc-ba02-521cff10214e","html_url":"https://github.com/jwizard-bot/jwizard-core","commit_stats":null,"previous_names":["jwizard-bot/jwizard-core"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwizard-bot%2Fjwizard-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwizard-bot%2Fjwizard-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwizard-bot%2Fjwizard-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwizard-bot%2Fjwizard-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jwizard-bot","download_url":"https://codeload.github.com/jwizard-bot/jwizard-core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243933440,"owners_count":20370988,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-16T21:18:09.782Z","updated_at":"2025-03-16T21:18:10.532Z","avatar_url":"https://github.com/jwizard-bot.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](.github/banner.png)\n\n[[About project](https://jwizard.pl/about)]\n| [[Docker image](https://hub.docker.com/r/milosz08/jwizard-core)]\n| [[Docker installation](./docker/README.md)]\n\nJWizard is an open-source Discord music bot that manages audio content from various multimedia\nsources and features an innovative web player. This repository contains the core of the application,\nwhich supports Discord API event handlers and a message broker for handling events from the web\ninterface. It is also designed for clustering, utilizing a shard-offset system.\n\n## Table of content\n\n* [Architecture concepts](#architecture-concepts)\n* [Project modules](#project-modules)\n* [Audio gateway client](#audio-gateway-client)\n* [Clone and install](#clone-and-install)\n* [Contributing](#contributing)\n* [License](#license)\n\n## Architecture concepts\n\n* This project was built using the Spring IoC architecture (without Spring Boot), ensuring loose\n  coupling through the SPI architecture and bean interfaces.\n* Bean interfaces help maintain loose coupling between the project's modules.\n* The entire codebase is written in Kotlin.\n* The Discord API is integrated using the JDA (Java Discord API) library.\n* OPUS audio support and streaming are handled by the custom audio gateway client and a modified\n  Lavalink server cluster.\n* Communication and event handling between the application and the back-end are managed via\n  WebSockets and RabbitMQ.\n\n## Project modules\n\n| Name              | Description                                                                                                                     |\n|-------------------|---------------------------------------------------------------------------------------------------------------------------------|\n| jwc-api           | JDA command handlers for capturing interactions triggered by Discord guild members.                                             |\n| jwc-app           | The application entry point, including configuration files and internationalization (i18n) content.                             |\n| jwc-audio         | JWizard audio client bridge, node manager, audio content loaders, and schedulers.                                               |\n| jwc-audio-gateway | Audio gateway facilitating communication between audio servers and the jwc-audio module.                                        |\n| jwc-command       | Framework for legacy (prefix) and slash command interactions, including component handlers and command reflection loader.       |\n| jwc-core          | JDA loader, configuration loader framework, SPI interfaces for jwc-audio, JVM thread helpers, and utility formatters.           |\n| jwc-exception     | Set of exceptions that may be thrown during the interaction pipeline, caught by the command interaction framework.              |\n| jwc-gateway       | Handle communication between Core and other JWizard projects (exclude communication with audio server) via HTTP, REST and AMQP. |\n| jwc-persistence   | Provides communication via S3 storage and RDBMS (SQL), with loosely coupled binding beans (provided through SPI).               |\n| jwc-radio         | Framework for parsing radio playback data and associated information.                                                           |\n| jwc-vote          | JDA voting framework that manages voting interactions via interaction components.                                               |\n\n## Audio gateway client\n\nThis project contains custom client for Lavalink nodes (`jwc-audio-gateway` module). It enables the\ncreation of separate node pools and implements load balancing based on the Discord gateway audio\nregion. This client is fully compatible with the Lavalink v4 protocol.\n\nKey concepts:\n\n* A modified version of the original Lavalink client for Java/Kotlin, supporting Lavalink v4.\n* Enables node pool fragmentation, allowing nodes to be categorized, restricted, or prioritized\n  for handling playback requests - useful for distributing traffic across nodes running different\n  audio plugins.\n* Each node is represented by an independent Lavalink server instance.\n* Load balancing within a selected node pool ensures that playback requests are handled by a node\n  located in the same region as the Discord voice server.\n* Additionally, the system selects the least loaded node from the pool based on a penalty system.\n* Each link (guild representation) dynamically assigns a node, automatically switching to another\n  node in case of failure, based on the load balancing algorithm.\n* Connections to Lavalink servers are established via HTTP (REST) and WebSocket protocols.\n\n## Clone and install\n\n1. Make sure you have at least JDK 17 and Kotlin 2.0.\n2. Clone **JWizard Lib** and **JWizard Tools** from organization repository via:\n\n```bash\n$ git clone https://github.com/jwizard-bot/jwizard-lib\n$ git clone https://github.com/jwizard-bot/jwizard-tools\n```\n\n3. Configure and run all necessary containers defined in `README.md` file\n   in [jwizard-lib](https://github.com/jwizard-bot/jwizard-lib) repository. You must have up these\n   containers:\n\n| Name                | Port(s) | Description                  |\n|---------------------|---------|------------------------------|\n| jwizard-vault       | 8761    | Secret keys storage service. |\n| jwizard-mysql-db    | 8762    | MySQL database.              |\n| jwizard-lava-node-1 | 8766    | Lavalink #1 node.            |\n| jwizard-lava-node-2 | 8767    | Lavalink #2 node.            |\n\n\u003e [!IMPORTANT]\n\u003e Don't forget to perform database migration after start DB (see\n\u003e [jwizard-lib](https://github.com/jwizard-bot/jwizard-lib) repository).\n\n\u003e [!TIP]\n\u003e Alternatively, you can run single Lavalink node, but in `docker-compose.yml` file in\n\u003e [jwizard-lib](https://github.com/jwizard-bot/jwizard-lib) repository you must remove second\n\u003e Lavalink node declaration.\n\u003e Running 2 nodes are useful for checking load-balancer in performance tests.\n\n4. Build library and package to Maven Local artifacts' storage (for **JWizard Lib**):\n\n* for UNIX based systems:\n\n```bash\n$ ./gradlew clean publishToMavenLocal\n```\n\n* for Windows systems:\n\n```bash\n.\\gradlew clean publishToMavenLocal\n```\n\n5. Clone this repository via:\n\n```bash\n$ git clone https://github.com/jwizard-bot/jwizard-core\n```\n\n6. Create `.env` file in root of the project path (based on `example.env`) and insert Vault token:\n\n```properties\nENV_VAULT_TOKEN=\u003cvault token\u003e\n```\n\nwhere `\u003cvalue token\u003e` property is the Vault token stored in configured `.env` file\nin [jwizard-lib](https://github.com/jwizard-bot/jwizard-lib) repository.\n\n7. That's it. Now you can run via Intellij IDEA. Make sure, you have set JVM parameters:\n\n```bash\n-Druntime.profiles=dev\n-Denv.enabled=true # optional, if false JWizard will prevent read .env file\n-Dserver.port=\u003cport number\u003e # only for production, for dev port is already pre-defined in vault\n\n-Djda.instance.name=core-instance/N # bot instance refer to Vault backend prefix\n-Djda.sharding.offset.start=\u003cnumber\u003e # shard ID which starts (inclusive) shards pool in process\n-Djda.sharding.offset.end=\u003cnumber\u003e # shard ID which end (inclusive) shards pool in process\n-Djda.sharding.total-shards=\u003cnumber\u003e # total shards for all processes in one instance\n\n-Xms1G -Xmx1G # optional, see NOTE\n# ... rest parameters, ex. JVM GC configuration\n```\n\nwhere:\n\n* `N` is instance number (`0` or `1`),\n* `Xmx` and `Xms` parameters are optional and can be modified.\n\n\u003e [!NOTE]\n\u003e For servers running on HotSpot JVM, Oracle recommended same Xms and Xmx parameter, ex. `-Xms1G`\n\u003e and `-Xmx1G`. More information you will find\n\u003e [here](https://docs.oracle.com/cd/E74363_01/ohi_vbp_-_installation_guide--20160224-094432-html-chunked/s66.html).\n\n\u003e [!IMPORTANT]\n\u003e You can run concurrently 2 instances, but you must set valid offsets in\n`-Djda.sharding.offset.start` and `-Djda.sharding.offset.end`. Concurrent instances can share same\n\u003e Lavalink node/nodes.\n\n### Clustering example with multiple concurrent instance\n\n```\ninstance 0              instance 1       ...     instance N\n├─ process 0            ├─ process 0\n│  ├─ shards 0-9        │  ├─ shards 0-9\n├─ process 1            ├─ process 1\n│  ├─ shards 10-19      │  ├─ shards 10-19\n│  ...                  │  ...\n├─ process N            ├─ process N\n```\n\nMore about sharding, clustering multiple concurrent instances and shards fragmentation (different\nshard ranges for distributed JVM architecture) you will find here:\n\n* [https://discord.com/developers/docs/events/gateway#sharding](https://discord.com/developers/docs/events/gateway#sharding)\n* [https://skelmis.co.nz/posts/discord-bot-sharding-and-clustering](https://skelmis.co.nz/posts/discord-bot-sharding-and-clustering)\n\n## Contributing\n\nWe welcome contributions from the community! Please read our [CONTRIBUTING](./CONTRIBUTING.md) file\nfor guidelines on how to get involved.\n\n## License\n\nThis project is licensed under the AGPL-3.0 License - see the LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwizard-bot%2Fjwizard-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjwizard-bot%2Fjwizard-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwizard-bot%2Fjwizard-core/lists"}