Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .iex.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ alias Algora.Payments.Customer
alias Algora.Payments.PaymentMethod
alias Algora.Payments.Transaction
alias Algora.Repo
alias Algora.Workspace.Ticket

IEx.configure(inspect: [charlists: :as_lists, limit: :infinity], auto_reload: true)

Expand Down
2 changes: 2 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ config :algora, Oban,
notify_bounty: 1,
notify_tip_intent: 1,
notify_claim: 1,
notify_transfer: 100,
prompt_payout_connect: 100,
transfers: 1,
activity_notifier: 1,
activity_mailer: 1
Expand Down
65 changes: 65 additions & 0 deletions lib/algora/bounties/jobs/notify_transfer.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
defmodule Algora.Bounties.Jobs.NotifyTransfer do
@moduledoc false
use Oban.Worker, queue: :notify_transfer

import Ecto.Query

alias Algora.Bounties.Ticket
alias Algora.Github
alias Algora.Payments.Transaction
alias Algora.Repo
alias Algora.Workspace.Installation
alias Algora.Workspace.Ticket

require Logger

@impl Oban.Worker
def perform(%Oban.Job{args: %{"transafer_id" => transafer_id}}) do
with {:ok, ticket} <-
Repo.fetch_one(
from t in Ticket,
left_join: bounty in assoc(t, :bounties),
left_join: tip in assoc(t, :tips),
left_join: tx in Transaction,
on: tx.bounty_id == bounty.id or tx.tip_id == tip.id,
join: repo in assoc(t, :repository),
join: user in assoc(repo, :user),
where: tx.id == ^transafer_id,
select_merge: %{
repository: %{repo | user: user}
}
),
ticket_ref = %{
owner: ticket.repository.user.provider_login,
repo: ticket.repository.name,
number: ticket.number
},
{:ok, transaction} <-
Repo.fetch_one(
from tx in Transaction,
join: user in assoc(tx, :user),
where: tx.id == ^transafer_id,
select_merge: %{user: user}
) do
installation = Repo.get_by(Installation, provider_user_id: ticket.repository.user.id)
body = "🎉🎈 @#{transaction.user.provider_login} has been awarded **#{transaction.net_amount}**! 🎈🎊"

do_perform(ticket_ref, body, installation)
end
end

defp do_perform(ticket_ref, body, nil) do
Github.try_without_installation(&Github.create_issue_comment/5, [
ticket_ref.owner,
ticket_ref.repo,
ticket_ref.number,
body
])
end

defp do_perform(ticket_ref, body, installation) do
with {:ok, token} <- Github.get_installation_token(installation.provider_id) do
Github.create_issue_comment(token, ticket_ref.owner, ticket_ref.repo, ticket_ref.number, body)
end
end
end
84 changes: 84 additions & 0 deletions lib/algora/bounties/jobs/prompt_payout_connect.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
defmodule Algora.Bounties.Jobs.PromptPayoutConnect do
@moduledoc false
use Oban.Worker, queue: :prompt_payout_connect

import Ecto.Query

alias Algora.Bounties.Ticket
alias Algora.Github
alias Algora.Payments.Transaction
alias Algora.Repo
alias Algora.Workspace.Installation
alias Algora.Workspace.Ticket

require Logger

# TODO: confirm url
@onboarding_url "https://console.algora.io/solve"

@impl Oban.Worker
def perform(%Oban.Job{args: %{"credit_id" => credit_id}}) do
with {:ok, ticket} <-
Repo.fetch_one(
from t in Ticket,
left_join: bounty in assoc(t, :bounties),
left_join: tip in assoc(t, :tips),
left_join: tx in Transaction,
on: tx.bounty_id == bounty.id or tx.tip_id == tip.id,
join: repo in assoc(t, :repository),
join: user in assoc(repo, :user),
where: tx.id == ^credit_id,
select_merge: %{
repository: %{repo | user: user}
}
),
ticket_ref = %{
owner: ticket.repository.user.provider_login,
repo: ticket.repository.name,
number: ticket.number
},
{:ok, transaction} <-
Repo.fetch_one(
from tx in Transaction,
join: user in assoc(tx, :user),
left_join: linked_tx in Transaction,
on: linked_tx.id == tx.linked_transaction_id,
left_join: sender in assoc(linked_tx, :user),
where: tx.id == ^credit_id,
select_merge: %{
user: user,
linked_transaction: %{linked_tx | user: sender}
}
) do
installation = Repo.get_by(Installation, provider_user_id: ticket.repository.user.id)

