├── LICENSE ├── README.md ├── install.py └── netmirror.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Kourva 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

netmirror

4 |

ArtixLinux Mirror Optimizer. Selects fastest mirror in mirrors based on ping ms

5 | 6 | 7 |

8 | 9 | # ▍Preview 10 | Mirror list is inside the main script. so if you want to **add** or **remove** mirrors, edit netmirror file.
11 | Netmirror will ping all mirrors and print the fastest mirror.
12 | Mirrors are for Artix Linux 13 | ```bash 14 | $ netmirror 15 | Ping process started on mirrors... 16 | * mirrors.dotsrc.org [130.225.254.116] 159.792 ms █▓▒░ 17 | * mirror.clarkson.edu [128.153.145.19 ] 226.728 ms █▓▒░ 18 | * mirror.freedif.org [132.147.122.105] 290.100 ms █▓▒░ 19 | * mirror.albony.xyz [188.114.99.0 ] 121.820 ms █▓▒░ 20 | * mirrors.cloud.tencent.com [43.152.29.12 ] 126.056 ms █▓▒░ 21 | * mirrors.42tm.tech [103.224.182.249] 286.557 ms █▓▒░ 22 | * mirror.aarnet.edu.au [202.158.214.106] 477.169 ms █▓▒░ 23 | 24 | Fastest mirror: https://mirror.albony.xyz/artix 25 | * speed: 121.82 ms 26 | ``` 27 |
28 | 29 | # ▍Setup 30 | Installing **netmirror** is so simple. just follow following steps...
31 | ▢ **⒈Clone repository** 32 | ```bash 33 | git clone https://github.com/Kourva/netmirror 34 | ``` 35 | ▢ **⒉Navigate to netmirror directory** 36 | ```bash 37 | cd netmirror/ 38 | ``` 39 | ▢ **⒊Make files executable** 40 | ```bash 41 | chmod +x install.py netmirror.py 42 | ``` 43 | ▢ **⒋Install the netmirror** 44 | ```bash 45 | python install.py 46 | ``` 47 |
48 | 49 | # ▍Uninstall 50 | use installer with --uninstall argument to uninstall the netmirror as follows... 51 | ```bash 52 | python install.py --uninstall 53 | ``` 54 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | # Libraries 2 | import os, sys, shutil 3 | 4 | 5 | # Function to check root access 6 | def check_root(): 7 | return not os.geteuid() 8 | 9 | 10 | # Check if netmirror is already installed 11 | def check_installed(): 12 | return os.path.exists("/usr/bin/netmirror") 13 | 14 | 15 | # Installing process 16 | def installer(): 17 | if check_installed(): 18 | # If package is already installed, print message and exit 19 | print("\ninfo: netmirror is already installed.") 20 | sys.exit(0) 21 | 22 | # Print install message 23 | print("\ninfo: installing netmirror for you.") 24 | 25 | # Copy file to /usr/bin 26 | try: 27 | shutil.copyfile("netmirror.py", "/usr/bin/netmirror") 28 | except: 29 | print("error: failed to copy file to /usr/bin") 30 | sys.exit(1) 31 | 32 | # Change permissions 33 | try: 34 | os.chmod("/usr/bin/netmirror", 0o755) 35 | except: 36 | print("error: failed to set executable permission for /usr/bin/netmirror") 37 | sys.exit(1) 38 | 39 | # Print success message 40 | print("success: netmirror has been installed.") 41 | 42 | 43 | # Uninstalling process 44 | def uninstaller(): 45 | # Print uninstall message 46 | print("\ninfo: uninstalling package from your system.") 47 | 48 | # Remove file from /usr/bin 49 | if check_installed(): 50 | try: 51 | os.remove("/usr/bin/netmirror") 52 | except: 53 | print("error: failed to remove /usr/bin/netmirror") 54 | sys.exit(1) 55 | 56 | # Print success message 57 | print("success: netmirror has been uninstalled.") 58 | else: 59 | # If package is not installed, print message and exit 60 | print("info: netmirror is not installed.") 61 | sys.exit(0) 62 | 63 | 64 | if __name__ == "__main__": 65 | if check_root(): 66 | if len(sys.argv) > 1 and sys.argv[1] == "--uninstall": 67 | uninstaller() 68 | else: 69 | installer() 70 | else: 71 | raise sys.exit("error: you cannot perform this operation unless you are root.") 72 | -------------------------------------------------------------------------------- /netmirror.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # ArtixLinux Mirror Optimizer || netmirror 5 | # Author : Kourva 6 | # Source : https://github.com/Kourva/netmirror 7 | 8 | 9 | #*# Imports 10 | import os 11 | import re 12 | import socket 13 | import subprocess 14 | import requests 15 | from urllib.parse import urlparse 16 | 17 | 18 | 19 | #*# Mirrors 20 | url = "https://gitea.artixlinux.org/packages/artix-mirrorlist/raw/branch/master/mirrorlist" 21 | response = requests.get(url) 22 | response.raise_for_status() 23 | 24 | lines = response.text.splitlines() 25 | 26 | #*# Remove Comments and irrelevant things 27 | regexs = [ 28 | (r"#.*", ""), # COMMENTS 29 | (r"Server\ =\ ", ""), # Irrelevant placeholder before server link 30 | ] 31 | 32 | #*# Get each mirror from lines extracted from mirrorlist raw file, using re to filter out the links 33 | mirrors = [] 34 | for i,line in enumerate(lines, start=1): 35 | for pat, repl in regexs: 36 | line = re.sub(pat, repl, line) 37 | if line.strip() == '': 38 | pass 39 | else: 40 | mirrors.append(line.strip()) 41 | 42 | #*# Ping all mirrors 43 | def ping_mirrors(): 44 | #*# Get Ip address 45 | ipaddr = lambda url: socket.gethostbyname(urlparse(url).hostname) if urlparse(url).hostname else None 46 | 47 | # Check mirrors 48 | speeds = {} 49 | print("Ping process started on mirrors...") 50 | 51 | # Get terminal size 52 | cols = os.get_terminal_size().columns 53 | info_bar = cols // 2 54 | 55 | for mirror in mirrors: 56 | # Get mirror Ip address 57 | # If server not accessible, then jump it and go to next one. 58 | try: 59 | ipadrs = ipaddr(mirror) 60 | except Exception as e: 61 | print(f"NOT ACCESSIBLE! : {e}") 62 | continue 63 | 64 | _, _, name, *_ = mirror.rsplit("/") 65 | info = name.ljust(info_bar) 66 | print(f" \33[2;36m*\33[m {info} [\33[2;36m{ipadrs.ljust(15)}\33[m]", end=" ") 67 | try: 68 | # Ping mirror 69 | ping_output = subprocess.check_output( 70 | ['ping', '-c', '3', '-q', '-i', '0.2', '-w', '1', ipadrs], 71 | stderr=subprocess.STDOUT, 72 | universal_newlines=True 73 | ) 74 | # Find ping ms 75 | match = re.search(r"= (\d+\.\d+)/", ping_output) 76 | if match: 77 | speed_ms = float(match.groups()[0]) 78 | speeds[mirror] = speed_ms 79 | if speed_ms <= 150: 80 | print(f"\33[2;32m{match.groups()[0]} ms █▓▒░\33[m", end="\n") 81 | if speed_ms > 150: 82 | print(f"\33[2;33m{match.groups()[0]} ms █▓▒░\33[m", end="\n") 83 | 84 | # Cancel progress when user pressed Ctrl+C 85 | except KeyboardInterrupt:raise SystemExit("\n\33[2;31mGot keyboard Interrupt. Leaving progress!\33[m") 86 | # Except ping error and set mirror unavailable 87 | except:print(f"\33[2;31mFailed █▓▒░\33[m", end="\n") 88 | 89 | # Return mirrors with ping ms 90 | return speeds 91 | 92 | #*# Update Mirrors 93 | def update_mirrors(): 94 | # Get mirrors speed 95 | speeds = ping_mirrors() 96 | 97 | # Print no mirrors available if all mirrors down 98 | if not speeds:print("No mirrors available.") 99 | 100 | # Find the fastest mirror and show save prompt 101 | else: 102 | # Sort the mirrors and find best mirror 103 | best_mirror = min(speeds, key=speeds.get) 104 | 105 | # Print fastest mirror 106 | print(f"\nFastest mirror:\33[2;36m {best_mirror}\33[m\n \33[2;36m*\33[m speed: {speeds[best_mirror]} ms") 107 | 108 | #*# Main section 109 | if __name__ == '__main__':update_mirrors() 110 | else:print("error: you cannot perform this operation unless you are root.") 111 | --------------------------------------------------------------------------------