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

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