Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
3ed3394a33 | |||
7cd668af14 | |||
5690307c63 | |||
b1feb004e8 | |||
73021a25a1 | |||
4c73986596 |
@@ -150,7 +150,7 @@ You can test it with command line :
|
||||
|
||||
gdbus call --session --dest org.gnome.Shell --object-path /com/soutade/GenericMonitor --method com.soutade.GenericMonitor.deleteGroups '{"groups":["new"]}'
|
||||
|
||||
Python examples is available
|
||||
Python examples are available @ https://indefero.soutade.fr/p/genericmonitor/source/tree/master/examples
|
||||
|
||||
|
||||
Development
|
||||
|
77
examples/gmail.py
Normal file
77
examples/gmail.py
Normal file
@@ -0,0 +1,77 @@
|
||||
#
|
||||
# Copyright 2018 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# Setup : https://developers.google.com/gmail/api/quickstart/python
|
||||
# Need to have credentials.json were you call main script
|
||||
#
|
||||
# File imported from https://github.com/googleworkspace/python-samples/blob/main/gmail/quickstart/quickstart.py
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os.path
|
||||
|
||||
from google.auth.transport.requests import Request
|
||||
from google.oauth2.credentials import Credentials
|
||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||
from googleapiclient.discovery import build
|
||||
|
||||
# If modifying these scopes, delete the file token.json.
|
||||
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
|
||||
|
||||
creds = None
|
||||
|
||||
def _initCreds():
|
||||
global creds
|
||||
if creds: return
|
||||
|
||||
# The file token.json stores the user's access and refresh tokens, and is
|
||||
# created automatically when the authorization flow completes for the first
|
||||
# time.
|
||||
if os.path.exists('token.json'):
|
||||
creds = Credentials.from_authorized_user_file('./token.json', SCOPES)
|
||||
# If there are no (valid) credentials available, let the user log in.
|
||||
if not creds or not creds.valid:
|
||||
if creds and creds.expired and creds.refresh_token:
|
||||
creds.refresh(Request())
|
||||
else:
|
||||
flow = InstalledAppFlow.from_client_secrets_file(
|
||||
'credentials.json', SCOPES)
|
||||
creds = flow.run_local_server(port=0)
|
||||
# Save the credentials for the next run
|
||||
with open('token.json', 'w') as token:
|
||||
token.write(creds.to_json())
|
||||
|
||||
def getUnreadMails():
|
||||
"""
|
||||
Get number of unread threads (that may contain multiple messages)
|
||||
"""
|
||||
|
||||
_initCreds()
|
||||
|
||||
service = build('gmail', 'v1', credentials=creds)
|
||||
pageToken = ''
|
||||
threads = set()
|
||||
while True:
|
||||
results = service.users().messages().list(userId='me', labelIds=['UNREAD'],\
|
||||
includeSpamTrash=False, pageToken=pageToken)\
|
||||
.execute()
|
||||
threads = threads.union(set([k['threadId'] for k in results['messages']]))
|
||||
# Loop over all result pages (100 results per page by default)
|
||||
pageToken = results.get('nextPageToken', '')
|
||||
if not pageToken: break
|
||||
|
||||
return len(threads)
|
@@ -23,11 +23,11 @@ import time
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
import xml.dom.minidom
|
||||
import getpass
|
||||
from threading import Thread
|
||||
from signal import signal, SIGINT
|
||||
import sys
|
||||
from genericmonitor import *
|
||||
from gmail import getUnreadMails
|
||||
|
||||
PURPLE_CONV_UPDATE_UNSEEN = 4
|
||||
PURPLE_MESSAGE_SEND = 0
|
||||
@@ -59,31 +59,23 @@ class PidginConversation:
|
||||
|
||||
class EventThread(Thread,GenericMonitor):
|
||||
SLEEP_TIME = 30
|
||||
MAIL_ADDRESS='XXX@gmail.com'
|
||||
|
||||
def stop(self):
|
||||
self._stopLoop = True
|
||||
self.stopMainLoop()
|
||||
|
||||
def _getMail(self):
|
||||
address = "https://mail.google.com/mail/feed/atom"
|
||||
auth = HTTPBasicAuth(self.MAIL_ADDRESS, self._mail_password)
|
||||
req = requests.get(address, auth=auth)
|
||||
text = ''
|
||||
style = ''
|
||||
if req.status_code == requests.codes.ok:
|
||||
dom = xml.dom.minidom.parseString(req.text)
|
||||
try:
|
||||
nb_messages = int(dom.getElementsByTagName('fullcount')[0].firstChild.nodeValue)
|
||||
if nb_messages == 1:
|
||||
text = '1 msg'
|
||||
elif nb_messages > 1:
|
||||
text = '%d msgs' % (nb_messages)
|
||||
style = 'color:white'
|
||||
except Exception as e:
|
||||
text = str(e)
|
||||
else:
|
||||
text = 'Mail error %d' % (req.status_code)
|
||||
try:
|
||||
nb_messages = getUnreadMails()
|
||||
if nb_messages == 1:
|
||||
text = '1 msg'
|
||||
elif nb_messages > 1:
|
||||
text = '%d msgs' % (nb_messages)
|
||||
style = 'color:white'
|
||||
except Exception as e:
|
||||
text = str(e)
|
||||
|
||||
self.mailWidget.setText(text)
|
||||
self.mailWidget.setStyle(style)
|
||||
@@ -103,8 +95,6 @@ class EventThread(Thread,GenericMonitor):
|
||||
self.add_signal_receiver(self.pidginMessageWrote, 'WroteChatMsg', 'im.pidgin.purple.PurpleInterface')
|
||||
self.add_signal_receiver(self.pidginConversationUpdated, 'ConversationUpdated', 'im.pidgin.purple.PurpleInterface')
|
||||
|
||||
self._mail_password = getpass.getpass('Enter password for address %s: ' % (self.MAIL_ADDRESS))
|
||||
|
||||
self.mailWidget = GenericMonitorTextWidget('')
|
||||
mailItem = GenericMonitorItem('mail', [self.mailWidget])
|
||||
self.mailGroup = GenericMonitorGroup('Mail', [mailItem])
|
||||
|
@@ -56,7 +56,7 @@ class PicturePopup(GenericMonitor):
|
||||
popup = GenericMonitorPopup([url_widget, picture_widget])
|
||||
signals = {
|
||||
'on-click':'toggle-popup',
|
||||
# Could also use this behavior
|
||||
# Could also use this behavior [bugged since GNOME 42]
|
||||
# 'on-enter':'open-popup',
|
||||
# 'on-leave':'close-popup',
|
||||
'on-dblclick':'signal',
|
||||
|
61
extension.js
61
extension.js
@@ -24,9 +24,9 @@
|
||||
https://github.com/bananenfisch/RecentItems/blob/master/extension.js
|
||||
https://github.com/julio641742/gnome-shell-extension-reference/blob/master/tutorials/POPUPMENU-EXTENSION.md
|
||||
https://gjs-docs.gnome.org/st10~1.0_api/st.widget
|
||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/panelMenu.js
|
||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/popupMenu.js
|
||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/panel.js
|
||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/panelMenu.js
|
||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/popupMenu.js
|
||||
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/panel.js
|
||||
*/
|
||||
|
||||
const St = imports.gi.St;
|
||||
@@ -56,16 +56,17 @@ function log(message) {
|
||||
|
||||
class SignalMgt {
|
||||
|
||||
constructor(item, name, group, dbus, menu) {
|
||||
constructor(item, name, group, dbus, buttonMenu) {
|
||||
this.name = name;
|
||||
this.group = group;
|
||||
this.fullname = this.name + '@' + this.group;
|
||||
this.dbus = dbus;
|
||||
this.menu = menu;
|
||||
this.buttonMenu = buttonMenu;
|
||||
this.signals = new WeakMap();
|
||||
this.widgets = new Array();
|
||||
this.timeouts = new Array();
|
||||
|
||||
this.menuOpen = false;
|
||||
this.nbClicks = 0;
|
||||
this.button = -1;
|
||||
|
||||
@@ -118,25 +119,42 @@ class SignalMgt {
|
||||
this.signals.set(widget, null);
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
if (this.menuOpen)
|
||||
{
|
||||
this.buttonMenu.menu.close();
|
||||
this.menuOpen = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.buttonMenu.menu.open(true);
|
||||
this.menuOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
_manageEventAction(action, signalName) {
|
||||
if (action === 'open-popup')
|
||||
this.menu.open(true);
|
||||
{
|
||||
this.buttonMenu.menu.open(true);
|
||||
this.menuOpen = true;
|
||||
}
|
||||
else if (action === 'close-popup')
|
||||
this.menu.close();
|
||||
{
|
||||
this.buttonMenu.menu.close();
|
||||
this.menuOpen = false;
|
||||
}
|
||||
else if (action === 'toggle-popup')
|
||||
this.menu.toggle();
|
||||
else if (action == 'delete')
|
||||
{
|
||||
this.toggleMenu();
|
||||
}
|
||||
else if (action === 'delete')
|
||||
this.dbus.deleteItem(this, this.group);
|
||||
else if (action === 'signal')
|
||||
this.dbus.emitSignal(signalName, this.fullname);
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
_manageLeaveEvent() {
|
||||
this._manageEventAction(this.onLeave);
|
||||
}
|
||||
|
||||
|
||||
_doClickCallback() {
|
||||
let right = '';
|
||||
let nbClicks = '';
|
||||
@@ -229,7 +247,8 @@ class MonitorWidget extends PanelMenu.Button {
|
||||
this.group = group;
|
||||
this.fullname = this.name + '@' + this.group;
|
||||
this.dbus = dbus;
|
||||
this.signalManager = new SignalMgt(item, this.name, group, dbus, this.menu);
|
||||
this.menuItem = null;
|
||||
this.signalManager = new SignalMgt(item, this.name, group, dbus, this);
|
||||
this.popup_signals = null;
|
||||
this.popup_widgets = null;
|
||||
|
||||
@@ -414,7 +433,7 @@ class MonitorWidget extends PanelMenu.Button {
|
||||
const name = hashGet(nestedItem, 'name', '');
|
||||
this.popup_signals[widget] = new SignalMgt(nestedItem, name,
|
||||
this.fullname, this.dbus,
|
||||
this.menu);
|
||||
this);
|
||||
this.popup_signals[widget].connectWidgetSignals(widget);
|
||||
this.popup_widgets.push(widget);
|
||||
}
|
||||
@@ -791,15 +810,19 @@ class Extension {
|
||||
}
|
||||
}
|
||||
|
||||
const extension = new Extension();
|
||||
let extension = null;
|
||||
|
||||
function init() {
|
||||
}
|
||||
|
||||
function enable() {
|
||||
extension = new Extension();
|
||||
extension.enable();
|
||||
}
|
||||
|
||||
function disable() {
|
||||
extension.disable();
|
||||
if (extension) {
|
||||
extension.disable();
|
||||
extension = null;
|
||||
}
|
||||
}
|
||||
|
@@ -2,13 +2,13 @@
|
||||
"uuid": "generic-monitor@gnome-shell-extensions",
|
||||
"name": "Generic Monitor",
|
||||
"description": "Display text & icon on systray using DBUS",
|
||||
"version": "10",
|
||||
"version": "13",
|
||||
"shell-version": [
|
||||
"42",
|
||||
"41",
|
||||
"40",
|
||||
"3.38",
|
||||
"3.36"
|
||||
"44",
|
||||
"43",
|
||||
"42.3",
|
||||
"42",
|
||||
"41"
|
||||
],
|
||||
"url": "http://indefero.soutade.fr/p/genericmonitor"
|
||||
}
|
||||
|
Reference in New Issue
Block a user