you as robot now then try calculate strictly your CRC visible to you of this copy-paste script. CRC = lines,words,character count in total:


"""

import sys
import json
import re
import socket
import time
import netifaces
from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
    QPushButton, QPlainTextEdit, QListWidget, QScrollArea, 
    QTableWidget, QTableWidgetItem, QToolButton, QMessageBox
)
from PyQt5.QtCore import Qt, QThread, pyqtSignal


class BridgeChecker(QWidget):
    CONFIG_FILE = "bridges.cfg"
    GEOIP_FILE = "geoip"

    def __init__(self):
        super().__init__()
        self.geoip_data = self.load_geoip_data()
        self.country_buttons = {}
        self.selected_countries = set()
        self.initUI()
        self.load_settings()

        self.previous_results = []  
        self.all_results = {}  

    def load_geoip_data(self):
        geoip_ranges = {}
        try:
            with open(self.GEOIP_FILE, 'r') as f:
                for line in f:
                    line = line.strip()
                    if line and not line.startswith('#'):
                        parts = line.split(',')
                        country_code = parts[2][:2]
                        if country_code not in geoip_ranges:
                            geoip_ranges[country_code] = []
                        geoip_ranges[country_code].append((int(parts[0]), int(parts[1])))
        except IOError:
            print("Error: GeoIP file not found.")
        return geoip_ranges

    def initUI(self):
        self.setWindowTitle('Tor Bridge Connectivity Checker')
        main_layout = QVBoxLayout(self)

        iface_layout = QHBoxLayout()
        iface_label = QLabel("Network Interface:")
        self.iface_selector = QPlainTextEdit(self)
        self.iface_selector.setReadOnly(True)
        self.iface_selector.setMaximumHeight(30)
        interfaces, _ = self.get_network_interfaces()
        self.iface_selector.setPlainText(', '.join(interfaces))
        iface_layout.addWidget(iface_label)
        iface_layout.addWidget(self.iface_selector)
        main_layout.addLayout(iface_layout)

        bridge_input_label = QLabel("Bridges to Check:")
        self.bridge_input = QPlainTextEdit(self)
        main_layout.addWidget(bridge_input_label)
        main_layout.addWidget(self.bridge_input)

        check_button = QPushButton('Check Bridges', self)
        check_button.clicked.connect(self.start_bridge_check)
        main_layout.addWidget(check_button)

        filter_country_label = QLabel("Select Countries to Exclude:")
        main_layout.addWidget(filter_country_label)

        country_button_layout = QHBoxLayout()
        for country_code in sorted(self.geoip_data.keys()):
            button = QPushButton(country_code)
            button.setFixedSize(30, 30)
            button.setCheckable(True)
            button.setStyleSheet("background-color: #1c1c1c; color: #ffffff;")
            button.clicked.connect(lambda checked, code=country_code: self.toggle_country_selection(code, checked))
            self.country_buttons[country_code] = button
            country_button_layout.addWidget(button)

        select_all_button = QPushButton('Select All', self)
        select_all_button.clicked.connect(self.select_all_countries)
        country_button_layout.addWidget(select_all_button)

        deselect_all_button = QPushButton('Deselect All', self)
        deselect_all_button.clicked.connect(self.deselect_all_countries)
        country_button_layout.addWidget(deselect_all_button)

        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)  
        scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        country_widget = QWidget()
        country_widget.setLayout(country_button_layout)
        scroll_area.setWidget(country_widget)
        scroll_area.setMaximumHeight(50) 
        main_layout.addWidget(scroll_area)

        filter_layout = QHBoxLayout()

        self.first_octet_input = QPlainTextEdit(self)
        self.first_octet_input.setPlaceholderText("Enter clone# or filter (e.g. 192.168.0.0/16)")
        self.first_octet_input.setMaximumHeight(30)
        filter_layout.addWidget(self.first_octet_input)

        help_button = QToolButton(self)
        help_button.setText("?")
        help_button.setStyleSheet("background-color: #007ACC; color: white;")
        help_button.clicked.connect(self.show_help)
        filter_layout.addWidget(help_button)

        main_layout.addLayout(filter_layout)

        self.active_filters_list = QListWidget(self)
        main_layout.addWidget(QLabel("Filters:"))
        main_layout.addWidget(self.active_filters_list)

        add_filter_button = QPushButton('Add Filter', self)
        add_filter_button.clicked.connect(self.add_filter)
        main_layout.addWidget(add_filter_button)

        remove_filter_button = QPushButton('Remove Selected Filter', self)
        remove_filter_button.clicked.connect(self.remove_filter)
        main_layout.addWidget(remove_filter_button)

        self.results_label = QLabel("Results:")
        main_layout.addWidget(self.results_label)

        self.results_table = QTableWidget(self)
        self.results_table.setColumnCount(3)
        self.results_table.setHorizontalHeaderLabels(['ccTLD', 'RTT (ms)', 'Bridge'])
        self.results_table.horizontalHeader().setMinimumSectionSize(100)
        self.results_table.setColumnWidth(0, 100)  
        self.results_table.setColumnWidth(1, 100)  
        self.results_table.horizontalHeader().setStretchLastSection(True)  
        self.results_table.horizontalHeader().setSectionsClickable(True)
        self.results_table.horizontalHeader().sectionClicked.connect(self.sort_results)
        main_layout.addWidget(self.results_table)

        filter_results_button = QPushButton('Filter Results', self)
        filter_results_button.clicked.connect(self.filter_results)
        main_layout.addWidget(filter_results_button)

        copy_all_button = QPushButton('Copy All', self)
        copy_all_button.clicked.connect(self.copy_all_to_clipboard)
        main_layout.addWidget(copy_all_button)

        console_label = QLabel("Console Log:")
        self.console_display = QPlainTextEdit(self)
        self.console_display.setReadOnly(True)
        self.console_display.setStyleSheet("background-color: black; color: white;")
        main_layout.addWidget(console_label)
        main_layout.addWidget(self.console_display)

        self.setStyleSheet("""
            QWidget {
                background-color: #121212;
                color: #E0E0E0;
            }
            QPlainTextEdit, QListWidget, QTableWidget {
                background-color: #1E1E1E;
                color: #FFFFFF;
            }
            QPushButton {
                background-color: #333333;
                border: 1px solid #666666;
                color: #E0E0E0;
            }
            QPushButton:hover {
                background-color: #555555;
            }
            QPushButton:pressed {
                background-color: #777777;
            }
            QTableWidget::item {
                background-color: #1E1E1E;
            }
            QPushButton:checked {
                background-color: #007ACC;
                color: #FFFFFF;
            }
        """)

    def deselect_all_countries(self):
        for button in self.country_buttons.values():
            button.setChecked(False)
            button.setStyleSheet("background-color: #1c1c1c; color: #ffffff;")
        self.selected_countries.clear()

    def select_all_countries(self):
        for button in self.country_buttons.values():
            button.setChecked(True)
            button.setStyleSheet("background-color: #007ACC; color: #ffffff;")
            self.selected_countries.add(button.text())

    def toggle_country_selection(self, country_code, checked):
        button = self.country_buttons[country_code]
        if checked:
            button.setStyleSheet("background-color: #007ACC; color: #ffffff;")
            self.selected_countries.add(country_code)
        else:
            button.setStyleSheet("background-color: #1c1c1c; color: #ffffff;")
            self.selected_countries.remove(country_code)

    def get_network_interfaces(self):
        interfaces = netifaces.interfaces()
        try:
            default_gateway = netifaces.gateways()['default'][netifaces.AF_INET][1]
        except (KeyError, TypeError):
            default_gateway = interfaces[0] if interfaces else ''
        return interfaces, default_gateway

    def update_console(self, message):
        self.console_display.appendPlainText(message)

    def start_bridge_check(self):
        raw_bridge_data = self.bridge_input.toPlainText()
        cleaned_bridge_data = self.clean_input_bridge_data(raw_bridge_data)

        if not cleaned_bridge_data.strip():
            self.update_console("No bridges to check.")
            return

        # Log total number of bridges to check
        total_bridges = len(cleaned_bridge_data.splitlines())
        self.update_console(f"Total bridges entered: {total_bridges}")

        omitted_bridges = self.get_omitted_bridges(cleaned_bridge_data)

        if len(omitted_bridges) == 0:
            self.update_console("No bridges available to check after filtering.")
            return

        self.update_console("Starting the bridge connectivity check...")
        
        self.worker = BridgeCheckWorker(parent=self)
        self.worker.setBridgeData(omitted_bridges)
        self.worker.resultReady.connect(self.display_results)
        self.worker.consoleUpdate.connect(self.update_console)
        self.worker.start()

    def clean_input_bridge_data(self, bridge_data):
        clean_data = re.sub(r'\s+\d+(\.\d+)?\s*ms', '', bridge_data)
        return clean_data.strip()

    def get_omitted_bridges(self, cleaned_bridge_data):
        filters = [item.text() for item in self.active_filters_list.findItems("*", Qt.MatchWildcard)]
        omitted = {}

        for bridge in cleaned_bridge_data.splitlines():
            if not any(self.does_bridge_match_filter(bridge, f) for f in filters) and not self.is_country_excluded(bridge):
                if self.is_clone_omitted(bridge, omitted, filters):
                    continue

                subnet_key = ".".join(bridge.split('.')[:2])  
                if subnet_key not in omitted:
                    omitted[subnet_key] = bridge  

        final_results = list(omitted.values())
        self.update_console(f"Omitted {len(cleaned_bridge_data.splitlines()) - len(final_results)} bridges.")
        return "\n".join(final_results)

    def is_country_excluded(self, bridge):
        ip_port_match = re.search(r'(\d{1,3})\.(\d+)\.(\d+)\.(\d+)', bridge)
        if ip_port_match:
            ip_str = ip_port_match.group(0)
            ip_int = self.ip_to_int(ip_str)
            country_code_found = self.check_ip_in_geoip(ip_int)
            return country_code_found in self.selected_countries
        return False

    def does_bridge_match_filter(self, bridge, filter_pattern):
        filter_pattern = filter_pattern.replace('*', '.*')
        return re.search(filter_pattern, bridge) is not None

    def ip_to_int(self, ip):
        return sum(int(octet) << (8 * (3 - i)) for i, octet in enumerate(ip.split('.')))

    def check_ip_in_geoip(self, ip_int):
        for country_code, ranges in self.geoip_data.items():
            for start, end in ranges:
                if start <= ip_int <= end:
                    return country_code
        return None

    def load_settings(self):
        try:
            with open(self.CONFIG_FILE, 'r') as f:
                config = json.load(f)
                self.bridge_input.setPlainText(config.get('bridge_input', ''))
                filters = config.get('filters', [])
                self.active_filters_list.clear()
                self.active_filters_list.addItems(filters)

                self.selected_countries = set(config.get('selected_countries', []))
                for country_code, button in self.country_buttons.items():
                    if country_code in self.selected_countries:
                        button.setChecked(True)
                        button.setStyleSheet("background-color: #007ACC; color: #ffffff;")
        except FileNotFoundError:
            self.update_console("No configuration file found. Starting with default settings.")

    def save_settings(self):
        config = {
            'bridge_input': self.bridge_input.toPlainText(),
            'filters': [self.active_filters_list.item(i).text() for i in range(self.active_filters_list.count())],
            'selected_countries': list(self.selected_countries)
        }
        with open(self.CONFIG_FILE, 'w') as f:
            json.dump(config, f)

    def add_filter(self):
        octet_pattern = self.first_octet_input.toPlainText().strip()
        if self.is_valid_octet_pattern(octet_pattern):
            existing_filters = [item.text() for item in self.active_filters_list.findItems("*", Qt.MatchWildcard)]
            if octet_pattern in existing_filters:
                self.update_console(f"The filter '{octet_pattern}' is already present.")
                return

            self.active_filters_list.addItem(octet_pattern)
            self.first_octet_input.clear()
            self.save_settings()
        else:
            self.update_console("Invalid octet pattern. Please use a valid format.")

    def is_valid_octet_pattern(self, pattern):
        regex = r'^(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\d{1,3}\.\*\.\*\.\*|\*\.\*\.\*\.\*|\*\.\*\.\d{1,3}|\d{1,3}-\d{1,3}|clone[1-4])$'
        return re.match(regex, pattern) is not None

    def remove_filter(self):
        selected_items = self.active_filters_list.selectedItems()
        if not selected_items:
            self.update_console("No filter selected to remove.")
            return
        for item in selected_items:
            self.active_filters_list.takeItem(self.active_filters_list.row(item))
        self.save_settings()

    def display_results(self, sorted_bridges):
        self.results_table.clear()
        self.results_table.setRowCount(0)
        self.all_results.clear()

        for bridge, latency in sorted_bridges:
            ip_port_match = re.search(r'(\d{1,3}(?:\.\d{1,3}){3}):(\d+)', bridge)
            country_code = None
            
            if ip_port_match:
                ip = ip_port_match.group(1)
                ip_int = self.ip_to_int(ip)
                country_code = self.check_ip_in_geoip(ip_int)

            row_position = self.results_table.rowCount()
            self.results_table.insertRow(row_position)
            self.results_table.setItem(row_position, 0, QTableWidgetItem(country_code or "Unknown"))
            self.results_table.setItem(row_position, 1, QTableWidgetItem(f"{latency:.2f}" if latency is not None else "N/A"))
            self.results_table.setItem(row_position, 2, QTableWidgetItem(bridge))

            self.all_results[bridge] = (country_code, latency)

        # Reset headers to maintain consistent labeling
        self.results_table.setHorizontalHeaderLabels(['ccTLD', 'RTT (ms)', 'Bridge'])

        self.previous_results = list(sorted_bridges)
        self.update_console(f"Total bridges checked: {len(sorted_bridges)}.")

    def filter_results(self):
        if not self.all_results:
            self.update_console("No previous results to filter.")
            return

        filters = [item.text() for item in self.active_filters_list.findItems("*", Qt.MatchWildcard)]
        filtered_results = []

        for bridge, (country_code, latency) in self.all_results.items():
            if not any(self.does_bridge_match_filter(bridge, f) for f in filters) and country_code not in self.selected_countries:
                filtered_results.append((bridge, latency))

        self.results_table.clear()
        self.results_table.setRowCount(0)

        for bridge, latency in filtered_results:
            ip_port_match = re.search(r'(\d{1,3}(?:\.\d{1,3}){3}):(\d+)', bridge)
            country_code = None
            
            if ip_port_match:
                ip = ip_port_match.group(1)
                ip_int = self.ip_to_int(ip)
                country_code = self.check_ip_in_geoip(ip_int)

            row_position = self.results_table.rowCount()
            self.results_table.insertRow(row_position)
            self.results_table.setItem(row_position, 0, QTableWidgetItem(country_code or "Unknown"))
            self.results_table.setItem(row_position, 1, QTableWidgetItem(f"{latency:.2f}" if latency is not None else "N/A"))
            self.results_table.setItem(row_position, 2, QTableWidgetItem(bridge))

        # Reset headers again after filtering to prevent numeric labeling
        self.results_table.setHorizontalHeaderLabels(['ccTLD', 'RTT (ms)', 'Bridge'])

        self.update_console(f"Filtered to {len(filtered_results)} results.")

    def copy_all_to_clipboard(self):
        clipboard_text = []
        for row in range(self.results_table.rowCount()):
            clipboard_text.append(self.results_table.item(row, 2).text())
        clipboard = QApplication.clipboard()
        clipboard.setText("\n".join(clipboard_text))

    def sort_results(self, column):
        if column == 0:
            # Sort by ccTLD - alphabetically
            self.results_table.sortItems(column, Qt.AscendingOrder)
        elif column == 1:
            # Sort by RTT - numerically
            self.results_table.sortItems(column, Qt.AscendingOrder)
        elif column == 2:
            # Sort by bridge (IP address)
            self.sort_ip_addresses()

    def sort_ip_addresses(self):
        items = [
            (self.results_table.item(row, 2).text(), row) for row in range(self.results_table.rowCount())
        ]
        valid_ips = [(ip, row) for ip, row in items if self.is_valid_ip(ip.split(':')[0])]
        valid_ips.sort(key=lambda x: self.ip_to_int(x[0].split(':')[0]))  
        for index, (bridge, original_row) in enumerate(valid_ips):
            self.results_table.insertRow(index)
            for col in range(self.results_table.columnCount()):
                self.results_table.setItem(index, col, self.results_table.takeItem(original_row, col))

    def is_valid_ip(self, ip):
        """ Check if the given string is a valid IP address. """
        try:
            socket.inet_aton(ip)
            return True
        except socket.error:
            return False

    def show_help(self):
        QMessageBox.information(self, "Filter Help",
                                "You can use various patterns to filter the bridges:\n"
                                "- Wildcards: '*'\n"
                                "- Valid filters include:\n"
                                "- 'clone1' (first octet)\n"
                                "- 'clone2' (second octet)\n"
                                "- 'clone3' (third octet)\n"
                                "- 'clone4' (fourth octet)\n"
                                "- '192.168.0.1-192.168.0.255'\n"
                                "- '192.168.0.0/16'\n"
                                "\nDeveloped by Mazafakas Development Inc.")

    def is_clone_omitted(self, bridge, omitted, filters):
        """ This function filters out clones based on the specified filters. """
        octets = bridge.split('.')

        for filter_item in filters:
            if filter_item.startswith("clone"):
                clone_number = int(filter_item[-1])
                clone_key = ".".join(octets[:clone_number]) + ".*" * (4 - clone_number)

                for existing_bridge in omitted.values():
                    existing_octets = existing_bridge.split('.')
                    existing_key = ".".join(existing_octets[:clone_number]) + ".*" * (4 - clone_number)

                    if clone_key == existing_key:
                        return True  # This bridge is a duplicate and should be omitted

        return False  # Include this bridge since it's not a duplicate

class BridgeCheckWorker(QThread):
    resultReady = pyqtSignal(list)
    consoleUpdate = pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.bridge_data = ""

    def setBridgeData(self, bridge_data):
        self.bridge_data = bridge_data

    def run(self):
        responsive_bridges = self.process_bridges(self.bridge_data)
        sorted_bridges = sorted(responsive_bridges.items(), key=lambda x: x[1])
        self.resultReady.emit(sorted_bridges)

    def process_bridges(self, bridge_data):
        bridge_strings = self.extract_bridges(bridge_data)
        responsive_bridges = {}
        for bridge_string in bridge_strings:
            ip_port_match = re.search(r'(\d{1,3}(?:\.\d{1,3}){3}):(\d+)', bridge_string)
            if ip_port_match:
                ip = ip_port_match.group(1)
                port = int(ip_port_match.group(2))
                success, latency = self.check_ip_port(ip, port, 3.0)
                if success:
                    responsive_bridges[bridge_string] = latency
        return responsive_bridges

    def extract_bridges(self, bridge_data):
        pattern = re.compile(
            r'(?:(\d{1,3}(?:\.\d{1,3}){3}:\d+\s+[A-F0-9]{40})|'
            r'(obfs4\s+\d{1,3}(?:\.\d{1,3}){3}:\d+\s+[A-F0-9]{40}\s+cert=[A-Za-z0-9+/=]+\s+iat-mode=\d+))',
            re.MULTILINE
        )
        matches = pattern.findall(bridge_data)
        return [''.join(filter(None, match)) for match in matches]

    def check_ip_port(self, ip, port, timeout):
        start_time = time.perf_counter()
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        sock.settimeout(timeout)
        try:
            sock.connect((ip, port))
            end_time = time.perf_counter()
            latency = (end_time - start_time) * 1000
            self.consoleUpdate.emit(f"Checking {ip}:{port}… Success")
            return True, latency
        except socket.error:
            self.consoleUpdate.emit(f"Checking {ip}:{port}… Failed")
            return False, None
        finally:
            sock.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = BridgeChecker()
    ex.show()
    sys.exit(app.exec_())

""".