Packages
game_server_sdk
1.0.1044
1.0.1082
1.0.1079
1.0.1078
1.0.1077
1.0.1076
1.0.1075
1.0.1074
1.0.1073
1.0.1070
1.0.1068
1.0.1067
1.0.1063
1.0.1059
1.0.1058
1.0.1057
1.0.1056
1.0.1055
1.0.1050
1.0.1049
1.0.1048
1.0.1047
1.0.1046
1.0.1044
1.0.1043
1.0.1042
1.0.1041
1.0.1040
1.0.1039
1.0.1038
1.0.1034
1.0.1033
1.0.1029
1.0.1028
1.0.1026
1.0.1025
1.0.1024
1.0.1023
1.0.1022
1.0.1021
1.0.1020
1.0.1019
1.0.1018
1.0.1017
1.0.1016
1.0.1015
1.0.1014
1.0.1013
1.0.1012
1.0.1011
1.0.1009
1.0.1008
1.0.1007
1.0.1006
1.0.1005
1.0.1004
1.0.1003
1.0.1001
1.0.999
1.0.998
1.0.997
1.0.996
1.0.995
1.0.994
1.0.993
1.0.992
1.0.991
1.0.990
1.0.989
1.0.988
1.0.987
1.0.986
1.0.985
1.0.984
1.0.983
1.0.982
1.0.981
1.0.980
1.0.979
1.0.978
1.0.977
1.0.976
1.0.975
1.0.974
1.0.973
1.0.972
1.0.971
1.0.970
1.0.969
1.0.968
1.0.967
1.0.966
1.0.965
1.0.964
1.0.963
1.0.962
1.0.961
1.0.959
1.0.958
1.0.956
1.0.951
1.0.950
1.0.943
1.0.942
1.0.941
1.0.940
1.0.938
1.0.936
1.0.935
1.0.931
1.0.929
1.0.928
1.0.927
1.0.926
1.0.925
1.0.924
1.0.923
1.0.921
1.0.920
1.0.919
1.0.918
1.0.917
1.0.916
1.0.911
1.0.910
1.0.902
1.0.899
1.0.898
1.0.897
1.0.896
1.0.894
1.0.893
1.0.891
1.0.890
1.0.889
1.0.888
1.0.887
1.0.886
1.0.885
1.0.884
1.0.883
1.0.882
1.0.881
1.0.880
1.0.879
1.0.878
1.0.877
1.0.26
1.0.25
1.0.22
1.0.21
1.0.20
1.0.19
1.0.15
1.0.14
1.0.13
1.0.12
1.0.10
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.1.0
SDK for GameServer hooks development. Provides type specs, documentation, and IDE autocomplete for GameServer modules without requiring the full server.
Current section
Files
Jump to
Current section
Files
lib/game_server/groups.ex
defmodule GameServer.Groups do
@moduledoc ~S"""
Context module for group management: creating, updating, listing, joining,
leaving, kicking, promoting/demoting members, and handling join requests.
Groups are persistent communities (unlike ephemeral lobbies). They support
three visibility types:
- **public** – anyone can join directly
- **private** – anyone can request to join; an admin must approve
- **hidden** – only invited users can join (via notifications / invite API)
## Usage
# Create a group (creator becomes admin)
{:ok, group} = Groups.create_group(user_id, %{"title" => "Cool Group"})
# List public/private groups (hidden excluded)
groups = Groups.list_groups(%{}, page: 1, page_size: 25)
# Join a public group
{:ok, member} = Groups.join_group(user_id, group.id)
# Request to join a private group
{:ok, request} = Groups.request_join(user_id, group.id)
# Admin approves a join request
{:ok, member} = Groups.approve_join_request(admin_id, request.id)
## PubSub Events
- `"groups"` topic:
- `{:group_created, group}`
- `{:group_updated, group}`
- `{:group_deleted, group_id}`
- `"group:<group_id>"` topic:
- `{:member_joined, group_id, user_id}`
- `{:member_left, group_id, user_id}`
- `{:member_kicked, group_id, user_id}`
- `{:member_promoted, group_id, user_id}`
- `{:member_demoted, group_id, user_id}`
- `{:group_updated, group}`
- `{:join_request_created, group_id, user_id}`
- `{:join_request_approved, group_id, user_id}`
- `{:join_request_rejected, group_id, user_id}`
- `{:group_notification, group_id, sender_id}`
**Note:** This is an SDK stub. Calling these functions will raise an error.
The actual implementation runs on the GameServer.
"""
@doc ~S"""
Accept a pending group invite by invite id (recipient only).
"""
@spec accept_invite(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupMember.t()} | {:error, atom()}
def accept_invite(_user_id, _invite_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.accept_invite/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Check if user is an admin of the group.
"""
@spec admin?(Ecto.UUID.t(), Ecto.UUID.t()) :: boolean()
def admin?(_group_id, _user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
false
_ ->
raise "GameServer.Groups.admin?/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Admin-level delete (no membership check, for server admins).
"""
@spec admin_delete_group(Ecto.UUID.t()) :: {:ok, GameServer.Groups.Group.t()} | {:error, term()}
def admin_delete_group(_group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.admin_delete_group/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Admin-level update, bypasses membership checks.
"""
@spec admin_update_group(GameServer.Groups.Group.t(), map()) ::
{:ok, GameServer.Groups.Group.t()} | {:error, Ecto.Changeset.t()}
def admin_update_group(_group, _attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.admin_update_group/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Approve a pending join request. Admin only.
"""
@spec approve_join_request(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupMember.t()} | {:error, atom()}
def approve_join_request(_admin_id, _request_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.approve_join_request/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Batch count members for a list of group IDs. Returns a map of group_id => count.
"""
@spec batch_member_counts([Ecto.UUID.t()]) :: %{required(Ecto.UUID.t()) => non_neg_integer()}
def batch_member_counts(_group_ids) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.batch_member_counts/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Broadcast a presence event (e.g. member_online, member_updated) to a group topic.
"""
@spec broadcast_member_presence(Ecto.UUID.t(), tuple()) :: :ok | {:error, term()}
def broadcast_member_presence(_group_id, _event) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Groups.broadcast_member_presence/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Cancel a group invitation the current user sent.
"""
@spec cancel_invite(Ecto.UUID.t(), Ecto.UUID.t()) :: :ok | {:error, atom()}
def cancel_invite(_user_id, _invite_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Groups.cancel_invite/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Cancel (delete) a pending join request. Only the requesting user can cancel.
"""
@spec cancel_join_request(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupJoinRequest.t()} | {:error, atom()}
def cancel_join_request(_user_id, _request_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.cancel_join_request/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Return a changeset for tracking group changes (admin edit forms).
"""
@spec change_group(GameServer.Groups.Group.t(), map()) :: Ecto.Changeset.t()
def change_group(_group, _attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Groups.change_group/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count ALL groups matching filters (admin).
"""
@spec count_all_groups(map()) :: non_neg_integer()
def count_all_groups(_filters) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_all_groups/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Total member count across all groups.
"""
@spec count_all_members() :: non_neg_integer()
def count_all_members() do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_all_members/0 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count members in a group. Accepts the same `:search` option as the listing.
"""
@spec count_group_members(Ecto.UUID.t()) :: non_neg_integer()
def count_group_members(_group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_group_members/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count members in a group. Accepts the same `:search` option as the listing.
"""
@spec count_group_members(
Ecto.UUID.t(),
keyword()
) :: non_neg_integer()
def count_group_members(_group_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_group_members/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count groups by type.
"""
@spec count_groups_by_type(String.t()) :: non_neg_integer()
def count_groups_by_type(_type) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_groups_by_type/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count how many groups a user has created (is admin of).
"""
@spec count_groups_created_by(Ecto.UUID.t()) :: non_neg_integer()
def count_groups_created_by(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_groups_created_by/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count pending invitations for a user.
"""
@spec count_invitations(Ecto.UUID.t()) :: non_neg_integer()
def count_invitations(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_invitations/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count pending join requests for a group.
"""
@spec count_join_requests(Ecto.UUID.t()) :: non_neg_integer()
def count_join_requests(_group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_join_requests/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count groups matching public filters (excludes hidden).
"""
@spec count_list_groups(map()) :: non_neg_integer()
def count_list_groups(_filters) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_list_groups/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count group invitations sent by a user.
"""
@spec count_sent_invitations(Ecto.UUID.t()) :: non_neg_integer()
def count_sent_invitations(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_sent_invitations/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count how many groups a user is a member of (any role).
"""
@spec count_user_group_memberships(Ecto.UUID.t()) :: non_neg_integer()
def count_user_group_memberships(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_user_group_memberships/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count groups the user belongs to.
"""
@spec count_user_groups(Ecto.UUID.t()) :: non_neg_integer()
def count_user_groups(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Groups.count_user_groups/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Create a new group. The creating user becomes an admin member automatically.
"""
@spec create_group(Ecto.UUID.t(), map()) ::
{:ok, GameServer.Groups.Group.t()} | {:error, Ecto.Changeset.t() | term()}
def create_group(_user_id, _attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.create_group/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Decline a pending group invite by invite id (recipient only).
"""
@spec decline_invite(Ecto.UUID.t(), Ecto.UUID.t()) :: :ok | {:error, atom()}
def decline_invite(_user_id, _invite_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Groups.decline_invite/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Delete a group. Admin-only. Refuses if the group still has members — groups
are auto-deleted when the last member leaves.
"""
@spec delete_group(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.Group.t()} | {:error, atom()}
def delete_group(_user_id, _group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.delete_group/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Demote an admin to member. Only admins can demote other admins.
"""
@spec demote_member(Ecto.UUID.t(), Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupMember.t()} | {:error, atom()}
def demote_member(_admin_id, _group_id, _target_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.demote_member/3 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Get a group by ID (cached).
"""
@spec get_group(Ecto.UUID.t()) :: GameServer.Groups.Group.t() | nil
def get_group(_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Groups.get_group/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Get a group by ID (raises if not found, cached).
"""
@spec get_group!(Ecto.UUID.t()) :: GameServer.Groups.Group.t()
def get_group!(_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Groups.get_group!/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Get a group by its unique title.
"""
@spec get_group_by_title(String.t()) :: GameServer.Groups.Group.t() | nil
def get_group_by_title(_title) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Groups.get_group_by_title/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Get all members of a group.
"""
@spec get_group_members(Ecto.UUID.t()) :: [GameServer.Groups.GroupMember.t()]
def get_group_members(_group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Groups.get_group_members/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Get paginated members of a group with user info.
Pass `:search` to filter by member name (display name or username).
"""
@spec get_group_members_paginated(
Ecto.UUID.t(),
keyword()
) :: [GameServer.Groups.GroupMember.t()]
def get_group_members_paginated(_group_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Groups.get_group_members_paginated/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Get a specific membership.
"""
@spec get_membership(Ecto.UUID.t(), Ecto.UUID.t()) :: GameServer.Groups.GroupMember.t() | nil
def get_membership(_group_id, _user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Groups.get_membership/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Clean up group memberships before a user is deleted.
For each group the user belongs to:
- If the user is the sole admin and other members exist, promotes the oldest
member to admin before removing the user's membership row.
- Removes the membership row.
- If the group has no members left after removal, deletes the group.
This must be called *before* `Repo.delete(user)` so that the membership
rows still exist (the DB cascade would silently delete them otherwise
without running the admin-transfer / empty-group logic).
"""
@spec handle_user_deletion(Ecto.UUID.t()) :: :ok
def handle_user_deletion(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Groups.handle_user_deletion/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Public wrapper for cache invalidation (used by admin controller).
"""
@spec invalidate_group_cache_public(Ecto.UUID.t()) :: :ok
def invalidate_group_cache_public(_group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Groups.invalidate_group_cache_public/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Invite a user to a group (see `GameServer.Groups.Invites.invite_to_group/3`).
"""
@spec invite_to_group(Ecto.UUID.t(), Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupInvite.t()} | {:ok, :request_approved} | {:error, atom()}
def invite_to_group(_admin_id, _group_id, _target_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.invite_to_group/3 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Join a public group directly. Returns error for private/hidden groups.
"""
@spec join_group(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupMember.t()} | {:error, atom()}
def join_group(_user_id, _group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.join_group/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Kick a member from the group. Only admins can kick.
"""
@spec kick_member(Ecto.UUID.t(), Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupMember.t()} | {:error, atom()}
def kick_member(_admin_id, _group_id, _target_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.kick_member/3 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Leave a group.
"""
@spec leave_group(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupMember.t()} | {:error, atom()}
def leave_group(_user_id, _group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.leave_group/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List ALL groups including hidden (admin only).
"""
@spec list_all_groups(
map(),
keyword()
) :: [GameServer.Groups.Group.t()]
def list_all_groups(_filters, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Groups.list_all_groups/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List groups visible to the public (excludes hidden).
## Filters
* `:title` – prefix search on title (case-insensitive)
* `:type` – exact match on type (`"public"` or `"private"`)
* `:min_members` – groups with max_members >= value
* `:max_members` – groups with max_members <= value
* `:metadata_key` / `:metadata_value` – filter by metadata entry
## Options
* `:page` – page number (default 1)
* `:page_size` – results per page (default 25)
"""
@spec list_groups(
map(),
keyword()
) :: [GameServer.Groups.Group.t()]
def list_groups(_filters, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Groups.list_groups/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List pending group invitations for a user.
"""
@spec list_invitations(
Ecto.UUID.t(),
keyword()
) :: [map()]
def list_invitations(_user_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
%{}
_ ->
raise "GameServer.Groups.list_invitations/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List pending join requests for a group (admin only).
"""
@spec list_join_requests(Ecto.UUID.t(), Ecto.UUID.t(), keyword()) ::
{:ok, [GameServer.Groups.GroupJoinRequest.t()]} | {:error, atom()}
def list_join_requests(_admin_id, _group_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.list_join_requests/3 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List group invitations sent by a user.
"""
@spec list_sent_invitations(
Ecto.UUID.t(),
keyword()
) :: [map()]
def list_sent_invitations(_user_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
%{}
_ ->
raise "GameServer.Groups.list_sent_invitations/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List groups the user belongs to.
"""
@spec list_user_groups(
Ecto.UUID.t(),
keyword()
) :: [GameServer.Groups.Group.t()]
def list_user_groups(_user_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Groups.list_user_groups/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List groups the user belongs to, together with the membership role.
"""
@spec list_user_groups_with_role(Ecto.UUID.t()) :: [{GameServer.Groups.Group.t(), String.t()}]
def list_user_groups_with_role(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
""
_ ->
raise "GameServer.Groups.list_user_groups_with_role/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List pending join requests sent by a user.
"""
@spec list_user_pending_requests(Ecto.UUID.t()) :: [GameServer.Groups.GroupJoinRequest.t()]
def list_user_pending_requests(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Groups.list_user_pending_requests/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Check if user is a member (any role) of the group.
"""
@spec member?(Ecto.UUID.t(), Ecto.UUID.t()) :: boolean()
def member?(_group_id, _user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
false
_ ->
raise "GameServer.Groups.member?/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Send a notification to all members of a group (except the sender).
Any group member can send a notification. The notification is created for
each member using a direct insert (bypassing the friends-only check).
The `group_id` / `group_name` are stored in metadata so the client can
recognise and route it.
## Options
* `title` – notification title string (default: `"Group Notification"`).
The title is part of the unique constraint `(sender_id, recipient_id, title)`,
so different titles create separate notification slots.
Because of the unique constraint on `(sender_id, recipient_id, title)`, a
new notification from the same sender to the same recipient with the same title
replaces the previous one (upsert). This prevents spam while keeping the latest
message.
Returns `{:ok, count}` with the number of notifications sent.
"""
@spec notify_group(Ecto.UUID.t(), Ecto.UUID.t(), String.t(), map()) ::
{:ok, non_neg_integer()} | {:error, atom()}
def notify_group(_sender_id, _group_id, _content, _metadata) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.notify_group/4 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Promote a member to admin. Only admins can promote.
"""
@spec promote_member(Ecto.UUID.t(), Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupMember.t()} | {:error, atom()}
def promote_member(_admin_id, _group_id, _target_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.promote_member/3 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Reject a pending join request. Admin only.
"""
@spec reject_join_request(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupJoinRequest.t()} | {:error, atom()}
def reject_join_request(_admin_id, _request_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.reject_join_request/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Request to join a private group. Creates a pending join request.
"""
@spec request_join(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, GameServer.Groups.GroupJoinRequest.t()} | {:error, atom()}
def request_join(_user_id, _group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.request_join/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Return true if both users share at least one common group membership.
"""
@spec shared_group_member?(Ecto.UUID.t(), Ecto.UUID.t()) :: boolean()
def shared_group_member?(_user_a_id, _user_b_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
false
_ ->
raise "GameServer.Groups.shared_group_member?/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Subscribe to a specific group's events.
"""
@spec subscribe_group(Ecto.UUID.t()) :: :ok | {:error, term()}
def subscribe_group(_group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Groups.subscribe_group/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Subscribe to global group events.
"""
@spec subscribe_groups() :: :ok | {:error, term()}
def subscribe_groups() do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Groups.subscribe_groups/0 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Unsubscribe from a specific group's events.
"""
@spec unsubscribe_group(Ecto.UUID.t()) :: :ok
def unsubscribe_group(_group_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Groups.unsubscribe_group/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Update group settings. Only admins can update.
Cannot lower max_members below current member count.
"""
@spec update_group(Ecto.UUID.t(), Ecto.UUID.t(), map()) ::
{:ok, GameServer.Groups.Group.t()} | {:error, atom() | Ecto.Changeset.t()}
def update_group(_user_id, _group_id, _attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.Groups.update_group/3 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Return the list of group IDs the user belongs to (lightweight, no preloads).
"""
@spec user_group_ids(Ecto.UUID.t()) :: [Ecto.UUID.t()]
def user_group_ids(_user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Groups.user_group_ids/1 is a stub - only available at runtime on GameServer"
end
end
end