Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

2331 - 3 #270

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions 2331/3/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
source 'https://rubygems.org'

gem 'json'
gem 'mechanize'
gem 'ohm'
gem 'rake'
gem 'sinatra'
gem 'thin'

group :development do
gem 'pry'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shotgun is also dev dependency

gem 'shotgun'
end
83 changes: 83 additions & 0 deletions 2331/3/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
GEM
remote: https://rubygems.org/
specs:
coderay (1.1.2)
connection_pool (2.2.2)
daemons (1.2.6)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
eventmachine (1.2.7)
hiredis (0.6.1)
http-cookie (1.0.3)
domain_name (~> 0.5)
json (2.1.0)
mechanize (2.7.6)
domain_name (~> 0.5, >= 0.5.1)
http-cookie (~> 1.0)
mime-types (>= 1.17.2)
net-http-digest_auth (~> 1.1, >= 1.1.1)
net-http-persistent (>= 2.5.2)
nokogiri (~> 1.6)
ntlm-http (~> 0.1, >= 0.1.1)
webrobots (>= 0.0.9, < 0.2)
method_source (0.9.0)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_portile2 (2.3.0)
mustermann (1.0.2)
nest (3.1.1)
redic
net-http-digest_auth (1.4.1)
net-http-persistent (3.0.0)
connection_pool (~> 2.2)
nokogiri (1.8.4)
mini_portile2 (~> 2.3.0)
ntlm-http (0.1.1)
ohm (3.1.1)
nest (~> 3)
redic (~> 1.5.0)
stal
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
rack (2.0.5)
rack-protection (2.0.3)
rack
rake (12.3.1)
redic (1.5.0)
hiredis
shotgun (0.9.2)
rack (>= 1.0)
sinatra (2.0.3)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.3)
tilt (~> 2.0)
stal (0.3.0)
redic (~> 1.5)
thin (1.7.2)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
tilt (2.0.8)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
webrobots (0.1.2)

PLATFORMS
ruby

DEPENDENCIES
json
mechanize
ohm
pry
rake
shotgun
sinatra
thin

BUNDLED WITH
1.16.0
7 changes: 7 additions & 0 deletions 2331/3/config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'bundler'
Bundler.require

Dir.glob('./{controllers,helpers,models}/*.rb').each { |file| require_relative file }

map('/articles') { run ArticlesController }
map('/') { run ApplicationController }
12 changes: 12 additions & 0 deletions 2331/3/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class ApplicationController < Sinatra::Base
set :views, File.expand_path(File.join(__FILE__, '../../views'))
set :method_override, true

not_found do
erb :not_found
end

get '/' do
redirect to '/articles'
end
end
39 changes: 39 additions & 0 deletions 2331/3/controllers/articles_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require_relative './application_controller.rb'

class ArticlesController < ApplicationController
get '/' do
@articles = Article.all
erb :'/articles/index'
end

get '/new' do
erb :'/articles/create'
end

post '/' do
@article = ArticleBuilder.new(params).create
redirect to '/'
end

get '/:id' do
@article = Article[params[:id]]
@comments = @article.comments
erb :'/articles/show'
end

get '/:id/edit' do
@article = Article[params[:id]]
erb :'articles/edit'
end

delete '/:id' do
Article[params[:id]].delete
redirect to '/'
end

post '/:id' do
@article = Article[params[:id]]
@article.update(link: params[:article])
redirect to "/#{params[:id]}"
end
end
28 changes: 28 additions & 0 deletions 2331/3/helpers/article_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class ArticleBuilder
attr_reader :article

def initialize(options)
@article_link = options[:article]
@comments = ArticleParser.new(@article_link).comments
end

def create
@article = Article.create(link: @article_link, title: title, rating: article_rating)
CommentsBuilder.new(comments_with_rating, article).create
article
end

private

def article_rating
comments_with_rating.map { |comment| comment[:rating] }.sum / @comments.size
end

def comments_with_rating
CommentsReferee.new(@comments).put_ratings
end

def title
ArticleParser.new(@article_link).title
end
end
36 changes: 36 additions & 0 deletions 2331/3/helpers/article_parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class ArticleParser
def initialize(link = 'https://people.onliner.by/2018/07/23/vodol')
@agent = Mechanize.new
@article_link = link
end

def title
@agent.get(@article_link).search('.news-header__title').text.strip
end

def comments
data['comments'].reverse.map do |comment|
{ author: CommentHelper.author(comment),
text: CommentHelper.text(comment),
votes: CommentHelper.votes(comment) }
end
end

private

def data
JSON.parse(@agent.get(comment_link).body)
end

def comment_link
"https://comments.api.onliner.by/news/#{section}.post/#{article_id}/comments?limit=9999"
end

