diff --git a/README.md b/README.md
new file mode 100644
index 0000000..15cb98c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# PythonHomework
+[Introduction to Python] Homework Repository
+# How to use
+* pip install .
+* python rss-reader https://news.tut.by/rss/economics.rss --limit 2 --json
+# Parameters
+* --help (Show this help message and exit)
+* source (RSS URL)
+* --limit LIMIT (Limit news topics if this parameter provided)
+* --json (Prints result as JSON in stdout)
+* --verbose (Outputs verbose status messages)
+* --version (Print version info)
+* --date ()
+* --to-pdf (Converter in pdf)
+* --to-html (Converter in html)
+* --colorize
+# JSON structure
+news = {"Title": "title", "Date":"date", "Alt image":"alt", "Discription":"discription", "Links":{"News":"link", "Image":"src"} }
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..db46317
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+bs4 # for xml and html
+feedparser # rss parsing
+requests # http requests
+python-dateutil
+fpdf
+colorama
\ No newline at end of file
diff --git a/rss_app/RSS.py b/rss_app/RSS.py
new file mode 100644
index 0000000..0693a3f
--- /dev/null
+++ b/rss_app/RSS.py
@@ -0,0 +1,213 @@
+"""
+A file with the RssAggregator class that parses the URL
+and performs various actions with the received data
+"""
+
+import feedparser
+from bs4 import BeautifulSoup
+import json
+from dateutil.parser import parse
+import urllib
+import httplib2
+import os
+from colorama import init
+from colorama import Fore
+
+
+class RssAggregator():
+
+ """ Class for rss feed """
+
+ feedurl = ""
+
+ def __init__(self, source, limit, date, log, colorize):
+ self.source = source
+ self.limit = limit
+ self.date = date
+ self.log = log
+ self.colorize = colorize
+ init()
+
+ def get_news(self):
+
+ """ Returns parsed news and caches it"""
+
+ self.log.info("Getting rss feed")
+ thefeed = feedparser.parse(self.source)
+ self.save_to_json_file(thefeed.entries)
+ return thefeed.entries[:self.limit]
+
+ def print_news(self, entries):
+
+ """ Print rss news """
+
+ self.log.info("Printing news")
+ for thefeedentry in entries:
+ try:
+ if self.colorize:
+ print("--------------------------------------------------")
+ print(f"{Fore.RED}Title:{Fore.RESET} ", Fore.RED + thefeedentry.title + Fore.RESET)
+ print(f"{Fore.BLUE}Date:{Fore.RESET} ", Fore.BLUE + thefeedentry.published + Fore.RESET, end="\n\n")
+ print(f"{Fore.YELLOW}Alt image:{Fore.RESET} ", Fore.YELLOW + BeautifulSoup(thefeedentry.description + Fore.RESET, "html.parser").find('img')['alt'])
+ print(Fore.GREEN + BeautifulSoup(thefeedentry.description, "html.parser").text + Fore.RESET, end="\n\n")
+ print("Links:")
+ print(f"{Fore.YELLOW}News:{Fore.RESET} ", Fore.YELLOW + thefeedentry.link + Fore.RESET)
+ print(f"{Fore.YELLOW}Image:{Fore.RESET} ", Fore.YELLOW + BeautifulSoup(thefeedentry.description + Fore.RESET, "html.parser").find('img')['src'])
+ else:
+ print("Title: ", thefeedentry.title)
+ print("Date: ", thefeedentry.published, end="\n\n")
+ print("Alt image: ", BeautifulSoup(thefeedentry.description, "html.parser").find('img')['alt'])
+ print(BeautifulSoup(thefeedentry.description, "html.parser").text, end="\n\n")
+ print("Links:")
+ print("News: ", thefeedentry.link)
+ print("Image: ", BeautifulSoup(thefeedentry.description, "html.parser").find('img')['src'])
+ except TypeError:
+ self.log.info("TypeError: 'NoneType'")
+
+ def print_json(self, entries):
+
+ """ Print rss news in json format"""
+
+ self.log.info("RSS news to json")
+ for thefeedentry in entries:
+ try:
+ news = {
+ "Title": thefeedentry.title,
+ "Date": thefeedentry.published,
+ "Alt image": BeautifulSoup(thefeedentry.description, "html.parser").find('img')['alt'],
+ "Discription": BeautifulSoup(thefeedentry.description, "html.parser").text,
+ "Links": {
+ "News": thefeedentry.link,
+ "Image": BeautifulSoup(thefeedentry.description, "html.parser").find('img')['src']
+ }
+ }
+ print(json.dumps(news, indent=3))
+ except TypeError:
+ self.log.info("TypeError: 'NoneType'")
+
+ def save_to_json_file(self, entries):
+
+ """ Save rss news to json file"""
+
+ self.log.info("Save news to json file")
+ news_list = list()
+ file_name = self.get_file_name()
+ with open(file_name, "w", encoding="utf-8") as write_file:
+ for thefeedentry in entries:
+ try:
+ news = {
+ "Title": thefeedentry.title,
+ "Date": thefeedentry.published,
+ "Alt image": BeautifulSoup(thefeedentry.description, "html.parser").find('img')['alt'],
+ "Discription": BeautifulSoup(thefeedentry.description, "html.parser").text,
+ "Links": {
+ "News": thefeedentry.link,
+ "Image": BeautifulSoup(thefeedentry.description, "html.parser").find('img')['src']
+ }
+ }
+ self.save_image(thefeedentry, file_name)
+ news_list.append(news)
+ except TypeError:
+ self.log.info("TypeError: 'NoneType'")
+ json.dump(news_list, write_file, indent=3)
+
+ def get_file_name(self):
+
+ """ Getting the file name for storing news """
+
+ self.log.info("Getting file name")
+ file_name_list = self.source.split("//")
+ file_name = file_name_list[1].replace("/", "")
+ file_name += ".json"
+ return file_name
+
+ def save_image(self, thefeedentry, file_name):
+
+ """ Save image to file"""
+
+ file_path = self.get_path_image(thefeedentry)
+ h = httplib2.Http('.cache')
+ response, content = h.request(BeautifulSoup(thefeedentry.description, "html.parser").find('img')['src'])
+ try:
+ out = open(file_path, "wb")
+ out.write(content)
+ out.close()
+ except FileNotFoundError:
+ self.log.info("Error: image not found")
+ except OSError:
+ self.log.info("[Errno 22] Invalid argument {}".format(file_path))
+
+ def get_path_image(self, thefeedentry):
+
+ """ Get path image """
+
+ file_name_list = self.source.split("//")
+ file_name = file_name_list[1].replace("/", "")
+ folder_path = "image_" + file_name + os.path.sep
+ if not os.path.exists(folder_path):
+ self.log.info('Creating directory images')
+ os.mkdir(folder_path)
+ img = BeautifulSoup(thefeedentry.description, "html.parser").find('img')['src']
+ image = img.split("/")
+ file_path = os.path.abspath('') + os.path.sep + folder_path + image[-1]
+ if ".jpg" or ".gif" or ".png" in file_path:
+ return file_path
+ file_path += ".jpg"
+ return file_path
+
+ def get_from_json_file(self):
+
+ """ Get news on the argument --date from json file"""
+
+ self.log.info("Getting news by date")
+ file_name = self.get_file_name()
+ news_by_date = list()
+ try:
+ with open(file_name, "r") as read_file:
+ news = json.load(read_file)
+ for thefeedentry in news:
+ published = parse(thefeedentry['Date']).strftime('%Y%m%d')
+ if published >= self.date:
+ news_by_date.append(thefeedentry)
+ return news_by_date
+ except FileNotFoundError:
+ self.log.info("File not found error")
+
+ def get_news_for_converter(self):
+
+ """ Get news from json file for converter in pdf or html"""
+
+ self.log.info("Getting news for converter")
+ file_name = self.get_file_name()
+ news = list()
+ try:
+ with open(file_name, "r") as read_file:
+ news = json.load(read_file)
+ return news
+ except FileNotFoundError:
+ self.log.info("File not found error")
+
+ def print_news_from_file(self, entries):
+
+ """ Print a certain amount of news by date """
+
+ self.log.info("Printing news by date")
+ for thefeedentry in entries[:self.limit]:
+ if self.colorize:
+ print("--------------------------------------------------")
+ print(f"{Fore.RED}Title:{Fore.RESET} ", Fore.RED + thefeedentry['Title'] + Fore.RESET)
+ print(f"{Fore.BLUE}Date:{Fore.RESET} ", Fore.BLUE + thefeedentry['Date'] + Fore.RESET, end="\n\n")
+ print(f"{Fore.YELLOW}Alt image:{Fore.RESET} ", Fore.YELLOW + thefeedentry['Alt image'] + Fore.RESET)
+ print(Fore.GREEN + thefeedentry['Discription'] + Fore.RESET, end="\n\n")
+ print("Links: ")
+ print(f"{Fore.YELLOW}News:{Fore.RESET} ", Fore.YELLOW + thefeedentry['Links']['News'] + Fore.RESET)
+ print(f"{Fore.YELLOW}Image:{Fore.RESET} ", Fore.YELLOW + thefeedentry['Links']['Image'] + Fore.RESET)
+ else:
+ print("--------------------------------------------------")
+ print("Title: ", thefeedentry['Title'])
+ print("Date: ", thefeedentry['Date'], end="\n\n")
+ print("Alt image: ", thefeedentry['Alt image'])
+ print(thefeedentry['Discription'], end="\n\n")
+ print("Links: ")
+ print("News: ", thefeedentry['Links']['News'])
+ print("Image: ", thefeedentry['Links']['Image'])
diff --git a/rss_app/__init__.py b/rss_app/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rss_app/converter.py b/rss_app/converter.py
new file mode 100644
index 0000000..cca7f9b
--- /dev/null
+++ b/rss_app/converter.py
@@ -0,0 +1,85 @@
+"""
+File with a class Converter designed to convert data to pdf and html formats
+"""
+
+
+import fpdf
+from bs4 import BeautifulSoup
+import os
+
+
+class Converter:
+
+ """ News conversion class """
+
+ fpdf.set_global("SYSTEM_TTFONTS", os.path.join(os.path.dirname(__file__), 'fonts', 'ttf'))
+
+ def __init__(self, source, limit, to_pdf, to_html, log):
+ self.source = source
+ self.limit = limit
+ self.to_pdf = to_pdf
+ self.to_html = to_html
+ self.log = log
+
+ def pdf_converter(self, entries):
+
+ """ Convert data to pdf file """
+
+ self.log.info("Converter in pdf format")
+ pdf = fpdf.FPDF()
+ pdf.add_page()
+ pdf.add_font('DejaVu', '', 'DejaVuSansCondensed.ttf', uni=True)
+ pdf.set_font('DejaVu', size=14)
+ for thefeedentry in entries[:self.limit]:
+ path = self.get_path_image(thefeedentry)
+ pdf.multi_cell(0, 10, txt="{}".format(thefeedentry['Title']))
+ pdf.multi_cell(0, 10, txt="{}".format(thefeedentry['Links']['News']))
+ try:
+ pdf.image(path)
+ except RuntimeError:
+ self.log.info("Error add image")
+ pdf.multi_cell(0, 10, txt="{}".format(thefeedentry['Alt image']))
+ pdf.multi_cell(0, 10, txt="{}".format(thefeedentry['Discription']))
+ pdf.multi_cell(0, 10, txt="{}".format(thefeedentry['Date']))
+ pdf.ln(10)
+ pdf.output(self.to_pdf)
+ print(self.to_pdf)
+
+ def html_converter(self, entries):
+
+ """ Convert data to html file """
+
+ self.log.info("Converter in html format")
+ with open(self.to_html, "w", encoding="utf-8") as file_text:
+ file_text.write("")
+ file_text.write("
")
+ file_text.write("")
+ for thefeedentry in entries[:self.limit]:
+ file_text.write("{}
".format(thefeedentry['Title']))
+ file_text.write("{}
".format(thefeedentry['Links']['News']))
+ file_text.write("
".format(thefeedentry['Links']['Image']))
+ file_text.write("{}
".format(thefeedentry['Discription']))
+ file_text.write("{}
".format(thefeedentry['Date']))
+ file_text.write("
")
+ file_text.write("")
+ file_text.write("")
+
+ def get_path_image(self, thefeedentry):
+
+ """ Get the path of the image to add to the pdf file """
+
+ self.log.info("Getting path image")
+ file_name_list = self.source.split("//")
+ file_name = file_name_list[1].replace("/", "")
+ folder_path = "image_" + file_name + os.path.sep
+ if not os.path.exists(folder_path):
+ self.log.info('Creating directory images')
+ os.mkdir(folder_path)
+ img = thefeedentry['Links']['Image']
+ image = img.split("/")
+ file_path = os.path.abspath('') + os.path.sep + folder_path + image[-1]
+ if ".jpg" or ".gif" or ".png" in file_path:
+ print(file_path)
+ return file_path
+ file_path += ".jpg"
+ return file_path
diff --git a/rss_app/fonts/fontconfig/20-unhint-small-dejavu-sans-mono.conf b/rss_app/fonts/fontconfig/20-unhint-small-dejavu-sans-mono.conf
new file mode 100644
index 0000000..102dbcc
--- /dev/null
+++ b/rss_app/fonts/fontconfig/20-unhint-small-dejavu-sans-mono.conf
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ DejaVu Sans Mono
+
+
+ 7.5
+
+
+ false
+
+
+
diff --git a/rss_app/fonts/fontconfig/20-unhint-small-dejavu-sans.conf b/rss_app/fonts/fontconfig/20-unhint-small-dejavu-sans.conf
new file mode 100644
index 0000000..ee69996
--- /dev/null
+++ b/rss_app/fonts/fontconfig/20-unhint-small-dejavu-sans.conf
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ DejaVu Sans
+
+
+ 7.5
+
+
+ false
+
+
+
diff --git a/rss_app/fonts/fontconfig/20-unhint-small-dejavu-serif.conf b/rss_app/fonts/fontconfig/20-unhint-small-dejavu-serif.conf
new file mode 100644
index 0000000..cf6caa2
--- /dev/null
+++ b/rss_app/fonts/fontconfig/20-unhint-small-dejavu-serif.conf
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ DejaVu Serif
+
+
+ 7.5
+
+
+ false
+
+
+
diff --git a/rss_app/fonts/fontconfig/57-dejavu-sans-mono.conf b/rss_app/fonts/fontconfig/57-dejavu-sans-mono.conf
new file mode 100644
index 0000000..cc42561
--- /dev/null
+++ b/rss_app/fonts/fontconfig/57-dejavu-sans-mono.conf
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+ Bepa Mono
+
+ DejaVu Sans Mono
+
+
+
+ Bitstream Prima Sans Mono
+
+ DejaVu Sans Mono
+
+
+
+ Bitstream Vera Sans Mono
+
+ DejaVu Sans Mono
+
+
+
+ DejaVu LGC Sans Mono
+
+ DejaVu Sans Mono
+
+
+
+ Olwen Sans Mono
+
+ DejaVu Sans Mono
+
+
+
+ SUSE Sans Mono
+
+ DejaVu Sans Mono
+
+
+
+
+ DejaVu Sans Mono
+
+ monospace
+
+
+
+
+ monospace
+
+ DejaVu Sans Mono
+
+
+
diff --git a/rss_app/fonts/fontconfig/57-dejavu-sans.conf b/rss_app/fonts/fontconfig/57-dejavu-sans.conf
new file mode 100644
index 0000000..565cab5
--- /dev/null
+++ b/rss_app/fonts/fontconfig/57-dejavu-sans.conf
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+ Arev Sans
+
+ DejaVu Sans
+
+
+
+ Bepa
+
+ DejaVu Sans
+
+
+
+ Bitstream Prima Sans
+
+ DejaVu Sans
+
+
+
+ Bitstream Vera Sans
+
+ DejaVu Sans
+
+
+
+ DejaVu LGC Sans
+
+ DejaVu Sans
+
+
+
+ Hunky Sans
+
+ DejaVu Sans
+
+
+
+ Olwen Sans
+
+ DejaVu Sans
+
+
+
+ SUSE Sans
+
+ DejaVu Sans
+
+
+
+ Verajja
+
+ DejaVu Sans
+
+
+
+
+ VerajjaPDA
+
+ DejaVu Sans
+
+
+
+
+ DejaVu Sans
+
+ sans-serif
+
+
+
+
+ sans-serif
+
+ DejaVu Sans
+
+
+
diff --git a/rss_app/fonts/fontconfig/57-dejavu-serif.conf b/rss_app/fonts/fontconfig/57-dejavu-serif.conf
new file mode 100644
index 0000000..a922e9b
--- /dev/null
+++ b/rss_app/fonts/fontconfig/57-dejavu-serif.conf
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+ Bitstream Prima Serif
+
+ DejaVu Serif
+
+
+
+ Bitstream Vera Serif
+
+ DejaVu Serif
+
+
+
+ DejaVu LGC Serif
+
+ DejaVu Serif
+
+
+
+ Hunky Serif
+
+ DejaVu Serif
+
+
+
+ Olwen Serif
+
+ DejaVu Serif
+
+
+
+ SUSE Serif
+
+ DejaVu Serif
+
+
+
+
+ Verajja Serif
+
+ DejaVu Serif
+
+
+
+
+ DejaVu Serif
+
+ serif
+
+
+
+
+ serif
+
+ DejaVu Serif
+
+
+
diff --git a/rss_app/fonts/ttf/DejaVuMathTeXGyre.ttf b/rss_app/fonts/ttf/DejaVuMathTeXGyre.ttf
new file mode 100644
index 0000000..8a24f06
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuMathTeXGyre.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSans-Bold.ttf b/rss_app/fonts/ttf/DejaVuSans-Bold.ttf
new file mode 100644
index 0000000..6d65fa7
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSans-Bold.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSans-BoldOblique.ttf b/rss_app/fonts/ttf/DejaVuSans-BoldOblique.ttf
new file mode 100644
index 0000000..753f2d8
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSans-BoldOblique.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSans-ExtraLight.ttf b/rss_app/fonts/ttf/DejaVuSans-ExtraLight.ttf
new file mode 100644
index 0000000..b09f32d
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSans-ExtraLight.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSans-Oblique.ttf b/rss_app/fonts/ttf/DejaVuSans-Oblique.ttf
new file mode 100644
index 0000000..999bac7
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSans-Oblique.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSans.ttf b/rss_app/fonts/ttf/DejaVuSans.ttf
new file mode 100644
index 0000000..e5f7eec
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSans.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSansCondensed-Bold.ttf b/rss_app/fonts/ttf/DejaVuSansCondensed-Bold.ttf
new file mode 100644
index 0000000..22987c6
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansCondensed-Bold.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSansCondensed-BoldOblique.ttf b/rss_app/fonts/ttf/DejaVuSansCondensed-BoldOblique.ttf
new file mode 100644
index 0000000..f5fa0ca
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansCondensed-BoldOblique.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSansCondensed-Oblique.ttf b/rss_app/fonts/ttf/DejaVuSansCondensed-Oblique.ttf
new file mode 100644
index 0000000..7fde907
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansCondensed-Oblique.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSansCondensed.cw127.pkl b/rss_app/fonts/ttf/DejaVuSansCondensed.cw127.pkl
new file mode 100644
index 0000000..aadd269
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansCondensed.cw127.pkl differ
diff --git a/rss_app/fonts/ttf/DejaVuSansCondensed.pkl b/rss_app/fonts/ttf/DejaVuSansCondensed.pkl
new file mode 100644
index 0000000..a8e73f5
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansCondensed.pkl differ
diff --git a/rss_app/fonts/ttf/DejaVuSansCondensed.ttf b/rss_app/fonts/ttf/DejaVuSansCondensed.ttf
new file mode 100644
index 0000000..3259bc2
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansCondensed.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSansMono-Bold.ttf b/rss_app/fonts/ttf/DejaVuSansMono-Bold.ttf
new file mode 100644
index 0000000..8184ced
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansMono-Bold.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSansMono-BoldOblique.ttf b/rss_app/fonts/ttf/DejaVuSansMono-BoldOblique.ttf
new file mode 100644
index 0000000..754dca7
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansMono-BoldOblique.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSansMono-Oblique.ttf b/rss_app/fonts/ttf/DejaVuSansMono-Oblique.ttf
new file mode 100644
index 0000000..4c858d4
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansMono-Oblique.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSansMono.ttf b/rss_app/fonts/ttf/DejaVuSansMono.ttf
new file mode 100644
index 0000000..f578602
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSansMono.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSerif-Bold.ttf b/rss_app/fonts/ttf/DejaVuSerif-Bold.ttf
new file mode 100644
index 0000000..3bb755f
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSerif-Bold.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSerif-BoldItalic.ttf b/rss_app/fonts/ttf/DejaVuSerif-BoldItalic.ttf
new file mode 100644
index 0000000..a36dd4b
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSerif-BoldItalic.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSerif-Italic.ttf b/rss_app/fonts/ttf/DejaVuSerif-Italic.ttf
new file mode 100644
index 0000000..805daf2
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSerif-Italic.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSerif.ttf b/rss_app/fonts/ttf/DejaVuSerif.ttf
new file mode 100644
index 0000000..0b803d2
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSerif.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSerifCondensed-Bold.ttf b/rss_app/fonts/ttf/DejaVuSerifCondensed-Bold.ttf
new file mode 100644
index 0000000..222bf13
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSerifCondensed-Bold.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSerifCondensed-BoldItalic.ttf b/rss_app/fonts/ttf/DejaVuSerifCondensed-BoldItalic.ttf
new file mode 100644
index 0000000..e446636
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSerifCondensed-BoldItalic.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSerifCondensed-Italic.ttf b/rss_app/fonts/ttf/DejaVuSerifCondensed-Italic.ttf
new file mode 100644
index 0000000..c529df3
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSerifCondensed-Italic.ttf differ
diff --git a/rss_app/fonts/ttf/DejaVuSerifCondensed.ttf b/rss_app/fonts/ttf/DejaVuSerifCondensed.ttf
new file mode 100644
index 0000000..d3959b3
Binary files /dev/null and b/rss_app/fonts/ttf/DejaVuSerifCondensed.ttf differ
diff --git a/rss_app/main.py b/rss_app/main.py
new file mode 100644
index 0000000..abf3fbc
--- /dev/null
+++ b/rss_app/main.py
@@ -0,0 +1,87 @@
+"""
+The main file to run the script
+"""
+
+
+import argparse
+from rss_app.RSS import RssAggregator
+from rss_app.converter import Converter
+import logging
+from datetime import datetime
+
+
+__version__ = "0.5.0"
+
+
+def get_args():
+
+ """ Reads and returns arguments """
+
+ parser = argparse.ArgumentParser(description="Pure Python command-line RSS reader.")
+ parser.add_argument('source', type=str, help="RSS URL")
+ parser.add_argument("-v", "--version", action="version", version="%(prog)s version" +
+ "{version}".format(version=__version__), default=None, help="Print version info")
+ parser.add_argument("--json", action="store_true", help="Print result as JSON in stdout")
+ parser.add_argument("--verbose", action="store_true", help="Outputs verbose status messages")
+ parser.add_argument("--limit", type=int, default=None, help="Limit news topics if this parameter provided")
+ parser.add_argument("--date", type=str, help="For example: --date 20191020")
+ parser.add_argument("--to-pdf", type=str, help="This argument receives the path where new file will" +
+ "be saved in format pdf. For example: --to-pdf d:/news.pdf")
+ parser.add_argument("--to-html", type=str, help="This argument receives the path where new file will" +
+ "be saved in format html. For example: --to-html d:/news.html")
+ parser.add_argument("--colorize", action="store_true", help="Print the result of the utility in colorized mode")
+ args = parser.parse_args()
+ return args
+
+
+def main():
+
+ """ Reads arguments and print news """
+
+ args = get_args()
+ if args.version:
+ print(args.version)
+ if args.verbose:
+ logger = get_log()
+ else:
+ logger = logging.getLogger()
+ rssobject = RssAggregator(args.source, args.limit, args.date, logger, args.colorize)
+ converter = Converter(args.source, args.limit, args.to_pdf, args.to_html, logger)
+ news = rssobject.get_news()
+ if args.to_pdf:
+ news_for_converter_pdf = rssobject.get_news_for_converter()
+ converter.pdf_converter(news_for_converter_pdf)
+ if args.to_html:
+ news_for_converter_html = rssobject.get_news_for_converter()
+ converter.html_converter(news_for_converter_html)
+ if args.date:
+ try:
+ datetime.strptime(args.date, "%Y%m%d")
+ data = rssobject.get_from_json_file()
+ rssobject.print_news_from_file(data)
+ return
+ except ValueError:
+ print("ValueError: Time data {} does not match format %Y%m%d".format(args.date))
+ return
+ if args.json:
+ rssobject.print_json(news)
+ else:
+ rssobject.print_news(news)
+ logger.info("Exit")
+
+
+def get_log():
+
+ """ Returns logger with DEBUG level for creating logs in stdout """
+
+ logger = logging.getLogger(__name__)
+ logger.level = logging.DEBUG
+ formatter = logging.Formatter('%(levelname)s: %(message)s')
+ stream_handler = logging.StreamHandler()
+ stream_handler.setFormatter(formatter)
+ logger.addHandler(stream_handler)
+ return logger
+
+
+if __name__ == "__main__":
+ main()
diff --git a/rss_app/test_date_html.txt b/rss_app/test_date_html.txt
new file mode 100644
index 0000000..d2d63ea
--- /dev/null
+++ b/rss_app/test_date_html.txt
@@ -0,0 +1 @@
+Почти окончательно. Минфин рассказал, как будут взимать дорожный налог
https://news.tut.by/economics/663393.html?utm_campaign=news-feed&utm_medium=rss&utm_source=rss-news
Министерство финансов подготовило проект указа об изменении существующей системы уплаты госпошлины за доступ транспортных средств к участию в дорожном движении.
Sun, 01 Dec 2019 19:57:00 +0300
\ No newline at end of file
diff --git a/rss_app/test_json.json b/rss_app/test_json.json
new file mode 100644
index 0000000..b49fdf8
--- /dev/null
+++ b/rss_app/test_json.json
@@ -0,0 +1,12 @@
+[
+ {
+ "Title": "\u041f\u043e\u0447\u0442\u0438 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e. \u041c\u0438\u043d\u0444\u0438\u043d \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043b, \u043a\u0430\u043a \u0431\u0443\u0434\u0443\u0442 \u0432\u0437\u0438\u043c\u0430\u0442\u044c \u0434\u043e\u0440\u043e\u0436\u043d\u044b\u0439 \u043d\u0430\u043b\u043e\u0433",
+ "Date": "Sun, 01 Dec 2019 19:57:00 +0300",
+ "Alt image": "\u0424\u043e\u0442\u043e: \u0413\u043b\u0435\u0431 \u041c\u0430\u043b\u043e\u0444\u0435\u0435\u0432, TUT.BY",
+ "Discription": "\u041c\u0438\u043d\u0438\u0441\u0442\u0435\u0440\u0441\u0442\u0432\u043e \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043b\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0443\u043a\u0430\u0437\u0430 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0443\u043f\u043b\u0430\u0442\u044b \u0433\u043e\u0441\u043f\u043e\u0448\u043b\u0438\u043d\u044b \u0437\u0430 \u0434\u043e\u0441\u0442\u0443\u043f \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043a \u0443\u0447\u0430\u0441\u0442\u0438\u044e \u0432 \u0434\u043e\u0440\u043e\u0436\u043d\u043e\u043c \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0438.",
+ "Links": {
+ "News": "https://news.tut.by/economics/663393.html?utm_campaign=news-feed&utm_medium=rss&utm_source=rss-news",
+ "Image": "https://img.tyt.by/thumbnails/n/avto/0c/4/1593_m6_trassa_ograzhdenie_doroga_20190326_mag_tutby_phsl.jpg"
+ }
+ }
+]
\ No newline at end of file
diff --git a/rss_app/unit_test.py b/rss_app/unit_test.py
new file mode 100644
index 0000000..e4e5fe5
--- /dev/null
+++ b/rss_app/unit_test.py
@@ -0,0 +1,45 @@
+"""Unittests are performed in this module."""
+
+
+import unittest
+import logging
+import json
+
+from rss_app.RSS import RssAggregator
+from rss_app.converter import Converter
+
+
+class TestRSS(unittest.TestCase):
+
+ def setUp(self):
+ logger = logging.getLogger()
+ logger.level = logging.DEBUG
+ stream_handler = logging.StreamHandler()
+ logger.addHandler(stream_handler)
+
+ self.url = "http://news.com/rss"
+ self.to_pdf = "d:/test_html.pdf"
+ self.to_html = "d:/test_html.html"
+ self.converter = Converter(self.url, 1, self.to_pdf, self.to_html, logger)
+ self.test_date = RssAggregator(self.url, 1, 1, logger)
+
+ with open("test_json.json", "r") as read_file:
+ self.news = json.load(read_file)
+
+ def test_get_file_name(self):
+ test_url = "news.comrss.json"
+ self.assertEqual(self.test_date.get_file_name(), test_url)
+
+ def test_html_converter(self):
+ with open("test_date_html.txt", "r") as rf:
+ test_html_date = rf.read()
+
+ self.converter.html_converter(self.news)
+
+ with open(self.to_html, "r") as rf:
+ new_html_date = rf.read()
+
+ self.assertEqual(str(new_html_date), test_html_date)
+
+ if __name__ == "__main__":
+ unittest.main()
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..64b7fd4
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,38 @@
+from setuptools import setup, find_packages
+from os import path
+
+here = path.abspath(path.dirname(__file__))
+
+# Get the long description from the README file
+with open(path.join(here, 'README.md'), encoding='utf-8') as f:
+ long_description = f.read()
+
+
+setup(
+ name='rss-reader',
+ version='0.5.0',
+ description='A simple Python3.8 rss reader',
+ long_description=long_description,
+ long_description_content_type='text/markdown',
+ url='https://github.com/introduction-to-python-bsuir-2019/PythonHomework',
+ author='ge2nadiy',
+ author_email='ge2nadiy.k@gmail.com',
+ keywords='simple rss reader',
+ packages=find_packages(),
+ package_data={
+ 'rss_app': [
+ 'fonts/ttf/DejaVuSansCondensed.ttf'
+ ]
+ },
+ python_requires='>=3.8',
+ install_requires=['bs4', 'feedparser', 'requests', 'python-dateutil', 'httplib2', 'fpdf', 'colorama'],
+ entry_points={
+ 'console_scripts': [
+ 'rss-reader=rss_app.main:main',
+ ],
+ },
+ project_urls={
+ 'Bug Reports': 'https://github.com/introduction-to-python-bsuir-2019/PythonHomework/issues',
+ 'Source': 'https://github.com/introduction-to-python-bsuir-2019/PythonHomework',
+ },
+)