diff --git a/Salikov/.gitignore b/Salikov/.gitignore new file mode 100644 index 0000000..c2b8552 --- /dev/null +++ b/Salikov/.gitignore @@ -0,0 +1,4 @@ +*.json +*.rss +*.atom +*.txt \ No newline at end of file diff --git a/Salikov/bin/converter.rb b/Salikov/bin/converter.rb new file mode 100644 index 0000000..269dcfd --- /dev/null +++ b/Salikov/bin/converter.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require './options.rb' +require '../main.rb' + +options = OptionsParser.options + +main_programm = Main.new(options) +main_programm.run diff --git a/Salikov/bin/options.rb b/Salikov/bin/options.rb new file mode 100644 index 0000000..5229a57 --- /dev/null +++ b/Salikov/bin/options.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'optparse' +require 'ostruct' +require 'uri' + +module OptionsParser + def self.options + options = {} + parser = OptionParser.new do |opt| + opt.banner = 'Usage converter.rb [options]' + opt.separator '' + opt.on('-i', '--input [url | file]', 'The input link | file') do |input| + options[:input] = input + end + opt.on('-o', '--output-format [format]', + 'The output format(rss | json | atom)') do |output| + options[:output_format] = output + end + opt.on('-s', '--sort [asc | desc]', 'Sorting method') do |sort| + options[:sort] = sort + end + + opt.separator '' + + opt.on('-h', '--help', 'Show this message') do |_help| + puts opt + exit + end + end + + parser.parse! + options + end +end diff --git a/Salikov/lib/converters/base_converter.rb b/Salikov/lib/converters/base_converter.rb new file mode 100644 index 0000000..9a57398 --- /dev/null +++ b/Salikov/lib/converters/base_converter.rb @@ -0,0 +1,8 @@ +module BaseConverter + def self.convert(data, option) + Main::CONVERTES.each do |parser_name| + class_name = Module.const_get(parser_name) + return class_name.convert(data) if class_name.to_s.include?(option.to_s.capitalize) + end + end +end \ No newline at end of file diff --git a/Salikov/lib/converters/module/atom_convert.rb b/Salikov/lib/converters/module/atom_convert.rb new file mode 100644 index 0000000..1863d86 --- /dev/null +++ b/Salikov/lib/converters/module/atom_convert.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'nokogiri' + +# Class which converts hash data to RSS format +module AtomConvert + def self.convert(data) + builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml| + xml.rss('version' => '2.0', 'xmlns:atom' => 'http://www.w3.org/2005/Atom') do + xml.title data[:feed][:title] + xml.link data[:feed][:link] + data[:items].each do |v| + xml.entry do + xml.title v[:title] + xml.summary v[:description] + xml.link v[:link] + xml.published v[:date] + xml.category v[:category] + end + end + end + end + builder.to_xml + end +end \ No newline at end of file diff --git a/Salikov/lib/converters/module/json_convert.rb b/Salikov/lib/converters/module/json_convert.rb new file mode 100644 index 0000000..722698a --- /dev/null +++ b/Salikov/lib/converters/module/json_convert.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'json' + +module JsonConvert + def self.convert(data) + JSON.pretty_generate(data) + end +end diff --git a/Salikov/lib/converters/module/rss_convert.rb b/Salikov/lib/converters/module/rss_convert.rb new file mode 100644 index 0000000..9a75ea7 --- /dev/null +++ b/Salikov/lib/converters/module/rss_convert.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module RssConvert + def self.convert(data) + builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml| + xml.rss('version' => '2.0', 'xmlns:atom' => 'http://www.w3.org/2005/Atom') do + xml.title data[:feed][:title] + xml.link data[:feed][:link] + data[:items].each do |v| + xml.item do + xml.title v[:title] + xml.description v[:description] + xml.link v[:link] + xml.published v[:date] + xml.category v[:category] + end + end + end + end + builder.to_xml + end +end diff --git a/Salikov/lib/parsers/base_parsers.rb b/Salikov/lib/parsers/base_parsers.rb new file mode 100644 index 0000000..13563e6 --- /dev/null +++ b/Salikov/lib/parsers/base_parsers.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module BaseParsers + def self.parse(data) + Main::PARSERS.each do |parser_name| + class_name = Module.const_get(parser_name) + return class_name.parse(data) if class_name.can_parse?(data) + end + end +end diff --git a/Salikov/lib/parsers/modules/atom_parser.rb b/Salikov/lib/parsers/modules/atom_parser.rb new file mode 100644 index 0000000..38a2adb --- /dev/null +++ b/Salikov/lib/parsers/modules/atom_parser.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true +require 'nokogiri' + +module AtomParser + def self.parse(data) + doc = Nokogiri::XML(data) + {feed: parse_feed(doc), + items: parse_items(doc)} + end + + def self.parse_feed(doc) + { + title: doc.at_css('feed title').text.strip, + link: doc.at_css('feed link').text.strip + } + end + + def self.parse_items(doc) + arr = [] + doc.remove_namespaces! + doc = doc.xpath('//entry') + doc.each do |item| + hash = { + title: item.at('title').text, + description: item.at('summary').text, + link: item.at('link').text, + date: item.at('published').text, + category: item.at('category').text + } + arr << hash + end + arr + end + + def self.can_parse?(data) + data.include?(' e + false + end +end diff --git a/Salikov/lib/parsers/modules/rss_parser.rb b/Salikov/lib/parsers/modules/rss_parser.rb new file mode 100644 index 0000000..1036148 --- /dev/null +++ b/Salikov/lib/parsers/modules/rss_parser.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'nokogiri' + +module RssParser + def self.parse(data) + doc = Nokogiri::XML(data) + + {feed: parse_feed(doc), + items: parse_items(doc) } + end + + def self.parse_feed(doc) + { + title: doc.at_css('channel title').text.strip, + link: doc.at_css('channel link').text.strip + } + end + + def self.parse_items(doc) + doc = doc.xpath('//item') + arr = [] + doc.each do |item| + hash = { + title: item.at('title').text, + description: item.at('description').text, + link: item.at('link').text, + date: item.at('pubDate').text, + category: item.at('category').text + } + arr << hash + end + arr + end + + + def self.can_parse?(data) + data.include?('') + end +end diff --git a/Salikov/lib/readers/file_reader.rb b/Salikov/lib/readers/file_reader.rb new file mode 100644 index 0000000..2c5b836 --- /dev/null +++ b/Salikov/lib/readers/file_reader.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module FileReader + def self.read(input) + File.read(input) + end +end diff --git a/Salikov/lib/readers/link_reader.rb b/Salikov/lib/readers/link_reader.rb new file mode 100644 index 0000000..7f85810 --- /dev/null +++ b/Salikov/lib/readers/link_reader.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require 'open-uri' + +module LinkReader + def self.read(input) + page = open(input) + page.read + end +end diff --git a/Salikov/lib/sort/asc_sorter.rb b/Salikov/lib/sort/asc_sorter.rb new file mode 100644 index 0000000..033dda6 --- /dev/null +++ b/Salikov/lib/sort/asc_sorter.rb @@ -0,0 +1,5 @@ +module AscSorter + def self.sort(data) + data.sort_by { |h| h[:pubDate].split(/\/|:|-|T|Z/).reverse } + end +end \ No newline at end of file diff --git a/Salikov/lib/sort/desc_sorter.rb b/Salikov/lib/sort/desc_sorter.rb new file mode 100644 index 0000000..ecfed03 --- /dev/null +++ b/Salikov/lib/sort/desc_sorter.rb @@ -0,0 +1,3 @@ +module DescSorter + +end \ No newline at end of file diff --git a/Salikov/lib/writer/file_writer.rb b/Salikov/lib/writer/file_writer.rb new file mode 100644 index 0000000..4483f02 --- /dev/null +++ b/Salikov/lib/writer/file_writer.rb @@ -0,0 +1,7 @@ +module FileWriter + def self.write(data, link) + file_name = link.split('/') + file_name = file_name[-1].split('.') + File.write("../#{file_name[0]}", data) + end +end \ No newline at end of file diff --git a/Salikov/main.rb b/Salikov/main.rb new file mode 100644 index 0000000..e18832c --- /dev/null +++ b/Salikov/main.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'require_all' +require 'uri' +require_all '../lib/**/*.rb' + +class Main + PARSERS = %w[JsonParser RssParser AtomParser].freeze + CONVERTES = %w[JsonConvert RssConvert AtomConvert].freeze + + def initialize(options) + @input = options[:input] + @output_format = options[:output_format] + @sort = options[:sort] + end + + def run + data = if @input =~ URI::DEFAULT_PARSER.make_regexp + LinkReader.read(@input) + elsif File.file?(@input) + FileReader.read(@input) + else + puts 'ERROR: Not found file' + exit + end + parsed_data = BaseParsers.parse(data) + converted_data = BaseConverter.convert(parsed_data, @output_format) + + FileWriter.write(converted_data, @input) + end +end diff --git a/Salikov/rss-ru-news b/Salikov/rss-ru-news new file mode 100644 index 0000000..da47545 --- /dev/null +++ b/Salikov/rss-ru-news @@ -0,0 +1,145 @@ + + + Deutsche Welle: DW.COM News + + + Меркель призвала немцев к дисциплине в борьбе с вирусом + Распространение коронавируса SARS-CoV-2 - вызов, с какими Германия не сталкивалась со времен Второй мировой, заявила Ангела Меркель. + + 2020-03-18T17:31:00Z + + + + Фирма, связанная с "поваром Путина", доставляет еду пациентам с коронавирусом + Контракт на доставку питания в московскую больницу, где наблюдаются пациенты с коронавирусом, получила без проведения конкурса компания АВК, которую связывают с Евгением Пригожиным. + + 2020-03-18T17:06:00Z + + + + В ЕСПЧ подана первая жалоба избитого силовиками на протестах в Москве + Полицейские ударили Евгения Дубинина об автозак при задержании на протестах в Москве 27 июля. Следственный комитет не нашел нарушений в их действиях. Активист Либертарианской партии обратился в Страсбургский суд. + + 2020-03-18T16:29:00Z + + + + Курс доллара в РФ превысил 80 рублей, евро дорос до 87 рублей + Доллар и евро на Московской бирже 18 марта подорожали на четыре с лишним рубля: впервые за четыре года курс американской валюты превысил 80 рублей, а европейской - 87 рублей. + + 2020-03-18T16:13:00Z + + + + Суд в Ярославле отменил приговор сотруднику колонии по делу об избиении + Сотрудник Ярославской ИК-1 Максим Яблоков был осужден на 3,5 года за избиение заключенного. Областной суд направил дело на новое рассмотрение, сообщили правозащитники. + + 2020-03-18T15:24:00Z + + + + Фигурант "московского дела" Малышевский объявил голодовку в СИЗО + Эдуард Малышевский обвинен в применении насилия к представителю власти на протестах в Москве 27 июля и приговорен к 33 месяцам колонии. Он держит голодовку с 28 февраля, протестуя против приговоров по "московскому делу". + + 2020-03-18T14:41:00Z + + + + Дочь экс-президента Узбекистана приговорена к 13 годам заключения + Гульнару Каримову осудили в третий раз, признав виновной в организации преступного сообщества, вымогательстве, хищении и других преступлениях. Наказание будет исчисляться с 21 августа 2015 года. + + 2020-03-18T14:05:00Z + + + + В ЕС заявили о росте дезинформации из России по теме коронавируса + С началом эпидемии коронавируса российские источники начали распространять в Евросоюзе дезинформацию, связанную с COVID-19. Об этом заявили во внешнеполитической службе Евросоюза. + + 2020-03-18T13:46:00Z + + + + Песенный конкурс "Евровидение-2020" отменен + Европейский вещательный союз увязал отмену "Евровидения-2020" в Роттердаме с угрозой распространения коронавируса. + + 2020-03-18T13:42:00Z + + + + Бывший главный следователь Москвы приговорен к 12 годам колонии за взятку + Мосгорсуд признал Александра Дрыманова виновным в получении крупной взятки. Экс-главе московского СК назначен штраф в 196 млн рублей. Ему на 7 лет запрещено занимать должности в органах власти. + + 2020-03-18T13:18:00Z + + + + Израиль заблокировал палестинские территории из-за коронавируса + Из Палестинской автономии в Израиль впредь будут впускать лишь по гуманитарным причинам. В Израиле зафиксировано уже более 400 случаев заражения коронавирусом. + + 2020-03-18T13:11:00Z + + + + Джо Байден победил на праймериз во Флориде, Иллинойсе и Аризоне + Победив в первичных выборах еще в трех штатах, Джо Байден оставил мало шансов своему сопернику Берни Сандерсу. Однако, несмотря на давление, Сандерс не намерен выходить из предвыборной гонки. + + 2020-03-18T11:55:00Z + + + + Глава института ifo предрекает Германии более суровую рецессию, чем в 2009 году + Пандемия коронавируса может погрузить ФРГ в пучину сложного кризиса, масштабы которого многие недооценивают, полагает институт ifo. Немецкой экономике угрожает даже более крупный обвал, чем в 2009 году. + + 2020-03-18T11:39:00Z + + + + Азербайджанскому журналисту Мухтарли разрешили выехать в ФРГ + Афган Мухтарли занимался расследованием коррупции в Азербайджане и был посажен в тюрьму. Его освобождения активно добивалась правозащитная организация "Репортеры без границ". + + 2020-03-18T09:32:00Z + + + + Чемпионат Европы по футболу в 2021 пройдет в тех же городах + Матчи чемпионата состоятся на тех же стадионах, на которых они планировались летом нынешнего года. ЧЕ-2020 был перенесен на будущий год из-за пандемии коронавируса. + + 2020-03-18T08:14:00Z + + + + Немецкий врач раскритиковал запрет покидать дома из-за коронавируса + По мнению председателя Всемирной медицинской ассоциации, такие меры не помогают остановить распространение вируса. Франк Монтгомери назвал локдаун жестом отчаяния властей и акционизмом. + + 2020-03-18T07:29:00Z + + + + Китай отозвал аккредитацию у журналистов крупных американских газет + Это ответные меры на действия США, которые ранее приравняли сотрудников китайских государственных СМИ к иностранным агентам. Из-за этого Китаю пришлось сократить количество журналистов в американских бюро. + + 2020-03-18T03:54:00Z + + + + Помпео обвинил Россию в убийстве турецких солдат в Сирии + США заявили о поддержке Турции и намерены принять дополнительные меры по поддержке Анкары, чтобы "положить конец насилию в Сирии", заявил глава Государственного департамента. + + 2020-03-18T01:50:00Z + + + + Меркель официально объявила о закрытии границ Евросоюза + В ближайшие 30 дней в Евросоюз смогут въезжать только европейские граждане и члены их семей, граждане Великобритании, Исландии, Лихтенштейна, Норвегии, Швейцарии, а также лица с видом на жительство ЕС. + + 2020-03-18T00:34:00Z + + + + Хроника пандемии: В России выявлено 33 новых случая заражения коронавирусом + В мире принимаются беспрецедентные меры, чтобы сдержать дальнейшее распространение коронавируса SARS-CoV-2, которым заразились более 213 тысяч человек. DW следит за развитием событий. + + 2020-03-17T23:17:00Z + + + diff --git a/Salikov/test/file_reader_test.rb b/Salikov/test/file_reader_test.rb new file mode 100644 index 0000000..e69de29