Skip to content
This repository has been archived by the owner on Dec 28, 2021. It is now read-only.

Commit

Permalink
Add authentication with Activision Single Sign-On
Browse files Browse the repository at this point in the history
  • Loading branch information
EthanC committed Jul 28, 2021
1 parent c7c5aab commit 9952f05
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 30 deletions.
65 changes: 48 additions & 17 deletions callofduty/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from .client import Client
from .errors import LoginFailure
from .http import HTTP
from .http import HTTP, JSONorText

log: logging.Logger = logging.getLogger(__name__)

Expand All @@ -17,10 +17,12 @@ class Auth:
Parameters
----------
email : str
email : str, optional
Activision account email address.
password : str
password : str, optional
Activision account password.
sso : str, optional
Activision single sign-on cookie value.
"""

loginUrl: str = "https://profile.callofduty.com/cod/mapp/login"
Expand All @@ -29,12 +31,21 @@ class Auth:
_accessToken: Optional[str] = None
_deviceId: Optional[str] = None

def __init__(self, email: str, password: str):
self.email: str = email
self.password: str = password

def __init__(
self,
email: Optional[str] = None,
password: Optional[str] = None,
sso: Optional[str] = None,
):
self.email: Optional[str] = email
self.password: Optional[str] = password
self.sso: Optional[str] = sso

self.session: httpx.AsyncClient = httpx.AsyncClient()

if self.sso is not None:
self.session.cookies.set("ACT_SSO_COOKIE", self.sso)

@property
def AccessToken(self) -> Optional[str]:
"""
Expand Down Expand Up @@ -107,29 +118,49 @@ async def SubmitLogin(self):

if res.status_code != 200:
raise LoginFailure(f"Failed to login (HTTP {res.status_code})")


async def Login(email: str, password: str) -> Client:
elif isinstance(data := await JSONorText(res), dict):
if data.get("success") is not True:
# The API tends to return HTTP 200 even when an error occurs
raise LoginFailure(
f"Failed to login (HTTP {res.status_code}), "
+ data.get("token", data)
)


async def Login(
email: Optional[str] = None,
password: Optional[str] = None,
sso: Optional[str] = None,
) -> Client:
"""
Convenience function to make login with the Call of Duty authorization flow
as easy as possible.
as easy as possible. Requires one of email and password or sso cookie value.
Parameters
----------
email : str
email : str, optional
Activision account email address.
password : str
password : str, optional
Activision account password.
sso: str, optional
Activision single sign-on cookie value.
Returns
-------
object
Authenticated Call of Duty client.
"""

auth: Auth = Auth(email, password)
auth: Auth = Auth(email, password, sso)

if (email is None) and (sso is None):
raise LoginFailure("Failed to login, insufficient credentials provided")
elif (email is not None) and (password is not None):
await auth.RegisterDevice()
await auth.SubmitLogin()

await auth.RegisterDevice()
await auth.SubmitLogin()
return Client(HTTP(auth))
elif sso is not None:
await auth.RegisterDevice()

return Client(HTTP(auth))
return Client(HTTP(auth))
29 changes: 16 additions & 13 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@

async def main():
load_dotenv()
client = await callofduty.Login(
os.environ["ATVI_EMAIL"], os.environ["ATVI_PASSWORD"]
)

# client = await callofduty.Login(
# os.environ["ATVI_EMAIL"], os.environ["ATVI_PASSWORD"]
# )
# OR
# client = await callofduty.Login(sso=os.environ["ATVI_SSO"])

# season = await client.GetLootSeason(Title.BlackOps4, 3)
# print(f"{season.title.name}: {season.name}")
Expand Down Expand Up @@ -43,10 +46,10 @@ async def main():
# for account in accounts:
# print(f"{account.username} ({account.platform.name})")

# player = await client.GetPlayer(Platform.BattleNet, "Mxtive#1930")
# player = await client.GetPlayer(Platform.BattleNet, "Yeah#11207")
# print(f"{player.username} ({player.platform.name})")

# player = await client.GetPlayer(Platform.BattleNet, "Mxtive#1930")
# player = await client.GetPlayer(Platform.BattleNet, "Yeah#11207")
# summary = await player.matchesSummary(Title.ModernWarfare, Mode.Warzone, limit=20)
# print(summary)

Expand All @@ -65,13 +68,13 @@ async def main():
# print(f"#{entry.rank}: {entry.username} ({entry.platform.name})")

# leaderboard = await client.GetPlayerLeaderboard(
# Title.BlackOps4, Platform.BattleNet, "Mxtive#1930"
# Title.BlackOps4, Platform.BattleNet, "Yeah#11207"
# )
# for entry in leaderboard.entries:
# if entry.username == "Mxtive#1930":
# if entry.username == "Yeah#11207":
# print(f"#{entry.rank}: {entry.username} ({entry.platform.name})")

# player = await client.GetPlayer(Platform.Steam, "RdJokr")
# player = await client.GetPlayer(Platform.Steam, "Mxtive")
# leaderboard = await player.leaderboard(Title.WWII)
# for entry in leaderboard.entries:
# if entry.username == player.username:
Expand Down Expand Up @@ -112,11 +115,11 @@ async def main():
# for mode in maps[mapName]:
# print(f" - {mode}")

# match = (await client.GetPlayerMatches(Platform.Activision, "Yeah#8649242", Title.ModernWarfare, Mode.Warzone, limit=3))[0]
# match = (await client.GetPlayerMatches(Platform.BattleNet, "Yeah#11207", Title.ModernWarfare, Mode.Warzone, limit=3))[0]
# teams = await match.teams()
# print(teams)

# player = await client.GetPlayer(Platform.BattleNet, "Mxtive#1930")
# player = await client.GetPlayer(Platform.BattleNet, "Yeah#11207")
# match = (await player.matches(Title.ModernWarfare, Mode.Multiplayer, limit=3))[1]
# match = await client.GetMatch(Title.ModernWarfare, Platform.Activision, match.id)
# teams = await match.teams()
Expand All @@ -126,7 +129,7 @@ async def main():
# details = await match.details()
# print(details)

# player = await client.GetPlayer(Platform.BattleNet, "Mxtive#1930")
# player = await client.GetPlayer(Platform.BattleNet, "Yeah#11207")
# match = (await player.matches(Title.ModernWarfare, Mode.Multiplayer, limit=3))[1]
# match = await client.GetFullMatch(Platform.Activision, Title.ModernWarfare, Mode.Multiplayer, match.id)
# print(match)
Expand All @@ -135,7 +138,7 @@ async def main():
# for player in results:
# print(f"{player.username} ({player.platform.name})")

# player = await client.GetPlayer(Platform.BattleNet, "Mxtive#1930")
# player = await client.GetPlayer(Platform.BattleNet, "Yeah#11207")
# profile = await player.profile(Title.ModernWarfare, Mode.Multiplayer)
# print(profile)

Expand Down Expand Up @@ -233,7 +236,7 @@ async def main():
# if member.username != squad.owner.username:
# print(f"Member: {member.username} ({member.platform.name})")

# squad = await client.GetPlayerSquad(Platform.Activision, "Yeah#8649242")
# squad = await client.GetPlayerSquad(Platform.Activision, "Yeah#11207")
# print(f"{squad.name} - {squad.description}")
# print(f"Owner: {squad.owner.username} ({squad.owner.platform.name})")
# for member in squad.members:
Expand Down

0 comments on commit 9952f05

Please sign in to comment.