-
Notifications
You must be signed in to change notification settings - Fork 2
Permanent Memory
Otherwise known as permamem, this framework feature stores data on all conversations and users the bot encounters.
It is intended as a workaround for some of the known limitations (forgotten users/conversations) of the current version of the hangups library.
Other names: convmem
The bot stores a persistent memory of all conversations in memory.json
under the key convmem
.
The memory of each conversation is updated each time the bot is run and for every event that occurs during the bot's operation.
The structure of the "convmem" is directly accessible via bot.conversations.catalog
, and is as follows:
bot.conversations.catalog = bot.memory["convmem"] = {
'<conversation id>' : {
"source": "init", # or event
"title": "<conversation title>",
"type": "GROUP", # or ONE_TO_ONE
"updated": "20150101000000",
"participants": [
"<user chat id>",
"<user chat id>",
"<user chat id>"
},
'<conversation id>' : { ... }
}
The hangups User object is also cached in the user_data
key in memory.json
.
These records are updated each time a conversation event occurs, if there are any changes in the user list and/or individual user attributes.
bot.memory["user_data"]["<user chat id>"]["_hangups"] = {
"chat_id": "<user chat id>",
"gaia_id": "<user gaia id>",
"first_name": "<user first name>",
"full_name": "<user full name>",
"emails": [
"<user email 1>"
], # or []
"photo_url": "<user photo url>", # or null
"is_self": false, # true for bot account
"is_definitive": false, # true if canonical record from API query or hangups
"updated": "20150101000000",
}
bot.conversations.get([<convfilter>])
Hint: You can use convfilter
from CONVID Commands to test this function
-
<convfilter>
can be:-
id:<convid>
or<convid>
- returns single matching conversation -
text:<text fragment>
- return conversations with matching fragment in title -
""
(or not supplied) - returns all conversations (no filter) -
chat_id:<chatid>
- returns conversations wherechatid
is a participant -
[ver>=2.7]
tag:<conversation tag>
- returns conversations with matching tag -
[ver>=2.7]
type:ONE_TO_ONE
ortype:GROUP
- returns conversations matching type (case-insensitive) -
[ver>=2.7]
minusers:<num>
- returns conversations with at least<num>
users -
[ver>=2.7]
maxusers:<num>
- returns conversations with at most<num>
users -
[ver>=2.7]
random:<float>
- returns conversations based on random selection criteria:random.random()
generates numbers in range[0.0, 1.0)
, if the generated number is lower or equal to<float>
the conversation will be added
-
-
[ver>=2.7]
supports multiple filter terms with sequential boolean operations- each term must be enclosed in brackets
- supported boolean operators:
and
,or
- returns a filtered conversation catalog based on
<convfilter>
`- the return is always a
{dictionary}
indexed by`convid`
- the return is always a
# data retrieval examples
## single conversation returned
[(convid, convdata)] = bot.conversations.get(<conversation id>).items()
[convdata] = bot.conversations.get(<conversation id>).values()
## multiple conversations returned
for convid, convdata in bot.conversations.get("text:something").items():
# ...do something
bot.conversations.get("(text:bot)and(tag:test-tag)")
# returns conversations with "bot" in title AND tagged "test-tag"
bot.conversations.get("(text:bot)or(chat_id:111111)")<br />
# returns conversations with "bot" in title OR has user 111111
bot.conversations.get_name(<conv|conv id>, truncate=False, fallback_string=None)
- drop-in replacement for
hangups.ui.utils.get_conv_name
- truncate will always be
False
and serves no purpose except to provide compatibility forhangups.ui.utils.get_conv_name(conv, truncate=True)
usage - internally, no truncation will occur - returns the conversation name for the given conversation object or id
- if
conv
(hangups Conversation object) is supplied:- try to get title from from permanent memory; otherwise,
- get it via
permamem.name_from_hangups_conversation()
, which is a custom adaptation ofhangups.ui.utils.get_conv_name
without the presentation logic
- if
conv id
(conversation id) is supplied:- try and get title from permanent memory; otherwise,
- return
fallback_string
if provided, or raise aValueError
exception
bot.get_users_in_conversation(<conversation id|[list of conversation ids]>)
- returns a list of unique hangups.user.User for the given conversation id(s)
- the user list is derived from two sources:
-
bot.conversations.catalog
- always complete
- basic fields only:
id_.chat_id
,id_.gaia_id
,full_name
,is_self
-
bot._user_list._user_dict
- if available, overwrites the incomplete entry derived from
bot.conversations.catalog
- incomplete for less active users
- additional fields:
emails
,photo url
,first_name
- if available, overwrites the incomplete entry derived from
- each user object in the list will always have the following values set properly:
id_.chat_id
,id_.gaia_id
,full_name
,is_self
- never returns the bot's own user details, please see
bot.user_self()
bot.get_hangups_user(<string chat_id|namedtuple hangups.user.UserID>)
- implements workaround for unreliable hangups user list (related to forgotten conversation bug)
- returns a single hangups.user.User for the supplied parameter(s)
- tries hangups-based
bot._user_list
first and will re-construct thehangups.user.User
object from permanent conversation memory if not found. if the user still cannot be found, will return a user with name "unknown user" - the user object will always have the following values set properly:
id_.chat_id
,id_.gaia_id
,full_name
,is_self
- depending on the source the user object may also have the following fields set correctly:
emails
,photo url
,first_name
bot.get_hangups_conversation(<string conv_id|hangups.conversation.Conversation>)
- implements workaround for unreliable hangups conversations list (related to forgotten conversation bug)
- returns a single HangupsConversation instance that inherits from hangups.conversation.Conversation
- the returned object is re-built from permanent conversation memory, with additional data cloned from the hangups-based
bot._conv_list
when available - it is intended to be a reliable substitute for an actual instance ofhangups.conversation.Conversation
via duck-typing- the
_user_list
of this derivative object is instantiated as a blank list - the users property has been overridden to directly support permanent user memory. Thus this object has a more complete user list than hangups itself
- the
- it is highly-recommended to use this functionality instead of attempting to
bot._conv_list.get()
, which usually results in general pain and confusion ;)
[ver<2.7]
Requires plugin: unittest_convmem, [ver>=2.7]
no plugin dependency
Helper commands for permamem that can be used to perform some diagnostics and permanent memory manipulation.
All these commands are admin-only.
/bot dumpunknownusers
- prints cached users marked as unknown but definitive
- command maintained mostly for historical purposes - the bot will mark unknown or fallback users as indefinite
/bot resetunknownusers
- removes the
is_definitive
flag from cached but unknown users - command maintained mostly for historical purposes - the bot will mark unknown or fallback users as indefinite
/bot refreshusermemory <chat id> [<chat id> [...]]
- attempts to update the designated chat id(s) with the results of
contact/getentitybyid
/bot removeconvrecord <convid> [<convid> [...]]
- permanently removes conv record in memory (until next update)
- use if you a stray conversation data hanging around in
memory.json
even though the bot has previously left the conversation
/bot makeallusersindefinite
- makes all cached user records indefinite (sets
is_definite = False
) - command maintained mostly for historical purposes - the bot will mark unknown or fallback users as indefinite
- use with care - it will take time to rebuild the user list again
Plugin List | Developer Reference: [ Intro | Plugins | Sinks | In-built Functionality | [Configuration] (Configuration) ]