Wrapper for the undocumented CodinGame API. Can be used both synchronously and asynchronlously.

Overview

codingame API wrapper

PyPI version info Supported Python versions Lint and test workflow status Documentation build status Code coverage Code style: Black Discord support server

Pythonic wrapper for the undocumented CodinGame API.

Installation

Python 3.6 or higher is required.

Install codingame with pip:

pip install codingame

Quickstart

Create an application, in example.py:

import codingame

client = codingame.Client()

# get a codingamer
codingamer = client.get_codingamer("username")
print(codingamer.pseudo)

# get the global leaderboard
global_leaderboard = client.get_global_leaderboard()
# print the pseudo of the top codingamer
print(global_leaderboard.users[0].pseudo)

See the docs.

Contribute

Support

If you are having issues, please let me know by joining the discord support server at https://discord.gg/8HgtN6E

License

The project is licensed under the MIT license.

Links

Comments
  • [FR] Make Client useable for any authenticated POST request

    [FR] Make Client useable for any authenticated POST request

    Is your feature request related to a problem? Please describe. I made a small app that downloads all my CodinGame solutions. I need to make authenticated API requests to different URLs e.g. https://www.codingame.com/services/Puzzle/findAllMinimalProgress, /Solution/findSolution, etc.

    I've now blocked with the login problem #5 and at the same time I was guessing about some solution you were building it! (wow!)

    Describe the solution you'd like Add codingame.Client.request(service: str, func: str, json: list = []) to the public API for both the sync and async clients.

    Describe alternatives you've considered

    • I think my app could invoke client.request() but as it's undocumented it seems to be an internal API?
    • I could add cookie session in my own repo, but I'd rather rely on some dedicated client to handle the logic.
    • It would be awesome if this client natively supported the various CodinGame APIs my puzzle solution download app needed, but that feels like a big request. Instead, having the generic .request() escape hatch enables the library to be used for any new APIs that CodinGame releases!

    Additional context I'm impressed by this project! Nice!

    enhancement good first issue 
    opened by darthwalsh 2
  • [RELEASE] 1.4.x

    [RELEASE] 1.4.x

    Version 1.4.0

    Added

    • Client.mark_notifications_as_seen and Client.mark_notifications_as_read.
    • Notification.mark_as_seen and Notification.mark_as_read.

    Removed

    • Removed support for python 3.6 as it has reached its end of life. For more information, see PEP 494.
    release 
    opened by takos22 1
  • implement state.current_language

    implement state.current_language

    implement state.current_language

    def str(self) -> str:

    return self[state.current_language]

    https://github.com/takos22/codingame/blob/a169a0c6ccb4b096fe599ffc2b725ea8c90e6bc5/codingame/notification/data.py#L77

    
    import re
    import typing
    from datetime import datetime
    
    from ..abc import Mapping
    from ..types import notification as types
    from ..utils import to_datetime
    from .enums import (
        CommentType,
        ContributionModeratedActionType,
        ContributionType,
        NotificationType,
    )
    
    if typing.TYPE_CHECKING:
        from ..state import ConnectionState
    
    __all__ = (
        "LanguageMapping",
        "NotificationData",
        "AchievementUnlockedData",
        "LeagueData",
        "NewBlogData",
        "ClashInviteData",
        "ClashOverData",
        "Contribution",
        "PuzzleSolution",
        "NewCommentData",
        "ContributionData",
        "FeatureData",
        "NewHintData",
        "ContributionModeratedData",
        "NewPuzzleData",
        "PuzzleOfTheWeekData",
        "QuestCompletedData",
        "FriendRegisteredData",
        "NewLevelData",
        "GenericData",
        "CustomData",
        "CareerCandidateData",
        "TestFinishedData",
        "JobAcceptedData",
        "JobExpiredData",
        "NewWorkBlogData",
        "OfferApplyData",
    )
    
    
    class LanguageMapping(Mapping):
        """Mapping to store text with multiple languages.
    
        This class has the same interface as :class:`dict` for backwards
        compatibility.
    
        Attributes
        -----------
            en: :class:`str`
                The text in english.
    
            fr: :class:`str`
                The text in french.
        """
    
        en: str
        fr: str
    
        __slots__ = ("en", "fr")
    
        def __init__(
            self, state: "ConnectionState", mapping: types.LanguageMapping
        ):
            self.en = mapping["en"]
            self.fr = mapping["fr"]
    
            super().__init__(state, mapping)
    
        # TODO implement state.current_language
        # def __str__(self) -> str:
        #     return self[state.current_language]
    
    
    class NotificationData(Mapping):
        """Base class for the notification data classes.
    
        This class has the same interface as :class:`dict` for backwards
        compatibility.
    
        Attributes
        -----------
            _raw: :class:`dict`
                Raw data of the :class:`Notification`, useful when one of the values
                isn't an attribute.
        """
    
        _raw: dict
    
        def __init__(self, state: "ConnectionState", data: types.NotificationData):
            super().__init__(state, data)
    
        @classmethod
        def from_type(
            cls,
            type: NotificationType,
            state: "ConnectionState",
            data: types.NotificationData,
        ) -> typing.Optional["NotificationData"]:
            """Create the correct :class:`NotificationData` subclass according to
            the :class:`notification type <NotificationType>`.
    
            Parameters
            ----------
                type : :class:`NotificationType`
                    The notification type.
    
                data : :class:`dict`
                    The notification data.
    
            Returns
            -------
                :class:`NotificationData`
                    The parsed data of the notifcation.
            """
    
            NT = NotificationType
            type_to_obj = {
                NT.achievement_unlocked: AchievementUnlockedData,
                NT.new_league: LeagueData,
                NT.eligible_for_next_league: LeagueData,
                NT.promoted_league: LeagueData,
                NT.new_league_opened: LeagueData,
                NT.new_blog: NewBlogData,
                NT.clash_invite: ClashInviteData,
                NT.clash_over: ClashOverData,
                NT.new_comment: NewCommentData,
                NT.new_comment_response: NewCommentData,
                NT.contribution_received: ContributionData,
                NT.contribution_accepted: ContributionData,
                NT.contribution_refused: ContributionData,
                NT.contribution_clash_mode_removed: ContributionData,
                NT.feature: FeatureData,
                NT.new_hint: NewHintData,
                NT.contribution_moderated: ContributionModeratedData,
                NT.new_puzzle: NewPuzzleData,
                NT.puzzle_of_the_week: PuzzleOfTheWeekData,
                NT.quest_completed: QuestCompletedData,
                NT.friend_registered: FriendRegisteredData,
                NT.new_level: NewLevelData,
                NT.info_generic: GenericData,
                NT.warning_generic: GenericData,
                NT.important_generic: GenericData,
                NT.custom: CustomData,
                NT.career_new_candidate: CareerCandidateData,
                NT.career_update_candidate: CareerCandidateData,
                NT.test_finished: TestFinishedData,
                NT.job_accepted: JobAcceptedData,
                NT.job_expired: JobExpiredData,
                NT.new_work_blog: NewWorkBlogData,
                NT.offer_apply: OfferApplyData,
            }
            return (
                type_to_obj.get(type, NotificationData)(state, data)
                if data
                else None
            )
    
    
    # achievement
    
    
    class AchievementUnlockedData(NotificationData):
        """Data of a :attr:`NotificationType.achievement_unlocked` notification."""
    
        id: str
        label: LanguageMapping
        points: int
        level: str
        completion_time: datetime
        image_url: str
    
        __slots__ = (
            "id",
            "label",
            "points",
            "level",
            "completion_time",
            "image_url",
        )
    
        def __init__(
            self, state: "ConnectionState", data: types.AchievementUnlockedData
        ):
            self.id = data["id"]
            self.label = LanguageMapping(state, data["label"])
            self.points = data["points"]
            self.level = data["level"]
            self.completion_time = to_datetime(data["completionTime"])
            self.image_url = state.http.get_file_url(
                data["imageId"], format="notification_picture"
            )
    
            super().__init__(state, data)
    
    
    # arena and new-league-opened
    
    
    class LeagueData(NotificationData):
        """Data of :attr:`NotificationType.new_league`,
        :attr:`NotificationType.eligible_for_next_league`,
        :attr:`NotificationType.promoted_league` and
        :attr:`NotificationType.new_league_opened` notifications."""
    
        title_label: LanguageMapping
        division_index: int
        division_count: int
        division_offset: int
        threshold_index: int
        thumbnail_url: str
        test_session_handle: str
    
        __slots__ = (
            "title_label",
            "division_index",
            "division_count",
            "division_offset",
            "threshold_index",
            "thumbnail_url",
            "test_session_handle",
        )
    
        def __init__(self, state: "ConnectionState", data: types.LeagueData):
            self.title_label = LanguageMapping(state, data["titleLabel"])
            self.division_index = data["divisionIndex"]
            self.division_count = data["divisionCount"]
            self.division_offset = data["divisionOffset"]
            self.threshold_index = data["thresholdIndex"]
            self.thumbnail_url = state.http.get_file_url(
                data["thumbnailBinaryId"], format="notification_picture"
            )
            self.test_session_handle = data["testSessionHandle"]
    
            super().__init__(state, data)
    
    
    # blog
    
    
    class NewBlogData(NotificationData):
        """Data of a :attr:`NotificationType.new_blog` notification."""
    
        title: LanguageMapping
        url: LanguageMapping
    
        __slots__ = (
            "title",
            "url",
        )
    
        def __init__(self, state: "ConnectionState", data: types.NewBlogData):
            self.title = LanguageMapping(state, data["title"])
            self.url = LanguageMapping(state, data["url"])
    
            super().__init__(state, data)
    
    
    # clash
    
    
    class ClashInviteData(NotificationData):
        """Data of a :attr:`NotificationType.clash_invite` notification."""
    
        handle: str
    
        __slots__ = ("handle",)
    
        def __init__(self, state: "ConnectionState", data: types.ClashInviteData):
            self.handle = data["handle"]
    
            super().__init__(state, data)
    
    
    class ClashOverData(NotificationData):
        """Data of a :attr:`NotificationType.clash_over` notification."""
    
        handle: str
        rank: int
        player_count: int
    
        __slots__ = (
            "handle",
            "rank",
            "player_count",
        )
    
        def __init__(self, state: "ConnectionState", data: types.ClashOverData):
            self.handle = data["handle"]
            self.rank = data["rank"]
            self.player_count = data["playerCount"]
    
            super().__init__(state, data)
    
    
    # comment
    
    
    class Contribution(Mapping):
        """Data about a contribution.
    
        This class has the same interface as :class:`dict` for backwards
        compatibility.
        """
    
        handle: str
        title: typing.Optional[str]
        type: typing.Optional[ContributionType]
    
        __slots__ = ("handle", "title", "type")
    
        def __init__(self, state: "ConnectionState", data: types.ContributionData):
            self.handle = data["handle"]
            self.title = data.get("title")
            self.type = ContributionType(data["type"]) if "type" in data else None
    
            super().__init__(state, data)
    
    
    class PuzzleSolution(Mapping):
        """Data about a puzzle solution.
    
        This class has the same interface as :class:`dict` for backwards
        compatibility.
        """
    
        puzzle_id: str
        puzzle_url: typing.Optional[str]
        test_session_submission_id: int
    
        __slots__ = ("puzzle_id", "puzzle_url", "test_session_submission_id")
    
        def __init__(
            self, state: "ConnectionState", data: types.PuzzleSolutionData
        ):
            self.puzzle_id = data["puzzleId"]
            self.puzzle_url = (
                (state.http.BASE_URL + data["puzzleDetailsPageUrl"])
                if "puzzleDetailsPageUrl" in data
                else None
            )
            self.test_session_submission_id = data["testSessionSubmissionId"]
    
            super().__init__(state, data)
    
    
    class NewCommentData(NotificationData):
        """Data of a :attr:`NotificationType.new_comment` and
        :attr:`NotificationType.new_comment_response` notifications."""
    
        type: LanguageMapping
        comment_type: typing.Optional[CommentType]
        type_data: typing.Union[Contribution, PuzzleSolution, None]
        url: typing.Optional[str]
    
        __slots__ = ("type", "comment_type", "type_data", "url")
    
        def __init__(self, state: "ConnectionState", data: types.NewCommentData):
            self.type = LanguageMapping(state, data["type"])
            self.comment_type = (
                CommentType(data["commentType"]) if "commentType" in data else None
            )
            self.type_data = None
            if "typeData" in data:
                self.type_data = (
                    Contribution(state, data["typeData"])
                    if self.comment_type == CommentType.contribution
                    else PuzzleSolution(state, data["typeData"])
                )
            self.url = (
                (state.http.BASE_URL + data["url"]) if "url" in data else None
            )
    
            super().__init__(state, data)
    
    
    # contribution
    
    
    class ContributionData(Mapping):
        """Data of :attr:`NotificationType.contribution_received`,
        :attr:`NotificationType.contribution_accepted`,
        :attr:`NotificationType.contribution_refused` and
        :attr:`NotificationType.contribution_clash_mode_removed` notifications."""
    
        handle: str
        title: typing.Optional[str]
        type: typing.Optional[ContributionType]
    
        __slots__ = ("handle", "title", "type")
    
        def __init__(self, state: "ConnectionState", data: types.ContributionData):
            self.handle = data["handle"]
            self.title = data.get("title")
            self.type = ContributionType(data["type"]) if "type" in data else None
    
            super().__init__(state, data)
    
    
    # feature
    
    
    class FeatureData(NotificationData):
        """Data of a :attr:`NotificationType.feature` notification."""
    
        title: typing.Optional[LanguageMapping]
        description: LanguageMapping
        image_url: str
        url: str
    
        __slots__ = (
            "title",
            "description",
            "image_url",
            "url",
        )
    
        def __init__(self, state: "ConnectionState", data: types.FeatureData):
            self.title = (
                LanguageMapping(state, data["title"]) if "title" in data else None
            )
            self.description = LanguageMapping(state, data["description"])
            self.image_url = data["image-instant"]
            self.url = (
                data["url"]
                if re.match(r"https?://", data["url"])
                else (state.http.BASE_URL + data["url"])
            )
    
            super().__init__(state, data)
    
    
    # hints
    
    
    class NewHintData(NotificationData):
        """Data of a :attr:`NotificationType.new_hint` notification."""
    
        puzzle_title: LanguageMapping
        thumbnail_url: str
        test_session_handle: str
    
        __slots__ = (
            "puzzle_title",
            "thumbnail_url",
            "test_session_handle",
        )
    
        def __init__(self, state: "ConnectionState", data: types.NewHintData):
            self.puzzle_title = LanguageMapping(state, data["puzzleTitle"])
            self.thumbnail_url = state.http.get_file_url(
                data["thumbnailBinaryId"], format="notification_picture"
            )
            self.test_session_handle = data["testSessionHandle"]
    
            super().__init__(state, data)
    
    
    # moderation
    
    
    class ContributionModeratedData(NotificationData):
        """Data of a :attr:`NotificationType.contribution_moderated`
        notification."""
    
        action_type: ContributionModeratedActionType
        contribution: Contribution
    
        __slots__ = (
            "action_type",
            "contribution",
        )
    
        def __init__(
            self, state: "ConnectionState", data: types.ContributionModeratedData
        ):
            self.action_type = ContributionModeratedActionType(data["actionType"])
            self.contribution = Contribution(state, data["contribution"])
    
            super().__init__(state, data)
    
    
    # puzzle
    
    
    class NewPuzzleData(NotificationData):
        """Data of a :attr:`NotificationType.new_puzzle` notification."""
    
        level: LanguageMapping
        name: LanguageMapping
        image_url: str
        puzzle_id: int
    
        __slots__ = (
            "level",
            "name",
            "image_url",
            "puzzle_id",
        )
    
        def __init__(self, state: "ConnectionState", data: types.NewPuzzleData):
            self.level = LanguageMapping(state, data["level"])
            self.name = LanguageMapping(state, data["name"])
            self.image_url = data["image"]
            self.puzzle_id = data["puzzleId"]
    
            super().__init__(state, data)
    
    
    class PuzzleOfTheWeekData(NotificationData):
        """Data of a :attr:`NotificationType.puzzle_of_the_week` notification."""
    
        puzzle_id: int
        puzzle_level: str
        puzzle_pretty_id: str
        puzzle_name: LanguageMapping
        puzzle_image_url: str
        contributor_pseudo: str
        contributor_avatar_url: typing.Optional[str]
    
        __slots__ = (
            "puzzle_id",
            "puzzle_level",
            "puzzle_pretty_id",
            "puzzle_name",
            "puzzle_image_url",
            "contributor_pseudo",
            "contributor_avatar_url",
        )
    
        def __init__(
            self, state: "ConnectionState", data: types.PuzzleOfTheWeekData
        ):
            self.puzzle_id = data["puzzleId"]
            self.puzzle_level = data["puzzleLevel"]
            self.puzzle_pretty_id = data["puzzlePrettyId"]
            self.puzzle_name = LanguageMapping(state, data["puzzleName"])
            self.puzzle_image_url = state.http.get_file_url(
                data["puzzleOfTheWeekImageId"], format="notification_picture"
            )
            self.contributor_pseudo = data["contributorNickname"]
            self.contributor_avatar_url = (
                state.http.get_file_url(
                    data["contributorAvatarId"], format="notification_picture"
                )
                if "contributorAvatarId" in data
                else None
            )
    
            super().__init__(state, data)
    
    
    # quest
    
    
    class QuestCompletedData(NotificationData):
        """Data of a :attr:`NotificationType.quest_completed` notification."""
    
        id: int
        label: LanguageMapping
    
        __slots__ = (
            "id",
            "label",
        )
    
        def __init__(
            self, state: "ConnectionState", data: types.QuestCompletedData
        ):
            self.id = data["questId"]
            self.label = LanguageMapping(state, data["label"])
    
            super().__init__(state, data)
    
    
    # social
    
    
    class FriendRegisteredData(NotificationData):
        """Data of a :attr:`NotificationType.friend_registered` notification."""
    
        name: str
    
        __slots__ = ("name",)
    
        def __init__(
            self, state: "ConnectionState", data: types.FriendRegisteredData
        ):
            self.name = data["name"]
    
            super().__init__(state, data)
    
    
    # xp
    
    
    class NewLevelData(NotificationData):
        """Data of a :attr:`NotificationType.new_level` notification."""
    
        level: int
        reward: typing.Optional[LanguageMapping]
        trigger_career_popup: typing.Optional[bool]
    
        __slots__ = (
            "level",
            "reward",
            "trigger_career_popup",
        )
    
        def __init__(self, state: "ConnectionState", data: types.NewLevelData):
            self.level = data["level"]
            self.reward = (
                LanguageMapping(state, data["reward"]) if "reward" in data else None
            )
            self.trigger_career_popup = data.get("triggerCareerPopup")
    
            super().__init__(state, data)
    
    
    # generic
    
    
    class GenericData(NotificationData):
        """Data of a :attr:`NotificationType.info_generic`,
        :attr:`NotificationType.warning_generic` and
        :attr:`NotificationType.important_generic` notifications."""
    
        title: LanguageMapping
        description: LanguageMapping
        image_url: str
        url: str
    
        __slots__ = (
            "title",
            "description",
            "image_url",
            "url",
        )
    
        def __init__(self, state: "ConnectionState", data: types.GenericData):
            self.description = LanguageMapping(state, data["description"])
            self.url = data["url"]
    
            super().__init__(state, data)
    
    
    # custom
    
    
    class CustomData(NotificationData):
        """Data of a :attr:`NotificationType.custom` notification."""
    
        title: LanguageMapping
        description: LanguageMapping
        image_url: str
        url: str
    
        __slots__ = (
            "title",
            "description",
            "image_url",
            "url",
        )
    
        def __init__(self, state: "ConnectionState", data: types.CustomData):
            self.title = LanguageMapping(state, data["title"])
            self.description = LanguageMapping(state, data["description"])
            self.image_url = state.http.STATIC_URL + data["image"]
            self.url = (
                (state.http.BASE_URL + data["url"])
                if data["url"].startswith("/")
                else data["url"]
            )
    
            super().__init__(state, data)
    
    
    # other
    
    
    class CareerCandidateData(NotificationData):
        """Data of a :attr:`NotificationType.career_new_candidate` and
        :attr:`NotificationType.career_update_candidate` notifications."""
    
        handle: str
        username: typing.Optional[str]
        country: str
        region: str
        avatar_url: typing.Optional[str]
    
        __slots__ = (
            "handle",
            "username",
            "country",
            "region",
            "avatar_url",
        )
    
        def __init__(
            self, state: "ConnectionState", data: types.CareerCandidateData
        ):
            self.handle = data["handle"]
            self.username = data.get("username")
            self.country = data["country"]
            self.region = data["region"]
            self.avatar_url = (
                state.http.get_file_url(
                    data["avatar"], format="notification_picture"
                )
                if "avatar" in data
                else None
            )
    
            super().__init__(state, data)
    
    
    # no category
    
    
    class TestFinishedData(NotificationData):
        """Data of a :attr:`NotificationType.test_finished` notification."""
    
        campaign_id: int
        candidate_id: int
        candidate_name: typing.Optional[str]
        candidate_email: str
    
        __slots__ = (
            "campaign_id",
            "candidate_id",
            "candidate_name",
            "candidate_email",
        )
    
        def __init__(self, state: "ConnectionState", data: types.TestFinishedData):
            self.campaign_id = data["campaignId"]
            self.candidate_id = data["candidateId"]
            self.candidate_name = data.get("candidateName")
            self.candidate_email = data["candidateEmail"]
    
            super().__init__(state, data)
    
    
    class JobAcceptedData(NotificationData):
        """Data of a :attr:`NotificationType.job_accepted` notification."""
    
        job_name: typing.Optional[str]
        job_offer_location: str
        challenge_id: typing.Optional[int]
    
        __slots__ = (
            "job_name",
            "job_offer_location",
            "challenge_id",
        )
    
        def __init__(self, state: "ConnectionState", data: types.JobAcceptedData):
            self.job_name = data.get("jobName")
            self.job_offer_location = data["jobOfferLocation"]
            self.challenge_id = data.get("challengeId")
    
            super().__init__(state, data)
    
    
    class JobExpiredData(NotificationData):
        """Data of a :attr:`NotificationType.job_expired` notification."""
    
        job_name: typing.Optional[str]
    
        __slots__ = ("job_name",)
    
        def __init__(self, state: "ConnectionState", data: types.JobExpiredData):
            self.job_name = data.get("jobName")
    
            super().__init__(state, data)
    
    
    class NewWorkBlogData(NotificationData):
        """Data of a :attr:`NotificationType.new_work_blog` notification."""
    
        title: LanguageMapping
        url: LanguageMapping
    
        __slots__ = (
            "title",
            "url",
        )
    
        def __init__(self, state: "ConnectionState", data: types.NewWorkBlogData):
            self.title = LanguageMapping(state, data["title"])
            self.url = LanguageMapping(
                state,
                {
                    lang: state.http.BASE_URL + path
                    for lang, path in data["url"].items()
                },
            )
    
            super().__init__(state, data)
    
    
    class OfferApplyData(NotificationData):
        """Data of a :attr:`NotificationType.offer_apply` notification."""
    
        candidate_name: str
        job_name: typing.Optional[str]
        job_offer_location: str
        challenge_id: typing.Optional[int]
        job_offer_id: typing.Optional[int]
        job_offer_applicant_id: typing.Optional[int]
    
        __slots__ = (
            "candidate_name",
            "job_name",
            "job_offer_location",
            "challenge_id",
            "job_offer_id",
            "job_offer_applicant_id",
        )
    
        def __init__(self, state: "ConnectionState", data: types.OfferApplyData):
            self.candidate_name = data["candidateName"]
            self.job_name = data.get("jobName")
            self.job_offer_location = data["jobOfferLocation"]
            self.challenge_id = data.get("challengeId")
            self.job_offer_id = data.get("jobOfferId")
            self.job_offer_applicant_id = data.get("jobOfferApplicantId")
    
            super().__init__(state, data)
    
    

    3e717771f317d9ca1ad8ad0078d2a34a832f2ad2

    todo 
    opened by github-actions[bot] 1
  • [RELEASE] v1.2.4

    [RELEASE] v1.2.4

    Version 1.2.4

    Fixed

    • CodinGamer.get_followers and CodinGamer.get_followed now work while being logged in as any user, not just as the user you want to get the followers of.
    release 
    opened by takos22 1
  • Fix docs bug with remember_me_cookie as login param

    Fix docs bug with remember_me_cookie as login param

    codingame.Client() doesn't have param remember_me_cookie Update example code to pass cookie to login()

    (Sorry if the PR isn't based from the right branch; I didn't see CONTRIBUTING docs about which branch the PR should merge into. Maybe it should go to 1.2.x if you are still updating that.)

    opened by darthwalsh 1
  • [FR] Use ID of the logged in user for following endpoints

    [FR] Use ID of the logged in user for following endpoints

    Duplicate of #8

    Generated automatically

    fix this to use [id, logged_in.id]

    https://github.com/takos22/codingame/blob/a09f6bd11a1475c84add70b7231f07bd50246b8e/codingame/http/base.py#L92

    
        ):
            ...  # pragma: no cover
    
        def get_file_url(self, id: int, format: str = None) -> str:
            url = f"https://static.codingame.com/servlet/fileservlet?id={id}"
            if format:
                url += f"&format={format}"
            return url
    
        # Search
    
        def search(self, query: str):
            return self.request("Search", "search", [query, "en", None])
    
        # ProgrammingLanguage
    
        def get_language_ids(self) -> typing.List[str]:
            return self.request("ProgrammingLanguage", "findAllIds")
    
        # CodinGamer
    
        def login(self, email: str, password: str):
            return self.request(
                "CodinGamer", "loginSiteV2", [email, password, True]
            )
    
        def get_codingamer_from_handle(self, handle: str) -> PointsStatsFromHandle:
            return self.request(
                "CodinGamer", "findCodingamePointsStatsByHandle", [handle]
            )
    
        def get_codingamer_from_id(self, id: int) -> CodinGamerFromID:
            return self.request(
                "CodinGamer", "findCodinGamerPublicInformations", [id]
            )
    
        def get_codingamer_followers(self, id: int) -> typing.List[Follower]:
            # TODO fix this to use [id, logged_in.id, None]
            return self.request("CodinGamer", "findFollowers", [id, id, None])
    
        def get_codingamer_follower_ids(self, id: int) -> typing.List[int]:
            return self.request("CodinGamer", "findFollowerIds", [id])
    
        def get_codingamer_following(self, id: int) -> typing.List[Following]:
            # TODO fix this to use [id, logged_in.id]
            return self.request("CodinGamer", "findFollowing", [id, id])
    
        def get_codingamer_following_ids(self, id: int) -> typing.List[int]:
            return self.request("CodinGamer", "findFollowingIds", [id])
    
        # ClashOfCode/
    
        def get_codingamer_clash_of_code_rank(self, id: int) -> int:
            return self.request("ClashOfCode", "getClashRankByCodinGamerId", [id])
    
        def get_clash_of_code_from_handle(self, handle: str) -> ClashOfCode:
            return self.request("ClashOfCode", "findClashByHandle", [handle])
    
        def get_pending_clash_of_code(self) -> ClashOfCode:
            return self.request("ClashOfCode", "findPendingClashes")
    
        # Notification
    
        def get_unread_notifications(self, id: int) -> typing.List[Notification]:
            return self.request("Notification", "findUnreadNotifications", [id])
    
        def get_unseen_notifications(self, id: int) -> typing.List[Notification]:
            return self.request("Notification", "findUnseenNotifications", [id])
    
        def get_last_read_notifications(self, id: int) -> typing.List[Notification]:
            return self.request(
                "Notification", "findLastReadNotifications", [id, None]
            )
    
        # Leaderboards
    
        def get_global_leaderboard(
            self,
    
    

    23aaa6ecba8d489eb5cda32f2848dd0a2601700e

    duplicate todo 
    opened by github-actions[bot] 1
  • [BUG] Login service not found

    [BUG] Login service not found

    Describe the bug

    When logging in to CodinGame API, with Client.login(email, password), a LoginError is raised saying Service not found: codingamer.loginsitev2(3). This means that the endpoint in the API no longer exists, so the login endpoint was changed.

    To Reproduce

    Steps to reproduce the behavior:

    1. Copy this code to a file (you can replace email and password with your own but that doesn't change anything to the error):
      import codingame
      client = codingame.Client()
      client.login("[email protected]", "password")
      
    2. Execute the previously copied code.
    3. See error: codingame.exceptions.LoginError: Service not found: codingamer.loginsitev2(3)

    Expected behavior

    Login works and doesn't raise an error.

    Environment information:

    • OS: Windows 10 (but works on any OS)
    • Python version: 3.7.6 (but works on any version)
    • codingame module version: 1.0.1 (but works on any version)

    Additional context

    The login endpoint was moved to CodinGamer/loginSite and now needs a Captcha or a valid session.

    bug 
    opened by takos22 1
  • Add marking notifications as seen or read

    Add marking notifications as seen or read

    Feature description

    Add Client.mark_notifications_as_seen, Client.mark_notifications_as_read, Notification.mark_as_seen`` andNotification.mark_as_read` to mark a notification as seen or read.

    Added to both the Notification class and Client class for convenience. Client.mark_notifications_as_seen and Client.mark_notifications_as_read take a list of Notification objects or notification IDs to mark them all at the same time and only with one API call.

    Checklist

    • [x] If classes/methods/attributes were added/changed then they have been documented and tested.
      • [x] I have updated the documentation to reflect the changes.
      • [x] I have updated the tests to support the changes.
    • [ ] This PR fixes an issue.
    • [x] This PR adds something new (e.g. new class, method or attribute).
    • [ ] This PR is a breaking change (e.g. classes, methods, attributes or parameters removed/renamed)
    • [ ] This PR is not a code change (e.g. documentation, README, ...)
    • [x] The code follows the style guidelines and passes linting and testing.
    enhancement 
    opened by takos22 0
  • [RELEASE] 1.3.0

    [RELEASE] 1.3.0

    Version 1.3.0

    Added

    • Client.get_unread_notifications.
    • Client.get_read_notifications.
    • PartialCodinGamer.
    • Notification.codingamer.
    • Notification.seen, Notification.seen_date, Notification.read and Notification.read_date.
    • NotificationType and NotificationTypeGroup enums for Notification.type and Notification.type_group.
    • NotificationData and subclasses.

    Changed

    • Deprecated Notification.creation_time in favor of Notification.date

    Removed

    • Removed Notification._raw.
    release 
    opened by takos22 0
  • [RELEASE] v1.2.0

    [RELEASE] v1.2.0

    Version 1.2.0

    Added

    • Client.request to make requests to CodinGame API services that aren't implemented yet in the library. Resolves #7.

    Removed

    • codingame.endpoints submodule.
    release 
    opened by takos22 0
  • [FR] Use ID of the logged in user for follower endpoints

    [FR] Use ID of the logged in user for follower endpoints

    Related problem

    Only the followers and follows of the logged in CodinGamer can be accessed with CodinGamer.get_followers and CodinGamer.get_followed.

    Wanted solution

    Being able to access anyone's followers and follows, the 2nd parameter to the API in HTTPClient.get_codingamer_followers and HTTPClient.get_codingamer_following need to be updated to self.state.codingamer.id

        def get_codingamer_followers(self, id: int) -> typing.List[Follower]:
            # TODO fix this to use [id, logged_in.id, None]
            return self.request("CodinGamer", "findFollowers", [id, id, None])
    
        def get_codingamer_following(self, id: int) -> typing.List[Following]:
            # TODO fix this to use [id, logged_in.id]
            return self.request("CodinGamer", "findFollowing", [id, id])
    

    Considered alternatives

    Using CodinGamer.get_followers_ids and CodinGamer.get_followed_ids, but that would be slower as it requires way more requests to the API.

    Additional context

    None

    enhancement good first issue todo 
    opened by github-actions[bot] 0
  • [FR] Add ConnectionState.current_language

    [FR] Add ConnectionState.current_language

    Related problem

    When dealing with endpoint that give a title/description in both French and English, displaying both is a bit bulky, so having the ConnectionState know its current language would help displaying only the message in the correct language.

    Wanted solution

    Adding a ConnectionState.current_language attribute/property to display texts in the right language.

    Considered alternatives

    None

    Additional context

    None

    enhancement good first issue todo 
    opened by github-actions[bot] 0
Releases(v1.4.0)
  • v1.4.0(Aug 18, 2022)

    Version 1.4.0

    Changelog

    Added

    • Client.mark_notifications_as_seen and Client.mark_notifications_as_read.
    • Notification.mark_as_seen and Notification.mark_as_read.

    Removed

    • Removed support for python 3.6 as it has reached its end of life. For more information, see PEP 494.

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Jun 20, 2022)

    Version 1.3.0

    Changelog

    Added

    • Client.get_unread_notifications.
    • Client.get_read_notifications.
    • PartialCodinGamer.
    • Notification.codingamer.
    • Notification.seen, Notification.seen_date, Notification.read and Notification.read_date.
    • NotificationType and NotificationTypeGroup enums for Notification.type and Notification.type_group.
    • NotificationData and subclasses.

    Changed

    • Deprecated Notification.creation_time in favor of Notification.date

    Removed

    • Removed Notification._raw.

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.2.4(Jun 16, 2022)

    Version 1.2.4

    Changelog

    Fixed

    • CodinGamer.get_followers and CodinGamer.get_followed now work while being logged in as any user, not just as the user you want to get the followers of.

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.2.3(Nov 7, 2021)

    Version 1.2.3

    Changelog

    Fixed

    • ImportError of codingame.types submodule when importing codingame, the 1.2.1 and 1.2.2 fixes don't work.

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.2.2(Nov 6, 2021)

    Version 1.2.2

    Changelog

    Fixed

    • ImportError of codingame.types submodule when importing codingame.

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.2.1(Nov 6, 2021)

    Version 1.2.1

    Changelog

    Fixed

    • ModuleNotFoundError of codingame.types submodule when importing codingame.

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Nov 4, 2021)

    Version 1.2.0

    Changelog

    Added

    • Client.request to make requests to CodinGame API services that aren't implemented yet in the library.

    Removed

    • codingame.endpoints submodule.

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Nov 1, 2021)

    Version 1.1.0

    Changelog

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Jul 12, 2021)

    Version 1.0.1

    Changelog

    • Add CodinGamer.profile_url

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jul 11, 2021)

    Version 1.0

    Changelog

    • Add support for asynchronous client with Client(is_async=True), see the docs.

    • Add support for context managers:

      # synchronous
      with Client() as client:
          client.get_global_leaderboard()
      
      # asynchronous
      async with Client(is_async=True) as client:
          await client.get_global_leaderboard()
      
    • Remove properties like CodinGamer.followers in favor of methods like CodinGamer.get_followers to better differentiate API calls and to make it compatible with async API calls. Here's a list of all of the changed ones:

      • Client.language_ids -> Client.get_language_ids
      • Client.unseen_notifications -> Client.get_unseen_notifications
      • CodinGamer.followers -> CodinGamer.get_followers
      • CodinGamer.followers_ids -> CodinGamer.get_followers_ids
      • CodinGamer.following -> CodinGamer.get_followed
      • CodinGamer.following_ids -> CodinGamer.get_followed_ids
      • CodinGamer.clash_of_code_rank -> CodinGamer.get_clash_of_code_rank
    • Add more exceptions: LoginError regroups all the exceptions related to login: LoginRequired, EmailRequired, MalformedEmail, PasswordRequired, EmailNotLinked and IncorrectPassword. And NotFound regroups CodinGamerNotFound, ClashOfCodeNotFound, ChallengeNotFound and PuzzleNotFound.

    • Make all attributes of CodinGame models read-only.

    • Add ChallengeLeaderboard.has_leagues and PuzzleLeaderboard.has_leagues.

    • Add Notification._raw.

    • Change ClashOfCode.time_before_start and ClashOfCode.time_before_end from float to datetime.timedelta.

    • Remove argument type validation, not my fault if you can't read the docs.

    • Rewrite the way the client works to implement a class to manage the connection state and separate the Client that the user uses from the HTTP client that interacts with the API.

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Jun 19, 2021)

    Version 0.4

    Changelog

    • Add support for leaderboards in Client.get_global_leaderboard, Client.get_challenge_leaderboard and Client.get_puzzle_leaderboard. See docs.
    • Bug fixes

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io/en/latest/index.html

    Source code(tar.gz)
    Source code(zip)
  • v0.3.5(Dec 10, 2020)

    Version 0.3.5

    Changelog

    • Add support for ids in Client.get_codingamer.

      import codingame
      client = codingame.Client()
      codingamer = client.get_codingamer(3877165)
      print(codingamer.pseudo)
      
    • Add CodinGamer.followers_ids and CodinGamer.following_ids to get information without logging in.

      import codingame
      client = codingame.Client()
      codingamer = client.get_codingamer(3877165)
      print(codingamer.followers_ids)
      print(codingamer.following_ids)
      
    • Add CodinGamer.clash_of_code_rank to get the CodinGamer’s ranking in Clash of Codes.

      import codingame
      client = codingame.Client()
      codingamer = client.get_codingamer(3877165)
      print(codingamer.clash_of_code_rank)
      
    • Bug fixes

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io/en/latest/index.html

    Source code(tar.gz)
    Source code(zip)
  • v.0.3.4(Dec 1, 2020)

  • v0.3.3(Nov 6, 2020)

    Version 0.3.3

    Changelog

    Add support for usernames in Client.get_codingamer.

    import codingame
    client = codingame.Client()
    codingamer= client.get_codingamer("takos")
    print(codingamer.pseudo)
    

    Bug fixes

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io/en/latest/index.html

    Source code(tar.gz)
    Source code(zip)
  • v0.3.2(Sep 23, 2020)

    Version 0.3.2

    Changelog

    Add Client.get_pending_clash_of_code that returns a pending public Clash of Code.

    import codingame
    client = codingame.Client()
    clash_of_code = client.get_pending_clash_of_code()
    print(clash_of_code.join_url)
    

    Bug fixes

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io/en/latest/index.html

    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Sep 20, 2020)

    Version 0.3.1

    Changelog

    Add Client.notifications that returns a generator of all the notifications. Note: you need to login for the notifications.

    import codingame
    client = codingame.Client("email", "password")
    notifications = [n for n in client.notifications]
    

    Bug fixes

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io/en/latest/index.html

    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Sep 20, 2020)

    Version 0.3.0

    Changelog

    Add login with Client:

    import codingame
    # like this
    client = codingame.Client()
    client.login("email", "password")
    # or like this
    client = codingame.Client("email", "password")
    # then you can get the loged in user with like this
    if client.logged_in:
        user = client.codingamer
    

    Add list of language ids accessible with Client().language_ids Add CodinGamer.followers and CodinGamer.following for the currently logged in CodinGamer Bug fixes

    Update

    Update the module by doing pip install codingame --upgrade

    Links

    PyPi: https://pypi.org/project/codingame Docs: https://codingame.readthedocs.io/en/latest/index.html

    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Sep 16, 2020)

  • v0.2.0(Sep 13, 2020)

    Version 0.2.0

    Changelog

    Add Client.get_clash_of_code() and data classes for it (ClashOfCode and Player)

    Update

    Update the module by doing pip install codingame --upgrade

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Sep 12, 2020)

Owner
Takos
Python developer and freelancer
Takos
Script to quickly get the metrics from Github repos to analyze.

commit-prefix-analysis Script to quickly get the metrics from Github repos to analyze. Setup Install the Github CLI. You'll know its working when runn

David Carpenter 1 Dec 17, 2022
Implements a polyglot REPL which supports multiple languages and shared meta-object protocol scope between REPLs.

MetaCall Polyglot REPL Description This repository implements a Polyglot REPL which shares the state of the meta-object protocol between the REPLs. Us

MetaCall 10 Dec 28, 2022
Python PID Controller and Process Simulator (FOPDT) with GUI.

PythonPID_Simulator Python PID Controller and Process Simulator (FOPDT) with GUI. Run the File. Then select Model Values and Tune PID.. Hit Refresh to

19 Oct 14, 2022
Traductor de webs desde consola usando el servicio de Google Traductor.

proxiGG Traductor de webs desde consola usando el servicio de Google Traductor. Se adjunta el código fuente para Python3 y un binario compilado en C p

@as_informatico 2 Oct 20, 2021
Our Ping Pong Project of numerical analysis, 2nd year IC B2 INSA Toulouse

Ping Pong Project The objective of this project was to determine the moment of impact of the ball with the ground. To do this, we used different model

0 Jan 02, 2022
Sequence clustering and database creation using mmseqs, from local fasta files

Sequence clustering and database creation using mmseqs, from local fasta files

Ana Julia Velez Rueda 3 Oct 27, 2022
Add-In for Blender to automatically save files when rendering

Autosave - Render: Automatically save .blend, .png and readme.txt files when rendering with Blender Purpose This Blender Add-On provides an easy way t

Volker 9 Aug 10, 2022
Automatización del proceso Inmofianza

Selenium Inmofianza Proyecto de pruebas automatizadas con selenium webdriver para el aplicativo Omnicanalidad Pre-requisitos 📋 Componentes que deben

Natalia Narváez 1 Jan 07, 2022
Source for the Fedora Silverblue and Kinoite variants.

Source for the Fedora Silverblue and Kinoite variants.

Fedora Kinoite 7 Aug 20, 2022
Strong Typing in Python with Decorators

typy Strong Typing in Python with Decorators Description This light-weight library provides decorators that can be used to implement strongly-typed be

Ekin 0 Feb 06, 2022
Bootstraparse is a personal project started with a specific goal in mind: creating static html pages for direct display from a markdown-like file

Bootstraparse is a personal project started with a specific goal in mind: creating static html pages for direct display from a markdown-like file

1 Jun 15, 2022
Stopmagic gives you the power of creating amazing Stop Motion animations faster and easier than ever before.

Stopmagic gives you the power of creating amazing Stop Motion animations faster and easier than ever before. This project is maintained by Aldrin Mathew.

Aldrin's Art Factory 67 Dec 31, 2022
SWS Filters App - SWS Filters App With Python

SWS Filters App Fun 😅 ... Fun 😅 Click On photo and see 😂 😂 😂 Your Video rec

Sagar Jangid 3 Jul 07, 2022
A simple python script that print the Mandelbrot set for every power of the formal formula.

Python Mandelbrot A simple python script that print the Mandelbrot set for every power of the formal formula.

Paride Giunta 2 Apr 15, 2022
World's best free and open source ERP.

World's best free and open source ERP.

Frappe 12.5k Jan 07, 2023
Two predictive attributes (Speed and Angle) and one attribute target (Power)

Two predictive attributes (Speed and Angle) and one attribute target (Power). A container crane has the function of transporting containers from one point to another point. The difficulty of this tas

Astitva Veer Garg 1 Jan 11, 2022
Find all social media accounts with a username!

Aliens_eye FIND ALL SOCIAL MEDIA ACCOUNTS WITH A USERNAME! OSINT To install: Open terminal and type: git clone https://github.com/BLINKING-IDIOT/Alien

Aaron Thomas 84 Dec 28, 2022
Free components that wrap up Python into Delphi and Lazarus (FPC)

Python for Delphi (P4D) is a set of free components that wrap up the Python DLL into Delphi and Lazarus (FPC). They let you easily execute Python scri

747 Jan 02, 2023
A feed generator. Currently supports generating RSS feeds from Google, Bing, and Yahoo news.

A feed generator. Currently supports generating RSS feeds from Google, Bing, and Yahoo news.

Josh Cardenzana 0 Dec 13, 2021
PBN Obfuscator: A overpowered obfuscator for python, which will help you protect your source code

PBN Obfuscator PBN Obfuscator is a overpowered obfuscator for python, which will

Karim 6 Dec 22, 2022