add sharing to telegram

This commit is contained in:
Georg Gadinger 2023-02-19 20:58:47 +01:00
parent 6b976e0f89
commit 4ee2b46b32
8 changed files with 152 additions and 25 deletions

View File

@ -5,6 +5,7 @@ require "cgi"
class Ajax::AnswerController < AjaxController class Ajax::AnswerController < AjaxController
include SocialHelper::TwitterMethods include SocialHelper::TwitterMethods
include SocialHelper::TumblrMethods include SocialHelper::TumblrMethods
include SocialHelper::TelegramMethods
def create def create
params.require :id params.require :id
@ -41,13 +42,7 @@ class Ajax::AnswerController < AjaxController
@response[:message] = t(".success") @response[:message] = t(".success")
@response[:success] = true @response[:success] = true
if current_user.sharing_enabled @response[:sharing] = sharing_hash(answer) if current_user.sharing_enabled
@response[:sharing] = {
twitter: twitter_share_url(answer),
tumblr: tumblr_share_url(answer),
custom: CGI.escape(prepare_tweet(answer))
}
end
return if inbox return if inbox
@ -74,4 +69,13 @@ class Ajax::AnswerController < AjaxController
@response[:message] = t(".success") @response[:message] = t(".success")
@response[:success] = true @response[:success] = true
end end
private
def sharing_hash(answer) = {
twitter: twitter_share_url(answer),
tumblr: tumblr_share_url(answer),
telegram: telegram_share_url(answer),
custom: CGI.escape(prepare_tweet(answer)),
}
end end

View File

@ -1,4 +1,7 @@
# frozen_string_literal: true
module SocialHelper module SocialHelper
include SocialHelper::TwitterMethods include SocialHelper::TwitterMethods
include SocialHelper::TumblrMethods include SocialHelper::TumblrMethods
end include SocialHelper::TelegramMethods
end

View File

