Skip to content

Commit

Permalink
Support login to torec, if no login or login has failed - failing bac…
Browse files Browse the repository at this point in the history
…k to guest user (XBMCil#53)

* Support login to torec, if no login or login has failed - failing back to guest user

* Saving cookie on login. Chekcing if cookie exists, if yes, try to use it

* fix cookie permissions on non root Kodi run

* 1.4.2 - login to seperated function on get_download_link

* 1.4.* -> consolidate to 1.4.0
  • Loading branch information
gabik authored and Mor Sela committed Apr 14, 2017
1 parent 41db7a0 commit aee7f59
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 18 deletions.
2 changes: 1 addition & 1 deletion addon.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="service.subtitles.torec"
name="Torec"
version="1.3.1"
version="1.4.0"
provider-name="slmosl">
<requires>
<import addon="xbmc.python" version="2.14.0"/>
Expand Down
8 changes: 8 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
1.4.0
- Add login feature - Will download the subtitles from Torec with registered
user credentials
- Save session on cookie and rerty with it next time, if session not valid
will try to re-login and get new session
- Fix cookie permissions
- Added tests for both movies and tvshows download

1.3.1
- Fixed broken download due to site changes and added some future changes protection

Expand Down
76 changes: 63 additions & 13 deletions resources/lib/TorecSubtitlesDownloader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-

import os
import cookielib
import datetime
import re
Expand All @@ -8,10 +9,12 @@
import zlib
import json
import itertools
import random

import bs4

import xbmc
import xbmcaddon
from SubtitleHelper import log

class SubtitleOption(object):
Expand Down Expand Up @@ -78,13 +81,19 @@ class FirefoxURLHandler(object):
Firefox user agent class
"""
def __init__(self):
cookie = "torec.cookie"
cj = cookielib.MozillaCookieJar(cookie)
self.__addon__ = xbmcaddon.Addon(id="service.subtitles.torec")
self.__addonname__ = self.__addon__.getAddonInfo('id')

dataroot = xbmc.translatePath('special://profile/addon_data/%s' % self.__addonname__ ).decode('utf-8')
cookie = os.path.join(dataroot, "torec.cookie")
self.cj = cookielib.LWPCookieJar(cookie)
if os.path.exists(cookie):
self.cj.load(ignore_discard=True)

self.opener = urllib2.build_opener(
urllib2.HTTPRedirectHandler(),
urllib2.HTTPHandler(),
urllib2.HTTPCookieProcessor(cj)
urllib2.HTTPCookieProcessor(self.cj)
)
self.opener.addheaders = [
(
Expand All @@ -96,20 +105,29 @@ def __init__(self):
]

def login(self):
username = __addon__.getSetting("username")
password = __addon__.getSetting("password")
username = self.__addon__.getSetting("username")
password = self.__addon__.getSetting("password")
log(__name__, "Checking if the user filled login credentials on Settings")
if not username or not password:
log(__name__, "No login creds, failing back to guest")
return False

log(__name__, "Settings filled with username and password, trying to login")
login_data_ = {
"ref": "/Default.asp?",
"Form": "True",
"site": "true",
"form": "true",
"username": username,
"password": password,
"login": "submit"
}
login_data = urllib.urlencode(login_data_)
login_url = "http://www.torec.net/login.asp"
rnd_float = random.uniform(0.1, 0.9)
login_url = 'http://www.torec.net/ajax/login/t7/loginProcess.asp?rnd={0}'.format(rnd_float)
log(__name__, "Login URL: %s" % login_url)
# For debug, not for prod - will pring credentials to log.
#log(__name__, "Login params: %s" % login_data)
response = self.opener.open(login_url, login_data)
content = ''.join(response.readlines())
content = ''.join(response.read())
log(__name__, "Response: %s" % content)
self.cj.save(ignore_discard=True)
return username in content

class TorecGuestTokenGenerator():
Expand Down Expand Up @@ -267,13 +285,16 @@ def _confirm_download_code(self, sub_id, option_id):
response = self.opener.open("%s/ajax/sub/t7/guest_dl_code.asp" % self.BASE_URL, urllib.urlencode(params))
response_data = response.read()

def _try_get_download_link(self, sub_id, option_id, guest_token):
def _try_get_download_link(self, sub_id, option_id, guest_token, is_login=False):
if guest_token is None:
guest_token = ""

encoded_params = urllib.urlencode({
"sub_id": sub_id,
"code": option_id,
"sh": "yes",
"guest": guest_token,
"timewaited": 13
"timewaited": -1 if is_login else 13
})

response = self.opener.open("%s/ajax/sub/t7/downloadun.asp" % self.BASE_URL, encoded_params)
Expand Down Expand Up @@ -303,9 +324,38 @@ def _get_download_link_with_regular_token(self, sub_id, option_id):

return download_link

def _get_download_link_with_login(self, sub_id, option_id):
# Checking if we have cookie - if so, we will try to use it
log(__name__, "Checking if we have cookie")
cookie_root = 'www.torec.net'
cookie_name = 'Torec%5FNC%5Fsite'
if cookie_root in self.cj._cookies and \
cookie_name in self.cj._cookies[cookie_root]['/'] and \
self.__addon__.getSetting("username") in self.cj._cookies[cookie_root]['/'][cookie_name].value:
log(__name__, "Cookie found. Trying to get link")
download_link = self._try_get_download_link(sub_id, option_id, None, True)
if download_link:
return download_link

# Checking if the user has credentials, if so - logging in and downloading,
# If not (or the login failed) - failing back to guest user download
log(__name__, "Trying to login")
if self.login():
log(__name__, "Logged in. Trying to get link")
download_link = self._try_get_download_link(sub_id, option_id, None, True)
if download_link:
return download_link

return None

def get_download_link(self, sub_id, option_id):
self._confirm_download_code(sub_id, option_id)

# Will try to download with logged in user
download_link = self._get_download_link_with_login(sub_id, option_id)
if download_link:
return download_link

log(__name__, "trying to retrieve download link with skewed generated guest token")
generated_time_skewed_guest_token = TorecGuestTokenGenerator(sub_id, True).generate_ticket()
download_link = self._try_get_download_link(sub_id, option_id, generated_time_skewed_guest_token)
Expand Down
2 changes: 1 addition & 1 deletion tests/movie_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ def _assert_subtitle_data(self, subtitleData, fileName):
break

if __name__ == '__main__':
unittest.main()
unittest.main(verbosity=2)
5 changes: 4 additions & 1 deletion tests/xbmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ def log(message, level):
print(message)

def sleep(msec):
time.sleep(msec / 1000.0)
time.sleep(msec / 1000.0)

def translatePath(path):
return "/tmp"
23 changes: 21 additions & 2 deletions tests/xbmcaddon.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
class Addon(object):
def getAddonInfo(self, type):
pass
def __init__(self, id=None):
pass

def getAddonInfo(self, type):
if type == "id":
return "Torec"
pass

def openSetting(self):
""" Can simulate openSettings xbmc call """
print "Settings"

def getSetting(self, kind):
""" For unittest - you can return real user credentials
to check user login.
returning Nano or empty string will skip login
"""
if kind == "username":
return "A"
elif kind == "password":
return "X"

0 comments on commit aee7f59

Please sign in to comment.