Skip to content

Homework 2 #778

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit 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
2 changes: 2 additions & 0 deletions 2018/AnatoliDobshikov/2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
passport.yml
octotest.rb
12 changes: 12 additions & 0 deletions 2018/AnatoliDobshikov/2/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
source "https://rubygems.org"

# bot api
gem 'telegram-bot-ruby'
# for easier classes requiring
gem 'require_all'
# GitHub api
gem 'octokit'
# postgresql gem
gem 'pg'
# ORM adapter
gem 'activerecord'
68 changes: 68 additions & 0 deletions 2018/AnatoliDobshikov/2/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
GEM
remote: https://rubygems.org/
specs:
activemodel (5.2.0)
activesupport (= 5.2.0)
activerecord (5.2.0)
activemodel (= 5.2.0)
activesupport (= 5.2.0)
arel (>= 9.0)
activesupport (5.2.0)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
arel (9.0.0)
axiom-types (0.1.1)
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
concurrent-ruby (1.0.5)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
equalizer (0.0.11)
faraday (0.14.0)
multipart-post (>= 1.2, < 3)
i18n (1.0.0)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
inflecto (0.0.2)
minitest (5.11.3)
multipart-post (2.0.0)
octokit (4.8.0)
sawyer (~> 0.8.0, >= 0.5.3)
pg (1.0.0)
public_suffix (3.0.2)
require_all (2.0.0)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
telegram-bot-ruby (0.8.6.1)
faraday
inflecto
virtus
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
virtus (1.0.5)
axiom-types (~> 0.1)
coercible (~> 1.0)
descendants_tracker (~> 0.0, >= 0.0.3)
equalizer (~> 0.0, >= 0.0.9)

PLATFORMS
ruby

DEPENDENCIES
activerecord
octokit
pg
require_all
telegram-bot-ruby

BUNDLED WITH
1.16.1
44 changes: 44 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/CommandController.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# here is the main logic
# here we decide what to response
require 'telegram/bot'
require 'pg'
require 'active_record'
require_relative 'model/User.rb'

