Release v1.1.1
This commit is contained in:
parent
2866913c05
commit
cc56a52b88
29
CHANGELOG.md
29
CHANGELOG.md
@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.1.1] - 2024-10-05
|
||||
|
||||
### Added
|
||||
|
||||
- Option to export the KID and key based on the service in the server settings.
|
||||
- Introduced a rule to monitor and manage the usage count for users with free tickets.
|
||||
- Rule to keep track of updates for users with free tickets.
|
||||
- Rule to disable the evolution of the license, preventing unwanted advertisements.
|
||||
- New server specifically designed to bypass trial limitations for DRM services.
|
||||
|
||||
### Changed
|
||||
|
||||
- Enhanced the documentation for better clarity and usability.
|
||||
- New method for bypassing restrictions using the KID.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed issues in the trial disc patch.
|
||||
- Resolved issues with the expiration date display for `LIFETIME` tickets.
|
||||
|
||||
## [1.1.0] - 2024-09-29
|
||||
|
||||
### Added
|
||||
@ -54,7 +74,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
|
||||
- Initial release of the project, laying the foundation for future enhancements and features.
|
||||
|
||||
[1.1.0]: https://cdm-project.com/hyugogirubato/DVDFabLifetimeActivation
|
||||
[1.0.2]: https://cdm-project.com/hyugogirubato/DVDFabLifetimeActivation
|
||||
[1.0.1]: https://cdm-project.com/hyugogirubato/DVDFabLifetimeActivation
|
||||
[1.0.0]: https://cdm-project.com/hyugogirubato/DVDFabLifetimeActivation
|
||||
[1.1.1]: https://cdm-project.com/hyugogirubato/DVDFabExtendedLicense/releases/tag/v1.1.1
|
||||
[1.1.0]: https://cdm-project.com/hyugogirubato/DVDFabExtendedLicense/releases/tag/v1.1.0
|
||||
[1.0.2]: https://cdm-project.com/hyugogirubato/DVDFabExtendedLicense/releases/tag/v1.0.2
|
||||
[1.0.1]: https://cdm-project.com/hyugogirubato/DVDFabExtendedLicense/releases/tag/v1.0.1
|
||||
[1.0.0]: https://cdm-project.com/hyugogirubato/DVDFabExtendedLicense/releases/tag/v1.0.0
|
||||
|
113
README.md
113
README.md
@ -1,47 +1,49 @@
|
||||
# DVDFab: Extended License
|
||||
|
||||
This tool provides advanced license management and ticketing capabilities for DVDFab software, bypassing limitations and enabling unrestricted access to all available features.
|
||||
The **DVDFab Extended License** is designed to manage licenses for DVDFab software effectively. It offers advanced features that enable unrestricted access to all DVDFab products while ensuring user privacy and security.
|
||||
|
||||
## Features
|
||||
|
||||
The DVDFab Extended License tool offers a wide range of features, including:
|
||||
|
||||
- 🔒 **Analytics Deactivation:** Disables all data collection and analytics within DVDFab to protect user privacy.
|
||||
- 🔓 **Unlock All Products & Features:** Provides access to every product and feature available within the DVDFab suite without limitations.
|
||||
- 💻 **Cross-Platform Support:** Works across multiple operating systems, including Windows, macOS, and Android (with appropriate configurations).
|
||||
- 🛠️ **Custom Ticket Generation:** Create fully customized tickets with various licensing options such as "Lifetime," "Subscriber," "Free," or "No Login."
|
||||
- 🌐 **Mocking Server Support:** Integrates with HTTP interception tools to patch requests and bypass server-side verification.
|
||||
- 🔒 **Analytics Deactivation**: Completely disable data collection and analytics in DVDFab to protect user privacy.
|
||||
- 🔓 **Unlock All Products & Features**: Gain unrestricted access to every product and feature available within the DVDFab suite.
|
||||
- 💻 **Cross-Platform Support**: Compatible with multiple operating systems, including Windows, macOS, and Android.
|
||||
- 🛠️ **Custom Ticket Generation**: Generate fully customized tickets with various licensing options, including "Lifetime," "Subscriber," "Free," or "No Login."
|
||||
- 🌐 **Mocking Server Support**: Integrate with HTTP interception tools to modify requests and bypass server-side verification for enhanced functionality.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You'll need **HTTP Toolkit (Pro)** to intercept and modify network traffic. Download it from the [HTTP Toolkit Website](https://httptoolkit.com/).
|
||||
To use this tool, you will need **HTTP Toolkit (Pro)** for intercepting and modifying network traffic. You can download it from the [HTTP Toolkit Website](https://httptoolkit.com/).
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Clone the Repository**
|
||||
Open your terminal and run the following commands:
|
||||
```bash
|
||||
git clone https://cdm-project.com/hyugogirubato/DVDFabExtendedLicense.git
|
||||
cd dvdfabextendedlicense
|
||||
```
|
||||
### Step 1: Clone the Repository
|
||||
|
||||
2. **Install Python Dependencies**
|
||||
Run the following command to install the required packages:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
Open your terminal and run the following commands:
|
||||
|
||||
```bash
|
||||
git clone https://cdm-project.com/hyugogirubato/DVDFabExtendedLicense
|
||||
```
|
||||
|
||||
### Step 2: Install Python Dependencies
|
||||
|
||||
Install the required packages by running:
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### 1. Import Certificates
|
||||
|
||||
In the **HTTP Toolkit** settings, you need to import the `.crt` certificates located in the `docs` folder to intercept the network traffic of applications.
|
||||
Import the `.crt` certificates located in the `docs` folder into the **HTTP Toolkit** settings to enable interception of the application's network traffic.
|
||||
|
||||
<img src="./docs/images/import_ca.png" width="60%">
|
||||
|
||||
|
||||
### 2. Generate Custom Mock Rules
|
||||
|
||||
You will need to generate mock rules to be used in **HTTP Toolkit** for intercepting and modifying network traffic.
|
||||
Create mock rules to be used with **HTTP Toolkit** for intercepting and modifying network traffic.
|
||||
|
||||
Run the following command:
|
||||
```bash
|
||||
@ -55,20 +57,32 @@ python rules.py --rules template.json --output my_rules.json
|
||||
|
||||
After generating the rules, import the resulting file into HTTP Toolkit.
|
||||
|
||||
### 3. Bypass License Authentication
|
||||
### 3. Run the Mock Server
|
||||
|
||||
After generating the ticket, enable the **Bypass Auth Ticket** rule in HTTP Toolkit. Then, launch the DVDFab software through an intercepted terminal and log in with your credentials.
|
||||
> [!WARNING]
|
||||
> This step is required for applications that process DRM content but optional for others.
|
||||
|
||||
Once logged in, close the software, enable the **Bypass Auth Ticket** rule, and relaunch the software.
|
||||
Before launching any DVDFab product with the mock rules, ensure the server is running.
|
||||
|
||||
To run the server:
|
||||
```bash
|
||||
python server.py --export
|
||||
```
|
||||
|
||||
### 4. Bypass License Authentication
|
||||
|
||||
After generating custom mock rules, import them into **HTTP Toolkit**. Launch the DVDFab software through an intercepted terminal and log in with your credentials. After logging in, close the software and enable the **Bypass Auth Ticket** rule to activate the software.
|
||||
|
||||
<img src="./docs/images/mock_rules.png" width="60%">
|
||||
|
||||
### 4. Advanced License Management
|
||||
### 5. Advanced License Management
|
||||
|
||||
> [!NOTE]
|
||||
> By default, the generated ticket corresponds to a Fab365 ticket. However, this module allows users to generate other ticket formats based on their preferences.
|
||||
|
||||
This tool provides multiple ways to manage tickets, including logging in, using an existing token, or extracting information from old tickets.
|
||||
|
||||
<img src="./docs/images/mock_requests.png" width="60%">
|
||||
|
||||
<img src="./docs/images/ticket_info.png" width="80%">
|
||||
|
||||
#### Command Options for Ticket Management
|
||||
|
||||
@ -78,55 +92,44 @@ usage: ticket.py [-h] [--type {SUBSCRIBER,LIFETIME,FREE,NO_LOGIN}]
|
||||
{login,token,ticket,info} ...
|
||||
```
|
||||
|
||||
**Positional Arguments:**
|
||||
**Positional Arguments**:
|
||||
|
||||
- `login` – Log in using account credentials.
|
||||
- `token` – Use an existing user token.
|
||||
- `ticket` – Use a pre-existing ticket string.
|
||||
- `info` – Extract ticket information from a serialized ticket string.
|
||||
|
||||
**Optional Arguments:**
|
||||
- `--type` – Ticket type, options: `SUBSCRIBER`, `LIFETIME`, `FREE`, `NO_LOGIN`.
|
||||
**Optional Arguments**:
|
||||
|
||||
- `--type` – Ticket type options: `SUBSCRIBER`, `LIFETIME`, `FREE`, `NO_LOGIN`.
|
||||
- `--version` – Specify software version (default: 6200).
|
||||
- `--expire` – Number of days until the ticket expires (default: 365 days).
|
||||
- `--expire` – Specify the number of days until the ticket expires (default: 365 days).
|
||||
|
||||
#### Example Ticket Generation
|
||||
|
||||
1. **Log in and Generate Ticket:**
|
||||
1. **Log in and Generate a Ticket**:
|
||||
|
||||
```bash
|
||||
python ticket.py login myemail@example.com mypassword --client WINDOWS
|
||||
```
|
||||
|
||||
2. **Use an Existing Token:**
|
||||
2. **Use an Existing Token**:
|
||||
|
||||
```bash
|
||||
python ticket.py token "your-32-char-token"
|
||||
```
|
||||
|
||||
3. **Extract Information from a Ticket:**
|
||||
3. **Extract Information from a Ticket**:
|
||||
|
||||
```bash
|
||||
python ticket.py info "serialized-ticket-string"
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### IP/MAC-Based DRM Restriction Circumvention
|
||||
|
||||
> [!WARNING]
|
||||
> Avoid using the same account across multiple regions or devices simultaneously, as it could lead to account suspension or banning.
|
||||
|
||||
Some DRM-protected services may block access based on the IP or MAC address of the user. To avoid this, the tool includes a **mocking server** that can spoof the device identity and circumvent such restrictions.
|
||||
|
||||
To run the server:
|
||||
```bash
|
||||
python server.py --email "user@example.com"
|
||||
```
|
||||
|
||||
At the same time, enable the mock rules in HTTP Toolkit that are associated with DRM services.
|
||||
|
||||
## Common Issues
|
||||
|
||||
- **Invalid Token Error:** Ensure that your token is exactly 32 characters long. If it's shorter or longer, regenerate it or verify the token source.
|
||||
- **Expired License:** If you encounter an expired license error, check the expiration date of your ticket using the `info` command and extend it by generating a new ticket.
|
||||
- **DRM Block:** If the software blocks your IP/MAC address, ensure you're using the correct DRM circumvention server configuration.
|
||||
- **Invalid Token Error**: Ensure that your token is exactly 32 characters long. If it's shorter or longer, regenerate it or verify the token source.
|
||||
- **Expired License**: If you encounter an expired license error, check the expiration date of your ticket using the `info` command and generate a new ticket if necessary.
|
||||
- **DRM Block**: If the software blocks your IP/MAC address, verify that you’re using the correct DRM circumvention server configuration.
|
||||
|
||||
## License
|
||||
|
||||
@ -134,4 +137,4 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This tool is provided for **educational purposes only**. Unauthorized use of software tools to bypass security mechanisms, including licensing, may violate laws and terms of service. Always ensure compliance with software terms of use before attempting any modifications.
|
||||
This tool is provided for **educational purposes only**. Unauthorized use of software tools to bypass security mechanisms, including licensing, may violate laws and terms of service. Always ensure compliance with software terms of use before attempting any modifications.
|
Binary file not shown.
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 32 KiB |
BIN
docs/images/ticket_info.png
Normal file
BIN
docs/images/ticket_info.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -1,3 +1,5 @@
|
||||
pathlib~=1.0.1
|
||||
requests~=2.31.0
|
||||
requests-toolbelt~=1.0.0
|
||||
requests-toolbelt~=1.0.0
|
||||
xmltodict~=0.13.0
|
||||
flask~=3.0.3
|
176
src/server.py
176
src/server.py
@ -3,25 +3,29 @@ import json
|
||||
import re
|
||||
import secrets
|
||||
import string
|
||||
|
||||
from enum import Enum
|
||||
|
||||
import requests
|
||||
import xmltodict
|
||||
|
||||
from flask import Flask, Response, jsonify, request
|
||||
from pathlib import Path
|
||||
from requests_toolbelt import MultipartEncoder
|
||||
|
||||
# Path to export data
|
||||
EXPORTS = Path(__file__).parent / 'exports.json'
|
||||
|
||||
|
||||
def parse_boundary(data: str) -> dict:
|
||||
"""
|
||||
Parse the multipart form data to extract fields.
|
||||
Parse multipart form data to extract fields.
|
||||
|
||||
Parameters:
|
||||
- data (str): The raw multipart form data as a string.
|
||||
- data (str): Raw multipart form data as a string.
|
||||
|
||||
Returns:
|
||||
- dict: A dictionary with form field names as keys and field values as values.
|
||||
- dict: A dictionary with form field names as keys and values as values.
|
||||
"""
|
||||
fields = {}
|
||||
# Split parts using the boundary (separator) and process each part
|
||||
@ -38,11 +42,28 @@ def parse_boundary(data: str) -> dict:
|
||||
|
||||
|
||||
class ServiceType(Enum):
|
||||
STREAM = 'Stream' # StreamFab, PlayerFab
|
||||
STREAM = 'Stream' # StreamFab
|
||||
MUSIC = 'Music' # MusicFab
|
||||
|
||||
|
||||
class Session:
|
||||
"""
|
||||
Session class to manage and generate random user-related data (email, MAC, etc.).
|
||||
|
||||
Attributes:
|
||||
- DOMAINS (list): Predefined list of popular email domains.
|
||||
- CHARACTERS (str): Character set used for generating random local email parts.
|
||||
- type (ServiceType): The type of service (Stream or Music).
|
||||
- max (int): Maximum number of session usages before resetting.
|
||||
- export (bool): Flag to determine if data should be exported.
|
||||
- running (dict): Stores information about the current active session.
|
||||
|
||||
Methods:
|
||||
- email (property): Generates or returns the current session email.
|
||||
- mac (property): Generates or returns the current session MAC address.
|
||||
- patch(data: dict): Patches the incoming data with session-specific fields.
|
||||
"""
|
||||
|
||||
DOMAINS = ['hotmail.com', 'gmail.com', 'yahoo.com', 'outlook.com', 'protonmail.com', 'yandex.com']
|
||||
CHARACTERS = string.ascii_lowercase + string.digits + '.-'
|
||||
|
||||
@ -56,6 +77,12 @@ class Session:
|
||||
|
||||
@property
|
||||
def email(self) -> str:
|
||||
"""
|
||||
Generate a random email address if not already set.
|
||||
|
||||
Returns:
|
||||
- str: Randomly generated or pre-set email address.
|
||||
"""
|
||||
length = secrets.choice(range(5, 15))
|
||||
return self._email or '{local}@{domain}'.format(
|
||||
local=''.join(secrets.choice(self.CHARACTERS) for _ in range(length)),
|
||||
@ -64,10 +91,19 @@ class Session:
|
||||
|
||||
@email.setter
|
||||
def email(self, value: str) -> None:
|
||||
"""
|
||||
Set the email manually if provided.
|
||||
"""
|
||||
self._email = value
|
||||
|
||||
@property
|
||||
def mac(self) -> str:
|
||||
"""
|
||||
Generate a random MAC address if not already set.
|
||||
|
||||
Returns:
|
||||
- str: Randomly generated or pre-set MAC address.
|
||||
"""
|
||||
return self._mac or ':'.join([
|
||||
'-'.join(f'{b:02x}' for b in secrets.token_bytes(6)),
|
||||
'-'.join(f'{b:02x}' for b in secrets.token_bytes(6))
|
||||
@ -75,10 +111,25 @@ class Session:
|
||||
|
||||
@mac.setter
|
||||
def mac(self, value: str) -> None:
|
||||
"""
|
||||
Set the MAC address manually if provided.
|
||||
"""
|
||||
self._mac = value
|
||||
|
||||
def patch(self, data: dict) -> dict:
|
||||
kid = data['KD']
|
||||
"""
|
||||
Patch the data dictionary with dynamic fields (email, mac, etc.).
|
||||
|
||||
Parameters:
|
||||
- data (dict): Incoming data dictionary to be patched.
|
||||
|
||||
Returns:
|
||||
- dict: Modified data dictionary with session-specific fields.
|
||||
"""
|
||||
# Use kid or current running session's kid
|
||||
kid = data.get('KD', self.running.get('kid'))
|
||||
|
||||
# Initialize new session if no session exists or conditions change
|
||||
if not self.running or self.running.get('kid') != kid or self.running.get('count') >= self.max:
|
||||
self.running = {
|
||||
'kid': kid,
|
||||
@ -87,50 +138,76 @@ class Session:
|
||||
'count': 0
|
||||
}
|
||||
|
||||
# Update necessary fields
|
||||
for key, value in data.items():
|
||||
if key in ('MD'):
|
||||
if key in ('MD', 'EM'):
|
||||
data[key] = self.running['mac']
|
||||
elif key in ('EM'):
|
||||
data[key] = self.running['email']
|
||||
elif key in ('PW', 'TK'):
|
||||
data[key] = '' # Empty password/token
|
||||
elif key in ('RT'):
|
||||
data[key] = 'trial'
|
||||
elif key in ('DS', 'IS', 'BI'):
|
||||
# Random token for certain fields
|
||||
data[key] = secrets.token_hex(16)
|
||||
elif key in ('PS'):
|
||||
data[key] = self.type.value
|
||||
elif key in ('PW', 'TK'):
|
||||
data[key] = secrets.token_hex(16)
|
||||
|
||||
# Generate an invalid KID
|
||||
data['KD'] = secrets.token_hex(16)
|
||||
elif key == 'DT' and self.export:
|
||||
# Export data if 'DT' key and export is enabled
|
||||
exports = json.loads(EXPORTS.read_bytes()) if EXPORTS.is_file() else {}
|
||||
exports[data['PD']] = value
|
||||
exports.setdefault(data['TB'], {}).setdefault(data['PD'], value)
|
||||
EXPORTS.write_text(json.dumps(exports, indent=2))
|
||||
|
||||
self.running['count'] += 1
|
||||
return data
|
||||
|
||||
|
||||
# Initialize session and Flask app
|
||||
session = Session()
|
||||
app = Flask(__name__)
|
||||
app.config.update(ALLOWED_HOSTS=['127.0.0.1', 'localhost'])
|
||||
|
||||
|
||||
@app.route('/', defaults={'path': ''})
|
||||
@app.route('/<path:path>', methods=['POST', 'GET'])
|
||||
@app.route('/<path:path>', methods=['POST'])
|
||||
def catch_all(path: str) -> Response:
|
||||
"""
|
||||
Catch-all route to proxy requests.
|
||||
Parses the multipart form data, modifies it, and forwards the request.
|
||||
|
||||
Parameters:
|
||||
- path (str): The request path for matching.
|
||||
|
||||
Returns:
|
||||
- Response: A Flask Response object containing the forwarded request's response.
|
||||
"""
|
||||
global session
|
||||
|
||||
# Remove unnecessary headers
|
||||
headers = dict(request.headers)
|
||||
del headers['Connection']
|
||||
del headers['Content-Length']
|
||||
headers.pop('Connection', None)
|
||||
headers.pop('Content-Length', None)
|
||||
|
||||
# Get raw body data
|
||||
body = request.get_data()
|
||||
boundary = parse_boundary(body.decode('utf-8'))
|
||||
patched = session.patch(boundary) # TODO: fix patch
|
||||
# patched = boundary
|
||||
mp_encoder = MultipartEncoder(patched)
|
||||
|
||||
# Extract boundary from content-type
|
||||
content_type = headers.get('Content-Type', '')
|
||||
boundary_match = re.search(r'boundary=(.*)', content_type)
|
||||
if not boundary_match:
|
||||
return Response(status=400, response='Invalid or missing boundary')
|
||||
|
||||
# Parse and patch the multipart form data
|
||||
boundary_data = parse_boundary(body.decode('utf-8'))
|
||||
patched = session.patch(boundary_data)
|
||||
|
||||
# Re-encode patched data using MultipartEncoder
|
||||
mp_encoder = MultipartEncoder(fields=patched)
|
||||
headers['Content-Type'] = mp_encoder.content_type
|
||||
body = mp_encoder.read()
|
||||
|
||||
# Forward the request to the same URL over HTTPS
|
||||
# Forward the request to the target URL over HTTPS
|
||||
r = requests.request(
|
||||
method=request.method,
|
||||
url=request.url.replace('http://', 'https://'),
|
||||
@ -141,11 +218,41 @@ def catch_all(path: str) -> Response:
|
||||
)
|
||||
|
||||
# Return the response from the forwarded request
|
||||
return Response(status=r.status_code, response=r.content)
|
||||
return Response(status=r.status_code, response=r.content, headers={'Content-Type': 'text/html; charset=UTF-8'})
|
||||
|
||||
|
||||
@app.route('/session', methods=['GET'])
|
||||
@app.route('/auth/trial_disc.php', methods=['POST'])
|
||||
def trial_disc() -> Response:
|
||||
"""
|
||||
Trial endpoint to provide disc information with MacID.
|
||||
|
||||
Returns:
|
||||
- Response: XML response containing trial disc information with the generated MacID.
|
||||
"""
|
||||
global session
|
||||
|
||||
params = request.args.to_dict()
|
||||
data = {
|
||||
'TrialOpenDiscInfo': {
|
||||
'@Client': params.get('Client', 49),
|
||||
'@MacID': params.get('MacID', session.mac)
|
||||
}
|
||||
}
|
||||
|
||||
content = xmltodict.unparse(data, pretty=False, full_document=True).encode('utf-8')
|
||||
return Response(status=200, response=content, headers={'Content-Type': 'text/html'})
|
||||
|
||||
|
||||
@app.route('/debug', methods=['GET'])
|
||||
def session_info() -> Response:
|
||||
"""
|
||||
Debug endpoint to display session information (email, MAC, etc.).
|
||||
|
||||
Returns:
|
||||
- Response: JSON response with current session data.
|
||||
"""
|
||||
global session
|
||||
|
||||
return jsonify({
|
||||
'email': session.email,
|
||||
'mac': session.mac,
|
||||
@ -155,13 +262,13 @@ def session_info() -> Response:
|
||||
|
||||
|
||||
# Add the catch_all route to Flask
|
||||
|
||||
app.add_url_rule('/', 'catch_all', catch_all, defaults={'path': ''})
|
||||
app.add_url_rule('/<path:path>', 'catch_all', catch_all, defaults={'path': ''})
|
||||
app.config.update(ALLOWED_HOSTS=['127.0.0.1', 'localhost'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Set up argument parsing
|
||||
parser = argparse.ArgumentParser(description='DVDFab-Server: ')
|
||||
parser = argparse.ArgumentParser(description='DVDFab-Server: A server for proxying requests and managing sessions for DVDFab-related services.')
|
||||
|
||||
# Command-line arguments
|
||||
parser.add_argument('--email', type=str, metavar='<email>', help='Email address (default: random)')
|
||||
@ -173,17 +280,12 @@ if __name__ == '__main__':
|
||||
# Parse the arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
# Set session values from the command-line arguments
|
||||
session.email = args.email
|
||||
session.mac = args.mac
|
||||
session.type = ServiceType[args.type]
|
||||
session.max = args.max
|
||||
session.export = args.export
|
||||
# Set session parameters based on arguments
|
||||
session.email = args.email
|
||||
session.mac = args.mac
|
||||
session.type = ServiceType[args.type]
|
||||
session.max = args.max
|
||||
session.export = args.export
|
||||
|
||||
# Start the Flask app
|
||||
app.run(host='127.0.0.1', port=5000, debug=True)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f'[!] {e}')
|
||||
# Start the Flask app
|
||||
app.run(host='127.0.0.1', port=5000, debug=False)
|
||||
|
3861
src/template.json
3861
src/template.json
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user