# bloyid.py

Python API wrapper for Bloyid originating from [Fiiral](https://github.com/F-iiral), maintained by [Deutscher775](https://github.com/Deutscher775)
### **[Nerimity Server](https://web.bloyid.com/i/493CV)** <br>
For questions, help or anything else feel free to join the **[bloyid.py](https://web.bloyid.com/i/493CV)** Bloyid server.
# Quick jumps
- **[Current Features](#current-features)** <br>
See the features that the framework currently supports.
- **[Installation](#installation)** <br>
Guide on how to install bloyid.py.
- **[Example Bot](#example-commands-bot)** <br>
An example bot you can directly use.
- **[Use-case-examples](#use-case-examples)** <br>
Many various examples on how to use specific functions.

# Current features
#### Command Handling:
- Define and register commands using the @client.command decorator.
- Execute commands with parameters.
Register event listeners using the @client.listen decorator.
Handle various events such as:
- on_ready
- on_message_create
- on_message_updated
- on_message_deleted
- on_button_clicked
- on_presence_change
- on_reaction_add
- on_member_updated
- on_role_updated
- on_role_deleted
- on_role_created
- on_channel_updated
- on_channel_deleted
- on_channel_created
- on_server_updated
- on_member_join
- on_member_left
- on_server_joined
- on_server_left
- on_friend_request_sent
- on_friend_request_pending
- on_friend_request_accepted
- on_friend_removed
- on_minute_pulse
- on_hour_pulse

#### Message Handling:
- Send messages to channels.
    - add attachments
    - add buttons with custom callback
- Edit and delete messages.
- React and unreact to messages.

#### Attachment Handling:
- Create and upload attachments.
- Deserialize attachments from JSON.

#### Channel Management:
- Update channel information.
- Send messages to channels.
- Get messages from channels.
- Purge messages from channels.
- Deserialize channels from JSON.

#### Context Handling:
- Send messages, remove messages, and react to messages within a command context.

#### Invite Management:
- Create and delete server invites.
- Deserialize invites from JSON.

#### Member Management:
- Follow, unfollow, add friend, remove friend, and send direct messages to members.
- Kick, ban, and unban server members.
- Deserialize members and server members from JSON.

#### Post Management:
- Create, delete, comment on, like, and unlike posts.
- Get comments on posts.
- Deserialize posts from JSON.

#### Role Management:
- Create, update, and delete roles.
- Deserialize roles from JSON.

#### Server Management:
- Get server details and ban list.
- Create, update, and delete channels and roles.
- Create and delete invites.
- Update server members.
- Deserialize servers from JSON.

#### Status Management:
- Change the presence status of the bot.

#### Button Interaction:
- Handle button interactions and send popups.
- Deserialize button interactions from JSON.

#### Permissions:
- Manage user and role permissions.
- Check for specific permissions before executing commands.
- Deserialize permissions from JSON.

# Installation
## Option 1: Install via PyPI (recommended)
```shell
pip install bloyid
```

## Option 2: clone this repository
1. Clone the repository
```shell
git clone https://github.com/ukyyyy/bloyid.py.git
```
2. Copy the `bloyid` folder and insert it into your workspace. It should look like this:
![Image](./readme-assets/directory-view.png)

### Done!
## Example commands bot
```py
import bloyid


client = bloyid.Client(
    token="YOUR_BOT_TOKEN",
    prefix='!',
)

@client.command(name="ping")
async def ping(ctx: bloyid.Context, params: str):
    await ctx.send("Pong!")


@client.listen("on_ready")
async def on_ready(params):
    print(f"Logged in as {client.account.username}")


client.run()
```

## Issues
If you encounter any issues while using the framework feel free to open an [Issue](https://github.com/ukyyyy/bloyid.py).

## Use case examples
### Sending an attachment
```py
@client.command(name="testattachment")
async def testattachment(ctx: bloyid.Context, params):
    file = await bloyid.Attachment.construct("test.png").upload()
    result = await ctx.send("Test", attachment=file)
```

### Sending buttons with messages
```py
@client.command(name="testbutton")
async def testbutton(ctx: bloyid.Context, params):
    popup_button = bloyid.Button.construct(label="Popup!", id="popuptestbutton", alert=True)
    async def popup_callback(buttoninteraction: bloyid.ButtonInteraction):
        user = client.get_user(buttoninteraction.userId)
        buttoninteraction.send_popup("Test", f"Hello, {user.username}!")
    await popup_button.set_callback(popup_callback)

    message_button = bloyid.Button.construct(label="Message!", id="messagetestbutton")
    async def message_callback(buttoninteraction: bloyid.ButtonInteraction):
        user = client.get_user(buttoninteraction.userId)
        await ctx.send(f"Hello, {user.username}!")
    await message_button.set_callback(message_callback)
    await ctx.send("Test", buttons=[message_button, popup_button])
```

### Creating a post
```py
@client.command(name="createpost")
async def createpost(ctx: bloyid.Context, params):
    content = ""
    for param in params:
        content += param + " "
    await ctx.send("Creating post with text: " + content)
    post = bloyid.Post.create_post(content)
    print(post)
    await ctx.send("Post created.")
```

### Commenting on a post
```py
@client.command(name="comment")
async def comment(ctx: bloyid.Context, params):
    post_id = int(params[0])
    content = ""
    for param in params[1:]:
        content += param + " "
    post = bloyid.Post.get_post(post_id)
    post.create_comment(content)
    await ctx.send("Commented on post.")
```

### Deleting a post
```py
@client.command(name="deletepost")
async def deletepost(ctx: bloyid.Context, params):
    post_id = int(params[0])
    post = bloyid.Post.get_post(post_id)
    post.delete_post()
    await ctx.send("Deleted post.")
```

### Creating a channel
```py
@client.command(name="createchannel")
async def createchannel(ctx: bloyid.Context, params):
    title = params[0]
    permissions = bloyid.Permissions.ChannelPermissions.construct(public=True, send_messages=True, join_voice=True)
    print(permissions)
    everyone_role = ctx.server.get_role(ctx.server.default_role_id)
    new_channel = ctx.server.create_channel(title, type=bloyid.ChannelTypes.SERVER_TEXT)
    await new_channel.set_permissions(permission_integer=permissions, role=everyone_role)
    await ctx.send(f"Channel '{title}' created.")
```

### Creating a role
```py
@client.command(name="createrole")
async def createrole(ctx: bloyid.Context, params):
    name = params[0]
    hide_role = bool(params[1])
    role = ctx.server.create_role()
    role.update_role(name=name, hide_role=hide_role)
    permissions = bloyid.Permissions.RolePermissions.construct(admin=True, manage_roles=True, send_messages=True)
    print(permissions)
    await role.set_permissions(permissions)
    await ctx.send(f"Role '{name}' created.")
```

### Setting for a role in a channel
```py
@client.command(name="setpermissions")
async def setpermissions(ctx: bloyid.Context, params):
    channel_id = int(params[0])
    role_id = int(params[1])
    send_messages = bool(params[2])
    join_voice = bool(params[3])
    
    channel = ctx.server.get_channel(channel_id)
    role = ctx.server.get_role(role_id)
    
    permissions = bloyid.Permissions.ChannelPermissions.construct(send_messages=send_messages, join_voice=join_voice)
    await channel.set_permissions(permission_integer=permissions, role=role)
    
    await ctx.send(f"Permissions set for role '{role.name}' in channel '{channel.name}'.")
```


## Issues
If you encounter any issues while using the framework feel free to open an [Issue](https://github.com/ukyyyy/bloyid.py).