suzuyu0115 / meshitelog

8 stars 0 forks source link

LINEで送られてきたFlexMessageに画像が付加されない不具合について #117

Closed suzuyu0115 closed 1 year ago

suzuyu0115 commented 1 year ago

質問内容・実現したいこと

LINEのFlexMessageに画像が付加されない不具合

発生している問題

飯投稿アプリで投稿をユーザーに送ることができ、送られたユーザーはLINEのFlexMessageで画像つきの投稿が届く仕様となっています。

## _form.html.erb
<%= form_with model: post, local: true do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="form-group">
    <%= f.label :title %>
    <%= f.text_field :title, class: 'form-control', placeholder: '必須' %>
  </div>
  <br>
  <div class="form-group">
    <%= f.label :content %>
    <%= f.text_area :content, class: 'form-control', rows: 10, placeholder: '感想や店名、送り相手への煽りなどご自由に!(必須)' %>
  </div>
  <br>
  <div class="form-group">
    <%= f.label :food_image %>
    <%= f.file_field :food_image, class: 'form-control mb-3',
        accept: 'image/*', onchange: 'previewImage()' %>
    <%= f.hidden_field :food_image_cache %>
  </div>
  <br>
  <div class="mt-3 mb-3">
    <%= image_tag post.food_image.url,
                  id: 'preview',
                  size: '300x200' %>
  </div>
  <br>
  <div class="form-group">
    <%= f.label :tag_list %>
    <%= f.text_field :tag_list, class: 'form-control', value: post.tag_list.join('、'), placeholder: '、で区切って入力してください' %>
  </div>
  <br>
  <div class="form-group">
    <% if post.new_record? || (post.published_at.present? && post.published_at > Time.current) %>
      <%= f.label :published_at %>
      <%= f.datetime_field :published_at, class: 'form-control' %>
    <% end %>
  </div>
  <br>
  <div class="form-group">
    <% if post.new_record? || (post.published_at.present? && post.published_at > Time.current) %>
      <%= f.label :recipients %>
      <div class="dropup">
        <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          <%= t('posts.new.recipients') %>
        </button>
        <div class="dropdown-menu scrollable-dropdown dropdown-menu-padding" aria-labelledby="dropdownMenuButton">
          <%= f.collection_check_boxes :recipient_ids, User.all, :id, :display_name do |b| %>
            <div class="form-check">
              <%= b.check_box class: 'form-check-input' %>
              <%= b.label { b.object.display_name.presence || b.object.name } %>
            </div>
          <% end %>
        </div>
      </div>
    <% end %>
  </div>
  <br>
  <br>
  <%= f.submit t('posts.new.title'), class: 'btn btn-warning btn-lg d-grid gap-2 col-6 mx-auto' %>
<% end %>
  <br>
FlexMessage関連の記してあるpost.rb

  # 各投稿詳細ページのURLを返す
  def post_url
    "#{ROOT_URL}/posts/#{id}"
  end

  def notify_line
    # 予約投稿か否かを判定
    return unless published?

    line_client = LineClient.new
    flex_contents = {
      type: "bubble",
      header: {
        type: 'box',
        layout: 'vertical',
        contents: [
          {
            type: 'text',
            text: "飯が届きました!",
            weight: "bold",
            size: "xl",
            wrap: true
          }
        ]
      },
      hero: {
        type: "image",
        url: food_image.url,
        size: "full",
        aspectRatio: "20:13",
        aspectMode: "cover",
        action: {
          type: "uri",
          uri: post_url
        }
      },
      body: {
        type: "box",
        layout: "vertical",
        contents: [
          {
            type: "text",
            text: title,
            weight: "bold",
            size: "xl",
            wrap: true
          },
          {
            type: "box",
            layout: "vertical",
            margin: "lg",
            spacing: "sm",
            contents: [
              {
                type: "box",
                layout: "baseline",
                spacing: "sm",
                contents: [
                  {
                    type: "text",
                    text: "#{sender_name} さんより",
                    wrap: true,
                    color: "#666666",
                    size: "sm",
                    flex: 5
                  }
                ]
              },
              {
                type: "box",
                layout: "baseline",
                spacing: "sm",
                contents: [
                  {
                    type: "text",
                    text: content,
                    wrap: true,
                    color: "#666666",
                    size: "md",
                    flex: 5
                  }
                ]
              }
            ]
          }
        ]
      },
      footer: {
        type: "box",
        layout: "vertical",
        spacing: "sm",
        contents: [
          {
            type: "button",
            style: "link",
            height: "sm",
            action: {
              type: "uri",
              label: "詳細を見る",
              uri: post_url
            }
          },
          {
            type: "box",
            layout: "vertical",
            contents: [],
            margin: "sm"
          }
        ],
        flex: 0
      }
    }