reward_type =
cond do
transaction.tip_id -> "tip"
transaction.bounty_id -> "bounty"
transaction.contract_id -> "contract"
true -> raise "Unknown transaction type"
end

body =
"@#{transaction.user.provider_login}: You've been awarded a **#{transaction.net_amount}** #{reward_type} #{if transaction.linked_transaction, do: "by **#{transaction.linked_transaction.user.name}**", else: ""}! 👉 [Complete your Algora onboarding](#{@onboarding_url}) to collect the #{reward_type}."

do_perform(ticket_ref, body, installation)
end
end

defp do_perform(ticket_ref, body, nil) do
Github.try_without_installation(&Github.create_issue_comment/5, [
ticket_ref.owner,
ticket_ref.repo,
ticket_ref.number,
body
])
end

defp do_perform(ticket_ref, body, installation) do
with {:ok, token} <- Github.get_installation_token(installation.provider_id) do
Github.create_issue_comment(token, ticket_ref.owner, ticket_ref.repo, ticket_ref.number, body)
end
end
end
23 changes: 23 additions & 0 deletions lib/algora/integrations/github/github.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ defmodule Algora.Github do
@moduledoc false
@behaviour Algora.Github.Behaviour

require Logger

@type token :: String.t()

def client_id, do: Algora.config([:github, :client_id])
Expand Down Expand Up @@ -43,6 +45,27 @@ defmodule Algora.Github do

defp client, do: Application.get_env(:algora, :github_client, Algora.Github.Client)

def try_without_installation(function, args) do
if pat_enabled() do
apply(function, [pat() | args])
else
{_, module} = Function.info(function, :module)
{_, name} = Function.info(function, :name)
function_name = String.trim_leading("#{module}.#{name}", "Elixir.")

formatted_args =
Enum.map_join(args, ", ", fn
arg when is_binary(arg) -> "\"#{arg}\""
arg -> "#{arg}"
end)

Logger.warning("""
App installation not found and GITHUB_PAT_ENABLED is false, skipping Github call:
#{function_name}(#{formatted_args})
""")
end
end

@impl true
def get_repository(token, owner, repo), do: client().get_repository(token, owner, repo)

Expand Down
12 changes: 12 additions & 0 deletions lib/algora/integrations/stripe/stripe.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,16 @@ defmodule Algora.Stripe do

def create(params), do: Algora.Stripe.client(__MODULE__).create(params)
end

defmodule PaymentMethod do
@moduledoc false

def attach(params), do: Algora.Stripe.client(__MODULE__).attach(params)
end

defmodule SetupIntent do
@moduledoc false

def retrieve(id, params), do: Algora.Stripe.client(__MODULE__).retrieve(id, params)
end
end
6 changes: 3 additions & 3 deletions lib/algora/payments/jobs/execute_pending_transfers.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Algora.Payments.Jobs.ExecutePendingTransfers do
defmodule Algora.Payments.Jobs.ExecutePendingTransfer do
@moduledoc false
use Oban.Worker,
queue: :transfers,
Expand All @@ -7,7 +7,7 @@ defmodule Algora.Payments.Jobs.ExecutePendingTransfers do
alias Algora.Payments

@impl Oban.Worker
def perform(%Oban.Job{args: %{"user_id" => user_id}}) do
Payments.execute_pending_transfers(user_id)
def perform(%Oban.Job{args: %{"credit_id" => credit_id}}) do
Payments.execute_pending_transfer(credit_id)
end
end
Loading