Skip to content

Conversation

@cudoriver
Copy link

@cudoriver cudoriver commented Jan 19, 2026

Description

I have added a new dispatch task module named R01SevkiyatTask within the dev.shared.cudoriver.task package. This module is designed to handle R01 dispatch missions.

Status: Not Tested

Please note that I haven't been able to test this code in-game yet due to signature restrictions on my local build. I've followed the project's existing code structure (based on CloseAdOffer and other tasks) to ensure compatibility.

Changes

  • Added R01SevkiyatTask.java to dev.shared.cudoriver.task.
  • Registered the new task in plugin.json.

I would appreciate it if you could review the logic and let me know if any adjustments are needed. Thanks!

Summary by Sourcery

Add an automated R-01 dispatch task and adjust Gradle wrapper startup script behavior.

New Features:

  • Introduce R01SevkiyatTask to periodically collect and resend R-01 dispatches via BackpageAPI.

Enhancements:

  • Update Gradle wrapper scripts to add SPDX license identification, direct error output to stderr, and invoke the wrapper JAR via -jar.

Build:

  • Modify Windows Gradle wrapper script configuration and invocation to use the wrapper JAR directly.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 19, 2026

Reviewer's Guide

Implements a new Darkbot dispatch automation task R01SevkiyatTask for recurring R-01 missions, registers it in the plugin, and adjusts Gradle wrapper scripts for licensing, stderr logging, and jar-based execution on Windows.

Sequence diagram for periodic R01SevkiyatTask dispatch cycle

sequenceDiagram
    participant Scheduler
    participant R01SevkiyatTask
    participant SevkiyatThread
    participant BackpageAPI
    participant DispatchBackend

    loop every_tick
        Scheduler->>R01SevkiyatTask: onTickTask()
        alt kontrol_suresi_gecti
            R01SevkiyatTask->>R01SevkiyatTask: calistirSevkiyatDongusu()
            R01SevkiyatTask->>SevkiyatThread: new Thread(runnable).start()
            activate SevkiyatThread
            SevkiyatThread->>SevkiyatThread: log Sevkiyat_dongusu_baslatiliyor
            loop slot 1..4 collect
                SevkiyatThread->>BackpageAPI: getConnection(indexInternal.es?action=internalDispatch&subaction=collect&slotId=slot)
                BackpageAPI->>DispatchBackend: HTTP request
                DispatchBackend-->>BackpageAPI: HTTP response
                BackpageAPI-->>SevkiyatThread: connection_result
                SevkiyatThread->>SevkiyatThread: Thread.sleep(1000)
            end
            loop slot 1..4 init_R01
                SevkiyatThread->>BackpageAPI: getConnection(indexInternal.es?action=internalDispatch&subaction=init&retrieverId=1&slotId=slot)
                BackpageAPI->>DispatchBackend: HTTP request
                DispatchBackend-->>BackpageAPI: HTTP response
                BackpageAPI-->>SevkiyatThread: connection_result
                SevkiyatThread->>SevkiyatThread: Thread.sleep(1000)
            end
            SevkiyatThread->>SevkiyatThread: log Sevkiyat_basarili
            deactivate SevkiyatThread
        else bekleme_suresi_dolmamadi
            R01SevkiyatTask-->>Scheduler: return
        end
    end
Loading

Class diagram for new R01SevkiyatTask dispatch automation

classDiagram
    class R01SevkiyatTask {
        -BackpageAPI backpage
        -long sonKontrolZamani
        -long BEKLEME_SURESI
        +R01SevkiyatTask(PluginAPI api)
        +void onTickTask()
        +void onBackgroundTick()
        -void calistirSevkiyatDongusu()
    }

    class Task {
        +void onTickTask()
        +void onBackgroundTick()
    }
    <<interface>> Task

    class PluginAPI {
        +BackpageAPI requireAPI(Class apiClass)
    }

    class BackpageAPI {
        +Object getConnection(String url)
    }

    R01SevkiyatTask ..|> Task
    R01SevkiyatTask --> BackpageAPI
    R01SevkiyatTask --> PluginAPI
Loading

File-Level Changes

