Make this program extremely advanced and complex. Add max-combinations-length or whatever. and a smart system to auto sort and remove `bad` channels.
Use this channel list to show you what is a valid channel. First, make actual connections and provide a highly advanced algorithm to find the most channels.
[
    "Common",
    "Ganesh",
    "LIVE",
    "ZActivityHistory",
    "ZActivityHistory2",
    "ZActivityHistory3",
    "ZAddCloseReasonAPIPrivate",
    "ZAFlag",
    "ZAIDiff",
    "ZAIDiffMessage",
    "ZAllocateCacheContiguousWithConstraint",
    "ZAllocCallbacks",
    "ZAllocTrackWinQuickFix",
    "ZAnrReporterOnWindowsTesting",
    "ZAssetAccessErrorMessageImprovements",
    "ZAssetCacheInitProd",
    "ZAssetDeliveryV2",
    "ZAssetPreloading",
    "ZAsyncApolloCow",
    "ZAsyncApolloCowExperiment",
    "ZAudioTestsAndExperiments",
    "ZAudioQualityTesting",
    "ZAutoSetup",
    "ZAutoSetup-Alpha",
    "ZAvatarEmotion",
    "ZAvatarPathFinding",
    "ZAvatarRelease",
    "ZAvatarTeam",
    "ZAvatarTeam2",
    "ZBaseRCU",
    "ZBeta",
    "ZBillTest",
    "ZBisect1",
    "ZBisect2",
    "ZBisect3",
    "ZBisect4",
    "ZBisect5",
    "ZBisect6",
    "ZBugfixAccessory-Welds",
    "ZBugfixAssorted-Channel-Test-Changes",
    "ZBugfixBoost-Mutex-Revert",
    "ZBugfixCLI-54676-Test",
    "ZBugfixCLI-55214-Master",
    "ZBugfixQuaternionChannels",
    "ZBugfixSanity-Check",
    "ZBugfixTruss-Crash",
    "ZBuilderFont",
    "ZCanary",
    "ZCanary1",
    "ZCanary2",
    "ZCanary3",
    "ZCanary4",
    "ZCanary5",
    "ZCanary6",
    "ZCanary7",
    "ZCanary8",
    "ZCanary9",
    "ZCanaryApps",
    "ZCanaryTest1",
    "ZCanaryTest2",
    "ZCanaryTest3",
    "ZCanaryTest4",
    "ZCanaryTest5",
    "ZCanaryTest6",
    "ZCandidateFixIC",
    "ZCandidateFixIC2",
    "ZCandidateFixIC3",
    "ZCanidateFixIC3",
    "ZCaptures",
    "ZCheckSendTypeBeforeSetupTimer",
    "ZCheckSendTypeBeforeSetUptimerInHttpPointsReporter",
    "ZChunkExperimentBinary",
    "ZChunkExperimentBinaryControl",
    "ZCLI-92373",
    "ZCLI-92373-2",
    "ZCLI-97809",
    "ZCLI109812",
    "ZCLI111800",
    "ZClientIntegration",
    "ZClientIntegration1",
    "ZClientPresence2",
    "ZClientTokenFromHeader3",
    "ZClientWatcher",
    "ZClockSkew",
    "ZCommonCLFB",
    "ZCompatibilityTelemetryChannelFlagOnly",
    "ZControl",
    "ZConvAICodeRunner",
    "ZCopy_Both",
    "ZCrashHandlerShutdownTesting",
    "ZCrashOnShutdown",
    "ZCreateMRDAllocsReduc",
    "ZCSCTesting",
    "ZCSG4",
    "ZCSPUHotfixTest",
    "ZDeeplinkPrototype",
    "ZDisableMemoryTrackingTest",
    "ZDisableMemoryTrackingTestComparison",
    "ZDMAccessorMigrations",
    "ZDontRerenderForBadTexture",
    "ZDraggerImprovements",
    "ZDummy",
    "ZDummy3",
    "ZDXT",
    "ZEnableZstdForClientSettings",
    "ZExpControl",
    "ZExpControl1",
    "ZExpControl2",
    "ZExpControl3",
    "ZExpControlStandby",
    "ZExpControlTest",
    "ZExpD1",
    "ZExpD256",
    "ZExperienceCoordinator",
    "ZExpR256",
    "ZExpVariantPrivate",
    "ZExpVariantPrivate613",
    "ZExpVariantPublic",
    "ZExpVariantPublic3",
    "ZExpVariantStandby",
    "ZFallThroughCleanup",
    "ZFCCache",
    "ZFCThreadSafe",
    "ZFeature600-Public-URE-Testing",
    "ZFeature610Curl680",
    "ZFeature613Curl860",
    "ZFeature613Curl860-2",
    "ZFeature618Cares",
    "ZFeatureAbstractMetricStorage2",
    "ZFeatureAbstractSessionMetricStorage",
    "ZFeatureAeroChannel",
    "ZFeatureAeroChannel2",
    "ZFeatureAerodynamics",
    "ZFeatureAlwaysStrafing",
    "ZFeatureAlwaysStrafing2",
    "ZFeatureAndroidDeeplink",
    "ZFeatureAndroid-Crash-Fix",
    "ZFeatureAsset-Access-Error-Message-Improvements",
    "ZFeatureAudioDiscovery",
    "ZFeatureAudioMetadata",
    "ZFeatureAutoReconnect",
    "ZFeatureAvatarCreationService",
    "ZFeatureBaseline",
    "ZFeatureBoost_Removal_Test_In_Prod",
    "ZFeatureBootstrapper_Fix",
    "ZFeatureChannel_Test",
    "ZFeatureCharacter-Controller",
    "ZFeatureCLI-88773-Curl-Update",
    "ZFeatureCLI-88773-Curl-Update-2",
    "ZFeatureCLI-88773-Curl-Update-3",
    "ZFeatureCrash-On-Shutdown",
    "ZFeatureDeeplink",
    "ZFeatureDynamicHeadExportTool",
    "ZFeatureEnablingNewCSGApis",
    "ZFeatureFF1",
    "ZFeatureFiber",
    "ZFeatureFMOD-20109",
    "ZFeatureFMOD-20115",
    "ZFeatureFMOD-Recording-Test",
    "ZFeatureGame-Engine-ML",
    "ZFeatureGrowth",
    "ZFeatureHackWeek-2022Group-Teleport-Improvements",
    "ZFeatureHarmony",
    "ZFeatureHon",
    "ZFeatureHSR2CDNPlayTest",
    "ZFeatureHSR2CDNPlayTest2",
    "ZFeatureHumanoidDescriptionInstanceSupport",
    "ZFeatureHyperion-Test",
    "ZFeatureHypTelem616",
    "ZFeatureIdle-Mode",
    "ZFeatureInExperienceCreation",
    "ZFeatureInstance-Parent-Weak-Ptr",
    "ZFeatureInstance-Parent-Weak-Ptr-2",
    "ZFeatureKeyboard-Navigation",
    "ZFeatureLTCG1",
    "ZFeatureLatency_Log",
    "ZFeatureLiveParts",
    "ZFeatureLuaCharacterController",
    "ZFeatureLuaIInline1",
    "ZFeatureLuaObjectInstanceBridgeMergeFix",
    "ZFeatureLuaSM",
    "ZFeatureLUATOOLS-121-rbxpMoonbeamReleaseTest",
    "ZFeatureLua-File-Sync",
    "ZFeatureMarkVisibleBitForUILayout-618",
    "ZFeatureMesh-Compression",
    "ZFeatureModel-Scale",
    "ZFeatureOnboarding",
    "ZFeatureOpenXR",
    "ZFeaturePackagePublishTest",
    "ZFeaturePathEdit",
    "ZFeaturePC-VR",
    "ZFeaturePlane-Handles",
    "ZFeaturePrepare-Shorelines",
    "ZFeaturePrepare-Shorelines2",
    "ZFeaturePrepare-Shorelines3",
    "ZFeaturePrepare-Shorelines4",
    "ZFeaturePresence-Manager",
    "ZFeaturePrototypeOnboarding",
    "ZFeatureQt5.15",
    "ZFeatureQuest_VR_Demo",
    "ZFeatureR15Migrator-Test",
    "ZFeatureRail",
    "ZFeatureRealWorldCommerce",
    "ZFeatureReport-Anything",
    "ZFeatureRetchecksV2",
    "ZFeatureRibbonRefactor",
    "ZFeatureSecret-Store-Test",
    "ZFeatureShorelines",
    "ZFeatureSignal-Reduce-Copies",
    "ZFeatureSignalConcurrency",
    "ZFeatureSignalDoubleLink",
    "ZFeatureSoundworks-Testing",
    "ZFeatureStrafing",
    "ZFeatureStudioNotifications",
    "ZFeatureSubsystemAtomic",
    "ZFeatureSubsystemHttpClient",
    "ZFeatureSupport_Installer",
    "ZFeatureTelemLife",
    "ZFeatureTeleport_Fix",
    "ZFeatureTest-Build",
    "ZFeatureTestDeploy",
    "ZFeatureTestLength",
    "ZFeatureTest_Rename",
    "ZFeatureThreadNamesWindows",
    "ZFeatureUIEdgeExtension",
    "ZFeatureUpgrade-LZ4",
    "ZFeatureUpgrade-libyuv-Bento4",
    "ZFeatureUse-New-RapidJSON-In-Flag-Loading",
    "ZFeatureVRImmersionMode",
    "ZFeatureVR-Follow-Camera",
    "ZFeatureWin64_Client_Deploy_Test",
    "ZFFlagFCFixDestroyClusters",
    "ZFFPContractOff",
    "ZFileWatcherTesting",
    "ZFixDockPanelCrash",
    "ZFixExtraParserMapEntries",
    "ZFlag",
    "ZFlagEditor",
    "ZFlaggedSplitHashUpdateTestingV2",
    "ZFlexLayoutControl",
    "ZFlexLayoutTest2",
    "ZForceConstructionInCreatable",
    "ZFPM",
    "ZFullCache",
    "ZGraphicsControlGroup",
    "ZGraphicsOptimizationModeScalesHighFlag",
    "ZGraphicsOptimizationModeScalesLowFlag",
    "ZGraphicsOptimizationModeScalesMidFlag",
    "ZGraphicsSurfaceGuiRender3DAdornOpt",
    "ZGuiMixinMigrationChannel",
    "ZHack-Group",
    "ZHarmonyFRMFixRunningAverageTestChannel",
    "ZHarmonyFRMTunableV1Binary",
    "ZHarmonyNewEffectModelOff",
    "ZHarmonyNewEffectModelOff638",
    "ZHarmonyNewEffectModelOn",
    "ZHarmonyNewEffectModelOn637",
    "ZHarmonyNewEffectModelOn638",
    "ZHighEnrollmentMetricsTest",
    "ZHighPingTest",
    "ZHumanoidDefaultReplaceUnsafeBlockingLoadInstance",
    "ZHumanoidDescriptionTesting",
    "ZHumanoidPhysics",
    "ZIlya",
    "ZIlyaControl",
    "ZImmersiveAdsDebug",
    "ZIncreaseFileDescriptorLimit",
    "ZInsertServiceReplaceUnsafeBlockingLoadInstance",
    "ZInstanceClusterDeferredMeshRebind",
    "ZInstanceClusterRetryPartInvalidation",
    "ZInstanceGlob",
    "ZInstanceGlob3",
    "ZInstanceGlob-Control",
    "ZIntegration",
    "ZIntegration1",
    "ZIntegration2",
    "ZIntegration3",
    "ZIntegration4",
    "ZIntegration5",
    "ZIntegration6",
    "ZIntegration7",
    "ZIntegration8",
    "ZIntegration9",
    "ZIntegrationTest",
    "ZIntegrationTest1",
    "ZIntegrationTest2",
    "ZIntegrationTest3",
    "ZIntegrationTest4",
    "ZIntegrationTest5",
    "ZJJJ",
    "ZJsonAllocatorChanges",
    "ZKTong-Crash-Hang-Testing",
    "ZKTong-Crash-Hang-Testing-Windows",
    "ZLang",
    "ZLive",
    "ZLive1",
    "ZLive2",
    "ZLive3",
    "ZLiveForBeta",
    "ZLogServiceTest",
    "ZLoom",
    "ZLuaRibbon",
    "ZLuaStartPageSmokeTest",
    "ZLuaTest",
    "ZLuauFileSyncTesting",
    "ZMacArm64",
    "ZManualHookTest",
    "ZManualHookTest5",
    "ZMaterialGenerator",
    "ZMaterialPicker",
    "ZMoreGranularTelemetryProfiling",
    "ZMovementAlpha",
    "ZNativeCodegen2",
    "ZNetworkInspector",
    "ZNewDocking",
    "ZNew-Grid",
    "ZNew-Grid-Desktop",
    "ZNew-Grid-Test",
    "ZNext",
    "ZNoCommonVerbs627",
    "ZNoRupp",
    "ZOverlapTest",
    "ZP2A-2",
    "ZPackageVersionNotes",
    "ZPathFinding-Improvements",
    "ZPerfRegression",
    "ZPerfVerify",
    "ZPhysicsDebug",
    "ZPhysicsDebugSK",
    "ZProject512-Boost-Remove-Mutex-1",
    "ZProject516-Boost-Remove-Mutex-Network",
    "ZProject587-Split-Remote-File",
    "ZProject588-Split-Remote-File",
    "ZProjectAssetDeliveryV2",
    "ZProjectAutoSetup",
    "ZProjectBackupLiveEditingTest",
    "ZProjectELiu",
    "ZProjectEngineStyling",
    "ZProjectEngine-Styling-Demo",
    "ZProjectEngine-Styling",
    "ZProjectGeometryGenerator",
    "ZProjectImmersiveAdsDebug",
    "ZProjectLiveEditingDemo",
    "ZProjectLiveEditingProperty",
    "ZProjectLiveEditingProperty2",
    "ZProjectLoadingScreen",
    "ZProjectLoadingScreenDeployment",
    "ZProjectLoadingScreen2",
    "ZProjectLuaProxyParts",
    "ZProjectMacProtocolHandlerSwitch",
    "ZProjectMacProtocolHandlerSwitchPublic",
    "ZProjectManageCollaborators3",
    "ZProjectModelsAsPackages",
    "ZProjectMovement-Alpha",
    "ZProjectMovement-Beta",
    "ZProjectNetwork-Transport-Split",
    "ZProjectProxyParts",
    "ZProjectQt5159",
    "ZProjectRCCELiu",
    "ZProjectServer-Authority",
    "ZProjectTelemetry-Test",
    "ZProjectTerrainEditorAlpha",
    "ZProjectTerrainEditorOverhaul",
    "ZProjectTerrainSmoothTool",
    "ZProjectUWPUA",
    "ZProjectUpgradeLibPNG",
    "ZProjectUpdate-WebRTC",
    "ZProjectUpdate-WebRTC-Fetch-Content",
    "ZPublic",
    "ZPublicBetaDogFooding2",
    "ZPublicBetaDogFoodingChris1",
    "ZPublicBetaDogFoodingChris2",
    "ZPublicBetaDogFoodingGeneral1",
    "ZPublicBetaDogFoodingGeneral2",
    "ZPublicBetaDogFoodingGeneral3",
    "ZPublicBetaDogFoodingJeffrey1",
    "ZPublicBetaDogFoodingJeffrey3",
    "ZPublicBetaDogFoodingMichael1",
    "ZPublicBetaDogFoodingMichael2",
    "ZPublicBetaDogFoodingRyan1",
    "ZPublicBetaDogFoodingRyan2",
    "ZPublicBetaDogFoodingRyan3",
    "ZPublicBetaDogFoodingTheo1",
    "ZPublicBetaDogFoodingTheo2",
    "ZPublicBetaDogFoodingsIjun1",
    "ZPublicBetaDogFoodingsIjun2",
    "ZPublicHookTest2",
    "ZPublicHookTest4",
    "ZPublicTestingGUIMemoryReduction",
    "ZPureHookTest",
    "ZPureHookTest2",
    "ZPureHookTest3",
    "ZQt",
    "ZQtCanary",
    "ZQtIntegration",
    "ZQTitanStudio",
    "ZQTitanStudioRelease",
    "ZQTitanStudioReleaseHighDpi",
    "ZQTitanStudioReleaseHighDpiTest",
    "ZQTitanStudioReleaseTest",
    "ZQQIU-0903-ST-1",
    "ZQQIU-0903-ST-3",
    "ZQQIU-Channel-Adoption",
    "ZQQIU-Channel-Adoption-1",
    "ZQQIU-Point-V2-Gating-Logic-V1",
    "ZQQIU-Point-V2-Parity-Check-1",
    "ZQQIU-Point-V2-Parity-Check-2",
    "ZQQIU-Point-V2-Parity-Check-3",
    "ZQQIU-Point-V2-Parity-Check-4",
    "ZQQIU-Send-Points-To-V2",
    "ZQQIU-ST-Common-Device-1",
    "ZQQIU-ST-Point-V2-0812",
    "ZQQIU-Telemetry-Tiger-1",
    "ZQQIU-Telemetry-Tiger-2",
    "ZQQIU-V2Point-Dup-Fix",
    "ZQQIU-V2Point-Dup-Fix1",
    "ZQQIU-V2Point-Verification-Fix1",
    "ZQQIU-V2-Point-ClientCrash-1",
    "ZQQIU-V2-Point-PlaceId",
    "ZQQIU-V2-Point-PlaceId-Client",
    "ZRCCCrashHandlerTest",
    "ZRealTimeSessionTrackingReportingMac2",
    "ZReduceFontAssetIdAllocs",
    "ZRegressionTest1",
    "ZRegressionTest2",
    "ZRegressionTest3",
    "ZRegressionTest4",
    "ZRegressionTest10",
    "ZRegressionTest11",
    "ZRegressionTest12",
    "ZRegressionTest13",
    "ZRegressionTest14",
    "ZRegressionTest15",
    "ZRegressionTest16",
    "ZRegressionTest17",
    "ZRegressionTest18",
    "ZRegressionTest19",
    "ZRegressionTest20",
    "ZRegressionTest21",
    "ZRegressionTest22",
    "ZRegressionTest23",
    "ZRegressionTest24",
    "ZRegressionTest25",
    "ZRegressionTest26",
    "ZRegressionTest27",
    "ZRegressionTest28",
    "ZRegressionTest29",
    "ZReleaseVS2019",
    "ZRemoveExternalTextureRef",
    "ZRemoveExternalTextureRef-Control",
    "ZRemoveMTypesetters",
    "ZRenderInvalidateOpt",
    "ZReportEarlyTelemetryData",
    "ZRobusta",
    "ZRupp",
    "ZRuppDebug",
    "ZSATintTest633",
    "ZScopedRefPtrReleaseBug",
    "ZSecretStoreTest",
    "ZSecretUrlEncodeTest",
    "ZSerializerApiTest",
    "ZSessionTrackingRealTimeReportingMac",
    "ZSessionTrackingRealTimeReportingWindows",
    "ZSimLazyIslandUpdateAndRepack",
    "ZSimpleJSONDeprecateStringDefaultHandler",
    "ZSlowerTerrain",
    "ZSmoothClusterFixes",
    "ZSocialTeam",
    "ZSocial-Presence",
    "ZSplitHashUpdateTesting",
    "ZSplitHashUpdateTestingV2",
    "ZStagedRolloutTest1",
    "ZStagedRolloutTest2",
    "ZStaleFlag",
    "ZStaleFlagCleanup",
    "ZStaleFlagControl",
    "ZStandByPrivate",
    "ZSTIntegration",
    "ZStudioInt1",
    "ZStudioInt2",
    "ZStudioInt3",
    "ZStudioInt4",
    "ZStudioInt5",
    "ZStudioInt6",
    "ZStudioInt7",
    "ZStudioInt8",
    "ZTagPopup",
    "ZTagPopupTest",
    "ZTagTest",
    "ZTaskSchedulerMK3OffAndroid",
    "ZTaskSchedulerMK3OnAndroid",
    "ZTelemetryLarge",
    "ZTelemetrySmall",
    "ZTeleport-Migration",
    "ZTempTestDogFoodSession2A",
    "ZTempTestDogFoodSession2B",
    "ZTempTestEnrollmentSubmit1",
    "ZTempTestEnrollmentSubmit2",
    "ZTempTestEnrollmentSubmit3",
    "ZTempTestEnrollmentSubmit5",
    "ZTempTestEnrollmentSubmit6",
    "ZTempTest4",
    "ZTerrain-Validator",
    "ZTerrain-Validator2",
    "ZTerrainGenerationAlpha",
    "ZTerrainGenerationTest",
    "ZTest1",
    "ZTestChannelService",
    "ZTestChannel",
    "ZTestConnectionPreWarmingMac4",
    "ZTesting",
    "ZTestMac2",
    "ZTestMacShaderAllocation",
    "ZTestPose",
    "ZTextureDedup",
    "ZTextureDedup-Control",
    "ZTheod-Test-003",
    "ZTotalBytesInAllocStats",
    "ZUADF",
    "ZUADF2",
    "ZUADFMeshLODRelease",
    "ZUADFMobile",
    "ZUADFRelease",
    "ZUFCTesting",
    "ZUFCTesting-Flags-On",
    "ZUIDragDetector",
    "ZUnifiedHangMonitor",
    "ZUpdateLayoutTelemetryExperiment",
    "ZUpdateLayoutTelemetryExperiment2",
    "ZUpdateLayoutTelemetryExperiment3",
    "ZUserInfoAcquiredLog",
    "ZUserInfoAcquiredTelemetry",
    "ZVariantPrivate1",
    "ZVariantPrivate2",
    "ZViewportFrameEnvMapSupport",
    "ZVisBugChecks",
    "ZVisBugChecks-619",
    "ZVisBugChecks-620",
    "ZVisualizationModes",
    "ZVNG",
    "ZVoice1485DurationLogger",
    "ZVoiceChatCulling",
    "ZVoiceChatMemoryImprovements",
    "ZVoiceCulling",
    "ZVoiceJoinOperationExtendedTimeout",
    "ZVoiceJoinOperationFix",
    "ZVoiceJoinOperationLuaFixFlagOnly",
    "ZVoiceUpsell",
    "ZVoiceUpsell3",
    "ZVS2019",
    "ZWin64_Client_Test",
    "ZWindowsConnectionPreWarmingTest",
    "ZWinInstallerTelemExperiment",
    "ZWinPlayer64",
    "ZXCode13",
    "ZXCode13Release",
    "ZZTempTestEnrollmentSubmit4",
    "Z1DAFlag",
    "Z1WAFlag",
    "Z2WAFlag",
    "Z3WAFlag",
    "Z4WAFlag",
    "Z16Cookie"
]

