diff --git a/.gitignore b/.gitignore index 4c0afde3..4635d155 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,5 @@ .DS_Store .idea/ + +.env.dev diff --git a/Gemfile b/Gemfile index 879efebb..ac24ff8e 100644 --- a/Gemfile +++ b/Gemfile @@ -42,7 +42,9 @@ gem 'stimulus-rails' # Build JSON APIs with ease [https://github.com/rails/jbuilder] gem 'jbuilder' - +gem 'public_suffix' +gem 'rack' +gem 'rack-session' # Use Redis adapter to run Action Cable in production # gem "redis", ">= 4.0.1" diff --git a/Gemfile.lock b/Gemfile.lock index fb0cc760..56603df2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -370,7 +370,10 @@ DEPENDENCIES jbuilder pg (~> 1.1) pkce_challenge + public_suffix puma (>= 5.0) + rack + rack-session rails (~> 7.1.3, >= 7.1.3.4) rails_performance rubocop (~> 1.65) diff --git a/Makefile b/Makefile index fad5873c..540254fb 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ SHELL=/bin/sh UID := $(shell id -u) GID := $(shell id -g) -include .env -export +# include .env +# export setup: build db-prepare diff --git a/_Gemfile.lock b/_Gemfile.lock new file mode 100644 index 00000000..49b6ff85 --- /dev/null +++ b/_Gemfile.lock @@ -0,0 +1,386 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.1.3.4) + actionpack (= 7.1.3.4) + activesupport (= 7.1.3.4) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + zeitwerk (~> 2.6) + actionmailbox (7.1.3.4) + actionpack (= 7.1.3.4) + activejob (= 7.1.3.4) + activerecord (= 7.1.3.4) + activestorage (= 7.1.3.4) + activesupport (= 7.1.3.4) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.1.3.4) + actionpack (= 7.1.3.4) + actionview (= 7.1.3.4) + activejob (= 7.1.3.4) + activesupport (= 7.1.3.4) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.2) + actionpack (7.1.3.4) + actionview (= 7.1.3.4) + activesupport (= 7.1.3.4) + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4) + rack-session (>= 1.0.1) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + actiontext (7.1.3.4) + actionpack (= 7.1.3.4) + activerecord (= 7.1.3.4) + activestorage (= 7.1.3.4) + activesupport (= 7.1.3.4) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.1.3.4) + activesupport (= 7.1.3.4) + builder (~> 3.1) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.1.3.4) + activesupport (= 7.1.3.4) + globalid (>= 0.3.6) + activemodel (7.1.3.4) + activesupport (= 7.1.3.4) + activerecord (7.1.3.4) + activemodel (= 7.1.3.4) + activesupport (= 7.1.3.4) + timeout (>= 0.4.0) + activestorage (7.1.3.4) + actionpack (= 7.1.3.4) + activejob (= 7.1.3.4) + activerecord (= 7.1.3.4) + activesupport (= 7.1.3.4) + marcel (~> 1.0) + activesupport (7.1.3.4) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + administrate (0.20.1) + actionpack (>= 6.0, < 8.0) + actionview (>= 6.0, < 8.0) + activerecord (>= 6.0, < 8.0) + jquery-rails (~> 4.6.0) + kaminari (~> 1.2.2) + sassc-rails (~> 2.1) + selectize-rails (~> 0.6) + ast (2.4.2) + base64 (0.2.0) + bcrypt (3.1.20) + bigdecimal (3.1.8) + bindex (0.8.1) + bootsnap (1.18.3) + msgpack (~> 1.2) + browser (6.0.0) + builder (3.3.0) + capybara (3.40.0) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.11) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + concurrent-ruby (1.3.3) + connection_pool (2.4.1) + crass (1.0.6) + cssbundling-rails (1.4.0) + railties (>= 6.0.0) + csv (3.3.0) + date (3.3.4) + debug (1.9.2) + irb (~> 1.10) + reline (>= 0.3.8) + devise (4.9.4) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0) + responders + warden (~> 1.2.3) + digest (3.1.1) + drb (2.2.1) + erubi (1.13.0) + faraday (2.10.0) + faraday-net_http (>= 2.0, < 3.2) + logger + faraday-net_http (3.1.0) + net-http + ffi (1.16.3) + ffi (1.16.3-x64-mingw-ucrt) + globalid (1.2.1) + activesupport (>= 6.1) + httparty (0.22.0) + csv + mini_mime (>= 1.0.0) + multi_xml (>= 0.5.2) + i18n (1.14.5) + concurrent-ruby (~> 1.0) + importmap-rails (2.0.1) + actionpack (>= 6.0.0) + activesupport (>= 6.0.0) + railties (>= 6.0.0) + io-console (0.7.2) + irb (1.14.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + jbuilder (2.12.0) + actionview (>= 5.0.0) + activesupport (>= 5.0.0) + jquery-rails (4.6.0) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + json (2.7.2) + kaminari (1.2.2) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.2.2) + kaminari-activerecord (= 1.2.2) + kaminari-core (= 1.2.2) + kaminari-actionview (1.2.2) + actionview + kaminari-core (= 1.2.2) + kaminari-activerecord (1.2.2) + activerecord + kaminari-core (= 1.2.2) + kaminari-core (1.2.2) + language_server-protocol (3.17.0.3) + logger (1.6.0) + loofah (2.22.0) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.4) + matrix (0.4.2) + mini_mime (1.1.5) + minitest (5.24.1) + msgpack (1.7.2) + multi_xml (0.7.1) + bigdecimal (~> 3.1) + mutex_m (0.2.0) + net-http (0.4.1) + uri + net-imap (0.4.14) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.0) + net-protocol + nio4r (2.7.3) + nokogiri (1.16.6-x64-mingw-ucrt) + racc (~> 1.4) + nokogiri (1.16.6-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.16.6-x86_64-linux) + racc (~> 1.4) + orm_adapter (0.5.0) + parallel (1.25.1) + parser (3.3.4.0) + ast (~> 2.4.1) + racc + pg (1.5.6) + pg (1.5.6-x64-mingw-ucrt) + pkce_challenge (1.0.0) + psych (5.1.2) + stringio + public_suffix (6.0.0) + puma (6.4.2) + nio4r (~> 2.0) + racc (1.8.0) + rack (3.1.7) + rack-session (2.0.0) + rack (>= 3.0.0) + rack-test (2.1.0) + rack (>= 1.3) + rackup (2.1.0) + rack (>= 3) + webrick (~> 1.8) + rails (7.1.3.4) + actioncable (= 7.1.3.4) + actionmailbox (= 7.1.3.4) + actionmailer (= 7.1.3.4) + actionpack (= 7.1.3.4) + actiontext (= 7.1.3.4) + actionview (= 7.1.3.4) + activejob (= 7.1.3.4) + activemodel (= 7.1.3.4) + activerecord (= 7.1.3.4) + activestorage (= 7.1.3.4) + activesupport (= 7.1.3.4) + bundler (>= 1.15.0) + railties (= 7.1.3.4) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + rails_performance (1.2.2) + browser + railties + redis + redis-namespace + railties (7.1.3.4) + actionpack (= 7.1.3.4) + activesupport (= 7.1.3.4) + irb + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) + rainbow (3.1.1) + rake (13.2.1) + rdoc (6.7.0) + psych (>= 4.0.0) + redis (5.2.0) + redis-client (>= 0.22.0) + redis-client (0.22.2) + connection_pool + redis-namespace (1.11.0) + redis (>= 4) + regexp_parser (2.9.2) + reline (0.5.9) + io-console (~> 0.5) + responders (3.1.1) + actionpack (>= 5.2) + railties (>= 5.2) + rexml (3.3.2) + strscan + rubocop (1.65.0) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.4, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.31.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.31.3) + parser (>= 3.3.1.0) + ruby-progressbar (1.13.0) + rubyzip (2.3.2) + sassc (2.4.0) + ffi (~> 1.9) + sassc-rails (2.1.2) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt + selectize-rails (0.12.6) + selenium-webdriver (4.23.0) + base64 (~> 0.2) + logger (~> 1.4) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + sprockets (4.2.1) + concurrent-ruby (~> 1.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + sprockets (>= 3.0.0) + stimulus-rails (1.3.3) + railties (>= 6.0.0) + stringio (3.1.1) + strscan (3.1.0) + thor (1.3.1) + tilt (2.4.0) + timeout (0.4.1) + turbo-rails (2.0.6) + actionpack (>= 6.0.0) + activejob (>= 6.0.0) + railties (>= 6.0.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + tzinfo-data (1.2024.1) + tzinfo (>= 1.0.0) + unicode-display_width (2.5.0) + uri (0.13.0) + warden (1.2.9) + rack (>= 2.0.9) + web-console (4.2.1) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) + bindex (>= 0.4.0) + railties (>= 6.0.0) + webrick (1.8.1) + websocket (1.2.11) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.16) + +PLATFORMS + x64-mingw-ucrt + x86_64-darwin-23 + x86_64-linux + +DEPENDENCIES + administrate + bootsnap + capybara + cssbundling-rails + debug + devise + digest + faraday + ffi (~> 1.16.3) + httparty + importmap-rails (~> 2.0.1) + jbuilder + pg (~> 1.1) + pkce_challenge + puma (>= 5.0) + rack (~> 3.1.7) + rack-session (~> 2.0.0) + rackup (~> 2.1.0) + rails (~> 7.1.3, >= 7.1.3.4) + rails_performance + rubocop (~> 1.65) + selenium-webdriver (~> 4.23.0) + sprockets-rails + stimulus-rails + turbo-rails (~> 2.0.6) + tzinfo-data + web-console + +RUBY VERSION + ruby 3.2.4p170 + +BUNDLED WITH + 2.4.19 diff --git a/app/api/vk.rb b/app/api/vk.rb new file mode 100644 index 00000000..c54fb4f6 --- /dev/null +++ b/app/api/vk.rb @@ -0,0 +1,279 @@ +# frozen_string_literal: true + +class Vk # rubocop:disable Metrics/ClassLength + def self.client + Faraday.new(url: 'https://api.vk.com') do |conn| + conn.headers['Content-Type'] = 'application/json' + conn.headers['Accept'] = 'application/json' + conn.request :json + conn.response :json + conn.response :logger + end + end + + def self.vkid_client + Faraday.new(url: 'https://id.vk.com') do |conn| + conn.headers['Content-Type'] = 'application/json' + conn.headers['Accept'] = 'application/json' + conn.request :json + conn.response :json + conn.response :logger + end + end + + def self.try_request(method, path, body = nil, headers = nil, client: self.client) + client.send method, path, body, headers + end + + def self.exchange_code(code, code_verifier, device_id, state) + resp = try_request(:post, + '/oauth2/auth', + { grant_type: 'authorization_code', + code:, + code_verifier:, + device_id:, + redirect_uri: "#{ENV['HOST']}/auth/vkontakte/callback/", + state:, + client_id: '51989509' }, + client: vkid_client) + resp.body + end + + def self.refresh_usertokens(refresh_token, device_id, state) + resp = try_request(:post, + '/oauth2/auth', + { grant_type: 'refresh_token', + refresh_token:, + device_id:, + state:, + client_id: '51989509' }, + client: vkid_client) + resp.body + end + + def self.get_friends(user) + resp = try_request(:get, + '/method/friends.get', + { access_token: user.access_token, + v: '5.199', + fields: %w[photo_50 first_name last_name] }, + { 'Authorization': "Bearer #{user.access_token}" }) + response_hash = resp.body['response']['items'] + puts 'FRIENDLY FIRE' + puts resp.body + # friends_id_list_str = response_hash.map(&:to_s).join(', ') + + # response_info = try_request(:get, + # '/method/users.get', + # { access_token: user.access_token, + # v: '5.199', + # user_ids: friends_id_list_str, + # fields: 'photo_100 first_name last_name' }, + # { 'Authorization': "Bearer #{user.access_token}" } + # client:) + response_hash + end + + def self.get_followers(user) + resp = try_request(:get, + 'method/users.getFollowers', + { access_token: user.access_token, + user_id: user.user_id, + v: '5.199' }, + client:) + resp.body['response']['items'] + end + + # def self.get_data(user) + # resp = try_request(:get, + # '/method/wall.get', + # { access_token: user.access_token, + # user_id: user.user_id, + # count: 100, + # v: '5.199', + # filter: 'all' }, + # client:) + + # resp.body['response']['items'] + # end + + def self.get_profile_info(user) + resp = try_request(:get, + '/method/users.get', + { access_token: user.access_token, + user_ids: user.user_id, + v: '5.199', + fields: 'first_name last_name photo_100' }, + client:) + resp.body['response'][0] + end + + def self.get_data(user) # rubocop:disable Metrics/AbcSize + resp = try_request(:get, + '/method/wall.get', + { access_token: user.access_token, + v: '5.199', + user_id: user.user_id, + count: 100, + filter: 'all' }, + client:) + post_data_all = resp.body['response']['items'] + post_data_all.map do |post_data| + like_count = post_data['likes']['count'] + comment_count = post_data['comments']['count'] + + post_likers = if like_count.zero? + [] + else + get_likers(post_data['id'], like_count.to_i, user) + end + # post_commentators = if comment_count.zero? + # [] + # else + # get_commentators(post_data['id'], comment_count.to_i, user) + # end + { + post_id: post_data['id'], + date: post_data['date'], + image_url: get_image_from_post(post_data['attachments']), + count_likes: post_data['likes']['count'], + # count_comments: post_data['comments']['count'], + count_comments: 0, + likers: post_likers, + # commentators: post_commentators + commentators: [] + } + end + end + + # проверить утром на работо способность!!!!!!!!!!! + def self.get_image_from_post(post_media) + image_url = 'https://a.d-cd.net/8bdfd7cs-960.jpg' # серый квадрат + post_media.each do |media| + image_url = find_image_from_media(media) + break if image_url != 'https://a.d-cd.net/8bdfd7cs-960.jpg' || !image_url.nil? # серый квадрат + end + image_url + end + + def self.find_image_from_media(media) # rubocop:disable Metrics/AbcSize + case media['type'] + when 'photo' + return find_image_of_size(media['photo']['sizes']) + when 'album' + return find_image_of_size(media['album']['thumb']['sizes']) + when 'link' + return find_image_of_size(media['link']['photo']['sizes']) if media['link'].key?('photo') + when 'video' + return media['video']['image'][0]['url'] + when 'poll' + return 'https://www.tgu-dpo.ru/wp-content/uploads/2023/06/%D0%BE%D0%BF%D1%80%D0%BE%D1%81-%D0%B2-Google-%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D1%85.jpg' # картинка опроса + end + nil + end + + def self.find_image_of_size(photo_from_media) + photo_from_media.each do |photo| + return photo['url'] if photo['type'] == 'm' + end + nil + end + # def self.get_image_from_post(post_media) + # photo_found = false + # image_url = 'https://a.d-cd.net/8bdfd7cs-960.jpg' # серый квадрат + + # post_media.each do |media| + # if media['type'] == 'photo' + # photo_from_media = media['photo']['sizes'] + + # photo_from_media.each do |photo| + # if photo['type'] == 'm' + # image_url = photo['url'] + # break + # end + # end + # break + # end + # # ? + # if media['type'] == 'album' + # photo_from_media = media['album']['thumb']['sizes'] + # photo_from_media.each do |photo| + # if photo['type'] == 'm' + # image_url = photo['url'] + # break + # end + # end + # break + # end + # # если тип медиа не картинка и не альбом и еще не подобрано фото + # if media['type'] == 'link' && !photo_found + # next unless media['link'].key?('photo') + + # photo_from_media = media['link']['photo']['sizes'] + + # photo_from_media.each do |photo| + # next unless photo['type'] == 'm' + + # image_url = photo['url'] + # photo_found = true + # break + # end + # end + + # if media['type'] == 'video' && !photo_found + # image_url = media['video']['image'][0]['url'] + # photo_found = true + # end + + # if media['type'] == 'poll' && !photo_found + # image_url = 'https://www.tgu-dpo.ru/wp-content/uploads/2023/06/%D0%BE%D0%BF%D1%80%D0%BE%D1%81-%D0%B2-Google-%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D1%85.jpg' # картинка опроса + # photo_found = true + # end + # end + + # image_url + # end + + def self.get_likers(post_id, like_count, user) + likers = [] + bundles = like_count / 100 + 1 + (0...bundles).each do |i| + resp = try_request(:get, + '/method/likes.getList', + { access_token: user.access_token, + v: '5.199', + type: 'post', + owner_id: user.user_id, + item_id: post_id, + count: 100, + offset: 100 * i, + friends_only: 1 }, + client:) + current_likers = resp.body['response']['items'] + likers << current_likers + end + likers + end + + def self.get_commentators(post_id, comments_count, user) + commentators = [] + bundles = comments_count / 100 + 1 + (0...bundles).each do |i| + resp = try_request(:get, + '/method/wall.getComments', + { access_token: user.access_token, + v: '5.199', + owner_id: user.user_id, + post_id:, + count: 100, + offset: 100 * i }, + client:) + puts 'RESPONSE' + puts resp.body + comments = resp.body['response']['items'] + current_commentators = comments.map { |comment| comment['from_id'] } + commentators << current_commentators + end + commentators + end +end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 8465b413..cb92e54a 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -1,48 +1,50 @@ # frozen_string_literal: true -module Admin - class UsersController < Admin::ApplicationController - # Overwrite any of the RESTful controller actions to implement custom behavior - # For example, you may want to send an email after a foo is updated. - # - # def update - # super - # send_foo_updated_email(requested_resource) - # end +# # frozen_string_literal: true - # Override this method to specify custom lookup behavior. - # This will be used to set the resource for the `show`, `edit`, and `update` - # actions. - # - # def find_resource(param) - # Foo.find_by!(slug: param) - # end +# module Admin +# class UsersController < Admin::ApplicationController +# # Overwrite any of the RESTful controller actions to implement custom behavior +# # For example, you may want to send an email after a foo is updated. +# # +# # def update +# # super +# # send_foo_updated_email(requested_resource) +# # end - # The result of this lookup will be available as `requested_resource` +# # Override this method to specify custom lookup behavior. +# # This will be used to set the resource for the `show`, `edit`, and `update` +# # actions. +# # +# # def find_resource(param) +# # Foo.find_by!(slug: param) +# # end - # Override this if you have certain roles that require a subset - # this will be used to set the records shown on the `index` action. - # - # def scoped_resource - # if current_user.super_admin? - # resource_class - # else - # resource_class.with_less_stuff - # end - # end +# # The result of this lookup will be available as `requested_resource` - # Override `resource_params` if you want to transform the submitted - # data before it's persisted. For example, the following would turn all - # empty values into nil values. It uses other APIs such as `resource_class` - # and `dashboard`: - # - # def resource_params - # params.require(resource_class.model_name.param_key). - # permit(dashboard.permitted_attributes(action_name)). - # transform_values { |value| value == "" ? nil : value } - # end +# # Override this if you have certain roles that require a subset +# # this will be used to set the records shown on the `index` action. +# # +# # def scoped_resource +# # if current_user.super_admin? +# # resource_class +# # else +# # resource_class.with_less_stuff +# # end +# # end - # See https://administrate-demo.herokuapp.com/customizing_controller_actions - # for more information - end -end +# # Override `resource_params` if you want to transform the submitted +# # data before it's persisted. For example, the following would turn all +# # empty values into nil values. It uses other APIs such as `resource_class` +# # and `dashboard`: +# # +# # def resource_params +# # params.require(resource_class.model_name.param_key). +# # permit(dashboard.permitted_attributes(action_name)). +# # transform_values { |value| value == "" ? nil : value } +# # end + +# # See https://administrate-demo.herokuapp.com/customizing_controller_actions +# # for more information +# end +# end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 5600cec8..91d9448a 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -2,34 +2,12 @@ class HomeController < ApplicationController def index - # @code_verifier = SecureRandom.urlsafe_base64(64) - # @code_challenge = Digest::SHA256.base64digest(@code_verifier) - # @state = 'df29figadjsd82' - # @scopes = 'vkid.personal_info friends wall'\ - # @data_attributes = { - # code_challenge: @code_challenge, - # state: @state, - # scopes: @scopes - # }.to_json - pkce_challenge = PkceChallenge.challenge - session[:code_verifier] = pkce_challenge.code_verifier - @data_attributes = { - challenge: pkce_challenge.code_challenge, state: session.id.public_id - }.to_json - #if user_sign_in? - #if user.update_metrics_needed? - #user.update_metrics - #end - #end - end - - def auth - @response = HTTParty.post('https://id.vk.com/oauth2/auth', - body: { - code:, - code_verifier:, - device_id:, - grant_type: 'authorization_code' - }) + unless current_user + pkce_challenge = PkceChallenge.challenge + session[:code_verifier] = pkce_challenge.code_verifier + @data_attributes = { + challenge: pkce_challenge.code_challenge, state: session.id.public_id + }.to_json + end end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index d8d4590e..1cc2a3ae 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -3,41 +3,40 @@ require 'digest' require 'faraday' require 'json' - +require 'date' +require_relative '../api/vk' class SessionsController < ApplicationController def new render :new end - def challenge - pkce_challenge = PkceChallenge.challenge - session[:code_verifier] = pkce_challenge.code_verifier - render json: { challenge: pkce_challenge.code_challenge, state: session.id.public_id } - end - - def create - exchange_code(params['code'], session[:code_verifier], params['device_id'], params['state']) + def create # rubocop:disable Metrics/AbcSize + unless user_signed_in? + response = Vk.exchange_code(params['code'], session[:code_verifier], params['device_id'], params['state']) + # поиск пользователя или создание его + user = User.user_create(response.merge({ deviceid: params['device_id'], state: params['state'] })) + user.link_friends Vk.get_friends(user).map { |h| Friend.from_vk h } + Vk.get_data(user).map { |h| Post.from_vk h, user } + MetricsCalculator.call user + sign_in user + end + redirect_to root_path end - def exchange_code(code, code_verifier, device_id, state) - conn = Faraday.new(url: 'https://id.vk.com') do |conn_builder| - conn_builder.headers['Content-Type'] = 'application/json' - conn_builder.headers['Accept'] = 'application/json' - conn_builder.request :json - conn_builder.response :json - conn_builder.response :logger + def view # rubocop:disable Metrics/AbcSize + if user_signed_in? + if User.needs_refresh_token?(current_user) + response_from_refresh = Vk.refresh_usertokens(current_user.refresh_token, current_user.user_device_id, + current_user.user_state) + current_user.update(access_token: response_from_refresh['access_token'], + refresh_token: response_from_refresh['refresh_token'], access_token_expiration_time: Time.current + params['expires_in']) + end + profile_data = Vk.get_profile_info(current_user) + @user_name = "#{profile_data['first_name']} #{profile_data['last_name']}" + @db = Vk.get_data(current_user) + else + redirect_to root_path end - - response = conn.post('/oauth2/auth', { - grant_type: 'authorization_code', - code:, - code_verifier:, - device_id:, - redirect_uri: 'https://wheremylikes.com/auth/vkontakte/callback/', - state:, - client_id: '51989509' - }) - puts response.body['access_token'] end # rubocop:disable Metrics/AbcSize diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 1500b47f..864b28d2 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,7 +4,7 @@ class UsersController < ApplicationController def index; end def show - user = User.find(params[:id]) - @profile = user.get_profile_info + # user = User.find(params[:id]) + # @profile = user.get_profile_info end end diff --git a/app/models/friend.rb b/app/models/friend.rb index 237f7306..f6a3ed5a 100644 --- a/app/models/friend.rb +++ b/app/models/friend.rb @@ -4,7 +4,22 @@ class Friend < ApplicationRecord has_many :relationships has_many :users, through: :relationships - validates :first_name, presence: true - validates :last_name, presence: true - validates :vk_uid, presence: true, uniqueness: true + # validates :first_name, presence: true + # validates :last_name, presence: true + # validates :vk_uid, presence: true, uniqueness: true + + def self.from_vk(payload) + existing_friend=find_or_create_by(vk_uid: payload["id"]) do |friend| + # friend.vk_uid = payload[:id], + friend.first_name =payload['first_name'], + friend.last_name = payload['last_name'], + friend.image_url = payload['photo_50'] + end + existing_friend.update( + first_name: payload['first_name'], + last_name: payload['last_name'], + image_url: payload['photo_50'] + ) + existing_friend + end end diff --git a/app/models/post.rb b/app/models/post.rb index 4c1cf671..8b75a371 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -4,4 +4,27 @@ class Post < ApplicationRecord belongs_to :user validates :vk_uid, presence: true, uniqueness: true + + def self.from_vk(payload, owner) + puts 'PAYLOAD!!!' + puts payload + existing_post= find_or_create_by(vk_uid: payload[:post_id]) do |post| + # post.vk_uid = payload[:post_id], + post.date = payload[:date], + post.image_url = payload[:image_url], + # post.count_likes = payload[:count_likes], + # post.count_comments = payload[:count_comments], + post.likes = payload[:likers], + post.comments = payload[:commentators] + post.user = owner + end + existing_post.update( + date: payload[:date], + image_url: payload[:image_url], + # count_likes: payload[:count_likes], + # count_comments: payload[:count_comments], + likes: payload[:likers], + comments: payload[:commentators]) + existing_post + end end diff --git a/app/models/user.rb b/app/models/user.rb index a2f19aca..85a71bbb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,8 +3,8 @@ class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable - devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :validatable + validates :user_id, uniqueness: true + devise :database_authenticatable, :rememberable has_one :metric, dependent: :destroy @@ -56,4 +56,38 @@ def update_metrics_needed? metrics_have_nil || post_metrics_have_nil end + + def password_required? + new_record? ? false : super + false + end + + def email_required? + false + end + + def self.needs_refresh_token?(user) + Time.now > user.access_token_expiration_time + end + + def self.user_create(response) # rubocop:disable Metrics/AbcSize + user = User.find_or_create_by(user_id: response['user_id']) do |u| + u.access_token = response['access_token'] + u.refresh_token = response['refresh_token'] + u.user_device_id = response['device_id'] + u.access_token_expiration_time = Time.current + response['expires_in'] + u.user_state = response['state'] + end + if user.persisted? + user.update(access_token: response['access_token'], refresh_token: response['refresh_token'], + access_token_expiration_time: Time.current + response['expires_in'], + user_device_id: response['device_id'], + user_state: response['state']) + end + user + end + + def link_friends(friends_array) + self.friends = friends_array + end end diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index 9f352df4..5286a96a 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -2,4 +2,5 @@ <%= render partial: "partial_content/user-signed"%> <%else%> <%= render partial: "partial_content/no-user"%> -<%end%> \ No newline at end of file +<%end%> + diff --git a/app/views/partial_content/_navbar.html.erb b/app/views/partial_content/_navbar.html.erb index 1948773c..d668820e 100644 --- a/app/views/partial_content/_navbar.html.erb +++ b/app/views/partial_content/_navbar.html.erb @@ -26,6 +26,11 @@ <% end %> + <%if current_user%> +