Source code for airshare.utils

"""Utility functions for Airshare."""


import magic
import os
import pyperclip
import re
import requests
import socket
import tempfile
from time import strftime
from tqdm import tqdm
from zipfile import ZipFile
from zeroconf import IPVersion, ServiceInfo, Zeroconf


__all__ = ["get_local_ip_address", "get_service_info", "register_service",
           "get_zip_file", "unzip_file", "get_clipboard_paths",
           "is_file_copyable"]


# Local IP Address


[docs]def get_local_ip_address(): r"""Obtains the device's local network IP address. Returns ------- ip : bytes Packed 32-bit representation of the device's local IP Address. """ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("10.255.255.255", 1)) ip = s.getsockname()[0] s.close() ip = socket.inet_aton(ip) return ip
# Zeroconf Utilities
[docs]def get_service_info(code): r"""Get service information for an Airshare service. Parameters ---------- code : str Identifying code for the Airshare service. Returns ------- info : zeroconf.ServiceInfo Details of the Airshare service. """ zeroconf = Zeroconf(ip_version=IPVersion.V4Only) service = "_airshare._http._tcp.local." info = zeroconf.get_service_info(service, code + service) return info
[docs]def register_service(code, addresses, port): r"""Registers an Airshare Multicast-DNS service based in the local network. Parameters ---------- code : str Identifying code for the Airshare service. addresses : list List of local network IP Addresses for the service. port : int Port number for the Airshare service's server. Returns ------- info : zeroconf.ServiceInfo Details of the Airshare service. """ zeroconf = Zeroconf(ip_version=IPVersion.V4Only) service = "_airshare._http._tcp.local." info = ServiceInfo( service, code + service, addresses=addresses, port=port, server=code + ".local." ) zeroconf.register_service(info) return info
# Zip and Unzip
[docs]def get_zip_file(files): r"""Creates a temporary Zip Archive of files and directories. Parameters ---------- files : list List of paths of files and directories to compress. Returns ------- zip_file_path : str Canonical file path of the temporary Zip Archive file. zip_file_name : str File name to be assigned to the Zip Archive (during sending). """ files = [os.path.realpath(x) for x in files] _, zip_file_path = tempfile.mkstemp(prefix="airshare", suffix=".zip") zip_archive = ZipFile(zip_file_path, "w") num_files = len(files) index = -1 if num_files == 1: index = 0 for item in files: index += len(item.split(os.path.sep)) if os.path.isdir(item): for root, _, file_list in os.walk(item): for file in file_list: file_path = os.path.realpath(os.path.join(root, file)) zip_archive.write(file_path, os.path.join( *tuple(root.split(os.path.sep)[index:] + [file]))) else: file_path = os.path.realpath(item) zip_archive.write(file_path, os.path.join( *tuple(file_path.split(os.path.sep)[index:]))) index = -1 zip_archive.close() zip_file_path = os.path.abspath(zip_file_path) zip_file_name = "airshare.zip" if num_files == 1: zip_file_name = os.path.splitext( os.path.realpath(files[0]).split(os.path.sep)[-1])[0] + ".zip" return zip_file_path, zip_file_name
[docs]def unzip_file(zip_file_path): r"""Unzips a Zip Archive file into a new directory. Parameters ---------- zip_file_path : str Path of the Zip Archive file to unzip. Returns ------- zip_dir : str Canonical path of the unzipped directory. """ zip_dir = zip_file_path[:-4] if os.path.isdir(zip_dir): zip_dir += "-" + strftime("%Y%m%d%H%M%S") os.mkdir(zip_dir) with ZipFile(zip_file_path, "r") as zip_archive: zip_archive.extractall(zip_dir) zip_dir = os.path.realpath(zip_dir) return zip_dir
# Clipboard Utilities
[docs]def get_clipboard_paths(): r"""Extract file paths from the clipboard. Returns ------- file_paths : list List of canonical paths extracted from the clipboard. """ file_paths = [] clipboard = pyperclip.paste() erase = ["x-special/nautilus-clipboard\ncopy\n", "file://", "\r", "'", '"'] file_paths = re.sub("|".join(erase), "", clipboard.strip()).split("\n") file_paths = [os.path.realpath(str(x).strip()) for x in file_paths] return file_paths
[docs]def is_file_copyable(file_path): r"""Check if a file can be copied to the clipboard or not. Parameters ---------- file_path : str Path of the file to check. Returns ------- copyable : boolean True if the file can be copied to the clipboard, False otherwise. """ file_type = magic.Magic(mime=True).from_file(file_path) if (re.findall("text|json", file_type, re.IGNORECASE)): copyable = True else: copyable = False return copyable