Don't repeat this list at all.

Provide the full code.

use clap::{Arg, Command};
use indicatif::{ProgressBar, ProgressStyle};
use itertools::Itertools;
use prettytable::{row, Table};
use rayon::prelude::*;
use reqwest::blocking::Client;
use colored::*;
use reqwest::StatusCode;
use retry::{delay::Exponential, retry};
use serde::Serialize;
use std::collections::HashSet;
use std::error::Error;
use std::fs;
use std::io::{self, BufRead};
use std::path::Path;
use std::time::Duration;
use thiserror::Error;
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
use tracing::{debug, error, info};
use tracing_subscriber::fmt::format::FmtSpan;

fn main() -> Result<(), Box<dyn Error>> {
    // Initialize logging
    tracing_subscriber::fmt()
        .with_span_events(FmtSpan::CLOSE) // Log span end events
        .init();

    // Parse command-line arguments
    let matches = Command::new("Roblox Channel Checker")
        .version("1.0")
        .author("Your Name <youremail@example.com>")
        .about("Checks for valid Roblox channels based on wordlist combinations")
        .arg(
            Arg::new("input")
                .short('i')
                .long("input")
                .value_name("FILE")
                .help("Sets a custom input wordlist file"),
        )
        .arg(
            Arg::new("output")
                .short('o')
                .long("output")
                .value_name("FILE")
                .help("Sets an output file to save results in JSON format"),
        )
        .arg(
            Arg::new("concurrency")
                .short('c')
                .long("concurrency")
                .value_name("NUMBER")
                .help("Sets the level of concurrency for HTTP requests")
                .default_value("8"),
        )
        .arg(
            Arg::new("timeout")
                .short('t')
                .long("timeout")
                .value_name("SECONDS")
                .help("Sets the timeout for HTTP requests in seconds")
                .default_value("10"),
        )
        .arg(
            Arg::new("verbose")
                .short('v')
                .help("Increases verbosity level"),
        )
        .arg(
            Arg::new("prefixes")
                .short('p')
                .long("prefixes")
                .value_name("PREFIXES")
                .help("Comma-separated list of prefixes to add to words"),
        )
        .arg(
            Arg::new("suffixes")
                .short('s')
                .long("suffixes")
                .value_name("SUFFIXES")
                .help("Comma-separated list of suffixes to add to words"),
        )
        .arg(
            Arg::new("random-strings")
                .short('r')
                .long("random-strings")
                .value_name("NUMBER")
                .help("Number of random alphanumeric strings to generate and add to the wordlist"),
        )
        .get_matches();

    // Read wordlist from file or stdin
    let wordlist = if let Some(input_path) = matches.get_one::<String>("input") {
        read_wordlist_from_file(input_path)?
    } else {
        info!("Reading wordlist from stdin. Enter words followed by Enter. Press Ctrl+D (Unix) or Ctrl+Z (Windows) to finish:");
        read_wordlist_from_stdin()?
    };

    // Deduplicate wordlist
    let mut unique_wordlist: Vec<String> = wordlist.into_iter().unique().collect();
    unique_wordlist.sort();

    // Wordlist Augmentation
    if let Some(prefixes_str) = matches.get_one::<String>("prefixes") {
        let prefixes: Vec<&str> = prefixes_str.split(',').collect();
        augment_wordlist_with_prefixes(&mut unique_wordlist, &prefixes);
    }

    if let Some(suffixes_str) = matches.get_one::<String>("suffixes") {
        let suffixes: Vec<&str> = suffixes_str.split(',').collect();
        augment_wordlist_with_suffixes(&mut unique_wordlist, &suffixes);
    }

    if let Some(num_random_str) = matches.get_one::<String>("random-strings") {
        let num_random: usize = num_random_str.parse().unwrap_or(0);
        augment_wordlist_with_random_strings(&mut unique_wordlist, num_random);
    }

    if unique_wordlist.is_empty() {
        error!("Wordlist is empty. Please provide at least one word.");
        return Ok(());
    }

    info!("Generating combinations...");
    let combinations = generate_combinations(&unique_wordlist);
    info!("Total combinations generated: {}", combinations.len());

    // Configure HTTP client
    let timeout = matches
        .get_one::<String>("timeout")
        .unwrap()
        .parse::<u64>()
        .unwrap_or(10);
    let client = Client::builder()
        .timeout(Duration::from_secs(timeout))
        .build()?;

    // Setup progress bar
    let pb = ProgressBar::new(combinations.len() as u64);
    pb.set_style(
        ProgressStyle::default_bar()
            .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})")
            .unwrap()
            .progress_chars("#>-"),
    );

    let concurrency = matches
        .get_one::<String>("concurrency")
        .unwrap()
        .parse::<usize>()
        .unwrap_or(8);
    rayon::ThreadPoolBuilder::new()
        .num_threads(concurrency)
        .build_global()
        .unwrap();

    info!("Starting channel checks with concurrency level: {}", concurrency);

    // Process combinations in parallel
    let results: Vec<ChannelInfo> = combinations
        .par_iter()
        .map(|combination| {
            let result = check_channel(&client, combination);
            pb.inc(1);
            result
        })
        .filter_map(|res| res)
        .collect();

    pb.finish_with_message("Channel checks completed.");

    // Display results in table format
    if results.is_empty() {
        info!("No valid channels found.");
    } else {
        let mut table = Table::new();
table.add_row(row![
    "Channel",
    "Roblox.exe",
    "DeployHistory.txt",
    "Mac DeployHistory.txt",
    "ClientSettings",
]);
for info in &results {
    table.add_row(row![
        info.colored_channel,
        info.roblox_exe,
        info.deploy_history,
        info.mac_deploy_history,
        info.client_settings,
    ]);
}
table.printstd();
    }

    // Save results to file if output path is provided
    if let Some(output_path) = matches.get_one::<String>("output") {
        info!("Saving results to {}", output_path);
        save_results_to_file(&results, output_path)?;
    }

    Ok(())
}

