diff --git a/fbchat/models.py b/fbchat/models.py index 770299b..e9e8167 100644 --- a/fbchat/models.py +++ b/fbchat/models.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import aenum +from string import Formatter class FBchatException(Exception): @@ -219,6 +220,52 @@ class Message(object): def __unicode__(self): return ''.format(self.uid, repr(self.text), self.mentions, self.emoji_size, self.attachments) + @classmethod + def formatMentions(cls, text, *args, **kwargs): + """Like `str.format`, but takes tuples with a thread id and text instead. + + Returns a `Message` object, with the formatted string and relevant mentions. + + ``` + >>> Message.formatMentions("Hey {!r}! My name is {}", ("1234", "Peter"), ("4321", "Michael")) + , ] emoji_size=None attachments=[]> + + >>> Message.formatMentions("Hey {p}! My name is {}", ("1234", "Michael"), p=("4321", "Peter")) + , ] emoji_size=None attachments=[]> + ``` + """ + result = "" + mentions = list() + offset = 0 + f = Formatter() + field_names = [field_name[1] for field_name in f.parse(text)] + automatic = '' in field_names + i = 0 + + for (literal_text, field_name, format_spec, conversion) in f.parse(text): + offset += len(literal_text) + result += literal_text + + if field_name is None: continue + + if field_name == '': + field_name = str(i) + i += 1 + elif automatic and field_name.isdigit(): + raise ValueError("cannot switch from automatic field numbering to manual field specification") + + thread_id, name = f.get_field(field_name, args, kwargs)[0] + + if format_spec: name = f.format_field(name, format_spec) + if conversion: name = f.convert_field(name, conversion) + + result += name + mentions.append(Mention(thread_id=thread_id, offset=offset, length=len(name))) + offset += len(name) + + message = cls(text=result, mentions=mentions) + return message + class Attachment(object): #: The attachment ID uid = None