async def func():
     start = time.time()
     while True:
         if time.time() - start > timeout:
             LOGGER.warning(
                 f'Login failed: {account_id} <<<{page.page_source=}>>>')
             await notify('Login failed', f'{account_id}')
             return False
         # noinspection PyProtectedMember
         try:
             await page.goto(
                 'http://fresh.ahau.edu.cn/yxxt-v5/web/jkxxtb/tbJkxx.zf')
         except playwright._impl._api_types.Error as e:
             LOGGER.exception(e)
             continue
         await sleep(2)
         await page.evaluate(js_codes.login())
         await sleep(2)
         await page.fill('#zh', account_id)
         await page.fill('#mm', password)
         await sleep(2)
         await page.click('#dlan')
         await sleep(2)
         if page.url != 'http://fresh.ahau.edu.cn/yxxt-v5/web/jkxxtb/tbJkxx.zf':
             await sleep(60 * 10)
             continue
         await sleep(5)
         return True
async def main():
    global BROWSER
    REQUEST_LIMITS['pushplus.plus'] = Limit(SleepTime(120))

    async with contextlib.AsyncExitStack() as stack:
        play = await stack.enter_async_context(async_playwright())
        BROWSER = await play.chromium.launch()
        stack.push_async_callback(play.stop)
        stack.push_async_callback(BROWSER.close)
        scheduler = AsyncIOScheduler(job_defaults={
            'misfire_grace_time': 3600,
            'coalesce': True
        },
                                     timezone=str(tzlocal.get_localzone()))
        loop = asyncio.get_running_loop()
        for s in (signal.SIGINT, signal.SIGTERM, signal.SIGQUIT):
            loop.add_signal_handler(s, lambda: create_task(shutdown()))
        event = asyncio.Event()
        SHUTDOWN_VARIABLES['event'] = event

        if RUN_IMMEDIATELY:
            try:
                task = create_task(run(return_cancelled_error=True))
                TASKS.add(task)
                await task
                TASKS.discard(task)
                LOGGER.warning('immediately running finished')
            except CancelledError:
                return
        scheduler.add_job(run, 'cron', hour=7)
        scheduler.add_job(run, 'cron', hour=12)
        scheduler.add_job(run, 'cron', hour=19, minute=30)
        scheduler.start()
        stack.callback(scheduler.shutdown)
        stack.push_async_callback(event.wait)
async def shutdown():
    if SHUTDOWN_VARIABLES['killed']:
        os._exit(1)
    SHUTDOWN_VARIABLES['killed'] = True
    LOGGER.warning('Exiting')
    for t in TASKS:
        t.cancel()
    if TASKS:
        await asyncio.wait(TASKS)
    LOGGER.debug(f'{TASKS=}')
    SHUTDOWN_VARIABLES['event'].set()
    async def func():
        async with contextlib.AsyncExitStack() as stack:
            if not RUN_IMMEDIATELY:
                await sleep(random() * 30 * 60)
            account_id = account['account-id']
            password = account['password']
            context, page = await new_context()
            stack.push_async_callback(context.close)
            stack.push_async_callback(page.close)
            logged = await login(page, account_id, password)
            if not logged:
                return
            html = HTML(await page.content())
            source = await get_script_source(html=html)
            if SCRIPT_SOURCE:
                if diff := '\n'.join(
                        get_diff(SCRIPT_SOURCE, source.splitlines())):
                    await handle_page_changing(diff, source)
                    return

            name = html.xpath("//input[@id='xm']/@value")[0]
            await page.evaluate(js_codes.submit())
            await sleep(2)

            async with page.expect_response('**/tbBcJkxx.zf') as response:
                await page.click("//button[text()='提交']")
                await sleep(5)
            response = await (await response.value).json()
            if response['status'] == 'success':
                await page.wait_for_selector("//div[text()='保存数据成功']",
                                             state='attached')
                LOGGER.warning(f'Success: {account_id} {name}')
            else:
                LOGGER.warning(
                    f'Submit failed: {account_id} {name} <<<{source=}>>>')
                await notify('Submit failed', f'{account_id} {name}')
Example #5
0
 async def on_command_error(_, error):
     LOGGER.warning("Command error: %s", error)
Example #6
0
def read_stats(args):
    # This is the command to grab all of the necessary info.
    # Note that -v is passed to tail - this is so we always the filename
    # given to us, which is needed for parsing.
    # As processes can be transient, we can get errors here about
    # non-existent files, so ignore them, this is expected.
    cmd = 'nice tail -v -n +1 '\
              '/proc/%s/{cmdline,smaps} '\
              '/proc/meminfo '\
              '/proc/loadavg '\
              '/proc/uptime '\
              '/proc/vmstat '\
          '2>/dev/null; ' \
          'nice find /proc/%s -type f -name stat '\
            '-exec tail -v -n +1 {} \; 2>/dev/null | '\
            'awk \''\
              '/==>/ {print} '\
              '/^[0-9]/ {print \$2, \$10, \$12, \$14, \$15, \$22}\';'


    # Accept a space-separated list of pids as that is what pidof(8) returns and
    # it's quite likely you'll want to invoke this script with something like:
    #
    #     --pid "`pidof foobar`"
    #
    # at some point.
    if args.pid.isdigit() or args.pid == '*':
        pids = args.pid
    else:
        pids = '{%s}' % args.pid.replace(' ', ',')

    # root can see all of /proc, another user is likely not going to be able
    # to read all of it. This isn't a hard error, but won't give a full view
    # of the system.
    if (args.host == '' and getpass.getuser() != "root") or\
       (args.host != '' and args.user != 'root'):
        LOGGER.warning("If not running as root you may not see all info.")

    if args.host == '':
        LOGGER.info('Loading local procfs files')
        cmd = "bash -c \"%s\"" % (cmd % (pids, pids))
    elif args.host != '':
        ssh = (
            "ssh %s@%s"
            " -o UserKnownHostsFile=/dev/null"
            " -o StrictHostKeyChecking=no"
            " -o LogLevel=error"
            % (args.user, args.host)
        )
        if args.password:
            ssh = "sshpass -p %s %s" % (args.password, ssh)
        else:
            ssh = "%s -o PasswordAuthentication=no" % ssh

        cmd = """%s "%s" """ % (ssh, cmd % (pids, pids))

    LOGGER.info('Reading procfs with cmd: %s' % cmd)
    p = Popen(cmd, shell=True, bufsize=-1, stdout=PIPE, stderr=PIPE)
    stats = read_tailed_files(p.stdout)
    if p.poll() != 0:
        LOGGER.error("Command failed with: %r" % p.stderr.read().strip())
        sys.exit(1)

    return stats
async def handle_page_changing(diff, current):
    LOGGER.warning('Page changed:\n{}'.format(diff))
    PREVIOUS_PATH.write_text(current)
    await notify(f'Page changed', f'```diff\n{diff}\n```')
    create_task(shutdown())