#!/usr/bin/python3
import os
import re
import subprocess
import sys

ver = "1.3"
f"""
 Hardware ID output script
 Version {ver}
 Last update: 09-06-2022

 Mail: vladlen.murylyov@red-soft.ru
 (c) RED SOFT
"""

version = f"script version {ver}\n"


if not os.path.isdir("/tmp/loginfo"):
    os.system("mkdir -p /tmp/loginfo")
date = os.popen("echo $(date \'+%F-%T\')").readline().strip()
filename = f'/tmp/loginfo/hw-id-{date}.txt'


def modinfo(d, vid, did):
    d_ = re.sub(r"[\_\-\:\\]", "*", d)
    if os.popen(f"find /usr/lib/modules/$(uname -r)/ -name {d_}*").readline():
        modinfo = subprocess.Popen(f'modinfo {d} | grep -i {vid} | grep -i {did}',
                                   stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                   shell=True)
        drova = modinfo.communicate()[0].decode("utf-8").strip()
        if drova == "" or drova is None:
            modinfo = subprocess.Popen(f'modinfo {d} | grep -i {vid}',
                                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                       shell=True)
            drova = modinfo.communicate()[0].decode("utf-8").strip()
        return drova

def inxi_fun(inxi, flag):
    inxi = re.sub("\x03", ":", inxi)
    pattern = r'Device-[0-9]*:'
    devices = re.split(pattern, inxi)
    devices = devices[1:]
    for i in range(0, len(devices)):
        devices[i] = f"Device-{i + 1}: {devices[i]}"
        device = re.findall(r'Device-[0-9]*: [ /\[\]\(\)A-Za-z_0-9-]*', devices[i], re.MULTILINE + re.DOTALL)
        device = re.sub(r'vendor|type|info', '', device[0])
        vendors = re.findall(r'vendor. [\:A-Za-z\_0-9\-]*', devices[i], re.MULTILINE + re.DOTALL)
        driver = re.findall(r'driver. [/,:A-Za-z_0-9-]*', devices[i], re.MULTILINE + re.DOTALL)
        chip_IDS = re.findall(r'chip ID. [:A-Za-z_0-9-]*', devices[i], re.MULTILINE + re.DOTALL)
        info = re.findall(r'info. [ \[\]\(\)A-Za-z_0-9-]*', devices[i], re.MULTILINE + re.DOTALL)
        info = re.sub(r'type', '', info[0]) if len(info) > 0 else ""
        modules = re.findall(r'modules. [/,:A-Za-z_0-9-]*', devices[i], re.MULTILINE + re.DOTALL)
        out = ""
        out += f"{device.strip()}\n" if len(devices) > 0 else ""
        out += f"{vendors[0].strip()}\n" if len(vendors) > 0 else ""
        out += f"{info.strip()}\n" if len(info) > 0 else ""
        out += f"{driver[0].strip()}\n" if len(driver) > 0 else ""
        out += f"{chip_IDS[0].strip()}\n" if len(chip_IDS) > 0 else ""
        if len(chip_IDS) > 0:
            vid, did = re.sub("chip ID: ", "", chip_IDS[0]).split(":")

            lspci = subprocess.Popen(f'lspci -n -k -d {vid}:{did}',
                                     stdout=subprocess.PIPE,
                                     shell=True)
            svid, sdid = None, None
            if lspci != "" and lspci:
                lspci = lspci.communicate()[0].decode("utf-8")
                lspci = re.findall(r'Subsystem. [:A-Za-z_0-9-]*', lspci, re.MULTILINE + re.DOTALL)
                if lspci != "" and lspci:
                    svid, sdid = re.sub(r"Subsystem. ", "", lspci[0]).split(":")

            if "N/A" not in driver[0]:
                dr = re.sub("driver: ", "", driver[0]).split(",")
                if len(modules) > 0:
                    for d in dr:
                        drova = modinfo(d, vid, did)
                        if drova != "" and drova:
                            out += f"{d} {drova}\n"
                        else:
                            for j in modules:
                                mod = re.sub("modules: ", "", j).split(",")
                                for m in mod:
                                    drova = modinfo(m, vid, did)
                                    if drova != "" and drova:
                                        out += f"{m} {drova}\n"
                                    else:
                                        out += f"module in use: {m}\n"
                else:
                    for d in dr:
                        drova = modinfo(d, vid, did)
                        if drova != "" and drova:
                            out += f"{d} {drova}\n"

            if svid and sdid:
                out += "\nЗдесь вы можете найти ваше устройство с идентичными VID:DID:SVID:SDID\n"
                out += f"https://linux-hardware.org/?view=search" \
                       f"&vendorid={vid}" \
                       f"&deviceid={did}" \
                       f"&subvendorid={svid}" \
                       f"&subdeviceid={sdid}#list \n "

            else:
                out += "\nЗдесь вы можете найти ваше устройство с идентичными VID:DID\n"
                out += f"https://linux-hardware.org/?view=search" \
                       f"&vendorid={vid}" \
                       f"&deviceid={did}#list \n"
        if flag:
            with open(filename, "a") as f:
                print(out, file=f)
        else:
            print(out)

def hwid(usefile):
    if usefile == "-nofile":
        flag = False
    else:
        flag = True
    if flag:
        with open(filename, "a") as f:
            print(version, file=f)
    else:
        print(version)
    for letter in ["A", "G", "N", "J"]:
        if flag:
            with open(filename, "a") as f:
                if letter == "A":
                    print("# Audio output #", file=f)
                elif letter == "G":
                    print("# Graphics output #", file=f)
                elif letter == "N":
                    print("# Network output #", file=f)
                elif letter == "J":
                    print("# Usb output #", file=f)
        else:
            if letter == "A":
                print("# Audio output #")
            elif letter == "G":
                print("# Graphics output #")
            elif letter == "N":
                print("# Network output #")
            elif letter == "J":
                print("# Usb output #")
        inxi = subprocess.Popen(f'inxi -a -{letter}',
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                shell=True)
        inxi = inxi.communicate()[0].decode("utf-8")
        if "Unsupported option" in inxi and letter == "J":
            inxi = subprocess.Popen(f'inxi -a --usb',
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    shell=True)
            inxi = inxi.communicate()[0].decode("utf-8")
            if "Unsupported option" in inxi:
                pass
            else:
                inxi_fun(inxi, flag)
        else:
            inxi_fun(inxi, flag)
        if flag:
            with open(filename, "a") as f:
                print("-------------------------------", file=f)
        else:
            print("-------------------------------")

if __name__ == "__main__":
    if len(sys.argv) > 1:
        if sys.argv[1] == "-nofile":
            hwid("-nofile")
    else:
        hwid(filename)
        print(f'Создан файл {filename}')
