unread.py
· 5.5 KiB · Python
Raw
#!/usr/bin/env python3
c = {
"client_id": "",
"client_secret": "",
"refresh_token": "" # obtained after running script for first time
}
import os
import sys
import time
try:
import requests
except ImportError:
print("pip install requests")
sys.exit(1)
if sys.platform == "win32":
try:
import win32con
import win32gui
from win32api import GetModuleHandle
except ImportError:
print("Install pywin32 from https://sourceforge.net/projects/pywin32/files/pywin32/")
sys.exit(1)
elif sys.platform == "linux": # Untested
try:
import notify2
except ImportError:
print("pip install notify2, uses dbus notifications")
sys.exit(1)
elif sys.platform == "darwin": # Untested
try:
from pync import Notifier
except ImportError:
print("pip install pync")
sys.exit(1)
if not c["client_id"] or not c["client_secret"]:
print("Set client_id and client_secret (create a script app)")
sys.exit(1)
if not c["refresh_token"]:
import webbrowser
webbrowser.open("https://www.reddit.com/api/v1/authorize?client_id=" + c["client_id"] + "&response_type=code&state=a&redirect_uri=http://localhost&scope=identity,privatemessages&duration=permanent")
code = input("Code: ").strip()
if code:
print(requests.post("https://www.reddit.com/api/v1/access_token", auth=(c["client_id"], c["client_secret"]), headers={"User-Agent": "Unread by /u/suudo"}, data={"grant_type": "authorization_code", "code": code, "redirect_uri": "http://localhost"}).json()["refresh_token"])
sys.exit(1)
else:
print("No code entered")
sys.exit(1)
if sys.platform == "win32":
class Notifier:
def __init__(self, msg, title="Unread"):
# This obscure block of code brought to you by the letters "not pythonic"
# From https://github.com/K-DawG007/Stack-Watch/blob/master/windows_popup.py, adapted from dead url https://gist.github.com/brousch/6523559
message_map = {win32con.WM_DESTROY: self.OnDestroy, }
wc = win32gui.WNDCLASS()
self.destroyed = False
hinst = wc.hInstance = GetModuleHandle(None)
wc.lpszClassName = "PythonTaskbar"
wc.lpfnWndProc = message_map
class_atom = win32gui.RegisterClass(wc)
style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
self.hwnd = win32gui.CreateWindow(class_atom, "Taskbar", style,
0, 0, win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT, 0, 0,
hinst, None)
win32gui.UpdateWindow(self.hwnd)
icon_path_name = os.path.abspath(os.path.join(sys.path[0],
"balloontip.ico"))
icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
try:
hicon = win32gui.LoadImage(hinst, icon_path_name,
win32con.IMAGE_ICON, 0, 0, icon_flags)
except:
hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP
nid = (self.hwnd, 0, flags, win32con.WM_USER+20, hicon, "tooltip")
win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, nid)
win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY,
(self.hwnd, 0, win32gui.NIF_INFO,
win32con.WM_USER+20, hicon,
"Balloon tooltip", msg, 200, title))
time.sleep(10)
win32gui.DestroyWindow(self.hwnd)
win32gui.UnregisterClass(class_atom, hinst)
self.destroyed = True
def OnDestroy(self, hwnd, msg, wparam, lparam):
nid = (self.hwnd, 0)
win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid)
win32gui.PostQuitMessage(0) # Terminate the app.
def isDestroyed(self):
return self.destroyed
elif sys.platform == "linux": # Untested
class Notifier:
def __init__(self, msg, title="Unread"):
n = notify2.Notification(title, msg, "notification-message-im")
n.show()
return n
elif sys.platform == "darwin": # Untested
pass # Notifier class already imported with pync
def truncate(text):
if len(text) > 150:
return text[:147] + "..."
return text
def main():
token = requests.post("https://www.reddit.com/api/v1/access_token", auth=(c["client_id"], c["client_secret"]), headers={"User-Agent": "Unread by /u/suudo"}, data={"grant_type": "refresh_token", "refresh_token": c["refresh_token"]}).json()["access_token"]
h = {"User-Agent": "Unread by /u/suudo", "Authorization": "Bearer " + token}
messages = requests.get("https://oauth.reddit.com/message/unread", headers=h).json()["data"]["children"]
if len(messages) > 1:
n = Notifier("\n".join(
"/u/{}: {}".format(m["data"]["author"], truncate(m["data"]["body"])) for m in messages
), "Unread: New messages from")
elif messages:
message = messages[0]["data"]
text = message["body"]
n = Notifier(truncate(message["body"]),
"Unread: New {} from /u/{}".format("comment" if message["was_comment"] else "message", message["author"]) )
# requests.post("https://oauth.reddit.com/api/read_all_messages", headers=h)
if __name__ == "__main__":
main()
| 1 | #!/usr/bin/env python3 |
| 2 | c = { |
| 3 | "client_id": "", |
| 4 | "client_secret": "", |
| 5 | "refresh_token": "" # obtained after running script for first time |
| 6 | } |
| 7 | |
| 8 | import os |
| 9 | import sys |
| 10 | import time |
| 11 | try: |
| 12 | import requests |
| 13 | except ImportError: |
| 14 | print("pip install requests") |
| 15 | sys.exit(1) |
| 16 | if sys.platform == "win32": |
| 17 | try: |
| 18 | import win32con |
| 19 | import win32gui |
| 20 | from win32api import GetModuleHandle |
| 21 | except ImportError: |
| 22 | print("Install pywin32 from https://sourceforge.net/projects/pywin32/files/pywin32/") |
| 23 | sys.exit(1) |
| 24 | elif sys.platform == "linux": # Untested |
| 25 | try: |
| 26 | import notify2 |
| 27 | except ImportError: |
| 28 | print("pip install notify2, uses dbus notifications") |
| 29 | sys.exit(1) |
| 30 | elif sys.platform == "darwin": # Untested |
| 31 | try: |
| 32 | from pync import Notifier |
| 33 | except ImportError: |
| 34 | print("pip install pync") |
| 35 | sys.exit(1) |
| 36 | |
| 37 | if not c["client_id"] or not c["client_secret"]: |
| 38 | print("Set client_id and client_secret (create a script app)") |
| 39 | sys.exit(1) |
| 40 | |
| 41 | if not c["refresh_token"]: |
| 42 | import webbrowser |
| 43 | webbrowser.open("https://www.reddit.com/api/v1/authorize?client_id=" + c["client_id"] + "&response_type=code&state=a&redirect_uri=http://localhost&scope=identity,privatemessages&duration=permanent") |
| 44 | code = input("Code: ").strip() |
| 45 | if code: |
| 46 | print(requests.post("https://www.reddit.com/api/v1/access_token", auth=(c["client_id"], c["client_secret"]), headers={"User-Agent": "Unread by /u/suudo"}, data={"grant_type": "authorization_code", "code": code, "redirect_uri": "http://localhost"}).json()["refresh_token"]) |
| 47 | sys.exit(1) |
| 48 | else: |
| 49 | print("No code entered") |
| 50 | sys.exit(1) |
| 51 | |
| 52 | if sys.platform == "win32": |
| 53 | class Notifier: |
| 54 | def __init__(self, msg, title="Unread"): |
| 55 | # This obscure block of code brought to you by the letters "not pythonic" |
| 56 | # From https://github.com/K-DawG007/Stack-Watch/blob/master/windows_popup.py, adapted from dead url https://gist.github.com/brousch/6523559 |
| 57 | message_map = {win32con.WM_DESTROY: self.OnDestroy, } |
| 58 | wc = win32gui.WNDCLASS() |
| 59 | self.destroyed = False |
| 60 | hinst = wc.hInstance = GetModuleHandle(None) |
| 61 | wc.lpszClassName = "PythonTaskbar" |
| 62 | wc.lpfnWndProc = message_map |
| 63 | class_atom = win32gui.RegisterClass(wc) |
| 64 | style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU |
| 65 | self.hwnd = win32gui.CreateWindow(class_atom, "Taskbar", style, |
| 66 | 0, 0, win32con.CW_USEDEFAULT, |
| 67 | win32con.CW_USEDEFAULT, 0, 0, |
| 68 | hinst, None) |
| 69 | win32gui.UpdateWindow(self.hwnd) |
| 70 | icon_path_name = os.path.abspath(os.path.join(sys.path[0], |
| 71 | "balloontip.ico")) |
| 72 | icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE |
| 73 | try: |
| 74 | hicon = win32gui.LoadImage(hinst, icon_path_name, |
| 75 | win32con.IMAGE_ICON, 0, 0, icon_flags) |
| 76 | except: |
| 77 | hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION) |
| 78 | flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP |
| 79 | nid = (self.hwnd, 0, flags, win32con.WM_USER+20, hicon, "tooltip") |
| 80 | win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, nid) |
| 81 | win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, |
| 82 | (self.hwnd, 0, win32gui.NIF_INFO, |
| 83 | win32con.WM_USER+20, hicon, |
| 84 | "Balloon tooltip", msg, 200, title)) |
| 85 | time.sleep(10) |
| 86 | win32gui.DestroyWindow(self.hwnd) |
| 87 | win32gui.UnregisterClass(class_atom, hinst) |
| 88 | self.destroyed = True |
| 89 | |
| 90 | def OnDestroy(self, hwnd, msg, wparam, lparam): |
| 91 | nid = (self.hwnd, 0) |
| 92 | win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid) |
| 93 | win32gui.PostQuitMessage(0) # Terminate the app. |
| 94 | |
| 95 | def isDestroyed(self): |
| 96 | return self.destroyed |
| 97 | elif sys.platform == "linux": # Untested |
| 98 | class Notifier: |
| 99 | def __init__(self, msg, title="Unread"): |
| 100 | n = notify2.Notification(title, msg, "notification-message-im") |
| 101 | n.show() |
| 102 | return n |
| 103 | elif sys.platform == "darwin": # Untested |
| 104 | pass # Notifier class already imported with pync |
| 105 | |
| 106 | def truncate(text): |
| 107 | if len(text) > 150: |
| 108 | return text[:147] + "..." |
| 109 | return text |
| 110 | |
| 111 | def main(): |
| 112 | token = requests.post("https://www.reddit.com/api/v1/access_token", auth=(c["client_id"], c["client_secret"]), headers={"User-Agent": "Unread by /u/suudo"}, data={"grant_type": "refresh_token", "refresh_token": c["refresh_token"]}).json()["access_token"] |
| 113 | h = {"User-Agent": "Unread by /u/suudo", "Authorization": "Bearer " + token} |
| 114 | messages = requests.get("https://oauth.reddit.com/message/unread", headers=h).json()["data"]["children"] |
| 115 | if len(messages) > 1: |
| 116 | n = Notifier("\n".join( |
| 117 | "/u/{}: {}".format(m["data"]["author"], truncate(m["data"]["body"])) for m in messages |
| 118 | ), "Unread: New messages from") |
| 119 | elif messages: |
| 120 | message = messages[0]["data"] |
| 121 | text = message["body"] |
| 122 | n = Notifier(truncate(message["body"]), |
| 123 | "Unread: New {} from /u/{}".format("comment" if message["was_comment"] else "message", message["author"]) ) |
| 124 | # requests.post("https://oauth.reddit.com/api/read_all_messages", headers=h) |
| 125 | |
| 126 | if __name__ == "__main__": |
| 127 | main() |