sousa-andre / lcu-driver Goto Github PK
View Code? Open in Web Editor NEW๐ Python3 interface for League of Legends Client API
License: MIT License
๐ Python3 interface for League of Legends Client API
License: MIT License
Running the request example on the /lol-chat/v1/me endpoint returns a string like so:
{'availability': 'chat', 'gameName': 'Natrocx', 'gameTag': 'EUW', 'icon': 715, 'id': '[email protected]', 'lastSeenOnlineTimestamp': None, 'lol': {'championId': '', 'companionId': '4008', 'gameQueueType': '', 'gameStatus': 'outOfGame', 'level': '311', 'mapId': '', 'masteryScore': '526', 'puuid': '04e3da3d-8761-5fc7-819b-e5b85923d940', 'rankedLeagueDivision': 'III', 'rankedLeagueQueue': 'RANKED_FLEX_SR', 'rankedLeagueTier': 'GOLD', 'rankedLosses': '0', 'rankedSplitRewardLevel': '2', 'rankedWins': '41', 'regalia': '{"bannerType":2,"crestType":1}', 'skinVariant': '', 'skinname': ''}, 'name': 'Natrocx', 'patchline': 'live', 'pid': '[email protected]', 'platformId': 'EUW1', 'product': 'league_of_legends', 'productName': '', 'puuid': '04e3da3d-8761-5fc7-819b-e5b85923d940', 'statusMessage': '', 'summary': '', 'summonerId': 0000000, 'time': 0}
There are multiple things wrong with this.
This wouldn't bother me if I wasn't trying to parse this again, which quite frankly doesn't work without a huge hassle.
Trying to run the following code...
# fired when LCU API is ready to be used
@conn.ready
async def connect(connection):
print('LCU API is ready to be used.')
# fired when League Client is closed (or disconnected from websocket)
@conn.close
async def disconnect(_):
print('The client have been closed!')
await connect.stop()
# subscribe to '/lol-summoner/v1/current-summoner' endpoint for the UPDATE event
# when an update to the user happen (e.g. name change, profile icon change, level, ...) the function will be called
@conn.ws.register('/lol-summoner/v1/current-summoner', event_types=('UPDATE',))
async def icon_changed(connection, event):
print(f'The summoner {event.data["displayName"]} was updated.')
# starts the connector
conn.start()
Results in the following error...
Traceback (most recent call last):
File "D:\Python\Python38-32\lib\site-packages\psutil\_common.py", line 446, in wrapper
ret = self._cache[fun]
AttributeError: _cache
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\Python\Python38-32\lib\site-packages\psutil\_pswindows.py", line 679, in wrapper
return fun(self, *args, **kwargs)
File "D:\Python\Python38-32\lib\site-packages\psutil\_common.py", line 449, in wrapper
return fun(self)
File "D:\Python\Python38-32\lib\site-packages\psutil\_pswindows.py", line 766, in exe
exe = cext.proc_exe(self.pid)
PermissionError: [WinError 24] The program issued a command but the command length is incorrect: '(originated from NtQuerySystemInformation)'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "LeagueListener.py", line 43, in <module>
conn.start()
File "D:\Python\Python38-32\lib\site-packages\lcu_driver\connector.py", line 53, in start
wrapper()
File "D:\Python\Python38-32\lib\site-packages\lcu_driver\connector.py", line 45, in wrapper
connection = _return_ux_process_when_available()
File "D:\Python\Python38-32\lib\site-packages\lcu_driver\utils.py", line 25, in _return_ux_process_when_available
process = return_process(['LeagueClientUx.exe', 'LeagueClientUx'])
File "D:\Python\Python38-32\lib\site-packages\lcu_driver\utils.py", line 17, in return_process
if process.name() in process_name:
File "D:\Python\Python38-32\lib\site-packages\psutil\__init__.py", line 615, in name
name = self._proc.name()
File "D:\Python\Python38-32\lib\site-packages\psutil\_pswindows.py", line 750, in name
return os.path.basename(self.exe())
File "D:\Python\Python38-32\lib\site-packages\psutil\_pswindows.py", line 681, in wrapper
raise convert_oserror(err, pid=self.pid, name=self._name)
psutil.AccessDenied: psutil.AccessDenied (pid=8040)
This happens both with running as admin, and running as a user.
I know this can be resolved by using an earlier version of "psutil", but shouldn't it also work on the latest? Is there no work around?
Hiya! I've encountered an issue that is affecting lcu-driver
. It seems to have started yesterday and happens occassionally (sometimes it works, sometimes it doesn't). ;w;
Describe the bug
lcu-driver
fails when attempting to start the driver with a ValueError
.
To Reproduce
Steps to reproduce the behavior:
psutil
5.6.5.ValueError
(only if --riotgamesapi-settings
has an offending line, see Error section).Expected behavior
Expected lcu-driver
to start without encountering the ValueError
.
Error
Traceback (most recent call last):
File "app.py", line 19, in <module>
connector.start()
File "C:\Users\Maevie\Desktop\lcu_driver\env\lib\site-packages\lcu_driver\connector.py", line 53, in start
wrapper()
File "C:\Users\Maevie\Desktop\lcu_driver\env\lib\site-packages\lcu_driver\connector.py", line 46, in wrapper
self.create_connection(connection)
File "C:\Users\Maevie\Desktop\lcu_driver\env\lib\site-packages\lcu_driver\connector.py", line 25, in create_connection
connection = Connection(self, process_or_string)
File "C:\Users\Maevie\Desktop\lcu_driver\env\lib\site-packages\lcu_driver\connection.py", line 37, in __init__
process_args = parse_cmdline_args(process_or_string.cmdline())
File "C:\Users\Maevie\Desktop\lcu_driver\env\lib\site-packages\lcu_driver\utils.py", line 10, in parse_cmdline_args
key, value = cmdline_arg[2:].split('=')
ValueError: too many values to unpack (expected 2)
This is the offending line that cmdline_arg
encounters (shortened for brevity):
--riotgamesapi-settings=eyJjbGllbnfQ==
Desktop (please complete the following information):
Additional context
from lcu_driver import Connector
from lcu_driver.events.responses import WebsocketEventResponse
connector = Connector()
@connector.ready
async def connect(connection):
print("ready")
@connector.close
async def disconnect(connection):
print("finished")
await connector.stop()
@connector.ws.register('/lol-summoner/v1/current-summoner', event_types=('UPDATE',))
async def update(connection, event: WebsocketEventResponse):
print(event.data)
connector.start()
connector accidently close once loading the game, and it will reconnect later, even if I have set never close the client when gaming in the client config.
When the client closes, 'await connector.stop()' causes an infinite loop, making the 'async def disconnect(_)' repeat infinitely. I am using the normal code example from the docs:
`from lcu_driver import Connector
connector = Connector()
@connector.ready
async def connect(connection):
print('LCU API is ready to be used.')
@connector.close
async def disconnect(_):
print('The client have been closed!')
await connector.stop()
@connector.ws.register('/lol-summoner/v1/current-summoner', event_types=('UPDATE',))
async def icon_changed(connection, event):
print(f'The summoner {event.data["displayName"]} was updated.')
connector.start()`
Now some LCU API force to use http2. Requests Unable to communicate properly #
Hello, I recently tried a piece of code that was an example in the library,
The problem is that when i run the code i get the message that says that the LCU API is ready to be used then i get directly after the message that says that the client has been closed (it is not).
As you can see with the time that is displayed in the output the client opens and closes instantly.
from random import randint
from datetime import datetime
from lcu_driver import Connector
connector = Connector()
# fired when LCU API is ready to be used
@connector.ready
async def connect(connection):
print(datetime.now(), 'LCU API is ready to be used.')
# fired when League Client is closed (or disconnected from websocket)
@connector.close
async def disconnect(_):
print(datetime.now(), 'The client have been closed!')
# starts the connector
connector.start()
2022-08-14 15:10:10.715474 LCU API is ready to be used.
2022-08-14 15:10:10.716652 The client have been closed!
response = await connection.request('POST', '/lol-login/v1/session/invoke?destination=lcdsServiceProxy&method=call&args=["","teambuilder-draft","quitV2",""]')
print(await response.json())
returns:
{'body': {'body': None, 'clientId': 'nil', 'correlationId': '3954134057-197', 'destination': None, 'headers': {}, 'messageId': 'A1C5A6D0-FDCA-7F02-224D-2CDF4B030A25', 'timeToLive': 0.0, 'timestamp': 1654777177421.0}, 'typeName': 'flex.messaging.messages.AcknowledgeMessage'}
instead of dodging the lobby.
The endpoint is correct. I think something is wrong with the library
Any idea?
Response
"squarePortraitPath": "/lol-game-data/assets/v1/champion-icons/10.png",
How to display it on tkinter or something else?
The auto json encode on the ["data"] field is not a good idea, as "data" is usually supposed to be the body.
If you have a JSON body, you should send the "json" parameter instead of data, as they are mutually exclusive.
Excerpt from aiohttp doc
json โ Any json compatible python object (optional). json and data parameters could not be used at the same time.
you dont even need to parse the data field into json, as aiohttp will do it for you.
As some of the lcu-api functions require plain-text / form encoded data, the data field should be passed along and not parsed.
Remove 'data'-autoparsing on the request and adjust the pydoc to the following.
Send JSON body data via the **json** keyword argument. The **data** keyword can be used for form based data.
Both keywords (json and data) are mutually exclusive. Make sure to only send one.
connector.stop() does not work, well it works with that pull requests but not when the League client isnt open
I'm trying out the following example: https://lcu-driver.readthedocs.io/en/latest/examples.html#change-summoner-icon
It updates my summoner-icon but the script immediately ends while the client is still open. Is this expected behavior?
Hi,
Im trying to create a websocket connection but it does not seem to do anything... How do I know if an endpoint has a websocket connection?
@connector.ws.register('/lol-game-client-chat/v1/muted-summoners', event_types=('UPDATE',))
async def muted_summoner(connection, event):
print(f'The summoner {event.data["displayName"]} was muted.')
Hi,
it seems like the connection.request
is returning _RequestContextManager instead of the proper ClientResponse.
I'm testing it on the example code from docs:
from lcu_driver import Connector
connector = Connector()
@connector.ready
async def connect(connection):
summoner = await connection.request('get', '/lol-summoner/v1/current-summoner')
print(await summoner.json())
connector.start()
Throws:
Traceback (most recent call last):
File "C:\MyProjects\PoroLobby\test.py", line 11, in <module>
connector.start()
File "c:\users\pc\.virtualenvs\porolobby-tdh_zplj\src\lcu-driver\lcu_driver\connector.py", line 70, in start
wrapper()
File "c:\users\pc\.virtualenvs\porolobby-tdh_zplj\src\lcu-driver\lcu_driver\connector.py", line 64, in wrapper
self.loop.run_until_complete(connection.init())
File "C:\Users\PC\.pyenv\pyenv-win\versions\3.10.6\lib\asyncio\base_events.py", line 646, in run_until_complete
return future.result()
File "c:\users\pc\.virtualenvs\porolobby-tdh_zplj\src\lcu-driver\lcu_driver\connection.py", line 78, in init
await asyncio.gather(*tasks)
File "c:\users\pc\.virtualenvs\porolobby-tdh_zplj\src\lcu-driver\lcu_driver\events\managers.py", line 30, in run_event
await asyncio.create_task(
File "C:\MyProjects\PoroLobby\test.py", line 9, in connect
print(await summoner.json())
AttributeError: '_RequestContextManager' object has no attribute 'json'
sys:1: RuntimeWarning: coroutine 'ClientSession._request' was never awaited
Exception ignored in: <function LoopSensitiveManager.__del__ at 0x00000283E2E3DFC0>
Traceback (most recent call last):
File "c:\users\pc\.virtualenvs\porolobby-tdh_zplj\src\lcu-driver\lcu_driver\loop.py", line 47, in __del__
File "C:\Users\PC\.pyenv\pyenv-win\versions\3.10.6\lib\asyncio\runners.py", line 39, in run
File "C:\Users\PC\.pyenv\pyenv-win\versions\3.10.6\lib\asyncio\events.py", line 782, in new_event_loop
File "C:\Users\PC\.pyenv\pyenv-win\versions\3.10.6\lib\asyncio\events.py", line 673, in new_event_loop
File "C:\Users\PC\.pyenv\pyenv-win\versions\3.10.6\lib\asyncio\windows_events.py", line 315, in __init__
File "C:\Users\PC\.pyenv\pyenv-win\versions\3.10.6\lib\asyncio\proactor_events.py", line 635, in __init__
ImportError: sys.meta_path is None, Python is likely shutting down
sys:1: RuntimeWarning: coroutine 'LoopSensitiveManager.cull' was never awaited
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x00000283E2E66320>
I am using the latest lcu-driver from github. Pipfile:
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
lcu-driver = {editable = true, git = "https://github.com/sousa-andre/lcu-driver.git"}
[dev-packages]
[requires]
python_version = "3.10"
I'm running a script to launch League Client and some python script to fetch some data from it with the help of lcu-driver(Thank you for your great work and sharing).
This is being done in a cheap remote server, to be specifically, an Azure B1S instance(1vCPU, 1GB RAM).
Probably because of its poor performance(it takes almost 5 mins to finish loading from graphical perspective), even when connecting to it when ready() is fired, it's giving error like this
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\aiohttp\connector.py", line 969, in _wrap_create_connection
return await self._loop.create_connection(*args, **kwargs) # type: ignore # noqa
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 1056, in create_connection
raise exceptions[0]
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 1041, in create_connection
sock = await self._connect_sock(
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 955, in _connect_sock await self.sock_connect(sock, address)
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 702, in sock_connect
return await self._proactor.connect(sock, address)
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\asyncio\windows_events.py", line 812, in _poll
value = callback(transferred, key, ov)
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\asyncio\windows_events.py", line 599, in finish_connect
ov.getresult()
ConnectionRefusedError: [WinError 1225] The remote computer refused the network connection
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "C:\Users\lstp2021\Desktop\lolskin-price-tracker\backend\app\update_price_history.py", line 57, in
connector.start()
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\lcu_driver\connector.py", line 53, in start
wrapper()
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\lcu_driver\connector.py", line 47, in wrapper
self.loop.run_until_complete(self.connection.init())
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 642, in run_until_complete
return future.result()
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\lcu_driver\connection.py", line 70, in init
await asyncio.gather(tasks)
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\lcu_driver\events\managers.py", line 27, in run_event
await asyncio.create_task(
File "C:\Users\lstp2021\Desktop\lolskin-price-tracker\backend\app\update_price_history.py", line 51, in update_skins_price
await tqdm_asyncio.gather([update(connection, db, skin) for skin in db.query(models.Skin).all()])
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\tqdm\asyncio.py", line 79, in gather
res = [await f for f in cls.as_completed(ifs, loop=loop, timeout=timeout,
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\tqdm\asyncio.py", line 79, in
res = [await f for f in cls.as_completed(ifs, loop=loop, timeout=timeout,
File "C:\Users\lstp2021\AppData\Local\Programs\Python\Python39\lib\asyncio\tasks.py", line 614, in _wait_for_one
return f.result() # May raise f.exception().
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\tqdm\asyncio.py", line 76, in wrap_awaitable
return i, await f
File "C:\Users\lstp2021\Desktop\lolskin-price-tracker\backend\app\update_price_history.py", line 18, in update
skin_data = await connection.request('get', skin_api_uri)
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\lcu_driver\connection.py", line 157, in request
return await self.session.request(method, url, verify_ssl=False, **kwargs)
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\aiohttp\client.py", line 520, in _request
conn = await self._connector.connect(
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\aiohttp\connector.py", line 535, in connect
proto = await self._create_connection(req, traces, timeout)
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\aiohttp\connector.py", line 892, in _create_connection
_, proto = await self._create_direct_connection(req, traces, timeout)
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\aiohttp\connector.py", line 1051, in _create_direct_connection
raise last_exc
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\aiohttp\connector.py", line 1020, in _create_direct_connection
transp, proto = await self._wrap_create_connection(
File "C:\Users\lstp2021\AppData\Local\pypoetry\Cache\virtualenvs\app-k5ozR0H0-py3.9\lib\site-packages\aiohttp\connector.py", line 975, in _wrap_create_connection
raise client_error(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host 127.0.0.1:50763 ssl:False [The remote computer refused the network connection]
I tried to solve this by just waiting for 5mins after the ready() is fired. But it's causing another problem, the connection seems to be timed out so an
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
is raised by CHANCE. Sometimes it works.
I could possibly fix this by using two connectors one just to detect the launch of League Client(by ready()) and sleep 5mins, after that just close and use another connector to my job. Don't know if it will workout.
But I guess ready() is not working as expected(it's not ready yet!). Or is it?
So a fix to ready() would help very much. Or maybe I'm miss using the driver, is there anything I should try?
Should the library have an option to unregister an event from the connector or is the locals
attribute enough? With the current architeture unregistering events from the connector instance might cause problems when handling events from multiple clients.
The documentation should be updated.
BaseConnector
in order to create a more customized connector class.Some endpoints return error code, but in browser they can return data, such as /lol-mactch-history/v3/matchlist/account/{accountId}
.
I'm confusing...
Hi there.
I copied one of the examples, but when it is supposed to print summoner displayname etc, nothing is getting printed. The same happens with lockfile.
Am I stupid or did I just miss something?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.