Code
Code
</div>
<div class="col-md-7 col-lg-8"> <!-- Adjusted columns -->
<!-- Log Card -->
<div class="card">
<div class="card-header">Activity Log</div>
<div class="card-body p-0"> <!-- Remove padding to
let log fill it -->
<div class="log"></div> <!-- Log content will
go here -->
</div>
<div class="card-footer text-center">
<button title="Clear Log" type="submit"
name="clear" class="btn btn-sm btn-secondary"><i class="fa fa-close"></i> Clear
Log</button> <!-- Secondary color for clear -->
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="settings" role="tabpanel" aria-
labelledby="profile-tab">
<div class="card">
<div class="card-header">Tool Settings</div>
<div class="card-body">
<div class="row">
<div class="col-md-6 mb-3 mb-md-0"> <!-- Add
bottom margin on small screens -->
<h5>Behavior Options</h5>
<div class="custom-control custom-switch mb-
2">
<input class="custom-control-input"
type="checkbox" id="prison_all">
<label class="custom-control-label"
for="prison_all">Jail everyone (Ignore lists)</label>
</div>
<div class="custom-control custom-switch mb-
2">
<input class="custom-control-input"
type="checkbox" id="user_part" checked>
<label class="custom-control-label"
for="user_part">Disconnect if target leaves planet</label>
</div>
<div class="custom-control custom-switch mb-
2">
<input class="custom-control-input"
type="checkbox" id="timeout_3_sec" checked>
<label class="custom-control-label"
for="timeout_3_sec">Disconnect on 3-sec jailing timeout</label>
</div>
<div class="custom-control custom-switch d-
none"> <!-- Kept hidden -->
<input class="custom-control-input"
type="checkbox" id="join_user_not_blacklist">
<label class="custom-control-label"
for="join_user_not_blacklist">Disconnect if non-blacklisted user joins</label>
</div>
<div class="custom-control custom-switch mb-
2">
<input class="custom-control-input"
type="checkbox" id="disconnect_action">
<label class="custom-control-label"
for="disconnect_action">Disconnect immediately after sending jail command</label>
</div>
<div class="custom-control custom-switch mb-
2">
<input class="custom-control-input"
type="checkbox" id="reconnect">
<label class="custom-control-label"
for="reconnect">Enable Auto-Reconnect</label>
</div>
<div class="custom-control custom-switch mb-
2">
<input class="custom-control-input"
type="checkbox" id="remove">
<label class="custom-control-label"
for="remove">Stand on target user</label>
</div>
<div class="custom-control custom-switch mb-
2">
<input class="custom-control-input"
type="checkbox" id="prison_and_off" checked>
<label class="custom-control-label"
for="prison_and_off">Disconnect after successful jail confirmation</label>
</div>
<div class="custom-control custom-switch mb-
2">
<input class="custom-control-input"
type="checkbox" id="re-fly-join">
<label class="custom-control-label"
for="re-fly-join">Re-fly to planet after jailing</label>
</div>
<div class="custom-control custom-switch d-
none"> <!-- Kept hidden/disabled -->
<input disabled class="custom-control-
input" type="checkbox" id="authority">
<label class="custom-control-label"
for="authority">Check authority (Emperor check - Attack only)</label>
</div>
<div class="custom-control custom-switch d-
none"> <!-- Kept hidden/disabled -->
<input disabled class="custom-control-
input" type="checkbox" id="not_prison_newcomers">
<label class="custom-control-label"
for="not_prison_newcomers">Ignore users below 'Dad' authority</label>
</div>
</div>
<div class="col-md-6">
<h5>Timings (milliseconds)</h5>
<div class="mb-3">
<label class="form-label">Reconnect
Interval:</label>
<input type="number" name="timer-
reconnect" class="form-control form-control-sm" value="10200">
</div>
<hr style="border-top: 1px solid #445;"> <!--
Darker HR -->
<div class="mb-3">
<label class="form-label">Attack Interval
(min/max/adjust):</label>
<div class="custom-control custom-switch
custom-switch-sm mb-2">
<input class="custom-control-input"
type="checkbox" id="pm-tm-a">
<label class="custom-control-label
small" for="pm-tm-a">Enable Auto-Adjust</label>
</div>
<div class="row g-2">
<div class="col">
<label class="small form-label mb-
1">Min</label>
<input type="number" name="t-a"
class="form-control form-control-sm" value="1700">
</div>
<div class="col">
<label class="small form-label
mb-1">Max</label>
<input type="number" name="max-t-
a" class="form-control form-control-sm" value="2000">
</div>
<div class="col">
<label class="small form-label
mb-1">+/-</label>
<input type="number" name="pm-t-a"
class="form-control form-control-sm" value="5">
</div>
</div>
</div>
<hr style="border-top: 1px solid #445;">
<div class="mb-3">
<label class="form-label">Defense Interval
(min/max/adjust):</label>
<div class="custom-control custom-switch
custom-switch-sm mb-2">
<input class="custom-control-input"
type="checkbox" id="pm-tm-z">
<label class="custom-control-label
small" for="pm-tm-z">Enable Auto-Adjust</label>
</div>
<div class="row g-2">
<div class="col">
<label class="small form-label mb-
1">Min</label>
<input type="number" name="t-z"
class="form-control form-control-sm" value="1600">
</div>
<div class="col">
<label class="small form-label
mb-1">Max</label>
<input type="number" name="max-t-
z" class="form-control form-control-sm" value="1600">
</div>
<div class="col">
<label class="small form-label
mb-1">+/-</label>
<input type="number" name="pm-t-z"
class="form-control form-control-sm" value="5">
</div>
</div>
</div>
<hr style="border-top: 1px solid #445;">
<div class="mt-3">
<input type="submit" name="set_timeout"
class="btn btn-sm btn-info" value="Determine Interval from Ping">
</div>
</div>
</div>
</div> <!-- End card-body -->
</div> <!-- End card -->
</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-
labelledby="profile-tab">
<div class="card">
<div class="card-header">Blacklists</div>
<div class="card-body">
<p class="text-muted small mb-3">Users or clans listed
here will be targeted for jailing (unless 'Jail everyone' is active). Enter one
item per line or separate by spaces.</p>
<div class="row">
<div class="col-md-6 mb-3 mb-md-0">
<div class="form-group">
<label for="black_clan" class="form-
label">Blacklisted Clans:</label>
<textarea class="form-control form-
control-sm" name="black_clan" id="black_clan" rows="10"
placeholder="EnemyClan1 Bad Clan 2"></textarea>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="black_nick" class="form-
label">Blacklisted Nicks:</label>
<textarea class="form-control form-
control-sm" name="black_nick" id="black_nick" rows="10"
placeholder="BadUser1 Target Name 2"></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-
labelledby="contact-tab">
<div class="card">
<div class="card-header">Whitelists</div>
<div class="card-body">
<p class="text-muted small mb-3">Users or clans listed
here will *never* be targeted for jailing, even if 'Jail everyone' is active. Enter
one item per line or separate by spaces.</p>
<div class="row">
<div class="col-md-6 mb-3 mb-md-0">
<div class="form-group">
<label for="white_clan" class="form-
label">Whitelisted Clans:</label>
<textarea class="form-control form-
control-sm" name="white_clan" id="white_clan" rows="10"
placeholder="FriendlyClan1 Ally Clan 2"></textarea>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="white_nick" class="form-
label">Whitelisted Nicks:</label>
<textarea class="form-control form-
control-sm" name="white_nick" id="white_nick" rows="10"
placeholder="GoodUser1 Friend Nick 2"></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
</div> <!-- End tab-content -->
</div>
<!-- Hidden original section - kept for reference or potential future use
-->
<div class="row no-gutters d-none">
<div class="col-sm">
<div class="m-3">
<div class="">
<div class="form-group">
<label for="recovers">Codes:</label>
<input class="form-control form-control-sm"
name="recovers" id="recovers">
</div>
</div>
<div class="mt-1 mb-1">
<div class="form-group">
<label for="count_message">Log message count:</label>
<input type="text" name="count_message"
id="count_message" class="form-control form-control-sm" value="20" style="width:
70px">
</div>
</div>
<div class="mt-1 mb-1">
<div class="form-group">
<label for="main_join">Default start planet:</label>
<input type="text" name="main_join" id="main_join"
class="form-control form-control-sm" value="" style="max-width: 140px"
placeholder="main">
</div>
</div>
<input type="submit" name="check" class="btn btn-sm btn-info"
value="Start">
<input type="submit" name="stop" class="btn btn-sm btn-info"
value="Stop">
<input type="submit" name="reset" class="btn btn-sm btn-info"
value="Reset">
</div>
</div>
<div class="col-sm">
<div class="m-3">
<div class="">
<div>Log:</div>
<div class="log" style="height: 200px; overflow-y: auto;
border: #8c929a 1px solid; border-radius: .2rem;"></div>
<button title="Update Log" type="submit" name="check"
class="btn btn-sm btn-info mt-2"><i style="color: white!important;" class="fa fa-
refresh"></i></button>
<button title="Clear Log" type="submit" name="clear"
class="btn btn-sm btn-info mt-2"><i style="color: white!important;" class="fa fa-
close"></i></button>
</div>
</div>
</div>
</div>
<!-- End Hidden Section -->
<script>
// --- Helper Functions (from original) ---
[Link] = function (){ if([Link])
[Link](this); };
[Link] = function() {
return [Link](/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
};
function getRecoveryCodes() {
const stored = [Link](LS_RECOVERY_CODES);
try {
return stored ? [Link](stored) : [];
} catch (e) {
[Link]("Error parsing recovery codes from localStorage",
e);
return [];
}
}
function saveRecoveryCodes(codes) {
[Link](LS_RECOVERY_CODES, [Link](codes));
}
function populateRecoverySelect() {
const codes = getRecoveryCodes();
const selectedCodeValue = [Link](LS_SELECTED_CODE);
[Link] = ''; // Clear existing options
if ([Link] === 0) {
[Link] = '<option value="">-- No codes saved
--</option>';
[Link] = true;
[Link] = true;
} else {
[Link] = false;
[Link] = false;
[Link](code => {
const displayCode = [Link] > 15 ? [Link](0, 8)
+ '...' + [Link]([Link] - 4) : code;
const option = [Link]('option');
[Link] = code;
[Link] = displayCode;
if (code === selectedCodeValue) {
[Link] = true;
}
[Link](option);
});
}
}
[Link]('click', () => {
const newCode = [Link]();
if (!newCode) {
[Link]({ title: 'Error', text: 'Recovery code cannot be
empty.', icon: 'warning', background: '#2a2a3a', color: '#eee'});
return;
}
const codes = getRecoveryCodes();
if ([Link](newCode)) {
[Link]({ title: 'Info', text: 'This recovery code is already
saved.', icon: 'info', background: '#2a2a3a', color: '#eee'});
[Link] = newCode;
[Link](LS_SELECTED_CODE, newCode);
return;
}
[Link](newCode);
saveRecoveryCodes(codes);
populateRecoverySelect();
[Link] = newCode;
[Link](LS_SELECTED_CODE, newCode);
[Link] = '';
add_log(`Added new recovery code.`);
});
[Link]('click', () => {
const selectedCodeValue = [Link];
if (!selectedCodeValue) {
[Link]({ title: 'Error', text: 'No code selected to
remove.', icon: 'warning', background: '#2a2a3a', color: '#eee'});
return;
}
let codes = getRecoveryCodes();
codes = [Link](code => code !== selectedCodeValue);
saveRecoveryCodes(codes);
if ([Link](LS_SELECTED_CODE) === selectedCodeValue) {
[Link](LS_SELECTED_CODE);
}
populateRecoverySelect();
add_log(`Removed selected recovery code.`);
if([Link] > 0 &&
[Link][0].value) {
[Link] = 0;
[Link](LS_SELECTED_CODE, [Link]);
} else {
[Link](LS_SELECTED_CODE);
}
});
[Link]('change', () => {
if([Link]) {
[Link](LS_SELECTED_CODE, [Link]);
} else {
[Link](LS_SELECTED_CODE);
}
});
[Link]("[name=t-a]").value = suggestedAttack;
[Link]("[name=t-z]").value = suggestedDefense;
add_log(`Suggested Minimum Intervals - Attack: $
{suggestedAttack}ms, Defense: ${suggestedDefense}ms`);
// Load checkboxes
$('#settings input[type="checkbox"]').each(function() {
const key = LS_SETTINGS_PREFIX + $(this).attr('id');
const value = [Link](key);
if (value !== null) {
$(this).prop('checked', value === 'true');
} else {
// Set default based on initial HTML 'checked' attribute if
no value saved
$(this).prop('checked', $(this).is('[checked]'));
}
});
function saveSetting(element) {
const id = $(element).attr('id');
const name = $(element).attr('name');
let key;
let value;
if ($(element).is(':checkbox')) {
key = LS_SETTINGS_PREFIX + id;
value = $(element).prop('checked');
} else if ($(element).is('textarea')) {
key = LS_SETTINGS_PREFIX + id; // Use ID for textareas
value = $(element).val();
} else if ($(element).attr('type') === 'text' || $
(element).attr('type') === 'number') {
key = LS_SETTINGS_PREFIX + name; // Use name for text/number
inputs
value = $(element).val();
} else if ([Link] === 'join') { // Specific handling for #join
input
key = LS_JOIN_PLANET;
value = $(element).val();
} else {
return; // Don't save if type is unknown
}
[Link](key, value);
}
});
// --- End Load/Save Settings ---
let timeout = 0;
let isAttack = (type === 1);
if(isAttack) {
type_prison = "a";
// Use internal timer if set and auto-adjust enabled, otherwise
read from input
timeout = ($('#pm-tm-a').prop('checked') && timer_a > 0) ?
timer_a : parseInt($('[name=t-a]').val() || "1700");
} else {
type_prison = "z";
timeout = ($('#pm-tm-z').prop('checked') && timer_z > 0) ?
timer_z : parseInt($('[name=t-z]').val() || "1600");
}
let targetsFound = 0;
for (let i=0; i < [Link]; i++){
const user = users[i];
if (!user || typeof [Link] === 'undefined') continue; // Skip
invalid user data
if(parseInt([Link]) === [Link]) continue; // Skip self
if (is_action([Link])) continue; // Skip if already processing
if (shouldJail) {
targetsFound++;
let currentAction = { id: [Link], nick: [Link] };
add_log(`Scheduling ${isAttack ? 'attack' : 'defense'} jail
for <b>${[Link]}</b> [${[Link]}] in ${timeout}ms`);
[Link] = setTimeout(function (){
if (is_user_list([Link])) { // Re-check
presence
prison([Link]);
} else {
add_log(`User ${[Link]} [$
{[Link]}] left before action.`);
remove_action([Link]);
}
}, timeout);
[Link](currentAction);
if($('#user_part').prop('checked')){
// Check if this user was the *only* target we were waiting
for
const isOnlyTarget = ; //
Check if any *other* actions exist
if (isOnlyTarget) {
add_log("Disconnecting because the only target left (as
configured).");
set_offline();
} else {
add_log(`Target ${nick} left, but other actions
pending.`);
}
}
}
if($('#disconnect_action').prop('checked')) {
add_log("Disconnecting immediately after sending action
(as configured).");
set_offline();
}
} else {
prison_not_found(id); // User left between schedule and
fire
}
} catch (e){
add_log(`<span style='color: red;'>Error during jail attempt
for ${id}: ${e}</span>`);
[Link]("Jail error:", e); remove_action(id);
}
}
if (shouldJail) {
let timeout = ($('#pm-tm-z').prop('checked') && timer_z >
0) ? timer_z : parseInt( $('[name=t-z]').val() || "1600" );
type_prison = "z"; // Defense mode
if (!is_action([Link])) { // Avoid queuing multiple actions
for the same join
let currentAction = { id: [Link], nick: [Link] };
add_log(`Scheduling defense jail for <b>${[Link]}</b>
[${[Link]}] in ${timeout}ms`);
[Link] = setTimeout(function (){
if (is_user_list([Link]))
{ prison([Link]); }
else { add_log(`Joined user ${[Link]}
left before defense.`); remove_action([Link]); }
}, timeout);
[Link](currentAction);
}
}
} catch(e) { add_log("<span style='color: red;'>Error processing
user join.</span>"); [Link]("Error in join:", e, "Data:", data); }
}
// If the user who left was the *only* target we had an action
for
if($('#user_part').prop('checked') && hadAction &&
[Link] === 0) {
add_log(`Target ${nick} left - disconnecting (as
configured).`);
set_offline();
}
} catch(e) { add_log("<span style='color: red;'>Error processing
user leave.</span>"); [Link]("Error in remove_user:", e, "UserID:", userID);
}
}
[Link](o);
} catch (err) {
[Link]("Error parsing user chunk starting near
index:", s, err, "Data snippet:", [Link](s, s + 10));
// Attempt to recover by moving to the next element,
might cause cascade errors.
s++;
// break; // Alternative: Stop parsing entirely on error
}
}
users = resultUsers; // Update global users array
// [Link]("Final parsed user list:", users); // Debug
}
try {
if (typeof GALAXY !== 'undefined' && [Link]()) {
add_log("Closing existing connection before
reconnecting...");
[Link]();
// Wait a tiny bit before reconnecting if needed, though
onClose should handle state reset.
}
me = {}; users_clear(); // Reset state immediately
// Initiate connection
[Link]([Link]());
} catch (e) {
add_log(`<span style='color: red;'>Fatal Error during
connection setup: ${e}</span>`);
[Link]("Connect function error:", e); running = false;
off();
}
}
$(document).on("click","[name=stop]",function (e){
[Link]();
if (!running) { add_log("Already stopped."); return; }
add_log("Stopping requested by user...");
off(); // Use the force stop function
})
$(document).on("click","[name=go_join]",function (e){
[Link]();
if (!running || (typeof GALAXY === 'undefined') || !
[Link]()) {
add_log("<span style='color: orange;'>Cannot fly: Not
connected.</span>");
[Link]({title: 'Error', text: 'You must be connected to fly
to a planet.', icon: 'warning', background: '#2a2a3a', color: '#eee'}); return;
}
try{
let targetPlanet = $('#join').val().trim();
if (!targetPlanet) { add_log("<span style='color:
orange;'>Cannot fly: Planet name is empty.</span>"); return; }
main_join = targetPlanet; // Update the target planet
add_log(`Attempting to fly to planet: ${main_join}`);
[Link]("JOIN "+main_join);
users_clear(); // Clear state immediately on attempting to fly
}catch (e){ add_log(`<span style='color: red;'>Error trying to fly:
${e}</span>`); [Link]("Fly error:", e); }
})
</script>
</div>
</div>