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
oracle arm registration script.

oracle_arm oracle arm registration script. 乌龟壳刷ARM脚本 本脚本优点 简单,主机配置好oci,然后下载main.tf即可,不用自己获取各种参数。 运行环境配置 本简单脚本使用python3编写,请自行配置好python3环境和requests库。(高版

test1234455 419 Jan 01, 2023
Script to automate the scanning of "old printed photos"

photoscanner Script to automate the scanning of "old printed photos" Just run: ./scan_photos.py The script is prepared to be run by fades. Otherw

Facundo Batista 2 Jan 21, 2022
TeamFleming is a multicultural group of 20 young bioinformatics enthusiasts participating in the 2021 HackBio Virtual Summer Internship

💻 Welcome to Team Fleming's Repo! #TeamFleming is a multicultural group of 20 young bioinformatics enthusiasts participating in the 2021 HackBio Virt

3 Aug 08, 2021
A python script that automatically joins a zoom meeting based on your timetable.

Zoom Automation A python script that automatically joins a zoom meeting based on your timetable. What does it do? It performs the following processes:

Shourya Gupta 3 Jan 01, 2022
Ahmed Hossam 12 Oct 17, 2022
a pull switch (or BYO button) that gets you out of video calls, quick

zoomout a pull switch (or BYO button) that gets you out of video calls, quick. As seen on Twitter System compatibility Tested on macOS Catalina (10.15

Brian Moore 422 Dec 30, 2022
Automatically find solutions when your Python code encounters an issue.

What The Python?! Helping you find answers to the errors Python spits out. Installation You can find the source code on GitHub at: https://github.com/

What The Python?! 139 Dec 14, 2022
A bot to use in a pump & dump event

A bot to use in a pump & dump event on Binance.com. Please note the bot is in heavy devleopment currently so be aware of errors. If you experience err

Freddie Jonas 189 Dec 24, 2022
Bazel rules to install Python dependencies with Poetry

rules_python_poetry Bazel rules to install Python dependencies from a Poetry project. Works with native Python rules for Bazel. Getting started Add th

Martin Liu 7 Dec 15, 2021
Trackthis - This library can be used to track USPS and UPS shipments.

Trackthis - This library can be used to track USPS and UPS shipments. It has the option of returning the raw API response, or optionally, it can be used to standardize the USPS and UPS responses so t

Aaron Guzman 0 Mar 29, 2022
*考研学习利器,玩电脑控制不住自己时,可以使用该程序定日期锁屏,同时有精美壁纸锁屏显示,也不会枯燥。

LockscreenbyTime_win10 A python program in win10. You can set the time to lock the computer(by setting year, month, day), Fullscreen pictures will sho

PixianDouban 4 Jul 10, 2022
A web interface for a soft serve Git server.

Soft Serve monitor Soft Sevre is a very nice git server. It offers a really nice TUI to browse the repositories on the server. Unfortunately, it does

Maxime Bouillot 5 Apr 26, 2022
Subscribe, listen and (in the future) download your favorite podcasts, quickly and easily.

Minimal Podcasts Player https://github.com/son-link/minimal-podcasts-player Subscribe, listen and (in the future) download your favorite podcasts, qui

Alfonso Saavedra 14 Nov 11, 2022
Framework for creating efficient data processing pipelines

Aqueduct Framework for creating efficient data processing pipelines. Contact Feel free to ask questions in telegram t.me/avito-ml Key Features Increas

avito.tech 137 Dec 29, 2022
A collection of modern themes for Tkinter TTK

ttkbootstrap A collection of modern flat themes inspired by Bootstrap. Also includes TTK Creator which allows you to easily create and use your own th

Israel Dryer 827 Jan 04, 2023
API moment - LussovAPI

LussovAPI TL;DR: py API container, pip install -r requirements.txt, example, main configuration Long version: Install Dependancies Download file requi

William Pedersen 1 Nov 30, 2021
You'll learn about Iterators, Generators, Closure, Decorators, Property, and RegEx in detail with examples.

07_Python_Advanced_Topics Introduction 👋 In this tutorial, you will learn about: Python Iterators: They are objects that can be iterated upon. In thi

Milaan Parmar / Милан пармар / _米兰 帕尔马 252 Dec 23, 2022
Chalice - A tool to facilitate Python based lambda deployment

Chalice is a tool to facilitate Python based lambda deployment. This repo contains the output of my basic exploration of this tool.

Csilla Bessenyei 1 Feb 03, 2022
Kubernetes-native workflow automation platform for complex, mission-critical data and ML processes at scale. It has been battle-tested at Lyft, Spotify, Freenome, and others and is truly open-source.

Flyte Flyte is a workflow automation platform for complex, mission-critical data, and ML processes at scale Home Page · Quick Start · Documentation ·

Flyte 3k Jan 01, 2023