unread.py
                        
                             · 5.3 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"):
            message_map = {win32con.WM_DESTROY: self.OnDestroy, }
            wc = win32gui.WNDCLASS()
            self.destroyed = False
            hinst = wc.hInstance = GetModuleHandle(None)
            wc.lpszClassName = "PythonTaskbar{}".format(str(time.time()))
            wc.lpfnWndProc = message_map    # could also specify a wndproc.
            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 | message_map = {win32con.WM_DESTROY: self.OnDestroy, } | 
| 56 | wc = win32gui.WNDCLASS() | 
| 57 | self.destroyed = False | 
| 58 | hinst = wc.hInstance = GetModuleHandle(None) | 
| 59 | wc.lpszClassName = "PythonTaskbar{}".format(str(time.time())) | 
| 60 | wc.lpfnWndProc = message_map # could also specify a wndproc. | 
| 61 | class_atom = win32gui.RegisterClass(wc) | 
| 62 | style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU | 
| 63 | self.hwnd = win32gui.CreateWindow(class_atom, "Taskbar", style, | 
| 64 | 0, 0, win32con.CW_USEDEFAULT, | 
| 65 | win32con.CW_USEDEFAULT, 0, 0, | 
| 66 | hinst, None) | 
| 67 | win32gui.UpdateWindow(self.hwnd) | 
| 68 | icon_path_name = os.path.abspath(os.path.join(sys.path[0], | 
| 69 | "balloontip.ico")) | 
| 70 | icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE | 
| 71 | try: | 
| 72 | hicon = win32gui.LoadImage(hinst, icon_path_name, | 
| 73 | win32con.IMAGE_ICON, 0, 0, icon_flags) | 
| 74 | except: | 
| 75 | hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION) | 
| 76 | flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP | 
| 77 | nid = (self.hwnd, 0, flags, win32con.WM_USER+20, hicon, "tooltip") | 
| 78 | win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, nid) | 
| 79 | win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, | 
| 80 | (self.hwnd, 0, win32gui.NIF_INFO, | 
| 81 | win32con.WM_USER+20, hicon, | 
| 82 | "Balloon tooltip", msg, 200, title)) | 
| 83 | time.sleep(10) | 
| 84 | win32gui.DestroyWindow(self.hwnd) | 
| 85 | win32gui.UnregisterClass(class_atom, hinst) | 
| 86 | self.destroyed = True | 
| 87 | |
| 88 | def OnDestroy(self, hwnd, msg, wparam, lparam): | 
| 89 | nid = (self.hwnd, 0) | 
| 90 | win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid) | 
| 91 | win32gui.PostQuitMessage(0) # Terminate the app. | 
| 92 | |
| 93 | def isDestroyed(self): | 
| 94 | return self.destroyed | 
| 95 | elif sys.platform == "linux": # Untested | 
| 96 | class Notifier: | 
| 97 | def __init__(self, msg, title="Unread"): | 
| 98 | n = notify2.Notification(title, msg, "notification-message-im") | 
| 99 | n.show() | 
| 100 | return n | 
| 101 | elif sys.platform == "darwin": # Untested | 
| 102 | pass # Notifier class already imported with pync | 
| 103 | |
| 104 | def truncate(text): | 
| 105 | if len(text) > 150: | 
| 106 | return text[:147] + "..." | 
| 107 | return text | 
| 108 | |
| 109 | def main(): | 
| 110 | 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"] | 
| 111 | h = {"User-Agent": "Unread by /u/suudo", "Authorization": "Bearer " + token} | 
| 112 | messages = requests.get("https://oauth.reddit.com/message/unread", headers=h).json()["data"]["children"] | 
| 113 | if len(messages) > 1: | 
| 114 | n = Notifier("\n".join( | 
| 115 | "/u/{}: {}".format(m["data"]["author"], truncate(m["data"]["body"])) for m in messages | 
| 116 | ), "Unread: New messages from") | 
| 117 | elif messages: | 
| 118 | message = messages[0]["data"] | 
| 119 | text = message["body"] | 
| 120 | n = Notifier(truncate(message["body"]), | 
| 121 | "Unread: New {} from /u/{}".format("comment" if message["was_comment"] else "message", message["author"]) ) | 
| 122 | # requests.post("https://oauth.reddit.com/api/read_all_messages", headers=h) | 
| 123 | |
| 124 | if __name__ == "__main__": | 
| 125 | main() |