# -*- coding: utf-8 -*-
import sys
import re
import requests
import base64
import random
import six
if six.PY3:
    from urllib.parse import urlparse, parse_qs, quote, unquote, unquote_plus
else:
    from urlparse import urlparse, parse_qs
    from urllib import quote, unquote, unquote_plus
import socket
import threading
import os

def get_local_ip():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('10.255.255.255', 1))
        local_ip = s.getsockname()[0]
    except Exception as e:
        local_ip = '127.0.0.1'
    finally:
        try:
            s.close()
        except:
            pass
    return local_ip

HOST_NAME = get_local_ip()
PORT_NUMBER = 59332
global HEADERS_BASE
global HOST_BASE
global STOP_SERVER
HEADERS_BASE = {}
HOST_BASE = ''
STOP_SERVER = False

url_proxy = 'http://' + HOST_NAME + ':' + str(PORT_NUMBER) + '/?url='

class DNSPROXY:
    def set_headers(self, url):
        global HEADERS_BASE        
        headers_default = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive'}
        headers = {}
        
        if 'Host=' in url:
            host_header = self.extract_header_value(url, 'Host=')
            headers['Host'] = host_header
            
        if 'User-Agent=' in url:
            user_agent = self.extract_header_value(url, 'User-Agent=')
            headers['User-Agent'] = user_agent
        
        if 'Referer=' in url:
            referer = self.extract_header_value(url, 'Referer=')
            headers['Referer'] = referer
        
        if 'Origin=' in url:
            origin = self.extract_header_value(url, 'Origin=')
            headers['Origin'] = origin
        
        if headers:
            headers.update({'Connection': 'keep-alive'})
            HEADERS_ = headers
        else:
            HEADERS_ = headers_default
        
        if not HEADERS_BASE:
            HEADERS_BASE = HEADERS_

    def extract_header_value(self, url, header_name):
        value = url.split(header_name)[1]
        try:
            value = value.split('&')[0]
        except:
            pass
        try:
            value = unquote_plus(value)
        except:
            pass
        try:
            value = unquote(value)
        except:
            pass
        return value

    def send_m3u8(self, self_server, url):
        global HEADERS_BASE
        global HOST_BASE
        if '.m3u8' in url:
            self_server.send_header('Content-Type', 'application/x-mpegURL')
            self_server.end_headers()
            try:            
                host_ = 'http://' + url.split('/')[2] + '/' + url.split('/')[3]
            except:
                host_ = 'http://' + url.split('/')[2] + '/'
            HOST_BASE = host_
            try:
                r = requests.get(url, headers=HEADERS_BASE, allow_redirects=True, timeout=4, verify=False)
                code = r.status_code
                if code == 200:
                    src = r.text
                    src = src.replace(',\n', ',\nhttp://%s:%s/' % (HOST_NAME, str(PORT_NUMBER)))
                    src = src.encode('utf-8')
                    self_server.conn.sendall(src)
            except:
                pass

    def send_ts(self, self_server, url):
        global HEADERS_BASE
        global HOST_BASE
        if '.ts' in url:
            self_server.send_header('Content-Type', 'video/mp2t')
            self_server.end_headers()             
            url = HOST_BASE + url
            try:
                r = requests.get(url, headers=HEADERS_BASE, allow_redirects=True, stream=True, verify=False)
                code = r.status_code
                if code == 200:
                    for chunk in r.iter_content(50*1024): 
                        try:
                            self_server.conn.sendall(chunk)
                        except:
                            pass
            except:
                pass                   

