diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fc9aee16..5ee95d1c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,12 @@ Changelog Due to this library relying on external content, older versions are not guaranteed to work. Try to always use the latest version. +.. _v2.3.0: + +2.3.0 (2019-09-16) +================== +- Added proxy option to client. + .. _v2.2.6: 2.2.6 (2019-09-01) diff --git a/requirements.txt b/requirements.txt index c9e6bb7f..ac662b63 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ beautifulsoup4 lxml -aiohttp \ No newline at end of file +aiohttp +aiohttp-socks \ No newline at end of file diff --git a/serve.py b/serve.py index 959e0cab..0bdc829c 100644 --- a/serve.py +++ b/serve.py @@ -143,7 +143,7 @@ async def middleware_handler(request): async def init_client(app): - app["tibiapy"] = tibiapy.Client() + app["tibiapy"] = tibiapy.Client(proxy_url='socks5://127.0.0.1:7744') if __name__ == "__main__": app = web.Application(middlewares=[error_middleware]) diff --git a/tibiapy/__init__.py b/tibiapy/__init__.py index 72c3a7bd..e17ee2b1 100644 --- a/tibiapy/__init__.py +++ b/tibiapy/__init__.py @@ -13,7 +13,7 @@ from tibiapy.creature import * from tibiapy.client import * -__version__ = '2.2.6' +__version__ = '2.3.0' from logging import NullHandler diff --git a/tibiapy/client.py b/tibiapy/client.py index 312c1b79..582d7615 100644 --- a/tibiapy/client.py +++ b/tibiapy/client.py @@ -2,6 +2,7 @@ import datetime import aiohttp +import aiohttp_socks import tibiapy from tibiapy import Character, Guild, World, House, KillStatistics, ListedGuild, Highscores, Category, VocationFilter, \ @@ -14,7 +15,7 @@ class Client: - """An asynchronous client that fetches information from Tibia.com.ArithmeticError + """An asynchronous client that fetches information from Tibia.com The client uses a :class:`aiohttp.ClientSession` to request the information. A single session is shared across all operations. @@ -29,20 +30,26 @@ class Client: The event loop to use. The default one will be used if not defined. session: :class:`aiohttp.ClientSession` The client session that will be used for the requests. One will be created by default. + proxy_url: :class:`str` + The URL of the SOCKS proxy to use for requests. + Note that if a session is passed, the SOCKS proxy won't be used and must be applied when creating the session. """ - def __init__(self, loop=None, session=None): + + def __init__(self, loop=None, session=None, *, proxy_url=None): self.loop = asyncio.get_event_loop() if loop is None else loop # type: asyncio.AbstractEventLoop if session is not None: self.session = session # type: aiohttp.ClientSession else: - self.loop.create_task(self._initialize_session()) + self.loop.create_task(self._initialize_session(proxy_url)) - async def _initialize_session(self): + async def _initialize_session(self, proxy_url=None): headers = { 'User-Agent': "Tibia.py/%s (+https://github.com/Galarzaa90/tibia.py" % tibiapy.__version__, 'Accept-Encoding': "deflate, gzip" } - self.session = aiohttp.ClientSession(loop=self.loop, headers=headers) # type: aiohttp.ClientSession + connector = aiohttp_socks.SocksConnector.from_url(proxy_url) if proxy_url else None + self.session = aiohttp.ClientSession(loop=self.loop, headers=headers, + connector=connector) # type: aiohttp.ClientSession @classmethod def _handle_status(cls, status_code): @@ -81,6 +88,8 @@ async def _get(self, url): return await resp.text() except aiohttp.ClientError as e: raise NetworkError("aiohttp.ClientError: %s" % e, e) + except aiohttp_socks.SocksConnectionError as e: + raise NetworkError("aiohttp_socks.SocksConnectionError: %s" % e, e) async def _post(self, url, data): """Base POST request, handling possible error statuses.