@ -0,0 +1,23 @@
# frozen_string_literal: true
require "cgi"
module SocialHelper::TelegramMethods
include MarkdownHelper
def telegram_text(answer)
# using twitter_markdown here as it removes all formatting
"#{twitter_markdown answer.question.content}\n———\n#{twitter_markdown answer.content}"
end
def telegram_share_url(answer)
url = answer_url(
id: answer.id,
username: answer.user.screen_name,
host: APP_CONFIG["hostname"],
protocol: (APP_CONFIG["https"] ? :https : :http)
)
%(https://t.me/share/url?url=#{CGI.escape(url)}&text=#{CGI.escape(telegram_text(answer))})
end
end

View File

@ -1,10 +1,11 @@
import { Controller } from '@hotwired/stimulus'; import { Controller } from '@hotwired/stimulus';
export default class extends Controller { export default class extends Controller {
static targets = ['twitter', 'tumblr', 'custom']; static targets = ['twitter', 'tumblr', 'telegram', 'custom'];
declare readonly twitterTarget: HTMLAnchorElement; declare readonly twitterTarget: HTMLAnchorElement;
declare readonly tumblrTarget: HTMLAnchorElement; declare readonly tumblrTarget: HTMLAnchorElement;
declare readonly telegramTarget: HTMLAnchorElement;
declare readonly customTarget: HTMLAnchorElement; declare readonly customTarget: HTMLAnchorElement;
declare readonly hasCustomTarget: boolean; declare readonly hasCustomTarget: boolean;
@ -20,6 +21,7 @@ export default class extends Controller {
if (this.autoCloseValue) { if (this.autoCloseValue) {
this.twitterTarget.addEventListener('click', () => this.close()); this.twitterTarget.addEventListener('click', () => this.close());
this.tumblrTarget.addEventListener('click', () => this.close()); this.tumblrTarget.addEventListener('click', () => this.close());
this.telegramTarget.addEventListener('click', () => this.close());
if (this.hasCustomTarget) { if (this.hasCustomTarget) {
this.customTarget.addEventListener('click', () => this.close()); this.customTarget.addEventListener('click', () => this.close());
@ -36,6 +38,7 @@ export default class extends Controller {
this.twitterTarget.href = this.configValue['twitter']; this.twitterTarget.href = this.configValue['twitter'];
this.tumblrTarget.href = this.configValue['tumblr']; this.tumblrTarget.href = this.configValue['tumblr'];
this.telegramTarget.href = this.configValue['telegram'];
if (this.hasCustomTarget) { if (this.hasCustomTarget) {
this.customTarget.href = `${this.customTarget.href}${this.configValue['custom']}`; this.customTarget.href = `${this.customTarget.href}${this.configValue['custom']}`;

View File

@ -49,6 +49,9 @@
%a.btn.btn-primary{ href: "#", data: { inbox_sharing_target: "tumblr" }, target: "_blank" } %a.btn.btn-primary{ href: "#", data: { inbox_sharing_target: "tumblr" }, target: "_blank" }
%i.fab.fa-tumblr.fa-fw %i.fab.fa-tumblr.fa-fw
Tumblr Tumblr
%a.btn.btn-primary{ href: "#", data: { inbox_sharing_target: "telegram" }, target: "_blank" }
%i.fab.fa-telegram.fa-fw
Telegram
- if current_user.sharing_custom_url.present? - if current_user.sharing_custom_url.present?
%a.btn.btn-primary{ href: current_user.sharing_custom_url, data: { inbox_sharing_target: "custom" }, target: "_blank" } %a.btn.btn-primary{ href: current_user.sharing_custom_url, data: { inbox_sharing_target: "custom" }, target: "_blank" }
= current_user.display_sharing_custom_url = current_user.display_sharing_custom_url

View File

@ -13,7 +13,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
id:, id:,
answer:, answer:,
share: shared_services&.to_json, share: shared_services&.to_json,
inbox: inbox:,
}.compact }.compact
end end
@ -42,7 +42,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
"success" => false, "success" => false,
# caught by rescue_from, so status is not peter_dinklage # caught by rescue_from, so status is not peter_dinklage
"status" => "parameter_error", "status" => "parameter_error",
"message" => anything "message" => anything,
} }
end end
@ -70,13 +70,33 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => true, "success" => true,
"status" => "okay", "status" => "okay",
"message" => anything "message" => anything,
} }
end end
include_examples "creates the answer" include_examples "creates the answer"
it_behaves_like "fails when answer content is empty" it_behaves_like "fails when answer content is empty"
context "when the user has sharing enabled" do
before do
user.sharing_enabled = true
user.save
end
let(:expected_response) do
super().merge(
"sharing" => {
"twitter" => a_string_matching("https://twitter.com/"),
"tumblr" => a_string_matching("https://www.tumblr.com/"),
"telegram" => a_string_matching("https://t.me/"),
"custom" => a_string_matching(/Werfen\+Sie\+nicht\+l%C3%A4nger\+das\+Fenster\+zum\+Geld\+hinaus%21/),
}
)
end
include_examples "creates the answer"
end
end end
context "when the inbox entry does not belong to the user" do context "when the inbox entry does not belong to the user" do
@ -85,7 +105,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => false, "success" => false,
"status" => "fail", "status" => "fail",
"message" => anything "message" => anything,
} }
end end
@ -100,7 +120,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => true, "success" => true,
"status" => "okay", "status" => "okay",
"message" => anything "message" => anything,
} }
end end
@ -129,13 +149,33 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
"success" => true, "success" => true,
"status" => "okay", "status" => "okay",
"message" => anything, "message" => anything,
"render" => anything "render" => anything,
} }
end end
include_examples "creates the answer" include_examples "creates the answer"
it_behaves_like "fails when answer content is empty" it_behaves_like "fails when answer content is empty"
context "when the user has sharing enabled" do
before do
user.sharing_enabled = true
user.save
end
let(:expected_response) do
super().merge(
"sharing" => {
"twitter" => a_string_matching("https://twitter.com/"),
"tumblr" => a_string_matching("https://www.tumblr.com/"),
"telegram" => a_string_matching("https://t.me/"),
"custom" => a_string_matching(/Werfen\+Sie\+nicht\+l%C3%A4nger\+das\+Fenster\+zum\+Geld\+hinaus%21/),
}
)
end
include_examples "creates the answer"
end
end end
context "when question asker does not allow strangers to answer (i.e. question was not in inbox)" do context "when question asker does not allow strangers to answer (i.e. question was not in inbox)" do
@ -144,7 +184,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => false, "success" => false,
"status" => "privacy_stronk", "status" => "privacy_stronk",
"message" => anything "message" => anything,
} }
end end
@ -160,7 +200,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => false, "success" => false,
"status" => "answering_other_blocked_self", "status" => "answering_other_blocked_self",
"message" => I18n.t("errors.answering_other_blocked_self") "message" => I18n.t("errors.answering_other_blocked_self"),
} }
end end
@ -176,7 +216,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => false, "success" => false,
"status" => "answering_self_blocked_other", "status" => "answering_self_blocked_other",
"message" => I18n.t("errors.answering_self_blocked_other") "message" => I18n.t("errors.answering_self_blocked_other"),
} }
end end
@ -196,7 +236,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
"success" => false, "success" => false,
# caught by rescue_from, so status is not peter_dinklage # caught by rescue_from, so status is not peter_dinklage
"status" => "parameter_error", "status" => "parameter_error",
"message" => anything "message" => anything,
} }
end end
@ -214,7 +254,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => false, "success" => false,
"status" => "err", "status" => "err",
"message" => anything "message" => anything,
} }
end end
@ -230,7 +270,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
let(:params) do let(:params) do
{ {
answer: answer_id answer: answer_id,
} }
end end
@ -242,7 +282,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => true, "success" => true,
"status" => "okay", "status" => "okay",
"message" => anything "message" => anything,
} }
end end
@ -259,7 +299,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => false, "success" => false,
"status" => "nopriv", "status" => "nopriv",
"message" => anything "message" => anything,
} }
end end
@ -311,7 +351,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => false, "success" => false,
"status" => anything, "status" => anything,
"message" => anything "message" => anything,
} }
end end
@ -324,7 +364,7 @@ describe Ajax::AnswerController, :ajax_controller, type: :controller do
{ {
"success" => false, "success" => false,
"status" => "nopriv", "status" => "nopriv",
"message" => anything "message" => anything,
} }
end end

