Spaces:
Sleeping
Sleeping
Commit
·
f07275b
1
Parent(s):
016c36e
Add initial implementation of ReXplore Blog Poster app with email functionality and environment configuration
Browse files- .gitignore +1 -0
- app.py +54 -0
- post_blog.py +110 -0
- requirements.txt +5 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.env
|
app.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from post_blog import main
|
3 |
+
|
4 |
+
def post_blog(title, category, summary, mindmap, citation, access_key):
|
5 |
+
status = main(title, category, summary, mindmap, citation, access_key)
|
6 |
+
return status
|
7 |
+
|
8 |
+
def clear_everything(title, category, summary, mindmap, citation, status, access_key):
|
9 |
+
return None, None, None, None, None, None, None
|
10 |
+
|
11 |
+
theme = gr.themes.Soft(
|
12 |
+
primary_hue="purple",
|
13 |
+
secondary_hue="cyan",
|
14 |
+
neutral_hue="slate",
|
15 |
+
font=[
|
16 |
+
gr.themes.GoogleFont("Syne"),
|
17 |
+
gr.themes.GoogleFont("Poppins"),
|
18 |
+
gr.themes.GoogleFont("Poppins"),
|
19 |
+
gr.themes.GoogleFont("Poppins")
|
20 |
+
],
|
21 |
+
)
|
22 |
+
|
23 |
+
with gr.Blocks(theme=theme, title="ReXplore Blog Poster", fill_height=True) as app:
|
24 |
+
gr.HTML(
|
25 |
+
value ="""
|
26 |
+
<h1 style="text-align: center;">ReXplore Blog Poster <p style="text-align: center;">Designed and Developed by <a href="https://raannakasturi.eu.org" target="_blank" rel="nofollow noreferrer external">Nayan Kasturi</a></p> </h1>
|
27 |
+
<p style="text-align: center;">This app posts Blogs to Blogger.</p>
|
28 |
+
""")
|
29 |
+
with gr.Column():
|
30 |
+
with gr.Row():
|
31 |
+
title = gr.Textbox(label="Title", placeholder="Enter Blog Title")
|
32 |
+
category = gr.Textbox(label="Category", placeholder="Enter Blog Category")
|
33 |
+
access_key = gr.Textbox(label="Access Key", placeholder="Enter the Access Key", type="password")
|
34 |
+
with gr.Row():
|
35 |
+
summary = gr.Textbox(label="Summary", placeholder="Enter the summary", lines=7)
|
36 |
+
mindmap = gr.Textbox(label="Mindmap", placeholder="Enter the mindmap", lines=7)
|
37 |
+
citation = gr.Textbox(label="Citation", placeholder="Enter the citation", lines=7)
|
38 |
+
with gr.Row():
|
39 |
+
clear_btn = gr.Button(value="Clear", variant="stop")
|
40 |
+
summarize_btn = gr.Button(value="Summarize", variant="primary")
|
41 |
+
status = gr.Textbox(label="Status", placeholder="Blog Post Status", interactive=False)
|
42 |
+
summarize_btn.click(
|
43 |
+
post_blog,
|
44 |
+
inputs=[category, title, summary, mindmap, citation, access_key],
|
45 |
+
outputs=[status],
|
46 |
+
concurrency_limit=25,
|
47 |
+
scroll_to_output=True,
|
48 |
+
show_api=True,
|
49 |
+
api_name="rexplore_blog_poster",
|
50 |
+
show_progress="full",
|
51 |
+
)
|
52 |
+
clear_btn.click(clear_everything, inputs=[category, title, summary, mindmap, citation, access_key, status], outputs=[category, title, summary, mindmap, citation, access_key, status], show_api=False)
|
53 |
+
|
54 |
+
app.queue(default_concurrency_limit=25).launch(show_api=True)
|
post_blog.py
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import re
|
2 |
+
import os
|
3 |
+
import dotenv
|
4 |
+
import mistune
|
5 |
+
import smtplib
|
6 |
+
from email.mime.text import MIMEText
|
7 |
+
from email.mime.multipart import MIMEMultipart
|
8 |
+
|
9 |
+
dotenv.load_dotenv()
|
10 |
+
|
11 |
+
def generate_post_html(title, summary, mindmap, citation):
|
12 |
+
html_summary = mistune.html(summary)
|
13 |
+
post = f"""
|
14 |
+
<!DOCTYPE html>
|
15 |
+
<html lang="en">
|
16 |
+
<head>
|
17 |
+
<meta charset="UTF-8">
|
18 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
19 |
+
<title>{title}</title>
|
20 |
+
</head>
|
21 |
+
<body>
|
22 |
+
<script src="https://cdn.jsdelivr.net/npm/markmap-autoloader@latest"></script>
|
23 |
+
<style>
|
24 |
+
.markmap {{
|
25 |
+
position: relative;
|
26 |
+
}}
|
27 |
+
.markmap > svg {{
|
28 |
+
width: 100%;
|
29 |
+
border: 2px solid #000;
|
30 |
+
height: 80dvh;
|
31 |
+
}}
|
32 |
+
</style>
|
33 |
+
<h1 id="paper_title" data="{title.replace("&", "&")}">{title.replace("&", "&")}</h1>
|
34 |
+
<hr>
|
35 |
+
<br>
|
36 |
+
<h2>SUMMARY</h2>
|
37 |
+
<p id="paper_summary" data="{summary.replace("&", "&")}">
|
38 |
+
{html_summary.replace("&", "&")}
|
39 |
+
</p>
|
40 |
+
<br>
|
41 |
+
<br>
|
42 |
+
<h2>MINDMAP</h2>
|
43 |
+
<div class="markmap" data="{mindmap.replace("&", "&")}">
|
44 |
+
<script type="text/template">
|
45 |
+
# {title.replace("&", "&")}
|
46 |
+
{mindmap.replace("&", "&")}
|
47 |
+
</script>
|
48 |
+
</div>
|
49 |
+
<br>
|
50 |
+
<br>
|
51 |
+
<h2>CITATION</h2>
|
52 |
+
<p id="paper_citation" data="{citation.replace("&", "&")}">
|
53 |
+
{mistune.html(citation.replace("&", "&"))}
|
54 |
+
</p>
|
55 |
+
</body>
|
56 |
+
</html>
|
57 |
+
#end
|
58 |
+
"""
|
59 |
+
return post
|
60 |
+
|
61 |
+
def sanitize_citation(citation):
|
62 |
+
pattern = r"(https://doi\.org/\S+)"
|
63 |
+
sanitized_citation = re.sub(
|
64 |
+
pattern,
|
65 |
+
lambda match: f"[{match.group(1)}](https://doi.org/{match.group(1).split('/')[-1]})",
|
66 |
+
citation
|
67 |
+
)
|
68 |
+
return sanitized_citation
|
69 |
+
|
70 |
+
|
71 |
+
def create_post(title, category, summary, mindmap, citation):
|
72 |
+
mail_title = f"[{category}] {title}"
|
73 |
+
mail_body = generate_post_html(title, summary, mindmap, sanitize_citation(citation))
|
74 |
+
return mail_title, mail_body
|
75 |
+
|
76 |
+
def send_mail(mail_title, mail_body):
|
77 |
+
sender_email = os.getenv('SENDER_EMAIL')
|
78 |
+
sender_password = os.getenv('SENDER_PASSWORD')
|
79 |
+
receiver_email = os.getenv('RECEIVER_EMAIL')
|
80 |
+
msg = MIMEMultipart()
|
81 |
+
msg['From'] = sender_email
|
82 |
+
msg['To'] = receiver_email
|
83 |
+
msg['Subject'] = mail_title
|
84 |
+
msg.attach(MIMEText(mail_body, 'HTML'))
|
85 |
+
smtp_server = os.getenv('SMTP_SERVER')
|
86 |
+
smtp_port = os.getenv('SMTP_PORT')
|
87 |
+
res = None
|
88 |
+
try:
|
89 |
+
server = smtplib.SMTP(smtp_server, smtp_port)
|
90 |
+
server.starttls()
|
91 |
+
server.login(sender_email, sender_password)
|
92 |
+
text = msg.as_string()
|
93 |
+
server.sendmail(sender_email, receiver_email, text)
|
94 |
+
print('Email sent successfully')
|
95 |
+
except Exception as e:
|
96 |
+
print('Email not sent. An error occurred:', str(e))
|
97 |
+
finally:
|
98 |
+
server.quit()
|
99 |
+
return res
|
100 |
+
|
101 |
+
def main(title, category, summary, mindmap, citation, access_key):
|
102 |
+
if access_key != os.getenv('ACCESS_KEY'):
|
103 |
+
return False
|
104 |
+
try:
|
105 |
+
mail_title, mail_body = create_post(title, category, summary, mindmap, citation)
|
106 |
+
send_mail(mail_title, mail_body)
|
107 |
+
return True
|
108 |
+
except Exception as e:
|
109 |
+
print('An error occurred:', str(e))
|
110 |
+
return False
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
nbconvert>=7
|
3 |
+
mistune>=2
|
4 |
+
email
|
5 |
+
python-dotenv
|