(.*?)')
- data = data.replace('" + "', '')
- videourl = scrapertools.find_multiple_matches(data, 'var quality_(\d+)p=(.*?);')
- scrapertools.printMatches(videourl)
- for scrapedquality,scrapedurl in videourl:
- orden = scrapertools.find_multiple_matches(scrapedurl, '\*\/([A-z0-9]+)')
- logger.debug(orden)
- url= ""
- for i in orden:
- url += scrapertools.find_single_match(data, '%s="([^"]+)"' %i)
- logger.debug(url)
- video_urls.append([scrapedquality + "p [pornhub]", url])
- return video_urls
diff --git a/servers/pornrewind.json b/servers/pornrewind.json
deleted file mode 100644
index da36adf5..00000000
--- a/servers/pornrewind.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "(https://www.pornrewind.com/embed/\\w+)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "pornrewind",
- "name": "pornrewind",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/pornrewind.py b/servers/pornrewind.py
deleted file mode 100644
index d7132fc0..00000000
--- a/servers/pornrewind.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-# --------------------------------------------------------
-# Conector pornrewind By Alfa development Group
-# --------------------------------------------------------
-from core import httptools
-from core import scrapertools
-from platformcode import config
-from platformcode import logger
-
-
-def test_video_exists(page_url):
-
- response = httptools.downloadpage(page_url)
-
- if not response.sucess or \
- "Not Found" in response.data \
- or "File was deleted" in response.data \
- or "is no longer available" in response.data:
- return False, config.get_localized_string(70449) % "pornrewind"
-
- global video_url, license_code
- video_url = scrapertools.find_single_match(response.data, "video_url: '([^']+)'")
- license_code = scrapertools.find_single_match(response.data, "license_code: '([^']+)'")
-
- return True, ""
-
-def get_video_url(page_url, premium=False, user="", password="", video_password=""):
- logger.info()
- # mediaurl = decode(video_url, license_code)
- mediaurl = video_url
- if not mediaurl.startswith("https"):
- mediaurl = "https://%s" % mediaurl
- return [["[pornrewind]", mediaurl]]
\ No newline at end of file
diff --git a/servers/redtube.json b/servers/redtube.json
deleted file mode 100644
index ddec76fa..00000000
--- a/servers/redtube.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "https://embed.redtube.com/\\?id=([A-z0-9]+)",
- "url": "https://es.redtube.com/\\1"
- },
- {
- "pattern": "(https://es.redtube.com/[A-z0-9]+)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "redtube",
- "name": "redtube",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/redtube.py b/servers/redtube.py
deleted file mode 100644
index 3ac456fc..00000000
--- a/servers/redtube.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-# --------------------------------------------------------
-# Conector redtube By Alfa development Group
-# --------------------------------------------------------
-from core import httptools
-from core import scrapertools
-from platformcode import config
-from platformcode import logger
-
-
-def test_video_exists(page_url):
-
- response = httptools.downloadpage(page_url)
-
- if not response.sucess or \
- "Not Found" in response.data \
- or "File was deleted" in response.data \
- or "is no longer available" in response.data:
- return False, config.get_localized_string(70449) % "redtube"
- return True, ""
-
-
-def get_video_url(page_url, premium=False, user="", password="", video_password=""):
- logger.info()
- video_urls = []
- data = httptools.downloadpage(page_url).data
- data = scrapertools.find_single_match(data,'mediaDefinition: \[(.*?)\]')
- logger.debug(data)
- patron = '"defaultQuality":.*?,"quality":"([^"]+)","videoUrl"\:"([^"]+)"'
- matches = scrapertools.find_multiple_matches(data, patron)
- for quality,scrapedurl in matches:
- url = scrapedurl.replace("\/", "/")
- video_urls.append(["[redtube] %s" %quality, url])
- return video_urls
\ No newline at end of file
diff --git a/servers/tube8.json b/servers/tube8.json
deleted file mode 100644
index a02e69c6..00000000
--- a/servers/tube8.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "(https://www.tube8.com/[A-z0-9-+]+/[A-z0-9-]+/[0-9]+/)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "tube8",
- "name": "tube8",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/tube8.py b/servers/tube8.py
deleted file mode 100644
index 1649d0ba..00000000
--- a/servers/tube8.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-from core import httptools
-from core import scrapertools
-from platformcode import config
-from platformcode import logger
-
-
-def test_video_exists(page_url):
- logger.info("(page_url='%s')" % page_url)
- global data
- data = httptools.downloadpage(page_url).data
- if "
WE ARE SORRY
" in data or '
404 Not Found' in data:
- return False, config.get_localized_string(70449) % "tube8"
- return True, ""
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- data = httptools.downloadpage(page_url).data
- patron = '"quality":(\d+),"videoUrl":"([^"]+)"'
- matches = scrapertools.find_multiple_matches(data, patron)
- for quality, scrapedurl in matches:
- url = scrapedurl.replace("\/", "/").replace("\u0026", "&")
- video_urls.append(["[tube8] %sp" %quality, url])
- return video_urls
diff --git a/servers/tubeon.json b/servers/tubeon.json
deleted file mode 100644
index 3916954e..00000000
--- a/servers/tubeon.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "https://www.tubeon.com/es/video/([0-9]+)/",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "tubeon",
- "name": "tubeon",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/tubeon.py b/servers/tubeon.py
deleted file mode 100644
index 9947345a..00000000
--- a/servers/tubeon.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-from core import httptools
-from core import scrapertools
-from platformcode import logger
-
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- url = "https://www.tubeon.com/player_config_json/?vid=%s&aid=0&domain_id=0&embed=0&ref=null&check_speed=0" %page_url
- data = httptools.downloadpage(url).data
- data = scrapertools.find_single_match(data, '"files":(.*?)"quality"')
- patron = '"([lh])q":"([^"]+)"'
- matches = scrapertools.find_multiple_matches(data, patron)
- for quality, scrapedurl in matches:
- url = scrapedurl.replace("\/", "/")
- if "l" in quality: quality = "360"
- if "h" in quality: quality = "720"
- video_urls.append(["[tubeon] %s" %quality, url])
- return video_urls
-
diff --git a/servers/tubst.json b/servers/tubst.json
deleted file mode 100644
index 441b6ce1..00000000
--- a/servers/tubst.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "(https://www.tubst.net/embed/\\w+)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "tubst",
- "name": "tubst",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/tubst.py b/servers/tubst.py
deleted file mode 100644
index fc17790d..00000000
--- a/servers/tubst.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-# --------------------------------------------------------
-# Conector tubst By Alfa development Group
-# --------------------------------------------------------
-from core import httptools
-from core import scrapertools
-from platformcode import config
-from platformcode import logger
-
-
-def test_video_exists(page_url):
- logger.info("(page_url='%s')" % page_url)
- response = httptools.downloadpage(page_url)
- if not response.sucess or "Not Found" in response.data or "File was deleted" in response.data or "is no longer available" in response.data:
- return False, config.get_localized_string(70449) % "tubst"
- return True, ""
-
-
-def get_video_url(page_url, premium=False, user="", password="", video_password=""):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- data = httptools.downloadpage(page_url).data
- patron = """source src="([^"]+).*?res\s*='([^']+)"""
- match = scrapertools.find_multiple_matches(data, patron)
- for media_url, calidad in match:
- title = "%s [tubst]" % (calidad)
- video_urls.append([title, media_url, int(calidad)])
-
- video_urls.sort(key=lambda x: x[2])
- for video_url in video_urls:
- video_url[2] = 0
- logger.info("%s - %s" % (video_url[0], video_url[1]))
-
- return video_urls
diff --git a/servers/txxx.json b/servers/txxx.json
deleted file mode 100644
index 9f8e3046..00000000
--- a/servers/txxx.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "https://(?:www.|)txxx.com/(?:embed|videos)/([0-9]+)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "txxx",
- "name": "txxx",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/txxx.py b/servers/txxx.py
deleted file mode 100644
index d678566c..00000000
--- a/servers/txxx.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-from core import httptools
-from core import scrapertools
-from platformcode import logger
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- url= "https://txxx.com/api/videofile.php?video_id=%s&lifetime=864000" % page_url
- ref= "https://txxx.com/embed/%s/" % page_url
- headers = {'Referer': ref}
- data = httptools.downloadpage(url, headers=headers).data
- texto = scrapertools.find_single_match(data, '"video_url":"([^"]+)"')
- url = dec_url(texto)
- url = "https://txxx.com%s" % url
- url = httptools.downloadpage(url, only_headers=True).url
- video_urls.append(["[TXX]", url])
- return video_urls
-
-
-def dec_url(txt):
- #truco del mendrugo
- # txt = txt.replace('\u0410', 'A').replace('\u0412', 'B').replace('\u0421', 'C').replace('\u0415', 'E').replace('\u041c', 'M').replace('~', '=').replace(',','/')
- txt = txt.decode('unicode-escape').encode('utf8')
- txt = txt.replace('А', 'A').replace('В', 'B').replace('С', 'C').replace('Е', 'E').replace('М', 'M').replace('~', '=').replace(',','/')
- import base64
- url = base64.b64decode(txt)
- return url
diff --git a/servers/vipporns.json b/servers/vipporns.json
deleted file mode 100644
index f83d9898..00000000
--- a/servers/vipporns.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "(https://(?:www|).vipporns.com/embed/\\w+)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "vipporns",
- "name": "vipporns",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/vipporns.py b/servers/vipporns.py
deleted file mode 100644
index cb94dc10..00000000
--- a/servers/vipporns.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-# --------------------------------------------------------
-# Conector vipporns By Alfa development Group
-# --------------------------------------------------------
-from lib.kt_player import decode
-
-from core import httptools
-from core import scrapertools
-from platformcode import config
-from platformcode import logger
-
-
-def test_video_exists(page_url):
-
- response = httptools.downloadpage(page_url)
-
- if not response.sucess or \
- "Not Found" in response.data \
- or "File was deleted" in response.data \
- or "is no longer available" in response.data:
- return False, config.get_localized_string(70449) % "vipporns"
-
- global video_url, license_code
- video_url = scrapertools.find_single_match(response.data, "video_url: '([^']+)'")
- license_code = scrapertools.find_single_match(response.data, "license_code: '([^']+)'")
-
- return True, ""
-
-def get_video_url(page_url, premium=False, user="", password="", video_password=""):
- logger.info()
- return [["[vipporns]", decode(video_url, license_code)]]
\ No newline at end of file
diff --git a/servers/viptube.json b/servers/viptube.json
deleted file mode 100644
index f3e23641..00000000
--- a/servers/viptube.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "http://www.viptube.com/embed/([0-9]+)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "viptube",
- "name": "viptube",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/viptube.py b/servers/viptube.py
deleted file mode 100644
index 9af31d6e..00000000
--- a/servers/viptube.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-from core import httptools
-from core import scrapertools
-from platformcode import logger
-
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- url = "https://www.viptube.com/player_config_json/?vid=%s&aid=0&domain_id=0&embed=0&ref=null&check_speed=0" %page_url
- data = httptools.downloadpage(url).data
- data = scrapertools.find_single_match(data, '"files":(.*?)"quality"')
- patron = '"([lh])q":"([^"]+)"'
- matches = scrapertools.find_multiple_matches(data, patron)
- for quality, scrapedurl in matches:
- url = scrapedurl.replace("\/", "/")
- if "l" in quality: quality = "360"
- if "h" in quality: quality = "720"
- video_urls.append(["[viptube] %s" %quality, url])
- return video_urls
-
diff --git a/servers/vivatube.json b/servers/vivatube.json
deleted file mode 100644
index 9d48b32c..00000000
--- a/servers/vivatube.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "http://www.vivatube.com/embed/([0-9]+)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "vivatube",
- "name": "vivatube",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/vivatube.py b/servers/vivatube.py
deleted file mode 100644
index f3515701..00000000
--- a/servers/vivatube.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-from core import httptools
-from core import scrapertools
-from platformcode import logger
-
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- url = "https://www.vivatube.com/player_config_json/?vid=%s&aid=0&domain_id=0&embed=0&ref=null&check_speed=0" %page_url
- data = httptools.downloadpage(url).data
- data = scrapertools.find_single_match(data, '"files":(.*?)"quality"')
- patron = '"([lh])q":"([^"]+)"'
- matches = scrapertools.find_multiple_matches(data, patron)
- for quality, scrapedurl in matches:
- url = scrapedurl.replace("\/", "/")
- if "l" in quality: quality = "360"
- if "h" in quality: quality = "720"
- video_urls.append(["[vivatube] %s" %quality, url])
- return video_urls
-
diff --git a/servers/vvvvid.py b/servers/vvvvid.py
index 3f1ddc53..dc644426 100644
--- a/servers/vvvvid.py
+++ b/servers/vvvvid.py
@@ -6,7 +6,7 @@ import requests
from core import httptools
from lib import vvvvid_decoder
-from platformcode import logger
+from platformcode import logger, config
# Creating persistent session
current_session = requests.Session()
@@ -16,19 +16,18 @@ headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/2010010
login_page = 'https://www.vvvvid.it/user/login'
conn_id = current_session.get(login_page, headers=headers).json()['data']['conn_id']
payload = {'conn_id': conn_id}
-# logger.info('CONNECTION ID= ' + str(payload))
def test_video_exists(page_url):
logger.info("(page_url='%s')" % page_url)
data = httptools.downloadpage(page_url).data
if "Not Found" in data or "File was deleted" in data:
- return False, "[VVVVID] The file does not exist or has been deleted"
+ return False, config.get_localized_string(70449) % "VVVVID"
else:
page_url = page_url.replace("/show/","/#!show/")
show_id = re.findall("#!show/([0-9]+)/", page_url)[0]
name = re.findall(show_id + "/(.+?)/", page_url)
- if not name: return False, "[VVVVID] The file does not exist or has been deleted"
+ if not name: return False, config.get_localized_string(70449) % "VVVVID"
return True, ""
@@ -45,20 +44,16 @@ def get_video_url(page_url, premium=False, user="", password="", video_password=
# Getting info from Site
json_url = "https://www.vvvvid.it/vvvvid/ondemand/" + show_id + '/season/' +season_id + '/'
- # logger.info('URL= ' + json_url)
json_file = current_session.get(json_url, headers=headers, params=payload).json()
logger.info(json_file['data'])
# Search for the correct episode
for episode in json_file['data']:
- # import web_pdb; web_pdb.set_trace()
if episode['video_id'] == int(video_id):
ep_title = '[B]' + episode['title'] + '[/B]'
embed_info = vvvvid_decoder.dec_ei(episode['embed_info'])
embed_info = embed_info.replace('manifest.f4m','master.m3u8').replace('http://','https://').replace('/z/','/i/')
- # import web_pdb; web_pdb.set_trace()
-
video_urls.append([ep_title, str(embed_info)])
return video_urls
\ No newline at end of file
diff --git a/servers/winporn.json b/servers/winporn.json
deleted file mode 100644
index 9e102009..00000000
--- a/servers/winporn.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "https://www.winporn.com/es/video/([0-9]+)/",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "winporn",
- "name": "winporn",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/winporn.py b/servers/winporn.py
deleted file mode 100644
index 74db631e..00000000
--- a/servers/winporn.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-from core import httptools
-from core import scrapertools
-from platformcode import logger
-
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- url = "https://www.winporn.com/player_config_json/?vid=%s&aid=0&domain_id=0&embed=0&ref=null&check_speed=0" %page_url
- data = httptools.downloadpage(url).data
- data = scrapertools.find_single_match(data, '"files":(.*?)"quality"')
- patron = '"([lh])q":"([^"]+)"'
- matches = scrapertools.find_multiple_matches(data, patron)
- for quality, scrapedurl in matches:
- url = scrapedurl.replace("\/", "/")
- if "l" in quality: quality = "360"
- if "h" in quality: quality = "720"
- video_urls.append(["[winporn] %s" %quality, url])
- return video_urls
-
diff --git a/servers/wstream.py b/servers/wstream.py
index a9f5786d..ceda52ce 100644
--- a/servers/wstream.py
+++ b/servers/wstream.py
@@ -30,7 +30,7 @@ def test_video_exists(page_url):
data = httptools.downloadpage(page_url, headers=headers, follow_redirects=True, verify=False).data
real_url = page_url
- if "Not Found" in data or "File was deleted" in data:
+ if "Not Found" in data or "File was deleted" in data or 'Video is processing' in data:
return False, config.get_localized_string(70449) % 'Wstream'
else:
return True, ""
diff --git a/servers/xdrive.json b/servers/xdrive.json
deleted file mode 100644
index 5df04ffc..00000000
--- a/servers/xdrive.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "https://xdrive.cc/embed/([A-z0-9]+)",
- "url": "https://xdrive.cc/embed/\\1"
- }
- ]
- },
- "free": true,
- "id": "xdrive",
- "name": "xdrive",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": "https://i.postimg.cc/MHyNdRPZ/xdrive.png"
-}
diff --git a/servers/xdrive.py b/servers/xdrive.py
deleted file mode 100644
index 5baaeab4..00000000
--- a/servers/xdrive.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-# ------------------------------------------------------------
-# Alfa addon - KODI Plugin
-# Conector para xdrive
-# https://github.com/alfa-addon
-# ------------------------------------------------------------
-from core import httptools
-from core import scrapertools
-from platformcode import config
-from platformcode import logger
-
-
-def test_video_exists(page_url):
- logger.info("(page_url='%s')" % page_url)
- data = httptools.downloadpage(page_url).data
- if "Object not found" in data or "no longer exists" in data or '"sources": [false]' in data:
- return False, config.get_localized_string(70449) % "xdrive"
-
- return True, ""
-
-
-def get_video_url(page_url, user="", password="", video_password=""):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- data1 = httptools.downloadpage("https://xdrive.cc/geo_ip").data
- _ip = scrapertools.find_single_match(data1, 'ip":"([^"]+)')
- data = httptools.downloadpage(page_url).data
- video_id = scrapertools.find_single_match(data, '&video_id=(\d+)')
- data = httptools.downloadpage("https://xdrive.cc/secure_link?ip=%s&video_id=%s" %(_ip, video_id)).data.replace("\\","")
- videourl = scrapertools.find_multiple_matches(data, '"([^"]+)"')
- for scrapedurl in videourl:
- video_urls.append(["[xdrive]", scrapedurl])
- return video_urls
diff --git a/servers/xhamster.json b/servers/xhamster.json
deleted file mode 100644
index 359ddc2f..00000000
--- a/servers/xhamster.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "(?:http|s)://xhamster.com/(?:xembed.php\\?video=|embed/)([0-9]+)",
- "url": "https://xhamster.com/embed/\\1"
- }
- ]
- },
- "free": true,
- "id": "xhamster",
- "name": "xhamster",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/xhamster.py b/servers/xhamster.py
deleted file mode 100644
index df46152f..00000000
--- a/servers/xhamster.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- coding: utf-8 -*-
-from core import httptools
-from core import scrapertools
-from platformcode import logger
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- data = httptools.downloadpage(page_url).data
- patron = '"fallback":"([^"]+)","quality":"([0-9]+p)"'
- matches = scrapertools.find_multiple_matches(data, patron)
- for scrapedurl, quality in matches:
- url = scrapedurl.replace("\/", "/")
- video_urls.append(["[xhamster] %s" %quality, url])
- return video_urls
diff --git a/servers/xstreamcdn.json b/servers/xstreamcdn.json
deleted file mode 100644
index 80115bba..00000000
--- a/servers/xstreamcdn.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "(https://www.xstreamcdn.com/v/[A-z0-9_-]+)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "xstreamcdn",
- "name": "xstreamcdn",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": "https://library.vodkr.com/media/24364/xstreamlogo.jpg"
-}
diff --git a/servers/xstreamcdn.py b/servers/xstreamcdn.py
deleted file mode 100644
index 27310f4d..00000000
--- a/servers/xstreamcdn.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import sys
-PY3 = False
-if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
-
-if PY3:
- #from future import standard_library
- #standard_library.install_aliases()
- import urllib.parse as urllib # Es muy lento en PY2. En PY3 es nativo
-else:
- import urllib # Usamos el nativo de PY2 que es más rápido
-
-from core import httptools
-from core import scrapertools
-from core import jsontools
-from platformcode import logger
-
-
-def test_video_exists(page_url):
- logger.info("(page_url='%s')" % page_url)
- data = httptools.downloadpage(page_url).data
- if "ile was deleted" in data or "Page Cannot Be Found" in data or "
Sorry 404 not found" in data:
- return False, "[xstreamcdn.com] El archivo ha sido eliminado o no existe"
- return True, ""
-
-
-def get_video_url(page_url, premium=False, user="", password="", video_password=""):
- logger.info("url=" + page_url)
- video_urls = []
- post = {}
- post = urllib.urlencode(post)
- data = httptools.downloadpage("https://xstreamcdn.com/api/source/" + scrapertools.find_single_match(page_url, "/v/([A-z0-9_-]+)"), post=post, add_referer=page_url).data
-
- json_data = jsontools.load(data)
- check = json_data['success']
- if check == True:
- for element in json_data['data']:
- media_url = element['file']
- res = element['label']
- tipo = element['type']
- video_urls.append([tipo + " (" + res + ") [xstreamcdn]", media_url])
- return video_urls
diff --git a/servers/xvideos.json b/servers/xvideos.json
deleted file mode 100755
index b09288ab..00000000
--- a/servers/xvideos.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "https://(?:flashservice|www).xvideos.com/embedframe/([0-9]+)",
- "url": "https://www.xvideos.com/video\\1/"
- },
- {
- "pattern": "https://www.xvideos.com/video([0-9]+)/",
- "url": "https://www.xvideos.com/video\\1/"
- },
- {
- "pattern": "http://www.xvideos.com/video([0-9]+)/",
- "url": "https://www.xvideos.com/video\\1/"
- }
- ]
- },
- "free": true,
- "id": "xvideos",
- "name": "xvideos",
- "premium": [
- "alldebrid"
- ],
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ]
-}
diff --git a/servers/xvideos.py b/servers/xvideos.py
deleted file mode 100755
index 947376df..00000000
--- a/servers/xvideos.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-import re
-
-from core import httptools
-from platformcode import config
-from platformcode import logger
-
-
-def test_video_exists(page_url):
- logger.info("(page_url='%s')" % page_url)
- global data
-
- data = httptools.downloadpage(page_url).data
- if "Lo sentimos" in data or "File not found" in data or 'og:video">' in data:
- return False, config.get_localized_string(70449) % "Xvideos"
-
- return True, ""
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- data = httptools.downloadpage(page_url).data
- patron = 'html5player.setVideo(?:Url|H)(\w+)\(\'([^\']+)\'\)'
- matches = re.compile(patron,re.DOTALL).findall(data)
- for quality,url in matches:
- if "LS" in quality: quality = "HLS"
- video_urls.append(["[xvideos] %s" %quality, url])
- return video_urls
diff --git a/servers/youporn.json b/servers/youporn.json
deleted file mode 100644
index eb40da00..00000000
--- a/servers/youporn.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "active": true,
- "find_videos": {
- "ignore_urls": [],
- "patterns": [
- {
- "pattern": "(https://www.youporn.com/(?:embed|watch)/[0-9]+/[A-z0-9-]+/)",
- "url": "\\1"
- }
- ]
- },
- "free": true,
- "id": "youporn",
- "name": "youporn",
- "settings": [
- {
- "default": false,
- "enabled": true,
- "id": "black_list",
- "label": "@60654",
- "type": "bool",
- "visible": true
- },
- {
- "default": 0,
- "enabled": true,
- "id": "favorites_servers_list",
- "label": "@60655",
- "lvalues": [
- "No",
- "1",
- "2",
- "3",
- "4",
- "5"
- ],
- "type": "list",
- "visible": false
- }
- ],
- "thumbnail": ""
-}
diff --git a/servers/youporn.py b/servers/youporn.py
deleted file mode 100644
index ebc5d10f..00000000
--- a/servers/youporn.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- coding: utf-8 -*-
-from core import httptools
-from core import scrapertools
-from platformcode import logger
-
-
-def get_video_url(page_url, video_password):
- logger.info("(page_url='%s')" % page_url)
- video_urls = []
- data = httptools.downloadpage(page_url).data
- patron = '"format":"","quality":"([^"]+)","videoUrl":"([^"]+)"'
- matches = scrapertools.find_multiple_matches(data, patron)
- for quality, scrapedurl in matches:
- url = scrapedurl.replace("\/", "/").replace("\u0026", "&")
- video_urls.append(["[youporn] %sp" %quality, url])
- return video_urls
diff --git a/specials/autoplay.py b/specials/autoplay.py
index 552e5be8..71e588af 100644
--- a/specials/autoplay.py
+++ b/specials/autoplay.py
@@ -8,12 +8,9 @@ from builtins import range
import os
-from core import channeltools
-from core import jsontools
+from core import channeltools, jsontools
from core.item import Item
-from platformcode import config, logger
-from platformcode import platformtools
-from platformcode import launcher
+from platformcode import config, logger, platformtools, launcher
from time import sleep
from platformcode.config import get_setting
@@ -28,7 +25,7 @@ colorKOD = '0xFF65B3DA'
def context():
'''
- Agrega la opcion Configurar AutoPlay al menu contextual
+ Add the Configure AutoPlay option to the context menu
:return:
'''
@@ -47,12 +44,12 @@ context = context()
def show_option(channel, itemlist, text_color=colorKOD, thumbnail=None, fanart=None):
'''
- Agrega la opcion Configurar AutoPlay en la lista recibida
+ Add the option Configure AutoPlay in the received list
:param channel: str
:param itemlist: list (lista donde se desea integrar la opcion de configurar AutoPlay)
- :param text_color: str (color para el texto de la opcion Configurar Autoplay)
- :param thumbnail: str (direccion donde se encuentra el thumbnail para la opcion Configurar Autoplay)
+ :param text_color: str (color for the text of the option Configure Autoplay)
+ :param thumbnail: str (address where the thumbnail is for the Configure Autoplay option)
:return:
'''
from channelselector import get_thumb
@@ -85,14 +82,16 @@ def show_option(channel, itemlist, text_color=colorKOD, thumbnail=None, fanart=N
def start(itemlist, item):
'''
- Metodo principal desde donde se reproduce automaticamente los enlaces
- - En caso la opcion de personalizar activa utilizara las opciones definidas por el usuario.
- - En caso contrario intentara reproducir cualquier enlace que cuente con el idioma preferido.
+ Main method from which the links are automatically reproduced
+ - In case the option to activate it will use the options defined by the user.
+ - Otherwise it will try to reproduce any link that has the preferred language.
- :param itemlist: list (lista de items listos para reproducir, o sea con action='play')
- :param item: item (el item principal del canal)
- :return: intenta autoreproducir, en caso de fallar devuelve el itemlist que recibio en un principio
+ :param itemlist: list (list of items ready to play, ie with action = 'play')
+ :param item: item (the main item of the channel)
+ :return: try to auto-reproduce, in case of failure it returns the itemlist that it received in the beginning
'''
+ if item.global_search:
+ return itemlist
logger.info()
global PLAYED
@@ -103,11 +102,11 @@ def start(itemlist, item):
if not config.is_xbmc():
- #platformtools.dialog_notification('AutoPlay ERROR', 'Sólo disponible para XBMC/Kodi')
+ # platformtools.dialog_notification('AutoPlay ERROR', 'Sólo disponible para XBMC/Kodi')
return itemlist
if not autoplay_node:
- # Obtiene el nodo AUTOPLAY desde el json
+ # Get AUTOPLAY node from json
autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY')
channel_id = item.channel
@@ -122,12 +121,12 @@ def start(itemlist, item):
if not channel_id in autoplay_node: # or not active:
return itemlist
- # Agrega servidores y calidades que no estaban listados a autoplay_node
+ # Add servers and qualities not listed to autoplay_node
new_options = check_value(channel_id, itemlist)
- # Obtiene el nodo del canal desde autoplay_node
+ # Get the channel node from autoplay_node
channel_node = autoplay_node.get(channel_id, {})
- # Obtiene los ajustes des autoplay para este canal
+ # Get the autoplay settings for this channel
settings_node = channel_node.get('settings', {})
if get_setting('autoplay') or settings_node['active']:
@@ -138,66 +137,65 @@ def start(itemlist, item):
favorite_servers = []
favorite_quality = []
- #2nd lang, vemos si se quiere o no filtrar
+ # 2nd lang, see if you want to filter or not
status_language = config.get_setting("filter_languages", channel_id)
- # Guarda el valor actual de "Accion y Player Mode" en preferencias
+ # Save the current value of "Action and Player Mode" in preferences
user_config_setting_action = config.get_setting("default_action")
user_config_setting_player = config.get_setting("player_mode")
- # Habilita la accion "Ver en calidad alta" (si el servidor devuelve más de una calidad p.e. gdrive)
+ # Enable the "View in high quality" action (if the server returns more than one quality, eg gdrive)
if user_config_setting_action != 2:
config.set_setting("default_action", 2)
if user_config_setting_player != 0:
config.set_setting("player_mode", 0)
- # Informa que AutoPlay esta activo
- #platformtools.dialog_notification('AutoPlay Activo', '', sound=False)
+ # Report that AutoPlay is active
+ # platformtools.dialog_notification('AutoPlay Activo', '', sound=False)
- # Prioridades a la hora de ordenar itemlist:
- # 0: Servidores y calidades
- # 1: Calidades y servidores
- # 2: Solo servidores
- # 3: Solo calidades
- # 4: No ordenar
+ # Priorities when ordering itemlist:
+ # 0: Servers and qualities
+ # 1: Qualities and servers
+ # 2: Servers only
+ # 3: Only qualities
+ # 4: Do not order
if (settings_node['custom_servers'] and settings_node['custom_quality']) or get_setting('autoplay'):
- priority = settings_node['priority'] # 0: Servidores y calidades o 1: Calidades y servidores
+ priority = settings_node['priority'] # 0: Servers and qualities or 1: Qualities and servers
elif settings_node['custom_servers']:
- priority = 2 # Solo servidores
+ priority = 2 # Servers only
elif settings_node['custom_quality']:
- priority = 3 # Solo calidades
+ priority = 3 # Only qualities
else:
- priority = 4 # No ordenar
+ priority = 4 # Do not order
- # Obtiene las listas servidores, calidades disponibles desde el nodo del json de AutoPlay
+ # Get server lists, qualities available from AutoPlay json node
server_list = channel_node.get('servers', [])
for server in server_list:
server = server.lower()
quality_list = channel_node.get('quality', [])
- # Si no se definen calidades la se asigna default como calidad unica
+ # If no qualities are defined, default is assigned as unique quality.
if len(quality_list) == 0:
quality_list =['default']
- # Se guardan los textos de cada servidor y calidad en listas p.e. favorite_servers = ['verystream', 'openload',
- # 'streamcloud']
+ # The texts of each server and quality are stored in lists, e.g. favorite_servers = ['verystream', 'openload', 'streamcloud']
for num in range(1, 4):
favorite_servers.append(channel_node['servers'][settings_node['server_%s' % num]].lower())
favorite_quality.append(channel_node['quality'][settings_node['quality_%s' % num]])
- # Se filtran los enlaces de itemlist y que se correspondan con los valores de autoplay
+ # Itemlist links are filtered and correspond to autoplay values
for n, item in enumerate(itemlist):
autoplay_elem = dict()
b_dict = dict()
- # Comprobamos q se trata de un item de video
+ # We check that it is a video item
if 'server' not in item:
continue
- #2nd lang lista idiomas
+ # 2nd lang language list
if item.language not in favorite_langs:
favorite_langs.append(item.language)
- # Agrega la opcion configurar AutoPlay al menu contextual
+ # Add the option to configure AutoPlay to the context menu
if 'context' not in item:
item.context = list()
if not [x for x in context if x['action'] == 'autoplay_config']:
@@ -206,15 +204,14 @@ def start(itemlist, item):
"channel": "autoplay",
"from_channel": channel_id})
- # Si no tiene calidad definida le asigna calidad 'default'
+ # If it does not have a defined quality, it assigns a 'default' quality.
if item.quality == '':
item.quality = 'default'
- # Se crea la lista para configuracion personalizada
- if priority < 2: # 0: Servidores y calidades o 1: Calidades y servidores
+ # The list for custom settings is created
+ if priority < 2: # 0: Servers and qualities or 1: Qualities and servers
- # si el servidor y la calidad no se encuentran en las listas de favoritos o la url esta repetida,
- # descartamos el item
+ # if the server and the quality are not in the favorites lists or the url is repeated, we discard the item
if item.server.lower() not in favorite_servers or item.quality not in favorite_quality \
or item.url in url_list_valid:
item.type_b = True
@@ -225,10 +222,9 @@ def start(itemlist, item):
autoplay_elem["indice_server"] = favorite_servers.index(item.server.lower())
autoplay_elem["indice_quality"] = favorite_quality.index(item.quality)
- elif priority == 2: # Solo servidores
+ elif priority == 2: # Servers only
- # si el servidor no se encuentra en la lista de favoritos o la url esta repetida,
- # descartamos el item
+ # if the server is not in the favorites list or the url is repeated, we discard the item
if item.server.lower() not in favorite_servers or item.url in url_list_valid:
item.type_b = True
b_dict['videoitem'] = item
@@ -239,8 +235,7 @@ def start(itemlist, item):
elif priority == 3: # Solo calidades
- # si la calidad no se encuentra en la lista de favoritos o la url esta repetida,
- # descartamos el item
+ # if the quality is not in the favorites list or the url is repeated, we discard the item
if item.quality not in favorite_quality or item.url in url_list_valid:
item.type_b = True
b_dict['videoitem'] = item
@@ -249,13 +244,13 @@ def start(itemlist, item):
autoplay_elem["indice_lang"] = favorite_langs.index(item.language)
autoplay_elem["indice_quality"] = favorite_quality.index(item.quality)
- else: # No ordenar
+ else: # Do not order
- # si la url esta repetida, descartamos el item
+ # if the url is repeated, we discard the item
if item.url in url_list_valid:
continue
- # Si el item llega hasta aqui lo añadimos al listado de urls validas y a autoplay_list
+ # If the item reaches here we add it to the list of valid urls and to autoplay_list
url_list_valid.append(item.url)
item.plan_b=True
autoplay_elem['videoitem'] = item
@@ -263,20 +258,20 @@ def start(itemlist, item):
# autoplay_elem['quality'] = item.quality
autoplay_list.append(autoplay_elem)
- # Ordenamos segun la prioridad
- if priority == 0: # Servidores y calidades
+ # We order according to priority
+ if priority == 0: # Servers and qualities
autoplay_list.sort(key=lambda orden: (orden['indice_lang'], orden['indice_server'], orden['indice_quality']))
- elif priority == 1: # Calidades y servidores
+ elif priority == 1: # Qualities and servers
autoplay_list.sort(key=lambda orden: (orden['indice_lang'], orden['indice_quality'], orden['indice_server']))
- elif priority == 2: # Solo servidores
+ elif priority == 2: # Servers only
autoplay_list.sort(key=lambda orden: (orden['indice_lang'], orden['indice_server']))
- elif priority == 3: # Solo calidades
+ elif priority == 3: # Only qualities
autoplay_list.sort(key=lambda orden: (orden['indice_lang'], orden['indice_quality']))
- # Se prepara el plan b, en caso de estar activo se agregan los elementos no favoritos al final
+ # Plan b is prepared, in case it is active the non-favorite elements are added at the end
try:
plan_b = settings_node['plan_b']
except:
@@ -284,23 +279,22 @@ def start(itemlist, item):
text_b = ''
if plan_b:
autoplay_list.extend(autoplay_b)
- # Si hay elementos en la lista de autoplay se intenta reproducir cada elemento, hasta encontrar uno
- # funcional o fallen todos
+ # If there are elements in the autoplay list, an attempt is made to reproduce each element, until one is found or all fail.
if autoplay_list or (plan_b and autoplay_b):
- #played = False
+ # played = False
max_intentos = 5
max_intentos_servers = {}
- # Si se esta reproduciendo algo detiene la reproduccion
+ # If something is playing it stops playing
if platformtools.is_playing():
platformtools.stop_video()
for autoplay_elem in autoplay_list:
play_item = Item
- # Si no es un elemento favorito si agrega el texto plan b
+ # If it is not a favorite element if you add the text plan b
if autoplay_elem['videoitem'].type_b:
text_b = '(Plan B)'
if not platformtools.is_playing() and not PLAYED:
@@ -308,7 +302,7 @@ def start(itemlist, item):
if videoitem.server.lower() not in max_intentos_servers:
max_intentos_servers[videoitem.server.lower()] = max_intentos
- # Si se han alcanzado el numero maximo de intentos de este servidor saltamos al siguiente
+ # If the maximum number of attempts of this server have been reached, we jump to the next
if max_intentos_servers[videoitem.server.lower()] == 0:
continue
@@ -318,10 +312,9 @@ def start(itemlist, item):
platformtools.dialog_notification("AutoPlay %s" %text_b, "%s%s%s" % (
videoitem.server.upper(), lang, videoitem.quality.upper()), sound=False)
- # TODO videoitem.server es el id del server, pero podria no ser el nombre!!!
+ # TODO videoitem.server is the id of the server, but it might not be the name !!!
- # Intenta reproducir los enlaces
- # Si el canal tiene metodo play propio lo utiliza
+ # Try to play the links If the channel has its own play method, use it
try:
channel = __import__('channels.%s' % channel_id, None, None, ["channels.%s" % channel_id])
except:
@@ -334,19 +327,19 @@ def start(itemlist, item):
else:
videoitem = resolved_item[0]
- # Si no directamente reproduce y marca como visto
+ # If not directly reproduce and mark as seen
- # Verifica si el item viene de la videoteca
+ #Check if the item comes from the video library
try:
if base_item.contentChannel =='videolibrary':
- # Marca como visto
+ # Mark as seen
from platformcode import xbmc_videolibrary
xbmc_videolibrary.mark_auto_as_watched(base_item)
- # Rellena el video con los datos del item principal y reproduce
+ # Fill the video with the data of the main item and play
play_item = base_item.clone(url=videoitem)
platformtools.play_video(play_item.url, autoplay=True)
else:
- # Si no viene de la videoteca solo reproduce
+ # If it doesn't come from the video library, just play
platformtools.play_video(videoitem, autoplay=True)
except:
pass
@@ -358,18 +351,16 @@ def start(itemlist, item):
except:
logger.debug(str(len(autoplay_list)))
- # Si hemos llegado hasta aqui es por q no se ha podido reproducir
+ # If we have come this far, it is because it could not be reproduced
max_intentos_servers[videoitem.server.lower()] -= 1
- # Si se han alcanzado el numero maximo de intentos de este servidor
- # preguntar si queremos seguir probando o lo ignoramos
+ # If the maximum number of attempts of this server has been reached, ask if we want to continue testing or ignore it.
if max_intentos_servers[videoitem.server.lower()] == 0:
text = config.get_localized_string(60072) % videoitem.server.upper()
- if not platformtools.dialog_yesno("AutoPlay", text,
- config.get_localized_string(60073)):
+ if not platformtools.dialog_yesno("AutoPlay", text, config.get_localized_string(60073)):
max_intentos_servers[videoitem.server.lower()] = max_intentos
- # Si no quedan elementos en la lista se informa
+ # If there are no items in the list, it is reported
if autoplay_elem == autoplay_list[-1]:
platformtools.dialog_notification('AutoPlay', config.get_localized_string(60072) % videoitem.server.upper())
@@ -378,7 +369,7 @@ def start(itemlist, item):
if new_options:
platformtools.dialog_notification("AutoPlay", config.get_localized_string(60076), sound=False)
- # Restaura si es necesario el valor previo de "Accion y Player Mode" en preferencias
+ # Restore if necessary the previous value of "Action and Player Mode" in preferences
if user_config_setting_action != 2:
config.set_setting("default_action", user_config_setting_action)
if user_config_setting_player != 0:
@@ -389,15 +380,15 @@ def start(itemlist, item):
def init(channel, list_servers, list_quality, reset=False):
'''
- Comprueba la existencia de canal en el archivo de configuracion de Autoplay y si no existe lo añade.
- Es necesario llamar a esta funcion al entrar a cualquier canal que incluya la funcion Autoplay.
+ Check the existence of a channel in the Autoplay configuration file and if it does not exist, add it.
+ It is necessary to call this function when entering any channel that includes the Autoplay function.
- :param channel: (str) id del canal
- :param list_servers: (list) lista inicial de servidores validos para el canal. No es necesario incluirlos todos,
- ya que la lista de servidores validos se ira actualizando dinamicamente.
- :param list_quality: (list) lista inicial de calidades validas para el canal. No es necesario incluirlas todas,
- ya que la lista de calidades validas se ira actualizando dinamicamente.
- :return: (bool) True si la inicializacion ha sido correcta.
+ :param channel: (str) channel id
+ :param list_servers: (list) initial list of valid servers for the channel. It is not necessary to include them all,
+ since the list of valid servers will be updated dynamically.
+ :param list_quality: (list) initial list of valid qualities for the channel. It is not necessary to include them all,
+ since the list of valid qualities will be updated dynamically.
+ :return: (bool) True if the initialization was successful.
'''
logger.info()
change = False
@@ -418,13 +409,13 @@ def init(channel, list_servers, list_quality, reset=False):
if channel not in autoplay_node or reset:
change = True
- # Se comprueba que no haya calidades ni servidores duplicados
+ # It is verified that there are no duplicate qualities or servers
if 'default' not in list_quality:
list_quality.append('default')
# list_servers = list(set(list_servers))
# list_quality = list(set(list_quality))
- # Creamos el nodo del canal y lo añadimos
+ # We create the channel node and add it
channel_node = {"servers": list_servers,
"quality": list_quality,
"settings": {
@@ -458,11 +449,11 @@ def init(channel, list_servers, list_quality, reset=False):
def check_value(channel, itemlist):
- ''' comprueba la existencia de un valor en la lista de servidores o calidades
- si no existiera los agrega a la lista en el json
+ '''
+ checks the existence of a value in the list of servers or qualities if it does not exist adds them to the list in the json
:param channel: str
- :param values: list (una de servidores o calidades)
+ :param values: list (one of servers or qualities)
:param value_type: str (server o quality)
:return: list
'''
@@ -471,7 +462,7 @@ def check_value(channel, itemlist):
change = False
if not autoplay_node:
- # Obtiene el nodo AUTOPLAY desde el json
+ # Get AUTOPLAY node from json
autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY')
channel_node = autoplay_node.get(channel)
@@ -507,7 +498,7 @@ def autoplay_config(item):
channel_name = channel_parameters['title']
if not autoplay_node:
- # Obtiene el nodo AUTOPLAY desde el json
+ # Get AUTOPLAY node from json
autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY')
channel_node = autoplay_node.get(item.from_channel, {})
@@ -515,21 +506,19 @@ def autoplay_config(item):
allow_option = True
- active_settings = {"id": "active", "label": config.get_localized_string(60079),
- "type": "bool", "default": False, "enabled": allow_option,
- "visible": allow_option}
+ active_settings = {"id": "active", "label": config.get_localized_string(60079), "type": "bool",
+ "default": False, "enabled": allow_option, "visible": allow_option}
list_controls.append(active_settings)
dict_values['active'] = settings_node.get('active', False)
- hide_servers = {"id": "hide_servers", "label": config.get_localized_string(70747),
- "type": "bool", "default": False, "enabled": "eq(-" + str(len(list_controls)) + ",true)",
- "visible": allow_option}
+ hide_servers = {"id": "hide_servers", "label": config.get_localized_string(70747), "type": "bool",
+ "default": False, "enabled": "eq(-" + str(len(list_controls)) + ",true)", "visible": allow_option}
list_controls.append(hide_servers)
dict_values['hide_servers'] = settings_node.get('hide_servers', False)
- # Idioma
+ # Language
status_language = config.get_setting("filter_languages", item.from_channel)
if not status_language:
status_language = 0
@@ -546,7 +535,7 @@ def autoplay_config(item):
"type": "label", "enabled": True, "visible": True}
list_controls.append(separador)
- # Seccion servidores favoritos
+ # Favorite servers section
server_list = channel_node.get("servers", [])
if not server_list:
enabled = False
@@ -578,7 +567,7 @@ def autoplay_config(item):
if settings_node.get("server_%s" % num, 0) > len(server_list) - 1:
dict_values["server_%s" % num] = 0
- # Seccion Calidades favoritas
+ # Favorite Qualities Section
quality_list = channel_node.get("quality", [])
if not quality_list:
enabled = False
@@ -586,8 +575,7 @@ def autoplay_config(item):
else:
enabled = "eq(-" + str(len(list_controls)) + ",true)"
- custom_quality_settings = {"id": "custom_quality", "label": config.get_localized_string(60083),
- "type": "bool", "default": False, "enabled": enabled, "visible": True}
+ custom_quality_settings = {"id": "custom_quality", "label": config.get_localized_string(60083), "type": "bool", "default": False, "enabled": enabled, "visible": True}
custom_quality_pos = len(list_controls)
list_controls.append(custom_quality_settings)
if dict_values['active'] and enabled:
@@ -617,7 +605,7 @@ def autoplay_config(item):
list_controls.append(plan_b)
- # Seccion Prioridades
+ # Priorities Section
priority_list = [config.get_localized_string(70174), config.get_localized_string(70175)]
set_priority = {"id": "priority", "label": config.get_localized_string(60085), "type": "list", "default": 0,
"enabled": True, "visible": "eq(-5,true)+eq(-9,true)+eq(-12,true)", "lvalues": priority_list}
@@ -626,7 +614,7 @@ def autoplay_config(item):
- # Abrir cuadro de dialogo
+ # Open dialog box
platformtools.show_channel_settings(list_controls=list_controls, dict_values=dict_values, callback='save',
item=item, caption='%s - AutoPlay' % channel_name,
custom_button={'visible': True,
@@ -637,7 +625,7 @@ def autoplay_config(item):
def save(item, dict_data_saved):
'''
- Guarda los datos de la ventana de configuracion
+ Save the data from the configuration window
:param item: item
:param dict_data_saved: dict
@@ -647,7 +635,7 @@ def save(item, dict_data_saved):
global autoplay_node
if not autoplay_node:
- # Obtiene el nodo AUTOPLAY desde el json
+ # Get AUTOPLAY node from json
autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY')
new_config = dict_data_saved
@@ -665,7 +653,7 @@ def save(item, dict_data_saved):
def get_languages(channel):
'''
- Obtiene los idiomas desde el json del canal
+ Get the languages from the channel's json
:param channel: str
:return: list
@@ -685,9 +673,9 @@ def get_languages(channel):
def is_active(channel):
'''
- Devuelve un booleano q indica si esta activo o no autoplay en el canal desde el que se llama
+ Returns a boolean that indicates whether or not autoplay is active on the channel from which it is called
- :return: True si esta activo autoplay para el canal desde el que se llama, False en caso contrario.
+ :return:True if autoplay is active for the channel from which it is called, False otherwise.
'''
logger.info()
global autoplay_node
@@ -696,18 +684,18 @@ def is_active(channel):
return False
if not autoplay_node:
- # Obtiene el nodo AUTOPLAY desde el json
+ # Get AUTOPLAY node from json
autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY')
- # Obtine el canal desde el q se hace la llamada
+ # Get the channel from which the call is made
#import inspect
#module = inspect.getmodule(inspect.currentframe().f_back)
#canal = module.__name__.split('.')[1]
canal = channel
- # Obtiene el nodo del canal desde autoplay_node
+ # Get the channel node from autoplay_node
channel_node = autoplay_node.get(canal, {})
- # Obtiene los ajustes des autoplay para este canal
+ # Get the autoplay settings for this channel
settings_node = channel_node.get('settings', {})
return settings_node.get('active', False) or get_setting('autoplay')
@@ -727,7 +715,7 @@ def reset(item, dict):
# def set_status(status):
# logger.info()
-# # Obtiene el nodo AUTOPLAY desde el json
+# # Get AUTOPLAY node from json
# autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY')
# autoplay_node['status'] = status
#
@@ -737,7 +725,7 @@ def reset(item, dict):
def get_channel_AP_HS(item):
autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY')
channel_node = autoplay_node.get(item.channel, {})
- if not channel_node: # non ha mai aperto il menu del canale quindi in autoplay_data.json non c'e la key
+ if not channel_node: # never opened the channel menu so in autoplay_data.json there is no key
try:
channelFile = __import__('channels.' + item.channel, fromlist=["channels.%s" % item.channel])
except:
diff --git a/specials/checkhost.py b/specials/checkhost.py
index 5593aae3..31ea9187 100644
--- a/specials/checkhost.py
+++ b/specials/checkhost.py
@@ -18,7 +18,7 @@ addonid = addon.getAddonInfo('id')
LIST_SITE = ['http://www.ansa.it/', 'https://www.google.it']#, 'https://www.google.com']
-# lista di siti che non verranno raggiunti con i DNS del gestore
+# list of sites that will not be reached with the manager's DNS
LST_SITE_CHCK_DNS = ['https://www.casacinema.me/', 'https://cb01-nuovo-indirizzo.info/']
#'https://www.italia-film.pw', 'https://www.cb01.uno/',] # tolti
@@ -41,13 +41,8 @@ class Kdicc():
def check_Ip(self):
"""
- controllo l'ip
- se ip_addr = 127.0.0.1 o ip_addr = '' allora il device non
- e' connesso al modem/router
-
check the ip
- if ip_addr = 127.0.0.1 or ip_addr = '' then the device does not
- is connected to the modem/router
+ if ip_addr = 127.0.0.1 or ip_addr = '' then the device does not is connected to the modem/router
return: bool
"""
@@ -59,7 +54,7 @@ class Kdicc():
def check_Adsl(self):
"""
- controllo se il device raggiunge i siti
+ check if the device reaches the sites
"""
urls = LIST_SITE
@@ -67,8 +62,8 @@ class Kdicc():
http_errr = 0
for rslt in r:
xbmc.log("check_Adsl rslt: %s" % rslt['code'], level=xbmc.LOGNOTICE)
- # Errno -2 potrebbe essere mancanza di connessione adsl o sito non raggiungibile....
- # anche nei casi in cui ci sia il cambio gestore.
+ # Errno -2 could be lack of adsl connection or unreachable site ....
+ # even in cases where there is a change of manager.
if rslt['code'] == '111' or '[Errno -3]' in str(rslt['code']) or 'Errno -2' in str(rslt['code']):
http_errr +=1
@@ -80,7 +75,7 @@ class Kdicc():
def check_Dns(self):
"""
- Controllo se i DNS raggiungono certi siti
+ Control if DNS reaches certain sites
"""
if self.lst_site_check_dns == []:
urls = LST_SITE_CHCK_DNS
@@ -88,7 +83,7 @@ class Kdicc():
urls = self.lst_site_check_dns
r = self.rqst(urls)
- xbmc.log("check_Dns risultato: %s" % r, level=xbmc.LOGNOTICE)
+ xbmc.log("check_Dns result: %s" % r, level=xbmc.LOGNOTICE)
http_errr = 0
for rslt in r:
xbmc.log("check_Dns rslt: %s" % rslt['code'], level=xbmc.LOGNOTICE)
@@ -103,7 +98,7 @@ class Kdicc():
def rqst(self, lst_urls):
"""
- url deve iniziare con http(s):'
+ url must start with http(s):'
return : (esito, sito, url, code, reurl)
"""
rslt_final = []
@@ -114,7 +109,7 @@ class Kdicc():
for sito in lst_urls:
rslt = {}
try:
- r = requests.head(sito, allow_redirects = True)#, timeout=7) # da errore dopo l'inserimento in lib di httplib2
+ r = requests.head(sito, allow_redirects = True) #, timeout=7) # from error after lib insertion of httplib2
if r.url.endswith('/'):
r.url = r.url[:-1]
if str(sito) != str(r.url):
@@ -130,17 +125,17 @@ class Kdicc():
xbmc.log("Risultato nel try: %s" % (r,), level=xbmc.LOGNOTICE)
except requests.exceptions.ConnectionError as conn_errr:
- # Errno 10061 per s.o. win
- # gli Errno 10xxx e 11xxx saranno da compattare in qualche modo?
- # gli errori vengono inglobati in code = '111' in quanto in quel momento
- # non vengono raggiunti per una qualsiasi causa
+ # Errno 10061 for s.o. win
+ # will the Errno 10xxx and 11xxx be to be compacted in any way?
+ # the errors are incorporated in code = '111' since at that moment
+ # they are not reached for any reason
if '[Errno 111]' in str(conn_errr) or 'Errno 10060' in str(conn_errr) \
or 'Errno 10061' in str(conn_errr) \
or '[Errno 110]' in str(conn_errr) \
or 'ConnectTimeoutError' in str(conn_errr) \
or 'Errno 11002' in str(conn_errr) or 'ReadTimeout' in str(conn_errr) \
or 'Errno 11001' in str(conn_errr) \
- or 'Errno -2' in str(conn_errr): # questo errore è anche nel code: -2
+ or 'Errno -2' in str(conn_errr): # this error is also in the code: -2
rslt['code'] = '111'
rslt['url'] = str(sito)
rslt['http_err'] = 'Connection error'
@@ -169,11 +164,11 @@ class Kdicc():
else:
rslt['code'] = code.status
except httplib2.ServerNotFoundError as msg:
- # sia per mancanza di ADSL che per i siti non esistenti
+ # both for lack of ADSL and for non-existent sites
rslt['code'] = -2
except socket.error as msg:
- # per siti irraggiungibili senza DNS corretti
- #[Errno 111] Connection refused
+ # for unreachable sites without correct DNS
+ # [Errno 111] Connection refused
rslt['code'] = 111
except:
rslt['code'] = 'Connection error'
@@ -181,8 +176,7 @@ class Kdicc():
def view_Advise(self, txt = '' ):
"""
- Avviso per utente
- testConnected
+ Notice per user testConnected
"""
ip = self.check_Ip()
if ip:
@@ -201,37 +195,36 @@ class Kdicc():
txt = config.get_localized_string(707402)
dialog.notification(addonname, txt, xbmcgui.NOTIFICATION_INFO, 10000)
"""
- def richiamato in launcher.py
+ def called in launcher.py
"""
def test_conn(is_exit, check_dns, view_msg,
lst_urls, lst_site_check_dns, in_addon):
ktest = Kdicc(is_exit, check_dns, view_msg, lst_urls, lst_site_check_dns, in_addon)
- # se non ha l'ip lo comunico all'utente
+ # if it does not have the IP, I will communicate it to the user
if not ktest.check_Ip():
- # non permetto di entrare nell'addon
# I don't let you get into the addon
- # inserire codice lingua
+ # enter language code
if view_msg == True:
ktest.view_Advise(config.get_localized_string(70720))
if ktest.is_exit == True:
exit()
- # se non ha connessione ADSL lo comunico all'utente
+ # if it has no ADSL connection, I will communicate it to the user
if not ktest.check_Adsl():
if view_msg == True:
ktest.view_Advise(config.get_localized_string(70721))
if ktest.is_exit == True:
exit()
- # se ha i DNS filtrati lo comunico all'utente
+ # if it has DNS filtered, I will communicate it to the user
if check_dns == True:
if not ktest.check_Dns():
if view_msg == True:
ktest.view_Advise(config.get_localized_string(70722))
- xbmc.log("############ Inizio Check DNS ############", level=xbmc.LOGNOTICE)
+ xbmc.log("############ Start Check DNS ############", level=xbmc.LOGNOTICE)
xbmc.log("## IP: %s" % (ktest.ip_addr), level=xbmc.LOGNOTICE)
xbmc.log("## DNS: %s" % (ktest.dns), level=xbmc.LOGNOTICE)
- xbmc.log("############ Fine Check DNS ############", level=xbmc.LOGNOTICE)
+ xbmc.log("############# End Check DNS #############", level=xbmc.LOGNOTICE)
# if check_dns == True:
# if ktest.check_Ip() == True and ktest.check_Adsl() == True and ktest.check_Dns() == True:
# return True
@@ -243,21 +236,17 @@ def test_conn(is_exit, check_dns, view_msg,
# else:
# return False
-# def per la creazione del file channels.json
+# def for creating the channels.json file
def check_channels(inutile=''):
"""
- leggo gli host dei canali dal file channels.json
- li controllo
- scrivo il file channels-test.json
- con il codice di errore e il nuovio url in caso di redirect
+ I read the channel hosts from the channels.json file, I check them,
+ I write the channels-test.json file with the error code and the new url in case of redirect
- gli url DEVONO avere http(s)
+ urls MUST have http (s)
- Durante il controllo degli urls vengono rieffettuati
- i controlli di ip, asdl e dns.
- Questo perchè può succedere che in un qualsiasi momento
- la connessione possa avere problemi. Nel caso accada, il controllo e
- relativa scrittura del file viene interrotto con messaggio di avvertimento
+ During the urls check the ip, asdl and dns checks are carried out.
+ This is because it can happen that at any time the connection may have problems. If it does, check it
+ relative writing of the file is interrupted with a warning message
"""
logger.info()
@@ -272,37 +261,37 @@ def check_channels(inutile=''):
for chann, host in sorted(data.items()):
ris = []
- # per avere un'idea della tempistica
- # utile solo se si controllano tutti i canali
- # per i canali con error 522 si perdono circa 40 sec...
+ # to get an idea of the timing
+ # useful only if you control all channels
+ # for channels with error 522 about 40 seconds are lost ...
logger.info("check #### INIZIO #### channel - host :%s - %s " % (chann, host))
rslt = Kdicc(lst_urls = [host]).http_Resp()
- # tutto ok
+ # all right
if rslt['code'] == 200:
risultato[chann] = host
# redirect
elif str(rslt['code']).startswith('3'):
- #risultato[chann] = str(rslt['code']) +' - '+ rslt['redirect'][:-1]
+ # risultato[chann] = str(rslt['code']) +' - '+ rslt['redirect'][:-1]
if rslt['redirect'].endswith('/'):
rslt['redirect'] = rslt['redirect'][:-1]
risultato[chann] = rslt['redirect']
- # sito inesistente
+ # non-existent site
elif rslt['code'] == -2:
risultato[chann] = 'Host Sconosciuto - '+ str(rslt['code']) +' - '+ host
- # sito non raggiungibile - probabili dns non settati
+ # site not reachable - probable dns not set
elif rslt['code'] == 111:
risultato[chann] = ['Host non raggiungibile - '+ str(rslt['code']) +' - '+ host]
else:
- # altri tipi di errore
- #risultato[chann] = 'Errore Sconosciuto - '+str(rslt['code']) +' - '+ host
+ # other types of errors
+ # risultato[chann] = 'Errore Sconosciuto - '+str(rslt['code']) +' - '+ host
risultato[chann] = host
logger.info("check #### FINE #### rslt :%s " % (rslt))
fileJson_test = 'channels-test.json'
- # scrivo il file aggiornato
+ # I write the updated file
with open(folderJson+'/'+fileJson_test, 'w') as f:
data = json.dump(risultato, f, sort_keys=True, indent=4)
logger.info(data)
diff --git a/specials/downloads.py b/specials/downloads.py
index ae6014ea..2467b63d 100644
--- a/specials/downloads.py
+++ b/specials/downloads.py
@@ -11,17 +11,13 @@ if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
from future.builtins import filter
from past.utils import old_div
-import re
-import time
-import unicodedata
-import xbmc
+import re, time, unicodedata, xbmc
from channelselector import get_thumb
from core import filetools, jsontools, scraper, scrapertools, servertools, videolibrarytools, support
from core.downloader import Downloader
from core.item import Item
-from platformcode import config, logger
-from platformcode import platformtools
+from platformcode import config, logger, platformtools
from core.support import log, dbg, typo
from servers import torrent
diff --git a/specials/favorites.py b/specials/favorites.py
index 51089d8f..bc4ba832 100644
--- a/specials/favorites.py
+++ b/specials/favorites.py
@@ -1,19 +1,16 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
-# Lista de vídeos favoritos
+# List of favorite videos
# ------------------------------------------------------------
-import os
-import time
+import os, time
-from core import filetools
-from core import scrapertools
+from core import filetools, scrapertools
from core.item import Item
-from platformcode import config, logger
-from platformcode import platformtools
+from platformcode import config, logger, platformtools
try:
- # Fijamos la ruta a favourites.xml
+ # We set the path to favorites.xml
if config.is_xbmc():
import xbmc
@@ -32,8 +29,7 @@ def mainlist(item):
for name, thumb, data in read_favourites():
if "plugin://plugin.video.%s/?" % config.PLUGIN_NAME in data:
- url = scrapertools.find_single_match(data, 'plugin://plugin.video.%s/\?([^;]*)' % config.PLUGIN_NAME) \
- .replace(""", "")
+ url = scrapertools.find_single_match(data, 'plugin://plugin.video.%s/\?([^;]*)' % config.PLUGIN_NAME).replace(""", "")
item = Item().fromurl(url)
item.title = name
@@ -45,7 +41,7 @@ def mainlist(item):
elif type(item.context) != list:
item.context = []
- item.context.extend([{"title": config.get_localized_string(30154), # "Quitar de favoritos"
+ item.context.extend([{"title": config.get_localized_string(30154), # "Remove from favorites "
"action": "delFavourite",
"channel": "favorites",
"from_title": item.title},
@@ -88,7 +84,7 @@ def addFavourite(item):
logger.info()
# logger.debug(item.tostring('\n'))
- # Si se llega aqui mediante el menu contextual, hay que recuperar los parametros action y channel
+ # If you get here through the context menu, you must retrieve the action and channel parameters
if item.from_action:
item.__dict__["action"] = item.__dict__.pop("from_action")
if item.from_channel:
@@ -100,8 +96,7 @@ def addFavourite(item):
favourites_list.append((titulo, item.thumbnail, data))
if save_favourites(favourites_list):
- platformtools.dialog_ok(config.get_localized_string(30102), titulo,
- config.get_localized_string(30108)) # 'se ha añadido a favoritos'
+ platformtools.dialog_ok(config.get_localized_string(30102), titulo, config.get_localized_string(30108)) # 'added to favorites'
def delFavourite(item):
@@ -117,8 +112,7 @@ def delFavourite(item):
favourites_list.remove(fav)
if save_favourites(favourites_list):
- platformtools.dialog_ok(config.get_localized_string(30102), item.title,
- config.get_localized_string(30105).lower()) # 'Se ha quitado de favoritos'
+ platformtools.dialog_ok(config.get_localized_string(30102), item.title, config.get_localized_string(30105).lower()) # 'Removed from favorites'
platformtools.itemlist_refresh()
break
@@ -127,22 +121,21 @@ def renameFavourite(item):
logger.info()
# logger.debug(item.tostring('\n'))
- # Buscar el item q queremos renombrar en favourites.xml
+ # Find the item we want to rename in favorites.xml
favourites_list = read_favourites()
for i, fav in enumerate(favourites_list):
if fav[0] == item.from_title:
- # abrir el teclado
+ # open keyboard
new_title = platformtools.dialog_input(item.from_title, item.title)
if new_title:
favourites_list[i] = (new_title, fav[1], fav[2])
if save_favourites(favourites_list):
- platformtools.dialog_ok(config.get_localized_string(30102), item.from_title,
- "se ha renombrado como:", new_title) # 'Se ha quitado de favoritos'
+ platformtools.dialog_ok(config.get_localized_string(30102), item.from_title, config.get_localized_string(60086) + ' ', new_title) # 'Removed from favorites'
platformtools.itemlist_refresh()
##################################################
-# Funciones para migrar favoritos antiguos (.txt)
+# Features to migrate old favorites (.txt)
def readbookmark(filepath):
logger.info()
import urllib
@@ -176,7 +169,7 @@ def readbookmark(filepath):
except:
plot = lines[4].strip()
- # Campos contentTitle y canal añadidos
+ # ContentTitle and channel fields added
if len(lines) >= 6:
try:
contentTitle = urllib.unquote_plus(lines[5].strip())
@@ -199,7 +192,7 @@ def readbookmark(filepath):
def check_bookmark(readpath):
- # Crea un listado con las entradas de favoritos
+ # Create a list with favorite entries
itemlist = []
if readpath.startswith("special://") and config.is_xbmc():
@@ -207,12 +200,12 @@ def check_bookmark(readpath):
readpath = xbmc.translatePath(readpath)
for fichero in sorted(filetools.listdir(readpath)):
- # Ficheros antiguos (".txt")
+ # Old files (".txt")
if fichero.endswith(".txt"):
- # Esperamos 0.1 segundos entre ficheros, para que no se solapen los nombres de archivo
+ # We wait 0.1 seconds between files, so that the file names do not overlap
time.sleep(0.1)
- # Obtenemos el item desde el .txt
+ # We get the item from the .txt
canal, titulo, thumbnail, plot, server, url, contentTitle = readbookmark(filetools.join(readpath, fichero))
if canal == "":
canal = "favorites"
@@ -222,21 +215,21 @@ def check_bookmark(readpath):
filetools.rename(filetools.join(readpath, fichero), fichero[:-4] + ".old")
itemlist.append(item)
- # Si hay Favoritos q guardar
+ # If there are Favorites to save
if itemlist:
favourites_list = read_favourites()
for item in itemlist:
data = "ActivateWindow(10025,"plugin://plugin.video.kod/?" + item.tourl() + "",return)"
favourites_list.append((item.title, item.thumbnail, data))
if save_favourites(favourites_list):
- logger.debug("Conversion de txt a xml correcta")
+ logger.debug("Correct txt to xml conversion")
-# Esto solo funcionara al migrar de versiones anteriores, ya no existe "bookmarkpath"
+# This will only work when migrating from previous versions, there is no longer a "bookmarkpath"
try:
if config.get_setting("bookmarkpath") != "":
check_bookmark(config.get_setting("bookmarkpath"))
else:
- logger.info("No existe la ruta a los favoritos de versiones antiguas")
+ logger.info("No path to old version favorites")
except:
pass
diff --git a/specials/filtertools.py b/specials/filtertools.py
index f8d05001..8dae6e0d 100644
--- a/specials/filtertools.py
+++ b/specials/filtertools.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
-# filtertools - se encarga de filtrar resultados
+# filtertools - is responsible for filtering results
# ------------------------------------------------------------
from builtins import object
@@ -27,7 +27,7 @@ filter_global = None
__channel__ = "filtertools"
-# TODO echar un ojo a https://pyformat.info/, se puede formatear el estilo y hacer referencias directamente a elementos
+# TODO take a look at https://pyformat.info/, you can format the style and make references directly to elements
class ResultFilter(object):
@@ -37,8 +37,7 @@ class ResultFilter(object):
self.quality_allowed = dict_filter[TAG_QUALITY_ALLOWED]
def __str__(self):
- return "{active: '%s', language: '%s', quality_allowed: '%s'}" % \
- (self.active, self.language, self.quality_allowed)
+ return "{active: '%s', language: '%s', quality_allowed: '%s'}" % (self.active, self.language, self.quality_allowed)
class Filter(object):
@@ -59,7 +58,7 @@ class Filter(object):
TAG_LANGUAGE: dict_filtered_shows[tvshow][TAG_LANGUAGE],
TAG_QUALITY_ALLOWED: dict_filtered_shows[tvshow][TAG_QUALITY_ALLOWED]})
- # opcion general "no filtrar"
+ # general option "do not filter"
elif global_filter_language != 0:
from core import channeltools
list_controls, dict_settings = channeltools.get_channel_controls_settings(item.channel)
@@ -71,8 +70,7 @@ class Filter(object):
language = control["lvalues"][global_filter_language]
# logger.debug("language %s" % language)
except:
- logger.error("No se ha encontrado el valor asociado al codigo '%s': %s" %
- (global_filter_lang_id, global_filter_language))
+ logger.error("The value associated with the code was not found '%s': %s" % (global_filter_lang_id, global_filter_language))
break
self.result = ResultFilter({TAG_ACTIVE: True, TAG_LANGUAGE: language, TAG_QUALITY_ALLOWED: []})
@@ -84,7 +82,7 @@ class Filter(object):
def access():
"""
- Devuelve si se puede usar o no filtertools
+ Returns whether or not filtertools can be used
"""
allow = False
@@ -96,24 +94,23 @@ def access():
def context(item, list_language=None, list_quality=None, exist=False):
"""
- Para xbmc/kodi y mediaserver ya que pueden mostrar el menú contextual, se añade un menu para configuración
- la opción de filtro, sólo si es para series.
- Dependiendo del lugar y si existe filtro se añadirán más opciones a mostrar.
- El contexto -solo se muestra para series-.
+ For xbmc / kodi and mediaserver since they can show the contextual menu, a filter option is added to the configuration menu, only if it is for series.
+ Depending on the place and if there is a filter, more options will be added to show.
+ The context -is shown only for series-.
- @param item: elemento para obtener la información y ver que contexto añadir
+ @param item: eelement to get the information and see what context to add
@type item: item
- param list_language: listado de idiomas posibles
+ param list_language: list of possible languages
@type list_language: list[str]
- @param list_quality: listado de calidades posibles
+ @param list_quality: list of possible qualities
@type list_quality: list[str]
- @param exist: si existe el filtro
+ @param exist: if the filter exists
@type exist: bool
- @return: lista de opciones a mostrar en el menú contextual
+ @return: list of options to display in the context menu
@rtype: list
"""
- # Dependiendo de como sea el contexto lo guardamos y añadimos las opciones de filtertools.
+ # Depending on how the context is, we save it and add the filtertools options.
if isinstance(item.context, str):
_context = item.context.split("|")
elif isinstance(item.context, list):
@@ -152,10 +149,8 @@ def context(item, list_language=None, list_quality=None, exist=False):
def show_option(itemlist, channel, list_language, list_quality):
if access():
- itemlist.append(Item(channel=__channel__, title=config.get_localized_string(60429) %
- COLOR.get("parent_item", "auto"), action="load",
- list_language=list_language,
- list_quality=list_quality, from_channel=channel))
+ itemlist.append(Item(channel=__channel__, title=config.get_localized_string(60429) % COLOR.get("parent_item", "auto"), action="load",
+ list_language=list_language, list_quality=list_quality, from_channel=channel))
return itemlist
@@ -169,14 +164,14 @@ def check_conditions(_filter, list_item, item, list_language, list_quality, qual
if _filter.language:
# logger.debug("title es %s" % item.title)
- #2nd lang
+ # 2nd lang
from platformcode import unify
_filter.language = unify.set_lang(_filter.language).upper()
- # viene de episodios
+ # comes from episodes
if isinstance(item.language, list):
- #2nd lang
+ # 2nd lang
for n, lang in enumerate(item.language):
item.language[n] = unify.set_lang(lang).upper()
@@ -184,9 +179,9 @@ def check_conditions(_filter, list_item, item, list_language, list_quality, qual
language_count += 1
else:
is_language_valid = False
- # viene de findvideos
+ # comes from findvideos
else:
- #2nd lang
+ # 2nd lang
item.language = unify.set_lang(item.language).upper()
if item.language.lower() == _filter.language.lower():
@@ -198,7 +193,7 @@ def check_conditions(_filter, list_item, item, list_language, list_quality, qual
quality = ""
if _filter.quality_allowed and item.quality != "":
- # if hasattr(item, 'quality'): # esta validación no hace falta por que SIEMPRE se devuelve el atributo vacío
+ # if hasattr (item, 'quality'): # this validation is not necessary because the empty attribute is ALWAYS returned
if item.quality.lower() in _filter.quality_allowed:
quality = item.quality.lower()
quality_count += 1
@@ -206,7 +201,7 @@ def check_conditions(_filter, list_item, item, list_language, list_quality, qual
is_quality_valid = False
if is_language_valid and is_quality_valid:
- #TODO 2nd lang: habría que ver si conviene unificar el idioma aqui o no
+ #TODO 2nd lang: we should see if it is convenient to unify the language here or not
item.list_language = list_language
if list_quality:
item.list_quality = list_quality
@@ -216,34 +211,32 @@ def check_conditions(_filter, list_item, item, list_language, list_quality, qual
# logger.debug(" -Enlace añadido")
elif not item.language:
list_item.append(item)
- logger.debug(" idioma valido?: %s, item.language: %s, filter.language: %s" %
- (is_language_valid, item.language, _filter.language))
- logger.debug(" calidad valida?: %s, item.quality: %s, filter.quality_allowed: %s"
- % (is_quality_valid, quality, _filter.quality_allowed))
+ logger.debug(" idioma valido?: %s, item.language: %s, filter.language: %s" % (is_language_valid, item.language, _filter.language))
+ logger.debug(" calidad valida?: %s, item.quality: %s, filter.quality_allowed: %s" % (is_quality_valid, quality, _filter.quality_allowed))
return list_item, quality_count, language_count, _filter.language
def get_link(list_item, item, list_language, list_quality=None, global_filter_lang_id="filter_languages"):
"""
- Devuelve una lista de enlaces, si el item está filtrado correctamente se agrega a la lista recibida.
+ Returns a list of links, if the item is correctly filtered it is added to the received list.
- @param list_item: lista de enlaces
+ @param list_item: list of links
@type list_item: list[Item]
- @param item: elemento a filtrar
+ @param item: element to filter
@type item: Item
- @param list_language: listado de idiomas posibles
+ @param list_language: list of possible languages
@type list_language: list[str]
- @param list_quality: listado de calidades posibles
+ @param list_quality: list of possible qualities
@type list_quality: list[str]
- @param global_filter_lang_id: id de la variable de filtrado por idioma que está en settings
+ @param global_filter_lang_id: id of the filtering variable by language that is in settings
@type global_filter_lang_id: str
- @return: lista de Item
+ @return: Item list
@rtype: list[Item]
"""
logger.info()
- # si los campos obligatorios son None salimos
+ # if the required fields are None we leave
if list_item is None or item is None:
return []
@@ -256,8 +249,7 @@ def get_link(list_item, item, list_language, list_quality=None, global_filter_la
logger.debug("filter: '%s' datos: '%s'" % (item.show, filter_global))
if filter_global and filter_global.active:
- list_item, quality_count, language_count = \
- check_conditions(filter_global, list_item, item, list_language, list_quality)[:3]
+ list_item, quality_count, language_count = check_conditions(filter_global, list_item, item, list_language, list_quality)[:3]
else:
item.context = context(item)
list_item.append(item)
@@ -267,17 +259,17 @@ def get_link(list_item, item, list_language, list_quality=None, global_filter_la
def get_links(list_item, item, list_language, list_quality=None, global_filter_lang_id="filter_languages"):
"""
- Devuelve una lista de enlaces filtrados.
+ Returns a list of filtered links.
- @param list_item: lista de enlaces
+ @param list_item: list of links
@type list_item: list[Item]
- @param item: elemento a filtrar
+ @param item: element to filter
@type item: item
- @param list_language: listado de idiomas posibles
+ @param list_language: list of possible languages
@type list_language: list[str]
- @param list_quality: listado de calidades posibles
+ @param list_quality: list of possible qualities
@type list_quality: list[str]
- @param global_filter_lang_id: id de la variable de filtrado por idioma que está en settings
+ @param global_filter_lang_id: id of the filtering variable by language that is in settings
@type global_filter_lang_id: str
@return: lista de Item
@rtype: list[Item]
@@ -285,18 +277,18 @@ def get_links(list_item, item, list_language, list_quality=None, global_filter_l
logger.info()
- # si los campos obligatorios son None salimos
+ # if the required fields are None we leave
if list_item is None or item is None:
return []
- # si list_item está vacío volvemos, no se añade validación de plataforma para que Plex pueda hacer filtro global
+ # if list_item is empty we go back, no platform validation is added so Plex can do global filter
if len(list_item) == 0:
return list_item
second_lang = config.get_setting('second_language')
- #Ordena segun servidores favoritos, elima servers de blacklist y desactivados
+ # Sort by favorite servers, delete blacklist servers and disabled
from core import servertools
list_item= servertools.filter_servers(list_item)
@@ -313,8 +305,7 @@ def get_links(list_item, item, list_language, list_quality=None, global_filter_l
if _filter and _filter.active:
for item in list_item:
- new_itemlist, quality_count, language_count, first_lang = check_conditions(_filter, new_itemlist, item, list_language,
- list_quality, quality_count, language_count)
+ new_itemlist, quality_count, language_count, first_lang = check_conditions(_filter, new_itemlist, item, list_language, list_quality, quality_count, language_count)
#2nd lang
if second_lang and second_lang != 'No' and first_lang.lower() != second_lang.lower() :
@@ -322,7 +313,6 @@ def get_links(list_item, item, list_language, list_quality=None, global_filter_l
_filter2 = _filter
_filter2.language = second_lang
for it in new_itemlist:
-
if isinstance(it.language, list):
if not second_lang in it.language:
second_list.append(it)
@@ -330,32 +320,27 @@ def get_links(list_item, item, list_language, list_quality=None, global_filter_l
second_list = new_itemlist
break
for item in list_item:
- new_itemlist, quality_count, language_count, second_lang = check_conditions(_filter2, second_list, item, list_language,
- list_quality, quality_count, language_count)
+ new_itemlist, quality_count, language_count, second_lang = check_conditions(_filter2, second_list, item, list_language, list_quality, quality_count, language_count)
- logger.debug("ITEMS FILTRADOS: %s/%s, idioma [%s]: %s, calidad_permitida %s: %s"
- % (len(new_itemlist), len(list_item), _filter.language, language_count, _filter.quality_allowed,
- quality_count))
+ logger.debug("FILTERED ITEMS: %s/%s, language [%s]: %s, allowed quality %s: %s" % (len(new_itemlist), len(list_item), _filter.language, language_count, _filter.quality_allowed, quality_count))
if len(new_itemlist) == 0:
list_item_all = []
for i in list_item:
list_item_all.append(i.tourl())
- _context = [
- {"title": config.get_localized_string(60430) % _filter.language, "action": "delete_from_context",
- "channel": "filtertools", "to_channel": item.channel}]
+ _context = [{"title": config.get_localized_string(60430) % _filter.language, "action": "delete_from_context", "channel": "filtertools", "to_channel": item.channel}]
if _filter.quality_allowed:
msg_quality_allowed = " y calidad %s" % _filter.quality_allowed
else:
msg_quality_allowed = ""
-
+
msg_lang = ' %s' % first_lang.upper()
if second_lang and second_lang != 'No':
msg_lang = 's %s ni %s' % (first_lang.upper(), second_lang.upper())
-
+
new_itemlist.append(Item(channel=__channel__, action="no_filter", list_item_all=list_item_all,
show=item.show,
title=config.get_localized_string(60432) % (_filter.language, msg_quality_allowed),
@@ -392,15 +377,15 @@ def no_filter(item):
def mainlist(channel, list_language, list_quality):
"""
- Muestra una lista de las series filtradas
+ Shows a list of the leaked series
- @param channel: nombre del canal para obtener las series filtradas
+ @param channel: channel name to get filtered series
@type channel: str
- @param list_language: lista de idiomas del canal
+ @param list_language: channel language list
@type list_language: list[str]
- @param list_quality: lista de calidades del canal
+ @param list_quality: channel quality list
@type list_quality: list[str]
- @return: lista de Item
+ @return: Item list
@rtype: list[Item]
"""
logger.info()
@@ -439,7 +424,7 @@ def mainlist(channel, list_language, list_quality):
def config_item(item):
"""
- muestra una serie filtrada para su configuración
+ displays a filtered series for your setup
@param item: item
@type item: Item
@@ -447,7 +432,7 @@ def config_item(item):
logger.info()
logger.info("item %s" % item.tostring())
- # OBTENEMOS LOS DATOS DEL JSON
+ # WE GET THE JSON DATA
dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_FILTER)
tvshow = item.show.lower().strip()
@@ -462,7 +447,7 @@ def config_item(item):
pass
if default_lang == '':
- platformtools.dialog_notification("FilterTools", "No hay idiomas definidos")
+ platformtools.dialog_notification("FilterTools", "There are no defined languages")
return
else:
lang_selected = dict_series.get(tvshow, {}).get(TAG_LANGUAGE, default_lang)
@@ -525,7 +510,7 @@ def config_item(item):
"visible": True,
})
- # concatenamos list_controls con list_controls_calidad
+ # we concatenate list_controls with list_controls_quality
list_controls.extend(list_controls_calidad)
title = config.get_localized_string(60441) % (COLOR.get("selected", "auto"), item.show)
@@ -566,11 +551,11 @@ def delete(item, dict_values):
def save(item, dict_data_saved):
"""
- Guarda los valores configurados en la ventana
+ Save the configured values in the window
@param item: item
@type item: Item
- @param dict_data_saved: diccionario con los datos salvados
+ @param dict_data_saved: dictionary with saved data
@type dict_data_saved: dict
"""
logger.info()
@@ -583,7 +568,7 @@ def save(item, dict_data_saved):
dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_FILTER)
tvshow = item.show.strip().lower()
- logger.info("Se actualiza los datos")
+ logger.info("Data is updated")
list_quality = []
for _id, value in list(dict_data_saved.items()):
@@ -613,7 +598,7 @@ def save(item, dict_data_saved):
def save_from_context(item):
"""
- Salva el filtro a través del menú contextual
+ Save the filter through the context menu
@param item: item
@type item: item
@@ -630,9 +615,9 @@ def save_from_context(item):
sound = False
if result:
- message = "FILTRO GUARDADO"
+ message = "SAVED FILTER"
else:
- message = "Error al guardar en disco"
+ message = "Error saving to disk"
sound = True
heading = "%s [%s]" % (item.show.strip(), item.language)
@@ -644,14 +629,14 @@ def save_from_context(item):
def delete_from_context(item):
"""
- Elimina el filtro a través del menú contextual
+ Delete the filter through the context menu
@param item: item
@type item: item
"""
logger.info()
- # venimos desde get_links y no se ha obtenido ningún resultado, en menu contextual y damos a borrar
+ # We come from get_links and no result has been obtained, in context menu and we delete
if item.to_channel != "":
item.from_channel = item.to_channel
@@ -665,9 +650,9 @@ def delete_from_context(item):
sound = False
if result:
- message = "FILTRO ELIMINADO"
+ message = "FILTER REMOVED"
else:
- message = "Error al guardar en disco"
+ message = "Error saving to disk"
sound = True
heading = "%s [%s]" % (item.show.strip(), lang_selected)
diff --git a/specials/kodfavorites.py b/specials/kodfavorites.py
index 0322ec3c..615b3117 100644
--- a/specials/kodfavorites.py
+++ b/specials/kodfavorites.py
@@ -1,21 +1,21 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
-# Alfa favoritos
+# KoD favorites
# ==============
-# - Lista de enlaces guardados como favoritos, solamente en Alfa, no Kodi.
-# - Los enlaces se organizan en carpetas (virtuales) que puede definir el usuario.
-# - Se utiliza un sólo fichero para guardar todas las carpetas y enlaces: kodfavourites-default.json
-# - Se puede copiar kodfavourites-default.json a otros dispositivos ya que la única dependencia local es el thumbnail asociado a los enlaces,
-# pero se detecta por código y se ajusta al dispositivo actual.
-# - Se pueden tener distintos ficheros de alfavoritos y alternar entre ellos, pero solamente uno de ellos es la "lista activa".
-# - Los ficheros deben estar en config.get_data_path() y empezar por kodfavourites- y terminar en .json
+# - List of links saved as favorites, only in Alpha, not Kodi.
+# - Links are organized in (virtual) folders that can be defined by the user.
+# - A single file is used to save all folders and links: kodfavourites-default.json
+# - kodfavourites-default.json can be copied to other devices since the only local dependency is the thumbnail associated with the links,
+# but it is detected by code and adjusts to the current device.
+# - You can have different alphabet files and alternate between them, but only one of them is the "active list".
+# - Files must be in config.get_data_path () and start with kodfavourites- and end in .json
-# Requerimientos en otros módulos para ejecutar este canal:
-# - Añadir un enlace a este canal en channelselector.py
-# - Modificar platformtools.py para controlar el menú contextual y añadir "Guardar enlace" en set_context_commands
+# Requirements in other modules to run this channel:
+# - Add a link to this channel in channelselector.py
+# - Modify platformtools.py to control the context menu and add "Save link" in set_context_commands
# ------------------------------------------------------------
-#from builtins import str
+# from builtins import str
import sys
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
@@ -32,35 +32,34 @@ from core import filetools, jsontools
def fechahora_actual():
return datetime.now().strftime('%Y-%m-%d %H:%M')
-# Helpers para listas
-# -------------------
+# List Helpers
PREFIJO_LISTA = 'kodfavorites-'
-# Devuelve el nombre de la lista activa (Ej: kodfavourites-default.json)
+# Returns the name of the active list (Ex: kodfavourites-default.json)
def get_lista_activa():
return config.get_setting('lista_activa', default = PREFIJO_LISTA + 'default.json')
-# Extrae nombre de la lista del fichero, quitando prefijo y sufijo (Ej: kodfavourites-Prueba.json => Prueba)
+# Extract list name from file, removing prefix and suffix (Ex: kodfavourites-Test.json => Test)
def get_name_from_filename(filename):
return filename.replace(PREFIJO_LISTA, '').replace('.json', '')
-# Componer el fichero de lista a partir de un nombre, añadiendo prefijo y sufijo (Ej: Prueba => kodfavourites-Prueba.json)
+# Compose the list file from a name, adding prefix and suffix (Ex: Test => kodfavourites-Test.json)
def get_filename_from_name(name):
return PREFIJO_LISTA + name + '.json'
-# Apuntar en un fichero de log los códigos de los ficheros que se hayan compartido
+# Record the codes of the files that have been shared in a log file
def save_log_lista_shared(msg):
msg = fechahora_actual() + ': ' + msg + os.linesep
fullfilename = os.path.join(config.get_data_path(), 'kodfavorites_shared.log')
with open(fullfilename, 'a') as f: f.write(msg); f.close()
-# Limpiar texto para usar como nombre de fichero
+# Clean text to use as file name
def text_clean(txt, disallowed_chars = '[^a-zA-Z0-9\-_()\[\]. ]+', blank_char = ' '):
import unicodedata
try:
txt = unicode(txt, 'utf-8')
- except NameError: # unicode is a default on python 3
+ except NameError: # unicode is a default on python 3
pass
txt = unicodedata.normalize('NFKD', txt).encode('ascii', 'ignore')
txt = txt.decode('utf-8').strip()
@@ -70,13 +69,12 @@ def text_clean(txt, disallowed_chars = '[^a-zA-Z0-9\-_()\[\]. ]+', blank_char =
-# Clase para cargar y guardar en el fichero de Alfavoritos
-# --------------------------------------------------------
+# Class to load and save in the KoDFavorites file
class KodfavouritesData(object):
def __init__(self, filename = None):
- # Si no se especifica ningún fichero se usa la lista_activa (si no la hay se crea)
+ # If no file is specified, the active_list is used (if not, it is created)
if filename == None:
filename = get_lista_activa()
@@ -84,7 +82,7 @@ class KodfavouritesData(object):
if not os.path.exists(self.user_favorites_file):
fichero_anterior = os.path.join(config.get_data_path(), 'user_favorites.json')
- if os.path.exists(fichero_anterior): # formato anterior, convertir (a eliminar después de algunas versiones)
+ if os.path.exists(fichero_anterior): # old format, convert (to delete after some versions)
jsondata = jsontools.load(filetools.read(fichero_anterior))
self.user_favorites = jsondata
self.info_lista = {}
@@ -94,7 +92,7 @@ class KodfavouritesData(object):
self.user_favorites = []
else:
jsondata = jsontools.load(filetools.read(self.user_favorites_file))
- if not 'user_favorites' in jsondata or not 'info_lista' in jsondata: # formato incorrecto
+ if not 'user_favorites' in jsondata or not 'info_lista' in jsondata: # incorrect format
self.user_favorites = []
else:
self.user_favorites = jsondata['user_favorites']
@@ -103,8 +101,8 @@ class KodfavouritesData(object):
if len(self.user_favorites) == 0:
self.info_lista = {}
-
- # Crear algunas carpetas por defecto
+
+ # Create some default folders
self.user_favorites.append({ 'title': config.get_localized_string(30122), 'items': [] })
self.user_favorites.append({ 'title': config.get_localized_string(30123), 'items': [] })
self.user_favorites.append({ 'title': config.get_localized_string(70149), 'items': [] })
@@ -112,7 +110,7 @@ class KodfavouritesData(object):
self.save()
def save(self):
- if 'created' not in self.info_lista:
+ if 'created' not in self.info_lista:
self.info_lista['created'] = fechahora_actual()
self.info_lista['updated'] = fechahora_actual()
@@ -120,34 +118,34 @@ class KodfavouritesData(object):
jsondata['user_favorites'] = self.user_favorites
jsondata['info_lista'] = self.info_lista
if not filetools.write(self.user_favorites_file, jsontools.dump(jsondata)):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70614), os.path.basename(self.user_favorites_file))
+ platformtools.dialog_ok('KoD', config.get_localized_string(70614), os.path.basename(self.user_favorites_file))
# ============================
-# Añadir desde menú contextual
+# Add from context menu
# ============================
def addFavourite(item):
logger.info()
alfav = KodfavouritesData()
- # Si se llega aquí mediante el menú contextual, hay que recuperar los parámetros action y channel
+ # If you get here through the context menu, you must retrieve the action and channel parameters
if item.from_action:
item.__dict__['action'] = item.__dict__.pop('from_action')
if item.from_channel:
item.__dict__['channel'] = item.__dict__.pop('from_channel')
- # Limpiar título
+ #Clear title
item.title = re.sub(r'\[COLOR [^\]]*\]', '', item.title.replace('[/COLOR]', '')).strip()
if item.text_color:
item.__dict__.pop('text_color')
- # Diálogo para escoger/crear carpeta
+ # Dialog to choose / create folder
i_perfil = _selecciona_perfil(alfav, config.get_localized_string(70546))
if i_perfil == -1: return False
- # Detectar que el mismo enlace no exista ya en la carpeta
- campos = ['channel','action','url','extra','list_type'] # si todos estos campos coinciden se considera que el enlace ya existe
+ # Detect that the same link does not already exist in the folder
+ campos = ['channel','action','url','extra','list_type'] # if all these fields match the link is considered to already exist
for enlace in alfav.user_favorites[i_perfil]['items']:
it = Item().fromurl(enlace)
repe = True
@@ -159,25 +157,25 @@ def addFavourite(item):
platformtools.dialog_notification(config.get_localized_string(70615), config.get_localized_string(70616))
return False
- # Si es una película/serie, completar información de tmdb si no se tiene activado tmdb_plus_info (para season/episodio no hace falta pq ya se habrá hecho la "segunda pasada")
+ # If it is a movie / series, fill in tmdb information if tmdb_plus_info is not activated (for season / episode it is not necessary because the "second pass" will have already been done)
if (item.contentType == 'movie' or item.contentType == 'tvshow') and not config.get_setting('tmdb_plus_info', default=False):
from core import tmdb
- tmdb.set_infoLabels(item, True) # obtener más datos en "segunda pasada" (actores, duración, ...)
+ tmdb.set_infoLabels(item, True) # get more data in "second pass" (actors, duration, ...)
- # Añadir fecha en que se guarda
+ # Add date saved
item.date_added = fechahora_actual()
- # Guardar
+ # save
alfav.user_favorites[i_perfil]['items'].append(item.tourl())
alfav.save()
platformtools.dialog_notification(config.get_localized_string(70531), config.get_localized_string(70532) % alfav.user_favorites[i_perfil]['title'])
-
+
return True
# ====================
-# NAVEGACIÓN
+# NAVIGATION
# ====================
def mainlist(item):
@@ -211,7 +209,7 @@ def mainlist(item):
itemlist.append(Item(channel=item.channel, action='mostrar_perfil', title=perfil['title'], plot=plot, i_perfil=i_perfil, context=context))
itemlist.append(item.clone(action='crear_perfil', title=config.get_localized_string(70542), folder=False))
-
+
itemlist.append(item.clone(action='mainlist_listas', title=config.get_localized_string(70603)))
return itemlist
@@ -240,15 +238,15 @@ def mostrar_perfil(item):
it.plot += '[CR][COLOR blue]Url:[/COLOR] ' + it.url if isinstance(it.url, str) else '...'
if it.date_added != '': it.plot += '[CR][COLOR blue]' + config.get_localized_string(70469) + ':[/COLOR] ' + it.date_added
- # Si no es una url, ni tiene la ruta del sistema, convertir el path ya que se habrá copiado de otro dispositivo.
- # Sería más óptimo que la conversión se hiciera con un menú de importar, pero de momento se controla en run-time.
+ # If it is not a url, nor does it have the system path, convert the path since it will have been copied from another device.
+ # It would be more optimal if the conversion was done with an import menu, but at the moment it is controlled in run-time.
if it.thumbnail and '://' not in it.thumbnail and not it.thumbnail.startswith(ruta_runtime):
ruta, fichero = filetools.split(it.thumbnail)
- if ruta == '' and fichero == it.thumbnail: # en linux el split con un path de windows no separa correctamente
+ if ruta == '' and fichero == it.thumbnail: # in linux the split with a windows path does not separate correctly
ruta, fichero = filetools.split(it.thumbnail.replace('\\','/'))
- if 'channels' in ruta and 'thumb' in ruta:
+ if 'channels' in ruta and 'thumb' in ruta:
it.thumbnail = filetools.join(ruta_runtime, 'resources', 'media', 'channels', 'thumb', fichero)
- elif 'themes' in ruta and 'default' in ruta:
+ elif 'themes' in ruta and 'default' in ruta:
it.thumbnail = filetools.join(ruta_runtime, 'resources', 'media', 'themes', 'default', fichero)
itemlist.append(it)
@@ -256,28 +254,27 @@ def mostrar_perfil(item):
return itemlist
-# Rutinas internas compartidas
-# ----------------------------
+# Shared internal routines
-# Diálogo para seleccionar/crear una carpeta. Devuelve índice de la carpeta en user_favorites (-1 si cancel)
+# Dialog to select / create a folder. Returns index of folder on user_favorites (-1 if cancel)
def _selecciona_perfil(alfav, titulo='Seleccionar carpeta', i_actual=-1):
acciones = [(perfil['title'] if i_p != i_actual else '[I][COLOR pink]%s[/COLOR][/I]' % perfil['title']) for i_p, perfil in enumerate(alfav.user_favorites)]
acciones.append('Crear nueva carpeta')
i_perfil = -1
- while i_perfil == -1: # repetir hasta seleccionar una carpeta o cancelar
+ while i_perfil == -1: # repeat until a folder is selected or cancel
ret = platformtools.dialog_select(titulo, acciones)
- if ret == -1: return -1 # pedido cancel
+ if ret == -1: return -1 # order cancel
if ret < len(alfav.user_favorites):
i_perfil = ret
- else: # crear nueva carpeta
+ else: # create new folder
if _crea_perfil(alfav):
i_perfil = len(alfav.user_favorites) - 1
return i_perfil
-# Diálogo para crear una carpeta
+# Dialog to create a folder
def _crea_perfil(alfav):
titulo = platformtools.dialog_input(default='', heading=config.get_localized_string(70551))
if titulo is None or titulo == '':
@@ -289,8 +286,7 @@ def _crea_perfil(alfav):
return True
-# Gestión de perfiles y enlaces
-# -----------------------------
+# Profile and link management
def crear_perfil(item):
logger.info()
@@ -325,7 +321,7 @@ def eliminar_perfil(item):
if not alfav.user_favorites[item.i_perfil]: return False
- # Pedir confirmación
+ # Ask for confirmation
if not platformtools.dialog_yesno(config.get_localized_string(70618), config.get_localized_string(70619)): return False
del alfav.user_favorites[item.i_perfil]
@@ -342,9 +338,9 @@ def acciones_enlace(item):
config.get_localized_string(70624), config.get_localized_string(70548), config.get_localized_string(70625),
config.get_localized_string(70626), config.get_localized_string(70627), config.get_localized_string(70628)]
- ret = platformtools.dialog_select('Acción a ejecutar', acciones)
- if ret == -1:
- return False # pedido cancel
+ ret = platformtools.dialog_select('Action to execute', acciones)
+ if ret == -1:
+ return False # order cancel
elif ret == 0:
return editar_enlace_titulo(item)
elif ret == 1:
@@ -375,11 +371,11 @@ def editar_enlace_titulo(item):
if not alfav.user_favorites[item.i_perfil]['items'][item.i_enlace]: return False
it = Item().fromurl(alfav.user_favorites[item.i_perfil]['items'][item.i_enlace])
-
- titulo = platformtools.dialog_input(default=it.title, heading='Cambiar título del enlace')
+
+ titulo = platformtools.dialog_input(default=it.title, heading='Change link title')
if titulo is None or titulo == '' or titulo == it.title:
return False
-
+
it.title = titulo
alfav.user_favorites[item.i_perfil]['items'][item.i_enlace] = it.tourl()
@@ -397,13 +393,13 @@ def editar_enlace_color(item):
if not alfav.user_favorites[item.i_perfil]['items'][item.i_enlace]: return False
it = Item().fromurl(alfav.user_favorites[item.i_perfil]['items'][item.i_enlace])
-
+
colores = ['green','yellow','red','blue','white','orange','lime','aqua','pink','violet','purple','tomato','olive','antiquewhite','gold']
opciones = ['[COLOR %s]%s[/COLOR]' % (col, col) for col in colores]
- ret = platformtools.dialog_select('Seleccionar color:', opciones)
+ ret = platformtools.dialog_select('Select color:', opciones)
- if ret == -1: return False # pedido cancel
+ if ret == -1: return False # order cancel
it.text_color = colores[ret]
alfav.user_favorites[item.i_perfil]['items'][item.i_enlace] = it.tourl()
@@ -421,13 +417,13 @@ def editar_enlace_thumbnail(item):
if not alfav.user_favorites[item.i_perfil]['items'][item.i_enlace]: return False
it = Item().fromurl(alfav.user_favorites[item.i_perfil]['items'][item.i_enlace])
-
- # A partir de Kodi 17 se puede usar xbmcgui.Dialog().select con thumbnails (ListItem & useDetails=True)
+
+ # Starting with Kodi 17, you can use xbmcgui.Dialog (). Select with thumbnails (ListItem & useDetails = True)
is_kodi17 = (config.get_platform(True)['num_version'] >= 17.0)
if is_kodi17:
import xbmcgui
- # Diálogo para escoger thumbnail (el del canal o iconos predefinidos)
+ # Dialog to choose thumbnail (the channel or predefined icons)
opciones = []
ids = []
try:
@@ -444,7 +440,7 @@ def editar_enlace_thumbnail(item):
ids.append(channel_parameters['thumbnail'])
except:
pass
-
+
resource_path = os.path.join(config.get_runtime_path(), 'resources', 'media', 'themes', 'default')
for f in sorted(os.listdir(resource_path)):
if f.startswith('thumb_') and not f.startswith('thumb_intervenido') and f != 'thumb_back.png':
@@ -458,11 +454,11 @@ def editar_enlace_thumbnail(item):
ids.append(os.path.join(resource_path, f))
if is_kodi17:
- ret = xbmcgui.Dialog().select('Seleccionar thumbnail:', opciones, useDetails=True)
+ ret = xbmcgui.Dialog().select('Select thumbnail:', opciones, useDetails=True)
else:
- ret = platformtools.dialog_select('Seleccionar thumbnail:', opciones)
+ ret = platformtools.dialog_select('Select thumbnail:', opciones)
- if ret == -1: return False # pedido cancel
+ if ret == -1: return False # order cancel
it.thumbnail = ids[ret]
@@ -480,8 +476,8 @@ def editar_enlace_carpeta(item):
if not alfav.user_favorites[item.i_perfil]: return False
if not alfav.user_favorites[item.i_perfil]['items'][item.i_enlace]: return False
- # Diálogo para escoger/crear carpeta
- i_perfil = _selecciona_perfil(alfav, 'Mover enlace a:', item.i_perfil)
+ # Dialog to choose / create folder
+ i_perfil = _selecciona_perfil(alfav, 'Move link to:', item.i_perfil)
if i_perfil == -1 or i_perfil == item.i_perfil: return False
alfav.user_favorites[i_perfil]['items'].append(alfav.user_favorites[item.i_perfil]['items'][item.i_enlace])
@@ -499,26 +495,26 @@ def editar_enlace_lista(item):
if not alfav.user_favorites[item.i_perfil]: return False
if not alfav.user_favorites[item.i_perfil]['items'][item.i_enlace]: return False
- # Diálogo para escoger lista
+ # Dialog to choose list
opciones = []
itemlist_listas = mainlist_listas(item)
for it in itemlist_listas:
- if it.lista != '' and '[<---]' not in it.title: # descarta item crear y lista activa
+ if it.lista != '' and '[<---]' not in it.title: # discard item create and active list
opciones.append(it.lista)
if len(opciones) == 0:
- platformtools.dialog_ok('Alfa', 'No hay otras listas dónde mover el enlace.', 'Puedes crearlas desde el menú Gestionar listas de enlaces')
+ platformtools.dialog_ok('KoD', 'There are no other lists where to move the link.', 'You can create them from the Manage link lists menu')
return False
- ret = platformtools.dialog_select('Seleccionar lista destino', opciones)
+ ret = platformtools.dialog_select('Select destination list', opciones)
- if ret == -1:
- return False # pedido cancel
+ if ret == -1:
+ return False # order cancel
alfav_destino = KodfavouritesData(opciones[ret])
- # Diálogo para escoger/crear carpeta en la lista de destino
- i_perfil = _selecciona_perfil(alfav_destino, 'Seleccionar carpeta destino', -1)
+ # Dialog to choose / create folder in the destination list
+ i_perfil = _selecciona_perfil(alfav_destino, 'Select destination folder', -1)
if i_perfil == -1: return False
alfav_destino.user_favorites[i_perfil]['items'].append(alfav.user_favorites[item.i_perfil]['items'][item.i_enlace])
@@ -544,8 +540,7 @@ def eliminar_enlace(item):
return True
-# Mover perfiles y enlaces (arriba, abajo, top, bottom)
-# ------------------------
+# Move profiles and links (up, down, top, bottom)
def mover_perfil(item):
logger.info()
alfav = KodfavouritesData()
@@ -568,28 +563,28 @@ def mover_enlace(item):
return True
-# Mueve un item determinado (numérico) de una lista (arriba, abajo, top, bottom) y devuelve la lista modificada
+# Move a certain item (numeric) from a list (up, down, top, bottom) and return the modified list
def _mover_item(lista, i_selected, direccion):
last_i = len(lista) - 1
- if i_selected > last_i or i_selected < 0: return lista # índice inexistente en lista
+ if i_selected > last_i or i_selected < 0: return lista # non-existent index in list
if direccion == 'arriba':
- if i_selected == 0: # Ya está arriba de todo
+ if i_selected == 0: # It's already on top of everything
return lista
lista.insert(i_selected - 1, lista.pop(i_selected))
elif direccion == 'abajo':
- if i_selected == last_i: # Ya está abajo de todo
+ if i_selected == last_i: # It's already down
return lista
lista.insert(i_selected + 1, lista.pop(i_selected))
elif direccion == 'top':
- if i_selected == 0: # Ya está arriba de todo
+ if i_selected == 0: # It's already on top of everything
return lista
lista.insert(0, lista.pop(i_selected))
elif direccion == 'bottom':
- if i_selected == last_i: # Ya está abajo de todo
+ if i_selected == last_i: # It's already down
return lista
lista.insert(last_i, lista.pop(i_selected))
@@ -598,7 +593,7 @@ def _mover_item(lista, i_selected, direccion):
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Gestionar diferentes listas de alfavoritos
+# Manage different alphabetical lists
# ------------------------------------------
def mainlist_listas(item):
@@ -607,19 +602,19 @@ def mainlist_listas(item):
item.category = 'Listas'
lista_activa = get_lista_activa()
-
+
import glob
path = os.path.join(config.get_data_path(), PREFIJO_LISTA+'*.json')
for fichero in glob.glob(path):
lista = os.path.basename(fichero)
nombre = get_name_from_filename(lista)
- titulo = nombre if lista != lista_activa else '[COLOR gold]%s[/COLOR] [<---]' % nombre
-
+ titulo = nombre if lista != lista_activa else nombre
+
itemlist.append(item.clone(action='acciones_lista', lista=lista, title=titulo, folder=False))
itemlist.append(item.clone(action='acciones_nueva_lista', title=config.get_localized_string(70642), folder=False))
-
+
return itemlist
@@ -631,7 +626,7 @@ def acciones_lista(item):
ret = platformtools.dialog_select(item.lista, acciones)
- if ret == -1:
+ if ret == -1:
return False # pedido cancel
elif ret == 0:
return activar_lista(item)
@@ -650,7 +645,7 @@ def activar_lista(item):
fullfilename = os.path.join(config.get_data_path(), item.lista)
if not os.path.exists(fullfilename):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70630), item.lista)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70630), item.lista)
return False
config.set_setting('lista_activa', item.lista)
@@ -668,9 +663,9 @@ def renombrar_lista(item):
fullfilename_current = os.path.join(config.get_data_path(), item.lista)
if not os.path.exists(fullfilename_current):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70630), fullfilename_current)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70630), fullfilename_current)
return False
-
+
nombre = get_name_from_filename(item.lista)
titulo = platformtools.dialog_input(default=nombre, heading=config.get_localized_string(70612))
if titulo is None or titulo == '' or titulo == nombre:
@@ -680,17 +675,17 @@ def renombrar_lista(item):
filename = get_filename_from_name(titulo)
fullfilename = os.path.join(config.get_data_path(), filename)
- # Comprobar que el nuevo nombre no exista
+ # Check that the new name does not exist
if os.path.exists(fullfilename):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70613), fullfilename)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70613), fullfilename)
return False
- # Rename del fichero
+ # Rename the file
if not filetools.rename(fullfilename_current, filename):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70631), fullfilename)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70631), fullfilename)
return False
- # Update settings si es la lista activa
+ # Update settings if it is the active list
if item.lista == get_lista_activa():
config.set_setting('lista_activa', filename)
@@ -704,11 +699,11 @@ def eliminar_lista(item):
fullfilename = os.path.join(config.get_data_path(), item.lista)
if not os.path.exists(fullfilename):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70630), item.lista)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70630), item.lista)
return False
if item.lista == get_lista_activa():
- platformtools.dialog_ok('Alfa', config.get_localized_string(70632), item.lista)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70632), item.lista)
return False
if not platformtools.dialog_yesno(config.get_localized_string(70606), config.get_localized_string(70633) + ' %s ?' % item.lista): return False
@@ -720,15 +715,15 @@ def eliminar_lista(item):
def informacion_lista(item):
logger.info()
-
+
fullfilename = os.path.join(config.get_data_path(), item.lista)
if not os.path.exists(fullfilename):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70630), item.lista)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70630), item.lista)
return False
alfav = KodfavouritesData(item.lista)
-
- txt = 'Lista: [COLOR gold]%s[/COLOR]' % item.lista
+
+ txt = 'Lista: %s' % item.lista
txt += '[CR]' + config.get_localized_string(70634) + ' ' + alfav.info_lista['created'] + ' ' + config.get_localized_string(70635) + ' ' + alfav.info_lista['updated']
if 'downloaded_date' in alfav.info_lista:
@@ -736,7 +731,7 @@ def informacion_lista(item):
if 'tinyupload_date' in alfav.info_lista:
txt += '[CR]' + config.get_localized_string(70638) + ' ' + alfav.info_lista['tinyupload_date'] + ' ' + config.get_localized_string(70639) + ' [COLOR blue]' + alfav.info_lista['tinyupload_code'] + '[/COLOR]'
-
+
txt += '[CR]' + config.get_localized_string(70640) + ' ' + str(len(alfav.user_favorites))
for perfil in alfav.user_favorites:
txt += '[CR]- %s (%d %s)' % (perfil['title'], len(perfil['items']), config.get_localized_string(70641))
@@ -750,21 +745,21 @@ def compartir_lista(item):
fullfilename = os.path.join(config.get_data_path(), item.lista)
if not os.path.exists(fullfilename):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70630), fullfilename)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70630), fullfilename)
return False
try:
progreso = platformtools.dialog_progress_bg(config.get_localized_string(70643), config.get_localized_string(70644))
-
- # Acceso a la página principal de tinyupload para obtener datos necesarios
+
+ # Access to the tinyupload home page to obtain necessary data
from core import httptools, scrapertools
data = httptools.downloadpage('http://s000.tinyupload.com/index.php').data
upload_url = scrapertools.find_single_match(data, 'form action="([^"]+)')
sessionid = scrapertools.find_single_match(upload_url, 'sid=(.+)')
-
+
progreso.update(10, config.get_localized_string(70645), config.get_localized_string(70646))
- # Envío del fichero a tinyupload mediante multipart/form-data
+ # Sending the file to tinyupload using multipart / form-data
from future import standard_library
standard_library.install_aliases()
from lib import MultipartPostHandler
@@ -773,31 +768,31 @@ def compartir_lista(item):
params = { 'MAX_FILE_SIZE' : '52428800', 'file_description' : '', 'sessionid' : sessionid, 'uploaded_file' : open(fullfilename, 'rb') }
handle = opener.open(upload_url, params)
data = handle.read()
-
+
progreso.close()
if not 'File was uploaded successfuly' in data:
logger.debug(data)
- platformtools.dialog_ok('Alfa', config.get_localized_string(70647))
+ platformtools.dialog_ok('KoD', config.get_localized_string(70647))
return False
codigo = scrapertools.find_single_match(data, 'href="index\.php\?file_id=([^"]+)')
except:
- platformtools.dialog_ok('Alfa', config.get_localized_string(70647), item.lista)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70647), item.lista)
return False
- # Apuntar código en fichero de log y dentro de la lista
+ # Point code in log file and inside the list
save_log_lista_shared(config.get_localized_string(70648) + ' ' + item.lista + ' ' + codigo + ' ' + config.get_localized_string(70649))
-
+
alfav = KodfavouritesData(item.lista)
alfav.info_lista['tinyupload_date'] = fechahora_actual()
alfav.info_lista['tinyupload_code'] = codigo
alfav.save()
- platformtools.dialog_ok('Alfa', config.get_localized_string(70650), codigo)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70650), codigo)
return True
-
+
def acciones_nueva_lista(item):
@@ -810,8 +805,8 @@ def acciones_nueva_lista(item):
ret = platformtools.dialog_select(config.get_localized_string(70608), acciones)
- if ret == -1:
- return False # pedido cancel
+ if ret == -1:
+ return False # order cancel
elif ret == 0:
return crear_lista(item)
@@ -845,12 +840,12 @@ def crear_lista(item):
filename = get_filename_from_name(titulo)
fullfilename = os.path.join(config.get_data_path(), filename)
- # Comprobar que el fichero no exista ya
+ # Check that the file does not already exist
if os.path.exists(fullfilename):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70613), fullfilename)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70613), fullfilename)
return False
- # Provocar que se guarde con las carpetas vacías por defecto
+ # Cause it to be saved with empty folders by default
alfav = KodfavouritesData(filename)
platformtools.itemlist_refresh()
@@ -860,7 +855,7 @@ def crear_lista(item):
def descargar_lista(item, url):
logger.info()
from core import httptools, scrapertools
-
+
if 'tinyupload.com/' in url:
try:
from urllib.parse import urlparse
@@ -869,15 +864,15 @@ def descargar_lista(item, url):
down_url, url_name = scrapertools.find_single_match(data, ' href="(download\.php[^"]*)">([^<]*)')
url_json = '{uri.scheme}://{uri.netloc}/'.format(uri=urlparse(url)) + down_url
except:
- platformtools.dialog_ok('Alfa', config.get_localized_string(70655), url)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70655), url)
return False
elif 'zippyshare.com/' in url:
from core import servertools
video_urls, puedes, motivo = servertools.resolve_video_urls_for_playing('zippyshare', url)
-
+
if not puedes:
- platformtools.dialog_ok('Alfa', config.get_localized_string(70655), motivo)
+ platformtools.dialog_ok('KoD', config.get_localized_string(70655), motivo)
return False
url_json = video_urls[0][1] # https://www58.zippyshare.com/d/qPzzQ0UM/25460/kodfavourites-testeanding.json
url_name = url_json[url_json.rfind('/')+1:]
@@ -893,19 +888,19 @@ def descargar_lista(item, url):
# Download json
data = httptools.downloadpage(url_json).data
-
- # Verificar formato json de kodfavourites y añadir info de la descarga
+
+ # Verify ksonfavourites json format and add download info
jsondata = jsontools.load(data)
if 'user_favorites' not in jsondata or 'info_lista' not in jsondata:
logger.debug(data)
- platformtools.dialog_ok('Alfa', config.get_localized_string(70656))
+ platformtools.dialog_ok('KoD', config.get_localized_string(70656))
return False
jsondata['info_lista']['downloaded_date'] = fechahora_actual()
jsondata['info_lista']['downloaded_from'] = url
data = jsontools.dump(jsondata)
- # Pedir nombre para la lista descargada
+ # Ask for name for downloaded list
nombre = get_name_from_filename(url_name)
titulo = platformtools.dialog_input(default=nombre, heading=config.get_localized_string(70657))
if titulo is None or titulo == '':
@@ -915,14 +910,14 @@ def descargar_lista(item, url):
filename = get_filename_from_name(titulo)
fullfilename = os.path.join(config.get_data_path(), filename)
- # Si el nuevo nombre ya existe pedir confirmación para sobrescribir
+ # If the new name already exists ask for confirmation to overwrite
if os.path.exists(fullfilename):
- if not platformtools.dialog_yesno('Alfa', config.get_localized_string(70613), config.get_localized_string(70658), filename):
+ if not platformtools.dialog_yesno('KoD', config.get_localized_string(70613), config.get_localized_string(70658), filename):
return False
-
- if not filetools.write(fullfilename, data):
- platformtools.dialog_ok('Alfa', config.get_localized_string(70659), filename)
- platformtools.dialog_ok('Alfa', config.get_localized_string(70660), filename)
+ if not filetools.write(fullfilename, data):
+ platformtools.dialog_ok('KoD', config.get_localized_string(70659), filename)
+
+ platformtools.dialog_ok('KoD', config.get_localized_string(70660), filename)
platformtools.itemlist_refresh()
return True
diff --git a/specials/news.py b/specials/news.py
index 3d9a4ad1..2287a15a 100644
--- a/specials/news.py
+++ b/specials/news.py
@@ -11,25 +11,19 @@ from core.support import typo
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
-import glob
-import os
-import re
-import time
+import glob, os, re, time
from threading import Thread
from channelselector import get_thumb, auto_filter
-from core import channeltools
-from core import jsontools
-from core import scrapertools, support
+from core import channeltools, jsontools, scrapertools, support
from core.item import Item
-from platformcode import config, logger
-from platformcode import platformtools
+from platformcode import config, logger, platformtools
THUMBNAILS = {'0': 'posters', '1': 'banners', '2': 'squares'}
__perfil__ = config.get_setting('perfil', "news")
-# Fijar perfil de color
+# Set color profile
perfil = [['0xFF0B7B92', '0xFF89FDFB', '0xFFACD5D4'],
['0xFFB31313', '0xFFFF9000', '0xFFFFEE82'],
['0xFF891180', '0xFFCB22D7', '0xFFEEA1EB'],
@@ -141,7 +135,7 @@ def get_channels_list():
list_canales = {'peliculas': [], 'series': [],'anime': [], 'italiano':[], 'documentales': []}
any_active = False
- # Rellenar listas de canales disponibles
+ # Fill available channel lists
channels_path = os.path.join(config.get_runtime_path(), "channels", '*.json')
channel_language = config.get_setting("channel_language", default="all")
if channel_language =="auto":
@@ -151,16 +145,16 @@ def get_channels_list():
channel_id = os.path.basename(infile)[:-5]
channel_parameters = channeltools.get_channel_parameters(channel_id)
- # No incluir si es un canal inactivo
+ # Do not include if it is an inactive channel
if not channel_parameters["active"]:
continue
- # No incluir si el canal es en un idioma filtrado
+ # Do not include if the channel is in a filtered language
if channel_language != "all" and channel_language not in str(channel_parameters["language"]) \
and "*" not in channel_parameters["language"]:
continue
- # Incluir en cada categoria, si en su configuracion el canal esta activado para mostrar novedades
+ # Include in each category, if in your configuration the channel is activated to show news
for categoria in list_canales:
include_in_newest = config.get_setting("include_in_newest_" + categoria, channel_id)
@@ -267,7 +261,7 @@ def novedades(item):
if any_active and len(list_canales[item.extra])>0:
import math
- # fix float porque la division se hace mal en python 2.x
+ # fix float because division is done poorly in python 2.x
number_of_channels = float(100) / len(list_canales[item.extra])
for index, channel in enumerate(list_canales[item.extra]):
@@ -294,7 +288,7 @@ def novedades(item):
progreso.update(percentage, "", config.get_localized_string(60520) % channel_title)
get_newest(channel_id, item.extra)
- # Modo Multi Thread: esperar q todos los hilos terminen
+ # Multi Thread mode: wait for all threads to finish
if multithread:
pendent = [a for a in threads if a.isAlive()]
t = float(100) / len(pendent)
@@ -326,15 +320,15 @@ def novedades(item):
if mode != 'normal':
result_mode=0
- if result_mode == 0: # Agrupados por contenido
+ if result_mode == 0: # Grouped by content
ret = group_by_content(list_newest)
- elif result_mode == 1: # Agrupados por canales
+ elif result_mode == 1: # Grouped by channels
ret = group_by_channel(list_newest)
- else: # Sin agrupar
+ else: # Ungrouped
ret = no_group(list_newest)
while time.time() - start_time < 2:
- # mostrar cuadro de progreso con el tiempo empleado durante almenos 2 segundos
+ # show progress chart with time spent for at least 2 seconds
time.sleep(0.5)
if mode == 'normal':
progreso.close()
@@ -356,8 +350,8 @@ def get_newest(channel_id, categoria):
global list_newest
global list_newest_tourl
- # Solicitamos las novedades de la categoria (item.extra) buscada en el canal channel
- # Si no existen novedades para esa categoria en el canal devuelve una lista vacia
+ # We request the news of the category (item.extra) searched in the channel channel
+ # If there are no news for that category in the channel, it returns an empty list
try:
puede = True
@@ -381,7 +375,7 @@ def get_newest(channel_id, categoria):
exist=True
else:
cache_node = {}
- #logger.debug('cache node: %s' % cache_node)
+ # logger.debug('cache node: %s' % cache_node)
for item in list_result:
# logger.info("item="+item.tostring())
item.channel = channel_id
@@ -399,11 +393,11 @@ def get_newest(channel_id, categoria):
def get_title(item):
- #support.log("ITEM NEWEST ->", item)
+ # support.log("ITEM NEWEST ->", item)
# item.contentSerieName c'è anche se è un film
if item.contentSerieName and item.contentType != 'movie': # Si es una serie
title = item.contentSerieName
- #title = re.compile("\[.*?\]", re.DOTALL).sub("", item.contentSerieName)
+ # title = re.compile("\[.*?\]", re.DOTALL).sub("", item.contentSerieName)
if not scrapertools.get_season_and_episode(title) and item.contentEpisodeNumber:
# contentSeason non c'è in support
if not item.contentSeason:
@@ -414,14 +408,14 @@ def get_title(item):
if seas:
title = "%s - %s" % (seas, title)
- elif item.contentTitle: # Si es una pelicula con el canal adaptado
+ elif item.contentTitle: # If it is a movie with the adapted channel
title = item.contentTitle
- elif item.contentTitle: # Si el canal no esta adaptado
+ elif item.contentTitle: # If the channel is not adapted
title = item.contentTitle
- else: # Como ultimo recurso
+ else: # As a last resort
title = item.title
- # Limpiamos el titulo de etiquetas de formato anteriores
+ # We clean the title of previous format labels
title = re.compile("\[/*COLO.*?\]", re.DOTALL).sub("", title)
title = re.compile("\[/*B\]", re.DOTALL).sub("", title)
title = re.compile("\[/*I\]", re.DOTALL).sub("", title)
@@ -452,9 +446,9 @@ def no_group(list_result_canal):
global channels_id_name
for i in list_result_canal:
- #support.log("NO GROUP i -> ", i)
+ # support.log("NO GROUP i -> ", i)
canale = channels_id_name[i.channel]
- canale = canale # per differenziarlo dal colore delle altre voci
+ canale = canale # to differentiate it from the color of the other items
i.title = get_title(i) + " [" + canale + "]"
# i.text_color = color3
@@ -471,12 +465,12 @@ def group_by_channel(list_result_canal):
for i in list_result_canal:
if i.channel not in dict_canales:
dict_canales[i.channel] = []
- # Formatear titulo
+ # Format title
i.title = get_title(i)
- # Añadimos el contenido al listado de cada canal
+ # We add the content to the list of each channel
dict_canales[i.channel].append(i)
- # Añadimos el contenido encontrado en la lista list_result
+ # We add the content found in the list_result list
for c in sorted(dict_canales):
itemlist.append(Item(channel="news", title=channels_id_name[c] + ':', text_color=color1, text_bold=True))
@@ -498,10 +492,10 @@ def group_by_content(list_result_canal):
list_result = []
for i in list_result_canal:
- # Formatear titulo
+ # Format title
i.title = get_title(i)
- # Eliminar tildes y otros caracteres especiales para la key
+ # Remove tildes and other special characters for the key
import unicodedata
try:
new_key = i.title.lower().strip().decode("UTF-8")
@@ -511,16 +505,16 @@ def group_by_content(list_result_canal):
new_key = i.title
if new_key in dict_contenidos:
- # Si el contenido ya estaba en el diccionario añadirlo a la lista de opciones...
+ #If the content was already in the dictionary add it to the list of options ...
dict_contenidos[new_key].append(i)
- else: # ...sino añadirlo al diccionario
+ else: # ...but add it to the dictionary
dict_contenidos[new_key] = [i]
- # Añadimos el contenido encontrado en la lista list_result
+ # We add the content found in the list_result list
for v in list(dict_contenidos.values()):
title = v[0].title
if len(v) > 1:
- # Eliminar de la lista de nombres de canales los q esten duplicados
+ # Remove duplicate q's from the channel names list
canales_no_duplicados = []
for i in v:
if i.channel not in canales_no_duplicados:
@@ -622,16 +616,16 @@ def setting_channel(item):
channel_id = os.path.basename(infile)[:-5]
channel_parameters = channeltools.get_channel_parameters(channel_id)
- # No incluir si es un canal inactivo
+ # Do not include if it is an inactive channel
if not channel_parameters["active"]:
continue
- # No incluir si el canal es en un idioma filtrado
+ # Do not include if the channel is in a filtered language
if channel_language != "all" and channel_language not in str(channel_parameters["language"]) \
and "*" not in channel_parameters["language"]:
continue
- # No incluir si en su configuracion el canal no existe 'include_in_newest'
+ # Do not include if the channel does not exist 'include_in_newest' in your configuration
include_in_newest = config.get_setting("include_in_newest_" + item.extra, channel_id)
if include_in_newest is None:
continue
diff --git a/specials/renumbertools.py b/specials/renumbertools.py
deleted file mode 100644
index ddb22080..00000000
--- a/specials/renumbertools.py
+++ /dev/null
@@ -1,1008 +0,0 @@
-# -*- coding: utf-8 -*-
-# --------------------------------------------------------------------------------
-# renumeratetools - se encarga de renumerar episodios
-# --------------------------------------------------------------------------------
-
-#from builtins import str
-import sys
-PY3 = False
-if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
-from builtins import range
-from builtins import object
-
-import os
-
-try:
- import xbmcgui
-except:
- xbmcgui = None
-
-from platformcode import config, logger
-from core import jsontools
-from core.item import Item
-from platformcode import platformtools
-
-TAG_TVSHOW_RENUMERATE = "TVSHOW_RENUMBER"
-TAG_SEASON_EPISODE = "season_episode"
-__channel__ = "renumbertools"
-
-
-def access():
- """
- Devuelve si se puede usar o no renumbertools
- """
- allow = False
-
- if config.is_xbmc():
- allow = True
-
- return allow
-
-
-def context(item):
- """
- Para xbmc/kodi que pueden mostrar el menú contextual, se añade un menu para configuración
- la opción de renumerar, sólo si es para series.
-
- @param item: elemento para obtener la información y ver que contexto añadir
- @type item: item
- @return: lista de opciones a mostrar en el menú contextual
- @rtype: list
- """
-
- # Dependiendo de como sea el contexto lo guardamos y añadimos las opciones de filtertools.
- if isinstance(item.context, str):
- _context = item.context.split("|")
- elif isinstance(item.context, list):
- _context = item.context
- else:
- _context = []
-
- if access():
- dict_data = {"title": config.get_localized_string(70585), "action": "config_item", "channel": "renumbertools"}
- _context.append(dict_data)
-
- return _context
-
-
-def show_option(channel, itemlist):
- if access():
- itemlist.append(Item(channel=__channel__, title="[COLOR yellow]" + config.get_localized_string(70586)+ "[/COLOR]",
- action="load", from_channel=channel))
-
- return itemlist
-
-
-def load(item):
- return mainlist(channel=item.from_channel)
-
-
-def mainlist(channel):
- """
- Muestra una lista de las series renumeradas
-
- :param channel: nombre del canal para obtener las series renumeradas
- :type channel: str
- :return: lista de Item
- :rtype: list[Item]
- """
- logger.info()
- itemlist = []
- dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_RENUMERATE)
-
- idx = 0
- for tvshow in sorted(dict_series):
- tag_color = "0xff008000"
- if idx % 2 == 0:
- tag_color = "blue"
-
- idx += 1
- name = tvshow
- title = config.get_localized_string(70587)+" [COLOR %s][%s][/COLOR]" % (tag_color, name)
-
- itemlist.append(Item(channel=__channel__, action="config_item", title=title, show=name, from_channel=channel))
-
- if len(itemlist) == 0:
- itemlist.append(Item(channel=channel, action="mainlist",
- title=config.get_localized_string(70588) + ' ' + config.get_localized_string(70585)))
-
- return itemlist
-
-
-def config_item(item):
- """
- muestra una serie renumerada para su configuración
-
- :param item: item
- :type item: Item
- """
- logger.info("item %s" % item.tostring("\n"))
-
- dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_RENUMERATE)
- data = dict_series.get(item.show, {})
-
- if data:
- data = data.get(TAG_SEASON_EPISODE, [])
-
- ventana = RenumberWindow(show=item.show, channel=item.from_channel, data=data)
- del ventana
- else:
- # tenemos información y devolvemos los datos añadidos para que se muestre en la ventana
- if data:
- return add_season(data)
- # es la primera vez que se añaden datos (usando menú contextual) por lo que no devolvemos nada
- # para evitar error al listar los items
- else:
- data = add_season(data)
- write_data(item.from_channel, item.show, data)
-
-
-def numbered_for_tratk(channel, show, season, episode):
- """
- Devuelve la temporada y episodio convertido para que se marque correctamente en tratk.tv
-
- @param channel: Nombre del canal
- @type channel: str
- @param show: Nombre de la serie a comprobar
- @type show: str
- @param season: Temporada que devuelve el scrapper
- @type season: int
- @param episode: Episodio que devuelve el scrapper
- @type episode: int
- @return: season, episode
- @rtype: int, int
- """
- logger.info()
-
- if access():
- show = show.lower()
-
- new_season = season
- new_episode = episode
- dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_RENUMERATE)
-
- # ponemos en minusculas el key, ya que previamente hemos hecho lo mismo con show.
- for key in list(dict_series.keys()):
- new_key = key.lower()
- if new_key != key:
- dict_series[new_key] = dict_series[key]
- del dict_series[key]
-
- if show in dict_series:
- logger.debug(config.get_localized_string(70589) + " %s" % dict_series[show])
-
- if len(dict_series[show]['season_episode']) > 1:
- for row in dict_series[show]['season_episode']:
-
- if new_episode > row[1]:
- new_episode -= row[1]
- new_season = row[0]
- break
-
- else:
- new_season = dict_series[show]['season_episode'][0][0]
- new_episode += dict_series[show]['season_episode'][0][1]
-
- logger.debug("%s:%s" % (new_season, new_episode))
- else:
- # no se tiene acceso se devuelven los datos.
- new_season = season
- new_episode = episode
-
- return new_season, new_episode
-
-
-def borrar(channel, show):
- logger.info()
- heading = config.get_localized_string(70590)
- line1 = config.get_localized_string(70591) + ' [COLOR blue]' + show.strip() + '[/COLOR], ' + config.get_localized_string(70592)
-
- if platformtools.dialog_yesno(heading, line1) == 1:
- dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_RENUMERATE)
- dict_series.pop(show, None)
-
- result, json_data = jsontools.update_node(dict_series, channel, TAG_TVSHOW_RENUMERATE)
-
- if result:
- message = config.get_localized_string(60444)
- else:
- message = config.get_localized_string(70593)
-
- heading = show.strip()
- platformtools.dialog_notification(heading, message)
-
-
-def add_season(data=None):
- logger.debug("data %s" % data)
- heading = config.get_localized_string(70594)
- # default = 2
- # se reordena la lista
- list_season_episode = data
- if list_season_episode:
- list_season_episode.sort(key=lambda el: int(el[0]), reverse=False)
-
- # if list_season_episode:
- # # mostrar temporada + 1 de la lista
- # # TODO buscar la primera posicion libre
- # default = list_season_episode[0][0]+1
-
- season = platformtools.dialog_numeric(0, heading) # , str(default))
- for element in list_season_episode:
- if int(season) == element[0]:
- platformtools.dialog_notification(config.get_localized_string(70595), config.get_localized_string(70596))
- return
-
- # si hemos insertado un valor en la temporada
- if season != "" and int(season) > 0:
- heading = config.get_localized_string(70597)
- # default = 0
- # if list_season_episode:
- # for e in list_season_episode:
- # # mostrar suma episodios de la lista
- # # sumar hasta el indice del primer libre encontrado
- # default += e[1]
- episode = platformtools.dialog_numeric(0, heading) # , str(default))
-
- # si hemos insertado un valor en el episodio
- if episode != "":
- if list_season_episode:
- list_season_episode.insert(0, [int(season), int(episode)])
- new_list_season_episode = list_season_episode[:]
- return new_list_season_episode
- else:
- return [[int(season), int(episode)]]
-
-
-def write_data(channel, show, data):
- # OBTENEMOS LOS DATOS DEL JSON
- dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_RENUMERATE)
- tvshow = show.strip()
- list_season_episode = dict_series.get(tvshow, {}).get(TAG_SEASON_EPISODE, [])
- logger.debug("data %s" % list_season_episode)
-
- if data:
- # cambiamos el orden para que se vea en orden descendente y usarse bien en el _data.json
- data.sort(key=lambda el: int(el[0]), reverse=True)
- dict_renumerate = {TAG_SEASON_EPISODE: data}
-
- dict_series[tvshow] = dict_renumerate
- else:
- # hemos borrado todos los elementos, por lo que se borra la serie del fichero
- dict_series.pop(tvshow, None)
-
- result, json_data = jsontools.update_node(dict_series, channel, TAG_TVSHOW_RENUMERATE)
-
- if result:
- if data:
- message = config.get_localized_string(60446)
- else:
- message = config.get_localized_string(60444)
- else:
- message = config.get_localized_string(70593)
-
- heading = show.strip()
- platformtools.dialog_notification(heading, message)
-
-
-if xbmcgui:
-
- # Align
- ALIGN_LEFT = 0
- ALIGN_RIGHT = 1
- ALIGN_CENTER_X = 2
- ALIGN_CENTER_Y = 4
- ALIGN_CENTER = 6
- ALIGN_TRUNCATED = 8
- ALIGN_JUSTIFY = 10
-
- # button ids
- ID_BUTTON_CLOSE = 3003
- ID_BUTTON_ADD_SEASON = 3008
- ID_BUTTON_INFO = 3009
- ID_CHECK_UPDATE_INTERNET = 3010
- ID_BUTTON_OK = 3012
- ID_BUTTON_CANCEL = 3013
- ID_BUTTON_DELETE = 3014
-
-
- class RenumberWindow(xbmcgui.WindowDialog):
- def __init__(self, *args, **kwargs):
- logger.debug()
-
- #### Compatibilidad con Kodi 18 ####
- if config.get_platform(True)['num_version'] < 18:
- if xbmcgui.__version__ == "1.2":
- self.setCoordinateResolution(1)
- else:
- self.setCoordinateResolution(5)
-
- self.show = kwargs.get("show")
- self.channel = kwargs.get("channel")
- self.data = kwargs.get("data")
- self.init = True
-
- self.mediapath = os.path.join(config.get_runtime_path(), 'resources', 'skins', 'Default', 'media')
- self.font = "font12"
-
- window_bg = xbmcgui.ControlImage(320, 130, 600, 440,
- os.path.join(self.mediapath, 'Windows', 'DialogBack.png'))
- self.addControl(window_bg)
-
- header_bg = xbmcgui.ControlImage(window_bg.getX(), window_bg.getY() + 8, window_bg.getWidth(), 35,
- os.path.join(self.mediapath, 'Windows', 'dialogheader.png'))
- self.addControl(header_bg)
-
- btn_close_w = 64
- self.btn_close = xbmcgui.ControlButton(window_bg.getX() + window_bg.getWidth() - btn_close_w - 13,
- header_bg.getY() + 6, btn_close_w, 30, '',
- focusTexture=os.path.join(self.mediapath, 'Controls',
- 'DialogCloseButton-focus.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'DialogCloseButton.png'))
- self.addControl(self.btn_close)
-
- header_title_x = window_bg.getX() + 20
- header_title = xbmcgui.ControlFadeLabel(header_title_x, header_bg.getY() + 5, self.btn_close.getX() -
- header_title_x, 30, font="font12_title", textColor="0xFFFFA500",
- _alignment=ALIGN_CENTER)
- self.addControl(header_title)
- header_title.addLabel(self.show)
-
- self.controls_bg = xbmcgui.ControlImage(window_bg.getX() + 20, header_bg.getY() + header_bg.getHeight() + 6,
- 562, 260,
- os.path.join(self.mediapath, 'Windows', 'BackControls.png'))
- self.addControl(self.controls_bg)
-
- self.scroll_bg = xbmcgui.ControlImage(window_bg.getX() + window_bg.getWidth() - 25, self.controls_bg.getY(),
- 10,
- self.controls_bg.getHeight(), os.path.join(self.mediapath, 'Controls',
- 'ScrollBack.png'))
- self.addControl(self.scroll_bg)
- self.scroll_bg.setVisible(False)
-
- self.scroll2_bg = xbmcgui.ControlImage(window_bg.getX() + window_bg.getWidth() - 25,
- self.controls_bg.getY(),
- 10, self.controls_bg.getHeight(), os.path.join(self.mediapath,
- 'Controls',
- 'ScrollBar.png'))
- self.addControl(self.scroll2_bg)
- self.scroll2_bg.setVisible(False)
-
- btn_add_season = xbmcgui.ControlButton(window_bg.getX() + 20, self.controls_bg.getY() +
- self.controls_bg.getHeight() + 14, 165, 30, config.get_localized_string(70600),
- font=self.font, focusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKey.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKeyNF.png'),
- alignment=ALIGN_CENTER)
- self.addControl(btn_add_season)
-
- self.btn_info = xbmcgui.ControlButton(window_bg.getX() + 210, btn_add_season.getY(), 120, 30, config.get_localized_string(60348),
- font=self.font, focusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKey.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKeyNF.png'),
- alignment=ALIGN_CENTER)
- self.addControl(self.btn_info)
-
- check_update_internet_w = 235
- # Versiones antiguas no admite algunas texturas
- if xbmcgui.__version__ in ["1.2", "2.0"]:
- self.check_update_internet = xbmcgui.ControlRadioButton(
- window_bg.getX() + window_bg.getWidth() - check_update_internet_w - 20, btn_add_season.getY() - 3,
- check_update_internet_w, 34, config.get_localized_string(70601), font=self.font,
- focusTexture=os.path.join(self.mediapath, 'Controls', 'MenuItemFO.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls', 'MenuItemNF.png'))
- else:
- self.check_update_internet = xbmcgui.ControlRadioButton(
- window_bg.getX() + window_bg.getWidth() - check_update_internet_w - 20, btn_add_season.getY() - 3,
- check_update_internet_w, 34, config.get_localized_string(70601), font=self.font,
- focusTexture=os.path.join(self.mediapath, 'Controls', 'MenuItemFO.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls', 'MenuItemNF.png'),
- focusOnTexture=os.path.join(self.mediapath, 'Controls', 'radiobutton-focus.png'),
- noFocusOnTexture=os.path.join(self.mediapath, 'Controls', 'radiobutton-focus.png'),
- focusOffTexture=os.path.join(self.mediapath, 'Controls', 'radiobutton-nofocus.png'),
- noFocusOffTexture=os.path.join(self.mediapath, 'Controls', 'radiobutton-nofocus.png'))
-
- self.addControl(self.check_update_internet)
- self.check_update_internet.setEnabled(False)
-
- hb_bg = xbmcgui.ControlImage(window_bg.getX() + 20, btn_add_season.getY() + btn_add_season.getHeight() + 13,
- window_bg.getWidth() - 40, 2,
- os.path.join(self.mediapath, 'Controls', 'ScrollBack.png'))
- self.addControl(hb_bg)
-
- self.btn_ok = xbmcgui.ControlButton(window_bg.getX() + 68, hb_bg.getY() + hb_bg.getHeight() + 13, 120, 30,
- 'OK', font=self.font,
- focusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKey.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKeyNF.png'),
- alignment=ALIGN_CENTER)
- self.addControl(self.btn_ok)
-
- self.btn_cancel = xbmcgui.ControlButton(self.btn_info.getX() + 30, self.btn_ok.getY(), 120, 30, config.get_localized_string(70002),
- font=self.font,
- focusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKey.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKeyNF.png'),
- alignment=ALIGN_CENTER)
- self.addControl(self.btn_cancel)
-
- self.btn_delete = xbmcgui.ControlButton(self.btn_cancel.getX() + self.btn_cancel.getWidth() + 50,
- self.btn_ok.getY(), 120, 30, config.get_localized_string(60437), font=self.font,
- focusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKey.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKeyNF.png'),
- alignment=ALIGN_CENTER)
- self.addControl(self.btn_delete)
-
- self.controls = []
- self.onInit()
- self.setFocus(self.controls[0].edit_season)
- self.doModal()
-
- def onInit(self, *args, **kwargs):
- try:
- # listado temporada / episodios
- pos_y = self.controls_bg.getY() + 10
-
- # eliminamos los componentes al repintar la ventana
- for linea in self.controls:
- self.removeControls(linea.list_elements())
-
- # mostramos el scroll si hay más de 5 elementos
- if len(self.data) > 5:
- self.controls_bg.setWidth(545)
- self.scroll_bg.setVisible(True)
- self.scroll2_bg.setVisible(True)
- else:
- self.controls_bg.setWidth(562)
- self.scroll_bg.setVisible(False)
- self.scroll2_bg.setVisible(False)
-
- self.controls = []
- # cambiamos el orden para que se vea en orden ascendente
- self.data.sort(key=lambda el: int(el[0]), reverse=False)
-
- for index, e in enumerate(self.data):
- pos_x = self.controls_bg.getX() + 15
- label_season_w = 100
- label_season = xbmcgui.ControlLabel(pos_x, pos_y + 3, label_season_w, 34,
- config.get_localized_string(60385), font=self.font, textColor="0xFF2E64FE")
- self.addControl(label_season)
- label_season.setVisible(False)
-
- pos_x += label_season_w + 5
-
- # TODO mirar retro-compatilibidad
- # if xbmcgui.ControlEdit == ControlEdit:
- # edit_season = xbmcgui.ControlEdit(0, 0, 0, 0, '', font=self.font, isPassword=False,
- # textColor='',
- # focusTexture=os.path.join(self.mediapath, 'Controls',
- # 'MenuItemFO.png'),
- # noFocusTexture=os.path.join(self.mediapath, 'Controls',
- # 'MenuItemNF.png'), window=self)
- # else:
-
- # control bugeado se tiene que usar metodos sets para que se cree correctamente.
- edit_season = xbmcgui.ControlEdit(0, 0, 0, 0, "", self.font, "", '', 4, isPassword=False,
- focusTexture=os.path.join(self.mediapath, 'Controls',
- 'MenuItemFO.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'MenuItemNF.png'))
- self.addControl(edit_season)
- edit_season.setText(str(e[0]))
- # edit_season.setLabel("Temporada:", font=self.font, textColor="0xFF2E64FE")
- edit_season.setPosition(pos_x, pos_y - 2)
- edit_season.setWidth(25)
- edit_season.setHeight(35)
- edit_season.setVisible(False)
-
- label_episode_w = 90
- pos_x += edit_season.getWidth() + 60
- label_episode = xbmcgui.ControlLabel(pos_x, pos_y + 3, label_episode_w, 34, config.get_localized_string(70598),
- font=self.font, textColor="0xFF2E64FE")
- self.addControl(label_episode)
- label_episode.setVisible(False)
-
- pos_x += label_episode_w + 5
- # control bugeado se tiene que usar metodos sets para que se cree correctamente.
- edit_episode = xbmcgui.ControlEdit(0, 0, 0, 0, "", self.font, "", '', 4, isPassword=False,
- focusTexture=os.path.join(self.mediapath, 'Controls',
- 'MenuItemFO.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'MenuItemNF.png'))
- self.addControl(edit_episode)
- edit_episode.setText(str(e[1]))
- # edit_episode.setLabel("Episodios:", font=self.font, textColor="0xFF2E64FE")
- edit_episode.setPosition(pos_x, pos_y - 2)
- edit_episode.setWidth(40)
- edit_episode.setHeight(35)
- edit_episode.setVisible(False)
-
- btn_delete_season_w = 120
- btn_delete_season = xbmcgui.ControlButton(self.controls_bg.getX() + self.controls_bg.getWidth() -
- btn_delete_season_w - 14, pos_y, btn_delete_season_w, 30,
- config.get_localized_string(70599), font=self.font,
- focusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKey.png'),
- noFocusTexture=os.path.join(self.mediapath, 'Controls',
- 'KeyboardKeyNF.png'),
- alignment=ALIGN_CENTER)
- self.addControl(btn_delete_season)
- btn_delete_season.setVisible(False)
-
- hb_bg = xbmcgui.ControlImage(self.controls_bg.getX() + 10, pos_y + 40,
- self.controls_bg.getWidth() - 20,
- 2, os.path.join(self.mediapath, 'Controls', 'ScrollBack.png'))
- self.addControl(hb_bg)
- hb_bg.setVisible(False)
-
- group = ControlGroup(label_season=label_season, edit_season=edit_season,
- label_episode=label_episode,
- edit_episode=edit_episode, btn_delete_season=btn_delete_season, hb=hb_bg)
-
- pos_y += 50
-
- if index < 5:
- group.set_visible(True)
-
- self.controls.append(group)
-
- if len(self.data) > 5:
- self.move_scroll()
-
- except Exception as Ex:
- logger.error("HA HABIDO UNA HOSTIA %s" % Ex)
-
- # def onClick(self, control_id):
- # pass
- #
- # def onFocus(self, control_id):
- # pass
-
- def onControl(self, control):
- # logger.debug("%s" % control.getId())
- control_id = control.getId()
-
- if control_id == ID_BUTTON_OK:
- write_data(self.channel, self.show, self.data)
- self.close()
- if control_id in [ID_BUTTON_CLOSE, ID_BUTTON_CANCEL]:
- self.close()
- elif control_id == ID_BUTTON_DELETE:
- self.close()
- borrar(self.channel, self.show)
- elif control_id == ID_BUTTON_ADD_SEASON:
- # logger.debug("data que enviamos: {}".format(self.data))
- data = add_season(self.data)
- if data:
- self.data = data
- # logger.debug("data que recibimos: {}".format(self.data))
- self.onInit()
-
- # si hay más de 5 elementos movemos el scroll
- if len(self.data) > 5:
- self.scroll(len(self.data) - 2, 1)
- self.move_scroll()
-
- elif control_id == ID_BUTTON_INFO:
- self.method_info()
- else:
- for x, grupo in enumerate(self.controls):
- if control_id == self.controls[x].btn_delete_season.getId():
- # logger.debug("A data %s" % self.data)
- self.removeControls(self.controls[x].list_elements())
- del self.controls[x]
- del self.data[x]
- # logger.debug("D data %s" % self.data)
- self.onInit()
-
- return
-
- def onAction(self, action):
- # logger.debug("%s" % action.getId())
- # logger.debug("focus %s" % self.getFocusId())
- # Obtenemos el foco
- focus = self.getFocusId()
-
- action = action.getId()
- # Flecha izquierda
- if action == xbmcgui.ACTION_MOVE_LEFT:
- # Si el foco no está en ninguno de los 6 botones inferiores, y esta en un "list" cambiamos el valor
- if focus not in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET,
- ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]:
-
- # Localizamos en el listado de controles el control que tiene el focus
- # todo mirar tema del cursor en el valor al desplazar lateralmente
- for x, linea in enumerate(self.controls):
- if focus == linea.edit_season.getId():
- return self.setFocus(self.controls[x].btn_delete_season)
- elif focus == linea.edit_episode.getId():
- return self.setFocus(self.controls[x].edit_season)
- elif focus == linea.btn_delete_season.getId():
- return self.setFocus(self.controls[x].edit_episode)
-
- # Si el foco está en alguno de los 6 botones inferiores, movemos al siguiente
- else:
- if focus in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET]:
- if focus == ID_BUTTON_ADD_SEASON:
- self.setFocusId(ID_BUTTON_INFO)
- # TODO cambiar cuando se habilite la opcion de actualizar por internet
- # self.setFocusId(ID_CHECK_UPDATE_INTERNET)
- elif focus == ID_BUTTON_INFO:
- self.setFocusId(ID_BUTTON_ADD_SEASON)
- elif focus == ID_CHECK_UPDATE_INTERNET:
- self.setFocusId(ID_BUTTON_INFO)
-
- elif focus in [ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]:
- if focus == ID_BUTTON_OK:
- self.setFocusId(ID_BUTTON_DELETE)
- elif focus == ID_BUTTON_CANCEL:
- self.setFocusId(ID_BUTTON_OK)
- elif focus == ID_BUTTON_DELETE:
- self.setFocusId(ID_BUTTON_CANCEL)
-
- # Flecha derecha
- elif action == xbmcgui.ACTION_MOVE_RIGHT:
- # Si el foco no está en ninguno de los 6 botones inferiores, y esta en un "list" cambiamos el valor
- if focus not in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET,
- ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]:
-
- # Localizamos en el listado de controles el control que tiene el focus
- # todo mirar tema del cursor en el valor al desplazar lateralmente
- for x, linea in enumerate(self.controls):
- if focus == linea.edit_season.getId():
- return self.setFocus(self.controls[x].edit_episode)
- elif focus == linea.edit_episode.getId():
- return self.setFocus(self.controls[x].btn_delete_season)
- elif focus == linea.btn_delete_season.getId():
- return self.setFocus(self.controls[x].edit_season)
-
- # Si el foco está en alguno de los 6 botones inferiores, movemos al siguiente
- else:
- if focus in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET]:
- if focus == ID_BUTTON_ADD_SEASON:
- self.setFocusId(ID_BUTTON_INFO)
- if focus == ID_BUTTON_INFO:
- self.setFocusId(ID_BUTTON_ADD_SEASON)
- # TODO cambiar cuando se habilite la opcion de actualizar por internet
- # self.setFocusId(ID_CHECK_UPDATE_INTERNET)
- if focus == ID_CHECK_UPDATE_INTERNET:
- self.setFocusId(ID_BUTTON_OK)
-
- elif focus in [ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]:
- if focus == ID_BUTTON_OK:
- self.setFocusId(ID_BUTTON_CANCEL)
- if focus == ID_BUTTON_CANCEL:
- self.setFocusId(ID_BUTTON_DELETE)
- if focus == ID_BUTTON_DELETE:
- self.setFocusId(ID_BUTTON_OK)
-
- # Flecha arriba
- elif action == xbmcgui.ACTION_MOVE_UP:
- self.move_up(focus)
- # Flecha abajo
- elif action == xbmcgui.ACTION_MOVE_DOWN:
- self.move_down(focus)
- # scroll up
- elif action == xbmcgui.ACTION_MOUSE_WHEEL_UP:
- self.move_up(focus)
- # scroll down
- elif action == xbmcgui.ACTION_MOUSE_WHEEL_DOWN:
- self.move_down(focus)
-
- # ACTION_PAGE_DOWN = 6
- # ACTION_PAGE_UP = 5
-
- # Menú previo o Atrás
- elif action in [xbmcgui.ACTION_PREVIOUS_MENU, xbmcgui.ACTION_NAV_BACK]:
- self.close()
-
- def move_down(self, focus):
- # logger.debug("focus " + str(focus))
- # Si el foco está en uno de los tres botones medios, bajamos el foco a la otra linea de botones
- if focus in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET]:
- if focus == ID_BUTTON_ADD_SEASON:
- self.setFocusId(ID_BUTTON_OK)
- elif focus == ID_BUTTON_INFO:
- self.setFocusId(ID_BUTTON_CANCEL)
- elif focus == ID_CHECK_UPDATE_INTERNET:
- self.setFocusId(ID_BUTTON_DELETE)
- # Si el foco está en uno de los tres botones inferiores, subimos el foco al primer control del listado
- elif focus in [ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]:
- first_visible = 0
- for x, linea in enumerate(self.controls):
- if linea.get_visible():
- first_visible = x
- break
-
- if focus == ID_BUTTON_OK:
- self.setFocus(self.controls[first_visible].edit_season)
- elif focus == ID_BUTTON_CANCEL:
- self.setFocus(self.controls[first_visible].edit_episode)
- elif focus == ID_BUTTON_DELETE:
- self.setFocus(self.controls[first_visible].btn_delete_season)
- # nos movemos entre los elementos del listado
- else:
- # Localizamos en el listado de controles el control que tiene el focus
- for x, linea in enumerate(self.controls):
- if focus == linea.edit_season.getId():
- if x + 1 < len(self.controls):
- if not self.controls[x + 1].get_visible():
- self.scroll(x, 1)
-
- return self.setFocus(self.controls[x + 1].edit_season)
- else:
- return self.setFocusId(ID_BUTTON_ADD_SEASON)
- elif focus == linea.edit_episode.getId():
- if x + 1 < len(self.controls):
- if not self.controls[x + 1].get_visible():
- self.scroll(x, 1)
-
- return self.setFocus(self.controls[x + 1].edit_episode)
- else:
- self.setFocusId(ID_BUTTON_INFO)
- elif focus == linea.btn_delete_season.getId():
- if x + 1 < len(self.controls):
- if not self.controls[x + 1].get_visible():
- self.scroll(x, 1)
-
- return self.setFocus(self.controls[x + 1].btn_delete_season)
- else:
- return self.setFocusId(ID_BUTTON_INFO)
- # TODO cambiar cuando se habilite la opcion de actualizar por internet
- # return self.setFocusId(ID_CHECK_UPDATE_INTERNET)
-
- def move_up(self, focus):
- # Si el foco está en uno de los tres botones medios, subimos el foco al último control del listado
- if focus in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET]:
- last_visible = 0
- for x, linea in reversed(list(enumerate(self.controls))):
- if linea.get_visible():
- last_visible = x
- break
-
- if focus == ID_BUTTON_ADD_SEASON:
- self.setFocus(self.controls[last_visible].edit_season)
- elif focus == ID_BUTTON_INFO:
- self.setFocus(self.controls[last_visible].edit_episode)
- elif focus == ID_CHECK_UPDATE_INTERNET:
- self.setFocus(self.controls[last_visible].btn_delete_season)
- # Si el foco está en uno de los tres botones inferiores, subimos el foco a la otra linea de botones
- elif focus in [ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]:
- if focus == ID_BUTTON_OK:
- self.setFocusId(ID_BUTTON_ADD_SEASON)
- elif focus == ID_BUTTON_CANCEL:
- self.setFocusId(ID_BUTTON_INFO)
- elif focus == ID_BUTTON_DELETE:
- self.setFocusId(ID_BUTTON_INFO)
- # TODO cambiar cuando se habilite la opcion de actualizar por internet
- # self.setFocusId(ID_CHECK_UPDATE_INTERNET)
- # nos movemos entre los elementos del listado
- else:
- # Localizamos en el listado de controles el control que tiene el focus
- for x, linea in enumerate(self.controls):
- if focus == linea.edit_season.getId():
- if x > 0:
- if not self.controls[x - 1].get_visible():
- self.scroll(x, -1)
-
- return self.setFocus(self.controls[x - 1].edit_season)
- else:
- return self.setFocusId(ID_BUTTON_OK)
- elif focus == linea.edit_episode.getId():
- if x > 0:
- if not self.controls[x - 1].get_visible():
- self.scroll(x, -1)
-
- return self.setFocus(self.controls[x - 1].edit_episode)
- else:
- self.setFocusId(ID_BUTTON_CANCEL)
- elif focus == linea.btn_delete_season.getId():
- if x > 0:
- if not self.controls[x - 1].get_visible():
- self.scroll(x, -1)
-
- return self.setFocus(self.controls[x - 1].btn_delete_season)
- else:
- return self.setFocusId(ID_BUTTON_DELETE)
- # TODO cambiar cuando se habilite la opcion de actualizar por internet
- # return self.setFocusId(ID_CHECK_UPDATE_INTERNET)
-
- def scroll(self, position, movement):
- try:
- for index, group in enumerate(self.controls):
- # ponemos todos los elementos como no visibles
- group.set_visible(False)
-
- if movement > 0:
- pos_fin = position + movement + 1
- pos_inicio = pos_fin - 5
- else:
- pos_inicio = position + movement
- pos_fin = pos_inicio + 5
-
- # logger.debug("position {}, movement {}, pos_inicio{}, pos_fin{}, self.data.length{}".
- # format(position, movement, pos_inicio, pos_fin, len(self.data)))
- pos_y = self.controls_bg.getY() + 10
- for i in range(pos_inicio, pos_fin):
- pos_x = self.controls_bg.getX() + 15
-
- self.controls[i].label_season.setPosition(pos_x, pos_y + 3)
-
- pos_x += self.controls[i].label_season.getWidth() + 5
- self.controls[i].edit_season.setPosition(pos_x, pos_y - 2)
-
- pos_x += self.controls[i].edit_season.getWidth() + 60
- self.controls[i].label_episode.setPosition(pos_x, pos_y + 3)
-
- pos_x += self.controls[i].label_episode.getWidth() + 5
- self.controls[i].edit_episode.setPosition(pos_x, pos_y - 2)
-
- self.controls[i].btn_delete_season.setPosition(
- self.controls_bg.getX() + self.controls_bg.getWidth() -
- self.controls[i].btn_delete_season.getWidth() - 14,
- pos_y)
-
- self.controls[i].hb.setPosition(self.controls_bg.getX() + 10, pos_y + 40)
-
- pos_y += 50
-
- # logger.debug("ponemos como True %s" % i)
- self.controls[i].set_visible(True)
-
- self.move_scroll()
-
- except Exception as Ex:
- logger.error("HA HABIDO UNA HOSTIA %s" % Ex)
-
- def move_scroll(self):
- visible_controls = [group for group in self.controls if group.get_visible() == True]
- hidden_controls = [group for group in self.controls if group.get_visible() == False]
- scroll_position = self.controls.index(visible_controls[0])
- scrollbar_height = self.scroll_bg.getHeight() - (len(hidden_controls) * 10)
- scrollbar_y = self.scroll_bg.getPosition()[1] + (scroll_position * 10)
- self.scroll2_bg.setPosition(self.scroll_bg.getPosition()[0], scrollbar_y)
- self.scroll2_bg.setHeight(scrollbar_height)
-
- @staticmethod
- def method_info():
- title = config.get_localized_string(60348)
- # text = "La primera temporada que se añade siempre empieza en \"0\" episodios, la segunda temporada que se "
- # text += "añade empieza en el número total de episodios de la primera temporada, la tercera temporada será "
- # text += "la suma de los episodios de las temporadas previas y así sucesivamente.\n"
- # text += "[COLOR blue]\nEjemplo de serie divida en varias temporadas:\n"
- # text += "\nFairy Tail:\n"
- # text += " - SEASON 1: EPISODE 48 --> [season 1, episode: 0]\n"
- # text += " - SEASON 2: EPISODE 48 --> [season 2, episode: 48]\n"
- # text += " - SEASON 3: EPISODE 54 --> [season 3, episode: 96 ([48=season2] + [48=season1])]\n"
- # text += " - SEASON 4: EPISODE 175 --> [season 4: episode: 150 ([54=season3] + [48=season2] + [48=season3" \
- # "])][/COLOR]\n"
- # text += "[COLOR green]\nEjemplo de serie que continua en la temporada de la original:\n"
- # text += "\nFate/Zero 2nd Season:\n"
- # text += " - SEASON 1: EPISODE 12 --> [season 1, episode: 13][/COLOR]\n"
-
- # text += "[COLOR blue]\nEjemplo de serie que es la segunda temporada de la original:\n"
- # text += "\nFate/kaleid liner Prisma☆Illya 2wei!:\n"
- # text += " - SEASON 1: EPISODE 12 --> [season 2, episode: 0][/COLOR]\n"
- text = config.get_localized_string(70602)
-
- return TextBox("DialogTextViewer.xml", os.getcwd(), "Default", title=title, text=text)
-
-
- class ControlGroup(object):
- """
- conjunto de controles, son los elementos que se muestra por línea de una lista.
- """
-
- def __init__(self, label_season, edit_season, label_episode, edit_episode, btn_delete_season, hb):
- self.visible = False
- self.label_season = label_season
- self.edit_season = edit_season
- self.label_episode = label_episode
- self.edit_episode = edit_episode
- self.btn_delete_season = btn_delete_season
- self.hb = hb
-
- def list_elements(self):
- return [self.label_season, self.edit_season, self.label_episode, self.edit_episode, self.btn_delete_season,
- self.hb]
-
- def get_visible(self):
- return self.visible
-
- def set_visible(self, visible):
- self.visible = visible
- self.label_season.setVisible(visible)
- self.edit_season.setVisible(visible)
- self.label_episode.setVisible(visible)
- self.edit_episode.setVisible(visible)
- self.btn_delete_season.setVisible(visible)
- self.hb.setVisible(visible)
-
-
- class TextBox(xbmcgui.WindowXMLDialog):
- """ Create a skinned textbox window """
-
- def __init__(self, *args, **kwargs):
- self.title = kwargs.get('title')
- self.text = kwargs.get('text')
- self.doModal()
-
- def onInit(self):
- try:
- self.getControl(5).setText(self.text)
- self.getControl(1).setLabel(self.title)
- except:
- pass
-
- def onClick(self, control_id):
- pass
-
- def onFocus(self, control_id):
- pass
-
- def onAction(self, action):
- self.close()
-
- # TODO mirar retro-compatiblidad
- # class ControlEdit(xbmcgui.ControlButton):
- # def __new__(self, *args, **kwargs):
- # del kwargs["isPassword"]
- # del kwargs["window"]
- # args = list(args)
- # return xbmcgui.ControlButton.__new__(self, *args, **kwargs)
- #
- # def __init__(self, *args, **kwargs):
- # self.isPassword = kwargs["isPassword"]
- # self.window = kwargs["window"]
- # self.label = ""
- # self.text = ""
- # self.textControl = xbmcgui.ControlLabel(self.getX(), self.getY(), self.getWidth(), self.getHeight(),
- # self.text,
- # font=kwargs["font"], textColor=kwargs["textColor"], alignment=4 | 1)
- # self.window.addControl(self.textControl)
- #
- # def setLabel(self, val):
- # self.label = val
- # xbmcgui.ControlButton.setLabel(self, val)
- #
- # def getX(self):
- # return xbmcgui.ControlButton.getPosition(self)[0]
- #
- # def getY(self):
- # return xbmcgui.ControlButton.getPosition(self)[1]
- #
- # def setEnabled(self, e):
- # xbmcgui.ControlButton.setEnabled(self, e)
- # self.textControl.setEnabled(e)
- #
- # def setWidth(self, w):
- # xbmcgui.ControlButton.setWidth(self, w)
- # self.textControl.setWidth(w / 2)
- #
- # def setHeight(self, w):
- # xbmcgui.ControlButton.setHeight(self, w)
- # self.textControl.setHeight(w)
- #
- # def setPosition(self, x, y):
- # xbmcgui.ControlButton.setPosition(self, x, y)
- # self.textControl.setPosition(x + self.getWidth() / 2, y)
- #
- # def setText(self, text):
- # self.text = text
- # if self.isPassword:
- # self.textControl.setLabel("*" * len(self.text))
- # else:
- # self.textControl.setLabel(self.text)
- #
- # def getText(self):
- # return self.text
- #
- #
- # if not hasattr(xbmcgui, "ControlEdit"):
- # xbmcgui.ControlEdit = ControlEdit
diff --git a/specials/search.py b/specials/search.py
index 09169daa..0b2fa194 100644
--- a/specials/search.py
+++ b/specials/search.py
@@ -198,25 +198,56 @@ def channel_search(item):
cnt = 0
progress = platformtools.dialog_progress(config.get_localized_string(30993) % item.title, config.get_localized_string(70744) % len(channel_list),
- str(searching_titles))
+ ', '.join(searching_titles))
config.set_setting('tmdb_active', False)
+ search_action_list = []
+ module_dict = {}
+ for ch in channel_list:
+ try:
+ module = __import__('channels.%s' % ch, fromlist=["channels.%s" % ch])
+ mainlist = getattr(module, 'mainlist')(Item(channel=ch, global_search=True))
+
+ module_dict[ch] = module
+ search_action_list.extend([elem for elem in mainlist if
+ elem.action == "search" and (mode == 'all' or elem.contentType == mode)])
+ if progress.iscanceled():
+ return []
+ except:
+ import traceback
+ logger.error('error importing/getting search items of ' + ch)
+ logger.error(traceback.format_exc())
+
+ total_search_actions = len(search_action_list)
with futures.ThreadPoolExecutor(max_workers=set_workers()) as executor:
- c_results = [executor.submit(get_channel_results, ch, item) for ch in channel_list]
+ c_results = []
+ for search_action in search_action_list:
+ c_results.append(executor.submit(get_channel_results, item, module_dict, search_action))
+ if progress.iscanceled():
+ break
for res in futures.as_completed(c_results):
- cnt += 1
- finished = res.result()[0]
+ search_action = res.result()[0]
+ channel = search_action.channel
if res.result()[1]:
- ch_list[res.result()[0]] = res.result()[1]
+ if channel not in ch_list:
+ ch_list[channel] = []
+ ch_list[channel].extend(res.result()[1])
if progress.iscanceled():
break
- if finished in searching:
- searching_titles.remove(searching_titles[searching.index(finished)])
- searching.remove(finished)
- progress.update(old_div((cnt * 100), len(channel_list)), config.get_localized_string(70744) % str(len(channel_list) - cnt),
- str(searching_titles))
+
+ search_action_list.remove(search_action)
+ # if no action of this channel remains
+ for it in search_action_list:
+ if it.channel == channel:
+ break
+ else:
+ cnt += 1
+ searching_titles.remove(searching_titles[searching.index(channel)])
+ searching.remove(channel)
+ progress.update(old_div(((total_search_actions - len(search_action_list)) * 100), total_search_actions), config.get_localized_string(70744) % str(len(channel_list) - cnt),
+ ', '.join(searching_titles))
progress.close()
@@ -225,7 +256,7 @@ def channel_search(item):
config.get_localized_string(60293))
config.set_setting('tmdb_active', True)
- res_count = 0
+ # res_count = 0
for key, value in ch_list.items():
ch_name = channel_titles[channel_list.index(key)]
grouped = list()
@@ -235,12 +266,11 @@ def channel_search(item):
if len(value) == 1:
if not value[0].action or config.get_localized_string(70006).lower() in value[0].title.lower():
continue
- tmdb.set_infoLabels_itemlist(value, True, forced=True)
for elem in value:
if not elem.infoLabels.get('year', ""):
elem.infoLabels['year'] = '-'
- tmdb.set_infoLabels_item(elem, True)
-
+ tmdb.set_infoLabels_itemlist(value, True, forced=True)
+ for elem in value:
if elem.infoLabels['tmdb_id'] == searched_id:
elem.from_channel = key
if not config.get_setting('unify'):
@@ -272,7 +302,7 @@ def channel_search(item):
title = typo(ch_name,'bold') + typo(str(len(grouped)), '_ [] color kod bold')
else:
title = typo('%s %s' % (len(grouped), config.get_localized_string(70695)), 'bold')
- res_count += len(grouped)
+ # res_count += len(grouped)
plot=''
for it in grouped:
@@ -281,35 +311,48 @@ def channel_search(item):
results.append(Item(channel='search', title=title,
action='get_from_temp', thumbnail=ch_thumb, itemlist=[ris.tourl() for ris in grouped], plot=plot, page=1))
+ progress.close()
+ # "All Together" and movie mode -> search servers
+ if config.get_setting('result_mode') == 1 and mode == 'movie':
+ progress = platformtools.dialog_progress(config.get_localized_string(30993) % item.title, config.get_localized_string(60683))
+ valid_servers = []
+ with futures.ThreadPoolExecutor(max_workers=set_workers()) as executor:
+ c_results = [executor.submit(get_servers, v, module_dict) for v in valid]
+ completed = 0
+ for res in futures.as_completed(c_results):
+ if progress.iscanceled():
+ break
+ if res.result():
+ completed += 1
+ valid_servers.extend(res.result())
+ progress.update(old_div(completed * 100, len(valid)))
+ valid = valid_servers
+ progress.close()
# send_to_temp(to_temp)
- config.set_setting('tmdb_active', True)
- if item.mode == 'all':
- if config.get_setting('result_mode', 'search') != 0:
- res_count = len(results)
- results = sorted(results, key=lambda it: it.title)
- results_statistic = config.get_localized_string(59972) % (item.title, res_count, time.time() - start)
- results.insert(0, Item(title = typo(results_statistic,'color kod bold')))
+
+ results = sorted(results, key=lambda it: it.title)
+ results_statistic = config.get_localized_string(59972) % (item.title, time.time() - start)
+ if mode == 'all':
+ results.insert(0, Item(title=typo(results_statistic, 'color kod bold'), thumbnail=get_thumb('search.png')))
+ else:
+ valid.insert(0, Item(title=typo(results_statistic, 'color kod bold'), thumbnail=get_thumb('search.png')))
+
+ if results:
+ results.insert(0, Item(title=typo(config.get_localized_string(30025), 'color kod bold'), thumbnail=get_thumb('search.png')))
# logger.debug(results_statistic)
return valid + results
-def get_channel_results(ch, item):
+def get_channel_results(item, module_dict, search_action):
+ ch = search_action.channel
max_results = 10
results = list()
+ module = module_dict[ch]
+
try:
- ch_params = channeltools.get_channel_parameters(ch)
-
- module = __import__('channels.%s' % ch_params["channel"], fromlist=["channels.%s" % ch_params["channel"]])
- mainlist = getattr(module, 'mainlist')(Item(channel=ch_params["channel"]))
- search_action = [elem for elem in mainlist if elem.action == "search" and (item.mode == 'all' or elem.contentType == item.mode)]
-
- if search_action:
- for search_ in search_action:
- results.extend(module.search(search_, item.text))
- else:
- results.extend(module.search(item, item.text))
+ results.extend(module.search(search_action, item.text))
if len(results) < 0 and len(results) < max_results and item.mode != 'all':
@@ -319,9 +362,22 @@ def get_channel_results(ch, item):
results = get_info(results)
- return [ch, results]
+ return [search_action, results]
except:
- return [ch, results]
+ return [search_action, results]
+
+
+def get_servers(item, module_dict):
+ item.global_search = True
+ ch = item.channel
+ results = list()
+ module = module_dict[ch]
+ try:
+ results = getattr(module, item.action)(item)
+ except:
+ import traceback
+ logger.error(traceback.format_exc())
+ return [r.clone(title=r.title + typo(item.channel, '_ [] color kod')) for r in results if r.action == 'play']
def get_info(itemlist):
diff --git a/specials/setting.py b/specials/setting.py
index 27826152..1a886e70 100644
--- a/specials/setting.py
+++ b/specials/setting.py
@@ -12,11 +12,9 @@ from builtins import range
from past.utils import old_div
from channelselector import get_thumb
-from core import filetools
-from core import servertools
+from core import filetools, servertools
from core.item import Item
-from platformcode import config, logger
-from platformcode import platformtools
+from platformcode import config, logger, platformtools
import xbmcgui
CHANNELNAME = "setting"
@@ -73,7 +71,7 @@ def menu_channels(item):
itemlist.append(Item(channel=CHANNELNAME, title=config.get_localized_string(60546) + ":", action="", folder=False,
text_bold = True, thumbnail=get_thumb("setting_0.png")))
- # Inicio - Canales configurables
+ # Home - Configurable channels
import channelselector
from core import channeltools
channel_list = channelselector.filterchannels("all")
@@ -85,7 +83,7 @@ def menu_channels(item):
itemlist.append(Item(channel=CHANNELNAME, title=". " + config.get_localized_string(60547) % channel.title,
action="channel_config", config=channel.channel, folder=False,
thumbnail=channel.thumbnail))
- # Fin - Canales configurables
+ # End - Configurable channels
itemlist.append(Item(channel=CHANNELNAME, action="", title="", folder=False, thumbnail=get_thumb("setting_0.png")))
itemlist.append(Item(channel=CHANNELNAME, title=config.get_localized_string(60548) + ":", action="", folder=False,
text_bold=True, thumbnail=get_thumb("channels.png")))
@@ -98,7 +96,7 @@ def channel_config(item):
return platformtools.show_channel_settings(channelpath=filetools.join(config.get_runtime_path(), "channels", item.config))
-def autostart(item): # item necessario launcher.py linea 265
+def autostart(item): # item required launcher.py line 265
if config.enable_disable_autorun(AUTOSTART):
logger.info('AUTOSTART ENABLED')
# xbmcgui.Dialog().ok(config.get_localized_string(20000), config.get_localized_string(70709))
@@ -126,7 +124,7 @@ def autostart(item): # item necessario launcher.py linea 265
# torrent_options = [config.get_localized_string(30006), config.get_localized_string(70254), config.get_localized_string(70255)]
# torrent_options.extend(platformtools.torrent_client_installed())
-
+
# list_controls = [
# {
@@ -257,7 +255,7 @@ def menu_servers(item):
itemlist.append(Item(channel=CHANNELNAME, title=config.get_localized_string(60552),
action="", folder=False, text_bold = True, thumbnail=get_thumb("setting_0.png")))
- # Inicio - Servidores configurables
+ # Home - Configurable servers
server_list = list(servertools.get_debriders_list().keys())
for server in server_list:
@@ -280,7 +278,7 @@ def menu_servers(item):
Item(channel=CHANNELNAME, title=". " + config.get_localized_string(60553) % server_parameters["name"],
action="server_config", config=server, folder=False, thumbnail=""))
- # Fin - Servidores configurables
+ # End - Configurable servers
return itemlist
@@ -332,13 +330,13 @@ def cb_servers_blacklist(item, dict_values):
config.set_setting('filter_servers', v)
else:
config.set_setting("black_list", v, server=k)
- if v: # Si el servidor esta en la lista negra no puede estar en la de favoritos
+ if v: # If the server is blacklisted it cannot be in the favorites list
config.set_setting("favorites_servers_list", 100, server=k)
f = True
progreso.update(old_div((i * 100), n), config.get_localized_string(60559) % k)
i += 1
- if not f: # Si no hay ningun servidor en la lista, desactivarla
+ if not f: # If there is no server in the list, deactivate it
config.set_setting('filter_servers', False)
progreso.close()
@@ -406,7 +404,7 @@ def cb_servers_favorites(server_names, dict_values):
progreso.update(old_div((i * 100), n), config.get_localized_string(60559) % server_parameters['name'])
i += 1
- if not dict_name: # Si no hay ningun servidor en lalista desactivarla
+ if not dict_name: # If there is no server in the list, deactivate it
config.set_setting("favorites_servers", False)
progreso.close()
@@ -420,7 +418,7 @@ def submenu_tools(item):
logger.info()
itemlist = list()
- # Herramientas personalizadas
+ # Custom tools
import os
channel_custom = os.path.join(config.get_runtime_path(), 'channels', 'custom.py')
if not filetools.exists(channel_custom):
@@ -483,9 +481,9 @@ def check_quickfixes(item):
def conf_tools(item):
logger.info()
- # Activar o desactivar canales
+ # Enable or disable channels
if item.extra == "channels_onoff":
- if config.get_platform(True)['num_version'] >= 17.0: # A partir de Kodi 16 se puede usar multiselect, y de 17 con preselect
+ if config.get_platform(True)['num_version'] >= 17.0: # From Kodi 16 you can use multiselect, and from 17 with preselect
return channels_onoff(item)
import channelselector
@@ -515,14 +513,14 @@ def conf_tools(item):
config.get_localized_string(60593)]})
for channel in channel_list:
- # Si el canal esta en la lista de exclusiones lo saltamos
+ # If the channel is on the exclusion list, we skip it
if channel.channel not in excluded_channels:
channel_parameters = channeltools.get_channel_parameters(channel.channel)
status_control = ""
status = config.get_setting("enabled", channel.channel)
- # si status no existe es que NO HAY valor en _data.json
+ # if status does not exist, there is NO value in _data.json
if status is None:
status = channel_parameters["active"]
logger.debug("%s | Status (XML): %s" % (channel.channel, status))
@@ -552,15 +550,14 @@ def conf_tools(item):
callback="channel_status",
custom_button={"visible": False})
- # Comprobacion de archivos channel_data.json
+ # Checking channel_data.json files
elif item.extra == "lib_check_datajson":
itemlist = []
import channelselector
from core import channeltools
channel_list = channelselector.filterchannels("allchannelstatus")
- # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si channel.json tiene "settings",
- # pero por si acaso se deja
+ # Having an exclusion list doesn't make much sense because it checks if channel.json has "settings", but just in case it is left
excluded_channels = ['url',
'setting',
'help']
@@ -573,9 +570,9 @@ def conf_tools(item):
list_status = None
default_settings = None
- # Se comprueba si el canal esta en la lista de exclusiones
+ # It is checked if the channel is in the exclusion list
if channel.channel not in excluded_channels:
- # Se comprueba que tenga "settings", sino se salta
+ # It is checked that it has "settings", otherwise it skips
list_controls, dict_settings = channeltools.get_channel_controls_settings(channel.channel)
if not list_controls:
@@ -586,23 +583,22 @@ def conf_tools(item):
continue
# logger.info(channel.channel + " SALTADO!")
- # Se cargan los ajustes del archivo json del canal
- file_settings = os.path.join(config.get_data_path(), "settings_channels",
- channel.channel + "_data.json")
+ # The json file settings of the channel are loaded
+ file_settings = os.path.join(config.get_data_path(), "settings_channels", channel.channel + "_data.json")
dict_settings = {}
dict_file = {}
if filetools.exists(file_settings):
- # logger.info(channel.channel + " Tiene archivo _data.json")
+ # logger.info(channel.channel + " Has _data.json file")
channeljson_exists = True
- # Obtenemos configuracion guardada de ../settings/channel_data.json
+ # We get saved settings from ../settings/channel_data.json
try:
dict_file = jsontools.load(filetools.read(file_settings))
if isinstance(dict_file, dict) and 'settings' in dict_file:
dict_settings = dict_file['settings']
except EnvironmentError:
- logger.error("ERROR al leer el archivo: %s" % file_settings)
+ logger.error("ERROR when reading the file: %s" % file_settings)
else:
- # logger.info(channel.channel + " No tiene archivo _data.json")
+ # logger.info(channel.channel + " No _data.json file")
channeljson_exists = False
if channeljson_exists:
@@ -614,12 +610,12 @@ def conf_tools(item):
else:
datajson_size = None
- # Si el _data.json esta vacio o no existe...
+ # If the _data.json is empty or does not exist ...
if (len(dict_settings) and datajson_size) == 0 or not channeljson_exists:
- # Obtenemos controles del archivo ../channels/channel.json
+ # We get controls from the file ../channels/channel.json
needsfix = True
try:
- # Se cargan los ajustes por defecto
+ # Default settings are loaded
list_controls, default_settings = channeltools.get_channel_controls_settings(
channel.channel)
# logger.info(channel.title + " | Default: %s" % default_settings)
@@ -628,26 +624,26 @@ def conf_tools(item):
logger.error(channel.title + config.get_localized_string(60570) % traceback.format_exc())
# default_settings = {}
- # Si _data.json necesita ser reparado o no existe...
+ # If _data.json needs to be repaired or doesn't exist ...
if needsfix or not channeljson_exists:
if default_settings is not None:
- # Creamos el channel_data.json
+ # We create the channel_data.json
default_settings.update(dict_settings)
dict_settings = default_settings
dict_file['settings'] = dict_settings
- # Creamos el archivo ../settings/channel_data.json
+ # We create the file ../settings/channel_data.json
if not filetools.write(file_settings, jsontools.dump(dict_file), silent=True):
- logger.error("ERROR al salvar el archivo: %s" % file_settings)
+ logger.error("ERROR saving file: %s" % file_settings)
list_status = config.get_localized_string(60560)
else:
if default_settings is None:
list_status = config.get_localized_string(60571)
else:
- # logger.info(channel.channel + " - NO necesita correccion!")
+ # logger.info(channel.channel + " - NO correction needed!")
needsfix = False
- # Si se ha establecido el estado del canal se añade a la lista
+ # If the channel status has been set it is added to the list
if needsfix is not None:
if needsfix:
if not channeljson_exists:
@@ -657,8 +653,7 @@ def conf_tools(item):
list_status = config.get_localized_string(60589)
list_colour = "green"
else:
- # Si "needsfix" es "false" y "datjson_size" es None habra
- # ocurrido algun error
+ # If "needsfix" is "false" and "datjson_size" is None, an error will have occurred
if datajson_size is None:
list_status = config.get_localized_string(60590)
list_colour = "red"
@@ -673,9 +668,9 @@ def conf_tools(item):
thumbnail=channel.thumbnail,
text_color=list_colour))
else:
- logger.error("Algo va mal con el canal %s" % channel.channel)
+ logger.error("Something is wrong with the channel %s" % channel.channel)
- # Si el canal esta en la lista de exclusiones lo saltamos
+ # If the channel is on the exclusion list, we skip it
else:
continue
except:
@@ -689,7 +684,7 @@ def channels_onoff(item):
import channelselector, xbmcgui
from core import channeltools
- # Cargar lista de opciones
+ # Load list of options
# ------------------------
lista = []; ids = []
channels_list = channelselector.filterchannels('allchannelstatus')
@@ -704,11 +699,11 @@ def channels_onoff(item):
lista.append(it)
ids.append(channel.channel)
- # Diálogo para pre-seleccionar
+ # Dialog to pre-select
# ----------------------------
preselecciones = [config.get_localized_string(70517), config.get_localized_string(70518), config.get_localized_string(70519)]
ret = platformtools.dialog_select(config.get_localized_string(60545), preselecciones)
- if ret == -1: return False # pedido cancel
+ if ret == -1: return False # order cancel
if ret == 2: preselect = []
elif ret == 1: preselect = list(range(len(ids)))
else:
@@ -719,13 +714,13 @@ def channels_onoff(item):
if channel_status:
preselect.append(i)
- # Diálogo para seleccionar
+ # Dialog to select
# ------------------------
ret = xbmcgui.Dialog().multiselect(config.get_localized_string(60545), lista, preselect=preselect, useDetails=True)
- if ret == None: return False # pedido cancel
+ if ret == None: return False # order cancel
seleccionados = [ids[i] for i in ret]
- # Guardar cambios en canales activados
+ # Save changes to activated channels
# ------------------------------------
for canal in ids:
channel_status = config.get_setting('enabled', canal)
@@ -744,7 +739,7 @@ def channel_status(item, dict_values):
for k in dict_values:
if k == "all_channels":
- logger.info("Todos los canales | Estado seleccionado: %s" % dict_values[k])
+ logger.info("All channels | Selected state: %s" % dict_values[k])
if dict_values[k] != 0:
excluded_channels = ['url', 'search',
'videolibrary', 'setting',
@@ -759,25 +754,25 @@ def channel_status(item, dict_values):
new_status_all = None
new_status_all_default = channel_parameters["active"]
- # Opcion Activar todos
+ # Option Activate all
if dict_values[k] == 1:
new_status_all = True
- # Opcion Desactivar todos
+ # Option Deactivate all
if dict_values[k] == 2:
new_status_all = False
- # Opcion Recuperar estado por defecto
+ # Retrieve default status option
if dict_values[k] == 3:
- # Si tiene "enabled" en el _data.json es porque el estado no es el del channel.json
+ # If you have "enabled" in the _data.json, it is because the state is not that of the channel.json
if config.get_setting("enabled", channel.channel):
new_status_all = new_status_all_default
- # Si el canal no tiene "enabled" en el _data.json no se guarda, se pasa al siguiente
+ # If the channel does not have "enabled" in the _data.json it is not saved, it goes to the next
else:
continue
- # Se guarda el estado del canal
+ # Channel status is saved
if new_status_all is not None:
config.set_setting("enabled", new_status_all, channel.channel)
break
@@ -785,15 +780,15 @@ def channel_status(item, dict_values):
continue
else:
- logger.info("Canal: %s | Estado: %s" % (k, dict_values[k]))
+ logger.info("Channel: %s | State: %s" % (k, dict_values[k]))
config.set_setting("enabled", dict_values[k], k)
- logger.info("el valor esta como %s " % config.get_setting("enabled", k))
+ logger.info("the value is like %s " % config.get_setting("enabled", k))
platformtools.itemlist_update(Item(channel=CHANNELNAME, action="mainlist"))
except:
import traceback
- logger.error("Detalle del error: %s" % traceback.format_exc())
+ logger.error("Error detail: %s" % traceback.format_exc())
platformtools.dialog_notification(config.get_localized_string(60579), config.get_localized_string(60580))
@@ -823,15 +818,15 @@ def restore_tools(item):
path = filetools.dirname(tvshow_file)
if not serie.active:
- # si la serie no esta activa descartar
+ # if the series is not active discard
continue
- # Eliminamos la carpeta con la serie ...
+ # We delete the folder with the series ...
if tvshow_file.endswith('.strm') or tvshow_file.endswith('.json') or tvshow_file.endswith('.nfo'):
os.remove(os.path.join(path, tvshow_file))
# filetools.rmdirtree(path)
- # ... y la volvemos a añadir
+ # ... and we add it again
service.update(path, p_dialog, i, t, serie, 3)
p_dialog.close()
@@ -855,7 +850,7 @@ def restore_tools(item):
path = filetools.dirname(movie_json)
movie = Item().fromjson(filetools.read(movie_json))
- # Eliminamos la carpeta con la pelicula ...
+ # We delete the folder with the movie ...
filetools.rmdirtree(path)
import math
@@ -863,69 +858,69 @@ def restore_tools(item):
p_dialog2.update(int(math.ceil((i + 1) * t)), heading, config.get_localized_string(60389) % (movie.contentTitle,
movie.channel.capitalize()))
- # ... y la volvemos a añadir
+ # ... and we add it again
videolibrarytools.save_movie(movie)
except Exception as ex:
- logger.error("Error al crear de nuevo la película")
+ logger.error("Error creating movie again")
template = "An exception of type %s occured. Arguments:\n%r"
message = template % (type(ex).__name__, ex.args)
logger.error(message)
p_dialog2.close()
-
+
def report_menu(item):
logger.info('URL: ' + item.url)
-
+
from channelselector import get_thumb
-
+
thumb_debug = get_thumb("update.png")
thumb_error = get_thumb("error.png")
thumb_next = get_thumb("next.png")
itemlist = []
paso = 1
- # Crea un menú de opciones para permitir al usuario reportar un fallo de Alfa a través de un servidor "pastebin"
- # Para que el informe sea completo el usuario debe tener la opción de DEBUG=ON
- # Los servidores "pastbin" gratuitos tienen limitación de capacidad, por lo que el tamaño del log es importante
- # Al final de la operación de upload, se pasa al usuario la dirección de log en el servidor para que los reporte
-
+ # Create a menu of options to allow the user to report an Alpha failure through a "pastebin" server
+ # For the report to be complete, the user must have the option DEBUG = ON
+ # Free pastbin servers have capacity limitations, so the size of the log is important
+ # At the end of the upload operation, the user is passed the log address on the server to report them
+
itemlist.append(Item(channel=item.channel, action="", title=config.get_localized_string(707418),
thumbnail=thumb_next, folder=False))
- #if not config.get_setting('debug'):
- itemlist.append(Item(channel=item.channel, action="activate_debug", extra=True,
+ # if not config.get_setting('debug'):
+ itemlist.append(Item(channel=item.channel, action="activate_debug", extra=True,
title=config.get_localized_string(707419) %
str(paso), thumbnail=thumb_debug, folder=False))
paso += 1
- itemlist.append(Item(channel="channelselector", action="getmainlist",
+ itemlist.append(Item(channel="channelselector", action="getmainlist",
title=config.get_localized_string(707420) %
str(paso), thumbnail=thumb_debug))
paso += 1
- itemlist.append(Item(channel=item.channel, action="report_send",
+ itemlist.append(Item(channel=item.channel, action="report_send",
title=config.get_localized_string(707421) %
str(paso), thumbnail=thumb_error, folder=False))
paso += 1
- #if config.get_setting('debug'):
- itemlist.append(Item(channel=item.channel, action="activate_debug", extra=False,
+ # if config.get_setting('debug'):
+ itemlist.append(Item(channel=item.channel, action="activate_debug", extra=False,
title=config.get_localized_string(707422) % str(paso),
thumbnail=thumb_debug, folder=False))
paso += 1
-
+
if item.url:
itemlist.append(Item(channel=item.channel, action="", title="", folder=False))
-
- itemlist.append(Item(channel=item.channel, action="",
+
+ itemlist.append(Item(channel=item.channel, action="",
title=config.get_localized_string(707423),
thumbnail=thumb_next, folder=False))
-
+
if item.one_use:
action = ''
url = ''
else:
action = 'call_browser'
url = item.url
- itemlist.append(Item(channel=item.channel, action=action,
- title="**- LOG: [COLOR gold]%s[/COLOR] -**" % item.url, url=url,
+ itemlist.append(Item(channel=item.channel, action=action,
+ title="**- LOG: [COLOR gold]%s[/COLOR] -**" % item.url, url=url,
thumbnail=thumb_next, unify=False, folder=False))
itemlist.append(Item(channel=item.channel, action="call_browser",
@@ -935,24 +930,24 @@ def report_menu(item):
itemlist.append(Item(channel=item.channel, action="call_browser",
url='https://t.me/kodiondemand', title="Su telegram",
thumbnail=thumb_next, unify=False, folder=False))
-
+
if item.one_use:
- itemlist.append(Item(channel=item.channel, action="",
- title="[COLOR orange]NO ACCEDA al INFORME: se BORRARÁ[/COLOR]",
+ itemlist.append(Item(channel=item.channel, action="",
+ title="[COLOR orange]NO ACCEDA al INFORME: se BORRARÁ[/COLOR]",
thumbnail=thumb_next, folder=False))
- itemlist.append(Item(channel=item.channel, action="",
- title="[COLOR orange]ya que es de un solo uso[/COLOR]",
+ itemlist.append(Item(channel=item.channel, action="",
+ title="[COLOR orange]ya que es de un solo uso[/COLOR]",
thumbnail=thumb_next, folder=False))
-
+
return itemlist
-
-
+
+
def activate_debug(item):
logger.info(item.extra)
from platformcode import platformtools
-
- # Activa/Desactiva la opción de DEBUB en settings.xml
-
+
+ #Enable / disable DEBUB option in settings.xml
+
if isinstance(item.extra, str):
return report_menu(item)
if item.extra:
@@ -961,20 +956,20 @@ def activate_debug(item):
else:
config.set_setting('debug', False)
platformtools.dialog_notification(config.get_localized_string(707430), config.get_localized_string(707432))
-
-
+
+
def report_send(item, description='', fatal=False):
import xbmc
import random
import traceback
if PY3:
- #from future import standard_library
- #standard_library.install_aliases()
- import urllib.parse as urlparse # Es muy lento en PY2. En PY3 es nativo
+ # from future import standard_library
+ # standard_library.install_aliases()
+ import urllib.parse as urlparse # It is very slow in PY2. In PY3 it is native
import urllib.parse as urllib
else:
- import urllib # Usamos el nativo de PY2 que es más rápido
+ import urllib # We use the native of PY2 which is faster
import urlparse
try:
@@ -983,149 +978,149 @@ def report_send(item, description='', fatal=False):
except:
requests_status = False
logger.error(traceback.format_exc())
-
+
from core import jsontools, httptools, scrapertools
from platformcode import envtal
-
- # Esta función realiza la operación de upload del LOG. El tamaño del archivo es de gran importacia porque
- # los servicios de "pastebin" gratuitos tienen limitaciones, a veces muy bajas.
- # Hay un ervicio, File.io, que permite subida directa de "achivos binarios" a través de la función "request"
- # Esto aumenta dráticamente la capacidad del envío del log, muy por encima de lo necesitado
- # Por ello es necesario contar con una lista de servicios "pastebin" que puedan realizar la operación de upload,
- # ya sea por capacidad disponible o por disponibilidad.
- # Para poder usar los servidores "pastebin" con un código común, se ha creado un diccionario con los servidores
- # y sus características. En cada entrada se recogen las peculiaridades de cada servidor, tanto para formar
- # la petición consu POST como para la forma de recibir el código del upload en la respuesta (json, header, regex
- # en datos,...).
- # Al iniciar este método se aleatoriza la lista de servidores "pastebin" para evitar que todos los usuarios hagan
- # uploads contra el mismo servidor y puedan ocasionar sobrecargas.
- # Se lee el arcivo de log y se compara su tamaño con la capacidad del servidor (parámetro 10 de cada entrada
- # (empezando desde 0), expresado en MB, hasta que se encuentra uno capacitado. Si el upload falla se sigue intentado
- # con los siguientes servidores que tengan la capacidad requerida.
- # Si no se encuentra ningun servidor disponible se pide al usuario que lo intente más tarde, o que suba el log
- # directamente en el foro. Si es un problema de tamaño, se le pide que reicinie Kodi y reporducza el fallo, para
- # que el LOG sea más pequeño.
-
-
+
+ # This function performs the LOG upload operation. The file size is of great importance because
+ # Free pastebin services have limitations, sometimes very low.
+ # There is an ervice, File.io, that allows direct upload of "binary files" through the "request" function
+ # This dramatically increases the ability to send the log, well above what is needed.
+ # Therefore it is necessary to have a list of "pastebin" services that can perform the upload operation,
+ # either by available capacity or by availability.
+ # In order to use the "pastebin" servers with a common code, a dictionary has been created with the servers
+ # and their characteristics. In each entry the peculiarities of each server are collected, both to form
+ # the request with POST as for the way to receive the upload code in the response (json, header, regex
+ # in data, ...).
+ # Starting this method randomizes the list of "pastebin" servers to prevent all users from doing
+ # uploads against the same server and may cause overloads.
+ # The log file is read and its size is compared with the server capacity (parameter 10 of each entry
+ # (starting from 0), expressed in MB, until a qualified one is found. If the upload fails, it continues trying
+ # with the following servers that have the required capacity.
+ # If no available server is found, the user is asked to try again later, or to upload the log.
+ # directly on the forum. If it is a size problem, you are asked to reset Kodi and redo the fault, to
+ # that the LOG is smaller.
+
+
pastebin_list = {
- 'hastebin': ('1', 'https://hastebin.com/', 'documents', 'random', '', '',
- 'data', 'json', 'key', '', '0.29', '10', True, 'raw/', '', ''),
- 'dpaste': ('1', 'http://dpaste.com/', 'api/v2/', 'random', 'content=',
- '&syntax=text&title=%s&poster=alfa&expiry_days=7',
+ 'hastebin': ('1', 'https://hastebin.com/', 'documents', 'random', '', '',
+ 'data', 'json', 'key', '', '0.29', '10', True, 'raw/', '', ''),
+ 'dpaste': ('1', 'http://dpaste.com/', 'api/v2/', 'random', 'content=',
+ '&syntax=text&title=%s&poster=alfa&expiry_days=7',
'headers', '', '', 'location', '0.23', '15', True, '', '.txt', ''),
- 'ghostbin': ('1', 'https://ghostbin.com/', 'paste/new', 'random', 'lang=text&text=',
- '&expire=2d&password=&title=%s',
- 'data', 'regex', '(.*?)\s*-\s*Ghostbin<\/title>', '',
+ 'ghostbin': ('1', 'https://ghostbin.com/', 'paste/new', 'random', 'lang=text&text=',
+ '&expire=2d&password=&title=%s',
+ 'data', 'regex', '(.*?)\s*-\s*Ghostbin<\/title>', '',
'0.49', '15', False, 'paste/', '', ''),
- 'write.as': ('1', 'https://write.as/', 'api/posts', 'random', 'body=', '&title=%s',
+ 'write.as': ('1', 'https://write.as/', 'api/posts', 'random', 'body=', '&title=%s',
'data', 'json', 'data', 'id', '0.018', '15', True, '', '', ''),
- 'oneclickpaste': ('1', 'http://oneclickpaste.com/', 'index.php', 'random', 'paste_data=',
- '&title=%s&format=text&paste_expire_date=1W&visibility=0&pass=&submit=Submit',
- 'data', 'regex', '\s*View\s*Paste\s*<\/a>',
+ 'oneclickpaste': ('1', 'http://oneclickpaste.com/', 'index.php', 'random', 'paste_data=',
+ '&title=%s&format=text&paste_expire_date=1W&visibility=0&pass=&submit=Submit',
+ 'data', 'regex', '\s*View\s*Paste\s*<\/a>',
'', '0.060', '5', True, '', '', ''),
- 'bpaste': ('1', 'https://bpaste.net/', '', 'random', 'code=', '&lexer=text&expiry=1week',
- 'data', 'regex', 'View\s*raw<\/a>', '',
+ 'bpaste': ('1', 'https://bpaste.net/', '', 'random', 'code=', '&lexer=text&expiry=1week',
+ 'data', 'regex', 'View\s*raw<\/a>', '',
'0.79', '15', True, 'raw/', '', ''),
- 'dumpz': ('0', 'http://dumpz.org/', 'api/dump', 'random', 'code=', '&lexer=text&comment=%s&password=',
+ 'dumpz': ('0', 'http://dumpz.org/', 'api/dump', 'random', 'code=', '&lexer=text&comment=%s&password=',
'headers', '', '', 'location', '0.99', '15', False, '', '', ''),
- 'file.io': ('1', 'https://file.io/', '', 'random', '', 'expires=1w',
- 'requests', 'json', 'key', '', '99.0', '30', False, '', '.log', ''),
- 'uploadfiles': ('1', 'https://up.uploadfiles.io/upload', '', 'random', '', '',
- 'requests', 'json', 'url', '', '99.0', '30', False, None, '', '')
+ 'file.io': ('1', 'https://file.io/', '', 'random', '', 'expires=1w',
+ 'requests', 'json', 'key', '', '99.0', '30', False, '', '.log', ''),
+ 'uploadfiles': ('1', 'https://up.uploadfiles.io/upload', '', 'random', '', '',
+ 'requests', 'json', 'url', '', '99.0', '30', False, None, '', '')
}
- pastebin_list_last = ['hastebin', 'ghostbin', 'file.io'] # Estos servicios los dejamos los últimos
- pastebin_one_use = ['file.io'] # Servidores de un solo uso y se borra
+ pastebin_list_last = ['hastebin', 'ghostbin', 'file.io'] # We leave these services the last
+ pastebin_one_use = ['file.io'] # Single-use servers and deletes
pastebin_dir = []
paste_file = {}
paste_params = ()
paste_post = ''
status = False
msg = config.get_localized_string(707424)
-
- # Se verifica que el DEBUG=ON, si no está se rechaza y se pide al usuario que lo active y reproduzca el fallo
+
+ # DEBUG = ON is verified, if it is not it is rejected and the user is asked to activate it and reproduce the fault
if not config.get_setting('debug'):
platformtools.dialog_notification(config.get_localized_string(707425), config.get_localized_string(707426))
return report_menu(item)
-
- # De cada al futuro se permitira al usuario que introduzca una breve descripción del fallo que se añadirá al LOG
+
+ # From each to the future the user will be allowed to enter a brief description of the fault that will be added to the LOG
if description == 'OK':
description = platformtools.dialog_input('', 'Introduzca una breve descripción del fallo')
- # Escribimos en el log algunas variables de Kodi y Alfa que nos ayudarán en el diagnóstico del fallo
+ # We write in the log some Kodi and Alpha variables that will help us diagnose the failure
environment = envtal.list_env()
if not environment['log_path']:
environment['log_path'] = str(filetools.join(xbmc.translatePath("special://logpath/"), 'kodi.log'))
environment['log_size_bytes'] = str(filetools.getsize(environment['log_path']))
environment['log_size'] = str(round(float(environment['log_size_bytes']) / (1024*1024), 3))
-
- # Se lee el archivo de LOG
+
+ # LOG file is read
log_path = environment['log_path']
if filetools.exists(log_path):
- log_size_bytes = int(environment['log_size_bytes']) # Tamaño del archivivo en Bytes
- log_size = float(environment['log_size']) # Tamaño del archivivo en MB
- log_data = filetools.read(log_path) # Datos del archivo
- if not log_data: # Algún error?
+ log_size_bytes = int(environment['log_size_bytes']) # File size in Bytes
+ log_size = float(environment['log_size']) # File size in MB
+ log_data = filetools.read(log_path) # File data
+ if not log_data: # Some mistake?
platformtools.dialog_notification(config.get_localized_string(707427), '', 2)
return report_menu(item)
- else: # Log no existe o path erroneo?
+ else: # Log no existe or erroneous path?
platformtools.dialog_notification(config.get_localized_string(707427), '', 2)
return report_menu(item)
- # Si se ha introducido la descripción del fallo, se inserta la principio de los datos del LOG
- # log_title = '***** DESCRIPCIÓN DEL FALLO *****'
+ # If the fault description has been entered, the beginning of the LOG data is inserted
+ # log_title = '***** FAULT DESCRIPTION *****'
# if description:
# log_data = '%s\n%s\n\n%s' %(log_title, description, log_data)
-
- # Se aleatorizan los nombre de los servidores "patebin"
+
+ # Server names "patebin" are scrambled
for label_a, value_a in list(pastebin_list.items()):
if label_a not in pastebin_list_last:
pastebin_dir.append(label_a)
random.shuffle(pastebin_dir)
- pastebin_dir.extend(pastebin_list_last) # Estos servicios los dejamos los últimos
-
- #pastebin_dir = ['uploadfiles'] # Para pruebas de un servicio
- #log_data = 'TEST PARA PRUEBAS DEL SERVICIO'
-
- # Se recorre la lista de servidores "pastebin" hasta localizar uno activo, con capacidad y disponibilidad
+ pastebin_dir.extend(pastebin_list_last) # We leave these services the last
+
+ #pastebin_dir = ['uploadfiles'] # For testing a service
+ #log_data = 'TEST FOR SERVICE TESTS'
+
+ # The list of "pastebin" servers is scrolled to locate an active one, with capacity and availability
for paste_name in pastebin_dir:
- if pastebin_list[paste_name][0] != '1': # Si no esta activo el servidore, pasamos
+ if pastebin_list[paste_name][0] != '1': # If the server is not active, we pass
continue
- if pastebin_list[paste_name][6] == 'requests' and not requests_status: # Si "requests" no esta activo, pasamos
+ if pastebin_list[paste_name][6] == 'requests' and not requests_status: # If "requests" is not active, we pass
continue
- paste_host = pastebin_list[paste_name][1] # URL del servidor "pastebin"
- paste_sufix = pastebin_list[paste_name][2] # sufijo del API para el POST
+ paste_host = pastebin_list[paste_name][1] # Server URL "pastebin"
+ paste_sufix = pastebin_list[paste_name][2] # API suffix for POST
paste_title = ''
if pastebin_list[paste_name][3] == 'random':
- paste_title = "LOG" + str(random.randrange(1, 999999999)) # Título del LOG
- paste_post1 = pastebin_list[paste_name][4] # Parte inicial del POST
- paste_post2 = pastebin_list[paste_name][5] # Parte secundaria del POST
- paste_type = pastebin_list[paste_name][6] # Tipo de downloadpage: DATA o HEADERS
- paste_resp = pastebin_list[paste_name][7] # Tipo de respuesta: JSON o datos con REGEX
- paste_resp_key = pastebin_list[paste_name][8] # Si es JSON, etiqueta `primaria con la CLAVE
- paste_url = pastebin_list[paste_name][9] # Etiqueta primaria para HEADER y sec. para JSON
- paste_file_size = float(pastebin_list[paste_name][10]) # Capacidad en MB del servidor
- if paste_file_size > 0: # Si es 0, la capacidad es ilimitada
- if log_size > paste_file_size: # Verificación de capacidad y tamaño
- msg = 'Archivo de log demasiado grande. Reinicie Kodi y reinténtelo'
+ paste_title = "LOG" + str(random.randrange(1, 999999999)) # LOG title
+ paste_post1 = pastebin_list[paste_name][4] # Initial part of the POST
+ paste_post2 = pastebin_list[paste_name][5] # Secondary part of POST
+ paste_type = pastebin_list[paste_name][6] # Type of downloadpage: DATE HEADERS
+ paste_resp = pastebin_list[paste_name][7] # Response type: JSON or data with REGEX
+ paste_resp_key = pastebin_list[paste_name][8] # If JSON, label `primary with KEY
+ paste_url = pastebin_list[paste_name][9] # Primary label for HEADER and sec. for JSON
+ paste_file_size = float(pastebin_list[paste_name][10]) # Server capacity in MB
+ if paste_file_size > 0: # If it is 0, the capacity is unlimited
+ if log_size > paste_file_size: # Capacity and size verification
+ msg = 'Log file too large. Restart Kodi and retry'
continue
- paste_timeout = int(pastebin_list[paste_name][11]) # Timeout para el servidor
- paste_random_headers = pastebin_list[paste_name][12] # Utiliza RAMDOM headers para despistar el serv.?
- paste_host_return = pastebin_list[paste_name][13] # Parte de url para componer la clave para usuario
- paste_host_return_tail = pastebin_list[paste_name][14] # Sufijo de url para componer la clave para usuario
+ paste_timeout = int(pastebin_list[paste_name][11]) # Timeout for the server
+ paste_random_headers = pastebin_list[paste_name][12] # Do you use RAMDOM headers to mislead the serv?
+ paste_host_return = pastebin_list[paste_name][13] # Part of url to compose the key for user
+ paste_host_return_tail = pastebin_list[paste_name][14] # Url suffix to compose user key
paste_headers = {}
- if pastebin_list[paste_name][15]: # Headers requeridas por el servidor
+ if pastebin_list[paste_name][15]: # Headers required by the server
paste_headers.update(jsontools.load((pastebin_list[paste_name][15])))
if paste_name in pastebin_one_use:
- pastebin_one_use_msg = '[COLOR red]NO ACCEDA al INFORME: se BORRARÁ[/COLOR]'
+ pastebin_one_use_msg = 'DO NOT ACCESS THE REPORT: it will be DELETED'
item.one_use = True
else:
pastebin_one_use_msg = ''
-
+
try:
- # Se crea el POST con las opciones del servidor "pastebin"
- # Se trata el formato de "requests"
+ # POST is created with server options "pastebin"
+ # This is the "requests" format
if paste_type == 'requests':
paste_file = {'file': (paste_title+'.log', log_data)}
if paste_post1:
@@ -1135,14 +1130,14 @@ def report_send(item, description='', fatal=False):
paste_params = paste_post2 % (paste_title+'.log', log_size_bytes)
else:
paste_params = paste_post2
-
- #Se trata el formato de downloads
+
+ # This is the download format
else:
- #log_data = 'Test de Servidor para ver su viabilidad (áéíóúñ¿?)'
- if paste_name in ['hastebin']: # Hay algunos servicios que no necesitan "quote"
+ # log_data = 'Server Test to see its viability (áéíóúñ¿?)'
+ if paste_name in ['hastebin']: # There are some services that do not need "quote"
paste_post = log_data
else:
- paste_post = urllib.quote_plus(log_data) # Se hace un "quote" de los datos del LOG
+ paste_post = urllib.quote_plus(log_data) # A "quote" is made from the LOG data
if paste_post1:
paste_post = '%s%s' % (paste_post1, paste_post)
if paste_post2:
@@ -1151,104 +1146,101 @@ def report_send(item, description='', fatal=False):
else:
paste_post += paste_post2
- # Se hace la petición en downloadpage con HEADERS o DATA, con los parámetros del servidor
+ # Request is made on downloadpage with HEADERS or DATA, with server parameters
if paste_type == 'headers':
- data = httptools.downloadpage(paste_host+paste_sufix, post=paste_post,
- timeout=paste_timeout, random_headers=paste_random_headers,
+ data = httptools.downloadpage(paste_host+paste_sufix, post=paste_post,
+ timeout=paste_timeout, random_headers=paste_random_headers,
headers=paste_headers).headers
elif paste_type == 'data':
- data = httptools.downloadpage(paste_host+paste_sufix, post=paste_post,
- timeout=paste_timeout, random_headers=paste_random_headers,
+ data = httptools.downloadpage(paste_host+paste_sufix, post=paste_post,
+ timeout=paste_timeout, random_headers=paste_random_headers,
headers=paste_headers).data
-
- # Si la petición es con formato REQUESTS, se realiza aquí
+
+ # If the request is in REQUESTS format, it is made here
elif paste_type == 'requests':
- #data = requests.post(paste_host, params=paste_params, files=paste_file,
+ #data = requests.post(paste_host, params=paste_params, files=paste_file,
# timeout=paste_timeout)
- data = httptools.downloadpage(paste_host, params=paste_params, file=log_data,
- file_name=paste_title+'.log', timeout=paste_timeout,
+ data = httptools.downloadpage(paste_host, params=paste_params, file=log_data,
+ file_name=paste_title+'.log', timeout=paste_timeout,
random_headers=paste_random_headers, headers=paste_headers)
except:
msg = 'Inténtelo más tarde'
- logger.error('Fallo al guardar el informe. ' + msg)
+ logger.error('Failed to save report. ' + msg)
logger.error(traceback.format_exc())
continue
- # Se analiza la respuesta del servidor y se localiza la clave del upload para formar la url a pasar al usuario
+ # The server response is analyzed and the upload key is located to form the url to pass to the user
if data:
paste_host_resp = paste_host
- if paste_host_return == None: # Si devuelve la url completa, no se compone
+ if paste_host_return == None: # If you return the full url, it is not composed
paste_host_resp = ''
paste_host_return = ''
-
- # Respuestas a peticiones REQUESTS
- if paste_type == 'requests': # Respuesta de petición tipo "requests"?
- if paste_resp == 'json': # Respuesta en formato JSON?
+
+ # Responses to REQUESTS requests
+ if paste_type == 'requests': # Response of request type "requests"?
+ if paste_resp == 'json': # Answer in JSON format?
if paste_resp_key in data.data:
if not paste_url:
- key = jsontools.load(data.data)[paste_resp_key] # con una etiqueta
+ key = jsontools.load(data.data)[paste_resp_key] # with a label
else:
- key = jsontools.load(data.data)[paste_resp_key][paste_url] # con dos etiquetas anidadas
- item.url = "%s%s%s" % (paste_host_resp+paste_host_return, key,
+ key = jsontools.load(data.data)[paste_resp_key][paste_url] # with two nested tags
+ item.url = "%s%s%s" % (paste_host_resp+paste_host_return, key,
paste_host_return_tail)
else:
- logger.error('ERROR en formato de retorno de datos. data.data=' +
- str(data.data))
+ logger.error('ERROR in data return format. data.data=' + str(data.data))
continue
-
- # Respuestas a peticiones DOWNLOADPAGE
- elif paste_resp == 'json': # Respuesta en formato JSON?
+
+ # Responses to DOWNLOADPAGE requests
+ elif paste_resp == 'json': # Answer in JSON format?
if paste_resp_key in data:
if not paste_url:
- key = jsontools.load(data)[paste_resp_key] # con una etiqueta
+ key = jsontools.load(data)[paste_resp_key] # with a label
else:
- key = jsontools.load(data)[paste_resp_key][paste_url] # con dos etiquetas anidadas
- item.url = "%s%s%s" % (paste_host_resp+paste_host_return, key,
+ key = jsontools.load(data)[paste_resp_key][paste_url] # con two nested tags
+ item.url = "%s%s%s" % (paste_host_resp+paste_host_return, key,
paste_host_return_tail)
else:
- logger.error('ERROR en formato de retorno de datos. data=' + str(data))
+ logger.error('ERROR in data return format. data=' + str(data))
continue
- elif paste_resp == 'regex': # Respuesta en DATOS, a buscar con un REGEX?
+ elif paste_resp == 'regex': # Answer in DATA, to search with a REGEX?
key = scrapertools.find_single_match(data, paste_resp_key)
if key:
- item.url = "%s%s%s" % (paste_host_resp+paste_host_return, key,
+ item.url = "%s%s%s" % (paste_host_resp+paste_host_return, key,
paste_host_return_tail)
else:
- logger.error('ERROR en formato de retorno de datos. data=' + str(data))
+ logger.error('ERROR in data return format. data=' + str(data))
continue
- elif paste_type == 'headers': # Respuesta en HEADERS, a buscar en "location"?
+ elif paste_type == 'headers': # Answer in HEADERS, to search in "location"?
if paste_url in data:
- item.url = data[paste_url] # Etiqueta de retorno de la clave
- item.url = urlparse.urljoin(paste_host_resp + paste_host_return,
+ item.url = data[paste_url] # Key return label
+ item.url = urlparse.urljoin(paste_host_resp + paste_host_return,
item.url + paste_host_return_tail)
else:
- logger.error('ERROR en formato de retorno de datos. response.headers=' +
- str(data))
+ logger.error('ERROR in data return format. response.headers=' + str(data))
continue
else:
- logger.error('ERROR en formato de retorno de datos. paste_type=' +
- str(paste_type) + ' / DATA: ' + data)
+ logger.error('ERROR in data return format. paste_type=' + str(paste_type) + ' / DATA: ' + data)
continue
- status = True # Operación de upload terminada con éxito
- logger.info('Report created: ' + str(item.url)) #Se guarda la URL del informe a usuario
- # if fatal: # De uso futuro, para logger.crash
- # platformtools.dialog_ok('Informe de ERROR en Alfa CREADO', 'Repórtelo en el foro agregando ERROR FATAL y esta URL: ', '[COLOR gold]%s[/COLOR]' % item.url, pastebin_one_use_msg)
- # else: # Se pasa la URL del informe a usuario
- # platformtools.dialog_ok('Informe de Fallo en Alfa CREADO', 'Repórtelo en el foro agregando una descripcion del fallo y esta URL: ', '[COLOR gold]%s[/COLOR]' % item.url, pastebin_one_use_msg)
+ status = True # Upload operation completed successfully
+ logger.info('Report created: ' + str(item.url)) # The URL of the user report is saved
+ # if fatal: # For future use, for logger.crash
+ # platformtools.dialog_ok('KoD CREATED ERROR report', 'Report it in the forum by adding FATAL ERROR and this URL: ', '[COLOR gold]%s[/COLOR]' % item.url, pastebin_one_use_msg)
+ # else: # Report URL passed to user
+ # platformtools.dialog_ok('KoD Crash Report CREATED', 'Report it on the forum by adding a bug description and this URL: ', '[COLOR gold]%s[/COLOR]' % item.url, pastebin_one_use_msg)
- break # Operación terminado, no seguimos buscando
-
- if not status and not fatal: # Operación fracasada...
- platformtools.dialog_notification(config.get_localized_string(707428), msg) #... se notifica la causa
+ break # Operation finished, we don't keep looking
+
+ if not status and not fatal: # Operation failed ...
+ platformtools.dialog_notification(config.get_localized_string(707428), msg) #... cause is reported
logger.error(config.get_localized_string(707428) + msg)
-
- # Se devuelve control con item.url actualizado, así aparecerá en el menú la URL del informe
+
+ # Control is returned with updated item.url, so the report URL will appear in the menu
item.action = 'report_menu'
platformtools.itemlist_update(item, True)
# return report_menu(item)
-
-
+
+
def call_browser(item):
import webbrowser
if not webbrowser.open(item.url):
diff --git a/specials/side_menu.py b/specials/side_menu.py
index b0da3e4d..1ede1c95 100644
--- a/specials/side_menu.py
+++ b/specials/side_menu.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
-#from builtins import str
+# from builtins import str
import sys
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
@@ -9,8 +9,7 @@ if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
import os
from core.item import Item
from core import jsontools
-from platformcode import config, logger
-from platformcode import launcher
+from platformcode import config, logger, launcher
import xbmc, xbmcgui, xbmcplugin, xbmcaddon
media_path = os.path.join(config.get_runtime_path(), "resources/skins/Default/media/side_menu/")
@@ -113,7 +112,7 @@ class Main(xbmcgui.WindowXMLDialog):
self.items = []
def onInit(self):
- #### Compatibilidad con Kodi 18 ####
+ #### Kodi 18 compatibility ####
if config.get_platform(True)['num_version'] < 18:
self.setCoordinateResolution(2)
diff --git a/specials/trailertools.py b/specials/trailertools.py
index 7db64695..a240cea3 100644
--- a/specials/trailertools.py
+++ b/specials/trailertools.py
@@ -16,10 +16,10 @@ from past.utils import old_div
if PY3:
#from future import standard_library
#standard_library.install_aliases()
- import urllib.parse as urllib # Es muy lento en PY2. En PY3 es nativo
+ import urllib.parse as urllib # It is very slow in PY2. In PY3 it is native
import urllib.parse as urlparse
else:
- import urllib # Usamos el nativo de PY2 que es más rápido
+ import urllib # We use the native of PY2 which is faster
import urlparse
import re
@@ -37,7 +37,7 @@ def_lang = info_language[config.get_setting("info_language", "videolibrary")]
result = None
window_select = []
-# Para habilitar o no la opción de búsqueda manual
+# To enable or disable the manual search option
if config.get_platform() != "plex":
keyboard = True
else:
@@ -47,14 +47,14 @@ else:
def buscartrailer(item, trailers=[]):
logger.info()
- # Lista de acciones si se ejecuta desde el menú contextual
+ # List of actions if run from context menu
if item.action == "manual_search" and item.contextual:
itemlist = manual_search(item)
item.contentTitle = itemlist[0].contentTitle
elif 'search' in item.action and item.contextual:
itemlist = globals()[item.action](item)
else:
- # Se elimina la opción de Buscar Trailer del menú contextual para evitar redundancias
+ # Remove Trailer Search option from context menu to avoid redundancies
if isinstance(item.context, str) and "buscar_trailer" in item.context:
item.context = item.context.replace("buscar_trailer", "")
elif isinstance(item.context, list) and "buscar_trailer" in item.context:
@@ -80,8 +80,8 @@ def buscartrailer(item, trailers=[]):
item.year = item.infoLabels['year']
- logger.info("Búsqueda: %s" % item.contentTitle)
- logger.info("Año: %s" % item.year)
+ logger.info("Search: %s" % item.contentTitle)
+ logger.info("Year: %s" % item.year)
if item.infoLabels['trailer'] and not trailers:
url = item.infoLabels['trailer']
if "youtube" in url:
@@ -98,8 +98,7 @@ def buscartrailer(item, trailers=[]):
itemlist.extend(tmdb_trailers(item, tipo))
else:
for trailer in trailers:
- title = trailer['name'] + " [" + trailer['size'] + "p] (" + trailer['language'].replace("en", "ING") \
- .replace("it", "ITA") + ") [tmdb/youtube]"
+ title = trailer['name'] + " [" + trailer['size'] + "p] (" + trailer['language'].replace("en", "ING").replace("it", "ITA") + ") [tmdb/youtube]"
itemlist.append(item.clone(action="play", title=title, url=trailer['url'], server="youtube"))
except:
import traceback
@@ -111,7 +110,7 @@ def buscartrailer(item, trailers=[]):
title = "%s"
itemlist.append(item.clone(title=title % config.get_localized_string(70507), action="youtube_search"))
itemlist.append(item.clone(title=title % config.get_localized_string(70024), action="filmaffinity_search"))
- # Si se trata de una serie, no se incluye la opción de buscar en Abandomoviez
+ # If it is a series, the option to search in Abandomoviez is not included
if not item.show and not item.infoLabels['tvshowtitle']:
itemlist.append(item.clone(title=title % config.get_localized_string(70508), action="abandomoviez_search"))
@@ -152,8 +151,7 @@ def tmdb_trailers(item, tipo="movie"):
if tmdb_search:
for result in tmdb_search.get_videos():
- title = result['name'] + " [" + result['size'] + "p] (" + result['language'].replace("en", "ING") \
- .replace("it", "ITA") + ") [tmdb/youtube]"
+ title = result['name'] + " [" + result['size'] + "p] (" + result['language'].replace("en", "ING").replace("it", "ITA") + ") [tmdb/youtube]"
itemlist.append(item.clone(action="play", title=title, url=result['url'], server="youtube"))
return itemlist
@@ -165,7 +163,7 @@ def youtube_search(item):
titulo = item.contentTitle
if item.extra != "youtube":
titulo += " trailer"
- # Comprueba si es una búsqueda de cero o viene de la opción Siguiente
+ # Check if it is a zero search or comes from the Next option
if item.page != "":
data = httptools.downloadpage(item.page).data
else:
@@ -183,8 +181,7 @@ def youtube_search(item):
if item.contextual:
scrapedtitle = "%s" % scrapedtitle
url = urlparse.urljoin('https://www.youtube.com/', scrapedurl)
- itemlist.append(item.clone(title=scrapedtitle, action="play", server="youtube", url=url,
- thumbnail=scrapedthumbnail))
+ itemlist.append(item.clone(title=scrapedtitle, action="play", server="youtube", url=url, thumbnail=scrapedthumbnail))
next_page = scrapertools.find_single_match(data, ']+>'
'Siguiente')
if next_page != "":
@@ -207,7 +204,7 @@ def youtube_search(item):
def abandomoviez_search(item):
logger.info()
- # Comprueba si es una búsqueda de cero o viene de la opción Siguiente
+ # Check if it is a zero search or comes from the Next option
if item.page != "":
data = httptools.downloadpage(item.page).data
else:
@@ -226,7 +223,7 @@ def abandomoviez_search(item):
patron = '(?:).*? (.*?)(?:<\/td>|<\/small>)'
matches = scrapertools.find_multiple_matches(data, patron)
- # Si solo hay un resultado busca directamente los trailers, sino lista todos los resultados
+ # If there is only one result, search directly for the trailers, but list all the results
if len(matches) == 1:
item.url = urlparse.urljoin("http://www.abandomoviez.net/%s" % item.prefix, matches[0][1])
item.thumbnail = matches[0][0]
@@ -235,26 +232,22 @@ def abandomoviez_search(item):
for scrapedthumbnail, scrapedurl, scrapedtitle in matches:
scrapedurl = urlparse.urljoin("http://www.abandomoviez.net/%s" % item.prefix, scrapedurl)
scrapedtitle = scrapertools.htmlclean(scrapedtitle)
- itemlist.append(item.clone(title=scrapedtitle, action="search_links_abando",
- url=scrapedurl, thumbnail=scrapedthumbnail))
+ itemlist.append(item.clone(title=scrapedtitle, action="search_links_abando", url=scrapedurl, thumbnail=scrapedthumbnail))
next_page = scrapertools.find_single_match(data, 'Siguiente')
if next_page != "":
next_page = urlparse.urljoin("http://www.abandomoviez.net/%s" % item.prefix, next_page)
- itemlist.append(item.clone(title=config.get_localized_string(70502), action="abandomoviez_search", page=next_page, thumbnail="",
- text_color=""))
+ itemlist.append(item.clone(title=config.get_localized_string(70502), action="abandomoviez_search", page=next_page, thumbnail="", text_color=""))
if not itemlist:
- itemlist.append(item.clone(title=config.get_localized_string(70501), action="", thumbnail="",
- text_color=""))
+ itemlist.append(item.clone(title=config.get_localized_string(70501), action="", thumbnail="", text_color=""))
if keyboard:
if item.contextual:
title = "%s"
else:
title = "%s"
- itemlist.append(item.clone(title=title % config.get_localized_string(70511),
- action="manual_search", thumbnail="", extra="abandomoviez"))
+ itemlist.append(item.clone(title=title % config.get_localized_string(70511), action="manual_search", thumbnail="", extra="abandomoviez"))
return itemlist
@@ -321,7 +314,7 @@ def filmaffinity_search(item):
item.url = item.filmaffinity
return search_links_filmaff(item)
- # Comprueba si es una búsqueda de cero o viene de la opción Siguiente
+ # Check if it is a zero search or comes from the Next option
if item.page != "":
data = httptools.downloadpage(item.page).data
else:
@@ -334,7 +327,7 @@ def filmaffinity_search(item):
patron = '.*? ]+>(.*?) >>')
if next_page != "":
next_page = urlparse.urljoin("http://www.filmaffinity.com/es/", next_page)
- itemlist.append(item.clone(title=config.get_localized_string(70502), page=next_page, action="filmaffinity_search", thumbnail="",
- text_color=""))
+ itemlist.append(item.clone(title=config.get_localized_string(70502), page=next_page, action="filmaffinity_search", thumbnail="", text_color=""))
if not itemlist:
- itemlist.append(item.clone(title=config.get_localized_string(70501) % item.contentTitle,
- action="", thumbnail="", text_color=""))
+ itemlist.append(item.clone(title=config.get_localized_string(70501) % item.contentTitle, action="", thumbnail="", text_color=""))
if keyboard:
if item.contextual:
title = "%s"
else:
title = "%s"
- itemlist.append(item.clone(title=title % config.get_localized_string(70513),
- action="manual_search", thumbnail="", extra="filmaffinity"))
+ itemlist.append(item.clone(title=title % config.get_localized_string(70513), action="manual_search", thumbnail="", extra="filmaffinity"))
return itemlist
@@ -400,8 +389,7 @@ def search_links_filmaff(item):
scrapedtitle += " [" + server + "]"
if item.contextual:
scrapedtitle = "%s" % scrapedtitle
- itemlist.append(item.clone(title=scrapedtitle, url=trailer_url, server=server, action="play",
- thumbnail=thumbnail))
+ itemlist.append(item.clone(title=scrapedtitle, url=trailer_url, server=server, action="play", thumbnail=thumbnail))
itemlist = servertools.get_servers_itemlist(itemlist)
if keyboard:
@@ -409,8 +397,7 @@ def search_links_filmaff(item):
title = "%s"
else:
title = "%s"
- itemlist.append(item.clone(title=title % config.get_localized_string(70513),
- action="manual_search", thumbnail="", extra="filmaffinity"))
+ itemlist.append(item.clone(title=title % config.get_localized_string(70513), action="manual_search", thumbnail="", extra="filmaffinity"))
return itemlist
@@ -451,7 +438,7 @@ try:
self.control_list.addItems(self.items)
self.setFocus(self.control_list)
def onClick(self, id):
- # Boton Cancelar y [X]
+ # Cancel button y [X]
if id == 5:
global window_select, result
self.result = "_no_video"
diff --git a/specials/tvmoviedb.py b/specials/tvmoviedb.py
index dc6263b2..03250850 100644
--- a/specials/tvmoviedb.py
+++ b/specials/tvmoviedb.py
@@ -1,22 +1,14 @@
# -*- coding: utf-8 -*-
-import re
-import urllib
+import re, urllib, xbmcaddon
from base64 import b64decode as bdec
-import xbmcaddon
-
from channelselector import get_thumb
-from core import filetools
-from core import httptools
-from core import jsontools
-from core import scrapertools
+from core import filetools, httptools, jsontools, scrapertools, trakt_tools
from core.item import Item
from core.support import typo
from core.tmdb import Tmdb
-from core import trakt_tools
-from platformcode import config, logger
-from platformcode import platformtools
+from platformcode import config, logger, platformtools
info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json
def_lang = info_language[config.get_setting("info_language", "videolibrary")]
@@ -102,8 +94,7 @@ def search_(item):
return listado_fa(item)
if "myanimelist" in item.url:
item.url += texto.replace(" ", "%20")
- item.url += "&type=0&score=0&status=0&p=0&r=0&sm=0&sd=0&sy=0&em=0&ed=0&ey=0&c[0]=a" \
- "&c[1]=b&c[2]=c&c[3]=d&c[4]=f&gx=0"
+ item.url += "&type=0&score=0&status=0&p=0&r=0&sm=0&sd=0&sy=0&em=0&ed=0&ey=0&c[0]=a&c[1]=b&c[2]=c&c[3]=d&c[4]=f&gx=0"
item.action = "busqueda_mal"
return busqueda_mal(item)
@@ -125,8 +116,7 @@ def search_(item):
def busqueda(item):
logger.info()
- new_item = Item(title=item.contentTitle, text=item.contentTitle.replace("+", " "), mode=item.contentType,
- infoLabels=item.infoLabels)
+ new_item = Item(title=item.contentTitle, text=item.contentTitle.replace("+", " "), mode=item.contentType, infoLabels=item.infoLabels)
from specials import search
return search.channel_search(new_item)
@@ -278,35 +268,26 @@ def trakt(item):
itemlist.append(item.clone(title=typo(config.get_localized_string(70048), 'color kod bold'), extra="cuenta"))
else:
item.extra = "movie"
- # Se comprueba si existe un token guardado y sino se ejecuta el proceso de autentificación
+ # A saved token is checked and the authentication process is executed
if not token_auth:
- #folder = (config.get_platform() == "plex")
+ # folder = (config.get_platform() == "plex")
itemlist.append(item.clone(title=config.get_localized_string(70054), action="auth_trakt", folder=folder))
else:
itemlist.append(item.clone(title=config.get_localized_string(70055), action="", ))
itemlist.append(
- item.clone(title=config.get_localized_string(60651), action="acciones_trakt", url="users/me/watchlist/movies%s" % page,
- order="added", how="desc"))
+ item.clone(title=config.get_localized_string(60651), action="acciones_trakt", url="users/me/watchlist/movies%s" % page, order="added", how="desc"))
itemlist.append(
- item.clone(title=config.get_localized_string(60652), action="acciones_trakt", url="users/me/watchlist/shows%s" % page,
- extra="show",
- order="added", how="desc"))
+ item.clone(title=config.get_localized_string(60652), action="acciones_trakt", url="users/me/watchlist/shows%s" % page, extra="show", order="added", how="desc"))
itemlist.append(item.clone(title=config.get_localized_string(70056), action="", ))
itemlist.append(
- item.clone(title=config.get_localized_string(60651), action="acciones_trakt", url="users/me/watched/movies%s" % page,
- order="added", how="desc"))
+ item.clone(title=config.get_localized_string(60651), action="acciones_trakt", url="users/me/watched/movies%s" % page, order="added", how="desc"))
itemlist.append(
- item.clone(title=config.get_localized_string(60652), action="acciones_trakt", url="users/me/watched/shows%s" % page,
- extra="show",
- order="added", how="desc"))
+ item.clone(title=config.get_localized_string(60652), action="acciones_trakt", url="users/me/watched/shows%s" % page, extra="show", order="added", how="desc"))
itemlist.append(item.clone(title=config.get_localized_string(70068), action="", ))
itemlist.append(
- item.clone(title=config.get_localized_string(60651), action="acciones_trakt", url="users/me/collection/movies%s" % page,
- order="added", how="desc"))
+ item.clone(title=config.get_localized_string(60651), action="acciones_trakt", url="users/me/collection/movies%s" % page, order="added", how="desc"))
itemlist.append(
- item.clone(title=config.get_localized_string(60652), action="acciones_trakt", url="users/me/collection/shows%s" % page,
- extra="show",
- order="added", how="desc"))
+ item.clone(title=config.get_localized_string(60652), action="acciones_trakt", url="users/me/collection/shows%s" % page, extra="show", order="added", how="desc"))
itemlist.append(
item.clone(title=config.get_localized_string(70057), action="acciones_trakt", url="users/me/lists", ))
@@ -320,24 +301,17 @@ def mal(item):
item.login = True
itemlist.append(
- item.clone(title=config.get_localized_string(70058), url="https://myanimelist.net/topanime.php?type=tv&limit=0", action="top_mal",
- contentType="tvshow", extra="tv"))
- itemlist.append(item.clone(title=config.get_localized_string(70059), url="https://myanimelist.net/topanime.php?type=movie&limit=0",
- action="top_mal",
- contentType="movie", extra="movie"))
+ item.clone(title=config.get_localized_string(70058), url="https://myanimelist.net/topanime.php?type=tv&limit=0", action="top_mal", contentType="tvshow", extra="tv"))
+ itemlist.append(item.clone(title=config.get_localized_string(70059), url="https://myanimelist.net/topanime.php?type=movie&limit=0", action="top_mal", contentType="movie", extra="movie"))
itemlist.append(
- item.clone(title=config.get_localized_string(70061), url="https://myanimelist.net/topanime.php?type=ova&limit=0", action="top_mal",
- contentType="tvshow", extra="tv", tipo="ova"))
+ item.clone(title=config.get_localized_string(70061), url="https://myanimelist.net/topanime.php?type=ova&limit=0", action="top_mal", contentType="tvshow", extra="tv", tipo="ova"))
itemlist.append(
- item.clone(title=config.get_localized_string(70028), url="https://myanimelist.net/topanime.php?type=bypopularity&limit=0",
- action="top_mal"))
- itemlist.append(item.clone(title=config.get_localized_string(70060), url="https://myanimelist.net/topanime.php?type=upcoming&limit=0",
- action="top_mal"))
+ item.clone(title=config.get_localized_string(70028), url="https://myanimelist.net/topanime.php?type=bypopularity&limit=0", action="top_mal"))
+ itemlist.append(item.clone(title=config.get_localized_string(70060), url="https://myanimelist.net/topanime.php?type=upcoming&limit=0", action="top_mal"))
itemlist.append(item.clone(title=config.get_localized_string(70062), url="", action="indices_mal"))
itemlist.append(item.clone(title=config.get_localized_string(70063), url="", action="indices_mal"))
if config.get_platform() != "plex":
- itemlist.append(item.clone(title=config.get_localized_string(70064), url="https://myanimelist.net/anime.php?q=",
- action="search_"))
+ itemlist.append(item.clone(title=config.get_localized_string(70064), url="https://myanimelist.net/anime.php?q=", action="search_"))
itemlist.append(item.clone(title=typo(config.get_localized_string(70038), 'bold submenu'), action="filtro_mal"))
itemlist.append(item.clone(title=typo(config.get_localized_string(70057), 'bold submenu'), action="cuenta_mal"))
@@ -345,15 +319,15 @@ def mal(item):
return itemlist
-##-------------------- SECCION TMDB ------------------------##
+##-------------------- SECTION TMDB ------------------------##
def listado_tmdb(item):
- # Listados principales de la categoría Tmdb (Más populares, más vistas, etc...)
+ # Main listings of the Tmdb category (Most popular, Most viewed, etc ...)
itemlist = []
item.fanart = default_fan
if not item.pagina:
item.pagina = 1
- # Listado de actores
+ # List of actors
if 'nm' in item.infoLabels['imdb_id']:
try:
@@ -370,7 +344,7 @@ def listado_tmdb(item):
else:
ob_tmdb = Tmdb(discover=item.search, tipo=item.extra, idioma_busqueda=langt)
- # Sagas y colecciones
+ # Sagas and collections
if "collection" in item.search["url"]:
try:
new_item = item.clone(action="", url='')
@@ -394,7 +368,7 @@ def listado_tmdb(item):
else:
try:
orden = False
- # Si se hace una búsqueda por actores o directores, se extraen esos resultados
+ # If you do a search for actors or directors, those results are extracted
if "cast" in ob_tmdb.result and not item.crew:
ob_tmdb.results = ob_tmdb.result["cast"]
orden = True
@@ -404,7 +378,7 @@ def listado_tmdb(item):
for i in range(0, len(ob_tmdb.results)):
new_item = item.clone(action="detalles", url='', infoLabels={'mediatype': item.contentType})
new_item.infoLabels = ob_tmdb.get_infoLabels(new_item.infoLabels, origen=ob_tmdb.results[i])
- # Si no hay sinopsis en idioma elegido, buscar en el alternativo
+ # If there is no synopsis in the chosen language, search in the alternative
if not new_item.infoLabels["plot"] and not 'person' in item.search["url"]:
ob_tmdb2 = Tmdb(id_Tmdb=new_item.infoLabels["tmdb_id"], tipo=item.extra, idioma_busqueda=langt_alt)
new_item.infoLabels["plot"] = ob_tmdb2.get_sinopsis()
@@ -443,7 +417,7 @@ def listado_tmdb(item):
% (typo(new_item.contentTitle,'bold'),
typo(new_item.infoLabels['rating'].replace("0.0", ""),'color kod bold'))
else:
- # Si es una búsqueda de personas se incluye en el título y fanart una película por la que es conocido
+ # If it is a search for people, a film for which it is known is included in the title and fanart
known_for = ob_tmdb.results[i].get("known_for")
type=item.type
if known_for:
@@ -475,7 +449,7 @@ def detalles(item):
itemlist = []
images = {}
data = ""
- # Si viene de seccion imdb
+ # If it comes from imdb section
if not item.infoLabels["tmdb_id"]:
headers = [['Accept-Language', langi]]
#data = httptools.downloadpage("http://www.imdb.com/title/" + item.infoLabels['imdb_id'], headers=headers,
@@ -483,7 +457,7 @@ def detalles(item):
data = httptools.downloadpage("http://www.imdb.com/title/" + item.infoLabels['imdb_id'], headers=headers).data
pics = scrapertools.find_single_match(data, 'showAllVidsAndPics.*?href=".*?(tt\d+)')
- # Imágenes imdb
+ # Imdb images
if pics:
images["imdb"] = {'url': 'http://www.imdb.com/_json/title/%s/mediaviewer' % pics}
@@ -495,7 +469,7 @@ def detalles(item):
try:
item.infoLabels = ob_tmdb.get_infoLabels(item.infoLabels)
- # Si no hay sinopsis en idioma elegido, buscar en el alternativo
+ # If there is no synopsis in the chosen language, search in the alternative
if not item.infoLabels["plot"]:
item.infoLabels["plot"] = ob_tmdb.get_sinopsis(idioma_alternativo=langt_alt)
except:
@@ -505,7 +479,7 @@ def detalles(item):
if item.infoLabels['thumbnail']:
item.thumbnail = item.infoLabels['thumbnail']
- # Sinopsis, votos de imdb
+ # Synopsis, votes from imdb
if data:
plot = scrapertools.find_single_match(data, 'class="inline canwrap" itemprop="description">(.*?) ')
plot = scrapertools.htmlclean(plot)
@@ -525,29 +499,24 @@ def detalles(item):
itemlist.append(item.clone(title="--- %s ---" % item.infoLabels['tagline'], action=""))
title = item.contentType.replace("movie", config.get_localized_string(70283)).replace("tvshow", "serie")
- # Búsqueda por títulos idioma elegido y/o versión original y español
+ # Search by titles chosen language and / or original version and Spanish
itemlist.append(item.clone(action="busqueda", title=config.get_localized_string(70069) % (title, item.contentTitle)))
if item.infoLabels['originaltitle'] and item.contentTitle != item.infoLabels['originaltitle']:
- itemlist.append(item.clone(action="busqueda", contentTitle=item.infoLabels['originaltitle'],
- title=config.get_localized_string(70070) % item.infoLabels['originaltitle']))
+ itemlist.append(item.clone(action="busqueda", contentTitle=item.infoLabels['originaltitle'], title=config.get_localized_string(70070) % item.infoLabels['originaltitle']))
if langt != "es" and langt != "en" and item.infoLabels["tmdb_id"]:
tmdb_lang = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], tipo=item.extra, idioma_busqueda=def_lang)
if tmdb_lang.result.get("title") and tmdb_lang.result["title"] != item.contentTitle \
and tmdb_lang.result["title"] != item.infoLabels['originaltitle']:
tmdb_lang = tmdb_lang.result["title"]
- itemlist.append(item.clone(action="busqueda", title=config.get_localized_string(70066) % tmdb_lang,
- contentTitle=tmdb_lang))
+ itemlist.append(item.clone(action="busqueda", title=config.get_localized_string(70066) % tmdb_lang, contentTitle=tmdb_lang))
- # En caso de serie, opción de info por temporadas
+ # In case of series, option of info by seasons
if item.contentType == "tvshow" and item.infoLabels['tmdb_id']:
- itemlist.append(item.clone(action="info_seasons",
- title=config.get_localized_string(70067) % item.infoLabels["number_of_seasons"]))
- # Opción de ver el reparto y navegar por sus películas/series
+ itemlist.append(item.clone(action="info_seasons", title=config.get_localized_string(70067) % item.infoLabels["number_of_seasons"]))
+ # Option to watch the cast and browse their movies / series
if item.infoLabels['tmdb_id']:
- itemlist.append(item.clone(action="reparto", title=config.get_localized_string(70071),
- infoLabels={'tmdb_id': item.infoLabels['tmdb_id'],
- 'mediatype': item.contentType}))
+ itemlist.append(item.clone(action="reparto", title=config.get_localized_string(70071), infoLabels={'tmdb_id': item.infoLabels['tmdb_id'], 'mediatype': item.contentType}))
if config.is_xbmc():
item.contextual = True
@@ -556,8 +525,7 @@ def detalles(item):
try:
images['tmdb'] = ob_tmdb.result["images"]
- itemlist.append(item.clone(action="imagenes", title=config.get_localized_string(70316), images=images,
- extra="menu"))
+ itemlist.append(item.clone(action="imagenes", title=config.get_localized_string(70316), images=images, extra="menu"))
except:
pass
@@ -580,9 +548,7 @@ def detalles(item):
url_album = scrapertools.find_single_match(data_music, 'album(?:|s) on request.*?href="([^"]+)"')
if url_album:
url_album = "https://nl.hideproxy.me" + url_album
- itemlist.append(
- item.clone(action="musica_movie", title=config.get_localized_string(70317), url=url_album,
- ))
+ itemlist.append(item.clone(action="musica_movie", title=config.get_localized_string(70317), url=url_album))
except:
pass
@@ -591,7 +557,7 @@ def detalles(item):
itemlist.append(item.clone(title=config.get_localized_string(70318), action="menu_trakt"))
itemlist.append(item.clone(title="", action=""))
- # Es parte de una colección
+ # It is part of a collection
try:
if ob_tmdb.result.get("belongs_to_collection"):
new_item = item.clone(search='', infoLabels={'mediatype': item.contentType})
@@ -602,12 +568,11 @@ def detalles(item):
if saga["backdrop_path"]:
new_item.fanart = 'http://image.tmdb.org/t/p/original' + saga["backdrop_path"]
new_item.search = {'url': 'collection/%s' % saga['id'], 'language': langt}
- itemlist.append(new_item.clone(title=config.get_localized_string(70327) % saga["name"], action="listado_tmdb",
- ))
+ itemlist.append(new_item.clone(title=config.get_localized_string(70327) % saga["name"], action="listado_tmdb"))
except:
pass
- # Películas/Series similares y recomendaciones
+ # Similar Movies / Series and Recommendations
if item.infoLabels['tmdb_id']:
item.extra = item.contentType.replace('tvshow', 'tv')
title = title.replace("película", config.get_localized_string(70137)).replace("serie", config.get_localized_string(30123))
@@ -624,7 +589,7 @@ def detalles(item):
def reparto(item):
- # Actores y equipo de rodaje de una película/serie
+ # Actors and film crew for a movie / series
itemlist = []
item.extra=item.contentType.replace('tvshow','tv')
item.search = {'url': '%s/%s/credits' % (item.extra, item.infoLabels['tmdb_id'])}
@@ -672,7 +637,7 @@ def reparto(item):
def info_seasons(item):
- # Info de temporadas y episodios
+ # Season and episode info
itemlist = []
ob_tmdb = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], tipo="tv", idioma_busqueda=langt)
@@ -719,7 +684,7 @@ def info_seasons(item):
def indices_tmdb(item):
- # Indices por genero y año
+ # Indices by gender and year
itemlist = []
from datetime import datetime
if config.get_localized_string(70032) in item.title:
@@ -835,7 +800,7 @@ def filtro(item):
def filtrado(item, values):
values_copy = values.copy()
- # Guarda el filtro para que sea el que se cargue por defecto
+ # Save the filter to be the one loaded by default
if "save" in values and values["save"]:
values_copy.pop("save")
config.set_setting("filtro_defecto_" + item.extra, values_copy, item.channel)
@@ -882,24 +847,24 @@ def musica_movie(item):
return itemlist
-##-------------------- SECCION IMDB ------------------------##
+##-------------------- SECTION IMDB ------------------------##
def listado_imdb(item):
- # Método principal para secciones de imdb
+ # Main method for imdb sections
itemlist = []
headers = [['Accept-Language', langi]]
if "www.imdb.com" in item.url:
- #data = httptools.downloadpage(item.url, headers=headers, replace_headers=True).data
+ # data = httptools.downloadpage(item.url, headers=headers, replace_headers=True).data
data = httptools.downloadpage(item.url, headers=headers).data
else:
url = 'http://www.imdb.com/search/title?' + item.url
- #data = httptools.downloadpage(url, headers=headers, replace_headers=True).data
+ # data = httptools.downloadpage(url, headers=headers, replace_headers=True).data
data = httptools.downloadpage(url, headers=headers).data
data = re.sub(r"\n|\r|\t| ", "", data)
data = re.sub(r"\s{2}", " ", data)
- # Listado de actores
+ # List of actors
if 'search/name' in item.url:
patron = ' | .*?src="([^"]+)".*?href="/name/(nm\d+).*?>([^<]+)<.*?href.*?>([^<]+)' \
'(.*?) | '
@@ -996,7 +961,7 @@ def filtro_imdb(item):
valores = {}
dict_values = None
- # Se utilizan los valores por defecto/guardados
+ # Default / saved values are used
valores_guardados = config.get_setting("filtro_defecto_imdb_" + item.extra, item.channel)
if valores_guardados:
dict_values = valores_guardados
@@ -1086,7 +1051,7 @@ def filtro_imdb(item):
def filtrado_imdb(item, values):
values_copy = values.copy()
- # Guarda el filtro para que sea el que se cargue por defecto
+ # Save the filter to be the one loaded by default
if "save" in values and values["save"]:
values_copy.pop("save")
config.set_setting("filtro_defecto_imdb_" + item.extra, values_copy, item.channel)
@@ -1119,7 +1084,7 @@ def filtrado_imdb(item, values):
def indices_imdb(item):
- # Índices imdb por año y genero
+ # Imdb indices by year and gender
itemlist = []
from datetime import datetime
if config.get_localized_string(70032) in item.title:
@@ -1149,12 +1114,12 @@ def indices_imdb(item):
return itemlist
-##-------------------- SECCION FILMAFFINITY ------------------------##
+##-------------------- FILMAFFINITY SECTION ------------------------##
def listado_fa(item):
- # Método para listados principales de filmaffinity
+ # Filmaffinity main listing method
itemlist = []
- # Listados con paginación por post
+ # Listings with pagination per post
if item.extra == "top":
if item.page_fa:
post = "from=%s" % item.page_fa
@@ -1176,7 +1141,7 @@ def listado_fa(item):
data = re.sub(r"\s{2}", " ", data)
votaciones = []
- # Si es la sección de estrenos cambia la estructura del scraper
+ # If it is the premiere section, change the structure of the scraper
if item.extra == "estrenos":
patron = '\s*(\d+[^<]+)<(.*?)(?:|' \
'
.*?
([^<]+)').strip()
if item.contentType == "movie":
item.infoLabels['originaltitle'] = re.sub(r"(?i)\(TV Series\)|\(S\)|\(TV\)", "", orig_title)
@@ -1426,11 +1391,11 @@ def detalles_fa(item):
ob_tmdb = Tmdb(id_Tmdb=ob_tmdb.get_id(), tipo=item_tmdb.extra, idioma_busqueda=langt)
item.infoLabels = ob_tmdb.get_infoLabels(item.infoLabels)
- # Si no hay sinopsis en idioma elegido, buscar en el alternativo
+ # If there is no synopsis in the chosen language, search in the alternative
if not item.infoLabels["plot"]:
item.infoLabels["plot"] = ob_tmdb.get_sinopsis(idioma_alternativo=langt_alt)
- # Se concatena el plot de filmaffinity al de tmdb si lo hay
+ # The filmaffinity plot is concatenated to the tmdb plot if any
plot = scrapertools.find_single_match(data, '(.*?)')
plot = plot.replace("
", "\n")
plot = scrapertools.decodeHtmlentities(plot).replace(" (FILMAFFINITY)", "")
@@ -1439,7 +1404,7 @@ def detalles_fa(item):
elif plot and not item.infoLabels['plot']:
item.infoLabels['plot'] = plot
- # Se busca y rellena con la info de filmaffinity para diferenciarla de tmdb
+ # It is searched and filled with the filmaffinity info to differentiate it from tmdb
if not item.infoLabels['duration']:
duration = scrapertools.find_single_match(data, '(\d+)')
if duration:
@@ -1544,7 +1509,7 @@ def detalles_fa(item):
token_auth = config.get_setting("token_trakt", "trakt")
if token_auth and ob_tmdb.result:
itemlist.append(item.clone(title=config.get_localized_string(70323), action="menu_trakt"))
- # Acciones si se configura cuenta en FA (Votar y añadir/quitar en listas)
+ # Actions if account is configured in FA (Vote and add / remove in lists)
mivoto = scrapertools.find_single_match(data, 'bg-my-rating.*?>\s*(\d+)')
itk = scrapertools.find_single_match(data, 'data-itk="([^"]+)"')
folder = not config.is_xbmc()
@@ -1568,7 +1533,7 @@ def detalles_fa(item):
new_item.infoLabels["duration"] = ""
itemlist.append(new_item)
- # Si pertenece a una saga/colección
+ # If you belong to a saga / collection
if ob_tmdb.result:
itemlist.append(item.clone(title="", action="", infoLabels={}))
if ob_tmdb.result.get("belongs_to_collection"):
@@ -1603,7 +1568,7 @@ def filtro_fa(item):
valores = {}
dict_values = None
- # Se utilizan los valores por defecto/guardados
+ # Default / saved values are used
valores_guardados = config.get_setting("filtro_defecto_filmaf_" + item.extra, item.channel)
if valores_guardados:
dict_values = valores_guardados
@@ -1675,7 +1640,7 @@ def filtro_fa(item):
def filtrado_fa(item, values):
values_copy = values.copy()
- # Guarda el filtro para que sea el que se cargue por defecto
+ # Save the filter to be the one loaded by default
if "save" in values and values["save"]:
values_copy.pop("save")
config.set_setting("filtro_defecto_filmaf_" + item.extra, values_copy, item.channel)
@@ -1732,7 +1697,7 @@ def login_fa():
def cuenta_fa(item):
- # Menú de cuenta filmaffinity
+ # Filmaffinity account menu
itemlist = []
login, message = login_fa()
if not login:
@@ -1748,7 +1713,7 @@ def cuenta_fa(item):
def acciones_fa(item):
- # Acciones cuenta filmaffinity, votar, ver listas o añadir/quitar de lista
+ # Actions account filmaffinity, vote, view lists or add / remove from list
itemlist = []
if item.accion == "votos" or item.accion == "lista":
@@ -1847,7 +1812,7 @@ def acciones_fa(item):
def votar_fa(item):
- # Ventana para seleccionar el voto
+ # Window to select the vote
logger.info()
list_controls = []
@@ -1889,7 +1854,7 @@ def callback_voto(item, values):
def newlist(item):
- # Creación de nueva lista en filmaffinity
+ # Creation of new list in filmaffinity
itemlist = []
if item.accion == "lista":
location = httptools.downloadpage(item.url, only_headers=True).headers["location"]
@@ -1910,7 +1875,7 @@ def newlist(item):
return itemlist
-##-------------------- LISTADOS DE IMAGENES ------------------------##
+##-------------------- IMAGE LISTINGS ------------------------##
def imagenes(item):
itemlist = []
@@ -2055,13 +2020,13 @@ def fanartv(item):
return item, resultado
-##-------------------- SECCION TRAKT.TV ------------------------##
+##-------------------- SECTION TRAKT.TV ------------------------##
def auth_trakt(item):
return trakt_tools.auth_trakt()
def menu_trakt(item):
- # Menú con acciones de cuenta trakt (vistas, watchlist, coleccion)
+ # Menu with trakt account actions (views, watchlist, collection)
itemlist = []
token_auth = config.get_setting("token_trakt", "trakt")
tipo = item.extra.replace("tv", "show") + "s"
@@ -2279,9 +2244,9 @@ def order_trakt(item, values):
return acciones_trakt(item)
-##-------------------- SECCION MYANIMELIST ------------------------##
+##-------------------- MYANIMELIST SECTION ------------------------##
def top_mal(item):
- # Para los menús principales de tops pelícuas/series/ovas
+ # For the main menus of movie tops / series / ova
itemlist = []
data = httptools.downloadpage(item.url, cookies=False).data
data = re.sub(r"\n|\r|\t| ", "", data)
@@ -2388,7 +2353,7 @@ def detalles_mal(item):
ob_tmdb = Tmdb(id_Tmdb=ob_tmdb.get_id(), tipo=item_tmdb.extra, idioma_busqueda=langt)
item.infoLabels = ob_tmdb.get_infoLabels(item.infoLabels)
- # Se concatena sinopsis myanimelist con la de tmdb si la hubiese
+ # Myanimelist synopsis is concatenated with that of tmdb if any
plot = scrapertools.find_single_match(data, '(.*?)')
plot = plot.replace("
", "\n").replace("", "[I]").replace("", "[/I]")
plot = scrapertools.decodeHtmlentities(plot)
@@ -2411,7 +2376,7 @@ def detalles_mal(item):
except:
pass
- # Se sobreescribe la info de myanimelist sobre la de tmdb
+ # Myanimelist info overwrites tmdb info
generos = scrapertools.find_single_match(data, 'Genres:(.*?)')
if generos:
item.infoLabels['genre'] = scrapertools.htmlclean(generos)
@@ -2445,7 +2410,7 @@ def detalles_mal(item):
itemlist.append(item.clone(action="videos_mal", title=config.get_localized_string(70353),
url=item.url + "/video"))
- # Opción para ver la info de personajes y dobladores/equipo de rodaje
+ # Option to see the info of characters and voiceovers / filming equipment
if not "No characters or voice actors" in data and not "No staff for this anime" in data:
itemlist.append(item.clone(action="staff_mal", title=config.get_localized_string(70354),
url=item.url + "/characters"))
@@ -2497,7 +2462,7 @@ def detalles_mal(item):
if token_auth and ob_tmdb.result:
itemlist.append(item.clone(title=config.get_localized_string(70323), action="menu_trakt"))
- # Se listan precuelas, secuelas y series alternativas
+ # Prequels, sequels and alternative series are listed
prequel = scrapertools.find_single_match(data, 'Prequel:(.*?)')
if prequel:
matches = scrapertools.find_multiple_matches(prequel, 'href="([^"]+)">(.*?)')
@@ -2550,7 +2515,7 @@ def detalles_mal(item):
search={'url': '%s/%s/recommendations' % (item.extra, item.infoLabels['tmdb_id']),
'language': langt, 'page': 1}, ))
- # Recomendaciones myanimelist y búsqueda de info en anidb (fansubs en español)
+ # Myanimelist recommendations and info search on anidb (fansubs in Spanish)
itemlist.append(item.clone(title=config.get_localized_string(70359), action="reco_mal"))
anidb_link = scrapertools.find_single_match(data,
'