From 62f41a715050d4bfc78aaa99b1a6b0d8852ec949 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 16 Mar 2017 12:22:25 +0900 Subject: [PATCH 01/51] Update epg2xml.py --- epg2xml.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/epg2xml.py b/epg2xml.py index ea6a5e1..3e5b246 100644 --- a/epg2xml.py +++ b/epg2xml.py @@ -16,7 +16,7 @@ import argparse reload(sys) sys.setdefaultencoding('utf-8') -__version__ = '1.1.2' +__version__ = '1.1.3' # Set My Configuration default_icon_url = '' # TV channel icon url (ex : http://www.example.com/Channels) @@ -95,7 +95,6 @@ def getEpg(): GetEPGFromSKY(ChannelInfo) elif ChannelSource == 'NAVER': GetEPGFromNaver(ChannelInfo) - print('') # Get EPG data from epg.co.kr @@ -104,8 +103,7 @@ def GetEPGFromEPG(ChannelInfo): ChannelName = ChannelInfo[1] ServiceId = ChannelInfo[3] epginfo = [] - url = 'http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi' - contenturl = 'http://www.epg.co.kr/epg-cgi/guide_schedule_content.cgi' + url = 'http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi' for k in range(period): day = today + datetime.timedelta(days=k) params = {'beforegroup':'100', 'checkchannel':ServiceId, 'select_group':'100', 'start_date':day.strftime('%Y%m%d')} @@ -116,11 +114,11 @@ def GetEPGFromEPG(ChannelInfo): data = unicode(html_data, 'euc-kr', 'ignore').encode('utf-8', 'ignore') strainer = SoupStrainer('table', {'style':'margin-bottom:30'}) soup = BeautifulSoup(data, 'lxml', parse_only=strainer, from_encoding='utf-8') - table = soup.find_all('table', {'style':'margin-bottom:30'}) + tables = soup.find_all('table', {'style':'margin-bottom:30'}) for i in range(1,4): thisday = day - row = table[i].find_all('td', {'colspan':'2'}) + row = tables[i].find_all('td', {'colspan':'2'}) for j, cell in enumerate(row): hour = int(cell.text.strip().strip('시')) if(i == 1) : hour = 'AM ' + str(hour) @@ -436,14 +434,14 @@ def writeProgram(programdata): category = escape(programdata['category']) episode = programdata['episode'] rebroadcast = programdata['rebroadcast'] - if addepisode == 'y': programName = programName + '('+ episode + ')' + if episode and addepisode == 'y': programName = programName + ' ('+ str(episode) + '회)' if rebroadcast == True and addrebroadcast == 'y' : programName = programName + ' (재)' if programdata['rating'] == 0 : rating = '전체 관람가' else : rating = '%s세 이상 관람가' % (programdata['rating']) if verbose == 'y': - desc = programName + desc = escape(programdata['programName']) if subprogramName : desc = desc + '\n부제 : ' + subprogramName if episode : desc = desc + '\n회차 : ' + str(episode) + '회' if category : desc = desc + '\n장르 : ' + category From 3d185cc9a952a7383b95745ef4076f32602b8b9e Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 16 Mar 2017 12:22:41 +0900 Subject: [PATCH 02/51] Update readme.txt --- readme.txt | 82 ++++++++---------------------------------------------- 1 file changed, 12 insertions(+), 70 deletions(-) diff --git a/readme.txt b/readme.txt index 89d2e46..9cfe3a0 100644 --- a/readme.txt +++ b/readme.txt @@ -1,76 +1,18 @@ 목차 -0. 버전 -1. 소개 -2. 설치전 확인 사항 -3. 설치방법 -4. 설정방법 -5. 인수소개 -6. 변경사항 -7. 개선사항 -8. 알려진 버그 -9. 저작권 +1. 버전 +2. 소개 +3. 변경사항 +4. 저작권 -0. 버전 - 1.1.2 -1. 소개 - 이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2에서 사용 가능하도록 제작되었다. +1. 버전 + 1.1.3 + +2. 소개 + 이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5에서 사용 가능하도록 제작되었다. 기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. -2. 설치전 확인 사항 - BeautifulSoup(bs4), lxml 모듈이 추가로 필요하다. - 설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다. - synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml 이다 +3. 변경사항 + - 제목에 회차정보, 재방송 정보 추가시 오류 수정 -3. 설치방법 - 파일 압축 해제후 원하는 경로에 넣는다. - 3.1 tv_grab_file 사용시 - tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 - /파이썬설치경로/python /epg2xml.py 경로/epg2xml.py -i KT(SK, LG) -d 또는 - /epg2xml.py 경로/epg2xml.py -i KG(SK, LG) -d - 3.2 XMLTV 사용시 - /파이썬설치경로/python /epg2xml.py 경로/epg2xml.py -i KT(SK, LG) -s xmltv.sock경로 또는 - /epg2xml.py 경로/epg2xml.py -i KT(SK, LG) -s xmltv.sock 경로 - - - XMLTV 사용시에는 크론에 실행할 시간을 등록해야 한다. - -4. 설정방법 - # Set My Configuratoin 안의 항목이 설정 가능한 항목이다. 인수로 처리하지 않고 이 부분을 수정해서 사용할 수도 있지만, - 이 부분을 직접 수정하는 것보다는 향후 업그레이드시 변경될 수 있으므로 인수로 처리하기를 권장한다. - - default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다. - default_fetch_limit : EPG 데이터 가져오는 기간이다. - default_xml_filename : EPG 저장시 기본 저장 이름으로 tvheadend 서버가 쓰기가 가능한 경로로 설정해야 한다. - default_xml_socket : External XMLTV 사용시 xmltv.sock가 있는 경로로 설정해준다. - - Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보가 들어 있다. - 이중 Enabled:1로 되어 있는 부분을 Enabled:0으로 바꾸면 EPG정보를 가져오지 않는다. - 필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다. - 삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다. - -5. 인수소개 -실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다 - -h --help : 도움말 출력 - --version : 버전을 보여준다. - -i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT - -d --display : EPG 정보를 화면으로 보여준다. - -o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml - -s --socket : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock - -l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2 - --icon : 채널 icon 위치 URL ex) --icon http://www.example.com - --rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y - --episode : 제목에 회차정보 표기 ex) --episode y - --verbose : EPG 정보 상세하게 표기 ex) --verbose y - -6. 변경사항 - - 재방송정보, 회차정보 옵션 추가 - - 7. 개선사항 - - 코드 최적화 - - 속도 개선 - - 채널 json 편집기 추가 - -8. 알려진 버그 - - KT, LG, Naver, epg.co.kr을 소스로 하는 채널의 EPG정보는 가져오는 기간의 제일 마지막 방송정보를 표시하지 않음 - -9. 저작권 +4. 저작권 - BSD From a40b629188ddf808445079558b5435bf14ca585f Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 16 Mar 2017 12:23:03 +0900 Subject: [PATCH 03/51] Create epg2xml.php --- epg2xml.php | 565 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 565 insertions(+) create mode 100644 epg2xml.php diff --git a/epg2xml.php b/epg2xml.php new file mode 100644 index 0000000..d6ea211 --- /dev/null +++ b/epg2xml.php @@ -0,0 +1,565 @@ +#!/usr/bin/env php +getMessage()); + exit; + } + endif; + } + catch(Exception $e) { + printError($e->getMessage()); + exit; + } + + printf("\n"); + printf("\n\n"); + + printf("\n", VERSION); + + foreach ($Channeldatas as $Channeldata) : #Get Channel & Print Channel info + if($Channeldata['Enabled'] == 1) : + $ChannelId = $Channeldata['Id']; + $ChannelName = $Channeldata['Name']; + $ChannelSource = $Channeldata['Source']; + $ChannelServiceId = $Channeldata['ServiceId']; + $ChannelISPName = "[".$Channeldata[$MyISP.'Ch']."]".$Channeldata[$MyISP." Name"]; + $ChannelIconUrl = $Channeldata['Icon_url']; + + if($Channeldata[$MyISP.'Ch'] != Null): + $ChannelInfos[] = array($ChannelId, $ChannelName, $ChannelSource, $ChannelServiceId); + printf(" \n", $ChannelId); + printf(" %s\n", $ChannelName); + printf(" %s\n", $ChannelISPName); + if($IconUrl) : + printf(" \n", $IconUrl, $ChannelId); + else : + printf(" \n", $ChannelIconUrl); + endif; + printf(" \n"); + endif; + endif; + endforeach; + + # Print Program Information + foreach ($ChannelInfos as $ChannelInfo) : + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ChannelSource = $ChannelInfo[2]; + $ChannelServiceId = $ChannelInfo[3]; + if($GLOBALS['debug']) printLog($ChannelName.' 채널 EPG 데이터를 가져오고 있습니다'); + if($ChannelSource == 'EPG') : + //GetEPGFromEPG($ChannelInfo); + elseif($ChannelSource == 'KT') : + GetEPGFromKT($ChannelInfo); + elseif($ChannelSource == 'LG') : + GetEPGFromLG($ChannelInfo); + elseif($ChannelSource == 'SK') : + //GetEPGFromSK($ChannelInfo); + elseif($ChannelSource == 'SKY') : + GetEPGFromSKY(ChannelInfo); + elseif($ChannelSource == 'NAVER') : + GetEPGFromNaver(ChannelInfo); + endif; + endforeach; + print("\n"); +} +function GetEPGFromEPG($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $epginfo = array(); + $options = array( + 'http' => array( + 'method' => 'GET', + 'user-agent' => $GLOBALS['ua'] + )); + $context = stream_context_create($options); + + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi"; + $day = date("Ymd", strtotime("+".($k - 1)." days")); + $params = array( + 'beforegroup' => '100', + 'checkchannel' => $ServiceId, + 'select_group' => '100', + 'start_date' => $day + ); + + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + throw new Exception ($ChannelName.HTTP_ERROR); + else : + $response = str_replace("charset=euc-kr", "charset=utf-8", $response); + $dom = new DomDocument; + libxml_use_internal_errors(true); + $dom->loadHTML(mb_convert_encoding($response, 'UTF-8', 'EUC-KR')); + $xpath = new DomXPath($dom); + for($i = 2; $i < 5; $i++) : + $thisday = $day; + $query = "//table[contains(@style,'margin-bottom:30')][".$i."]//td[contains(@colspan,'2')]/following::td[1]/table[1]//td[2]"; + $programs = $xpath->query($query); + foreach($programs as $program) : + $hour = $xpath->query("parent::*/parent::*/parent::*/parent::*/td[1]", $program)->item(0); + $hour = str_replace("시", "", trim($hour->nodeValue)); + $minute = $xpath->query("preceding-sibling::td[1]", $program)->item(0); + $hour = $hour.":".str_replace(array("[", "]"), array("",""), trim($minute->nodeValue)); + switch ($i) : + case 2 : + $hour = $hour." AM"; + break; + case 3 : + $hour = $hour." PM"; + break; + case 4 : + if($hour > 5 ) : + $hour = $hour." PM"; + else : + $hour = $hour." AM"; + $thisday = date("Ymd", strtotime("+1 days")); + endif; + break; + endswitch; + $startTime = date("YmdHis", strtotime($thisday." ".$hour)); + preg_match('/?(.*)?(.*?)\s*(<(.*)>)?\s*(\(재\))?\s*(\(([\d,]+)회\))?()?\s*<\/td>/', trim($dom->saveHTML($program)), $matches); + //var_dump($matches); + if ($matches != NULL) : + $image = $matches[8] ? $matches[8] : ""; + preg_match('/.*schedule_([\d,]+)?.*/', $image, $grade); + if($grade != NULL) : + $rating = $grade[1]; + else : + $rating = 0; + endif; + endif; + #programName, startTime, rating, subprogramName, rebroadcast, episode + $epginfo[] = array(trim($matches[2]), $startTime, $rating, trim($matches[4]), $matches[5], $matches[7]); + endforeach; + endfor; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + $programName = $epg[0][0] ?: ""; + $subprogramName = $epg[0][3] ?: ""; + $startTime = $epg[0][1] ?: ""; + $endTime = $epg[1][1] ?: ""; + $desc = ""; + $actors = ""; + $producers = ""; + $category = ""; + $rebroadcast = $epg[0][4] ? True : False; + $episode = $epg[0][5] ?: ""; + $rating = $epg[0][2] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch (Exception $e) { + printError($e->getMessage()); + } + endforeach; +} +function GetEPGFromKT($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $epginfo = array(); + $options = array( + 'http' => array( + 'method' => 'GET', + 'user-agent' => $GLOBALS['ua'] + )); + $context = stream_context_create($options); +} +function GetEPGFromLG($ChannelInfo) { +} + +function GetEPGFromSK($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $today = date("Ymd"); + $lastday = date("Ymd", strtotime("+".($GLOBALS['period'] - 1)." days")); + $options = array( + 'http' => array( + 'method' => 'GET', + 'user-agent' => $GLOBALS['ua'] + )); + $context = stream_context_create($options); + $url = "http://m.btvplus.co.kr/Common/Inc/IFGetData.asp"; + $params = array( + 'variable' => 'IF_LIVECHART_DETAIL', + 'pcode' => '|^|start_time='.$today.'00|^|end_time='.$lastday.'24|^|svc_id='.$ServiceId + ); + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + throw new Exception ($ChannelName.HTTP_ERROR); + else : + try { + $data = json_decode($response, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); + if($data['channel'] == NULL) : + printError($ChannelName.CHANNEL_ERROR); + else : + $programs = $data['channel']['programs']; + foreach ($programs as $program) : + $programName = ""; + $subprogramName = ""; + $episode = ""; + $rebroadcast = False; + preg_match('/^(.*?)(?:\s*[\(<]([\d,회]+)[\)>])?(?:\s*<([^<]*?)>)?(\((재)\))?$/', str_replace('...', '>', $program['programName']), $matches); + if ($matches != NULL) : + $programName = trim($matches[1]) ?: ""; + $subprogramName = trim($matches[3]) ?: ""; + $episode = str_replace("회", "", $matches[2]) ?: ""; + $rebroadcast = $matches[5] ? True : False; + endif; + $startTime = date("YmdHis",$program['startTime']/1000); + $endTime = date("YmdHis",$program['endTime']/1000); + if ($GLOBALS['verbose'] == 'y') : + $desc = $program['synopsis'] ?: ""; + $actors =trim(str_replace('...','',$program['actorName']), ', ') ?: "";//.replace('...','').strip(', ') if program['actorName'] else '' + $producers = trim(str_replace('...','',$program['directorName']), ', ') ?: "";// if program['directorName'] else '' + else : + $desc = ""; + $actors = ""; + $producers = ""; + endif; + if ($program['mainGenreName'] != NULL) : + $category = $program['mainGenreName']; + else: + $category = ''; + endif; + $rating = $program['ratingCd'] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } + catch(Exception $e) { + printError($e->getMessage()); + } + endif; + } catch (Exception $e) { + printError($e->getMessage()); + } +} +function GetEPGFromSKY($ChannelInfo) { +} +function GetEPGFromNaver($ChannelInfo) { +} +function writeProgram($programdata) { + $ChannelId = $programdata['channelId']; + $startTime = $programdata['startTime']; + $endTime = $programdata['endTime']; + $programName = $programdata['programName']; + $subprogramName = $programdata['subprogramName']; + $actors = $programdata['actors']; + $producers = $programdata['producers']; + $category = $programdata['category']; + $episode = $programdata['episode']; + $rebroadcast = $programdata['rebroadcast']; + if($GLOBALS['addepisode'] == 'y') $programName = $programName." (".$episode."회)"; + if($rebroadcast == True && $GLOBALS['addrebroadcast'] == 'y') $programName = $programName." (재)"; + if($programdata['rating'] == 0) : + $rating = "전체 관람가"; + else : + $rating = sprintf("%s세 이상 관람가", $programdata['rating']); + endif; + if($GLOBALS['verbose'] == 'y') : + $desc = $programdata['programName']; + if($subprogramName) $desc = $desc."\n부제 : ".$subprogramName; + if($episode) $desc = $desc."\n회차 : (".$episode."회)"; + if($category) $desc = $desc."\n장르 : ".$category; + if($actors) $desc = $desc."\n출연 : ".$actors; + if($producers) $desc = $desc."\n제작 : ".$producers; + $desc = $desc."\n등급 : ".$rating; + else: + $desc = ""; + endif; + if($programdata['desc']) $desc = $desc."\n".$programdata['desc']; + $contentTypeDict = array( + '교양' => 'Arts / Culture (without music)', + '만화' => 'Cartoons / Puppets', + '교육' => 'Education / Science / Factual topics', + '취미' => 'Leisure hobbies', + '드라마' => 'Movie / Drama', + '영화' => 'Movie / Drama', + '음악' => 'Music / Ballet / Dance', + '뉴스' => 'News / Current affairs', + '다큐' => 'Documentary', + '시사/다큐' => 'Documentary', + '연예' => 'Show / Game show', + '스포츠' => 'Sports', + '홈쇼핑' => 'Advertisement / Shopping' + ); + $contentType = ""; + foreach($contentTypeDict as $key => $value) : + if(!(strpos($category, $key) === false)) : + $contentType = $value; + endif; + endforeach; + printf(" \n", $startTime, $endTime, $ChannelId); + printf(" %s\n", $programName); + if($subprogramName) : + printf(" %s\n", $subprogramName); + endif; + if($GLOBALS['verbose']=='y') : + printf(" %s\n", $desc); + if($actors || $producers): + printf(" \n"); + if($actors) : + foreach(split(',', $actors) as $actor): + if($actor) printf(" %s\n", $actor); + endforeach; + endif; + if($producers) : + foreach(split(',', $producers) as $producer): + if($producer) printf(" %s\n", $producer); + endforeach; + endif; + printf(" \n"); + endif; + endif; + if($category) printf(" %s\n", $category); + if($contentType) printf(" %s\n", $contentType); + if($episode) printf(" %s\n", $episode); + if($rebroadcast) printf(" \n"); + if($rating) : + printf(" \n"); + printf(" %s\n", $rating); + printf(" \n"); + endif; + printf(" \n"); +} +function printLog($args) { + fwrite(STDERR, $args."\n"); +} +function printError($args) { + fwrite(STDERR, "Error : ".$args."\n"); +} +set_error_handler (function ($errno, $errstr, $errfile, $errline) { + throw new ErrorException ($errstr, 0, $errno, $errfile, $errline); +}); +?> From cfcc343b546867cd6ae60b08921bd411d87cb0a8 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 16 Mar 2017 12:29:14 +0900 Subject: [PATCH 04/51] Update epg2xml.php --- epg2xml.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/epg2xml.php b/epg2xml.php index d6ea211..866d7e5 100644 --- a/epg2xml.php +++ b/epg2xml.php @@ -239,13 +239,13 @@ function getEPG() { $ChannelServiceId = $ChannelInfo[3]; if($GLOBALS['debug']) printLog($ChannelName.' 채널 EPG 데이터를 가져오고 있습니다'); if($ChannelSource == 'EPG') : - //GetEPGFromEPG($ChannelInfo); + GetEPGFromEPG($ChannelInfo); elseif($ChannelSource == 'KT') : GetEPGFromKT($ChannelInfo); elseif($ChannelSource == 'LG') : GetEPGFromLG($ChannelInfo); elseif($ChannelSource == 'SK') : - //GetEPGFromSK($ChannelInfo); + GetEPGFromSK($ChannelInfo); elseif($ChannelSource == 'SKY') : GetEPGFromSKY(ChannelInfo); elseif($ChannelSource == 'NAVER') : From fb4453e7a746d6c1a78321d504d7d4b562df834c Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 16 Mar 2017 12:30:57 +0900 Subject: [PATCH 05/51] Delete epg2xml.php --- epg2xml.php | 565 ---------------------------------------------------- 1 file changed, 565 deletions(-) delete mode 100644 epg2xml.php diff --git a/epg2xml.php b/epg2xml.php deleted file mode 100644 index 866d7e5..0000000 --- a/epg2xml.php +++ /dev/null @@ -1,565 +0,0 @@ -#!/usr/bin/env php -getMessage()); - exit; - } - endif; - } - catch(Exception $e) { - printError($e->getMessage()); - exit; - } - - printf("\n"); - printf("\n\n"); - - printf("\n", VERSION); - - foreach ($Channeldatas as $Channeldata) : #Get Channel & Print Channel info - if($Channeldata['Enabled'] == 1) : - $ChannelId = $Channeldata['Id']; - $ChannelName = $Channeldata['Name']; - $ChannelSource = $Channeldata['Source']; - $ChannelServiceId = $Channeldata['ServiceId']; - $ChannelISPName = "[".$Channeldata[$MyISP.'Ch']."]".$Channeldata[$MyISP." Name"]; - $ChannelIconUrl = $Channeldata['Icon_url']; - - if($Channeldata[$MyISP.'Ch'] != Null): - $ChannelInfos[] = array($ChannelId, $ChannelName, $ChannelSource, $ChannelServiceId); - printf(" \n", $ChannelId); - printf(" %s\n", $ChannelName); - printf(" %s\n", $ChannelISPName); - if($IconUrl) : - printf(" \n", $IconUrl, $ChannelId); - else : - printf(" \n", $ChannelIconUrl); - endif; - printf(" \n"); - endif; - endif; - endforeach; - - # Print Program Information - foreach ($ChannelInfos as $ChannelInfo) : - $ChannelId = $ChannelInfo[0]; - $ChannelName = $ChannelInfo[1]; - $ChannelSource = $ChannelInfo[2]; - $ChannelServiceId = $ChannelInfo[3]; - if($GLOBALS['debug']) printLog($ChannelName.' 채널 EPG 데이터를 가져오고 있습니다'); - if($ChannelSource == 'EPG') : - GetEPGFromEPG($ChannelInfo); - elseif($ChannelSource == 'KT') : - GetEPGFromKT($ChannelInfo); - elseif($ChannelSource == 'LG') : - GetEPGFromLG($ChannelInfo); - elseif($ChannelSource == 'SK') : - GetEPGFromSK($ChannelInfo); - elseif($ChannelSource == 'SKY') : - GetEPGFromSKY(ChannelInfo); - elseif($ChannelSource == 'NAVER') : - GetEPGFromNaver(ChannelInfo); - endif; - endforeach; - print("\n"); -} -function GetEPGFromEPG($ChannelInfo) { - $ChannelId = $ChannelInfo[0]; - $ChannelName = $ChannelInfo[1]; - $ServiceId = $ChannelInfo[3]; - $epginfo = array(); - $options = array( - 'http' => array( - 'method' => 'GET', - 'user-agent' => $GLOBALS['ua'] - )); - $context = stream_context_create($options); - - foreach(range(1, $GLOBALS['period']) as $k) : - $url = "http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi"; - $day = date("Ymd", strtotime("+".($k - 1)." days")); - $params = array( - 'beforegroup' => '100', - 'checkchannel' => $ServiceId, - 'select_group' => '100', - 'start_date' => $day - ); - - $params = http_build_query($params); - $url = $url."?".$params; - try { - $response = @file_get_contents($url, False, $context); - if ($response === False) : - throw new Exception ($ChannelName.HTTP_ERROR); - else : - $response = str_replace("charset=euc-kr", "charset=utf-8", $response); - $dom = new DomDocument; - libxml_use_internal_errors(true); - $dom->loadHTML(mb_convert_encoding($response, 'UTF-8', 'EUC-KR')); - $xpath = new DomXPath($dom); - for($i = 2; $i < 5; $i++) : - $thisday = $day; - $query = "//table[contains(@style,'margin-bottom:30')][".$i."]//td[contains(@colspan,'2')]/following::td[1]/table[1]//td[2]"; - $programs = $xpath->query($query); - foreach($programs as $program) : - $hour = $xpath->query("parent::*/parent::*/parent::*/parent::*/td[1]", $program)->item(0); - $hour = str_replace("시", "", trim($hour->nodeValue)); - $minute = $xpath->query("preceding-sibling::td[1]", $program)->item(0); - $hour = $hour.":".str_replace(array("[", "]"), array("",""), trim($minute->nodeValue)); - switch ($i) : - case 2 : - $hour = $hour." AM"; - break; - case 3 : - $hour = $hour." PM"; - break; - case 4 : - if($hour > 5 ) : - $hour = $hour." PM"; - else : - $hour = $hour." AM"; - $thisday = date("Ymd", strtotime("+1 days")); - endif; - break; - endswitch; - $startTime = date("YmdHis", strtotime($thisday." ".$hour)); - preg_match('/?(.*)?(.*?)\s*(<(.*)>)?\s*(\(재\))?\s*(\(([\d,]+)회\))?()?\s*<\/td>/', trim($dom->saveHTML($program)), $matches); - //var_dump($matches); - if ($matches != NULL) : - $image = $matches[8] ? $matches[8] : ""; - preg_match('/.*schedule_([\d,]+)?.*/', $image, $grade); - if($grade != NULL) : - $rating = $grade[1]; - else : - $rating = 0; - endif; - endif; - #programName, startTime, rating, subprogramName, rebroadcast, episode - $epginfo[] = array(trim($matches[2]), $startTime, $rating, trim($matches[4]), $matches[5], $matches[7]); - endforeach; - endfor; - $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); - foreach($zipped as $epg) : - $programName = $epg[0][0] ?: ""; - $subprogramName = $epg[0][3] ?: ""; - $startTime = $epg[0][1] ?: ""; - $endTime = $epg[1][1] ?: ""; - $desc = ""; - $actors = ""; - $producers = ""; - $category = ""; - $rebroadcast = $epg[0][4] ? True : False; - $episode = $epg[0][5] ?: ""; - $rating = $epg[0][2] ?: 0; - $programdata = array( - 'channelId'=> $ChannelId, - 'startTime' => $startTime, - 'endTime' => $endTime, - 'programName' => $programName, - 'subprogramName'=> $subprogramName, - 'desc' => $desc, - 'actors' => $actors, - 'producers' => $producers, - 'category' => $category, - 'episode' => $episode, - 'rebroadcast' => $rebroadcast, - 'rating' => $rating - ); - writeProgram($programdata); - endforeach; - endif; - } catch (Exception $e) { - printError($e->getMessage()); - } - endforeach; -} -function GetEPGFromKT($ChannelInfo) { - $ChannelId = $ChannelInfo[0]; - $ChannelName = $ChannelInfo[1]; - $ServiceId = $ChannelInfo[3]; - $epginfo = array(); - $options = array( - 'http' => array( - 'method' => 'GET', - 'user-agent' => $GLOBALS['ua'] - )); - $context = stream_context_create($options); -} -function GetEPGFromLG($ChannelInfo) { -} - -function GetEPGFromSK($ChannelInfo) { - $ChannelId = $ChannelInfo[0]; - $ChannelName = $ChannelInfo[1]; - $ServiceId = $ChannelInfo[3]; - $today = date("Ymd"); - $lastday = date("Ymd", strtotime("+".($GLOBALS['period'] - 1)." days")); - $options = array( - 'http' => array( - 'method' => 'GET', - 'user-agent' => $GLOBALS['ua'] - )); - $context = stream_context_create($options); - $url = "http://m.btvplus.co.kr/Common/Inc/IFGetData.asp"; - $params = array( - 'variable' => 'IF_LIVECHART_DETAIL', - 'pcode' => '|^|start_time='.$today.'00|^|end_time='.$lastday.'24|^|svc_id='.$ServiceId - ); - $params = http_build_query($params); - $url = $url."?".$params; - try { - $response = @file_get_contents($url, False, $context); - if ($response === False) : - throw new Exception ($ChannelName.HTTP_ERROR); - else : - try { - $data = json_decode($response, TRUE); - if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); - if($data['channel'] == NULL) : - printError($ChannelName.CHANNEL_ERROR); - else : - $programs = $data['channel']['programs']; - foreach ($programs as $program) : - $programName = ""; - $subprogramName = ""; - $episode = ""; - $rebroadcast = False; - preg_match('/^(.*?)(?:\s*[\(<]([\d,회]+)[\)>])?(?:\s*<([^<]*?)>)?(\((재)\))?$/', str_replace('...', '>', $program['programName']), $matches); - if ($matches != NULL) : - $programName = trim($matches[1]) ?: ""; - $subprogramName = trim($matches[3]) ?: ""; - $episode = str_replace("회", "", $matches[2]) ?: ""; - $rebroadcast = $matches[5] ? True : False; - endif; - $startTime = date("YmdHis",$program['startTime']/1000); - $endTime = date("YmdHis",$program['endTime']/1000); - if ($GLOBALS['verbose'] == 'y') : - $desc = $program['synopsis'] ?: ""; - $actors =trim(str_replace('...','',$program['actorName']), ', ') ?: "";//.replace('...','').strip(', ') if program['actorName'] else '' - $producers = trim(str_replace('...','',$program['directorName']), ', ') ?: "";// if program['directorName'] else '' - else : - $desc = ""; - $actors = ""; - $producers = ""; - endif; - if ($program['mainGenreName'] != NULL) : - $category = $program['mainGenreName']; - else: - $category = ''; - endif; - $rating = $program['ratingCd'] ?: 0; - $programdata = array( - 'channelId'=> $ChannelId, - 'startTime' => $startTime, - 'endTime' => $endTime, - 'programName' => $programName, - 'subprogramName'=> $subprogramName, - 'desc' => $desc, - 'actors' => $actors, - 'producers' => $producers, - 'category' => $category, - 'episode' => $episode, - 'rebroadcast' => $rebroadcast, - 'rating' => $rating - ); - writeProgram($programdata); - endforeach; - endif; - } - catch(Exception $e) { - printError($e->getMessage()); - } - endif; - } catch (Exception $e) { - printError($e->getMessage()); - } -} -function GetEPGFromSKY($ChannelInfo) { -} -function GetEPGFromNaver($ChannelInfo) { -} -function writeProgram($programdata) { - $ChannelId = $programdata['channelId']; - $startTime = $programdata['startTime']; - $endTime = $programdata['endTime']; - $programName = $programdata['programName']; - $subprogramName = $programdata['subprogramName']; - $actors = $programdata['actors']; - $producers = $programdata['producers']; - $category = $programdata['category']; - $episode = $programdata['episode']; - $rebroadcast = $programdata['rebroadcast']; - if($GLOBALS['addepisode'] == 'y') $programName = $programName." (".$episode."회)"; - if($rebroadcast == True && $GLOBALS['addrebroadcast'] == 'y') $programName = $programName." (재)"; - if($programdata['rating'] == 0) : - $rating = "전체 관람가"; - else : - $rating = sprintf("%s세 이상 관람가", $programdata['rating']); - endif; - if($GLOBALS['verbose'] == 'y') : - $desc = $programdata['programName']; - if($subprogramName) $desc = $desc."\n부제 : ".$subprogramName; - if($episode) $desc = $desc."\n회차 : (".$episode."회)"; - if($category) $desc = $desc."\n장르 : ".$category; - if($actors) $desc = $desc."\n출연 : ".$actors; - if($producers) $desc = $desc."\n제작 : ".$producers; - $desc = $desc."\n등급 : ".$rating; - else: - $desc = ""; - endif; - if($programdata['desc']) $desc = $desc."\n".$programdata['desc']; - $contentTypeDict = array( - '교양' => 'Arts / Culture (without music)', - '만화' => 'Cartoons / Puppets', - '교육' => 'Education / Science / Factual topics', - '취미' => 'Leisure hobbies', - '드라마' => 'Movie / Drama', - '영화' => 'Movie / Drama', - '음악' => 'Music / Ballet / Dance', - '뉴스' => 'News / Current affairs', - '다큐' => 'Documentary', - '시사/다큐' => 'Documentary', - '연예' => 'Show / Game show', - '스포츠' => 'Sports', - '홈쇼핑' => 'Advertisement / Shopping' - ); - $contentType = ""; - foreach($contentTypeDict as $key => $value) : - if(!(strpos($category, $key) === false)) : - $contentType = $value; - endif; - endforeach; - printf(" \n", $startTime, $endTime, $ChannelId); - printf(" %s\n", $programName); - if($subprogramName) : - printf(" %s\n", $subprogramName); - endif; - if($GLOBALS['verbose']=='y') : - printf(" %s\n", $desc); - if($actors || $producers): - printf(" \n"); - if($actors) : - foreach(split(',', $actors) as $actor): - if($actor) printf(" %s\n", $actor); - endforeach; - endif; - if($producers) : - foreach(split(',', $producers) as $producer): - if($producer) printf(" %s\n", $producer); - endforeach; - endif; - printf(" \n"); - endif; - endif; - if($category) printf(" %s\n", $category); - if($contentType) printf(" %s\n", $contentType); - if($episode) printf(" %s\n", $episode); - if($rebroadcast) printf(" \n"); - if($rating) : - printf(" \n"); - printf(" %s\n", $rating); - printf(" \n"); - endif; - printf(" \n"); -} -function printLog($args) { - fwrite(STDERR, $args."\n"); -} -function printError($args) { - fwrite(STDERR, "Error : ".$args."\n"); -} -set_error_handler (function ($errno, $errstr, $errfile, $errline) { - throw new ErrorException ($errstr, 0, $errno, $errfile, $errline); -}); -?> From cec4a9ac62a3174d71e6392d05e5412cf64f0761 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Tue, 21 Mar 2017 15:56:19 +0900 Subject: [PATCH 06/51] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8e0c1de..f1fdf2d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # EPG2XML -이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5에서 사용 가능하도록 제작되었다. +이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 cli에서 사용 가능하도록 제작되었다. 기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. ## 필요 모듈 @@ -10,7 +10,7 @@ BeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다. 설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다. synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다. -### EPG2XML.php +### EPG2XML.PHP PHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. ## 설치방법 From 5c7df6ca69098e45bc2eea6c654999a2d50476b8 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Mon, 27 Mar 2017 18:04:52 +0900 Subject: [PATCH 07/51] Update README.md --- README.md | 78 +++++++++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index f1fdf2d..08102f2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # EPG2XML -이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 cli에서 사용 가능하도록 제작되었다. +이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다. 기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. ## 필요 모듈 @@ -10,43 +10,13 @@ BeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다. 설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다. synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다. -### EPG2XML.PHP +### EPG2XML.php PHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. -## 설치방법 - -### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea) -tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 - -#### PYTHON의 경우 -
-/usr/bin/python /home/hts/epg2xml.py -i KT(SK, LG) -d 또는
-/home/hts/epg2xml.py -i KG(SK, LG) -d
-
- -#### PHP의 경우 -
-/usr/bin/php /home/hts/epg2xml.php -i KT(SK, LG) -d 또는
-/home/hts/epg2xml.php -i KG(SK, LG) -d
-
- -### XMLTV 사용시 -#### PYTHON의 경우 -
-/usr/bin/python /home/hts/epg2xml.py -i KT(SK, LG) -s xmltv.sock경로 또는
-/home/hts/epg2xml.py -i KT(SK, LG) -s xmltv.sock 경로
-
- -#### PHP의 경우 -
-/usr/bin/php /home/hts/epg2xml.php -i KT(SK, LG) -s xmltv.sock경로 또는
-/home/hts/epg2xml.php -i KT(SK, LG) -s xmltv.sock 경로
-
- ## 설정방법 -Set My Configuratoin 안의 항목이 설정 가능한 항목이다. 인수로 처리하지 않고 이 부분을 수정해서 사용할 수도 있지만, -이 부분을 직접 수정하는 것보다는 향후 업그레이드시 변경될 수 있으므로 인수로 처리하기를 권장한다. +epg2xml.json 안의 항목이 설정 가능한 항목이다.
+MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)
 default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
 default_rebroadcast : 제목에 재방송 정보 출력
 default_episode : 제목에 회차정보 출력
@@ -61,21 +31,43 @@ Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보
 필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다.
 삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다.
 
+## 사용방법
+
+### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea)
+epg2xml
+tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을
+
+#### PYTHON의 경우
+
+/usr/bin/python /home/hts/epg2xml.py 또는
+/home/hts/epg2xml.py
+
+ +#### PHP의 경우 +
+/usr/bin/php /home/hts/epg2xml.php 또는
+/home/hts/epg2xml.php
+
+ +### XMLTV 사용시 +#### PYTHON의 경우 +
+/usr/bin/python /home/hts/epg2xml.py 또는
+/home/hts/epg2xml.py
+
+ +#### PHP의 경우 +
+/usr/bin/php /home/hts/epg2xml.php 또는
+/home/hts/epg2xml.php
+
+ ## 옵션 소개 실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다
 -h --help : 도움말 출력
 --version : 버전을 보여준다.
--i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
--d --display : EPG 정보를 화면으로 보여준다.
--o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
--s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
--l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2
---icon : 채널 icon 위치 URL ex) --icon http://www.example.com
---rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y
---episode : 제목에 회차정보 표기 ex) --episode y
---verbose : EPG 정보 상세하게 표기 ex) --verbose y
 
## 라이센스 From 63d3dfb149069cea43cce9c894a1ad84d60e4842 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Mon, 27 Mar 2017 18:05:25 +0900 Subject: [PATCH 08/51] add epg2xml.json --- epg2xml.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 epg2xml.json diff --git a/epg2xml.json b/epg2xml.json new file mode 100644 index 0000000..ce02869 --- /dev/null +++ b/epg2xml.json @@ -0,0 +1,26 @@ +{ + "###_COMMENT_###" : "", + "###_COMMENT_###" : "epg 정보를 가져오는 설정 파일", + "###_COMMENT_###" : "사용하는 ISP 선택 (KT, LG, SK)", + "MyISP": "KT", + "###_COMMENT_###" : "output 셋팅은 (d, o, s) 셋중에 하나로 선택한다", + "###_COMMENT_###" : " d - EPG 정보 화면 출력", + "###_COMMENT_###" : " o - EPG 정보 파일로 저정", + "###_COMMENT_###" : " s - EPG 정보 소켓으로 출력", + "output": "d", + "###_COMMENT_###" : "### TV channel icon url (ex : http://www.example.com/Channels) ###", + "default_icon_url": "", + "###_COMMENT_###" : "### 제목에 재방송 정보 출력 ###", + "default_rebroadcast": "y", + "###_COMMENT_###" : "#### 제목에 회차정보 출력 ###", + "default_episode" : "n", + "###_COMMENT_###" : "### EPG 정보 추가 출력 ###", + "default_verbose" : "n", + "###_COMMENT_###" : "### epg 데이터 가져오는 기간으로 1에서 7까지 설정가능 ###", + "default_fetch_limit" : "2", + "###_COMMENT_###" : "### epg 저장시 기본 저장 이름 (ex: /home/tvheadend/xmltv.xml) ###", + "default_xml_filename" : "xmltv.xml", + "###_COMMENT_###" : "### # External XMLTV 사용시 기본 소켓 이름 (ex: /home/tvheadend/xmltv.sock) ###", + "default_xml_socket" : "xmltv.sock", + "###_COMMENT_###" : "" +} From 898efdc8b9a943e24fab2d7310027cc640ebbf44 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Mon, 27 Mar 2017 18:05:45 +0900 Subject: [PATCH 09/51] Update epg2xml.py --- epg2xml.py | 202 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 128 insertions(+), 74 deletions(-) diff --git a/epg2xml.py b/epg2xml.py index 3e5b246..1bcc10b 100644 --- a/epg2xml.py +++ b/epg2xml.py @@ -13,19 +13,20 @@ import socket import re from xml.sax.saxutils import escape, unescape import argparse +import pprint reload(sys) sys.setdefaultencoding('utf-8') -__version__ = '1.1.3' +__version__ = '1.1.4' # Set My Configuration -default_icon_url = '' # TV channel icon url (ex : http://www.example.com/Channels) -default_rebroadcast = 'y' # 제목에 재방송 정보 출력 -default_episode = 'n' # 제목에 회차정보 출력 -default_verbose = 'n' # 자세한 epg 데이터 출력 -default_fetch_limit = 2 # epg 데이터 가져오는 기간 -default_xml_filename = 'xmltv.xml' # epg 저장시 기본 저장 이름 (ex: /home/tvheadend/xmltv.xml) -default_xml_socket = 'xmltv.sock' # External XMLTV 사용시 기본 소켓 이름 (ex: /home/tvheadend/xmltv.sock) +#default_icon_url = '' # TV channel icon url (ex : http://www.example.com/Channels) +#default_rebroadcast = 'y' # 제목에 재방송 정보 출력 +#default_episode = 'n' # 제목에 회차정보 출력 +#default_verbose = 'n' # 자세한 epg 데이터 출력 +#default_fetch_limit = 2 # epg 데이터 가져오는 기간 +#default_xml_filename = 'xmltv.xml' # epg 저장시 기본 저장 이름 (ex: /home/tvheadend/xmltv.xml) +#default_xml_socket = 'xmltv.sock' # External XMLTV 사용시 기본 소켓 이름 (ex: /home/tvheadend/xmltv.sock) # Set My Configuration # Set variable @@ -36,8 +37,8 @@ CHANNEL_ERROR = ' 존재하지 않는 채널입니다.' CONTENT_ERROR = ' EPG 정보가 없습니다.' HTTP_ERROR = ' EPG 정보를 가져오는데 문제가 있습니다.' SOCKET_ERROR = 'xmltv.sock 파일을 찾을 수 없습니다.' -JSON_FILE_ERROR = 'Channel.json 파일을 읽을 수 없습니다.' -JSON_SYNTAX_ERROR = 'Channel.json 파일 형식이 잘못되었습니다.' +JSON_FILE_ERROR = 'json 파일을 읽을 수 없습니다.' +JSON_SYNTAX_ERROR = 'json 파일 형식이 잘못되었습니다.' # Get epg data def getEpg(): @@ -47,10 +48,10 @@ def getEpg(): with open(Channelfile) as f: # Read Channel Information file Channeldatas = json.load(f) except EnvironmentError: - printError(JSON_FILE_ERROR) + printError("Channel." + JSON_FILE_ERROR) sys.exit() except ValueError: - printError(JSON_SYNTAX_ERROR) + printError("Channel." + JSON_SYNTAX_ERROR) sys.exit() print('') @@ -87,7 +88,7 @@ def getEpg(): GetEPGFromEPG(ChannelInfo) elif ChannelSource == 'KT': GetEPGFromKT(ChannelInfo) - elif ChannelSource == 'LG': + elif ChannelSource == 'LG': GetEPGFromLG(ChannelInfo) elif ChannelSource == 'SK': GetEPGFromSK(ChannelInfo) @@ -103,7 +104,7 @@ def GetEPGFromEPG(ChannelInfo): ChannelName = ChannelInfo[1] ServiceId = ChannelInfo[3] epginfo = [] - url = 'http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi' + url = 'http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi' for k in range(period): day = today + datetime.timedelta(days=k) params = {'beforegroup':'100', 'checkchannel':ServiceId, 'select_group':'100', 'start_date':day.strftime('%Y%m%d')} @@ -141,7 +142,7 @@ def GetEPGFromEPG(ChannelInfo): else : rating = 0 #programName, startTime, rating, subprogramName, rebroadcast, episode epginfo.append([matches.group(2), startTime, rating, matches.group(4), matches.group(5), matches.group(7)]) - + for epg1, epg2 in zip(epginfo, epginfo[1:]): programName = epg1[0] if epg1[0] else '' subprogramName = epg1[3] if epg1[3] else '' @@ -223,13 +224,13 @@ def GetEPGFromLG(ChannelInfo): for k in range(period): day = today + datetime.timedelta(days=k) params = {'chnlCd': ServiceId, 'evntCmpYmd': day.strftime('%Y%m%d')} - + try: response = requests.get(url, params=params, headers=ua) response.raise_for_status() html_data = response.content data = unicode(html_data, 'euc-kr', 'ignore').encode('utf-8', 'ignore') - strainer = SoupStrainer('table') + strainer = SoupStrainer('table') soup = BeautifulSoup(data, 'lxml', parse_only=strainer, from_encoding='utf-8') html = soup.find('table', {'class':'datatable06'}).tbody.find_all('tr') if soup.find('table', {'class':'datatable06'}) else '' if(html): @@ -264,7 +265,7 @@ def GetEPGFromLG(ChannelInfo): except requests.exceptions.HTTPError: if(debug): printError(ChannelName + HTTP_ERROR) else: pass - + # Get EPG data from SK def GetEPGFromSK(ChannelInfo): ChannelId = ChannelInfo[0] @@ -280,7 +281,8 @@ def GetEPGFromSK(ChannelInfo): try: data = json.loads(json_data, encoding='utf-8') if (data['channel'] is None) : - printError(ChannelName + CHANNEL_ERROR) + if(debug): printError(ChannelName + CONTENT_ERROR) + else: pass else : programs = data['channel']['programs'] for program in programs: @@ -298,7 +300,7 @@ def GetEPGFromSK(ChannelInfo): startTime = startTime.strftime('%Y%m%d%H%M%S') endTime = datetime.datetime.fromtimestamp(int(program['endTime'])/1000) endTime = endTime.strftime('%Y%m%d%H%M%S') - if verbose=='y' : + if addverbose=='y' : desc = program['synopsis'] if program['synopsis'] else '' actors = program['actorName'].replace('...','').strip(', ') if program['actorName'] else '' producers = program['directorName'].replace('...','').strip(', ') if program['directorName'] else '' @@ -345,11 +347,10 @@ def GetEPGFromSKY(ChannelInfo): subprogramName = unescape(program['program_subname']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['program_subname'] else '' startTime = program['starttime'] endTime = program['endtime'] - if verbose == 'y': + if addverbose == 'y': actors = program['cast'].replace('...','').strip(', ') if program['cast'] else '' producers = program['dirt'].replace('...','').strip(', ') if program['dirt'] else '' description = unescape(program['description']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['description'] else '' - if description: description = unescape(description).replace('lt;','<').replace('gt;','>').replace('amp;','&') summary = unescape(program['summary']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['summary'] else '' desc = description if description else '' if summary : desc = desc + '\n' + summary @@ -421,7 +422,6 @@ def GetEPGFromNaver(ChannelInfo): if(debug): printError(ChannelName + HTTP_ERROR) else: pass - # Write Program def writeProgram(programdata): ChannelId = programdata['channelId'] @@ -440,7 +440,7 @@ def writeProgram(programdata): rating = '전체 관람가' else : rating = '%s세 이상 관람가' % (programdata['rating']) - if verbose == 'y': + if addverbose == 'y': desc = escape(programdata['programName']) if subprogramName : desc = desc + '\n부제 : ' + subprogramName if episode : desc = desc + '\n회차 : ' + str(episode) + '회' @@ -460,7 +460,7 @@ def writeProgram(programdata): print(' %s' % (programName)) if subprogramName : print(' %s' % (subprogramName)) - if verbose=='y' : + if addverbose=='y' : print(' %s' % (desc)) if actors or producers: print(' ') @@ -471,7 +471,7 @@ def writeProgram(programdata): for producer in producers.split(','): if producer: print(' %s' % (producer)) print(' ') - + if category: print(' %s' % (category)) if contentType: print(' %s' % (contentType)) if episode: print(' %s' % (episode)) @@ -489,65 +489,119 @@ def printLog(*args): def printError(*args): print("Error : ", *args, file=sys.stderr) -parser = argparse.ArgumentParser(description = 'EPG 정보를 출력하는 방법을 선택한다') -argu1 = parser.add_argument_group(description = 'IPTV 선택') -argu1.add_argument('-i', dest = 'iptv', choices = ['KT', 'LG', 'SK'], help = '사용하는 IPTV : KT, LG, SK', required = True) -argu2 = parser.add_mutually_exclusive_group(required = True) -argu2.add_argument('-v', '--version', action = 'version', version = '%(prog)s version : ' + __version__) -argu2.add_argument('-d', '--display', action = 'store_true', help = 'EPG 정보 화면출력') -argu2.add_argument('-o', '--outfile', metavar = default_xml_filename, nargs = '?', const = default_xml_filename, help = 'EPG 정보 저장') -argu2.add_argument('-s', '--socket', metavar = default_xml_socket, nargs = '?', const = default_xml_socket, help = 'xmltv.sock(External: XMLTV)로 EPG정보 전송') -argu3 = parser.add_argument_group('추가옵션') -argu3.add_argument('-l', '--limit', dest = 'limit', type = int, metavar = "1-7", choices = range(1,8), help = 'EPG 정보를 가져올 기간, 기본값: '+ str(default_fetch_limit), default = default_fetch_limit) -argu3.add_argument('--icon', dest = 'icon', metavar = "http://www.example.com/icon", help = '채널 아이콘 URL, 기본값: '+ default_icon_url, default = default_icon_url) -argu3.add_argument('--rebroadcast', dest = 'rebroadcast', metavar = 'y, n', choices = 'yn', help = '제목에 재방송 정보 출력', default = default_rebroadcast) -argu3.add_argument('--episode', dest = 'episode', metavar = 'y, n', choices = 'yn', help = '제목에 회차 정보 출력', default = default_episode) -argu3.add_argument('--verbose', dest = 'verbose', metavar = 'y, n', choices = 'yn', help = 'EPG 정보 추가 출력', default = default_verbose) +parser = argparse.ArgumentParser(description = 'EPG 정보 출력 프로그램') +parser.add_argument('-v', '--version', action = 'version', version = '%(prog)s version : ' + __version__) +parser.parse_args() -args = parser.parse_args() -if args.iptv: - if any(args.iptv in s for s in ['KT', 'LG', 'SK']): - MyISP = args.iptv - else: +Settingfile = os.path.dirname(os.path.abspath(__file__)) + '/epg2xml.json' +ChannelInfos = [] +try: + with open(Settingfile) as f: # Read Channel Information file + Settings = json.load(f) + MyISP = Settings['MyISP'] if 'MyISP' in Settings else '' + default_output = Settings['output'] if 'output' in Settings else '' + default_icon_url = Settings['default_icon_url'] if 'default_icon_url' in Settings else None + default_rebroadcast = Settings['default_rebroadcast'] if 'default_rebroadcast' in Settings else '' + default_episode = Settings['default_episode'] if 'default_episode' in Settings else '' + default_verbose = Settings['default_verbose'] if 'default_verbose' in Settings else '' + default_fetch_limit = Settings['default_fetch_limit'] if 'default_fetch_limit' in Settings else '' + default_xml_filename = Settings['default_xml_filename'] if 'default_xml_filename' in Settings else '' + default_xml_socket = Settings['default_xml_socket'] if 'default_xml_socket' in Settings else '' +except EnvironmentError: + printError("epg2xml." + JSON_FILE_ERROR) + sys.exit() +except ValueError: + printError("epg2xml." + JSON_SYNTAX_ERROR) + sys.exit() + +if MyISP: + if not any(MyISP in s for s in ['KT', 'LG', 'SK']): + printError("MyISP는 KT, LG, SK만 가능합니다.") sys.exit() +else : + printError("epg2xml.json 파일의 MyISP항목이 없습니다.") + sys.exit() -if args.limit: - period = args.limit -else: - period = default_fetch_limit +if default_output : + if any(default_output in s for s in ['d', 'o', 's']): + if default_output == "d" : + output = "display"; + elif default_output == "o" : + output = "file"; + elif default_output == 's' : + output = "socket"; + else : + printError("default_output는 d, o, s만 가능합니다.") + sys.exit() +else : + printError("epg2xml.json 파일의 output항목이 없습니다."); + sys.exit() -if args.icon: - IconUrl = args.icon -else: +if default_icon_url : + printError("epg2xml.json 파일의 default_icon_url항목이 없습니다."); + sys.exit() +else : IconUrl = default_icon_url -if args.rebroadcast: - addrebroadcast = args.rebroadcast -else: - addrebroadecast = default_rebroadecast +if default_rebroadcast : + if not any(default_rebroadcast in s for s in ['y', 'n']): + printError("default_rebroadcast는 y, n만 가능합니다.") + sys.exit() + else : + addrebroadcast = default_rebroadcast +else : + printError("epg2xml.json 파일의 default_rebroadcast항목이 없습니다."); + sys.exit() +if default_episode : + if not any(default_episode in s for s in ['y', 'n']): + printError("default_episode는 y, n만 가능합니다.") + sys.exit() + else : + addepisode = default_episode +else : + printError("epg2xml.json 파일의 default_episode항목이 없습니다."); + sys.exit() -if args.episode: - addepisode = args.episode -else: - addepisode = default_episode +if default_verbose : + if not any(default_verbose in s for s in ['y', 'n']): + printError("default_verbose는 y, n만 가능합니다.") + sys.exit() + else : + addverbose = default_verbose +else : + printError("epg2xml.json 파일의 default_verbose항목이 없습니다."); + sys.exit() -if args.verbose: - verbose = args.verbose -else: - verbose = default_verbse +if default_fetch_limit : + if not any(default_fetch_limit in s for s in ['1', '2', '3', '4', '5', '6', '7']): + printError("default_fetch_limit 는 1, 2, 3, 4, 5, 6, 7만 가능합니다.") + sys.exit() + else : + period = int(default_fetch_limit) +else : + printError("epg2xml.json 파일의 default_fetch_limit항목이 없습니다."); + sys.exit() -if args.outfile: - sys.stdout = codecs.open(args.outfile, 'w+', encoding='utf-8') -elif args.socket: - try: - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sock.connect(args.socket) - sockfile = sock.makefile('w+') - sys.stdout = sockfile - except socket.error: - printError(SOCKET_ERROR) +if output == "file" : + if default_xml_filename : + sys.stdout = codecs.open(default_xml_filename, 'w+', encoding='utf-8') + else : + printError("epg2xml.json 파일의 default_xml_file항목이 없습니다."); + sys.exit() +elif output == "socket" : + if default_xml_socket : + try: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.connect(default_xml_socket) + sockfile = sock.makefile('w+') + sys.stdout = sockfile + except socket.error: + printError(SOCKET_ERROR) + sys.exit() + else : + printError("epg2xml.json 파일의 default_xml_socket항목이 없습니다."); sys.exit() getEpg() From 08209fa7a2296b837ce42eed40f501cd56fcd355 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Mon, 27 Mar 2017 18:06:18 +0900 Subject: [PATCH 10/51] add epg2xml.php --- epg2xml.php | 915 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 915 insertions(+) create mode 100644 epg2xml.php diff --git a/epg2xml.php b/epg2xml.php new file mode 100644 index 0000000..5da2c93 --- /dev/null +++ b/epg2xml.php @@ -0,0 +1,915 @@ +#!/usr/bin/env php +getMessage()); + exit; + } + endif; + } + catch(Exception $e) { + printError($e->getMessage()); + exit; + } + endif; + +if($output == "display") : + $fp = fopen('php://output', 'w+'); + if ($fp === False) : + printError(DISPLAY_ERROR); + exit; + else : + try { + getEpg(); + fclose($fp); + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; +elseif($output == "file") : + if($default_xml_file) : + $fp = fopen($default_xml_file, 'w+'); + if ($fp === False) : + printError(FIEL_ERROR); + exit; + else : + try { + getEpg(); + fclose($fp); + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + else : + printError("epg2xml.json 파일의 default_xml_file항목이 없습니다."); + exit; + endif; +elseif($output == "socket") : + if($default_xml_socket) : + $default_xml_socket = "unix://".$default_xml_socket; + $fp = @fsockopen($default_xml_socket, -1, $errno, $errstr, 30); + if ($fp === False) : + printError(SOCKET_ERROR); + exit; + else : + try { + getEpg(); + fclose($fp); + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + else : + printError("epg2xml.json 파일의 default_xml_socket항목이 없습니다."); + exit; + endif; +endif; + +function getEPG() { + $fp = $GLOBALS['fp']; + $MyISP = $GLOBALS['MyISP']; + $Channelfile = __DIR__."/Channel.json"; + try { + $f = @file_get_contents($Channelfile); + if($f === False) : + printError("Channel.json.".JSON_FILE_ERROR); + exit; + else : + try { + $Channeldatas = json_decode($f, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception("Channel.".JSON_SYNTAX_ERROR); + } + catch(Exception $e) { + printError($e->getMessage()); + exit; + } + endif; + } + catch(Exception $e) { + printError($e->getMessage()); + exit; + } + fprintf($fp, "\n"); + fprintf($fp, "\n\n"); + fprintf($fp, "\n", VERSION); + foreach ($Channeldatas as $Channeldata) : #Get Channel & Print Channel info + if($Channeldata['Enabled'] == 1) : + $ChannelId = $Channeldata['Id']; + $ChannelName = htmlspecialchars($Channeldata['Name'], ENT_XML1); + $ChannelSource = $Channeldata['Source']; + $ChannelServiceId = $Channeldata['ServiceId']; + $Channelnumber = $Channeldata[$MyISP.'Ch']; + $ChannelISPName = htmlspecialchars($Channeldata[$MyISP." Name"], ENT_XML1); + $ChannelIconUrl = htmlspecialchars($Channeldata['Icon_url'], ENT_XML1); + if($Channeldata[$MyISP.'Ch'] != Null): + $ChannelInfos[] = array($ChannelId, $ChannelName, $ChannelSource, $ChannelServiceId); + fprintf($fp, " \n", $ChannelId); + fprintf($fp, " %s\n", $ChannelName); + fprintf($fp, " %s\n", $ChannelISPName); + fprintf($fp, " %s\n", $Channelnumber); + fprintf($fp, " %s\n", $Channelnumber." ".$ChannelISPName); + if($IconUrl) : + fprintf($fp, " \n", $IconUrl, $ChannelId); + else : + fprintf($fp, " \n", $ChannelIconUrl); + endif; + fprintf($fp, " \n"); + endif; + endif; + endforeach; + + # Print Program Information + foreach ($ChannelInfos as $ChannelInfo) : + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ChannelSource = $ChannelInfo[2]; + $ChannelServiceId = $ChannelInfo[3]; + if($GLOBALS['debug']) printLog($ChannelName.' 채널 EPG 데이터를 가져오고 있습니다'); + if($ChannelSource == 'EPG') : + GetEPGFromEPG($ChannelInfo); + elseif($ChannelSource == 'KT') : + GetEPGFromKT($ChannelInfo); + elseif($ChannelSource == 'LG') : + GetEPGFromLG($ChannelInfo); + elseif($ChannelSource == 'SK') : + GetEPGFromSK($ChannelInfo); + elseif($ChannelSource == 'SKY') : + GetEPGFromSKY($ChannelInfo); + elseif($ChannelSource == 'NAVER') : + GetEPGFromNaver($ChannelInfo); + endif; + endforeach; + fprintf($fp, "\n"); +} + +function GetEPGFromEPG($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $epginfo = array(); + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi"; + $day = date("Ymd", strtotime("+".($k - 1)." days")); + $params = array( + 'beforegroup' => '100', + 'checkchannel' => $ServiceId, + 'select_group' => '100', + 'start_date' => $day + ); + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + $response = str_replace("charset=euc-kr", "charset=utf-8", $response); + $dom = new DomDocument; + libxml_use_internal_errors(true); + $dom->loadHTML(mb_convert_encoding($response, "UTF-8", "EUC-KR")); + $xpath = new DomXPath($dom); + for($i = 2; $i < 5; $i++) : + $thisday = $day; + $query = "//table[contains(@style,'margin-bottom:30')][".$i."]//td[contains(@colspan,'2')]/following::td[1]/table[1]//td[2]"; + $programs = $xpath->query($query); + foreach($programs as $program) : + $hour = $xpath->query("parent::*/parent::*/parent::*/parent::*/td[1]", $program)->item(0); + $hour = str_replace("시", "", trim($hour->nodeValue)); + $minute = $xpath->query("preceding-sibling::td[1]", $program)->item(0); + $hour = $hour.":".str_replace(array("[", "]"), array("",""), trim($minute->nodeValue)); + switch ($i) : + case 2 : + $hour = $hour." AM"; + break; + case 3 : + $hour = $hour." PM"; + break; + case 4 : + if($hour > 5 ) : + $hour = $hour." PM"; + else : + $hour = $hour." AM"; + $thisday = date("Ymd", strtotime("+1 days")); + endif; + break; + endswitch; + $startTime = date("YmdHis", strtotime($thisday." ".$hour)); + preg_match('/?(.*)?(.*?)\s*(<(.*)>)?\s*(\(재\))?\s*(\(([\d,]+)회\))?()?\s*<\/td>/', trim($dom->saveHTML($program)), $matches); + if ($matches != NULL) : + $image = $matches[8] ? $matches[8] : ""; + preg_match('/.*schedule_([\d,]+)?.*/', $image, $grade); + if($grade != NULL) : + $rating = $grade[1]; + else : + $rating = 0; + endif; + endif; + #programName, startTime, rating, subprogramName, rebroadcast, episode + $epginfo[] = array(trim($matches[2]), $startTime, $rating, trim($matches[4]), $matches[5], $matches[7]); + endforeach; + endfor; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + $programName = $epg[0][0] ?: ""; + $subprogramName = $epg[0][3] ?: ""; + $startTime = $epg[0][1] ?: ""; + $endTime = $epg[1][1] ?: ""; + $desc = ""; + $actors = ""; + $producers = ""; + $category = ""; + $rebroadcast = $epg[0][4] ? True : False; + $episode = $epg[0][5] ?: ""; + $rating = $epg[0][2] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endforeach; +} +function GetEPGFromKT($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $epginfo = array(); + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://tv.olleh.com/renewal_sub/liveTv/pop_schedule_week.asp"; + $day = date("Ymd", strtotime("+".($k - 1)." days")); + $params = array( + 'ch_name' => '', + 'ch_no' => $ServiceId, + 'nowdate'=> $day, + 'seldatie' => $day, + 'tab_no' => '1' + ); + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + $response = str_replace("charset=euc-kr", "charset=utf-8", $response); + $dom = new DomDocument; + libxml_use_internal_errors(true); + $dom->loadHTML(mb_convert_encoding($response, "UTF-8", "EUC-KR")); + $xpath = new DomXPath($dom); + $query = "//table[@id='pop_day']/tbody/tr"; + $rows = $xpath->query($query); + foreach($rows as $row) : + $cells = $row->getElementsByTagName('td'); + #programName, startTime, rating, category + $startTime = date("YmdHis", strtotime($day." ".trim($cells[0]->nodeValue))); + $rating = str_replace("all", 0, str_replace("세 이상", "", trim($cells[2]->nodeValue))); + $epginfo[]= array(trim($cells[1]->nodeValue), $startTime, $rating, trim($cells[4]->nodeValue)); + endforeach; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + $programName = $epg[0][0] ?: ""; + $subprogramName = ""; + $startTime = $epg[0][1] ?: ""; + $endTime = $epg[1][1] ?: ""; + $desc = ""; + $actors = ""; + $producers = ""; + $category = $epg[0][3] ?: ""; + $rebroadcast = False; + $episode = ""; + $rating = $epg[0][2] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endforeach; +} +function GetEPGFromLG($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $epginfo = array(); + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://www.uplus.co.kr/css/chgi/chgi/RetrieveTvSchedule.hpi"; + $day = date("Ymd", strtotime("+".($k - 1)." days")); + $params = array( + 'chnlCd' => $ServiceId, + 'evntCmpYmd' => $day + ); + $params = http_build_query($params); + $url = $url."?".$params; + + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + $response = ''.$response; + $dom = new DomDocument; + libxml_use_internal_errors(true); + $response = mb_convert_encoding($response, "UTF-8", "EUC-KR"); + $response = str_replace(array('<재>', ' [..', ' (..'), array('<재>', '', ''), $response); + $dom->loadHTML($response); + $xpath = new DomXPath($dom); + $query = "//table[@class='datatable06 datatable06_type01']/tbody/tr"; + $rows = $xpath->query($query); + foreach($rows as $row) : + $cells = $row->getElementsByTagName('td'); + $startTime = date("YmdHis", strtotime($day." ".trim($cells[0]->nodeValue))); + $images = $cells[1]->getElementsByTagName('img'); + $rating = 0; + foreach($images as $image) : + if(preg_match('/(\d+)세이상 관람가/', $image->attributes->getNamedItem('alt')->nodeValue, $ratings)) $rating = $ratings[1]; + endforeach; + #programName, startTime, rating, category + $epginfo[]= array(trim($cells[1]->nodeValue), $startTime, $rating, trim($cells[2]->nodeValue)); + endforeach; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + preg_match('/(<재>?)?(.*?)(\[(.*)\])?\s?(\(([\d,]+)회\))?$/', $epg[0][0], $matches); + $programName = trim($matches[2]) ?: ""; + $subprogramName = trim($matches[4]) ?: ""; + $startTime = $epg[0][1] ?: ""; + $endTime = $epg[1][1] ?: ""; + $desc = ""; + $actors = ""; + $producers = ""; + $category = $epg[0][3] ?: ""; + $rebroadcast = trim($matches[1]) ? True: False; + $episode = trim($matches[6]) ?: ""; + $rating = $epg[0][2] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endforeach; +} +function GetEPGFromSK($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $today = date("Ymd"); + $lastday = date("Ymd", strtotime("+".($GLOBALS['period'] - 1)." days")); + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + $url = "http://m.btvplus.co.kr/Common/Inc/IFGetData.asp"; + $params = array( + 'variable' => 'IF_LIVECHART_DETAIL', + 'pcode' => '|^|start_time='.$today.'00|^|end_time='.$lastday.'24|^|svc_id='.$ServiceId + ); + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + try { + $data = json_decode($response, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); + if($data['channel'] == NULL) : + if($GLOBALS['debug']) : + printError($ChannelName.CHANNEL_ERROR); + endif; + else : + $programs = $data['channel']['programs']; + foreach ($programs as $program) : + $programName = ""; + $subprogramName = ""; + $episode = ""; + $rebroadcast = False; + preg_match('/^(.*?)(?:\s*[\(<]([\d,회]+)[\)>])?(?:\s*<([^<]*?)>)?(\((재)\))?$/', str_replace('...', '>', $program['programName']), $matches); + if ($matches != NULL) : + $programName = trim($matches[1]) ?: ""; + $subprogramName = trim($matches[3]) ?: ""; + $episode = str_replace("회", "", $matches[2]) ?: ""; + $rebroadcast = $matches[5] ? True : False; + endif; + $startTime = date("YmdHis",$program['startTime']/1000); + $endTime = date("YmdHis",$program['endTime']/1000); + if ($GLOBALS['addverbose'] == "y") : + $desc = $program['synopsis'] ?: ""; + $actors =trim(str_replace('...','',$program['actorName']), ', ') ?: ""; + $producers = trim(str_replace('...','',$program['directorName']), ', ') ?: ""; + else : + $desc = ""; + $actors = ""; + $producers = ""; + endif; + if ($program['mainGenreName'] != NULL) : + $category = $program['mainGenreName']; + else: + $category = ""; + endif; + $rating = $program['ratingCd'] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } +} + +function GetEPGFromSKY($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://www.skylife.co.kr/channel/epg/channelScheduleList.do"; + $day = date("Y-m-d", strtotime("+".($k - 1)." days")); + $params = array( + 'area' => 'in', + 'inFd_channel_id' => $ServiceId, + 'inairdate' => $day, + 'indate_type' => 'now' + ); + $params = http_build_query($params); + $url = $url."?".$params; + + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + try { + $data = json_decode($response, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); + if(count($data['scheduleListIn']) == 0) : + if($GLOBALS['debug']) : + printError($ChannelName.CHANNEL_ERROR); + endif; + else : + $programs = $data['scheduleListIn']; + foreach($programs as $program) : + $programName = str_replace(array('<', '>', '&'), array('<', '>', '&'),$program['program_name']) ?: ""; + $subprogramName = str_replace(array('<', '>', '&'), array('<', '>', '&'),$program['program_subname']) ?: ""; + $startTime = $program['starttime']; + $endTime = $program['endtime']; + if ($GLOBALS['addverbose'] == "y") : + $actors = trim(str_replace('...', '',$program['cast']), ', ') ?: ""; + $producers = trim(str_replace('...', '',$program['dirt']), ', ') ?: ""; + $description = str_replace(array('<', '>', '&'), array('<', '>', '&'),$program['description']) ?: ""; + $summary = str_replace(array('<', '>', '&'), array('<', '>', '&'),$program['summary']) ?: ""; + $desc = $description ?: ""; + if($summary) : + $desc = $desc."\n".$summary; + endif; + else: + $desc = ""; + $actors = ""; + $producers = ""; + endif; + $category = $program['program_category1']; + $episode = $program['episode_id'] ?: ""; + $rebroadcast = $program['rebroad']== "Y" ? True : False; + $rating = $program['grade'] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endforeach; +} +function GetEPGFromNaver($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "https://search.naver.com/p/csearch/content/batchrender_ssl.nhn"; + $day = date("Ymd", strtotime("+".($k - 1)." days")); + $totaldate[] = $day; + endforeach; + $params = array( + '_callback' => 'epg', + 'fileKey' => 'single_schedule_channel_day', + 'pkid' => '66', + 'u1' => 'single_schedule_channel_day', + 'u2' => join(",", $totaldate), + 'u3' => $day, + 'u4' => $GLOBALS['period'], + 'u5' => $ServiceId, + 'u6' => 1, + 'u7' => $ChannelName."편성표", + 'u8' => $ChannelName."편성표", + 'where' => 'nexearch' + ); + + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + try { + $response = str_replace('epg( ', '', $response ); + $response = substr($response, 0, strlen($response)-2); + $response = preg_replace("/\/\*.*?\*\//","",$response); + $data = json_decode($response, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); + if($data['displayDates'][0]['count'] == 0) : + if($GLOBALS['debug']) : + printError($ChannelName.CHANNEL_ERROR); + endif; + else : + for($i = 0; $i < count($data['displayDates']); $i++) : + for($j = 0; $j < 24; $j++) : + foreach($data['schedules'][$j][$i] as $program) : + #programName, startTime, episode, rebroadcast, rating + $startTime = date("YmdHis", strtotime($data['displayDates'][$i]['date']." ".$program['startTime'])); + $epginfo[] = array($program['title'], $startTime, str_replace("회","", $program['episode']), $program['isRerun'], $program['grade']); + endforeach; + endfor; + endfor; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + $programName = $epg[0][0] ?: ""; + $subprogramName = ""; + $startTime = $epg[0][1] ?: ""; + $endTime = $epg[1][1] ?: ""; + $desc = ""; + $actors = ""; + $producers = ""; + $category = ""; + $rebroadcast = $epg[0][3] ? True: False; + $episode = $epg[0][2] ?: ""; + $rating = $epg[0][4] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } +} +function writeProgram($programdata) { + $fp = $GLOBALS['fp']; + $ChannelId = $programdata['channelId']; + $startTime = $programdata['startTime']; + $endTime = $programdata['endTime']; + $programName = htmlspecialchars($programdata['programName'], ENT_XML1); + $subprogramName = htmlspecialchars($programdata['subprogramName'], ENT_XML1); + $actors = htmlspecialchars($programdata['actors'], ENT_XML1); + $producers = htmlspecialchars($programdata['producers'], ENT_XML1); + $category = htmlspecialchars($programdata['category'], ENT_XML1); + $episode = $programdata['episode']; + $rebroadcast = $programdata['rebroadcast']; + if($episode && $GLOBALS['addepisode'] == 'y') $programName = $programName." (".$episode."회)"; + if($rebroadcast == True && $GLOBALS['addrebroadcast'] == 'y') $programName = $programName." (재)"; + if($programdata['rating'] == 0) : + $rating = "전체 관람가"; + else : + $rating = sprintf("%s세 이상 관람가", $programdata['rating']); + endif; + if($GLOBALS['addverbose'] == 'y') : + $desc = $programdata['programName']; + if($subprogramName) $desc = $desc."\n부제 : ".$subprogramName; + if($episode) $desc = $desc."\n회차 : (".$episode."회)"; + if($category) $desc = $desc."\n장르 : ".$category; + if($actors) $desc = $desc."\n출연 : ".$actors; + if($producers) $desc = $desc."\n제작 : ".$producers; + $desc = $desc."\n등급 : ".$rating; + else: + $desc = ""; + endif; + if($programdata['desc']) $desc = $desc."\n".$programdata['desc']; + $desc = htmlspecialchars($desc, ENT_XML1); + $contentTypeDict = array( + '교양' => 'Arts / Culture (without music)', + '만화' => 'Cartoons / Puppets', + '교육' => 'Education / Science / Factual topics', + '취미' => 'Leisure hobbies', + '드라마' => 'Movie / Drama', + '영화' => 'Movie / Drama', + '음악' => 'Music / Ballet / Dance', + '뉴스' => 'News / Current affairs', + '다큐' => 'Documentary', + '라이프' => 'Documentary', + '시사/다큐' => 'Documentary', + '연예' => 'Show / Game show', + '스포츠' => 'Sports', + '홈쇼핑' => 'Advertisement / Shopping' + ); + $contentType = ""; + foreach($contentTypeDict as $key => $value) : + if(!(strpos($category, $key) === False)) : + $contentType = $value; + endif; + endforeach; + fprintf($fp, " \n", $startTime, $endTime, $ChannelId); + fprintf($fp, " %s\n", $programName); + if($subprogramName) : + fprintf($fp, " %s\n", $subprogramName); + endif; + if($GLOBALS['addverbose']=='y') : + fprintf($fp, " %s\n", $desc); + if($actors || $producers): + fprintf($fp, " \n"); + if($actors) : + foreach(split(',', $actors) as $actor): + if($actor) fprintf($fp, " %s\n", $actor); + endforeach; + endif; + if($producers) : + foreach(split(',', $producers) as $producer): + if($producer) fprintf($fp, " %s\n", $producer); + endforeach; + endif; + fprintf($fp, " \n"); + endif; + endif; + if($category) fprintf($fp, " %s\n", $category); + if($contentType) fprintf($fp, " %s\n", $contentType); + if($episode) fprintf($fp, " %s\n", $episode); + if($rebroadcast) fprintf($fp, " \n"); + if($rating) : + fprintf($fp, " \n"); + fprintf($fp, " %s\n", $rating); + fprintf($fp, " \n"); + endif; + fprintf($fp, " \n"); +} +function printLog($args) { + fwrite(STDERR, $args."\n"); +} +function printError($args) { + fwrite(STDERR, "Error : ".$args."\n"); +} +?> From 6fa5185469b3a40dadc8df71db6468c6bd962840 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Mon, 27 Mar 2017 18:06:35 +0900 Subject: [PATCH 11/51] Update readme.txt --- readme.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index 9cfe3a0..840ce6b 100644 --- a/readme.txt +++ b/readme.txt @@ -5,14 +5,14 @@ 4. 저작권 1. 버전 - 1.1.3 + 1.1.4 2. 소개 이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5에서 사용 가능하도록 제작되었다. 기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. 3. 변경사항 - - 제목에 회차정보, 재방송 정보 추가시 오류 수정 - + - PHP 버전 추가 + - 버그 수정 4. 저작권 - BSD From cbb74b1c65a4c7b82eb7b8abe40ed3b5a4f2ca8f Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 30 Mar 2017 10:36:55 +0900 Subject: [PATCH 12/51] Update README.md --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 08102f2..17df837 100644 --- a/README.md +++ b/README.md @@ -63,11 +63,20 @@ tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을
## 옵션 소개 - 실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다 +epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
 -h --help : 도움말 출력
 --version : 버전을 보여준다.
+-i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
+-d --display : EPG 정보를 화면으로 보여준다.
+-o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
+-s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
+-l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2
+--icon : 채널 icon 위치 URL ex) --icon http://www.example.com
+--rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y
+--episode : 제목에 회차정보 표기 ex) --episode y
+--verbose : EPG 정보 상세하게 표기 ex) --verbose y
 
## 라이센스 From c5cc215f291b28fd2d6e96f46b3b0cddad4467ef Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 30 Mar 2017 10:38:31 +0900 Subject: [PATCH 13/51] Update readme.txt --- readme.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.txt b/readme.txt index 840ce6b..3515f7d 100644 --- a/readme.txt +++ b/readme.txt @@ -5,14 +5,14 @@ 4. 저작권 1. 버전 - 1.1.4 - + 1.1.5 + 2. 소개 이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5에서 사용 가능하도록 제작되었다. 기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. 3. 변경사항 - - PHP 버전 추가 - - 버그 수정 + - inline   + 4. 저작권 - BSD From 22fe20615f8ddd3012a423211b3abaacc67c9f84 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 30 Mar 2017 10:39:40 +0900 Subject: [PATCH 14/51] Update readme.txt --- readme.txt | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/readme.txt b/readme.txt index 3515f7d..4e202bf 100644 --- a/readme.txt +++ b/readme.txt @@ -1,18 +1,12 @@ -목차 -1. 버전 -2. 소개 -3. 변경사항 -4. 저작권 - 1. 버전 1.1.5 - + 2. 소개 - 이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5에서 사용 가능하도록 제작되었다. + 이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다. 기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. 3. 변경사항 - - inline   - + - inline 변수 재추가 + 4. 저작권 - BSD From d09d1da359f887fab07f0344675431addec1078d Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 30 Mar 2017 10:40:20 +0900 Subject: [PATCH 15/51] Update epg2xml.php --- epg2xml.php | 105 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 22 deletions(-) diff --git a/epg2xml.php b/epg2xml.php index 5da2c93..6aab418 100644 --- a/epg2xml.php +++ b/epg2xml.php @@ -1,7 +1,7 @@ #!/usr/bin/env php getMessage()); From a1b1000360ec5fde81342642ccb0d1c93e107984 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Thu, 30 Mar 2017 10:40:50 +0900 Subject: [PATCH 16/51] Update epg2xml.py --- epg2xml.py | 71 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/epg2xml.py b/epg2xml.py index 1bcc10b..b7a5158 100644 --- a/epg2xml.py +++ b/epg2xml.py @@ -17,17 +17,7 @@ import pprint reload(sys) sys.setdefaultencoding('utf-8') -__version__ = '1.1.4' - -# Set My Configuration -#default_icon_url = '' # TV channel icon url (ex : http://www.example.com/Channels) -#default_rebroadcast = 'y' # 제목에 재방송 정보 출력 -#default_episode = 'n' # 제목에 회차정보 출력 -#default_verbose = 'n' # 자세한 epg 데이터 출력 -#default_fetch_limit = 2 # epg 데이터 가져오는 기간 -#default_xml_filename = 'xmltv.xml' # epg 저장시 기본 저장 이름 (ex: /home/tvheadend/xmltv.xml) -#default_xml_socket = 'xmltv.sock' # External XMLTV 사용시 기본 소켓 이름 (ex: /home/tvheadend/xmltv.sock) -# Set My Configuration +__version__ = '1.1.5' # Set variable debug = False @@ -489,10 +479,9 @@ def printLog(*args): def printError(*args): print("Error : ", *args, file=sys.stderr) -parser = argparse.ArgumentParser(description = 'EPG 정보 출력 프로그램') -parser.add_argument('-v', '--version', action = 'version', version = '%(prog)s version : ' + __version__) -parser.parse_args() - +#parser = argparse.ArgumentParser(description = 'EPG 정보 출력 프로그램') +#parser.add_argument('-v', '--version', action = 'version', version = '%(prog)s version : ' + __version__) +#parser.parse_args() Settingfile = os.path.dirname(os.path.abspath(__file__)) + '/epg2xml.json' ChannelInfos = [] @@ -501,13 +490,14 @@ try: Settings = json.load(f) MyISP = Settings['MyISP'] if 'MyISP' in Settings else '' default_output = Settings['output'] if 'output' in Settings else '' + default_xml_file = Settings['default_xml_file'] if 'default_xml_file' in Settings else 'xmltv.xml' + default_xml_socket = Settings['default_xml_socket'] if 'default_xml_socket' in Settings else 'xmltv.sock' default_icon_url = Settings['default_icon_url'] if 'default_icon_url' in Settings else None + default_fetch_limit = Settings['default_fetch_limit'] if 'default_fetch_limit' in Settings else '' default_rebroadcast = Settings['default_rebroadcast'] if 'default_rebroadcast' in Settings else '' default_episode = Settings['default_episode'] if 'default_episode' in Settings else '' default_verbose = Settings['default_verbose'] if 'default_verbose' in Settings else '' - default_fetch_limit = Settings['default_fetch_limit'] if 'default_fetch_limit' in Settings else '' - default_xml_filename = Settings['default_xml_filename'] if 'default_xml_filename' in Settings else '' - default_xml_socket = Settings['default_xml_socket'] if 'default_xml_socket' in Settings else '' + except EnvironmentError: printError("epg2xml." + JSON_FILE_ERROR) sys.exit() @@ -515,6 +505,38 @@ except ValueError: printError("epg2xml." + JSON_SYNTAX_ERROR) sys.exit() + +parser = argparse.ArgumentParser(description = 'EPG 정보를 출력하는 방법을 선택한다') +argu1 = parser.add_argument_group(description = 'IPTV 선택') +argu1.add_argument('-i', dest = 'MyISP', choices = ['KT', 'LG', 'SK'], help = '사용하는 IPTV : KT, LG, SK', default = MyISP) +argu2 = parser.add_mutually_exclusive_group() +argu2.add_argument('-v', '--version', action = 'version', version = '%(prog)s version : ' + __version__) +argu2.add_argument('-d', '--display', action = 'store_true', help = 'EPG 정보 화면출력') +argu2.add_argument('-o', '--outfile', metavar = default_xml_file, nargs = '?', const = default_xml_file, help = 'EPG 정보 저장') +argu2.add_argument('-s', '--socket', metavar = default_xml_socket, nargs = '?', const = default_xml_socket, help = 'xmltv.sock(External: XMLTV)로 EPG정보 전송') +argu3 = parser.add_argument_group('추가옵션') +argu3.add_argument('--icon', dest = 'icon', metavar = "http://www.example.com/icon", help = '채널 아이콘 URL, 기본값: '+ default_icon_url, default = default_icon_url) +argu3.add_argument('-l', '--limit', dest = 'limit', type=int, metavar = "1-7", choices = range(1,8), help = 'EPG 정보를 가져올 기간, 기본값: '+ str(default_fetch_limit), default = default_fetch_limit) +argu3.add_argument('--rebroadcast', dest = 'rebroadcast', metavar = 'y, n', choices = 'yn', help = '제목에 재방송 정보 출력', default = default_rebroadcast) +argu3.add_argument('--episode', dest = 'episode', metavar = 'y, n', choices = 'yn', help = '제목에 회차 정보 출력', default = default_episode) +argu3.add_argument('--verbose', dest = 'verbose', metavar = 'y, n', choices = 'yn', help = 'EPG 정보 추가 출력', default = default_verbose) + +args = parser.parse_args() +if args.MyISP : MyISP = args.MyISP +if args.display : + default_output = "d" +elif args.outfile : + default_output = "o" + default_xml_file = args.outfile +elif args.socket : + default_output = "s" + default_xml_socket = args.socket +if args.icon : default_icon_url = args.icon +if args.limit : default_fetch_limit = args.limit +if args.rebroadcast : default_rebroadcast = args.rebroadcast +if args.episode : default_episode = args.episode +if args.verbose : default_verbose = args.verbose + if MyISP: if not any(MyISP in s for s in ['KT', 'LG', 'SK']): printError("MyISP는 KT, LG, SK만 가능합니다.") @@ -538,11 +560,7 @@ else : printError("epg2xml.json 파일의 output항목이 없습니다."); sys.exit() -if default_icon_url : - printError("epg2xml.json 파일의 default_icon_url항목이 없습니다."); - sys.exit() -else : - IconUrl = default_icon_url +IconUrl = default_icon_url if default_rebroadcast : if not any(default_rebroadcast in s for s in ['y', 'n']): @@ -575,7 +593,7 @@ else : sys.exit() if default_fetch_limit : - if not any(default_fetch_limit in s for s in ['1', '2', '3', '4', '5', '6', '7']): + if not any(str(default_fetch_limit) in s for s in ['1', '2', '3', '4', '5', '6', '7']): printError("default_fetch_limit 는 1, 2, 3, 4, 5, 6, 7만 가능합니다.") sys.exit() else : @@ -585,8 +603,8 @@ else : sys.exit() if output == "file" : - if default_xml_filename : - sys.stdout = codecs.open(default_xml_filename, 'w+', encoding='utf-8') + if default_xml_file : + sys.stdout = codecs.open(default_xml_file, 'w+', encoding='utf-8') else : printError("epg2xml.json 파일의 default_xml_file항목이 없습니다."); sys.exit() @@ -603,5 +621,4 @@ elif output == "socket" : else : printError("epg2xml.json 파일의 default_xml_socket항목이 없습니다."); sys.exit() - getEpg() From d45aecd1cfc59944e05a8e7a9aea6087fde039af Mon Sep 17 00:00:00 2001 From: wonipapa Date: Sat, 1 Apr 2017 11:05:38 +0900 Subject: [PATCH 17/51] Update epg2xml.json --- epg2xml.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/epg2xml.json b/epg2xml.json index ce02869..d52619f 100644 --- a/epg2xml.json +++ b/epg2xml.json @@ -19,7 +19,7 @@ "###_COMMENT_###" : "### epg 데이터 가져오는 기간으로 1에서 7까지 설정가능 ###", "default_fetch_limit" : "2", "###_COMMENT_###" : "### epg 저장시 기본 저장 이름 (ex: /home/tvheadend/xmltv.xml) ###", - "default_xml_filename" : "xmltv.xml", + "default_xml_file" : "xmltv.xml", "###_COMMENT_###" : "### # External XMLTV 사용시 기본 소켓 이름 (ex: /home/tvheadend/xmltv.sock) ###", "default_xml_socket" : "xmltv.sock", "###_COMMENT_###" : "" From 21260d0977c3c4b368de33fd60f9086a489438a4 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Tue, 11 Apr 2017 14:24:57 +0900 Subject: [PATCH 18/51] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 17df837..72815f4 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,8 @@ tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 /home/hts/epg2xml.php -### XMLTV 사용시 + +### XMLTV SOCKET 사용시 (xmltv.sock 사용시 socat 등을 사용할 필요는 없다) #### PYTHON의 경우
 /usr/bin/python /home/hts/epg2xml.py 또는

From 78112445444ef95f0c71e4680d0c6e9180301ace Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Tue, 11 Apr 2017 14:25:55 +0900
Subject: [PATCH 19/51] Update README.md

---
 README.md | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/README.md b/README.md
index 72815f4..7a6d2e0 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,48 @@ Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보
 epg2xml
 tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을
 
+#### PYTHON의 경우
+
+/usr/bin/python /home/hts/epg2xml.py 또는
+/home/hts/epg2xml.py# EPG2XML
+
+이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다.
+기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다.
+
+## 필요 모듈
+
+### EPG2XML.PY
+BeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다.
+설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다.
+synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다.
+
+### EPG2XML.php
+PHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. 
+
+## 설정방법
+epg2xml.json 안의 항목이 설정 가능한 항목이다. 
+
+MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)
+default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
+default_rebroadcast : 제목에 재방송 정보 출력
+default_episode : 제목에 회차정보 출력
+default_verbose : EPG 정보 상세 출력
+default_fetch_limit : EPG 데이터 가져오는 기간이다.
+default_xml_filename : EPG 저장시 기본 저장 이름으로 tvheadend 서버가 쓰기가 가능한 경로로 설정해야 한다.
+default_xml_socket   : External XMLTV 사용시 xmltv.sock가 있는 경로로 설정해준다.
+
+ +Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보가 들어 있다. +이중 Enabled:1로 되어 있는 부분을 Enabled:0으로 바꾸면 EPG정보를 가져오지 않는다. +필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다. +삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다. + +## 사용방법 + +### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea) +epg2xml +tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 + #### PYTHON의 경우
 /usr/bin/python /home/hts/epg2xml.py 또는
@@ -50,6 +92,48 @@ tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을
 
+### XMLTV SOCKET 사용시 (xmltv.sock 사용시 socat 등을 사용할 필요는 없다) +#### PYTHON의 경우 +
+/usr/bin/python /home/hts/epg2xml.py 또는
+/home/hts/epg2xml.py
+
+ +#### PHP의 경우 +
+/usr/bin/php /home/hts/epg2xml.php 또는
+/home/hts/epg2xml.php
+
+ +## 옵션 소개 +실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다 +epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다. +
+-h --help : 도움말 출력
+--version : 버전을 보여준다.
+-i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
+-d --display : EPG 정보를 화면으로 보여준다.
+-o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
+-s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
+-l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2
+--icon : 채널 icon 위치 URL ex) --icon http://www.example.com
+--rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y
+--episode : 제목에 회차정보 표기 ex) --episode y
+--verbose : EPG 정보 상세하게 표기 ex) --verbose y
+
+ +## 라이센스 +BSD + +
+ +#### PHP의 경우 +
+/usr/bin/php /home/hts/epg2xml.php 또는
+/home/hts/epg2xml.php
+
+ + ### XMLTV SOCKET 사용시 (xmltv.sock 사용시 socat 등을 사용할 필요는 없다) #### PYTHON의 경우

From 64cc889b15d009a21195f685b1f266d00fe2f791 Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Tue, 11 Apr 2017 14:27:24 +0900
Subject: [PATCH 20/51] Update README.md

---
 README.md | 177 ++++--------------------------------------------------
 1 file changed, 13 insertions(+), 164 deletions(-)

diff --git a/README.md b/README.md
index 7a6d2e0..513218c 100644
--- a/README.md
+++ b/README.md
@@ -1,168 +1,17 @@
 # EPG2XML
-
-이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다.
-기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다.
-
+이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다.기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다.
 ## 필요 모듈
-
-### EPG2XML.PY
-BeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다.
-설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다.
-synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다.
-
-### EPG2XML.php
-PHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. 
-
-## 설정방법
-epg2xml.json 안의 항목이 설정 가능한 항목이다. 
-
-MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)
-default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
-default_rebroadcast : 제목에 재방송 정보 출력
-default_episode : 제목에 회차정보 출력
-default_verbose : EPG 정보 상세 출력
-default_fetch_limit : EPG 데이터 가져오는 기간이다.
-default_xml_filename : EPG 저장시 기본 저장 이름으로 tvheadend 서버가 쓰기가 가능한 경로로 설정해야 한다.
-default_xml_socket   : External XMLTV 사용시 xmltv.sock가 있는 경로로 설정해준다.
-
- -Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보가 들어 있다. -이중 Enabled:1로 되어 있는 부분을 Enabled:0으로 바꾸면 EPG정보를 가져오지 않는다. -필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다. -삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다. - +### EPG2XML.PYBeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다.설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다.synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다. +### EPG2XML.phpPHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. +## 설정방법epg2xml.json 안의 항목이 설정 가능한 항목이다.
MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.default_rebroadcast : 제목에 재방송 정보 출력default_episode : 제목에 회차정보 출력default_verbose : EPG 정보 상세 출력default_fetch_limit : EPG 데이터 가져오는 기간이다.default_xml_filename : EPG 저장시 기본 저장 이름으로 tvheadend 서버가 쓰기가 가능한 경로로 설정해야 한다.default_xml_socket   : External XMLTV 사용시 xmltv.sock가 있는 경로로 설정해준다.
+Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보가 들어 있다.이중 Enabled:1로 되어 있는 부분을 Enabled:0으로 바꾸면 EPG정보를 가져오지 않는다.필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다.삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다. ## 사용방법 +### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea)epg2xml tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 아래와 같이 변경해준다. +#### PYTHON의 경우
/usr/bin/python /home/hts/epg2xml.py 또는/home/hts/epg2xml.py
+#### PHP의 경우
/usr/bin/php /home/hts/epg2xml.php 또는/home/hts/epg2xml.php
-### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea) -epg2xml -tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 - -#### PYTHON의 경우 -
-/usr/bin/python /home/hts/epg2xml.py 또는
-/home/hts/epg2xml.py# EPG2XML
-
-이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다.
-기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다.
-
-## 필요 모듈
-
-### EPG2XML.PY
-BeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다.
-설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다.
-synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다.
-
-### EPG2XML.php
-PHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. 
-
-## 설정방법
-epg2xml.json 안의 항목이 설정 가능한 항목이다. 
-
-MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)
-default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
-default_rebroadcast : 제목에 재방송 정보 출력
-default_episode : 제목에 회차정보 출력
-default_verbose : EPG 정보 상세 출력
-default_fetch_limit : EPG 데이터 가져오는 기간이다.
-default_xml_filename : EPG 저장시 기본 저장 이름으로 tvheadend 서버가 쓰기가 가능한 경로로 설정해야 한다.
-default_xml_socket   : External XMLTV 사용시 xmltv.sock가 있는 경로로 설정해준다.
-
- -Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보가 들어 있다. -이중 Enabled:1로 되어 있는 부분을 Enabled:0으로 바꾸면 EPG정보를 가져오지 않는다. -필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다. -삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다. - -## 사용방법 - -### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea) -epg2xml -tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 - -#### PYTHON의 경우 -
-/usr/bin/python /home/hts/epg2xml.py 또는
-/home/hts/epg2xml.py
-
- -#### PHP의 경우 -
-/usr/bin/php /home/hts/epg2xml.php 또는
-/home/hts/epg2xml.php
-
- - -### XMLTV SOCKET 사용시 (xmltv.sock 사용시 socat 등을 사용할 필요는 없다) -#### PYTHON의 경우 -
-/usr/bin/python /home/hts/epg2xml.py 또는
-/home/hts/epg2xml.py
-
- -#### PHP의 경우 -
-/usr/bin/php /home/hts/epg2xml.php 또는
-/home/hts/epg2xml.php
-
- -## 옵션 소개 -실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다 -epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다. -
--h --help : 도움말 출력
---version : 버전을 보여준다.
--i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
--d --display : EPG 정보를 화면으로 보여준다.
--o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
--s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
--l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2
---icon : 채널 icon 위치 URL ex) --icon http://www.example.com
---rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y
---episode : 제목에 회차정보 표기 ex) --episode y
---verbose : EPG 정보 상세하게 표기 ex) --verbose y
-
- -## 라이센스 -BSD - -
- -#### PHP의 경우 -
-/usr/bin/php /home/hts/epg2xml.php 또는
-/home/hts/epg2xml.php
-
- - -### XMLTV SOCKET 사용시 (xmltv.sock 사용시 socat 등을 사용할 필요는 없다) -#### PYTHON의 경우 -
-/usr/bin/python /home/hts/epg2xml.py 또는
-/home/hts/epg2xml.py
-
- -#### PHP의 경우 -
-/usr/bin/php /home/hts/epg2xml.php 또는
-/home/hts/epg2xml.php
-
- -## 옵션 소개 -실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다 -epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다. -
--h --help : 도움말 출력
---version : 버전을 보여준다.
--i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
--d --display : EPG 정보를 화면으로 보여준다.
--o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
--s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
--l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2
---icon : 채널 icon 위치 URL ex) --icon http://www.example.com
---rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y
---episode : 제목에 회차정보 표기 ex) --episode y
---verbose : EPG 정보 상세하게 표기 ex) --verbose y
-
- -## 라이센스 -BSD +### XMLTV SOCKET 사용시xmltv.sock 사용시 socat 등을 사용하지 않고 바로 socket에 쓰기가 가능하다 +#### PYTHON의 경우
/usr/bin/python /home/hts/epg2xml.py 또는/home/hts/epg2xml.py
+#### PHP의 경우
/usr/bin/php /home/hts/epg2xml.php 또는/home/hts/epg2xml.php
+## 옵션 소개실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
-h --help : 도움말 출력--version : 버전을 보여준다.-i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT-d --display : EPG 정보를 화면으로 보여준다.-o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml-s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock-l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2--icon : 채널 icon 위치 URL ex) --icon http://www.example.com--rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y--episode : 제목에 회차정보 표기 ex) --episode y--verbose : EPG 정보 상세하게 표기 ex) --verbose y
+## 라이센스BSD From a548ad7683a26d22e28bce8602c75041d1eb7c29 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Tue, 11 Apr 2017 14:28:09 +0900 Subject: [PATCH 21/51] Update README.md --- README.md | 99 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 513218c..b754667 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,86 @@ # EPG2XML -이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다.기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. -## 필요 모듈 -### EPG2XML.PYBeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다.설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다.synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다. -### EPG2XML.phpPHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. -## 설정방법epg2xml.json 안의 항목이 설정 가능한 항목이다.
MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.default_rebroadcast : 제목에 재방송 정보 출력default_episode : 제목에 회차정보 출력default_verbose : EPG 정보 상세 출력default_fetch_limit : EPG 데이터 가져오는 기간이다.default_xml_filename : EPG 저장시 기본 저장 이름으로 tvheadend 서버가 쓰기가 가능한 경로로 설정해야 한다.default_xml_socket   : External XMLTV 사용시 xmltv.sock가 있는 경로로 설정해준다.
-Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보가 들어 있다.이중 Enabled:1로 되어 있는 부분을 Enabled:0으로 바꾸면 EPG정보를 가져오지 않는다.필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다.삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다. -## 사용방법 -### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea)epg2xml tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 아래와 같이 변경해준다. -#### PYTHON의 경우
/usr/bin/python /home/hts/epg2xml.py 또는/home/hts/epg2xml.py
-#### PHP의 경우
/usr/bin/php /home/hts/epg2xml.php 또는/home/hts/epg2xml.php
-### XMLTV SOCKET 사용시xmltv.sock 사용시 socat 등을 사용하지 않고 바로 socket에 쓰기가 가능하다 -#### PYTHON의 경우
/usr/bin/python /home/hts/epg2xml.py 또는/home/hts/epg2xml.py
-#### PHP의 경우
/usr/bin/php /home/hts/epg2xml.php 또는/home/hts/epg2xml.php
-## 옵션 소개실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
-h --help : 도움말 출력--version : 버전을 보여준다.-i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT-d --display : EPG 정보를 화면으로 보여준다.-o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml-s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock-l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2--icon : 채널 icon 위치 URL ex) --icon http://www.example.com--rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y--episode : 제목에 회차정보 표기 ex) --episode y--verbose : EPG 정보 상세하게 표기 ex) --verbose y
-## 라이센스BSD +이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다. +기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. + +## 필요 모듈 + +### EPG2XML.PY +BeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다. +설치 OS별로 모듈을 설치하기 위한 사전 설치 방법이 다를 수도 있으므로 검색해서 설치하도록 한다. +synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다. + +### EPG2XML.php +PHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. + +## 설정방법 +epg2xml.json 안의 항목이 설정 가능한 항목이다. +
+MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)
+default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
+default_rebroadcast : 제목에 재방송 정보 출력
+default_episode : 제목에 회차정보 출력
+default_verbose : EPG 정보 상세 출력
+default_fetch_limit : EPG 데이터 가져오는 기간이다.
+default_xml_filename : EPG 저장시 기본 저장 이름으로 tvheadend 서버가 쓰기가 가능한 경로로 설정해야 한다.
+default_xml_socket   : External XMLTV 사용시 xmltv.sock가 있는 경로로 설정해준다.
+
+ +Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보가 들어 있다. +이중 Enabled:1로 되어 있는 부분을 Enabled:0으로 바꾸면 EPG정보를 가져오지 않는다. +필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다. +삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다. + +## 사용방법 + +### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea) +epg2xml tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 아래와 같이 변경해준다. + +#### PYTHON의 경우 +
+/usr/bin/python /home/hts/epg2xml.py 또는
+/home/hts/epg2xml.py
+
+ +#### PHP의 경우 +
+/usr/bin/php /home/hts/epg2xml.php 또는
+/home/hts/epg2xml.php
+
+ + + +### XMLTV SOCKET 사용시 +xmltv.sock 사용시 socat 등을 사용하지 않고 바로 socket에 쓰기가 가능하다 + +#### PYTHON의 경우 +
+/usr/bin/python /home/hts/epg2xml.py 또는
+/home/hts/epg2xml.py
+
+ +#### PHP의 경우 +
+/usr/bin/php /home/hts/epg2xml.php 또는
+/home/hts/epg2xml.php
+
+ +## 옵션 소개 +실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다 +epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다. +
+-h --help : 도움말 출력
+--version : 버전을 보여준다.
+-i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
+-d --display : EPG 정보를 화면으로 보여준다.
+-o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
+-s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
+-l --limit : EPG 정보 가져올 기간으로 기본값은 2일이며 최대 7일까지 설정 가능하다. ex) -l 2
+--icon : 채널 icon 위치 URL ex) --icon http://www.example.com
+--rebroadcast : 제목에 재방송정보 표기 ex) --rebroadcast y
+--episode : 제목에 회차정보 표기 ex) --episode y
+--verbose : EPG 정보 상세하게 표기 ex) --verbose y
+
+ +## 라이센스 +BSD From 22b54ff4fddd96934e9891b90c6ffa126d40c27c Mon Sep 17 00:00:00 2001 From: wonipapa Date: Tue, 11 Apr 2017 14:29:57 +0900 Subject: [PATCH 22/51] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b754667..504555f 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ epg2xml tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 아래와 같이 ### XMLTV SOCKET 사용시 -xmltv.sock 사용시 socat 등을 사용하지 않고 바로 socket에 쓰기가 가능하다 +**xmltv.sock 사용시 socat 등을 사용하지 않고 바로 socket에 쓰기가 가능하다** #### PYTHON의 경우

From 6d002d0538826d4c651e9bb792ea93cf213ceb9e Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Thu, 13 Apr 2017 12:18:51 +0900
Subject: [PATCH 23/51] =?UTF-8?q?IPTV=20=EC=9E=85=EB=A0=A5=20ALL=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80,=20=EC=A4=91=EB=B3=B5=20=EB=8D=B0=EC=9D=B4?=
 =?UTF-8?q?=ED=84=B0=20=EC=B6=9C=EB=A0=A5=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 epg2xml.php | 241 +++++++++++++++++++++++++++-------------------------
 1 file changed, 123 insertions(+), 118 deletions(-)

diff --git a/epg2xml.php b/epg2xml.php
index 6aab418..1489860 100644
--- a/epg2xml.php
+++ b/epg2xml.php
@@ -1,7 +1,7 @@
 #!/usr/bin/env php
 \n");
     fprintf($fp, "\n\n");
-    fprintf($fp, "\n", VERSION);
+    fprintf($fp, "\n", VERSION);
+ 
     foreach ($Channeldatas as $Channeldata) : #Get Channel & Print Channel info
         if($Channeldata['Enabled'] == 1) :
             $ChannelId = $Channeldata['Id'];
             $ChannelName = htmlspecialchars($Channeldata['Name'], ENT_XML1);
             $ChannelSource = $Channeldata['Source'];
             $ChannelServiceId = $Channeldata['ServiceId'];
-            $Channelnumber = $Channeldata[$MyISP.'Ch'];
-            $ChannelISPName = htmlspecialchars($Channeldata[$MyISP." Name"], ENT_XML1);
-            $ChannelIconUrl = htmlspecialchars($Channeldata['Icon_url'], ENT_XML1);
-            if($Channeldata[$MyISP.'Ch'] != Null):
-                $ChannelInfos[] = array($ChannelId,  $ChannelName, $ChannelSource, $ChannelServiceId);
-                fprintf($fp, "  \n", $ChannelId);
-                fprintf($fp, "    %s\n", $ChannelName);
+            $ChannelIconUrl = htmlspecialchars($Channeldata['Icon_url'], ENT_XML1);            
+            $ChannelInfos[] = array($ChannelId,  $ChannelName, $ChannelSource, $ChannelServiceId);
+            fprintf($fp, "  \n", $ChannelId);
+            fprintf($fp, "    %s\n", $ChannelName);
+            if($MyISP != "ALL" && $Channeldata[$MyISP.'Ch'] != Null):
+                $Channelnumber = $Channeldata[$MyISP.'Ch'];
+                $ChannelISPName = htmlspecialchars($Channeldata[$MyISP." Name"], ENT_XML1);
                 fprintf($fp, "    %s\n", $ChannelISPName);
                 fprintf($fp, "    %s\n", $Channelnumber);
                 fprintf($fp, "    %s\n", $Channelnumber." ".$ChannelISPName);
-                if($IconUrl) :
-                    fprintf($fp, "    \n", $IconUrl, $ChannelId);
-                else :
-                    fprintf($fp, "    \n", $ChannelIconUrl);
-                endif;
-                fprintf($fp, "  \n");
             endif;
+            if($IconUrl) :
+                fprintf($fp, "    \n", $IconUrl, $ChannelId);
+            else :
+                fprintf($fp, "    \n", $ChannelIconUrl);
+            endif;
+            fprintf($fp, "  \n");
         endif;
     endforeach;
-
     # Print Program Information
     foreach ($ChannelInfos as $ChannelInfo) :
         $ChannelId = $ChannelInfo[0];
@@ -368,6 +368,7 @@ function GetEPGFromEPG($ChannelInfo) {
         );
         $params = http_build_query($params);
         $url = $url."?".$params;
+        $epginfo = array();
         try {
             $response = @file_get_contents($url, False, $context);
             if ($response === False) :
@@ -399,7 +400,7 @@ function GetEPGFromEPG($ChannelInfo) {
                                     $hour = $hour." PM";
                                 else :
                                     $hour = $hour." AM";
-                                    $thisday = date("Ymd", strtotime("+1 days"));
+                                    $thisday = date("Ymd", strtotime($day." +1 days"));
                                 endif;
                                 break;
                         endswitch;
@@ -476,6 +477,7 @@ function GetEPGFromKT($ChannelInfo) {
         );
         $params = http_build_query($params);
         $url = $url."?".$params;
+        $epginfo = array();
         try {
             $response = @file_get_contents($url, False, $context);
             if ($response === False) :
@@ -491,14 +493,19 @@ function GetEPGFromKT($ChannelInfo) {
                 foreach($rows as $row) :
                     $cells = $row->getElementsByTagName('td');
                     #programName, startTime, rating, category
-                    $startTime = date("YmdHis", strtotime($day." ".trim($cells[0]->nodeValue)));
-                    $rating = str_replace("all", 0, str_replace("세 이상", "", trim($cells[2]->nodeValue)));
-                    $epginfo[]= array(trim($cells[1]->nodeValue), $startTime, $rating, trim($cells[4]->nodeValue));
+                    $startTime = date("YmdHis", strtotime($day." ".trim($cells->item(0)->nodeValue)));
+                    $rating = str_replace("all", 0, str_replace("세 이상", "", trim($cells->item(2)->nodeValue)));
+                    $epginfo[]= array(trim($cells->item(1)->nodeValue), $startTime, $rating, trim($cells->item(4)->nodeValue));
                 endforeach;
                 $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1);
                 foreach($zipped as $epg) :
-                    $programName = $epg[0][0] ?: "";
+                    $programName = "";
                     $subprogramName = "";
+                    preg_match('/^(.*?)( <(.*)>)?$/', $epg[0][0], $matches);
+                    if($matches) :
+                       $programName = $matches[1] ?: "";
+                       $subprogramName = $matches[3] ?: "";
+                    endif;
                     $startTime = $epg[0][1] ?: "";
                     $endTime = $epg[1][1] ?: "";
                     $desc = "";
@@ -522,6 +529,7 @@ function GetEPGFromKT($ChannelInfo) {
                         'rebroadcast' => $rebroadcast,
                         'rating' => $rating
                     );
+
                     writeProgram($programdata);
                 endforeach;
             endif;
@@ -550,7 +558,7 @@ function GetEPGFromLG($ChannelInfo) {
         );
         $params = http_build_query($params);
         $url = $url."?".$params;
-
+        $epginfo = array();
         try {
             $response = @file_get_contents($url, False, $context);
             if ($response === False) :
@@ -563,18 +571,16 @@ function GetEPGFromLG($ChannelInfo) {
                 $response = str_replace(array('<재>', ' [..', ' (..'), array('<재>', '', ''), $response);
                 $dom->loadHTML($response);
                 $xpath = new DomXPath($dom);
-                $query = "//table[@class='datatable06 datatable06_type01']/tbody/tr";
+                $query = "//div[@class='tblType list']/table/tbody/tr";
                 $rows = $xpath->query($query);
                 foreach($rows as $row) :
                     $cells = $row->getElementsByTagName('td');
-                    $startTime = date("YmdHis", strtotime($day." ".trim($cells[0]->nodeValue)));
-                    $images = $cells[1]->getElementsByTagName('img');
-                    $rating = 0;
-                    foreach($images as $image) :
-                        if(preg_match('/(\d+)세이상 관람가/', $image->attributes->getNamedItem('alt')->nodeValue, $ratings)) $rating = $ratings[1];
-                    endforeach;
+                    $programName = trim($cells->item(1)->childNodes->item(0)->nodeValue);
+                    $startTime = date("YmdHis", strtotime($day." ".trim($cells->item(0)->nodeValue)));
+                    $spans = $cells->item(1)->getElementsByTagName('span');
+                    $rating = trim($spans->item(1)->nodeValue)=="All" ? 0 : trim($spans->item(1)->nodeValue);
                     #programName, startTime, rating, category
-                    $epginfo[]= array(trim($cells[1]->nodeValue), $startTime, $rating, trim($cells[2]->nodeValue));
+                    $epginfo[]= array($programName, $startTime, $rating, trim($cells->item(2)->nodeValue));
                 endforeach;
                 $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1);
                 foreach($zipped as $epg) :
@@ -737,15 +743,15 @@ function GetEPGFromSKY($ChannelInfo) {
                     else :
                         $programs = $data['scheduleListIn'];
                         foreach($programs as $program) :
-                            $programName = str_replace(array('<', '>', '&'), array('<', '>', '&'),$program['program_name']) ?: "";
-                            $subprogramName = str_replace(array('<', '>', '&'), array('<', '>', '&'),$program['program_subname']) ?: "";
+                            $programName = htmlspecialchars_decode($program['program_name']) ?: "";
+                            $subprogramName = str_replace(array('amp;'), array('&'),$program['program_subname']) ?: "";
                             $startTime = $program['starttime'];
                             $endTime = $program['endtime'];
                             if ($GLOBALS['addverbose'] == "y") :
                                 $actors = trim(str_replace('...', '',$program['cast']), ', ') ?: "";
                                 $producers = trim(str_replace('...', '',$program['dirt']), ', ') ?: "";
-                                $description = str_replace(array('<', '>', '&'), array('<', '>', '&'),$program['description']) ?: "";
-                                $summary = str_replace(array('<', '>', '&'), array('<', '>', '&'),$program['summary']) ?: "";
+                                $description = str_replace(array('lt;', 'gt;', 'amp;'), array('<', '>', '&'),$program['description']) ?: "";
+                                $summary = str_replace(array('lt;', 'gt;', 'amp;'), array('<', '>', '&'),$program['summary']) ?: "";
                                 $desc = $description ?: "";
                                 if($summary) :
                                     $desc = $desc."\n".$summary;
@@ -800,85 +806,85 @@ function GetEPGFromNaver($ChannelInfo) {
         $day = date("Ymd", strtotime("+".($k - 1)." days"));
         $totaldate[] = $day;
     endforeach;
-        $params = array(
-            '_callback' => 'epg',
-            'fileKey' => 'single_schedule_channel_day',
-            'pkid' => '66',
-            'u1' => 'single_schedule_channel_day',
-            'u2' => join(",", $totaldate),
-            'u3' => $day,
-            'u4' => $GLOBALS['period'],
-            'u5' => $ServiceId,
-            'u6' => 1,
-            'u7' => $ChannelName."편성표", 
-            'u8' => $ChannelName."편성표",
-            'where' => 'nexearch'
-        );
+    $params = array(
+        '_callback' => 'epg',
+        'fileKey' => 'single_schedule_channel_day',
+        'pkid' => '66',
+        'u1' => 'single_schedule_channel_day',
+        'u2' => join(",", $totaldate),
+        'u3' => $day,
+        'u4' => $GLOBALS['period'],
+        'u5' => $ServiceId,
+        'u6' => 1,
+        'u7' => $ChannelName."편성표", 
+        'u8' => $ChannelName."편성표",
+        'where' => 'nexearch'
+    );
 
-        $params = http_build_query($params);
-        $url = $url."?".$params;
-        try {
-            $response = @file_get_contents($url, False, $context);
-            if ($response === False) :
-                printError($ChannelName.HTTP_ERROR);
-            else :
-                try {
-                    $response = str_replace('epg( ', '', $response );
-                    $response = substr($response, 0, strlen($response)-2);
-                    $response = preg_replace("/\/\*.*?\*\//","",$response);
-                    $data = json_decode($response, TRUE);
-                    if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR);
-                     if($data['displayDates'][0]['count'] == 0) :
-                        if($GLOBALS['debug']) : 
-                            printError($ChannelName.CHANNEL_ERROR);
-                        endif;
-                    else :
-                        for($i = 0; $i < count($data['displayDates']); $i++) :
-                            for($j = 0; $j < 24; $j++) :
-                                foreach($data['schedules'][$j][$i] as $program) :
-                                    #programName, startTime, episode, rebroadcast, rating
-                                    $startTime = date("YmdHis", strtotime($data['displayDates'][$i]['date']." ".$program['startTime']));
-                                    $epginfo[] = array($program['title'], $startTime, str_replace("회","", $program['episode']), $program['isRerun'], $program['grade']);
-                                endforeach;
-                            endfor;
-                        endfor;
-                        $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1);
-                        foreach($zipped as $epg) :
-                            $programName = $epg[0][0] ?: "";
-                            $subprogramName = "";
-                            $startTime = $epg[0][1] ?: "";
-                            $endTime = $epg[1][1] ?: "";
-                            $desc = "";
-                            $actors = "";
-                            $producers = "";
-                            $category = "";
-                            $rebroadcast = $epg[0][3] ? True: False;
-                            $episode = $epg[0][2] ?: "";
-                            $rating = $epg[0][4] ?: 0;
-                            $programdata = array(
-                                'channelId'=> $ChannelId,
-                                'startTime' => $startTime,
-                                'endTime' => $endTime,
-                                'programName' => $programName,
-                                'subprogramName'=> $subprogramName,
-                                'desc' => $desc,
-                                'actors' => $actors,
-                                'producers' => $producers,
-                                'category' => $category,
-                                'episode' => $episode,
-                                'rebroadcast' => $rebroadcast,
-                                'rating' => $rating
-                            );
-                            writeProgram($programdata);
-                        endforeach;
+    $params = http_build_query($params);
+    $url = $url."?".$params;
+    try {
+        $response = @file_get_contents($url, False, $context);
+        if ($response === False) :
+            printError($ChannelName.HTTP_ERROR);
+        else :
+            try {
+                $response = str_replace('epg( ', '', $response );
+                $response = substr($response, 0, strlen($response)-2);
+                $response = preg_replace("/\/\*.*?\*\//","",$response);
+                $data = json_decode($response, TRUE);
+                if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR);
+                 if($data['displayDates'][0]['count'] == 0) :
+                    if($GLOBALS['debug']) : 
+                        printError($ChannelName.CHANNEL_ERROR);
                     endif;
-                 } catch(Exception $e) {
-                    if($GLOBALS['debug']) printError($e->getMessage());
-                }
-            endif;
-        } catch (Exception $e) {
-            if($GLOBALS['debug']) printError($e->getMessage());
-        }
+                else :
+                    for($i = 0; $i < count($data['displayDates']); $i++) :
+                        for($j = 0; $j < 24; $j++) :
+                            foreach($data['schedules'][$j][$i] as $program) :
+                                #programName, startTime, episode, rebroadcast, rating
+                                $startTime = date("YmdHis", strtotime($data['displayDates'][$i]['date']." ".$program['startTime']));
+                                $epginfo[] = array($program['title'], $startTime, str_replace("회","", $program['episode']), $program['isRerun'], $program['grade']);
+                            endforeach;
+                        endfor;
+                    endfor;
+                    $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1);
+                    foreach($zipped as $epg) :
+                        $programName = htmlspecialchars_decode($epg[0][0], ENT_XML1) ?: "";
+                        $subprogramName = "";
+                        $startTime = $epg[0][1] ?: "";
+                        $endTime = $epg[1][1] ?: "";
+                        $desc = "";
+                        $actors = "";
+                        $producers = "";
+                        $category = "";
+                        $rebroadcast = $epg[0][3] ? True: False;
+                        $episode = $epg[0][2] ?: "";
+                        $rating = $epg[0][4] ?: 0;
+                        $programdata = array(
+                            'channelId'=> $ChannelId,
+                            'startTime' => $startTime,
+                            'endTime' => $endTime,
+                            'programName' => $programName,
+                            'subprogramName'=> $subprogramName,
+                            'desc' => $desc,
+                            'actors' => $actors,
+                            'producers' => $producers,
+                            'category' => $category,
+                            'episode' => $episode,
+                            'rebroadcast' => $rebroadcast,
+                            'rating' => $rating
+                        );
+                        writeProgram($programdata);
+                    endforeach;
+                endif;
+             } catch(Exception $e) {
+                if($GLOBALS['debug']) printError($e->getMessage());
+            }
+        endif;
+    } catch (Exception $e) {
+        if($GLOBALS['debug']) printError($e->getMessage());
+    }
 }
 function writeProgram($programdata) {
     $fp = $GLOBALS['fp'];
@@ -900,9 +906,9 @@ function writeProgram($programdata) {
         $rating = sprintf("%s세 이상 관람가", $programdata['rating']);
     endif;
     if($GLOBALS['addverbose'] == 'y') :
-        $desc = $programdata['programName'];
+        $desc = htmlspecialchars($programdata['programName'], ENT_XML1);
         if($subprogramName)  $desc = $desc."\n부제 : ".$subprogramName;
-        if($episode) $desc = $desc."\n회차 : (".$episode."회)";
+        if($episode) $desc = $desc."\n회차 : ".$episode."회";
         if($category) $desc = $desc."\n장르 : ".$category;
         if($actors) $desc = $desc."\n출연 : ".$actors;
         if($producers) $desc = $desc."\n제작 : ".$producers;
@@ -910,8 +916,7 @@ function writeProgram($programdata) {
     else:
         $desc = "";
     endif;
-    if($programdata['desc']) $desc = $desc."\n".$programdata['desc'];
-    $desc = htmlspecialchars($desc, ENT_XML1);
+    if($programdata['desc']) $desc = $desc."\n".htmlspecialchars($programdata['desc'], ENT_XML1);
     $contentTypeDict = array(
         '교양' => 'Arts / Culture (without music)',
         '만화' => 'Cartoons / Puppets',

From e5dda3c175eefe17419db01c00ad73da05ef31ee Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Thu, 13 Apr 2017 12:19:24 +0900
Subject: [PATCH 24/51] =?UTF-8?q?IPTV=20=EC=9E=85=EB=A0=A5=20ALL=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80,=20=EC=A4=91=EB=B3=B5=20=EB=8D=B0=EC=9D=B4?=
 =?UTF-8?q?=ED=84=B0=20=EC=B6=9C=EB=A0=A5=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 epg2xml.py | 85 +++++++++++++++++++++++++++++-------------------------
 1 file changed, 45 insertions(+), 40 deletions(-)

diff --git a/epg2xml.py b/epg2xml.py
index b7a5158..658d7ea 100644
--- a/epg2xml.py
+++ b/epg2xml.py
@@ -17,7 +17,7 @@ import pprint
 reload(sys)
 sys.setdefaultencoding('utf-8')
 
-__version__ = '1.1.5'
+__version__ = '1.1.6'
 
 # Set variable
 debug = False
@@ -46,7 +46,7 @@ def getEpg():
 
     print('')
     print('\n')
-    print('')
+    print('')
 
     for Channeldata in Channeldatas: #Get Channel & Print Channel info
         if Channeldata['Enabled'] == 1:
@@ -54,18 +54,21 @@ def getEpg():
             ChannelName = escape(Channeldata['Name'])
             ChannelSource = Channeldata['Source']
             ChannelServiceId = Channeldata['ServiceId']
-            ChannelISPName = '[' + str(Channeldata[MyISP+'Ch']) + '] ' + escape(Channeldata[MyISP+' Name'])
             ChannelIconUrl = escape(Channeldata['Icon_url'])
-            if not (Channeldata[MyISP+'Ch'] is None):
-                ChannelInfos.append([ChannelId,  ChannelName, ChannelSource, ChannelServiceId])
-                print('  ' % (ChannelId))
-                print('    %s' % (ChannelName))
+            ChannelInfos.append([ChannelId,  ChannelName, ChannelSource, ChannelServiceId])
+            print('  ' % (ChannelId))
+            print('    %s' % (ChannelName))
+            if MyISP != "ALL" and Channeldata[MyISP+'Ch'] is not None:
+                ChannelNumber = str(Channeldata[MyISP+'Ch']);
+                ChannelISPName = escape(Channeldata[MyISP+' Name'])
                 print('    %s' % (ChannelISPName))
-                if IconUrl:
-                    print('    ' % (IconUrl, ChannelId))
-                else :
-                    print('    ' % (ChannelIconUrl))
-                print('  ')
+                print('    %s' % (ChannelNumber))
+                print('    %s' % (ChannelNumber+' '+ChannelISPName))
+            if IconUrl:
+                print('    ' % (IconUrl, ChannelId))
+            else :
+                print('    ' % (ChannelIconUrl))
+            print('  ')
 
     # Print Program Information
     for ChannelInfo in ChannelInfos:
@@ -81,11 +84,11 @@ def getEpg():
         elif ChannelSource == 'LG':
             GetEPGFromLG(ChannelInfo)
         elif ChannelSource == 'SK':
-           GetEPGFromSK(ChannelInfo)
+            GetEPGFromSK(ChannelInfo)
         elif ChannelSource == 'SKY':
-           GetEPGFromSKY(ChannelInfo)
+            GetEPGFromSKY(ChannelInfo)
         elif ChannelSource == 'NAVER':
-           GetEPGFromNaver(ChannelInfo)
+            GetEPGFromNaver(ChannelInfo)
     print('')
 
 # Get EPG data from epg.co.kr
@@ -93,11 +96,11 @@ def GetEPGFromEPG(ChannelInfo):
     ChannelId = ChannelInfo[0]
     ChannelName = ChannelInfo[1]
     ServiceId =  ChannelInfo[3]
-    epginfo = []
     url = 'http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi'
     for k in range(period):
         day = today + datetime.timedelta(days=k)
         params = {'beforegroup':'100', 'checkchannel':ServiceId, 'select_group':'100', 'start_date':day.strftime('%Y%m%d')}
+        epginfo = []
         try:
             response = requests.post(url, data=params, headers=ua)
             response.raise_for_status()
@@ -130,8 +133,10 @@ def GetEPGFromEPG(ChannelInfo):
                             grade = re.match('.*schedule_([\d,]+)?.*',image)
                             if not (grade is None): rating = int(grade.group(1))
                             else : rating = 0
+                            programName = matches.group(2).strip() if matches.group(2) else ''
+                            subprogramName = matches.group(4).strip() if matches.group(4) else ''
                             #programName, startTime, rating, subprogramName, rebroadcast, episode
-                            epginfo.append([matches.group(2), startTime, rating, matches.group(4), matches.group(5), matches.group(7)])
+                            epginfo.append([programName, startTime, rating, subprogramName, matches.group(5), matches.group(7)])
 
             for epg1, epg2 in zip(epginfo, epginfo[1:]):
                 programName = epg1[0] if epg1[0] else ''
@@ -156,12 +161,12 @@ def GetEPGFromKT(ChannelInfo):
     ChannelId = ChannelInfo[0]
     ChannelName = ChannelInfo[1]
     ServiceId =  ChannelInfo[3]
-    epginfo = []
+
     url = 'http://tv.olleh.com/renewal_sub/liveTv/pop_schedule_week.asp'
     for k in range(period):
         day = today + datetime.timedelta(days=k)
         params = {'ch_name':'', 'ch_no':ServiceId, 'nowdate':day.strftime('%Y%m%d'), 'seldatie':day.strftime('%Y%m%d'), 'tab_no':'1'}
-
+        epginfo = []
         try:
             response = requests.get(url, params=params, headers=ua)
             response.raise_for_status()
@@ -170,7 +175,6 @@ def GetEPGFromKT(ChannelInfo):
             strainer = SoupStrainer('table', {'id':'pop_day'})
             soup = BeautifulSoup(data, 'lxml', parse_only=strainer, from_encoding='utf-8')
             html = soup.find('table', {'id':'pop_day'}).tbody.find_all('tr') if soup.find('table', {'id':'pop_day'}) else ''
-
             if(html):
                 for row in html:
                     for cell in [row.find_all('td')]:
@@ -209,32 +213,39 @@ def GetEPGFromLG(ChannelInfo):
     ChannelId = ChannelInfo[0]
     ChannelName = ChannelInfo[1]
     ServiceId =  ChannelInfo[3]
-    epginfo = []
+
     url = 'http://www.uplus.co.kr/css/chgi/chgi/RetrieveTvSchedule.hpi'
     for k in range(period):
         day = today + datetime.timedelta(days=k)
         params = {'chnlCd': ServiceId, 'evntCmpYmd': day.strftime('%Y%m%d')}
-
+        epginfo = []
         try:
             response = requests.get(url, params=params, headers=ua)
             response.raise_for_status()
             html_data = response.content
             data = unicode(html_data, 'euc-kr', 'ignore').encode('utf-8', 'ignore')
+            data = data.replace('<재>', '<재>')
             strainer = SoupStrainer('table')
             soup = BeautifulSoup(data, 'lxml', parse_only=strainer, from_encoding='utf-8')
-            html = soup.find('table', {'class':'datatable06'}).tbody.find_all('tr') if soup.find('table', {'class':'datatable06'}) else ''
+            html = soup.find('table').tbody.find_all('tr') if soup.find('table') else ''
             if(html):
                 for row in html:
                     for cell in [row.find_all('td')]:
-                        epginfo.append([cell[1].text.strip(), str(day) + ' ' + cell[0].text, cell[2].text.strip(), cell[1].find('img', alt=True)['alt'].strip()])
+                        rating = 0 if cell[1].find('span', {'class': 'tag cte_all'}).text.strip()=="All" else int(cell[1].find('span', {'class': 'tag cte_all'}).text.strip())
+                        cell[1].find('span', {'class': 'tagGroup'}).decompose()
+                        epginfo.append([cell[1].text.strip(), str(day) + ' ' + cell[0].text, cell[2].text.strip(), rating])
+                        #cell[1].find('img', alt=True)['alt'].strip()])
                 for epg1, epg2 in zip(epginfo, epginfo[1:]):
                     programName = ''
                     subprogramName = ''
                     episode = ''
-                    matches = re.match('^(.*?)(\(([\d,]+)회\))?$',  epg1[0].decode('string_escape'))
+                    matches = re.match('(<재>?)?(.*?)(\[(.*)\])?\s?(\(([\d,]+)회\))?$',  epg1[0].decode('string_escape'))
+                    rebroadcast = False
                     if not (matches is None):
-                        programName = matches.group(1) if matches.group(1) else ''
-                        episode = matches.group(3) if matches.group(3) else ''
+                        programName = matches.group(2) if matches.group(2) else ''
+                        subprogramName = matches.group(4) if matches.group(4) else ''
+                        rebroadcast = True if matches.group(1) else False
+                        episode = matches.group(6) if matches.group(6) else ''
                     startTime = datetime.datetime.strptime(epg1[1], '%Y-%m-%d %H:%M')
                     startTime = startTime.strftime('%Y%m%d%H%M%S')
                     endTime = datetime.datetime.strptime(epg2[1], '%Y-%m-%d %H:%M')
@@ -243,10 +254,6 @@ def GetEPGFromLG(ChannelInfo):
                     desc = ''
                     actors = ''
                     producers = ''
-                    rebroadcast = False
-                    rating = 0
-                    matches = re.match('(\d+)세이상 관람가', epg1[3].encode('utf-8'))
-                    if not(matches is None): rating = int(matches.group(1))
                     programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating}
                     writeProgram(programdata)
             else:
@@ -285,6 +292,8 @@ def GetEPGFromSK(ChannelInfo):
                         programName = matches.group(1).strip() if matches.group(1) else ''
                         subprogramName = matches.group(3).strip() if matches.group(3) else ''
                         episode = matches.group(2).replace('회', '') if matches.group(2) else ''
+                        episode = '' if episode== '0' else episode
+#                            printError(episode)
                         rebroadcast = True if matches.group(5) else False
                     startTime = datetime.datetime.fromtimestamp(int(program['startTime'])/1000)
                     startTime = startTime.strftime('%Y%m%d%H%M%S')
@@ -332,7 +341,7 @@ def GetEPGFromSKY(ChannelInfo):
                     else: pass
                 else :
                     programs = data['scheduleListIn']
-                    for program  in {v['starttime']:v for v in programs}.values():
+                    for program in programs :
                         programName = unescape(program['program_name']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['program_name'] else ''
                         subprogramName = unescape(program['program_subname']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['program_subname'] else ''
                         startTime = program['starttime']
@@ -441,7 +450,7 @@ def writeProgram(programdata):
     else:
         desc =''
     if programdata['desc'] : desc = desc + '\n' + escape(programdata['desc'])
-    contentTypeDict={'교양':'Arts / Culture (without music)', '만화':'Cartoons / Puppets', '교육':'Education / Science / Factual topics', '취미':'Leisure hobbies', '드라마':'Movie / Drama', '영화':'Movie / Drama', '음악':'Music / Ballet / Dance', '뉴스':'News / Current affairs', '다큐':'Documentary', '시사/다큐':'Documentary', '연예':'Show / Game show', '스포츠':'Sports', '홈쇼핑':'Advertisement / Shopping'}
+    contentTypeDict={'교양':'Arts / Culture (without music)', '만화':'Cartoons / Puppets', '교육':'Education / Science / Factual topics', '취미':'Leisure hobbies', '드라마':'Movie / Drama', '영화':'Movie / Drama', '음악':'Music / Ballet / Dance', '뉴스':'News / Current affairs', '다큐':'Documentary', '라이프':'Documentary', '시사/다큐':'Documentary', '연예':'Show / Game show', '스포츠':'Sports', '홈쇼핑':'Advertisement / Shopping'}
     contentType = ''
     for key, value in contentTypeDict.iteritems():
         if category.startswith(key):
@@ -479,10 +488,6 @@ def printLog(*args):
 def printError(*args):
     print("Error : ", *args, file=sys.stderr)
 
-#parser = argparse.ArgumentParser(description = 'EPG 정보 출력 프로그램')
-#parser.add_argument('-v', '--version', action = 'version', version = '%(prog)s version : ' + __version__)
-#parser.parse_args()
-
 Settingfile = os.path.dirname(os.path.abspath(__file__)) + '/epg2xml.json'
 ChannelInfos = []
 try:
@@ -508,7 +513,7 @@ except ValueError:
 
 parser = argparse.ArgumentParser(description = 'EPG 정보를 출력하는 방법을 선택한다')
 argu1 = parser.add_argument_group(description = 'IPTV 선택')
-argu1.add_argument('-i', dest = 'MyISP', choices = ['KT', 'LG', 'SK'], help = '사용하는 IPTV : KT, LG, SK', default = MyISP)
+argu1.add_argument('-i', dest = 'MyISP', choices = ['ALL', 'KT', 'LG', 'SK'], help = '사용하는 IPTV : ALL, KT, LG, SK', default = MyISP)
 argu2 = parser.add_mutually_exclusive_group()
 argu2.add_argument('-v', '--version', action = 'version', version = '%(prog)s version : ' + __version__)
 argu2.add_argument('-d', '--display', action = 'store_true', help = 'EPG 정보 화면출력')
@@ -538,8 +543,8 @@ if args.episode : default_episode = args.episode
 if args.verbose : default_verbose = args.verbose
 
 if MyISP:
-    if not any(MyISP in s for s in ['KT', 'LG', 'SK']):
-        printError("MyISP는 KT, LG, SK만 가능합니다.")
+    if not any(MyISP in s for s in ['ALL', 'KT', 'LG', 'SK']):
+        printError("MyISP는 ALL, KT, LG, SK만 가능합니다.")
         sys.exit()
 else :
     printError("epg2xml.json 파일의 MyISP항목이 없습니다.")

From 07ab61a4c69936173c375c315f25fe43f6a2acdd Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Thu, 13 Apr 2017 12:22:14 +0900
Subject: [PATCH 25/51] Update readme.txt

---
 readme.txt | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/readme.txt b/readme.txt
index 4e202bf..1cfa661 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,12 +1,17 @@
 1. 버전
- 1.1.5
+ 1.1.6
 
 2. 소개
  이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2  및 php5 Cli에서 사용 가능하도록 제작되었다.
  기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다.
 
 3. 변경사항
-  - inline 변수 재추가
-  
+  - 에피소드 넘버 출력 수정
+  - 시작 시간 에러 출력 수정
+  - 타이틀 출력 수정
+  - 서브타이틀 추출 수정
+  - 데이터 중복 출력 문제 수정
+  - php 버전이 5.6.3 이전일 때 오류 수정 DOM access 관련 에러 수정
+  
 4. 저작권
   - BSD 

From 299611a19b506db821322ea33c6f3b6babbfee7e Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Thu, 13 Apr 2017 12:22:44 +0900
Subject: [PATCH 26/51] Update readme.txt

---
 readme.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/readme.txt b/readme.txt
index 1cfa661..9c8a482 100644
--- a/readme.txt
+++ b/readme.txt
@@ -6,6 +6,7 @@
  기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다.
 
 3. 변경사항
+  - iptv 선택 항목에 ALL 추가
   - 에피소드 넘버 출력 수정
   - 시작 시간 에러 출력 수정
   - 타이틀 출력 수정

From e42f4bc8a961c087a92d003c60ff115229c6bc4d Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Thu, 13 Apr 2017 12:23:36 +0900
Subject: [PATCH 27/51] Update epg2xml.json

---
 epg2xml.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/epg2xml.json b/epg2xml.json
index d52619f..0f94945 100644
--- a/epg2xml.json
+++ b/epg2xml.json
@@ -1,7 +1,7 @@
 {
     "###_COMMENT_###" : "",
     "###_COMMENT_###" : "epg 정보를 가져오는 설정 파일",
-    "###_COMMENT_###" : "사용하는 ISP 선택 (KT, LG, SK)",
+    "###_COMMENT_###" : "사용하는 ISP 선택 (ALL, KT, LG, SK)",
     "MyISP": "KT",
     "###_COMMENT_###" : "output 셋팅은 (d, o, s) 셋중에 하나로 선택한다",
     "###_COMMENT_###" : " d - EPG 정보 화면 출력",

From dd26f142d172b62269cc6cf26bbf1ecbc098a9ab Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Thu, 13 Apr 2017 12:24:45 +0900
Subject: [PATCH 28/51] Update readme.txt

---
 readme.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/readme.txt b/readme.txt
index 9c8a482..e6cb4a5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -12,7 +12,7 @@
   - 타이틀 출력 수정
   - 서브타이틀 추출 수정
   - 데이터 중복 출력 문제 수정
-  - php 버전이 5.6.3 이전일 때 오류 수정 DOM access 관련 에러 수정
+  - php 버전이 5.6.3 이전일 때 DOM access 관련 에러 수정
   
 4. 저작권
   - BSD 

From a0b654ae41304649f4c4fea2702d716421fdd978 Mon Sep 17 00:00:00 2001
From: wonipapa 
Date: Fri, 14 Apr 2017 10:47:08 +0900
Subject: [PATCH 29/51] Update README.md

---
 README.md | 67 +++++++++++++++++++++++++++----------------------------
 1 file changed, 33 insertions(+), 34 deletions(-)

diff --git a/README.md b/README.md
index 504555f..4be9587 100644
--- a/README.md
+++ b/README.md
@@ -31,40 +31,6 @@ Channel.json 파일을 텍스트 편집기로 열어보면 각채널별 정보
 필요없는 채널정보를 가져오지 않게 하는 것으로 EPG 정보 수집시 시간을 단축할 수 있다.
 삭제된 채널등으로 인해서 오류 발생시에도 Enabled:0으로 변경하면 오류 발생을 차단할 수 있다.
 
-## 사용방법
-
-### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea)
-epg2xml tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 아래와 같이 변경해준다.
-
-#### PYTHON의 경우
-
-/usr/bin/python /home/hts/epg2xml.py 또는
-/home/hts/epg2xml.py
-
- -#### PHP의 경우 -
-/usr/bin/php /home/hts/epg2xml.php 또는
-/home/hts/epg2xml.php
-
- - - -### XMLTV SOCKET 사용시 -**xmltv.sock 사용시 socat 등을 사용하지 않고 바로 socket에 쓰기가 가능하다** - -#### PYTHON의 경우 -
-/usr/bin/python /home/hts/epg2xml.py 또는
-/home/hts/epg2xml.py
-
- -#### PHP의 경우 -
-/usr/bin/php /home/hts/epg2xml.php 또는
-/home/hts/epg2xml.php
-
- ## 옵션 소개 실행시 사용가능한 인수는 --help 명령어로 확인이 가능하다 epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다. @@ -82,5 +48,38 @@ epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다. --verbose : EPG 정보 상세하게 표기 ex) --verbose y
+## 사용방법 + +### tv_grab_file 사용시 (https://github.com/neo365/tvheadend-for-Korea) +epg2xml tv_grab_file 안의 cat xmltv.xml 또는 wget 부분을 아래와 같이 변경해준다. + +#### PYTHON의 경우 +
+/usr/bin/python /home/hts/epg2xml.py 또는
+/home/hts/epg2xml.py
+
+ +#### PHP의 경우 +
+/usr/bin/php /home/hts/epg2xml.php 또는
+/home/hts/epg2xml.php
+
+ +### XMLTV SOCKET 사용시 +**xmltv.sock 사용시 socat 등을 사용하지 않고 바로 socket에 쓰기가 가능하다** + +#### PYTHON의 경우 +
+/usr/bin/python /home/hts/epg2xml.py 또는
+/home/hts/epg2xml.py
+
+ +#### PHP의 경우 +
+/usr/bin/php /home/hts/epg2xml.php 또는
+/home/hts/epg2xml.php
+
+ + ## 라이센스 BSD From bb64dcecec6acabedfa3c64302e2e316a6fe5e00 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Fri, 14 Apr 2017 15:39:34 +0900 Subject: [PATCH 30/51] Update epg2xml.py --- epg2xml.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/epg2xml.py b/epg2xml.py index 658d7ea..cdf7fd0 100644 --- a/epg2xml.py +++ b/epg2xml.py @@ -293,7 +293,6 @@ def GetEPGFromSK(ChannelInfo): subprogramName = matches.group(3).strip() if matches.group(3) else '' episode = matches.group(2).replace('회', '') if matches.group(2) else '' episode = '' if episode== '0' else episode -# printError(episode) rebroadcast = True if matches.group(5) else False startTime = datetime.datetime.fromtimestamp(int(program['startTime'])/1000) startTime = startTime.strftime('%Y%m%d%H%M%S') @@ -357,7 +356,6 @@ def GetEPGFromSKY(ChannelInfo): desc = '' actors = '' producers = '' - category = program['program_category1'] episode = program['episode_id'] if program['episode_id'] else '' if episode : episode = int(episode) From 780813a4df8698da934f862f56bbfd1e2cfcf905 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Wed, 19 Apr 2017 12:42:49 +0900 Subject: [PATCH 31/51] =?UTF-8?q?KT=202017=EB=85=84=204=EC=9B=94=2020?= =?UTF-8?q?=EC=9D=BC=20=EC=B1=84=EB=84=90=20=EB=B3=80=EA=B2=BD=20=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=88=98=EC=A0=95,=20=EB=9D=BC=EB=94=94=EC=98=A4?= =?UTF-8?q?=20=EC=B1=84=EB=84=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Channel.json | 126 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 49 deletions(-) diff --git a/Channel.json b/Channel.json index 048a40e..d769122 100644 --- a/Channel.json +++ b/Channel.json @@ -1,6 +1,7 @@ -[{"Id":1,"Name":"9colors","KT Name":"9colors","KTCh":163,"LG Name":"9 colors","LGCh":178,"SK Name":"9colors","SKCh":220,"Icon_url":"http://i.imgur.com/tRhzBgK.png","Source":"SK","ServiceId":285,"Enabled":1}, +[ +{"Id":1,"Name":"9colors","KT Name":"9colors","KTCh":163,"LG Name":"9 colors","LGCh":178,"SK Name":"9colors","SKCh":220,"Icon_url":"http://i.imgur.com/tRhzBgK.png","Source":"SK","ServiceId":285,"Enabled":1}, {"Id":2,"Name":"애니박스","KT Name":"애니박스","KTCh":135,"LG Name":"애니박스","LGCh":148,"SK Name":"애니박스","SKCh":179,"Icon_url":"http://i.imgur.com/ipM9AXe.png","Source":"SK","ServiceId":191,"Enabled":1}, -{"Id":3,"Name":"Animal Planet","KT Name":"Animal Planet","KTCh":202,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ae70Di1.png","Source":"SKY","ServiceId":182,"Enabled":1}, +{"Id":3,"Name":"Animal Planet","KT Name":"Animal Planet","KTCh":179,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ae70Di1.png","Source":"SKY","ServiceId":182,"Enabled":1}, {"Id":4,"Name":"ANIMAX","KT Name":"ANIMAX","KTCh":133,"LG Name":"ANIMAX","LGCh":167,"SK Name":"Animax","SKCh":173,"Icon_url":"http://i.imgur.com/2Gfqhuj.png","Source":"SK","ServiceId":371,"Enabled":1}, {"Id":5,"Name":"애니원","KT Name":"애니원","KTCh":134,"LG Name":"애니원","LGCh":153,"SK Name":"애니원","SKCh":174,"Icon_url":"http://i.imgur.com/sIp2MZ3.png","Source":"SK","ServiceId":379,"Enabled":1}, {"Id":6,"Name":"예술 TV아르떼","KT Name":"예술 TV아르떼","KTCh":91,"LG Name":"예술TV Arte","LGCh":139,"SK Name":"Arte TV","SKCh":234,"Icon_url":"http://i.imgur.com/zReu7df.png","Source":"SK","ServiceId":421,"Enabled":1}, @@ -8,7 +9,7 @@ {"Id":8,"Name":"AsiaN","KT Name":"AsiaN","KTCh":111,"LG Name":"AsiaN","LGCh":88,"SK Name":"Asia N","SKCh":106,"Icon_url":"http://i.imgur.com/gleMSFq.png","Source":"SK","ServiceId":177,"Enabled":1}, {"Id":9,"Name":"Australia Plus","KT Name":"Australia Plus","KTCh":258,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/6k9j2Hj.png","Source":"NAVER","ServiceId":815391,"Enabled":1}, {"Id":10,"Name":"AXN","KT Name":"AXN","KTCh":113,"LG Name":"AXN","LGCh":45,"SK Name":"AXN","SKCh":102,"Icon_url":"http://i.imgur.com/QrAXBEm.png","Source":"SK","ServiceId":195,"Enabled":1}, -{"Id":11,"Name":"B Shopping","KT Name":"B Shopping","KTCh":40,"LG Name":"Btv 쇼핑","LGCh":28,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/HiCKxpt.png","Source":"SKY","ServiceId":529,"Enabled":1}, +{"Id":11,"Name":"B Shopping","KT Name":"B Shopping","KTCh":30,"LG Name":"Btv 쇼핑","LGCh":28,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/HiCKxpt.png","Source":"SKY","ServiceId":529,"Enabled":1}, {"Id":14,"Name":"Baby TV","KT Name":"Baby TV","KTCh":146,"LG Name":"","LGCh":null,"SK Name":"Baby TV","SKCh":195,"Icon_url":"http://i.imgur.com/mU7QuTz.png","Source":"SK","ServiceId":785,"Enabled":1}, {"Id":15,"Name":"BBC Earth","KT Name":"BBC Earth","KTCh":172,"LG Name":"BBC Earth","LGCh":130,"SK Name":"BBC earth","SKCh":265,"Icon_url":"http://i.imgur.com/SJZjuqO.png","Source":"SK","ServiceId":472,"Enabled":1}, {"Id":18,"Name":"BBC WN","KT Name":"BBC WN","KTCh":192,"LG Name":"BBC World News","LGCh":126,"SK Name":"BBC World News","SKCh":160,"Icon_url":"http://i.imgur.com/IwJBNd4.png","Source":"SK","ServiceId":778,"Enabled":1}, @@ -23,13 +24,13 @@ {"Id":28,"Name":"CBS","KT Name":"CBS","KTCh":238,"LG Name":"CBS","LGCh":181,"SK Name":"CBS","SKCh":300,"Icon_url":"http://i.imgur.com/yBNo2mS.png","Source":"SK","ServiceId":727,"Enabled":1}, {"Id":31,"Name":"CCTV4","KT Name":"CCTV4","KTCh":280,"LG Name":"CCTV4","LGCh":120,"SK Name":"CCTV4","SKCh":277,"Icon_url":"http://i.imgur.com/ACwvhcc.png","Source":"SK","ServiceId":779,"Enabled":1}, {"Id":32,"Name":"CGNTV","KT Name":"CGNTV","KTCh":237,"LG Name":"CGNTV","LGCh":183,"SK Name":"CGNTV","SKCh":302,"Icon_url":"http://i.imgur.com/9fNvKEX.png","Source":"SK","ServiceId":723,"Enabled":1}, -{"Id":34,"Name":"Channel [V]","KT Name":"Channel [V]","KTCh":98,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/t1PNA6v.png","Source":"EPG","ServiceId":463,"Enabled":1}, +{"Id":34,"Name":"Channel [V]","KT Name":"Channel [V]","KTCh":89,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/t1PNA6v.png","Source":"EPG","ServiceId":463,"Enabled":1}, {"Id":35,"Name":"채널 J","KT Name":"채널 J","KTCh":108,"LG Name":"채널J","LGCh":145,"SK Name":"채널J","SKCh":103,"Icon_url":"http://i.imgur.com/V9jGCZm.png","Source":"SK","ServiceId":197,"Enabled":1}, {"Id":36,"Name":"Channel News Asia","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"Channel News Asia","SKCh":163,"Icon_url":"http://i.imgur.com/hahdOp1.png","Source":"SK","ServiceId":777,"Enabled":1}, {"Id":38,"Name":"cineF","KT Name":"","KTCh":null,"LG Name":"cineF","LGCh":42,"SK Name":"Cinef","SKCh":58,"Icon_url":"http://i.imgur.com/TfhQXIv.png","Source":"SK","ServiceId":193,"Enabled":1}, {"Id":39,"Name":"UXN","KT Name":"UXN","KTCh":101,"LG Name":"UXN","LGCh":2,"SK Name":"UXN","SKCh":70,"Icon_url":"http://i.imgur.com/5rRW0R3.png","Source":"SKY","ServiceId":624,"Enabled":1}, {"Id":40,"Name":"CJ오쇼핑","KT Name":"CJ오쇼핑","KTCh":4,"LG Name":"CJ오쇼핑","LGCh":8,"SK Name":"CJ오쇼핑","SKCh":6,"Icon_url":"http://i.imgur.com/uBClUx6.png","Source":"SK","ServiceId":324,"Enabled":1}, -{"Id":41,"Name":"CJ오쇼핑 플러스","KT Name":"CJ오쇼핑플러스","KTCh":46,"LG Name":"CJ오쇼핑 플러스","LGCh":32,"SK Name":"CJ오쇼핑 플러스","SKCh":33,"Icon_url":"http://i.imgur.com/WlK2YDk.png","Source":"SK","ServiceId":340,"Enabled":1}, +{"Id":41,"Name":"CJ오쇼핑 플러스","KT Name":"CJ오쇼핑플러스","KTCh":28,"LG Name":"CJ오쇼핑 플러스","LGCh":32,"SK Name":"CJ오쇼핑 플러스","SKCh":33,"Icon_url":"http://i.imgur.com/WlK2YDk.png","Source":"SK","ServiceId":340,"Enabled":1}, {"Id":42,"Name":"CLASSICA","KT Name":"CLASSICA","KTCh":90,"LG Name":"Classica","LGCh":146,"SK Name":"Classica HD","SKCh":235,"Icon_url":"http://i.imgur.com/FEfMS0W.png","Source":"SK","ServiceId":787,"Enabled":1}, {"Id":43,"Name":"CMC가족오락TV","KT Name":"CMC가족오락TV","KTCh":126,"LG Name":"","LGCh":null,"SK Name":"CMC 가족오락TV","SKCh":93,"Icon_url":"http://i.imgur.com/fNuqGzR.png","Source":"SK","ServiceId":876,"Enabled":1}, {"Id":44,"Name":"CMTV","KT Name":"CMTV","KTCh":262,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ITweLdv.png","Source":"NAVER","ServiceId":2843917,"Enabled":1}, @@ -42,7 +43,7 @@ {"Id":51,"Name":"디스커버리채널","KT Name":"디스커버리채널","KTCh":177,"LG Name":"","LGCh":null,"SK Name":"Discovery Channel","SKCh":261,"Icon_url":"http://i.imgur.com/1SgSI0P.png","Source":"SK","ServiceId":437,"Enabled":1}, {"Id":52,"Name":"Dog TV","KT Name":"Dog TV","KTCh":201,"LG Name":"DOG TV","LGCh":89,"SK Name":"DOG TV","SKCh":79,"Icon_url":"http://i.imgur.com/4Xqehq9.png","Source":"SK","ServiceId":255,"Enabled":1}, {"Id":53,"Name":"Dream Works Channel","KT Name":"Dream Works Channel","KTCh":131,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ETfF49T.png","Source":"KT","ServiceId":131,"Enabled":1}, -{"Id":54,"Name":"DW-TV Asia+","KT Name":"DW-TV Asia+","KTCh":257,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/b0yhwNu.png","Source":"KT","ServiceId":257,"Enabled":1}, +{"Id":54,"Name":"DW-TV Asia+","KT Name":"DW-TV Asia+","KTCh":257,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/b0yhwNu.png","Source":"NAVER","ServiceId":815529,"Enabled":1}, {"Id":55,"Name":"E채널","KT Name":"E채널","KTCh":48,"LG Name":"E channel","LGCh":104,"SK Name":"E채널","SKCh":83,"Icon_url":"http://i.imgur.com/0WmEGB4.png","Source":"SK","ServiceId":886,"Enabled":1}, {"Id":56,"Name":"EBS English","KT Name":"EBS English","KTCh":156,"LG Name":"EBS English","LGCh":162,"SK Name":"EBS English","SKCh":202,"Icon_url":"http://i.imgur.com/Rx4mgpm.png","Source":"SK","ServiceId":822,"Enabled":1}, {"Id":57,"Name":"EBS u","KT Name":"EBS u","KTCh":145,"LG Name":"EBS u","LGCh":168,"SK Name":"EBSu","SKCh":194,"Icon_url":"http://i.imgur.com/RIgVjvP.png","Source":"SK","ServiceId":372,"Enabled":1}, @@ -50,7 +51,7 @@ {"Id":59,"Name":"EBS PLUS2","KT Name":"EBS PLUS2","KTCh":158,"LG Name":"EBS Plus2","LGCh":164,"SK Name":"EBS +2","SKCh":204,"Icon_url":"http://i.imgur.com/QPq2wcg.png","Source":"SK","ServiceId":821,"Enabled":1}, {"Id":60,"Name":"EBS","KT Name":"EBS","KTCh":13,"LG Name":"EBS1","LGCh":14,"SK Name":"EBS","SKCh":13,"Icon_url":"http://i.imgur.com/WViFruZ.png","Source":"SK","ServiceId":15,"Enabled":1}, {"Id":61,"Name":"EBS2","KT Name":"EBS2","KTCh":95,"LG Name":"EBS2","LGCh":95,"SK Name":"EBS2","SKCh":95,"Icon_url":"http://i.imgur.com/RIrBF4D.png","Source":"SK","ServiceId":63,"Enabled":1}, -{"Id":62,"Name":"Edge TV","KT Name":"Edge TV","KTCh":127,"LG Name":"EDGE TV","LGCh":68,"SK Name":"EDGE TV","SKCh":44,"Icon_url":"http://i.imgur.com/gsnjG4A.png","Source":"SK","ServiceId":128,"Enabled":1}, +{"Id":62,"Name":"Edge TV","KT Name":"Edge TV","KTCh":79,"LG Name":"EDGE TV","LGCh":68,"SK Name":"EDGE TV","SKCh":44,"Icon_url":"http://i.imgur.com/gsnjG4A.png","Source":"SK","ServiceId":128,"Enabled":1}, {"Id":63,"Name":"edu TV","KT Name":"edu TV","KTCh":159,"LG Name":"eduTV","LGCh":165,"SK Name":"edu TV","SKCh":205,"Icon_url":"http://i.imgur.com/ZsMKNGe.png","Source":"SK","ServiceId":823,"Enabled":1}, {"Id":67,"Name":"Euro News","KT Name":"Euro News","KTCh":193,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/6jswCZM.png","Source":"NAVER","ServiceId":814935,"Enabled":1}, {"Id":68,"Name":"Euro sport","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"Eurosport","SKCh":134,"Icon_url":"http://i.imgur.com/7hVKz6n.png","Source":"SK","ServiceId":120,"Enabled":1}, @@ -71,19 +72,19 @@ {"Id":86,"Name":"GTV","KT Name":"GTV","KTCh":73,"LG Name":"GTV","LGCh":136,"SK Name":"Gtv","SKCh":217,"Icon_url":"http://i.imgur.com/1qXSXRa.png","Source":"SK","ServiceId":284,"Enabled":1}, {"Id":87,"Name":"히어로액션","KT Name":"히어로액션","KTCh":112,"LG Name":"Hero Action","LGCh":110,"SK Name":"히어로액션","SKCh":107,"Icon_url":"http://i.imgur.com/yBChQVh.png","Source":"SK","ServiceId":176,"Enabled":1}, {"Id":88,"Name":"High4K","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"High 4K","SKCh":74,"Icon_url":"http://i.imgur.com/rCn37Vx.png","Source":"EPG","ServiceId":647,"Enabled":1}, -{"Id":89,"Name":"하이라이트TV","KT Name":"하이라이트TV","KTCh":87,"LG Name":"하이라이트TV","LGCh":91,"SK Name":"Highlight TV","SKCh":42,"Icon_url":"http://i.imgur.com/V9CQ4A6.png","Source":"SK","ServiceId":885,"Enabled":1}, +{"Id":89,"Name":"하이라이트TV","KT Name":"하이라이트TV","KTCh":74,"LG Name":"하이라이트TV","LGCh":91,"SK Name":"Highlight TV","SKCh":42,"Icon_url":"http://i.imgur.com/V9CQ4A6.png","Source":"SK","ServiceId":885,"Enabled":1}, {"Id":90,"Name":"History HD","KT Name":"History HD","KTCh":169,"LG Name":"History HD","LGCh":132,"SK Name":"History HD","SKCh":264,"Icon_url":"http://i.imgur.com/SSkop4X.png","Source":"SK","ServiceId":470,"Enabled":1}, -{"Id":91,"Name":"HQ+","KT Name":"HQ+","KTCh":275,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/GTANuZS.png","Source":"NAVER","ServiceId":3566359,"Enabled":1}, +{"Id":91,"Name":"HQ+","KT Name":"HQ+","KTCh":253,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/GTANuZS.png","Source":"NAVER","ServiceId":3566359,"Enabled":1}, {"Id":92,"Name":"아이넷TV","KT Name":"아이넷TV","KTCh":92,"LG Name":"아이넷TV","LGCh":106,"SK Name":"아이넷 TV","SKCh":233,"Icon_url":"http://i.imgur.com/JYQpemw.png","Source":"SK","ServiceId":261,"Enabled":1}, {"Id":93,"Name":"IB SPORTS","KT Name":"IB SPORTS","KTCh":53,"LG Name":"IB SPORTS","LGCh":62,"SK Name":"IB Sports","SKCh":129,"Icon_url":"http://i.imgur.com/wOOQEC1.png","Source":"SK","ServiceId":123,"Enabled":1}, -{"Id":94,"Name":"i-Concerts","KT Name":"Stingray iConcerts","KTCh":89,"LG Name":"i-Concerts","LGCh":108,"SK Name":"i-Concerts","SKCh":236,"Icon_url":"http://i.imgur.com/oUUZQdi.png","Source":"SK","ServiceId":786,"Enabled":1}, +{"Id":94,"Name":"i-Concerts","KT Name":"","KTCh":null,"LG Name":"i-Concerts","LGCh":108,"SK Name":"i-Concerts","SKCh":236,"Icon_url":"http://i.imgur.com/oUUZQdi.png","Source":"SK","ServiceId":786,"Enabled":1}, {"Id":95,"Name":"JEI EnglishTV","KT Name":"JEI EnglishTV","KTCh":154,"LG Name":"JEI EnglishTV","LGCh":160,"SK Name":"JEI 재능 English","SKCh":200,"Icon_url":"http://i.imgur.com/R1oJmLo.png","Source":"SK","ServiceId":825,"Enabled":1}, {"Id":96,"Name":"JEI 재능TV","KT Name":"JEI 재능TV","KTCh":142,"LG Name":"JEI재능TV","LGCh":159,"SK Name":"JEI 재능TV","SKCh":192,"Icon_url":"http://i.imgur.com/NoNRdSt.png","Source":"SK","ServiceId":378,"Enabled":1}, {"Id":97,"Name":"JTBC","KT Name":"JTBC","KTCh":15,"LG Name":"JTBC","LGCh":15,"SK Name":"JTBC","SKCh":15,"Icon_url":"http://i.imgur.com/YOYosLG.png","Source":"SK","ServiceId":240,"Enabled":1}, {"Id":98,"Name":"JTBC Golf","KT Name":"JTBC Golf","KTCh":56,"LG Name":"JTBC Golf","LGCh":54,"SK Name":"JTBC GOLF","SKCh":132,"Icon_url":"http://i.imgur.com/Bnw7O5U.png","Source":"SK","ServiceId":127,"Enabled":1}, -{"Id":99,"Name":"JTBC2","KT Name":"JTBC2","KTCh":47,"LG Name":"JTBC2","LGCh":94,"SK Name":"jtbc2","SKCh":82,"Icon_url":"http://i.imgur.com/WtXDuFU.png","Source":"SK","ServiceId":874,"Enabled":1}, -{"Id":100,"Name":"JTBC3","KT Name":"JTBC3","KTCh":61,"LG Name":"JTBC3 FOX","LGCh":50,"SK Name":"JTBC3 FOXSPORTS","SKCh":126,"Icon_url":"http://i.imgur.com/KvGwEc1.png","Source":"SK","ServiceId":436,"Enabled":1}, -{"Id":101,"Name":"K STAR","KT Name":"K STAR","KTCh":99,"LG Name":"K STAR","LGCh":105,"SK Name":"K star","SKCh":88,"Icon_url":"http://i.imgur.com/5VMBbSq.png","Source":"SK","ServiceId":884,"Enabled":1}, +{"Id":99,"Name":"JTBC2","KT Name":"JTBC2","KTCh":39,"LG Name":"JTBC2","LGCh":94,"SK Name":"jtbc2","SKCh":82,"Icon_url":"http://i.imgur.com/WtXDuFU.png","Source":"SK","ServiceId":874,"Enabled":1}, +{"Id":100,"Name":"JTBC3","KT Name":"JTBC3","KTCh":62,"LG Name":"JTBC3 FOX","LGCh":50,"SK Name":"JTBC3 FOXSPORTS","SKCh":126,"Icon_url":"http://i.imgur.com/KvGwEc1.png","Source":"SK","ServiceId":436,"Enabled":1}, +{"Id":101,"Name":"K STAR","KT Name":"K STAR","KTCh":87,"LG Name":"K STAR","LGCh":105,"SK Name":"K star","SKCh":88,"Icon_url":"http://i.imgur.com/5VMBbSq.png","Source":"SK","ServiceId":884,"Enabled":1}, {"Id":103,"Name":"KBS DRAMA","KT Name":"KBS Drama","KTCh":35,"LG Name":"KBS DRAMA","LGCh":31,"SK Name":"KBS 드라마","SKCh":30,"Icon_url":"http://i.imgur.com/CrLMIEQ.png","Source":"SK","ServiceId":902,"Enabled":1}, {"Id":104,"Name":"KBS JOY","KT Name":"KBS Joy","KTCh":41,"LG Name":"KBS JOY","LGCh":3,"SK Name":"KBS joy","SKCh":80,"Icon_url":"http://i.imgur.com/D1o9by9.png","Source":"SK","ServiceId":880,"Enabled":1}, {"Id":105,"Name":"KBS kids","KT Name":"KBS Kids","KTCh":144,"LG Name":"KBS Kids","LGCh":169,"SK Name":"KBS KIDS","SKCh":190,"Icon_url":"http://i.imgur.com/Jcfjs9E.png","Source":"SK","ServiceId":382,"Enabled":1}, @@ -92,22 +93,22 @@ {"Id":108,"Name":"KBS W","KT Name":"KBS W","KTCh":83,"LG Name":"KBS W","LGCh":77,"SK Name":"KBS W","SKCh":214,"Icon_url":"http://i.imgur.com/sVqBczs.png","Source":"SK","ServiceId":425,"Enabled":1}, {"Id":110,"Name":"KBS1","KT Name":"KBS1","KTCh":9,"LG Name":"KBS1","LGCh":9,"SK Name":"KBS1","SKCh":9,"Icon_url":"http://i.imgur.com/e31o5gw.png","Source":"SK","ServiceId":11,"Enabled":1}, {"Id":111,"Name":"KBS2","KT Name":"KBS2","KTCh":7,"LG Name":"KBS2","LGCh":7,"SK Name":"KBS2","SKCh":7,"Icon_url":"http://i.imgur.com/XgibZbD.png","Source":"SK","ServiceId":12,"Enabled":1}, -{"Id":112,"Name":"키즈톡톡","KT Name":"키즈톡톡","KTCh":153,"LG Name":"키즈톡톡","LGCh":158,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/0loInJO.png","Source":"SKY","ServiceId":92,"Enabled":1}, +{"Id":112,"Name":"키즈톡톡","KT Name":"","KTCh":null,"LG Name":"키즈톡톡","LGCh":158,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/0loInJO.png","Source":"SKY","ServiceId":92,"Enabled":1}, {"Id":115,"Name":"KIDS-TV","KT Name":"KIDS-TV","KTCh":149,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/AVCSEdn.png","Source":"NAVER","ServiceId":814999,"Enabled":1}, -{"Id":116,"Name":"K-NET TV","KT Name":"K-NET TV","KTCh":230,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/GelnqjB.png","Source":"NAVER","ServiceId":815050,"Enabled":1}, +{"Id":116,"Name":"K-NET TV","KT Name":"K-NET TV","KTCh":230,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/GelnqjB.png","Source":"KT","ServiceId":230,"Enabled":1}, {"Id":117,"Name":"KTV","KT Name":"KTV","KTCh":64,"LG Name":"KTV","LGCh":171,"SK Name":"KTV","SKCh":290,"Icon_url":"http://i.imgur.com/yUk2RhO.png","Source":"SK","ServiceId":222,"Enabled":1}, {"Id":118,"Name":"K-바둑","KT Name":"K-바둑","KTCh":121,"LG Name":"K-바둑","LGCh":107,"SK Name":"K-바둑","SKCh":241,"Icon_url":"http://i.imgur.com/EAk5ySy.png","Source":"SK","ServiceId":253,"Enabled":1}, {"Id":119,"Name":"K쇼핑","KT Name":"K쇼핑","KTCh":20,"LG Name":"","LGCh":null,"SK Name":"K쇼핑","SKCh":25,"Icon_url":"http://i.imgur.com/6ORm0Rz.png","Source":"SK","ServiceId":333,"Enabled":1}, {"Id":121,"Name":"Mnet","KT Name":"Mnet","KTCh":27,"LG Name":"M.net","LGCh":22,"SK Name":"M.net","SKCh":27,"Icon_url":"http://i.imgur.com/putHm2b.png","Source":"SK","ServiceId":873,"Enabled":1}, {"Id":122,"Name":"MBC","KT Name":"MBC","KTCh":11,"LG Name":"MBC","LGCh":11,"SK Name":"MBC","SKCh":11,"Icon_url":"http://i.imgur.com/duig32i.png","Source":"SK","ServiceId":13,"Enabled":1}, -{"Id":123,"Name":"MBC Every1","KT Name":"MBC Every1","KTCh":1,"LG Name":"MBC에브리원","LGCh":29,"SK Name":"MBC Every1","SKCh":28,"Icon_url":"http://i.imgur.com/oOnpFes.png","Source":"SK","ServiceId":881,"Enabled":1}, +{"Id":123,"Name":"MBC Every1","KT Name":"MBC Every1","KTCh":3,"LG Name":"MBC에브리원","LGCh":29,"SK Name":"MBC Every1","SKCh":28,"Icon_url":"http://i.imgur.com/oOnpFes.png","Source":"SK","ServiceId":881,"Enabled":1}, {"Id":124,"Name":"MBC MUSIC","KT Name":"MBC MUSIC","KTCh":97,"LG Name":"MBC뮤직","LGCh":99,"SK Name":"MBC Music","SKCh":231,"Icon_url":"http://i.imgur.com/6g56RDx.png","Source":"SK","ServiceId":250,"Enabled":1}, {"Id":125,"Name":"MBC NET","KT Name":"MBC NET","KTCh":164,"LG Name":"MBCNET","LGCh":140,"SK Name":"MBC NET","SKCh":274,"Icon_url":"http://i.imgur.com/lxDOgY8.png","Source":"SK","ServiceId":281,"Enabled":1}, -{"Id":126,"Name":"MBC SPORT+","KT Name":"MBC SPORT+","KTCh":62,"LG Name":"MBC스포츠플러스","LGCh":60,"SK Name":"MBC Sports+","SKCh":123,"Icon_url":"http://i.imgur.com/Su21uj3.png","Source":"SK","ServiceId":131,"Enabled":1}, -{"Id":127,"Name":"MBC SPORTS+2","KT Name":"MBC SPORTS+2","KTCh":63,"LG Name":"MBC스포츠플러스2","LGCh":61,"SK Name":"MBC SPORTS+2","SKCh":124,"Icon_url":"http://i.imgur.com/frAuUS3.png","Source":"SK","ServiceId":531,"Enabled":1}, -{"Id":128,"Name":"MBC Dramanet","KT Name":"MBC Dramanet","KTCh":39,"LG Name":"MBC드라마넷","LGCh":35,"SK Name":"MBC 드라마","SKCh":32,"Icon_url":"http://i.imgur.com/VBMFcZ3.png","Source":"SK","ServiceId":900,"Enabled":1}, +{"Id":126,"Name":"MBC SPORT+","KT Name":"MBC SPORT+","KTCh":60,"LG Name":"MBC스포츠플러스","LGCh":60,"SK Name":"MBC Sports+","SKCh":123,"Icon_url":"http://i.imgur.com/Su21uj3.png","Source":"SK","ServiceId":131,"Enabled":1}, +{"Id":127,"Name":"MBC SPORTS+2","KT Name":"MBC SPORTS+2","KTCh":61,"LG Name":"MBC스포츠플러스2","LGCh":61,"SK Name":"MBC SPORTS+2","SKCh":124,"Icon_url":"http://i.imgur.com/frAuUS3.png","Source":"SK","ServiceId":531,"Enabled":1}, +{"Id":128,"Name":"MBC Dramanet","KT Name":"MBC Dramanet","KTCh":75,"LG Name":"MBC드라마넷","LGCh":35,"SK Name":"MBC 드라마","SKCh":32,"Icon_url":"http://i.imgur.com/VBMFcZ3.png","Source":"SK","ServiceId":900,"Enabled":1}, {"Id":129,"Name":"MBN","KT Name":"MBN","KTCh":16,"LG Name":"MBN","LGCh":16,"SK Name":"MBN","SKCh":16,"Icon_url":"http://i.imgur.com/p0mvIJN.png","Source":"SK","ServiceId":241,"Enabled":1}, -{"Id":130,"Name":"MBN Plus","KT Name":"MBN Plus","KTCh":272,"LG Name":"MBN플러스","LGCh":116,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yMZiUUp.png","Source":"EPG","ServiceId":658,"Enabled":1}, +{"Id":130,"Name":"MBN Plus","KT Name":"MBN Plus","KTCh":99,"LG Name":"MBN플러스","LGCh":116,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yMZiUUp.png","Source":"EPG","ServiceId":658,"Enabled":1}, {"Id":133,"Name":"마운틴TV","KT Name":"마운틴TV","KTCh":117,"LG Name":"마운틴TV","LGCh":69,"SK Name":"Mountain TV","SKCh":247,"Icon_url":"http://i.imgur.com/4nLYnVC.png","Source":"SK","ServiceId":251,"Enabled":1}, {"Id":134,"Name":"mplex","KT Name":"mplex","KTCh":103,"LG Name":"Mplex","LGCh":46,"SK Name":"Mplex","SKCh":57,"Icon_url":"http://i.imgur.com/dOOBYJm.png","Source":"SK","ServiceId":171,"Enabled":1}, {"Id":135,"Name":"머니투데이방송","KT Name":"머니투데이방송","KTCh":181,"LG Name":"MTN","LGCh":122,"SK Name":"MTN","SKCh":152,"Icon_url":"http://i.imgur.com/joWd14j.png","Source":"SK","ServiceId":627,"Enabled":1}, @@ -118,7 +119,7 @@ {"Id":141,"Name":"니켈로디언","KT Name":"니켈로디언","KTCh":136,"LG Name":"니켈로디언","LGCh":154,"SK Name":"Nickelodeon","SKCh":176,"Icon_url":"http://i.imgur.com/6pWpFCX.png","Source":"SK","ServiceId":383,"Enabled":1}, {"Id":142,"Name":"놀티비","KT Name":"놀티비","KTCh":128,"LG Name":"NOLL TV","LGCh":92,"SK Name":"Noll TV","SKCh":248,"Icon_url":"http://i.imgur.com/IK9h4rw.png","Source":"SK","ServiceId":259,"Enabled":1}, {"Id":143,"Name":"NS Shop+","KT Name":"NS Shop+","KTCh":42,"LG Name":"","LGCh":null,"SK Name":"NS Shop+","SKCh":41,"Icon_url":"http://i.imgur.com/ipGXgEK.png","Source":"SK","ServiceId":341,"Enabled":1}, -{"Id":144,"Name":"NS홈쇼핑","KT Name":"NS홈쇼핑","KTCh":6,"LG Name":"NS홈쇼핑","LGCh":13,"SK Name":"NS홈쇼핑","SKCh":14,"Icon_url":"http://i.imgur.com/UD1yoj1.png","Source":"SK","ServiceId":322,"Enabled":1}, +{"Id":144,"Name":"NS홈쇼핑","KT Name":"NS홈쇼핑","KTCh":12,"LG Name":"NS홈쇼핑","LGCh":13,"SK Name":"NS홈쇼핑","SKCh":14,"Icon_url":"http://i.imgur.com/UD1yoj1.png","Source":"SK","ServiceId":322,"Enabled":1}, {"Id":147,"Name":"O tvN","KT Name":"O tvn","KTCh":45,"LG Name":"O tvN","LGCh":71,"SK Name":"O tvN","SKCh":34,"Icon_url":"http://i.imgur.com/0SMl3O5.png","Source":"SK","ServiceId":527,"Enabled":1}, {"Id":148,"Name":"올리브","KT Name":"올리브","KTCh":34,"LG Name":"O´live","LGCh":82,"SK Name":"올리브","SKCh":84,"Icon_url":"http://i.imgur.com/5kF0Ypt.png","Source":"SK","ServiceId":431,"Enabled":1}, {"Id":149,"Name":"OBS","KT Name":"OBS","KTCh":26,"LG Name":"OBS","LGCh":26,"SK Name":"OBS","SKCh":20,"Icon_url":"http://i.imgur.com/DJHN8M6.png","Source":"SK","ServiceId":70,"Enabled":1}, @@ -129,8 +130,8 @@ {"Id":156,"Name":"ONT","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"ONT","SKCh":245,"Icon_url":"http://i.imgur.com/2lu0ZBu.png","Source":"SK","ServiceId":256,"Enabled":1}, {"Id":157,"Name":"OUN","KT Name":"OUN","KTCh":160,"LG Name":"OUN","LGCh":170,"SK Name":"OUN","SKCh":292,"Icon_url":"http://i.imgur.com/VimbcIH.png","Source":"SK","ServiceId":220,"Enabled":1}, {"Id":158,"Name":"Outdoor","KT Name":"","KTCh":null,"LG Name":"아웃도어 채널","LGCh":135,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/4M65Rrv.png","Source":"SKY","ServiceId":544,"Enabled":1}, -{"Id":159,"Name":"Playboy TV","KT Name":"Playboy TV","KTCh":247,"LG Name":"플레이보이TV","LGCh":190,"SK Name":"플레이보이TV","SKCh":320,"Icon_url":"http://i.imgur.com/NglRqcV.png","Source":"SK","ServiceId":183,"Enabled":1}, -{"Id":160,"Name":"리얼TV","KT Name":"리얼TV","KTCh":253,"LG Name":"","LGCh":null,"SK Name":"리얼TV","SKCh":267,"Icon_url":"http://i.imgur.com/PYnXtlb.png","Source":"SK","ServiceId":440,"Enabled":1}, +{"Id":159,"Name":"Playboy TV","KT Name":"Playboy TV","KTCh":206,"LG Name":"플레이보이TV","LGCh":190,"SK Name":"플레이보이TV","SKCh":320,"Icon_url":"http://i.imgur.com/NglRqcV.png","Source":"SK","ServiceId":183,"Enabled":1}, +{"Id":160,"Name":"리얼TV","KT Name":"리얼TV","KTCh":127,"LG Name":"","LGCh":null,"SK Name":"리얼TV","SKCh":267,"Icon_url":"http://i.imgur.com/PYnXtlb.png","Source":"SK","ServiceId":440,"Enabled":1}, {"Id":164,"Name":"SBS","KT Name":"SBS","KTCh":5,"LG Name":"SBS","LGCh":5,"SK Name":"SBS","SKCh":5,"Icon_url":"http://i.imgur.com/K2ztoDT.png","Source":"SK","ServiceId":14,"Enabled":1}, {"Id":165,"Name":"SBS CNBC","KT Name":"SBS CNBC","KTCh":25,"LG Name":"SBS CNBC","LGCh":27,"SK Name":"SBS CNBC","SKCh":26,"Icon_url":"http://i.imgur.com/SfDs4qN.png","Source":"SK","ServiceId":625,"Enabled":1}, {"Id":166,"Name":"SBS funE","KT Name":"SBS funE","KTCh":43,"LG Name":"SBS funE","LGCh":75,"SK Name":"SBS fun E","SKCh":81,"Icon_url":"http://i.imgur.com/D1EYJmr.png","Source":"SK","ServiceId":882,"Enabled":1}, @@ -140,14 +141,13 @@ {"Id":170,"Name":"SBS Plus","KT Name":"SBS Plus","KTCh":37,"LG Name":"SBS 플러스","LGCh":33,"SK Name":"SBS 플러스","SKCh":2,"Icon_url":"http://i.imgur.com/asfyrTm.png","Source":"SK","ServiceId":901,"Enabled":1}, {"Id":171,"Name":"스크린","KT Name":"스크린","KTCh":106,"LG Name":"SCREEN","LGCh":41,"SK Name":"Screen","SKCh":56,"Icon_url":"http://i.imgur.com/lTK9VD4.png","Source":"SK","ServiceId":192,"Enabled":1}, {"Id":172,"Name":"SkyA&C","KT Name":"SkyA&C","KTCh":80,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/cljag6U.png","Source":"SKY","ServiceId":514,"Enabled":1}, -{"Id":173,"Name":"SkyDrama","KT Name":"SkyDrama","KTCh":30,"LG Name":"스카이드라마","LGCh":79,"SK Name":"sky Drama","SKCh":40,"Icon_url":"http://i.imgur.com/e9BTUAb.png","Source":"SK","ServiceId":871,"Enabled":1}, -{"Id":174,"Name":"SkyENT","KT Name":"SkyENT","KTCh":86,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ALqDHH6.png","Source":"SKY","ServiceId":970,"Enabled":1}, +{"Id":173,"Name":"SkyDrama","KT Name":"SkyDrama","KTCh":31,"LG Name":"스카이드라마","LGCh":79,"SK Name":"sky Drama","SKCh":40,"Icon_url":"http://i.imgur.com/e9BTUAb.png","Source":"SK","ServiceId":871,"Enabled":1}, +{"Id":174,"Name":"SkyENT","KT Name":"SkyENT","KTCh":50,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ALqDHH6.png","Source":"SKY","ServiceId":970,"Enabled":1}, {"Id":175,"Name":"Sky힐링","KT Name":"Sky힐링","KTCh":167,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/64SK0o9.png","Source":"SKY","ServiceId":40,"Enabled":1}, {"Id":176,"Name":"SkyICT","KT Name":"SkyICT","KTCh":165,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/luZjU1e.png","Source":"SKY","ServiceId":568,"Enabled":1}, {"Id":177,"Name":"SkyPetPark","KT Name":"SkyPetPark","KTCh":49,"LG Name":"","LGCh":null,"SK Name":"Sky Petpark","SKCh":94,"Icon_url":"http://i.imgur.com/RDUfvRG.png","Source":"SK","ServiceId":889,"Enabled":1}, {"Id":178,"Name":"SkySports","KT Name":"SkySports","KTCh":54,"LG Name":"스카이스포츠","LGCh":57,"SK Name":"sky Sports","SKCh":125,"Icon_url":"http://i.imgur.com/QHV9bdA.png","Source":"SK","ServiceId":282,"Enabled":1}, -{"Id":179,"Name":"SkyTravel","KT Name":"SkyTravel","KTCh":2,"LG Name":"스카이트래블","LGCh":66,"SK Name":"sky Travel","SKCh":246,"Icon_url":"http://i.imgur.com/fAJgmna.png","Source":"SK","ServiceId":283,"Enabled":1}, -{"Id":180,"Name":"UHD ONE","KT Name":"UHD ONE","KTCh":100,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/lqJZzSG.png","Source":"KT","ServiceId":100,"Enabled":1}, +{"Id":179,"Name":"SkyTravel","KT Name":"SkyTravel","KTCh":100,"LG Name":"스카이트래블","LGCh":66,"SK Name":"sky Travel","SKCh":246,"Icon_url":"http://i.imgur.com/fAJgmna.png","Source":"SK","ServiceId":283,"Enabled":1}, {"Id":181,"Name":"Sky UHD","KT Name":"Sky UHD","KTCh":174,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/BNxE2zT.png","Source":"SKY","ServiceId":500,"Enabled":1}, {"Id":182,"Name":"Smlie TV","KT Name":"Smile TV","KTCh":84,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/alk8plD.png","Source":"NAVER","ServiceId":814939,"Enabled":1}, {"Id":183,"Name":"SPOTV","KT Name":"SPOTV","KTCh":51,"LG Name":"SPOTV","LGCh":56,"SK Name":"SPOTV","SKCh":120,"Icon_url":"http://i.imgur.com/cIpIf6b.png","Source":"SK","ServiceId":125,"Enabled":1}, @@ -155,10 +155,10 @@ {"Id":185,"Name":"SPOTV+","KT Name":"SPOTV+","KTCh":125,"LG Name":"SPOTV PLUS","LGCh":51,"SK Name":"SPOTV+","SKCh":127,"Icon_url":"http://i.imgur.com/81Fshnn.png","Source":"SK","ServiceId":134,"Enabled":1}, {"Id":186,"Name":"SPOTV2","KT Name":"SPOTV2","KTCh":52,"LG Name":"SPOTV2","LGCh":52,"SK Name":"SPOTV2","SKCh":128,"Icon_url":"http://i.imgur.com/GNicmGY.png","Source":"SK","ServiceId":424,"Enabled":1}, {"Id":191,"Name":"Star Chinese Channel","KT Name":"Star Chinese Channel","KTCh":178,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/Af0Atf2.png","Source":"EPG","ServiceId":637,"Enabled":1}, -{"Id":192,"Name":"Star Sports","KT Name":"Star Sports","KTCh":60,"LG Name":"","LGCh":null,"SK Name":"Star Sports","SKCh":135,"Icon_url":"http://i.imgur.com/8ndGr4n.png","Source":"SK","ServiceId":781,"Enabled":1}, +{"Id":192,"Name":"Star Sports","KT Name":"Star Sports","KTCh":63,"LG Name":"","LGCh":null,"SK Name":"Star Sports","SKCh":135,"Icon_url":"http://i.imgur.com/8ndGr4n.png","Source":"SK","ServiceId":781,"Enabled":1}, {"Id":193,"Name":"STB상생방송","KT Name":"STB상생방송","KTCh":261,"LG Name":"상생방송","LGCh":187,"SK Name":"STB 상생방송","SKCh":308,"Icon_url":"http://i.imgur.com/Z3Xknso.png","Source":"SK","ServiceId":278,"Enabled":1}, {"Id":194,"Name":"STN","KT Name":"STN","KTCh":267,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ZJi3NQy.png","Source":"EPG","ServiceId":628,"Enabled":1}, -{"Id":195,"Name":"선댄스 채널","KT Name":"선댄스 채널","KTCh":105,"LG Name":"Sundance Channel","LGCh":43,"SK Name":"Sundance CH","SKCh":60,"Icon_url":"http://i.imgur.com/Kf9hZQN.png","Source":"SK","ServiceId":776,"Enabled":1}, +{"Id":195,"Name":"선댄스 채널","KT Name":"선댄스 채널","KTCh":105,"LG Name":"Sundance Channel","LGCh":43,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/Kf9hZQN.png","Source":"SKY","ServiceId":750,"Enabled":1}, {"Id":196,"Name":"슈퍼액션","KT Name":"슈퍼액션","KTCh":32,"LG Name":"Super Action","LGCh":40,"SK Name":"SUPER ACTION","SKCh":55,"Icon_url":"http://i.imgur.com/D9PzDBr.png","Source":"SK","ServiceId":179,"Enabled":1}, {"Id":197,"Name":"tag TV","KT Name":"tag TV","KTCh":94,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/Mmc89FS.png","Source":"KT","ServiceId":94,"Enabled":1}, {"Id":198,"Name":"tbsTV","KT Name":"tbsTV","KTCh":214,"LG Name":"tbsTV","LGCh":176,"SK Name":"tbsTV","SKCh":272,"Icon_url":"http://i.imgur.com/o3MWHfb.png","Source":"SK","ServiceId":171,"Enabled":1}, @@ -170,13 +170,13 @@ {"Id":205,"Name":"TV5MONDE","KT Name":"TV5MONDE","KTCh":198,"LG Name":"","LGCh":null,"SK Name":"TV5Monde","SKCh":279,"Icon_url":"http://i.imgur.com/NogUKpP.png","Source":"SK","ServiceId":780,"Enabled":1}, {"Id":207,"Name":"tvN","KT Name":"tvN","KTCh":17,"LG Name":"tvN","LGCh":17,"SK Name":"tvN","SKCh":17,"Icon_url":"http://i.imgur.com/OJ9A8fZ.png","Source":"SK","ServiceId":872,"Enabled":1}, {"Id":208,"Name":"TV조선","KT Name":"TV조선","KTCh":19,"LG Name":"TV조선","LGCh":19,"SK Name":"TV조선","SKCh":19,"Icon_url":"http://i.imgur.com/ShJ5joR.png","Source":"SK","ServiceId":243,"Enabled":1}, -{"Id":212,"Name":"viki","KT Name":"viki","KTCh":245,"LG Name":"VIKI","LGCh":192,"SK Name":"Viki","SKCh":322,"Icon_url":"http://i.imgur.com/ZVD51K9.png","Source":"SK","ServiceId":188,"Enabled":1}, -{"Id":213,"Name":"W 쇼핑","KT Name":"W 쇼핑","KTCh":36,"LG Name":"","LGCh":null,"SK Name":"W쇼핑","SKCh":37,"Icon_url":"http://i.imgur.com/Cged9ve.png","Source":"SK","ServiceId":342,"Enabled":1}, +{"Id":212,"Name":"viki","KT Name":"viki","KTCh":204,"LG Name":"VIKI","LGCh":192,"SK Name":"Viki","SKCh":322,"Icon_url":"http://i.imgur.com/ZVD51K9.png","Source":"SK","ServiceId":188,"Enabled":1}, +{"Id":213,"Name":"W 쇼핑","KT Name":"W 쇼핑","KTCh":40,"LG Name":"","LGCh":null,"SK Name":"W쇼핑","SKCh":37,"Icon_url":"http://i.imgur.com/Cged9ve.png","Source":"SK","ServiceId":342,"Enabled":1}, {"Id":215,"Name":"WBS원음방송","KT Name":"원음방송","KTCh":284,"LG Name":"WBS원음방송","LGCh":188,"SK Name":"원음방송","SKCh":309,"Icon_url":"http://i.imgur.com/mKWQE7z.png","Source":"SK","ServiceId":270,"Enabled":1}, {"Id":216,"Name":"XTM","KT Name":"XTM","KTCh":76,"LG Name":"XTM","LGCh":72,"SK Name":"XTM","SKCh":85,"Icon_url":"http://i.imgur.com/hGwA39y.png","Source":"SK","ServiceId":185,"Enabled":1}, {"Id":218,"Name":"YTN","KT Name":"YTN","KTCh":24,"LG Name":"YTN","LGCh":24,"SK Name":"YTN","SKCh":24,"Icon_url":"http://i.imgur.com/ByeeX5e.png","Source":"SK","ServiceId":570,"Enabled":1}, {"Id":219,"Name":"YTN 사이언스","KT Name":"YTN 사이언스","KTCh":175,"LG Name":"사이언스TV","LGCh":25,"SK Name":"YTN 사이언스","SKCh":262,"Icon_url":"http://i.imgur.com/gwDHYGf.png","Source":"SK","ServiceId":422,"Enabled":1}, -{"Id":220,"Name":"YTN life","KT Name":"YTN life","KTCh":207,"LG Name":"YTN life","LGCh":125,"SK Name":"YTN 라이프","SKCh":157,"Icon_url":"http://i.imgur.com/f66yRT9.png","Source":"SK","ServiceId":632,"Enabled":1}, +{"Id":220,"Name":"YTN life","KT Name":"YTN life","KTCh":190,"LG Name":"YTN life","LGCh":125,"SK Name":"YTN 라이프","SKCh":157,"Icon_url":"http://i.imgur.com/f66yRT9.png","Source":"SK","ServiceId":632,"Enabled":1}, {"Id":221,"Name":"가요TV","KT Name":"가요TV","KTCh":93,"LG Name":"가요TV","LGCh":102,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/6ncOOSg.png","Source":"NAVER","ServiceId":814829,"Enabled":1}, {"Id":222,"Name":"국방TV","KT Name":"국방TV","KTCh":260,"LG Name":"국방TV","LGCh":174,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yyXkYzJ.png","Source":"SKY","ServiceId":698,"Enabled":1}, {"Id":223,"Name":"국회방송","KT Name":"국회방송","KTCh":65,"LG Name":"국회방송","LGCh":172,"SK Name":"국회방송","SKCh":291,"Icon_url":"http://i.imgur.com/l1OEn7O.png","Source":"SK","ServiceId":221,"Enabled":1}, @@ -186,21 +186,21 @@ {"Id":228,"Name":"대교 어린이TV","KT Name":"대교 어린이TV","KTCh":141,"LG Name":"어린이TV","LGCh":156,"SK Name":"어린이TV","SKCh":191,"Icon_url":"http://i.imgur.com/CETWIE6.png","Source":"SK","ServiceId":374,"Enabled":1}, {"Id":229,"Name":"동아TV","KT Name":"동아TV","KTCh":82,"LG Name":"동아TV","LGCh":84,"SK Name":"동아TV","SKCh":218,"Icon_url":"http://i.imgur.com/AlmV8jS.png","Source":"SK","ServiceId":272,"Enabled":1}, {"Id":230,"Name":"드라마H","KT Name":"드라마H","KTCh":70,"LG Name":"","LGCh":null,"SK Name":"드라마H","SKCh":46,"Icon_url":"http://i.imgur.com/xT7pVuI.png","Source":"SK","ServiceId":875,"Enabled":1}, -{"Id":231,"Name":"드라마큐브","KT Name":"드라마큐브","KTCh":74,"LG Name":"","LGCh":null,"SK Name":"드라마큐브","SKCh":36,"Icon_url":"http://i.imgur.com/4ESaIH6.png","Source":"SK","ServiceId":903,"Enabled":1}, -{"Id":232,"Name":"드라맥스","KT Name":"드라맥스","KTCh":72,"LG Name":"","LGCh":null,"SK Name":"드라맥스","SKCh":38,"Icon_url":"http://i.imgur.com/jcguamX.png","Source":"SK","ServiceId":904,"Enabled":1}, +{"Id":231,"Name":"드라마큐브","KT Name":"드라마큐브","KTCh":46,"LG Name":"","LGCh":null,"SK Name":"드라마큐브","SKCh":36,"Icon_url":"http://i.imgur.com/4ESaIH6.png","Source":"SK","ServiceId":903,"Enabled":1}, +{"Id":232,"Name":"드라맥스","KT Name":"드라맥스","KTCh":47,"LG Name":"","LGCh":null,"SK Name":"드라맥스","SKCh":38,"Icon_url":"http://i.imgur.com/jcguamX.png","Source":"SK","ServiceId":904,"Enabled":1}, {"Id":233,"Name":"디원","KT Name":"디원","KTCh":115,"LG Name":"D1","LGCh":90,"SK Name":"디원","SKCh":45,"Icon_url":"http://i.imgur.com/8nE7mmk.png","Source":"SK","ServiceId":170,"Enabled":1}, {"Id":234,"Name":"디즈니주니어","KT Name":"디즈니주니어","KTCh":151,"LG Name":"디즈니 주니어","LGCh":151,"SK Name":"디즈니주니어","SKCh":172,"Icon_url":"http://i.imgur.com/EGiEKhj.png","Source":"SK","ServiceId":381,"Enabled":1}, {"Id":235,"Name":"Disney Channel","KT Name":"Disney Channel","KTCh":130,"LG Name":"디즈니 채널","LGCh":150,"SK Name":"디즈니채널","SKCh":171,"Icon_url":"http://i.imgur.com/qZdqeZo.png","Source":"SK","ServiceId":380,"Enabled":1}, {"Id":237,"Name":"롯데원티비","KT Name":"롯데원티비","KTCh":44,"LG Name":"롯데 OneTV","LGCh":21,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/vri0qlq.png","Source":"SKY","ServiceId":548,"Enabled":1}, -{"Id":238,"Name":"롯데홈쇼핑","KT Name":"롯데홈쇼핑","KTCh":12,"LG Name":"롯데홈쇼핑","LGCh":12,"SK Name":"롯데홈쇼핑","SKCh":10,"Icon_url":"http://i.imgur.com/2bCfj0y.png","Source":"SK","ServiceId":323,"Enabled":1}, +{"Id":238,"Name":"롯데홈쇼핑","KT Name":"롯데홈쇼핑","KTCh":6,"LG Name":"롯데홈쇼핑","LGCh":12,"SK Name":"롯데홈쇼핑","SKCh":10,"Icon_url":"http://i.imgur.com/2bCfj0y.png","Source":"SK","ServiceId":323,"Enabled":1}, {"Id":239,"Name":"리빙TV","KT Name":"리빙TV","KTCh":276,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/0jGCpfx.png","Source":"SKY","ServiceId":28,"Enabled":1}, {"Id":240,"Name":"마이펫TV","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"마이펫TV","SKCh":92,"Icon_url":"http://i.imgur.com/Oy7qjnW.png","Source":"SK","ServiceId":258,"Enabled":1}, {"Id":241,"Name":"매일경제TV","KT Name":"매일경제TV","KTCh":182,"LG Name":"매일경제TV","LGCh":112,"SK Name":"매일경제TV","SKCh":153,"Icon_url":"http://i.imgur.com/a4PwnPm.png","Source":"SK","ServiceId":628,"Enabled":1}, -{"Id":244,"Name":"미드나잇","KT Name":"미드나잇","KTCh":246,"LG Name":"미드나잇","LGCh":191,"SK Name":"미드나잇","SKCh":321,"Icon_url":"http://i.imgur.com/zLJHU3J.png","Source":"SK","ServiceId":184,"Enabled":1}, +{"Id":244,"Name":"미드나잇","KT Name":"미드나잇","KTCh":205,"LG Name":"미드나잇","LGCh":191,"SK Name":"미드나잇","SKCh":321,"Icon_url":"http://i.imgur.com/zLJHU3J.png","Source":"SK","ServiceId":184,"Enabled":1}, {"Id":245,"Name":"바둑TV","KT Name":"바둑TV","KTCh":120,"LG Name":"바둑TV","LGCh":97,"SK Name":"바둑TV","SKCh":240,"Icon_url":"http://i.imgur.com/jbRu8T2.png","Source":"SK","ServiceId":528,"Enabled":1}, {"Id":246,"Name":"법률방송","KT Name":"법률방송","KTCh":213,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/WJaHOAP.png","Source":"NAVER","ServiceId":815085,"Enabled":1}, {"Id":247,"Name":"복지TV","KT Name":"복지TV","KTCh":219,"LG Name":"복지TV","LGCh":173,"SK Name":"복지TV","SKCh":293,"Icon_url":"http://i.imgur.com/cTV0rnb.png","Source":"SK","ServiceId":223,"Enabled":1}, -{"Id":248,"Name":"부동산TV","KT Name":"부동산TV","KTCh":187,"LG Name":"부동산TV","LGCh":114,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/O9e2qns.png","Source":"SKY","ServiceId":125,"Enabled":1}, +{"Id":248,"Name":"부동산TV","KT Name":"부동산TV","KTCh":187,"LG Name":"부동산TV","LGCh":114,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/O9e2qns.png","Source":"NAVER","ServiceId":814908,"Enabled":1}, {"Id":249,"Name":"부동산토마토","KT Name":"부동산토마토","KTCh":188,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ePLp200.png","Source":"SK","ServiceId":620,"Enabled":1}, {"Id":250,"Name":"부메랑","KT Name":"부메랑","KTCh":139,"LG Name":"부메랑","LGCh":166,"SK Name":"부메랑","SKCh":175,"Icon_url":"http://i.imgur.com/GSPRJqf.png","Source":"SK","ServiceId":433,"Enabled":1}, {"Id":251,"Name":"브레인TV","KT Name":"브레인TV","KTCh":122,"LG Name":"브레인TV","LGCh":98,"SK Name":"브레인TV","SKCh":242,"Icon_url":"http://i.imgur.com/1422kP1.png","Source":"SK","ServiceId":279,"Enabled":1}, @@ -209,10 +209,10 @@ {"Id":255,"Name":"서울경제TV","KT Name":"서울경제TV","KTCh":184,"LG Name":"서울경제TV","LGCh":124,"SK Name":"서울경제TV","SKCh":156,"Icon_url":"http://i.imgur.com/LBzj77k.png","Source":"SK","ServiceId":629,"Enabled":1}, {"Id":256,"Name":"소비자TV","KT Name":"소비자TV","KTCh":265,"LG Name":"소비자TV","LGCh":177,"SK Name":"소비자TV","SKCh":275,"Icon_url":"http://i.imgur.com/971hUD2.png","Source":"SK","ServiceId":442,"Enabled":1}, {"Id":257,"Name":"소상공인방송","KT Name":"소상공인방송","KTCh":255,"LG Name":"소상공인방송","LGCh":175,"SK Name":"소상공인방송","SKCh":271,"Icon_url":"http://i.imgur.com/3k1D4LA.png","Source":"SK","ServiceId":428,"Enabled":1}, -{"Id":258,"Name":"쇼핑엔T","KT Name":"쇼핑엔T","KTCh":31,"LG Name":"","LGCh":null,"SK Name":"쇼핑 앤 T","SKCh":35,"Icon_url":"http://i.imgur.com/Q7FHxYB.png","Source":"SK","ServiceId":336,"Enabled":1}, -{"Id":260,"Name":"신세계쇼핑","KT Name":"신세계쇼핑","KTCh":28,"LG Name":"","LGCh":null,"SK Name":"신세계쇼핑","SKCh":22,"Icon_url":"http://i.imgur.com/ZhYaqpt.png","Source":"SK","ServiceId":339,"Enabled":1}, +{"Id":258,"Name":"쇼핑엔T","KT Name":"쇼핑엔티","KTCh":33,"LG Name":"","LGCh":null,"SK Name":"쇼핑 앤 T","SKCh":35,"Icon_url":"http://i.imgur.com/Q7FHxYB.png","Source":"SK","ServiceId":336,"Enabled":1}, +{"Id":260,"Name":"신세계쇼핑","KT Name":"신세계쇼핑","KTCh":2,"LG Name":"","LGCh":null,"SK Name":"신세계쇼핑","SKCh":22,"Icon_url":"http://i.imgur.com/ZhYaqpt.png","Source":"SK","ServiceId":339,"Enabled":1}, {"Id":262,"Name":"실버아이TV","KT Name":"실버아이TV","KTCh":266,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/xm1O8eQ.png","Source":"SKY","ServiceId":378,"Enabled":1}, -{"Id":263,"Name":"아리랑 TV","KT Name":"아리랑 TV","KTCh":206,"LG Name":"아리랑TV","LGCh":141,"SK Name":"아리랑TV","SKCh":270,"Icon_url":"http://i.imgur.com/nFWWIFP.png","Source":"SK","ServiceId":427,"Enabled":1}, +{"Id":263,"Name":"아리랑 TV","KT Name":"아리랑 TV","KTCh":200,"LG Name":"아리랑TV","LGCh":141,"SK Name":"아리랑TV","SKCh":270,"Icon_url":"http://i.imgur.com/nFWWIFP.png","Source":"SK","ServiceId":427,"Enabled":1}, {"Id":264,"Name":"아시아경제TV","KT Name":"아시아경제TV","KTCh":186,"LG Name":"아시아경제TV","LGCh":113,"SK Name":"아시아경제TV","SKCh":154,"Icon_url":"http://i.imgur.com/2D6WoS8.png","Source":"SK","ServiceId":622,"Enabled":1}, {"Id":265,"Name":"아임쇼핑","KT Name":"아임쇼핑","KTCh":22,"LG Name":"아임쇼핑","LGCh":20,"SK Name":"아임쇼핑","SKCh":3,"Icon_url":"http://i.imgur.com/E3pJ5Jz.png","Source":"SK","ServiceId":332,"Enabled":1}, {"Id":266,"Name":"애니플러스","KT Name":"애니플러스","KTCh":138,"LG Name":"애니플러스","LGCh":149,"SK Name":"애니플러스","SKCh":178,"Icon_url":"http://i.imgur.com/7RKoOZq.png","Source":"SK","ServiceId":377,"Enabled":1}, @@ -226,31 +226,31 @@ {"Id":279,"Name":"JJC지방자치TV","KT Name":"JJC지방자치TV","KTCh":279,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/AuXr9jA.png","Source":"NAVER","ServiceId":3244879,"Enabled":1}, {"Id":280,"Name":"채널 Ching","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"채널 Ching","SKCh":105,"Icon_url":"http://i.imgur.com/tRqGKcS.png","Source":"SK","ServiceId":907,"Enabled":1}, {"Id":281,"Name":"채널A","KT Name":"채널A","KTCh":18,"LG Name":"채널A","LGCh":18,"SK Name":"채널A","SKCh":18,"Icon_url":"http://i.imgur.com/xti35f5.png","Source":"SK","ServiceId":242,"Enabled":1}, -{"Id":282,"Name":"채널A 플러스","KT Name":"채널A 플러스","KTCh":268,"LG Name":"채널A플러스","LGCh":115,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/rRisTh8.png","Source":"EPG","ServiceId":627,"Enabled":1}, +{"Id":282,"Name":"채널A 플러스","KT Name":"채널A 플러스","KTCh":98,"LG Name":"채널A플러스","LGCh":115,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/rRisTh8.png","Source":"EPG","ServiceId":627,"Enabled":1}, {"Id":283,"Name":"채널CGV","KT Name":"채널CGV","KTCh":29,"LG Name":"CH CGV","LGCh":39,"SK Name":"Ch CGV","SKCh":53,"Icon_url":"http://i.imgur.com/fwjRwkx.png","Source":"SK","ServiceId":187,"Enabled":1}, {"Id":284,"Name":"채널i","KT Name":"채널i","KTCh":250,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/X7lXvtw.png","Source":"NAVER","ServiceId":3173174,"Enabled":1}, {"Id":285,"Name":"채널뷰","KT Name":"채널뷰","KTCh":176,"LG Name":"","LGCh":null,"SK Name":"채널View","SKCh":212,"Icon_url":"http://i.imgur.com/lvtWgFL.png","Source":"SK","ServiceId":276,"Enabled":1}, -{"Id":286,"Name":"채널차이나","KT Name":"채널차이나","KTCh":79,"LG Name":"채널차이나","LGCh":80,"SK Name":"채널차이나","SKCh":108,"Icon_url":"http://i.imgur.com/jEyoLS1.png","Source":"SK","ServiceId":520,"Enabled":1}, +{"Id":286,"Name":"채널차이나","KT Name":"채널차이나","KTCh":102,"LG Name":"채널차이나","LGCh":80,"SK Name":"채널차이나","SKCh":108,"Icon_url":"http://i.imgur.com/jEyoLS1.png","Source":"SK","ServiceId":520,"Enabled":1}, {"Id":287,"Name":"채널해피독","KT Name":"채널해피독","KTCh":203,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ly649tS.png","Source":"NAVER","ServiceId":2296260,"Enabled":1}, {"Id":289,"Name":"카툰네트워크","KT Name":"카툰네트워크","KTCh":137,"LG Name":"카툰네트워크","LGCh":155,"SK Name":"카툰네트워크","SKCh":177,"Icon_url":"http://i.imgur.com/cJZHPjr.png","Source":"SK","ServiceId":384,"Enabled":1}, {"Id":290,"Name":"캐치온1","KT Name":"캐치온1","KTCh":66,"LG Name":"캐치온1","LGCh":48,"SK Name":"CATCH ON 1","SKCh":51,"Icon_url":"http://i.imgur.com/qK9KkRd.png","Source":"SK","ServiceId":181,"Enabled":1}, {"Id":291,"Name":"캐치온2","KT Name":"캐치온2","KTCh":67,"LG Name":"캐치온2","LGCh":49,"SK Name":"CATCH ON 2","SKCh":52,"Icon_url":"http://i.imgur.com/sLc2req.png","Source":"SK","ServiceId":182,"Enabled":1}, -{"Id":292,"Name":"캠퍼스TV","KT Name":"캠퍼스TV","KTCh":270,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/XLA5bhf.png","Source":"EPG","ServiceId":645,"Enabled":1}, +{"Id":292,"Name":"브릿지TV","KT Name":"브릿지TV","KTCh":270,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/KATTup7.png","Source":"EPG","ServiceId":645,"Enabled":1}, {"Id":293,"Name":"코미디TV","KT Name":"코미디TV","KTCh":85,"LG Name":"","LGCh":null,"SK Name":"코미디TV","SKCh":87,"Icon_url":"http://i.imgur.com/DHbUoDm.png","Source":"SK","ServiceId":906,"Enabled":1}, {"Id":294,"Name":"쿠키건강TV","KT Name":"쿠키건강TV","KTCh":220,"LG Name":"쿠키건강TV","LGCh":144,"SK Name":"쿠키건강TV","SKCh":269,"Icon_url":"http://i.imgur.com/4gl92D1.png","Source":"SK","ServiceId":434,"Enabled":1}, {"Id":296,"Name":"키즈원","KT Name":"키즈원","KTCh":148,"LG Name":"키즈원","LGCh":157,"SK Name":"KIDS1","SKCh":193,"Icon_url":"http://i.imgur.com/f8T1Sw4.png","Source":"SK","ServiceId":370,"Enabled":1}, {"Id":297,"Name":"토마토TV","KT Name":"토마토TV","KTCh":185,"LG Name":"토마토TV","LGCh":111,"SK Name":"토마토TV","SKCh":150,"Icon_url":"http://i.imgur.com/dVWy3Ex.png","Source":"SK","ServiceId":620,"Enabled":1}, -{"Id":299,"Name":"펜트하우스tv","KT Name":"펜트하우스tv","KTCh":249,"LG Name":"","LGCh":null,"SK Name":"펜트하우스TV","SKCh":324,"Icon_url":"http://i.imgur.com/03U2Ges.png","Source":"SK","ServiceId":190,"Enabled":1}, -{"Id":301,"Name":"가톨릭평화방송","KT Name":"가톨릭평화방송","KTCh":231,"LG Name":"가톨릭평화방송","LGCh":184,"SK Name":"가톨릭평화방송","SKCh":307,"Icon_url":"http://i.imgur.com/TYLAZ0S.png","Source":"SK","ServiceId":724,"Enabled":1}, +{"Id":299,"Name":"펜트하우스tv","KT Name":"펜트하우스tv","KTCh":208,"LG Name":"","LGCh":null,"SK Name":"펜트하우스TV","SKCh":324,"Icon_url":"http://i.imgur.com/03U2Ges.png","Source":"SK","ServiceId":190,"Enabled":1}, +{"Id":301,"Name":"가톨릭평화방송","KT Name":"가톨릭평화방송","KTCh":231,"LG Name":"가톨릭평화방송","LGCh":184,"SK Name":"가톨릭평화방송","SKCh":307,"Icon_url":"http://i.imgur.com/G5fTCL3.png","Source":"SK","ServiceId":724,"Enabled":1}, {"Id":302,"Name":"폴라리스TV","KT Name":"폴라리스TV","KTCh":129,"LG Name":"폴라리스 TV","LGCh":67,"SK Name":"폴라리스TV","SKCh":249,"Icon_url":"http://i.imgur.com/aghufJ7.png","Source":"SK","ServiceId":252,"Enabled":1}, {"Id":303,"Name":"한국경제TV","KT Name":"한국경제TV","KTCh":180,"LG Name":"한국경제TV","LGCh":121,"SK Name":"한국경제TV","SKCh":151,"Icon_url":"http://i.imgur.com/ChnD0FT.png","Source":"SK","ServiceId":626,"Enabled":1}, {"Id":305,"Name":"한국승마방송","KT Name":"한국승마방송","KTCh":259,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/VZdQLwj.png","Source":"NAVER","ServiceId":814904,"Enabled":1}, {"Id":307,"Name":"한국직업방송","KT Name":"한국직업방송","KTCh":252,"LG Name":"","LGCh":null,"SK Name":"한국직업방송","SKCh":273,"Icon_url":"http://i.imgur.com/WUvf0If.png","Source":"SK","ServiceId":429,"Enabled":1}, -{"Id":309,"Name":"허니TV","KT Name":"허니TV","KTCh":248,"LG Name":"허니TV","LGCh":193,"SK Name":"허니TV","SKCh":323,"Icon_url":"http://i.imgur.com/KczRCLW.png","Source":"SK","ServiceId":196,"Enabled":1}, +{"Id":309,"Name":"허니TV","KT Name":"허니TV","KTCh":207,"LG Name":"허니TV","LGCh":193,"SK Name":"허니TV","SKCh":323,"Icon_url":"http://i.imgur.com/KczRCLW.png","Source":"SK","ServiceId":196,"Enabled":1}, {"Id":310,"Name":"헝그리앱TV","KT Name":"헝그리앱TV","KTCh":269,"LG Name":"","LGCh":null,"SK Name":"헝그리앱TV","SKCh":138,"Icon_url":"http://i.imgur.com/5Q7JZeM.png","Source":"SK","ServiceId":257,"Enabled":1}, {"Id":311,"Name":"헬스메디tv","KT Name":"헬스메디tv","KTCh":271,"LG Name":"헬스메디TV","LGCh":138,"SK Name":"헬스메디TV","SKCh":268,"Icon_url":"http://i.imgur.com/vsxRuFh.png","Source":"SK","ServiceId":432,"Enabled":1}, {"Id":312,"Name":"현대홈쇼핑","KT Name":"현대홈쇼핑","KTCh":10,"LG Name":"현대홈쇼핑","LGCh":10,"SK Name":"현대홈쇼핑","SKCh":8,"Icon_url":"http://i.imgur.com/87fdrA5.png","Source":"SK","ServiceId":321,"Enabled":1}, -{"Id":313,"Name":"현대홈쇼핑+샵","KT Name":"현대홈쇼핑+샵","KTCh":33,"LG Name":"현대홈쇼핑 플러스샵","LGCh":34,"SK Name":"현대홈쇼핑+Shop","SKCh":31,"Icon_url":"http://i.imgur.com/COo8Bcm.png","Source":"SK","ServiceId":337,"Enabled":1}, +{"Id":313,"Name":"현대홈쇼핑+샵","KT Name":"현대홈쇼핑+샵","KTCh":36,"LG Name":"현대홈쇼핑 플러스샵","LGCh":34,"SK Name":"현대홈쇼핑+Shop","SKCh":31,"Icon_url":"http://i.imgur.com/COo8Bcm.png","Source":"SK","ServiceId":337,"Enabled":1}, {"Id":314,"Name":"홈&쇼핑","KT Name":"홈&쇼핑","KTCh":14,"LG Name":"홈&쇼핑","LGCh":4,"SK Name":"홈&쇼핑","SKCh":4,"Icon_url":"http://i.imgur.com/nLxw0LW.png","Source":"SK","ServiceId":327,"Enabled":1}, {"Id":315,"Name":"환경TV","KT Name":"환경TV","KTCh":166,"LG Name":"","LGCh":null,"SK Name":"환경TV","SKCh":276,"Icon_url":"http://i.imgur.com/eITOr2Y.png","Source":"SK","ServiceId":443,"Enabled":1}, {"Id":316,"Name":"Life N","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"Life N","SKCh":215,"Icon_url":"http://i.imgur.com/qNde2j7.png","Source":"SK","ServiceId":277,"Enabled":1}, @@ -305,10 +305,38 @@ {"Id":406,"Name":"충주 MBC","KT Name":"충주 MBC","KTCh":11,"LG Name":"충주 MBC","LGCh":11,"SK Name":"충주 MBC","SKCh":11,"Icon_url":"http://i.imgur.com/duig32i.png","Source":"SK","ServiceId":46,"Enabled":0}, {"Id":407,"Name":"포항 KBS1","KT Name":"포항 KBS1","KTCh":9,"LG Name":"포항 KBS1","LGCh":9,"SK Name":"포항 KBS1","SKCh":9,"Icon_url":"http://i.imgur.com/e31o5gw.png","Source":"SK","ServiceId":47,"Enabled":0}, {"Id":408,"Name":"포항 MBC","KT Name":"포항 MBC","KTCh":11,"LG Name":"포항 MBC","LGCh":11,"SK Name":"포항 MBC","SKCh":11,"Icon_url":"http://i.imgur.com/duig32i.png","Source":"SK","ServiceId":48,"Enabled":0}, -{"Id":409,"Name":"DIA TV","KT Name":"DIA TV","KTCh":102,"LG Name":"DIA TV","LGCh":93,"SK Name":"DIA TV","SKCh":96,"Icon_url":"http://i.imgur.com/BH3DnrW.png","Source":"SK","ServiceId":180,"Enabled":1}, +{"Id":409,"Name":"DIA TV","KT Name":"DIA TV","KTCh":72,"LG Name":"DIA TV","LGCh":93,"SK Name":"DIA TV","SKCh":96,"Icon_url":"http://i.imgur.com/BH3DnrW.png","Source":"SK","ServiceId":180,"Enabled":1}, {"Id":410,"Name":"메디컬TV","KT Name":"메디컬TV","KTCh":254,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/S73ArUy.png","Source":"KT","ServiceId":254,"Enabled":1}, {"Id":411,"Name":"CGTN","KT Name":"CGTN","KTCh":194,"LG Name":"CGTN","LGCh":119,"SK Name":"CGTN","SKCh":161,"Icon_url":"http://i.imgur.com/rhZf4Zx.png","Source":"SK","ServiceId":771,"Enabled":1}, {"Id":412,"Name":"C Music TV","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"C Music TV","SKCh":237,"Icon_url":"http://i.imgur.com/hV270KM.png","Source":"SK","ServiceId":672,"Enabled":1}, {"Id":413,"Name":"Tvis","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"Tvis","SKCh":250,"Icon_url":"http://i.imgur.com/7jq2VMs.png","Source":"SK","ServiceId":260,"Enabled":1}, {"Id":414,"Name":"SPOTV ON","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"SPOTV ON","SKCh":118,"Icon_url":"http://i.imgur.com/Y3eYOc2.png","Source":"SK","ServiceId":136,"Enabled":1}, -{"Id":415,"Name":"SPOTV ON2","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"SPOTV ON2","SKCh":119,"Icon_url":"http://i.imgur.com/jbdurz4.png","Source":"SK","ServiceId":137,"Enabled":1}] +{"Id":415,"Name":"SPOTV ON2","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"SPOTV ON2","SKCh":119,"Icon_url":"http://i.imgur.com/jbdurz4.png","Source":"SK","ServiceId":137,"Enabled":1}, +{"Id":416,"Name":"한국선거방송","KT Name":"한국선거방송","KTCh":273,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ZSdcknl.png","Source":"KT","ServiceId":273,"Enabled":1}, +{"Id":417,"Name":"EBS 교육방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/eEsZJop.png","Source":"NAVER","ServiceId":815452,"Enabled":1}, +{"Id":418,"Name":"KBS 1 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ikJ7QQn.png","Source":"NAVER","ServiceId":815455,"Enabled":1}, +{"Id":419,"Name":"KBS 2 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/qTrmNld.png","Source":"NAVER","ServiceId":815458,"Enabled":1}, +{"Id":420,"Name":"KBS 3 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/3tHl7QR.png","Source":"NAVER","ServiceId":815460,"Enabled":1}, +{"Id":421,"Name":"KBS ClassicFM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/Z46a05G.png","Source":"NAVER","ServiceId":815454,"Enabled":1}, +{"Id":422,"Name":"KBS CoolFM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/0SQrpHZ.png","Source":"NAVER","ServiceId":815457,"Enabled":1}, +{"Id":423,"Name":"KBS WorldRaido","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ns1k6LN.png","Source":"NAVER","ServiceId":815447,"Enabled":1}, +{"Id":424,"Name":"KBS 한민족방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/S5YVPyx.png","Source":"NAVER","ServiceId":815461,"Enabled":1}, +{"Id":425,"Name":"MBC 표준FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/E9OMdnO.png","Source":"NAVER","ServiceId":815464,"Enabled":1}, +{"Id":426,"Name":"MBC FM4U","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/csdszZD.png","Source":"NAVER","ServiceId":815463,"Enabled":1}, +{"Id":427,"Name":"MBC Channel M","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/jlKGpWs.png","Source":"MBC","ServiceId":1,"Enabled":1}, +{"Id":428,"Name":"SBS 파워 FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/7qcJ4bm.png","Source":"NAVER","ServiceId":815467,"Enabled":1}, +{"Id":429,"Name":"SBS 러브 FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/XHHHUZ1.png","Source":"NAVER","ServiceId":815465,"Enabled":1}, +{"Id":430,"Name":"국악방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/qpbhUhF.png","Source":"NAVER","ServiceId":2891853,"Enabled":1}, +{"Id":431,"Name":"극동방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/PlqBFtV.png","Source":"NAVER","ServiceId":2074616,"Enabled":1}, +{"Id":432,"Name":"BBS 불교방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/B34jpmo.png","Source":"NAVER","ServiceId":815448,"Enabled":1}, +{"Id":433,"Name":"CBS 표준FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yBNo2mS.png","Source":"NAVER","ServiceId":815451,"Enabled":1}, +{"Id":434,"Name":"CBS 음악FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yBNo2mS.png","Source":"NAVER","ServiceId":815449,"Enabled":1}, +{"Id":435,"Name":"KFM 경기방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/8hSikAY.png","Source":"NAVER","ServiceId":1974893,"Enabled":1}, +{"Id":436,"Name":"PBC 평화방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/G5fTCL3.png","Source":"NAVER","ServiceId":1974894,"Enabled":1}, +{"Id":437,"Name":"TBS 교통방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/9RxxTSi.png","Source":"NAVER","ServiceId":815468,"Enabled":1}, +{"Id":438,"Name":"YTN NEWS FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/dSC3YPR.png","Source":"NAVER","ServiceId":2074615,"Enabled":1}, +{"Id":439,"Name":"원음방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/mKWQE7z.png","Source":"NAVER","ServiceId":5534687,"Enabled":1}, +{"Id":440,"Name":"국방FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/zjvlIIp.png","Source":"MIL","ServiceId":2,"Enabled":1}, +{"Id":441,"Name":"경인방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/zBTPTRe.png","Source":"IFM","ServiceId":3,"Enabled":1}, +{"Id":442,"Name":"AMC","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"AMC","SKCh":100,"Icon_url":"http://i.imgur.com/cJ1B77S.png","Source":"SK","ServiceId":199,"Enabled":1} +] From b4d051f5a42576eac206621d594874510aed4bab Mon Sep 17 00:00:00 2001 From: wonipapa Date: Wed, 19 Apr 2017 12:43:51 +0900 Subject: [PATCH 32/51] =?UTF-8?q?=EB=9D=BC=EB=94=94=EC=98=A4=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=20epg=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80,=20ph?= =?UTF-8?q?p=207.0=20=ED=98=B8=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epg2xml.php | 323 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 291 insertions(+), 32 deletions(-) diff --git a/epg2xml.php b/epg2xml.php index 1489860..7230084 100644 --- a/epg2xml.php +++ b/epg2xml.php @@ -1,7 +1,7 @@ #!/usr/bin/env php \n"); } +// Get EPG data from epg.co.kr function GetEPGFromEPG($ChannelInfo) { $ChannelId = $ChannelInfo[0]; $ChannelName = $ChannelInfo[1]; @@ -454,6 +465,8 @@ function GetEPGFromEPG($ChannelInfo) { } endforeach; } + +// Get EPG data from KT function GetEPGFromKT($ChannelInfo) { $ChannelId = $ChannelInfo[0]; $ChannelName = $ChannelInfo[1]; @@ -538,6 +551,8 @@ function GetEPGFromKT($ChannelInfo) { } endforeach; } + +// Get EPG data from LG function GetEPGFromLG($ChannelInfo) { $ChannelId = $ChannelInfo[0]; $ChannelName = $ChannelInfo[1]; @@ -618,6 +633,8 @@ function GetEPGFromLG($ChannelInfo) { } endforeach; } + +// Get EPG data from SK function GetEPGFromSK($ChannelInfo) { $ChannelId = $ChannelInfo[0]; $ChannelName = $ChannelInfo[1]; @@ -665,15 +682,9 @@ function GetEPGFromSK($ChannelInfo) { endif; $startTime = date("YmdHis",$program['startTime']/1000); $endTime = date("YmdHis",$program['endTime']/1000); - if ($GLOBALS['addverbose'] == "y") : - $desc = $program['synopsis'] ?: ""; - $actors =trim(str_replace('...','',$program['actorName']), ', ') ?: ""; - $producers = trim(str_replace('...','',$program['directorName']), ', ') ?: ""; - else : - $desc = ""; - $actors = ""; - $producers = ""; - endif; + $desc = $program['synopsis'] ?: ""; + $actors =trim(str_replace('...','',$program['actorName']), ', ') ?: ""; + $producers = trim(str_replace('...','',$program['directorName']), ', ') ?: ""; if ($program['mainGenreName'] != NULL) : $category = $program['mainGenreName']; else: @@ -706,6 +717,7 @@ function GetEPGFromSK($ChannelInfo) { } } +// Get EPG data from SKY function GetEPGFromSKY($ChannelInfo) { $ChannelId = $ChannelInfo[0]; $ChannelName = $ChannelInfo[1]; @@ -727,7 +739,6 @@ function GetEPGFromSKY($ChannelInfo) { ); $params = http_build_query($params); $url = $url."?".$params; - try { $response = @file_get_contents($url, False, $context); if ($response === False) : @@ -744,22 +755,16 @@ function GetEPGFromSKY($ChannelInfo) { $programs = $data['scheduleListIn']; foreach($programs as $program) : $programName = htmlspecialchars_decode($program['program_name']) ?: ""; - $subprogramName = str_replace(array('amp;'), array('&'),$program['program_subname']) ?: ""; + $subprogramName = str_replace(array('lt;', 'gt;', 'amp;'), array('<', '>', '&'),$program['program_subname']) ?: ""; $startTime = $program['starttime']; $endTime = $program['endtime']; - if ($GLOBALS['addverbose'] == "y") : - $actors = trim(str_replace('...', '',$program['cast']), ', ') ?: ""; - $producers = trim(str_replace('...', '',$program['dirt']), ', ') ?: ""; - $description = str_replace(array('lt;', 'gt;', 'amp;'), array('<', '>', '&'),$program['description']) ?: ""; - $summary = str_replace(array('lt;', 'gt;', 'amp;'), array('<', '>', '&'),$program['summary']) ?: ""; - $desc = $description ?: ""; - if($summary) : - $desc = $desc."\n".$summary; - endif; - else: - $desc = ""; - $actors = ""; - $producers = ""; + $actors = trim(str_replace('...', '',$program['cast']), ', ') ?: ""; + $producers = trim(str_replace('...', '',$program['dirt']), ', ') ?: ""; + $description = str_replace(array('lt;', 'gt;', 'amp;'), array('<', '>', '&'),$program['description']) ?: ""; + $summary = str_replace(array('lt;', 'gt;', 'amp;'), array('<', '>', '&'),$program['summary']) ?: ""; + $desc = $description ?: ""; + if($summary) : + $desc = $desc."\n".$summary; endif; $category = $program['program_category1']; $episode = $program['episode_id'] ?: ""; @@ -791,6 +796,8 @@ function GetEPGFromSKY($ChannelInfo) { } endforeach; } + +// Get EPG data from Naver function GetEPGFromNaver($ChannelInfo) { $ChannelId = $ChannelInfo[0]; $ChannelName = $ChannelInfo[1]; @@ -820,7 +827,6 @@ function GetEPGFromNaver($ChannelInfo) { 'u8' => $ChannelName."편성표", 'where' => 'nexearch' ); - $params = http_build_query($params); $url = $url."?".$params; try { @@ -886,6 +892,259 @@ function GetEPGFromNaver($ChannelInfo) { if($GLOBALS['debug']) printError($e->getMessage()); } } + +// Get EPG data from Tbroad +function GetEPGFromTbroad($ChannelInfo) { + $url='https://www.tbroad.com/chplan/selectRealTimeListForNormal.tb'; +} + +// Get EPG data from Iscs +function GetEPGFromIscs($ChannelInfo) { + $url='http://service.iscs.co.kr/sub/channel_view.asp'; + $params = array( + 'chan_idx'=>'242', + 'source_id'=>'203', + 'Chan_Date'=>'2017-04-18' + ); +} + +// Get EPG data from MBC +function GetEPGFromMbc($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + $dayofweek = array('일', '월', '화', '수', '목', '금', '토'); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://miniunit.imbc.com/Schedule"; + $day = date("Y-m-d", strtotime("+".($k - 1)." days")); + $params = array( + 'rtype' => 'json' + ); + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + try { + $data = json_decode($response, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); + if(count($data['Programs']) == 0) : + if($GLOBALS['debug']) : + printError($ChannelName.CHANNEL_ERROR); + endif; + else : + $programs = $data['Programs']; + foreach($programs as $program) : + if($program['Channel'] == "CHAM" && $program['LiveDays'] == $dayofweek[date("w", strtotime($day))]) : + $programName = ""; + $rebroadcast = False; + preg_match('/^(.*?)(\(재\))?$/', htmlspecialchars_decode($program['ProgramTitle']), $matches); + if ($matches != NULL) : + $programName = $matches[1]; + $rebroadcast = $matches[2] ? True : False; + endif; + $subprogramName = ""; + $startTime = $day." ".$program['StartTime']; + $startTime = date("YmdHis", strtotime($startTime)); + $endTime = date("YmdHis", strtotime("+".$program['RunningTime']." minutes", strtotime($startTime))); + $desc = ""; + $actors = ""; + $producers = ""; + $category = "음악"; + $episode = ""; + $rating = 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endif; + + endforeach; + endif; + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endforeach; +} + +// Get EPG data from MIL +function GetEPGFromMil($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://radio.dema.mil.kr/web/fm/quick/ajaxTimetableList.do"; + $day = date("Y-m-d", strtotime("+".($k - 1)." days")); + $params = array( + 'program_date' => date("Ymd", strtotime($day)) + ); + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + try { + $data = json_decode($response, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); + if(count($data['resultList']) == 0) : + if($GLOBALS['debug']) : + printError($ChannelName.CHANNEL_ERROR); + endif; + else : + $programs = $data['resultList']; + foreach($programs as $program) : + $programName = ""; + $rebroadcast = False; + preg_match('/^(.*?)(\(재\))?$/', htmlspecialchars_decode($program['program_title']), $matches); + if ($matches != NULL) : + $programName = $matches[1]; + $rebroadcast = $matches[2] ? True : False; + endif; + $subprogramName = htmlspecialchars_decode($program['program_subtitle']); + $startTime = $day." ".$program['program_time']; + $startTime = date("YmdHis", strtotime($startTime)); + $endTime = $day." ".$program['program_end_time']; + $endTime = date("YmdHis", strtotime($endTime)); + $desc = ""; + $actors = htmlspecialchars_decode($program['movie_actor']); + $producers = htmlspecialchars_decode($program['movie_director']); + $category = ""; + $episode = ""; + $rating = 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endforeach; +} + +// Get EPG data from IFM +function GetEPGFromIfm($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + $dayofweek = array('1', '2', '3', '4', '5', '6', '7'); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://mapp.itvfm.co.kr/hyb/front/selectHybPgmList.do"; + $day = date("Y-m-d", strtotime("+".($k - 1)." days")); + $params = array( + 'outDay' => $dayofweek[(date("w", strtotime($day)+1))%7], + 'viewDt' => $day + ); + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False) : + printError($ChannelName.HTTP_ERROR); + else : + try { + $data = json_decode($response, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); + if(count($data['hybMusicInfoList']) == 0) : + if($GLOBALS['debug']) : + printError($ChannelName.CHANNEL_ERROR); + endif; + else : + $programs = $data['hybMusicInfoList']; + foreach($programs as $program) : + $programName = htmlspecialchars_decode($program['pgmTitle']) ?: ""; + $subprogramName = ""; + $startTime = $day." ".$program['pgmStime']; + $startTime = date("YmdHis", strtotime($startTime)); + $endTime = $day." ".$program['pgmEtime']; + $endTime = date("YmdHis", strtotime($endTime)); + $desc = ""; + $actors = htmlspecialchars_decode($program['pgmDj']); + $producers = htmlspecialchars_decode($program['pgmPd']); + $category = ""; + $episode = ""; + $rebroadcast = False; + $rating = 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; + endif; + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endforeach; +} + function writeProgram($programdata) { $fp = $GLOBALS['fp']; $ChannelId = $programdata['channelId']; @@ -949,13 +1208,13 @@ function writeProgram($programdata) { if($actors || $producers): fprintf($fp, " \n"); if($actors) : - foreach(split(',', $actors) as $actor): - if($actor) fprintf($fp, " %s\n", $actor); + foreach(explode(',', $actors) as $actor): + if(trim($actor)) fprintf($fp, " %s\n", trim($actor)); endforeach; endif; if($producers) : - foreach(split(',', $producers) as $producer): - if($producer) fprintf($fp, " %s\n", $producer); + foreach(explode(',', $producers) as $producer): + if(trim($producer)) fprintf($fp, " %s\n", trim($producer)); endforeach; endif; fprintf($fp, " \n"); From da5c1a756cd8f38cba2e540877b002e5c6d8273a Mon Sep 17 00:00:00 2001 From: wonipapa Date: Wed, 19 Apr 2017 12:44:18 +0900 Subject: [PATCH 33/51] =?UTF-8?q?=EB=9D=BC=EB=94=94=EC=98=A4=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=20epg=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epg2xml.py | 211 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 178 insertions(+), 33 deletions(-) diff --git a/epg2xml.py b/epg2xml.py index cdf7fd0..c17f415 100644 --- a/epg2xml.py +++ b/epg2xml.py @@ -6,6 +6,7 @@ import os import sys import requests import json +import locale import datetime from bs4 import BeautifulSoup, SoupStrainer import codecs @@ -14,10 +15,11 @@ import re from xml.sax.saxutils import escape, unescape import argparse import pprint + reload(sys) sys.setdefaultencoding('utf-8') -__version__ = '1.1.6' +__version__ = '1.1.7' # Set variable debug = False @@ -43,7 +45,6 @@ def getEpg(): except ValueError: printError("Channel." + JSON_SYNTAX_ERROR) sys.exit() - print('') print('\n') print('') @@ -89,6 +90,16 @@ def getEpg(): GetEPGFromSKY(ChannelInfo) elif ChannelSource == 'NAVER': GetEPGFromNaver(ChannelInfo) + elif ChannelSource == 'TBROAD': + GetEPGFromTbroad(ChannelInfo) + elif ChannelSource == 'ISCS': + GetEPGFromIscs(ChannelInfo) + elif ChannelSource == 'MBC': + GetEPGFromMbc(ChannelInfo) + elif ChannelSource == 'MIL': + GetEPGFromMil(ChannelInfo) + elif ChannelSource == 'IFM': + GetEPGFromIfm(ChannelInfo) print('') # Get EPG data from epg.co.kr @@ -109,7 +120,6 @@ def GetEPGFromEPG(ChannelInfo): strainer = SoupStrainer('table', {'style':'margin-bottom:30'}) soup = BeautifulSoup(data, 'lxml', parse_only=strainer, from_encoding='utf-8') tables = soup.find_all('table', {'style':'margin-bottom:30'}) - for i in range(1,4): thisday = day row = tables[i].find_all('td', {'colspan':'2'}) @@ -137,7 +147,6 @@ def GetEPGFromEPG(ChannelInfo): subprogramName = matches.group(4).strip() if matches.group(4) else '' #programName, startTime, rating, subprogramName, rebroadcast, episode epginfo.append([programName, startTime, rating, subprogramName, matches.group(5), matches.group(7)]) - for epg1, epg2 in zip(epginfo, epginfo[1:]): programName = epg1[0] if epg1[0] else '' subprogramName = epg1[3] if epg1[3] else '' @@ -161,7 +170,6 @@ def GetEPGFromKT(ChannelInfo): ChannelId = ChannelInfo[0] ChannelName = ChannelInfo[1] ServiceId = ChannelInfo[3] - url = 'http://tv.olleh.com/renewal_sub/liveTv/pop_schedule_week.asp' for k in range(period): day = today + datetime.timedelta(days=k) @@ -213,7 +221,6 @@ def GetEPGFromLG(ChannelInfo): ChannelId = ChannelInfo[0] ChannelName = ChannelInfo[1] ServiceId = ChannelInfo[3] - url = 'http://www.uplus.co.kr/css/chgi/chgi/RetrieveTvSchedule.hpi' for k in range(period): day = today + datetime.timedelta(days=k) @@ -234,7 +241,6 @@ def GetEPGFromLG(ChannelInfo): rating = 0 if cell[1].find('span', {'class': 'tag cte_all'}).text.strip()=="All" else int(cell[1].find('span', {'class': 'tag cte_all'}).text.strip()) cell[1].find('span', {'class': 'tagGroup'}).decompose() epginfo.append([cell[1].text.strip(), str(day) + ' ' + cell[0].text, cell[2].text.strip(), rating]) - #cell[1].find('img', alt=True)['alt'].strip()]) for epg1, epg2 in zip(epginfo, epginfo[1:]): programName = '' subprogramName = '' @@ -298,14 +304,9 @@ def GetEPGFromSK(ChannelInfo): startTime = startTime.strftime('%Y%m%d%H%M%S') endTime = datetime.datetime.fromtimestamp(int(program['endTime'])/1000) endTime = endTime.strftime('%Y%m%d%H%M%S') - if addverbose=='y' : - desc = program['synopsis'] if program['synopsis'] else '' - actors = program['actorName'].replace('...','').strip(', ') if program['actorName'] else '' - producers = program['directorName'].replace('...','').strip(', ') if program['directorName'] else '' - else: - desc = '' - actors = '' - producers = '' + desc = program['synopsis'] if program['synopsis'] else '' + actors = program['actorName'].replace('...','').strip(', ') if program['actorName'] else '' + producers = program['directorName'].replace('...','').strip(', ') if program['directorName'] else '' if not (program['mainGenreName'] is None) : category = program['mainGenreName'] else: @@ -345,21 +346,16 @@ def GetEPGFromSKY(ChannelInfo): subprogramName = unescape(program['program_subname']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['program_subname'] else '' startTime = program['starttime'] endTime = program['endtime'] - if addverbose == 'y': - actors = program['cast'].replace('...','').strip(', ') if program['cast'] else '' - producers = program['dirt'].replace('...','').strip(', ') if program['dirt'] else '' - description = unescape(program['description']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['description'] else '' - summary = unescape(program['summary']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['summary'] else '' - desc = description if description else '' - if summary : desc = desc + '\n' + summary - else: - desc = '' - actors = '' - producers = '' + actors = program['cast'].replace('...','').strip(', ') if program['cast'] else '' + producers = program['dirt'].replace('...','').strip(', ') if program['dirt'] else '' + description = unescape(program['description']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['description'] else '' + summary = unescape(program['summary']).replace('lt;','<').replace('gt;','>').replace('amp;','&') if program['summary'] else '' + desc = description if description else '' + if summary : desc = desc + '\n' + summary category = program['program_category1'] episode = program['episode_id'] if program['episode_id'] else '' if episode : episode = int(episode) - rebroadcast = True if program['rebroad']== 'Y' else False + rebroadcast = True if program['rebroad']== 'Y' else False rating = int(program['grade']) if program['grade'] else 0 programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} writeProgram(programdata) @@ -381,9 +377,7 @@ def GetEPGFromNaver(ChannelInfo): for k in range(period): day = today + datetime.timedelta(days=k) totaldate.append(day.strftime('%Y%m%d')) - params = {'_callback': 'epg', 'fileKey': 'single_schedule_channel_day', 'pkid': '66', 'u1': 'single_schedule_channel_day', 'u2': ','.join(totaldate), 'u3': today.strftime('%Y%m%d'), 'u4': period, 'u5': ServiceId, 'u6': '1', 'u7': ChannelName + '편성표', 'u8': ChannelName + '편성표', 'where': 'nexearch'} - try: response = requests.get(url, params=params, headers=ua) response.raise_for_status() @@ -394,7 +388,6 @@ def GetEPGFromNaver(ChannelInfo): for j in range(0,24): for program in data['schedules'][j][i]: epginfo.append([program['title'], date['date'] + ' ' + program['startTime'], program['episode'].replace('회',''), program['isRerun'], program['grade']]) - for epg1, epg2 in zip(epginfo, epginfo[1:]): programName = unescape(epg1[0]) if epg1[0] else '' subprogramName = '' @@ -419,6 +412,159 @@ def GetEPGFromNaver(ChannelInfo): if(debug): printError(ChannelName + HTTP_ERROR) else: pass +# Get EPG data from Tbroad +def GetEPGFromTbroad(ChannelInfo): + url='https://www.tbroad.com/chplan/selectRealTimeListForNormal.tb' + pass + +# Get EPG data from Iscs +def GetEPGFromIscs(ChannelInfo): + url='http://service.iscs.co.kr/sub/channel_view.asp' + params = {'chan_idx':'242', 'source_id':'203', 'Chan_Date':'2017-04-18'} + pass + +# Get EPG data from MBC +def GetEPGFromMbc(ChannelInfo): + ChannelId = ChannelInfo[0] + ChannelName = ChannelInfo[1] + ServiceId = ChannelInfo[3] + dayofweek = ['월', '화', '수', '목', '금', '토', '일'] + url = 'http://miniunit.imbc.com/Schedule' + params = {'rtype': 'json'} + for k in range(period): + day = today + datetime.timedelta(days=k) + try: + response = requests.get(url, params=params, headers=ua) + response.raise_for_status() + json_data = response.text + try: + data = json.loads(json_data, encoding='utf-8') + for program in data['Programs']: + if program['Channel'] == "CHAM" and program['LiveDays'] == dayofweek[day.weekday()]: + programName = '' + rebroadcast = True + matches = re.match('^(.*?)(\(재\))?$', unescape(program['ProgramTitle'].encode('utf-8', 'ignore'))) + if not(matches is None): + programName = matches.group(1) + rebroadcast = True if matches.group(2) else False + subprogramName = '' + startTime = str(day) + ' ' + program['StartTime'] + startTime = datetime.datetime.strptime(startTime, '%Y-%m-%d %H%M') + endTime = startTime + datetime.timedelta(minutes=int(program['RunningTime'])) + startTime = startTime.strftime('%Y%m%d%H%M%S') + endTime = endTime.strftime('%Y%m%d%H%M%S') + desc = '' + actors = '' + producers = '' + category = '음악' + episode = '' + rating = 0 + programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} + writeProgram(programdata) + except ValueError: + if(debug): printError(ChannelName + CONTENT_ERROR) + else: pass + except requests.exceptions.HTTPError: + if(debug): printError(ChannelName + HTTP_ERROR) + else: pass + +# Get EPG data from MIL +def GetEPGFromMil(ChannelInfo): + ChannelId = ChannelInfo[0] + ChannelName = ChannelInfo[1] + ServiceId = ChannelInfo[3] + url = 'http://radio.dema.mil.kr/web/fm/quick/ajaxTimetableList.do' + for k in range(period): + day = today + datetime.timedelta(days=k) + params = {'program_date': day.strftime('%Y%m%d')} + try: + response = requests.get(url, params=params, headers=ua) + response.raise_for_status() + json_data = response.text + try: + data = json.loads(json_data, encoding='utf-8') + for program in data['resultList']: + programName = '' + rebroadcast = False + matches = re.match('^(.*?)(\(재\))?$', unescape(program['program_title'].encode('utf-8', 'ignore'))) + if not(matches is None): + programName = matches.group(1) + rebroadcast = True if matches.group(2) else False + subprogramName = unescape(program['program_subtitle']) + startTime = str(day) + ' ' + program['program_time'] + startTime = datetime.datetime.strptime(startTime, '%Y-%m-%d %H%M') + startTime = startTime.strftime('%Y%m%d%H%M%S') + endTime = str(day) + ' ' + program['program_end_time'] + try: + endTime = datetime.datetime.strptime(endTime, '%Y-%m-%d %H%M') + endTime = endTime.strftime('%Y%m%d%H%M%S') + except ValueError: + endTime = endTime.replace(' 24', ' 23') + endTime = datetime.datetime.strptime(endTime, '%Y-%m-%d %H%M') + endTime = endTime + datetime.timedelta(hours=1) + endTime = endTime.strftime('%Y%m%d%H%M%S') + desc = '' + actors = unescape(program['movie_actor']) + producers = unescape(program['movie_director']) + category = '' + episode = '' + rating = 0 + programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} + writeProgram(programdata) + except ValueError: + if(debug): printError(ChannelName + CONTENT_ERROR) + else: pass + except requests.exceptions.HTTPError: + if(debug): printError(ChannelName + HTTP_ERROR) + else: pass + +# Get EPG data from IFM +def GetEPGFromIfm(ChannelInfo): + ChannelId = ChannelInfo[0] + ChannelName = ChannelInfo[1] + ServiceId = ChannelInfo[3] + dayofweek = ['1', '2', '3', '4', '5', '6', '7'] + url = 'http://mapp.itvfm.co.kr/hyb/front/selectHybPgmList.do' + for k in range(period): + day = today + datetime.timedelta(days=k) + params = {'outDay':dayofweek[(day.weekday()+1)%7], 'viewDt':day} + try: + response = requests.get(url, params=params, headers=ua) + response.raise_for_status() + json_data = response.text + try: + data = json.loads(json_data, encoding='utf-8') + for program in data['hybMusicInfoList']: + programName = unescape(program['pgmTitle']) + subprogramName = '' + startTime = str(day) + ' ' + program['pgmStime'] + startTime = datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M') + startTime = startTime.strftime('%Y%m%d%H%M%S') + endTime = str(day) + ' ' + program['pgmEtime'] + try: + endTime = datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M') + endTime = endTime.strftime('%Y%m%d%H%M%S') + except ValueError: + endTime = endTime.replace(' 24', ' 23') + endTime = datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M') + endTime = endTime + datetime.timedelta(hours=1) + endTime = endTime.strftime('%Y%m%d%H%M%S') + desc = '' + actors = program['pgmDj'] + producers = program['pgmPd'] + category = '' + episode = '' + rebroadcast = False + rating = 0 + programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} + writeProgram(programdata) + except ValueError: + if(debug): printError(ChannelName + CONTENT_ERROR) + else: pass + except requests.exceptions.HTTPError: + if(debug): printError(ChannelName + HTTP_ERROR) + else: pass + # Write Program def writeProgram(programdata): ChannelId = programdata['channelId'] @@ -463,10 +609,10 @@ def writeProgram(programdata): print(' ') if actors: for actor in actors.split(','): - if actor: print(' %s' % (actor)) + if actor.strip(): print(' %s' % (actor.strip())) if producers: for producer in producers.split(','): - if producer: print(' %s' % (producer)) + if producer.strip(): print(' %s' % (producer).strip()) print(' ') if category: print(' %s' % (category)) @@ -508,7 +654,6 @@ except ValueError: printError("epg2xml." + JSON_SYNTAX_ERROR) sys.exit() - parser = argparse.ArgumentParser(description = 'EPG 정보를 출력하는 방법을 선택한다') argu1 = parser.add_argument_group(description = 'IPTV 선택') argu1.add_argument('-i', dest = 'MyISP', choices = ['ALL', 'KT', 'LG', 'SK'], help = '사용하는 IPTV : ALL, KT, LG, SK', default = MyISP) From 18013547b8accbd6f31f60593bd1417607c92278 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Wed, 19 Apr 2017 12:44:39 +0900 Subject: [PATCH 34/51] Update readme.txt --- readme.txt | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/readme.txt b/readme.txt index e6cb4a5..a1e465c 100644 --- a/readme.txt +++ b/readme.txt @@ -1,18 +1,15 @@ 1. 버전 - 1.1.6 + 1.1.7 2. 소개 이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다. 기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. 3. 변경사항 - - iptv 선택 항목에 ALL 추가 - - 에피소드 넘버 출력 수정 - - 시작 시간 에러 출력 수정 - - 타이틀 출력 수정 - - 서브타이틀 추출 수정 - - 데이터 중복 출력 문제 수정 - - php 버전이 5.6.3 이전일 때 DOM access 관련 에러 수정 -   + - PHP 7.0 지원 +  - 신규채널 추가 + - 변경채널 반영 + - 라디오 채널 추가 + 4. 저작권 - BSD From d8a4fdb3585cbb97c345c7bcd5d2cd35744e6ee7 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Wed, 19 Apr 2017 12:45:12 +0900 Subject: [PATCH 35/51] =?UTF-8?q?KT=202014=EB=85=84=204=EC=9B=94=20?= =?UTF-8?q?=EC=B1=84=EB=84=90=20=EB=B3=80=EA=B2=BD=20=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 채널정보.xlsx | Bin 78221 -> 81165 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/채널정보.xlsx b/채널정보.xlsx index fc5d28f5fc804899ec0307d453166f5f45742087..5c39553c343b8f27e4b586d00d5b960cac511624 100644 GIT binary patch delta 74119 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�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 delta 71191 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 O;QJH|U Date: Wed, 19 Apr 2017 18:43:18 +0900 Subject: [PATCH 36/51] =?UTF-8?q?iptv=20=EC=84=A4=EC=A0=95=20=EC=9D=B8?= =?UTF-8?q?=EC=88=98=20=EC=82=AC=ED=95=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epg2xml.php | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/epg2xml.php b/epg2xml.php index 7230084..1656371 100644 --- a/epg2xml.php +++ b/epg2xml.php @@ -1,7 +1,7 @@ #!/usr/bin/env php \n", $ChannelId); - fprintf($fp, " %s\n", $ChannelName); if($MyISP != "ALL" && $Channeldata[$MyISP.'Ch'] != Null): + $ChannelInfos[] = array($ChannelId, $ChannelName, $ChannelSource, $ChannelServiceId); $Channelnumber = $Channeldata[$MyISP.'Ch']; $ChannelISPName = htmlspecialchars($Channeldata[$MyISP." Name"], ENT_XML1); + fprintf($fp, " \n", $ChannelId); + fprintf($fp, " %s\n", $ChannelName); fprintf($fp, " %s\n", $ChannelISPName); fprintf($fp, " %s\n", $Channelnumber); fprintf($fp, " %s\n", $Channelnumber." ".$ChannelISPName); + if($IconUrl) : + fprintf($fp, " \n", $IconUrl, $ChannelId); + else : + fprintf($fp, " \n", $ChannelIconUrl); + endif; + fprintf($fp, " \n"); + elseif($MyISP == "ALL"): + $ChannelInfos[] = array($ChannelId, $ChannelName, $ChannelSource, $ChannelServiceId); + fprintf($fp, " \n", $ChannelId); + fprintf($fp, " %s\n", $ChannelName); + if($IconUrl) : + fprintf($fp, " \n", $IconUrl, $ChannelId); + else : + fprintf($fp, " \n", $ChannelIconUrl); + endif; + fprintf($fp, " \n"); endif; - if($IconUrl) : - fprintf($fp, " \n", $IconUrl, $ChannelId); - else : - fprintf($fp, " \n", $ChannelIconUrl); - endif; - fprintf($fp, " \n"); endif; endforeach; # Print Program Information From 42999f9dfd6e6b0fe0e1fa01485679f5cb1d2315 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Wed, 19 Apr 2017 18:46:19 +0900 Subject: [PATCH 37/51] =?UTF-8?q?iptv=20=EC=84=A4=EC=A0=95=20=EC=9D=B8?= =?UTF-8?q?=EC=88=98=20=EC=82=AC=ED=95=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epg2xml.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/epg2xml.py b/epg2xml.py index c17f415..c519144 100644 --- a/epg2xml.py +++ b/epg2xml.py @@ -19,7 +19,7 @@ import pprint reload(sys) sys.setdefaultencoding('utf-8') -__version__ = '1.1.7' +__version__ = '1.1.7p' # Set variable debug = False @@ -56,21 +56,29 @@ def getEpg(): ChannelSource = Channeldata['Source'] ChannelServiceId = Channeldata['ServiceId'] ChannelIconUrl = escape(Channeldata['Icon_url']) - ChannelInfos.append([ChannelId, ChannelName, ChannelSource, ChannelServiceId]) - print(' ' % (ChannelId)) - print(' %s' % (ChannelName)) if MyISP != "ALL" and Channeldata[MyISP+'Ch'] is not None: + ChannelInfos.append([ChannelId, ChannelName, ChannelSource, ChannelServiceId]) ChannelNumber = str(Channeldata[MyISP+'Ch']); ChannelISPName = escape(Channeldata[MyISP+' Name']) + print(' ' % (ChannelId)) + print(' %s' % (ChannelName)) print(' %s' % (ChannelISPName)) print(' %s' % (ChannelNumber)) print(' %s' % (ChannelNumber+' '+ChannelISPName)) - if IconUrl: - print(' ' % (IconUrl, ChannelId)) - else : - print(' ' % (ChannelIconUrl)) - print(' ') - + if IconUrl: + print(' ' % (IconUrl, ChannelId)) + else : + print(' ' % (ChannelIconUrl)) + print(' ') + elif MyISP == "ALL": + ChannelInfos.append([ChannelId, ChannelName, ChannelSource, ChannelServiceId]) + print(' ' % (ChannelId)) + print(' %s' % (ChannelName)) + if IconUrl: + print(' ' % (IconUrl, ChannelId)) + else : + print(' ' % (ChannelIconUrl)) + print(' ') # Print Program Information for ChannelInfo in ChannelInfos: ChannelId = ChannelInfo[0] From 03c3df833222da0563c91cfb0ee867e24dda9a7d Mon Sep 17 00:00:00 2001 From: wonipapa Date: Wed, 19 Apr 2017 18:49:52 +0900 Subject: [PATCH 38/51] Update epg2xml.py --- epg2xml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/epg2xml.py b/epg2xml.py index c519144..77046f0 100644 --- a/epg2xml.py +++ b/epg2xml.py @@ -19,7 +19,7 @@ import pprint reload(sys) sys.setdefaultencoding('utf-8') -__version__ = '1.1.7p' +__version__ = '1.1.7p1' # Set variable debug = False From 70ded7408c0f19503fd3a1d3066d4776979983df Mon Sep 17 00:00:00 2001 From: wonipapa Date: Fri, 21 Apr 2017 16:02:59 +0900 Subject: [PATCH 39/51] Update Channel.json --- Channel.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Channel.json b/Channel.json index d769122..0724cf4 100644 --- a/Channel.json +++ b/Channel.json @@ -108,7 +108,7 @@ {"Id":127,"Name":"MBC SPORTS+2","KT Name":"MBC SPORTS+2","KTCh":61,"LG Name":"MBC스포츠플러스2","LGCh":61,"SK Name":"MBC SPORTS+2","SKCh":124,"Icon_url":"http://i.imgur.com/frAuUS3.png","Source":"SK","ServiceId":531,"Enabled":1}, {"Id":128,"Name":"MBC Dramanet","KT Name":"MBC Dramanet","KTCh":75,"LG Name":"MBC드라마넷","LGCh":35,"SK Name":"MBC 드라마","SKCh":32,"Icon_url":"http://i.imgur.com/VBMFcZ3.png","Source":"SK","ServiceId":900,"Enabled":1}, {"Id":129,"Name":"MBN","KT Name":"MBN","KTCh":16,"LG Name":"MBN","LGCh":16,"SK Name":"MBN","SKCh":16,"Icon_url":"http://i.imgur.com/p0mvIJN.png","Source":"SK","ServiceId":241,"Enabled":1}, -{"Id":130,"Name":"MBN Plus","KT Name":"MBN Plus","KTCh":99,"LG Name":"MBN플러스","LGCh":116,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yMZiUUp.png","Source":"EPG","ServiceId":658,"Enabled":1}, +{"Id":130,"Name":"MBN Plus","KT Name":"MBN Plus","KTCh":99,"LG Name":"MBN플러스","LGCh":116,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yMZiUUp.png","Source":"NAVER","ServiceId":5286722,"Enabled":1}, {"Id":133,"Name":"마운틴TV","KT Name":"마운틴TV","KTCh":117,"LG Name":"마운틴TV","LGCh":69,"SK Name":"Mountain TV","SKCh":247,"Icon_url":"http://i.imgur.com/4nLYnVC.png","Source":"SK","ServiceId":251,"Enabled":1}, {"Id":134,"Name":"mplex","KT Name":"mplex","KTCh":103,"LG Name":"Mplex","LGCh":46,"SK Name":"Mplex","SKCh":57,"Icon_url":"http://i.imgur.com/dOOBYJm.png","Source":"SK","ServiceId":171,"Enabled":1}, {"Id":135,"Name":"머니투데이방송","KT Name":"머니투데이방송","KTCh":181,"LG Name":"MTN","LGCh":122,"SK Name":"MTN","SKCh":152,"Icon_url":"http://i.imgur.com/joWd14j.png","Source":"SK","ServiceId":627,"Enabled":1}, @@ -226,7 +226,7 @@ {"Id":279,"Name":"JJC지방자치TV","KT Name":"JJC지방자치TV","KTCh":279,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/AuXr9jA.png","Source":"NAVER","ServiceId":3244879,"Enabled":1}, {"Id":280,"Name":"채널 Ching","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"채널 Ching","SKCh":105,"Icon_url":"http://i.imgur.com/tRqGKcS.png","Source":"SK","ServiceId":907,"Enabled":1}, {"Id":281,"Name":"채널A","KT Name":"채널A","KTCh":18,"LG Name":"채널A","LGCh":18,"SK Name":"채널A","SKCh":18,"Icon_url":"http://i.imgur.com/xti35f5.png","Source":"SK","ServiceId":242,"Enabled":1}, -{"Id":282,"Name":"채널A 플러스","KT Name":"채널A 플러스","KTCh":98,"LG Name":"채널A플러스","LGCh":115,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/rRisTh8.png","Source":"EPG","ServiceId":627,"Enabled":1}, +{"Id":282,"Name":"채널A 플러스","KT Name":"채널A 플러스","KTCh":98,"LG Name":"채널A플러스","LGCh":115,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/rRisTh8.png","Source":"NAVER","ServiceId"5286712:,"Enabled":1}, {"Id":283,"Name":"채널CGV","KT Name":"채널CGV","KTCh":29,"LG Name":"CH CGV","LGCh":39,"SK Name":"Ch CGV","SKCh":53,"Icon_url":"http://i.imgur.com/fwjRwkx.png","Source":"SK","ServiceId":187,"Enabled":1}, {"Id":284,"Name":"채널i","KT Name":"채널i","KTCh":250,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/X7lXvtw.png","Source":"NAVER","ServiceId":3173174,"Enabled":1}, {"Id":285,"Name":"채널뷰","KT Name":"채널뷰","KTCh":176,"LG Name":"","LGCh":null,"SK Name":"채널View","SKCh":212,"Icon_url":"http://i.imgur.com/lvtWgFL.png","Source":"SK","ServiceId":276,"Enabled":1}, From 00c021c8cc4b0c636a1ec334fb9a93e4ab53bafe Mon Sep 17 00:00:00 2001 From: wonipapa Date: Fri, 21 Apr 2017 16:05:14 +0900 Subject: [PATCH 40/51] =?UTF-8?q?kbs=20=ED=95=A8=EC=88=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20=EC=8A=A4=EC=B9=B4=EC=9D=B4=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=ED=94=84=20url=20=EB=B3=80=EA=B2=BD=20=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81,=20=EB=88=84=EB=9D=BD=20epg=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epg2xml.php | 325 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 208 insertions(+), 117 deletions(-) diff --git a/epg2xml.php b/epg2xml.php index 1656371..7bbc235 100644 --- a/epg2xml.php +++ b/epg2xml.php @@ -1,7 +1,7 @@ #!/usr/bin/env php \n"); @@ -378,6 +380,7 @@ function GetEPGFromEPG($ChannelInfo) { 'header'=> $GLOBALS['ua'] )); $context = stream_context_create($options); + $epginfo = array(); foreach(range(1, $GLOBALS['period']) as $k) : $url = "http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi"; $day = date("Ymd", strtotime("+".($k - 1)." days")); @@ -389,10 +392,9 @@ function GetEPGFromEPG($ChannelInfo) { ); $params = http_build_query($params); $url = $url."?".$params; - $epginfo = array(); try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : $response = str_replace("charset=euc-kr", "charset=utf-8", $response); @@ -417,9 +419,9 @@ function GetEPGFromEPG($ChannelInfo) { $hour = $hour." PM"; break; case 4 : - if($hour > 5 ) : + if($hour > 5 && $hour < 12) : $hour = $hour." PM"; - else : + elseif($hour <5 || $hour == 12) : $hour = $hour." AM"; $thisday = date("Ymd", strtotime($day." +1 days")); endif; @@ -436,44 +438,44 @@ function GetEPGFromEPG($ChannelInfo) { $rating = 0; endif; endif; - #programName, startTime, rating, subprogramName, rebroadcast, episode + //programName, startTime, rating, subprogramName, rebroadcast, episode $epginfo[] = array(trim($matches[2]), $startTime, $rating, trim($matches[4]), $matches[5], $matches[7]); endforeach; endfor; - $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); - foreach($zipped as $epg) : - $programName = $epg[0][0] ?: ""; - $subprogramName = $epg[0][3] ?: ""; - $startTime = $epg[0][1] ?: ""; - $endTime = $epg[1][1] ?: ""; - $desc = ""; - $actors = ""; - $producers = ""; - $category = ""; - $rebroadcast = $epg[0][4] ? True : False; - $episode = $epg[0][5] ?: ""; - $rating = $epg[0][2] ?: 0; - $programdata = array( - 'channelId'=> $ChannelId, - 'startTime' => $startTime, - 'endTime' => $endTime, - 'programName' => $programName, - 'subprogramName'=> $subprogramName, - 'desc' => $desc, - 'actors' => $actors, - 'producers' => $producers, - 'category' => $category, - 'episode' => $episode, - 'rebroadcast' => $rebroadcast, - 'rating' => $rating - ); - writeProgram($programdata); - endforeach; endif; } catch (Exception $e) { if($GLOBALS['debug']) printError($e->getMessage()); } endforeach; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + $programName = $epg[0][0] ?: ""; + $subprogramName = $epg[0][3] ?: ""; + $startTime = $epg[0][1] ?: ""; + $endTime = $epg[1][1] ?: ""; + $desc = ""; + $actors = ""; + $producers = ""; + $category = ""; + $rebroadcast = $epg[0][4] ? True : False; + $episode = $epg[0][5] ?: ""; + $rating = $epg[0][2] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; } // Get EPG data from KT @@ -488,6 +490,7 @@ function GetEPGFromKT($ChannelInfo) { 'header'=> $GLOBALS['ua'] )); $context = stream_context_create($options); + $epginfo = array(); foreach(range(1, $GLOBALS['period']) as $k) : $url = "http://tv.olleh.com/renewal_sub/liveTv/pop_schedule_week.asp"; $day = date("Ymd", strtotime("+".($k - 1)." days")); @@ -500,10 +503,9 @@ function GetEPGFromKT($ChannelInfo) { ); $params = http_build_query($params); $url = $url."?".$params; - $epginfo = array(); try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : $response = str_replace("charset=euc-kr", "charset=utf-8", $response); @@ -520,46 +522,45 @@ function GetEPGFromKT($ChannelInfo) { $rating = str_replace("all", 0, str_replace("세 이상", "", trim($cells->item(2)->nodeValue))); $epginfo[]= array(trim($cells->item(1)->nodeValue), $startTime, $rating, trim($cells->item(4)->nodeValue)); endforeach; - $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); - foreach($zipped as $epg) : - $programName = ""; - $subprogramName = ""; - preg_match('/^(.*?)( <(.*)>)?$/', $epg[0][0], $matches); - if($matches) : - $programName = $matches[1] ?: ""; - $subprogramName = $matches[3] ?: ""; - endif; - $startTime = $epg[0][1] ?: ""; - $endTime = $epg[1][1] ?: ""; - $desc = ""; - $actors = ""; - $producers = ""; - $category = $epg[0][3] ?: ""; - $rebroadcast = False; - $episode = ""; - $rating = $epg[0][2] ?: 0; - $programdata = array( - 'channelId'=> $ChannelId, - 'startTime' => $startTime, - 'endTime' => $endTime, - 'programName' => $programName, - 'subprogramName'=> $subprogramName, - 'desc' => $desc, - 'actors' => $actors, - 'producers' => $producers, - 'category' => $category, - 'episode' => $episode, - 'rebroadcast' => $rebroadcast, - 'rating' => $rating - ); - - writeProgram($programdata); - endforeach; endif; } catch (Exception $e) { if($GLOBALS['debug']) printError($e->getMessage()); } endforeach; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + $programName = ""; + $subprogramName = ""; + preg_match('/^(.*?)( <(.*)>)?$/', $epg[0][0], $matches); + if($matches) : + $programName = $matches[1] ?: ""; + $subprogramName = $matches[3] ?: ""; + endif; + $startTime = $epg[0][1] ?: ""; + $endTime = $epg[1][1] ?: ""; + $desc = ""; + $actors = ""; + $producers = ""; + $category = $epg[0][3] ?: ""; + $rebroadcast = False; + $episode = ""; + $rating = $epg[0][2] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; } // Get EPG data from LG @@ -574,6 +575,7 @@ function GetEPGFromLG($ChannelInfo) { 'header'=> $GLOBALS['ua'] )); $context = stream_context_create($options); + $epginfo = array(); foreach(range(1, $GLOBALS['period']) as $k) : $url = "http://www.uplus.co.kr/css/chgi/chgi/RetrieveTvSchedule.hpi"; $day = date("Ymd", strtotime("+".($k - 1)." days")); @@ -583,10 +585,9 @@ function GetEPGFromLG($ChannelInfo) { ); $params = http_build_query($params); $url = $url."?".$params; - $epginfo = array(); try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : $response = ''.$response; @@ -604,44 +605,44 @@ function GetEPGFromLG($ChannelInfo) { $startTime = date("YmdHis", strtotime($day." ".trim($cells->item(0)->nodeValue))); $spans = $cells->item(1)->getElementsByTagName('span'); $rating = trim($spans->item(1)->nodeValue)=="All" ? 0 : trim($spans->item(1)->nodeValue); - #programName, startTime, rating, category + //programName, startTime, rating, category $epginfo[]= array($programName, $startTime, $rating, trim($cells->item(2)->nodeValue)); endforeach; - $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); - foreach($zipped as $epg) : - preg_match('/(<재>?)?(.*?)(\[(.*)\])?\s?(\(([\d,]+)회\))?$/', $epg[0][0], $matches); - $programName = trim($matches[2]) ?: ""; - $subprogramName = trim($matches[4]) ?: ""; - $startTime = $epg[0][1] ?: ""; - $endTime = $epg[1][1] ?: ""; - $desc = ""; - $actors = ""; - $producers = ""; - $category = $epg[0][3] ?: ""; - $rebroadcast = trim($matches[1]) ? True: False; - $episode = trim($matches[6]) ?: ""; - $rating = $epg[0][2] ?: 0; - $programdata = array( - 'channelId'=> $ChannelId, - 'startTime' => $startTime, - 'endTime' => $endTime, - 'programName' => $programName, - 'subprogramName'=> $subprogramName, - 'desc' => $desc, - 'actors' => $actors, - 'producers' => $producers, - 'category' => $category, - 'episode' => $episode, - 'rebroadcast' => $rebroadcast, - 'rating' => $rating - ); - writeProgram($programdata); - endforeach; endif; } catch (Exception $e) { if($GLOBALS['debug']) printError($e->getMessage()); } endforeach; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + preg_match('/(<재>?)?(.*?)(\[(.*)\])?\s?(\(([\d,]+)회\))?$/', $epg[0][0], $matches); + $programName = trim($matches[2]) ?: ""; + $subprogramName = trim($matches[4]) ?: ""; + $startTime = $epg[0][1] ?: ""; + $endTime = $epg[1][1] ?: ""; + $desc = ""; + $actors = ""; + $producers = ""; + $category = $epg[0][3] ?: ""; + $rebroadcast = trim($matches[1]) ? True: False; + $episode = trim($matches[6]) ?: ""; + $rating = $epg[0][2] ?: 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; } // Get EPG data from SK @@ -666,7 +667,7 @@ function GetEPGFromSK($ChannelInfo) { $url = $url."?".$params; try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : try { @@ -734,12 +735,12 @@ function GetEPGFromSKY($ChannelInfo) { $ServiceId = $ChannelInfo[3]; $options = array( 'http' => array( - 'method' => 'GET', + 'method' => 'POST', 'header'=> $GLOBALS['ua'] )); $context = stream_context_create($options); foreach(range(1, $GLOBALS['period']) as $k) : - $url = "http://www.skylife.co.kr/channel/epg/channelScheduleList.do"; + $url = "http://www.skylife.co.kr/channel/epg/channelScheduleListJson.do"; $day = date("Y-m-d", strtotime("+".($k - 1)." days")); $params = array( 'area' => 'in', @@ -751,14 +752,14 @@ function GetEPGFromSKY($ChannelInfo) { $url = $url."?".$params; try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : try { $data = json_decode($response, TRUE); if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); if(count($data['scheduleListIn']) == 0) : - if($GLOBALS['debug']) : + if($GLOBALS['debug']) : printError($ChannelName.CHANNEL_ERROR); endif; else : @@ -818,6 +819,8 @@ function GetEPGFromNaver($ChannelInfo) { 'header'=> $GLOBALS['ua'] )); $context = stream_context_create($options); + $epginfo = array(); + $totaldate = array(); foreach(range(1, $GLOBALS['period']) as $k) : $url = "https://search.naver.com/p/csearch/content/batchrender_ssl.nhn"; $day = date("Ymd", strtotime("+".($k - 1)." days")); @@ -841,7 +844,7 @@ function GetEPGFromNaver($ChannelInfo) { $url = $url."?".$params; try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : try { @@ -858,7 +861,7 @@ function GetEPGFromNaver($ChannelInfo) { for($i = 0; $i < count($data['displayDates']); $i++) : for($j = 0; $j < 24; $j++) : foreach($data['schedules'][$j][$i] as $program) : - #programName, startTime, episode, rebroadcast, rating + //programName, startTime, episode, rebroadcast, rating $startTime = date("YmdHis", strtotime($data['displayDates'][$i]['date']." ".$program['startTime'])); $epginfo[] = array($program['title'], $startTime, str_replace("회","", $program['episode']), $program['isRerun'], $program['grade']); endforeach; @@ -940,7 +943,7 @@ function GetEPGFromMbc($ChannelInfo) { $url = $url."?".$params; try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : try { @@ -987,7 +990,6 @@ function GetEPGFromMbc($ChannelInfo) { ); writeProgram($programdata); endif; - endforeach; endif; } catch(Exception $e) { @@ -1021,7 +1023,7 @@ function GetEPGFromMil($ChannelInfo) { $url = $url."?".$params; try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : try { @@ -1102,7 +1104,7 @@ function GetEPGFromIfm($ChannelInfo) { $url = $url."?".$params; try { $response = @file_get_contents($url, False, $context); - if ($response === False) : + if ($response === False && $GLOBALS['debug']) : printError($ChannelName.HTTP_ERROR); else : try { @@ -1154,7 +1156,96 @@ function GetEPGFromIfm($ChannelInfo) { } endforeach; } - + +// Get EPG data from KBS +function GetEPGFromKbs($ChannelInfo) { + $ChannelId = $ChannelInfo[0]; + $ChannelName = $ChannelInfo[1]; + $ServiceId = $ChannelInfo[3]; + $options = array( + 'http' => array( + 'method' => 'GET', + 'header'=> $GLOBALS['ua'] + )); + $context = stream_context_create($options); + $epginfo = array(); + foreach(range(1, $GLOBALS['period']) as $k) : + $url = "http://world.kbs.co.kr/include/wink/_ajax_schedule.php"; + $day = date("Y-m-d", strtotime("+".($k - 1)." days")); + $params = array( + 'channel'=>'wink_11' + ); + $params = http_build_query($params); + $url = $url."?".$params; + try { + $response = @file_get_contents($url, False, $context); + if ($response === False && $GLOBALS['debug']) : + printError($ChannelName.HTTP_ERROR); + else : + try { + $data = json_decode($response, TRUE); + if(json_last_error() != JSON_ERROR_NONE) throw new Exception(JSON_SYNTAX_ERROR); + if(count($data['schedule']) == 0) : + if($GLOBALS['debug']) : + printError($ChannelName.CHANNEL_ERROR); + endif; + else : + $dom = new DomDocument; + libxml_use_internal_errors(true); + $dom->loadHTML($data['schedule']); + $xpath = new DomXPath($dom); + $query = "//li"; + $rows = $xpath->query($query); + foreach($rows as $row) : + $cells = $row->getElementsByTagName('span'); + $programName = trim($cells->item(2)->childNodes->item(0)->nodeValue); + $programName = str_replace(array("[","]", " Broadcast"), array("", "", ""), $programName); + $startTime = $day." ".trim($cells->item(0)->childNodes->item(0)->nodeValue); + //programName, startTime, rating, category + $epginfo[]= array($programName, $startTime); + endforeach; + endif; + } catch(Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endif; + } catch (Exception $e) { + if($GLOBALS['debug']) printError($e->getMessage()); + } + endforeach; + $zipped = array_slice(array_map(NULL, $epginfo, array_slice($epginfo,1)),0,-1); + foreach($zipped as $epg) : + $programName = $epg[0][0] ?: ""; + $subprogramName = ""; + $startTime = $epg[0][1] ?: ""; + $startTime = date("YmdHis", strtotime($startTime)); + $endTime = $epg[1][1] ?: ""; + $endTime = date("YmdHis", strtotime($endTime)); + $desc = ""; + $actors = ""; + $producers = ""; + $category = ""; + $rebroadcast = False; + $episode = ""; + $rating = 0; + $programdata = array( + 'channelId'=> $ChannelId, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'programName' => $programName, + 'subprogramName'=> $subprogramName, + 'desc' => $desc, + 'actors' => $actors, + 'producers' => $producers, + 'category' => $category, + 'episode' => $episode, + 'rebroadcast' => $rebroadcast, + 'rating' => $rating + ); + writeProgram($programdata); + endforeach; +} + function writeProgram($programdata) { $fp = $GLOBALS['fp']; $ChannelId = $programdata['channelId']; From 15c25fc08d744a9028796f1976176f8e273845a1 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Fri, 21 Apr 2017 16:05:53 +0900 Subject: [PATCH 41/51] =?UTF-8?q?kbs=20=ED=95=A8=EC=88=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20=EC=8A=A4=EC=B9=B4=EC=9D=B4=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=ED=94=84=20url=20=EB=B3=80=EA=B2=BD=20=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81,=20=EB=88=84=EB=9D=BD=20epg=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epg2xml.py | 186 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 66 deletions(-) diff --git a/epg2xml.py b/epg2xml.py index 77046f0..c14161e 100644 --- a/epg2xml.py +++ b/epg2xml.py @@ -19,7 +19,7 @@ import pprint reload(sys) sys.setdefaultencoding('utf-8') -__version__ = '1.1.7p1' +__version__ = '1.1.8' # Set variable debug = False @@ -108,6 +108,8 @@ def getEpg(): GetEPGFromMil(ChannelInfo) elif ChannelSource == 'IFM': GetEPGFromIfm(ChannelInfo) + elif ChannelSource == 'KBS': + GetEPGFromKbs(ChannelInfo) print('') # Get EPG data from epg.co.kr @@ -116,10 +118,10 @@ def GetEPGFromEPG(ChannelInfo): ChannelName = ChannelInfo[1] ServiceId = ChannelInfo[3] url = 'http://www.epg.co.kr/epg-cgi/extern/cnm_guide_type_v070530.cgi' + epginfo = [] for k in range(period): day = today + datetime.timedelta(days=k) params = {'beforegroup':'100', 'checkchannel':ServiceId, 'select_group':'100', 'start_date':day.strftime('%Y%m%d')} - epginfo = [] try: response = requests.post(url, data=params, headers=ua) response.raise_for_status() @@ -131,12 +133,13 @@ def GetEPGFromEPG(ChannelInfo): for i in range(1,4): thisday = day row = tables[i].find_all('td', {'colspan':'2'}) - for j, cell in enumerate(row): + for cell in row: hour = int(cell.text.strip().strip('시')) + if(i == 1) : hour = 'AM ' + str(hour) elif(i == 2) : hour = 'PM ' + str(hour) - elif(i == 3 and hour > 5) : hour = 'PM ' + str(hour) - elif(i == 3 and hour < 5) : + elif(i == 3 and hour > 5 and hour < 12 ) : hour = 'PM ' + str(hour) + elif(i == 3 and (hour < 5 or hour == 12)) : hour = 'AM ' + str(hour) thisday = day + datetime.timedelta(days=1) for celldata in cell.parent.find_all('tr'): @@ -155,23 +158,23 @@ def GetEPGFromEPG(ChannelInfo): subprogramName = matches.group(4).strip() if matches.group(4) else '' #programName, startTime, rating, subprogramName, rebroadcast, episode epginfo.append([programName, startTime, rating, subprogramName, matches.group(5), matches.group(7)]) - for epg1, epg2 in zip(epginfo, epginfo[1:]): - programName = epg1[0] if epg1[0] else '' - subprogramName = epg1[3] if epg1[3] else '' - startTime = epg1[1] if epg1[1] else '' - endTime = epg2[1] if epg2[1] else '' - desc = '' - actors = '' - producers = '' - category = '' - rebroadcast = True if epg1[4] else False - episode = epg1[5] if epg1[5] else '' - rating = int(epg1[2]) if epg1[2] else 0 - programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} - writeProgram(programdata) except requests.exceptions.HTTPError: if(debug): printError(ChannelName + HTTP_ERROR) else: pass + for epg1, epg2 in zip(epginfo, epginfo[1:]): + programName = epg1[0] if epg1[0] else '' + subprogramName = epg1[3] if epg1[3] else '' + startTime = epg1[1] if epg1[1] else '' + endTime = epg2[1] if epg2[1] else '' + desc = '' + actors = '' + producers = '' + category = '' + rebroadcast = True if epg1[4] else False + episode = epg1[5] if epg1[5] else '' + rating = int(epg1[2]) if epg1[2] else 0 + programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} + writeProgram(programdata) # Get EPG data from KT def GetEPGFromKT(ChannelInfo): @@ -179,10 +182,10 @@ def GetEPGFromKT(ChannelInfo): ChannelName = ChannelInfo[1] ServiceId = ChannelInfo[3] url = 'http://tv.olleh.com/renewal_sub/liveTv/pop_schedule_week.asp' + epginfo = [] for k in range(period): day = today + datetime.timedelta(days=k) params = {'ch_name':'', 'ch_no':ServiceId, 'nowdate':day.strftime('%Y%m%d'), 'seldatie':day.strftime('%Y%m%d'), 'tab_no':'1'} - epginfo = [] try: response = requests.get(url, params=params, headers=ua) response.raise_for_status() @@ -195,34 +198,34 @@ def GetEPGFromKT(ChannelInfo): for row in html: for cell in [row.find_all('td')]: epginfo.append([cell[1].text, str(day) + ' ' + cell[0].text, cell[4].text, cell[2].text]) - for epg1, epg2 in zip(epginfo, epginfo[1:]): - programName = '' - subprogrmaName = '' - matches = re.match('^(.*?)( <(.*)>)?$', epg1[0].decode('string_escape')) - if not (matches is None): - programName = matches.group(1) if matches.group(1) else '' - subprogramName = matches.group(3) if matches.group(3) else '' - startTime = datetime.datetime.strptime(epg1[1], '%Y-%m-%d %H:%M') - startTime = startTime.strftime('%Y%m%d%H%M%S') - endTime = datetime.datetime.strptime(epg2[1], '%Y-%m-%d %H:%M') - endTime = endTime.strftime('%Y%m%d%H%M%S') - category = epg1[2] - desc = '' - actors = '' - producers = '' - episode = '' - rebroadcast = False - rating = 0 - matches = re.match('(\d+)', epg1[3]) - if not(matches is None): rating = int(matches.group()) - programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} - writeProgram(programdata) else: if(debug): printError(ChannelName + CONTENT_ERROR) else: pass except requests.exceptions.HTTPError: if(debug): printError(ChannelName + HTTP_ERROR) else: pass + for epg1, epg2 in zip(epginfo, epginfo[1:]): + programName = '' + subprogrmaName = '' + matches = re.match('^(.*?)( <(.*)>)?$', epg1[0].decode('string_escape')) + if not (matches is None): + programName = matches.group(1) if matches.group(1) else '' + subprogramName = matches.group(3) if matches.group(3) else '' + startTime = datetime.datetime.strptime(epg1[1], '%Y-%m-%d %H:%M') + startTime = startTime.strftime('%Y%m%d%H%M%S') + endTime = datetime.datetime.strptime(epg2[1], '%Y-%m-%d %H:%M') + endTime = endTime.strftime('%Y%m%d%H%M%S') + category = epg1[2] + desc = '' + actors = '' + producers = '' + episode = '' + rebroadcast = False + rating = 0 + matches = re.match('(\d+)', epg1[3]) + if not(matches is None): rating = int(matches.group()) + programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} + writeProgram(programdata) # Get EPG data from LG def GetEPGFromLG(ChannelInfo): @@ -230,10 +233,10 @@ def GetEPGFromLG(ChannelInfo): ChannelName = ChannelInfo[1] ServiceId = ChannelInfo[3] url = 'http://www.uplus.co.kr/css/chgi/chgi/RetrieveTvSchedule.hpi' + epginfo = [] for k in range(period): day = today + datetime.timedelta(days=k) params = {'chnlCd': ServiceId, 'evntCmpYmd': day.strftime('%Y%m%d')} - epginfo = [] try: response = requests.get(url, params=params, headers=ua) response.raise_for_status() @@ -249,33 +252,33 @@ def GetEPGFromLG(ChannelInfo): rating = 0 if cell[1].find('span', {'class': 'tag cte_all'}).text.strip()=="All" else int(cell[1].find('span', {'class': 'tag cte_all'}).text.strip()) cell[1].find('span', {'class': 'tagGroup'}).decompose() epginfo.append([cell[1].text.strip(), str(day) + ' ' + cell[0].text, cell[2].text.strip(), rating]) - for epg1, epg2 in zip(epginfo, epginfo[1:]): - programName = '' - subprogramName = '' - episode = '' - matches = re.match('(<재>?)?(.*?)(\[(.*)\])?\s?(\(([\d,]+)회\))?$', epg1[0].decode('string_escape')) - rebroadcast = False - if not (matches is None): - programName = matches.group(2) if matches.group(2) else '' - subprogramName = matches.group(4) if matches.group(4) else '' - rebroadcast = True if matches.group(1) else False - episode = matches.group(6) if matches.group(6) else '' - startTime = datetime.datetime.strptime(epg1[1], '%Y-%m-%d %H:%M') - startTime = startTime.strftime('%Y%m%d%H%M%S') - endTime = datetime.datetime.strptime(epg2[1], '%Y-%m-%d %H:%M') - endTime = endTime.strftime('%Y%m%d%H%M%S') - category = epg1[2] - desc = '' - actors = '' - producers = '' - programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} - writeProgram(programdata) else: if(debug): printError(ChannelName + CONTENT_ERROR) else: pass except requests.exceptions.HTTPError: if(debug): printError(ChannelName + HTTP_ERROR) else: pass + for epg1, epg2 in zip(epginfo, epginfo[1:]): + programName = '' + subprogramName = '' + episode = '' + matches = re.match('(<재>?)?(.*?)(\[(.*)\])?\s?(\(([\d,]+)회\))?$', epg1[0].decode('string_escape')) + rebroadcast = False + if not (matches is None): + programName = matches.group(2) if matches.group(2) else '' + subprogramName = matches.group(4) if matches.group(4) else '' + rebroadcast = True if matches.group(1) else False + episode = matches.group(6) if matches.group(6) else '' + startTime = datetime.datetime.strptime(epg1[1], '%Y-%m-%d %H:%M') + startTime = startTime.strftime('%Y%m%d%H%M%S') + endTime = datetime.datetime.strptime(epg2[1], '%Y-%m-%d %H:%M') + endTime = endTime.strftime('%Y%m%d%H%M%S') + category = epg1[2] + desc = '' + actors = '' + producers = '' + programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} + writeProgram(programdata) # Get EPG data from SK def GetEPGFromSK(ChannelInfo): @@ -334,12 +337,12 @@ def GetEPGFromSKY(ChannelInfo): ChannelId = ChannelInfo[0] ChannelName = ChannelInfo[1] ServiceId = ChannelInfo[3] - url = 'http://www.skylife.co.kr/channel/epg/channelScheduleList.do' + url = 'http://www.skylife.co.kr/channel/epg/channelScheduleListJson.do' for k in range(period): day = today + datetime.timedelta(days=k) params = {'area': 'in', 'inFd_channel_id': ServiceId, 'inairdate': day.strftime('%Y-%m-%d'), 'indate_type': 'now'} try: - response = requests.get(url, params=params, headers=ua) + response = requests.post(url, params=params, headers=ua) response.raise_for_status() json_data = response.text try: @@ -573,6 +576,57 @@ def GetEPGFromIfm(ChannelInfo): if(debug): printError(ChannelName + HTTP_ERROR) else: pass +# Get EPG data from KBS +def GetEPGFromKbs(ChannelInfo): + ChannelId = ChannelInfo[0] + ChannelName = ChannelInfo[1] + ServiceId = ChannelInfo[3] + url = 'http://world.kbs.co.kr/include/wink/_ajax_schedule.php' + params = {'channel':'wink_11'} + epginfo = [] + for k in range(period): + day = today + datetime.timedelta(days=k) + try: + response = requests.get(url, params=params, headers=ua) + response.raise_for_status() + json_data = response.text + try: + data = json.loads(json_data, encoding='utf-8') + soup = BeautifulSoup(data['schedule'], 'lxml') + for row in soup.find_all('li'): + programName = '' + startTime = '' + matches = re.match('([0-2][0-9]:[0-5][0-9])[0-2][0-9]:[0-5][0-9]\[(.*)\] Broadcast', unescape(row.text.encode('utf-8', 'ignore'))) + if not(matches is None): + programName = unescape(matches.group(2)) + startTime = str(day) + ' ' + matches.group(1) + #programName, startTime + epginfo.append([programName, startTime]) + except ValueError: + if(debug): printError(ChannelName + CONTENT_ERROR) + else: pass + except requests.exceptions.HTTPError: + if(debug): printError(ChannelName + HTTP_ERROR) + else: pass + for epg1, epg2 in zip(epginfo, epginfo[1:]): + programName = epg1[0] + subprogramName = '' + startTime = epg1[1] + startTime = datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M') + startTime = startTime.strftime('%Y%m%d%H%M%S') + endTime = epg2[1] + endTime = datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M') + endTime = endTime.strftime('%Y%m%d%H%M%S') + desc = '' + actors = '' + producers = '' + category = '' + episode = '' + rebroadcast = False + rating = 0 + programdata = {'channelId':ChannelId, 'startTime':startTime, 'endTime':endTime, 'programName':programName, 'subprogramName':subprogramName, 'desc':desc, 'actors':actors, 'producers':producers, 'category':category, 'episode':episode, 'rebroadcast':rebroadcast, 'rating':rating} + writeProgram(programdata) + # Write Program def writeProgram(programdata): ChannelId = programdata['channelId'] From b676a6db9cd9e66351d138bd1e08c6f8a79cab4e Mon Sep 17 00:00:00 2001 From: wonipapa Date: Fri, 21 Apr 2017 16:07:50 +0900 Subject: [PATCH 42/51] Update readme.txt --- readme.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/readme.txt b/readme.txt index a1e465c..b18c958 100644 --- a/readme.txt +++ b/readme.txt @@ -1,15 +1,15 @@ 1. 버전 - 1.1.7 + 1.1.8 2. 소개 이 프로그램은 EPG(Electronic Program Guide)를 웹상의 여러 소스에서 가져와서 XML로 출력하는 프로그램으로 python2 및 php5 Cli에서 사용 가능하도록 제작되었다. 기본적으로 외부의 소스를 분석하여 출력하므로 외부 소스 사이트가 변경되거나 삭제되면 문제가 발생할 수 있다. 3. 변경사항 - - PHP 7.0 지원 -  - 신규채널 추가 - - 변경채널 반영 - - 라디오 채널 추가 + - KBS 함수 추가 + - Channel.json 소스 변경 + -스카이라이프 url 변경 + - EPG 누락 데이터 수정 4. 저작권 - BSD From 39e9a7d9bda8d64d93fa3c0d141b71b46f94d687 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Fri, 21 Apr 2017 16:08:24 +0900 Subject: [PATCH 43/51] =?UTF-8?q?=EC=B1=84=EB=84=90=20=EC=86=8C=EC=8A=A4?= =?UTF-8?q?=20=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 채널정보.xlsx | Bin 81165 -> 81249 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/채널정보.xlsx b/채널정보.xlsx index 5c39553c343b8f27e4b586d00d5b960cac511624..f12c448ea76caa57066ec73bf6e47023d2743b12 100644 GIT binary patch delta 41205 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≪^W z=>uv+$()Qw+fqKgvx!>UxDVhQF{u9LaV@9K+oV)gjZEy!fehsdVT0NVZ>MVqWXC7i zL<+1)1)C7WT(4ECAbA#W$1j4r;@o*j=o(R<47P;dyNbsCY*9u!18;5{>uOO~L!L-e zMSzkpgrGfh5G@}a$c9zVYqy}yOF>a*a&%pw7@2Cu}FwYoR)5O;dfZ#ob zixCl(^RGXC1dglo(6Am$v!xu&Pu2S)e#UYs5pWTzA zbT4;fAZ+f1+J8ZDn%L6pMU+sMUurb)Qnx}gxh2`r1Zi!f58bzsBv+*8l}>Ca+N?oN z`WvIOwACRJ*24Zb4P}LxcPte@GH54$RdYYO|D(2GC6K(xH_ z@^pO}%v_l_|A{lqW}Ak}FCm6?Y_XEb5dKoXMOS)zLx^)WfdLjwx&+z>)uH~RJ?qci4Yob_&VM%44DxU}J ze`4c?tXt%7a8f1E-W_rt`^&dEA(phkljA8B`9Ys4a%dn&CxmFXKUEddx5H1TRTl?7 z#w1`Mg|?@+;WaFfVkZ&Ue{;5)WXS6(VJssWBMS!CJm&&`us5V#gx8m-WbU zwP+AChWBLU1)X0we{a9rX+HBUE$0#x8ZAuuY45(zy@T3T4aQkONaoFng`v*g8~mn= zvN*%CXkkPC(lFYHJ@xVwOH{}7Az9b*E&T5&dEOw42D>q%C!iNhpo9uwQ;lt@)Rx2d zjB>ex2%+-2^zt8*yui+r|F9yC1+G3xk6%qN|C<|o7C=j%nDq9F_eLtg<(&PtCP53g zFKQfTNf@omo)&0n-Jxbk_Pj#1@#W^f8uqP!dtDy8(f)hq4=8^*#VCX;WZ6zBE@6iv z%K};bvY_zw$Y8i64za2$(baGvN}4z3G<@}MUTi>ydq(T5UVrz&ep`W{1)^|P>^2+F_pp z`KbVB#QJjTJ44!9e<>z3WkOIb#_n3m2 z$WN&o8-^i~a3kiD;Nmt78(8aUq^g2_{xK+x{r-FCycOpPd-FvKOh(9qd>xPu_k11o z!hi{JXnxOG+!=lU+C}n8B znrLE+$FP~A%~E-seZiECB-|>OfuV@7NN2zw?F&C~1sgKzj!nosS&+}y7NNy# zh`q&WV}ReEBEbE8r%LedIJ}p-%l4VFFsGlo%QAS7)o3gJ#Ao}gD=+YH?C=+1XUcbu zwtA7wpk2Wr1EgOXE!f5#e-9vsA0OeYo`B2{c~hvE9k-W8=z!R$bxP9F8+n`3 z-RCC2y;ne*!AqWst~i`=QbXNPEK0*hqU^KA$@e~L_0lrA20^LbjF49>2UzBeleB8= zrSR04k(rWN635x(hH7Wat`S&iJ*M?J?&zzodiVfh2%pE6EOAp^3AO)NR*04)vEL51 z;cqJRDn2R?nI3Yj^U@VdG0mZVv_ut0Kz=hA?iH_xc^^^(yQUDMBDokn31+HjI~vSS zG3i;E>W#VGM1<;jIa_d8KJA3GYHV3ZA6qAqH9l?HI|m-ugnWrtC3aCC(#bIvhQ6d6 zX}tuf*l{P$tJrt@y`>J)_I<-G2Yyy{si_1Zd<6&O`ve&eoM> zVfn4T`e!&;O|RAR7+V}OY*BI7Mtj!|5No66AyLB2sybq6=+ROBU33ONBj|^a4v)s# z=21-Q7>lx9Q15$lTu6gJ$V4U(SK{bti#<5mLvMfCu@{7(RWe$#;SJmId+O}`cJ~BW zY0CH0ZDTqxHo7qHvBg4cHOhTHx-p)Lv~X9?LtK8?pvq|$qAj~uHt5kk7%@M7SbSo4o`|ae0l(?fn%@l-Qalj^NGT} z&YZP8g^C+L4@_PW54T)Exel!ibGEo_X(Jn<%pgP)%TA&~(%ZD3Q5C4!zjJU&l1u`F zP=ro;6py5yPARrDWGyiqS3TdO+5*O4Ub1wQ)o7pFu?B6s;3jk1xaG9Kxh>#?t)ywY zM9uDnhRC-0oz%sngCaEPy_ljH=T(uqL#p)Mkc$}7%jy1iY_5&=?iG^3iya|}U%ikt zmCDg7FcE3H5_#Zef%-iYas#-=j4?5mmqT#*0u9uv1{oeH9S4uNCq!os0(%>WLqZHYPd{5XOSN|pqVom2wA>-_H{MqgZrU3Egjxfj&!|}vD6>8k+ho94Qrrz|{quv( zh0e3MwVuv)_XxI(V*OV6S3E?ha7pshSRROpC-RUt)+%SDH(6^Wzq%90!5)F5YfT+W z&|b=M^+VT`kZuAVGPHFg3uo;M`^^@YYWCJX^yUrRt}C1pez{^$BDD()h0A}i_3Mv1 zygtOMEEh6BP5*8mRV-3E=5M}ddGLlGa*oB+SieLw-kXAtV9nkWVP4+73n}TPi9S1r zKP_ka>i&F0fZ#f$kd|3aA|LU$^`P|?R{b|ED&^u)m>W4}hfU9^qE`8$V2XN>%4_Nq zEOJV7#u-`;jvtC&Hd31_j`q(Dw}aeI%vBA4P6|E%Ur@~Zy6Yx|e~nL>0zXh|v?|_M z3TnLdHB+EpRJS@wt9p>S%)v-4A)}6FyMjM;MT>+}U3(m_`55%b{U>ubT)}Wj%zCfJ zk`;@%Py>;ma0Wqx{U%Djyl^IU$&eA34A+`Pxh%fe>U>c|uv0)pc-MOCK>Qe8gY*9K z^K`#Guo8%hBOg_vOophGS=%^*Ojq9TuzM-TDEP`?xG0r28$W`!d_9ibyRPMgZx#L5JS&8zao zz;BXZU1B<7<8-U^$vHG_iOg{%mk|arin~w&Xz@m#{VG#q=Mv57tJDUaBb;^~kdbqZ zVkT;7z97urbN8pt?=63Cdx!DB34OliB6O?sK9XqVC6I&-_meCYV<)fm_Q&oUl$g(W zC8rf7f|LU@N1|`nAsOGWtJpkEhuUOnAE{SRiHau>H2ys1i~m&DurV*ssY(4E{k}~A ze18#0wrPl!Ua{PNJ|$DiS&b?@x8I@=01J&;hBnxI1 znHiPIDh6-DGpQLHGaJfhRzw1A8WlPLt($XI^a6Fy2R?m-Ba0aIFplZzv116|7xDBe z19f?b{LXdx6b>WRib(XvwX5cLf4}P_c7`R%161gB1%J?)g`3$FSGOt*1pG}IP5Hp$ zk{Qx&yQVzW83v{69{R>RO$X70@pfgw*jEjk)8-F? zGZtzb^{Gfp!5bBI0{jI(nqsb(;lEi&?>|?6rvCYa)!u*g@n&a))Ii9|=Zw(wp&SKe zw7C2I2a`VfhAzzj(RtwN3e-(o{_gGac0NyzTK{{J-P!VY)cU>X9iHJ=P0Qs}yMF#! zbIT2j-eq^5q1n`>RK~PCcokwA`K+q;&PZ6mqlXh8{r@ z-R3dn9Znw=P{cL3FL4!65-C>=QsK7nvG1^o4XkfBF$JEQ#uT*}l+cbhtDk(cWw8|e zSc6n(-2A<8btg5YGG*spUyP?U^m|$RDYYiD^MSACtYrl>)rFEQjOJ2>T9uZ4KkZ#( z%31LaaN3a%n%!ycBd1`H=4(c8yPuZ1U-~?xItno4@+(?|A(pWw>zKbaR)jCIje|Wp zkei3zH2@6CUF;XC<$Rtz(eiA0E+niMDaAKR1GBG87x#E~zX@FXYO>VO+^{1fChtl8 z>1tW%zR=4%^==`nDUkULFTbn@>|Liw?XV7TR_OJ-Uqh;j)I0RI4Z8v} z%-kL)k))6P=e-6V;b+thzP>k&uA14RH`K5h86aki4AV5hDD*~?>g9C?fmR_;M$8`> zY)}8k=>$z2_TQpDFQaD`846pH$OdqtXJy&?1{zGk zYqx^Wz)bNRQsJZ*y{JSX&!89OAfZj-;{MzRd$c(0sXd>;d2O!tmVk(o z4RcZ^=p|fS?h8kJIlH`Jjt`#(;2OlJ9q~j0DK>_+DpHPMhpiz30?{~974?zh2A$giy`1%c(R#G4A#^MkaK3A|K z(x7Zi7EL&vwv69dhV{j}W|_m9YI;Z1=p_ge26^2($9Ls3RO8S;t8!VAlvm`^u2U?k z78FbL98j4P0r=SHAu8V5V5y1=)Ffs?Xe`Hu1|j;PX0Da0@0Kz4kI!X7fP3*pk6T^A zfvPWI%E0c$_oamuBd4INKG;QEj^$jBmfbs@Pdt%5TWT*ueilrH#5OZfPbI9-NBy4A zgie&AQMh_(elh{Q5W~$MC0FR8B2)kHnVz3R41v5zUO7yn`k&Z77RW!0K@BQSx5Zn1oykX zHE8_NRl=8D%6*_O#^FY zi_PMrH*L(G^8Dl^kW+q;AYH0AyP9+5X-yfm=aIu#<9krSwcaYj@?gi#BWXSzhMvQX z;%T9BaoNNn*cZO~enR+3zL}uRCM_gJ;rB1kc5GwxUC&muikr*wcwHC_DNw#SdOJ)c z(utFNR4-de05sz?K6< zWTlKZXiM0btI|?F2{JYb!JDrwjn9ggyo2yepSeGhD!xYE@6vlk5?_ReeGyu}<5>Wj z#jaS@hQX4>GuZtB++n0}^hqmY5k7^u;F1##9;v@6Y4wLu>=V;DO60ZnO*f|wz(e1p zpm$T}y`MAi&@Z^)PUG$F!Atkd+i$wKenTH0MQ80ch$iVr*%Zxe&oihtq_sNvphrkB z-L5k@y&^Azz@?n$#lB&PS{$6REgqMapG=m=UE^-A+EJ=TLPtQDIZ>8!(Bmdv*j<$Y zDH2fWbUB6st#>gZ-2rn(o`2ar-|(2{Wr%)pgB$>2dm{tCf)O0qqD`@;CWOBc)j=Qk z?H_e=zKv`)BFcM}r3vj~>-udp)>5~|W4w_pO%=U#FB9kT4T9lW|;`nT}bYD2sov-d#$8 zcXfM*-6Ok{+pC0Klc$17gh+g2rR?^MP)`$3cR9Y^lg%cA4zA$j#Z#y`X$Fud^;%=e zrV@1|LGXFw=@EgMZ_$Q({7k$~JDz>ub>Eg>x`SC3#0Uee-15g|@ynHkE;lznr;6M( zw(SUoqHkIqv2&WwzRNVmSgNO>?o$$xPtxU5?;{;Fku4%B=P}Pbh@O&8=HtElA5C8! z7ghItO(RN|G)R{yDGWnN*N{>MNDU<_A?>9kq=$x?p}SK-LZrJ>Kw@YFNon5e^ZUO4 z>BZ08oPEyOXYIAtxdOax91&ydarq;0cV8STeL1|u^Us|dl-CeY=<@Fw9!{IKe^R(e zRn+RpIT!Upsw*v;@67=7oObij|6b1nE#X(g>J6+7 zur_^DOmiikcc7nUDdg4#X2nZwLqz~KV zmza?ejEw%QWL47@OT)Vv$yo>$TZNlyP@i7)x9!~~cPF4?z`A~DWJBKuaO<=e372(e z<`@zcWhe+=n}OR-YIJx>9NYM=DEM$E&O%g>8=gq+6swE|WtYTms2BKMkiAa}WO4W1 z*&jo8tOWUdcT6V2A%%+pd|c56H6tTZQz-{7Zri8dhI0F%Nqa zaz>G|b7k{Sh{cMUMcHcNHXL7WEAkeUnoZ0~7cS=TaWBh@R(W8Yd#+zfdD$_a4rM#- zBZ-a99eZ&8=#r#%Ch%LiVuY%Xs%nME0YZiXfQ0A3vwRo0U6QxKZ0>2@ki{x4w2@`? zGIt53dJ`F@t&`5x6mb%{ltcfHEoW)$s9Du^Yakd^8w)nZHyRT89)9N-jG~f?OJecF z+ze$8{Q@UhHE~i{OpG+qMUm4}Og!dO`>)=qa98w(xz|cX#Wkk0^%>v5w~`^b5>fzw z?;4OLIaY-;1?BO;(z~l$;=QrKg3u~uW5aWT0~Q3%BpcL3R>>B4Uc8=Mhtg?HFiA;c z1&zC`jgUAA+U$`&?ultPn<$bhTof(*01XM@CgvCCNs6!fk+m)umgc&4Zrr#!G#P7B z3+bBbApuv?#E_M7f z>iKZ%Scc^z55JMezp=q-8Y{v^ss}QqF59+Y$ee1T?zP&Kq%^fcM@Y$PZr^(n#cSvzlF_=n4Nu0)iL zl`3&Gdee!#zdo9dNuZGfc;4Rv<4@rkek*X|{pX2a%gNG=Yt`u1dv;;2n{8`UCmTc0 zaHr>MEo@@C7%}PZm z2*&c<$7<^sGA+)PtU?k8kV?Z95GxiRy+4{ez3L=4nULzL?^)Q{ouUy(ON z)D*hD*KGzA4258Jc87ty$5P;FnqU3yE4Xo2>CTRq`*qBHw!Fme(1OK6#^qjkG)Me1 zOXA}WdvF-<{~HE5$||!!I$a@udFd1Rmjh*Y#si|D1(nOh*c3^|L>;IX@_B0ZJxOl% zAv5US{Y${H+0Uh!wh%|Hd_{2E5X4adhWub~oLnqg`Lvs^A6YBbJCX9VvRC&>qN}71 zD=Fz!hnm}Rc(l@0*;jXyoPHRmd$i2Udb9my_jtm0%Yt-uRzhf8ad(n2=o5AzqIh1V z>t?S7bEVJw;b-o)%=uT>6zBepQcmv}i0kGL1auwNiRZ=4UPUR<*p~J~M8Ucxo0v+) zkoKo&0BQ0HT_wb93#%XM*_cc&Uy$`xh)!NmhG$GyHHc))Lf((@%Tx!Y3c#pz-HLaJ zQF~Z2H(ru)C!3=(M7$(3$hK&|olpE;h(D(0P28EA2GjH_B>wBpyA2~A51#MMuryZz zc@4Y0Ds$5t9s#F9CBEWKu}LL{5M0S9qYZX_E_v{sYZjYo(l-;tTn6%qSycT*nWT#F zUSj6?9yq3Lx}g12;$F7m2)*=#&W=|3LtGt$=L$g*=*9RFhei&a;=dSvV-JZ)8$KSt zf>Lk`Z}=2wp_h#M$k^Up1ebX91ptwGSMh#D09HTyP&KSW;lw#CK~eaQmJ(CyBMZP7 zcE>GDQj>k<#d+_^eNs_-=|;z)nAqs{;w~2Pz{4{Fayx#0yJ7Ci(&gN@31HcP*E%id zmO#q)oN$_pTpb#7Mx}_5vTbG1`{a1}I-Zb64RoJz86352*YNIByIk9v0tLS^y>+rK zj#(KPc#6w3GQbgjBE7a%AKQ50by2-II{NY*i$bWE=!XJ|gb)gHu|dXKIENbLhV@e@ zRpUdFW2q9ArYF(K2}F8=CKhJfM5F7mn7-cNFnYdwqrNsuVV(4RFiGwAKO)8A-sSQV zGT47as)a2EGHGgvjzNgvfRvh~3+H#w6g9~*#5+r=2cr*`1yh5m)aIpqe)EKWnb5Qv z)udFg}d@}QyQs<&90v_;qTYQ)G?s0-r@Z}z$d z&bu&S{gGbwx-Cvh($hNv5UP8s&N76ki68WZ_L#eDUFv9IxG8)Y$n=(j6(=x*=v}f% z5NQJ2bTg6Ev|Yx7OiFeCD_I($;BE9|ua^nHUF>}O=u8Dhtt5$pORD4JJh)hL=dOrV z2IdiYKRO5I0v@1Ny<;2J&fHF{GZ~#G%J~ztUK@sh@g75nQCy;Kz^j(ivBjI1ieHjV?qRpBA68Y?$5ltC>7R4k ziI}Uh7zekF8ETCb4dzcz7i~p%ZMx!vXOf|}A1ZCn&TS|W)iE7sF6X~m`+_vUWOhr+ zeoc%nh~xf;B=;Yr#U4R9^Ua@u0=s#ZAymZK1PkJ)o6z;UQ6 zPJp#z#=f(OiP{^dj_;U38eGU5wMZG&(hBeF8b0eT*p`H)zaWFOr_e4oVtq)Do;9AZ zF|h$I&pC(^^{+UVEo;a^4NvUsY)zt-qVm9GqszRzy8UJF5f?{c2W;VUFtnpn40|vjZ9BBQ^#xe=8gm*SIDZ3fxsQ2x{Y?4@D2Vf2{J8`!*T1LBtQ-C=>}yC!SC!sg&wNIw3r<1%jJ^Ff z@>_T7)d!#3_}}UK{X|Y43to?zr-o)q2n@KNN&Nwo9b9`68&}7j?a8NT&%L#sC(7RR zk4*=tf_a^|P46-vJY&{M`$&0Fn`+JHhW5Hxy7bZ6HJ1TQwR|7@R;vvb?ReVIt3GXh z&8_1hAWrc|ooY+T!8#3pq*ohVKZF6%7_3fJKuj#lAQf7L9NBv8WoCKUU2-A^3w3J=}6`vtFVWNu%)~pkS1v5fg!RPik^>*rWmEl(FVB{@F%=r1yOt; z{mUT_0p%Wc5qOOoF)XyA1L`7;gA!jy;!l|;bbu+3$o>S zl8#IRM;w%o@U)b|o_ugntF+Q^vD)5T^Thm2ua|zaTt@CA1lGaeQ*W;D*f*{C-dv3W z7i4(!(f)6loALYIfA@|F1%UlGw=R#6g`T&ti~Dy6Xit(47<$Zk^Un%bw_m*fIY8M7 z_YVClwCKC_$Bf}orOmUynzo(A?aW^Ex^`QT)VpZ@deEOsS);QPE8`k*j7h zg!NB;=?_SnRk7I$=gKpEi#i@Z?Rx6^G*4fpH$fvY4_plV%wsy~C8Aog6^l(?s~5l9 zlbypa!-lz)O|6|`hyk9C^EUM(7u;|GT}Dk8hpB^wM=>AY|J^M4lcg4g6#Ul@xzK*V z&qrZvk7NDVcg#^I&K#5JjP1p#o3+M?z50qJSwQ9?@Z}yZj30|+WMFLv8lokHRp*XF zUi?=vpVI%SV*CRGo8A8aIo8DbwvuEk@MmHRFnpV>ENu-qMfmqNu{KYR(d3fY&R$YD z2NcmiP)YBp{u4jvS-$B++h44c_BJzL+M5uyQxiVRffB+>VQ}7Z4LO-bM~aICZ7LxY zmnDa<_8%==CC3Ayx4X^9e}AQxZSS&xq@1C*0thCvs(mcI=zk=(?}6o*T=tvq;h{mn zWGzS=0K2vBPG!DSAQKfBi;QJ*YlWZD+ogc!EyL+i%7N74J-bM*WVX%`cPedS3RJmh zL->=oSGw9pTiRlT9aY@}X5X&LJwN^}In|VNY5nu5_QjwPp^DKV+dqy>coP1s;3Cs| zIQ!xi$PZN(8fKWlSoA};YuJm2`@baGPrn45SrkJTL_Z{X`B2MY@rt>F6~I6Z!$QMm zBA9=lL7Ib@G6SAJVGPotVHjOOnk6X~kcpJKt4VMNFTSP{vyRKAHvEHO#H4@tk$mhu znG#4Acm&{0^7N04gk@eCRLVuH;VFcU)UZDto`iqNfCjtp!1ETwH>BKppjI*T0BI*H z!#g{EA-m!A*dFLPFSeE5TY4YP$CPpKeAwkXW&3tDB{WEBAe2FJ1J;hv3+&@4Qs7MXG;*gTEA~(tnxF)s`_tTiJMzKUgM-qr4%f?zqiLF`PN`sNmav`|=B6&!>gRDe`t#f`e!+c%kW>{1T{S%*-8w|Ob$4<- zE(Izl>2C8pl2#O$%AOBY8%UgRLVeZZx}CC0Ii5F3*U3IiP{hv_G-T9YIT)zxrcz|4 zb?qn-%+eq)gA8a(MU*~B!pl7F(@R^bLtP7 z{k~OWSvEq~;o=p=i)ISP|F%p4>7(L*^wGzZi3q9ic#aC(_FTUArA#moS^VL-Vy)Od znaFMdX=8FudJnfbHE^{CDs|~$SHd@V;UQr3KtXv%1@@&LtSayL zJAh=FNjpxU;dlBG6I&Gpv^)G6&r+s$Oy<~-qGEiq3fB@ith*3ABn`#8cesD+D}Zp0 zkT0#?x$_DC;fk7Ps@tfljrqSMbw0B+hhpX&r+D-tII+I$S#E|^RQz6FJl^6+dpj`?l(T1sl7ZZYF zwH)q3t-BVLVuNvs?OnZ7^o0G*_seh9!d<{EL^RkS!7ep5W3|^G3NfCg$=BxXZKpz; zF>}udI;h@hvyER{>ixdekS>AbB-FV>_0#u{$9;!pHxv6(iPT+;pqCO|51=K++<<@2 zdMv(%z|w5XFmT{O-Lu!r?k@{A!M-S8zaPwku%VX=h~z@bnLmU1mS0~Dt#Afhb@p>X z0#b8*#>`77y-f7@tDgPN3%xXpY@L^(DqglKIbv;0J_A?Rab1VABc>iTTZ3Y4N(GHD zAx0f-k7JmFox8_|$0%?T0Xa;(cxomzZ76i=kuA+?y-*m$P3W(2PkINU2`+D@Ny1)` zNmI2M=yY)*WKJ4NGl9h1Uip+Z*}fA5(Ssv~d)*Cvrl&vGNhoTZA`#Ou*&9m4VhaAr zaE7AaZE4gH@#p6p)LZlqh-2R7#dj-B$ECBhamWZeTI2$gm(n2!_6YaJA@31)h7)Z{ zE(6*`;rsnW5u`8S+HTCy-0oIB-#c67(sEEp0;-dOL&$j8UPq^PbRv*%gCq$fxG6n1&NFv%&h^ z8F~X^jU3$+)!*lq)_6<>HIEk#$ML2j3dI^t0GOKFjI^WWKGXHec+MkMX5iia*?qDY zmgcBW*yrxm-!85^x6}qiPf=8a$CtT9jhPDRDiuAe7kFL-|#Lhq;Uu zV8<_(B#st)Z+-aq%i*}F9a46ep20_BuEAxC;NxepDI(~O!crU$3F^m_(O{Leu}+t# zK#t;)X}l9O^Wdz`<3I*;Rz|4ik)0A|X{aeTaMx|l$m7>x z6BA3#E1ow2VeqCd*d^<8i`a$e|Heu{OTOW4=5d&GQ&n^uGM5>heM}is;C4TN<6DG8 zbO$(bGq20UDLgS#<|AtO=m13B3x*$9z4&N%)c2t61uUuQGm0*xBNRICt3KR; z&O#6>O{SKgR3Dg9zvxowJ<>Sb?nx)&lxdq&^B&&@x1%E9#=aFkq=J}{mgaQ*LiwWl zxxH&I=?LZU!>?M$%&CjCFZBK3OEw%jWZ20se$7s7fxU)nk#E4ri1kYGF$yHezB)5q z!0Mxy4u6SWIC?D1iceQ{9#Z|QNc{2KECVm%(saR+qzc4I8cZ^ij1uO7T!@BJ!A{EG zgBN#B0nD$&y&QGSOvx+h_l|2R+FN_v{<`YD8nJ<1XhPod_qiYB+BbgLp37 za7z9k!VvinVZ8q16xQbIw$CCl*Na{KZRJYFEq9Loa{TW*2?PE{0X0UIm3<_w0X4a) zn8&+=b!qE**fIX3uuS=x6O(!|YF-;J3;>A>CBz$5bO0$im7nS!Es&mpWkW6$%* z*yS;^A0*r_z%s#BoWrH4NJXC50`gN~q<(P4W7In`xo;62c|UKj-<<7NOsMwmZ6E1E zIMG%6#0e0_TmcJ44aw`+6vQ}Q&1zmL6O{RvG-p!Jh**8msq0Dm5jSgn;2%KRUm3pNcMt9hU? zytVVinW;q|g3A1M2(5^2uj~3K+SEt$c)(733!h}J2{8brdUfl$u^F8riZzwpCU&aD z{Y6kS25Ll6>HVYbHJ7Qk3Sc5S8fZvcrp>QD6GZH~#Tzy%{{Ca`FuuP14|G6g1B^#1 zfm*%H;G;y)A;%FCnU-a(QLO(F#CMaRnI+}$sFyYR<2kwLLgtk(#|LZ_>3tJ#`1>J>UMk0vTI&Z?i`ML1vyzWj&F4&u$NR=yGB+KX%zeA!OqGNLd3Ojl2 zSF?|g3VdKOa$nPR@+V({E1*$8rwvv*-!)HIAH2tMk9oS}J5bT1{mdbn>Gx$0&l4_zL@`;u=uh)mbd)=j#kataGB!B46 z(-X8l7b6HR6ZkoJlc+S9RYpSS6*Bz1jt2?NBsR;XVhUFOlvSxl!E+4GzW%7ie&{1# zlwv&2+*a*`l^0!FA`Nylm+_yy!0NdvR?<+G)XOp7XJ{!8yt@e732>2Dq_4&m?d)|# z?bXn`v8KW);-`x)M|$ckn{3lQ_jF}lTJLO{QyENt-s>3@_$E6J$LGi?kY;SEUg!8; z@~;G6>91@J5yWiCWc(rtC%pN6+as4rM-UN0#zNpj#~Bhc;1Kbohtp@+%w}J`?<5p~ z9i0~v3*QH3Cx~PV7fFJ~aPfl;*0Q9sNb4fjtm)kD$TA|DH#U!SzOec|pKFGkok z8)lFGaFC|U!Zd=3*{3&IdJsppQ&XrK1u)|E2ZKY z64Urs>%Ngs#pX<|#j?xB>dnCM*T=WRBK-Da!UI-}wY=Kpaq8Uc`Mc{O)7O(`fWD>w zDrRT{NhOzZTz68BupsmOOF~VS$Tu z&ICNtx;HdZRIb<#ZEvsrjyx{p0q!z-b;Uf=i0B_FC|AsZcIVWlAdgc_8Dk&WZH&Vk z6J39Sr4ae^H2L!<6LGsP#E*NnuGtzmcPD+g*FrYSvxwsLapn@KxZe=nDYO0>_2r=C zQuX$REnTs>bq|_ce^+cv+*JVXB2fFtFulL}ZbH)=BX`xC(}bfl&VFdi9^k}+qW3KZ ziTZ{lud(j0iT30EuU8s-uao0qDsT1I?4v&^QcM0$z>qrQ!ff_ex%oL;qhur`?&rbp4oKU^Rs>?wN~ zv{|Gp65zsZ@OQV5D4~8M$mmYO?cd2t?fsKbdLd1go?L|=T)jVov^}<-<9w|xO$O;= zu6SRKI2>)-qA2boA6t=G)FXXHZ8&L0@!sZw8);(rFvk}G%R*!lP_ZV`*V)tOT|a}2 zb(E>946{j`2-;_EH{om53PJEC>2J>_QVG5(A}o`vBu-V7ZH>77Op|f5eH3r}b0_r} z^*o724!T+EmOPTFT_75x^UMR2>b`z(;0~wSO7QxZSgCNN>_FLk^&R$jm(*E$CDL$T zj6SZ4dhyYcfeNtDH%3Ih5fZjPp^` zKO0y->@YD$N_^5IDC_NCF%lzEGp)avtX>eTmDI0_W(_zPr7F_q?p+HiTRc~5P`K^z-?7k_%=YAbZ8*D6{W2my zbteD+rKHJ69*o%1%sck|ux3r`=p$bCX!6oO zrE9hhk`N=(nijBM0c~xx zV(k`hsGr}Cp08g6UpG}AQibfCYFDK;D*mTU~oIZ@_>;zy_p-kU;qj2Sdo zn`JDZem^!rk>5*|Pn43O$S`8YrPkE2S}z^iQaE8TSR)G#Q32#p$uFA}+mFsg!=%vxcvI1`F3k@@>mw9Hybzj*Mtf}Qr`7|XVdpWsRF~ILf)%?eQXTwH(#NA zG@X)9$Y-S~KKU92Y=kNl?Vv02K>wrl!mmUsfSvj7NF=ZPPjl$ZqSx`6jz@LF-5>Y~ z+`xx&)~g+n1olU`DPmk~VsOzdXj4hC^bc#(TM8|3-KTPf`)#7|l6GNpCWsE%!w9-c zr0kSHL+Blo>L%IiL;}Gz?Aof_FdGz(7$Y^C*BG=?i<+(BIe|%<%D_Mtmd#E_5lb|1 zc(F}Ns@TK)jPl}<-qr{JV#p)2a|Miz|Qv(s^X{z2f&}{e6nXY(|1wHH%pjZmZ~?TttwmN zz3T1~l#2o~adT>vxP^3lA?mb6GFp^`g>j}9!Y~-?{v?rCt+848w7<6#?cpEkrC#Pt zQxtCSwhVf^#MaI(us~~N9Hfx^+$H5jSFk=&9NuSLY5jypuuQ3;Q;r%02yYvq0i6w6 zV^$uWj-q|Ala&KY{IE{Pk1&NM8~wahe0}W)pf@qMx~AE)X(_SO@u&}WhA=;9+d1|! zS660k=bH>9h&BU_62|5DgWy*+4fnmCvC4wY!Ylk?I+%8h_4-I)wR_jH+vWSMmo>b2 zQ4bNz2}BAPHsfF|oQRPU;p=1SyZavwDWW2u0njYJsAuc-y_L`-zWV{r6; zwjn}&+@IP%Rc~O?^08ZYJt)M2rQIz|o#cC3xY%AK2Rb`-bEvaM;tu@UvhEC~u)E!2 zi`26I^10ju{EEm#h~kn$^ri2U--y#|tP#yyFLzf{vv0qjXY{;9Ex5y5-J>5S z5e-hw+Q{gBD|wlf7M4AZkV*Ks3%Vh?OuVT8ZMo8~jiOmfZjI4KzlVRL1uo`O1fv&< zxX$d|HpaU>xjf`vsrA=6OaGxj#0XBnsah&}Bb<5p4S18{GbUc& z6(69!*xY%ifiqNfy{jqn;)5|dbo4b*)b(}+pXin(>+VNlhEfs^DQaT#$j@zPqU-wr z_raYGrbjjI*@FdyTGJ>{R0$y`qOGj9c%v51EEa!rUl%32F3?~?U|7T~wlv;H^-kzS zA>mU?{t)R?u*RR1afykw8O|zHA)yVV(uJ=-kUOs%XRzEtYqG%l4$UEzvfCB=+i5Up z4{~Oa2r-3#QKww2+QMPByNtR?eBi{5cuTn1mhyoF&qy_2!rn7bX4fL=`y5LLEzmjE z*bBsq>s|Kbcb)dvm?>c&4kSpNCwJH;1}CA&P_rI1;A)&tzitJKyGH1PiN}g}KKyR> z>0Vx4Viu2isKI3wfl(2WQEOSW+7zQ<00H3^O)zK+5r%A3fo?16RDjK}DUObBHmX)t z!;-LWWs(Bd#*(nt)gXYYE{MR8RwNk`yZeBD2)?tMX?;u404F0)%17f7o z;9_erll|Iyz1?Ca-3PUIuLB+xLw7|u+e zWaA-Syb6orLqShDWK!gfot=nVU(ok76Ici=6gm+*pzu@Ym-NljtM#ZF-qgslxCfuO zND(DlbQ0Pq0@R$p$a`K!?)+*&Ek=C}x_YA0ki=m&!O>R1+@_?ni& z_^;#RJs0Rg9N~o5-INMxM!C0UY|}CJWRW(vs=f@uldSXi8RhbC+~8`fnSXYk+?ej+ z?w}j4o`?An)9q>5$}$?KtwmEtM*Q1ZqCik5VBdf)IrVhP4TyLTo*~+(E0D_i$~&Ay z7!rQP@uYDXHAbz(5PAi=Hh%Gadww2lw#@hWft3}W68CkXQcXGA8-~=Q_|wW`YbXJKpsR+eXKd=!%U?L3y*@r=Y=oqAP6f9wf> zc2(O#oapdnj=!Nes^fU}Od&e;u+OWnM!R-|WN$Yn<2dbh%^n^0xP_+Vfuu>BHA3fh zfHoUHOZfypZYH=|P{9S8G7S6)#X}$2l@c{&4~)(m(|wBZsgB*abjG&zTHl9HUccJy zd;iL~b>{QxC$l^*iy30Jn`@7=r^8La&9u|4f4e4@)s<{4Px*QiSZWr+o{t$Diu}9kgTFe@D{lg(PtNN^fqA6#}^f^cY ztQLOw1nTLM{J%i;jET8r77~3uRMZefO-OP zq7*qpnnj^6+64C44LF0kt{=J4v0R60oQ%J8`)KGk1GP#{B})*f;~S?bAjy6*4KnH& zy_5Be_wMkZ9+zu3kAvBr&|7w6&&@ZrgvuZ0lEq%OS%V5(#b-Ji`{InSa9`+SewR4- zE1pA8Ny?d9q+wuqpHSep_oNEBv`Ox@u7%lh#+)wSZDS#fs6i{!Rdr); z1dkWjU%tSOt$1{57ipMSdVO5c&SPhW2x)iPVc$y6sXjXSUTRgFe`=sJL=Y`i*nU4{t(!T+}JgglH`VLHd5HkKQ5jU_QjMKH*i&L+vlSHP*5JD%b zT}RkjO~Pm36X`D;SndDDa%tzmPuM$y)bIYOT-0w0!|;V1(T#?cT6Mr? z%m42CKwa7bP&~usBoiUX1aH6KYK&q1mU~a*IGmg@NA;J=qFVCJWAz(WFAVcntzg#F zZu%Ev$8xxjM9&Xc75Q{-MJrrE=YxIiXxVCOVT|aM*jhSKYAxW8$_h(0b4%dHmN;EQg zdA@V_hU!)6)a!5kLlu*d>YGT^cAZ%wImO#_wAveyW}YB$_uQN%TxS3i-LCHNqfHt5 z|J+tbIqDbGJ2BkjE_`XPh`-1#jS6*y5?l0)UkvQzvKsCSPcSI3U-#^Mubn&=TPNM( zdCmiSe(SQoN%s1S4MBT0mZ*f9Gkfn=4XvCc?=hZ(fytELSnvaobtFeQ%7Q2ET~peO zu{Rx+JyP5@fxyJ6N|f@CmUA1S5x?(v&PVGhL}YA@w3yHf;=e@w+#GIzweu;HQ#>z zY7v;W`4%xmwcWET`XTjz7{h<(j(AM_(;$f~&KjKuu0LrZ$laNWyssJl<5UGC zJnGx72UozBfJ0Vjmz`*@%ej-G&@3kPRWGvA0^4;-AEAJcAe_noTgE(tRIh&yGTi`LC49)u7qSE4qqCdKpTD3=cW0B|mc-TA zMMe%%s+d}`+DBSo#IEVw97MOZcmFkQqkmhrwujacGjc1=eXUW|b3`?}dAC_doOh z3zh%c@1h^~S6}yl4h%gR;hz`;0N&G1QFs(Fo1e^io!U<_?8%6dy>vwVmExOzn6bw5qBih7s3F%~IpG1`-$PD}cd_c`3+?-{BhrctYAc7AsuaU*Nc zUVeqMtm@Z*K+)A7d^=F=8lik<$57g*MDQYFj+niQ=X(bg!rWbU`&PtadpsJ9=UwW*tJxDT6YBKX$mU6n4@H1FxSg- z!q(L;vR;l22Dd}uUpe2ajbF*6q&wwMvf|aH%Bo+)g=6G|g`mu!8_wsZ6^LJ;96=B; zgRC}a#}HWgZxew&w@u)wpoxE9V4XsqYDf{Mcdu0oA{7t3*%dt`&m8Fal z1^d~2hx?{rKU?HNWhs?{2e@GM-Jsfz)!8dI&wMPz~B)^uL-C> zrg|hBMhkWpYR$FMle`QKK1{3mMI(Yt)w=aC5oc#P;LYXElY8>C27{5m5uu5kBo3Hh ze5(Q;3r4jHQNw>rjVKqynra9kyR%EPCKTP{+26HWoT))+i8sdxJEcPlN#c}omus9k z*P7V4VjtHcjG zs;$~E5S&7>hm39x2I~3*%<%S(7fGM&hiy!Y+0L`bT}^dTB+yFSeW66WpamhJgEMVs z{5vAln`^upOQV>Qq;f#Qo3{U1whc-nc$+x^5FtD);s%9beN-8Jf4?qh$JDDIBJGP| zx$Wja%GEaCsz%v*tj#75Rt<`z%|i6J5I=g`_PR6M((JMgUKZ?&OZKOj~--GWjDlgFTK#3q4Hv<>E|8n zF@ku>`6fXGZ-i3i#fXeDa^-{Sux)7Ld|klWS|`j!J1R^>n?jq&ch$50C$+5RGNNSc zHFwOp2Koh#RuN2Wsb)mgfQ&0I2H@|9pups7O%i~~$1}(~>vRb$QsglcL2X`3tG;dZ zzG_?eJ=`MGa*LjzY1ABc-B#lj`+zhpr8y;fEG`4O@vZtI*=cuE-(lxbbiIE%S+~XYVw7qriu@2tKo8#Pxob(VFE=$cxaZkX* zhRk`EX0V>?U?l1Xq$s~!^u@ew;XMi(4SVw;^+Rq;4JX;H#yS&Llh}@Ku!ay3 z?yEhfhdW3P!~NxFK>Ew4id3G7RCN7BO{5!k>PQaaa=`C5&!d|+uY(_I@LHt@KS#K! zq5JPRYwr{I&COFzhjrf72kS+Vl8Cdem&Hbv^pp{;A z!pA8Ee5*V{e)IU``S3!M-`SXe&jzf3j6WYJP+lNvO_rfXP(KxINWS|Pkxw2B0~?H| zx}Zx*C8;Gl_o?n7T?MVi9gV(D>DkU370~uQTHS^Pd(TuFACMG8%o#)1A(_%6Uj~7R zCQ%VHi;RdE^GK7XRrk$MH~4^kX=D(3&xyEsJ!Yr7_Wa29o{Kv?UUeYjy8S-sTcFwZ zdhVW&&SI0_^`9gLiikxr5E-#k?iW0hYWfGZJ*KVXbLWQTdmy50F2CWX1=rw>4L1JY zJYr(>>k%Kb{#j229)V9?3hO(JH=*1{_f9@IUf&L~4EOj@@K%3dSFM;jJ?9sc{}1~H7BU}*S!xIUxc=UG ztvebtS5o&e&lkkzL$Y+eWUHFAUhn(?!L`fkYi$pkyWM+*7cP|%Xcf4A*q$2-IkWnC zDEHm&5V_Bbg;eTn>6h>`m)n7OovR=w+;8xQmo{Eb;fvtc#g2200Q2|)53avLuhcS} zQ3`LrTXLT?X)d!8SZIuo*26YH89^@ZC^+Opki|Dcb2cj}FL`E&&hsg+F@?%}X&18o zjgNUjY%w=lu{2@EW!EMz<7yc;?juVz<$Q~n-yOJgNM#HnOg8VGnvUJN=GbVYscGAGESAYV_GVZkY)jUBxS~&^39BxZ%~nEDmM2mn6dQkg9Ijv>WqNG1`NXkWU^vL**MiUWwcHE8i-!pl z(-}7f2gJRG&(`aSO29D<77G+-YGyoJ!AvL-R0&q=2v)g@Rf)&>S@r_wuf*fp9!BiC z_77d?&)cf{^|A_CeaKVwQ_jp)4HAFHHi)SooHkW8SCxH9@Flf^;}_QJ5AIP(?w=|Q zN~z$}-6<~*H2aK!i#fI_H`#R~qAKeh7HubRL?+LFNnu{M@!#92aY%=TrcHt)FX>oc zeyzZFZ^uBxiKUrf=oI)9w~wvBm*~YVdl8!OUqaVRRg+a0!vn_#*0vJ+MHAy^>wc`6 z#y|9BSzRFJ?HnvtDB24CFP%oRY5K+=6_UY(a_^J^>K`F(chHpg?_nv}cs z7k`&Jc2INQd}yF-E`fHZ15K0nZ!fy@DJM6=p3Qt~&-gi$XyKd~GRc|T-tyAJ=B36# zl^d$K@~@{!@>s*h=O=};kN4MxN%uGC3Z*BBSgRsB+hdp3vefOy7P}{itHz!5 z=0cD4gu^R`NKo`z4RAR6K9*>Bare5=gs1xumGg7Vo=(o)Yp#?$W?fc1@lZ12%eKpf z3FQ$lsc|BeVcHOd$eH2Tc-vtsU**4$NlK7vmq3lA@d5;jB)=ZJx9cQezJkg`{}=Be z``=OAr1>Y?KYck2$sEnNM2SfTTl6Y?bBd6HNBq7yXs2aBlqvMjBe?{)=D2z)Bc}j# zg<)%U?Bwl8UJTd!r~%{>V(qwr6CH5G#=*hL|EuaD~dbKARd&?PF9#%y)-EOMG1CBgQ4Lx)cG5N_9?U`eYWpF4K{c!yK%e04EXqmX=PaiQ<@*-7Et|7q1CNUVpB2`L} zvCd}L5Jp=?Go-77%<`nytjV*F{WqF$9z##es+s8KcsC;KsS!-K*X6>ny3D7e7%Rrt z;or1K_w*6*gON2X@n~%O-CiWyY8K;xBYFL&>U&4EHqmwt<;1jFKlCLH0_=3r54GXe&av;*o!DfaHwF?n9#?Tn#HLcc04F9{32&^%=D#%Jq)N4c z6XUAR1pc%9)kd-B`h@>xriS|ewRPq3P_^xU29=VOHDuqJu}78&m5}AJGh`=aD`Xo^ zQiMX58L~_s`<56>WJq>ni&P@Aj6E{evHs3T&-1?T=jR{C?aX~`-|Kr__c>?ovjjhc z^%(;$4(@CFTto^ zJ%|LFDt$Z;?MbLxbF)YQO-xojGLe2JPx468oDh+hj+zn$<)^{xrmls}Px5gEEc;i0 z7h5?=!gDU7)h>A5Cu>HoU@M<_vMh7 z`998j{#)}1cXz=M0G~ky`Qhf)eaf2K`hDxtHvRR`_!=WKI)$D#U%RTVR$MufSAy8) zOs7FHOdP7PP$5J71QjitwP&^@B4BuPlb?q=_IE3-VvAQdIm|L zHRdXyHLjf!?LT@@EsE#P?eSNMlEH#3PJ0FB7Er(+ADaQk-m^}IWA8tA`f+W)_O$tZ zyvu+y=~du+Lw6f#*+kodo}Vu}PokJmz2R=sj3K%oBO5_qGHfL=jspIHo;Xxq|sW{AK~(ftNucR&-Fq_<}TB3p@JslCjctZzRI z!{}BZ<>sll6SK{uPRzgWuT+;~Lg|<3)pftyp1^)-AZf7b44eXq)x64F#RM!1ph?qI zC|F*sQ#8Q{#0LNZ#97Z4%mDHkLvO|HejB3z#R^m-<=jzpg%LxBBT5s;w46z9Nd$5^ zF8?P)xE$9fWQItEVg4&X4;B=hCq!nIADUKjs7OkQ@GI z$e9FE!XeDqsi41M#%0V^mbe*{441*X6g}8ZIRf+I8o;nYCn8~gh-NP>S*~Euxo;A) z{p7rH*7E}0VnyGrIffwD1`ug~NNM%sCK+jdLhY@%5PEihi>MZXH&dwIs&1m%`okPW z&D*zyQ{ZH84V!y_>1m%nH+p~MbDk_B2HZE3|A9wuZn=4zfA{`ppjU2UY9@LtI!JNrwvK?<8J~i*oi$7`*YfMU^`_TuBVsTA z@V&E#gn;TL*SvD%Va+381yFQ7YK`@MEkpNrzdDJF$zniC`AmUY;*`JLb7Y+Byo7fi z@EDK6Aq&YQ{wICO1LgOu{ihO=?!qV~h}2aPJfZM0_hH!om#g&TT>Zd@SusKv6o19L zEMcc{PGEy_7$>zHkp}Ltcj55QWiC2joYjN=BZspl^M7mi=eM<@f zlG-qt)RM`8kxlGEbrMrLfkRe9S*T2&yV?>&&Xr+4m9Qeh5szECSX9MW<~DBO{9e1_H~y zpl5AL+^V%7mm_kRiIG!A$#Cn`lfm2O()hOa-&Gl8&`p%d7qA*ws9gVDzUezO8>+in zeF4xxpcp5(7X&qOgeK;)P9iIKTgm=i@IOh3hhYxR_k4u)qH>v~)FW&5?3scsM;Q3HW0P9E)tlo49w*h^Yj*f*{A6|`X##YUpco?tZiKAgqv6a)=V=?A1liEIN|?-s;HCip znc)xVZ~~;mym*m6)_`Y#Y^a;$!-r|dhlVJrGjS;=*HmpzkUFp|)vw_muwT6M%Pd6+ zLh>2=#Gbimp}by6($51o|F|8;<%!Rg@)7e*#x>v2QN3Rcq)oJ2T+BS|BiTHa{ddj4 zuT!_`$BdfS-`fPbBVtFl=k!;(R8R{y(bofji>oz<{4{L93D*AeJ&P-Z5q@eL=)Oc9E^5WE~2cnYB zc#j6H6;`lk&6$vqOSBbX!hp~B_M0L5w4vX3rRN3QfUQqXqQOlOV@>cUSn6>%M9oN8ZBqN;?CcAFW<^bm3cn0^?jBb}E=r^8Clh?;Q~i9wDwHzeKxlSzt&z|G zj$`oQ&ynOMhIC6?=V5bC9w3rig`w*z3=-)hQjVgMWp0MZ+C5vr;wjwZM}v6#e=UiM zc5~4&ZAH3k*U|jW`@Yhw2Bu-H!9SxA)ig%-KuB7Xg*ncsCmi+cJi92icu)pH3L6S$kX1s^qywJA>3H$G@qh^CVpz>M=3%c<^ z-E5Ff;g-*iE-2u#a%2*S=DuD22mfQmp%K!EDz_;kG)M`;D)-)^oIxtfD|h-M@u+np z412?hZgi$|4rf4JPz zxz%v#VCt9PzQZqy+C9MoB%a%DnHPtuL35Z0-d@KhK<% z^U)k|1#Ep4y^>=lLg4kDjdr=jc0S%lyOC1Om{VTowP9yi+~w#BPn=2WCKs$IZT95O zpR5jl*{w1zTy_7kF&sOVa$Hk!o1D0VvIiTkf?n;gHFwR|uX z71y50sZ+R;0E4Ezbkmxcr88R>K^q5k!%V)DAoPftjZr18hD$+zdq_UabY1u%G4F5# za7)iYhSHrLP#Y<2xpU&YbC^|z)0xwhoOc73iC&^oQf@L2Y~P2o{>7>k#{Mq#oEh<} zi|wrY#3Q!-&I)r)I%C_feH^U$8<_}^_4nWAQuJxa!1!=!3*c}Dl1#h&LHYc9^FkZ(i1QM3x{%?Kv}-=z z%*42oGXgRX_bk7&fiG&~EcWtdu1e*bR$D$TjQkPlCw9 zhm^g8`d8-(*x!*@1Hm)ehSW*i@<|NTVmH&CxKB`1;}|ftH6qeC-A`yC5o=_rQ5CAl6PxY8!K?ByLPUFTmupPrXKxE zk|NV#7B}7BOG&U8(R0{2I+QAd%0`vi^m>f1Kpb zCPJ!!*KRfdd&#^2W3B%LWm0i_fW_eQ$bo3E-R;|c2gCR_1L_o%C-b%%Vq=+xN2Ax_ zhLdb-tW&sK5Nq92i7=LVCrR!8xWM@vczGh{F*E6%%_ni0Gg8@slN_oj*7Bbm!@Ttl zh$s_5=h(%ckC9&@0I?L*WY+Z9B6Z5%j(U6F>e+Iy>UJQe&Mhc3bbivyx{&3(hQ_K_ zQo`0fbdu*3W00!EvTys>Reu4(XLOS)rwYnf0PP+d{@3Nl#;Qx;^#Jv#`;Tve;-hJJ zuz(FUYapkFsHbQMOvZ6ItlA0rtIC*e)Id67q@62+&(Rd9KWon8Xe!R)P8Uub?=8w$ zZaWz3`m$l=z>2vG8}z14%x3v(O0&KK$=865lK}0BJ|D<=?-S3QV9EFLpY`Vkn{JqF zKG)EA_oDX24uU*Y1NN*m0?VQvp3xS^rWyFgz1j_d$_k_|KyGDbQfaOzoRx-;wJ*aS zckKuB0FJW(r$sgc&hJa@^|&GyVUzZnZ09vOwEM*hn3V!ZhPa&`ywdu>$X6_9fz^Oj zRf)I3Wvi=|J*;fn;(wp-c>8onQ8UDPoL6xn4Rp%6bw5$`D9U}|f-xP>pdz@eKUr|~ z?_#p@XZtN?nn9KBNU_j#OMI^K?U8=%tq4^1sA;ho#)A7#V2u~jcE?z}()3KeiOby? zOA-$e7jybj)dyatHSB!OA5)u|Ib~Sr5@SJfF7PNN0;NW+8R(t8J8-lXUBu{6wceMi zezo;D!xEqH@c6_#b{R=ri$&M2>@U-Z%p~<_!@DNiq$Qk&wewPYqzuG368U)uUy)~Pv|pM9^!4d2_# zeU~_1yW`Wv#r+g3N7Op}1%96J`ab`>K_wvY!P26iqe*mNci6k-Mcnq1L}`ey%Ht+3 z85`5c()T+70psFAf>v%jgV!^To!kOQwS{*PW|@HxZAyy5!=1MXGgms@tOYi&s%g7e zGX7uUXh6Tis=;R8-(o5os@u4fP;5_^oYzph>qS}46#UpxQJ)GVJ< zJjc=+yf%b3EO}i{e6Gw&%acB6vZ&BydWUdMr(0*Js&0OQSZIV7OUxEocS{0LrGz54 z>@H534)|HF(}bq6%^$B2CGvO9vFdaux-S%ozb-Ys6Z|B8P47xxS0`cnw8-lHbzAw3 zVi(bUYS+Q4a`p9l#jii{WoKrRGE8dc+pKSin>lYf)ofV?NhY#zDK{UC)rJ&RU1TbZ zK;F^4D4RHvP*i=xsOEBHiD>f&z&<_xZ>`=z-O$&$7-#BmGQYbLV5x|p(#~}%O+#&^3E)A&3<`eE!gc@&D+o~fNs-={T5OS zAq$^?A25GYca9?=^T!4Wo9BXdnd!|1eBICUzXKi}sK_JzS4j~wy?PS88M_nq%X_OX z=r;YbYeG-=2&)5#FB$1sCFndBiN3FW?W+mkJ5&^Ewtg%QMdM=i#!h_RQEf5~xVO<5 zF#t3u11kFs=BM|%Ndy8w8q+;kXc|b!%iCh=ee+Q$P*Jn+m#Y1{SUm~VkowKtDbid^ z7S<-y8|jI$Nwf3rOW?tm-0eO0b7E?d_-!;|>i~Gt8%X?^KI2mTy2Q)2hq-6k%lWtp zteo+bxJMe#P|M0d%hs2zsoe?BwuZIw0~!bfa&SNiG0>r;VuU30P*P)&Yqm7NbIa5d zT9goo{YeOf7Cgt_O~TtJz|F~9+~3`;&UDyg`1;vki9W!5QK>unstNrKHk1n|LsGWLX#a7Hv+6;jtTTR&5M>w!QI`|B z#cHG<+#q6V95;P+(D;L1P6hYz+`u{c%G_+XMS;dWVe0Gk+&AqbB$-+?u26mavhYnT zF+b9drZr`#%KUt!{kEe>k|50)WBKtoMy16EMA|yrC#KH}yH36*6&9KUY7I^bD?%#V zPFgwHt_GQ(`?LM2`#yhIvn)iU48y5y{X}(Mj`h)wzoEBR)j8FYbp1FlW%D;CEh=9j zmEE1~$yBr1y?51I`@49~*H3Mc3vyW-8&R{zDSkq-BCYQ>jqp$(*BibzChen4ce?e# z%z=zwc2n3S$C1Zq{KFAv5 zF9_zd+qmCtuY1gPKj2R9ckjT04!LI&qsJO9CJWHy=;RNjGnUMc7^1u^S=+0f@kx7Z zCQZxgtdtbJ@$oNm;vXYQ7Cn3@z4BhA*?g-Fu?P;u6~tLZTO|uQMP&jS=1D)pf83Dw z@%M-qc#O?qG=6laK(6>rrNR3|#Y_)T+rH|V;?2`-KR!*;X6dd|AJ_cBXZQuVgM>31 z&$!2W4<0}omdn}H92>ZLaArM)?sA$4YydK@5^F8Ed@<7FVnOL_u7HbxGZu-i4r>cs zK&r;;7AY85fZN&K2$le}9F?4-RB`(|ld7e!2K~y_qc2W|YY9m&Ozt1IMWt$tSLn8X z&C7=u;Fz8UX^E9jPv2=snP}Q#g%4RiWUe)8C}(%Fe9Fkxs_z~g!8gp#J*v+>yZ!6h z-EPC(ot8y($1ZPd-91V6peE>ZoR)HG(8@2Q9A+kg`&7@tEbf`JW?l5p9a^n35d+~( z3k6CpN-qt}CTGxuVH zcE{dEgmQ&1^@6We)2C%fl&QfFifind+@QY+{CM1ee++DSCk7u+Sg~L{xgj<8aqT<= z@~xVK5=sfB2)al#u7?_Dt@I7ssC5dc*-AB%zU#3BAt&m9BQY0ClFM zn)thRq`HR-Dg*^=bebd?TgHwxXmkXnuEiRu4~KSUT%a~(98JqOoqy_O;k$dQ^A`|}ziiKqQVpk@{S!!lDexWGs zZYP4WH+Rt1idOCyzmv$9W8W0=L|ReH;GWw75yXkyi}4D;fh?k!^}rGF{v;0#tWm1* zLepi*PYmbM;~weXz{z(*&R)=sh?Z+E7ZL=oxwxJ29p5 zHBkD2HH+`u*`}G;m7VQ5C-aNNCV<$P{H|kpBM|QrkyPAG?1f&@y>&L{@87rrjl$ll zX6T|H3DGucs$O{dUNh6-7nX=pQ8pDb7UZv|)uL~Wj^dXUSQFfto!OsX&U$_<;N`xA z6ivcgUXgA?Z4Z}bnO9vaEq=lcP;w~H(aO-X)uz1AznD)3xwadxQ$Qdu&~Gk5^`M^U zgG8lc290gocH=ZoV{N0xR%6??8r!y=#!mXb{e7P2)!p3}JNL|) z`C`u5euj#ChN{+uh1D2sCD?`h@WCp`Cv5kn~utUnv>*Q1rISV4E$B(Lo5tKvz(0&Jd5h{#slicdw0=~xL*GmD?x;NVkRKT~636whG<9>( z_U#Gc4k8WyS}=$^PZ2&1E7za&+DK9czOKzhaP1(uY#Wj{kaeWXh$wgHza{|T&D;<(2Ja4GyjDUJU+L~ zuaX&R8?hz9r@L$0@hZidF*x)mn7Vqi+=t3J!#bu78_GprFTAahKV7+t&>-213Y3D@ zY8TQ6NhSBgJPzGi3j3w8)_2o~F2E$$G$e5Ofu>9cXN@x5#qH}tyOkFY8` zd;-(=J>GlTwNlIA<@F9KTYFxn=*w5byORWQm>V33xaSai-pP~j@~iXU%6H@Qe2$!U z`*LKE?mFr3>b3^ID*SiM{vjZ9lL(p|OpqBRxjT9}=$OXAR%`iplU4aZ>!hXc82UZQ z&C~@}g2R{H2WH16(`D}By=*VO`y*DJ4??OuERhU}pm6Gk56X2UIt>uuJqSNubvf+cX2$>_Qb={2J__Eov*LrVhqjDoQnop{3jDJmXav!nd9K4Eho+cABwWnz= z44sMWhzJFF+nzV>gTu$c$1l-0!53Xg)063cSE>YGFO9x?h|J6F7@QtVI@j{&@g0GA z6%|Ta3e{u>iQ7HOB)bNVd&>r$3m$X?3lJ1C_2X*YM#KA~TVKd!7~YEw|4wHQ#k!TO|9rd*>>yJ#78P%}^FWS^7?O@9)+-I3jFcu=o6$n!faK z>+!_>Z)Es6GH;-PL9p61l+(3mrgSyjQPbp~4pC0k0zH**ug*<;q|N5H^wOukf~d5T z&@2wCLYG;7!MpBBx4j~Tx2_-+i;c}FlEaq2O_yr$f9*+KmgNXHF7$$SeU&5qP=y%a#v12%YWI8X~Gk7;JS;uaFL;t!KWTN~HIL`Qt2j&RYu9DB=*I+UD)yCWPm#5fh{w(a zvBT?dtXkO51uz@4Vt#w5w)r!R!js(4Mnn|`79iUR9T{N7imUwbbU9Y7?4fpJ5|iP4)R!;XKAx40oZhKdRpo-M z{M>7wKWSeA;d80r1%K%0N@;9T&^ZTlGPXahW_{Fq`u=lk#f#M7DKJ^3)MP`f~%P{SZjZ@J?!D-%<^@9doVQo zdmY`a^WIIm;OY@p9&}MGFt*Lk(!j1$jEFG@7m2)ayw=jZ@_21t%Lm`2@8?Ig9HczG zwqUW%q14J6C(i!)Ev0=-BkJccQ$Zf-b;Dhm#$xoEkeF`$**OQ6+%eK)Zb7qc+ zmy0k)scFo+bu(;JWp=eXJ80si5>)Crym)HsAM>v*5J($FC2Tx%ctQDSXN@-c zSSsZEH{p0BN2$ZDaV>W zy(Qij-s&uxU&VuhnajRoaKmq?Fcg|zx~2>a)hp$p70`OxuT+a`r?wUo(HGK(v(HeD zk9)-jGmOkQi;oj~MslnMJT)h77W&Qf=4$hA5>sg>%a66OD=PkB<%o1h9FwkyF;7xhnfqsr4lW$ zvLZ1hfPl+m@#k)l1((LT8=cc@d_ocT1^)Pu|J3CrV#6$IYy#N;v0=D0wJ8&&m?&&>_B9u#&y_}G(2 zp1n08r!(rM5oxyfQW#Bx?tI5`(O)WwOkk+B`A@)Odq@iGUfoM3czIJ$3in=T@NgF5 zK2V0VZDVXfGlQ$X{yvX<5;>unXMbrh?A!?%*@CFN+pZz?-HBH&XRLddiJr^aO`#2k z#gQ$z7BQJ1y(cq&=tj;i3;%pPrYrE(udt_zHjUlVCkW zyz98tn_oj0gENh_hv^CNypD#h<8T8gi9WI!R?*o(LF;-*qBTiO6n;rNJ%6;~$?0Oj zsYj#;-66q^j;{RsCtUDtcCxDLIXErLJ8B)AZ7Nk%wDh~i zoP2f4Pd@S~IdY9;+PSkIBB`Ox3f+8vXO!5g1*OW3W6ZQ+=R6w zNF7uw3eDT$i)CkIi=+w*`xu1Sooo<3aX+PUOv#Fou^gCJ+^Q6(!GY1rn-$gral|!Q zurdDA`T!_{+;eeh4AzlHn>L^8jRUa1ysr#WFb`{r(0Gi$Lc3LjNPM@HqD*)#n~P(( zXVRA-U+H+B{*>A>Zo6kts?Oy&np0MHnmBVYg-_!_47t*o_6GYlg4b~3;%{89iA;7Q zU1{|ynVFGt5jX6!ZG$Gh< z$niw?r+Kv60wL?z47zuE%RWUbU(}HUOfVK(E>R5N&13*tXDtR2bbtVeM1Y%~p6?p=|hAry=%^!@vc=phA#Dw1^$kLV*1#Ktc~cZhR}G)x zEK)_{1^d^3H)>9pV5Gj%-X{%@3j#EVYSX7<`7C#f5iW~O&6R8bKQUF?0F=BZCFaM* z+3sz!oJB^1(D0QXx?U<@Oks8OO4V>XLW(KF`psrMs@r+RFZw>?kp6)Slu|xp@L6+2 z$(!g?sA-aWzq4kv2TK&dDQk-iU{WdSJ)6X5Fkj0ZnA(r}7GGnf@}P4suhmAMBpLLM zPqqFF=}3w2#&~f~o0%D5w2eDapV%98!3dq++(kWEK;)3yTOgAdT1UuOvg44_-n88A z*7`NpKVJ#Q#o*df72YgvTSYWN2)$J*T=rjiDc6CR&A=)3!&umVb}Io=VYKp@d}+Q( zwN9!Q63#S)ub7GQ`zq3gi(~x_CB8nf1Bj*7i+RtNOlWNx`Ae;Y#k#SBQvHk}{tDIA zHm;^%LZXtXe<{w@QBov=1D&;h>398j7|&;TYnV%x66L$cQ?12kk(= zlE3dPWqT-diN(3ip0c^CniOYPFd=oZuGR(DK2@0L`s9MflGojou%ih?!@NWB&RAl^ ze1=GPM-0g7D`xdm)dNAez{_XArhk*~N#w3tH;1hZ_8LZL9!Z51TwW0-gIF9%jY|Ss zpW?_E%Prz}=dc62mzHlUFO6v(mX>$+`r`Kf5eY=8D3g&9k+CCkHhUwqXzsCzU)wq@I6|eVWO5d*(r|Rom z-KB~fYBTfqRd@z?31{!1zcs(=7mR?5mlxvIYBCeP4`*OHQE@Atw3|-MDbbwmjyqW@ zg;H78-k5e_e10|;H-qAB*4IcCXbCV$(>DPDWaXF*b;rQwL*!fWF`< zGkqYzYzOO@(@Ht1kj_qqCAU*lBF`v6#bXydUE{qqTsA+EWPPEan=GUCeooyeaFOxnv z%*Tghe9MSkVhU)wtSw|V)9wZ)rl3PakL6K)yl?7gw>NX|z2VO7= z_4){SFtS@VPXHN?+-&^ij2S+>N^dE1mELn;nI?M@=N?Jfya>k28wUrF#Rz`oEy+!B3q($T zGcHa~VJ&HJg{ooogx+=_;jNa@g&dC@9-QA`ebx{kZetI1#5Q9d|7!CLMhYB=@%3PAOHt@^0FXUyEiN1JsKhuLj&P_8||tUSH~92&+}Nb4fjo zY#9%dDT!Leq55}|@F+TUhOqi-oQj->Rx=CYyFeAT=MSHpL9FvlE|@6%5|YnV7FGdgV9 zCcTzF+eo~v8$ZxQd4Sjnjo}4!S>T6R0%-!^)qSHSTD6QvSWqLJYk;q_ly|=GG_y`M zN@l;htr)R9Lpu@i8?eM@;X1i(Pi5Zt{5UP3WsPO4YHEL-(sePAn@zO-R$z5C{hV;8 zqYcotaeC-NB44uSzXwP?zuZDs)4xfL@pI=}w)>P)#{5%AB(r-s9k?|5ehkMJ%Sw%; zOMH%FwqE;9S0BSZnqEmJf+L&*6thY8P1kazoT!2kRLuq-k04vsZ{AGkyw7PVG_D*| zZE2(~veZ6fZDx?u20u5|9(Smc_wxXVC^61abzA>PgBh^FJ_?#g(AXzb*5jR;e zbPS~C=o;-endO&583lg*wityFTB~uNXkcYHJk=?(Xgw0s1CW-g`KqR8n9u%myy8%` z)6L(`=66Bjec|kn5CuqK)W{1t=Y}PtNZwf4Pu_TW3#MOK7O> z_?h3Nb)y@_R36YHqN~L-su3WV)rTioz5YDtmO5LI%U3^Ts_(LcL#!>T-XIwJagS~n z`AqIsH9gQ0`xro*x3pA=G5=^&OyQ~s!2t~Fw{LC+d+k%Q?&v|0x-zxoiIG(%@)u|_ zc3W5~=A0t#Ol1On*|&V3kZG*Q-MmB~c--FB@z_&<0$b;PLE_seT)@aZb-qpA%_dP6 zYM3uvAg=Aygl(l1N;?Xr$WiPryZ@h)W!QLPz(zEolN#tL6_Jf%((@*x##w^q1}Ch#F}(6w9BfNk$Gy~3`dMo zB5znHpW$Duw21nGz67&cEGyanm?nz7s(lCMQs6e{Cp|;?5 z1k>Y8au5iHUzwm;!UDE$WGE9;G_{+0ntY1tppmG(?6B z$xot7m4qNP*9rtshf@!KZwQiehaX{O5D?WBNLmq&TA?!$c;)u>t!{R7aA{n+NA2Xy z^tRpz^aw9!!j^hQyMUp*TV5Pb;^QiW`HY+2GUnsDGR`NFC!J+1gZiIK@e3oQ>=#W) z_LUv@QAGD8g;Z;X+4Rto+lB&4cUjqU{~KRa-2f1lM3<)N43U2|3UCVy%?Iia2;0Ei zZ;9y~oacQ~3%L#{@tmTuvX33%lYpE^!1bh?RS;(H15+wb{n zkh)E5ime>%#?03F`|~;ZFHU}%OpZCw=~y2U_zO@UN~W7G%y1P*(K2c&ZQ%PeG>i$h zAS^c*55FcjUQQN?oPNT@A$zO2Z8zZ!k$8((O>C^x0HBOEe>m2ijL1q{6JUrU;MTap zqIpz!gS1<)q753E_3dMVNB4k%NanffFh-Wl2KL@w&+D-;U=*%x!e#Ugvh{b;EC9Nm zqEM_U#()duQ{tM%NZqr#NDyGF@&GIwUw=j%-7DjeuI07dHAaBUNYvF8K9k*yfyZz} zJ6aei@4({K>@4A+;=_W(4+Ti~m)P@cif<3%uqA0n_=1nZW_!d2ir zev&uIPZ^@U(vZSCJR@NKjlN{GVnkPe94$Z>PEg3o~z1V(AZJ@p*jzxvB)rRyd?qf2t%8 zc(FUP$eHY=RMRph9QUO2Vpyc|)tRW;(AaEHNMsJD8H>V>{LA7V1~J@4je(~;XYU>` zT8W`^1aGxz6H=pnukfbPZn=!woCn~|2+4#EAjt2H$dszyG-<(;kVE^?cw!TcnR7uw z0vngk0XQC1-$zIVD3IM0$HKyZI_Ng*LV118ts}S!q;F3W%#i>v)umF%iEouc|IftFG|#Ly;Hf4J>*m7(5R}TOU`nDB@Nc(*tFPm< z>!D$UeF-RZ`WG1G{VNh-DCsoU9M_l&PZ5`<0st_rUM5PAyU%uCb=LtWP->=}30*Z_ z0T4!p4gQG>O;dFoZn`v}3t7nn8WxRt8-lTF`81(#a zR;+(IBK=c!^D@wAohVyqzwtHdG%C?sc@6!0FXwmplGoAni1n$}OA%7fd4|~*hha3a z)2P!X&X&3Ft>aGf!4nF0NvWr%9|HERA|%jxmR)wvGpqr@&WOZwYDxA?DSu>I6l!4_ zHEo7OZWbMieKTrZgNyg5;me|SpVLdyqfuRn2DPBGEX#s@20=ym4_Wb6WC0jwUp0sm zm*52;c@2p?F9TTKH74$PK9H?Su1{r0iBc`7}1y zHAQsGD%q+IbN<^z_u+C?I$SB3m}*yt&v}EsbcV3&`p(~Qy16F{F6O2*RSLqg?`#dF zFR>1#e=$U3je2?CED2vV=WI)5q-lNc(RIzKa`;Ihk=suIU`PoCQ4K7bd^)?Z3U>dX zj*TyvLL#l75Oc_$xzs*~ww|Y{Rj885Y&Oo|W!wRL2Vl!30XpsJww^zf0iCY&W{`XL zxubIj1ks8NK)`&f8Z(+UlwZJC<9FZ}On7e6HqgM)=0V9>ey z)kIcAUSiFGxd(T@w!eN4pG5X>`VRfq#HOkIly<8Lw6&hD+f>`1(}+Ob?1IO&WgT{3 zSD4AJ7DjYuzG%)f$1VM;H4-~dC=lCj@m5;u^(31PvF#`-sN5)Z?p`L)SGAbq%o+g_V?qXM zhV&6CKuO z7cNQv0zea{M^kEu7P88>U+y;tM4#F}tfc%pgO$qm{k9ladJ4G(7?J-}M)52prjHp|klNoi^&PS*926h8e@EM6}}4|bT*cs4PvH1Xip z>TV3!h{z)56S)O4c?!TjZ&Jj@$^lM5I9{IOB}YfsvcbHTDyzCK+CqZ911oL2^9_Jb zB|2K1+Sxq#^Ooh6#ew zqI;3*f*aie_eBBLiK#vsKxd;ypZuyN$%EJO<{jYxb#vl;RqXyUn<0tFqz->4R#H{} zM2CM4nESX`oVF*W#Y3(?C7)JVrnxzYYT|6H{*nSm!{fLCyo}HU4PZ00?yzu{;!QFv znoY$k`J2-@!J;7`Tp;kDC4olcSQVT}ej|UmnK~I0zA6{qIQu~9V&x~Ui~z?IIc))n zeN6rjXUc{lWL}q1MkPfA&ManqQIVpLh-H=Tv+$%VGrJw+nw0)4SHimbM zg6e<|u6K%^T7Pm|L4hMaY?<4%IwAuOaMqw3!ztXu(~5o(yIj1BA6i~5_-N_T5pjy? zWuz@p1vE87GAqmiXBnRe0O(kzZGV3YPcsDj+!($OCv(kG=n(4blYvXNgjsHILb1F6 zZ`EJi7gRX)yNZ$Na-~md)PQ_~X`_2Y_5!?(D;kUx$*9m-4vabt=~#!mgG{=2l>zTB z$QBRe8Qhp+n*B>UqzlFSsSbL(u7d(t_%2W&ZIPDrfu!DAdGTlA^w11r3cpEz zj|eVcv@D5M{(l-jmZF-m;daILrynd(rmpT$L5!!D0G#R3;SXo)@q!0wl1*9-J_f`4 z#)H(MCmLfBFz|=d86Yqwac!a-Bl8()ndm}wKN#ny)YCGeQP~zsvntP$#T!*`djN35 z(J#c(<%tBpn#zIB)-M#dL%J?o)nktH>tDCe$b3G!wf}py7=;vCuK^t=+~OJaJqsXs z5=2A_K$xZ4lHh`AdZZ2B5BmR2@84fFfg?)ao83tVZ`yv^lDdS!WSR6hD8qzVoD3>g zne4d!pZ8-M+{4Iv0}zF|(|wAensF5FQhES!3HIydF6`%8f_pfN&zW;h4(c_+i!J+f zJsEg<-9G_)o};A_hhUUl?fNK1(|G+0K_(h@VmI;_?D~o{2TlJu&>y)O)fudqhbN#l<&9k$K;Ac{pM8UE{~8?m+R@zFz=cp7E6lFWy0TnFZJuW|ulJv^> z+(p19k3)T#Nu9~1e`-ME@d=JDIs`Djes}?6a%L@;UOt)a2Rsv_z^5f2w}Q ziFS{;a}}ip4x=@|F_o410U2KHu1iv%8?Va|MiQS1ripo}#N=XzfAKQAj!ol=ogP+6cV%$=~F(u^iQ~y87jPvO0N|GqY^8 z!qYM5!6=?Zb1hao2}H=qbz!lV%#z6c_RJKFY@t}rE`AV;aFsfY9gS(*k}H4~IwC;+ z=o*$M8kImSBL^2zhGQ8rWBe2&#VD+`IOat0pt zUs1>Cm_hPTm^Wd$PK71)JOV1Tsv!#{9uZ)fc#;18xU%-A@#ICpx0lPFba?qv={(OR zBzj}U4vCDM2M?gE@XC5!FHuk=W5i78BuA_D#)!9}omvfMLuRu9*eaZMtw+F=l+_O) zkT^C?SD``lt!8l;_`pE(f1_EoK&fuh!?fSycCnYITz%I6vB4S^+$E14;J8f=+c z?5?*Lre{ee|GB}E_K~6McE#!EA$ujjNneL0vE6*C2)WP#E5;amop8Z{ezO1rim^UD||Ycq4)B=aOxXvgeR#JQ<4 zAid+$9CZkZKWIG?T@F_3B!|*Wql;PNd3l$oYA2CUqERic3ke3uKLcBe>YWovmfH<4 z&K(6Kxp0HyN97#WQGoHd;0X9@PL*GhE4{w#3V;E0%m}$fusAD-c^2&h86LUYI1)YH=mIwFq7?5U~Yiw z8)tJg7c9cn&Q=~b=>rU|L{e9~=O3tO<@r9~oCYb0)K2{p&-SO|1wcW0 zV!CuNqu^@2LdAQg+K-fM4x;d~iJ)C`U9F#CL6r8fKOTjziiOwCa6m5F1f1zkSpy-g zj;dpHLCr|;2;8$!sYA3Im=X4Tz}m@*v@~5IMXg2QcoBb|=(&j$XGaxkF zdQ>Uli*He)$KoXXS!N(xwQc?phXyDmzDxAY03|$f z$1f5g7%yV7K>AkL(2F)1b-@&XqiJ*eh@Z6pktMh~$fD*=@3CLeNKEEEBhBQZ!Qy>= z%>Tk~nKlbJZtt-0f|!Q|LlVz0zPd?OK6)mHEWmFMtJ2fAw08B4=wdK1JQ~Bcs2WX3 zF;{POo);`SvGR3$0;PSR2VC-bYuTX~TPsck14oXMDL5aUa!?Waj0Df9E)b!-nY4U`$eO;hL0d zFp;s$4(0&jN=$+qYa%f4;d9)o>dZ-Rki!NMYb|uOPOc%}^GNUAfpe65Q}}Rf&kk|z z>ooDkO81@tK$*wJ%hPQL1pON)bH%NFZN3F;_U>K{q-l{oqr1j~?K9TXY1zovb$?|fqL-mn6VBPre#=U=Yqc}8;g zR{kR;q)AkNUfe}Y9>|{+d?0e{Z^p=)6SO&@q^)YDrogC%}ysy(zF|CA(Oe-Ro=(^OwdcZuZ72R7NNWpf;6 zS71lCWUxGGd06SBptf|l)g|oYi9YT|(B{Arc&Y=DxK_(pRN6smw%z~r@Wxqy&q*$q zee)BaL~3Z-j>`6oc`92xM}IaXc;C&>rXIKDO^%Ec%R4S z?DD$0rp}rL8wF(-hi!%TMHPw&7Bq7uZ{>Wr!HETqa4Gwc|77vt00E@2rv&_)buvNT* zR_9d#1;M{Ul+aq=J?0c0NlJd3G9^Bs9QwpC-pRlcB?I_!i&#fBfb+X3%x*#_wd-2U zk7#w&qg5CK{aSXXgqh?#$?FNL=!Bq_bUYL#CcOOp^uPlNQ)kOl-atC5mk;7&%>_K} zHf|vV>nq*YNNn$w1zjBd=0DUk$eBQ;)(;<`gW0>`EJUL1W~lHLU*~^>)XJ@xPKIul z^(Rx#QhCXHucV%{i=qR=_laIcZ&X4a1Qi?T(=cSe1`Ub$Sk_b{xl?9JHf_-&pcm@Q zdF3U*sk4D@-{KJS{<~*j=D)pG2-L#}TQclwj*gnhB_djF^dk|1%9m(j$M9P|3BZCM zFbn_VPi{}OS4vvL{d>rKgs;W5*LZ9%Ms&T^7l$aGIl@$H#o%P9HPm}id1knoB6q1aEfV2aheys9Gnfk1=8B7}6k8t~FADT)B z(z@PvM-{o_XRZVz$1tcw88J0Uh#p0xc;KTzGZHK_fitCC>bY}tp5&9wJ2q&EkF>!# zAPSTQP`&WnPT>}ZQx~Dd(HBxMQW_)O#6O_}Q{0zBE_p(r%dHy6-*g$(@taH0Dni^5 zHkwB=xspwJHAAFjh+u<%Q?DjUIV@vlNZKk#<~9LC6J-Zu1qF1F&{oA9I!F5r?OZ|G zv2aT${JHO!Oue+)7%fC-Uk=suff6tEXHAS(*Yxc`O2;Le!*o$MJuL8m9|;m6H(GE- zIqh)fO`#DcYH%j^C(XwYQM!rG>!{39>aVnJ+9-+Fj=j68t64Md+1=fU>%SZ!Z4oe| z;n1Z}WP+jgk?lo`iO~1DWPHD4*%YM|RO59ig_k<`18jtGS`nL^wL}&lzO39pfV)Q-r|IqAEZ<|NW;BrLdI;_qB*E4W<`Dg9cUHKxL{_n$$RcfZus> zUIeNYd5M_KaI7f^R!Y7AG2e9wh1YY^ehT+zDkVu8V&+F}uz%dn0tMs@DFwvx$d~vt z?p_4wv>dyc?_=3HKLyAbWMS7)uTV>VnP2PBH*Rk|iSDZgzeulg&$=^iC>k%Bi?B!( zMdqXRP!jiQ=sFtsUe}#=y~MpI-leDv#p^}M7o*JviI+yj+k7k)bD=G5o3*7f#<9}1@H+dQ1i!~kxBw!yiEM(3Z!Bhua~D-@=n>A)$D*Auuoe7Iq;NU zwH9qT>M(E7yl6XGWz6D@D6ws^O2F$*P<+zzjpY->SEbyOMNyrS<1Yb@4wO4t^pr%p zZ<(Rw^v+k(LCQw1Ra@lc`jG0X-vUbe{G>1QB89+r^gK92NkX=T-<4#4)P5*NVt}2~ zpvo|<;^_){f#yp?YIQH>Y(RR?;U)7_?JtSfG((M}trsKnaK$SCMQS*n8%0Q+D4Ha! zWP=7WUfb%z^uz{BYBJT(tsnAr@^KKNu&5WP)Euw(=0W{dpjDH{Pd1W~!>5@hXA4=5 ziwt1YlV#5-cbPz-9CI%Cm=M;a^-C_!q*u7Tj_!Xi2h6(dQcM$G_^`Em58;oj)Pt(e$%iNd2!La}=!XEVO9Qiqy?`b8IU@ zAcZWVObtTnX=s)2&kmt%HuDrKG$4bli1;O&VV`m{GUdBxwZJVRyb~&yIlo`d=lHQR)dD&SiC;cw{b%3bx;k6lANxnK4GsP-R$a610XKZ{*Is>NFd%<# z#-Vm*wLW$ye-01+gE(GJ!%WK~c7l+2Uz*}`spMol zbK9eo!x100EU6~rQ&2cZ)cY-pIDI7BBNL~9BP(oo@G51|%EIx70-t(0VzK$_@s0M9 z`Nuzhgn1xJ@xTOJAHkho`64pU)ixHd(x5+(x~2IERM|{x1=_^3DDh%AVE>2a_tTAZ zZWG`pJ+c8gfuPIR94qI?PoKwdf;fJK?H@i@b#^{oQ7;m|y&gOW{<|S2_;$m&*!6U_ zPyN^5Ijx zZKOv5mXQKIgPF{h2eW9hLvQcizcua!IA|=I%w(cx@8C!Z8>T+)`4P=CiSzHv=-`xW z%r{S4DNJygVpuQ_fW8tNgDCh=CExBGFA*-gy`InJDg>l?%aGR%yj^#`(F&hv`&`~6 zldvN)Ne9kTyDK()yS@rf69jJEylO6Hc{|;V+T&E@LKIG@<){Ny=iW{+4P3h^RIhoN z8cQxuf^JRKNmFOALFTpRRj3#*-Fawn^Slli2QS}mn|n=2w4|y4**TBj`kE(ZRhRhi zz!VmpHL=Jc>)DFqmrgT(E?~vm2E2?4T)gf-L}ca;ED}GT*`J(Z`+b4lUX*)FE$I1l z1zdD`{QN{u#KW~vQ5XM&u%RlCux;0Am97x42miK-Fnf^?vp_<}{ra~=c5i+u z02>{`%F~!e5PxWiOTacv)ggiptO!!bkk3UMq}B@#Z#O;mL1(!Y661It=dO(MAyOK( z9`-@#7N+p@^LAjoul8Oze9^b-FFQh|@|$s80K%Kbw!mLUe8aj5cN01Ny6|j(_w@~S zL$yOW+TcAJd%Iev-z3;EqWXO<2%0K@D~egfmH_i`l3$wUE;jcjSnLD3_VtQjheETRnO^2B32&kZDA zvgO_hF4zGtdWub+*(&gg+CAEu&)%gnvv+Y&*r5E@H!|dpDmL~J`B%8q=OLU>j)bs3 z)X77ypGw8>CC_m{jZJi5ncT>{oflXsKpN}R3#)kxHiN`SJUfXI`h-bJJBeYW2Hrkl z@~99mPdvo)G(ko+!HP{j1n?Sv7MuMTFY)N>|G|TfF3RNg?v=AAt%6zBKy;wo*{Ar*OoD z9m2q52AbAMKcFA+!b;Cy?RF>KLO+He>xC)qyiI?6m`2Y=BvbZL`ymwb z$&!2sDhvI19ulf3*@5oV?t}2j1A?X0G8D3-J7HF#!XIJq!^ME|0z9N&=mvS+r_XHa zF#|adrY{IknYO|xh^)z2#oYFi0v|~1q8AMHl~-`k8mQ69giJ|SNK{HB?Pw2q z<2gdbPJ|UDD+go!xxcWCDG!C>2xtm0&12DPr0f`s_=g7X6}ap zvHcXfL~3wjJas8jVi763H{+i&`_#7HalsD9V!mC|6pNiwPzaq+nyB%0@dx3r%2qu+ zs~Bij7L1usvrGs=%B51O$p0>Vl|BibGLL!W zNj3{KiV?SDl|mrY9!5m)gsjJ<@c;i%+INH=v5>#ThGQF;Kai?BkrC9EB9rXND5w_g zWqTp#_@>3uaL-7?1QzDca3!SMWUa@iei4am;xt_Ky{%{!r1!+%4GEOc@R77t+5(5o z{fs^0O13}K_t;l|YJm?iRbCN8LzXO^A({CuU`rPIGl0hal*W%Td}bidHlNb)=;LT# zPwc3sk+kduLNomyKS%W*(nR}2kMIML?46$mj^%ZnGB;OEM>}5zF98sqXw(#aPkY?i zjA-z94w8KtW|=c1l&o;p$JyDU6kM1$ZKZMNY~eGT@|lchox0LGvjv3Me4#SBp%d|O zdWkKk*K}Oud?8-1qoO>@@#_P;vu4+fEi@>#AbUsU(T(s+P+G4?hF!n~zt4$iInz|2 zK*4ICt4Nk;QwsX}!S(lVW-Ekt?+83{X^ypHWj^{V^O!mEBqjBEWKhB4$lydzaj2Y>F>+jVF7l_=&VyEC@-GAAbsJ zADC!Ys26_76uE0q$Fa;;!W!Mk>UR~%5v@;2ei%dJo|@Ai$Qd%6adIJy{m4JN429Na z{<3v(-(*kJ@!jpEtm>f=+zbx4uiRTCSRWq#JMO5(@yIWOd$lJg;Pf#zGsKo`G*!Mf z+-ctV);o#CMCTgRlB#<=^kd+7o{?pue+rLAn^CM0D$@I~+#^F5NI>K_>R})O66$Ky zjp%rUcH`+7^B(sF)>ZGltdn`xz38L>eUR#zsi9*i&@xG2& zHN0(ON$W;KpdIstrRcJhE1>PntPu$vM^ zYdc1`BHuW9NyC)hPyD|3KOWvPAgb^C9tI=@X;GxRLqNKFh@n#uL|_0x8YC~>HFOQ# zBFInzB7)S=jf8X~AT8;0{e1tw=iQzAV)i}zp0m$dYp-*AgZ-y}(75NRM*0bkR79tG za=GB|Mo+LNe-^o7m$M$%lEd_R$BdD%ID)C@ThtKEj4?vInJ1bhn;dS>1QDXPL?q$$KM=%Zk!hlS!W=aTwOP2&ypTURFQKXPcaOF>yii%;vKL}CPN)m>5 zcjL`gC6Fp2*})Q#P_IuX(E9K1#i7z_XsDuw;1X!UJcCq(*q1-Vd=#?Go^FgBCuDfU zC`7IgA_bhP@arCxwT=E!YPphKmmwM`0Bss&hDalPg7ox7dpmLAihc0Cr%`8^_GA!` zT$hhk^ytj^6WGZHJ@A_mdX@jiA`TV)UodOogj;4>4uLw?4QxHMF3{!(;uiFcwOkv7|ScmP_XV@ur zn#P@0J@O;?+OJb>WRN~EPEl{({o7<=rE)wuR>m>8`otA1mMXShQOq?(45bA|hv z8t(Uq6#ap5J1F0QVW0?sP-VLyeLei;Tk|~y_SrS#sX2+ArD6_>RawD0?~U1{n>MeI zvhPdaDSkvsCnrE-fJR%HYQkM9K&YaNw?L=9k8$i>;5zR@3M6h1++PwB>MJE24sHBJ z6Pu#BCGPR(Q0HT?$lfCCt*>Opa;y2`vj1B<&9mhByeOFE2`Q=kSEC=f?a^uNopSr5 z8_vElU3yb^-h&&SWK~td>w@P714N9S#g#tX)c4RPEwj@vfA;hM&x1a`zww-}muNii zO+Eietmle{0@Xb#8>;DfqE57f*U&vIuo&ELrKTaK@Le=vDaPrZx{)=u;?EEf205pe z{5tL%51#RhIvElE{MM^GbBGq|FHx<8$Ob1?=w56eSOeusx4ONOxu_jRLMp_JUimjJ z?3$H!7fnA;P=?Zfh$;Rm>7`^(rdqW|f9l+Uw`T^tzHwgEM7}?G!NrkOPdZD3EH8KlKcJ+MM@yDSfxczo7G{T-um2qFS9NUEz%gx#c{~N>{fu7yC^nrIxzcr)U-IF5J z_mgf7p=p^5rx93#MQLhALR!T6zWUO4EQ(3(Cy3@#)3lC=S}4zsqsF-zLXRDV+WlU) z1nL4gy~sMI*rsOw09vjYY=Vl>TryJK!rLTzY%VwLQ2~tm}%xT$3_10>k zGbRK@!T#oPRK1Eb@J+%`vM;a_!xd&w7nDyb`sh0R&aU=3B`6*xx{A7C&n+2E_;h1T zla&u!n#_{mPsQxo#g*PDbr!(Hb2^b_OizL8%mn3avjSEFSL;SJFtxJ;7mjx3FXZ*) zKaGr-5Lg8-wxHp%dX4Bl?ukBN#uERPi^UNWdcJ!VaD2?EYpJvSw2u+Sw|&%2^x$Rb zU`t5D71y9xh|FZNT$~pncMfLCo+aH#w?dQKx13cV+Nq9V!~CrJ0C?zHUj5K@E@o@u}Y`-P|%iPwa_RzsOyz5X<5w@gY(1}ol+X3KEr zQujdbQ|va09lWyws=c8#vlxH@8p;3+9s^FHB()yA2bw|T-!N1smyJdB{}saiuGqgt zozDqXcnulX`x`~xpM`;i+dB6rQ_k<1Ed*b4BHe&9ye%cQgJ?udq)3$|Fl7z@QRRa* zcs$#y9POgbFcsmJ(}%KiK8@%$eg=>uDk3LRL6vtOaOEqr1YITpJD(S%2F7)~`$J&G zy3)6WKDFyA7jU=o^XX~z$P}BCX395mHg9wPlRT91Qw~-;>-t$Be@@zUoKp%Jn#Bbr z)7GfEAxJqyle+i$0YBe44!~o7^uw$(!F?acz>RIS{_A^9+2`elg56YT!-ya5uMb0_ zg%VV>9PN4hknjuO{K~wbeUQ`n5nstcRq6;Dw0OEDN*`}bTmdHbRD2>q=7qu_xwg#? zSj8&7kC_N4;IN&DwH%-Cx>%Oh?+|6r;Mftm)q}H%2H_^jTpR`gmX=|xu?Aq zr|LzfrYz~rXs8sQ{?ubNa^c#?bW?UeVqau4S?n2-bpQOxC%`FcO`y3A3vol(7Sy9NbBgWt}sIQ8N zAWe(%AO-YVzwZS?v!K}nI_x1N&K5k$^*QYZBjnrJL#YnHk9 z&!{|(IP?J!BgwAIHyUiZTS*j-6)tl_u5!6XU(Hx}c;Mu!jJ;lpo3zI)eT|8!d5XP0 zhnw6bmPI@oX0IMC4V#X-={-&oV2Ht?Fi!WCZxCZ{bQ55(QW}sKa;7A)a#f0~EK!V&M-~ zl`quYq?%W71agm2wJl{jG3v1S#D1141; z6U?8_%OXj|v!244P2#+gnXx>qL}0B=8N^Iq#`y*yizfuI$gY z65-Wd@=YJfyvN$N^#hz9V`ncKaJsTJWjsNCR9Hk^%(+%I{n#ZG$>Hw{9&oe;OVx{O z2_mB~)|||Sl3yi&GxOWB;^)^hA8U3ss7Vlq#T^9FA|JBAP3dJbtC2I;-6nq9_uZPn z_IEU&>^ARqOMeqdSgQS*wii1n*mRtFW7wc^tY`WkCU3}1w-Z}vBT8KQivNMT?R;q0 z#QT>I1x?_HsQXs%KHm9oB$ru^lA+u-n@FI`K`(yz%Pl}q(oE2Zagj8gZBrts{&mga z#$?Ld`rUI+hcYI|^w{l^WjWRiFE0GipyA!p4rvC%q$f9muG<@G_v+tJB3~W$~vT9K~9nGxLqz0jHoqRC83q zTk#wvXOjO-_Qtn+M^WD9E6(%0Z&jJ3E-d@sV%#1xiaQ}Xz-<%QOZi8?Wj2qxy}I(h zFWX0VoDRq=&aj$$fAhJe&UqO>X@C37Ac$p3jq$!q~`|bQxmDq2Z3ehcwQUOpx}4fl|&(Hi4qITixjsPS%KzlZ0iR$^n7l z=^U{GGtmcON|7HYNndXNDZi{US{v7*qYF6i8CO}Z>Twu9dy2ziuu-&NGOQ&mX#J*N)7j1(bCi; zNea@?Fd-@Gl1_;3&_f1$;gdHh|FAu?J!dqSS8WID55`L$pbm_Ulhd)lQ zChM4HMC$|aL(c50c%P19r|n3pbbRT!+(@*bUhY_MuKv<|cY5~;C|(O~+qGcle>r8* z`-UDU%v>vO`rzKZH!hwd*-sUU2J|NVOG+2r zmj(}Bel<6IS$VT|CWSYhboQC$*q)MnUC)u$^@K_oGXO0 z;7|4@|H^D6|Ddd$Wh{fF(T6Tfw+#lT&nX-1M)Q;!I3vy`FM8$O<8A`OBpI1 zpS{lv-s_YIu;EX$ru@ncuf>=|1(n&OtzI^cGh=J-<}%tKWu1hx(3mZF(MEQAeh!R= zqq98@!nWHw@uKBO!IyPHpoJX<4CrHMgFBmmK~LTf=!yrftW%9v*r^}RXzsnAC!1-5 zLT?>z=FrVJkZ;-=($LB6C)35l|AML8j?9E2P?u`-F=E)tbtu9o{ z@zKg6Uiuv_6RZxr2E|Q9+cdQSQ{ILR!D+M@&Zhte*SH6m00 za-4K1s|tkbEE)7YW1gg%1Yltl6pI#dzLn)M+=U2{t%<(bGHLU#eII!F;UY0`YtaTYhjK)PoJz=rysQaK1ev!nv0u~ zo>=3eE18ZCO|JFHOi-`s*Ff|TvmKLZJgJ=}rixc45y8rsoB1JkCXQ^l;$eA@NqlRh zJMK0}QYBhA4-&*i3l+8~VM8wL_hUf{fSzmTd*MjMEtCr0(^%g@QKn#cl%!zeLL`?O zl``YWMlmLwTP;TwNtGT)s>sUXV+y~JWlnp~$f2u=2{&6anTAO2ERl%mCAxr9pE0c) zoceIWXqXanp2V!hml`|n8COab##wvlY4rUS-nqu~_h<(%iEqd!HoRHJx`tNAbF}xiHQnd9B{ZmgBz|>qGf%Y zuAlm$`#!z3s@`X;9Y;s12ILO1`oda{Z1m!ed5`OSzIHU<%{BKCE$Q)7C?&ZHVK8y@ zFdYrTpJ~owxzBT_2jrdkXaXQoRosp*0{I`PH~Y(YKa^vX2p5j--W(72PR4IZv%q-J ztq3aDwdTJP&qq)#+|H4?{pv^6d)8oq*O>y@M3zc=To328khCFT7Kkxsp57m{EhH|D z03vfV-qNn34}Zti+a6wdHmVv`2q$)LT-{f4Em$=e*HLUzC<0c}kl~By#LA6j-xA1Z zbmJ8>rb|SZGJh{3M@Gt-en9oQ7RGwI2OzM-v&5z7{$yo(OyKUQ+Pf9@n&N zSJy|f4pE{W*;mgg4x^6&=U$O3--D) zLy%l*A8OTZQar?e9}oO<(LanVu8fS%P!MD&=Q~2YZ!_Z067~t4~s!h&h5>^ts7lyT@ImTIzm+ zn3mm0BS}wPFQvP)^wigZ8h$5v2u+^L^d5hwt&W5|u5eB@wiY&Ybgp5Q`Nezr%s)do zfOp}HdSqI!Lkh}kB>81n@Q~spJRh(O)@XH~k=5Wrs3nP|HgQV6H=pGI6|9uXsS|LI zi{#YeZOU-pnJ?S{yEE3(K4jOcDuRReoZkoeWmdgLFB+J>B{EO;3G1RE z?s(y^xca^B!b^E?C5Ls@RD@fJERwx}{vj2l>|kfRrbgR|Il5Vo@SK`x+N^bLn;q_h zge!H!`N(`!4h?aoE5FpQD|2)3oy(l`AZn zkoj!y#Md^{Nd}%w=Qk6{3|S8qp$Q~F?uP{8Rixi3_X?>WTk2BjICJEIOe8MbqP;<( z=u8o&x69K54l;fui#PX8 zS&U@O^6W_JW|!pd6S|sR$7h3#TGy)v!yaM1$ler+1P$IT!>_*B@sqJq3U9O^5=Oi~ zziGjH#e-o|xRP$=g?jJVvd1dST7N+8Ja8r70=n@yLbM(Cyi1YP9p}WGyyP)T({HF# zb5(WY%i%Y~jL)+T@mU*nxFsYj^^Cybjb}ZT8lPiNN6-XYfufH%%qsU4>Ojq2d^e4E zf;4aEEGo>I-e#DnTGt1K@I+LBq7tWp560^P6sN&-Z_GiMa%5FKYt_j3Lao%*WE>WG%8&$!6Pvk%O7{pwD#|)sddgF8ms+{ymR`?p`J;qYAdo9 zm3QVr$M4l(B%;WAyLD9p+Lln7yhc`xMDVkXLb}1Q0&5<+M+|aq!7y{S-=K0s zzikR?s_~Ag4o_IuSa@d$gV`2TCZZ(NC0BJ+DX=nJwcXm2Tg6YTF(6u>gp-$$;x8u0 zi4m&4ML<2A`C^0+wOEOn@k<|MM2{M}J@I+T0#wqQu`=|RDc{fa|5W(KGV3kuc?}k4 zGfoRImnNS%1O8FW8mh>zDF;lSZ)fA~=V`nzvi3!-u40BSC~eb}$iRxAs>u#YU&YI+ zxs}-o5j&w1j}dq*MUw$Tr|)?&{Z5?Kw}EkHw_F1mi3}~s=uzO0r8T$+2MDDMU@&?c zrVjUxsXpyMu9ix{_hapBx+V|64iJ1`1tcA+k)8Dn*rVfjH-E;Uto?^kr`uyX4zOIU z{O@xbl{+=`PT=`KcT;X1S?lq|&d!|6q&eyFC;AI#pV#VLnM=Lg*huJ+Po0PXNFz-P zj<~GG8O;?9zii307q+bS5@$OxI%929edQ!bt8sLkcqp;6gDTDtKcKQ6I}%hyM`7-N z=A_7Zf8OUie+PilS8Cv5jhtXOj&p|p>goJAnfGbWfD{|BI)p0++t70o>B&y^n#Y*KYbz&(84G_0V$TR2(<-39xc zCZ%U#!CpgEclZ~uIt2f|wy&__u2{g`Mf`Uo^)@mO6%Z)Zwakb*M;KjU5^$O7`E~{g z*Omy3hRw<>O0{y$5Ck>a@y83M^zeL`U}`qNtj=?BGKQq(k<4f`0QBIVn4e*7Qs=%8Iq`^n{#P0X;v(T2k9Sy+IACUpnp$ z(RmzAmb*Oy)#aCyfn)DGH`-U{uF_-$;eFFLs+{O~#6Xu`w_cW^MP2}-Y zC)T7MNV#9N8_?!*nmz%{oc^r1zICq?~pT4{IC z${Fb_5bY+bK#6=H*wgbCaad33L1zLZiJb-a@qSp(=V778@OXtw)WvuQYkJk=NqCBp zS3ue9LxEzLIMo;A7Sp#6|Jn!sdTUuD*onJR`OEm>IQN@>2V@FVLzTYcJPAc$N3Sw{ zm|r6ls9dTyoc2rhx+}5{dQ-`;G3_Vp8A1fKdfRLJ76iFeNeZz|m3e_cQZ90(o?+TA zLHe)9&3JR^XmcymD4T-HL7wZbiFMOr$k%_*C@9obrDXUd##DV3->+!Oq1i0@6!k;xH11+j(3`P;n~q3LJrd)L zc&KPnAzV})mPp>}ssP?rPKC(!Xrr^^Ph+Q2%AUX}&@{>Euk_HgtI!^;tbE`<&r9Ky zecy8Y#IM=ntJk`)@Z$9$!I8~9uaKGU7jL%@_|#6SOaZx;7+uNC~s5J9k2FvdUno1cfDO>i%~OZo5^SdX1p6Zju) zJ7(u$WfQc`d(=xDZf>_pGbqCz;s<}rKALUne+ z?E%N^F@*N?Pg%W>havDAtjx;WzC$UmdOvdKU=xtdY6b$7SGda-RpP^Sbx~Gn*kM1j zaL6~mdKcPUHyAj`g00P>kLa(-L)Pg2Hr(AdYWQ+zF{J#1f_U-|ZsQj#@pi{`Uw4%V zM`+xmBBIawyBa2$c$S&&=X1})?N9sT@*Ok#6S*}cWF{u007i|Cz7mg7<-@kLru|!E zb{|g;EB!F!z^OfyATQCM!I!f^qaYVGA=T!EQF?G?Nsh7k*N?})?6S9*AcKX-T7Z5v zdFr53#e3Hr<8woG2B;Xbr1-1BF*GSE<5^GrY>__@e7aPcut)h-yE}6pWdq&Y@O&;t z1L(r+$@2lAr+>h==|^tTsIS!W1ZfJ= z9g%-y*re~qx1ZED%?f5oTpAnR{w|oDFz*TyMvRC{8%)CA&Y1M|i6Asf^tS#>EVG;M z^X8KjCE~1x!GRHaH}(xCx)=27x(J+FfxWz61b}#=5F?z0451>evb@|#M(u>aDR!X- zy#Ma3Uy_HjEWZ(;7KA^b_%b%4m>d0n zS9(k9eggX*bKno_;nxMbcpz&?J>kH9C~8t5oLiEr#nhaInG4~dyHZDk8V>vyo65u) z(`7^?qpSTU6i4y)PXNGkO8S?v@Bm>il>Q|A|<0 zCwpR!&IdojePt-AVnxyn^0eHoe*35E(&O?>=BVvn{hCK{&RqEOtNATwFi~vxb61U z<_W&7hs4oRa8uNA8~c%{dv7M&1bD%kzFT_AOZH<{4edt%X>gz__@O(HRWDxtuezqm z5Mw{PLvOTrMYb>~=Dy|Piws~ab8e4Mf;-qi=J`KdRaNAc;V z=ztZ<7@mihvfaU;6#K}oNsBzw`uTeOS5>fyS$X(I$u~j8VL}XA_4iQt`bx{qvvxz+ z=80E_qDrK%pO|)iQgcnlHGK?AV73Y3Cn$d*)HrY-Xzu8HfwGK;_^&+5I=?38_V$3& zbGG-7@5a|}0UlfLGapr&gi%rNt*`;pd7Pho>NJ*TpDa?q#&ZVmqo>vBYU|)E0Md4P z&8;Z03_r%VfwkpB$$g?{#6JY3oIZu&px+W={!KytapJ3BZZ7O8I!@X-2L|V$>P+o@ zZhE^0DdfrE4l8aGnROZ#`2rr25Z_LjyWl=_=K!evPRMfNq~^WoV|*YW8^u%8|DyVY zLCpAt5`7$uZ3>B-dj0;zB#Go8h4$WhOIdv<^Su^8d)Y)J{j)7QPlevZBj|U|yecV< z9q&CRLaTNs?KXl$5veP42VW8s%a1K(OST);hWCqO*$K1Dy2bYCJu+og9LT5!Eh6$I z3IKXG36|YWY~(^)V*c&%yCy?9(V&U7(VFv6z&t{C$_6c^3^NP_GKd^+15K4o?tPgM zh?a+NO35c8sg!TY2ndzB?hlo(BoERj2Yp#O7%dm zt>^jKySN#z?!d0@aH-K>5U43{`cA7qAMB>mUj%H75O6~Zu>X$O%S)Chd*N) z(>$$n_{Tn5r2%$mMI5n1)F)a^TA0V3=8j8PS1`U)f{LBkIHu&3{-)o_L^HuaA)7vx z!rI@JT1~pDs+z~Fe0QCwIjOaJvD;^*Mr>@;ORAr1&lDY)AOr}Zg$BZb?k#0rY0zy$Fi>`*Fi@1yNgyO473waIQTq`#-Atl%12 zIKfpc(ebi8dZ-I-Dc5YxRww|Nzxrln!Ma=5w$?~#)8>2p{unc==j~Uh+!q_&(se9d zO$OWt^Cigk_V-^_(t6&W4tV`Zc0TUhKl8PKDADYuI>xo zj1e4a?zJbZ2=|2=$wM;AqbJlcV{shvM6^ZnH^+C)iT9TozDy~^_8e*RjX}R_A)ILv zmXss!gS2yqh7J zPMR?u=^%So7}2I%XNFz5NS8f*r2wi_Rm;W9_eqO*wDwaC8n%Q0`vP0pxP^>(;P19# z;Qm>r?V);XI!crkQc_KuROPr5Grg6%tH5k%Iba2{pz9={I{u-W)b?~)>Ku4i7QD;A za*-7GI1XBSJgtFJfV7R2NlB<*5k8JP36a%ANQNEK6uaf=X+E_>P8nbYTlrnhG`RLF z%t^z?iDd9bDQWNC-OR9^n8Umm=e!Z?Q8x16DIf!)soCioZB51J_9$943opg2}1W=)iNB^f?o+# zuMlJh>96D}KsQ;jJI#Ldh%y{cz6T(S)<8i^5FF7oQ!y`9m(TZ_)NTy3h$7qyXwe_tR#S~*KwBiIrcmI7FNdCIg2RR&+?YPG zHl=dXOkP8NxLZN)Lz)iBOH zlf=z{DT&qj00c(kEoJA5FooU4zk^Q@n$~l8q|F)8kA%psaJZohg21S)pX%1IRozTl2zFRZ z?3_4D1!XFIivcf1eKe_%k(#z6o2+9;Wch~7tcl>5gt2t6g_+dxjI^CwX<!?3X!F5LwjA4pCiC0>I5m%Ep^B zUl+7bSoMoOMTbLVs>Z6hRCAQKZZ|@@<CupyL($68bA5`~~ zgLhpt2^O zU7!-|PkxEWm6*zN%*PzLs~;V7oTKre7;yc3!ZCCa{VI_Y_u%1V7^(Z7^!MDG?F;=l z*t2KF(QBgl_urXh{zy@634jN3B~!W`^PjFKdc z1NeF7S#+|-%HC4x2&4#q?WEsWd!J4KCIx_p6>Wda;zHJ}52)+Il+IrmJ+&K(adRKNV{Ia%rdb-v^^y1)y(oRn z*l+9nr55>S{10eNc*4B^tf*56DtZZRQfN3RK!pE*TVkD^&G>w*Arh70Uy`8ofz3Ea z$M)otB}l9~=L<-)V5}WJ*cH*kOfoMqE2g$6(Md^hM6V&BgJ)1t(){Z=Wb{i|OuHi@kjwqi@1+ zjpgSU%D{y+`odgF+F!Ul!$i6L$%;`EgAHpU3BLe4{twplLrm5YegV6+v;OU>m2`2b z2Wsx^&8RWmp#o3nsK1M^u+<=r^;q{Vd^w9DG@GJ-arMmlrkmjUZ|FdMz+e1T{yakW zC(_=}`j{%fKIxMI_a6I{fvUgcYnX-H&>U^u3qa-YC4sEe_9S+y{@om~$C)Q(5ooKG zs}+P=Yv^R&4BQ~}UJ*FHzlNLdsARS!>3~h@P+4b^s|x zXAfvF~GhYBP%cuDEp)UdYFMLzuQ+XlJf)M)iyq1Jnil>lWs;Ko1gOu1 zY#mKdca`o0zc9Cz+%K*E{K;nxGrATTyw4>yqu&NKzMkP^ES_i0wn*YEO)$5|oU5nUx6R;UOU{S?StEIR!YO?!-Ure+f=1;e zQRx%WPmV7d<66ESgXh5pXJnRTuA6_m+F*Y#IuamMg)(xiGA&aF%WD+~hugHVeI(Kq zq&zMYyI`eQH_kx;eroZtCbQ~E4k-AS4SbC~z|@O8 ztfy}!dipca%lT%(d((aHu;4UI{NYuco~`7AD{{=R>^6(nvf!NRFDGVO;f~Q}8hdadE}9;Au+&CV_N?dreoNr@{FlJw~Q_n;-uW}>F@B*&vz(dJ~?MbdZUu7dG+Lp z2eRIN5^_uDUtPVUaZA_2i-m~(%d{L}_6s1Q*f+d-MKYH%dulR8DZ4|9+%}sLL(kXa zv#K#@{{j8u@l-a}EPwT4164emuzbC?Q@>2taXQNWG`W^?0V~Pkr+C$M+$8K!cf%a_ z=?hIt0y{yqs%udzWo4dLt@X1o6T?N7uY4-X=iQDe>M=K>R@m*_wmGkK*I~RJ&b`3T zowIq1eSuL(+gGZCEYsa*G7p@37ER0Xd3??7czbj|69&TbUPYrUXuR@ zd{dCqHjrvYAx!=wA2w9sD5Eyun~+YJwGSHeoFYjwFrQ?Nvkd*Jp_IHC4p4X|6SrPM z4BMUX9>h0S=r*BMl<6Z~RKaH;nZluyzM4EzzX|hH$-|kh)A}LmjID1U^*|r&uT^xD zi?eoyOcp7H$~r>lSYMy`Sq1Ik&43;>d2ZvNfsjVIQi-t2Y#)@(S0Fk30eF%t0^5IO zx$J|ZKO_VxHn^hGe(C z3FDbInyCqL(rWP#zphFs2U81bb^n|+~kr(7d-#(%ZLI7p9q`VzRdWdJi>e1U{560KXNpPw?#CpMXx5qLb zwIS`InmOqe@L=A(KIu|^CFP}JtavOKP>YsIx6O#t^z1uWB+`iVv#D@N=i1@9ER;F;CBI`gT z9=l1VaB4Sm_Wp23a;z`QAQDZjiuBQ^Az|Ogg9b%52sMy7rXn|vD_Ox_u&z@n<-(vg zFAcz{(=cPoysh`fT+XoTkU;jFv<^#h7pn8Hub?yA&Pw-ZdA`u} zjakP>)TSt+wGhhka@KSa%4^yGm?K9ZP=~PG8;efY zVDtTZ2=?S@02k+*dgnyCFKnLShhwL?;twCjlfh_b9^PPPX6HTXt$%K#OoD%*AsVC` z;p&JhOq)x?&3}&h_RT;EBL%l8h>>zh>s0l!^`9m;+RAZE$1qBr_=qHP)bck}PsWV3 zm+QCdfKDxTg9!^qwp4MTp@?NNX2Si-qS^T#0yovy=?zAmL`5l`%!#YMXlERL6_S5G_t1)cwY#&?I5`T6Z33G>&1G;-?F6F zv7`f{tgGqdG|3D6AulJ}K*Z48{lcm)M4#e=CMP^@DuWlanP^8_b;~RH+7!-5kv6OP z1fw2*O{TjG(r)!LW>zuEqBV_)T@kOh6U$UW;)>=mu-L-6qZ&HivW1Bc6|rzAdfay2 ze0nUPl^C-HPI2IMN*djSlIGf|?DvLMZV9EeUAX-@y>bo;31QBo^#PHBHL1=8bBLlB zDQGp5W{!Qe)}m8HgwjHEGJfP2;zy22^b_$YQS5INZqgH>MCvS`!y`AE;w;DYHPQ)v z*cVh})+Ehe(4g0unc4Zm8D&7#oaF3~-)3$k~2qPg3ZAmIfY0QV|2r2Ed_EUyK%c=zkl}298{Uz}k6GX%p&fdD-WeNjJ4szhLoJ3vK z1Ait~4~%Lo{Opf*bG&QlmJBKDc7VGTp?OO9dl`Y(^bD-?iMOq^cyI@q2Mqff@*DG` zNa&5+r8EQQ0UOBqqttFd=YeA6MLqXhncb!=P!=W~97&`fpR#n>5RP7ok*nEpBps|u z{LBIRfl^eN^S4J3OA-P5zvmODMT9;-=Z=y7qX`~!-eIzk3+*bgPP+XCV3I=@Jf(l_ z+RYYW4eB0VHF)L`wR)2e@O{=Q)bNxqJn^^k%j%k0y|TX9IC%}8=6=|>TXF67DK<|T zrW>{Ek)QhmqzWZ2xg*4Wpq52$CH@ok-u>_5q}Cl`DEMb%dO*Eof})nWJ%g|Ahg#Hh zTk!v{C*Fm53v!ww8v9{PE;QFIbAJlp0U}eRy6Iv{LSp@G;P`q*SJs`t0h({(TK1 zS0++-@}A8GHp|rKidgMHGWfrd<@YXwmHXkkp&y>Sy<(tZD7<;pLi$AKbGMsP&)0{T zOxiUB4@ezx9Kl46k-5!cbvU(hic{bg|WHqi1$=xs|Gh=i2vecbbI&8w_BgjGfB zy1)NxxqUL+obea9*uG5^jc_0Jp2aA)buf9$YGvH}ZPS#sVubEA$9!xRH=`jld2#0X^t)8y&M)E`1ZTu)zMJ@XH`mrTJG${tUymM-qjFEj~eAKYV7 zo1%=jLs}%>$}td^ZfRJnNRQwYp>vXri@Vy=^kg-X!n6fc^rHpeh*7HIcW1pIfgRG( zNG`S9t{Yvb0uE{vdX3gD42N+MQwFfH5+V*ASZ>3&)Y9|kEEjRT4a^@CIqJYWXlbSA zax56}*q%$13sQ0zvZWZB%&H@b=nk@jn2jU(CMtmKM=w%Y6oGz=2&?Uv8s9qJ-!Nof zciq{23emUSS|_L`)|;v{7d6Re!}bv4d_ANf5fMJ1VPZ_DhkTI;MygKafIGZ5)*k4( zP9<$o*2}JVapGiKkXrTPrT<1CUEQ~mhLLI$m3rlxxH?|Vp=UmkPg7eDQLW#qQM6gvOoEs6u<)1a^7GoM)_!@^FqiI!+I7 zfX}zTB-ksDq;Is=X_G6fG(5=+Q6rMs21fdFDbgRhQ5?|(RwmZ@##Y;QR_cs5-N~1J zX^Pm*+{jTLzuAm6VV~&?;C59&+332e7B}_Gjvt4xBx`ZzN_>B3zrSs8MflirgN#0| zre++;``Z)D<@hZiIs-(+;goeWG_i)*k)$DFTl(#cQ6M<7QfnqUTF~S13A|FE`(KW&u77_j zNDV*dU};J$6M_e9KqCuM-|dkdk4s4PVZ=@}jhuI`ey^u&A(i^Jz?5rb?s#Z=}%-Ks2_RxmGEUHV^`)^=))t`O*Ddz85WZzqi`YJ*wtw$Ic6Bz2a+u zDyKKGZr4G{!vRCNmMNPaD%u-DbL3*3wy5*7Ip&+|OtD~=!QD5IC6cnG`HZuDsg_Rh zPbDv}6`_OSvi=u&#A3GRX&3a3Uw{fu|$lGL95c zDtbBDYFFa13pQc_+|fSdZ65~kI5oF%Dg8Nj7dj_K$&J&^wCL0sX-vfAz<_$FrAK8= z=#cC4yv15FW8G!;6UNK&?{=tw;-(RiuGQDj57rT1i%=pCY0g6FDfX{|ou`s{{I6#j zZU>33#wR><%O0W#5gz6~CCR6^hg%$Nk(K3j_g@J7Q*R0flCrPI3w1>8f_(l8$A<92#Jh2Jqv5?B1+xjdfh^7g5OLbpM*RjQam-z z#vagT=uG~h^h|xW8JslfzgR2{p_VAOYh%({)i)-|lYPnUe+Gd8JZ=*xow^mdJ@@vV zcqGe<7)CzzVEj)T$~rG$zu>|GT9~{r~4n;s5e=`78Ph_Zd$miz*xoY$>Zx(r4{4>62=)yASp?+K!bavXF#V=N2Syo>f}Eyo@qI ze|MF-aaPCdm6S%NkIa=$>&6|3OFs=nQ1MiflKYJFg(hOLrvEq33k+AlhA&Hn-pfC6 zo0x+bEESE-zvqaGwQB6!|`8NY` zt+y~UxXVXbT!YT+#ExcL#*@Wm;Tfe*OFuOc&}SLXh{-y61Z~Wd7_$;4`F{S*NUt z?E9`LjGaVTLSxI4C5-hwqx$u{zxVaena}y$bFTZkzRP{xW6l|d1GR#x??ZjJRkF6} z;+yx|qJCa;pQXkX<4!@LSlVx{x0o+Gh98gsex=CQrQ`UEWSNB4M_8rPg^WBV#=bs% z%uL)Ea%7d*Vb3sspcQd-q5DWfOoaIc67CWtL~=) zN$`h_m*Yt+eoquH2b?}Rgwru{B7dPUQ0azMFQevk@&3L2aHS32?_!i(w3V~kwD0BF~1;FS?vX*P(tbD7cthh z0#(Ax)o^=BAVFY!HSO(xm| zjSFOZRbumM@2W-L@(<@Tu>DGel{ib#(O% z=z0;I^zyacU=d&Anh-@; zgs~n`aP@+fDFdvE)c?T*B_nU010&R@(G#P$_=yu5!2}&RcL$_s}PB-KrxuXmR;$eQd_4VY^Ah@+z@=d~cfB52ht*|LU=|i5;2sC;AC2 z#-LzvmvB0|6tg4$S~g7V05ad6Y(;qnPUq{jdL%TRzXDq=OQa1C@72o#jl!1f_LL-v zi|Z|JT%CJJViB{$xZgBAuOArFE<(%}0tHlr{iUD0Vr(SETz|s@4iKFCSS439uo_X@ zY9s>DtY7&}=wj@4q+^^hNC1H14io}(la}kNc6T?2%QA&SK~tp^yNWdRNzD0>R==&g zO|Yc=|A1m*CVm$NNJ!wAuz=D^P45R~CL!3FME zLUW>NtHJq+Sil+O?>+}c0d45tz^I%?)&^F z>R}O$MToyL#m3hOz zvFiYmzkvQ;1)c%HN-#sISG_}gzhKq0A$TVk0kZv2N14?hZ3k=LqoI+IaC8!{g+>KTB zZ68c2g>Md-V_c^IhK^p4)59u6wR|pSoKS)tsHCD~YZGg-8_2gYpIC0V791pV)P+j{ zf7omevKjyXodDS^ZQ56dRkdsukL-;#LnZxUvk5BjT1l^-3Ca%H1d@4Joal6yM%Nek zMQ4rT_?UW@!?oH3rTTNN{@Vma@zey8-Pa@WuxuTNcv9Rtr3rx(p0JnUbztIZL|LK} z3!D&LjJ<)d8D97Uh9jBL<2x}1{H+v(;q}VAqC;&UDB7UViFo!W03}#(_4x@v5jK|M zmUEVkVl0#tb(mqbL$XQs~lV(ej;Ln>+Gk{qjIz)Mt=gO8ccK`HY; z!6MQ#T_s;=aceq~Pyg)E)cLsgMv73&=q~i<2)LGsqsHWQU@ix z9a$bX{L^zfVI!rwNWtr*{@BfrSBku-z|Qi0F`&94+ztk0{hbXsBExDXOykv- zisi<7|A|*yU*2`Zrx=OFSk+d0I(WL@rxgbpjJXu+HWu&|+Lj6me)pR^Hl6mON3!K+ zr1M7>n3u!bm4*yB~BgmOE`t0mRLv5$x91h7ORp4}6yZ zIw}jXYp*4O|H@7Ya6#twG$VkhqDx99+RVgy^}s0n8dLY24bpYMM_>s@S}$Bk8hC#f zxxA8m4p*W&nyhxSVbC~>)W=UJxb5HYL~^L8@ig4iE{loy64n~ZTbL}0>dZI5mXnTX zTCFI-&)n`OzRWHR{Orf;{x|mv0O15RnYN&`z*$=%1>ALuT-|f}>Wthz4cRcz-u1Cj zU6w4x93d_P9=k`Y zJw_(`?qD6Gw|@sQMoO4c)XT;}eo9&gitHnQvj#kqL6I+_MKD=NRkO;j)fj9{3?p?) zI66Y&DOR4G3yR=RjEgw1XFw=B{&><`?8r-?tZ?WR`q4|$lmPLU4g*lG|Kw-83ZD3N zeW$OPPZYV&FrZ;TE-Uv)dxWcI&el5r+UG*Om0{510$XUy#9)wkLL0Z0@v0J4 zR!pw9IGJe|uCs9uOxh-Jz~Q|1e*@evil==nz}*5YVUnfV6+>z1MO-aE8iMSM75;5S zgSGjhi?avaatVn=6htd)Je(+iqkT=wN2(&J??x)cPk- zXq}k&$$sv0=N^Oef9YIJDtR2)U7l<`CyIL6(t?mSHC1iRLm^BD-M;EmCM|?2ssVQs zVB7W^6ctczhkYF7#D8kk>#F%`3-~gI9!(i~zLn>jIVou%^;S=@V*PTE(qA;)@Q6w8 zZ?n@~am@Kvfpx&%eE(L)kG}!SL9LZt1S2i5FKOXT(Sxk&e|wmHXO8*hPuA%_Z$sRs9-CKY~o_V}a#X|KnXh ze(Wpbte4JiC7iRfR8ZWxeIN_oM*#&BAL-{tF~)keJ>++|unGI&eZr%Gec;9w-X{TL zfqN}AV)d1~4IYT=rij)&U4+KTDyJ&JbGrB2Vl(!|Z+=rSauk?&Z|Vz7KquYn-TMuW(%nWME>6SF4|<<~)irD1d~&Xr8>K>$LXe zd*h3d!t6QG#OO#3j?=`&6Lz}RYxXe_G2fY&QGQncM7$+Cvd8FaZIFoPB#%+A&Wu%5 za6_YKsUE6!D(R}#_E)$t?&xbtrL~OjE7#|2VN6u;%E`}A?`k7A@2UWIRFX~mWAN-= zt#TT2UNxusAMD&DYt$2#lw^iK?zrbNrqabk*rqg zUB@y7Wyrv2?fgl0OC^vIhT6X6v#6nG#|IN+9yw3Ko<;=6B11GDa}eo6Xau_6T=qN? zGR8qj%n|9+a;H_hV%(R^{9VkiE zwY6Sh?HKf!x^9K0%$_Y;}!3Z;8>0^G$+xV z@Ce#n&8+~oH&#Ca*d4|3x}BwOL}1s*r{Epy*8|=8@0E!nrUP>fGVQVzp~Kc0`cBM+CfAC)Y>hJ9DgT7nKi1F71rPJwhtvG+My;|sI-KZou- zPWW))0J&Pc1U<^cUHwf@p>b9;u{xKtIVLfqHty=eUTN)z^LE6y@lVaHHh>WV&W9iG zQxWEQmri)o!voyhoWF)t?jp*OTS6cIj^3UWne7mkSF=(cB|V0lf5)Mb^*9Cm{1vGz zKw`MhrYvv=g*bne7}y%mq(06w2K$D=eEEKh|3hbVecEt5D>v2uz96l@hq$P_rql6x zX7U%OCOvab#Rw%>sgGL3c^yV=R$xJt%7+Y~`zk(PCRSG=nV60AmI9ClQZ=!Y^0)YB z`V+K+Jc0A}h|#tXMmY0%k|XmTcfVL_^_gx&*WHXT&z|S@LHr-01mRY%XusU_OAjJ& zm<=k#*CZ0F+nAV`*>$yi!A#k8*X_-l?TdLEN^YG-Yq;ac+WH9#&KQ(O`im!hiWdjr9o6X1dvell)S8QWzq z2-Zm$E?Y*{IQSU#J_}PG{5D)u_)eURGZ+=GH+mP{UXy8RmkAVzIk@>%ea;{B%3m+^ zNXg1eT9Wdt?teMQq%kf0Avz@ktF!OF85Fl4C_s`LHOU$FlZWTNz3kJ^#d!|6n3=e= z&ZdRetDjhUsouW1E~~j)XNrD@3rD7G2StZEwpPz+vt-My?r`m0O38n?cBR$N?_!4J zXatIEiMQx%!%5NO#xniDt7o^0ZW^Uv&-04j7L4Be0!1|{!}T^{I47r9I}Ym6x!Jw5lD=TZQ=U5>1*m~k7!-+~K|2;YyK zD#^{l_=diHn`uyz3v!2Y09jk0cJ;cGFPj-tdVDpWRkKsmM7quem|TCQ+b{aGLw~;4 z#j+mPUGfA`^^tE=3EP9;BrK0vmYCjgIeA92^Qq5Tu0U78-!4I+v1E-a+30rCE~9Y2 zm(LyP^1RFQ5eMV#6|a&^CceKY$R7yIs84gZTFfX68pt4dIr>`R9u<_)2KtQ`o3^za zcueOe>A#*#)~N4a0G=zg?QZ9&se_-XJ$!v^;mv{s@^wxYa;L3*AlXZ$pSJp1XBG49 z-el5NR(G@u=y&a@9Bh|nP}0h>`pb3X*&C)>SB;3WpY*RuC1nmRi+#PrGpp%eU@md5 z-awS~c5r=Ti*33`r&I6@hvgp@5%*oOB^p@`9oUQW?b-4x~vtP%JIN*SPD8K_Vi`D z}EuBuyp$mk(XuB62$!0rV$2CqqaurdGgT z@D_9I_GY8A;VyMB?H67>9Ci;Y>}ZhvqvNLK6xZs$#Q;QP=bIO%#3k+1dtk=dC;ml# z%Ep-UQaOEV{qX67%H6wrB&skiv+Gi32+T9Lc9+nSI_NX9iy&LK$cG^t<44XMG^}y` z4`5ZuQOvu$6+x=rKsoEsCg8*~SXXDjc<@`YLT1%y! z)cUsy#?qP*wWh{^v)ie08}j3G%&k3VnEYSFg$0RotqX?R2%q(>4Bwnu3dmoUCMas6 zI5`A_oV@yTwZf|{oliakuD=<*{bn>UHI5M1M9s$h`c6{A!f6QPj6Vdz3W4Bz<)Cc% z5NhZwRZU<8<_PpV`!S0$Kd!yfweSPpIH>62Ow9Id!}O@_3$5edt$==;fR0h?>2Ce&5`9den5PcSFDu|J>^H zS6>*S;I1hzWG)Cn;4UWf?qQaX4DUXo`c{dneRauxmhKdM?OU#a6nfxjs@CW|PyV6C zxKf9-wjS^%RU5Y!Cf154cbvsAF6ouPnodc}U+e@dgUosR`)uGBw5KYm!#c042xhSI z77r)AqP>3q1r^OF6HYaW{S{g9_Wj`=QI>3x(V`W(lu7MjJ;upd)R31{xjRQ$Y0Sjh z`>nve^}d3$xayjC$kS{+ahrQJpT2&u>@|rLj9>C+tH3NW*9j|)ad&5FHpOj!QKV+F z|B_yKe#^u!ojIoE7>Pc@Lpe5NC5?wZJ*3l#dvwHV&!Y6jbM5{E{;oG$`8-c`+ox|U z%TuqiT4BR?IpXdKvQ{KsfZCj*|C?CNIYkA5c;b&Bq1sdyjB$?`&*Cvis0fv(Kpa7U zAKyTEeOnNG%@J28cnp7B7AgYu#mmV;uR+c6_hq4?oaZ!n6qOPo5M93`5D?ve{cW1y zTV Date: Fri, 21 Apr 2017 22:01:33 +0900 Subject: [PATCH 44/51] =?UTF-8?q?JSON=20=EC=97=90=EB=9F=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Channel.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Channel.json b/Channel.json index 0724cf4..673f049 100644 --- a/Channel.json +++ b/Channel.json @@ -226,7 +226,7 @@ {"Id":279,"Name":"JJC지방자치TV","KT Name":"JJC지방자치TV","KTCh":279,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/AuXr9jA.png","Source":"NAVER","ServiceId":3244879,"Enabled":1}, {"Id":280,"Name":"채널 Ching","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"채널 Ching","SKCh":105,"Icon_url":"http://i.imgur.com/tRqGKcS.png","Source":"SK","ServiceId":907,"Enabled":1}, {"Id":281,"Name":"채널A","KT Name":"채널A","KTCh":18,"LG Name":"채널A","LGCh":18,"SK Name":"채널A","SKCh":18,"Icon_url":"http://i.imgur.com/xti35f5.png","Source":"SK","ServiceId":242,"Enabled":1}, -{"Id":282,"Name":"채널A 플러스","KT Name":"채널A 플러스","KTCh":98,"LG Name":"채널A플러스","LGCh":115,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/rRisTh8.png","Source":"NAVER","ServiceId"5286712:,"Enabled":1}, +{"Id":282,"Name":"채널A 플러스","KT Name":"채널A 플러스","KTCh":98,"LG Name":"채널A플러스","LGCh":115,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/rRisTh8.png","Source":"NAVER","ServiceId"5286712,"Enabled":1}, {"Id":283,"Name":"채널CGV","KT Name":"채널CGV","KTCh":29,"LG Name":"CH CGV","LGCh":39,"SK Name":"Ch CGV","SKCh":53,"Icon_url":"http://i.imgur.com/fwjRwkx.png","Source":"SK","ServiceId":187,"Enabled":1}, {"Id":284,"Name":"채널i","KT Name":"채널i","KTCh":250,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/X7lXvtw.png","Source":"NAVER","ServiceId":3173174,"Enabled":1}, {"Id":285,"Name":"채널뷰","KT Name":"채널뷰","KTCh":176,"LG Name":"","LGCh":null,"SK Name":"채널View","SKCh":212,"Icon_url":"http://i.imgur.com/lvtWgFL.png","Source":"SK","ServiceId":276,"Enabled":1}, From 8e6def4ad1ba60cf5a6f5579183c7a2df7c02236 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Sat, 22 Apr 2017 22:57:28 +0900 Subject: [PATCH 45/51] =?UTF-8?q?JSON=20ERROR=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Channel.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Channel.json b/Channel.json index 673f049..f1c2a33 100644 --- a/Channel.json +++ b/Channel.json @@ -226,7 +226,7 @@ {"Id":279,"Name":"JJC지방자치TV","KT Name":"JJC지방자치TV","KTCh":279,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/AuXr9jA.png","Source":"NAVER","ServiceId":3244879,"Enabled":1}, {"Id":280,"Name":"채널 Ching","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"채널 Ching","SKCh":105,"Icon_url":"http://i.imgur.com/tRqGKcS.png","Source":"SK","ServiceId":907,"Enabled":1}, {"Id":281,"Name":"채널A","KT Name":"채널A","KTCh":18,"LG Name":"채널A","LGCh":18,"SK Name":"채널A","SKCh":18,"Icon_url":"http://i.imgur.com/xti35f5.png","Source":"SK","ServiceId":242,"Enabled":1}, -{"Id":282,"Name":"채널A 플러스","KT Name":"채널A 플러스","KTCh":98,"LG Name":"채널A플러스","LGCh":115,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/rRisTh8.png","Source":"NAVER","ServiceId"5286712,"Enabled":1}, +{"Id":282,"Name":"채널A 플러스","KT Name":"채널A 플러스","KTCh":98,"LG Name":"채널A플러스","LGCh":115,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/rRisTh8.png","Source":"NAVER","ServiceId":5286712,"Enabled":1}, {"Id":283,"Name":"채널CGV","KT Name":"채널CGV","KTCh":29,"LG Name":"CH CGV","LGCh":39,"SK Name":"Ch CGV","SKCh":53,"Icon_url":"http://i.imgur.com/fwjRwkx.png","Source":"SK","ServiceId":187,"Enabled":1}, {"Id":284,"Name":"채널i","KT Name":"채널i","KTCh":250,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/X7lXvtw.png","Source":"NAVER","ServiceId":3173174,"Enabled":1}, {"Id":285,"Name":"채널뷰","KT Name":"채널뷰","KTCh":176,"LG Name":"","LGCh":null,"SK Name":"채널View","SKCh":212,"Icon_url":"http://i.imgur.com/lvtWgFL.png","Source":"SK","ServiceId":276,"Enabled":1}, From bbd1244e5d4183656b63fcfbbe08ee0fbd492c71 Mon Sep 17 00:00:00 2001 From: wonipapa Date: Tue, 2 May 2017 09:58:32 +0900 Subject: [PATCH 46/51] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4be9587..eb7f4fb 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ PHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. ## 설정방법 epg2xml.json 안의 항목이 설정 가능한 항목이다.
    -MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)
    +MyISP : 사용하는 ISP를 넣는다 .(ALL, KT, LG, SK가 사용가능하다)
     default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
     default_rebroadcast : 제목에 재방송 정보 출력
     default_episode : 제목에 회차정보 출력
    @@ -37,7 +37,7 @@ epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
     
     -h --help : 도움말 출력
     --version : 버전을 보여준다.
    --i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
    +-i : IPTV 선택 (All, KT, SK, LG 선택가능) ex) -i KT
     -d --display : EPG 정보를 화면으로 보여준다.
     -o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
     -s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
    
    From edf2ad1596cded7b6d770877b7f370454ccaf2c6 Mon Sep 17 00:00:00 2001
    From: wonipapa 
    Date: Thu, 4 May 2017 18:04:39 +0900
    Subject: [PATCH 47/51] Update Channel.json
    
    ---
     Channel.json | 53 ++++++++++++++++++++++++++--------------------------
     1 file changed, 27 insertions(+), 26 deletions(-)
    
    diff --git a/Channel.json b/Channel.json
    index f1c2a33..61ef1de 100644
    --- a/Channel.json
    +++ b/Channel.json
    @@ -313,30 +313,31 @@
     {"Id":414,"Name":"SPOTV ON","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"SPOTV ON","SKCh":118,"Icon_url":"http://i.imgur.com/Y3eYOc2.png","Source":"SK","ServiceId":136,"Enabled":1},
     {"Id":415,"Name":"SPOTV ON2","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"SPOTV ON2","SKCh":119,"Icon_url":"http://i.imgur.com/jbdurz4.png","Source":"SK","ServiceId":137,"Enabled":1},
     {"Id":416,"Name":"한국선거방송","KT Name":"한국선거방송","KTCh":273,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ZSdcknl.png","Source":"KT","ServiceId":273,"Enabled":1},
    -{"Id":417,"Name":"EBS 교육방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/eEsZJop.png","Source":"NAVER","ServiceId":815452,"Enabled":1},
    -{"Id":418,"Name":"KBS 1 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ikJ7QQn.png","Source":"NAVER","ServiceId":815455,"Enabled":1},
    -{"Id":419,"Name":"KBS 2 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/qTrmNld.png","Source":"NAVER","ServiceId":815458,"Enabled":1},
    -{"Id":420,"Name":"KBS 3 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/3tHl7QR.png","Source":"NAVER","ServiceId":815460,"Enabled":1},
    -{"Id":421,"Name":"KBS ClassicFM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/Z46a05G.png","Source":"NAVER","ServiceId":815454,"Enabled":1},
    -{"Id":422,"Name":"KBS CoolFM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/0SQrpHZ.png","Source":"NAVER","ServiceId":815457,"Enabled":1},
    -{"Id":423,"Name":"KBS WorldRaido","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ns1k6LN.png","Source":"NAVER","ServiceId":815447,"Enabled":1},
    -{"Id":424,"Name":"KBS 한민족방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/S5YVPyx.png","Source":"NAVER","ServiceId":815461,"Enabled":1},
    -{"Id":425,"Name":"MBC 표준FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/E9OMdnO.png","Source":"NAVER","ServiceId":815464,"Enabled":1},
    -{"Id":426,"Name":"MBC FM4U","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/csdszZD.png","Source":"NAVER","ServiceId":815463,"Enabled":1},
    -{"Id":427,"Name":"MBC Channel M","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/jlKGpWs.png","Source":"MBC","ServiceId":1,"Enabled":1},
    -{"Id":428,"Name":"SBS 파워 FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/7qcJ4bm.png","Source":"NAVER","ServiceId":815467,"Enabled":1},
    -{"Id":429,"Name":"SBS 러브 FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/XHHHUZ1.png","Source":"NAVER","ServiceId":815465,"Enabled":1},
    -{"Id":430,"Name":"국악방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/qpbhUhF.png","Source":"NAVER","ServiceId":2891853,"Enabled":1},
    -{"Id":431,"Name":"극동방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/PlqBFtV.png","Source":"NAVER","ServiceId":2074616,"Enabled":1},
    -{"Id":432,"Name":"BBS 불교방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/B34jpmo.png","Source":"NAVER","ServiceId":815448,"Enabled":1},
    -{"Id":433,"Name":"CBS 표준FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yBNo2mS.png","Source":"NAVER","ServiceId":815451,"Enabled":1},
    -{"Id":434,"Name":"CBS 음악FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yBNo2mS.png","Source":"NAVER","ServiceId":815449,"Enabled":1},
    -{"Id":435,"Name":"KFM 경기방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/8hSikAY.png","Source":"NAVER","ServiceId":1974893,"Enabled":1},
    -{"Id":436,"Name":"PBC 평화방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/G5fTCL3.png","Source":"NAVER","ServiceId":1974894,"Enabled":1},
    -{"Id":437,"Name":"TBS 교통방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/9RxxTSi.png","Source":"NAVER","ServiceId":815468,"Enabled":1},
    -{"Id":438,"Name":"YTN NEWS FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/dSC3YPR.png","Source":"NAVER","ServiceId":2074615,"Enabled":1},
    -{"Id":439,"Name":"원음방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/mKWQE7z.png","Source":"NAVER","ServiceId":5534687,"Enabled":1},
    -{"Id":440,"Name":"국방FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/zjvlIIp.png","Source":"MIL","ServiceId":2,"Enabled":1},
    -{"Id":441,"Name":"경인방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/zBTPTRe.png","Source":"IFM","ServiceId":3,"Enabled":1},
    -{"Id":442,"Name":"AMC","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"AMC","SKCh":100,"Icon_url":"http://i.imgur.com/cJ1B77S.png","Source":"SK","ServiceId":199,"Enabled":1}
    +{"Id":417,"Name":"EBS 교육방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/eEsZJop.png","Source":"NAVER","ServiceId":815452,"Enabled":0},
    +{"Id":418,"Name":"KBS 1 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ikJ7QQn.png","Source":"NAVER","ServiceId":815455,"Enabled":0},
    +{"Id":419,"Name":"KBS 2 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/qTrmNld.png","Source":"NAVER","ServiceId":815458,"Enabled":0},
    +{"Id":420,"Name":"KBS 3 라디오","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/3tHl7QR.png","Source":"NAVER","ServiceId":815460,"Enabled":0},
    +{"Id":421,"Name":"KBS ClassicFM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/Z46a05G.png","Source":"NAVER","ServiceId":815454,"Enabled":0},
    +{"Id":422,"Name":"KBS CoolFM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/0SQrpHZ.png","Source":"NAVER","ServiceId":815457,"Enabled":0},
    +{"Id":423,"Name":"KBS WorldRaido","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/ns1k6LN.png","Source":"NAVER","ServiceId":815447,"Enabled":0},
    +{"Id":424,"Name":"KBS 한민족방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/S5YVPyx.png","Source":"NAVER","ServiceId":815461,"Enabled":0},
    +{"Id":425,"Name":"MBC 표준FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/E9OMdnO.png","Source":"NAVER","ServiceId":815464,"Enabled":0},
    +{"Id":426,"Name":"MBC FM4U","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/csdszZD.png","Source":"NAVER","ServiceId":815463,"Enabled":0},
    +{"Id":427,"Name":"MBC Channel M","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/jlKGpWs.png","Source":"MBC","ServiceId":1,"Enabled":0},
    +{"Id":428,"Name":"SBS 파워 FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/7qcJ4bm.png","Source":"NAVER","ServiceId":815467,"Enabled":0},
    +{"Id":429,"Name":"SBS 러브 FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/XHHHUZ1.png","Source":"NAVER","ServiceId":815465,"Enabled":0},
    +{"Id":430,"Name":"국악방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/qpbhUhF.png","Source":"NAVER","ServiceId":2891853,"Enabled":0},
    +{"Id":431,"Name":"극동방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/PlqBFtV.png","Source":"NAVER","ServiceId":2074616,"Enabled":0},
    +{"Id":432,"Name":"BBS 불교방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/B34jpmo.png","Source":"NAVER","ServiceId":815448,"Enabled":0},
    +{"Id":433,"Name":"CBS 표준FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yBNo2mS.png","Source":"NAVER","ServiceId":815451,"Enabled":0},
    +{"Id":434,"Name":"CBS 음악FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/yBNo2mS.png","Source":"NAVER","ServiceId":815449,"Enabled":0},
    +{"Id":435,"Name":"KFM 경기방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/8hSikAY.png","Source":"NAVER","ServiceId":1974893,"Enabled":0},
    +{"Id":436,"Name":"PBC 평화방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/G5fTCL3.png","Source":"NAVER","ServiceId":1974894,"Enabled":0},
    +{"Id":437,"Name":"TBS 교통방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/9RxxTSi.png","Source":"NAVER","ServiceId":815468,"Enabled":0},
    +{"Id":438,"Name":"YTN NEWS FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/dSC3YPR.png","Source":"NAVER","ServiceId":2074615,"Enabled":0},
    +{"Id":439,"Name":"원음방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/mKWQE7z.png","Source":"NAVER","ServiceId":5534687,"Enabled":0},
    +{"Id":440,"Name":"국방FM","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/zjvlIIp.png","Source":"MIL","ServiceId":2,"Enabled":0},
    +{"Id":441,"Name":"경인방송","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/zBTPTRe.png","Source":"IFM","ServiceId":3,"Enabled":0},
    +{"Id":442,"Name":"AMC","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"AMC","SKCh":100,"Icon_url":"http://i.imgur.com/cJ1B77S.png","Source":"SK","ServiceId":199,"Enabled":0},
    +{"Id":443,"Name":"TVA","KT Name":"","KTCh":null,"LG Name":"","LGCh":null,"SK Name":"","SKCh":null,"Icon_url":"http://i.imgur.com/tg99cob.png","Source":"NAVER","ServiceId":814777,"Enabled":0}
     ]
    
    From 6ec37704b909c4da0dd1a34725ef9de23ae47e06 Mon Sep 17 00:00:00 2001
    From: wonipapa 
    Date: Wed, 10 May 2017 16:30:04 +0900
    Subject: [PATCH 48/51] Update README.md
    
    ---
     README.md | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/README.md b/README.md
    index eb7f4fb..fdcf414 100644
    --- a/README.md
    +++ b/README.md
    @@ -37,7 +37,7 @@ epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
     
     -h --help : 도움말 출력
     --version : 버전을 보여준다.
    --i : IPTV 선택 (All, KT, SK, LG 선택가능) ex) -i KT
    +-i : IPTV 선택 (ALL, KT, SK, LG 선택가능) ex) -i KT
     -d --display : EPG 정보를 화면으로 보여준다.
     -o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
     -s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
    
    From 0f46275ea1c53c3dfd7bb8e428d100e5ac510cca Mon Sep 17 00:00:00 2001
    From: wonipapa 
    Date: Thu, 11 May 2017 14:36:12 +0900
    Subject: [PATCH 49/51] =?UTF-8?q?Notice=20=EA=B2=BD=EA=B3=A0=EB=A1=9C=20?=
     =?UTF-8?q?=20=EC=97=90=EB=9F=AC=EB=A6=AC=ED=8F=AC=ED=8C=85=20=ED=95=A8?=
     =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    1.1.9 버번에서 근본적인 문제 해결 예정
    ---
     epg2xml.php | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/epg2xml.php b/epg2xml.php
    index 7bbc235..6e58f95 100644
    --- a/epg2xml.php
    +++ b/epg2xml.php
    @@ -1,6 +1,8 @@
     #!/usr/bin/env php
     
    Date: Thu, 11 May 2017 16:02:58 +0900
    Subject: [PATCH 50/51] Update README.md
    
    ---
     README.md | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/README.md b/README.md
    index fdcf414..fd8ab8e 100644
    --- a/README.md
    +++ b/README.md
    @@ -11,12 +11,12 @@ BeautifulSoup(bs4), lxml, requests 모듈이 추가로 필요하다.
     synology의 경우 파이썬 모듈을 설치하면 easy_install beautifulsoup, easy_install lxml, easy_install requests 로 추가할 수 있다.
     
     ### EPG2XML.php
    -PHP의 내장함수를 이용하므로 특별한 모듈은 필요없다. 
    +json, dom, mbstring, openssl 모듈이 필요하다.
     
     ## 설정방법
     epg2xml.json 안의 항목이 설정 가능한 항목이다. 
     
    -MyISP : 사용하는 ISP를 넣는다 .(ALL, KT, LG, SK가 사용가능하다)
    +MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)
     default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
     default_rebroadcast : 제목에 재방송 정보 출력
     default_episode : 제목에 회차정보 출력
    @@ -37,7 +37,7 @@ epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
     
     -h --help : 도움말 출력
     --version : 버전을 보여준다.
    --i : IPTV 선택 (ALL, KT, SK, LG 선택가능) ex) -i KT
    +-i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
     -d --display : EPG 정보를 화면으로 보여준다.
     -o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
     -s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock
    
    From 355592ca469bb82572515656da10b20e8603be1a Mon Sep 17 00:00:00 2001
    From: wonipapa 
    Date: Fri, 12 May 2017 15:48:23 +0900
    Subject: [PATCH 51/51] Update README.md
    
    ---
     README.md | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/README.md b/README.md
    index fd8ab8e..6b1763e 100644
    --- a/README.md
    +++ b/README.md
    @@ -16,7 +16,7 @@ json, dom, mbstring, openssl 모듈이 필요하다.
     ## 설정방법
     epg2xml.json 안의 항목이 설정 가능한 항목이다. 
     
    -MyISP : 사용하는 ISP를 넣는다 .(KT, LG, SK가 사용가능하다)
    +MyISP : 사용하는 ISP를 넣는다 .(ALL, KT, LG, SK가 사용가능하다)
     default_icon_url : 채널별 아이콘이 있는 url을 설정할 수 있다. 아이콘의 이름은 json 파일에 있는 Id.png로 기본설정되어 있다.
     default_rebroadcast : 제목에 재방송 정보 출력
     default_episode : 제목에 회차정보 출력
    @@ -37,7 +37,7 @@ epg2xml.json의 설정을 옵션의 인수를 이용하여 변경할 수 있다.
     
     -h --help : 도움말 출력
     --version : 버전을 보여준다.
    --i : IPTV 선택 (KT, SK, LG 선택가능) ex) -i KT
    +-i : IPTV 선택 (ALL, KT, SK, LG 선택가능) ex) -i KT
     -d --display : EPG 정보를 화면으로 보여준다.
     -o --outfile : EPG 정보를 파일로 저장한다. ex) -o xmltv.xml
     -s --socket  : EPG 정보를 xmltv.sock로 전송한다. ex) -s /var/run/xmltv.sock