// Reads wordlist from a file
fn read_wordlist_from_file<P: AsRef<Path>>(path: P) -> Result<Vec<String>, AppError> {
    info!("Reading wordlist from file: {:?}", path.as_ref());
    let file = fs::File::open(path)?;
    let reader = io::BufReader::new(file);
    let wordlist = reader
        .lines()
        .filter_map(Result::ok)
        .filter(|line| !line.trim().is_empty())
        .collect();
    Ok(wordlist)
}

// Reads wordlist from standard input
fn read_wordlist_from_stdin() -> Result<Vec<String>, AppError> {
    let stdin = io::stdin();
    let wordlist = stdin
        .lock()
        .lines()
        .filter_map(Result::ok)
        .filter(|line| !line.trim().is_empty())
        .collect();
    Ok(wordlist)
}

// Generates combinations of words
fn generate_combinations(wordlist: &[String]) -> HashSet<String> {
    let mut combinations = HashSet::new();
    let max_combination_length = 3; // Adjust as needed

    for length in 1..=max_combination_length {
        for combo in wordlist.iter().permutations(length) {
            let concatenated = combo.into_iter().join("");
            combinations.insert(concatenated);
        }
    }

    combinations
}

// Augments the wordlist with prefixes
fn augment_wordlist_with_prefixes(wordlist: &mut Vec<String>, prefixes: &[&str]) {
    let mut new_words = Vec::new();
    for prefix in prefixes {
        for word in wordlist.iter() {
            new_words.push(format!("{}{}", prefix, word));
        }
    }
    wordlist.append(&mut new_words);
}

