2
\$\begingroup\$

This is a followup to Python script that reboots the router every 600 seconds.

Recently censorship in China has increased because of the meeting of heads of states, and my previous script has been rendered almost useless by the ISP.

So I spent the last few hours updating the script to make it work better, so that if the ISP is foolish enough to violate my basic human right they will have a very hard time.

The script:

import logging
import numpy as np
import random
import subprocess
import time
from datetime import datetime
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from tenacity import (
 after_log,
 before_sleep_log,
 retry,
 stop_after_attempt,
 wait_random
)
logging.basicConfig(
 filename='D:/network_guard.log',
 filemode='a',
 format='%(asctime)s %(name)s %(levelname)s %(message)s',
 datefmt='%Y-%m-%d %H:%M:%S',
 level=logging.INFO
)
logger = logging.getLogger(__name__)
Firefox = webdriver.Firefox()
wait = WebDriverWait(Firefox, 3)
decorator = retry(
 reraise=True,
 before_sleep=before_sleep_log(logger, logging.ERROR),
 after=after_log(logger, logging.INFO),
 stop=stop_after_attempt(10),
 wait=wait_random(min=1, max=2)
)
@decorator
def click(target):
 wait.until(EC.element_to_be_clickable(('id', target))).click()
@decorator
def accept_alert():
 Firefox.switch_to.alert.accept()
@decorator
def reboot():
 reboot_button = Firefox.find_element(by='id', value='reboot')
 Firefox.execute_script("arguments[0].scrollIntoView();", reboot_button)
 click('reboot')
 wait.until(EC.alert_is_present())
 accept_alert()
def login():
 logging.info('Attempting to access router login page')
 Firefox.get('http://192.168.0.1/login.html')
 logging.info('Successfully accessed router login page')
 time.sleep(1)
 logging.info('Attempting to log in to the router')
 try:
 wait.until(EC.visibility_of_element_located(('id', "login-password"))).send_keys('****')
 click('save')
 except TimeoutException:
 pass
 
 logging.info('Successfully logged in to the router')
@decorator
def auto_reboot():
 login()
 logging.info('Attempting to switch to system tab')
 click('system')
 logging.info('Successfully switched to the system tab')
 logging.info('Attempting to reboot the router')
 reboot()
 logging.info('Successfully rebooted the router')
@decorator
def refresh_connection():
 login()
 logging.info('Attempting to refresh the connection')
 click('network')
 time.sleep(2)
 click('dhcp')
 click('submit')
 time.sleep(6)
 click('adsl')
 click('submit')
 logging.info('Successfully refreshed the connection')
def reenable_adapter():
 subprocess.run('devcon disable *dev_8168*')
 time.sleep(3)
 subprocess.run('devcon enable *dev_8168*')
 logging.info('Successfully re-enabled adapter')
def agm(a, b, n):
 if a > b:
 a, b = b, a
 for i in range(n):
 c = (a * b) ** 0.5
 d = (a + b) / 2
 a, b = c, d
 return (c + d) / 2
def gauss(x, weight):
 return np.exp(-(x - 0.5) * (x - 0.5) / (2 * weight**2))
def randBias(base, top, bias, weight=0.5):
 assert 0 < weight <= 1
 influence = random.random()
 x = random.random() * (top - base) + base
 if x > bias:
 return x + gauss(influence, weight) * (bias - x)
 return x - gauss(influence, weight) * (x - bias)
while True:
 try:
 start_time = time.time()
 end_time = start_time + 570
 logging.info(
 'Will restart router at {0}'.format(
 datetime.fromtimestamp(end_time).strftime('%Y-%m-%d %H:%M:%S')
 )
 )
 while True:
 refresh_connection()
 reenable_adapter()
 now = time.time()
 if now >= end_time:
 break
 remaining_time = end_time - now
 low = int(min(120, remaining_time))
 high = int(remaining_time+1)
 nap_time = randBias(low, high, agm(low, high, 16))
 logging.info(
 'Will sleep for {0} seconds, next refresh attempt is at {1}'.format(
 round(nap_time, 3), datetime.fromtimestamp(now + nap_time).strftime('%Y-%m-%d %H:%M:%S')
 )
 )
 time.sleep(nap_time)
 
 auto_reboot()
 time.sleep(30)
 reenable_adapter()
 Firefox.get('https://www.google.com')
 except Exception:
 pass

I have made more than a few changes to the script, for instance I have added logging to it, and made it retry at every opportunity so that it is more exception-resistant, and refreshed the router WAN connection and Ethernet adapter connection at random intervals.

Here is a sample of the log

2023年04月09日 00:24:03 root INFO Attempting to log in to the router
2023年04月09日 00:24:03 root INFO Successfully logged in to the router
2023年04月09日 00:24:03 root INFO Attempting to refresh the connection
2023年04月09日 00:24:22 root INFO Successfully refreshed the connection
2023年04月09日 00:24:26 root INFO Successfully re-enabled adapter
2023年04月09日 00:24:26 root INFO Attempting to access router login page
2023年04月09日 00:24:31 root INFO Successfully accessed router login page
2023年04月09日 00:24:32 root INFO Attempting to log in to the router
2023年04月09日 00:24:38 root INFO Successfully logged in to the router
2023年04月09日 00:24:38 root INFO Attempting to switch to system tab
2023年04月09日 00:24:41 __main__ INFO Finished call to '__main__.click' after 3.078(s), this was the 1st time calling it.
2023年04月09日 00:24:41 __main__ ERROR Retrying __main__.click in 1.3839106722751287 seconds as it raised TimeoutException: Message: 
Stacktrace:
RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:180:5
NoSuchElementError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:392:5
element.find/</<@chrome://remote/content/marionette/element.sys.mjs:134:16
.
2023年04月09日 00:24:45 __main__ INFO Finished call to '__main__.click' after 7.562(s), this was the 2nd time calling it.
2023年04月09日 00:24:45 __main__ ERROR Retrying __main__.click in 1.2213370168062705 seconds as it raised TimeoutException: Message: 
Stacktrace:
RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:180:5
NoSuchElementError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:392:5
element.find/</<@chrome://remote/content/marionette/element.sys.mjs:134:16
.
2023年04月09日 00:24:48 root INFO Successfully switched to the system tab
2023年04月09日 00:24:48 root INFO Attempting to reboot the router
2023年04月09日 00:24:48 root INFO Successfully rebooted the router
2023年04月09日 00:25:22 root INFO Successfully re-enabled adapter
2023年04月09日 00:25:22 root INFO Will restart router at 2023年04月09日 00:34:52

How can I improve the script?


Update: I forgot to censor my router password. Anyway no one can use it and I change passwords very frequently.

asked Apr 8, 2023 at 16:33
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Probably want to name your decorator something other than "decorator". I mean, would you name your dog, "dog"? \$\endgroup\$ Commented Apr 8, 2023 at 17:41

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.