From 3f8af5efc85b04f107f5129b71f77c5ee74bd08f Mon Sep 17 00:00:00 2001 From: marco Date: Wed, 7 Oct 2020 20:54:03 +0200 Subject: [PATCH] HDmario: fix registrazione automatica (supporto a captcha e verifica mail) --- lib/fakeMail.py | 131 ++++++++++++++++++++++ lib/onesecmail.py | 56 --------- platformcode/platformtools.py | 74 +++++++++++- resources/skins/Default/720p/Register.xml | 125 +++++++++++++++++++++ servers/hdmario.py | 126 +++++++++++++-------- 5 files changed, 406 insertions(+), 106 deletions(-) create mode 100644 lib/fakeMail.py delete mode 100644 lib/onesecmail.py create mode 100644 resources/skins/Default/720p/Register.xml diff --git a/lib/fakeMail.py b/lib/fakeMail.py new file mode 100644 index 00000000..4e5f7217 --- /dev/null +++ b/lib/fakeMail.py @@ -0,0 +1,131 @@ +import random +import string +import time + +from core import httptools, support +from platformcode import platformtools, config, logger + + +class Mailbox: + def __init__(self): + self.address = self.new() + if '@' in self.address: + self.user, self.domain = self.address.split('@') + else: + self.user = None + self.domain = None + + def new(self): + return 'test@ciao.it' + + def inbox(self): + pass + + def readLast(self): + pass + + def waitForMail(self, timeout=50): + info = 'verifica tramite mail richiesta dal sito, sono in attesa di nuove mail sulla casella ' + self.address + # info += '\nTimeout tra ' + str(timeout) + ' secondi' + dialog = platformtools.dialog_progress(config.get_localized_string(20000), info) + secs = 0 + while secs < timeout: + msg = self.readLast() + logger.debug('Checked mail ' + self.address) + if msg: + dialog.close() + logger.debug(msg) + return msg + else: + time.sleep(1) + secs += 1 + dialog.update(0, info + '\nTimeout tra ' + str(timeout-secs) + ' secondi') + if dialog.iscanceled(): + break + logger.debug('No mail found, timeout reached or dialog canceled') + return None + + +class Email: + def __init__(self, subject='', body='', sender='', date=''): + self.subject = subject + self.body = body + self.sender = sender + self.date = date + + def __repr__(self): + r = "Date: " + self.date + '\n' + r += "Subject: " + self.subject + '\n' + r += "Sender: " + self.sender + '\n\n' + r += self.body + return r + + +class OneSecMailbox(Mailbox): + def __init__(self): + self.defDomain = '1secmail.com' + self.baseUrl = 'https://www.1secmail.com/api/v1/' + + Mailbox.__init__(self) + if not self.domain: + self.domain = self.defDomain + self.user = self.address + + def inbox(self): + """ + :return: json containing inbox id and subjects + """ + apiUrl = self.baseUrl + '?action=getMessages&login=' + self.user + '&domain=' + self.domain + return httptools.downloadpage(apiUrl).json + + def readLast(self): + try: + id = self.inbox()[0]['id'] + except: + return None + apiUrl = self.baseUrl + '?action=readMessage&login=' + self.user + '&domain=' + self.domain + '&id=' + str(id) + j = httptools.downloadpage(apiUrl).json + + return Email(j['subject'], j['htmlBody'], j['from'], j['date']) + + def new(self, len=10): + letters = string.ascii_lowercase + return ''.join(random.choice(letters) for i in range(len)) + '@' + self.defDomain + + +class Gmailnator(Mailbox): + def __init__(self, domains=('.gmail',)): + self.baseUrl = 'https://gmailnator.com/' + self.genDomains = { + 'gmailnator': 1, + '+gmail': 2, + '.gmail': 3 + } + self.data = [self.genDomains[d] for d in domains] + Mailbox.__init__(self) + + def new(self): + self.csrf = support.match(self.baseUrl, patron='csrf-token" content="([a-z0-9]+)').match + logger.debug(self.csrf) + e = httptools.downloadpage(self.baseUrl + 'index/indexquery', post={'csrf_gmailnator_token': self.csrf, 'action': 'GenerateEmail', 'data[]': self.data}) + if e.success: + return e.data + else: + platformtools.dialog_ok(config.get_localized_string(20000), 'Impossibile ottenere una mail temporanea') + + def inbox(self): + #[{"content":"\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
dsds<\/td>\n\t\t\t\t\t\t\t\tbody<\/td>\n\t\t\t\t\t\t\t\tone minute ago<\/td>\n\t\t\t\t\t\t\t<\/tr>\n\t\t\t\t\t\t<\/tbody>\n\t\t\t\t\t<\/table>\n\t\t\t\t<\/a>"}] + return httptools.downloadpage(self.baseUrl + 'mailbox/mailboxquery', post={'csrf_gmailnator_token': self.csrf, 'action': 'LoadMailList', 'Email_address': self.address}).json + + def readLast(self): + inbox = self.inbox() + if inbox: + self.user, id = support.match(inbox[0]['content'], patron='([^\/]+)\/messageid\/#([a-z0-9]+)').match + #subject
2 minutes ago