class CommandController
# switch message and find exact answer
def self.handler(message = Telegram::Bot::Types::Message.new)
# trying to find a user in database
user = User.find_by(id: message.from.id)
# add user to database if he is not already in it
if user.nil?
user = User.create(id: message.from.id, current_repo: 'none', last_command: 'none')
end
# use the bot's memory to make complicated requests
text = user.last_command == 'none' ? message.text : user.last_command
# chose the suitable answer to the /question
case text
# first contact with the user)))
when '/start'
StartCommand.new(message)
# show help
when '/help'
HelpCommand.new(message)
# set new repo adress
when '/set_repo'
SetRepoCommand.new(message, user)
# show user's new repository
when '/show_repo'
ShowRepoCommand.new(message, user)
# search in commits
when '/search'
SearchCommand.new(message, user)
# view search history
when '/history'
HistoryCommand.new(message)
# default answer for unknown commands
else
TeleBotCommand.new()
end
end
end
14 changes: 14 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/HelpCommand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'telegram/bot'
require_relative 'TeleBotCommand'
# It shows info about the bot
class HelpCommand < TeleBotCommand
def reply
"Available commands list:
/help - view help;
/set_repo - set the repository to search;
/show_repo - show current repository address;
/search - search in the current repository, while searching type /1 to get the first page or /3 to get the third page, type /ok to end searching;
/history - print your search queries.
!Warning - search works only with the first 30 results! Sorry for this(((("
end
end
27 changes: 27 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/HistoryCommand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# query history
require 'pg'
require 'active_record'
require 'telegram/bot'
require_relative 'TeleBotCommand'
require_relative 'model/Request'

class HistoryCommand < TeleBotCommand
def reply
# load all requests for current user
requests = Request.where(user_id: @message.from.id)
# if user haven't got queries YET
if requests.length == 0
return "You haven't got any queries. \nType /help to see the commands list."
end
# form history
history = "History of #{@message.from.first_name} #{@message.from.last_name}.\n"
requests.length.times do |index|
history += "#{requests[index].updated_at}: searching for #{requests[index].query} in #{requests[index].repository} repository.\n"
end
# cut VERY long history
if history.length > 4090
history = "..." + history.slice((history.length - 4090)..(history.length - 1))
end
history
end
end
18 changes: 18 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/RepoCommandExtension.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require 'octokit'
require_relative 'TeleBotCommand'
# safe repository setter
class RepoCommandExtension < TeleBotCommand
def initialize_repo(address = String.new)
begin
@repo = Octokit.repo(address)
rescue Octokit::NotFound
'Cannot find this repository.'
rescue Octokit::RepositoryUnavailable
'Access denied.'
rescue Octokit::InvalidRepository
'Invalid repository.'
rescue
'Unknown error.'
end
end
end
83 changes: 83 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/SearchCommand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Here we will search for something in somewhere and we would hope that we can find something really cool
require 'pg'
require 'active_record'
require 'json'
require_relative 'model/Request'
require_relative 'RepoCommandExtension'

class SearchCommand < RepoCommandExtension
def reply
# check if repo is available
error_message = initialize_repo(@user.current_repo)
if @repo.nil?
return "#{error_message}\nPlease, set the available repository."
end
# ask to input search query
unless @user.last_command == '/search'
@user.update(last_command: '/search')
return 'Input search query:'
end
# listing the results
@request = Request.find_by(user_id: @user.id, active: true)
# if user has active requests
unless @request.nil?
# end dialog
if @message.text == '/ok'
@user.update(last_command: 'none')
@request.update(active: false)
return 'I hope you found something useful.'
end
# page listing
@search_results = search(@request[:query])
page_number = @message.text.delete('/').to_i
case page_number
when 1..(@search_results['items'].length / 3)
return print_page(page_number)
else
return "Cannot find this page. Type '/ok' to end search. Type '/{page_number}' to view page(/5 for example)."
end
end
# process new query
@search_results = search(@message.text)
# add request to DB
@request = Request.create(query: @message.text, repository: @user.current_repo, user_id: @user.id, active: true)
return "I have found #{@search_results['total_count']} result(s).\n#{print_page(1)}"
end

private
# create query for http GET
def create_query(query_text = String.new)
"repo:#{@user.current_repo}+#{query_text.split(' ').join('+')}"
end
# search in github commits
def search(query_text = String.new)
query = create_query(query_text)
# search via github api
search_text = %x`curl -H 'Accept: application/vnd.github.cloak-preview+json' \
-i https://api.github.com/search/commits?q=#{query}`
# select JSON from response
search_text = search_text.slice(search_text.index('{')..(search_text.length - 1))
JSON.parse(search_text)
end
# list the search results
def print_page(page_number = 1)
# header
page = "Searching for #{@request.query} in #{@request.repository}.\n"
page += "Page /#{page_number} of /#{@search_results['items'].length / 3} (three items per page):\n#{'=' * 30}\n"
item_number = (page_number - 1) * 3 + 1
# body XD
3.times do
if item_number > @search_results['items'].length
return "#{page}\nThis is the last page. Type /ok to end search dialog, if you want.\n#{'=' * 30}\n"
end
commit_message = (@search_results['items'][item_number - 1]['commit']['message']).split("\n").join('. ')
# cut long messages
if commit_message.length > 100
commit_message = commit_message.slice(0..96) + '...'
end
page += "#{item_number}. Link: #{@search_results['items'][item_number - 1]['html_url']}\nMessage: #{commit_message}\n#{'=' * 30}\n"
item_number += 1
end
page
end
end
27 changes: 27 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/SetRepoCommand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'telegram/bot'
require_relative 'RepoCommandExtension'
require 'pg'
require 'active_record'
require_relative 'model/User.rb'
require 'octokit'
# set the repository to work with it
class SetRepoCommand < RepoCommandExtension
def reply
# if user is asked to set new adress of the repository
if @user.last_command != '/set_repo'
@user.update(last_command: '/set_repo')
"Please, input repository address ('rubyroidlabs/bsuir-courses' for example):"
# if user send his adress of the repository
else
# rescue errors
error_message = initialize_repo(@message.text)
unless @repo.nil?
@user.update(current_repo: @message.text, last_command: 'none')
return "#{@message.text} repository have set."
else
@user.update(last_command: 'none')
return error_message
end
end
end
end
9 changes: 9 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/ShowRepoCommand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# here we will show to User his current repository
require 'telegram/bot'
require_relative 'TeleBotCommand'
# command class
class ShowRepoCommand < TeleBotCommand
def reply
"Current repository is #{@user.current_repo}."
end
end
9 changes: 9 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/StartCommand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'telegram/bot'
require_relative 'TeleBotCommand'
# Cindy introduce itself in this class
class StartCommand < TeleBotCommand
# introducing and giving the additional information about Cindy
def reply
return "Hello, #{@message.from.first_name}.\nMy name is Cindy. I can help you to work with the GitHub.\nYou can type /help to see what I exactly can do."
end
end
14 changes: 14 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/TeleBotCommand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'telegram/bot'
require_relative 'model/User.rb'
# super class for all commands
class TeleBotCommand
# constructor
def initialize(message = Telegram::Bot::Types::Message.new(), user = User.new)
@message = message
@user = user
end
# here is the answer to wrong request
def reply
"I'm sorry I do not understand you.\nTry to type /help to see what I can understand."
end
end
7 changes: 7 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/model/Request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'pg'
require 'active_record'

class Request < ActiveRecord::Base
# owner of the requests history
belongs_to :user
end
7 changes: 7 additions & 0 deletions 2018/AnatoliDobshikov/2/lib/model/User.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'pg'
require 'active_record'

class User < ActiveRecord::Base
# requests history
has_many :requests, dependent: :destroy
end
38 changes: 38 additions & 0 deletions 2018/AnatoliDobshikov/2/migrations/Request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# here is the requests tablesheet migration
require 'pg'
require 'active_record'
require 'pry'

PASSPORT = YAML.load(File.read('../passport.yml'))
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base::establish_connection(
adapter: 'postgresql',
host: '',
user: PASSPORT['user'],
database: PASSPORT['database']
)

class CreateRequests < ActiveRecord::Migration[5.0]
def up
create_table :requests do |t|
# owner of the request
t.references :user, foreign_key: true, index: true
# text of the request
t.string :query
# repository address
t.string :repository
# is active
t.boolean :active
# when we had do it
t.timestamps
end
end

def down
drop_table :requests
end
end

create = CreateRequests.new

binding.pry
Loading