From dcad429ddbabe5bba10e38f656ad3aa846093f6b Mon Sep 17 00:00:00 2001 From: jmkdev Date: Tue, 19 Jan 2021 17:12:24 -0500 Subject: [PATCH] readme update + httpx + docs --- README.md | 7 +- docs/assets.html | 62 ++- docs/badges.html | 12 +- docs/chat.html | 41 +- docs/client.html | 221 ++++++--- docs/events.html | 147 ++++++ docs/extensions/anticaptcha.html | 230 +++++++++ docs/extensions/bots.html | 3 + docs/extensions/prompt.html | 55 ++- docs/games.html | 57 ++- docs/groups.html | 808 ++++++++++++++++++++----------- docs/index.html | 10 + docs/roles.html | 12 +- docs/thumbnails.html | 174 ++++++- docs/trades.html | 8 +- docs/users.html | 24 +- docs/utilities/errors.html | 240 ++++++++- docs/utilities/pages.html | 48 +- docs/utilities/requests.html | 130 ++++- docs/wall.html | 354 ++++++++++++++ setup.py | 2 +- 21 files changed, 2152 insertions(+), 493 deletions(-) create mode 100644 docs/events.html create mode 100644 docs/wall.html diff --git a/README.md b/README.md index 07c9dc4a..99bb5544 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,11 @@ ro.py is an object oriented, asynchronous wrapper for the Roblox Web API (and ot ro.py allows you to automate much of what you would do on the Roblox website and on other Roblox-related websites. ## Requirements +- httpx (for sending requests) - iso8601 (for parsing dates) - signalrcore (for recieving notifications) - ~~cachecontrol (for caching requests)~~ -- requests-async (for sending requests, might be updated to a new lib soon) +- ~~requests-async (for sending requests, might be updated to a new lib soon)~~ - pytweening (for UI animations for the "prompts" extension, optional) - wxPython (for the "prompts" extension, optional) - wxasync (see above) @@ -32,7 +33,9 @@ We are not responsible for any malicious use of this library. If you use this library in a way that violates the [Roblox Terms of Use](https://en.help.roblox.com/hc/en-us/articles/115004647846-Roblox-Terms-of-Use) your account may be punished. ## Documentation -You can view documentation for ro.py at [ro.py.jmksite.dev](https://ro.py.jmksite.dev/). If something's missing from docs, feel free to dive into the code and read the docstrings as most things are documented there. +You can view documentation for ro.py at [ro.py.jmksite.dev](https://ro.py.jmksite.dev/). +If something's missing from docs, feel free to dive into the code and read the docstrings as most things are documented there. +The docs are generated from docstrings in the code using pdoc3. ## Installation You can install ro.py from pip: diff --git a/docs/assets.html b/docs/assets.html index 053c7417..c7d8788d 100644 --- a/docs/assets.html +++ b/docs/assets.html @@ -79,9 +79,10 @@

Module ro_py.assets

ID of the asset. """ - def __init__(self, requests, asset_id): + def __init__(self, cso, asset_id): self.id = asset_id - self.requests = requests + self.cso = cso + self.requests = cso.requests self.target_id = None self.product_type = None self.asset_id = None @@ -172,7 +173,15 @@

Module ro_py.assets

class UserAsset(Asset): def __init__(self, requests, asset_id, user_asset_id): super().__init__(requests, asset_id) - self.user_asset_id = user_asset_id + self.user_asset_id = user_asset_id + + +class Events: + def __init__(self, cso): + self.cso = cso + + async def bind(self, func, event, delay=15): + pass
@@ -186,7 +195,7 @@

Classes

class Asset -(requests, asset_id) +(cso, asset_id)

Represents an asset.

@@ -213,9 +222,10 @@

Parameters

ID of the asset. """ - def __init__(self, requests, asset_id): + def __init__(self, cso, asset_id): self.id = asset_id - self.requests = requests + self.cso = cso + self.requests = cso.requests self.target_id = None self.product_type = None self.asset_id = None @@ -416,6 +426,40 @@

Returns

+
+class Events +(cso) +
+
+
+
+ +Expand source code + +
class Events:
+    def __init__(self, cso):
+        self.cso = cso
+
+    async def bind(self, func, event, delay=15):
+        pass
+
+

Methods

+
+
+async def bind(self, func, event, delay=15) +
+
+
+
+ +Expand source code + +
async def bind(self, func, event, delay=15):
+    pass
+
+
+
+
class UserAsset (requests, asset_id, user_asset_id) @@ -483,6 +527,12 @@

Asset
  • +

    Events

    + +
  • +
  • UserAsset

  • diff --git a/docs/badges.html b/docs/badges.html index 78c5d0e1..01397b20 100644 --- a/docs/badges.html +++ b/docs/badges.html @@ -84,9 +84,10 @@

    Module ro_py.badges

    badge_id ID of the badge. """ - def __init__(self, requests, badge_id): + def __init__(self, cso, badge_id): self.id = badge_id - self.requests = requests + self.cso = cso + self.requests = cso.requests self.name = None self.description = None self.display_name = None @@ -124,7 +125,7 @@

    Classes

    class Badge -(requests, badge_id) +(cso, badge_id)

    Represents a game-awarded badge.

    @@ -150,9 +151,10 @@

    Parameters

    badge_id ID of the badge. """ - def __init__(self, requests, badge_id): + def __init__(self, cso, badge_id): self.id = badge_id - self.requests = requests + self.cso = cso + self.requests = cso.requests self.name = None self.description = None self.display_name = None diff --git a/docs/chat.html b/docs/chat.html index c6c0b1e8..cfb43d2c 100644 --- a/docs/chat.html +++ b/docs/chat.html @@ -73,8 +73,9 @@

    Module ro_py.chat

    class ConversationTyping: - def __init__(self, requests, conversation_id): - self.requests = requests + def __init__(self, cso, conversation_id): + self.cso = cso + self.requests = cso.requests self.id = conversation_id async def __aenter__(self): @@ -97,22 +98,23 @@

    Module ro_py.chat

    class Conversation: - def __init__(self, requests, conversation_id=None, raw=False, raw_data=None): - self.requests = requests + def __init__(self, cso, conversation_id=None, raw=False, raw_data=None): + self.cso = cso + self.requests = cso.requests self.raw = raw self.id = None self.title = None self.initiator = None self.type = None - self.typing = ConversationTyping(self.requests, conversation_id) + self.typing = ConversationTyping(self.cso, conversation_id) if self.raw: data = raw_data self.id = data["id"] self.title = data["title"] - self.initiator = User(self.requests, data["initiator"]["targetId"]) + self.initiator = User(self.cso, data["initiator"]["targetId"]) self.type = data["conversationType"] - self.typing = ConversationTyping(self.requests, conversation_id) + self.typing = ConversationTyping(self.cso, conversation_id) async def update(self): conversation_req = await self.requests.get( @@ -126,7 +128,6 @@

    Module ro_py.chat

    self.title = data["title"] self.initiator = User(self.requests, data["initiator"]["targetId"]) self.type = data["conversationType"] - self.typing = ConversationTyping(self.requests, conversation_id) async def get_message(self, message_id): return Message(self.requests, message_id, self.id) @@ -370,7 +371,7 @@

    Parameters

    class Conversation -(requests, conversation_id=None, raw=False, raw_data=None) +(cso, conversation_id=None, raw=False, raw_data=None)
    @@ -379,22 +380,23 @@

    Parameters

    Expand source code
    class Conversation:
    -    def __init__(self, requests, conversation_id=None, raw=False, raw_data=None):
    -        self.requests = requests
    +    def __init__(self, cso, conversation_id=None, raw=False, raw_data=None):
    +        self.cso = cso
    +        self.requests = cso.requests
             self.raw = raw
             self.id = None
             self.title = None
             self.initiator = None
             self.type = None
    -        self.typing = ConversationTyping(self.requests, conversation_id)
    +        self.typing = ConversationTyping(self.cso, conversation_id)
     
             if self.raw:
                 data = raw_data
                 self.id = data["id"]
                 self.title = data["title"]
    -            self.initiator = User(self.requests, data["initiator"]["targetId"])
    +            self.initiator = User(self.cso, data["initiator"]["targetId"])
                 self.type = data["conversationType"]
    -            self.typing = ConversationTyping(self.requests, conversation_id)
    +            self.typing = ConversationTyping(self.cso, conversation_id)
     
         async def update(self):
             conversation_req = await self.requests.get(
    @@ -408,7 +410,6 @@ 

    Parameters

    self.title = data["title"] self.initiator = User(self.requests, data["initiator"]["targetId"]) self.type = data["conversationType"] - self.typing = ConversationTyping(self.requests, conversation_id) async def get_message(self, message_id): return Message(self.requests, message_id, self.id) @@ -486,15 +487,14 @@

    Methods

    self.id = data["id"] self.title = data["title"] self.initiator = User(self.requests, data["initiator"]["targetId"]) - self.type = data["conversationType"] - self.typing = ConversationTyping(self.requests, conversation_id)
    + self.type = data["conversationType"]
    class ConversationTyping -(requests, conversation_id) +(cso, conversation_id)
    @@ -503,8 +503,9 @@

    Methods

    Expand source code
    class ConversationTyping:
    -    def __init__(self, requests, conversation_id):
    -        self.requests = requests
    +    def __init__(self, cso, conversation_id):
    +        self.cso = cso
    +        self.requests = cso.requests
             self.id = conversation_id
     
         async def __aenter__(self):
    diff --git a/docs/client.html b/docs/client.html
    index 575c8f9c..a82cbe30 100644
    --- a/docs/client.html
    +++ b/docs/client.html
    @@ -66,10 +66,11 @@ 

    Module ro_py.client

    from ro_py.assets import Asset from ro_py.badges import Badge from ro_py.chat import ChatWrapper +from ro_py.events import EventTypes from ro_py.trades import TradesWrapper -from ro_py.utilities.cache import CacheType from ro_py.utilities.requests import Requests from ro_py.accountsettings import AccountSettings +from ro_py.utilities.cache import Cache, CacheType from ro_py.accountinformation import AccountInformation from ro_py.utilities.errors import UserDoesNotExistError, InvalidPlaceIDError from ro_py.captcha import UnsolvedLoginCaptcha @@ -77,6 +78,19 @@

    Module ro_py.client

    import logging +class ClientSharedObject: + """ + This object is shared across most instances and classes for a particular client. + """ + def __init__(self, client): + self.client = client + """Client (parent) of this object.""" + self.cache = Cache() + """Cache object to keep objects that don't need to be recreated.""" + self.requests = Requests() + """Reqests object for all web requests.""" + + class Client: """ Represents an authenticated Roblox client. @@ -88,7 +102,10 @@

    Module ro_py.client

    """ def __init__(self, token: str = None): - self.requests = Requests() + self.cso = ClientSharedObject(self) + """ClientSharedObject. Passed to each new object to share information.""" + self.requests = self.cso.requests + """See self.cso.requests""" logging.debug("Initialized requests.") @@ -100,16 +117,18 @@

    Module ro_py.client

    """ChatWrapper object. Only available for authenticated clients.""" self.trade = None """TradesWrapper object. Only available for authenticated clients.""" + self.events = EventTypes + """Types of events used for binding events to a function.""" if token: self.token_login(token) logging.debug("Initialized token.") - self.accountinformation = AccountInformation(self.requests) - self.accountsettings = AccountSettings(self.requests) + self.accountinformation = AccountInformation(self.cso) + self.accountsettings = AccountSettings(self.cso) logging.debug("Initialized AccountInformation and AccountSettings.") - self.chat = ChatWrapper(self.requests) + self.chat = ChatWrapper(self.cso) logging.debug("Initialized chat wrapper.") - self.trade = TradesWrapper(self.requests, self.get_self) + self.trade = TradesWrapper(self.cso, self.get_self) logging.debug("Initialized trade wrapper.") def token_login(self, token): @@ -183,7 +202,7 @@

    Module ro_py.client

    url="https://roblox.com/my/profile" ) data = self_req.json() - return User(self.requests, data['Username'], data['UserId']) + return User(self.cso, data['UserId'], data['Username']) async def get_user(self, user_id): """ @@ -194,10 +213,10 @@

    Module ro_py.client

    user_id ID of the user to generate the object from. """ - user = self.requests.cache.get(CacheType.Users, user_id) + user = self.cso.cache.get(CacheType.Users, user_id) if not user: - user = User(self.requests, user_id) - self.requests.cache.set(CacheType.Users, user_id, user) + user = User(self.cso, user_id) + self.cso.cache.set(CacheType.Users, user_id, user) await user.update() return user @@ -224,10 +243,10 @@

    Module ro_py.client

    username_data = username_req.json() if len(username_data["data"]) > 0: user_id = username_req.json()["data"][0]["id"] # TODO: make this a partialuser - user = self.requests.cache.get(CacheType.Users, user_id) + user = self.cso.cache.get(CacheType.Users, user_id) if not user: - user = User(self.requests, user_id) - self.requests.cache.set(CacheType.Users, user_id, user) + user = User(self.cso, user_id) + self.cso.cache.set(CacheType.Users, user_id, user) await user.update() return user else: @@ -242,10 +261,10 @@

    Module ro_py.client

    group_id ID of the group to generate the object from. """ - group = self.requests.cache.get(CacheType.Groups, group_id) + group = self.cso.cache.get(CacheType.Groups, group_id) if not group: - group = Group(self.requests, group_id) - self.requests.cache.set(CacheType.Groups, group_id, group) + group = Group(self.cso, group_id) + self.cso.cache.set(CacheType.Groups, group_id, group) await group.update() return group @@ -258,10 +277,10 @@

    Module ro_py.client

    universe_id ID of the game to generate the object from. """ - game = self.requests.cache.get(CacheType.Games, universe_id) + game = self.cso.cache.get(CacheType.Games, universe_id) if not game: - game = Game(self.requests, universe_id) - self.requests.cache.set(CacheType.Games, universe_id, game) + game = Game(self.cso, universe_id) + self.cso.cache.set(CacheType.Games, universe_id, game) await game.update() return game @@ -300,10 +319,10 @@

    Module ro_py.client

    asset_id ID of the asset to generate the object from. """ - asset = self.requests.cache.get(CacheType.Assets, asset_id) + asset = self.cso.cache.get(CacheType.Assets, asset_id) if not asset: - asset = Asset(self.requests, asset_id) - self.requests.cache.set(CacheType.Assets, asset_id, asset) + asset = Asset(self.cso, asset_id) + self.cso.cache.set(CacheType.Assets, asset_id, asset) await asset.update() return asset @@ -316,10 +335,10 @@

    Module ro_py.client

    badge_id ID of the badge to generate the object from. """ - badge = self.requests.cache.get(CacheType.Assets, badge_id) + badge = self.cso.cache.get(CacheType.Assets, badge_id) if not badge: - badge = Badge(self.requests, badge_id) - self.requests.cache.set(CacheType.Assets, badge_id, badge) + badge = Badge(self.cso, badge_id) + self.cso.cache.set(CacheType.Assets, badge_id, badge) await badge.update() return badge
    @@ -359,7 +378,10 @@

    Parameters

    """ def __init__(self, token: str = None): - self.requests = Requests() + self.cso = ClientSharedObject(self) + """ClientSharedObject. Passed to each new object to share information.""" + self.requests = self.cso.requests + """See self.cso.requests""" logging.debug("Initialized requests.") @@ -371,16 +393,18 @@

    Parameters

    """ChatWrapper object. Only available for authenticated clients.""" self.trade = None """TradesWrapper object. Only available for authenticated clients.""" + self.events = EventTypes + """Types of events used for binding events to a function.""" if token: self.token_login(token) logging.debug("Initialized token.") - self.accountinformation = AccountInformation(self.requests) - self.accountsettings = AccountSettings(self.requests) + self.accountinformation = AccountInformation(self.cso) + self.accountsettings = AccountSettings(self.cso) logging.debug("Initialized AccountInformation and AccountSettings.") - self.chat = ChatWrapper(self.requests) + self.chat = ChatWrapper(self.cso) logging.debug("Initialized chat wrapper.") - self.trade = TradesWrapper(self.requests, self.get_self) + self.trade = TradesWrapper(self.cso, self.get_self) logging.debug("Initialized trade wrapper.") def token_login(self, token): @@ -454,7 +478,7 @@

    Parameters

    url="https://roblox.com/my/profile" ) data = self_req.json() - return User(self.requests, data['Username'], data['UserId']) + return User(self.cso, data['UserId'], data['Username']) async def get_user(self, user_id): """ @@ -465,10 +489,10 @@

    Parameters

    user_id ID of the user to generate the object from. """ - user = self.requests.cache.get(CacheType.Users, user_id) + user = self.cso.cache.get(CacheType.Users, user_id) if not user: - user = User(self.requests, user_id) - self.requests.cache.set(CacheType.Users, user_id, user) + user = User(self.cso, user_id) + self.cso.cache.set(CacheType.Users, user_id, user) await user.update() return user @@ -495,10 +519,10 @@

    Parameters

    username_data = username_req.json() if len(username_data["data"]) > 0: user_id = username_req.json()["data"][0]["id"] # TODO: make this a partialuser - user = self.requests.cache.get(CacheType.Users, user_id) + user = self.cso.cache.get(CacheType.Users, user_id) if not user: - user = User(self.requests, user_id) - self.requests.cache.set(CacheType.Users, user_id, user) + user = User(self.cso, user_id) + self.cso.cache.set(CacheType.Users, user_id, user) await user.update() return user else: @@ -513,10 +537,10 @@

    Parameters

    group_id ID of the group to generate the object from. """ - group = self.requests.cache.get(CacheType.Groups, group_id) + group = self.cso.cache.get(CacheType.Groups, group_id) if not group: - group = Group(self.requests, group_id) - self.requests.cache.set(CacheType.Groups, group_id, group) + group = Group(self.cso, group_id) + self.cso.cache.set(CacheType.Groups, group_id, group) await group.update() return group @@ -529,10 +553,10 @@

    Parameters

    universe_id ID of the game to generate the object from. """ - game = self.requests.cache.get(CacheType.Games, universe_id) + game = self.cso.cache.get(CacheType.Games, universe_id) if not game: - game = Game(self.requests, universe_id) - self.requests.cache.set(CacheType.Games, universe_id, game) + game = Game(self.cso, universe_id) + self.cso.cache.set(CacheType.Games, universe_id, game) await game.update() return game @@ -571,10 +595,10 @@

    Parameters

    asset_id ID of the asset to generate the object from. """ - asset = self.requests.cache.get(CacheType.Assets, asset_id) + asset = self.cso.cache.get(CacheType.Assets, asset_id) if not asset: - asset = Asset(self.requests, asset_id) - self.requests.cache.set(CacheType.Assets, asset_id, asset) + asset = Asset(self.cso, asset_id) + self.cso.cache.set(CacheType.Assets, asset_id, asset) await asset.update() return asset @@ -587,10 +611,10 @@

    Parameters

    badge_id ID of the badge to generate the object from. """ - badge = self.requests.cache.get(CacheType.Assets, badge_id) + badge = self.cso.cache.get(CacheType.Assets, badge_id) if not badge: - badge = Badge(self.requests, badge_id) - self.requests.cache.set(CacheType.Assets, badge_id, badge) + badge = Badge(self.cso, badge_id) + self.cso.cache.set(CacheType.Assets, badge_id, badge) await badge.update() return badge
    @@ -612,6 +636,18 @@

    Instance variables

    ChatWrapper object. Only available for authenticated clients.

    +
    var cso
    +
    +

    ClientSharedObject. Passed to each new object to share information.

    +
    +
    var events
    +
    +

    Types of events used for binding events to a function.

    +
    +
    var requests
    +
    +

    See self.cso.requests

    +
    var trade

    TradesWrapper object. Only available for authenticated clients.

    @@ -642,10 +678,10 @@

    Parameters

    asset_id ID of the asset to generate the object from. """ - asset = self.requests.cache.get(CacheType.Assets, asset_id) + asset = self.cso.cache.get(CacheType.Assets, asset_id) if not asset: - asset = Asset(self.requests, asset_id) - self.requests.cache.set(CacheType.Assets, asset_id, asset) + asset = Asset(self.cso, asset_id) + self.cso.cache.set(CacheType.Assets, asset_id, asset) await asset.update() return asset @@ -673,10 +709,10 @@

    Parameters

    badge_id ID of the badge to generate the object from. """ - badge = self.requests.cache.get(CacheType.Assets, badge_id) + badge = self.cso.cache.get(CacheType.Assets, badge_id) if not badge: - badge = Badge(self.requests, badge_id) - self.requests.cache.set(CacheType.Assets, badge_id, badge) + badge = Badge(self.cso, badge_id) + self.cso.cache.set(CacheType.Assets, badge_id, badge) await badge.update() return badge @@ -745,10 +781,10 @@

    Parameters

    universe_id ID of the game to generate the object from. """ - game = self.requests.cache.get(CacheType.Games, universe_id) + game = self.cso.cache.get(CacheType.Games, universe_id) if not game: - game = Game(self.requests, universe_id) - self.requests.cache.set(CacheType.Games, universe_id, game) + game = Game(self.cso, universe_id) + self.cso.cache.set(CacheType.Games, universe_id, game) await game.update() return game @@ -776,10 +812,10 @@

    Parameters

    group_id ID of the group to generate the object from. """ - group = self.requests.cache.get(CacheType.Groups, group_id) + group = self.cso.cache.get(CacheType.Groups, group_id) if not group: - group = Group(self.requests, group_id) - self.requests.cache.set(CacheType.Groups, group_id, group) + group = Group(self.cso, group_id) + self.cso.cache.set(CacheType.Groups, group_id, group) await group.update() return group @@ -798,7 +834,7 @@

    Parameters

    url="https://roblox.com/my/profile" ) data = self_req.json() - return User(self.requests, data['Username'], data['UserId']) + return User(self.cso, data['UserId'], data['Username'])
    @@ -824,10 +860,10 @@

    Parameters

    user_id ID of the user to generate the object from. """ - user = self.requests.cache.get(CacheType.Users, user_id) + user = self.cso.cache.get(CacheType.Users, user_id) if not user: - user = User(self.requests, user_id) - self.requests.cache.set(CacheType.Users, user_id, user) + user = User(self.cso, user_id) + self.cso.cache.set(CacheType.Users, user_id, user) await user.update() return user
    @@ -871,10 +907,10 @@

    Parameters

    username_data = username_req.json() if len(username_data["data"]) > 0: user_id = username_req.json()["data"][0]["id"] # TODO: make this a partialuser - user = self.requests.cache.get(CacheType.Users, user_id) + user = self.cso.cache.get(CacheType.Users, user_id) if not user: - user = User(self.requests, user_id) - self.requests.cache.set(CacheType.Users, user_id, user) + user = User(self.cso, user_id) + self.cso.cache.set(CacheType.Users, user_id, user) await user.update() return user else: @@ -988,6 +1024,44 @@

    Returns

    +
    +class ClientSharedObject +(client) +
    +
    +

    This object is shared across most instances and classes for a particular client.

    +
    + +Expand source code + +
    class ClientSharedObject:
    +    """
    +    This object is shared across most instances and classes for a particular client.
    +    """
    +    def __init__(self, client):
    +        self.client = client
    +        """Client (parent) of this object."""
    +        self.cache = Cache()
    +        """Cache object to keep objects that don't need to be recreated."""
    +        self.requests = Requests()
    +        """Reqests object for all web requests."""
    +
    +

    Instance variables

    +
    +
    var cache
    +
    +

    Cache object to keep objects that don't need to be recreated.

    +
    +
    var client
    +
    +

    Client (parent) of this object.

    +
    +
    var requests
    +
    +

    Reqests object for all web requests.

    +
    +
    +

    @@ -1015,6 +1089,8 @@

    Client<
  • accountinformation
  • accountsettings
  • chat
  • +
  • cso
  • +
  • events
  • get_asset
  • get_badge
  • get_game_by_place_id
  • @@ -1023,11 +1099,20 @@

    Client<
  • get_self
  • get_user
  • get_user_by_username
  • +
  • requests
  • token_login
  • trade
  • user_login
  • +
  • +

    ClientSharedObject

    + +
  • diff --git a/docs/events.html b/docs/events.html new file mode 100644 index 00000000..02f637d2 --- /dev/null +++ b/docs/events.html @@ -0,0 +1,147 @@ + + + + + + +ro_py.events API documentation + + + + + + + + + + + + +
    +
    +
    +

    Module ro_py.events

    +
    +
    +
    + +Expand source code + +
    import enum
    +
    +
    +class EventTypes(enum.Enum):
    +    on_join_request = "on_join_request"
    +    on_wall_post = "on_wall_post"
    +    on_shout_update = "on_shout_update"
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class EventTypes +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
    +
    +

    An enumeration.

    +
    + +Expand source code + +
    class EventTypes(enum.Enum):
    +    on_join_request = "on_join_request"
    +    on_wall_post = "on_wall_post"
    +    on_shout_update = "on_shout_update"
    +
    +

    Ancestors

    +
      +
    • enum.Enum
    • +
    +

    Class variables

    +
    +
    var on_join_request
    +
    +
    +
    +
    var on_shout_update
    +
    +
    +
    +
    var on_wall_post
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/extensions/anticaptcha.html b/docs/extensions/anticaptcha.html index a054512e..fb6835a6 100644 --- a/docs/extensions/anticaptcha.html +++ b/docs/extensions/anticaptcha.html @@ -49,6 +49,73 @@

    Module ro_py.extensions.anticaptcha

    +
    + +Expand source code + +
    from ro_py.utilities.errors import IncorrectKeyError, InsufficientCreditError, NoAvailableWorkersError
    +from ro_py.captcha import UnsolvedCaptcha
    +import requests_async
    +import asyncio
    +
    +endpoint = "https://2captcha.com"
    +
    +
    +class Task:
    +    def __init__(self):
    +        self.type = "FunCaptchaTaskProxyless"
    +        self.website_url = None
    +        self.website_public_key = None
    +        self.funcaptcha_api_js_subdomain = None
    +
    +    def get_raw(self):
    +        return {
    +            "type": self.type,
    +            "websiteURL": self.website_url,
    +            "websitePublicKey": self.website_public_key,
    +            "funcaptchaApiJSSubdomain": self.funcaptcha_api_js_subdomain
    +        }
    +
    +
    +class AntiCaptcha:
    +    def __init__(self, api_key):
    +        self.api_key = api_key
    +
    +    async def solve(self, captcha: UnsolvedCaptcha):
    +        task = Task()
    +        task.website_url = "https://roblox.com"
    +        task.website_public_key = captcha.pkey
    +        task.funcaptcha_api_js_subdomain = "https://roblox-api.arkoselabs.com"
    +
    +        data = {
    +            "clientKey": self.api_key,
    +            "task": task.get_raw()
    +        }
    +
    +        create_req = await requests_async.post('https://api.anti-captcha.com/createTask', json=data)
    +        create_res = create_req.json()
    +        if create_res['errorId'] == 1:
    +            raise IncorrectKeyError("The provided anit-captcha api key was incorrect.")
    +        if create_res['errorId'] == 2:
    +            raise NoAvailableWorkersError("There are currently no available workers.")
    +        if create_res['errorId'] == 10:
    +            raise InsufficientCreditError("Insufficient credit in the 2captcha account.")
    +
    +        solution = None
    +        while True:
    +            await asyncio.sleep(5)
    +            check_data = {
    +                "clientKey": self.api_key,
    +                "taskId": create_res['taskId']
    +            }
    +            check_req = await requests_async.get("https://api.anti-captcha.com/getTaskResult", json=check_data)
    +            check_res = check_req.json()
    +            if check_res['status'] == "ready":
    +                solution = check_res['solution']['token']
    +                break
    +
    +        return solution
    +
    @@ -57,6 +124,153 @@

    Module ro_py.extensions.anticaptcha

    +

    Classes

    +
    +
    +class AntiCaptcha +(api_key) +
    +
    +
    +
    + +Expand source code + +
    class AntiCaptcha:
    +    def __init__(self, api_key):
    +        self.api_key = api_key
    +
    +    async def solve(self, captcha: UnsolvedCaptcha):
    +        task = Task()
    +        task.website_url = "https://roblox.com"
    +        task.website_public_key = captcha.pkey
    +        task.funcaptcha_api_js_subdomain = "https://roblox-api.arkoselabs.com"
    +
    +        data = {
    +            "clientKey": self.api_key,
    +            "task": task.get_raw()
    +        }
    +
    +        create_req = await requests_async.post('https://api.anti-captcha.com/createTask', json=data)
    +        create_res = create_req.json()
    +        if create_res['errorId'] == 1:
    +            raise IncorrectKeyError("The provided anit-captcha api key was incorrect.")
    +        if create_res['errorId'] == 2:
    +            raise NoAvailableWorkersError("There are currently no available workers.")
    +        if create_res['errorId'] == 10:
    +            raise InsufficientCreditError("Insufficient credit in the 2captcha account.")
    +
    +        solution = None
    +        while True:
    +            await asyncio.sleep(5)
    +            check_data = {
    +                "clientKey": self.api_key,
    +                "taskId": create_res['taskId']
    +            }
    +            check_req = await requests_async.get("https://api.anti-captcha.com/getTaskResult", json=check_data)
    +            check_res = check_req.json()
    +            if check_res['status'] == "ready":
    +                solution = check_res['solution']['token']
    +                break
    +
    +        return solution
    +
    +

    Methods

    +
    +
    +async def solve(self, captcha: UnsolvedCaptcha) +
    +
    +
    +
    + +Expand source code + +
    async def solve(self, captcha: UnsolvedCaptcha):
    +    task = Task()
    +    task.website_url = "https://roblox.com"
    +    task.website_public_key = captcha.pkey
    +    task.funcaptcha_api_js_subdomain = "https://roblox-api.arkoselabs.com"
    +
    +    data = {
    +        "clientKey": self.api_key,
    +        "task": task.get_raw()
    +    }
    +
    +    create_req = await requests_async.post('https://api.anti-captcha.com/createTask', json=data)
    +    create_res = create_req.json()
    +    if create_res['errorId'] == 1:
    +        raise IncorrectKeyError("The provided anit-captcha api key was incorrect.")
    +    if create_res['errorId'] == 2:
    +        raise NoAvailableWorkersError("There are currently no available workers.")
    +    if create_res['errorId'] == 10:
    +        raise InsufficientCreditError("Insufficient credit in the 2captcha account.")
    +
    +    solution = None
    +    while True:
    +        await asyncio.sleep(5)
    +        check_data = {
    +            "clientKey": self.api_key,
    +            "taskId": create_res['taskId']
    +        }
    +        check_req = await requests_async.get("https://api.anti-captcha.com/getTaskResult", json=check_data)
    +        check_res = check_req.json()
    +        if check_res['status'] == "ready":
    +            solution = check_res['solution']['token']
    +            break
    +
    +    return solution
    +
    +
    +
    +
    +
    +class Task +
    +
    +
    +
    + +Expand source code + +
    class Task:
    +    def __init__(self):
    +        self.type = "FunCaptchaTaskProxyless"
    +        self.website_url = None
    +        self.website_public_key = None
    +        self.funcaptcha_api_js_subdomain = None
    +
    +    def get_raw(self):
    +        return {
    +            "type": self.type,
    +            "websiteURL": self.website_url,
    +            "websitePublicKey": self.website_public_key,
    +            "funcaptchaApiJSSubdomain": self.funcaptcha_api_js_subdomain
    +        }
    +
    +

    Methods

    +
    +
    +def get_raw(self) +
    +
    +
    +
    + +Expand source code + +
    def get_raw(self):
    +    return {
    +        "type": self.type,
    +        "websiteURL": self.website_url,
    +        "websitePublicKey": self.website_public_key,
    +        "funcaptchaApiJSSubdomain": self.funcaptcha_api_js_subdomain
    +    }
    +
    +
    +
    +
    +
    diff --git a/docs/extensions/bots.html b/docs/extensions/bots.html index a352772d..a4d8bfcf 100644 --- a/docs/extensions/bots.html +++ b/docs/extensions/bots.html @@ -152,6 +152,8 @@

    Inherited members

  • accountinformation
  • accountsettings
  • chat
  • +
  • cso
  • +
  • events
  • get_asset
  • get_badge
  • get_game_by_place_id
  • @@ -159,6 +161,7 @@

    Inherited members

  • get_group
  • get_user
  • get_user_by_username
  • +
  • requests
  • token_login
  • trade
  • user_login
  • diff --git a/docs/extensions/prompt.html b/docs/extensions/prompt.html index 423f3d43..8e636f0c 100644 --- a/docs/extensions/prompt.html +++ b/docs/extensions/prompt.html @@ -64,8 +64,53 @@

    Module ro_py.extensions.prompt

    import wx import wxasync from wx import html2 -import os import pytweening +from wx.lib.embeddedimage import PyEmbeddedImage + +icon_image = PyEmbeddedImage( + b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARnQU1B' + b'AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAhaSURBVGhDxZl5bFRVFMbPfTNtQRTF' + b'uOAWVKKIylqptCBiNBQ1MURjQv8Qt8RoxCWKawTFGLdo4oIaY2LUGCUmBo3BAKJgtRTFQi3u' + b'KBA1LhEXqMK0nb7n79w7M05f36zt1C+9c++7b/re+c757rnLGCkBQbvMkyq5XHxZw+UGyldm' + b'guyzN/8nFEWgftGqC/Z1j1q55YrTa7jcKCNlgnRKkv/+juuPKOtob6T+FkJJ6iFDQQIYP5xq' + b'K+WG1kfmriQKZ0tcVhOFmHj0xikBpVsSPO1rWi3U66k3SbXsNONoVRDFEJhovNingd+7mcsZ' + b'kEhA4hUZJk2Y/B/0SUomRvEpPbKHvs9pfZgitJno/EI9qFAfFkK9icXFi9dMpX2l65IleHy3' + b'NTYNjUIPRUl1UwxCi0u91MgtvGUlpLYGHbKWsiTYKrMpB/OtAaOYCLyK8fMDPylB4P/MRy1R' + b'+Jko3C3D5Z6ih7CSTRcl6MtPvL2N1nrqD6m/IEJ/U5eEvAQwfj+qDuPFxyoBr2qY+D2JZRC4' + b'DgIHcm8TWekE6/lSoG9Njx9tdxE/IztofUxRQprhvoFQF3VeFCIwRYzZRDOG5/m24c9LMB5m' + b'QqINEvMZqK9ajw4EaoVGRgkpuniikW9ptVKvo/6Ieoc5VXrt/SwUInCtV1WzzO/5zxHISfxk' + b'15ogMOe2Lmg0+G4VOj+nsK9KQDYhl+H20vclrXRCaCM6P1AXHMRn2gdkAePFxKrmGBNcZCZZ' + b'j9xJ5u8qKh0UC32nziaaENQxRvaDUC3RvoF6BeOngyTQjALuyhkBvD+C6jNS6LFIxnWmoFkp' + b'6E1qzq9DSnt40NMM6GuGbE5WZ+no/Fva8vltPII/JvA1qfcFxuuA1inqetcj9+GtX23YhwJq' + b'kvPp6nwEZnjxakwKaSiFIMnINd5NROp4M5mUGMj9ZKShg8t8zfkIoP9o4xXMCQzoqlE0l7oe' + b'eY4obEGnlYdGOil/8NkeSQCvHkB1Wlj7YfhEgTEyn+/PJgo6Au4kvH7+3DYIcFLtIOq/5orA' + b'yeT7o6L03wdECAKa7B6Yvmh1NSRW4ZkVpNXKwhFoNlNyp9GZJl7NvdwSSkOjwFiZzoRwaapr' + b'MXm7c1DTahhO/x/oR67XzBI0XixcpMxipHQoUfgSET1ZsSg4/e/is10v+xHACF3j1BbSfzbc' + b'OqnmGJq3ux55lAG9k7mh8FRZKpx82nGUkoh8/Cno/8iC+g9B0yr/dzUOmMTD/0B9N5KrN1Pv' + b'tdEYRkkv3gYCR8DKRxFFQPXPawrrPxuaVk28SufHJXU3rRFIvCnfSx1vmEzIL2FcPI+0dD2T' + b'vQ0qDUreLRyb7SeIIkD+L837GTjOQVVqVWnmSi+Lrm2Ul81ENkNGyBvyYNnjQ63tZcbXFJpC' + b'HwKE/yCqKaXovw+cPNa2PDzHNsKw6/tAxpYtI+cY1b9OYhbhCEwwnje6VP1bsFcgpeoastV1' + b'9AeLPh3WDXalWQ6ctRn5KMIEzjCx0vWvMIbRFQQ7aX7jeiIxDu+P6b8tKQJO/2pYZgArwgRK' + b'yv/ZYEbWagPL63yL6gb0z1o8dVUK1NJee6qhRzwZZAigfz0lKF//apUx2xtufUcTZj8EW2x1' + b'TlnGK5z+t6D/v2wrhcxwgsBZePG98gkAY3T/tIOds57SreN6Y3fnru2fPNOUDDRv+PI688GF' + b'ZSVSHT375DYIPOw6HLIlhP4HvKCvYSycxHMuY9f2InNDe82Bh3+Mc+aRRhVL7f42LNxCUDdr' + b'/tI9cQj2URdf/JpWZes/A1anuqzQfbMu8sBwBge53zymEsV7HUThmZLnAbVSz5HEnvT1gSXw' + b'45iRh1JN0pcPKiDk9yR0nTSGq0WuUx5CQj+kNF0c3HfbcMBu28pCOpiT0P8hZeX/IpBaJy0k' + b'CuMx4jfEcG9qTVMcnJXv288Q0gRmDYL+c8Kuk2JVusu7Txbs0a6X0HRrUdtPp3/1bIu9DsGb' + b'fvNqrc+QCnk/Dbf9jM+rP2zDuURBB4huP/U3hvzQSPnyI59f2OsQPGOCw6knDrr++4HtJzqi' + b'cT9SGg6J9eyslhcc0E5qqv9O2wpBHzgZzxysYa40/N4ePZqcTPMq22HkbmLxZ97x4CIUqX+F' + b'EkD/paSEgcFG2pg7iMKReHU78ng051hQ47vtyilS/wol0KjrGBfdykNneqKgsl3seuQJZtiv' + b'Iw/FnP71EFc3QpFQq1eQq5uZgv70yETkbM0YsK8cIXtA7MUuJwrTUtq+y90JwQljE9/5x7Yi' + b'kMkBLMKOJt/V0pzNnD0TX42H0AhCY71m10h5TupKhRev1sz0bhCYxtYFjfhP3mZAN9rT6DR0' + b'WZiQhRB4ynX0R2QSa7h1Le4PjsfgOi7P4un11Cd4sWqrVtWxm/QGRkgjzsBuYgm+nM3OVCTT' + b'wiOH2azvLONFUgcBt5aNQCSBMIgOhgcn8rAGLomQJXYcXvQ0Ki5CpRNKHdNvozkNErsh8SSr' + b'p4X2kFLlk7S/Q0+EwF7qSBRFIAwIjcDYk7EXqVlCtSyhjzLIAib2+L3YtJz63e0eCCyFwGgs' + b'2kwkjrAEErIc45vcN6NRFoEwIDQKi3XBPItyJoTs2or5RZO/i1AOQqnst5v7GoVtkLgWES2z' + b'NxNyNQSete0cGBQCYUBoNBbrEUo6IZzqefGR4qG4iISgmc/v6VoOgSYI6NBtIQpTmQH0kCxz' + b'hBKFihDIxgUP/Sa7fm8fg8HTuFRCM7B+HAOYPZbLcCo7QtFLuxES70LifL77OGUCBPL+cFVx' + b'AmEQHXQVjGX8TOdSM5zWY+M1+8eTiU7dsNdvuHJugnR6Hsa/pf+TD0NOIAwIIZngJG0yu80h' + b'AbxAFN5wdwtB5F91LAlTEJXvrgAAAABJRU5ErkJggg==' +) async def user_login(client, username, password, key=None): @@ -85,7 +130,7 @@

    Module ro_py.extensions.prompt

    self.SetSize((512, 512)) self.SetTitle("Login with Roblox") self.SetBackgroundColour(wx.Colour(255, 255, 255)) - self.SetIcon(wx.Icon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "appicon.png"))) + self.SetIcon(icon_image.GetIcon()) self.username = None self.password = None @@ -217,7 +262,7 @@

    Module ro_py.extensions.prompt

    self.SetSize((512, 600)) self.SetTitle("Roblox Captcha (ro.py)") self.SetBackgroundColour(wx.Colour(255, 255, 255)) - self.SetIcon(wx.Icon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "appicon.png"))) + self.SetIcon(icon_image.GetIcon()) self.status = False self.token = None @@ -618,7 +663,7 @@

    Methods

    self.SetSize((512, 600)) self.SetTitle("Roblox Captcha (ro.py)") self.SetBackgroundColour(wx.Colour(255, 255, 255)) - self.SetIcon(wx.Icon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "appicon.png"))) + self.SetIcon(icon_image.GetIcon()) self.status = False self.token = None @@ -706,7 +751,7 @@

    Methods

    self.SetSize((512, 512)) self.SetTitle("Login with Roblox") self.SetBackgroundColour(wx.Colour(255, 255, 255)) - self.SetIcon(wx.Icon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "appicon.png"))) + self.SetIcon(icon_image.GetIcon()) self.username = None self.password = None diff --git a/docs/games.html b/docs/games.html index 2e380240..b3c34ab7 100644 --- a/docs/games.html +++ b/docs/games.html @@ -63,6 +63,7 @@

    Module ro_py.games

    from ro_py.users import User from ro_py.groups import Group from ro_py.badges import Badge +from ro_py.thumbnails import GameThumbnailGenerator from ro_py.utilities.errors import GameJoinError from ro_py.utilities.cache import CacheType import subprocess @@ -86,9 +87,10 @@

    Module ro_py.games

    Represents a Roblox game universe. This class represents multiple game-related endpoints. """ - def __init__(self, requests, universe_id): + def __init__(self, cso, universe_id): self.id = universe_id - self.requests = requests + self.cso = cso + self.requests = cso.requests self.name = None self.description = None self.root_place = None @@ -99,6 +101,7 @@

    Module ro_py.games

    self.max_players = None self.studio_access_to_apis_allowed = None self.create_vip_servers_allowed = None + self.thumbnails = GameThumbnailGenerator(self.requests, self.id) async def update(self): """ @@ -116,16 +119,16 @@

    Module ro_py.games

    self.description = game_info["description"] self.root_place = Place(self.requests, game_info["rootPlaceId"]) if game_info["creator"]["type"] == "User": - self.creator = self.requests.cache.get(CacheType.Users, game_info["creator"]["id"]) + self.creator = self.cso.cache.get(CacheType.Users, game_info["creator"]["id"]) if not self.creator: - self.creator = User(self.requests, game_info["creator"]["id"]) - self.requests.cache.set(CacheType.Users, game_info["creator"]["id"], self.creator) + self.creator = User(self.cso, game_info["creator"]["id"]) + self.cso.cache.set(CacheType.Users, game_info["creator"]["id"], self.creator) await self.creator.update() elif game_info["creator"]["type"] == "Group": - self.creator = self.requests.cache.get(CacheType.Groups, game_info["creator"]["id"]) + self.creator = self.cso.cache.get(CacheType.Groups, game_info["creator"]["id"]) if not self.creator: - self.creator = Group(self.requests, game_info["creator"]["id"]) - self.requests.cache.set(CacheType.Group, game_info["creator"]["id"], self.creator) + self.creator = Group(self.cso, game_info["creator"]["id"]) + self.cso.cache.set(CacheType.Groups, game_info["creator"]["id"], self.creator) await self.creator.update() self.price = game_info["price"] self.allowed_gear_genres = game_info["allowedGearGenres"] @@ -166,7 +169,7 @@

    Module ro_py.games

    badges_data = badges_req.json()["data"] badges = [] for badge in badges_data: - badges.append(Badge(self.requests, badge["id"])) + badges.append(Badge(self.cso, badge["id"])) return badges @@ -253,7 +256,7 @@

    Classes

    class Game -(requests, universe_id) +(cso, universe_id)

    Represents a Roblox game universe. @@ -267,9 +270,10 @@

    Classes

    Represents a Roblox game universe. This class represents multiple game-related endpoints. """ - def __init__(self, requests, universe_id): + def __init__(self, cso, universe_id): self.id = universe_id - self.requests = requests + self.cso = cso + self.requests = cso.requests self.name = None self.description = None self.root_place = None @@ -280,6 +284,7 @@

    Classes

    self.max_players = None self.studio_access_to_apis_allowed = None self.create_vip_servers_allowed = None + self.thumbnails = GameThumbnailGenerator(self.requests, self.id) async def update(self): """ @@ -297,16 +302,16 @@

    Classes

    self.description = game_info["description"] self.root_place = Place(self.requests, game_info["rootPlaceId"]) if game_info["creator"]["type"] == "User": - self.creator = self.requests.cache.get(CacheType.Users, game_info["creator"]["id"]) + self.creator = self.cso.cache.get(CacheType.Users, game_info["creator"]["id"]) if not self.creator: - self.creator = User(self.requests, game_info["creator"]["id"]) - self.requests.cache.set(CacheType.Users, game_info["creator"]["id"], self.creator) + self.creator = User(self.cso, game_info["creator"]["id"]) + self.cso.cache.set(CacheType.Users, game_info["creator"]["id"], self.creator) await self.creator.update() elif game_info["creator"]["type"] == "Group": - self.creator = self.requests.cache.get(CacheType.Groups, game_info["creator"]["id"]) + self.creator = self.cso.cache.get(CacheType.Groups, game_info["creator"]["id"]) if not self.creator: - self.creator = Group(self.requests, game_info["creator"]["id"]) - self.requests.cache.set(CacheType.Group, game_info["creator"]["id"], self.creator) + self.creator = Group(self.cso, game_info["creator"]["id"]) + self.cso.cache.set(CacheType.Groups, game_info["creator"]["id"], self.creator) await self.creator.update() self.price = game_info["price"] self.allowed_gear_genres = game_info["allowedGearGenres"] @@ -347,7 +352,7 @@

    Classes

    badges_data = badges_req.json()["data"] badges = [] for badge in badges_data: - badges.append(Badge(self.requests, badge["id"])) + badges.append(Badge(self.cso, badge["id"])) return badges

    Methods

    @@ -377,7 +382,7 @@

    Methods

    badges_data = badges_req.json()["data"] badges = [] for badge in badges_data: - badges.append(Badge(self.requests, badge["id"])) + badges.append(Badge(self.cso, badge["id"])) return badges
    @@ -437,16 +442,16 @@

    Methods

    self.description = game_info["description"] self.root_place = Place(self.requests, game_info["rootPlaceId"]) if game_info["creator"]["type"] == "User": - self.creator = self.requests.cache.get(CacheType.Users, game_info["creator"]["id"]) + self.creator = self.cso.cache.get(CacheType.Users, game_info["creator"]["id"]) if not self.creator: - self.creator = User(self.requests, game_info["creator"]["id"]) - self.requests.cache.set(CacheType.Users, game_info["creator"]["id"], self.creator) + self.creator = User(self.cso, game_info["creator"]["id"]) + self.cso.cache.set(CacheType.Users, game_info["creator"]["id"], self.creator) await self.creator.update() elif game_info["creator"]["type"] == "Group": - self.creator = self.requests.cache.get(CacheType.Groups, game_info["creator"]["id"]) + self.creator = self.cso.cache.get(CacheType.Groups, game_info["creator"]["id"]) if not self.creator: - self.creator = Group(self.requests, game_info["creator"]["id"]) - self.requests.cache.set(CacheType.Group, game_info["creator"]["id"], self.creator) + self.creator = Group(self.cso, game_info["creator"]["id"]) + self.cso.cache.set(CacheType.Groups, game_info["creator"]["id"], self.creator) await self.creator.update() self.price = game_info["price"] self.allowed_gear_genres = game_info["allowedGearGenres"] diff --git a/docs/groups.html b/docs/groups.html index a1c61999..d07b01c8 100644 --- a/docs/groups.html +++ b/docs/groups.html @@ -60,10 +60,12 @@

    Module ro_py.groups

    """ import iso8601 +import asyncio from typing import List -from ro_py.users import User +from ro_py.wall import Wall from ro_py.roles import Role from ro_py.captcha import UnsolvedCaptcha +from ro_py.users import User, PartialUser from ro_py.utilities.errors import NotFound from ro_py.utilities.pages import Pages, SortOrder @@ -74,46 +76,54 @@

    Module ro_py.groups

    """ Represents a group shout. """ - def __init__(self, requests, shout_data): + def __init__(self, cso, shout_data): self.body = shout_data["body"] - self.poster = User(requests, shout_data["poster"]["userId"]) + self.poster = User(cso, shout_data["poster"]["userId"], shout_data['poster']['username']) -class WallPost: - """ - Represents a roblox wall post. - """ - def __init__(self, requests, wall_data, group): - self.requests = requests +class JoinRequest: + def __init__(self, cso, data, group): + self.requests = cso.requests self.group = group - self.id = wall_data['id'] - self.body = wall_data['body'] - self.created = iso8601.parse(wall_data['created']) - self.updated = iso8601.parse(wall_data['updated']) - self.poster = User(requests, wall_data['user']['userId'], wall_data['user']['username']) - - async def delete(self): - wall_req = await self.requests.delete( - url=endpoint + f"/v1/groups/{self.id}/wall/posts/{self.id}" + self.requester = PartialUser(cso, data['requester']['userId'], data['requester']['username']) + self.created = iso8601.parse_date(data['created']) + + async def accept(self): + accept_req = await self.requests.post( + url=endpoint + f"/v1/groups/{self.group.id}/join-requests/users/{self.requests.id}" + ) + return accept_req.status_code == 200 + + async def decline(self): + accept_req = await self.requests.delete( + url=endpoint + f"/v1/groups/{self.group.id}/join-requests/users/{self.requests.id}" ) - return wall_req.status == 200 + return accept_req.status_code == 200 -def wall_post_handeler(requests, this_page, args) -> List[WallPost]: - wall_posts = [] - for wall_post in this_page: - wall_posts.append(WallPost(requests, wall_post, args)) - return wall_posts +def join_request_handler(cso, data, args): + join_requests = [] + for request in data: + join_requests.append(JoinRequest(cso, request, args)) + return join_requests + + +def member_handler(cso, data, args): + members = [] + for member in data: + members.append() + return members class Group: """ Represents a group. """ - def __init__(self, requests, group_id): - self.requests = requests + def __init__(self, cso, group_id): + self.cso = cso + self.requests = cso.requests self.id = group_id - self.wall = Wall(requests, self) + self.wall = Wall(self.cso, self) self.name = None self.description = None self.owner = None @@ -121,6 +131,7 @@

    Module ro_py.groups

    self.is_builders_club_only = None self.public_entry_allowed = None self.shout = None + self.events = Events(cso, self) async def update(self): """ @@ -130,12 +141,13 @@

    Module ro_py.groups

    group_info = group_info_req.json() self.name = group_info["name"] self.description = group_info["description"] - self.owner = User(self.requests, group_info["owner"]["userId"]) + self.owner = User(self.cso, group_info["owner"]["userId"]) self.member_count = group_info["memberCount"] self.is_builders_club_only = group_info["isBuildersClubOnly"] self.public_entry_allowed = group_info["publicEntryAllowed"] if "shout" in group_info: - self.shout = group_info["shout"] + if group_info["shout"]: + self.shout = Shout(self.cso, group_info["shout"]) else: self.shout = None # self.is_locked = group_info["isLocked"] @@ -174,7 +186,7 @@

    Module ro_py.groups

    ) roles = [] for role in role_req.json()['roles']: - roles.append(Role(self.requests, self, role)) + roles.append(Role(self.cso, self, role)) return roles async def get_member_by_id(self, roblox_id): @@ -196,54 +208,41 @@

    Module ro_py.groups

    raise NotFound(f"The user {roblox_id} was not found in group {self.id}") # Create data to return. - role = Role(self.requests, self, group_data['role']) - member = Member(self.requests, roblox_id, "", self, role) + role = Role(self.cso, self, group_data['role']) + member = Member(self.cso, roblox_id, "", self, role) return await member.update() - -class PartialGroup(Group): - """ - Represents a group with less information - """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - -class Wall: - def __init__(self, requests, group): - self.requests = requests - self.group = group - - async def get_posts(self, sort_order=SortOrder.Ascending, limit=100): - wall_req = Pages( - requests=self.requests, - url=endpoint + f"/v2/groups/{self.group.id}/wall/posts", + async def get_join_requests(self, sort_order=SortOrder.Ascending, limit=100): + pages = Pages( + cso=self.cso, + url=endpoint + f"/v1/groups/{self.id}/join-requests", sort_order=sort_order, limit=limit, - handler=wall_post_handeler, + handler=join_request_handler, handler_args=self ) - return wall_req + await pages.get_page() + return pages - async def post(self, content, captcha_key=None): - data = { - "body": content - } - - if captcha_key: - data['captchaProvider'] = "PROVIDER_ARKOSE_LABS" - data['captchaToken'] = captcha_key - - post_req = await self.requests.post( - url=endpoint + f"/v1/groups/2695946/wall/posts", - data=data, - quickreturn=True + async def get_members(self, sort_order=SortOrder.Ascending, limit=100): + pages = Pages( + cso=self.cso, + url=endpoint + f"/v1/groups/{self.id}/users?limit=100&sortOrder=Desc", + sort_order=sort_order, + limit=limit, + handler=member_handler, + handler_args=self ) + await pages.get_page() + return pages - if post_req.status_code == 403: - return UnsolvedCaptcha(pkey="63E4117F-E727-42B4-6DAA-C8448E9B137F") - else: - return post_req.status == 200 + +class PartialGroup(Group): + """ + Represents a group with less information + """ + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) class Member(User): @@ -263,8 +262,8 @@

    Module ro_py.groups

    role : ro_py.roles.Role The role the user has is the group. """ - def __init__(self, requests, roblox_id, name, group, role): - super().__init__(requests, roblox_id, name) + def __init__(self, cso, roblox_id, name, group, role): + super().__init__(cso, roblox_id, name) self.role = role self.group = group @@ -347,7 +346,7 @@

    Module ro_py.groups

    "roleId": rank } ) - return rank_request.status == 200 + return rank_request.status_code == 200 async def setrole(self, role_num): """ @@ -376,7 +375,75 @@

    Module ro_py.groups

    exile_req = await self.requests.delete( url=endpoint + f"/v1/groups/{self.group.id}/users/{self.id}" ) - return exile_req.status == 200 + return exile_req.status_code == 200 + + +class Events: + def __init__(self, cso, group): + self.cso = cso + self.group = group + + async def bind(self, func, event, delay=15): + """ + Binds a function to an event. + + Parameters + ---------- + func : function + Function that will be bound to the event. + event : str + Event that will be bound to the function. + delay : int + How many seconds between each poll. + """ + if event == "on_join_request": + return await asyncio.create_task(self.on_join_request(func, delay)) + if event == "on_wall_post": + return await asyncio.create_task(self.on_wall_post(func, delay)) + if event == "on_shout_update": + return await asyncio.create_task(self.on_shout_update(func, delay)) + + async def on_join_request(self, func, delay): + current_group_reqs = await self.group.get_join_requests() + old_req = current_group_reqs.data.requester.id + while True: + await asyncio.sleep(delay) + current_group_reqs = await self.group.get_join_requests() + current_group_reqs = current_group_reqs.data + if current_group_reqs[0].requester.id != old_req: + new_reqs = [] + for request in current_group_reqs: + if request.requester.id != old_req: + new_reqs.append(request) + old_req = current_group_reqs[0].requester.id + for new_req in new_reqs: + await func(new_req) + + async def on_wall_post(self, func, delay): + current_wall_posts = await self.group.wall.get_posts() + newest_wall_poster = current_wall_posts.data[0].poster.id + while True: + await asyncio.sleep(delay) + current_wall_posts = await self.group.wall.get_posts() + current_wall_posts = current_wall_posts.data + if current_wall_posts[0].poster.id != newest_wall_poster: + new_posts = [] + for post in current_wall_posts: + if post.poster.id != newest_wall_poster: + new_posts.append(post) + newest_wall_poster = current_wall_posts[0].poster.id + for new_post in new_posts: + await func(new_post) + + async def on_shout_update(self, func, delay): + await self.group.update() + current_shout = self.group.shout + while True: + await asyncio.sleep(delay) + await self.group.update() + if current_shout.poster.id != self.group.shout.poster.id or current_shout.body != self.group.shout.body: + current_shout = self.group.shout + await func(self.group.shout)
    @@ -386,8 +453,24 @@

    Module ro_py.groups

    Functions

    -
    -def wall_post_handeler(requests, this_page, args) ‑> List[WallPost] +
    +def join_request_handler(cso, data, args) +
    +
    +
    +
    + +Expand source code + +
    def join_request_handler(cso, data, args):
    +    join_requests = []
    +    for request in data:
    +        join_requests.append(JoinRequest(cso, request, args))
    +    return join_requests
    +
    +
    +
    +def member_handler(cso, data, args)
    @@ -395,11 +478,11 @@

    Functions

    Expand source code -
    def wall_post_handeler(requests, this_page, args) -> List[WallPost]:
    -    wall_posts = []
    -    for wall_post in this_page:
    -        wall_posts.append(WallPost(requests, wall_post, args))
    -    return wall_posts
    +
    def member_handler(cso, data, args):
    +    members = []
    +    for member in data:
    +        members.append()
    +    return members
    @@ -407,9 +490,201 @@

    Functions

    Classes

    +
    +class Events +(cso, group) +
    +
    +
    +
    + +Expand source code + +
    class Events:
    +    def __init__(self, cso, group):
    +        self.cso = cso
    +        self.group = group
    +
    +    async def bind(self, func, event, delay=15):
    +        """
    +        Binds a function to an event.
    +
    +        Parameters
    +        ----------
    +        func : function
    +                Function that will be bound to the event.
    +        event : str
    +                Event that will be bound to the function.
    +        delay : int
    +                How many seconds between each poll.
    +        """
    +        if event == "on_join_request":
    +            return await asyncio.create_task(self.on_join_request(func, delay))
    +        if event == "on_wall_post":
    +            return await asyncio.create_task(self.on_wall_post(func, delay))
    +        if event == "on_shout_update":
    +            return await asyncio.create_task(self.on_shout_update(func, delay))
    +
    +    async def on_join_request(self, func, delay):
    +        current_group_reqs = await self.group.get_join_requests()
    +        old_req = current_group_reqs.data.requester.id
    +        while True:
    +            await asyncio.sleep(delay)
    +            current_group_reqs = await self.group.get_join_requests()
    +            current_group_reqs = current_group_reqs.data
    +            if current_group_reqs[0].requester.id != old_req:
    +                new_reqs = []
    +                for request in current_group_reqs:
    +                    if request.requester.id != old_req:
    +                        new_reqs.append(request)
    +                old_req = current_group_reqs[0].requester.id
    +                for new_req in new_reqs:
    +                    await func(new_req)
    +
    +    async def on_wall_post(self, func, delay):
    +        current_wall_posts = await self.group.wall.get_posts()
    +        newest_wall_poster = current_wall_posts.data[0].poster.id
    +        while True:
    +            await asyncio.sleep(delay)
    +            current_wall_posts = await self.group.wall.get_posts()
    +            current_wall_posts = current_wall_posts.data
    +            if current_wall_posts[0].poster.id != newest_wall_poster:
    +                new_posts = []
    +                for post in current_wall_posts:
    +                    if post.poster.id != newest_wall_poster:
    +                        new_posts.append(post)
    +                newest_wall_poster = current_wall_posts[0].poster.id
    +                for new_post in new_posts:
    +                    await func(new_post)
    +
    +    async def on_shout_update(self, func, delay):
    +        await self.group.update()
    +        current_shout = self.group.shout
    +        while True:
    +            await asyncio.sleep(delay)
    +            await self.group.update()
    +            if current_shout.poster.id != self.group.shout.poster.id or current_shout.body != self.group.shout.body:
    +                current_shout = self.group.shout
    +                await func(self.group.shout)
    +
    +

    Methods

    +
    +
    +async def bind(self, func, event, delay=15) +
    +
    +

    Binds a function to an event.

    +

    Parameters

    +
    +
    func : function
    +
    Function that will be bound to the event.
    +
    event : str
    +
    Event that will be bound to the function.
    +
    delay : int
    +
    How many seconds between each poll.
    +
    +
    + +Expand source code + +
    async def bind(self, func, event, delay=15):
    +    """
    +    Binds a function to an event.
    +
    +    Parameters
    +    ----------
    +    func : function
    +            Function that will be bound to the event.
    +    event : str
    +            Event that will be bound to the function.
    +    delay : int
    +            How many seconds between each poll.
    +    """
    +    if event == "on_join_request":
    +        return await asyncio.create_task(self.on_join_request(func, delay))
    +    if event == "on_wall_post":
    +        return await asyncio.create_task(self.on_wall_post(func, delay))
    +    if event == "on_shout_update":
    +        return await asyncio.create_task(self.on_shout_update(func, delay))
    +
    +
    +
    +async def on_join_request(self, func, delay) +
    +
    +
    +
    + +Expand source code + +
    async def on_join_request(self, func, delay):
    +    current_group_reqs = await self.group.get_join_requests()
    +    old_req = current_group_reqs.data.requester.id
    +    while True:
    +        await asyncio.sleep(delay)
    +        current_group_reqs = await self.group.get_join_requests()
    +        current_group_reqs = current_group_reqs.data
    +        if current_group_reqs[0].requester.id != old_req:
    +            new_reqs = []
    +            for request in current_group_reqs:
    +                if request.requester.id != old_req:
    +                    new_reqs.append(request)
    +            old_req = current_group_reqs[0].requester.id
    +            for new_req in new_reqs:
    +                await func(new_req)
    +
    +
    +
    +async def on_shout_update(self, func, delay) +
    +
    +
    +
    + +Expand source code + +
    async def on_shout_update(self, func, delay):
    +    await self.group.update()
    +    current_shout = self.group.shout
    +    while True:
    +        await asyncio.sleep(delay)
    +        await self.group.update()
    +        if current_shout.poster.id != self.group.shout.poster.id or current_shout.body != self.group.shout.body:
    +            current_shout = self.group.shout
    +            await func(self.group.shout)
    +
    +
    +
    +async def on_wall_post(self, func, delay) +
    +
    +
    +
    + +Expand source code + +
    async def on_wall_post(self, func, delay):
    +    current_wall_posts = await self.group.wall.get_posts()
    +    newest_wall_poster = current_wall_posts.data[0].poster.id
    +    while True:
    +        await asyncio.sleep(delay)
    +        current_wall_posts = await self.group.wall.get_posts()
    +        current_wall_posts = current_wall_posts.data
    +        if current_wall_posts[0].poster.id != newest_wall_poster:
    +            new_posts = []
    +            for post in current_wall_posts:
    +                if post.poster.id != newest_wall_poster:
    +                    new_posts.append(post)
    +            newest_wall_poster = current_wall_posts[0].poster.id
    +            for new_post in new_posts:
    +                await func(new_post)
    +
    +
    +
    +
    class Group -(requests, group_id) +(cso, group_id)

    Represents a group.

    @@ -421,10 +696,11 @@

    Classes

    """ Represents a group. """ - def __init__(self, requests, group_id): - self.requests = requests + def __init__(self, cso, group_id): + self.cso = cso + self.requests = cso.requests self.id = group_id - self.wall = Wall(requests, self) + self.wall = Wall(self.cso, self) self.name = None self.description = None self.owner = None @@ -432,6 +708,7 @@

    Classes

    self.is_builders_club_only = None self.public_entry_allowed = None self.shout = None + self.events = Events(cso, self) async def update(self): """ @@ -441,12 +718,13 @@

    Classes

    group_info = group_info_req.json() self.name = group_info["name"] self.description = group_info["description"] - self.owner = User(self.requests, group_info["owner"]["userId"]) + self.owner = User(self.cso, group_info["owner"]["userId"]) self.member_count = group_info["memberCount"] self.is_builders_club_only = group_info["isBuildersClubOnly"] self.public_entry_allowed = group_info["publicEntryAllowed"] if "shout" in group_info: - self.shout = group_info["shout"] + if group_info["shout"]: + self.shout = Shout(self.cso, group_info["shout"]) else: self.shout = None # self.is_locked = group_info["isLocked"] @@ -485,7 +763,7 @@

    Classes

    ) roles = [] for role in role_req.json()['roles']: - roles.append(Role(self.requests, self, role)) + roles.append(Role(self.cso, self, role)) return roles async def get_member_by_id(self, roblox_id): @@ -507,9 +785,33 @@

    Classes

    raise NotFound(f"The user {roblox_id} was not found in group {self.id}") # Create data to return. - role = Role(self.requests, self, group_data['role']) - member = Member(self.requests, roblox_id, "", self, role) - return await member.update()
    + role = Role(self.cso, self, group_data['role']) + member = Member(self.cso, roblox_id, "", self, role) + return await member.update() + + async def get_join_requests(self, sort_order=SortOrder.Ascending, limit=100): + pages = Pages( + cso=self.cso, + url=endpoint + f"/v1/groups/{self.id}/join-requests", + sort_order=sort_order, + limit=limit, + handler=join_request_handler, + handler_args=self + ) + await pages.get_page() + return pages + + async def get_members(self, sort_order=SortOrder.Ascending, limit=100): + pages = Pages( + cso=self.cso, + url=endpoint + f"/v1/groups/{self.id}/users?limit=100&sortOrder=Desc", + sort_order=sort_order, + limit=limit, + handler=member_handler, + handler_args=self + ) + await pages.get_page() + return pages

    Subclasses

      @@ -517,6 +819,28 @@

      Subclasses

    Methods

    +
    +async def get_join_requests(self, sort_order=SortOrder.Ascending, limit=100) +
    +
    +
    +
    + +Expand source code + +
    async def get_join_requests(self, sort_order=SortOrder.Ascending, limit=100):
    +    pages = Pages(
    +        cso=self.cso,
    +        url=endpoint + f"/v1/groups/{self.id}/join-requests",
    +        sort_order=sort_order,
    +        limit=limit,
    +        handler=join_request_handler,
    +        handler_args=self
    +    )
    +    await pages.get_page()
    +    return pages
    +
    +
    async def get_member_by_id(self, roblox_id)
    @@ -545,11 +869,33 @@

    Methods

    raise NotFound(f"The user {roblox_id} was not found in group {self.id}") # Create data to return. - role = Role(self.requests, self, group_data['role']) - member = Member(self.requests, roblox_id, "", self, role) + role = Role(self.cso, self, group_data['role']) + member = Member(self.cso, roblox_id, "", self, role) return await member.update()
    +
    +async def get_members(self, sort_order=SortOrder.Ascending, limit=100) +
    +
    +
    +
    + +Expand source code + +
    async def get_members(self, sort_order=SortOrder.Ascending, limit=100):
    +    pages = Pages(
    +        cso=self.cso,
    +        url=endpoint + f"/v1/groups/{self.id}/users?limit=100&sortOrder=Desc",
    +        sort_order=sort_order,
    +        limit=limit,
    +        handler=member_handler,
    +        handler_args=self
    +    )
    +    await pages.get_page()
    +    return pages
    +
    +
    async def get_roles(self)
    @@ -577,7 +923,7 @@

    Returns

    ) roles = [] for role in role_req.json()['roles']: - roles.append(Role(self.requests, self, role)) + roles.append(Role(self.cso, self, role)) return roles @@ -598,12 +944,13 @@

    Returns

    group_info = group_info_req.json() self.name = group_info["name"] self.description = group_info["description"] - self.owner = User(self.requests, group_info["owner"]["userId"]) + self.owner = User(self.cso, group_info["owner"]["userId"]) self.member_count = group_info["memberCount"] self.is_builders_club_only = group_info["isBuildersClubOnly"] self.public_entry_allowed = group_info["publicEntryAllowed"] if "shout" in group_info: - self.shout = group_info["shout"] + if group_info["shout"]: + self.shout = Shout(self.cso, group_info["shout"]) else: self.shout = None @@ -651,9 +998,74 @@

    Returns

    +
    +class JoinRequest +(cso, data, group) +
    +
    +
    +
    + +Expand source code + +
    class JoinRequest:
    +    def __init__(self, cso, data, group):
    +        self.requests = cso.requests
    +        self.group = group
    +        self.requester = PartialUser(cso, data['requester']['userId'], data['requester']['username'])
    +        self.created = iso8601.parse_date(data['created'])
    +
    +    async def accept(self):
    +        accept_req = await self.requests.post(
    +            url=endpoint + f"/v1/groups/{self.group.id}/join-requests/users/{self.requests.id}"
    +        )
    +        return accept_req.status_code == 200
    +
    +    async def decline(self):
    +        accept_req = await self.requests.delete(
    +            url=endpoint + f"/v1/groups/{self.group.id}/join-requests/users/{self.requests.id}"
    +        )
    +        return accept_req.status_code == 200
    +
    +

    Methods

    +
    +
    +async def accept(self) +
    +
    +
    +
    + +Expand source code + +
    async def accept(self):
    +    accept_req = await self.requests.post(
    +        url=endpoint + f"/v1/groups/{self.group.id}/join-requests/users/{self.requests.id}"
    +    )
    +    return accept_req.status_code == 200
    +
    +
    +
    +async def decline(self) +
    +
    +
    +
    + +Expand source code + +
    async def decline(self):
    +    accept_req = await self.requests.delete(
    +        url=endpoint + f"/v1/groups/{self.group.id}/join-requests/users/{self.requests.id}"
    +    )
    +    return accept_req.status_code == 200
    +
    +
    +
    +
    class Member -(requests, roblox_id, name, group, role) +(cso, roblox_id, name, group, role)

    Represents a user in a group.

    @@ -691,8 +1103,8 @@

    Parameters

    role : ro_py.roles.Role The role the user has is the group. """ - def __init__(self, requests, roblox_id, name, group, role): - super().__init__(requests, roblox_id, name) + def __init__(self, cso, roblox_id, name, group, role): + super().__init__(cso, roblox_id, name) self.role = role self.group = group @@ -775,7 +1187,7 @@

    Parameters

    "roleId": rank } ) - return rank_request.status == 200 + return rank_request.status_code == 200 async def setrole(self, role_num): """ @@ -804,7 +1216,7 @@

    Parameters

    exile_req = await self.requests.delete( url=endpoint + f"/v1/groups/{self.group.id}/users/{self.id}" ) - return exile_req.status == 200 + return exile_req.status_code == 200

    Ancestors

      @@ -889,7 +1301,7 @@

      Returns

      exile_req = await self.requests.delete( url=endpoint + f"/v1/groups/{self.group.id}/users/{self.id}" ) - return exile_req.status == 200 + return exile_req.status_code == 200
    @@ -955,7 +1367,7 @@

    Returns

    "roleId": rank } ) - return rank_request.status == 200
    + return rank_request.status_code == 200
    @@ -1085,7 +1497,7 @@

    Inherited members

    class Shout -(requests, shout_data) +(cso, shout_data)

    Represents a group shout.

    @@ -1097,162 +1509,12 @@

    Inherited members

    """ Represents a group shout. """ - def __init__(self, requests, shout_data): + def __init__(self, cso, shout_data): self.body = shout_data["body"] - self.poster = User(requests, shout_data["poster"]["userId"])
    - -
    -
    -class Wall -(requests, group) -
    -
    -
    -
    - -Expand source code - -
    class Wall:
    -    def __init__(self, requests, group):
    -        self.requests = requests
    -        self.group = group
    -
    -    async def get_posts(self, sort_order=SortOrder.Ascending, limit=100):
    -        wall_req = Pages(
    -            requests=self.requests,
    -            url=endpoint + f"/v2/groups/{self.group.id}/wall/posts",
    -            sort_order=sort_order,
    -            limit=limit,
    -            handler=wall_post_handeler,
    -            handler_args=self
    -        )
    -        return wall_req
    -
    -    async def post(self, content, captcha_key=None):
    -        data = {
    -            "body": content
    -        }
    -
    -        if captcha_key:
    -            data['captchaProvider'] = "PROVIDER_ARKOSE_LABS"
    -            data['captchaToken'] = captcha_key
    -
    -        post_req = await self.requests.post(
    -            url=endpoint + f"/v1/groups/2695946/wall/posts",
    -            data=data,
    -            quickreturn=True
    -        )
    -
    -        if post_req.status_code == 403:
    -            return UnsolvedCaptcha(pkey="63E4117F-E727-42B4-6DAA-C8448E9B137F")
    -        else:
    -            return post_req.status == 200
    -
    -

    Methods

    -
    -
    -async def get_posts(self, sort_order=SortOrder.Ascending, limit=100) -
    -
    -
    -
    - -Expand source code - -
    async def get_posts(self, sort_order=SortOrder.Ascending, limit=100):
    -    wall_req = Pages(
    -        requests=self.requests,
    -        url=endpoint + f"/v2/groups/{self.group.id}/wall/posts",
    -        sort_order=sort_order,
    -        limit=limit,
    -        handler=wall_post_handeler,
    -        handler_args=self
    -    )
    -    return wall_req
    -
    -
    -
    -async def post(self, content, captcha_key=None) -
    -
    -
    -
    - -Expand source code - -
    async def post(self, content, captcha_key=None):
    -    data = {
    -        "body": content
    -    }
    -
    -    if captcha_key:
    -        data['captchaProvider'] = "PROVIDER_ARKOSE_LABS"
    -        data['captchaToken'] = captcha_key
    -
    -    post_req = await self.requests.post(
    -        url=endpoint + f"/v1/groups/2695946/wall/posts",
    -        data=data,
    -        quickreturn=True
    -    )
    -
    -    if post_req.status_code == 403:
    -        return UnsolvedCaptcha(pkey="63E4117F-E727-42B4-6DAA-C8448E9B137F")
    -    else:
    -        return post_req.status == 200
    + self.poster = User(cso, shout_data["poster"]["userId"], shout_data['poster']['username'])
    -
    -
    -class WallPost -(requests, wall_data, group) -
    -
    -

    Represents a roblox wall post.

    -
    - -Expand source code - -
    class WallPost:
    -    """
    -    Represents a roblox wall post.
    -    """
    -    def __init__(self, requests, wall_data, group):
    -        self.requests = requests
    -        self.group = group
    -        self.id = wall_data['id']
    -        self.body = wall_data['body']
    -        self.created = iso8601.parse(wall_data['created'])
    -        self.updated = iso8601.parse(wall_data['updated'])
    -        self.poster = User(requests, wall_data['user']['userId'], wall_data['user']['username'])
    -
    -    async def delete(self):
    -        wall_req = await self.requests.delete(
    -            url=endpoint + f"/v1/groups/{self.id}/wall/posts/{self.id}"
    -        )
    -        return wall_req.status == 200
    -
    -

    Methods

    -
    -
    -async def delete(self) -
    -
    -
    -
    - -Expand source code - -
    async def delete(self):
    -    wall_req = await self.requests.delete(
    -        url=endpoint + f"/v1/groups/{self.id}/wall/posts/{self.id}"
    -    )
    -    return wall_req.status == 200
    -
    -
    -
    -
    -