#!/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()