body
+ html = httptools.downloadpage(self.baseUrl + 'mailbox/get_single_message/', post={'csrf_gmailnator_token': self.csrf, 'action': 'get_message', 'message_id': id, 'email': self.user}).data + logger.debug(html) + m = Email() + m.subject, m.date, m.body = support.match(html, patron='([^<]+)<\/b>
([^<]+)<\/div>
(.*)').match + + return m + return inbox diff --git a/lib/onesecmail.py b/lib/onesecmail.py deleted file mode 100644 index 7fe81993..00000000 --- a/lib/onesecmail.py +++ /dev/null @@ -1,56 +0,0 @@ -import random -import string -import time - -from core import httptools -from platformcode import platformtools, config - -baseUrl = 'https://www.1secmail.com/api/v1/' -defDomain = '1secmail.com' - -def splitMail(mail): - if '@' in mail: - user, domain = mail.split('@') - else: - user = mail - domain = defDomain - return user, domain - -def getMessages(mail): - """ - :param user: user@1secmail.com - :return: json containing inbox id and subjects - """ - user, domain = splitMail(mail) - apiUrl = baseUrl + '?action=getMessages&login=' + user + '&domain=' + domain - return httptools.downloadpage(apiUrl).json - - -def readLastMessage(mail): - user, domain = splitMail(mail) - try: - id = getMessages(mail)[0]['id'] - except: - return None - apiUrl = baseUrl + '?action=readMessage&login=' + user + '&domain=' + domain + '&id=' + str(id) - return httptools.downloadpage(apiUrl).json - - -def waitForMail(mail, timeout=50): - dialog = platformtools.dialog_progress(config.get_localized_string(20000), 'verifica tramite mail richiesta dal sito, sono in attesa di nuove mail sulla casella ' + mail) - secs = 0 - while secs < timeout: - msg = readLastMessage(mail) - if msg: - dialog.close() - return msg - else: - time.sleep(1) - secs += 1 - if dialog.iscanceled(): - break - return None - -def getRandom(len=10): - letters = string.ascii_lowercase - return ''.join(random.choice(letters) for i in range(len)) + '@' + defDomain \ No newline at end of file diff --git a/platformcode/platformtools.py b/platformcode/platformtools.py index a1a9ac23..1e6c24a1 100644 --- a/platformcode/platformtools.py +++ b/platformcode/platformtools.py @@ -110,6 +110,11 @@ def dialog_browse(_type, heading, shares="files", mask="", useThumbs=False, trea return d +def dialog_register(heading, user=False, email=False, password=False, user_default='', email_default='', password_default='', captcha_img=''): + dialog = Register('Register.xml', config.get_runtime_path()).Start(heading, user, email, password, user_default, email_default, password_default, captcha_img) + return dialog + + def itemlist_refresh(): # pos = Item().fromurl(xbmc.getInfoLabel('ListItem.FileNameAndPath')).itemlistPosition # logger.info('Current position: ' + str(pos)) @@ -136,7 +141,7 @@ def render_items(itemlist, parent_item): logger.info('START render_items') thumb_type = config.get_setting('video_thumbnail_type') from platformcode import shortcuts - from core import httptools + # from core import httptools _handle = int(sys.argv[1]) default_fanart = config.get_fanart() def_context_commands = shortcuts.context() @@ -1268,4 +1273,69 @@ def get_platform(): ret["os"] = "ios" ret["arch"] = "arm" - return ret \ No newline at end of file + return ret + + +class Register(xbmcgui.WindowXMLDialog): + def Start(self, heading, user, email, password, user_default, email_default, password_default, captcha_img): + self.result = {} + self.heading = heading + self.user = user + self.email = email + self.password = password + self.user_default = user_default + self.email_default = email_default + self.password_default = password_default + self.captcha_img = captcha_img + self.doModal() + + return self.result + + def __init__(self, *args, **kwargs): + self.mensaje = kwargs.get("mensaje") + self.imagen = kwargs.get("imagen") + + def onInit(self): + #### Kodi 18 compatibility #### + if config.get_platform(True)['num_version'] < 18: + self.setCoordinateResolution(2) + height = 90 + self.getControl(10002).setText(self.heading) + if self.user: + self.getControl(10003).setText(self.user_default) + height+=70 + else: + self.getControl(10003).setVisible(False) + if self.email: + self.getControl(10004).setText(self.email_default) + height+=70 + else: + self.getControl(10004).setVisible(False) + if self.password: + self.getControl(10005).setText(self.password_default) + height+=70 + else: + self.getControl(10005).setVisible(False) + if self.captcha_img: + + self.getControl(10007).setImage(self.captcha_img) + height+=240 + else: + self.getControl(10005).setVisible(False) + height +=40 + if height < 250: height = 250 + self.getControl(10000).setHeight(height) + self.getControl(10001).setHeight(height) + self.getControl(10000).setPosition(255, (720-height)/2) + self.setFocusId(30000) + + def onClick(self, control): + if control in [10010]: + self.close() + + elif control in [10009]: + if self.user: self.result['user'] = self.getControl(10003).getText() + if self.email: self.result['email'] = self.getControl(10004).getText() + if self.password: self.result['password'] = self.getControl(10005).getText() + if self.captcha_img: self.result['captcha'] = self.getControl(10006).getText() + self.close() \ No newline at end of file diff --git a/resources/skins/Default/720p/Register.xml b/resources/skins/Default/720p/Register.xml new file mode 100644 index 00000000..00730a38 --- /dev/null +++ b/resources/skins/Default/720p/Register.xml @@ -0,0 +1,125 @@ + + + false + + + + + + + + + + + 790 + + + 790 + white.png + + + + 60 + 600 + FFFFFFFF + true + center + center + + + + + 90 + 40 + 20 + 10009 + + 50 + 560 + FFFFFFFF + white.png + white.png + center + + + + + 50 + 560 + FFFFFFFF + white.png + white.png + center + + + + + 50 + 560 + FFFFFFFF + white.png + white.png + center + + + + + 50 + 560 + FFFFFFFF + white.png + white.png + center + + + + + 560 + 170 + 20 + keep + + + + 90 + 620 + + 0 + 0 + 150 + 50 + 110 + FFFFFFFF + FFFFFFFF + white.png + white.png + center + center + + 10010 + 10010 + 10003 + 10003 + + + 70 + 0 + 150 + 50 + 110 + FFFFFFFF + FFFFFFFF + white.png + white.png + center + center + + 10009 + 10009 + 10003 + 10003 + + + + + \ No newline at end of file diff --git a/servers/hdmario.py b/servers/hdmario.py index 27bb27e9..7252827d 100644 --- a/servers/hdmario.py +++ b/servers/hdmario.py @@ -3,6 +3,7 @@ import xbmc from core import httptools, scrapertools, filetools from platformcode import logger, config, platformtools +from lib.fakeMail import Gmailnator baseUrl = 'https://hdmario.live' @@ -20,49 +21,78 @@ def test_video_exists(page_url): def login(): - httptools.downloadpage(page.url.replace('/unauthorized', '/login'), + r = httptools.downloadpage(page.url.replace('/unauthorized', '/login'), post={'email': config.get_setting('username', server='hdmario'), 'password': config.get_setting('password', server='hdmario')}) + if not r.success or 'Email o Password non validi' in r.data: + platformtools.dialog_ok('HDmario', 'Username/password non validi') + return False + + return True -def registerOrLogin(page_url, forced=False): - if not forced and config.get_setting('username', server='hdmario') and config.get_setting('password', server='hdmario'): - login() - else: - if platformtools.dialog_yesno('HDmario', - 'Questo server necessita di un account, ne hai già uno oppure vuoi tentare una registrazione automatica?', - yeslabel='Accedi', nolabel='Tenta registrazione'): - from specials import setting - from core.item import Item - setting.server_config(Item(config='hdmario')) - login() +def registerOrLogin(page_url): + if config.get_setting('username', server='hdmario') and config.get_setting('password', server='hdmario'): + if login(): + return True + + if platformtools.dialog_yesno('HDmario', + 'Questo server necessita di un account, ne hai già uno oppure vuoi tentare una registrazione automatica?', + yeslabel='Accedi', nolabel='Tenta registrazione'): + from specials import setting + from core.item import Item + user_pre = config.get_setting('username', server='hdmario') + password_pre = config.get_setting('password', server='hdmario') + setting.server_config(Item(config='hdmario')) + user_post = config.get_setting('username', server='hdmario') + password_post = config.get_setting('password', server='hdmario') + + if user_pre != user_post or password_pre != password_post: + return registerOrLogin(page_url) else: - logger.info('Registrazione automatica in corso') - import random - import string - randEmail = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(random.randint(9, 14))) + '@gmail.com' - randPsw = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(10)) - logger.info('email: ' + randEmail) - logger.info('pass: ' + randPsw) - nTry = 0 - while nTry < 5: - nTry += 1 - rq = 'loggedin' in httptools.downloadpage(baseUrl + '/register/', - post={'email': randEmail, 'email_confirmation': randEmail, - 'password': randPsw, - 'password_confirmation': randPsw}).url - if rq: - config.set_setting('username', randEmail, server='hdmario') - config.set_setting('password', randPsw, server='hdmario') - platformtools.dialog_ok('HDmario', - 'Registrato automaticamente con queste credenziali:\nemail:' + randEmail + '\npass: ' + randPsw) - break + return False + else: + import random + import string + logger.info('Registrazione automatica in corso') + mailbox = Gmailnator() + randPsw = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(10)) + captcha = httptools.downloadpage(baseUrl + '/captchaInfo').json + logger.info('email: ' + mailbox.address) + logger.info('pass: ' + randPsw) + reg = platformtools.dialog_register(baseUrl + '/register/', email=True, password=True, email_default=mailbox.address, password_default=randPsw, captcha_img=captcha['captchaUrl']) + if not reg: + return False + regPost = httptools.downloadpage(baseUrl + '/register/', + post={'email': reg['email'], 'email_confirmation': reg['email'], + 'password': reg['password'], + 'password_confirmation': reg['password'], + 'captchaUuid': captcha['captchaUuid'], + 'captcha': reg['captcha']}) + if '/register' in regPost.url: + error = scrapertools.htmlclean(scrapertools.find_single_match(regPost.data, 'Impossibile proseguire.*?
')) + error = scrapertools.unescape(scrapertools.re.sub('\n\s+', ' ', error)) + platformtools.dialog_ok('HDmario', error) + return False + if reg['email'] == mailbox.address: + mail = mailbox.waitForMail() + if mail: + checkUrl = scrapertools.find_single_match(mail.body, 'href="([^"]+)">Premi qui') + httptools.downloadpage(checkUrl) + config.set_setting('username', mailbox.address, server='hdmario') + config.set_setting('password', randPsw, server='hdmario') + platformtools.dialog_ok('HDmario', + 'Registrato automaticamente con queste credenziali:\nemail:' + mailbox.address + '\npass: ' + randPsw) else: platformtools.dialog_ok('HDmario', 'Impossibile registrarsi automaticamente') - logger.info('Registrazione completata') - global page, data - page = httptools.downloadpage(page_url) - data = page.data + return False + else: + platformtools.dialog_ok('HDmario', 'Hai modificato la mail quindi KoD non sarà in grado di effettuare la verifica in autonomia, apri la casella ' + reg['email'] + + ' e clicca sul link. Premi ok quando fatto') + logger.info('Registrazione completata') + + return True + def get_video_url(page_url, premium=False, user="", password="", video_password=""): global page, data @@ -70,27 +100,27 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= logger.info("url=" + page_url) if 'unconfirmed' in page.url: - from lib import onesecmail id = page_url.split('/')[-1] - mail = onesecmail.getRandom() + mailbox = Gmailnator() postData = { - 'email': mail, + 'email': mailbox.address, 'hls_video_id': id } httptools.downloadpage(page.url, post=postData) - jsonMail = onesecmail.waitForMail(mail) - logger.info(jsonMail) - if jsonMail: - code = jsonMail['subject'].split(' - ')[0] + mail = mailbox.waitForMail() + logger.info(mail) + if mail: + code = mail.subject.split(' - ')[0] page = httptools.downloadpage(page_url + '?code=' + code) data = page.data - if '/unauthorized' in page.url: - registerOrLogin(page_url) + if '/unauthorized' in page.url or '/not-active' in page.url: + httptools.set_cookies({}, True) # clear cookies + if not registerOrLogin(page_url): + return [] + page = httptools.downloadpage(page_url) + data = page.data - if 'Registrati' in data: - platformtools.dialog_ok('HDmario', 'Username/password non validi') - registerOrLogin(page_url, True) logger.info(data) from lib import jsunpack_js2py unpacked = jsunpack_js2py.unpack(scrapertools.find_single_match(data, '