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

122 lines
3.5 KiB

  1. require 'open-uri'
  2. require 'nokogiri'
  3. class PostsController < ApplicationController
  4. before_action :set_post, only: %i[ show update destroy ]
  5. # GET /posts
  6. def index
  7. if params[:tags].present?
  8. tag_names = params[:tags].split(',')
  9. match_type = params[:match]
  10. if match_type == 'any'
  11. posts = Post.joins(:tags).where(tags: { name: tag_names }).distinct
  12. else
  13. posts = Post.joins(:tags)
  14. tag_names.each do |tag|
  15. posts = posts.where(id: Post.joins(:tags).where(tags: { name: tag }))
  16. end
  17. posts = posts.distinct
  18. end
  19. else
  20. posts = Post.all
  21. end
  22. render json: posts.as_json(include: { tags: { only: [:id, :name, :category] } })
  23. end
  24. # GET /posts/1
  25. def show
  26. post = Post.includes(:tags).find(params[:id])
  27. viewed = current_user&.viewed?(post)
  28. render json: (post
  29. .as_json(include: { tags: { only: [:id, :name, :category] } })
  30. .merge(viewed: viewed))
  31. end
  32. # POST /posts
  33. def create
  34. return head :unauthorized unless current_user
  35. return head :forbidden unless ['admin', 'member'].include?(current_user.role)
  36. # TODO: URL が正規のものがチェック,不正ならエラー
  37. title = params[:title]
  38. unless title.present?
  39. # TODO: # 既知サイトなら決まったフォーマットで title 取得するやぅに.
  40. begin
  41. html = URI.open(params[:url], open_timeout: 5, read_timeout: 5).read
  42. doc = Nokogiri::HTML.parse(html)
  43. title = doc.at('title')&.text&.strip || ''
  44. rescue
  45. title = ''
  46. end
  47. end
  48. post = Post.new(title: title, url: params[:url], thumbnail_base: '', uploaded_user: current_user)
  49. if params[:thumbnail].present?
  50. post.thumbnail.attach(params[:thumbnail])
  51. else
  52. # TODO: 既知ドメインであれば指定のアドレスからサムネールを取得するやぅにする.
  53. path = Rails.root.join('tmp', "thumb_#{ SecureRandom.hex }.png")
  54. system("node #{ Rails.root }/lib/screenshot.js #{ Shellwords.escape(params[:url]) } #{ path }")
  55. if File.exist?(path)
  56. image = MiniMagick::Image.open(path)
  57. image.resize '180x180'
  58. post.thumbnail.attach(io: File.open(image.path),
  59. filename: 'thumbnail.png',
  60. content_type: 'image/png')
  61. File.delete(path) rescue nil
  62. end
  63. end
  64. if post.save
  65. post.resized_thumbnail!
  66. if params[:tags].present?
  67. tag_ids = JSON.parse(params[:tags])
  68. post.tags = Tag.where(id: tag_ids)
  69. end
  70. render json: post, status: :created
  71. else
  72. render json: { errors: post.errors.full_messages }, status: :unprocessable_entity
  73. end
  74. end
  75. def viewed
  76. return head :unauthorized unless current_user
  77. current_user.viewed_posts << Post.find(params[:id])
  78. head :no_content
  79. end
  80. def unviewed
  81. return head :unauthorized unless current_user
  82. current_user.viewed_posts.delete(Post.find(params[:id]))
  83. head :no_content
  84. end
  85. # PATCH/PUT /posts/1
  86. def update
  87. if @post.update(post_params)
  88. render json: @post
  89. else
  90. render json: @post.errors, status: :unprocessable_entity
  91. end
  92. end
  93. # DELETE /posts/1
  94. def destroy
  95. @post.destroy!
  96. end
  97. private
  98. # Use callbacks to share common setup or constraints between actions.
  99. def set_post
  100. @post = Post.find(params.expect(:id))
  101. end
  102. # Only allow a list of trusted parameters through.
  103. def post_params
  104. params.expect(post: [ :title, :body ])
  105. end
  106. end