Skip to content

Commit 15840c9

Browse files
committed
iterate
- Trying to fetch directly from the API is too dangerous at this point, since the API is blocked - I've chosen to iterate on a GraphQL subtitles upload API - Trying the GraphQL mutation with Absinthe, I got a "No query document supplied" error - ```gql mutation SetVideoCaptions($captions: Upload!) { setVideoCaptions(videoId: 1, captions: $captions) { captions { text } } } ``` - Decided to upgrade Absinthe to see how that goes - [absinthe_ecto](https://github.com/absinthe-graphql/absinthe_ecto) is deprecated, so I'm looking to move to [dataloader](https://github.com/absinthe-graphql/dataloader) - Updated the dependencies, now looking to migrate the actual `assoc` calls
1 parent 5d8b0c5 commit 15840c9

27 files changed

+158
-116
lines changed

apps/cf/lib/videos/captions_fetcher_youtube.ex

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -69,30 +69,7 @@ defmodule CF.Videos.CaptionsFetcherYoutube do
6969
end
7070

7171
defp process_transcript(transcript) do
72-
transcript
73-
|> SweetXml.xpath(
74-
~x"//transcript/text"l,
75-
text: ~x"./text()"s |> transform_by(&clean_text/1),
76-
start: ~x"./@start"s |> transform_by(&parse_float/1),
77-
duration: ~x"./@dur"os |> transform_by(&parse_float/1)
78-
)
79-
|> Enum.filter(fn %{text: text, start: start} ->
80-
start != nil and text != nil and text != ""
81-
end)
82-
end
83-
84-
defp clean_text(text) do
85-
text
86-
|> String.replace("&", "&")
87-
|> HtmlEntities.decode()
88-
|> String.trim()
89-
end
90-
91-
defp parse_float(val) do
92-
case Float.parse(val) do
93-
{num, _} -> num
94-
_ -> nil
95-
end
72+
CF.Videos.CaptionsSrv2Parser.parse_file(transcript)
9673
end
9774

9875
# Below is an implementation using the official YouTube API, but it requires OAuth2 authentication.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
defmodule CF.Videos.CaptionsSrv2Parser do
2+
@moduledoc """
3+
A captions parser for the srv2 format.
4+
"""
5+
6+
require Logger
7+
import SweetXml
8+
9+
def parse_file(content) do
10+
content
11+
|> SweetXml.xpath(
12+
~x"//transcript/text"l,
13+
text: ~x"./text()"s |> transform_by(&clean_text/1),
14+
start: ~x"./@start"s |> transform_by(&parse_float/1),
15+
duration: ~x"./@dur"os |> transform_by(&parse_float/1)
16+
)
17+
|> Enum.filter(fn %{text: text, start: start} ->
18+
start != nil and text != nil and text != ""
19+
end)
20+
end
21+
22+
defp clean_text(text) do
23+
text
24+
|> String.replace("&", "&")
25+
|> HtmlEntities.decode()
26+
|> String.trim()
27+
end
28+
29+
defp parse_float(val) do
30+
case Float.parse(val) do
31+
{num, _} -> num
32+
_ -> nil
33+
end
34+
end
35+
end

apps/cf_graphql/lib/resolvers/videos.ex

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -115,31 +115,47 @@ defmodule CF.Graphql.Resolvers.Videos do
115115
{:ok, video}
116116
end
117117

118-
def set_captions(_root, %{video_id: video_id, captions: captions_input}, %{
119-
context: %{user: user}
120-
}) do
121-
video = DB.Repo.get!(DB.Schema.Video, video_id)
122-
123-
Multi.new()
124-
|> Multi.insert(
125-
:caption,
126-
VideoCaption.changeset(%VideoCaption{
127-
video_id: video.id,
128-
raw: captions_input,
129-
parsed: captions_input,
130-
format: "user-provided"
131-
})
132-
)
133-
|> Multi.run(
134-
:action,
135-
fn _repo, %{caption: caption} ->
136-
CF.Actions.ActionCreator.action_upload_video_captions(user.id, video.id, caption)
137-
|> DB.Repo.insert!()
138-
139-
{:ok, caption}
140-
end
141-
)
142-
143-
{:ok, video}
118+
def set_captions(
119+
_root,
120+
%{video_id: video_id, captions: %{path: path, content_type: content_type}},
121+
%{
122+
context: %{user: user}
123+
}
124+
) do
125+
cond do
126+
content_type != "text/xml" ->
127+
{:error, "Unsupported content type: #{content_type}"}
128+
129+
File.stat!(path).size > 10_000_000 ->
130+
{:error, "File must be < 10MB"}
131+
132+
true ->
133+
video = DB.Repo.get!(DB.Schema.Video, video_id)
134+
captions_file_content = File.read!(path)
135+
parsed = CF.Videos.CaptionsSrv2Parser.parse_file(captions_file_content)
136+
137+
Multi.new()
138+
|> Multi.insert(
139+
:caption,
140+
VideoCaption.changeset(%VideoCaption{
141+
video_id: video.id,
142+
raw: captions_file_content,
143+
parsed: parsed,
144+
format: "xml"
145+
})
146+
)
147+
|> Multi.run(
148+
:action,
149+
fn _repo, %{caption: caption} ->
150+
CF.Actions.ActionCreator.action_upload_video_captions(user.id, video.id, caption)
151+
|> DB.Repo.insert!()
152+
153+
{:ok, caption}
154+
end
155+
)
156+
|> DB.Repo.transaction()
157+
158+
{:ok, video}
159+
end
144160
end
145161
end

apps/cf_graphql/lib/schema/input_objects.ex

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ defmodule CF.Graphql.Schema.InputObjects do
33

44
import_types(CF.Graphql.Schema.InputObjects.{
55
VideoFilter,
6-
StatementFilter,
7-
VideoCaption
6+
StatementFilter
87
})
98
end

apps/cf_graphql/lib/schema/input_objects/statement_filter.ex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ defmodule CF.Graphql.Schema.InputObjects.StatementFilter do
44
"""
55

66
use Absinthe.Schema.Notation
7-
use Absinthe.Ecto, repo: DB.Repo
87

98
@desc "Props to filter statements on"
109
input_object :statement_filter do

apps/cf_graphql/lib/schema/input_objects/video_caption.ex

Lines changed: 0 additions & 10 deletions
This file was deleted.

apps/cf_graphql/lib/schema/input_objects/video_filter.ex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ defmodule CF.Graphql.Schema.InputObjects.VideoFilter do
44
"""
55

66
use Absinthe.Schema.Notation
7-
use Absinthe.Ecto, repo: DB.Repo
87

98
@desc "Props to filter videos on"
109
input_object :video_filter do

apps/cf_graphql/lib/schema/schema.ex

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,24 @@ defmodule CF.Graphql.Schema do
22
use Absinthe.Schema
33
alias CF.Graphql.Resolvers
44
alias CF.Graphql.Schema.Middleware
5+
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
56

7+
import_types(Absinthe.Plug.Types)
68
import_types(CF.Graphql.Schema.Types)
79
import_types(CF.Graphql.Schema.InputObjects)
810

11+
def context(ctx) do
12+
loader =
13+
Dataloader.new()
14+
|> Dataloader.add_source(DB.Repo, Dataloader.Ecto.new(DB.Repo))
15+
16+
Map.put(ctx, :loader, loader)
17+
end
18+
19+
def plugins do
20+
[Absinthe.Middleware.Dataloader | Absinthe.Plugin.defaults()]
21+
end
22+
923
# Query API
1024

1125
query do
@@ -105,7 +119,7 @@ defmodule CF.Graphql.Schema do
105119
middleware(Middleware.RequireReputation, 450)
106120

107121
arg(:video_id, non_null(:id))
108-
arg(:captions, non_null(list_of(:video_caption_input)))
122+
arg(:captions, non_null(:upload))
109123

110124
resolve(&Resolvers.Videos.set_captions/3)
111125
end

apps/cf_graphql/lib/schema/types/app_info.ex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ defmodule CF.Graphql.Schema.Types.AppInfo do
44
"""
55

66
use Absinthe.Schema.Notation
7-
use Absinthe.Ecto, repo: DB.Repo
87

98
@desc "Information about the application"
109
object :app_info do

apps/cf_graphql/lib/schema/types/comment.ex

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ defmodule CF.Graphql.Schema.Types.Comment do
44
"""
55

66
use Absinthe.Schema.Notation
7-
use Absinthe.Ecto, repo: DB.Repo
7+
8+
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
89
import CF.Graphql.Schema.Utils
910
alias CF.Graphql.Resolvers
1011

@@ -13,7 +14,7 @@ defmodule CF.Graphql.Schema.Types.Comment do
1314
field(:id, non_null(:id))
1415
@desc "User who made the comment"
1516
field :user, :user do
16-
resolve(assoc(:user))
17+
resolve(dataloader(DB.Repo))
1718
complexity(join_complexity())
1819
end
1920

@@ -31,7 +32,7 @@ defmodule CF.Graphql.Schema.Types.Comment do
3132

3233
@desc "Source of the scomment. If null, a text must be set"
3334
field :source, :source do
34-
resolve(assoc(:source))
35+
resolve(dataloader(DB.Repo))
3536
complexity(join_complexity())
3637
end
3738

0 commit comments

Comments
 (0)