mirror of
https://github.com/deltachat/deltachat-core.git
synced 2025-10-04 18:29:19 +02:00
120 lines
4.1 KiB
Python
120 lines
4.1 KiB
Python
from __future__ import print_function
|
|
import threading
|
|
import requests
|
|
from . import capi
|
|
import deltachat
|
|
|
|
|
|
def eventprinter(evt):
|
|
evt_name, data1, data2 = evt
|
|
t = threading.currentThread()
|
|
tname = getattr(t, "name", t)
|
|
print("[" + tname + "]", evt_name, data1, data2)
|
|
|
|
|
|
class EventHandler:
|
|
def __init__(self, dc_context):
|
|
self.dc_context = dc_context
|
|
|
|
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)
|
|
# 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 Account:
|
|
def __init__(self, db_path, logcallback=None, eventhandler=None):
|
|
self.dc_context = ctx = capi.lib.dc_context_new(
|
|
capi.lib.py_dc_callback,
|
|
capi.ffi.NULL, capi.ffi.NULL)
|
|
if hasattr(db_path, "encode"):
|
|
db_path = db_path.encode("utf8")
|
|
capi.lib.dc_open(ctx, db_path, capi.ffi.NULL)
|
|
self._logcallback = logcallback or eventprinter
|
|
if eventhandler is None:
|
|
eventhandler = EventHandler(self.dc_context)
|
|
self._eventhandler = eventhandler
|
|
|
|
def set_config(self, **kwargs):
|
|
for name, value in kwargs.items():
|
|
name = name.encode("utf8")
|
|
value = value.encode("utf8")
|
|
capi.lib.dc_set_config(self.dc_context, name, value)
|
|
|
|
def start(self):
|
|
deltachat.set_context_callback(self.dc_context, self.process_event)
|
|
capi.lib.dc_configure(self.dc_context)
|
|
self._threads = IOThreads(self.dc_context)
|
|
self._threads.start()
|
|
|
|
def shutdown(self):
|
|
deltachat.clear_context_callback(self.dc_context)
|
|
self._threads.stop(wait=False)
|
|
# XXX actually we'd like to wait but the smtp/imap
|
|
# interrupt idle calls do not seem to release the
|
|
# blocking call to smtp|imap idle. This means we
|
|
# also can't now close the database because the
|
|
# threads might still need it.
|
|
# capi.lib.dc_close(self.dc_context)
|
|
|
|
def process_event(self, ctx, evt_name, data1, data2):
|
|
assert ctx == self.dc_context
|
|
self._logcallback((evt_name, data1, data2))
|
|
method = getattr(self._eventhandler, evt_name.lower(), None)
|
|
if method is not None:
|
|
return method(data1, data2) or 0
|
|
return 0
|
|
|
|
|
|
class IOThreads:
|
|
def __init__(self, dc_context):
|
|
self.dc_context = dc_context
|
|
self._thread_quitflag = False
|
|
self._name2thread = {}
|
|
|
|
def start(self, imap=True, smtp=True):
|
|
assert not self._name2thread
|
|
if imap:
|
|
self._start_one_thread("imap", self.imap_thread_run)
|
|
if smtp:
|
|
self._start_one_thread("smtp", self.smtp_thread_run)
|
|
|
|
def _start_one_thread(self, name, func):
|
|
self._name2thread[name] = t = threading.Thread(target=func, name=name)
|
|
t.setDaemon(1)
|
|
t.start()
|
|
|
|
def stop(self, wait=False):
|
|
self._thread_quitflag = True
|
|
# XXX interrupting does not quite work yet, the threads keep idling
|
|
print("interrupting smtp and idle")
|
|
capi.lib.dc_interrupt_imap_idle(self.dc_context)
|
|
capi.lib.dc_interrupt_smtp_idle(self.dc_context)
|
|
if wait:
|
|
for name, thread in self._name2thread.items():
|
|
thread.join()
|
|
|
|
def imap_thread_run(self):
|
|
print ("starting imap thread")
|
|
while not self._thread_quitflag:
|
|
capi.lib.dc_perform_imap_jobs(self.dc_context)
|
|
capi.lib.dc_perform_imap_fetch(self.dc_context)
|
|
capi.lib.dc_perform_imap_idle(self.dc_context)
|
|
|
|
def smtp_thread_run(self):
|
|
print ("starting smtp thread")
|
|
while not self._thread_quitflag:
|
|
capi.lib.dc_perform_smtp_jobs(self.dc_context)
|
|
capi.lib.dc_perform_smtp_idle(self.dc_context)
|