Skip to content

Commit

Permalink
improve documentation and add supported operations
Browse files Browse the repository at this point in the history
  • Loading branch information
treeben77 committed Sep 27, 2024
1 parent 9369257 commit 64a23ca
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 36 deletions.
50 changes: 25 additions & 25 deletions docs/guides/experience.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,109 +21,109 @@ Replace `00000000` with your experience/universe ID (NOT place ID), and `your-ap

You can use Open Cloud to access your experience's [Datastores](https://create.roblox.com/docs/cloud-services/Datastores) in Python, including Ordered Datastores. This could be useful if you're creating a Discord bot, or website to remotly manage user data, or to control certain settings.

To get started, you will need to create a [`rblxopencloud.Datastore`][rblxopencloud.Datastore] object. The following code example creates a [`rblxopencloud.Datastore`][rblxopencloud.Datastore] with the name 'ExampleStore' and the scope 'global' (global is the default scope in Lua):
To get started, you will need to create a [`rblxopencloud.DataStore`][rblxopencloud.DataStore] object. The following code example creates a [`rblxopencloud.DataStore`][rblxopencloud.DataStore] with the name 'ExampleStore' and the scope 'global' (global is the default scope in Lua):

```py
Datastore = experience.get_Datastore("ExampleStore", scope="global")
datastore = experience.get_datastore("ExampleStore", scope="global")
```

Great! Now that you've created a Datastore, you can now access it's entrys.
Great! Now that you've created a data store, you can now access it's entrys.

!!! tip
You can set the `scope` parameter to `None` if you want to access all scopes. You will be required to format keys in the `scope/key` syntax. For example, in `pets/user_287113233`, the scope is `pets`, and `user_287113233` is the key.

### Getting Keys

To get the value of a Datastore key, you can use [`Datastore.get_entry`][rblxopencloud.Datastore.get_entry]. The following code will get the value for `user_287113233` in the data store.
To get the value of a datastore key, you can use [`datastore.get_entry`][rblxopencloud.DataStore.get_entry]. The following code will get the value for `user_287113233` in the data store.

```py
value, info = Datastore.get_entry("user_287113233")
value, info = datastore.get_entry("user_287113233")
```

[`Datastore.get_entry`][rblxopencloud.Datastore.get_entry] returns a tuple of two items, the key's value, and an [`rblxopencloud.EntryInfo`][rblxopencloud.EntryInfo] object. The value can be either `str`, `int`, `float`, `list`, or `dict`, and is the equivalent value in Roblox Lua. The [`rblxopencloud.EntryInfo`][rblxopencloud.EntryInfo] object contains metadata about the Datastore key, such as the current version ID, when it was created and last updated, a list of user IDs for GDPR tracking, and the custom metadata, learn more about this on [Roblox's Datastore Guide](https://create.roblox.com/docs/cloud-services/Datastores#metadata).
[`datastore.get_entry`][rblxopencloud.DataStore.get_entry] returns a tuple of two items, the key's value, and an [`rblxopencloud.EntryInfo`][rblxopencloud.EntryInfo] object. The value can be either `str`, `int`, `float`, `list`, or `dict`, and is the equivalent value in Roblox Lua. The [`rblxopencloud.EntryInfo`][rblxopencloud.EntryInfo] object contains metadata about the datastore key, such as the current version ID, when it was created and last updated, a list of user IDs for GDPR tracking, and the custom metadata, learn more about this on [Roblox's Datastore Guide](https://create.roblox.com/docs/cloud-services/Datastores#metadata).

If the requested key does not exist, then this method will raise [`rblxopencloud.NotFound`][rblxopencloud.NotFound]. So, you should create a try block and deal with errors correctly, for example:

```py
try:
value, info = Datastore.get_entry("user_287113233")
value, info = datastore.get_entry("user_287113233")
except(rblxopencloud.NotFound):
print("the key doesn't exist!")
else:
print(f"the key's value is {value}.")
```

You can list all keys in a Data Store using [`Datastore.list_keys`][rblxopencloud.Datastore.list_keys], it will iterate all keys in the Datastore, and can be used like this:
You can list all keys in a Data Store using [`datastore.list_keys`][rblxopencloud.DataStore.list_keys], it will iterate all keys in the datastore, and can be used like this:

```py
for key in Datastore.list_keys():
for key in datastore.list_keys():
print(key.key, key.scope)
```

If the data store's scope is `None` this will return keys from every scope. You can also provide an optional `prefix`, and `limit`.

### Changing Keys

Datastore values can be changed with [`Datastore.set_entry`][rblxopencloud.Datastore.set_entry] and [`Datastore.increment_entry`][rblxopencloud.Datastore.increment_entry]. Both will need the 'Create Entry' permission to create new keys, and/or 'Update Entry' permission to update existing keys. First, here's an example using [`Datastore.set_entry`][rblxopencloud.Datastore.set_entry]:
Datastore values can be changed with [`datastore.set_entry`][rblxopencloud.DataStore.set_entry] and [`datastore.increment_entry`][rblxopencloud.DataStore.increment_entry]. Both will need the 'Create Entry' permission to create new keys, and/or 'Update Entry' permission to update existing keys. First, here's an example using [`datastore.set_entry`][rblxopencloud.DataStore.set_entry]:

```py
version = Datastore.set_entry("user_287113233", {"xp": 1337, "level": 7}, users=[287113233])
version = datastore.set_entry("user_287113233", {"xp": 1337, "level": 7}, users=[287113233])
```

This will set the key `user_287113233` to the dictionary `{"xp": 1337, "level": 7}`, with the user's ID in the list of users. The method returns [`rblxopencloud.EntryVersion`][rblxopencloud.EntryVersion], which contains metadata about the new version, such as it's version ID. The code above is equivalent to the the following lua code:

```lua
local version = Datastore:SetAsync("user_287113233", {["xp"] = 1337, ["level"] = 7}, {287113233})
local version = datastore:SetAsync("user_287113233", {["xp"] = 1337, ["level"] = 7}, {287113233})
```

If the current value of the key is an integer, or float you can use [`Datastore.increment_entry`][rblxopencloud.Datastore.increment_entry] to update the value, while guaranteeing you don't overwrite the old value. The following example will increment the key `user_score_287113233` by 70:
If the current value of the key is an integer, or float you can use [`datastore.increment_entry`][rblxopencloud.DataStore.increment_entry] to update the value, while guaranteeing you don't overwrite the old value. The following example will increment the key `user_score_287113233` by 70:

```py
value, info = Datastore.increment_entry("user_score_287113233", 70, users=[287113233])
value, info = datastore.increment_entry("user_score_287113233", 70, users=[287113233])
```

[`Datastore.increment_entry`][rblxopencloud.Datastore.increment_entry] actually returns the new value just like [`Datastore.get_entry`][rblxopencloud.Datastore.get_entry] instead.
[`datastore.increment_entry`][rblxopencloud.DataStore.increment_entry] actually returns the new value just like [`datastore.get_entry`][rblxopencloud.DataStore.get_entry] instead.

!!! warning
If an entry has `users` and `metadata`, you must provide them every time you set or increment the value, otherwise they will be removed.

### Removing Keys

You can remove a key from a Datastore with Open Cloud with the following code:
You can remove a key from a datastore with Open Cloud with the following code:

```py
version = Datastore.remove_entry("user_287113233")
version = datastore.remove_entry("user_287113233")
```

This will mark the key as deleted, and calls to get the key will fail. However, the old version of the key can still be accessed by listing versions (explained below), and listing keys will still return the key. These are limitations with Open Cloud, not one with the library.

### Key Versioning

Data Stores retain previous versions of the key for 30 days. You can list all previous versions with [`Datastore.list_versions`][rblxopencloud.Datastore.list_versions], like this:
Data Stores retain previous versions of the key for 30 days. You can list all previous versions with [`datastore.list_versions`][rblxopencloud.DataStore.list_versions], like this:

```py
for version in Datastore.list_versions("user_287113233"):
for version in datastore.list_versions("user_287113233"):
print(version, version.get_value())
```

This will iterate [`rblxopencloud.EntryVersion`][rblxopencloud.EntryVersion] for every version in the key. It contains information like the version ID, when the version was created, the content length, and wether it has been deleted. You can fetch a version's value with [`EntryVersion.get_value`][rblxopencloud.EntryVersion.get_value], but if you already have the version ID, and don't need to list versions you can use [`Datastore.get_version`][rblxopencloud.Datastore.get_version].
This will iterate [`rblxopencloud.EntryVersion`][rblxopencloud.EntryVersion] for every version in the key. It contains information like the version ID, when the version was created, the content length, and wether it has been deleted. You can fetch a version's value with [`EntryVersion.get_value`][rblxopencloud.EntryVersion.get_value], but if you already have the version ID, and don't need to list versions you can use [`datastore.get_version`][rblxopencloud.DataStore.get_version].

```py
value, info = Datastore.get_version("user_287113233", "VERSION_ID")
value, info = datastore.get_version("user_287113233", "VERSION_ID")
```

It returns the same as [`Datastore.get_entry`][rblxopencloud.Datastore.get_entry].
It returns the same as [`datastore.get_entry`][rblxopencloud.DataStore.get_entry].

### Ordered Data Stores

You can also access Ordered Data Stores with Open Cloud. There are a few differences between regular Data Stores and Ordered Data Stores:

- Ordered Data Store do not support versioning, therefore you can not use versioning functions.
- Ordered Data Stores also do not support user IDs or metadata, and since they also don't support versioning, there is no second parameter returned on get methods.
- [`OrderedDatastore.set_entry`][rblxopencloud.OrderedDatastore.set_entry] doesn't have the `previous_version` precondition, instead it has an `exclusive_update` precondition.
- Ordered Data Stores don't have a `list_keys` method, but instead [`OrderedDatastore.sort_keys`][rblxopencloud.OrderedDatastore.sort_keys]. They also iterate [`rblxopencloud.SortedEntry`][rblxopencloud.SortedEntry] which includes the key's value.
- [`OrderedDataStore.set_entry`][rblxopencloud.OrderedDataStore.set_entry] doesn't have the `previous_version` precondition, instead it has an `exclusive_update` precondition.
- Ordered Data Stores don't have a `list_keys` method, but instead [`OrderedDataStore.sort_keys`][rblxopencloud.OrderedDataStore.sort_keys]. They also iterate [`rblxopencloud.SortedEntry`][rblxopencloud.SortedEntry] which includes the key's value.

To create an Ordered Data Store, you can use the [`Experience.get_ordered_Datastore`][rblxopencloud.Experience.get_ordered_Datastore] method, which also supports `scope` being `None`:
To create an Ordered Data Store, you can use the [`Experience.get_ordered_datastore`][rblxopencloud.Experience.get_ordered_datastore] method, which also supports `scope` being `None`:

```py
Datastore = experience.get_ordered_datastore("ExampleStore", scope="global")
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/creator.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# Creator