画像には、food_image.urlを呼び出すようにしていますが、たまに画像が真っ白になって届くことがあります。 正常に届くこともあり、あまりエラーに規則性がなく、原因究明が難しいのが現状です。 下記、エラーについて記します。

- FlexMessageで、たまに画像が表示されない(真っ白)のまま届くことがある
- 画像付きで届くパターンと画像が読み込まれずに届くパターンとある。規則性はない
- 同じ投稿を複数人相手に送信した場合、画像付きで届く人と画像が真っ白のまま届く人といる
- 画像付きで届いた投稿をスマホで開き、後にPCで同じ投稿を開くと画像が白くなっていることがある(逆もまた然り)
- LINEに届いてすぐにトークを開くと画像が表示されている、時間を経って開いた場合は画像が表示されないケースが多い気がする

こちら、原因究明をお願いしたいです。 何卒よろしくお願いいたします。 参考に、posts_controller.rbのコードも追記いたします。

class PostsController < ApplicationController
  before_action :logged_in_user, only: [:new, :create, :edit, :update, :destroy, :scheduled]
  before_action :set_post, only: %i[edit update destroy]

  def index
    @q = Post.where('published_at IS NULL OR published_at <= ?', Time.current).ransack(params[:q])
    @posts = @q.result(distinct: true).includes(:user, :taggings).order(created_at: :desc)

    @posts = @posts.tagged_with("#{params[:tag_name]}") if params[:tag_name]

    @posts = @posts.page(params[:page])

    render partial: 'post', collection: @posts, as: :post, status: :ok if request.xhr?
  end

  # 高評価順
  def top_rated
    @q = Post.left_joins(:bookmarks)
      .select('posts.*, COUNT(bookmarks.post_id) AS bookmarks_count')
      .group('posts.id')
      .order('bookmarks_count DESC')
      .where('published_at IS NULL OR published_at <= ?', Time.current)
      .ransack(params[:q])

    @posts = @q.result(distinct: true).includes(:user, :taggings)

    @posts = @posts.tagged_with("#{params[:tag_name]}") if params[:tag_name]

    @posts = @posts.page(params[:page])
  end

  def show
    @post = Post.find(params[:id])
    # 予約投稿で現在時刻よりも後の投稿で、かつ現在のユーザーが投稿の作成者でない場合
    if @post.future_reserved_post?(current_user)
      redirect_to posts_path
    else
      @comment = Comment.new
      @comments = @post.comments.includes(:user).order(created_at: :desc)
    end
  end

  def new
    @post = Post.new
  end

  def edit; end

  def create
    @post = current_user.posts.build(post_params)
    @post.author = current_user
    if @post.save
      redirect_to posts_path, success: t('defaults.message.created', item: Post.model_name.human)
    else
      flash.now[:danger] = t('defaults.message.not_created', item: Post.model_name.human)
      render :new, status: :unprocessable_entity
    end
  end

  def update
    if @post.update(post_params)
      redirect_to @post, success: t('defaults.message.updated', item: Post.model_name.human)
    else
      flash.now[:danger] = t('defaults.message.not_updated', item: Post.model_name.human)
      render :edit, status: :unprocessable_entity
    end
  end

  def destroy
    @post.destroy!
    redirect_to posts_path, success: t('defaults.message.deleted', item: Post.model_name.human)
  end

  # お気に入り投稿一覧
  def bookmarks
    @q = current_user.bookmark_posts.ransack(params[:q])
    @bookmark_posts = @q.result(distinct: true).includes(:user, :taggings).order(created_at: :desc).page(params[:page])
  end

  # 送信待ちの投稿一覧
  def scheduled
    @posts = current_user.posts.where('published_at > ?', Time.current).order(created_at: :desc).page(params[:page])
  end

  # 受け取った飯投稿一覧
  def received
    @received_posts = current_user.received_posts.includes(:user, :taggings).where('published_at IS NULL OR published_at <= ?', Time.current).order(created_at: :desc).page(params[:page])
  end

  def search_tags
    query = params[:query]
    @tags = ActsAsTaggableOn::Tag.where('name LIKE ?', "%#{query}%")
    render json: @tags.pluck(:name)
  end

  private

  def set_post
    @post = current_user.posts.find(params[:id])
  end

  def post_params
    params.require(:post).permit(:title, :content, :food_image, :food_image_cache, :tag_list, :published_at, recipient_ids: [])
  end
end