Adding sync of follow relationships to Neo4J, accounts/suggestions API
This commit is contained in:
		
							parent
							
								
									91144d46ec
								
							
						
					
					
						commit
						e21a3fe0cd
					
				
					 11 changed files with 76 additions and 5 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -21,3 +21,4 @@ public/assets
 | 
			
		|||
.env
 | 
			
		||||
.env.*
 | 
			
		||||
node_modules/
 | 
			
		||||
neo4j/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								Gemfile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Gemfile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -39,6 +39,7 @@ gem 'will_paginate'
 | 
			
		|||
gem 'rack-attack'
 | 
			
		||||
gem 'sidekiq'
 | 
			
		||||
gem 'ledermann-rails-settings'
 | 
			
		||||
gem 'neography'
 | 
			
		||||
 | 
			
		||||
gem 'react-rails'
 | 
			
		||||
gem 'browserify-rails'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								Gemfile.lock
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								Gemfile.lock
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -97,6 +97,7 @@ GEM
 | 
			
		|||
      dotenv (= 2.1.1)
 | 
			
		||||
      railties (>= 4.0, < 5.1)
 | 
			
		||||
    erubis (2.7.0)
 | 
			
		||||
    excon (0.53.0)
 | 
			
		||||
    execjs (2.7.0)
 | 
			
		||||
    fabrication (2.15.2)
 | 
			
		||||
    fast_blank (1.0.0)
 | 
			
		||||
| 
						 | 
				
			
			@ -165,13 +166,21 @@ GEM
 | 
			
		|||
    mime-types-data (3.2016.0521)
 | 
			
		||||
    mimemagic (0.3.0)
 | 
			
		||||
    mini_portile2 (2.1.0)
 | 
			
		||||
    minitest (5.9.0)
 | 
			
		||||
    minitest (5.9.1)
 | 
			
		||||
    multi_json (1.12.1)
 | 
			
		||||
    neography (1.8.0)
 | 
			
		||||
      excon (>= 0.33.0)
 | 
			
		||||
      json (>= 1.7.7)
 | 
			
		||||
      multi_json (>= 1.3.2)
 | 
			
		||||
      os (>= 0.9.6)
 | 
			
		||||
      rake (>= 0.8.7)
 | 
			
		||||
      rubyzip (>= 1.0.0)
 | 
			
		||||
    nio4r (1.2.1)
 | 
			
		||||
    nokogiri (1.6.8.1)
 | 
			
		||||
      mini_portile2 (~> 2.1.0)
 | 
			
		||||
    oj (2.17.3)
 | 
			
		||||
    orm_adapter (0.5.0)
 | 
			
		||||
    os (0.9.6)
 | 
			
		||||
    ostatus2 (1.0.1)
 | 
			
		||||
      addressable (~> 2.4)
 | 
			
		||||
      http (~> 2.0)
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +245,7 @@ GEM
 | 
			
		|||
      rake (>= 0.8.7)
 | 
			
		||||
      thor (>= 0.18.1, < 2.0)
 | 
			
		||||
    rainbow (2.1.0)
 | 
			
		||||
    rake (11.2.2)
 | 
			
		||||
    rake (11.3.0)
 | 
			
		||||
    rdoc (4.2.2)
 | 
			
		||||
      json (~> 1.4)
 | 
			
		||||
    react-rails (1.8.2)
 | 
			
		||||
| 
						 | 
				
			
			@ -281,6 +290,7 @@ GEM
 | 
			
		|||
      ruby-progressbar (~> 1.7)
 | 
			
		||||
      unicode-display_width (~> 1.0, >= 1.0.1)
 | 
			
		||||
    ruby-progressbar (1.8.1)
 | 
			
		||||
    rubyzip (1.2.0)
 | 
			
		||||
    safe_yaml (1.0.4)
 | 
			
		||||
    sass (3.4.22)
 | 
			
		||||
    sass-rails (5.0.6)
 | 
			
		||||
| 
						 | 
				
			
			@ -370,6 +380,7 @@ DEPENDENCIES
 | 
			
		|||
  letter_opener
 | 
			
		||||
  link_header
 | 
			
		||||
  lograge
 | 
			
		||||
  neography
 | 
			
		||||
  nokogiri
 | 
			
		||||
  oj
 | 
			
		||||
  ostatus2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								app/assets/javascripts/components/actions/suggestions.jsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/assets/javascripts/components/actions/suggestions.jsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
import api from '../api';
 | 
			
		||||
 | 
			
		||||
export const SUGGESTIONS_FETCH_REQUEST = 'SUGGESTIONS_FETCH_REQUEST';
 | 
			
		||||
