Skip to content

Commit e3fd023

Browse files
authored
Merge branch 'main' into activity-notifications
2 parents caed346 + eca9ed3 commit e3fd023

File tree

6 files changed

+157
-46
lines changed

6 files changed

+157
-46
lines changed

config/config.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ config :algora, Oban,
3232
comment_consumers: 1,
3333
github_og_image: 5,
3434
notify_bounty: 1,
35+
notify_tip_intent: 1,
3536
activity_notifier: 1,
3637
activity_mailer: 1
3738
]

lib/algora/bounties/bounties.ex

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,47 @@ defmodule Algora.Bounties do
126126
|> Oban.insert()
127127
end
128128

129-
@spec create_tip(%{creator: User.t(), owner: User.t(), recipient: User.t(), amount: Money.t()}) ::
129+
@spec create_tip_intent(
130+
%{
131+
recipient: String.t(),
132+
amount: Money.t(),
133+
ticket_ref: %{owner: String.t(), repo: String.t(), number: integer()}
134+
},
135+
opts :: [installation_id: integer()]
136+
) ::
137+
{:ok, String.t()} | {:error, atom()}
138+
def create_tip_intent(
139+
%{recipient: recipient, amount: amount, ticket_ref: %{owner: owner, repo: repo, number: number}},
140+
opts \\ []
141+
) do
142+
query =
143+
URI.encode_query(
144+
amount: Money.to_decimal(amount),
145+
recipient: recipient,
146+
owner: owner,
147+
repo: repo,
148+
number: number
149+
)
150+
151+
url = AlgoraWeb.Endpoint.url() <> "/tip" <> "?" <> query
152+
153+
%{
154+
url: url,
155+
ticket_ref: %{owner: owner, repo: repo, number: number},
156+
installation_id: opts[:installation_id]
157+
}
158+
|> Jobs.NotifyTipIntent.new()
159+
|> Oban.insert()
160+
end
161+
162+
@spec create_tip(
163+
%{creator: User.t(), owner: User.t(), recipient: User.t(), amount: Money.t()},
164+
opts :: [ticket_ref: %{owner: String.t(), repo: String.t(), number: integer()}]
165+
) ::
130166
{:ok, String.t()} | {:error, atom()}
131-
def create_tip(%{creator: creator, owner: owner, recipient: recipient, amount: amount}) do
167+
def create_tip(%{creator: creator, owner: owner, recipient: recipient, amount: amount}, opts \\ []) do
168+
ticket_ref = opts[:ticket_ref]
169+
132170
changeset =
133171
Tip.changeset(%Tip{}, %{
134172
amount: amount,
@@ -162,7 +200,11 @@ defmodule Algora.Bounties do
162200
product_data: %{
163201
name: "Payment to @#{recipient.provider_login}",
164202
# TODO:
165-
# description: nil,
203+
description:
204+
if(ticket_ref,
205+
do: "#{ticket_ref[:owner]}/#{ticket_ref[:repo]}##{ticket_ref[:number]}",
206+
else: "Tip to @#{recipient.provider_login}"
207+
),
166208
images: [recipient.avatar_url]
167209
}
168210
},
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
defmodule Algora.Bounties.Jobs.NotifyTipIntent do
2+
@moduledoc false
3+
use Oban.Worker, queue: :notify_tip_intent
4+
5+
alias Algora.Github
6+
7+
require Logger
8+
9+
@impl Oban.Worker
10+
def perform(%Oban.Job{args: %{"url" => url, "ticket_ref" => ticket_ref, "installation_id" => nil}}) do
11+
body = get_body(url)
12+
13+
if Github.pat_enabled() do
14+
Github.create_issue_comment(
15+
Github.pat(),
16+
ticket_ref["owner"],
17+
ticket_ref["repo"],
18+
ticket_ref["number"],
19+
body
20+
)
21+
else
22+
Logger.info("""
23+
Github.create_issue_comment(Github.pat(), "#{ticket_ref["owner"]}", "#{ticket_ref["repo"]}", #{ticket_ref["number"]},
24+
\"\"\"
25+
#{body}
26+
\"\"\")
27+
""")
28+
end
29+
end
30+
31+
@impl Oban.Worker
32+
def perform(%Oban.Job{args: %{"url" => url, "ticket_ref" => ticket_ref, "installation_id" => installation_id}}) do
33+
with {:ok, token} <- Github.get_installation_token(installation_id) do
34+
body = get_body(url)
35+
36+
Github.create_issue_comment(
37+
token,
38+
ticket_ref["owner"],
39+
ticket_ref["repo"],
40+
ticket_ref["number"],
41+
body
42+
)
43+
end
44+
end
45+
46+
defp get_body(url), do: "Please visit [Algora](#{url}) to complete your tip via Stripe."
47+
end

lib/algora/integrations/github/poller/comment_consumer.ex

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ defmodule Algora.Github.Poller.CommentConsumer do
44

55
alias Algora.Accounts
66
alias Algora.Bounties
7-
alias Algora.Github
87
alias Algora.Util
98

109
require Logger
@@ -25,40 +24,23 @@ defmodule Algora.Github.Poller.CommentConsumer do
2524
end
2625

2726
defp run_command({:tip, args}, ticket_ref, _comment) do
28-
amount = Keyword.get(args, :amount)
29-
recipient = Keyword.get(args, :recipient)
30-
owner = Keyword.get(ticket_ref, :owner)
31-
repo = Keyword.get(ticket_ref, :repo)
32-
number = Keyword.get(ticket_ref, :number)
33-
34-
query = URI.encode_query(amount: Money.to_decimal(amount), recipient: recipient)
35-
url = AlgoraWeb.Endpoint.url() <> "/tip" <> "?" <> query
36-
body = "Please visit [Algora](#{url}) to complete your tip via Stripe."
37-
38-
if Github.pat_enabled() do
39-
Github.create_issue_comment(Github.pat(), owner, repo, number, body)
40-
else
41-
Logger.info("""
42-
Github.create_issue_comment(Github.pat(), "#{owner}", "#{repo}", #{number},
43-
\"\"\"
44-
#{body}
45-
\"\"\")
46-
""")
47-
48-
:ok
49-
end
27+
Bounties.create_tip_intent(%{
28+
recipient: args[:recipient],
29+
amount: args[:amount],
30+
ticket_ref: %{owner: ticket_ref[:owner], repo: ticket_ref[:repo], number: ticket_ref[:number]}
31+
})
5032
end
5133

5234
defp run_command({:bounty, args}, ticket_ref, comment) do
53-
with {:ok, user} <- Accounts.fetch_user_by(provider_id: to_string(comment["user"]["id"])),
54-
{:ok, amount} <- Keyword.fetch(args, :amount) do
55-
Bounties.create_bounty(%{
56-
creator: user,
57-
owner: user,
58-
amount: amount,
59-
ticket_ref: %{owner: ticket_ref[:owner], repo: ticket_ref[:repo], number: ticket_ref[:number]}
60-
})
61-
else
35+
case Accounts.fetch_user_by(provider_id: to_string(comment["user"]["id"])) do
36+
{:ok, user} ->
37+
Bounties.create_bounty(%{
38+
creator: user,
39+
owner: user,
40+
amount: args[:amount],
41+
ticket_ref: %{owner: ticket_ref[:owner], repo: ticket_ref[:repo], number: ticket_ref[:number]}
42+
})
43+
6244
{:error, _reason} = error ->
6345
Logger.error("Failed to create bounty: #{inspect(error)}")
6446
error

lib/algora_web/controllers/tip_controller.ex

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@ defmodule AlgoraWeb.TipController do
66
alias Algora.Workspace
77
alias AlgoraWeb.UserAuth
88

9-
def create(conn, %{"amount" => amount, "recipient" => recipient} = _params) do
9+
def create(conn, %{"amount" => amount, "recipient" => recipient} = params) do
10+
ticket_ref = extract_ticket_ref(params)
11+
1012
with {:ok, current_user} <- get_current_user(conn),
1113
%Money{} = amount <- Money.new(:USD, amount),
1214
{:ok, token} <- Accounts.get_access_token(current_user),
1315
{:ok, recipient_user} <- Workspace.ensure_user(token, recipient),
1416
{:ok, checkout_url} <-
15-
Bounties.create_tip(%{
16-
creator: current_user,
17-
owner: current_user,
18-
recipient: recipient_user,
19-
amount: amount
20-
}) do
17+
Bounties.create_tip(
18+
%{
19+
creator: current_user,
20+
owner: current_user,
21+
recipient: recipient_user,
22+
amount: amount
23+
},
24+
if(ticket_ref, do: [ticket_ref: ticket_ref], else: [])
25+
) do
2126
redirect(conn, external: checkout_url)
2227
else
2328
# TODO: just use a plug
@@ -40,6 +45,15 @@ defmodule AlgoraWeb.TipController do
4045
|> redirect(to: UserAuth.signed_in_path(conn))
4146
end
4247

48+
defp extract_ticket_ref(%{"owner" => owner, "repo" => repo, "number" => number}) do
49+
case Integer.parse(number) do
50+
{number, ""} -> [owner: owner, repo: repo, number: number]
51+
_ -> nil
52+
end
53+
end
54+
55+
defp extract_ticket_ref(_), do: nil
56+
4357
defp get_current_user(conn) do
4458
case conn.assigns.current_user do
4559
nil -> {:error, :unauthorized}

lib/algora_web/controllers/webhooks/github_controller.ex

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ defmodule AlgoraWeb.Webhooks.GithubController do
5757
issue = params["issue"]
5858
installation_id = params["installation"]["id"]
5959

60+
# TODO: community bounties?
6061
with {:ok, "admin"} <- get_permissions(author, params),
6162
{:ok, token} <- Github.get_installation_token(installation_id),
6263
{:ok, installation} <-
@@ -81,11 +82,35 @@ defmodule AlgoraWeb.Webhooks.GithubController do
8182
end
8283
end
8384

84-
defp execute_command({:tip, args}, _author, _params) when not is_nil(args) do
85-
amount = Keyword.get(args, :amount)
86-
recipient = Keyword.get(args, :username)
85+
defp execute_command({:tip, args}, author, params) when not is_nil(args) do
86+
amount = args[:amount]
87+
recipient = args[:recipient]
88+
repo = params["repository"]
89+
issue = params["issue"]
90+
installation_id = params["installation"]["id"]
91+
92+
# TODO: handle missing amount
93+
# TODO: handle missing recipient
94+
# TODO: handle tip to self
95+
# TODO: handle autopay with cooldown
96+
# TODO: community tips?
97+
case get_permissions(author, params) do
98+
{:ok, "admin"} ->
99+
Bounties.create_tip_intent(
100+
%{
101+
recipient: recipient,
102+
amount: amount,
103+
ticket_ref: %{owner: repo["owner"]["login"], repo: repo["name"], number: issue["number"]}
104+
},
105+
installation_id: installation_id
106+
)
87107

88-
Logger.info("Tip #{amount} to #{recipient}")
108+
{:ok, _permission} ->
109+
{:error, :unauthorized}
110+
111+
{:error, _reason} = error ->
112+
error
113+
end
89114
end
90115

91116
defp execute_command({:claim, args}, _author, _params) when not is_nil(args) do

0 commit comments

Comments
 (0)