Source code for modio.mod

"""Module storing representation of the mod objects"""
from typing import List, Optional, Union
from .enums import Level, Maturity, Status, Visibility
from .errors import modioException
from .mixins import OwnerMixin, RatingMixin, ReportMixin
from .entities import (
    Comment,
    Event,
    Image,
    Message,
    ModFile,
    ModMedia,
    ModStats,
    TeamMember,
    User,
)
from .objects import Filter, NewModFile, Pagination, Returned
from .utils import _convert_date, _clean_and_convert


[docs]class Mod(ReportMixin, RatingMixin, OwnerMixin): """Represent a modio mod object. Filter-Only Attributes ----------------------- These attributes can only be used at endpoints which return instances of this class and takes filter arguments. They are not attached to the object itself and trying to access them will cause an AttributeError sort_downloads : str Sort argument, provide to sort function to sort by most/least downloaded sort_popular : str Sort argument, provide to sort function to sort by most/least popular sort_rating : str Sort argument, provide to sort function to sort by weighed rating sort_subscribers : str Sort argument, provide to sort function to sort by most/least subscribers Attributes ----------- id : int ID of the mod. Filter attribute. status : Status Status of the mod. Filter attribute. visible : Visibility Visibility of the mod. Filter attribute. game_id : int ID of the game the mod is for. Filter attribute. submitter : User Instance of the modio User that submitted the mod. Filter attribute. date : datetime.datetime UNIX timestamp of the date the mod was registered. Filter attribute. updated : datetime.datetime UNIX timestamp of the date the mod was last updated. Filter attribute. live : datetime.datetime UNIX timestamp of the date the mod went live. Filter attribute. logo : Image The mod logo homepage : str Link to the homepage of the mod, can be None. Filter attribute. name : str Name of the mod. Filter attribute. name_id : str sub_domain mod for the game (https://game_name.mod.io/name_id). Filter attribute. summary : str Summary of the mod. Filter attribute. description :str Detailed description of the mod, supports HTML. Filter attribute. metadata : str Metadata stored by developers which may include properties on how information required. Can be None. Filter attribute. maturity : Maturity Maturity option of the mod. Filter attribute. profile : str URL of the mod's modio profile file : ModFile Latest released instance. Can be None. Filter attribute. media : ModMedia Contains mod media data (links and images) stats : ModStats Summary of all stats for this mod tags : dict Tags for this mod. Filter attribute. kvp : dict Contains key-value metadata. Filter attribute. plaintext : str description field converted into plaintext. """ _resource_type = "mods" mod_key = "id" def __init__(self, **attrs): self.id = attrs.pop("id") self.status = Status(attrs.pop("status")) self.visible = Visibility(attrs.pop("visible")) self.game_id = attrs.pop("game_id") # self.game_name = attrs.pop("game_name") self.date = _convert_date(attrs.pop("date_added")) self.updated = _convert_date(attrs.pop("date_updated")) self.live = _convert_date(attrs.pop("date_live")) self.logo = Image(**attrs.pop("logo")) self.homepage = attrs.pop("homepage_url", None) self.name = attrs.pop("name") self.name_id = attrs.pop("name_id") self.summary = attrs.pop("summary") self.description = attrs.pop("description") self.metadata = attrs.pop("metadata_blob") self.profile = attrs.pop("profile_url") self.media = ModMedia(**attrs.pop("media")) self.maturity = Maturity(attrs.pop("maturity_option")) self.stats = ModStats(**attrs.pop("stats")) self.tags = {tag["name"]: tag["date_added"] for tag in attrs.pop("tags", [])} self.connection = attrs.pop("connection") self._file = attrs.pop("modfile", None) self._kvp_raw = attrs.pop("metadata_kvp") self.file = ( ModFile(**self._file, game_id=self.game_id, connection=self.connection) if self._file else None ) self.submitter = User(connection=self.connection, **attrs.pop("submitted_by")) self.plaintext = attrs.pop("description_plaintext") @property def kvp(self): meta = {} for item in self._kvp_raw: if item["metakey"] not in meta: meta[item["metakey"]] = [] meta[item["metakey"]].append(item["metavalue"]) return meta def __repr__(self): return f"<Mod id={self.id} name={self.name} game_id={self.game_id}>"
[docs] def get_file(self, file_id: int) -> ModFile: """Get the Mod File with the following ID. |coro| Parameters ----------- file_id : int ID of the mod file you wish to retrieve Raises ------- NotFound A mod with that ID has not been found Returns ------- ModFile The found modfile """ file_json = self.connection.get_request(f"/games/{self.game_id}/mods/{self.id}/files/{file_id}") return ModFile(**file_json, game_id=self.game_id, connection=self.connection)
[docs] async def async_get_file(self, file_id: int) -> ModFile: file_json = await self.connection.async_get_request( f"/games/{self.game_id}/mods/{self.id}/files/{file_id}" ) return ModFile(**file_json, game_id=self.game_id, connection=self.connection)
[docs] def get_files(self, *, filters: Filter = None) -> Returned[ModFile]: """Get all mod files for this mod. Returns a named tuple with parameters results and pagination. |filterable| |coro| Parameters ----------- filter : Optional[Filter] A instance of Filter to be used for filtering, paginating and sorting results Returns -------- Returned[List[ModFile], Pagination] The results and pagination tuple from this request """ files_json = self.connection.get_request( f"/games/{self.game_id}/mods/{self.id}/files", filters=filters ) return Returned( [ ModFile(**file, game_id=self.game_id, connection=self.connection) for file in files_json["data"] ], Pagination(**files_json), )
[docs] async def async_get_files(self, *, filters: Filter = None) -> Returned[ModFile]: files_json = await self.connection.async_get_request( f"/games/{self.game_id}/mods/{self.id}/files", filters=filters ) return Returned( [ ModFile(**file, game_id=self.game_id, connection=self.connection) for file in files_json["data"] ], Pagination(**files_json), )
[docs] def get_events(self, *, filters: Filter = None) -> Returned[Event]: """Get all events for that mod sorted by latest. Returns, a named tuple with parameters results and pagination. |filterable| |coro| Parameters ----------- filter : Optional[Filter] A instance of Filter to be used for filtering, paginating and sorting results Returns -------- Returned[List[Event], Pagination] The results and pagination tuple from this request """ event_json = self.connection.get_request( f"/games/{self.game_id}/mods/{self.id}/events", filters=filters ) return Returned([Event(**event) for event in event_json["data"]], Pagination(**event_json))
[docs] async def async_get_events(self, *, filters: Filter = None) -> Returned[Event]: event_json = await self.connection.async_get_request( f"/games/{self.game_id}/mods/{self.id}/events", filters=filters ) return Returned([Event(**event) for event in event_json["data"]], Pagination(**event_json))
[docs] def get_tags(self, *, filters: Filter = None) -> Returned[dict]: """Gets all the tags for this mod. Updates the instance's tag attribute. Returns a named tuple with parameters results and pagination. |filterable| |coro| Parameters ----------- filter : Optional[Filter] A instance of Filter to be used for filtering, paginating and sorting results Returns -------- Returned[List[Tag], Pagination] The results and pagination tuple from this request """ tag_json = self.connection.get_request(f"/games/{self.game_id}/mods/{self.id}/tags", filters=filters) self.tags = new_tags = {tag["name"]: _convert_date(tag["date_added"]) for tag in tag_json["data"]} return Returned(new_tags, Pagination(**tag_json))
[docs] async def async_get_tags(self, *, filters: Filter = None) -> Returned[dict]: tag_json = await self.connection.async_get_request( f"/games/{self.game_id}/mods/{self.id}/tags", filters=filters ) self.tags = new_tags = {tag["name"]: _convert_date(tag["date_added"]) for tag in tag_json["data"]} return Returned(new_tags, Pagination(**tag_json))
[docs] def get_metadata(self) -> Returned[dict]: """Returns a dict of metakey-metavalue pairs. This will also update the mod's kvp attribute. |coro| Returns -------- Returned[List[MetaData], Pagination] The results and pagination tuple from this request """ meta_json = self.connection.get_request(f"/games/{self.game_id}/mods/{self.id}/metadatakvp") self._kvp_raw = meta_json["data"] return Returned(self.kvp, Pagination(**meta_json))
[docs] async def async_get_metadata(self) -> Returned[dict]: meta_json = await self.connection.async_get_request( f"/games/{self.game_id}/mods/{self.id}/metadatakvp" ) self._kvp_raw = meta_json["data"] return Returned(self.kvp, Pagination(**meta_json))
[docs] def get_dependencies(self, *, filters: Filter = None) -> Returned[dict]: """Returns a dict of dependency_id-date_added pairs. Returns a named tuple with parameters results and pagination. |filterable| |coro| Parameters ----------- filter : Optional[Filter] A instance of Filter to be used for filtering, paginating and sorting results Returns -------- Returned[List[Dependency], Pagination] The results and pagination tuple from this request """ depen_json = self.connection.get_request( f"/games/{self.game_id}/mods/{self.id}/dependencies", filters=filters ) return Returned( {dependecy["mod_id"]: _convert_date(dependecy["date_added"]) for dependecy in depen_json["data"]}, Pagination(**depen_json), )
[docs] async def async_get_dependencies(self, *, filters: Filter = None) -> Returned[dict]: depen_json = await self.connection.async_get_request( f"/games/{self.game_id}/mods/{self.id}/dependencies", filters=filters ) return Returned( {dependecy["mod_id"]: _convert_date(dependecy["date_added"]) for dependecy in depen_json["data"]}, Pagination(**depen_json), )
[docs] def get_team(self, *, filters: Filter = None) -> Returned[TeamMember]: """Returns a list of TeamMember object representing the Team in charge of the mod. |filterable| |coro| Parameters ----------- filter : Optional[Filter] A instance of Filter to be used for filtering, paginating and sorting results Returns -------- Returned[List[TeamMember], Pagination] The results and pagination tuple from this request """ team_json = self.connection.get_request(f"/games/{self.game_id}/mods/{self.id}/team", filters=filters) return Returned( [TeamMember(**member, connection=self.connection, mod=self) for member in team_json["data"]], Pagination(**team_json), )
[docs] async def async_get_team(self, *, filters: Filter = None) -> Returned[TeamMember]: team_json = await self.connection.async_get_request( f"/games/{self.game_id}/mods/{self.id}/team", filters=filters ) return Returned( [TeamMember(**member, connection=self.connection, mod=self) for member in team_json["data"]], Pagination(**team_json), )
[docs] def get_comments(self, *, filters: Filter = None) -> Returned[Comment]: """Returns a list of all the top level comments for this mod wih comments replying to top level comments stored in the children attribute. This can be flattened using the utils.flatten function. |filterable| |coro| Parameters ----------- filter : Optional[Filter] A instance of Filter to be used for filtering, paginating and sorting results Returns -------- Returned[List[Comment], Pagination] The results and pagination tuple from this request """ comment_json = self.connection.get_request( f"/games/{self.game_id}/mods/{self.id}/comments", filters=filters ) return Returned( [Comment(**comment, connection=self.connection, mod=self) for comment in comment_json["data"]], Pagination(**comment_json), )
[docs] async def async_get_comments(self, *, filters: Filter = None) -> Returned[Comment]: comment_json = await self.connection.async_get_request( f"/games/{self.game_id}/mods/{self.id}/comments", filters=filters ) return Returned( [Comment(**comment, connection=self.connection, mod=self) for comment in comment_json["data"]], Pagination(**comment_json), )
[docs] def add_comment(self, content: str, *, reply: int = None) -> Comment: """Add a comment to the mod page. You can specify a comment to reply too. |coro| Parameters ----------- content : str The content of the comment reply : Optional[Comment] The comment to reply to Returns ------- Comment The comment created """ data = {"content": content} if reply: data["reply_id"] = reply.id comment = self.connection.post_request(f"/games/{self.game_id}/mods/{self.id}/comments", data=data) return Comment(connection=self.connection, mod=self, **comment)
[docs] async def async_add_comment(self, content: str, *, reply: int = None) -> Comment: data = {"content": content} if reply: data["reply_id"] = reply.id comment = await self.connection.async_post_request( f"/games/{self.game_id}/mods/{self.id}/comments", data=data ) return Comment(connection=self.connection, mod=self, **comment)
[docs] def get_stats(self) -> ModStats: """Returns a ModStats object, representing a series of stats for the mod. |coro| Returns ------- Stats The stats summary object for the mod. """ stats_json = self.connection.get_request(f"/games/{self.game_id}/mods/{self.id}/stats") self.stats = stats = ModStats(**stats_json) return stats
[docs] async def async_get_stats(self) -> ModStats: stats_json = await self.connection.async_get_request(f"/games/{self.game_id}/mods/{self.id}/stats") self.stats = stats = ModStats(**stats_json) return stats
[docs] def edit(self, **fields) -> "Mod": """Used to edit the mod details. Sucessful editing will return the updated mod. |coro| Parameters ----------- status : Status For game admins only. visible : Visibility Modify the game visibility name : str Name of the mod, cannot exceed 80 characters name_id : str Subdomain for the mod, cannot exceed 80 characters summary : str Summary of the mod, cannot exceed 250 characters description : str Detailed description for your mod, which can include details such as 'About', 'Features', 'Install Instructions', 'FAQ', etc. HTML supported and encouraged. homepage : str URL to the official homepage for this mod. stock : str Maximium number of subscribers for this mod. A value of 0 disables this limit. maturity : Maturity Maturity option of the mod. metadata : str Metadata stored by the mod developer which may include properties as to how the item works, or other information you need to display. Returns -------- Mod The updated version of the mod """ fields = _clean_and_convert(fields) mod_json = self.connection.put_request(f"/games/{self.game_id}/mods/{self.id}", data=fields) return self.__class__(connection=self.connection, **mod_json)
[docs] async def async_edit(self, **fields) -> "Mod": fields = _clean_and_convert(fields) mod_json = await self.connection.async_put_request( f"/games/{self.game_id}/mods/{self.id}", data=fields ) return self.__class__(connection=self.connection, **mod_json)
[docs] def delete(self): """Delete a mod and set its status to deleted. |coro| """ resp = self.connection.delete_request(f"/games/{self.game_id}/mods/{self.id}") self.status = 3 return resp
[docs] async def async_delete(self): resp = await self.connection.async_delete_request(f"/games/{self.game_id}/mods/{self.id}") self.status = 3 return resp
[docs] def add_file(self, file: NewModFile) -> ModFile: """Adds a new file to the mod, to do so first construct an instance of NewModFile and then pass it to the function. |coro| Parameters ----------- file : NewModFile The mod file to upload Raises ------- modioException file argument must be type NewModFile Returns -------- ModFile The modfile after being processed by the mod.io API """ file_d = file.__dict__.copy() file_file = file_d.pop("file") with open(file_file, "rb") as f: file_json = self.connection.post_request( f"/games/{self.game_id}/mods/{self.id}/files", h_type=1, data=file_d, files={"filedata": f} ) return ModFile(**file_json, game_id=self.game_id, connection=self.connection)
[docs] async def async_add_file(self, file: NewModFile) -> ModFile: file_d = file.__dict__.copy() file_file = file_d.pop("file") with open(file_file, "rb") as f: file_json = await self.connection.async_post_request( f"/games/{self.game_id}/mods/{self.id}/files", h_type=1, data=file_d, files={"filedata": f} ) return ModFile(**file_json, game_id=self.game_id, connection=self.connection)
def _prepare_media(self, logo, images, youtube, sketchfab): media = {} if logo: media["logo"] = open(logo, "rb") if isinstance(images, str): images_d = {"images": ("image.zip", open(images, "rb"))} elif isinstance(images, list): images_d = {f"image{index}": open(image, "rb") for index, image in enumerate(images)} yt = {f"youtube[{index}]": link for index, link in enumerate(youtube)} sketch = {f"sketchfab[{index}]": link for index, link in enumerate(sketchfab)} media = {**media, **images_d} links = {**yt, **sketch} return media, links
[docs] def add_media( self, *, logo: Optional[str] = None, images: Optional[Union[str, List[str]]] = (), youtube: List[str] = (), sketchfab: List[str] = (), ): """Upload new media to the mod. |coro| Parameters ----------- logo : Optional[str] Path to the logo file. If on windows, must be \\ escaped. Image file which will represent your mods logo. Must be gif, jpg or png format and cannot exceed 8MB in filesize. Dimensions must be at least 640x360 and we recommended you supply a high resolution image with a 16 / 9 ratio. mod.io will use this logo to create three thumbnails with the dimensions of 320x180, 640x360 and 1280x720. images : Optional[Union[str, list]] Can be either the path to a file called .zip file containing all the images or a list of paths to multiple image files. If on windows, must be \\ escaped. Only valid gif, jpg and png images in the zip file will be processed. youtube : Optional[List[str]] List of youtube links to be added to the gallery sketchfab : Optional[List[str]] List of sketchfab links to the be added to the gallery. Returns ------- Message A message confirming the submission of the media """ medias, links = self._prepare_media(logo, images, youtube, sketchfab) try: media_json = self.connection.post_request( f"/games/{self.game_id}/mods/{self.id}/media", h_type=1, files=medias, data=links ) finally: for media in medias.values(): if isinstance(media, tuple): media[1].close() else: media.close() return Message(**media_json)
[docs] async def async_add_media( self, *, logo: Optional[str] = None, images: Optional[Union[str, List[str]]] = (), youtube: List[str] = (), sketchfab: List[str] = (), ): medias, links = self._prepare_media(logo, images, youtube, sketchfab) try: media_json = await self.connection.async_post_request( f"/games/{self.game_id}/mods/{self.id}/media", h_type=1, files=medias, data=links ) finally: for media in medias.values(): if isinstance(media, tuple): media[1].close() else: media.close() return Message(**media_json)
def _prepare_delete_media(self, images, youtube, sketchfab): images = {f"images[{index}]": image for index, image in enumerate(images)} yt = {f"youtube[{index}]": link for index, link in enumerate(youtube)} sketch = {f"sketchfab[{index}]": link for index, link in enumerate(sketchfab)} fields = {**images, **yt, **sketch} return fields
[docs] def delete_media( self, *, images: Optional[List[str]] = (), youtube: Optional[List[str]] = (), sketchfab: Optional[List[str]] = (), ): """Delete media from the mod page. |coro| Parameters ----------- images : Optional[List[str]] Optional. List of image filenames that you want to delete youtube : Optional[List[str]] Optional. List of youtube links that you want to delete sketchfab : Optional[List[str]] Optional. List sketchfab links that you want to delete """ resp = self.connection.delete_request( f"/games/{self.game_id}/mods/{self.id}/media", data=self._prepare_delete_media(images, youtube, sketchfab), ) return resp
[docs] async def async_delete_media( self, *, images: Optional[List[str]] = (), youtube: Optional[List[str]] = (), sketchfab: Optional[List[str]] = (), ): resp = await self.connection.async_delete_request( f"/games/{self.game_id}/mods/{self.id}/media", data=self._prepare_delete_media(images, youtube, sketchfab), ) return resp
[docs] def subscribe(self) -> "Mod": """Subscribe to the mod. Returns None if user is already subscribed. |coro| Returns -------- Mod The mod that was just subscribed to, if the user was already subscribed it will return None """ mod_json = self.connection.post_request(f"/games/{self.game_id}/mods/{self.id}/subscribe") return Mod(connection=self.connection, **mod_json)
[docs] async def async_subscribe(self) -> "Mod": mod_json = await self.connection.async_post_request(f"/games/{self.game_id}/mods/{self.id}/subscribe") return Mod(connection=self.connection, **mod_json)
[docs] def unsubscribe(self): """Unsubscribe from a mod. Returns None if the user is not subscribed. |coro|""" resp = self.connection.delete_request(f"/games/{self.game_id}/mods/{self.id}/subscribe") return resp
[docs] async def async_unsubscribe(self): resp = await self.connection.async_delete_request(f"/games/{self.game_id}/mods/{self.id}/subscribe") return resp
[docs] def add_tags(self, *tags: str): """Add tags to a mod, tags are case insensitive and duplicates will be removed. Tags which are not in the game's tag_options will not be added. |coro| Parameters ----------- tags : List[str] list of tags to be added. """ fields = {f"tags[{index}]": tag for index, tag in enumerate(tags)} message = self.connection.post_request(f"/games/{self.game_id}/mods/{self.id}/tags", data=fields) return Message(**message)
[docs] async def async_add_tags(self, *tags: str): fields = {f"tags[{index}]": tag for index, tag in enumerate(tags)} message = await self.connection.async_post_request( f"/games/{self.game_id}/mods/{self.id}/tags", data=fields ) return Message(**message)
[docs] def delete_tags(self, *tags: str): """Delete tags from the mod, tags are case insensitive and duplicates will be removed. Providing no arguments will remove every tag from the mod. |coro| Parameters ----------- tags : List[str] List of tags to remove, if no list is provided, will remove every tag from the mod. """ fields = {f"tags[{index}]": tag for index, tag in enumerate(tags)} if tags else {"tags[]": ""} self.connection.delete_request(f"/games/{self.game_id}/mods/{self.id}/tags", data=fields)
[docs] async def async_delete_tags(self, *tags: str): fields = {f"tags[{index}]": tag for index, tag in enumerate(tags)} if tags else {"tags[]": ""} await self.connection.async_delete_request(f"/games/{self.game_id}/mods/{self.id}/tags", data=fields)
[docs] def add_metadata(self, **metadata): """Add metadate key-value pairs to the mod. To submit new meta data, pass meta data keys as keyword arguments and meta data value as a list of values. E.g pistol_dmg = [800, 400]. Keys support alphanumeric, '-' and '_'. Total lengh of key and values cannot exceed 255 characters. To add meta-keys which contain a dash in their name they must be passed as an upacked dictionnary. |coro| Example -------- `mod.add_metadata(difficulty=["hard", "medium", "easy"])` This will add the values "hard", "medium" and "easy" to the meta key "difficulty" `mod.add_metadata(**{"test-var": ["test1", "test2", "test3"]})` This will add the values "test1", "test2" and "test3" to meta key "test-var" Returns -------- Message message on the status of the successful added meta data """ metadata_d = {} index = 0 for key, values in metadata.items(): metadata_d[f"metadata[{index}]"] = f"{key}:{':'.join(values)}" index += 1 checked = self.connection.post_request( f"/games/{self.game_id}/mods/{self.id}/metadatakvp", data=metadata_d ) for key, value in metadata.items(): for item in value: self._kvp_raw.append({"metakey": key, "metavalue": item}) return Message(**checked)
[docs] async def async_add_metadata(self, **metadata): metadata_d = {} index = 0 for key, values in metadata.items(): metadata_d[f"metadata[{index}]"] = f"{key}:{':'.join(values)}" index += 1 checked = await self.connection.async_post_request( f"/games/{self.game_id}/mods/{self.id}/metadatakvp", data=metadata_d ) for key, value in metadata.items(): for item in value: self._kvp_raw.append({"metakey": key, "metavalue": item}) return Message(**checked)
[docs] def delete_metadata(self, **metadata): """Deletes metadata from a mod. To do so pass the meta-key as a keyword argument and the meta-values you wish to delete as a list. You can pass an empty list in which case all meta-values for the meta-key will be deleted. To delete meta-keys which contain a dash in their name they must be passed as an upacked dictionnary. |coro| Example -------- `mod.delete_metadata(difficulty=["easy"])` This will remove the value "easy" from the meta key "difficulty" `mod.delete_metadata(difficulty=[])` This will remove the meta key "difficulty" `mod.delete_metadata(**{"test-var": ["test1"]})` This will remove the value "test1" from the meta key "test-var" `mod.delete_metadata(**{"test-var":[]})` This will remove the meta key "test-var" """ metadata_d = {} index = 0 for key, values in metadata.items(): metadata_d[f"metadata[{index}]"] = f"{key}{':' if len(values) > 0 else ''}{':'.join(values)}" index += 1 resp = self.connection.delete_request( f"/games/{self.game_id}/mods/{self.id}/metadatakvp", data=metadata_d ) for key, values in metadata.items(): if not values: self._kvp_raw = [x for x in self._kvp_raw if x["metakey"] != key] else: self._kvp_raw = [ x for x in self._kvp_raw if x["metakey"] != key and x["metavalue"] not in values ] return resp
[docs] async def async_delete_metadata(self, **metadata): metadata_d = {} index = 0 for key, values in metadata.items(): metadata_d[f"metadata[{index}]"] = f"{key}{':' if len(values) > 0 else ''}{':'.join(values)}" index += 1 resp = await self.connection.async_delete_request( f"/games/{self.game_id}/mods/{self.id}/metadatakvp", data=metadata_d ) for key, values in metadata.items(): if not values: self._kvp_raw = [x for x in self._kvp_raw if x["metakey"] != key] else: self._kvp_raw = [ x for x in self._kvp_raw if x["metakey"] != key and x["metavalue"] not in values ] return resp
[docs] def add_dependencies(self, dependencies: List[Union[int, "Mod"]]): """Add mod dependencies required by the corresponding mod. A dependency is a mod that should be installed for this mod to run. |coro| Parameters ---------- dependencies : List[Union[int, Mod]] List of mod ids to submit as dependencies. """ dependency = { f"dependencies[{index}]": getattr(data, "id", data) for index, data in enumerate(dependencies) } resp = self.connection.post_request( f"/games/{self.game_id}/mods/{self.id}/dependencies", data=dependency ) return Message(**resp)
[docs] async def async_add_dependencies(self, dependencies: List[Union[int, "Mod"]]): dependency = { f"dependencies[{index}]": getattr(data, "id", data) for index, data in enumerate(dependencies) } resp = await self.connection.async_post_request( f"/games/{self.game_id}/mods/{self.id}/dependencies", data=dependency ) return Message(**resp)
[docs] def delete_dependencies(self, dependencies: List[Union[int, "Mod"]]): """Delete mod dependecies required by this mod. You must supply at least one dependency. |coro| Parameters ----------- dependencies : List[Union[int, Mod]] List of dependencies to remove """ if not dependencies: raise modioException("Please supply at least on dependency to be deleted.") data = { f"dependencies[{index}]": getattr(data, "id", data) for index, data in enumerate(dependencies) } resp = self.connection.delete_request(f"/games/{self.game_id}/mods/{self.id}/dependencies", data=data) return resp
[docs] async def async_delete_dependencies(self, dependencies: List[Union[int, "Mod"]]): if not dependencies: raise modioException("Please supply at least on dependency to be deleted.") data = { f"dependencies[{index}]": getattr(data, "id", data) for index, data in enumerate(dependencies) } resp = await self.connection.async_delete_request( f"/games/{self.game_id}/mods/{self.id}/dependencies", data=data ) return resp
[docs] def add_team_member(self, email: str, level: Level, *, position: Optional[str] = None): """Add a user to the mod team. Will fire a MOD_TEAM_CHANGED event. |coro| Parameters ----------- email : str mod.io email of the user you wish to add level : Level Level of permissions you grant the user position : Optional[str] Title of the user position """ data = {"email": email, "level": level.value, "position": position} msg = self.connection.post_request(f"/games/{self.game_id}/mods/{self.id}/team", data=data) return Message(**msg)
[docs] async def async_add_team_member(self, email: str, level: Level, *, position: Optional[str] = None): data = {"email": email, "level": level.value, "position": position} msg = await self.connection.async_post_request( f"/games/{self.game_id}/mods/{self.id}/team", data=data ) return Message(**msg)