def section
@article_link[%r{https://(\w+)}, 1]
end

def article_id
@agent.get(@article_link).search('.news_view_count').attr('news_id').value
end
end
13 changes: 13 additions & 0 deletions 2331/3/helpers/comment_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module CommentHelper
def self.votes(options)
options['marks'].values.reduce(:+)
end

def self.author(options)
options['author']['name']
end

def self.text(options)
options['text']
end
end
15 changes: 15 additions & 0 deletions 2331/3/helpers/comments_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class CommentsBuilder
LIMIT = 50

def initialize(comments, article)
@comments = comments
@article = article
end

# :reek:FeatureEnvy
def create
@comments.each do |comment|
Comment.create(author: comment[:author], text: comment[:text], rating: comment[:rating], article: @article)
end
end
end
23 changes: 23 additions & 0 deletions 2331/3/helpers/comments_referee.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class CommentsReferee
LIMIT = 50

def initialize(comments)
@comments = comments
end

# :reek:FeatureEnvy
def put_ratings
selected_for_evaluation = sort_comments_by_votes
ratings = RatingCounter.new(selected_for_evaluation).calculate
selected_for_evaluation.zip(ratings).map do |record|
record.first[:rating] = record.last
record[0]
end
end

private

def sort_comments_by_votes
@comments.sort_by { |comment| comment[:votes] }.reverse.first(LIMIT)
end
end
45 changes: 45 additions & 0 deletions 2331/3/helpers/rating_counter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'net/https'
require 'uri'
require 'json'

class RatingCounter
URI = 'https://westeurope.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment'.freeze
ACCESS_KEY = ENV['ACCESS_KEY_AZURE']
attr_reader :request

def initialize(comments)
@uri = URI(URI)
@data = { documents: [] }
@comments = comments
end

def calculate
prepare_comments
@request = create_request
response = send_request
JSON.parse(response.body)['documents'].map do |data|
(data['score'] * 200).to_i - 100
end
end

private

def send_request
Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.scheme == 'https') do |http|
http.request(request)
end
end

def prepare_comments
@comments.each_with_index do |comment, index|
@data[:documents] << { 'id' => index.to_s, 'language' => 'ru', 'text' => comment[:text] }
end
end

def create_request
request = Net::HTTP::Post.new(@uri, 'Content-Type' => 'application/json',
'Ocp-Apim-Subscription-Key' => ACCESS_KEY)
request.body = @data.to_json
request
end
end
7 changes: 7 additions & 0 deletions 2331/3/models/article.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Article < Ohm::Model
attribute :link
attribute :title
attribute :rating
unique :link
collection :comments, :Comment
end
6 changes: 6 additions & 0 deletions 2331/3/models/comment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Comment < Ohm::Model
attribute :author
attribute :text
attribute :rating
reference :article, :Article
end
10 changes: 10 additions & 0 deletions 2331/3/views/articles/create.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<h1>New article</h1>

<form action="/articles" method="post">
<div class="form-group">
<label for="article">Article's link</label>
<input type="text" class="form-control" id="article" aria-describedby="emailHelp" title="Example: https://tech.onliner.by/2018/07/26/eksperiment-biosfera-2" placeholder="Input link" name="article" value="" pattern="^(http|https):\/\/\w+\.onliner.+" autofocus>
<small id="emailHelp" class="form-text text-muted">Link to be processed</small>
</div>
<button type="submit" class="btn btn-success">Add</button>
</form>
10 changes: 10 additions & 0 deletions 2331/3/views/articles/edit.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<h1>Edit article</h1>

<form action="/articles/<%= @article.id %>" method="post">
<div class="form-group">
<label for="article">Article's link</label>
<input type="text" class="form-control" id="article" aria-describedby="emailHelp" placeholder="Input link" name="article" title="Example: https://tech.onliner.by/2018/07/26/eksperiment-biosfera-2" pattern="^(http|https):\/\/\w+\.onliner.+" value="<%= @article.link %>" autofocus>
<small id="emailHelp" class="form-text text-muted">Link to be edited</small>
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
21 changes: 21 additions & 0 deletions 2331/3/views/articles/index.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<h1>Articles</h1>

<table class="table table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>Title</th>
<th colspan=2>Rating</th>
</tr>
</thead>
<tbody>
<% @articles.each_with_index do |article, index| %>
<tr>
<td><%= index + 1 %></td>
<td><a href=<%= article.link %>><%= article.title %></a></td>
<td><a><%= article.rating %></a></td>
<td><a href=<%= "/articles/#{article.id}" %>><span class="glyphicon glyphicon-search"></span></a></td>
</tr>
<% end %>
</tbody>
</table>
Loading