// Augments the wordlist with suffixes
fn augment_wordlist_with_suffixes(wordlist: &mut Vec<String>, suffixes: &[&str]) {
    let mut new_words = Vec::new();
    for suffix in suffixes {
        for word in wordlist.iter() {
            new_words.push(format!("{}{}", word, suffix));
        }
    }
    wordlist.append(&mut new_words);
}

// Augments the wordlist with random strings
fn augment_wordlist_with_random_strings(wordlist: &mut Vec<String>, num_strings: usize) {
    let rng = thread_rng();
    for _ in 0..num_strings {
        let random_string: String = rng
            .clone()
            .sample_iter(&Alphanumeric)
            .take(8) // Adjust the length of random strings as needed
            .map(char::from)
            .collect();
        wordlist.push(random_string);
    }
}

// Checks a single channel and returns ChannelInfo if valid
fn check_channel(client: &Client, channel_name: &str) -> Option<ChannelInfo> {
    let base_url = format!("http://setup.rbxcdn.com/channel/z{}", channel_name);
    let endpoints = [
        ("Roblox.exe", format!("{}/Roblox.exe", base_url)),
        ("DeployHistory.txt", format!("{}/DeployHistory.txt", base_url)),
        (
            "Mac DeployHistory.txt",
            format!("{}/mac/DeployHistory.txt", base_url),
        ),
        (
            "ClientSettings",
            format!(
                "http://clientsettings.roblox.com/v2/settings/application/RCCBootstrapper/bucket/z{}",
                channel_name
            ),
        ),
    ];

    let mut results = vec![];

    for (name, url) in &endpoints {
        let result = retry(Exponential::from_millis(500).take(3), || {
            debug!("Checking {} at {}", name, url);
            match client.get(url).send() {
                // Use GET instead of HEAD to get the response body
                Ok(response) => {
                    if response.status() == StatusCode::OK {
                        if *name == "ClientSettings" {
                            // Check ClientSettings response body
                            let body = response.text().unwrap_or_default();
                            Ok(!body.contains(r#"{"applicationSettings":null}"#)) // Valid if not null
                        } else {
                            Ok(true) // Other endpoints are valid if status is OK
                        }
                    } else {
                        Ok(false)
                    }
                }
                Err(e) => {
                    error!("Error checking {}: {}", url, e);
                    Err(e)
                }
            }
        })
        .unwrap_or(false);
        results.push(result);
    }

    if results[0] {
        Some(ChannelInfo {
            colored_channel: color_code_channel(channel_name),
            original_channel: channel_name.to_string(),
            roblox_exe: results[0],
            deploy_history: results[1],
            mac_deploy_history: results[2],
            client_settings: results[3],
        })
    } else {
        None
    }
}

fn color_code_channel(channel: &str) -> ColoredString {
    if channel.contains("feature") || channel.contains("project") || channel.contains("bugfix") {
        channel.bold().blue()
    }
    else {
        channel.red()
    }
}
// Saves results to a JSON file
fn save_results_to_file(results: &[ChannelInfo], path: &str) -> Result<(), AppError> {
    let json = serde_json::to_string_pretty(results)?;
    fs::write(path, json)?;
    Ok(())
}

#[derive(Debug, Serialize)]
struct ChannelInfo {
    #[serde(skip_serializing)]
    colored_channel: ColoredString,
    #[serde(rename = "channel")]
    original_channel: String,
    roblox_exe: bool,
    deploy_history: bool,
    mac_deploy_history: bool,
    client_settings: bool,
}

#[derive(Debug, Error)]
enum AppError {
    #[error("IO error occurred: {0}")]
    Io(#[from] io::Error),
    #[error("HTTP request error: {0}")]
    Http(#[from] reqwest::Error),
    #[error("Serialization error: {0}")]
    Serde(#[from] serde_json::Error),
}