comparison sat/plugins/plugin_misc_android.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 758bee45612b
children f91d0e6d9b13
comparison
equal deleted inserted replaced
3027:ff5bcb12ae60 3028:ab2696e34d29
1 #!/usr/bin/env python2 1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 # SAT plugin for file tansfer 4 # SAT plugin for file tansfer
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org)
6 6
34 34
35 PLUGIN_INFO = { 35 PLUGIN_INFO = {
36 C.PI_NAME: "Android ", 36 C.PI_NAME: "Android ",
37 C.PI_IMPORT_NAME: "android", 37 C.PI_IMPORT_NAME: "android",
38 C.PI_TYPE: C.PLUG_TYPE_MISC, 38 C.PI_TYPE: C.PLUG_TYPE_MISC,
39 C.PI_RECOMMENDATIONS: [u"XEP-0352"], 39 C.PI_RECOMMENDATIONS: ["XEP-0352"],
40 C.PI_MAIN: "AndroidPlugin", 40 C.PI_MAIN: "AndroidPlugin",
41 C.PI_HANDLER: "no", 41 C.PI_HANDLER: "no",
42 C.PI_DESCRIPTION: D_( 42 C.PI_DESCRIPTION: D_(
43 """Manage Android platform specificities, like pause or notifications""" 43 """Manage Android platform specificities, like pause or notifications"""
44 ), 44 ),
45 } 45 }
46 46
47 if sys.platform != "android": 47 if sys.platform != "android":
48 raise exceptions.CancelError(u"this module is not needed on this platform") 48 raise exceptions.CancelError("this module is not needed on this platform")
49 49
50 50
51 from plyer import notification, vibrator 51 from plyer import notification, vibrator
52 from plyer.platforms.android import activity 52 from plyer.platforms.android import activity
53 from jnius import autoclass 53 from jnius import autoclass
58 #: quickly on an other app. 58 #: quickly on an other app.
59 CSI_DELAY = 30 59 CSI_DELAY = 30
60 60
61 PARAM_VIBRATE_CATEGORY = "Notifications" 61 PARAM_VIBRATE_CATEGORY = "Notifications"
62 PARAM_VIBRATE_NAME = "vibrate" 62 PARAM_VIBRATE_NAME = "vibrate"
63 PARAM_VIBRATE_LABEL = D_(u"Vibrate on notifications") 63 PARAM_VIBRATE_LABEL = D_("Vibrate on notifications")
64 SOCKET_DIR = "/data/data/org.salutatoi.cagou/" 64 SOCKET_DIR = "/data/data/org.salutatoi.cagou/"
65 SOCKET_FILE = ".socket" 65 SOCKET_FILE = ".socket"
66 STATE_RUNNING = "running" 66 STATE_RUNNING = "running"
67 STATE_PAUSED = "paused" 67 STATE_PAUSED = "paused"
68 STATE_STOPPED = "stopped" 68 STATE_STOPPED = "stopped"
99 with tempfile.TemporaryFile() as f: 99 with tempfile.TemporaryFile() as f:
100 f.write(b'1234567890') 100 f.write(b'1234567890')
101 f.seek(0, os.SEEK_END) 101 f.seek(0, os.SEEK_END)
102 size = f.tell() 102 size = f.tell()
103 if size == 10: 103 if size == 10:
104 log.info(u"seek() bug not present anymore, workaround code can be removed") 104 log.info("seek() bug not present anymore, workaround code can be removed")
105 else: 105 else:
106 log.warning(u"seek() bug detected, applying a workaround") 106 log.warning("seek() bug detected, applying a workaround")
107 web_client.FileBodyProducer._determineLength = determineLength_workaround 107 web_client.FileBodyProducer._determineLength = determineLength_workaround
108 108
109 patch_seek_bug() 109 patch_seek_bug()
110 110
111 111
116 116
117 def dataReceived(self, data): 117 def dataReceived(self, data):
118 if data in STATES: 118 if data in STATES:
119 self.android_plugin.state = data 119 self.android_plugin.state = data
120 else: 120 else:
121 log.warning(u"Unexpected data: {data}".format(data=data)) 121 log.warning("Unexpected data: {data}".format(data=data))
122 122
123 123
124 class FrontendStateFactory(protocol.Factory): 124 class FrontendStateFactory(protocol.Factory):
125 125
126 def __init__(self, android_plugin): 126 def __init__(self, android_plugin):
147 param_name=PARAM_VIBRATE_NAME, 147 param_name=PARAM_VIBRATE_NAME,
148 param_label=PARAM_VIBRATE_LABEL, 148 param_label=PARAM_VIBRATE_LABEL,
149 ) 149 )
150 150
151 def __init__(self, host): 151 def __init__(self, host):
152 log.info(_(u"plugin Android initialization")) 152 log.info(_("plugin Android initialization"))
153 self.host = host 153 self.host = host
154 self._csi = host.plugins.get(u'XEP-0352') 154 self._csi = host.plugins.get('XEP-0352')
155 self._csi_timer = None 155 self._csi_timer = None
156 host.memory.updateParams(self.params) 156 host.memory.updateParams(self.params)
157 try: 157 try:
158 os.mkdir(SOCKET_DIR, 0700) 158 os.mkdir(SOCKET_DIR, 0o700)
159 except OSError as e: 159 except OSError as e:
160 if e.errno == 17: 160 if e.errno == 17:
161 # dir already exists 161 # dir already exists
162 pass 162 pass
163 else: 163 else:
186 # "XXX has no attribute 'invoke'" error (looks like the same issue as 186 # "XXX has no attribute 'invoke'" error (looks like the same issue as
187 # https://github.com/kivy/pyjnius/issues/59) 187 # https://github.com/kivy/pyjnius/issues/59)
188 self.br = BroadcastReceiver( 188 self.br = BroadcastReceiver(
189 callback=lambda *args, **kwargs: reactor.callLater(0, 189 callback=lambda *args, **kwargs: reactor.callLater(0,
190 self.onConnectivityChange), 190 self.onConnectivityChange),
191 actions=[u"android.net.conn.CONNECTIVITY_CHANGE"]) 191 actions=["android.net.conn.CONNECTIVITY_CHANGE"])
192 self.br.start() 192 self.br.start()
193 193
194 194
195 @property 195 @property
196 def state(self): 196 def state(self):
197 return self._state 197 return self._state
198 198
199 @state.setter 199 @state.setter
200 def state(self, new_state): 200 def state(self, new_state):
201 log.debug(u"frontend state has changed: {state}".format(state=new_state)) 201 log.debug("frontend state has changed: {state}".format(state=new_state))
202 previous_state = self._state 202 previous_state = self._state
203 self._state = new_state 203 self._state = new_state
204 if new_state == STATE_RUNNING: 204 if new_state == STATE_RUNNING:
205 self._onRunning(previous_state) 205 self._onRunning(previous_state)
206 elif new_state == STATE_PAUSED: 206 elif new_state == STATE_PAUSED:
231 - there is a message and it is not a groupchat 231 - there is a message and it is not a groupchat
232 - message is not coming from ourself 232 - message is not coming from ourself
233 """ 233 """
234 if (mess_data["message"] and mess_data["type"] != C.MESS_TYPE_GROUPCHAT 234 if (mess_data["message"] and mess_data["type"] != C.MESS_TYPE_GROUPCHAT
235 and not mess_data["from"].userhostJID() == client.jid.userhostJID()): 235 and not mess_data["from"].userhostJID() == client.jid.userhostJID()):
236 message = mess_data["message"].itervalues().next() 236 message = next(iter(mess_data["message"].values()))
237 try: 237 try:
238 subject = mess_data["subject"].itervalues().next() 238 subject = next(iter(mess_data["subject"].values()))
239 except StopIteration: 239 except StopIteration:
240 subject = u"Cagou new message" 240 subject = "Cagou new message"
241 241
242 notification.notify(title=subject, message=message) 242 notification.notify(title=subject, message=message)
243 if self.host.memory.getParamA( 243 if self.host.memory.getParamA(
244 PARAM_VIBRATE_NAME, PARAM_VIBRATE_CATEGORY, profile_key=client.profile 244 PARAM_VIBRATE_NAME, PARAM_VIBRATE_CATEGORY, profile_key=client.profile
245 ): 245 ):
246 try: 246 try:
247 vibrator.vibrate() 247 vibrator.vibrate()
248 except Exception as e: 248 except Exception as e:
249 # FIXME: vibrator is currently not working, 249 # FIXME: vibrator is currently not working,
250 # cf. https://github.com/kivy/plyer/issues/509 250 # cf. https://github.com/kivy/plyer/issues/509
251 log.warning(u"Can't use vibrator: {e}".format(e=e)) 251 log.warning("Can't use vibrator: {e}".format(e=e))
252 return mess_data 252 return mess_data
253 253
254 def messageReceivedTrigger(self, client, message_elt, post_treat): 254 def messageReceivedTrigger(self, client, message_elt, post_treat):
255 if not self.cagou_active: 255 if not self.cagou_active:
256 # we only send notification is the frontend is not displayed 256 # we only send notification is the frontend is not displayed
304 elif net_type_android == ConnectivityManager.TYPE_MOBILE: 304 elif net_type_android == ConnectivityManager.TYPE_MOBILE:
305 net_type = NET_TYPE_MOBILE 305 net_type = NET_TYPE_MOBILE
306 else: 306 else:
307 net_type = NET_TYPE_OTHER 307 net_type = NET_TYPE_OTHER
308 if net_type != self._net_type: 308 if net_type != self._net_type:
309 log.info(u"connectivity has changed") 309 log.info("connectivity has changed")
310 previous = self._net_type 310 previous = self._net_type
311 self._net_type = net_type 311 self._net_type = net_type
312 if net_type == NET_TYPE_NONE: 312 if net_type == NET_TYPE_NONE:
313 log.info(u"no network active") 313 log.info("no network active")
314 elif net_type == NET_TYPE_WIFI: 314 elif net_type == NET_TYPE_WIFI:
315 log.info(u"WIFI activated") 315 log.info("WIFI activated")
316 elif net_type == NET_TYPE_MOBILE: 316 elif net_type == NET_TYPE_MOBILE:
317 log.info(u"mobile data activated") 317 log.info("mobile data activated")
318 else: 318 else:
319 log.info(u"network activated (type={net_type_android})" 319 log.info("network activated (type={net_type_android})"
320 .format(net_type_android=net_type_android)) 320 .format(net_type_android=net_type_android))
321 self._handleNetworkChange(previous, net_type) 321 self._handleNetworkChange(previous, net_type)
322 else: 322 else:
323 log.debug(u"_checkConnectivity called without network change ({net_type})" 323 log.debug("_checkConnectivity called without network change ({net_type})"
324 .format(net_type = net_type)) 324 .format(net_type = net_type))
325 325
326 326
327 def onConnectivityChange(self): 327 def onConnectivityChange(self):
328 log.debug(u"onConnectivityChange called") 328 log.debug("onConnectivityChange called")
329 self._checkConnectivity() 329 self._checkConnectivity()