@@ -121,6 +121,88 @@ defmodule Algora.Bounties do
121121 |> Oban . insert ( )
122122 end
123123
124+ @ spec do_claim_bounty ( % { user: User . t ( ) , ticket: Ticket . t ( ) , pull_request: map ( ) } ) ::
125+ { :ok , Claim . t ( ) } | { :error , atom ( ) }
126+ defp do_claim_bounty ( % { user: user , ticket: ticket , pull_request: pull_request } ) do
127+ # TODO: ensure user is pull request author
128+ id = Nanoid . generate ( )
129+
130+ changeset =
131+ Claim . changeset ( % Claim { } , % {
132+ ticket_id: ticket . id ,
133+ user_id: user . id ,
134+ provider: "github" ,
135+ provider_id: pull_request [ "id" ] ,
136+ provider_meta: pull_request ,
137+ title: pull_request [ "title" ] ,
138+ url: pull_request [ "html_url" ] ,
139+ group_id: id ,
140+ merged_at: Util . to_date ( pull_request [ "merged_at" ] )
141+ } )
142+
143+ case Repo . insert ( changeset ) do
144+ { :ok , claim } ->
145+ { :ok , claim }
146+
147+ { :error , % { errors: [ ticket_id: { _ , [ constraint: :unique , constraint_name: _ ] } ] } } ->
148+ { :error , :already_exists }
149+
150+ { :error , _changeset } ->
151+ { :error , :internal_server_error }
152+ end
153+ end
154+
155+ @ spec claim_bounty (
156+ % {
157+ user: User . t ( ) ,
158+ ticket_ref: % { owner: String . t ( ) , repo: String . t ( ) , number: integer ( ) } ,
159+ pull_request: map ( )
160+ } ,
161+ opts :: [ installation_id: integer ( ) ]
162+ ) ::
163+ { :ok , Bounty . t ( ) } | { :error , atom ( ) }
164+ def claim_bounty (
165+ % {
166+ user: user ,
167+ ticket_ref: % { owner: repo_owner , repo: repo_name , number: number } = ticket_ref ,
168+ pull_request: pull_request
169+ } ,
170+ opts \\ [ ]
171+ ) do
172+ installation_id = opts [ :installation_id ]
173+
174+ token_res =
175+ if installation_id ,
176+ do: Github . get_installation_token ( installation_id ) ,
177+ else: Accounts . get_access_token ( user )
178+
179+ Repo . transact ( fn ->
180+ with { :ok , token } <- token_res ,
181+ { :ok , ticket } <- Workspace . ensure_ticket ( token , repo_owner , repo_name , number ) ,
182+ { :ok , claim } <- do_claim_bounty ( % { user: user , ticket: ticket , pull_request: pull_request } ) ,
183+ { :ok , _job } <- notify_claim ( % { ticket_ref: ticket_ref } , installation_id: installation_id ) do
184+ broadcast ( )
185+ { :ok , claim }
186+ else
187+ { :error , _reason } = error -> error
188+ end
189+ end )
190+ end
191+
192+ @ spec notify_claim (
193+ % { ticket_ref: % { owner: String . t ( ) , repo: String . t ( ) , number: integer ( ) } } ,
194+ opts :: [ installation_id: integer ( ) ]
195+ ) ::
196+ { :ok , Oban.Job . t ( ) } | { :error , atom ( ) }
197+ def notify_claim ( % { ticket_ref: ticket_ref } , opts \\ [ ] ) do
198+ % {
199+ ticket_ref: % { owner: ticket_ref . owner , repo: ticket_ref . repo , number: ticket_ref . number } ,
200+ installation_id: opts [ :installation_id ]
201+ }
202+ |> Jobs.NotifyClaim . new ( )
203+ |> Oban . insert ( )
204+ end
205+
124206 @ spec create_tip_intent (
125207 % {
126208 recipient: String . t ( ) ,
0 commit comments