diff --git a/tvtvus/ch_json2xml.pl b/tvtvus/ch_json2xml.pl
new file mode 100644
index 0000000..9a5e12f
--- /dev/null
+++ b/tvtvus/ch_json2xml.pl
@@ -0,0 +1,143 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+# ###############################
+# TVSPIELFILM JSON > XML CONVERTER #
+# ###############################
+
+# CHANNELS
+
+use strict;
+use warnings;
+
+binmode STDOUT, ":utf8";
+use utf8;
+
+use JSON;
+
+# READ JSON INPUT FILE: CHLIST
+my $json;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "chlist" or die;
+ $json = <$fh>;
+ close $fh;
+}
+
+# READ JSON INPUT FILE: SWC HARDCODED CHLIST
+my $chlist;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "tvtvus_channels.json" or die;
+ $chlist = <$fh>;
+ close $fh;
+}
+
+# READ JSON INPUT FILE: CHANNEL CONFIG
+my $chlist_config;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "channels.json" or die;
+ $chlist_config = <$fh>;
+ close $fh;
+}
+
+# READ INIT FILE
+my $init;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, '<', "init.json" or die;
+ $init = <$fh>;
+ close $fh;
+}
+
+# READ SETTINGS FILE
+my $settings;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, '<', "settings.json" or die;
+ $settings = <$fh>;
+ close $fh;
+}
+
+# CONVERT JSON TO PERL STRUCTURES
+my $data = decode_json($json);
+my $chdata = decode_json($chlist);
+my $configdata = decode_json($chlist_config);
+my $initdata = decode_json($init);
+my $setupdata = decode_json($settings);
+
+# DEFINE COUNTRY VERSION
+my $countryVER = $initdata->{'country'};
+
+my @stations = @{ $data->{'stations'} };
+foreach my $stations ( @stations ) {
+
+ # ####################
+ # DEFINE JSON VALUES #
+ # ####################
+
+ # DEFINE CHANNEL ID + NAME
+ my $cname = $stations->{'name'};
+ $cname =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+
+ # DEFINE LANGUAGE VERSION
+ # my $languageVER = $initdata->{'language'};
+ my $languageVER = $stations->{'Languages'}[0];
+
+ # DEFINE RYTEC CHANNEL ID (language)
+ my $rytec = $chdata->{'channels'}{$countryVER};
+
+ # DEFINE SELECTED CHANNELS
+ my @configdata = @{ $configdata->{'channels'} };
+
+ # DEFINE SETTINGS
+ my $setup_general = $setupdata->{'settings'};
+ my $setup_cid = $setup_general->{'cid'};
+
+ # DEFINE SETTINGS VALUES
+ my $enabled = "enabled";
+ my $disabled = "disabled";
+
+
+ # ##################
+ # PRINT XML OUTPUT #
+ # ##################
+
+ # CHANNEL ID (condition) (settings)
+ foreach my $selected_channel ( @configdata ) {
+ if( $cname eq $selected_channel ) {
+ if( $setup_cid eq $enabled ) {
+ if( defined $rytec->{$cname} ) {
+ print "{$cname} . "\">";
+ } else {
+ print "";
+ print STDERR "[ CHLIST WARNING ] Rytec ID not matched for: " . $cname . "\n";
+ }
+ } else {
+ print "";
+ }
+
+ # CHANNEL NAME (language)
+ print "" . $cname . "\n";
+ }
+ }
+}
diff --git a/tvtvus/chlist_printer.pl b/tvtvus/chlist_printer.pl
new file mode 100644
index 0000000..d8543eb
--- /dev/null
+++ b/tvtvus/chlist_printer.pl
@@ -0,0 +1,179 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+# ################################
+# TVTV-US CHANNEL LIST CREATOR #
+# ################################
+
+# CREATE JSON FILE FOR COMPARISM
+
+use strict;
+use warnings;
+
+binmode STDOUT, ":utf8";
+use utf8;
+
+use JSON;
+
+# READ JSON INPUT FILE: NEW CHLIST
+my $chlist_new;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "/tmp/chlist" or die;
+ $chlist_new = <$fh>;
+ close $fh;
+}
+
+# READ JSON INPUT FILE: OLD CHLIST
+my $chlist_old;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "chlist_old" or die;
+ $chlist_old = <$fh>;
+ close $fh;
+}
+
+# READ JSON INPUT FILE: CHANNEL CONFIG
+my $chlist_config;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "channels.json" or die;
+ $chlist_config = <$fh>;
+ close $fh;
+}
+
+# CONVERT JSON TO PERL STRUCTURES
+my $newdata = decode_json($chlist_new);
+my $olddata = decode_json($chlist_old);
+my $configdata = decode_json($chlist_config);
+
+
+# ##################
+# NEW CHANNEL LIST #
+# ##################
+
+# TOOL: NAME ==> ID
+
+print "{ \"newname2id\": {\n";
+
+my @newchannels_name2id = @{ $newdata->{'stations'} };
+foreach my $newchannels ( @newchannels_name2id ) {
+
+ #
+ # DEFINE JSON VALUES
+ #
+
+ # DEFINE NEW CHANNEL NAME
+ my $newcname = $newchannels->{'name'};
+ $newcname =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+
+ # DEFINE NEW CHANNEL ID
+ my $newcid = $newchannels->{'channelNumber'};
+
+ # PRINT NEW CHANNEL NAMES
+ print "\"$newcname\": \"$newcid\",\n";
+}
+
+# TOOL: ID ==> NAME
+
+print "\"DUMMY\": \"DUMMY\" },\n\"newid2name\": {\n";
+
+my @newchannels_id2name = @{ $newdata->{'stations'} };
+foreach my $newchannels ( @newchannels_id2name ) {
+
+ #
+ # DEFINE JSON VALUES
+ #
+
+ # DEFINE NEW CHANNEL NAME
+ my $newcname = $newchannels->{'name'};
+ $newcname =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+
+ # DEFINE NEW CHANNEL ID
+ my $newcid = $newchannels->{'channelNumber'};
+
+ # PRINT NEW CHANNEL NAMES newcid
+ print "\"$newcid\": \"$newcname\",\n";
+}
+
+
+# ##################
+# OLD CHANNEL LIST #
+# ##################
+
+# TOOL: NAME ==> ID
+
+print "\"DUMMY\": \"DUMMY\" },\n\"oldname2id\": {\n";
+
+my @oldchannels_name2id = @{ $olddata->{'stations'} };
+foreach my $oldchannels ( @oldchannels_name2id ) {
+
+ #
+ # DEFINE JSON VALUES
+ #
+
+ # DEFINE OLD CHANNEL NAME
+ my $oldcname = $oldchannels->{'name'};
+ $oldcname =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+
+ # DEFINE OLD CHANNEL ID
+ my $oldcid = $oldchannels->{'channelNumber'};
+
+ # PRINT OLD CHANNEL NAMES
+ print "\"$oldcname\": \"$oldcid\",\n";
+}
+
+# TOOL: ID ==> NAME
+
+print "\"DUMMY\": \"DUMMY\" },\n\"oldid2name\": {\n";
+
+my @oldchannels_id2name = @{ $olddata->{'stations'} };
+foreach my $oldchannels ( @oldchannels_id2name ) {
+
+ #
+ # DEFINE JSON VALUES
+ #
+
+ # DEFINE OLD CHANNEL NAME
+ my $oldcname = $oldchannels->{'name'};
+ $oldcname =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+
+ # DEFINE OLD CHANNEL ID
+ my $oldcid = $oldchannels->{'channelNumber'};
+
+ # PRINT OLD CHANNEL NAMES
+ print "\"$oldcid\": \"$oldcname\",\n";
+}
+
+
+# #######################
+# CHANNEL CONFIGURATION #
+# #######################
+
+print "\"DUMMY\": \"DUMMY\" },\n\"config\": [\n";
+
+my @configdata = @{ $configdata->{'channels'} };
+
+foreach my $configname ( @configdata ) {
+ print "\"$configname\",\n";
+}
+
+print "\"DUMMY\"]\n}";
diff --git a/tvtvus/cid_json.pl b/tvtvus/cid_json.pl
new file mode 100644
index 0000000..ac87ba2
--- /dev/null
+++ b/tvtvus/cid_json.pl
@@ -0,0 +1,72 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+# ###############################
+# TVSPIELFILM CHANNEL ID CREATOR #
+# ###############################
+
+# CHANNEL IDs
+
+use strict;
+use warnings;
+
+binmode STDOUT, ":utf8";
+use utf8;
+
+use JSON;
+
+# READ JSON INPUT FILE: CHLIST
+my $json;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "/tmp/chlist" or die;
+ $json = <$fh>;
+ close $fh;
+}
+
+# CONVERT JSON TO PERL STRUCTURES
+my $data = decode_json($json);
+
+print "{ \"cid\":\n {\n";
+
+my @stations = @{ $data->{'stations'} };
+foreach my $stations ( @stations ) {
+
+ # ####################
+ # DEFINE JSON VALUES #
+ # ####################
+
+ # DEFINE CHANNEL NAME
+ my $cname = $stations->{'name'};
+ $cname =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+
+ # DEFINE CHANNEL ID
+ my $cid = $stations->{'channelNumber'};
+
+ # ###################
+ # PRINT JSON OUTPUT #
+ # ###################
+
+ # CHANNEL ID (condition)
+ print " \"$cid\":\"$cname\",\n";
+}
+
+print " \"000000000000\":\"DUMMY\"\n }\n}";
diff --git a/tvtvus/compare_crid.pl b/tvtvus/compare_crid.pl
new file mode 100644
index 0000000..087c287
--- /dev/null
+++ b/tvtvus/compare_crid.pl
@@ -0,0 +1,66 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg/hzn
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+# ###############################
+# TVTV CHANNEL LIST CREATOR #
+# ###############################
+
+use strict;
+use warnings;
+
+binmode STDOUT, ":utf8";
+use utf8;
+
+use JSON;
+
+# READ JSON INPUT FILE: MANIFEST
+my $manifests;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "/tmp/epg_workfile" or die;
+ $manifests = <$fh>;
+ close $fh;
+}
+
+# CONVERT JSON TO PERL STRUCTURES
+my $manifestsdata = decode_json($manifests);
+
+#
+# DEFINE JSON VALUES
+#
+my @attributes = @{ $manifestsdata->{'attributes'} };
+
+# DEFINE manifests STRINGS
+foreach my $attributes ( @attributes ) {
+
+ my @listings = @{ $attributes->{'listings'} };
+ foreach my $listings ( @listings ) {
+
+ # ####################
+ # DEFINE JSON VALUES #
+ # ####################
+
+ # DEFINE TIMES AND CHANNEL ID
+ my $showID = $listings->{'showID'};
+
+ print $showID. "\n";
+ }
+}
\ No newline at end of file
diff --git a/tvtvus/compare_menu.pl b/tvtvus/compare_menu.pl
new file mode 100644
index 0000000..70df543
--- /dev/null
+++ b/tvtvus/compare_menu.pl
@@ -0,0 +1,81 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+# #################################
+# TVTV-US TV CHANNEL LIST CREATOR #
+# #################################
+
+# COMPARE STRINGS, CREATE MENU LIST
+
+use strict;
+use warnings;
+
+binmode STDOUT, ":utf8";
+use utf8;
+
+use JSON;
+
+# READ JSON INPUT FILE: COMPARISM LIST
+my $json;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "/tmp/compare.json" or die;
+ $json = <$fh>;
+ close $fh;
+}
+
+# CONVERT JSON TO PERL STRUCTURES
+my $data = decode_json($json);
+
+
+#
+# DEFINE JSON VALUES
+#
+
+my $new_name2id = $data->{'newname2id'};
+my $new_id2name = $data->{'newid2name'};
+my $old_name2id = $data->{'oldname2id'};
+my $old_id2name = $data->{'oldid2name'};
+my @configname = @{ $data->{'config'} };
+
+
+#
+# COMPARE VALUES + CREATE MENU LIST
+#
+
+foreach my $configname ( @configname ) {
+
+ # DEFINE IDs
+ my $old_id = $old_name2id->{$configname};
+ my $new_id = $new_name2id->{$configname};
+
+ # FIND MATCH - NEW + OLD CHANNEL ID VIA CONFIG NAME
+ if( $new_id eq $old_id ) {
+ print "$configname\n";
+
+ # IF MATCH NOT FOUND: FIND CHANNEL NAME IN NEW CHANNEL LIST
+ } elsif( defined $new_id ) {
+ print "$configname\n";
+ print STDERR "[ INFO ] CHANNEL \"$configname\" received new Channel ID!\n";
+ } else {
+ print STDERR "[ WARNING ] CHANNEL $configname not found in channel lists!\n";
+ }
+}
diff --git a/tvtvus/epg_json2xml.pl b/tvtvus/epg_json2xml.pl
new file mode 100644
index 0000000..7e470df
--- /dev/null
+++ b/tvtvus/epg_json2xml.pl
@@ -0,0 +1,426 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+# #################################
+# TVTV-US JSON > XML CONVERTER #
+# #################################
+
+# EPG
+
+use strict;
+use warnings;
+
+binmode STDOUT, ":utf8";
+
+use utf8;
+use JSON;
+use Data::Dumper;
+use Time::Piece;
+use DateTime::Format::Strptime;
+
+# READ JSON INPUT FILE: EPG WORKFILE
+my $json;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "/tmp/epg_workfile" or die;
+ $json = <$fh>;
+ close $fh;
+}
+
+# READ JSON INPUT FILE: MAGENTA NUMERIC CHANNEL IDs
+my $chidlist;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "tvtvus_cid.json" or die;
+ $chidlist = <$fh>;
+ close $fh;
+}
+
+# READ JSON INPUT FILE: RYTEC ID LIST
+my $chlist;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "tvtvus_channels.json" or die;
+ $chlist = <$fh>;
+ close $fh;
+}
+
+# READ JSON INPUT FILE: EIT CATEGORY LIST
+my $genrelist;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "tvtvus_genres.json" or die;
+ $genrelist = <$fh>;
+ close $fh;
+}
+
+# READ INIT FILE
+my $init;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, '<', "init.json" or die;
+ $init = <$fh>;
+ close $fh;
+}
+
+# READ SETTINGS FILE
+my $settings;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, '<', "settings.json" or die;
+ $settings = <$fh>;
+ close $fh;
+}
+
+# CONVERT JSON TO PERL STRUCTURES
+my $data = decode_json($json);
+my $chdata = decode_json($chlist);
+my $chiddata = decode_json($chidlist);
+my $genredata = decode_json($genrelist);
+my $initdata = decode_json($init);
+my $setupdata = decode_json($settings);
+
+# DEFINE COUNTRY VERSION
+my $countryVER = $initdata->{'country'};
+
+# DEFINE LANGUAGE VERSION
+my $languageVER = $initdata->{'language'};
+
+print "\n\n\n";
+
+my @attributes = @{ $data->{'attributes'} };
+foreach my $attributes ( @attributes ) {
+
+ my @listings = @{ $attributes->{'listings'} };
+ foreach my $listings ( @listings ) {
+
+ # ####################
+ # DEFINE JSON VALUES #
+ # ####################
+
+ # DEFINE TIMES AND CHANNEL ID
+ my $start = $listings->{'listDateTime'};
+ my $duration = $listings->{'duration'};
+ my $durations = $listings->{'duration'};
+ my $cid = $attributes->{'channel'}{'channelNumber'};
+ $cid =~ s/\&/\&/g;
+
+ # CONVERT FROM TIMESTAMP TO XMLTV DATE FORMAT
+ $start =~ s/://g;
+ $start =~ s/-//g;
+ $start =~ s/ //g;
+
+ # CONVERT PROGRAMM DURATION IN SEC
+ $duration = $duration * 60;
+
+ # CONVERT STARTTIME IN EPOCH SEC
+ my $parser = DateTime::Format::Strptime->new( pattern => '%Y%m%d%H%M%S' );
+ my $dt = $parser->parse_datetime( $start );
+ my $end = $dt->epoch;
+
+ # CALCULATE DURATION TO STARTTIME TO GET STOPTIME
+ $end = $end + $duration;
+
+ $end = gmtime($end)->strftime('%F %T');
+ $end =~ s/://g;
+ $end =~ s/-//g;
+ $end =~ s/ //g;
+
+ # DEFINE PROGRAM STRINGS
+ my $title = $listings->{'showName'};
+ my $subtitle = $listings->{'episodeTitle'};
+ my $director = $listings->{'director'};
+ my $desc = $listings->{'description'};
+ my $date = $listings->{'year'};
+ my $country = $listings->{'country'};
+ my $genre = $listings->{'showType'};
+ my $age = $listings->{'rating'};
+ my $star = $listings->{'starRating'};
+
+ # DEFINE RYTEC CHANNEL ID (language)
+ my $rytec = $chdata->{'channels'}{$countryVER};
+
+ # DEFINE CHANNEL ID
+ my $cidEXT = $chiddata->{'cid'};
+
+ # DEFINE EIT GENRES (language)
+ my $eit = $genredata->{'categories'}{$countryVER};
+
+ # DEFINE SETTINGS
+ my $setup_general = $setupdata->{'settings'};
+ my $setup_cid = $setup_general->{'cid'};
+ my $setup_genre = $setup_general->{'genre'};
+ my $setup_category = $setup_general->{'category'};
+ my $setup_episode = $setup_general->{'episode'};
+
+ # DEFINE SETTINGS VALUES
+ my $enabled = "enabled";
+ my $disabled = "disabled";
+ my $xmltv_ns = "xmltv_ns";
+ my $onscreen = "onscreen";
+
+ # ##################
+ # PRINT XML OUTPUT #
+ # ##################
+
+ # PRINT PROGRAMME STRING ONLY IF CERTAIN VALUES ARE DEFINED
+ if( defined $title and defined $start and defined $end and defined $cid ) {
+
+ # BEGIN OF PROGRAMME: START / STOP / CHANNEL (condition) (settings)
+ if( defined $cidEXT->{$cid} ) {
+ if( $setup_cid eq $enabled ) {
+ if( defined $rytec->{$cidEXT->{$cid}} ) {
+ print "{$cidEXT->{$cid}} . "\">\n";
+ } else {
+ print "{$cid} . "\">\n";
+ print STDERR "[ EPG WARNING ] Rytec ID not matched for: " . $cidEXT->{$cid} . "\n";
+ }
+ } else {
+ print "{$cid} . "\">\n";
+ }
+ } else {
+ print "\n";
+ print STDERR "[ EPG WARNING ] Channel ID unknown: " . $cid . "\n";
+ }
+
+ # IMAGE (condition)
+ if( defined $listings->{'artwork'}{'moviePoster'} ) {
+ my $image = $listings->{'artwork'}{'moviePoster'} ;
+ $image =~ s/^/https:\/\/www.tvtv.us\/tvm\/i\/image\/show\/960x1440\//g;
+ print " \n";
+ }else{
+ if( defined $listings->{'showPicture'} ) {
+ my $image = $listings->{'showPicture'} ;
+ $image =~ s/^/https:\/\/www.tvtv.us\/tvm\/i\/image\/show\/960x1440\//g;
+ print " \n";
+ }
+ }
+
+ # TITLE (language)
+ if ( $subtitle eq ''){
+ undef $subtitle;
+ }
+ if ( $title eq 'Movie') {
+ if( defined $subtitle ) {
+ $subtitle =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+ $title = $subtitle
+ }
+ }
+ $title =~ s/\&/\&/g;
+ print " " . $title . "\n";
+
+ # SUBTITLE (condition) (language)
+ if( defined $subtitle ) {
+ if ( $title eq $subtitle){
+ undef $subtitle;
+ }
+ }
+
+ if( defined $subtitle ) {
+ $subtitle =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+ print " $subtitle\n";
+ }
+
+ # DESCRIPTION (condition) (language)
+ if( defined $desc ) {
+ $desc =~ s/<[^>]*>//g; # REMOVE XML STRINGS WITHIN JSON VALUE
+ $desc =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+ print " $desc\n";
+ }
+
+ #CREDITS (condition)
+ if ( $director eq ''){
+ undef $director;
+ }
+ if( defined $director ) {
+ $director =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+ print " \n";
+ print " " . $director . "\n";
+ if( exists $listings->{'cast'} ) {
+ my $cast = $listings->{'cast'} ;
+ $cast =~ s/\&/\&/g;
+ foreach my $actors ( split /,\s*/, $cast ){
+ print " " . $actors . "\n";
+ }
+ }
+ print " \n";
+ } else{
+ my $cast = $listings->{'cast'} ;
+ if ($cast eq ''){
+ undef $cast;
+ }
+ if( defined $cast ) {
+ $cast =~ s/\&/\&/g;
+ print " \n";
+ foreach my $actors ( split /,\s*/, $cast ){
+ print " " . $actors . "\n";
+ }
+ print " \n";
+ }
+ }
+
+
+
+ # DATE (condition)
+ if( $date eq '' ) {
+ undef $date;
+ }
+ if( defined $date ) {
+ print " $date\n";
+ }
+
+ # COUNTRY (condition)
+ if( defined $country ) {
+ print " " . uc($country) . "\n";
+ }
+
+ # CATEGORIES (USE ONE CATEGORY ONLY) (condition) (language) (settings)
+ if ( defined $genre ) {
+ $genre =~ s/\&/\&/g; # REQUIRED TO READ XML FILE CORRECTLY
+ $genre =~ s/Movies, //g;
+ $genre =~ s/, / \/ /g;
+ if ( $setup_genre eq $enabled ) {
+ if ( defined $eit->{ $genre } ) {
+ print " " . $eit->{ $genre } . "\n";
+ } else {
+ print " $genre\n";
+ print STDERR "[ EPG WARNING ] CATEGORY UNAVAILABLE IN EIT LIST: " . "$genre" . "\n";;
+ }
+ }elsif ( $setup_genre eq $disabled ) {
+ print " $genre\n";
+ }
+ }
+
+
+
+
+ # SEASON/EPISODE (XMLTV_NS) (condition) (settings)
+ my $showID = $listings->{'showID'};
+ my $cridFile = "cache/$showID";
+ if( -e $cridFile ) {
+ my $crid;
+ {
+ local $/; #Enable 'slurp' mode
+ open my $fh, "<", "cache/$showID" or die;
+ $crid = <$fh>;
+ close $fh;
+ }
+ my $cridDATA = decode_json ($crid);
+
+ my $series = $cridDATA->{'seasons'}[0]{'seasonNumber'};
+ my $episode = $cridDATA->{'episodes'}[0]{'seasonSeqNo'};
+
+ if( defined $series ) {
+ if ( $series lt '1' || $series eq '' ) {
+ undef $series;
+ }
+ }
+
+ if( defined $episode ) {
+ if ( $episode lt '1'|| $episode eq '' ) {
+ undef $episode;
+ }
+ }
+
+ # USE SEASON / EPISODE PROVIDEY BY MANIFILES, ONLY IF EXIST, ELSE USE CRID INFORMATION
+ my $maniseason = $listings->{'episodeNumber'};
+ if( defined $maniseason ) {
+ if ( $maniseason =~ m/-/ ) {
+ undef $episode;
+ undef $series;
+ $episode = $maniseason;
+ $episode =~ s/.*\-//g;
+ $episode =~ s/[^0-9#\.\-_]//g;
+ $series = $maniseason;
+ $series =~ s/\-.*//g;
+ $series =~ s/[^0-9#\.\-_]//g;
+ if ($series eq '' ) {
+ undef $series;
+ }
+ if ( $episode eq '' ) {
+ undef $episode;
+ }
+ }
+ }
+
+ if( $setup_episode eq $xmltv_ns ) {
+ if( defined $series ) {
+ my $XMLseries = $series - 1;
+ if( defined $episode ) {
+ my $XMLepisode = $episode - 1;
+ print " $XMLseries . $XMLepisode . \n";
+ } else {
+ print " $XMLseries . 0 . \n";
+ }
+ } elsif( defined $episode ) {
+ my $XMLepisode = $episode - 1;
+ print " 0 . $XMLepisode . \n";
+ }
+ }
+
+ # SEASON/EPISODE (ONSCREEN) (condition) (settings)
+ if( $setup_episode eq $onscreen ) {
+ if( defined $series ) {
+ if( defined $episode ) {
+ print " S$series E$episode\n";
+ } else {
+ print " S$series\n";
+ }
+ } elsif( defined $episode ) {
+ print " E$episode\n";
+ }
+ }
+ }
+
+ # AGE RATING (condition)
+ if ( $age eq '' ) {
+ undef $age;
+ }
+ if( defined $age) {
+ $age =~ s/TV14/16/g ;
+ $age =~ s/TVG/6/g ;
+ $age =~ s/TVMA/18/g ;
+ $age =~ s/TVPG/6/g ;
+ $age =~ s/TVY7/12/g ;
+ $age =~ s/TVY/6/g ;
+ $age =~ s/TV6/6/g ;
+ if( $age ne '-1' ) {
+ print " \n $age\n \n";
+ }
+ }
+
+ # STAR RATING (condition)
+ if ( $star eq '' ) {
+ undef $star;
+ }
+ if( defined $star) {
+ if( $star gt '0' ) {
+ $star = $star *2;
+ $star =~ s/$/\/10/g;
+ print " \n $star\n \n";
+ }
+ }
+
+ # END OF PROGRAMME
+ print "\n";
+ }
+ }
+}
\ No newline at end of file
diff --git a/tvtvus/info b/tvtvus/info
new file mode 100644
index 0000000..8d1c8b6
--- /dev/null
+++ b/tvtvus/info
@@ -0,0 +1 @@
+
diff --git a/tvtvus/init.json b/tvtvus/init.json
new file mode 100644
index 0000000..8d5c401
--- /dev/null
+++ b/tvtvus/init.json
@@ -0,0 +1 @@
+{"country":"USA","language":"en"}
diff --git a/tvtvus/settings.sh b/tvtvus/settings.sh
new file mode 100644
index 0000000..517f690
--- /dev/null
+++ b/tvtvus/settings.sh
@@ -0,0 +1,497 @@
+#!/bin/bash
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+
+# ########################
+# E1000 TVTV-US SETTINGS #
+# ########################
+
+echo "H" > /tmp/value
+
+while grep -q "H" /tmp/value
+do
+ # E1000 MENU OVERLAY
+ echo 'dialog --backtitle "[E1000] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS" --title "SETTINGS" --menu "Please select the option you want to change:" 14 60 10 \' > /tmp/menu
+
+ if [ ! -e settings.json ]
+ then
+ if [ ! -e /tmp/settings_new ]
+ then
+ # INSERT DEFAULT VALUES
+ echo "day=7" > /tmp/settings_new # grab 7 days by default
+ echo "cid=disabled" >> /tmp/settings_new # do not use Rytec IDs by default
+ echo "genre=enabled" >> /tmp/settings_new # use EIT format for genres by default
+ echo "category=enabled" >> /tmp/settings_new # insert all categories by default
+ echo "episode=xmltv_ns" >> /tmp/settings_new # use XMLTV_NS format for episodes by default
+ fi
+ else
+ # EXTRACT VALUES FROM JSON FILE
+ grep '"day":' settings.json | sed 's/\("day": "\)\(.*\)",/day=\2/g' > /tmp/settings_new
+ grep '"cid":' settings.json | sed 's/\("cid": "\)\(.*\)",/cid=\2/g' >> /tmp/settings_new
+ grep '"genre":' settings.json | sed 's/\("genre": "\)\(.*\)",/genre=\2/g' >> /tmp/settings_new
+ grep '"category":' settings.json | sed 's/\("category": "\)\(.*\)",/category=\2/g' >> /tmp/settings_new
+ grep '"episode":' settings.json | sed 's/\("episode": "\)\(.*\)",/episode=\2/g' >> /tmp/settings_new
+ fi
+
+ # E1100 CHANNEL LIST
+ echo ' 1 "MODIFY CHANNEL LIST" \' >> /tmp/menu
+
+ # E1200 TIME PERIOD
+
+ if grep -q "day=10" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 10 days)" \' >> /tmp/menu
+ elif grep -q "day=11" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 11 days)" \' >> /tmp/menu
+ elif grep -q "day=12" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 12 days)" \' >> /tmp/menu
+ elif grep -q "day=13" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 13 days)" \' >> /tmp/menu
+ elif grep -q "day=14" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 14 days)" \' >> /tmp/menu
+ elif grep -q "day=1" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 1 day)" \' >> /tmp/menu
+ elif grep -q "day=2" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 2 days)" \' >> /tmp/menu
+ elif grep -q "day=3" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 3 days)" \' >> /tmp/menu
+ elif grep -q "day=4" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 4 days)" \' >> /tmp/menu
+ elif grep -q "day=5" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 5 days)" \' >> /tmp/menu
+ elif grep -q "day=6" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 6 days)" \' >> /tmp/menu
+ elif grep -q "day=7" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 7 days)" \' >> /tmp/menu
+ elif grep -q "day=8" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 8 days)" \' >> /tmp/menu
+ elif grep -q "day=9" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: 9 days)" \' >> /tmp/menu
+ elif grep -q "day=0" /tmp/settings_new
+ then
+ echo ' 2 "TIME PERIOD (currently: disabled)" \' >> /tmp/menu
+ fi
+
+ # E1300 CONVERT CHANNEL IDs
+ if grep -q "cid=enabled" /tmp/settings_new
+ then
+ echo ' 3 "CONVERT CHANNEL IDs INTO RYTEC FORMAT (enabled)" \' >> /tmp/menu
+ elif grep -q "cid=disabled" /tmp/settings_new
+ then
+ echo ' 3 "CONVERT CHANNEL IDs INTO RYTEC FORMAT (disabled)" \' >> /tmp/menu
+ fi
+
+ # E1400 CONVERT CATEGORIES
+ if grep -q "genre=enabled" /tmp/settings_new
+ then
+ echo ' 4 "CONVERT CATEGORIES INTO EIT FORMAT (enabled)" \' >> /tmp/menu
+ elif grep -q "genre=disabled" /tmp/settings_new
+ then
+ echo ' 4 "CONVERT CATEGORIES INTO EIT FORMAT (disabled)" \' >> /tmp/menu
+ fi
+
+ # E1600 EPISODE FORMAT
+ if grep -q "episode=xmltv_ns" /tmp/settings_new
+ then
+ echo ' 6 "EPISODE FORMAT (currently: xmltv_ns)" \' >> /tmp/menu
+ elif grep -q "episode=onscreen" /tmp/settings_new
+ then
+ echo ' 6 "EPISODE FORMAT (currently: onscreen)" \' >> /tmp/menu
+ fi
+
+ # E1700 RUN XML SCRIPT
+ echo ' 7 "RUN XML SCRIPT" \' >> /tmp/menu
+
+ # E1900 DELETE INSTANCE
+ echo ' 9 "REMOVE GRABBER INSTANCE" \' >> /tmp/menu
+
+ echo "2> /tmp/value" >> /tmp/menu
+
+ if [ ! -e channels.json ]
+ then
+ echo "1" > /tmp/value
+ else
+ sed -i "s/\[X\]/[$COUNTRY]/g" /tmp/menu
+ bash /tmp/menu
+ input="$(cat /tmp/value)"
+ fi
+
+
+ # ####################
+ # E1100 CHANNEL LIST #
+ # ####################
+
+ if grep -q "1" /tmp/value
+ then
+ # E1100 MENU OVERLAY
+ echo 'dialog --backtitle "[E1100] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CHANNEL LIST" --title "CHANNELS" --checklist "Please choose the channels you want to grab:" 15 50 10 \' > /tmp/chmenu
+
+ printf "\rFetching channel list... "
+ curl --compressed -s https://tvtv.us/tvm/t/tv/v4/lineups/2381D/ > /tmp/workfile
+ jq '.' /tmp/workfile > /tmp/chlist
+
+ printf "\rLoading channel configuration..."
+ perl cid_json.pl > /tmp/chvalues
+ sed -i '/{/d;/}/d;s/.*":"//g;s/",//g;/DUMMY/d' /tmp/chvalues
+ sort -u /tmp/chvalues > /tmp/chvalues_sorted && mv /tmp/chvalues_sorted /tmp/chvalues
+
+ if [ ! -e channels.json ]
+ then
+ nl /tmp/chvalues > /tmp/chvalues_count
+ sed -i 's/\( \)\([0-9].*\)/[\2/g;s/\( \)\([0-9].*\)/[\2/g;s/\( \)\([0-9].*\)/[\2/g;s/[\t]/] /g;s/\&/\&/g' /tmp/chvalues_count
+ mv /tmp/chvalues_count /tmp/chvalues
+ sed -i 's/.*/"&" "" off \\/g' /tmp/chvalues
+ sed -i '$s/.*/&\n2>\/tmp\/chconf/g' /tmp/chvalues
+ cat /tmp/chvalues >> /tmp/chmenu
+
+ sed -i "s/\[X\]/[$COUNTRY]/g" /tmp/chmenu
+ bash /tmp/chmenu
+
+ if [ -s /tmp/chconf ]
+ then
+ sed 's/" "/","/g;s/\\\[[0-9][^]]*\] //g;s/\\(/(/g;s/\\)/)/g;s/.*/{"channels":[&]}/g;s/\\\&/\&/g;s/\\//g' /tmp/chconf > channels.json
+ cp /tmp/chlist chlist_old
+ dialog --backtitle "[E1110] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CHANNEL LIST" --title "INFO" --msgbox "New channel list added!\nPlease run the grabber to add the channels to the setup modules!" 7 50
+ echo "H" > /tmp/value
+ else
+ dialog --backtitle "[E1120] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CHANNEL LIST" --title "INFO" --msgbox "Channel list creation aborted!\nPlease note that at least 1 channel must be included in channel list!" 7 50
+ echo "M" > /tmp/value
+ exit 1
+ fi
+ else
+ perl chlist_printer.pl > /tmp/compare.json
+ perl compare_menu.pl > /tmp/enabled_chvalues 2> /dev/null
+ comm -12 <(sort -u /tmp/enabled_chvalues) <(sort -u /tmp/chvalues) > /tmp/comm_menu_enabled
+ comm -2 -3 <(sort -u /tmp/chvalues) <(sort -u /tmp/enabled_chvalues) > /tmp/comm_menu_disabled
+ sed -i 's/.*/&" [ON]/g' /tmp/comm_menu_enabled
+ sed -i 's/.*/&" [OFF]/g' /tmp/comm_menu_disabled
+ cat /tmp/comm_menu_disabled >> /tmp/comm_menu_enabled
+ sort /tmp/comm_menu_enabled > /tmp/chvalues
+ nl /tmp/chvalues > /tmp/chvalues_count
+ sed -i 's/\( \)\([0-9].*\)/"[\2/g;s/\( \)\([0-9].*\)/"[\2/g;s/\( \)\([0-9].*\)/"[\2/g;s/[\t]/] /g;s/\&/\&/g' /tmp/chvalues_count
+ mv /tmp/chvalues_count /tmp/chvalues
+ sed -i 's/\[ON\]/"" on \\/g;s/\[OFF\]/"" off \\/g' /tmp/chvalues
+ sed -i '$s/.*/&\n2>\/tmp\/chconf/g' /tmp/chvalues
+ cat /tmp/chvalues >> /tmp/chmenu
+
+ bash /tmp/chmenu
+
+ if [ -s /tmp/chconf ]
+ then
+ sed 's/" "/","/g;s/\\\[[0-9][^]]*\] //g;s/\\(/(/g;s/\\)/)/g;s/.*/{"channels":[&]}/g;s/\\\&/\&/g;s/\\//g' /tmp/chconf > channels.json
+ dialog --backtitle "[E1130] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CHANNEL LIST" --title "INFO" --msgbox "New channel list saved!\nPlease run the grabber to add new channels to the setup modules!" 7 50
+ cp /tmp/chlist chlist_old
+ echo "H" > /tmp/value
+ else
+ dialog --backtitle "[E1140] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CHANNEL LIST" --title "INFO" --msgbox "Channel list creation aborted!\nPlease note that at least 1 channel must be included in channel list!" 7 50
+ echo "H" > /tmp/value
+ fi
+ fi
+
+
+ # ###################
+ # E1200 TIME PERIOD #
+ # ###################
+
+ elif grep -q "2" /tmp/value
+ then
+ echo "X" > /tmp/value
+
+ while grep -q "X" /tmp/value
+ do
+ # E1200 MENU OVERLAY
+ dialog --backtitle "[E1200] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > TIME PERIOD" --title "EPG GRABBER" --inputbox "Please enter the number of days you want to retrieve the EPG information. (0=disable | 1-14=enable)" 10 46 2>/tmp/value
+
+ sed -i 's/.*/epg&-/g' /tmp/value
+
+ # E1210 INPUT: DISABLED
+ if grep -q "epg0-" /tmp/value
+ then
+ sed -i '/day=/d' /tmp/settings_new
+ echo "day=0" >> /tmp/settings_new
+ dialog --backtitle "[E1210] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > TIME PERIOD" --title "INFO" --msgbox "EPG grabber disabled!" 5 26
+ echo "H" > /tmp/value
+
+ # E1220 INPUT: 1 DAY
+ elif grep -q "epg1-" /tmp/value
+ then
+ sed -i '/day=/d' /tmp/settings_new
+ echo "day=1" >> /tmp/settings_new
+ dialog --backtitle "[E1220] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > TIME PERIOD" --title "INFO" --msgbox "EPG grabber is enabled for 1 day!" 5 42
+ echo "H" > /tmp/value
+
+ # E1230 INPUT: 2-9 DAYS
+ elif grep -q "epg[2-9]-" /tmp/value
+ then
+ sed -i 's/epg//g;s/-//g' /tmp/value
+ sed -i '/day=/d' /tmp/settings_new
+ echo "day=$(> /tmp/settings_new
+ dialog --backtitle "[E1230] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > TIME PERIOD" --title "INFO" --msgbox "EPG grabber is enabled for $( /tmp/value
+
+ # E1240 INPUT: 10-14 DAYS
+ elif grep -q "epg1[0-4]-" /tmp/value
+ then
+ sed -i 's/epg//g;s/-//g' /tmp/value
+ sed -i '/day=/d' /tmp/settings_new
+ echo "day=$(> /tmp/settings_new
+ dialog --backtitle "[E1240] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > TIME PERIOD" --title "INFO" --msgbox "EPG grabber is enabled for $( /tmp/value
+
+ # E1250 WRONG INPUT
+ elif [ -s /tmp/value ]
+ then
+ dialog --backtitle "[E1250] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > TIME PERIOD" --title "ERROR" --msgbox "Wrong input detected!" 5 30
+ echo "X" > /tmp/value
+
+ # E12X0 EXIT
+ else
+ echo "H" > /tmp/value
+ fi
+ done
+
+
+ # ###########################
+ # E1300 CONVERT CHANNEL IDs #
+ # ###########################
+
+ elif grep -q "3" /tmp/value
+ then
+ # E1300 MENU OVERLAY
+ dialog --backtitle "[E1300] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CONVERT CHANNEL IDs" --title "CHANNEL IDs" --yesno "Do you want to use the Rytec ID format?\n\nRytec ID example: ChannelNameHD.de\nUsual ID example: Channel Name HD" 8 55
+
+ response=$?
+
+ # E1310 NO
+ if [ $response = 1 ]
+ then
+ dialog --backtitle "[E1310] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CONVERT CHANNEL IDs" --title "INFO" --msgbox "Rytec Channel IDs disabled!" 5 32
+ sed -i '/cid=/d' /tmp/settings_new
+ echo "cid=disabled" >> /tmp/settings_new
+ echo "H" > /tmp/value
+
+ # E1320 YES
+ elif [ $response = 0 ]
+ then
+ dialog --backtitle "[E1320] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CONVERT CHANNEL IDs" --title "INFO" --msgbox "Rytec Channel IDs enabled!" 5 30
+ sed -i '/cid=/d' /tmp/settings_new
+ echo "cid=enabled" >> /tmp/settings_new
+ echo "H" > /tmp/value
+
+ # E13X0 EXIT
+ elif [ $response = 255 ]
+ then
+ dialog --backtitle "[E13X0] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CONVERT CHANNEL IDs" --title "INFO" --msgbox "No changes applied!" 5 30
+ echo "H" > /tmp/value
+ fi
+
+
+ # ###########################
+ # E1400 CONVERT CATEGORIES #
+ # ###########################
+
+ elif grep -q "4" /tmp/value
+ then
+ # E1400 MENU OVERLAY
+ dialog --backtitle "[E1400] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CONVERT CATEGORIES" --title "CATEGORIES" --yesno "Do you want to use the EIT format for tvHeadend?" 5 55
+
+ response=$?
+
+ # E1410 NO
+ if [ $response = 1 ]
+ then
+ dialog --backtitle "[E1410] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CONVERT CATEGORIES" --title "INFO" --msgbox "EIT categories disabled!" 5 32
+ sed -i '/genre=/d' /tmp/settings_new
+ echo "genre=disabled" >> /tmp/settings_new
+ echo "H" > /tmp/value
+
+ # E1420 YES
+ elif [ $response = 0 ]
+ then
+ dialog --backtitle "[E1420] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CONVERT CATEGORIES" --title "INFO" --msgbox "EIT categories enabled!" 5 30
+ sed -i '/genre=/d' /tmp/settings_new
+ echo "genre=enabled" >> /tmp/settings_new
+ echo "H" > /tmp/value
+
+ # E14X0 EXIT
+ elif [ $response = 255 ]
+ then
+ dialog --backtitle "[E14X0] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > CONVERT CATEGORIES" --title "INFO" --msgbox "No changes applied!" 5 30
+ echo "H" > /tmp/value
+ fi
+
+
+ # ###########################
+ # E1500 MULTIPLE CATEGORIES #
+ # ###########################
+
+ elif grep -q "5" /tmp/value
+ then
+ # E1500 MENU OVERLAY
+ dialog --backtitle "[E1500] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > MULTIPLE CATEGORIES" --title "MULTIPLE CATEGORIES" --yesno "Do you want to use multiple categories for tvHeadend?" 5 60
+
+ response=$?
+
+ # E1510 NO
+ if [ $response = 1 ]
+ then
+ dialog --backtitle "[E1510] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > MULTIPLE CATEGORIES" --title "INFO" --msgbox "Multiple categories disabled!" 5 35
+ sed -i '/category=/d' /tmp/settings_new
+ echo "category=disabled" >> /tmp/settings_new
+ echo "H" > /tmp/value
+
+ # E1520 YES
+ elif [ $response = 0 ]
+ then
+ dialog --backtitle "[E1520] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > MULTIPLE CATEGORIES" --title "INFO" --msgbox "Multiple categories enabled!" 5 35
+ sed -i '/category=/d' /tmp/settings_new
+ echo "category=enabled" >> /tmp/settings_new
+ echo "H" > /tmp/value
+
+ # E15X0 EXIT
+ elif [ $response = 255 ]
+ then
+ dialog --backtitle "[E15X0] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > MULTIPLE CATEGORIES" --title "INFO" --msgbox "No changes applied!" 5 30
+ echo "H" > /tmp/value
+ fi
+
+
+ # ######################
+ # E1600 EPISODE FORMAT #
+ # ######################
+
+ elif grep -q "6" /tmp/value
+ then
+ # E1600 MENU OVERLAY
+ dialog --backtitle "[E1600] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > EPISODE FORMAT" --title "EPISODE" --menu "Please select the format you want to use.\n\nonscreen: move the episode data into the broadcast description\nxmltv_ns: episode data to be parsed by tvHeadend" 14 60 10 \
+ 1 "ONSCREEN" \
+ 2 "XMLTV_NS" \
+ 2>/tmp/value
+
+ # E1610 ONSCREEN
+ if grep -q "1" /tmp/value
+ then
+ dialog --backtitle "[E1610] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > EPISODE FORMAT" --title "INFO" --msgbox "Episode format 'onscreen' enabled!" 5 40
+ sed -i '/episode=/d' /tmp/settings_new
+ echo "episode=onscreen" >> /tmp/settings_new
+ echo "H" > /tmp/value
+
+ # E1620 XMLTV_NS
+ elif grep -q "2" /tmp/value
+ then
+ dialog --backtitle "[E1620] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > EPISODE FORMAT" --title "INFO" --msgbox "Episode format 'xmltv_ns' enabled!" 5 40
+ sed -i '/episode=/d' /tmp/settings_new
+ echo "episode=xmltv_ns" >> /tmp/settings_new
+ echo "H" > /tmp/value
+
+ # E16X0 EXIT
+ else
+ echo "H" > /tmp/value
+ fi
+
+
+ # ######################
+ # E1700 RUN XML SCRIPT #
+ # ######################
+
+ elif grep -q "7" /tmp/value
+ then
+ clear
+
+ echo ""
+ echo " --------------------------------------------"
+ echo " TVTV-US EPG SIMPLE XMLTV GRABBER "
+ echo " "
+ echo " (c) 2019 Jan-Luca Neumann / sunsettrack4 "
+ echo " --------------------------------------------"
+ echo ""
+ sleep 2s
+
+ bash tvtvus.sh && cd - > /dev/null
+
+ cp tvtvus/de/TVTV-US.xml xml/TVTV-US_de.xml 2> /dev/null
+
+ cd - > /dev/null
+
+ read -n 1 -s -r -p "Press any key to continue..."
+ echo "H" > /tmp/value
+
+
+ # #######################
+ # E1900 DELETE INSTANCE #
+ # #######################
+
+ elif grep -q "9" /tmp/value
+ then
+ # E1900 MENU OVERLAY
+ dialog --backtitle "[E1900] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > DELETE INSTANCE" --title "WARNING" --yesno "Do you want to delete this service?" 5 50
+
+ response=$?
+
+ # E1910 NO
+ if [ $response = 1 ]
+ then
+ dialog --backtitle "[E1910] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > DELETE INSTANCE" --title "INFO" --msgbox "Service not deleted!" 5 32
+ echo "H" > /tmp/value
+
+ # E1920 YES
+ elif [ $response = 0 ]
+ then
+ dialog --backtitle "[E1920] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > DELETE INSTANCE" --title "INFO" --msgbox "Service deleted!" 5 30
+ rm channels.json
+ echo "M" > /tmp/value
+
+ # E19X0 EXIT
+ elif [ $response = 255 ]
+ then
+ dialog --backtitle "[E19X0] EASYEPG SIMPLE XMLTV GRABBER > TVTV-US SETTINGS > DELETE INSTANCE" --title "INFO" --msgbox "Service not deleted!" 5 30
+ echo "H" > /tmp/value
+ fi
+
+
+ # ############
+ # E1X00 EXIT #
+ # ############
+
+ else
+ echo "M" > /tmp/value
+ fi
+
+sed -i 's/.*/"&",/g' /tmp/settings_new
+sed -i 's/=/": "/g' /tmp/settings_new
+sed -i '1i{ "settings": {' /tmp/settings_new
+sed '$s/.*/&\n"settings": "true" }\n}/g' /tmp/settings_new > settings.json
+rm /tmp/settings_new
+
+done
diff --git a/tvtvus/tvtvus.sh b/tvtvus/tvtvus.sh
new file mode 100644
index 0000000..cf3bc77
--- /dev/null
+++ b/tvtvus/tvtvus.sh
@@ -0,0 +1,456 @@
+#!/bin/bash
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+
+# ################
+# INITIALIZATION #
+# ################
+
+#
+# SETUP ENVIRONMENT
+#
+
+mkdir cache 2> /dev/null # cache
+mkdir day 2> /dev/null # download scripts
+mkdir mani 2> /dev/null # manifest files
+
+if grep -q "USA" init.json 2> /dev/null
+then
+ printf "+++ COUNTRY: USA +++\n\n"
+fi
+
+if grep -q '"day": "0"' settings.json
+then
+ printf "EPG Grabber disabled!\n\n"
+ exit 0
+fi
+
+if ! curl --write-out %{http_code} --silent --output /dev/null https://tvtv.us/ | grep -q "200"
+then
+ printf "Service provider unavailable!\n\n"
+ exit 0
+fi
+
+
+# ##################
+# DOWNLOAD PROCESS #
+# ##################
+
+echo "- DOWNLOAD PROCESS -" && echo ""
+
+#
+# DELETE OLD FILES
+#
+
+printf "\rDeleting old files... "
+
+rm -rf cache/ 2> /dev/null
+rm -rf day/ 2> /dev/null
+rm -rf mani/ 2> /dev/null
+rm /tmp/epg_workfile 2> /dev/null
+rm /tmp/workfile 2> /dev/null
+rm /tmp/workfile2 2> /dev/null
+
+mkdir cache 2> /dev/null
+mkdir day 2> /dev/null
+mkdir mani 2> /dev/null
+
+
+#
+# LOADING MANIFEST FILES
+#
+
+printf "\rFetching channel list... "
+curl --compressed -s https://tvtv.us/tvm/t/tv/v4/lineups/2381D/ > /tmp/workfile
+jq '.' /tmp/workfile > /tmp/chlist
+
+
+printf "\rChecking manifest files... "
+perl chlist_printer.pl > /tmp/compare.json
+perl url_printer.pl 2>errors.txt | sed '/DUMMY/d' > mani/common
+
+printf "\n$(echo $(wc -l < mani/common)) manifest file(s) to be downloaded!\n\n"
+
+if [ $(wc -l < mani/common) -ge 7 ]
+then
+ number=$(echo $(( $(wc -l < mani/common) / 7)))
+
+ split -l $number --numeric-suffixes mani/common mani/day
+
+else
+ cp mani/common mani/day00
+fi
+
+#
+# CREATE STATUS INFO FOR MANIFEST FILE DOWNLOAD
+#
+cp mani/common common
+
+function status_manifest_download {
+ #setup_scroll_area
+ sleep 2 2> /dev/null ;
+ thread=$(ps ax)
+ if [[ $thread =~ ^.*curl.*$ ]] ;
+ then
+ z0="[ ]"
+ z5="[# ]"
+ z10="[## ]"
+ z15="[### ]"
+ z20="[#### ]"
+ z25="[##### ]"
+ z30="[###### ]"
+ z35="[####### ]"
+ z40="[######## ]"
+ z45="[######### ]"
+ z50="[########## ]"
+ z55="[########### ]"
+ z60="[############ ]"
+ z65="[############# ]"
+ z70="[############## ]"
+ z75="[############### ]"
+ z80="[################ ]"
+ z85="[################# ]"
+ z90="[################## ]"
+ z95="[################### ]"
+ z100="[####################]"
+
+ df=$(find mani/ -type f | wc -l) ;
+ ftd=$(wc -l < mani/common) ;
+ status=$(expr $df \* 100 / $ftd - 2) ;
+ if [[ $status -gt 100 || $status -eq 100 ]]; then status="100"; fi
+ if [[ $status -gt 0 && $status -lt 5 || $status -eq 0 ]]; then bar="$z0"; elif [[ $status -gt 5 && $status -lt 10 ]]; then bar="$z5"; elif [[ $status -gt 10 && $status -lt 15 ]] ; then bar="$z10"; elif [[ $status -gt 15 && $status -lt 20 ]] ; then bar="$z15"; elif [[ $status -gt 20 && $status -lt 25 ]] ; then bar="$z20"; elif [[ $status -gt 25 && $status -lt 30 ]] ; then bar="$z25"; elif [[ $status -gt 30 && $status -lt 35 ]] ; then bar="$z30"; elif [[ $status -gt 35 && $status -lt 40 ]] ; then bar="$z35"; elif [[ $status -gt 40 && $status -lt 45 ]] ; then bar="$z40"; elif [[ $status -gt 40 && $status -lt 50 ]] ; then bar="$z45"; elif [[ $status -gt 50 && $status -lt 55 ]] ; then bar="$z50"; elif [[ $status -gt 55 && $status -lt 60 ]] ; then bar="$z55"; elif [[ $status -gt 60 && $status -lt 65 ]] ; then bar="$z60"; elif [[ $status -gt 60 && $status -lt 70 ]] ; then bar="$z65"; elif [[ $status -gt 70 && $status -lt 75 ]] ; then bar="$z70"; elif [[ $status -gt 70 && $status -lt 80 ]] ; then bar="$z75"; elif [[ $status -gt 80 && $status -lt 85 ]] ; then bar="$z80"; elif [[ $status -gt 85 && $status -lt 90 ]] ; then bar="$z85"; elif [[ $status -gt 90 && $status -lt 95 ]] ; then bar="$z90"; elif [[ $status -gt 95 && $status -lt 100 ]] ; then bar="$z95"; elif [ $status -eq 100 ] ; then bar="$z100";fi
+ printf "\rProgress $bar $status%% ";
+ status_manifest_download ;
+ fi
+ }
+
+#
+# CREATE MANIFEST DOWNLOAD SCRIPTS
+#
+
+for time in {0..8..1}
+do
+ sed -i '1i#\!\/bin\/bash\n' mani/day0${time} 2> /dev/null
+done
+
+
+#
+# COPY/PASTE EPG DETAILS
+#
+
+printf "\rLoading manifest files..."
+echo ""
+printf "\rProgress [ ] 0%% "
+
+status_manifest_download &
+
+for a in {0..8..1}
+do
+ bash mani/day0${a} 2> /dev/null &
+done
+wait
+
+rm mani/day0* 2> /dev/null && rm mani/common 2> /dev/null
+
+printf "\rProgress [####################] 100%% "
+echo "DONE!" && printf "\n"
+
+
+#
+# CREATE EPG BROADCAST LIST
+#
+
+printf "\rCreating EPG manifest file... "
+
+rm /tmp/manifile.json 2> /dev/null
+cat mani/* > /tmp/manifile.json
+cp /tmp/manifile.json manifile.json
+jq -s '.' /tmp/manifile.json > /tmp/epg_workfile 2>>errors.txt
+sed -i '1s/\[/{ "attributes":[/g;$s/\]/&}/g' /tmp/epg_workfile
+
+cp /tmp/epg_workfile epg_workfile.json
+rm mani/*
+echo "DONE!" && printf "\n"
+perl compare_crid.pl > day/daydlnew
+
+#
+# SHOW ERROR MESSAGE + ABORT PROCESS IF CHANNEL IDs WERE CHANGED
+#
+
+sort -u errors.txt > /tmp/errors_sorted.txt && mv /tmp/errors_sorted.txt errors.txt
+
+if [ -s errors.txt ]
+then
+ echo "================= CHANNEL LIST: LOG ==================="
+ echo ""
+
+ input="errors.txt"
+ while IFS= read -r var
+ do
+ echo "$var"
+ done < "$input"
+
+ echo ""
+ echo "======================================================="
+ echo ""
+
+ cp /tmp/chlist chlist_old
+else
+ rm errors.txt 2> /dev/null
+fi
+
+#
+# DOWNLOAD EPG DETAILS
+#
+
+printf "\rPreparing multithreaded download... "
+
+sed "s/.*/curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https:\/\/tvtv.us\/tvm\/t\/tv\/v4\/episodes\/&' | grep 'seriesID' > cache\/&/g" day/daydlnew > day/common
+
+sed -i '/^$/d' day/common
+sort -u day/common | uniq > /tmp/common
+cp /tmp/common day/common
+printf "\n$(echo $(wc -l < day/common)) broadasts files to be downloaded!\n\n"
+if [ $(wc -l < day/common) -ge 32 ]
+then
+ number=$(echo $(( $(wc -l < day/common) / 32)))
+
+ split -l $number --numeric-suffixes day/common day/day
+
+else
+ cp day/common day/day00
+fi
+
+
+#
+# CREATE STATUS BAR FOR DOWNLOAD SCRIPT
+#
+
+function status_detail_download {
+ #setup_scroll_area
+ sleep 2 2> /dev/null ;
+ thread=$(ps ax)
+ if [[ $thread =~ ^.*curl.*$ ]] ;
+ then
+ z0="[ ]"
+ z5="[# ]"
+ z10="[## ]"
+ z15="[### ]"
+ z20="[#### ]"
+ z25="[##### ]"
+ z30="[###### ]"
+ z35="[####### ]"
+ z40="[######## ]"
+ z45="[######### ]"
+ z50="[########## ]"
+ z55="[########### ]"
+ z60="[############ ]"
+ z65="[############# ]"
+ z70="[############## ]"
+ z75="[############### ]"
+ z80="[################ ]"
+ z85="[################# ]"
+ z90="[################## ]"
+ z95="[################### ]"
+ z100="[####################]"
+
+ df=$(find cache -type f | wc -l) ;
+ ftd=$(wc -l < day/common) ;
+ status=$(expr $df \* 100 / $ftd) ;
+ if [[ $status -gt 100 || $status -eq 100 ]]; then status="100"; fi
+ if [[ $status -gt 0 && $status -lt 5 || $status -eq 0 ]]; then bar="$z0"; elif [[ $status -gt 5 && $status -lt 10 ]]; then bar="$z5"; elif [[ $status -gt 10 && $status -lt 15 ]] ; then bar="$z10"; elif [[ $status -gt 15 && $status -lt 20 ]] ; then bar="$z15"; elif [[ $status -gt 20 && $status -lt 25 ]] ; then bar="$z20"; elif [[ $status -gt 25 && $status -lt 30 ]] ; then bar="$z25"; elif [[ $status -gt 30 && $status -lt 35 ]] ; then bar="$z30"; elif [[ $status -gt 35 && $status -lt 40 ]] ; then bar="$z35"; elif [[ $status -gt 40 && $status -lt 45 ]] ; then bar="$z40"; elif [[ $status -gt 40 && $status -lt 50 ]] ; then bar="$z45"; elif [[ $status -gt 50 && $status -lt 55 ]] ; then bar="$z50"; elif [[ $status -gt 55 && $status -lt 60 ]] ; then bar="$z55"; elif [[ $status -gt 60 && $status -lt 65 ]] ; then bar="$z60"; elif [[ $status -gt 60 && $status -lt 70 ]] ; then bar="$z65"; elif [[ $status -gt 70 && $status -lt 75 ]] ; then bar="$z70"; elif [[ $status -gt 70 && $status -lt 80 ]] ; then bar="$z75"; elif [[ $status -gt 80 && $status -lt 85 ]] ; then bar="$z80"; elif [[ $status -gt 85 && $status -lt 90 ]] ; then bar="$z85"; elif [[ $status -gt 90 && $status -lt 95 ]] ; then bar="$z90"; elif [[ $status -gt 95 && $status -lt 100 ]] ; then bar="$z95"; elif [ $status -eq 100 ] ; then bar="$z100";fi
+ printf "\rProgress $bar $status%% ";
+ status_detail_download ;
+ fi
+ }
+
+
+#
+# CREATE DOWNLOAD SCRIPTS
+#
+
+for time in {0..33..1}
+do
+ sed -i '1s/.*/#\!\/bin\/bash\n&/g' day/day0${time} 2> /dev/null & sed -i '1s/.*/#\!\/bin\/bash\n&/g' day/day0${time} 2> /dev/null
+done
+
+
+#
+# DOWNLOAD EPG DETAILS
+#
+
+printf "\rDownloading EPG details... "
+echo ""
+printf "\rProgress [ ] 0%% "
+
+status_detail_download &
+
+for a in {0..33..1}
+do
+ bash day/day0${a} 2> /dev/null & bash day/day${a} 2> /dev/null &
+done
+wait
+
+rm day/*
+
+printf "\rProgress [####################] 100%% "
+echo "DONE!" && printf "\n"
+
+#
+# EXPORT 0BYTE EPGDETAILS AND TRY TO REDOWNLOAD
+#
+
+find cache -size 0 | sed 's/cache\///g' >missingbroadcasts
+touch broadcast_warnings.txt
+
+if [ -s missingbroadcasts ]
+then
+ echo "Missing Broadcastfiles Detected" && printf "\n"
+ printf "\rWaiting for 10 Seconds"
+ sleep 10
+ printf "\rPreparing Broadcastdatabase (TVTV seems to hate Screen-Scrapper)... "
+ echo ""
+ find cache -size 0 | sed 's/cache\///g' >day/daydlnew
+ sed "s/.*/curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https:\/\/tvtv.us\/tvm\/t\/tv\/v4\/episodes\/&' | grep 'seriesID' > cache\/&/g" day/daydlnew > day/common
+ sed -i '1s/.*/#\!\/bin\/bash\n&/g' day/common 2> /dev/null
+ sed -i '/^$/d' day/common
+ printf "\n$(echo $(wc -l < day/common)) missing Broadastsfiles to be downloaded!\n\n"
+ bash day/common 2> /dev/null & wait
+ find cache -size 0 | sed 's/cache\///g' >missingbroadcasts
+ if [ -s missingbroadcasts ]
+ then
+ sed 's/.*/\[ EPG WARNING ] FAILED TO DOWNLOAD BROADCASTFILES &/g' missingbroadcasts >broadcast_warnings.txt
+ fi
+fi
+
+rm missingbroadcasts
+rm day/* 2> /dev/null
+
+echo "DONE!" && printf "\n"
+
+# ###################
+# CREATE XMLTV FILE #
+# ###################
+
+# WORK IN PROGRESS
+
+echo "- FILE CREATION PROCESS -" && echo ""
+
+rm workfile chlist 2> /dev/null
+
+
+# DOWNLOAD CHANNEL LIST + RYTEC/EIT CONFIG FILES (JSON)
+printf "\rRetrieving channel list and config files... "
+curl --compressed -s https://tvtv.us/tvm/t/tv/v4/lineups/2381D/ > /tmp/chlist
+jq '.' /tmp/chlist > chlist
+
+cp chlist /tmp/chlist
+curl -s https://raw.githubusercontent.com/sunsettrack4/config_files/master/tvtvus_channels.json > tvtvus_channels.json
+curl -s https://raw.githubusercontent.com/sunsettrack4/config_files/master/tvtvus_genres.json > tvtvus_genres.json
+
+# CONVERT JSON INTO XML: CHANNELS
+printf "\rConverting CHANNEL JSON file into XML format... "
+perl ch_json2xml.pl 2>warnings.txt > tvtv-us_channels
+sort -u tvtv-us_channels > /tmp/tvtv-us_channels && mv /tmp/tvtv-us_channels tvtv-us_channels
+sed -i 's/>>\n tvtvus_cid.json && rm chlist
+
+# CONVERT JSON INTO XML: EPG
+printf "\rConverting EPG JSON file into XML format... "
+perl epg_json2xml.pl > tvtv-us_epg 2>epg_warnings.txt && rm /tmp/epg_workfile 2> /dev/null
+
+
+# COMBINE: CHANNELS + EPG
+printf "\rCreating EPG XMLTV file... "
+cat tvtv-us_epg >> tvtv-us_channels && mv tvtv-us_channels tvtv-us && rm tvtv-us_epg
+sed -i '1i\n<\!-- EPG XMLTV FILE CREATED BY THE EASYEPG PROJECT - (c) 2019 Jan-Luca Neumann -->\n' tvtv-us
+sed -i "s//<\!-- created on $(date) -->\n&\n\n\n/g" tvtv-us
+sed -i '$s/.*/&\n\n<\/tv>/g' tvtv-us
+mv tvtv-us tvtv-us.xml
+
+# VALIDATING XML FILE
+printf "\rValidating EPG XMLTV file..."
+xmllint --noout tvtv-us.xml > errorlog 2>&1
+
+if grep -q "parser error" errorlog
+then
+ printf " DONE!\n\n"
+ mv tvtv-us.xml tvtv-us_ERROR.xml
+ echo "[ EPG ERROR ] XMLTV FILE VALIDATION FAILED DUE TO THE FOLLOWING ERRORS:" >> warnings.txt
+ cat errorlog >> warnings.txt
+else
+ printf " DONE!\n\n"
+ rm tvtv-us_ERROR.xml 2> /dev/null
+ rm errorlog 2> /dev/null
+
+ if ! grep -q "> errorlog
+ fi
+
+ if ! grep "> errorlog
+ fi
+
+ uniq -d /tmp/id_check > /tmp/id_checked
+ if [ -s /tmp/id_checked ]
+ then
+ echo "[ EPG ERROR ] XMLTV FILE CONTAINS DUPLICATED CHANNEL IDs!" >> errorlog
+ sed -i 's/.*/[ DUPLICATE ] &/g' /tmp/id_checked && cat /tmp/id_checked >> errorlog
+ rm /tmp/id_check /tmp/id_checked 2> /dev/null
+ else
+ rm /tmp/id_check /tmp/id_checked 2> /dev/null
+ fi
+
+ if [ -e errorlog ]
+ then
+ mv tvtv-us.xml tvtv-us_ERROR.xml
+ cat errorlog >> warnings.txt
+ else
+ rm errorlog 2> /dev/null
+ fi
+fi
+
+
+# SHOW WARNINGS
+cat epg_warnings.txt >> warnings.txt && rm epg_warnings.txt
+sort -u warnings.txt > sorted_warnings.txt && mv sorted_warnings.txt warnings.txt
+sed -i '/^$/d' warnings.txt
+
+if [ -s warnings.txt ]
+then
+ echo "========== EPG CREATION: WARNING/ERROR LOG ============"
+ echo ""
+
+ input="warnings.txt"
+ while IFS= read -r var
+ do
+ echo "$var"
+ done < "$input"
+
+ echo ""
+ echo "======================================================="
+ echo ""
+fi
diff --git a/tvtvus/url_printer.pl b/tvtvus/url_printer.pl
new file mode 100644
index 0000000..df69dec
--- /dev/null
+++ b/tvtvus/url_printer.pl
@@ -0,0 +1,175 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2019 Jan-Luca Neumann
+# https://github.com/sunsettrack4/easyepg
+#
+# Collaborators:
+# - DeBaschdi ( https://github.com/DeBaschdi )
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with easyepg. If not, see .
+
+# #################################
+# TVTV-US TV MANIFEST URL PRINTER #
+# #################################
+
+use strict;
+use warnings;
+
+binmode STDOUT, ":utf8";
+use utf8;
+
+use JSON;
+use Time::Piece;
+use Time::Seconds;
+
+# READ CHANNEL FILE
+my $channels;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, '<', "/tmp/compare.json" or die;
+ $channels = <$fh>;
+ close $fh;
+}
+
+# READ SETTINGS FILE
+my $settings;
+{
+ local $/; #Enable 'slurp' mode
+ open my $fh, '<', "settings.json" or die;
+ $settings = <$fh>;
+ close $fh;
+}
+
+# CONVERT JSON TO PERL STRUCTURES
+my $channels_data = decode_json($channels);
+my $settings_data = decode_json($settings);
+
+# SET DAY SETTING
+my $day_setting = $settings_data->{'settings'}{'day'};
+
+# SET DATE VALUES
+my $time1 = Time::Piece->new;
+my $time2 = $time1 + 86400;
+my $time3 = $time1 + 172800;
+my $time4 = $time1 + 259200;
+my $time5 = $time1 + 345600;
+my $time6 = $time1 + 432000;
+my $time7 = $time1 + 518400;
+my $time8 = $time1 + 604800;
+my $time9 = $time1 + 691200;
+my $time_10 = $time1 + 777600;
+my $time_11 = $time1 + 864000;
+my $time_12 = $time1 + 950400;
+my $time_13 = $time1 + 1036800;
+my $time_14 = $time1 + 1123200;
+my $time_15 = $time1 + 1209600;
+
+my $date1 = $time1->strftime('%Y-%m-%d');
+my $date2 = $time2->strftime('%Y-%m-%d');
+my $date3 = $time3->strftime('%Y-%m-%d');
+my $date4 = $time4->strftime('%Y-%m-%d');
+my $date5 = $time5->strftime('%Y-%m-%d');
+my $date6 = $time6->strftime('%Y-%m-%d');
+my $date7 = $time7->strftime('%Y-%m-%d');
+my $date8 = $time8->strftime('%Y-%m-%d');
+my $date9 = $time9->strftime('%Y-%m-%d');
+my $date_10 = $time_10->strftime('%Y-%m-%d');
+my $date_11 = $time_11->strftime('%Y-%m-%d');
+my $date_12 = $time_12->strftime('%Y-%m-%d');
+my $date_13 = $time_13->strftime('%Y-%m-%d');
+my $date_14 = $time_14->strftime('%Y-%m-%d');
+my $date_15 = $time_15->strftime('%Y-%m-%d');
+
+# DEFINE COMPARE DATA
+my $new_name2id = $channels_data->{'newname2id'};
+my $new_id2name = $channels_data->{'newid2name'};
+my $old_name2id = $channels_data->{'oldname2id'};
+my $old_id2name = $channels_data->{'oldid2name'};
+my @configname = @{ $channels_data->{'config'} };
+
+
+#
+# DOWNLOAD CHANNEL MANIFESTS
+#
+
+foreach my $configname ( @configname ) {
+
+ # DEFINE IDs
+ my $new_id = $new_name2id->{$configname};
+
+ # IF MATCH NOT FOUND: FIND CHANNEL NAME IN NEW CHANNEL LIST
+ if( defined $new_id ) {
+
+ # DAY 1
+ if( $day_setting == 1 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date2 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-2
+ } elsif( $day_setting == 2 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date3 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-3
+ } elsif( $day_setting == 3 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date4 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-4
+ } elsif( $day_setting == 4 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date5 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-5
+ } elsif( $day_setting == 5 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date6 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-6
+ } elsif( $day_setting == 6 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date7 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-7
+ } elsif( $day_setting == 7 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date8 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-8
+ } elsif( $day_setting == 8 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date9 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-9
+ } elsif( $day_setting == 9 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date_10 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-10
+ } elsif( $day_setting == 10 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date_11 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-11
+ } elsif( $day_setting == 11 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date_12 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-12
+ } elsif( $day_setting == 12 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date_13 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-13
+ } elsif( $day_setting == 13 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date_14 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ # DAYS 1-14
+ } elsif( $day_setting == 14 ) {
+ print "curl -s --compressed --connect-timeout 2 --max-time 10 --retry 8 --retry-delay 0 --retry-max-time 5 'https://tvtv.us/tvm/t/tv/v4/lineups/2381D/listings/grid?detail=%27brief%27&start=" . $date1 . "T00:00Z&end=" . $date_15 . "T23:59Z&startchan=" . $new_id . "&endchan=" . $new_id . "' | sed 's/\\[//' | sed 's/.\$//' | grep \"$new_id\" > mani/$new_id\n" ;
+
+ }
+
+ } else {
+ print STDERR "[ CHLIST WARNING ] CHANNEL \"$configname\" not found in channel list!\n";
+ }
+}