{{ title }}
55 |Publication Date:
65 |Summary: {{ summary }}
71 |Sentiment: {{ sentiment }}
72 |├── image.png
├── .gitattributes
├── requirements.txt
├── static
├── logo.jpeg
├── tumbnail.png
├── favicon_io
│ ├── favicon.ico
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── apple-touch-icon.png
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ └── site.webmanifest
├── light-theme.css
└── dark-theme.css
├── .github
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── LICENSE
├── app.py
├── README.md
├── CODE_OF_CONDUCT.md
└── templates
└── index.html
/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/image.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/requirements.txt
--------------------------------------------------------------------------------
/static/logo.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/static/logo.jpeg
--------------------------------------------------------------------------------
/static/tumbnail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/static/tumbnail.png
--------------------------------------------------------------------------------
/static/favicon_io/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/static/favicon_io/favicon.ico
--------------------------------------------------------------------------------
/static/favicon_io/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/static/favicon_io/favicon-16x16.png
--------------------------------------------------------------------------------
/static/favicon_io/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/static/favicon_io/favicon-32x32.png
--------------------------------------------------------------------------------
/static/favicon_io/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/static/favicon_io/apple-touch-icon.png
--------------------------------------------------------------------------------
/static/favicon_io/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/static/favicon_io/android-chrome-192x192.png
--------------------------------------------------------------------------------
/static/favicon_io/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Oxlac/AI-News-Summariser/HEAD/static/favicon_io/android-chrome-512x512.png
--------------------------------------------------------------------------------
/static/favicon_io/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Aadityaa
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, request, render_template, flash, redirect, url_for # Import flash
2 | import nltk
3 | from textblob import TextBlob
4 | from newspaper import Article
5 | from datetime import datetime
6 | from urllib.parse import urlparse
7 | import validators
8 | import requests
9 |
10 | nltk.download('punkt')
11 |
12 | app = Flask(__name__)
13 |
14 | def get_website_name(url):
15 | # Extract the website name from the URL
16 | parsed_url = urlparse(url)
17 | domain = parsed_url.netloc
18 | if domain.startswith("www."):
19 | domain = domain[4:]
20 | return domain
21 |
22 | @app.route('/', methods=['GET', 'POST'])
23 | def index():
24 | if request.method == 'POST':
25 | url = request.form['url']
26 | # Check if the input is a valid URL
27 |
28 | if not validators.url(url):
29 | flash('Please enter a valid URL.')
30 | return redirect(url_for('index'))
31 |
32 | try:
33 | response = requests.get(url)
34 | response.raise_for_status() # Raise an HTTPError if the HTTP request returned an unsuccessful status code
35 | except requests.RequestException:
36 | flash('Failed to download the content of the URL.')
37 | return redirect(url_for('index'))
38 |
39 | article = Article(url)
40 | article.download()
41 | article.parse()
42 | article.nlp() # Perform natural language processing
43 |
44 | title = article.title
45 | authors = ', '.join(article.authors)
46 | if not authors:
47 | authors = get_website_name(url) # Set the author field to the website name
48 | publish_date = article.publish_date.strftime('%B %d, %Y') if article.publish_date else "N/A"
49 |
50 | # Manually adjust the summary length by selecting a certain number of sentences
51 | article_text = article.text
52 | sentences = article_text.split('.')
53 | max_summarized_sentences = 5 # Adjust the number of sentences as needed
54 | summary = '.'.join(sentences[:max_summarized_sentences])
55 |
56 | top_image = article.top_image # Get the top image URL
57 |
58 | analysis = TextBlob(article.text)
59 | polarity = analysis.sentiment.polarity # Get the polarity value
60 |
61 | if summary == "":
62 | flash('Please enter a valid URL.')
63 | return redirect(url_for('index'))
64 |
65 | if polarity > 0:
66 | sentiment = 'happy 😊'
67 | elif polarity < 0:
68 | sentiment = ' sad 😟'
69 | else:
70 | sentiment = 'neutral 😐'
71 |
72 | return render_template('index.html', title=title, authors=authors, publish_date=publish_date, summary=summary, top_image=top_image, sentiment=sentiment)
73 |
74 | return render_template('index.html')
75 |
76 | app.secret_key = 'your_secret_key'
77 |
78 | if __name__ == '__main__':
79 | app.run(debug=True)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
6 | A tool for automatically summarizing news articles using artificial intelligence.
7 |
8 | Visit the Website »
9 |
10 |
11 | Contact Developer
12 | ·
13 | Report Bug
14 | ·
15 | Request Feature
16 | .
17 | Discord Support
18 |
{{ title }}
55 |Publication Date:
65 |Summary: {{ summary }}
71 |Sentiment: {{ sentiment }}
72 |© , Designed and Developed by Oxlac LLP
77 | 78 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /static/dark-theme.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap'); 2 | 3 | body { 4 | background-color: #0E1316; /* Dark background */ 5 | color: #EDEDED; 6 | font-family: 'Poppins', sans-serif; 7 | scroll-behavior: smooth; 8 | position: relative; 9 | min-height: calc(100vh - 90px); 10 | } 11 | 12 | .heading { 13 | text-align: center; 14 | font-size: 3.5rem; 15 | margin-top: 0; 16 | padding-top: 0; 17 | } 18 | 19 | body::-webkit-scrollbar { 20 | width: 7px; /* width of the entire scrollbar */ 21 | } 22 | 23 | body::-webkit-scrollbar-track { 24 | background: #0E1316; /* color of the tracking area */ 25 | } 26 | 27 | body::-webkit-scrollbar-thumb { 28 | background-color: #252930; /* color of the scroll thumb */ 29 | border-radius: 20px; /* roundness of the scroll thumb */ 30 | } 31 | 32 | .sub-heading { 33 | text-align: center; 34 | font-size: 2rem; 35 | margin-top: 5rem; 36 | margin-bottom: 0; 37 | padding-bottom: 0; 38 | } 39 | 40 | .form{ 41 | display: flex; 42 | justify-content: center; 43 | gap: .5rem; 44 | } 45 | 46 | .form input[type=text] { 47 | width: 40%; 48 | height: 3rem; 49 | border: none; 50 | border-radius: 10px; 51 | outline: none; 52 | padding-left: 1rem; 53 | } 54 | 55 | .form input[type=text]:active { 56 | border: none; 57 | outline: none; 58 | } 59 | 60 | .form button { 61 | position: relative; 62 | border-radius: 10px; 63 | width: 3rem; 64 | outline: none; 65 | border: none; 66 | cursor:pointer; 67 | user-select:none; 68 | transition-duration: 0.4s; 69 | -webkit-transition-duration: 0.4s; 70 | } 71 | 72 | .form button:hover { 73 | transition-duration: 0.1s; 74 | background-color: #28ffad; 75 | } 76 | 77 | .form button:active { 78 | top: 1px; 79 | } 80 | 81 | .form button:active::after { 82 | box-shadow: 0 0 0 0 white; 83 | position: absolute; 84 | border-radius: 10px; 85 | left: 0; 86 | top:0; 87 | opacity: 1; 88 | transition: 0s; 89 | } 90 | 91 | .form button:after { 92 | content: ""; 93 | display: block; 94 | position: absolute; 95 | border-radius: 10px; 96 | left: 0; 97 | top:0; 98 | width: 100%; 99 | height: 100%; 100 | opacity: 0; 101 | transition: all 0.5s; 102 | box-shadow: 0 0 10px 40px white; 103 | } 104 | 105 | .content { 106 | margin-top: 4rem; 107 | display: flex; 108 | justify-content: center; 109 | } 110 | 111 | .card { 112 | border: 2px solid #252930; 113 | width: 80vw; 114 | padding: 2rem; 115 | border-radius: 10px; 116 | background-color: #1C1E27; 117 | margin-bottom: 5rem; 118 | /* box-shadow: */ 119 | /* 0 0 21px 1px rgb(255, 35, 101); */ 120 | /* 0 0 .5px 1px rgb(7, 255, 152); */ 121 | } 122 | 123 | .card .heading { 124 | margin-top: 2rem; 125 | text-align: center; 126 | font-size: 2.5rem; 127 | } 128 | 129 | .main-wrapper { 130 | display: flex; 131 | align-items: center; 132 | } 133 | 134 | .main-wrapper .col-1 { 135 | width: 80%; 136 | } 137 | 138 | .main-wrapper .col-2 { 139 | display: flex; 140 | align-items: center; 141 | justify-content: center; 142 | } 143 | 144 | .main-wrapper .col-2 .top-image { 145 | max-width: 70%; 146 | height: auto; 147 | border-radius: 20px; 148 | } 149 | 150 | .summary-tag { 151 | font-size: 1.5rem; 152 | } 153 | 154 | .author-tag { 155 | font-size: 1.5rem; 156 | } 157 | 158 | .date-tag { 159 | font-size: 1.5rem; 160 | } 161 | 162 | .sentiment-tag { 163 | font-size: 1.5rem; 164 | } 165 | 166 | .author-list li.hidden { 167 | display: none; 168 | } 169 | 170 | #readMoreBtn { 171 | display: block; 172 | margin-top: 1rem; 173 | background-color: transparent; 174 | border: none; 175 | color: #28ffad; 176 | cursor: pointer; 177 | } 178 | 179 | #readMoreBtn:hover { 180 | text-decoration: underline; 181 | } 182 | 183 | /* Light Theme */ 184 | .light-theme { 185 | background-color: #FFFFFF; 186 | color: #000000; 187 | } 188 | 189 | /* Dark Theme */ 190 | .dark-theme { 191 | background-color: #0E1316; 192 | color: #EDEDED; 193 | } 194 | 195 | 196 | @media screen and (max-width: 768px) { 197 | .heading { 198 | font-size: 3rem; 199 | } 200 | 201 | .form input[type=text] { 202 | width: 60%; 203 | } 204 | 205 | .card { 206 | width: 75vw; 207 | padding: 1rem; 208 | } 209 | 210 | .card .heading { 211 | font-size: 1.5rem; 212 | } 213 | 214 | .main-wrapper { 215 | flex-direction: column-reverse; 216 | } 217 | 218 | .main-wrapper .col-2 .top-image { 219 | width: 100%; 220 | } 221 | 222 | .main-wrapper .col-1 { 223 | width: 100%; 224 | } 225 | 226 | .infos { 227 | width: 100%; 228 | text-align: center; 229 | } 230 | } 231 | 232 | 233 | .flash-message { 234 | position: fixed; 235 | top: 0; 236 | left: 0; 237 | width: 100%; 238 | background: transparent; /* Background color for the alert container */ 239 | color: #fff; /* Text color for the alert text */ 240 | text-align: center; 241 | padding: 10px 0; 242 | z-index: 9999; /* Ensures the alert is on top of other content */ 243 | } 244 | 245 | .alert { 246 | background: #ff3333; /* Background color for the alert */ 247 | color: #fff; /* Text color for the alert text */ 248 | padding: 10px; 249 | margin: 10px; 250 | border-radius: 5px; 251 | } 252 | 253 | .infos { 254 | position: absolute; 255 | color: #fff; 256 | font-size: 14px; 257 | bottom: 10px; 258 | left: 50%; 259 | transform: translateX(-50%); 260 | } 261 | 262 | .developer { 263 | text-decoration: none; 264 | cursor:pointer; 265 | color: #28ffad; 266 | } 267 | 268 | .theme-switch-wrapper { 269 | display: flex; 270 | align-items: center; 271 | justify-content: center; 272 | margin: 20px; 273 | } 274 | 275 | .theme-switch { 276 | position: relative; 277 | display: inline-block; 278 | width: 60px; 279 | height: 34px; 280 | } 281 | 282 | .theme-switch input { 283 | opacity: 0; 284 | width: 0; 285 | height: 0; 286 | } 287 | 288 | .slider { 289 | position: absolute; 290 | cursor: pointer; 291 | top: 0; 292 | left: 0; 293 | right: 0; 294 | bottom: 0; 295 | background-color: #ccc; 296 | -webkit-transition: .4s; 297 | transition: .4s; 298 | } 299 | 300 | .slider:before { 301 | position: absolute; 302 | content: ""; 303 | height: 26px; 304 | width: 26px; 305 | left: 4px; 306 | bottom: 4px; 307 | background-color: white; 308 | -webkit-transition: .4s; 309 | transition: .4s; 310 | } 311 | 312 | input:checked + .slider { 313 | background-color: #2196F3; 314 | } 315 | 316 | input:focus + .slider { 317 | box-shadow: 0 0 1px #2196F3; 318 | } 319 | 320 | input:checked + .slider:before { 321 | -webkit-transform: translateX(26px); 322 | -ms-transform: translateX(26px); 323 | transform: translateX(26px); 324 | } 325 | 326 | /* Rounded sliders */ 327 | .slider.round { 328 | border-radius: 34px; 329 | } 330 | 331 | .slider.round:before { 332 | border-radius: 50%; 333 | } 334 | 335 | .theme-switch-wrapper span { 336 | margin-right: 10px; 337 | /* Add more styling if needed */ 338 | } --------------------------------------------------------------------------------