ぼざクリ タグ広場 https://hub.nizika.monster
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

151 lines
4.1 KiB

  1. require 'open-uri'
  2. require 'nokogiri'
  3. class PostsController < ApplicationController
  4. # GET /posts
  5. def index
  6. limit = (params[:limit] || 20).to_i
  7. cursor = params[:cursor]
  8. q = filtered_posts.order(created_at: :desc)
  9. next_cursor = nil
  10. if cursor.present?
  11. q = q.where('posts.created_at < ?', Time.iso8601(cursor))
  12. end
  13. posts = q.limit(limit + 1)
  14. next_cursor = nil
  15. if posts.size > limit
  16. next_cursor = posts.last.created_at.iso8601(6)
  17. posts = posts.first(limit)
  18. end
  19. render json: { posts: posts.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } }),
  20. next_cursor: }
  21. end
  22. def random
  23. post = filtered_posts.order('RAND()').first
  24. return head :not_found unless post
  25. viewed = current_user&.viewed?(post) || false
  26. render json: (post
  27. .as_json(include: { tags: { only: [:id, :name, :category] } })
  28. .merge(viewed: viewed))
  29. end
  30. # GET /posts/1
  31. def show
  32. post = Post.includes(:tags).find(params[:id])
  33. return head :not_found unless post
  34. viewed = current_user&.viewed?(post) || false
  35. render json: (post
  36. .as_json(include: { tags: { only: [:id, :name, :category] } })
  37. .merge(viewed: viewed))
  38. end
  39. # POST /posts
  40. def create
  41. return head :unauthorized unless current_user
  42. return head :forbidden unless current_user.member?
  43. # TODO: URL が正規のものがチェック,不正ならエラー
  44. # TODO: title、URL は必須にする.
  45. # TODO: サイトに応じて thumbnail_base 設定
  46. title = params[:title]
  47. url = params[:url]
  48. thumbnail = params[:thumbnail]
  49. tag_names = params[:tags].to_s.split(' ')
  50. if tag_names.size < 20 && tag_names.none?('タグ希望')
  51. tag_names << 'タグ希望'
  52. end
  53. post = Post.new(title:, url:, thumbnail_base: '', uploaded_user: current_user)
  54. post.thumbnail.attach(thumbnail)
  55. if post.save
  56. post.resized_thumbnail!
  57. # TODO: 接頭辞に応じて category 変へる
  58. post.tags = tag_names.map { |name| Tag.find_or_initialize_by(name:) { |tag|
  59. tag.category = 'general'
  60. } }
  61. render json: post.as_json(include: { tags: { only: [:id, :name, :category] } }),
  62. status: :created
  63. else
  64. render json: { errors: post.errors.full_messages }, status: :unprocessable_entity
  65. end
  66. end
  67. def viewed
  68. return head :unauthorized unless current_user
  69. current_user.viewed_posts << Post.find(params[:id])
  70. head :no_content
  71. end
  72. def unviewed
  73. return head :unauthorized unless current_user
  74. current_user.viewed_posts.delete(Post.find(params[:id]))
  75. head :no_content
  76. end
  77. # PATCH/PUT /posts/1
  78. def update
  79. return head :unauthorized unless current_user
  80. return head :forbidden unless current_user.member?
  81. title = params[:title]
  82. tag_names = params[:tags].to_s.split(' ')
  83. if tag_names.size < 20 && tag_names.none?('タグ希望')
  84. tag_names << 'タグ希望'
  85. end
  86. post = Post.find(params[:id].to_i)
  87. tags = post.tags.where(category: 'nico').to_a
  88. tag_names.each do |name|
  89. # TODO: 接頭辞に応じて category 変へる
  90. tags << Tag.find_or_initialize_by(name:) { |tag|
  91. tag.category = 'general'
  92. }
  93. end
  94. if post.update(title:, tags:)
  95. render({ json: (post
  96. .as_json(include: { tags: { only: [:id, :name, :category] } })),
  97. status: :created })
  98. else
  99. render json: post.errors, status: :unprocessable_entity
  100. end
  101. end
  102. # DELETE /posts/1
  103. def destroy
  104. end
  105. private
  106. def filtered_posts
  107. tag_names = params[:tags]&.split(?\ )
  108. match_type = params[:match]
  109. tag_names.present? ? filter_posts_by_tags(tag_names, match_type) : Post.all
  110. end
  111. def filter_posts_by_tags tag_names, match_type
  112. posts = Post.joins(:tags)
  113. if match_type == 'any'
  114. posts = posts.where(tags: { name: tag_names }).distinct
  115. else
  116. tag_names.each do |tag|
  117. posts = posts.where(id: Post.joins(:tags).where(tags: { name: tag }))
  118. end
  119. end
  120. posts.distinct
  121. end
  122. end