Last active
March 9, 2017 18:17
-
-
Save blha303/2d8a9bdabfef832e07e5f26793ec52b0 to your computer and use it in GitHub Desktop.
Unread, a python script that can be set up in a scheduler to show desktop notifications for Reddit messages. Cross platform!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment