+
@@ -277,14 +322,18 @@
checkIpLimitServiceStatus();
- const usernameRegex = /^[a-zA-Z0-9]+$/;
+ const usernameRegex = /^[a-zA-Z0-9_]+$/;
function validateUsername(username, errorElementId) {
- const isValid = usernameRegex.test(username);
const errorElement = $("#" + errorElementId);
+ if (!username) {
+ errorElement.text("");
+ return false;
+ }
+ const isValid = usernameRegex.test(username);
if (!isValid) {
- errorElement.text("Usernames can only contain letters and numbers.");
+ errorElement.text("Usernames can only contain letters, numbers, and underscores.");
return false;
} else {
errorElement.text("");
@@ -297,17 +346,21 @@
$("#addUsername").on("input", function () {
const username = $(this).val();
const isValid = validateUsername(username, "addUsernameError");
- $("#addUserForm button[type='submit']").prop("disabled", !isValid);
$("#addSubmitButton").prop("disabled", !isValid);
});
+
+ $("#addBulkPrefix").on("input", function () {
+ const prefix = $(this).val();
+ const isValid = validateUsername(prefix, "addBulkPrefixError");
+ $("#addBulkSubmitButton").prop("disabled", !isValid);
+ });
$("#editUsername").on("input", function () {
const username = $(this).val();
const isValid = validateUsername(username, "editUsernameError");
- $("#editUserForm button[type='submit']").prop("disabled", !isValid);
$("#editSubmitButton").prop("disabled", !isValid);
});
-
+
$(".filter-button").on("click", function () {
const filter = $(this).data("filter");
@@ -465,6 +518,54 @@
}
});
});
+
+ $("#addBulkUsersForm").on("submit", function(e) {
+ e.preventDefault();
+ if (!validateUsername($("#addBulkPrefix").val(), "addBulkPrefixError")) {
+ $("#addBulkSubmitButton").prop("disabled", true);
+ return;
+ }
+ $("#addBulkSubmitButton").prop("disabled", true);
+
+ const jsonData = {
+ prefix: $("#addBulkPrefix").val(),
+ count: parseInt($("#addBulkCount").val()),
+ start_number: parseInt($("#addBulkStartNumber").val()),
+ traffic_gb: parseFloat($("#addBulkTrafficLimit").val()),
+ expiration_days: parseInt($("#addBulkExpirationDays").val()),
+ unlimited: $("#addBulkUnlimited").is(":checked")
+ };
+
+ $.ajax({
+ url: "{{ url_for('add_bulk_users_api') }}",
+ method: "POST",
+ contentType: "application/json",
+ data: JSON.stringify(jsonData),
+ success: function(response) {
+ Swal.fire({
+ title: "Success!",
+ text: response.detail || "Bulk user creation started successfully!",
+ icon: "success",
+ confirmButtonText: "OK",
+ }).then(() => {
+ location.reload();
+ });
+ },
+ error: function(jqXHR) {
+ let errorMessage = "An error occurred during bulk user creation.";
+ if (jqXHR.responseJSON && jqXHR.responseJSON.detail) {
+ errorMessage = jqXHR.responseJSON.detail;
+ }
+ Swal.fire({
+ title: "Error!",
+ text: errorMessage,
+ icon: "error",
+ confirmButtonText: "OK",
+ });
+ $("#addBulkSubmitButton").prop("disabled", false);
+ }
+ });
+ });
$(document).on("click", ".edit-user", function () {
const username = $(this).data("user");
@@ -795,10 +896,17 @@
$('#addUserModal').on('show.bs.modal', function (event) {
$('#addUserForm')[0].reset();
+ $('#addBulkUsersForm')[0].reset();
$('#addUsernameError').text('');
+ $('#addBulkPrefixError').text('');
$('#addTrafficLimit').val('30');
$('#addExpirationDays').val('30');
+ $('#addBulkTrafficLimit').val('30');
+ $('#addBulkExpirationDays').val('30');
+ $('#addBulkStartNumber').val('1');
$('#addSubmitButton').prop('disabled', true);
+ $('#addBulkSubmitButton').prop('disabled', true);
+ $('#addUserModal a[data-toggle="tab"]').first().tab('show');
});
$("#searchButton").on("click", filterUsers);
@@ -806,4 +914,4 @@
});
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/install.sh b/install.sh
index bf6a652..f7a2cef 100644
--- a/install.sh
+++ b/install.sh
@@ -123,7 +123,7 @@ clone_repository() {
fi
fi
- if git clone https://github.com/ReturnFI/Blitz /etc/hysteria &> /dev/null; then
+ if git clone -b beta https://github.com/ReturnFI/Blitz /etc/hysteria &> /dev/null; then
log_success "Repository cloned successfully"
else
log_error "Failed to clone repository"