Files
Hippolyzer/pyogp/lib/base/groups.py

1046 lines
25 KiB
Python

"""
@file groups.py
@date 2009-03-12
Contributors can be viewed at:
http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt
$LicenseInfo:firstyear=2008&license=apachev2$
Copyright 2009, Linden Research, Inc.
Licensed under the Apache License, Version 2.0 (the "License").
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
or in
http://svn.secondlife.com/svn/linden/projects/2008/pyogp/LICENSE.txt
$/LicenseInfo$
"""
# standard python libs
from logging import getLogger, CRITICAL, ERROR, WARNING, INFO, DEBUG
import uuid
# pyogp
from pyogp.lib.base.exc import DataParsingError
# pyogp messaging
from pyogp.lib.base.message.packets import CreateGroupRequestPacket
# initialize logging
logger = getLogger('pyogp.lib.base.groups')
log = logger.log
class GroupManager(object):
""" a storage bin for groups
also, a functional area for group creation operations
"""
def __init__(self, agent, settings = None):
""" initialize the group manager """
# allow the settings to be passed in
# otherwise, grab the defaults
if settings != None:
self.settings = settings
else:
from pyogp.lib.base.settings import Settings
self.settings = Settings()
self.agent = agent
# the group store consists of a list
# of Group() instances
self.group_store = []
# ~~~~~~~~~
# Callbacks
# ~~~~~~~~~
if self.settings.LOG_VERBOSE: log(DEBUG, "Initialized the Group Manager")
def store_group(self, _group):
""" append to or replace a group in self.group_store """
# replace an existing list member, else, append
try:
index = [self.group_store.index(_object_) for _group_ in self.group_store if _group_.ID == _group.GroupID]
self.group_store[index[0]] = _group
if self.settings.LOG_VERBOSE: log(DEBUG, 'Replacing a stored group: \'%s\'' % (_group.GroupID))
except:
self.group_store.append(_group)
if self.settings.LOG_VERBOSE: log(DEBUG, 'Stored a new group: \'%s\'' % (_group.GroupID))
def create_group(self, AgentID = None, SessionID = None, Name = None, Charter = '', ShowInList = True, InsigniaID = uuid.UUID('00000000-0000-0000-0000-000000000000'), MembershipFee = 0, OpenEnrollment = False, AllowPublish = False, MaturePublish = False):
""" sends a message to the agent's current region requesting to create a group
enables a callback (which should be unsubscribed from once we get a response)
"""
if Name != None:
log(INFO, "Sending a request to create group with a name of \'%s\'" % (Name))
if AgentID == None: AgentID = self.agent.agent_id
if SessionID == None: SessionID = self.agent.session_id
packet = CreateGroupRequestPacket()
# populate the AgentData block
packet.AgentData['AgentID'] = uuid.UUID(str(AgentID)) # MVT_LLUUID
packet.AgentData['SessionID'] = uuid.UUID(str(SessionID)) # MVT_LLUUID
# populate the GroupData block
packet.GroupData['Name'] = Name # MVT_VARIABLE
packet.GroupData['Charter'] = Charter # MVT_VARIABLE
packet.GroupData['ShowInList'] = ShowInList # MVT_BOOL
packet.GroupData['InsigniaID'] = uuid.UUID(str(InsigniaID)) # MVT_LLUUID
packet.GroupData['MembershipFee'] = MembershipFee # MVT_S32
packet.GroupData['OpenEnrollment'] = OpenEnrollment # MVT_BOOL
packet.GroupData['AllowPublish'] = AllowPublish # MVT_BOOL
packet.GroupData['MaturePublish'] = MaturePublish # MVT_BOOL
self.agent.region.enqueue_message(packet(), True)
if self.settings.HANDLE_PACKETS:
# enable the callback to watch for the CreateGroupReply packet
self.onCreateGroupReply_received = self.agent.packet_handler._register('CreateGroupReply')
self.onCreateGroupReply_received.subscribe(onCreateGroupReply, self)
else:
raise DataParsingError('Failed to create a group, please specify a name')
class Group(object):
""" representation of a group """
def __init__(self, AcceptNotices, GroupPowers, GroupID, GroupName, ListInProfile, Contribution, GroupInsigniaID):
self.AcceptNotices =AcceptNotices
self.GroupPowers = GroupPowers
self.GroupID = uuid.UUID(str(GroupID))
self.GroupName = GroupName
self.ListInProfile = ListInProfile
self.Contribution = Contribution
self.GroupInsigniaID = uuid.UUID(str(GroupInsigniaID))
class ChatterBoxInvitation_Message(object):
""" a group chat message sent over the event queue """
def __init__(self, session_name = None, from_name = None, session_id = None, _type = None, region_id = None, offline = None, timestamp = None, ttl = None, to_id = None, source = None, from_group = None, position = None, parent_estate_id = None, message = None, binary_bucket = None, _id = None, god_level = None, limited_to_estate = None, check_estate = None, agent_id = None, from_id = None, ChatterBoxInvitation_Data = None):
if ChatterBoxInvitation_Data != None:
self.session_name = ChatterBoxInvitation_Data['session_name']
self.from_name = ChatterBoxInvitation_Data['from_name']
self.session_id = uuid.UUID(str(ChatterBoxInvitation_Data['session_id']))
#self.from_name = ChatterBoxInvitation_Data['session_name']
self._type = ChatterBoxInvitation_Data['instantmessage']['message_params']['type']
self.region_id = uuid.UUID(str(ChatterBoxInvitation_Data['instantmessage']['message_params']['region_id']))
self.offline = ChatterBoxInvitation_Data['instantmessage']['message_params']['offline']
self.timestamp = ChatterBoxInvitation_Data['instantmessage']['message_params']['timestamp']
self.ttl = ChatterBoxInvitation_Data['instantmessage']['message_params']['ttl']
self.to_id = uuid.UUID(str(ChatterBoxInvitation_Data['instantmessage']['message_params']['to_id']))
self.source = ChatterBoxInvitation_Data['instantmessage']['message_params']['source']
self.from_group = ChatterBoxInvitation_Data['instantmessage']['message_params']['from_group']
self.position = ChatterBoxInvitation_Data['instantmessage']['message_params']['position']
self.parent_estate_id = ChatterBoxInvitation_Data['instantmessage']['message_params']['parent_estate_id']
self.message = ChatterBoxInvitation_Data['instantmessage']['message_params']['message']
self.binary_bucket = ChatterBoxInvitation_Data['instantmessage']['message_params']['data']['binary_bucket']
self._id = uuid.UUID(str(ChatterBoxInvitation_Data['instantmessage']['message_params']['id']))
#self.from_id = ChatterBoxInvitation_Data['instantmessage']['message_params']['from_id']
self.god_level = ChatterBoxInvitation_Data['instantmessage']['agent_params']['god_level']
self.limited_to_estate = ChatterBoxInvitation_Data['instantmessage']['agent_params']['limited_to_estate']
self.check_estate = ChatterBoxInvitation_Data['instantmessage']['agent_params']['check_estate']
self.agent_id = uuid.UUID(str(ChatterBoxInvitation_Data['instantmessage']['agent_params']['agent_id']))
self.from_id = uuid.UUID(str(ChatterBoxInvitation_Data['from_id']))
#self.message = ChatterBoxInvitation_Data['message']
self.name = 'ChatterBoxInvitation'
else:
self.session_name = session_name
self.from_name = from_name
self.session_id = session_id
#self.from_name = from_name
self._type = _type
self.region_id = region_id
self.offline = offline
self.timestamp = timestamp
self.ttl = ttl
self.to_id = to_id
self.source = source
self.from_group = from_group
self.position = position
self.parent_estate_id = parent_estate_id
self.message = message
self.binary_bucket = binary_bucket
self._id = _id
#self.from_id = from_id
self.god_level = god_level
self.limited_to_estate = limited_to_estate
self.check_estate = check_estate
self.agent_id = agent_id
self.from_id = from_id
#self.message = message
self.name = 'ChatterBoxInvitation'
# ~~~~~~~~~~~~~~~~~~
# Callback functions
# ~~~~~~~~~~~~~~~~~~
def onCreateGroupReply(packet, group_manager):
""" when we get a CreateGroupReply packet, log Success, and if True, request the group details. remove the callback in any case """
# remove the monitor
group_manager.onCreateGroupReply_received.unsubscribe(onCreateGroupReply, group_manager)
AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data
GroupID = packet.message_data.blocks['ReplyData'][0].get_variable('GroupID').data
Success = packet.message_data.blocks['ReplyData'][0].get_variable('Success').data
Message = packet.message_data.blocks['ReplyData'][0].get_variable('Message').data
if Success:
log(INFO, "Created group %s. Message data is: %s" % (GroupID, Message))
log(WARNING, "We now need to request the group data...")
else:
log(INFO, "Failed to create group due to: %s" % (Message))
'''
Groups related messages:
//-----------------------------------------------------------------------------
// Group messages
//-----------------------------------------------------------------------------
// CreateGroupRequest
// viewer -> simulator
// simulator -> dataserver
// reliable
{
CreateGroupRequest Low 339 NotTrusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ Name Variable 1 } // string
{ Charter Variable 2 } // string
{ ShowInList BOOL }
{ InsigniaID LLUUID }
{ MembershipFee S32 } // S32
{ OpenEnrollment BOOL } // BOOL (U8)
{ AllowPublish BOOL } // whether profile is externally visible or not
{ MaturePublish BOOL } // profile is "mature"
}
}
// CreateGroupReply
// dataserver -> simulator
// simulator -> viewer
// reliable
{
CreateGroupReply Low 340 Trusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
}
{
ReplyData Single
{ GroupID LLUUID }
{ Success BOOL }
{ Message Variable 1 } // string
}
}
// UpdateGroupInfo
// viewer -> simulator
// simulator -> dataserver
// reliable
{
UpdateGroupInfo Low 341 NotTrusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ Charter Variable 2 } // string
{ ShowInList BOOL }
{ InsigniaID LLUUID }
{ MembershipFee S32 }
{ OpenEnrollment BOOL }
{ AllowPublish BOOL }
{ MaturePublish BOOL }
}
}
// GroupRoleChanges
// viewer -> simulator -> dataserver
// reliable
{
GroupRoleChanges Low 342 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
{ GroupID LLUUID }
}
{
RoleChange Variable
{ RoleID LLUUID }
{ MemberID LLUUID }
{ Change U32 }
}
}
// JoinGroupRequest
// viewer -> simulator -> dataserver
// reliable
{
JoinGroupRequest Low 343 NotTrusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
}
}
// JoinGroupReply
// dataserver -> simulator -> viewer
{
JoinGroupReply Low 344 Trusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ Success BOOL }
}
}
// EjectGroupMemberRequest
// viewer -> simulator -> dataserver
// reliable
{
EjectGroupMemberRequest Low 345 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
}
{
EjectData Variable
{ EjecteeID LLUUID }
}
}
// EjectGroupMemberReply
// dataserver -> simulator -> viewer
// reliable
{
EjectGroupMemberReply Low 346 Trusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
}
{
EjectData Single
{ Success BOOL }
}
}
// LeaveGroupRequest
// viewer -> simulator -> dataserver
// reliable
{
LeaveGroupRequest Low 347 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
}
}
// LeaveGroupReply
// dataserver -> simulator -> viewer
{
LeaveGroupReply Low 348 Trusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ Success BOOL }
}
}
// InviteGroupRequest
// viewer -> simulator -> dataserver
// reliable
{
InviteGroupRequest Low 349 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID } // UUID of inviting agent
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
}
{
InviteData Variable
{ InviteeID LLUUID }
{ RoleID LLUUID }
}
}
// InviteGroupResponse
// simulator -> dataserver
// reliable
{
InviteGroupResponse Low 350 Trusted Unencoded
{
InviteData Single
{ AgentID LLUUID }
{ InviteeID LLUUID }
{ GroupID LLUUID }
{ RoleID LLUUID }
{ MembershipFee S32 }
}
}
// GroupProfileRequest
// viewer-> simulator -> dataserver
// reliable
{
GroupProfileRequest Low 351 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
}
}
// GroupProfileReply
// dataserver -> simulator -> viewer
// reliable
{
GroupProfileReply Low 352 Trusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ Name Variable 1 } // string
{ Charter Variable 2 } // string
{ ShowInList BOOL }
{ MemberTitle Variable 1 } // string
{ PowersMask U64 } // U32 mask
{ InsigniaID LLUUID }
{ FounderID LLUUID }
{ MembershipFee S32 }
{ OpenEnrollment BOOL } // BOOL (U8)
{ Money S32 }
{ GroupMembershipCount S32 }
{ GroupRolesCount S32 }
{ AllowPublish BOOL }
{ MaturePublish BOOL }
{ OwnerRole LLUUID }
}
}
// CurrentInterval = 0 => this period (week, day, etc.)
// CurrentInterval = 1 => last period
// viewer -> simulator -> dataserver
// reliable
{
GroupAccountSummaryRequest Low 353 NotTrusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
{ GroupID LLUUID }
}
{
MoneyData Single
{ RequestID LLUUID }
{ IntervalDays S32 }
{ CurrentInterval S32 }
}
}
// dataserver -> simulator -> viewer
// Reliable
{
GroupAccountSummaryReply Low 354 Trusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ GroupID LLUUID }
}
{
MoneyData Single
{ RequestID LLUUID }
{ IntervalDays S32 }
{ CurrentInterval S32 }
{ StartDate Variable 1 } // string
{ Balance S32 }
{ TotalCredits S32 }
{ TotalDebits S32 }
{ ObjectTaxCurrent S32 }
{ LightTaxCurrent S32 }
{ LandTaxCurrent S32 }
{ GroupTaxCurrent S32 }
{ ParcelDirFeeCurrent S32 }
{ ObjectTaxEstimate S32 }
{ LightTaxEstimate S32 }
{ LandTaxEstimate S32 }
{ GroupTaxEstimate S32 }
{ ParcelDirFeeEstimate S32 }
{ NonExemptMembers S32 }
{ LastTaxDate Variable 1 } // string
{ TaxDate Variable 1 } // string
}
}
// Reliable
{
GroupAccountDetailsRequest Low 355 NotTrusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
{ GroupID LLUUID }
}
{
MoneyData Single
{ RequestID LLUUID }
{ IntervalDays S32 }
{ CurrentInterval S32 }
}
}
// Reliable
{
GroupAccountDetailsReply Low 356 Trusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ GroupID LLUUID }
}
{
MoneyData Single
{ RequestID LLUUID }
{ IntervalDays S32 }
{ CurrentInterval S32 }
{ StartDate Variable 1 } // string
}
{
HistoryData Variable
{ Description Variable 1 } // string
{ Amount S32 }
}
}
// Reliable
{
GroupAccountTransactionsRequest Low 357 NotTrusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
{ GroupID LLUUID }
}
{
MoneyData Single
{ RequestID LLUUID }
{ IntervalDays S32 }
{ CurrentInterval S32 }
}
}
// Reliable
{
GroupAccountTransactionsReply Low 358 Trusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ GroupID LLUUID }
}
{
MoneyData Single
{ RequestID LLUUID }
{ IntervalDays S32 }
{ CurrentInterval S32 }
{ StartDate Variable 1 } // string
}
{
HistoryData Variable
{ Time Variable 1 } // string
{ User Variable 1 } // string
{ Type S32 }
{ Item Variable 1 } // string
{ Amount S32 }
}
}
// GroupActiveProposalsRequest
// viewer -> simulator -> dataserver
//reliable
{
GroupActiveProposalsRequest Low 359 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
}
{
TransactionData Single
{ TransactionID LLUUID }
}
}
// GroupActiveProposalItemReply
// dataserver -> simulator -> viewer
// reliable
{
GroupActiveProposalItemReply Low 360 Trusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ GroupID LLUUID }
}
{
TransactionData Single
{ TransactionID LLUUID }
{ TotalNumItems U32 }
}
{
ProposalData Variable
{ VoteID LLUUID }
{ VoteInitiator LLUUID }
{ TerseDateID Variable 1 } // string
{ StartDateTime Variable 1 } // string
{ EndDateTime Variable 1 } // string
{ AlreadyVoted BOOL }
{ VoteCast Variable 1 } // string
{ Majority F32 }
{ Quorum S32 }
{ ProposalText Variable 1 } // string
}
}
// GroupVoteHistoryRequest
// viewer -> simulator -> dataserver
//reliable
{
GroupVoteHistoryRequest Low 361 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
}
{
TransactionData Single
{ TransactionID LLUUID }
}
}
// GroupVoteHistoryItemReply
// dataserver -> simulator -> viewer
// reliable
{
GroupVoteHistoryItemReply Low 362 Trusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ GroupID LLUUID }
}
{
TransactionData Single
{ TransactionID LLUUID }
{ TotalNumItems U32 }
}
{
HistoryItemData Single
{ VoteID LLUUID }
{ TerseDateID Variable 1 } // string
{ StartDateTime Variable 1 } // string
{ EndDateTime Variable 1 } // string
{ VoteInitiator LLUUID }
{ VoteType Variable 1 } // string
{ VoteResult Variable 1 } // string
{ Majority F32 }
{ Quorum S32 }
{ ProposalText Variable 2 } // string
}
{
VoteItem Variable
{ CandidateID LLUUID }
{ VoteCast Variable 1 } // string
{ NumVotes S32 }
}
}
// StartGroupProposal
// viewer -> simulator -> dataserver
// reliable
{
StartGroupProposal Low 363 NotTrusted Zerocoded UDPDeprecated
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
ProposalData Single
{ GroupID LLUUID }
{ Quorum S32 }
{ Majority F32 } // F32
{ Duration S32 } // S32, seconds
{ ProposalText Variable 1 } // string
}
}
// GroupProposalBallot
// viewer -> simulator -> dataserver
// reliable
{
GroupProposalBallot Low 364 NotTrusted Unencoded UDPDeprecated
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
ProposalData Single
{ ProposalID LLUUID }
{ GroupID LLUUID }
{ VoteCast Variable 1 } // string
}
}
// TallyVotes userserver -> dataserver
// reliable
{
TallyVotes Low 365 Trusted Unencoded
}
// GroupMembersRequest
// get the group members
// simulator -> dataserver
// reliable
{
GroupMembersRequest Low 366 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ RequestID LLUUID }
}
}
// GroupMembersReply
// list of uuids for the group members
// dataserver -> simulator
// reliable
{
GroupMembersReply Low 367 Trusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ RequestID LLUUID }
{ MemberCount S32 }
}
{
MemberData Variable
{ AgentID LLUUID }
{ Contribution S32 }
{ OnlineStatus Variable 1 } // string
{ AgentPowers U64 }
{ Title Variable 1 } // string
{ IsOwner BOOL }
}
}
// used to switch an agent's currently active group.
// viewer -> simulator -> dataserver -> AgentDataUpdate...
{
ActivateGroup Low 368 NotTrusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
{ GroupID LLUUID }
}
}
// viewer -> simulator -> dataserver
{
SetGroupContribution Low 369 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
Data Single
{ GroupID LLUUID }
{ Contribution S32 }
}
}
// viewer -> simulator -> dataserver
{
SetGroupAcceptNotices Low 370 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
Data Single
{ GroupID LLUUID }
{ AcceptNotices BOOL }
}
{
NewData Single
{ ListInProfile BOOL }
}
}
// GroupRoleDataRequest
// viewer -> simulator -> dataserver
{
GroupRoleDataRequest Low 371 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ RequestID LLUUID }
}
}
// GroupRoleDataReply
// All role data for this group
// dataserver -> simulator -> agent
{
GroupRoleDataReply Low 372 Trusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ RequestID LLUUID }
{ RoleCount S32 }
}
{
RoleData Variable
{ RoleID LLUUID }
{ Name Variable 1 }
{ Title Variable 1 }
{ Description Variable 1 }
{ Powers U64 }
{ Members U32 }
}
}
// GroupRoleMembersRequest
// viewer -> simulator -> dataserver
{
GroupRoleMembersRequest Low 373 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
}
{
GroupData Single
{ GroupID LLUUID }
{ RequestID LLUUID }
}
}
// GroupRoleMembersReply
// All role::member pairs for this group.
// dataserver -> simulator -> agent
{
GroupRoleMembersReply Low 374 Trusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ GroupID LLUUID }
{ RequestID LLUUID }
{ TotalPairs U32 }
}
{
MemberData Variable
{ RoleID LLUUID }
{ MemberID LLUUID }
}
}
// GroupTitlesRequest
// viewer -> simulator -> dataserver
{
GroupTitlesRequest Low 375 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
{ GroupID LLUUID }
{ RequestID LLUUID }
}
}
// GroupTitlesReply
// dataserver -> simulator -> viewer
{
GroupTitlesReply Low 376 Trusted Zerocoded
{
AgentData Single
{ AgentID LLUUID }
{ GroupID LLUUID }
{ RequestID LLUUID }
}
{
GroupData Variable
{ Title Variable 1 } // string
{ RoleID LLUUID }
{ Selected BOOL }
}
}
// GroupTitleUpdate
// viewer -> simulator -> dataserver
{
GroupTitleUpdate Low 377 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
{ GroupID LLUUID }
{ TitleRoleID LLUUID }
}
}
// GroupRoleUpdate
// viewer -> simulator -> dataserver
{
GroupRoleUpdate Low 378 NotTrusted Unencoded
{
AgentData Single
{ AgentID LLUUID }
{ SessionID LLUUID }
{ GroupID LLUUID }
}
{
RoleData Variable
{ RoleID LLUUID }
{ Name Variable 1 }
{ Description Variable 1 }
{ Title Variable 1 }
{ Powers U64 }
{ UpdateType U8 }
}
}
// Request the members of the live help group needed for requesting agent.
// userserver -> dataserver
{
LiveHelpGroupRequest Low 379 Trusted Unencoded
{
RequestData Single
{ RequestID LLUUID }
{ AgentID LLUUID }
}
}
// Send down the group
// dataserver -> userserver
{
LiveHelpGroupReply Low 380 Trusted Unencoded
{
ReplyData Single
{ RequestID LLUUID }
{ GroupID LLUUID }
{ Selection Variable 1 } // selection criteria all or active
}
}
'''