11package com .xinecraft .minetrax .common .banwarden .hooks ;
22
3+ import com .xinecraft .minetrax .common .MinetraxCommon ;
4+ import com .xinecraft .minetrax .common .actions .ReportPlayerPunishment ;
35import com .xinecraft .minetrax .common .data .PunishmentData ;
6+ import com .xinecraft .minetrax .common .enums .BanWardenPluginType ;
7+ import com .xinecraft .minetrax .common .enums .BanWardenPunishmentType ;
48import com .xinecraft .minetrax .common .enums .BanWardenSyncType ;
59import com .xinecraft .minetrax .common .interfaces .banwarden .BanWardenHook ;
10+ import com .xinecraft .minetrax .common .utils .LoggingUtil ;
11+ import litebans .api .Database ;
12+ import litebans .api .Entry ;
13+ import litebans .api .Events ;
14+ import space .arim .omnibus .util .concurrent .ReactionStage ;
15+
16+ import java .sql .PreparedStatement ;
17+ import java .sql .ResultSet ;
18+ import java .sql .SQLException ;
19+ import java .util .ArrayList ;
20+ import java .util .List ;
21+ import java .util .concurrent .CompletableFuture ;
22+ import java .util .concurrent .CompletionStage ;
23+ import java .util .concurrent .TimeUnit ;
24+ import java .util .concurrent .atomic .AtomicInteger ;
25+ import java .util .function .Function ;
626
727public class LitebansHook implements BanWardenHook {
28+ public static final MinetraxCommon common = MinetraxCommon .getInstance ();
29+ private static final int RATE_LIMIT_DELAY_SECONDS = 1 ;
30+ private static final int CHUNK_SIZE = 50 ;
31+
32+ public LitebansHook () {
33+ registerEventListeners ();
34+ }
35+
836 @ Override
937 public void upsert (PunishmentData punishmentData ) {
1038
@@ -22,6 +50,159 @@ public PunishmentData getPunishment(String punishmentId) {
2250
2351 @ Override
2452 public void sync (BanWardenSyncType type ) {
25- System .out .println ("Syncing with Litebans from LitebansHook" );
53+ syncAllPunishments ().thenAccept (aVoid -> {
54+ LoggingUtil .debug ("[BanWarden] Syncing of punishments from LiteBans completed." );
55+ });
56+ }
57+
58+ private void registerEventListeners () {
59+ Events .get ().register (new Events .Listener () {
60+ @ Override
61+ public void entryAdded (Entry entry ) {
62+ try {
63+ PunishmentData data = convertEntryToData (entry );
64+ ReportPlayerPunishment .reportSync (data );
65+ } catch (Exception e ) {
66+ LoggingUtil .error ("[BanWarden] EntryAdded -> Error reporting event to Minetrax: " + e .getMessage ());
67+ }
68+ }
69+
70+ @ Override
71+ public void entryRemoved (Entry entry ) {
72+ try {
73+ PunishmentData data = convertEntryToData (entry );
74+ ReportPlayerPunishment .reportSync (data );
75+ } catch (Exception e ) {
76+ LoggingUtil .error ("[BanWarden] EntryRemoved -> Error reporting event to Minetrax: " + e .getMessage ());
77+ }
78+ }
79+ });
80+ }
81+
82+ private CompletableFuture <Void > syncAllPunishments () {
83+ AtomicInteger totalPunishments = new AtomicInteger (0 );
84+ AtomicInteger offset = new AtomicInteger (0 );
85+
86+ return CompletableFuture .<Void >completedFuture (null ).thenCompose (new Function <Void , CompletionStage <Void >>() {
87+ @ Override
88+ public CompletionStage <Void > apply (Void unused ) {
89+ return fetchPunishmentChunk (CHUNK_SIZE , offset .get ())
90+ .thenCompose (punishmentList -> {
91+ int fetchedCount = punishmentList .size ();
92+ totalPunishments .addAndGet (fetchedCount );
93+
94+ // Process the current chunk
95+ List <PunishmentData > punishmentDataList = new ArrayList <>(punishmentList );
96+
97+ // Report to Minetrax with API
98+ try {
99+ if (!punishmentDataList .isEmpty ()) {
100+ LoggingUtil .info ("Syncing batch of " + punishmentDataList .size () + " punishments to Minetrax..." );
101+ ReportPlayerPunishment .syncSync (punishmentDataList );
102+ }
103+ } catch (Exception e ) {
104+ LoggingUtil .error ("[BanWarden] Error syncing punishments to Minetrax: " + e .getMessage ());
105+ }
106+
107+ if (fetchedCount == CHUNK_SIZE ) {
108+ // If we fetched a full chunk, there might be more bans
109+ offset .addAndGet (CHUNK_SIZE );
110+
111+ // some delay to avoid rate limit.
112+ try {
113+ Thread .sleep (TimeUnit .SECONDS .toMillis (RATE_LIMIT_DELAY_SECONDS ));
114+ } catch (InterruptedException e ) {
115+ throw new RuntimeException (e );
116+ }
117+
118+ return apply (null ); // Recurse to fetch the next chunk
119+ } else {
120+ // We've fetched all bans
121+ LoggingUtil .info ("[BanWarden] Finished syncing total of " + totalPunishments .get () + " punishments from LiteBans." );
122+ return CompletableFuture .completedFuture (null );
123+ }
124+ });
125+ }
126+ });
127+ }
128+
129+ private CompletionStage <List <PunishmentData >> fetchPunishmentChunk (int limit , int offset ) {
130+ return CompletableFuture .supplyAsync (() -> {
131+ List <PunishmentData > punishmentDataList = new ArrayList <>();
132+ String sql = "SELECT id, uuid, ip, reason, banned_by_uuid, banned_by_name, removed_by_uuid, removed_by_name, removed_by_reason, removed_by_date, time, until, template, server_scope, server_origin, silent, ipban, ipban_wildcard, active,'ban'as type FROM litebans_bans UNION ALL SELECT id, uuid, ip, reason, banned_by_uuid, banned_by_name, removed_by_uuid, removed_by_name, removed_by_reason, removed_by_date, time, until, template, server_scope, server_origin, silent, ipban, ipban_wildcard, active,'mute'as type FROM litebans_mutes UNION ALL SELECT id, uuid, ip, reason, banned_by_uuid, banned_by_name, removed_by_uuid, removed_by_name, removed_by_reason, removed_by_date, time, until, template, server_scope, server_origin, silent, ipban, ipban_wildcard, active,'warn'as type FROM litebans_warnings ORDER BY id ASC LIMIT ? OFFSET ?" ;
133+
134+ try (PreparedStatement stmt = Database .get ().prepareStatement (sql )) {
135+ stmt .setInt (1 , limit );
136+ stmt .setInt (2 , offset );
137+ ResultSet rs = stmt .executeQuery ();
138+
139+ while (rs .next ()) {
140+ // Print fetched data.
141+ String s = rs .getString ("id" ) + rs .getString ("uuid" ) + ", " + rs .getString ("reason" ) + ", " + rs .getString ("server_origin" );
142+ System .out .println (s );
143+
144+ PunishmentData data = convertResultSetToData (rs );
145+ punishmentDataList .add (data );
146+ }
147+ } catch (SQLException e ) {
148+ LoggingUtil .error ("[BanWarden] Error fetching punishments from LiteBans: " + e .getMessage ());
149+ }
150+
151+ return punishmentDataList ;
152+ });
153+ }
154+
155+ private PunishmentData convertEntryToData (Entry entry ) {
156+ String type = getBanWardenPunishmentType (entry .getType ()).name ().toLowerCase ();
157+ PunishmentData punishmentData = new PunishmentData ();
158+ punishmentData .plugin_name = BanWardenPluginType .LITEBANS .name ().toLowerCase ();
159+ punishmentData .plugin_punishment_id = String .valueOf (entry .getId ());
160+ punishmentData .type = type ;
161+ punishmentData .start_at = entry .getDateStart ();
162+ punishmentData .end_at = entry .getDateEnd ();
163+ punishmentData .reason = entry .getReason ();
164+ punishmentData .is_active = entry .isActive ();
165+ punishmentData .server_scope = entry .getServerScope ();
166+ punishmentData .origin_server_name = entry .getServerOrigin ();
167+ punishmentData .uuid = entry .getUuid ();
168+ punishmentData .ip_address = entry .getIp ();
169+ punishmentData .is_ipban = entry .getType ().equalsIgnoreCase ("ipban" );
170+ punishmentData .creator_uuid = entry .getExecutorUUID ();
171+ punishmentData .creator_username = entry .getExecutorName ();
172+
173+ punishmentData .removed_at = 0 ; // TODO
174+ punishmentData .remover_uuid = entry .getRemovedByUUID ();
175+ punishmentData .remover_username = entry .getRemovedByName ();
176+
177+ return punishmentData ;
178+ }
179+
180+ private PunishmentData convertResultSetToData (ResultSet rs ) throws SQLException {
181+ PunishmentData punishmentData = new PunishmentData ();
182+ punishmentData .plugin_name = BanWardenPluginType .LITEBANS .name ().toLowerCase ();
183+ punishmentData .plugin_punishment_id = rs .getString ("id" );
184+ punishmentData .type = rs .getString ("type" ).toLowerCase ();
185+ punishmentData .start_at = rs .getLong ("time" );
186+ punishmentData .end_at = rs .getLong ("until" );
187+ punishmentData .reason = rs .getString ("reason" );
188+ punishmentData .is_active = true ;
189+ punishmentData .server_scope = rs .getString ("server_scope" );
190+ punishmentData .uuid = rs .getString ("uuid" );
191+ punishmentData .ip_address = rs .getString ("ip" );
192+ punishmentData .is_ipban = punishmentData .type .equals ("ban" ) && rs .getBoolean ("ipban" );
193+ punishmentData .creator_uuid = rs .getString ("banned_by_uuid" );
194+ punishmentData .creator_username = rs .getString ("banned_by_name" );
195+
196+ return punishmentData ;
197+ }
198+
199+ private BanWardenPunishmentType getBanWardenPunishmentType (String type ) {
200+ return switch (type .toLowerCase ()) {
201+ case "ban" -> BanWardenPunishmentType .BAN ;
202+ case "mute" -> BanWardenPunishmentType .MUTE ;
203+ case "warning" -> BanWardenPunishmentType .WARN ;
204+ case "kick" -> BanWardenPunishmentType .KICK ;
205+ default -> BanWardenPunishmentType .UNKNOWN ;
206+ };
26207 }
27208}
0 commit comments