Open not-so-smart opened 2 years ago
some of these data structures are very repetitive so I've condensed some common types into interfaces
for example, any User
object will have two fields: id
and nickname
User {
id: number;
nickname: string;
}
any other common types will be at the end of each section
bot.add
{
type: "bot.add",
data: {
user: User,
bot: string,
},
}
bot.del
{
type: "bot.del",
data: {
user: User,
bot: string,
},
}
calendar.event.created
{
type: "calendar.event.created",
data: {
event: {
id: string,
name: string,
},
url: string,
user: UserWeird,
},
}
user
- this strange User object uses a string
instead of a number
for the ID for some reason
UserWeird {
id: string,
nickname: string,
}
calendar.event.starting
{
type: "calendar.event.starting",
data: {
event_name: string,
minutes: string,
},
}
calendar.event.user.going
{
type: "calendar.event.user.going",
data: CalendarEventUserData,
}
calendar.event.user.not_going
{
type: "calendar.event.user.not_going",
data: CalendarEventUserData,
}
calendar.event.user.undecided
{
type: "calendar.event.user.undecided",
data: CalendarEventUserData,
}
all of the above use the same data structure
CalendarEventUserData {
event: {
id: string,
name: string,
},
user: UserWeird,
}
TODO: there's almost certainly a "change owner" event in here but I don't feel like finding a sample for it also, is it possible to remove a group from a directory? if so then there's probably an event for that too
group.added_to_directory
{
type: "group.added_to_directory",
data: {
user: User,
directory_name: string,
},
}
group.avatar_change
{
type: "group.avatar_change",
data: {
user: User,
avatar_url: string,
},
}
group.like_icon_set
{
type: "group.like_icon_set",
data: {
user: User,
like_icon: {
pack_id: number,
pack_index: number,
type: string,
},
},
}
group.name_change
{
type: "group.name_change",
data: {
user: User,
name: string,
},
}
group.office_mode_disabled
{
type: "group.office_mode_disabled",
data: {
user: User,
},
}
group.office_mode_enabled
{
type: "group.office_mode_enabled",
data: {
user: User,
},
}
group.role_change_admin
{
type: "group.role_change_admin",
data: {
user: User,
role: "admin",
member: User,
},
}
group.theme_change
{
type: "group.theme_change",
data: {
user: User,
theme_name: string,
},
}
group.topic_change
{
type: "group.topic_change",
data: {
user: User,
topic: string,
},
}
group.type_change
{
type: "group.type_change",
data: {
user: User,
type: string,
},
}
membership.announce.added
{
type: "membership.announce.added",
data: {
added_users: User[],
adder_user: User,
},
}
membership.announce.joined
{
type: "membership.announce.joined",
data: {
user: User,
},
}
membership.announce.rejoined
{
type: "membership.announce.rejoined",
data: {
user: User,
},
}
membership.avatar_changed
{
type: "membership.avatar_changed",
data: {
user: User,
avatar_url: string,
},
}
membership.nickname_changed
{
type: "membership.nickname_changed",
data: {
user: User,
name: string,
},
}
membership.notifications.autokicked
{
type: "membership.notifications.autokicked",
data: {
user: User,
},
}
membership.notifications.exited
{
type: "membership.notifications.exited",
data: {
removed_user: User,
},
}
membership.notifications.removed
{
type: "membership.notifications.removed",
data: {
remover_user: User,
removed_user: User,
},
}
more like "message" cuz still no edit/pin
message.deleted
{
type: "message.deleted",
data: {
message_id: string,
deleted_at: number,
deletion_actor: "sender",
deleter_id: string,
},
}
deletion_actor
- this is always "sender" for now
poll.created
{
type: "poll.created",
data: {
conversation: {
id: string,
},
poll: {
id: string,
subject: string,
},
user: UserWeird,
},
}
user
- this strange User object uses a string
instead of a number
for the ID for some reason
UserWeird {
id: string,
nickname: string,
}
poll.reminder
{
type: "poll.reminder",
data: {
conversation: {
id: string,
},
poll: {
expiration: number,
id: string,
subject: string,
},
},
}
poll.finished
{
type: "poll.finished",
data: {
conversation: {
id: string,
},
options: Option[],
poll: {
id: string,
subject: string,
},
},
}
options
- an array of objects, each following the format:
Option {
id: string,
title: string,
votes?: number,
voter_ids?: string[],
}
options[i].votes
- (optional) may be missingoptions[i].voter_ids
- (optional) may be missingvotes
for anonymous polls or voter_ids
for open pollsMessages
more like "message" cuz still no edit/pin
message.deleted
{ type: "message.deleted", data: { message_id: string, deleted_at: number, deletion_actor: "sender", deleter_id: string, }, }
deletion_actor
- this is always "sender" for now
- at some point, admins/owner will (maybe) be able to delete other users' messages
the deletion_actor
can also be system
when GroupMe steps in to remove messages due to abuse
however, the deleter_id
remains unchanged. You would think it gets set to system
or null
but instead it just stays as the author's ID
Polls
poll.finished
{ type: "poll.finished", data: { conversation: { id: string, }, options: Option[], poll: { id: string, subject: string, }, }, }
options
- an array of objects, each following the format:
Option { id: string, title: string, votes?: number, voter_ids?: string[], }
options[i].votes
- (optional) may be missing
options[i].voter_ids
- (optional) may be missingTODO: my theory is that one of these is always present -- either
votes
for anonymous polls orvoter_ids
for open pollshowever I don't feel like checking this so further research is needed
votes
is always present (regardless of type/visibility) UNLESS the option has 0 votes, in which case it is omitted entirely.
voter_ids
is also present alongside votes
if the poll's visibility is set to public
.
However, if the option has 0 votes, both votes
and voter_ids
fields are omitted.
Not to be confused with Calendar Events Events are things that happen in Groups on GroupMe. When an Event happens, a Message is emitted. The message has a top-level
event
property containing an Event object.event
object structure:type
is the name of the event type.data
is an object containing information about the event.To make things even more confusing, certain Group Events correspond to Calendar Events. If the Event is related to a Calendar Event, the Message will have an Attachment of type
event
(described below)event
attachment structure:view
is always either "brief" or "full".calendar.event.created
events, and "brief" is used for all other Calendar events.event_id
is a UUID string.I analyzed a bunch of messages from a large group and found these event types. (Sample: 80,000 messages from 1 group, August 2020-August 2021)
bot.add
bot.del
calendar.event.created
calendar.event.starting
calendar.event.user.going
calendar.event.user.not_going
calendar.event.user.undecided
group.added_to_directory
group.avatar_change
group.like_icon_set
group.name_change
group.office_mode_disabled
group.office_mode_enabled
group.role_change_admin
group.theme_change
group.topic_change
group.type_change
membership.announce.added
membership.announce.joined
membership.announce.rejoined
membership.avatar_changed
membership.nickname_changed
membership.notifications.autokicked
membership.notifications.exited
membership.notifications.removed
message.deleted
poll.created
poll.finished
poll.reminder
There could easily be more, but these are the ones I found in my sample. I think this should be enough for a starting point for a new doc page. The corresponding data object structures for each type will be a pain to document... I'll start posting examples in the comments