mirror of
https://github.com/deltachat/deltachat-core.git
synced 2025-10-04 18:29:19 +02:00
improve docs and structure
see online snapshot: https://m.devpi.net/hpk/dev/deltachat/0.5.dev0/+doc/index.html
This commit is contained in:
parent
099306408e
commit
8683de19e3
11 changed files with 253 additions and 213 deletions
1
python/.gitignore
vendored
Normal file
1
python/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
doc/_build/
|
3
python/doc/_templates/globaltoc.html
vendored
3
python/doc/_templates/globaltoc.html
vendored
|
@ -4,7 +4,8 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ pathto('index') }}">Home</a></li>
|
<li><a href="{{ pathto('index') }}">Home</a></li>
|
||||||
<li><a href="{{ pathto('install') }}">Install</a></li>
|
<li><a href="{{ pathto('install') }}">Install</a></li>
|
||||||
<li><a href="{{ pathto('api') }}">API Documentation</a></li>
|
<li><a href="{{ pathto('api') }}">High level API</a></li>
|
||||||
|
<li><a href="{{ pathto('capi') }}">Low level API</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<b>External Links:</b>
|
<b>External Links:</b>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
2
python/doc/_templates/sidebarintro.html
vendored
2
python/doc/_templates/sidebarintro.html
vendored
|
@ -1,4 +1,4 @@
|
||||||
<h3>deltachat {{release}}</h3>
|
<h3>deltachat {{release}}</h3>
|
||||||
<p>
|
<p>
|
||||||
Bindings for <a href="https://delta.chat">Delta.chat</a>
|
<a href="https://delta.chat">Delta.chat</a> Python Bindings
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
|
|
||||||
deltachat API Reference
|
deltachat high level API Reference
|
||||||
==============================
|
===================================
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This API is work in progress and may change in versions prior to 1.0.
|
||||||
|
|
||||||
.. autosummary::
|
.. autosummary::
|
||||||
|
|
||||||
deltachat.account
|
deltachat.account
|
||||||
|
deltachat.chatting
|
||||||
|
|
||||||
account module
|
account module
|
||||||
--------------
|
--------------
|
||||||
|
@ -12,3 +17,10 @@ account module
|
||||||
.. automodule:: deltachat.account
|
.. automodule:: deltachat.account
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
chatting module
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. automodule:: deltachat.chatting
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
7
python/doc/capi.rst
Normal file
7
python/doc/capi.rst
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
Low Level API Reference
|
||||||
|
===================================
|
||||||
|
|
||||||
|
.. automodule:: deltachat.capi.lib
|
||||||
|
:members:
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
deltachat: e-mail messaging/chatting API / deltachat-core C lib bindings
|
DeltaChat Python Bindings
|
||||||
========================================================================
|
=========================
|
||||||
|
|
||||||
.. include:: links.rst
|
The deltachat package provides two bindings for the core C-library
|
||||||
|
of the https://delta.chat messaging ecosystem:
|
||||||
|
|
||||||
The deltachat library provides interfaces into the core
|
- :doc:`capi` is a lowlevel CFFI-binding to the
|
||||||
C-library for https://delta.chat:
|
`deltachat-core C-API <https://deltachat.github.io/api/index.html>`_.
|
||||||
|
|
||||||
- **low level bindings to deltachat-core**: ``deltachat.capi.lib`` exposes
|
- :doc:`api` [work-in-progress] is a high level interface to deltachat-core which aims
|
||||||
a CFFI-interface to the `deltachat-core C-API <https://deltachat.github.io/api/index.html>`.
|
to be memory safe and thoroughly tested through continous tox/pytest runs.
|
||||||
|
|
||||||
- **higher level bindings**: :class:`deltachat.Account` serves as a high
|
|
||||||
level object through which you can configure, send and receive messages,
|
|
||||||
create and manage groups.
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
@ -22,6 +20,7 @@ Getting started
|
||||||
install
|
install
|
||||||
getting-started
|
getting-started
|
||||||
api
|
api
|
||||||
|
capi
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:hidden:
|
:hidden:
|
||||||
|
|
4
python/liveconfig.txt
Normal file
4
python/liveconfig.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
addr=test1@hq5.merlinux.eu mail_pw=CzCw6oV4w7WPkTy7BHn8OmC2Vak/
|
||||||
|
addr=test2@hq5.merlinux.eu mail_pw=J/fegsglkjJyXFncgn5MAg5t8pAq
|
||||||
|
addr=test3@hq5.merlinux.eu mail_pw=supersimplespasswort1
|
||||||
|
addr=test4@hq5.merlinux.eu mail_pw=supersimplespasswort2
|
|
@ -2,7 +2,6 @@ from deltachat import capi
|
||||||
from deltachat.capi import ffi
|
from deltachat.capi import ffi
|
||||||
from deltachat.account import Account # noqa
|
from deltachat.account import Account # noqa
|
||||||
|
|
||||||
|
|
||||||
__version__ = "0.5.dev0"
|
__version__ = "0.5.dev0"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
""" Delta.Chat high level API objects. """
|
""" Delta.Chat Account class. """
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import threading
|
import threading
|
||||||
|
@ -12,192 +12,11 @@ except ImportError:
|
||||||
|
|
||||||
import deltachat
|
import deltachat
|
||||||
from . import capi
|
from . import capi
|
||||||
|
from .cutil import convert_to_bytes_utf8, ffi_unicode, iter_array_and_unref
|
||||||
from .capi import ffi, lib
|
from .capi import ffi, lib
|
||||||
from .types import cached_property, property_with_doc
|
|
||||||
import attr
|
import attr
|
||||||
from attr import validators as v
|
from attr import validators as v
|
||||||
|
from .chatting import Contact, Chat, Message
|
||||||
|
|
||||||
@attr.s
|
|
||||||
class EventHandler(object):
|
|
||||||
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
|
|
||||||
|
|
||||||
def read_url(self, url):
|
|
||||||
try:
|
|
||||||
r = requests.get(url)
|
|
||||||
except requests.ConnectionError:
|
|
||||||
return ''
|
|
||||||
else:
|
|
||||||
return r.content
|
|
||||||
|
|
||||||
def dc_event_http_get(self, data1, data2):
|
|
||||||
url = data1
|
|
||||||
content = self.read_url(url)
|
|
||||||
if not isinstance(content, bytes):
|
|
||||||
content = content.encode("utf8")
|
|
||||||
# we need to return a fresh pointer that the core owns
|
|
||||||
return capi.lib.dupstring_helper(content)
|
|
||||||
|
|
||||||
def dc_event_is_offline(self, data1, data2):
|
|
||||||
return 0 # always online
|
|
||||||
|
|
||||||
|
|
||||||
class EventLogger:
|
|
||||||
def __init__(self, dc_context, logid=None, debug=True):
|
|
||||||
self.dc_context = dc_context
|
|
||||||
self._event_queue = Queue()
|
|
||||||
self._debug = debug
|
|
||||||
if logid is None:
|
|
||||||
logid = str(self.dc_context).strip(">").split()[-1]
|
|
||||||
self.logid = logid
|
|
||||||
self._timeout = None
|
|
||||||
|
|
||||||
def __call__(self, evt_name, data1, data2):
|
|
||||||
self._log_event(evt_name, data1, data2)
|
|
||||||
self._event_queue.put((evt_name, data1, data2))
|
|
||||||
|
|
||||||
def set_timeout(self, timeout):
|
|
||||||
self._timeout = timeout
|
|
||||||
|
|
||||||
def get(self, timeout=None, check_error=True):
|
|
||||||
timeout = timeout or self._timeout
|
|
||||||
ev = self._event_queue.get(timeout=timeout)
|
|
||||||
if check_error and ev[0] == "DC_EVENT_ERROR":
|
|
||||||
raise ValueError("{}({!r},{!r})".format(*ev))
|
|
||||||
return ev
|
|
||||||
|
|
||||||
def get_matching(self, event_name_regex):
|
|
||||||
rex = re.compile("(?:{}).*".format(event_name_regex))
|
|
||||||
while 1:
|
|
||||||
ev = self.get()
|
|
||||||
if rex.match(ev[0]):
|
|
||||||
return ev
|
|
||||||
|
|
||||||
def _log_event(self, evt_name, data1, data2):
|
|
||||||
if self._debug:
|
|
||||||
t = threading.currentThread()
|
|
||||||
tname = getattr(t, "name", t)
|
|
||||||
print("[{}-{}] {}({!r},{!r})".format(
|
|
||||||
tname, self.logid, evt_name, data1, data2))
|
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
|
||||||
class Contact(object):
|
|
||||||
""" Delta-Chat Contact. You obtain instances of it through the :class:`Account`.
|
|
||||||
|
|
||||||
:ivar id: integer id of this chat.
|
|
||||||
"""
|
|
||||||
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
|
|
||||||
id = attr.ib(validator=v.instance_of(int))
|
|
||||||
|
|
||||||
@cached_property # only get it once because we only free it once
|
|
||||||
def dc_contact_t(self):
|
|
||||||
return capi.lib.dc_get_contact(self.dc_context, self.id)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if lib is not None and hasattr(self, "_property_cache"):
|
|
||||||
lib.dc_contact_unref(self.dc_contact_t)
|
|
||||||
|
|
||||||
@property_with_doc
|
|
||||||
def addr(self):
|
|
||||||
""" normalized e-mail address for this account. """
|
|
||||||
return ffi_unicode(capi.lib.dc_contact_get_addr(self.dc_contact_t))
|
|
||||||
|
|
||||||
@property_with_doc
|
|
||||||
def display_name(self):
|
|
||||||
""" display name for this contact. """
|
|
||||||
return ffi_unicode(capi.lib.dc_contact_get_display_name(self.dc_contact_t))
|
|
||||||
|
|
||||||
def is_blocked(self):
|
|
||||||
""" Return True if the contact is blocked. """
|
|
||||||
return capi.lib.dc_contact_is_blocked(self.dc_contact_t)
|
|
||||||
|
|
||||||
def is_verified(self):
|
|
||||||
""" Return True if the contact is verified. """
|
|
||||||
return capi.lib.dc_contact_is_verified(self.dc_contact_t)
|
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
|
||||||
class Chat(object):
|
|
||||||
""" Chat object which manages members and through which you can send and retrieve messages.
|
|
||||||
"""
|
|
||||||
|
|
||||||
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
|
|
||||||
id = attr.ib(validator=v.instance_of(int))
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def dc_chat_t(self):
|
|
||||||
return capi.lib.dc_get_chat(self.dc_context, self.id)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if lib is not None and hasattr(self, "_property_cache"):
|
|
||||||
lib.dc_chat_unref(self.dc_chat_t)
|
|
||||||
|
|
||||||
def is_deaddrop(self):
|
|
||||||
""" return true if this chat is a deaddrop chat. """
|
|
||||||
return self.id == lib.DC_CHAT_ID_DEADDROP
|
|
||||||
|
|
||||||
def send_text_message(self, msg):
|
|
||||||
""" send a text message and return the resulting Message instance.
|
|
||||||
|
|
||||||
:param msg: unicode text
|
|
||||||
:returns: the resulting :class:`Message` instance
|
|
||||||
"""
|
|
||||||
msg = convert_to_bytes_utf8(msg)
|
|
||||||
print ("chat id", self.id)
|
|
||||||
msg_id = capi.lib.dc_send_text_msg(self.dc_context, self.id, msg)
|
|
||||||
return Message(self.dc_context, msg_id)
|
|
||||||
|
|
||||||
def get_messages(self):
|
|
||||||
""" return list of messages in this chat.
|
|
||||||
|
|
||||||
:returns: list of :class:`Message` objects for this chat.
|
|
||||||
"""
|
|
||||||
dc_array_t = lib.dc_get_chat_msgs(self.dc_context, self.id, 0, 0)
|
|
||||||
return list(iter_array_and_unref(dc_array_t, lambda x: Message(self.dc_context, x)))
|
|
||||||
|
|
||||||
def count_fresh_messages(self):
|
|
||||||
""" return number of fresh messages in this chat.
|
|
||||||
|
|
||||||
:returns: number of fresh messages
|
|
||||||
"""
|
|
||||||
return lib.dc_get_fresh_msg_cnt(self.dc_context, self.id)
|
|
||||||
|
|
||||||
def mark_noticed(self):
|
|
||||||
""" mark all messages in this chat as noticed.
|
|
||||||
|
|
||||||
Noticed messages are no longer fresh.
|
|
||||||
"""
|
|
||||||
return lib.dc_marknoticed_chat(self.dc_context, self.id)
|
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
|
||||||
class Message(object):
|
|
||||||
""" Message object. """
|
|
||||||
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
|
|
||||||
id = attr.ib(validator=v.instance_of(int))
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def dc_msg_t(self):
|
|
||||||
return capi.lib.dc_get_msg(self.dc_context, self.id)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if lib is not None and hasattr(self, "_property_cache"):
|
|
||||||
lib.dc_msg_unref(self.dc_msg_t)
|
|
||||||
|
|
||||||
@property_with_doc
|
|
||||||
def text(self):
|
|
||||||
"""unicode representation. """
|
|
||||||
return ffi_unicode(capi.lib.dc_msg_get_text(self.dc_msg_t))
|
|
||||||
|
|
||||||
@property
|
|
||||||
def chat(self):
|
|
||||||
"""chat this message was posted in.
|
|
||||||
|
|
||||||
:returns: :class:`Chat` object
|
|
||||||
"""
|
|
||||||
chat_id = capi.lib.dc_msg_get_chat_id(self.dc_msg_t)
|
|
||||||
return Chat(self.dc_context, chat_id)
|
|
||||||
|
|
||||||
|
|
||||||
class Account(object):
|
class Account(object):
|
||||||
|
@ -402,21 +221,64 @@ class IOThreads:
|
||||||
capi.lib.dc_perform_smtp_idle(self.dc_context)
|
capi.lib.dc_perform_smtp_idle(self.dc_context)
|
||||||
|
|
||||||
|
|
||||||
def convert_to_bytes_utf8(obj):
|
@attr.s
|
||||||
if obj == ffi.NULL:
|
class EventHandler(object):
|
||||||
return obj
|
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
|
||||||
if not isinstance(obj, bytes):
|
|
||||||
return obj.encode("utf8")
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
def read_url(self, url):
|
||||||
def iter_array_and_unref(dc_array_t, constructor):
|
|
||||||
try:
|
try:
|
||||||
for i in range(0, lib.dc_array_get_cnt(dc_array_t)):
|
r = requests.get(url)
|
||||||
yield constructor(lib.dc_array_get_id(dc_array_t, i))
|
except requests.ConnectionError:
|
||||||
finally:
|
return ''
|
||||||
lib.dc_array_unref(dc_array_t)
|
else:
|
||||||
|
return r.content
|
||||||
|
|
||||||
|
def dc_event_http_get(self, data1, data2):
|
||||||
|
url = data1
|
||||||
|
content = self.read_url(url)
|
||||||
|
if not isinstance(content, bytes):
|
||||||
|
content = content.encode("utf8")
|
||||||
|
# we need to return a fresh pointer that the core owns
|
||||||
|
return capi.lib.dupstring_helper(content)
|
||||||
|
|
||||||
|
def dc_event_is_offline(self, data1, data2):
|
||||||
|
return 0 # always online
|
||||||
|
|
||||||
|
|
||||||
def ffi_unicode(obj):
|
class EventLogger:
|
||||||
return ffi.string(obj).decode("utf8")
|
def __init__(self, dc_context, logid=None, debug=True):
|
||||||
|
self.dc_context = dc_context
|
||||||
|
self._event_queue = Queue()
|
||||||
|
self._debug = debug
|
||||||
|
if logid is None:
|
||||||
|
logid = str(self.dc_context).strip(">").split()[-1]
|
||||||
|
self.logid = logid
|
||||||
|
self._timeout = None
|
||||||
|
|
||||||
|
def __call__(self, evt_name, data1, data2):
|
||||||
|
self._log_event(evt_name, data1, data2)
|
||||||
|
self._event_queue.put((evt_name, data1, data2))
|
||||||
|
|
||||||
|
def set_timeout(self, timeout):
|
||||||
|
self._timeout = timeout
|
||||||
|
|
||||||
|
def get(self, timeout=None, check_error=True):
|
||||||
|
timeout = timeout or self._timeout
|
||||||
|
ev = self._event_queue.get(timeout=timeout)
|
||||||
|
if check_error and ev[0] == "DC_EVENT_ERROR":
|
||||||
|
raise ValueError("{}({!r},{!r})".format(*ev))
|
||||||
|
return ev
|
||||||
|
|
||||||
|
def get_matching(self, event_name_regex):
|
||||||
|
rex = re.compile("(?:{}).*".format(event_name_regex))
|
||||||
|
while 1:
|
||||||
|
ev = self.get()
|
||||||
|
if rex.match(ev[0]):
|
||||||
|
return ev
|
||||||
|
|
||||||
|
def _log_event(self, evt_name, data1, data2):
|
||||||
|
if self._debug:
|
||||||
|
t = threading.currentThread()
|
||||||
|
tname = getattr(t, "name", t)
|
||||||
|
print("[{}-{}] {}({!r},{!r})".format(
|
||||||
|
tname, self.logid, evt_name, data1, data2))
|
||||||
|
|
133
python/src/deltachat/chatting.py
Normal file
133
python/src/deltachat/chatting.py
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
""" Chatting related objects: Contact, Chat, Message. """
|
||||||
|
|
||||||
|
from . import capi
|
||||||
|
from .cutil import convert_to_bytes_utf8, ffi_unicode, iter_array_and_unref
|
||||||
|
from .capi import ffi, lib
|
||||||
|
from .types import cached_property, property_with_doc
|
||||||
|
import attr
|
||||||
|
from attr import validators as v
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s
|
||||||
|
class Contact(object):
|
||||||
|
""" Delta-Chat Contact.
|
||||||
|
|
||||||
|
You obtain instances of it through :class:`deltachat.account.Account`.
|
||||||
|
"""
|
||||||
|
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
|
||||||
|
id = attr.ib(validator=v.instance_of(int))
|
||||||
|
|
||||||
|
@cached_property # only get it once because we only free it once
|
||||||
|
def dc_contact_t(self):
|
||||||
|
return capi.lib.dc_get_contact(self.dc_context, self.id)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if lib is not None and hasattr(self, "_property_cache"):
|
||||||
|
lib.dc_contact_unref(self.dc_contact_t)
|
||||||
|
|
||||||
|
@property_with_doc
|
||||||
|
def addr(self):
|
||||||
|
""" normalized e-mail address for this account. """
|
||||||
|
return ffi_unicode(capi.lib.dc_contact_get_addr(self.dc_contact_t))
|
||||||
|
|
||||||
|
@property_with_doc
|
||||||
|
def display_name(self):
|
||||||
|
""" display name for this contact. """
|
||||||
|
return ffi_unicode(capi.lib.dc_contact_get_display_name(self.dc_contact_t))
|
||||||
|
|
||||||
|
def is_blocked(self):
|
||||||
|
""" Return True if the contact is blocked. """
|
||||||
|
return capi.lib.dc_contact_is_blocked(self.dc_contact_t)
|
||||||
|
|
||||||
|
def is_verified(self):
|
||||||
|
""" Return True if the contact is verified. """
|
||||||
|
return capi.lib.dc_contact_is_verified(self.dc_contact_t)
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s
|
||||||
|
class Chat(object):
|
||||||
|
""" Chat object which manages members and through which you can send and retrieve messages.
|
||||||
|
|
||||||
|
You obtain instances of it through :class:`deltachat.account.Account`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
|
||||||
|
id = attr.ib(validator=v.instance_of(int))
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def dc_chat_t(self):
|
||||||
|
return capi.lib.dc_get_chat(self.dc_context, self.id)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if lib is not None and hasattr(self, "_property_cache"):
|
||||||
|
lib.dc_chat_unref(self.dc_chat_t)
|
||||||
|
|
||||||
|
def is_deaddrop(self):
|
||||||
|
""" return true if this chat is a deaddrop chat. """
|
||||||
|
return self.id == lib.DC_CHAT_ID_DEADDROP
|
||||||
|
|
||||||
|
def send_text_message(self, msg):
|
||||||
|
""" send a text message and return the resulting Message instance.
|
||||||
|
|
||||||
|
:param msg: unicode text
|
||||||
|
:returns: the resulting :class:`Message` instance
|
||||||
|
"""
|
||||||
|
msg = convert_to_bytes_utf8(msg)
|
||||||
|
print ("chat id", self.id)
|
||||||
|
msg_id = capi.lib.dc_send_text_msg(self.dc_context, self.id, msg)
|
||||||
|
return Message(self.dc_context, msg_id)
|
||||||
|
|
||||||
|
def get_messages(self):
|
||||||
|
""" return list of messages in this chat.
|
||||||
|
|
||||||
|
:returns: list of :class:`Message` objects for this chat.
|
||||||
|
"""
|
||||||
|
dc_array_t = lib.dc_get_chat_msgs(self.dc_context, self.id, 0, 0)
|
||||||
|
return list(iter_array_and_unref(dc_array_t, lambda x: Message(self.dc_context, x)))
|
||||||
|
|
||||||
|
def count_fresh_messages(self):
|
||||||
|
""" return number of fresh messages in this chat.
|
||||||
|
|
||||||
|
:returns: number of fresh messages
|
||||||
|
"""
|
||||||
|
return lib.dc_get_fresh_msg_cnt(self.dc_context, self.id)
|
||||||
|
|
||||||
|
def mark_noticed(self):
|
||||||
|
""" mark all messages in this chat as noticed.
|
||||||
|
|
||||||
|
Noticed messages are no longer fresh.
|
||||||
|
"""
|
||||||
|
return lib.dc_marknoticed_chat(self.dc_context, self.id)
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s
|
||||||
|
class Message(object):
|
||||||
|
""" Message object.
|
||||||
|
|
||||||
|
You obtain instances of it through :class:`deltachat.account.Account` or
|
||||||
|
:class:`Chat`.
|
||||||
|
"""
|
||||||
|
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
|
||||||
|
id = attr.ib(validator=v.instance_of(int))
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def dc_msg_t(self):
|
||||||
|
return capi.lib.dc_get_msg(self.dc_context, self.id)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if lib is not None and hasattr(self, "_property_cache"):
|
||||||
|
lib.dc_msg_unref(self.dc_msg_t)
|
||||||
|
|
||||||
|
@property_with_doc
|
||||||
|
def text(self):
|
||||||
|
"""unicode representation. """
|
||||||
|
return ffi_unicode(capi.lib.dc_msg_get_text(self.dc_msg_t))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def chat(self):
|
||||||
|
"""chat this message was posted in.
|
||||||
|
|
||||||
|
:returns: :class:`Chat` object
|
||||||
|
"""
|
||||||
|
chat_id = capi.lib.dc_msg_get_chat_id(self.dc_msg_t)
|
||||||
|
return Chat(self.dc_context, chat_id)
|
22
python/src/deltachat/cutil.py
Normal file
22
python/src/deltachat/cutil.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
from .capi import lib
|
||||||
|
from .capi import ffi
|
||||||
|
|
||||||
|
|
||||||
|
def convert_to_bytes_utf8(obj):
|
||||||
|
if obj == ffi.NULL:
|
||||||
|
return obj
|
||||||
|
if not isinstance(obj, bytes):
|
||||||
|
return obj.encode("utf8")
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def iter_array_and_unref(dc_array_t, constructor):
|
||||||
|
try:
|
||||||
|
for i in range(0, lib.dc_array_get_cnt(dc_array_t)):
|
||||||
|
yield constructor(lib.dc_array_get_id(dc_array_t, i))
|
||||||
|
finally:
|
||||||
|
lib.dc_array_unref(dc_array_t)
|
||||||
|
|
||||||
|
|
||||||
|
def ffi_unicode(obj):
|
||||||
|
return ffi.string(obj).decode("utf8")
|
Loading…
Add table
Add a link
Reference in a new issue