|
- require 'open-uri'
- require 'nokogiri'
-
-
- class PostsController < ApplicationController
- # GET /posts
- def index
- limit = (params[:limit] || 20).to_i
- cursor = params[:cursor].presence
-
- q = filtered_posts.order(created_at: :desc)
- q = q.where('posts.created_at < ?', Time.iso8601(cursor)) if cursor
-
- posts = q.limit(limit + 1)
-
- next_cursor = nil
- if posts.size > limit
- next_cursor = posts.last.created_at.iso8601(6)
- posts = posts.first(limit)
- end
-
- render json: { posts: posts.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } }),
- next_cursor: }
- end
-
- def random
- post = filtered_posts.order('RAND()').first
- return head :not_found unless post
-
- viewed = current_user&.viewed?(post) || false
-
- render json: (post
- .as_json(include: { tags: { only: [:id, :name, :category] } })
- .merge(viewed: viewed))
- end
-
- # GET /posts/1
- def show
- post = Post.includes(:tags).find(params[:id])
- return head :not_found unless post
-
- viewed = current_user&.viewed?(post) || false
-
- render json: (post
- .as_json(include: { tags: { only: [:id, :name, :category] } })
- .merge(viewed: viewed))
- end
-
- # POST /posts
- def create
- return head :unauthorized unless current_user
- return head :forbidden unless current_user.member?
-
- # TODO: URL が正規のものがチェック,不正ならエラー
- # TODO: title、URL は必須にする.
- # TODO: サイトに応じて thumbnail_base 設定
- title = params[:title]
- url = params[:url]
- thumbnail = params[:thumbnail]
- tag_names = params[:tags].to_s.split(' ')
-
- post = Post.new(title:, url:, thumbnail_base: '', uploaded_user: current_user)
- post.thumbnail.attach(thumbnail)
- if post.save
- post.resized_thumbnail!
- post.tags = normalise_tags(tags_names)
- render json: post.as_json(include: { tags: { only: [:id, :name, :category] } }),
- status: :created
- else
- render json: { errors: post.errors.full_messages }, status: :unprocessable_entity
- end
- end
-
- def viewed
- return head :unauthorized unless current_user
-
- current_user.viewed_posts << Post.find(params[:id])
- head :no_content
- end
-
- def unviewed
- return head :unauthorized unless current_user
-
- current_user.viewed_posts.delete(Post.find(params[:id]))
- head :no_content
- end
-
- # PATCH/PUT /posts/1
- def update
- return head :unauthorized unless current_user
- return head :forbidden unless current_user.member?
-
- title = params[:title]
- tag_names = params[:tags].to_s.split(' ')
-
- post = Post.find(params[:id].to_i)
- tags = post.tags.where(category: 'nico').to_a + normalise_tags(tag_names)
- if post.update(title:, tags:)
- render json: post.as_json(include: { tags: { only: [:id, :name, :category] } }),
- status: :created
- else
- render json: post.errors, status: :unprocessable_entity
- end
- end
-
- # DELETE /posts/1
- def destroy
- end
-
- private
-
- CATEGORY_PREFIXES = {
- 'gen:' => 'general',
- 'djk:' => 'deerjikist',
- 'meme:' => 'meme',
- 'chr:' => 'character',
- 'mtr:' => 'material',
- 'meta:' => 'meta' }.freeze
-
- def filtered_posts
- tag_names = params[:tags]&.split(' ')
- match_type = params[:match]
- tag_names.present? ? filter_posts_by_tags(tag_names, match_type) : Post.all
- end
-
- def filter_posts_by_tags tag_names, match_type
- posts = Post.joins(:tags)
- if match_type == 'any'
- posts = posts.where(tags: { name: tag_names }).distinct
- else
- tag_names.each do |tag|
- posts = posts.where(id: Post.joins(:tags).where(tags: { name: tag }))
- end
- end
- posts.distinct
- end
-
- def normalise_tags tag_names
- tags = tag_names.map do |name|
- pf, cat = CATEGORY_PREFIXES.find { |p, _| name.start_with?(p) } || ['', nil]
- name.delete_prefix!(pf)
- Tag.find_or_initialize_by(name:).tap do |tag|
- if cat && tag.category != cat
- tag.category = cat
- tag.save!
- end
- end
- end
- tags << Tag.tagme if tags.size < 20 && tags.none?(Tag.tagme)
- tags.uniq
- end
- end
|