dbus notification, client side threads and more that i dont have strength to remember
This commit is contained in:
parent
4447468b77
commit
2bfc30a49a
92
client.py
92
client.py
@ -1,49 +1,85 @@
|
||||
import pyperclip
|
||||
import socketio
|
||||
import reauests
|
||||
import os
|
||||
"""
|
||||
This script is a daemon that, on event, send and sync the clipboard with a
|
||||
distant one
|
||||
"""
|
||||
import threading
|
||||
import time
|
||||
import sys
|
||||
import subprocess
|
||||
import json
|
||||
import pyperclip
|
||||
import requests
|
||||
import socketio
|
||||
import zc.lockfile
|
||||
# standard Python
|
||||
import notification as notif
|
||||
|
||||
# to put in a conf file
|
||||
ip = 'simailadjalim.fr'
|
||||
ip = 'localhost'
|
||||
port = "9564"
|
||||
hostname = "WarMachine"
|
||||
|
||||
username = "neotaku67"
|
||||
password = "un bon mot de passe de prefererance mais en sah tant qu'il est hashe ca passe"
|
||||
sign = "[AllSync] "
|
||||
|
||||
"""
|
||||
This script is a daemon that, on event, send and sync the clipboard with a distant one
|
||||
"""
|
||||
|
||||
ip = f"http://{ip}:{port}/"
|
||||
ip = f"http://{ip}:{port}"
|
||||
sio = socketio.Client()
|
||||
sio.connect(ip)
|
||||
|
||||
print("[Debug] Connected to Server .w.")
|
||||
auth = requests.post(f"{ip}/user",
|
||||
data={"username": username, "password": password},
|
||||
timeout=10000)
|
||||
if auth.status_code != 200:
|
||||
print("invalid credentials")
|
||||
sys.exit()
|
||||
token = json.loads(auth.content.decode())['token']
|
||||
notify_stop_event = threading.Event()
|
||||
# clipboard_stop_event = threading.Event()
|
||||
|
||||
def send_notification():
|
||||
notif.start_monitoring()
|
||||
while not notify_stop_event.is_set():
|
||||
while not notif.notification_queue.empty():
|
||||
notification = notif.notification_queue.get()
|
||||
if notification.title.find(sign) == -1:
|
||||
continue
|
||||
requests.put(f"{ip}/notification",
|
||||
data={"token": token,
|
||||
"title": notification.title,
|
||||
"content": notification.content,
|
||||
"deviceName": hostname},
|
||||
timeout=5000)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
notification_thread = threading.Thread(target=send_notification)
|
||||
# clipboard_thread = threading.Thread(target=)
|
||||
|
||||
def sendSystemNotification(title:str,content:str):
|
||||
"""
|
||||
Une fonction pour 1. rendre le truc plus secure et
|
||||
eviter que thomas face des rce sur mon pc .w. lmao
|
||||
"""
|
||||
subprocess.run(["notify-send",title,content])
|
||||
|
||||
@sio.event
|
||||
def NotificationUpdate(data):
|
||||
content = data["content"]
|
||||
clipCmd = f'echo {content} | xclip'
|
||||
print(f"[ClipEvent] received data from ")
|
||||
os.system(clipCmd)
|
||||
if data["device_name"] == hostname:
|
||||
return
|
||||
response = requests.get(f"{ip}/notification/-1?token={token}",
|
||||
timeout=2000)
|
||||
response = json.loads(response.content.decode())["notifications"]
|
||||
notification = notif.Notification(title=sign+response["title"],
|
||||
content=response["content"])
|
||||
notification.show()
|
||||
print("[NotificationEvent] received data")
|
||||
|
||||
|
||||
@sio.event
|
||||
def ClipboardUpdate(data):
|
||||
title, content = data["title"], data["content"]
|
||||
command = f'notify-send "{title}" "{content}"'
|
||||
print(command)
|
||||
os.system(command)
|
||||
if data["device_name"] == hostname:
|
||||
return
|
||||
clipboard = requests.get(f"{ip}/clipboard/-1?token={token}",
|
||||
timeout=2000)
|
||||
clipboard = json.loads(clipboard.content.decode())
|
||||
clipboard = clipboard["clipboard"]
|
||||
pyperclip.copy(clipboard)
|
||||
print("[ClipboardEvent] received data")
|
||||
|
||||
sio.wait()
|
||||
|
||||
if __name__ == "__main__":
|
||||
notification_thread.start()
|
||||
sio.wait()
|
||||
|
159
notification.py
Normal file
159
notification.py
Normal file
@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env python3
|
||||
import dbus
|
||||
import time
|
||||
import queue
|
||||
import threading
|
||||
from gi.repository import GLib
|
||||
import dbus
|
||||
from dbus.mainloop.glib import DBusGMainLoop
|
||||
|
||||
|
||||
class Notification:
|
||||
"""
|
||||
Reprensent a notification
|
||||
|
||||
:param name str:
|
||||
This is the optional name of the application sending the notification.
|
||||
This should be the application's formal name, rather than some sort of
|
||||
ID. An example would be "FredApp E-Mail Client," rather than
|
||||
"fredapp-email-client."
|
||||
|
||||
:param notification_id int:
|
||||
An optional ID of an existing notification that this notification is
|
||||
intended to replace.
|
||||
|
||||
:param notification_icon str:
|
||||
The notification icon.(not yet fully understood, use at your own risks)
|
||||
|
||||
:param title str:
|
||||
This is a single line overview of the notification. For instance, "You
|
||||
have mail" or "A friend has come online". It should generally not be
|
||||
longer than 40 characters, though this is not a requirement, and server
|
||||
implementations should word wrap if necessary.
|
||||
|
||||
:param content str:
|
||||
This is a multi-line body of text. Each line is a paragraph, server
|
||||
implementations are free to word wrap them as they see fit.
|
||||
The body mayfrom gi.repository import GLib
|
||||
import dbus
|
||||
from dbus.mainloop.glib import DBusGMainLoop
|
||||
functionality may not be implemented by the notification
|
||||
server, conforming clients should check if it is available before using
|
||||
it (see the GetCapabilities message in Protocol). An implementation is
|
||||
free to ignore any requested by the client. As an example one possible
|
||||
rendering of actions would be as buttons in the notification popup.
|
||||
Actions are sent over as a list of pairs. Each even element in the list
|
||||
(starting at index 0) represents the identifier for the action. Each
|
||||
odd element in the list is the localized string that will be displayed
|
||||
to the user. The default action (usually invoked by clicking the
|
||||
notification) should have a key named "default". The name can be
|
||||
anything, though implementations are free not to display it.
|
||||
|
||||
:param hints dict:
|
||||
Hints are a way to provide extra data to a notification server that the
|
||||
server may be able to make use of. See
|
||||
https://specifications.freedesktop.org/notification-spec/notification-\
|
||||
spec-latest.html#hints for a list of available hints.
|
||||
|
||||
:param timeout int:
|
||||
The timeout time in milliseconds since the display of the notification
|
||||
at which the notification should automatically close. If -1,
|
||||
the notification's expiration time is dependent on the notification
|
||||
server's settings, and may vary for the type of notification.
|
||||
If 0, the notification never expires.
|
||||
"""
|
||||
def __init__(self,
|
||||
name: str = "",
|
||||
notification_id: int = 0,
|
||||
notification_icon: str = "",
|
||||
title: str = "",
|
||||
content: str = "",
|
||||
actions: list = None,
|
||||
hints: dict = None,
|
||||
timeout: int = -1
|
||||
) -> None:
|
||||
self.name = name
|
||||
self.notification_id = notification_id
|
||||
self.notification_icon = notification_icon
|
||||
self.title = title
|
||||
self.content = content
|
||||
self.actions = actions if actions is not None else []
|
||||
self.hints = hints if hints is not None else {"urgency": 1}
|
||||
self.timeout = timeout
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"""{80*"_"}
|
||||
Notification :
|
||||
name = {self.name}
|
||||
notification_id = {self.notification_id}sleep
|
||||
notification_icon = {self.notification_icon}
|
||||
title = {self.title}
|
||||
content = {self.content}
|
||||
actions = {self.actions}
|
||||
hints = {self.hints}
|
||||
timeout = {self.timeout}
|
||||
{80*"_"}"""
|
||||
|
||||
def show(self):
|
||||
"""
|
||||
Display the notification by sending notification event
|
||||
to the dbus interface
|
||||
"""
|
||||
obj = dbus.Interface(dbus.SessionBus()
|
||||
.get_object("org.freedesktop.Notifications",
|
||||
"/org/freedesktop/Notifications"),
|
||||
"org.freedesktop.Notifications")
|
||||
obj.Notify(self.name,
|
||||
self.notification_id,
|
||||
self.notification_icon,
|
||||
self.title,
|
||||
self.content,
|
||||
self.actions,
|
||||
self.hints,
|
||||
self.timeout)
|
||||
|
||||
|
||||
notification_queue = queue.Queue()
|
||||
|
||||
def log_notification(bus, message):
|
||||
keys = ["app_name", "replaces_id", "app_icon", "summary",
|
||||
"body", "actions", "hints", "expire_timeout"]
|
||||
args = message.get_args_list()
|
||||
if len(args) == 8:
|
||||
notif = dict([(keys[i], args[i]) for i in range(8)])
|
||||
notif = Notification(args[0],
|
||||
args[1],
|
||||
args[2],
|
||||
args[3],
|
||||
args[4],
|
||||
list(args[5]),
|
||||
dict(args[6]),
|
||||
args[7],)
|
||||
notification_queue.put(notif)
|
||||
|
||||
|
||||
stop_event = threading.Event()
|
||||
|
||||
def monitor_notifications():
|
||||
loop = DBusGMainLoop(set_as_default=True)
|
||||
session_bus = dbus.SessionBus()
|
||||
session_bus.add_match_string(
|
||||
"type='method_call',interface='org.freedesktop.Notifications'\
|
||||
,member='Notify',eavesdrop=true")
|
||||
session_bus.add_message_filter(log_notification)
|
||||
while not stop_event.is_set():
|
||||
GLib.MainLoop().run()
|
||||
|
||||
thread = threading.Thread(target=monitor_notifications)
|
||||
thread.daemon = True
|
||||
|
||||
|
||||
def start_monitoring():
|
||||
thread.start()
|
||||
|
||||
def stop_monitoring():
|
||||
stop_event.set()
|
||||
|
||||
if __name__ == "__main__":
|
||||
n = Notification(title="test",content="je suis le test")
|
||||
n.show()
|
80
serveur.py
80
serveur.py
@ -116,7 +116,10 @@ def add_notification():
|
||||
notification)
|
||||
con.commit()
|
||||
con.close()
|
||||
socketio.emit("NotificationUpdate", broadcast=True)
|
||||
socketio.emit("NotificationUpdate",
|
||||
data={"device_name": device_name},
|
||||
broadcast=True)
|
||||
|
||||
return {"status": "ok"}, 200
|
||||
except:
|
||||
return {"status": "error"}, 500
|
||||
@ -132,9 +135,46 @@ def get_notifications():
|
||||
token = request.values.get("token")
|
||||
con = sqlite3.connect("database.db")
|
||||
cur = con.cursor()
|
||||
notifications = cur.execute("SELECT title,content FROM NOTIFICATION WHERE \
|
||||
token=?", (token, )).fetchall()
|
||||
return {"status": "ok", "notifications": notifications}, 200
|
||||
notifications = cur.execute("SELECT title,content \
|
||||
FROM NOTIFICATION \
|
||||
WHERE token=?",
|
||||
(token, )).fetchall()
|
||||
data = {"status": "ok"}
|
||||
data["notifications"] = []
|
||||
for notification in notifications:
|
||||
data["notifications"].append({"title": notification[0],"content": notification[1]})
|
||||
return data, 200
|
||||
|
||||
|
||||
@app.route("/notification/<notifid>", methods=['GET'])
|
||||
def get_notification_by_id(notifid):
|
||||
"""
|
||||
Le but de cet app se resume a cette fonction, elle recoit une requete
|
||||
http et renvoie via le websocket le contenu de la requette a tout les
|
||||
client.
|
||||
"""
|
||||
notifid = int(notifid)
|
||||
token = request.values.get("token")
|
||||
con = sqlite3.connect("database.db")
|
||||
cur = con.cursor()
|
||||
if notifid == -1:
|
||||
notifications = cur.execute("SELECT title,content \
|
||||
FROM NOTIFICATION \
|
||||
WHERE token=?\
|
||||
ORDER BY id DESC \
|
||||
LIMIT 1",
|
||||
(token,)).fetchone()
|
||||
else:
|
||||
notifications = cur.execute("SELECT title,content \
|
||||
FROM NOTIFICATION \
|
||||
WHERE token=? AND id=?",
|
||||
(token, notifid)).fetchone()
|
||||
|
||||
return {"status": "ok",
|
||||
"notifications": {"title": notifications[0],
|
||||
"content": notifications[1]
|
||||
}
|
||||
}, 200
|
||||
|
||||
###############################################################################
|
||||
|
||||
@ -159,7 +199,9 @@ def add_clipboard():
|
||||
cur.execute("INSERT INTO CLIPBOARD VALUES (null,?,?,?,?)", clipboard)
|
||||
con.commit()
|
||||
con.close()
|
||||
socketio.emit("ClipboardUpdate", broadcast=True)
|
||||
socketio.emit("ClipboardUpdate",
|
||||
data={"device_name": device_name},
|
||||
broadcast=True)
|
||||
return {"status": "ok"}, 200
|
||||
except:
|
||||
return {"status": "error"}, 500
|
||||
@ -175,10 +217,14 @@ def get_clipboard():
|
||||
token = request.values.get("token")
|
||||
con = sqlite3.connect("database.db")
|
||||
cur = con.cursor()
|
||||
clipboard = cur.execute("SELECT content, id FROM CLIPBOARD WHERE \
|
||||
token=?", (token, )).fetchall()
|
||||
clipboard = cur.execute("SELECT content \
|
||||
FROM CLIPBOARD \
|
||||
WHERE token=?",
|
||||
(token, )).fetchall()
|
||||
|
||||
return {"status": "ok", "clipboard": clipboard}, 200
|
||||
|
||||
|
||||
@app.route("/clipboard/<clipid>", methods=['GET'])
|
||||
def get_clipboard_by_id(clipid):
|
||||
"""
|
||||
@ -191,19 +237,19 @@ def get_clipboard_by_id(clipid):
|
||||
con = sqlite3.connect("database.db")
|
||||
cur = con.cursor()
|
||||
if clipid == -1:
|
||||
clipboard = cur.execute("SELECT content,id \
|
||||
FROM CLIPBOARD \
|
||||
WHERE token=? \
|
||||
ORDER BY id DESC \
|
||||
LIMIT 1",
|
||||
(token,)).fetchall()
|
||||
clipboard = cur.execute("SELECT content \
|
||||
FROM CLIPBOARD \
|
||||
WHERE token=? \
|
||||
ORDER BY id DESC \
|
||||
LIMIT 1",
|
||||
(token,)).fetchone()
|
||||
else:
|
||||
clipboard = cur.execute("SELECT content,id FROM CLIPBOARD WHERE \
|
||||
token=? AND\
|
||||
id=?",
|
||||
clipboard = cur.execute("SELECT content \
|
||||
FROM CLIPBOARD \
|
||||
token=? AND id=?",
|
||||
(token, clipid)).fetchone()
|
||||
|
||||
return {"status": "ok", "clipboard": clipboard}, 200
|
||||
return {"status": "ok", "clipboard": clipboard[0]}, 200
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
Reference in New Issue
Block a user