libfolks
libfolks is a library that aggregates people from multiple sources (eg, Telepathy connection managers for IM contacts, evolution data server for local contacts, libsocialweb for web service contacts, etc.) to create metacontacts. It's written in Vala (in part to evaluate Vala). The initial goal is for GObject/C support, though the Vala bindings should basically automatic.
libfolks is under heavy development and not yet API/ABI-stable.
Source
Reference Documentation
Debugging
The main way to debug libfolks (or applications using it) is using the FOLKS_DEBUG environment variable. For example, to collect a log file of all libfolks debug data from Empathy, use the command:
FOLKS_DEBUG_NO_COLOUR=1 FOLKS_DEBUG=all empathy &> folks.log
Available values for the FOLKS_DEBUG environment variable are:
- “all” (equivalent to listing all possible values)
- “folks” (for the core of libfolks)
- “eds” (for the evolution-data-server backend)
- “key-file” (for the key file backend)
- “libsocialweb” (for the libsocialweb backend)
- “telepathy” (for the Telepathy backend)
- “tracker” (for the Tracker backend)
Multiple values can be specified using commas, e.g.: FOLKS_DEBUG=folks,eds,key-file
Another way to debug libfolks itself is to run the folks-inspect utility which is bundled with libfolks (possibly in a utils or tools package, depending on your distribution). Its use is beyond the scope of this page, but it has a “help” command which should serve as an introduction.
Finally, libfolks has a status printing mechanism. Some libfolks clients may expose this as part of their own debug functionality (for example, folks-inspect uses this for its “debug” command), but it can be invoked more generally using gdb:
- Run the libfolks client you wish to debug under gdb.
- Break execution at a suitable (for example, once you've got the client into an erroneous state you wish to examine).
- At gdb's command prompt, enter the following commands:
set $folks_debug = folks_debug_dup() print folks_debug_emit_print_status($folks_debug)
This will print out a listing of the state of all the objects relevant to libfolks' linking decisions.
Finally, libfolks outputs debug and status information using terminal colours and formatting by default. If this isn't desired, set the FOLKS_DEBUG_NO_COLOUR environment variable.
Architecture
Some of this architecture has yet to be implemented.
Concepts
See also: Folks/Glossary
The core of folks is Folks.Individual. An Individual is meant to represent a person, and contains metadata from one or more contact sources (e.g. the Gabble Jabber connection manager, a local addressbook). Individuals contain one or more Personas, which are a subset of a person's metadata (as exposed by a contact source). These Personas form an unordered set. The Individual object will expose the sum of all n-ary attributes (e.g. e-mail addresses) from all contained Personas and will expose a single value for the attribute from amongst the Personas (according some some attribute-specific heuristic) for unary attributes (e.g. alias, avatar).
For example, an Individual's alias is chosen from its Personas by preferring aliases which are set (Personas don't necessarily have to implement Folks.Alias, or have a non-null alias set) and are not equal to the Persona's display ID (e.g. set to their IM address as a default). The aliases from writeable PersonaStores are preferred to those from other PersonaStores.
Currently, all backends except the key-file backend are read-only. The key-file backend is writeable, which allows for linking of Personas from other backends by creating a Kf.Persona containing linkable properties which can be matched against the Personas being linked together. There is only ever one writeable PersonaStore; libfolks does not do synchronisation, since that can only ever go wrong.
Because Individuals are basically just a set of Personas, it is possible to both link and unlink contacts.
Personas are linked using common fields; the single "blessed" writeable PersonaStore (i.e. the key-file backend's only PersonaStore) returns Personas with fields containing the UIDs of all the other Personas which are linked to that Persona. The IndividualAggregator then assembles Individuals from the Personas whose UIDs are are linked from the blessed PersonaStore.
For example, there are two PersonaStores: Telepathy and a blessed key file PersonaStore. The key file contains the following, which is exposed as a Persona:
[IndividualID]
jabber=foo@jabber.org
msn=bla@hotmail.comThe Telepathy backend exposes these two Personas:
Persona with uid = jabber:foo@jabber.org Persona with uid = msn:bla@hotmail.com
Since their UIDs are referenced by a Persona in blessed key file PersonaStore, the IndividualAggregator links the two Personas to form an Individual.
This linking can work on other fields from other PersonaStores. For example, if a verified e-mail address was provided by a Persona from a Facebook backend, that could be used to link Personas (by setting the "im-addresses" property from the Folks.IMable interface as a linkable property). This is only possible for Personas which come from "trusted" PersonaStores since, for example, a malicious user could otherwise set their Jabber address on Facebook to someoneelse@jabber.org and hijack people's contact lists; or someone could impersonate someone else's link-local XMPP account by changing their hostname and username (or just using hacked IM software). PersonaStores can either be completely untrusted (e.g. a link-local XMPP PersonaStore); can have their UIDs trusted, but no other properties (e.g. a Jabber PersonaStore); or can have all their properties trusted (e.g. the key-file backend's PersonaStore).
Classes
- Folks.Individual : GLib.Object, Folks.Alias, Folks.Avatar, Folks.Favourite, Folks.Groups, Folks.IMable, Folks.Presence
- represents a person
- based upon one or more Folks.Personas (in no specific order)
- the attributes presented will be, in general, the union of the attributes from all contained Personas (for n-ary attributes) and selected from the contained Personas by some heuristic specific to the attribute
- this will be one of the few classes client applications should need to care about
Folks.IndividualAggregator : GLib.Object
instantiates all the known PersonaStores (i.e. one for each valid TpAccount, one for each other type of account (e.g. e-d-s addressbook))
- assembles and notifies about Individuals from the pool of Personas
- this will be one of the few classes client applications should need to care about
- abstract Folks.Persona : GLib.Object
represents a "shard" of a person from a single source (e.g. xmpp://foo@jabber.org, evolution data server)
- in most cases (e.g. Telepathy CMs, Facebook), these will be read-only
- meant to be private inside libfolks (not currently, though)
- Tpf.Persona : Folks.Persona, Folks.Alias, Folks.Avatar, Folks.Favourite, Folks.Groups, Folks.IMable, Folks.Presence
a Persona wrapper of TpContact
- meant to be private inside libfolks (not currently, though)
abstract Folks.PersonaStore : GLib.Object
- produces Folks.Personas for a given source
Tpf.PersonaStore : Folks.PersonaStore
- a wrapper for a Telepathy CM / Connection's contact list channels
- meant to be private inside libfolks (not currently, though)
Interfaces
- interface Folks.Alias
- provides an "alias" property
- interface Folks.Avatar
- essentially the Telepathy Avatars interface
- interface Folks.Favourite
- allows objects to be marked as "favourites"
- interface Folks.Groups
- provides simple string-based grouping of similar objects
- interface Folks.IMable
- provides a map of IM protocol to a list of IM addresses the object owns on that protocol
- interface Folks.Presence
- provides a presence type, status, and status message
Roadmap
See the roadmap page.
Bindings
See QtFolks

