Skip to content
This repository was archived by the owner on Dec 12, 2023. It is now read-only.

Commit 7029ba6

Browse files
committed
authentication: implement logout
1 parent a079edb commit 7029ba6

10 files changed

+30
-7
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
cookies.pickle
22
test.py
3+
.direnv
34

45
# Created by https://www.toptal.com/developers/gitignore/api/python
56
# Edit at https://www.toptal.com/developers/gitignore?templates=python

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# v0.2.0
2+
3+
* Implemented logout endpoint.
4+
15
# v0.1.7
26

37
* Fix typo in InMail parsing.

examples/get-conversation.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from pathlib import Path
22

33
import asyncio
4-
from linkedin_messaging import LinkedInMessaging, ChallengeException
4+
from linkedin_messaging import ChallengeException, LinkedInMessaging
55
from linkedin_messaging.api_objects import URN
66

77
cookie_path = Path(__file__).parent.joinpath("cookies.pickle")
88
urn = URN(
9-
"urn:li:fs_conversation:2-OTNkODIyYTEtODFjZS00NTdlLThlYTItYWQyMDg2NTc4YWMyXzAxMA=="
9+
"urn:li:fs_conversation:2-YWM2YTJmYjUtNTdjMS00ZjlmLTgwMDUtOWYxMmMxNjY4M2FlXzAxMg=="
1010
)
1111

1212

@@ -35,6 +35,7 @@ async def main():
3535
for element in convo_resp.elements:
3636
print(element)
3737

38+
await linkedin.logout()
3839
await linkedin.close()
3940

4041

examples/listen-for-events.py

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ async def on_event(event: RealTimeEventStreamEvent):
4040

4141
asyncio.gather(task)
4242

43+
await linkedin.logout()
4344
await linkedin.close()
4445

4546

examples/pickle.py renamed to examples/pickle-example.py

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ async def main():
2323

2424
print(await linkedin.get_user_profile())
2525

26+
await linkedin.logout()
2627
await linkedin.close()
2728

2829

examples/send-message.py

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ async def main():
4040
mc = MessageCreate(AttributedBody(), attachments=[attachment])
4141
print(await linkedin.send_message(urn, mc))
4242

43+
await linkedin.logout()
4344
await linkedin.close()
4445

4546

examples/simple-2fa.py

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ async def main():
1616

1717
print(await linkedin.get_user_profile())
1818

19+
await linkedin.logout()
1920
await linkedin.close()
2021

2122

linkedin_messaging/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from .api_objects import URN
33

44
__title__ = "linkedin_messaging"
5-
__version__ = "0.1.7"
5+
__version__ = "0.2.0"
66
__description__ = "An unofficial API for interacting with LinkedIn Messaging"
77

88
__license__ = "MIT"

linkedin_messaging/linkedin.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@
5656
}
5757

5858
# URL to seed all of the auth requests
59-
SEED_URL = "https://www.linkedin.com/uas/login"
59+
HEARTBEAT_URL = "https://realtime.www.linkedin.com/realtime/realtimeFrontendClientConnectivityTracking" # noqa: E501
6060
LOGIN_URL = "https://www.linkedin.com/checkpoint/lg/login-submit"
61-
VERIFY_URL = "https://www.linkedin.com/checkpoint/challenge/verify"
61+
LOGOUT_URL = "https://www.linkedin.com/uas/logout"
6262
REALTIME_CONNECT_URL = "https://realtime.www.linkedin.com/realtime/connect"
63-
HEARTBEAT_URL = "https://realtime.www.linkedin.com/realtime/realtimeFrontendClientConnectivityTracking" # noqa: E501
63+
SEED_URL = "https://www.linkedin.com/uas/login"
64+
VERIFY_URL = "https://www.linkedin.com/checkpoint/challenge/verify"
6465

6566
LINKEDIN_BASE_URL = "https://www.linkedin.com"
6667
API_BASE_URL = f"{LINKEDIN_BASE_URL}/voyager/api"
@@ -196,6 +197,18 @@ async def enter_2fa(self, two_factor_code: str):
196197
# TODO (#1) can we scrape anything from the page?
197198
raise Exception("Failed to log in.")
198199

200+
async def logout(self) -> bool:
201+
csrf_token = None
202+
for c in self.session.cookie_jar:
203+
if c.key == "JSESSIONID":
204+
csrf_token = c.value.strip('"')
205+
response = await self.session.get(
206+
LOGOUT_URL,
207+
params={"csrfToken": csrf_token},
208+
allow_redirects=False,
209+
)
210+
return response.status == 303
211+
199212
# endregion
200213

201214
# region Conversations

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "linkedin_messaging"
3-
version = "0.1.7"
3+
version = "0.2.0"
44
description = "An unofficial API for interacting with LinkedIn Messaging"
55
authors = ["Sumner Evans <[email protected]>"]
66
license = "Apache-2.0"

0 commit comments

Comments
 (0)