2016-11-15 16:56:29 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# frozen_string_literal: true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-09-09 20:04:34 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								require  'singleton' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-03-25 02:13:30 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								class  FeedManager 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-09 20:04:34 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  include  Singleton 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:58:34 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  MAX_ITEMS  =  400 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-25 02:13:30 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-09-09 20:04:34 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  def  key ( type ,  id ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-25 02:13:30 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    " feed: #{ type } : #{ id } " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  def  filter? ( timeline_type ,  status ,  receiver_id ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-02 15:28:47 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  timeline_type  ==  :home 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      filter_from_home? ( status ,  receiver_id ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-07 23:20:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    elsif  timeline_type  ==  :mentions 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      filter_from_mentions? ( status ,  receiver_id ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-07 23:20:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      false 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-02 15:28:47 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    end 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-25 02:13:30 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-10 18:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  def  push ( timeline_type ,  account ,  status ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-02 18:49:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    timeline_key  =  key ( timeline_type ,  account . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  status . reblog? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      # If the original status is within 40 statuses from top, do not re-insert it into the feed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      rank  =  redis . zrevrank ( timeline_key ,  status . reblog_of_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      return  if  ! rank . nil?  &&  rank  <  40 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      redis . zadd ( timeline_key ,  status . id ,  status . reblog_of_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      redis . zadd ( timeline_key ,  status . id ,  status . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      trim ( timeline_type ,  account . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-05 19:45:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    PushUpdateWorker . perform_async ( account . id ,  status . id ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-12 18:22:43 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-09-10 18:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  def  trim ( type ,  account_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  unless  redis . zcard ( key ( type ,  account_id ) )  >  FeedManager :: MAX_ITEMS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    last  =  redis . zrevrange ( key ( type ,  account_id ) ,  FeedManager :: MAX_ITEMS  -  1 ,  FeedManager :: MAX_ITEMS  -  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    redis . zremrangebyscore ( key ( type ,  account_id ) ,  '-inf' ,  " ( #{ last . last } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-22 23:03:57 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  def  merge_into_timeline ( from_account ,  into_account ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    timeline_key  =  key ( :home ,  into_account . id ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:58:34 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    query         =  from_account . statuses . limit ( FeedManager :: MAX_ITEMS  /  4 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:43:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:58:34 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  redis . zcard ( timeline_key )  > =  FeedManager :: MAX_ITEMS  /  4 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:43:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      oldest_home_score  =  redis . zrange ( timeline_key ,  0 ,  0 ,  with_scores :  true ) & . first & . last & . to_i  ||  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      query  =  query . where ( 'id > ?' ,  oldest_home_score ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    end 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-22 23:03:57 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    redis . pipelined  do 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:43:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      query . each  do  | status | 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        next  if  status . direct_visibility?  ||  filter? ( :home ,  status ,  into_account ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        redis . zadd ( timeline_key ,  status . id ,  status . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      end 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-22 23:03:57 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    trim ( :home ,  into_account . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-23 21:29:34 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  def  unmerge_from_timeline ( from_account ,  into_account ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    timeline_key  =  key ( :home ,  into_account . id ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:43:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    oldest_home_score  =  redis . zrange ( timeline_key ,  0 ,  0 ,  with_scores :  true ) & . first & . last & . to_i  ||  0 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-23 21:29:34 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:43:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    from_account . statuses . select ( 'id' ) . where ( 'id > ?' ,  oldest_home_score ) . find_in_batches  do  | statuses | 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      redis . pipelined  do 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        statuses . each  do  | status | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          redis . zrem ( timeline_key ,  status . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          redis . zremrangebyscore ( timeline_key ,  status . id ,  status . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      end 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-23 21:29:34 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-07 16:00:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  private 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  def  redis 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-15 16:56:29 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    Redis . current 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-07 16:00:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  def  filter_from_home? ( status ,  receiver_id ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  true  if  status . reply?  &&  status . in_reply_to_id . nil? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    check_for_mutes  =  [ status . account_id ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    check_for_mutes . concat ( [ status . reblog . account_id ] )  if  status . reblog? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  true  if  Mute . where ( account_id :  receiver_id ,  target_account_id :  check_for_mutes ) . any? 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-02 18:49:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    check_for_blocks  =  status . mentions . map ( & :account_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    check_for_blocks . concat ( [ status . reblog . account_id ] )  if  status . reblog? 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-07 23:20:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  true  if  Block . where ( account_id :  receiver_id ,  target_account_id :  check_for_blocks ) . any? 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  status . reply?  &&  ! status . in_reply_to_account_id . nil?                                                               # Filter out if it's a reply 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      should_filter    =  ! Follow . where ( account_id :  receiver_id ,  target_account_id :  status . in_reply_to_account_id ) . exists?  # and I'm not following the person it's a reply to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      should_filter  && =  ! ( receiver_id  ==  status . in_reply_to_account_id )                                                   # and it's not a reply to me 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      should_filter  && =  ! ( status . account_id  ==  status . in_reply_to_account_id )                                             # and it's not a self-reply 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      return  should_filter 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    elsif  status . reblog?                                                                                                  # Filter out a reblog 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      return  Block . where ( account_id :  status . reblog . account_id ,  target_account_id :  receiver_id ) . exists?                    # or if the author of the reblogged status is blocking me 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-07 23:20:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    false 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-07 16:00:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  def  filter_from_mentions? ( status ,  receiver_id ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    check_for_blocks  =  [ status . account_id ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 09:04:07 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    check_for_blocks . concat ( status . mentions . pluck ( :account_id ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 13:01:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    check_for_blocks . concat ( [ status . in_reply_to_account ] )  if  status . reply?  &&  ! status . in_reply_to_account_id . nil? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 19:21:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    should_filter    =  receiver_id  ==  status . account_id                                                                                    # Filter if I'm mentioning myself 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    should_filter  || =  Block . where ( account_id :  receiver_id ,  target_account_id :  check_for_blocks ) . any?                                      # or it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    should_filter  || =  ( status . account . silenced?  &&  ! Follow . where ( account_id :  receiver_id ,  target_account_id :  status . account_id ) . exists? )  # of if the account is silenced and I'm not following them 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-13 21:11:45 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-11-07 23:20:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    should_filter 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-07 16:00:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  end 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-25 02:13:30 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								end