class ProxyHandler(DNSPROXY):
    def __init__(self, conn, addr, server):
        self.conn = conn
        self.addr = addr
        self.server = server
        self.path = ""
        self.request_method = ""

    def parse_request(self, request):
        parts = request.split(b' ')
        self.request_method = parts[0].decode()

    def parse_request2(self, request):
        parts = request.split(b' ')
        if len(parts) >= 2:
            self.path = parts[1].decode()

    def send_response(self, code, message=None):
        response = "HTTP/1.1 {} {}\r\n".format(code, message if message else "")
        self.conn.sendall(response.encode())

    def send_header(self, keyword, value):
        header = "{}: {}\r\n".format(keyword, value)
        self.conn.sendall(header.encode())

    def end_headers(self):
        self.conn.sendall(b"\r\n")

    def handle_request(self):
        global HOST_BASE
        global HEADERS_BASE
        global STOP_SERVER
        request_data = self.conn.recv(1024)
        self.parse_request(request_data)
        self.parse_request2(request_data)
        if self.request_method == 'HEAD':
            self.send_response(200)  # envia status 200 sempre
            pass
        elif self.path == '/check':
            self.send_response(200) # envia status 200 sempre
            self.send_header("Content-type", "text/html")
            self.end_headers()
            self.conn.sendall(b"Hello, world!")        
        elif self.path == "/reset":
            self.send_response(200)  # envia status 200 sempre
            HOST_BASE = ''
            HEADERS_BASE = {}
        elif self.path == "/stop":
            self.send_response(200)  # envia status 200 sempre
            HOST_BASE = ''
            HEADERS_BASE = {}
            STOP_SERVER = True
            try:          
                self.server.stop_server()
            except:
                pass
            try:
                self.server.server_socket.close()
            except:
                pass
        else:
            url_path = unquote_plus(self.path)
            self.set_headers(url_path)
            url_parts = urlparse(url_path)
            query_params = parse_qs(url_parts.query)
            if 'url' in query_params:
                url = url_path.split('url=')[1]
                try:
                    url = base64.b64decode(url).decode('utf-8')
                except:
                    pass
                try:
                    url = url.split('|')[0]
                except:
                    pass
                try:
                    url = url.split('%7C')[0]
                except:
                    pass
            else:
                url = url_path
            if '.m3u8' in url:
                #print('pegou a url')
                self.send_response(200)  # envia status 200 sempre
                self.send_m3u8(self, url)
            elif '.ts' in url and not '.m3u8' in url:
                self.send_response(200)  # envia status 200 sempre
                self.send_ts(self, url)
        self.conn.close()  # Fechar o socket de conexão após enviar a resposta                 

class Server:
    def __init__(self):
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket.bind((HOST_NAME, PORT_NUMBER))
        self.server_socket.listen(10)
        
    def serve_forever(self): 
        global STOP_SERVER
        while True:
            if STOP_SERVER:
                break
            conn, addr = self.server_socket.accept()
            handler = ProxyHandler(conn, addr, self)
            threading.Thread(target=handler.handle_request).start() 

    def stop_server(self):
        try:
            self.server_socket.close()
        except:
            pass

def loop_server():
    server = Server()
    server.serve_forever()

def monitor():
    try:
        from kodi_six import xbmc
        dependence = True
    except:
        try:
            import xbmc
            dependence = True
        except:
            dependence = False
    if dependence:
        monitor = xbmc.Monitor()
        while not monitor.waitForAbort(3):
            pass
        url = 'http://'+HOST_NAME+':'+str(PORT_NUMBER)+'/stop'
        try:
            r = requests.get(url,timeout=4)
        except:
            pass
        #sys.exit()
        try:
            os._exit(1)
        except:
            pass
  

class DNSProxyManager:
    def reset(self):
        try:
            url = 'http://'+HOST_NAME+':'+str(PORT_NUMBER)+'/reset'
            r = requests.get(url,timeout=3)
        except:
            pass
    def check_service(self):
        try:
            url = 'http://'+HOST_NAME+':'+str(PORT_NUMBER)+'/check'
            r = requests.head(url,timeout=3)
            if r.status_code == 200:
                return True
            return False
        except:
            return False           
    def start(self):
        status = self.check_service()
        if status == False:
            proxy_service = threading.Thread(target=loop_server).start()
            monitor_service = threading.Thread(target=monitor).start()
        else:
            self.reset()

# url_m3u8 = 'http://104.21.50.99/combate/tracks-v1a1/mono.ts.m3u8|Host=embedcanaistv.club&Origin=http://embedcanaistv.com&Referer=http://embedcanaistv.com/'
# url_final = url_proxy + quote_plus(url_m3u8)
# print(url_final)

# DNSProxyManager().start()
