phateio/kiris

View on GitHub
app/controllers/upload/niconico_controller.rb

Summary

Maintainability
B
6 hrs
Test Coverage
class Upload::NiconicoController < ApplicationController
  before_filter :filter_admin_info!
  before_action :load_internal_style_sheet!

  def index
    set_site_title(I18n.t('upload.niconico.title'))
    track_arel_recent_or_idle_niconico_tracks = Track.arel_recent_tracks
                                                .or(Track.arel_idle_tracks)
                                                .and(Track.arel_niconico_tracks)
    @tracks = Track.where(track_arel_recent_or_idle_niconico_tracks).order(id: :desc).page(page)
  end

  def new
    set_site_title(I18n.t('upload.niconico.title'))
    @track = Track.new
  end

  def fetch
    set_site_title(I18n.t('upload.niconico.title'))
    @track = Track.new(track_params)
    if @track.niconico.empty?
      flash.now[:error] = I18n.t('upload.niconico.blank_niconico_id')
      render 'new' and return
    end
    raw_video_id = @track.niconico.to_s.strip
    if raw_video_id =~ /\A[A-Za-z0-9]+\z/i
      niconico_location = get_niconico_location(raw_video_id)
      if niconico_location
        matches = /\/watch\/([A-Za-z0-9]+)/i.match(niconico_location)
        video_id = matches.to_a.last
      else
        video_id = raw_video_id
      end
    else
      matches = /\/watch\/([A-Za-z0-9]+)/i.match(raw_video_id)
      video_id = matches.to_a.last
    end
    if video_id.nil?
      flash.now[:error] = I18n.t('upload.niconico.invalid_niconico_id')
      render 'new' and return
    elsif Track.where(niconico: video_id).present? || Track.where(niconico: video_id).present?
      flash.now[:error] = I18n.t('upload.niconico.duplicate_niconico_id')
      render 'new' and return
    end
    set_site_title("#{I18n.t('upload.niconico.title')}#niconico-#{video_id}")
    @track.niconico = video_id
    niconico_video_info = get_niconico_thumb_info(video_id)
    if niconico_video_info == false
      flash.now[:error] = I18n.t('upload.niconico.niconico_id_not_found')
      render 'new' and return
    end
    unless ['mp4', 'swf', 'flv'].include?(niconico_video_info[:movie_type])
      flash.now[:error] = I18n.t('upload.niconico.movie_type_not_supported', movie_type: niconico_video_info[:movie_type])
      render 'new' and return
    end
    unless niconico_video_info[:view_counter] > 10000
      count = ActionController::Base.helpers.number_with_delimiter(10000)
      flash.now[:error] = I18n.t('upload.niconico.view_counter_not_enough', count: count)
      render 'new' and return
    end
    union_tags = niconico_video_info[:tags] & niconico_acceptable_tags
    unless union_tags.present?
      flash.now[:error] = I18n.t('upload.niconico.acceptable_tags_not_found')
      render 'new' and return
    end
    @track.attributes = {
      title: niconico_video_info[:title],
      tags: 'niconico,' + union_tags.join(',')
    }
  end

  def create
    set_site_title(I18n.t('upload.niconico.title'))
    @track = Track.new(track_params)
    @track.attributes = {
      album: 'ニコニコ',
      userip: @client[:ip],
      status: 'QUEUED',
      identity: @identity
    }
    track_tags = @track.tags.split(',')
    union_tags = track_tags & niconico_acceptable_tags
    unless track_tags.include?('niconico') && union_tags.present?
      flash.now[:error] = I18n.t('upload.niconico.reserved_tags_not_found')
      render 'fetch' and return
    end
    render 'fetch' and return if not @track.save
    x_redirect_to upload_niconico_index_path
  end

  def edit
    set_site_title(I18n.t('upload.niconico.title'))
    @track = Track.find(track_id)
  end

  def update
    set_site_title(I18n.t('upload.niconico.title'))
    @track = Track.find(track_id)
    redirect_to_index_if_not_permitted(@track); return if performed?
    @track.attributes = track_params
    if @track.status == 'PUBLIC'
      @track.attributes = {
        userip: @client[:ip],
        status: 'READY',
        identity: @identity
      }
    end
    track_tags = @track.tags.split(',')
    union_tags = track_tags & niconico_acceptable_tags
    unless track_tags.include?('niconico') && union_tags.present?
      flash.now[:error] = I18n.t('upload.niconico.reserved_tags_not_found')
      render 'edit' and return
    end
    render 'edit' and return if not @track.save
    x_redirect_to upload_niconico_index_path
  end

  def destroy
    @track = Track.find(track_id)
    redirect_to_index_if_not_permitted(@track); return if performed?
    @track.destroy
    x_redirect_to upload_niconico_index_path
  end

  private
  def track_id
    params[:track_id]
  end

  def niconico_acceptable_tags
    ['VOCALOID', 'UTAU', '東方Project', '歌ってみた', '音楽']
  end

  def niconico_touhou_tags
    ['東方アレンジ', '東方ヴォーカル']
  end

  def track_params
    params.require(:track).permit(track_attribute_names)
  end

  def track_attribute_names
    [
      :title,
      :tags,
      :artist,
      :niconico,
      :uploader
    ]
  end

  def redirect_to_index_if_not_permitted(track)
    if not track.editable?(@client[:ip], @identity)
      flash[:error] = 'Access Denied.'
      x_redirect_to upload_niconico_index_path and return
    end
  end

  def get_niconico_location(video_id)
    res = http_head_response("http://www.nicovideo.jp/watch/#{video_id}") rescue nil
    return nil if res.nil?
    res['Location']
  end

  def get_niconico_thumb_info(video_id)
    res_body = http_get_response_body("http://ext.nicovideo.jp/api/getthumbinfo/#{video_id}") rescue nil
    return false if res_body.nil?
    thumb_info_doc = Nokogiri::XML(res_body)
    thumb_element = thumb_info_doc.xpath('/nicovideo_thumb_response/thumb')
    document_element = thumb_info_doc.xpath('/nicovideo_thumb_response/thumb')
    document_hash = Hash.from_xml(thumb_element.to_s)
    return false if document_hash.nil?
    thumb_hash = document_hash['thumb']
    thumb_hash.slice!('video_id', 'title', 'length', 'movie_type', 'view_counter', 'tags')
    thumb_hash.symbolize_keys!
    thumb_hash[:tags] = Array(thumb_hash[:tags].to_h['tag'])
    thumb_hash[:tags] = thumb_hash[:tags].map { |tag| niconico_touhou_tags.include?(tag) ? '東方Project' : tag }.uniq
    thumb_hash[:view_counter] = thumb_hash[:view_counter].to_i
    thumb_hash
  end
end