Change Details Files
Add R01SevkiyatTask Darkbot task to automate R-01 dispatch collection and resend every ~3 hours.
  • Introduce R01SevkiyatTask implementing Task with BackpageAPI injection via PluginAPI constructor.
  • Implement onTickTask to rate-limit dispatch cycle execution based on a 3-hour + 1-minute interval using a timestamp field.
  • Add a no-op onBackgroundTick override to satisfy Task interface.
  • Implement calistirSevkiyatDongusu to spawn a background thread that collects dispatch rewards for slots 1–4 via Backpage internalDispatch collect calls, then re-initializes R-01 retrievers for the same slots, with 1-second sleeps between requests and basic stdout/stderr logging around the sequence.
src/main/java/dev/shared/do_gamer/task/R01SevkiyatTask.java
Register the new R01SevkiyatTask in the plugin metadata so Darkbot can discover it.
  • Add the R01SevkiyatTask entry to plugin.json’s feature/task configuration (exact JSON not shown in diff but implied by description).
src/main/resources/plugin.json
Adjust Windows Gradle wrapper script to include SPDX license identifier, improve error messaging to stderr, and change how the wrapper jar is invoked.
  • Add SPDX-License-Identifier: Apache-2.0 comment header to gradlew.bat.
  • Redirect JAVA_HOME-related error messages to stderr instead of stdout by appending 1>&2 to echo commands.
  • Clear CLASSPATH and switch from using -classpath gradle-wrapper.jar + main class invocation to using -classpath with an empty CLASSPATH and -jar %APP_HOME%\gradle\wrapper\gradle-wrapper.jar when launching Gradle.
gradlew.bat

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 5 issues, and left some high level feedback:

  • The custom changes to gradlew.bat (clearing CLASSPATH and switching to -jar invocation) diverge from the standard Gradle wrapper script and may break tooling or upgrades; consider reverting to the stock wrapper script unless there is a very specific, documented need for these changes.
  • In R01SevkiyatTask, spawning a new Thread and using Thread.sleep inside it is a bit heavyweight and may not integrate well with the host’s lifecycle; it might be safer to rely on the framework’s scheduling/tick model or a shared executor instead of creating unmanaged threads.
  • The task currently uses System.out.println/System.err.println for logging; if the project has a logging or notification API, routing these messages through that instead will make behavior more consistent and easier to control.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The custom changes to `gradlew.bat` (clearing `CLASSPATH` and switching to `-jar` invocation) diverge from the standard Gradle wrapper script and may break tooling or upgrades; consider reverting to the stock wrapper script unless there is a very specific, documented need for these changes.
- In `R01SevkiyatTask`, spawning a new `Thread` and using `Thread.sleep` inside it is a bit heavyweight and may not integrate well with the host’s lifecycle; it might be safer to rely on the framework’s scheduling/tick model or a shared executor instead of creating unmanaged threads.
- The task currently uses `System.out.println`/`System.err.println` for logging; if the project has a logging or notification API, routing these messages through that instead will make behavior more consistent and easier to control.

## Individual Comments