View File

@ -0,0 +1,47 @@
# frozen_string_literal: true
require "rails_helper"
describe SocialHelper::TelegramMethods, type: :helper do
let(:user) { FactoryBot.create(:user) }
let(:answer) do
FactoryBot.create(
:answer,
user:,
content: "this is an answer\nwith multiple lines\nand **FORMATTING**",
question_content: "this is a question .... or is it?"
)
end
before do
stub_const("APP_CONFIG", {
"hostname" => "example.com",
"https" => true,
"items_per_page" => 5,
})
end
describe "#telegram_text" do
subject { telegram_text(answer) }
it "returns a proper text for sharing" do
expect(subject).to eq(<<~TEXT.strip)
this is a question .... or is it?
this is an answer
with multiple lines
and FORMATTING
TEXT
end
end
describe "#telegram_share_url" do
subject { telegram_share_url(answer) }
it "returns a proper share link" do
expect(subject).to eq(<<~URL.strip)
https://t.me/share/url?url=https%3A%2F%2Fexample.com%2F%40#{answer.user.screen_name}%2Fa%2F#{answer.id}&text=this+is+a+question+....+or+is+it%3F%0A%E2%80%94%E2%80%94%E2%80%94%0Athis+is+an+answer%0Awith+multiple+lines%0Aand+FORMATTING
URL
end
end
end

View File

@ -82,6 +82,10 @@ describe "inbox/_entry.html.haml", type: :view do
expect(rendered).to have_css(%(.inbox-entry__sharing.d-none)) expect(rendered).to have_css(%(.inbox-entry__sharing.d-none))
end end
it "has a link-button to share to telegram" do
expect(rendered).to have_css(%(.inbox-entry__sharing a.btn[data-inbox-sharing-target="telegram"]))
end
it "has a link-button to share to tumblr" do it "has a link-button to share to tumblr" do
expect(rendered).to have_css(%(.inbox-entry__sharing a.btn[data-inbox-sharing-target="tumblr"])) expect(rendered).to have_css(%(.inbox-entry__sharing a.btn[data-inbox-sharing-target="tumblr"]))
end end