Skip to content

Instantly share code, notes, and snippets.

@nick-merrill
Last active October 24, 2022 22:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nick-merrill/9378c56a4642c1728a35200a570a67f3 to your computer and use it in GitHub Desktop.
Save nick-merrill/9378c56a4642c1728a35200a570a67f3 to your computer and use it in GitHub Desktop.
Gmail Checker for xbar
#!/usr/bin/python3
# <xbar.title>Gmail Checker</xbar.title>
# <xbar.version>v0.0.1</xbar.version>
# <xbar.author>Nick Merrill</xbar.author>
# <xbar.author.github>nick.merrill</xbar.author.github>
# <xbar.desc>Checks gmail and displays inbox count</xbar.desc>
import xml.etree.ElementTree as ET
from dataclasses import dataclass
from datetime import datetime
import os
import requests
import pytz
from dateutil import parser
USERNAME = "YOUR_EMAIL"
PASSWORD = "YOUR_PASSWORD"
ONE_HOUR_IN_SECONDS = 60 * 60
HIGHLIGHT_DURATION_S = 3 * ONE_HOUR_IN_SECONDS
ALL_MAIL = "https://mail.google.com/mail/feed/atom"
PRIMARY_INBOX = "https://mail.google.com/mail/feed/atom/%5Esq_ig_i_personal"
def main():
is_dark_mode = os.environ.get("BitBarDarkMode", "false") == "true"
color = "white"
size = 12
response = requests.get(PRIMARY_INBOX, auth=(USERNAME, PASSWORD))
if response.status_code != 200:
print(f"📬 XXX|color=red \n---\n{response.content}")
return
parsed = ET.fromstring(response.content)
emails = []
for email_elt in parsed.iterfind("./{http://purl.org/atom/ns#}entry"):
emails.append(
Email(
title=email_elt.find("./{http://purl.org/atom/ns#}title").text,
href=email_elt.find("./{http://purl.org/atom/ns#}link").get("href"),
sender=email_elt.find("./{http://purl.org/atom/ns#}author/{http://purl.org/atom/ns#}name").text,
latest_update_at=parser.isoparse(email_elt.find("./{http://purl.org/atom/ns#}modified").text),
)
)
count = int(parsed.find("./{http://purl.org/atom/ns#}fullcount").text)
recent_emails = {email for email in emails if email.sent_ago_s < HIGHLIGHT_DURATION_S}
if len(recent_emails) > 0:
color = "blue"
size = 16
if count > 0:
text = f"📬 {count}"
else:
text = "📭"
print(f"{escape(text)}|color={color} size={size}\n---\nOpen Gmail|href=https://mail.google.com/mail/u/0/#inbox")
for email in emails:
email_color = "blue" if email in recent_emails else "black"
text = f"【{email.sent_ago}】 {email.sender} ➢ {email.title}"
print(f"{escape(text)}|href={email.href} color={email_color}")
@dataclass
class Email:
title: str
href: str
sender: str
latest_update_at: datetime
@property
def sent_ago_s(self) -> float:
now = datetime.now(pytz.utc)
seconds_ago = (now - self.latest_update_at).total_seconds()
return seconds_ago
@property
def sent_ago(self) -> str:
seconds_ago = self.sent_ago_s
minutes_ago = round(seconds_ago / 60)
if minutes_ago < 60:
return f"{minutes_ago}m"
hours_ago = round(minutes_ago / 60)
if hours_ago < 24:
return f"{hours_ago}h"
days_ago = round(hours_ago / 24)
return f"{days_ago}d"
def __hash__(self):
return hash(self.href)
def escape(text):
# The pipe character deliminates parameters for xbar, so we must escape it.
# The replacement here is U+01C0.
return text.replace("|", "ǀ")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment