-
Notifications
You must be signed in to change notification settings - Fork 0
/
bot.py
142 lines (110 loc) · 4.84 KB
/
bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import asyncio
from datetime import datetime
from textwrap import dedent
from urllib.parse import urlencode
import aiohttp
import dateutil
import discord
from slugify import slugify
from email_server import email_view_server
from config import load_config
from email_scraper import *
config = load_config()
def formatted_current_time():
return (
datetime
.now(tz=dateutil.tz.gettz("US/Eastern"))
.strftime("%A, %B %d, %Y %I:%M:%S %p %Z")
)
def get_email_viewer_url(email_url):
return f"{config["viewer_host"]}/?{urlencode({'email_url': email_url})}"
def get_email_metadata_embed(email_meta, email_url):
return discord.Embed(
title=email_meta.subject,
description=f"*from* {email_meta.from_address}",
url=get_email_viewer_url(email_url) if email_meta.has_html else email_url,
timestamp=email_meta.timestamp
)
async def get_email_image_file(session, email_meta, email_url):
image = await get_email_image(session, email_url)
return discord.File(
image,
f"email_{slugify(email_meta.subject)}.png"
)
async def check_mail_forever():
global config
async with aiohttp.ClientSession() as webhook_session:
webhook = discord.Webhook.from_url(config["webhook_url"], session=webhook_session)
listmail_session = login(config["email_password"])
last_email_url = get_last_email_url(get_recent_email_urls(listmail_session))
last_email_id = email_url_to_id(last_email_url)
print(f"will alert for emails with IDs greater than {last_email_id}")
email_meta = get_email_metadata(listmail_session, last_email_url)
discord_embed = get_email_metadata_embed(email_meta, last_email_url)
await webhook.send(
"Email bot is active. Most recent email in inbox is:",
embed = discord_embed,
file = await get_email_image_file(
listmail_session, email_meta, last_email_url
)
)
if "release_notes" in config and len(config["release_notes"]):
await webhook.send("Release notes: " + config["release_notes"])
while True:
try:
# reload config in case it changed
config = load_config()
# check for emails newer than the last one observed
listmail_session = login(config["email_password"])
emails = get_recent_email_urls(listmail_session)
for email_url in emails:
if email_url_to_id(email_url) > last_email_id:
email_meta = get_email_metadata(listmail_session, email_url)
discord_embed = get_email_metadata_embed(email_meta, email_url)
print(f"sending message for email {email_url} at {formatted_current_time()}")
async with aiohttp.ClientSession() as webhook_session:
webhook = discord.Webhook.from_url(
config["webhook_url"], session=webhook_session
)
await webhook.send(
"You've got mail!",
embed = discord_embed,
file = await get_email_image_file(
listmail_session, email_meta, email_url
)
)
# update ID of the last email observed
new_last_email_id = email_url_to_id(get_last_email_url(emails))
if new_last_email_id != last_email_id:
print(f"will now alert for emails with IDs greater than {new_last_email_id}")
last_email_id = new_last_email_id
except Exception as e:
async with aiohttp.ClientSession() as webhook_session:
error_message = dedent(f"""
Failed to load emails! Error message:
```
{e}
```
Trying again in 10 minutes.
"""
).strip()
await discord.Webhook.from_url(
config["webhook_url"], session=webhook_session
).send(error_message)
# wait an extra 7 minutes to try to mitigate spam if something is
# persistently wrong
await asyncio.sleep(60 * 7)
# check again in 3 minutes
await asyncio.sleep(60 * 3)
async def main():
email_view_server.listen(8888)
print("email viewer listening on port 8888")
print("starting webhook-based discord bot")
await asyncio.create_task(check_mail_forever())
if __name__ == "__main__":
# discord.utils.setup_logging(level=logging.DEBUG, root=False)
try:
asyncio.run(main())
except KeyboardInterrupt:
print("exiting due to Ctrl-C")
exit()