export const SUGGESTIONS_FETCH_SUCCESS = 'SUGGESTIONS_FETCH_SUCCESS';
 | 
			
		||||
export const SUGGESTIONS_FETCH_FAIL    = 'SUGGESTIONS_FETCH_FAIL';
 | 
			
		||||
 | 
			
		||||
export function fetchSuggestions() {
 | 
			
		||||
  return (dispatch, getState) => {
 | 
			
		||||
    api(getState).get('/api/v1/accounts/suggestions').then(response => {
 | 
			
		||||
      console.log(response.data);
 | 
			
		||||
    }).catch(error => {
 | 
			
		||||
      console.error(error);
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
class Api::V1::AccountsController < ApiController
 | 
			
		||||
  before_action :doorkeeper_authorize!
 | 
			
		||||
  before_action :set_account, except: :verify_credentials
 | 
			
		||||
  before_action :set_account, except: [:verify_credentials, :suggestions]
 | 
			
		||||
  respond_to    :json
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +19,10 @@ class Api::V1::AccountsController < ApiController
 | 
			
		|||
    @followers = @account.followers
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def suggestions
 | 
			
		||||
    @accounts = FollowSuggestion.get(current_user.account_id)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def statuses
 | 
			
		||||
    @statuses = @account.statuses.with_includes.with_counters.paginate_by_max_id(20, params[:max_id], params[:since_id]).to_a
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,4 +22,28 @@ class Follow < ApplicationRecord
 | 
			
		|||
  def title
 | 
			
		||||
    destroyed? ? "#{account.acct} is no longer following #{target_account.acct}" : "#{account.acct} started following #{target_account.acct}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  after_create  :add_to_graph
 | 
			
		||||
  after_destroy :remove_from_graph
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def add_to_graph
 | 
			
		||||
    neo = Neography::Rest.new
 | 
			
		||||
 | 
			
		||||
    a = neo.create_unique_node('account_index', 'Account', account_id.to_s, account_id: account_id)
 | 
			
		||||
    b = neo.create_unique_node('account_index', 'Account', target_account_id.to_s, account_id: target_account_id)
 | 
			
		||||
 | 
			
		||||
    neo.create_unique_relationship('follow_index', 'Follow', id.to_s, 'follows', a, b)
 | 
			
		||||
  rescue Neography::NeographyError => e
 | 
			
		||||
    Rails.logger.error e
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def remove_from_graph
 | 
			
		||||
    neo = Neography::Rest.new
 | 
			
		||||
    rel = neo.get_relationship_index('follow_index', 'Follow', id.to_s)
 | 
			
		||||
    neo.delete_relationship(rel)
 | 
			
		||||
  rescue Neography::NeographyError => e
 | 
			
		||||
    Rails.logger.error e
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								app/models/follow_suggestion.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/models/follow_suggestion.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
class FollowSuggestion
 | 
			
		||||
  def self.get(for_account_id)
 | 
			
		||||
    neo = Neography::Rest.new
 | 
			
		||||
    account_ids = neo.execute_query('START a=node:account_index(Account={id}) MATCH (a)-[:follows]->(b)-[:follows]->(c) WHERE a <> c AND NOT (a)-[:follows]->(c) RETURN DISTINCT c.account_id', id: for_account_id)
 | 
			
		||||
    Account.where(id: account_ids['data'].first) unless account_ids.empty?
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										2
									
								
								app/views/api/v1/accounts/suggestions.rabl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/views/api/v1/accounts/suggestions.rabl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
collection @accounts
 | 
			
		||||
extends('api/v1/accounts/show')
 | 
			
		||||
| 
						 | 
				
			
			@ -22,8 +22,8 @@ module Mastodon
 | 
			
		|||
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
 | 
			
		||||
    # config.i18n.default_locale = :de
 | 
			
		||||
 | 
			
		||||
    config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
 | 
			
		||||
    config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
 | 
			
		||||
    # config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
 | 
			
		||||
    # config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
 | 
			
		||||
 | 
			
		||||
    config.active_job.queue_adapter = :sidekiq
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								config/initializers/neography.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								config/initializers/neography.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
Neography.configure do |config|
 | 
			
		||||
  config.protocol             = "http"
 | 
			
		||||
  config.server               = ENV['NEO4J_HOST'] || 'localhost'
 | 
			
		||||
  config.port                 = ENV['NEO4J_PORT'] || 7474
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +73,7 @@ Rails.application.routes.draw do
 | 
			
		|||
        collection do
 | 
			
		||||
          get :relationships
 | 
			
		||||
          get :verify_credentials
 | 
			
		||||
          get :suggestions
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        member do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Reference in a new issue