import os
import re
import shutil
import requests
import lzma
import gzip
import subprocess
def download_and_extract(url, process_directory):
filename = url.split('/')[-1]
xz_path = os.path.join(process_directory, filename)
target_filename = filename.replace('.xz', '')
target_path = os.path.join(process_directory, target_filename)
print(f"Downloading {url}...")
response = requests.get(url)
with open(xz_path, 'wb') as file:
file.write(response.content)
with lzma.open(xz_path) as f, open(target_path, 'wb') as fout:
file_content = f.read()
fout.write(file_content)
if os.path.exists(xz_path):
os.remove(xz_path)
return target_path
def build_epg(temp_directory, target_directory, matching_files):
temp_file_path = os.path.join(temp_directory, 'epgtemp.xml')
with open(temp_file_path, 'a') as output_file:
output_file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
first_file_path = matching_files[0]
with open(first_file_path, 'r') as first_file_content:
first_content = first_file_content.read()
header_and_channels = re.findall(r'<tv[^>]*>.*?<channel id="[^"]+">.*?</channel>', first_content, re.DOTALL)
for part in header_and_channels:
output_file.write(part + '\n')
for file in matching_files:
with open(file, 'r') as temp_file_content:
content = temp_file_content.read()
channels = re.findall(r'<channel id="[^"]+">.*?</channel>', content, re.DOTALL)
for channel_content in channels:
output_file.write(channel_content + '\n')
for file in matching_files:
with open(file, 'r') as temp_file_content:
content = temp_file_content.read()
programmes = re.findall(r'<programme start="[^"]+".*?</programme>', content, re.DOTALL)
for programme_content in programmes:
output_file.write(programme_content + '\n')
output_file.write('</tv>\n')
final_file_path = os.path.join(target_directory, 'epg.xml')
shutil.move(temp_file_path, final_file_path)
print(f'EPG has been created and saved in {final_file_path}.')
urls = {
"DE": [
"http://www.xmltvepg.nl/rytecDE_Basic.xz",
"http://www.xmltvepg.nl/rytecDE_Common.xz",
"http://www.xmltvepg.nl/rytecDE_SportMovies.xz"
],
"AT": [
"http://www.xmltvepg.nl/rytecAT_Basic.xz"
],
"CH": [
"http://www.xmltvepg.nl/rytecCH_Basic.xz"
],
"IPTV": [
"http://www.xmltvepg.nl/rytecIPTV.xz"
],
"Misc": [
"http://www.xmltvepg.nl/rytecMisc.xz"
],
"NL": [
"http://www.xmltvepg.nl/rytecNL_Basic.xz",
"http://www.xmltvepg.nl/rytecNL_Extra.xz"
],
"BE": [
"http://www.xmltvepg.nl/rytecBE_VL_Basic.xz",
"http://www.xmltvepg.nl/rytecBE_NL_Common.xz",
"http://www.xmltvepg.nl/rytecBE_FR_Basic.xz",
"http://www.xmltvepg.nl/rytecBE_FR_Common.xz"
],
"TNT": [
"http://www.xmltvepg.nl/rytecTNT_Basic.xz"
],
"FR": [
"http://www.xmltvepg.nl/rytecFR_Mixte.xz",
"http://www.xmltvepg.nl/rytecFR_SportMovies.xz"
],
"BG": [
"http://www.xmltvepg.nl/rytecBG.xz"
],
"CZ": [
"http://www.xmltvepg.nl/rytecCZ_Basic.xz",
"http://www.xmltvepg.nl/rytecCZ_SK_Common.xz",
"http://www.xmltvepg.nl/rytecCZ_SK_SportMovies.xz"
],
"DK": [
"http://www.xmltvepg.nl/rytecDK_Basic.xz",
"http://www.xmltvepg.nl/rytecDK_Misc.xz"
],
"GR": [
"http://www.xmltvepg.nl/rytecGR_Basic.xz",
"http://www.xmltvepg.nl/rytecGR_SportMovies.xz"
],
"IT": [
"http://www.xmltvepg.nl/rytecIT_Basic.xz",
"http://www.xmltvepg.nl/rytecIT_Sky.xz",
"http://www.xmltvepg.nl/rytecIT_SportMovies.xz"
],
"azman": [
"http://www.xmltvepg.nl/azman_basic.xml.xz",
"http://www.xmltvepg.nl/azman_misc.xml.xz",
"http://www.xmltvepg.nl/azman_iptv.xml.xz"
],
"PT": [
"http://www.xmltvepg.nl/rytecPT.xz"
],
"HU": [
"http://www.xmltvepg.nl/rytecHU_Basic.xz",
"http://www.xmltvepg.nl/rytecHU_SportMovies.xz"
],
"NO": [
"http://www.xmltvepg.nl/rytecNO_Basic.xz",
"http://www.xmltvepg.nl/rytecNO_Misc.xz",
"http://www.xmltvepg.nl/rytecNO_SportMovies.xz"
],
"RO": [
"http://www.xmltvepg.nl/rytecRO_Basic.xz",
"http://www.xmltvepg.nl/rytecRO_SportMovies.xz"
],
"HRV": [
"http://www.xmltvepg.nl/rytecHRV_Basic.xz",
"http://www.xmltvepg.nl/rytecHRV_Misc.xz",
"http://www.xmltvepg.nl/rytecHRV_SportMovies.xz"
],
"SRB": [
"http://www.xmltvepg.nl/rytecSRB_Basic.xz",
"http://www.xmltvepg.nl/rytecSRB_Misc.xz"
],
"SVN": [
"http://www.xmltvepg.nl/rytecSVN_Basic.xz",
"http://www.xmltvepg.nl/rytecSVN_Misc.xz",
"http://www.xmltvepg.nl/rytecSVN_SportMovies.xz"
],
"SE": [
"http://www.xmltvepg.nl/rytecSE_Basic.xz",
"http://www.xmltvepg.nl/rytecSE_Misc.xz",
"http://www.xmltvepg.nl/rytecSE_SportMovies.xz"
],
"FI": [
"http://www.xmltvepg.nl/rytecFI_Basic.xz",
"http://www.xmltvepg.nl/rytecFI_Misc.xz",
"http://www.xmltvepg.nl/rytecFI_SportMovies.xz"
],
"UK": [
"http://www.xmltvepg.nl/rytecUK_Basic.xz",
"http://www.xmltvepg.nl/rytecUK_SkyLive.xz",
"http://www.xmltvepg.nl/rytecUK_SportMovies.xz"
]
}
current_dir = os.path.dirname(os.path.realpath(__file__))
temp_folder = os.path.join(current_dir, 'temp')
process_folder = os.path.join(temp_folder, 'process')
target_folder = current_dir
print("Available country codes:")
for key in urls.keys():
print(key)
country_codes = input("Enter the country codes (comma-separated, e.g., DE, SE, FI, UK): ").split(',')
selected_urls = [url for code in country_codes for key, url_list in urls.items() if code.strip().upper() == key for url in url_list]
if not selected_urls:
print(f"No URLs found for country codes {country_codes}. Exiting.")
exit(1)
if not os.path.exists(process_folder):
os.makedirs(process_folder)
matching_files = []
for url in selected_urls:
file_path = download_and_extract(url, process_folder)
matching_files.append(file_path)
if matching_files:
build_epg(temp_folder, target_folder, matching_files)
else:
print(f"No matching EPG data files found for {country_codes}.")
epg_xml_path = os.path.join(target_folder, 'epg.xml')
epg_gz_path = os.path.join(target_folder, 'epg.xml.gz')
with open(epg_xml_path, 'rb') as f_in, gzip.open(epg_gz_path, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
print(f'EPG has been compressed and saved as {epg_gz_path}.')
shutil.rmtree(temp_folder)
try:
subprocess.run(['chmod', '755', epg_gz_path])
except Exception as e:
print(f'Failed to change permissions of epg.xml.gz: {e}')
try:
subprocess.run(['chown', 'www-data:www-data', epg_gz_path])
except Exception as e:
print(f'Failed to change owner of epg.xml.gz: {e}')