### Comment 1
<location> `src/main/java/dev/shared/do_gamer/task/R01SevkiyatTask.java:35` </location>
<code_context>
+    }
+
+    private void calistirSevkiyatDongusu() {
+        new Thread(() -> {
+            try {
+                System.out.println("Sevkiyat döngüsü başlatılıyor...");
</code_context>

<issue_to_address>
**suggestion (review_instructions):** Spawning a raw Thread inside the task is not ideal for a DarkBot plugin and can be made cleaner and more efficient by using the framework’s scheduling facilities or a shared executor.

Creating a new `Thread` directly in a plugin bypasses DarkBot’s lifecycle and can lead to harder-to-debug concurrency issues or stray threads if the plugin is reloaded or stopped. It’s also less efficient than reusing a scheduled executor or DarkBot’s own timed task mechanisms.

Consider refactoring `calistirSevkiyatDongusu` to run synchronously from `onTickTask` with non-blocking/backoff logic, or delegate to a shared `ScheduledExecutorService` / DarkBot’s scheduler instead of `new Thread(...).start()` and `Thread.sleep` calls.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `*.java`

**Instructions:**
It is a plugin for the darkbot bot in java, check that the code is clean and efficient.

</details>
</issue_to_address>

### Comment 2
<location> `src/main/java/dev/shared/do_gamer/task/R01SevkiyatTask.java:42` </location>
<code_context>
+                // 1. Adım: Topla
+                for (int slot = 1; slot <= 4; slot++) {
+                    backpage.getConnection("indexInternal.es?action=internalDispatch&subaction=collect&slotId=" + slot);
+                    Thread.sleep(1000);
+                }
+
</code_context>

<issue_to_address>
**suggestion (review_instructions):** Using `Thread.sleep(1000)` repeatedly inside a custom thread is a relatively inefficient way to pace requests and reduces code cleanliness.

The loop uses `Thread.sleep(1000)` after every request, which is a coarse and blocking way to rate-limit calls. Even though it runs on a separate thread, this pattern is less clean and makes timing behavior harder to control or adjust.

If you keep an asynchronous approach, consider using a scheduled executor or DarkBot’s own task scheduling to handle delays, which avoids manual sleeps and gives better control over timing and potential cancellation when the plugin stops.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `*.java`

**Instructions:**
It is a plugin for the darkbot bot in java, check that the code is clean and efficient.

</details>
</issue_to_address>

### Comment 3
<location> `src/main/java/dev/shared/do_gamer/task/R01SevkiyatTask.java:37` </location>
<code_context>
+    private void calistirSevkiyatDongusu() {
+        new Thread(() -> {
+            try {
+                System.out.println("Sevkiyat döngüsü başlatılıyor...");
+
+                // 1. Adım: Topla
</code_context>

<issue_to_address>
**suggestion (review_instructions):** Using `System.out.println`/`System.err.println` directly in a plugin is not considered clean; prefer DarkBot’s logging facilities or a proper logger.

Direct console printing (`System.out.println` / `System.err.println`) in a long-running plugin can clutter logs and makes it harder to integrate with DarkBot’s logging and debugging tools.

For cleaner code, switch to the logging mechanism recommended by DarkBot (or a standard logger such as SLF4J/Log4j if compatible), so messages can be filtered, formatted, and managed consistently with the rest of the bot.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `*.java`

**Instructions:**
It is a plugin for the darkbot bot in java, check that the code is clean and efficient.

</details>
</issue_to_address>

### Comment 4
<location> `src/main/java/dev/shared/do_gamer/task/R01SevkiyatTask.java:53` </location>
<code_context>
+
+                System.out.println("Sevkiyat başarıyla tamamlandı.");
+
+            } catch (Exception e) {
+                System.err.println("Sevkiyat hatası: " + e.getMessage());
+            }
</code_context>

<issue_to_address>
**suggestion (review_instructions):** Catching a raw `Exception` and only printing its message is not very clean; the error handling can be more precise and informative.

Catching the generic `Exception` makes it harder to understand what failures are expected and which are truly exceptional. It also discards the stack trace by only printing `e.getMessage()`.

For cleaner error handling, narrow the catch to the specific exceptions you expect (e.g., network-related), and log the full exception (including stack trace) through the plugin’s logger instead of `System.err`, so issues are easier to diagnose in DarkBot.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `*.java`

**Instructions:**
It is a plugin for the darkbot bot in java, check that the code is clean and efficient.

</details>
</issue_to_address>

### Comment 5
<location> `src/main/java/dev/shared/do_gamer/task/R01SevkiyatTask.java:40` </location>
<code_context>
+                System.out.println("Sevkiyat döngüsü başlatılıyor...");
+
+                // 1. Adım: Topla
+                for (int slot = 1; slot <= 4; slot++) {
+                    backpage.getConnection("indexInternal.es?action=internalDispatch&subaction=collect&slotId=" + slot);
+                    Thread.sleep(1000);
</code_context>

<issue_to_address>
**suggestion (review_instructions):** The repeated slot bounds (1 and 4), sleep duration (1000), and retrieverId (1) are magic numbers and should be extracted into named constants.

In `calistirSevkiyatDongusu`, there are several magic numbers used multiple times:
- Loop range: `slot = 1; slot <= 4; slot++` (used in both loops)
- Sleep duration: `Thread.sleep(1000);`
- Retriever ID in the URL: `retrieverId=1`

To follow the instruction of extracting magic numbers into constants and to keep consistent with `BEKLEME_SURESI`’s ALL_CAPS naming, consider something like:

```java
private static final int FIRST_SLOT_ID = 1;
private static final int LAST_SLOT_ID = 4;
private static final long SLOT_REQUEST_DELAY_MS = 1000L;
private static final int R01_RETRIEVER_ID = 1;
```

Then the loops and URL become:

```java
for (int slot = FIRST_SLOT_ID; slot <= LAST_SLOT_ID; slot++) {
    backpage.getConnection("indexInternal.es?action=internalDispatch&subaction=collect&slotId=" + slot);
    Thread.sleep(SLOT_REQUEST_DELAY_MS);
}

for (int slot = FIRST_SLOT_ID; slot <= LAST_SLOT_ID; slot++) {
    backpage.getConnection(
        "indexInternal.es?action=internalDispatch&subaction=init" +
        "&retrieverId=" + R01_RETRIEVER_ID +
        "&slotId=" + slot
    );
    Thread.sleep(SLOT_REQUEST_DELAY_MS);
}
```

This removes the hard-coded numbers, improves readability, and aligns with the existing constant naming style (`BEKLEME_SURESI`).

<details>
<summary>Review instructions:</summary>

**Path patterns:** `*`

**Instructions:**
Suggest extracting magic numbers into named constants to improve code readability and maintainability.

</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

@dm94 dm94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are not a do-gamer, you have to implement those features in other folders.
Also, do not use Thread.

@cudoriver cudoriver changed the title Add R01 Dispatch Task to do_gamer package Add R01 Dispatch Task to cudoriver/tasks Jan 19, 2026
Copy link
Contributor

@dm94 dm94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

import eu.darkbot.api.managers.BackpageAPI;
import eu.darkbot.api.utils.Inject;

@Feature(name = "R01 Sevkiyat Modülü", description = "R01 görevlerini otomatik toplar ve başlatır")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name and description must be in English or translated using the translation system.

@dm94
Copy link
Contributor

dm94 commented Jan 19, 2026

I'm sending it to you compressed because it won't let me send it unless it's a zip file.
Test it before merging it.

SharedPlugin.zip

@cudoriver
Copy link
Author

There was a problem but I think I fixed that.
Ekran görüntüsü 2026-01-20 021908

@dm94
Copy link
Contributor

dm94 commented Jan 19, 2026

There was a problem but I think I fixed that. Ekran görüntüsü 2026-01-20 021908

SharedPlugin.zip

@anjeshshrestha
Copy link

Hey, I wanted to chime in regarding running dispatch. I don’t see a Backpage mechanism for starting and collecting the retriever that’s visible to the user. Is it possible this is a “risky” change that relies on an endpoint that wasn’t intended to be used?

Can you add some more details?

@do-gamer
Copy link
Contributor

I agree that this method: indexInternal.es?action=internalDispatch, is probably a legacy one and does not support properly.
Better to use com.github.manolo8.darkbot.core.manager.DispatchManager.

Also, the Dispatch is a paid feature of PikaPlugin, there need to consider first with his contributor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to revert this file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also revert this one.


try {
if (collecting) {
backpage.getConnection("indexInternal.es?action=internalDispatch&subaction=collect&slotId=" + currentSlot);
Copy link
Contributor

@do-gamer do-gamer Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@do-gamer
Copy link
Contributor

do-gamer commented Jan 20, 2026

SharedPlugin.zip

I tested it and, for me with Linux API for the bot, it doesn't work at all. It simply does nothing.

P.S. I don't have a Windows to test with KekkaPlayer API.

@cudoriver
Copy link
Author

Also, the Dispatch is a paid feature of PikaPlugin, there need to consider first with his contributor.

This module is exclusively for Retriever-01. I developed it from scratch to fulfill a basic need. If everything goes well, I might consider adding other dispatch types in the future.

Actually, I haven't been able to test the project properly yet, as the main application requires a dev token which I don't have.

@do-gamer
Copy link
Contributor

Actually, I haven't been able to test the project properly yet, as the main application requires a dev token which I don't have.

Please refer to the "DarkBot" discord "coding" channel for more information on how to test without a dev token.

@dm94
Copy link
Contributor

dm94 commented Jan 20, 2026

Let me know when you want a new build to test.

@cudoriver
Copy link
Author

Let me know when you want a new build to test.

Yes, I will. Thank you for everything again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants