Skip to content

Commit

Permalink
removeRoles and addRolles macro
Browse files Browse the repository at this point in the history
These methods will always return a PromiseInterface that resolves to a Member object. This will make it easier to chain promises together in a way that can be more sanely maintained.
  • Loading branch information
valzargaming committed Jun 24, 2024
1 parent f0f8355 commit 484658b
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 26 deletions.
99 changes: 87 additions & 12 deletions src/Civ13/Civ13.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ class Civ13
const insults_path = 'insults.txt';
const status = 'status.txt';

/** @var array<string> */
const array faction_teams = ['red', 'blue'];
/** @var array<string> */
const array faction_admins = ['organizer'];

public bool $ready = false;
Expand Down Expand Up @@ -549,19 +551,92 @@ public function statusChanger(Activity $activity, string $state = 'online'): voi
{
$this->discord->updatePresence($activity, false, $state);
}
public function removeRoles(Member $member, array $roles = []): void
{
$promise = null;
foreach ($roles as $role) if ($member->roles->has($role)) $promise = $promise ? $promise->then(function () use ($member, $role) {
return $member->removeRole($role);
}, $this->onRejectedDefault) : $promise = $member->removeRole($role);
/**
* Removes specified roles from a member.
*
* @param Member $member The member object from which the roles will be removed.
* @param Collection<Role>|array<string|int>|Role|string|int $roles An array of role IDs to be removed.
* @param bool $patch Determines whether to use patch mode or not. If true, the member's roles will be updated using setRoles method. If false, the member's roles will be updated using removeRole method.
* @return PromiseInterface<Member> A promise that resolves to the updated member object.
*/
public function removeRoles(Member $member, Collection|array|Role|string|int $roles, bool $patch = true): PromiseInterface
{
if (! $roles) return \React\Promise\resolve($member);
$role_ids = [];
switch (true) {
case ($roles instanceof Collection && $roles->first() instanceof Role):
$role_ids = $roles->map(fn($role) => $role->id)->toArray();
break;
case (! $roles instanceof Collection && is_array($roles) && $roles[0] instanceof Role):
$role_ids = array_map(fn($role) => $role->id, $roles);
break;
case (is_array($roles)):
$role_ids = array_map('strval', $roles);
break;
case ($roles instanceof Role):
$role_ids[] = $roles->id;
break;
case (is_string($roles) || is_int($roles)):
$role_ids[] = "$roles";
break;
default:
$this->logger->warning('Roles not found for removeRoles: ' . json_encode($roles));
return \React\Promise\resolve($member);
}
foreach ($role_ids as &$role_id) if (! $member->roles->has($role_id)) unset($role_id);
if (! $role_ids) {
$this->logger->warning('No roles to remove for removeRoles');
return \React\Promise\resolve($member);
}

return $patch
? ((($new_roles = $member->roles->filter(function (Role $role) use ($role_ids) { return ! in_array($role->id, $role_ids); })->toArray()) !== $member->roles) ? $member->setRoles($new_roles) : \React\Promise\resolve($member))
: \React\Promise\all(array_map(fn($role) => $member->removeRole($role->id), $role_ids))
->then(function() use ($member) {
return $member->guild->members->get('id', $member->id);
});
}
public function addRoles(Member $member, array $roles = []): void
{
$promise = null;
foreach ($roles as $role) if ($member->roles->has($role)) $promise = $promise ? $promise->then(function () use ($member, $role) {
return $member->addRole($role);
}, $this->onRejectedDefault) : $promise = $member->addRole($role);
/**
* Adds specified roles to a member.
*
* @param Member $member The member object to which the roles will be added.
* @param Collection<Role>|array<string|int>|Role|string|int $roles An array of role IDs to be added.
* @param bool $patch Determines whether to use patch mode or not. If true, the member's roles will be updated using setRoles method. If false, the member's roles will be updated using addRole method.
* @return PromiseInterface<Member> A promise that resolves to the updated member object.
*/
public function addRoles(Member $member, Collection|array|Role|string|int $roles, bool $patch = true): PromiseInterface
{
if (! $roles) return \React\Promise\resolve($member);
$role_ids = [];
switch (true) {
case ($roles instanceof Collection && $roles->first() instanceof Role):
$role_ids = $roles->map(fn($role) => $role->id)->toArray();
break;
case (! $roles instanceof Collection && is_array($roles) && $roles[0] instanceof Role):
$role_ids = array_map(fn($role) => $role->id, $roles);
break;
case ($roles instanceof Role):
$role_ids[] = $roles->id;
break;
case (is_string($roles) || is_int($roles)):
$role_ids[] = "$roles";
break;
default:
$this->logger->warning('Roles not found for addRoles: ' . json_encode($roles));
return \React\Promise\resolve($member);
}
foreach ($role_ids as &$role_id) if ($member->roles->has($role_id)) unset($role_id);
if (! $role_ids) {
$this->logger->warning('No roles to add for addRoles');
return \React\Promise\resolve($member);
}

return $patch
? $member->setRoles(array_merge(array_values($member->roles->map(fn($role) => $role->id)->toArray()), $role_ids))
: \React\Promise\all(array_map(fn($role) => $member->addRole($role->id), $role_ids))
->then(function() use ($member) {
return $member->guild->members->get('id', $member->id);
});
}
/**
* Sends a message to the specified channel.
Expand Down
19 changes: 5 additions & 14 deletions src/Civ13/Slash.php
Original file line number Diff line number Diff line change
Expand Up @@ -789,25 +789,16 @@ private function __declareListeners(): void
if ($target_team !== 'none' && (! isset($this->civ13->role_ids[$target_team]) || ! $role_id = $this->civ13->role_ids[$target_team])) return $interaction->respondWithMessage(MessageBuilder::new()->setContent("Team not configured: `$target_team`"), true);
if ($role_id && $target_member->roles->has($role_id)) return $interaction->respondWithMessage(MessageBuilder::new()->setContent('The member is already in this faction!'), true);
//if ($target_member->roles->has($this->civ13->role_ids['red']) || $target_member->roles->has($this->civ13->role_ids['blue'])) return $interaction->respondWithMessage(MessageBuilder::new()->setContent('The member is already in a faction! Please remove their current faction role first.'), true); // Don't assign if they already have a faction role
$faction_ids = array_filter(array_map(fn($key) => $this->civ13->role_ids[$key] ?? null, Civ13::faction_teams));

if (in_array($target_team, Civ13::faction_teams)) {
$promise = $target_member->addRole($role_id)->then(function () use (&$promise, $target_member, $target_team) {
foreach(Civ13::faction_teams as $team) if ($team !== $target_team && $target_member->roles->has($this->civ13->role_ids[$team])) {
$promise = $promise->then(function() use ($target_member, $team) {
return $target_member->removeRole($this->civ13->role_ids[$team]);
}, $this->civ13->onRejectedDefault);
}
}, $this->civ13->onRejectedDefault);
$this->civ13->removeRoles($target_member, $faction_ids, true)->then(function (Member $member) use ($role_id) {
$this->civ13->addRoles($member, $role_id); // Only one role is being added so we don't need to PATCH
});
return $interaction->respondWithMessage(MessageBuilder::new()->setContent("The <@&$role_id> role has been assigned to <@{$target_member->id}>")->setAllowedMentions(['parse'=>['users']]), true);
}
if ($target_team === 'none') {
$promise = null;
foreach(Civ13::faction_teams as $team) if ($target_member->roles->has($this->civ13->role_ids[$team])) {
$promise = $promise ? $promise->then(function () use ($target_member, $team) {
return $target_member->removeRole($this->civ13->role_ids[$team]);
}, $this->civ13->onRejectedDefault) : $promise = $target_member->removeRole($team);
$target_member = $this->discord->guilds->get('id', $target_member->guild_id)->members->get('id', $target_member->id); // Refresh the member
}
$this->civ13->removeRoles($target_member, $faction_ids, true); // Multiple roles COULD be removed so we should PATCH
return $interaction->respondWithMessage(MessageBuilder::new()->setContent("The faction roles have been removed from <@{$target_member->id}>"), true);
}
return $interaction->respondWithMessage(MessageBuilder::new()->setContent("Invalid team: `$target_team`."), true);
Expand Down

0 comments on commit 484658b

Please sign in to comment.