Campus network control (cnc)
Project description
cnc
English | 简体中文
Introduction
cncis a third-party campus network client for schools using Ruijie as the campus network provider. As a Python CLI tool,cncis easy to install and lets you perform operations such as login, logout, status check, and keep-alive.
Plan
- :chart_with_upwards_trend: Add images
- :pencil2: Add flowchart(Using
Mermaid) - :iphone: Support
iOS Shortcut - :rocket: Support multiple ISP
- :school: Support multiple places(dormitory, classroom, etc.)
- :hammer: Upload to
PyPI - :beer: Upload to
Homebrew - :eyes: Add graphical user interface(maybe
Next.jsorGradio) - :file_folder: Package into a container
Install
- Pip
pip install cnc-cli
-
Source Code
- Clone this repository
git clone https://github.com/ermengchao/cnc . && cd cnc
- Install the
cncpackage
pip install -e .
Usage
:exclamation::exclamation: Before first usage, please run
cnc login
to create the cache. Cache example:
portal_url: http://10.254.241.19
updated_at: 1766905991
- portal_url: Portal URL for authentication (varies by school)
- updated_at: Cache creation time
If the cache is not created properly, all commands except login may be limited.
After the cache is created, you can use cnc normally. Supported operations:
- login: Log in to campus network
- logout: Log out of campus network
- status: Check campus network status
- keep-alive: Keep login alive via a persistent script (recommended with
systemd) - help: Show usage help
login
Use:
cnc login --user-id 2023083061 --password ****** --service 电信
Input:
user-id: Campus network account. You can also setCNC_USER_IDpassword: Campus network password. You can also setCNC_PASSWORDservice: ISP. You can also setCNC_SERVICE
Output:
Login successful: Login succeededAlready online. Login skipped.: Already online, login skippedYou appear to be offline. Login skipped.: Not connected to campus networkLogin failed: <error>: Login failed with server errorState is missing/expired but you appear to be already authenticated...: Cache missing
logout
Use:
cnc logout
Input:
- None (uses cached
portal_url)
Output:
Logged out successfully: Logout succeededAlready offline. Logout skipped.: Already offline, logout skippedLogout failed: <error>: Logout failed with server errorNo cached portal_url found. Please runcnc loginonce to initialize the cache before using other commands.: Cache missing
status
Use:
cnc status
Input:
- None (uses cached
portal_url)
Output:
Status: on_campus_unauth: On campus but unauthenticatedStatus: on_campus_auth: On campus and authenticatedStatus: off_campus: Off campusStatus: unknown: Status unknownNo cached portal_url found. Please runcnc loginonce to initialize the cache before using other commands.: Cache missing
keep-alive
Use (polling mode, default):
cnc keep-alive --polling --interval-seconds 300
Use (daily relogin mode):
cnc keep-alive --relogin --user-id 2023083061 --password ****** --service 电信 --run-at 05:00
Input:
--pollingor--relogin(choose one)--interval-seconds: Polling interval in seconds (polling mode only, default300)--user-id,--password,--service: Relogin mode only (can also useCNC_USER_ID,CNC_PASSWORD,CNC_SERVICE)--run-at: Daily relogin time (relogin mode only,HH:MM, default05:00)
Output:
Choose only one mode: --polling or --relogin: Mode conflictrelogin mode requires --user-id, --password, and --service: Missing relogin argsKeep-alive failed: <error>: Keep-alive failedNo cached portal_url found. Please runcnc loginonce to initialize the cache before using other commands.: Cache missing
help
Use:
cnc help
cnc help login
Input:
- Optional subcommand name
Output:
- Prints CLI help text
Process
flowchart TD
A[CampusNetClient initialization] --> B[StateStore read/write state.yaml]
A --> S["status()"]
S --> S1{"Has cached portal_url?"}
S1 -- No --> S2[StateError: login first to cache]
S1 -- Yes --> S3["detect_network_status(redirect_url)"]
S3 --> S4{Result UNKNOWN?}
S4 -- No --> S5[Return NetworkState]
S4 -- Yes --> S6["_status_from_portal_url(cached portal_url)"]
A --> E["ensure_state()"]
E --> E1["_state_has_fresh_portal_url?"]
E1 -- Yes --> E2[Return cached]
E1 -- No --> E3["status()"]
E3 --> E4{ON_CAMPUS_AUTH?}
E4 -- Yes --> E5[NeedUnauthed]
E4 -- No --> E6["get_portal_info -> save state"]
A --> L["login(user_id, password, service)"]
L --> L1{"cached portal_url?"}
L1 -- Yes --> L2["_status_from_portal_url"]
L1 -- No --> L3["detect_network_status"]
L2 --> L4{"ON_CAMPUS_AUTH?"}
L3 --> L4
L4 -- Yes --> L5[AlreadyOnline: Login skipped]
L4 -- No --> L6{"OFF_CAMPUS?"}
L6 -- Yes --> L7[AlreadyOffline: Login skipped]
L6 -- No --> L8["get_portal_info -> portal_url/query -> save"]
L8 --> L9["do_login(...)"]
A --> O["logout()"]
O --> O1{"cached portal_url?"}
O1 -- No --> O2[StateError: no cache]
O1 -- Yes --> O3["_status_from_portal_url"]
O3 --> O4{"ON_CAMPUS_UNAUTH or OFF_CAMPUS?"}
O4 -- Yes --> O5[AlreadyOffline: Logout skipped]
O4 -- No --> O6{"UNKNOWN?"}
O6 -- Yes --> O7[StateError: unknown]
O6 -- No --> O8["get_portal_info -> save"]
O8 --> O9{"portal_url exists?"}
O9 -- No --> O10[StateError: no portal_url]
O9 -- Yes --> O11["do_logout(...)"]
subgraph Helper
H1["_state_has_fresh_portal_url"]
H2["_status_from_portal_url"]
end
Principles
Optional. If you are interested, you can refer to the steps below. If you run into any issues, feel free to open an issue!
Login principle
Login is essentially a POST request to http://{portal_url}/eportal/Interface.do?method=login, with the following fields:
# Header
-H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
# Body
# User info
--data-urlencode "userId=$userId" \
--data-urlencode "password=$password" \
--data-urlencode "service=$service" \
--data-urlencode "queryString=$queryString" \
# Placeholder fields
--data-urlencode 'operatorPwd=' \
--data-urlencode 'operatorUserId=' \
--data-urlencode 'validcode=' \
--data-urlencode 'passwordEncrypt=false'
Logout principle
Logout is essentially a POST request to http://{portal_url}/eportal/Interface.do?method=logout. Unlike login, logout does not require a request body.
Status principle
Status is essentially a GET request to http://{portal_url}/eportal/redirectortosuccess.jsp, and you can determine the state by checking the Location header:
- Authenticated:
Location=http://{portal_url}/eportal/./success.jsp - Unauthenticated:
Location=http://123.123.123.123/ - Off campus: request timeout
LICENSE
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cnc_cli-0.1.1.tar.gz.
File metadata
- Download URL: cnc_cli-0.1.1.tar.gz
- Upload date:
- Size: 17.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d67617fe6088e89de2708a0d6b78a10006fa3868809921fde26d470ee4f46f23
|
|
| MD5 |
b47099ace06995d44f53f167a9409b34
|
|
| BLAKE2b-256 |
57bb8e6d5df0a0c8b49996e8700458e9abe53ba6b011b3c15329d4b21169a61a
|
File details
Details for the file cnc_cli-0.1.1-py3-none-any.whl.
File metadata
- Download URL: cnc_cli-0.1.1-py3-none-any.whl
- Upload date:
- Size: 17.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da0b5056af253baffcd660cbc4b29c84271ccaa113c02f7ad7f4b71d20b6517b
|
|
| MD5 |
1e07852a82678a1f129afc9551a30753
|
|
| BLAKE2b-256 |
3d0eb66faa7cd9cf550361d0ffa9656abb9432d893e7ca75305b5e2a10ed03b5
|