ぼざクリ タグ広場 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.
 
 
 
 
 
 

157 lines
4.2 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. post = Post.new(title:, url:, thumbnail_base: '', uploaded_user: current_user)
  51. post.thumbnail.attach(thumbnail)
  52. if post.save
  53. post.resized_thumbnail!
  54. post.tags = normalise_tags(tags_names)
  55. render json: post.as_json(include: { tags: { only: [:id, :name, :category] } }),
  56. status: :created
  57. else
  58. render json: { errors: post.errors.full_messages }, status: :unprocessable_entity
  59. end
  60. end
  61. def viewed
  62. return head :unauthorized unless current_user
  63. current_user.viewed_posts << Post.find(params[:id])
  64. head :no_content
  65. end
  66. def unviewed
  67. return head :unauthorized unless current_user
  68. current_user.viewed_posts.delete(Post.find(params[:id]))
  69. head :no_content
  70. end
  71. # PATCH/PUT /posts/1
  72. def update
  73. return head :unauthorized unless current_user
  74. return head :forbidden unless current_user.member?
  75. title = params[:title]
  76. tag_names = params[:tags].to_s.split(' ')
  77. post = Post.find(params[:id].to_i)
  78. tags = post.tags.where(category: 'nico').to_a + normalise_tags(tag_names)
  79. if post.update(title:, tags:)
  80. render json: post.as_json(include: { tags: { only: [:id, :name, :category] } }),
  81. status: :created
  82. else
  83. render json: post.errors, status: :unprocessable_entity
  84. end
  85. end
  86. # DELETE /posts/1
  87. def destroy
  88. end
  89. private
  90. CATEGORY_PREFIXES = {
  91. 'gen:' => 'general',
  92. 'djk:' => 'deerjikist',
  93. 'meme:' => 'meme',
  94. 'chr:' => 'character',
  95. 'mtr:' => 'material',
  96. 'meta:' => 'meta' }.freeze
  97. def filtered_posts
  98. tag_names = params[:tags]&.split(' ')
  99. match_type = params[:match]
  100. tag_names.present? ? filter_posts_by_tags(tag_names, match_type) : Post.all
  101. end
  102. def filter_posts_by_tags tag_names, match_type
  103. posts = Post.joins(:tags)
  104. if match_type == 'any'
  105. posts = posts.where(tags: { name: tag_names }).distinct
  106. else
  107. tag_names.each do |tag|
  108. posts = posts.where(id: Post.joins(:tags).where(tags: { name: tag }))
  109. end
  110. end
  111. posts.distinct
  112. end
  113. def normalise_tags tag_names
  114. tags = tag_names.map do |name|
  115. pf, cat = CATEGORY_PREFIXES.find { |p, _| name.start_with?(p) } || ['', nil]
  116. name.delete_prefix!(pf)
  117. Tag.find_or_initialize_by(name:).tap do |tag|
  118. if cat && tag.category != cat
  119. tag.category = cat
  120. tag.save!
  121. end
  122. end
  123. end
  124. tags << Tag.tagme if tags.size < 20 && tags.none?(Tag.tagme)
  125. tags.uniq
  126. end
  127. end