::: rblxopencloud.Asset
options:
merge_init_into_class: true

::: rblxopencloud.AssetVersion

::: rblxopencloud.CreatorStoreProduct
options:
merge_init_into_class: true

::: rblxopencloud.Creator

Expand Down
4 changes: 2 additions & 2 deletions rblxopencloud/apikey.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ApiKey:
[Creator Dashboard](https://create.roblox.com/credentials).
"""

def __init__(self, api_key) -> None:
def __init__(self, api_key: str) -> None:
self.__api_key = api_key

def get_experience(self, id: int, fetch_info: bool = False) -> Experience:
Expand Down Expand Up @@ -97,7 +97,7 @@ def fetch_creator_store_product(
Args:
asset_type: The type of asset the product is.
asset_id: The ID of the asset to fetch.
product_id: The ID of the asset to fetch.
Returns:
A [`CreatorStoreProduct`][rblxopencloud.CreatorStoreProduct] \
Expand Down
22 changes: 18 additions & 4 deletions rblxopencloud/creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,19 @@ class Money:
currencies will begin with `X-`.
quantity: The quantity of the currency. For instance, `4.99` would be \
four dollars and ninety-nine cents in USD.
**Supported Operations:**
| Operator | Description |
| -------- | ----------- |
| `==` | Whether two [`Money`][rblxopencloud.Money] have the same \
currency and quantity or `quantity` equals the [`float`][float]. |
| `<` | Whether the `quantity` is less than the `quantity` of \
another [`Money`][rblxopencloud.Money] with the same currency or a \
[`float`][float]. Also supports `<=`. |
| `>` | Whether the `quantity` is greater than the `quantity` of \
another [`Money`][rblxopencloud.Money] with the same currency or a \
[`float`][float]. Also supports `>=`. |
"""

def __init__(self, currency: str, quantity: float) -> None:
Expand All @@ -278,9 +291,10 @@ def __eq__(self, value: object) -> bool:
raise NotImplemented

if type(value) == Money:
if self.currency != value.currency:
raise ValueError("Cannot compare Money of different currency.")
return self.quantity == value.quantity
return (
self.currency == value.currency
and self.quantity == value.quantity
)

return self.quantity == value

Expand Down Expand Up @@ -747,7 +761,7 @@ def fetch_creator_store_product(
Args:
asset_type: The type of asset the product is.
asset_id: The ID of the asset to fetch.
product_id: The ID of the asset to fetch.
Returns:
A [`CreatorStoreProduct`][rblxopencloud.CreatorStoreProduct] \
Expand Down
21 changes: 21 additions & 0 deletions rblxopencloud/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ class EntryVersion:
content_length: The length of the value.
created: When this version was created.
key_created: When the key was first created.
**Supported Operations:**
| Operator | Description |
| -------- | ----------- |
| `==` | Whether two [`EntryVersion`][rblxopencloud.EntryVersion] \
have the same `version` and are of the same key and scope. |
"""

def __init__(
Expand Down Expand Up @@ -137,6 +144,13 @@ class ListedEntry:
Attributes:
key: The entry's key.
scope: The entry's scope, usually is `global`.
**Supported Operations:**
| Operator | Description |
| -------- | ----------- |
| `==` | Whether two [`ListedEntry`][rblxopencloud.ListedEntry] \
have the same `key` and `scope`. |
"""

def __init__(self, key, scope) -> None:
Expand Down Expand Up @@ -575,6 +589,13 @@ class SortedEntry:
key: The entry's key.
scope: The entry's scope.
value: The entry's value.
**Supported Operations:**
| Operator | Description |
| -------- | ----------- |
| `==` | Whether two [`SortedEntry`][rblxopencloud.SortedEntry] \
have the same `key`, `scope` and `value`. |
"""

def __init__(self, key: str, value: int, scope: str = "global") -> None:
Expand Down
2 changes: 1 addition & 1 deletion rblxopencloud/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def __init__(self, value, info, *args: object) -> None:
class InvalidCode(HttpException):
"""
The code provided to \
[OAuth2App.exchange_code](rblxopencloud.OAuth2App.exchange_code) was \
[`OAuth2App.exchange_code`][rblxopencloud.OAuth2App.exchange_code] was \
invalid.
"""

Expand Down
4 changes: 2 additions & 2 deletions rblxopencloudasync/apikey.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ApiKey:
[Creator Dashboard](https://create.roblox.com/credentials).
"""

def __init__(self, api_key) -> None:
def __init__(self, api_key: str) -> None:
self.__api_key = api_key

def get_experience(self, id: int, fetch_info: bool = False) -> Experience:
Expand Down Expand Up @@ -97,7 +97,7 @@ async def fetch_creator_store_product(
Args:
asset_type: The type of asset the product is.
asset_id: The ID of the asset to fetch.
product_id: The ID of the asset to fetch.
Returns:
A [`CreatorStoreProduct`][rblxopencloud.CreatorStoreProduct] \
Expand Down
15 changes: 14 additions & 1 deletion rblxopencloudasync/creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,19 @@ class Money:
currencies will begin with `X-`.
quantity: The quantity of the currency. For instance, `4.99` would be \
four dollars and ninety-nine cents in USD.
**Supported Operations:**
| Operator | Description |
| -------- | ----------- |
| `==` | Whether two [`Money`][rblxopencloud.Money] have the same \
currency and quantity or `quantity` equals the [`float`][float]. |
| `<` | Whether the `quantity` is less than the `quantity` of \
another [`Money`][rblxopencloud.Money] with the same currency or a \
[`float`][float]. Also supports `<=`. |
| `>` | Whether the `quantity` is greater than the `quantity` of \
another [`Money`][rblxopencloud.Money] with the same currency or a \
[`float`][float]. Also supports `>=`. |
"""

def __init__(self, currency: str, quantity: float) -> None:
Expand Down Expand Up @@ -741,7 +754,7 @@ async def fetch_creator_store_product(
Args:
asset_type: The type of asset the product is.
asset_id: The ID of the asset to fetch.
product_id: The ID of the asset to fetch.
Returns:
A [`CreatorStoreProduct`][rblxopencloud.CreatorStoreProduct] \
Expand Down
21 changes: 21 additions & 0 deletions rblxopencloudasync/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ class EntryVersion:
content_length: The length of the value.
created: When this version was created.
key_created: When the key was first created.
**Supported Operations:**
| Operator | Description |
| -------- | ----------- |
| `==` | Whether two [`EntryVersion`][rblxopencloud.EntryVersion] \
have the same `version` and are of the same key and scope. |
"""

def __init__(
Expand Down Expand Up @@ -137,6 +144,13 @@ class ListedEntry:
Attributes:
key: The entry's key.
scope: The entry's scope, usually is `global`.
**Supported Operations:**
| Operator | Description |
| -------- | ----------- |
| `==` | Whether two [`ListedEntry`][rblxopencloud.ListedEntry] \
have the same `key` and `scope`. |
"""

def __init__(self, key, scope) -> None:
Expand Down Expand Up @@ -575,6 +589,13 @@ class SortedEntry:
key: The entry's key.
scope: The entry's scope.
value: The entry's value.
**Supported Operations:**
| Operator | Description |
| -------- | ----------- |
| `==` | Whether two [`SortedEntry`][rblxopencloud.SortedEntry] \
have the same `key`, `scope` and `value`. |
"""

def __init__(self, key: str, value: int, scope: str = "global") -> None:
Expand Down
2 changes: 1 addition & 1 deletion rblxopencloudasync/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def __init__(self, value, info, *args: object) -> None:
class InvalidCode(HttpException):
"""
The code provided to \
[OAuth2App.exchange_code](rblxopencloud.OAuth2App.exchange_code) was \
[`OAuth2App.exchange_code`][rblxopencloud.OAuth2App.exchange_code] was \
invalid.
"""

Expand Down

0 comments on commit 64a23ca

Please sign in to comment.