Skip to content

Commit

Permalink
Merge pull request #8450 from pymedusa/release/release-0.4.2
Browse files Browse the repository at this point in the history
Release/release 0.4.2
  • Loading branch information
medariox authored Sep 6, 2020
2 parents 20915b5 + d111937 commit 708c2e9
Show file tree
Hide file tree
Showing 120 changed files with 11,161 additions and 14,884 deletions.
19 changes: 16 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
## 0.4.1 (2020-08-18)

#### New Features
## 0.4.2 (2020-09-06)

#### Improvements
- Added new page "restart", for restarting and shutting down medusa ([8399](https://github.com/pymedusa/Medusa/pull/8399))
- Added new page "update", for updating medusa to a new version ([8437](https://github.com/pymedusa/Medusa/pull/8437))

#### Fixes
- Fix show-selector using the show lists ([8426](https://github.com/pymedusa/Medusa/pull/8426))
- Fix home poster layout. Re-add the search by show title ([8415](https://github.com/pymedusa/Medusa/pull/8415))
- Fix backlog search ignoring cached search results ([8395](https://github.com/pymedusa/Medusa/pull/8395))
- Fix guessit parsing numbered episode titles as multi season ([8413](https://github.com/pymedusa/Medusa/pull/8413))
- Fix History page showing black text (on black) when using dark theme ([8375](https://github.com/pymedusa/Medusa/pull/8375))

-----

## 0.4.1 (2020-08-18)

#### Fixes
- Fixed show titles displayed in white text on the schedule page ([#8338](https://github.com/pymedusa/Medusa/pull/8338))
Expand All @@ -11,6 +22,8 @@
- Fixed home table layouts previous and next episode sorting ([#8337](https://github.com/pymedusa/Medusa/pull/8337))
- Fixed show's show lists not stored after restart ([#8337](https://github.com/pymedusa/Medusa/pull/8337))

-----

## 0.4.0 (2020-08-15)

#### New Features
Expand Down
166 changes: 126 additions & 40 deletions ext/cloudscraper/__init__.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
from __future__ import absolute_import

import requests
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse

from ..exceptions import (
reCaptchaServiceUnavailable,
reCaptchaAPIError,
reCaptchaTimeout,
reCaptchaParameter,
reCaptchaBadJobID,
reCaptchaReportError
CaptchaServiceUnavailable,
CaptchaAPIError,
CaptchaTimeout,
CaptchaParameter,
CaptchaBadJobID,
CaptchaReportError
)

try:
Expand All @@ -19,10 +23,10 @@
"https://github.com/justiniso/polling/"
)

from . import reCaptcha
from . import Captcha


class captchaSolver(reCaptcha):
class captchaSolver(Captcha):

def __init__(self):
super(captchaSolver, self).__init__('2captcha')
Expand All @@ -34,7 +38,7 @@ def __init__(self):
@staticmethod
def checkErrorStatus(response, request_type):
if response.status_code in [500, 502]:
raise reCaptchaServiceUnavailable('2Captcha: Server Side Error {}'.format(response.status_code))
raise CaptchaServiceUnavailable('2Captcha: Server Side Error {}'.format(response.status_code))

errors = {
'in.php': {
Expand Down Expand Up @@ -81,7 +85,7 @@ def checkErrorStatus(response, request_type):
}

if response.json().get('status') == 0 and response.json().get('request') in errors.get(request_type):
raise reCaptchaAPIError(
raise CaptchaAPIError(
'{} {}'.format(
response.json().get('request'),
errors.get(request_type).get(response.json().get('request'))
Expand All @@ -92,8 +96,8 @@ def checkErrorStatus(response, request_type):

def reportJob(self, jobID):
if not jobID:
raise reCaptchaBadJobID(
"2Captcha: Error bad job id to request reCaptcha."
raise CaptchaBadJobID(
"2Captcha: Error bad job id to request Captcha."
)

def _checkRequest(response):
Expand Down Expand Up @@ -123,15 +127,15 @@ def _checkRequest(response):
if response:
return True
else:
raise reCaptchaReportError(
"2Captcha: Error - Failed to report bad reCaptcha solve."
raise CaptchaReportError(
"2Captcha: Error - Failed to report bad Captcha solve."
)

# ------------------------------------------------------------------------------- #

def requestJob(self, jobID):
if not jobID:
raise reCaptchaBadJobID("2Captcha: Error bad job id to request reCaptcha.")
raise CaptchaBadJobID("2Captcha: Error bad job id to request Captcha.")

def _checkRequest(response):
if response.ok and response.json().get('status') == 1:
Expand Down Expand Up @@ -160,8 +164,8 @@ def _checkRequest(response):
if response:
return response.json().get('request')
else:
raise reCaptchaTimeout(
"2Captcha: Error failed to solve reCaptcha."
raise CaptchaTimeout(
"2Captcha: Error failed to solve Captcha."
)

# ------------------------------------------------------------------------------- #
Expand Down Expand Up @@ -192,6 +196,14 @@ def _checkRequest(response):
}
)

if self.proxy:
data.update(
{
'proxy': self.proxy,
'proxytype': self.proxyType
}
)

response = polling.poll(
lambda: self.session.post(
'{}/in.php'.format(self.host),
Expand All @@ -207,24 +219,35 @@ def _checkRequest(response):
if response:
return response.json().get('request')
else:
raise reCaptchaBadJobID(
raise CaptchaBadJobID(
'2Captcha: Error no job id was returned.'
)

# ------------------------------------------------------------------------------- #

def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams):
def getCaptchaAnswer(self, captchaType, url, siteKey, captchaParams):
jobID = None

if not reCaptchaParams.get('api_key'):
raise reCaptchaParameter(
if not captchaParams.get('api_key'):
raise CaptchaParameter(
"2Captcha: Missing api_key parameter."
)

self.api_key = reCaptchaParams.get('api_key')
self.api_key = captchaParams.get('api_key')

if reCaptchaParams.get('proxy'):
self.session.proxies = reCaptchaParams.get('proxies')
if captchaParams.get('proxy') and not captchaParams.get('no_proxy'):
hostParsed = urlparse(captchaParams.get('proxy', {}).get('https'))

if not hostParsed.scheme:
raise CaptchaParameter('Cannot parse proxy correctly, bad scheme')

if not hostParsed.netloc:
raise CaptchaParameter('Cannot parse proxy correctly, bad netloc')

self.proxyType = hostParsed.scheme
self.proxy = hostParsed.netloc
else:
self.proxy = None

try:
jobID = self.requestSolve(captchaType, url, siteKey)
Expand All @@ -234,12 +257,12 @@ def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams):
if jobID:
self.reportJob(jobID)
except polling.TimeoutException:
raise reCaptchaTimeout(
"2Captcha: reCaptcha solve took to long and also failed reporting the job the job id {}.".format(jobID)
raise CaptchaTimeout(
"2Captcha: Captcha solve took to long and also failed reporting the job the job id {}.".format(jobID)
)

raise reCaptchaTimeout(
"2Captcha: reCaptcha solve took to long to execute job id {}, aborting.".format(jobID)
raise CaptchaTimeout(
"2Captcha: Captcha solve took to long to execute job id {}, aborting.".format(jobID)
)


Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# ------------------------------------------------------------------------------- #


class reCaptcha(ABC):
class Captcha(ABC):
@abc.abstractmethod
def __init__(self, name):
captchaSolvers[name] = self
Expand All @@ -26,21 +26,21 @@ def dynamicImport(cls, name):
if name not in captchaSolvers:
try:
__import__('{}.{}'.format(cls.__module__, name))
if not isinstance(captchaSolvers.get(name), reCaptcha):
raise ImportError('The anti reCaptcha provider was not initialized.')
if not isinstance(captchaSolvers.get(name), Captcha):
raise ImportError('The anti captcha provider was not initialized.')
except ImportError:
logging.error("Unable to load {} anti reCaptcha provider".format(name))
logging.error("Unable to load {} anti captcha provider".format(name))
raise

return captchaSolvers[name]

# ------------------------------------------------------------------------------- #

@abc.abstractmethod
def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams):
def getCaptchaAnswer(self, captchaType, url, siteKey, captchaParams):
pass

# ------------------------------------------------------------------------------- #

def solveCaptcha(self, captchaType, url, siteKey, reCaptchaParams):
return self.getCaptchaAnswer(captchaType, url, siteKey, reCaptchaParams)
def solveCaptcha(self, captchaType, url, siteKey, captchaParams):
return self.getCaptchaAnswer(captchaType, url, siteKey, captchaParams)
109 changes: 109 additions & 0 deletions ext/cloudscraper/captcha/anticaptcha.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from __future__ import absolute_import
from ..exceptions import (
CaptchaParameter,
CaptchaTimeout,
CaptchaAPIError
)

try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse

try:
from python_anticaptcha import (
AnticaptchaClient,
NoCaptchaTaskProxylessTask,
HCaptchaTaskProxyless,
NoCaptchaTask,
HCaptchaTask,
AnticaptchaException
)
except ImportError:
raise ImportError(
"Please install/upgrade the python module 'python_anticaptcha' via "
"pip install python-anticaptcha or https://github.com/ad-m/python-anticaptcha/"
)

import sys

from . import Captcha


class captchaSolver(Captcha):

def __init__(self):
if sys.modules['python_anticaptcha'].__version__ < '0.6':
raise ImportError(
"Please upgrade the python module 'python_anticaptcha' via "
"pip install -U python-anticaptcha or https://github.com/ad-m/python-anticaptcha/"
)
super(captchaSolver, self).__init__('anticaptcha')

# ------------------------------------------------------------------------------- #

def parseProxy(self, url, user_agent):
parsed = urlparse(url)

return dict(
proxy_type=parsed.scheme,
proxy_address=parsed.hostname,
proxy_port=parsed.port,
proxy_login=parsed.username,
proxy_password=parsed.password,
user_agent=user_agent
)

# ------------------------------------------------------------------------------- #

def getCaptchaAnswer(self, captchaType, url, siteKey, captchaParams):
if not captchaParams.get('api_key'):
raise CaptchaParameter("anticaptcha: Missing api_key parameter.")

client = AnticaptchaClient(captchaParams.get('api_key'))

if captchaParams.get('proxy') and not captchaParams.get('no_proxy'):
captchaMap = {
'reCaptcha': NoCaptchaTask,
'hCaptcha': HCaptchaTask
}

proxy = self.parseProxy(
captchaParams.get('proxy', {}).get('https'),
captchaParams.get('User-Agent', '')
)

task = captchaMap[captchaType](
url,
siteKey,
**proxy
)
else:
captchaMap = {
'reCaptcha': NoCaptchaTaskProxylessTask,
'hCaptcha': HCaptchaTaskProxyless
}
task = captchaMap[captchaType](url, siteKey)

if not hasattr(client, 'createTaskSmee'):
raise NotImplementedError(
"Please upgrade 'python_anticaptcha' via pip or download it from "
"https://github.com/ad-m/python-anticaptcha/tree/hcaptcha"
)

job = client.createTaskSmee(task, timeout=180)

try:
job.join(maximum_time=180)
except (AnticaptchaException) as e:
raise CaptchaTimeout('{}'.format(getattr(e, 'message', e)))

if 'solution' in job._last_result:
return job.get_solution_response()
else:
raise CaptchaAPIError('Job did not return `solution` key in payload.')


# ------------------------------------------------------------------------------- #

captchaSolver()
File renamed without changes.
Loading

0 comments on commit 708c2e9

Please sign in to comment.