add sharing to telegram
This commit is contained in:
parent
6b976e0f89
commit
4ee2b46b32
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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']}`;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue