1 | #!/usr/bin/python3␊ |
2 | ␊ |
3 | #␊ |
4 | # This program is free software: you can redistribute it and/or modify␊ |
5 | # it under the terms of the GNU General Public License as published by␊ |
6 | # the Free Software Foundation, either version 3 of the License, or␊ |
7 | # (at your option) any later version.␊ |
8 | #␊ |
9 | # This program is distributed in the hope that it will be useful,␊ |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of␊ |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the␊ |
12 | # GNU General Public License for more details.␊ |
13 | #␊ |
14 | # You should have received a copy of the GNU General Public License␊ |
15 | # along with this program. If not, see <https://www.gnu.org/licenses/>.␊ |
16 | #␊ |
17 | ␊ |
18 | '''␊ |
19 | Display number of mail from gmail account and Pidgin icon if there is some unread Pidgin message␊ |
20 | '''␊ |
21 | ␊ |
22 | import time␊ |
23 | import requests␊ |
24 | from requests.auth import HTTPBasicAuth␊ |
25 | import xml.dom.minidom␊ |
26 | from threading import Thread␊ |
27 | from signal import signal, SIGINT␊ |
28 | import sys␊ |
29 | from genericmonitor import *␊ |
30 | from gmail import getUnreadMails␊ |
31 | ␊ |
32 | PURPLE_CONV_UPDATE_UNSEEN = 4␊ |
33 | PURPLE_MESSAGE_SEND = 0␊ |
34 | ␊ |
35 | class PidginConversation:␊ |
36 | STATUS_SEEN = 0␊ |
37 | STATUS_UNSEEN = 1␊ |
38 | ␊ |
39 | def __init__(self, _id):␊ |
40 | self._id = _id␊ |
41 | self.status = PidginConversation.STATUS_SEEN␊ |
42 | self.nbMessages = 1␊ |
43 | ␊ |
44 | def updateNbMessages(self):␊ |
45 | self.nbMessages += 1␊ |
46 | # Status is seen until it changes␊ |
47 | self.status = PidginConversation.STATUS_SEEN␊ |
48 | ␊ |
49 | def setSeen(self):␊ |
50 | self.status = PidginConversation.STATUS_SEEN␊ |
51 | ␊ |
52 | def setUnseen(self):␊ |
53 | self.nbMessages = 0␊ |
54 | self.status = PidginConversation.STATUS_UNSEEN␊ |
55 | ␊ |
56 | def isSeen(self):␊ |
57 | return (self.status == PidginConversation.STATUS_SEEN)␊ |
58 | ␊ |
59 | ␊ |
60 | class EventThread(Thread,GenericMonitor):␊ |
61 | SLEEP_TIME = 30␊ |
62 | ␊ |
63 | def stop(self):␊ |
64 | self._stopLoop = True␊ |
65 | self.stopMainLoop()␊ |
66 | ␊ |
67 | def _getMail(self):␊ |
68 | text = ''␊ |
69 | style = ''␊ |
70 | try:␊ |
71 | nb_messages = getUnreadMails()␊ |
72 | if nb_messages == 1:␊ |
73 | text = '1 msg'␊ |
74 | elif nb_messages > 1:␊ |
75 | text = '%d msgs' % (nb_messages)␊ |
76 | style = 'color:white'␊ |
77 | except Exception as e:␊ |
78 | text = str(e)␊ |
79 | ␊ |
80 | self.mailWidget.setText(text)␊ |
81 | self.mailWidget.setStyle(style)␊ |
82 | self.notify(self.mailGroup)␊ |
83 | ␊ |
84 | def getEvents(self):␊ |
85 | self._getMail()␊ |
86 | ␊ |
87 | def run(self):␊ |
88 | self._stopLoop = False␊ |
89 | self.setupMonitor()␊ |
90 | self.pidgin_conversations = {}␊ |
91 | ␊ |
92 | self.add_signal_receiver(self.pidginMessageReceived, 'ReceivedImMsg', 'im.pidgin.purple.PurpleInterface')␊ |
93 | self.add_signal_receiver(self.pidginMessageReceived, 'ReceivedChatMsg', 'im.pidgin.purple.PurpleInterface')␊ |
94 | self.add_signal_receiver(self.pidginMessageWrote, 'WroteImMsg', 'im.pidgin.purple.PurpleInterface')␊ |
95 | self.add_signal_receiver(self.pidginMessageWrote, 'WroteChatMsg', 'im.pidgin.purple.PurpleInterface')␊ |
96 | self.add_signal_receiver(self.pidginConversationUpdated, 'ConversationUpdated', 'im.pidgin.purple.PurpleInterface')␊ |
97 | ␊ |
98 | self.mailWidget = GenericMonitorTextWidget('')␊ |
99 | mailItem = GenericMonitorItem('mail', [self.mailWidget])␊ |
100 | self.mailGroup = GenericMonitorGroup('Mail', [mailItem])␊ |
101 | ␊ |
102 | icon = GenericMonitorIconWidget('/usr/share/icons/hicolor/22x22/apps/pidgin.png', 'icon-size:22px')␊ |
103 | pidginItem = GenericMonitorItem('pidgin', [icon])␊ |
104 | self.pidginGroup = GenericMonitorGroup('Pidgin', pidginItem)␊ |
105 | ␊ |
106 | while not self._stopLoop:␊ |
107 | self.getEvents()␊ |
108 | # Be more reactive on signal capture␊ |
109 | for i in range(0, self.SLEEP_TIME):␊ |
110 | if self._stopLoop: break␊ |
111 | time.sleep(1)␊ |
112 | ␊ |
113 | def pidginMessageReceived(self, account, sender, message, conversation, flags):␊ |
114 | pidginConversation = self.pidgin_conversations.get(conversation, None)␊ |
115 | if not pidginConversation:␊ |
116 | self.pidgin_conversations[conversation] = PidginConversation(conversation)␊ |
117 | else:␊ |
118 | pidginConversation.updateNbMessages()␊ |
119 | ␊ |
120 | def pidginMessageWrote(self, account, sender, message, conversation, flags):␊ |
121 | if not (flags & (1 << PURPLE_MESSAGE_SEND)):␊ |
122 | return␊ |
123 | pidginConversation = self.pidgin_conversations.get(conversation, None)␊ |
124 | if not pidginConversation:␊ |
125 | self.pidgin_conversations[conversation] = PidginConversation(conversation)␊ |
126 | pidginConversation = self.pidgin_conversations[conversation]␊ |
127 | pidginConversation.setSeen()␊ |
128 | pidginConversation.nbMessages = 1␊ |
129 | ␊ |
130 | def displayIcon(self):␊ |
131 | self.notify(self.pidginGroup)␊ |
132 | ␊ |
133 | def pidginConversationUpdated(self, conversation, _type):␊ |
134 | if _type != PURPLE_CONV_UPDATE_UNSEEN:␊ |
135 | return␊ |
136 | ␊ |
137 | pidginConversation = self.pidgin_conversations.get(conversation, None)␊ |
138 | if not pidginConversation:␊ |
139 | return␊ |
140 | ␊ |
141 | if pidginConversation.isSeen():␊ |
142 | if pidginConversation.nbMessages > 0:␊ |
143 | pidginConversation.setUnseen()␊ |
144 | else:␊ |
145 | pidginConversation.setSeen()␊ |
146 | ␊ |
147 | # Message not seen by user␊ |
148 | if not pidginConversation.isSeen():␊ |
149 | self.displayIcon()␊ |
150 | else:␊ |
151 | deleteIcon = True␊ |
152 | # Are all messages seen ?␊ |
153 | for pConv in self.pidgin_conversations.values():␊ |
154 | if not pConv.isSeen():␊ |
155 | deleteIcon = False␊ |
156 | break␊ |
157 | if deleteIcon:␊ |
158 | items = {'items':['pidgin@Pidgin']}␊ |
159 | self.deleteItems(items)␊ |
160 | ␊ |
161 | def onActivate(self):␊ |
162 | super().onActivate()␊ |
163 | for pConv in self.pidgin_conversations.values():␊ |
164 | if not pConv.isSeen():␊ |
165 | self.displayIcon()␊ |
166 | break␊ |
167 | ␊ |
168 | def signalHandler(signal_received, frame):␊ |
169 | eventThread.stop()␊ |
170 | eventThread.join()␊ |
171 | groups = ['Mail', 'Pidgin']␊ |
172 | eventThread.deleteGroups(groups)␊ |
173 | sys.exit(0)␊ |
174 | ␊ |
175 | eventThread = EventThread()␊ |
176 | eventThread.start()␊ |
177 | ␊ |
178 | signal(SIGINT, signalHandler)␊ |
179 | ␊ |
180 | eventThread.runMainLoop()␊ |