fix create_thumbnail automation
This commit is contained in:
parent
4cf90d78a9
commit
db0222ff94
|
@ -12,9 +12,16 @@ defmodule Bright.B2 do
|
||||||
|
|
||||||
alias Bright.B2
|
alias Bright.B2
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Put a file from local disk to Backblaze. This function uses the filename as the S3 key. Use put/2 if you want to specify the key
|
||||||
|
"""
|
||||||
|
def put(local_file) do
|
||||||
|
object_key = Path.basename(local_file)
|
||||||
|
put(local_file, object_key)
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Put a file from local disk to Backblaze
|
Put a file from local disk to Backblaze.
|
||||||
"""
|
"""
|
||||||
def put(local_file, object_key) do
|
def put(local_file, object_key) do
|
||||||
|
|
||||||
|
@ -23,13 +30,19 @@ defmodule Bright.B2 do
|
||||||
raise("bucket specification is missing")
|
raise("bucket specification is missing")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
s3_cdn_endpoint = Application.get_env(:bright, :s3_cdn_endpoint)
|
||||||
|
if s3_cdn_endpoint === nil do
|
||||||
|
raise("s3_cdn_endpoint specification is missing")
|
||||||
|
end
|
||||||
|
cdn_url = "#{s3_cdn_endpoint}/#{object_key}"
|
||||||
|
|
||||||
|
|
||||||
local_file
|
local_file
|
||||||
|> S3.Upload.stream_file
|
|> S3.Upload.stream_file
|
||||||
|> S3.upload(bucket, object_key)
|
|> S3.upload(bucket, object_key)
|
||||||
|> ExAws.request
|
|> ExAws.request
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, %{status_code: 200}} -> {:ok, object_key}
|
{:ok, %{status_code: 200}} -> {:ok, %{key: object_key, cdn_url: cdn_url}}
|
||||||
{:error, reason} -> {:error, reason}
|
{:error, reason} -> {:error, reason}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -56,17 +69,19 @@ defmodule Bright.B2 do
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Given a S3 object_key, generate an appropriate CDN url.
|
||||||
|
"""
|
||||||
|
def generate_cdn_url(object_key) do
|
||||||
|
cdn_url = Application.get_env(:bright, :public_s3_endpoint) || raise(":public_s3_endpoint missing from App env")
|
||||||
|
"#{cdn_url}/#{object_key}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# defp upload_to_s3(body, key) do
|
|
||||||
# body
|
|
||||||
# |> S3.upload(@bucket_name, key)
|
|
||||||
# |> ExAws.request()
|
|
||||||
# |> case do
|
|
||||||
# {:ok, _response} -> :ok
|
|
||||||
# {:error, reason} -> {:error, reason}
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,16 +6,38 @@ defmodule Bright.Cache do
|
||||||
alias Bright.Streams.Vod
|
alias Bright.Streams.Vod
|
||||||
|
|
||||||
|
|
||||||
@cache_dir "/tmp/bright_cache"
|
@cache_dir Path.join(System.user_home!(), ".cache/futureporn")
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
def generate_filename(input) do
|
def generate_basename(input) do
|
||||||
prefix = :crypto.strong_rand_bytes(6) |> Base.encode64(padding: false) |> String.replace(~r/[^a-zA-Z0-9]/, "")
|
prefix = :crypto.strong_rand_bytes(6) |> Base.encode64(padding: false) |> String.replace(~r/[^a-zA-Z0-9]/, "")
|
||||||
base = Path.basename(input)
|
base = Path.basename(input)
|
||||||
"#{prefix}-#{base}"
|
"#{prefix}-#{base}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generate_basename(input, ext) do
|
||||||
|
input
|
||||||
|
|> generate_basename
|
||||||
|
|> Path.rootname
|
||||||
|
|> Kernel.<>(".#{ext}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_filename(input) do
|
||||||
|
Path.join(@cache_dir, generate_basename(input))
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_filename(input, ext) do
|
||||||
|
Path.join(@cache_dir, generate_basename(input, ext))
|
||||||
|
|
||||||
|
# @cache_dir
|
||||||
|
# input
|
||||||
|
# |> generate_basename
|
||||||
|
# |> Path.join(@cache_dir)
|
||||||
|
# |> Path.rootname
|
||||||
|
# |> Kernel.<>(".#{ext}")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# Ensure the cache directory exists
|
# Ensure the cache directory exists
|
||||||
defp ensure_cache_dir! do
|
defp ensure_cache_dir! do
|
||||||
|
@ -24,98 +46,9 @@ defmodule Bright.Cache do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
|
||||||
Save data to the cache with a given key.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
iex> Bright.Cache.put("example_key", "example_data")
|
|
||||||
:ok
|
|
||||||
"""
|
|
||||||
def put(key, data) do
|
|
||||||
|
|
||||||
ensure_cache_dir!()
|
|
||||||
|
|
||||||
file_path = cache_file_path(key)
|
|
||||||
|
|
||||||
case File.write(file_path, data) do
|
|
||||||
:ok ->
|
|
||||||
Logger.debug("[Cache] Saved key #{key} to #{file_path}")
|
|
||||||
:ok
|
|
||||||
|
|
||||||
{:error, reason} ->
|
|
||||||
Logger.error("[Cache] Failed to save key #{key}: #{reason}")
|
|
||||||
{:error, reason}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Save a VOD file to the cache using its origin_temp_input_url.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
iex> Bright.Cache.put(%Vod{key: "vod_key", origin_temp_input_url: "http://example.com/video.mp4"})
|
|
||||||
:ok
|
|
||||||
"""
|
|
||||||
def put(%Vod{origin_temp_input_url: url}) do
|
|
||||||
ensure_cache_dir!()
|
|
||||||
|
|
||||||
key = generate_filename(url)
|
|
||||||
file_path = cache_file_path(key)
|
|
||||||
|
|
||||||
case HTTPoison.get(url) do
|
|
||||||
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
|
|
||||||
case File.write(file_path, body) do
|
|
||||||
:ok ->
|
|
||||||
Logger.debug("[Cache] Downloaded and saved VOD #{key} from #{url} to #{file_path}")
|
|
||||||
:ok
|
|
||||||
|
|
||||||
{:error, reason} ->
|
|
||||||
Logger.error("[Cache] Failed to save VOD #{key}: #{reason}")
|
|
||||||
{:error, reason}
|
|
||||||
end
|
|
||||||
|
|
||||||
{:ok, %HTTPoison.Response{status_code: status}} ->
|
|
||||||
Logger.error("[Cache] Failed to download VOD #{key}: HTTP #{status}")
|
|
||||||
{:error, :http_error}
|
|
||||||
|
|
||||||
{:error, %HTTPoison.Error{reason: reason}} ->
|
|
||||||
Logger.error("[Cache] Failed to download VOD #{key}: #{reason}")
|
|
||||||
{:error, reason}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Retrieve data from the cache for a given key.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
iex> Bright.Cache.get("example_key")
|
|
||||||
{:ok, "example_data"}
|
|
||||||
|
|
||||||
iex> Bright.Cache.get("nonexistent_key")
|
|
||||||
:error
|
|
||||||
"""
|
|
||||||
def get(key) do
|
|
||||||
ensure_cache_dir!()
|
|
||||||
|
|
||||||
file_path = cache_file_path(key)
|
|
||||||
|
|
||||||
case File.read(file_path) do
|
|
||||||
{:ok, data} ->
|
|
||||||
Logger.debug("[Cache] Retrieved key #{key} from #{file_path}")
|
|
||||||
{:ok, data}
|
|
||||||
|
|
||||||
{:error, :enoent} ->
|
|
||||||
Logger.debug("[Cache] Key #{key} not found in cache")
|
|
||||||
:error
|
|
||||||
|
|
||||||
{:error, reason} ->
|
|
||||||
Logger.error("[Cache] Failed to retrieve key #{key}: #{reason}")
|
|
||||||
{:error, reason}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Delete a cached item by its key.
|
Delete a cached item by its key.
|
||||||
|
@ -131,7 +64,7 @@ defmodule Bright.Cache do
|
||||||
def delete(key) do
|
def delete(key) do
|
||||||
ensure_cache_dir!()
|
ensure_cache_dir!()
|
||||||
|
|
||||||
file_path = cache_file_path(key)
|
file_path = generate_filename(key)
|
||||||
|
|
||||||
case File.rm(file_path) do
|
case File.rm(file_path) do
|
||||||
:ok ->
|
:ok ->
|
||||||
|
@ -171,8 +104,5 @@ defmodule Bright.Cache do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Helper function to generate the file path for a given key
|
|
||||||
defp cache_file_path(key) do
|
|
||||||
Path.join(@cache_dir, key)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule Bright.Downloader do
|
||||||
|
@moduledoc """
|
||||||
|
Downloader functions
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get(url) do
|
||||||
|
|
||||||
|
local_file = Bright.Cache.generate_filename(url)
|
||||||
|
headers = %{}
|
||||||
|
case HTTPoison.get(url, headers) do
|
||||||
|
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
|
||||||
|
case File.write(local_file, body) do
|
||||||
|
:ok -> {:ok, local_file}
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, %HTTPoison.Response{status_code: status, body: body}} ->
|
||||||
|
{:error, %{status: status, body: body}}
|
||||||
|
|
||||||
|
{:error, %HTTPoison.Error{reason: reason}} ->
|
||||||
|
{:error, reason}
|
||||||
|
|
||||||
|
failed ->
|
||||||
|
Logger.error("Failed to GET #{url}")
|
||||||
|
{:error, :failed}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -6,7 +6,7 @@ defmodule Bright.Images do
|
||||||
import FFmpex
|
import FFmpex
|
||||||
use FFmpex.Options
|
use FFmpex.Options
|
||||||
require Logger
|
require Logger
|
||||||
|
alias Bright.Cache
|
||||||
|
|
||||||
def get_video_duration(file_path) do
|
def get_video_duration(file_path) do
|
||||||
case FFprobe.streams(file_path) do
|
case FFprobe.streams(file_path) do
|
||||||
|
@ -56,9 +56,7 @@ defmodule Bright.Images do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp gen_thumb(input_file, output_file) do
|
||||||
def create_thumbnail(input_file, output_file) do
|
|
||||||
|
|
||||||
case get_video_framecount(input_file) do
|
case get_video_framecount(input_file) do
|
||||||
{:error, reason} -> {:error, reason}
|
{:error, reason} -> {:error, reason}
|
||||||
{:ok, framecount} ->
|
{:ok, framecount} ->
|
||||||
|
@ -75,14 +73,33 @@ defmodule Bright.Images do
|
||||||
|> add_output_file(output_file)
|
|> add_output_file(output_file)
|
||||||
|> add_file_option(option_vframes(1))
|
|> add_file_option(option_vframes(1))
|
||||||
|> add_file_option(option_vf("select=not(mod(n\\,#{frame_interval})),scale=#{scale_width}:-1,tile=#{tile_grid}"))
|
|> add_file_option(option_vf("select=not(mod(n\\,#{frame_interval})),scale=#{scale_width}:-1,tile=#{tile_grid}"))
|
||||||
|> add_file_option(option_vsync(1)) # -vsync is deprecated in ffmpeg but ffmpex doesn't have the modern replacement, -fps_mode
|
|> add_file_option(option_vsync(0)) # -vsync is deprecated in ffmpeg but ffmpex doesn't have the modern replacement, -fps_mode
|
||||||
# |> add_file_option(option_update(1)) # ffmpeg complains but it doesn't necessarily need this. I'm omitting because ffmpex doesn't know this function
|
# |> add_file_option(option_update(1)) # ffmpeg complains but it doesn't necessarily need this. I'm omitting because ffmpex doesn't know this function
|
||||||
# |> add_file_option(option_fps_mode("passthrough")) # -fps_mode is the modern replacement for -vsync
|
# |> add_file_option(option_fps_mode("passthrough")) # -fps_mode is the modern replacement for -vsync
|
||||||
|
|
||||||
execute(command)
|
|
||||||
|
Logger.info("generating thumbnail...")
|
||||||
|
IO.puts "generating thumbnail with input_file=#{input_file} output_file=#{output_file}"
|
||||||
|
case execute(command) do
|
||||||
|
{:ok, output} ->
|
||||||
|
{:ok, %{output: output, filename: output_file}}
|
||||||
|
{:error, reason} ->
|
||||||
|
Logger.error("Error generating thumbnail: #{inspect(reason)}")
|
||||||
|
{:error, reason}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_thumbnail(input_file) do
|
||||||
|
output_file = Cache.generate_filename(input_file, "png")
|
||||||
|
IO.puts "creating_thumbnail from #{input_file} and saving it to #{output_file}"
|
||||||
|
gen_thumb(input_file, output_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_thumbnail(input_file, output_file) do
|
||||||
|
gen_thumb(input_file, output_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,47 +1,48 @@
|
||||||
defmodule Bright.ObanWorkers.CreateS3Asset do
|
defmodule Bright.ObanWorkers.CreateS3Asset do
|
||||||
use Oban.Worker, queue: :default, max_attempts: 3
|
use Oban.Worker, queue: :default, max_attempts: 3
|
||||||
|
|
||||||
alias ExAws.S3
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@bucket_name System.get_env("AWS_BUCKET")
|
alias ExAws.S3
|
||||||
|
alias Bright.Cache
|
||||||
|
alias Bright.Downloader
|
||||||
|
alias Bright.B2
|
||||||
|
alias Bright.Repo
|
||||||
|
|
||||||
|
|
||||||
@impl Oban.Worker
|
@impl Oban.Worker
|
||||||
def perform(%Oban.Job{args: %{"input_url" => input_url, "vod_id" => vod_id}}) do
|
def perform(%Oban.Job{args: %{"input_url" => input_url, "vod_id" => vod_id}}) do
|
||||||
Logger.info("@todo implementation needed")
|
|
||||||
# random_string = for _ <- 1..12, into: "", do: <<Enum.random(~c"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")>>
|
Logger.info("CreateS3Asset begin.")
|
||||||
# output_file = "/tmp/#{random_string}-#{key}"
|
vod = Repo.get!(Vod, vod_id)
|
||||||
# with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- fetch_file(input_url),
|
basename = Cache.generate_basename(input_url)
|
||||||
# {:ok, local_path} <- save_file(body, key),
|
|
||||||
# :ok <- upload_to_s3(local_path, key) do
|
with {:ok, local_file} <- Downloader.get(input_url),
|
||||||
# :ok
|
{:ok, object_key} <- B2.put(local_file, basename) do
|
||||||
# else
|
update_vod_with_s3_asset(vod, object_key)
|
||||||
# {:error, reason} ->
|
|
||||||
# Logger.error("Failed to process job: #{inspect(reason)}")
|
else
|
||||||
# {:error, reason}
|
{:error, reason} ->
|
||||||
# end
|
Logger.error("Failed to create S3 Asset for VOD ID #{vod_id}: #{inspect(reason)}")
|
||||||
|
{:error, reason}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# defp fetch_file(url) do
|
defp update_vod_with_s3_asset(vod, object_key) do
|
||||||
# case HTTPoison.get(url, [], stream_to: self()) do
|
basename = Path.basename(vod.thumbnail_url)
|
||||||
# {:ok, response} when response.status_code in 200..299 ->
|
s3_cdn_url = B2.generate_cdn_url(object_key)
|
||||||
# {:ok, response}
|
|
||||||
|
|
||||||
# {:ok, %HTTPoison.Response{status_code: status}} ->
|
vod
|
||||||
# {:error, "HTTP request failed with status: #{status}"}
|
|> Ecto.Changeset.change(s3_cdn_url: s3_cdn_url)
|
||||||
|
|> Repo.update!()
|
||||||
|
end
|
||||||
|
|
||||||
# {:error, %HTTPoison.Error{reason: reason}} ->
|
# defp update_vod_with_playlist_url(vod, asset_id) do
|
||||||
# {:error, reason}
|
# playlist_url = generate_playlist_url(asset_id)
|
||||||
# end
|
# Logger.info("playlist_url=#{playlist_url}")
|
||||||
|
# vod
|
||||||
|
# |> Ecto.Changeset.change(playlist_url: playlist_url)
|
||||||
|
# |> Repo.update!()
|
||||||
# end
|
# end
|
||||||
|
|
||||||
# defp upload_to_s3(body, key) do
|
|
||||||
# body
|
|
||||||
# |> S3.upload(@bucket_name, key)
|
|
||||||
# |> ExAws.request()
|
|
||||||
# |> case do
|
|
||||||
# {:ok, _response} -> :ok
|
|
||||||
# {:error, reason} -> {:error, reason}
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,46 +1,60 @@
|
||||||
defmodule Bright.ObanWorkers.CreateThumbnail do
|
defmodule Bright.ObanWorkers.CreateThumbnail do
|
||||||
use Oban.Worker, queue: :default, max_attempts: 3
|
use Oban.Worker, queue: :default, max_attempts: 3
|
||||||
|
|
||||||
alias Bright.Cache
|
|
||||||
alias Bright.Images
|
|
||||||
alias Bright.B2
|
|
||||||
alias Bright.Streams.Vod
|
alias Bright.Streams.Vod
|
||||||
|
alias Bright.{
|
||||||
|
Repo,
|
||||||
|
Downloader,
|
||||||
|
B2,
|
||||||
|
Images,
|
||||||
|
Cache
|
||||||
|
}
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@impl Oban.Worker
|
@impl Oban.Worker
|
||||||
def perform(%Oban.Job{args: %{"vod_id" => vod_id, "origin_temp_input_url" => origin_temp_input_url}}) do
|
def perform(%Oban.Job{args: %{"vod_id" => vod_id}}) do
|
||||||
|
Logger.info(">>>> CreateThumbnail is performing. with vod_id=#{vod_id}")
|
||||||
|
|
||||||
IO.puts ">>>> CreateThumbnail is performing. with vod_id=#{vod_id}"
|
case Repo.get(Vod, vod_id) do
|
||||||
vod = Repo.get!(Vod, vod_id)
|
nil ->
|
||||||
|
Logger.error("VOD ID #{vod_id} not found")
|
||||||
|
{:error, "VOD not found"}
|
||||||
|
|
||||||
with {:ok, cache_filename} <- Cache.put(origin_temp_input_url),
|
%Vod{origin_temp_input_url: origin_temp_input_url} = vod ->
|
||||||
{:ok, thumb_filename} <- Images.create_thumbnail(cache_filename),
|
with {:ok, local_filename} <- Downloader.get(origin_temp_input_url),
|
||||||
{:ok, s3Asset} <- B2.put(thumb_filename) do
|
{:ok, %{output: output, filename: output_file}} <- Images.create_thumbnail(local_filename),
|
||||||
update_vod_with_thumbnail_url(vod, s3Asset.cdn_url)
|
{:ok, s3Asset} <- B2.put(output_file)
|
||||||
else
|
do
|
||||||
{:error, reason} ->
|
IO.puts("updating vod ...")
|
||||||
Logger.error("Failed to create HLS playlist for VOD ID #{vod_id}: #{inspect(reason)}")
|
update_vod_with_thumbnail_url(vod, s3Asset.cdn_url)
|
||||||
{:error, reason}
|
else
|
||||||
|
{:error, reason} ->
|
||||||
|
Logger.error("Failed to create thumbnail for VOD ID #{vod_id}: #{inspect(reason)}")
|
||||||
|
{:error, reason}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# vod
|
|
||||||
# |> Cache.put
|
|
||||||
# |> Images.create_thumbnail
|
|
||||||
# |> B2.put
|
|
||||||
|
|
||||||
defp generate_thumbnail_url(basename), do: "#{@public_s3_endpoint}/#{basename}"
|
defp generate_thumbnail_url(basename), do: "#{@public_s3_endpoint}/#{basename}"
|
||||||
|
|
||||||
|
# defp update_vod_with_thumbnail_url(vod, thumbnail_url) do
|
||||||
|
# IO.puts "thumbnail_url=#{thumbnail_url}"
|
||||||
|
# vod
|
||||||
|
# |> Ecto.Changeset.change(thumbnail_url: thumbnail_url)
|
||||||
|
# |> Repo.update!()
|
||||||
|
|
||||||
|
# end
|
||||||
|
|
||||||
defp update_vod_with_thumbnail_url(vod, thumbnail_url) do
|
defp update_vod_with_thumbnail_url(vod, thumbnail_url) do
|
||||||
basename = Path.basename(thumbnail_url)
|
IO.puts "thumbnail_url=#{thumbnail_url}"
|
||||||
thumbnail_url = generate_thumbnail_url(basename)
|
case Repo.update(vod |> Ecto.Changeset.change(thumbnail_url: thumbnail_url)) do
|
||||||
Logger.info("thumbnail_url=#{thumbnail_url}")
|
{:ok, updated_vod} -> {:ok, updated_vod}
|
||||||
vod
|
{:error, changeset} -> {:error, changeset}
|
||||||
|> Ecto.Changeset.change(thumbnail_url: thumbnail_url)
|
end
|
||||||
|> Repo.update!()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,22 +12,16 @@ defmodule Bright.ObanWorkers.ProcessVod do
|
||||||
}
|
}
|
||||||
|
|
||||||
@impl Oban.Worker
|
@impl Oban.Worker
|
||||||
def perform(%Oban.Job{args: %{"id" => id}} = job) do
|
def perform(%Oban.Job{args: %{"vod_id" => vod_id}}) do
|
||||||
Logger.info("Performing job: #{inspect(job)}")
|
|
||||||
|
|
||||||
|
|
||||||
vod = Repo.get!(Vod, id)
|
vod = Repo.get!(Vod, vod_id)
|
||||||
|
|
||||||
if vod.playlist_url == nil and vod.origin_temp_input_url != nil do
|
|
||||||
queue_create_hls_playlist(vod)
|
|
||||||
end
|
|
||||||
|
|
||||||
if vod.s3_key == nil do
|
if vod.origin_temp_input_url do
|
||||||
queue_create_s3_asset(vod)
|
unless vod.playlist_url, do: queue_create_hls_playlist(vod)
|
||||||
end
|
unless vod.s3_cdn_url, do: queue_create_s3_asset(vod)
|
||||||
|
unless vod.thumbnail_url, do: queue_create_thumbnail(vod)
|
||||||
if vod.thumbnail_url == nil and vod.origin_temp_input_url != nil do
|
|
||||||
queue_create_thumbnail(vod)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +40,7 @@ defmodule Bright.ObanWorkers.ProcessVod do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp queue_create_thumbnail(%Vod{id: id, origin_temp_input_url: url}) do
|
defp queue_create_thumbnail(%Vod{id: id, origin_temp_input_url: url}) do
|
||||||
job_args = %{vod_id: id}
|
job_args = %{vod_id: id, input_url: url}
|
||||||
Oban.insert!(CreateThumbnail.new(job_args))
|
Oban.insert!(CreateThumbnail.new(job_args))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -123,12 +123,6 @@ defmodule Bright.Streams do
|
||||||
|> Ecto.Changeset.put_assoc(:platforms, platforms)
|
|> Ecto.Changeset.put_assoc(:platforms, platforms)
|
||||||
end
|
end
|
||||||
|
|
||||||
def inc_page_views(%Stream{} = stream) do
|
|
||||||
{1, [%Stream{views: views}]} =
|
|
||||||
from(s in Stream, where: s.id == ^stream.id, select: [:views])
|
|
||||||
|> Repo.update_all(inc: [views: 1])
|
|
||||||
put_in(stream.views, views)
|
|
||||||
end
|
|
||||||
|
|
||||||
def list_tags_by_id(nil), do: []
|
def list_tags_by_id(nil), do: []
|
||||||
def list_tags_by_id(tag_ids) do
|
def list_tags_by_id(tag_ids) do
|
||||||
|
@ -198,8 +192,8 @@ defmodule Bright.Streams do
|
||||||
|> Vod.changeset(attrs)
|
|> Vod.changeset(attrs)
|
||||||
|> Repo.insert()
|
|> Repo.insert()
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, vod} ->
|
{:ok, %Vod{} = vod} ->
|
||||||
maybe_enqueue_process_vod(vod)
|
Oban.insert!(Bright.ObanWorkers.ProcessVod.new(%{vod_id: vod.id}))
|
||||||
{:ok, vod}
|
{:ok, vod}
|
||||||
|
|
||||||
{:error, changeset} ->
|
{:error, changeset} ->
|
||||||
|
@ -207,22 +201,28 @@ defmodule Bright.Streams do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_tag(attrs \\ %{}) do
|
||||||
defp maybe_enqueue_process_vod(%Vod{id: id, origin_temp_input_url: origin_temp_input_url} = vod) do
|
%Tag{}
|
||||||
|
|> Tag.changeset(attrs)
|
||||||
|
|> Repo.insert()
|
||||||
|
|
||||||
if origin_temp_input_url do
|
|
||||||
|
|
||||||
|
|
||||||
%{id: id, origin_temp_input_url: origin_temp_input_url}
|
|
||||||
|> Bright.ObanWorkers.ProcessVod.new()
|
|
||||||
|> Oban.insert()
|
|
||||||
|
|
||||||
end
|
|
||||||
vod
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# def create_stream(attrs \\ %{}) do
|
||||||
|
# %Stream{}
|
||||||
|
# # |> Stream.changeset(attrs)
|
||||||
|
# |> change_stream(attrs)
|
||||||
|
# |> Repo.insert()
|
||||||
|
# end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# defp enqueue_process_vod(%Vod{id: id} = vod) do
|
||||||
|
# %{vod_id: id}
|
||||||
|
# |> Bright.ObanWorkers.ProcessVod.new()
|
||||||
|
# |> Oban.insert()
|
||||||
|
# vod
|
||||||
|
# end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
|
@ -9,7 +9,6 @@ defmodule Bright.Streams.Stream do
|
||||||
field :date, :utc_datetime
|
field :date, :utc_datetime
|
||||||
field :title, :string
|
field :title, :string
|
||||||
field :notes, :string
|
field :notes, :string
|
||||||
field :views, :integer
|
|
||||||
|
|
||||||
|
|
||||||
many_to_many :tags, Tag, join_through: "streams_tags", on_replace: :delete
|
many_to_many :tags, Tag, join_through: "streams_tags", on_replace: :delete
|
||||||
|
|
|
@ -23,7 +23,7 @@ defmodule Bright.Uploads do
|
||||||
def download_file(url, destination_path) do
|
def download_file(url, destination_path) do
|
||||||
case HTTPoison.get(url) do
|
case HTTPoison.get(url) do
|
||||||
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
|
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
|
||||||
IO.puts "WE GOT A GOOD RESPONSE SO LETS WRITE"
|
# IO.puts "WE GOT A GOOD RESPONSE SO LETS WRITE"
|
||||||
case File.write(destination_path, body) do
|
case File.write(destination_path, body) do
|
||||||
:ok -> {:ok, "File downloaded successfully"}
|
:ok -> {:ok, "File downloaded successfully"}
|
||||||
{:error, reason} -> {:error, reason}
|
{:error, reason} -> {:error, reason}
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
<:item title="S3 upload">{@vod.s3_upload_id}</:item>
|
<:item title="S3 upload">{@vod.s3_upload_id}</:item>
|
||||||
<:item title="S3 key">{@vod.s3_key}</:item>
|
<:item title="S3 key">{@vod.s3_key}</:item>
|
||||||
<:item title="S3 bucket">{@vod.s3_bucket}</:item>
|
<:item title="S3 bucket">{@vod.s3_bucket}</:item>
|
||||||
|
<:item title="Thumbnail URL">{@vod.thumbnail_url}</:item>
|
||||||
<:item title="Ipfs CID">{@vod.ipfs_cid}</:item>
|
<:item title="Ipfs CID">{@vod.ipfs_cid}</:item>
|
||||||
<:item title="Torrent">{@vod.torrent}</:item>
|
<:item title="Torrent">{@vod.torrent}</:item>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
defmodule Bright.Repo.Migrations.RemoveViewsFromStreams do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:streams) do
|
||||||
|
remove :views
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,19 +3,25 @@ defmodule Bright.B2Test do
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@cdn_url Application.get_env(:bright, :public_s3_endpoint)
|
||||||
|
|
||||||
describe "B2" do
|
describe "B2" do
|
||||||
|
|
||||||
alias Bright.B2
|
alias Bright.B2
|
||||||
|
|
||||||
|
|
||||||
@tag :acceptance
|
@tag :acceptance
|
||||||
test "put/1" do
|
test "put/1" do
|
||||||
|
local_file = Path.absname("test/fixtures/SampleVideo_1280x720_1mb.mp4")
|
||||||
|
{:ok, %{key: key, cdn_url: cdn_url}} = B2.put(local_file)
|
||||||
|
assert key === "SampleVideo_1280x720_1mb.mp4"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :acceptance
|
||||||
|
test "put/2" do
|
||||||
local_file = Path.absname("test/fixtures/SampleVideo_1280x720_1mb.mp4")
|
local_file = Path.absname("test/fixtures/SampleVideo_1280x720_1mb.mp4")
|
||||||
object_key = "test/SampleVideo_1280x720_1mb.mp4"
|
object_key = "test/SampleVideo_1280x720_1mb.mp4"
|
||||||
{:ok, remote_file} = B2.put(local_file, object_key)
|
{:ok, %{key: key, cdn_url: cdn_url}} = B2.put(local_file, object_key)
|
||||||
assert Regex.match?(~r/SampleVideo/, remote_file)
|
assert Regex.match?(~r/SampleVideo/, key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +40,15 @@ defmodule Bright.B2Test do
|
||||||
File.rm!(local_file)
|
File.rm!(local_file)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@tag :integration
|
||||||
|
test "generate_cdn_url/1" do
|
||||||
|
assert Regex.match?(~r"https:\/\/", @cdn_url), ":public_s3_endpoint was missing from `:bright` app config, which is a requirement for this test."
|
||||||
|
object_key = "test/SampleVideo_1280x720_1mb.mp4"
|
||||||
|
cdn_url = B2.generate_cdn_url(object_key)
|
||||||
|
assert cdn_url === "#{@cdn_url}/#{object_key}"
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
defmodule Bright.BlogTest do
|
|
||||||
use Bright.DataCase
|
|
||||||
|
|
||||||
alias Bright.Blog
|
|
||||||
|
|
||||||
describe "posts" do
|
|
||||||
alias Bright.Blog.Post
|
|
||||||
|
|
||||||
import Bright.BlogFixtures
|
|
||||||
|
|
||||||
@invalid_attrs %{title: nil, body: nil}
|
|
||||||
|
|
||||||
test "list_posts/0 returns all posts" do
|
|
||||||
post = post_fixture()
|
|
||||||
assert Blog.list_posts() == [post]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "get_post!/1 returns the post with given id" do
|
|
||||||
post = post_fixture()
|
|
||||||
assert Blog.get_post!(post.id) == post
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_post/1 with valid data creates a post" do
|
|
||||||
valid_attrs = %{title: "some title", body: "some body"}
|
|
||||||
|
|
||||||
assert {:ok, %Post{} = post} = Blog.create_post(valid_attrs)
|
|
||||||
assert post.title == "some title"
|
|
||||||
assert post.body == "some body"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_post/1 with invalid data returns error changeset" do
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Blog.create_post(@invalid_attrs)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_post/2 with valid data updates the post" do
|
|
||||||
post = post_fixture()
|
|
||||||
update_attrs = %{title: "some updated title", body: "some updated body"}
|
|
||||||
|
|
||||||
assert {:ok, %Post{} = post} = Blog.update_post(post, update_attrs)
|
|
||||||
assert post.title == "some updated title"
|
|
||||||
assert post.body == "some updated body"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_post/2 with invalid data returns error changeset" do
|
|
||||||
post = post_fixture()
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Blog.update_post(post, @invalid_attrs)
|
|
||||||
assert post == Blog.get_post!(post.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "delete_post/1 deletes the post" do
|
|
||||||
post = post_fixture()
|
|
||||||
assert {:ok, %Post{}} = Blog.delete_post(post)
|
|
||||||
assert_raise Ecto.NoResultsError, fn -> Blog.get_post!(post.id) end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "change_post/1 returns a post changeset" do
|
|
||||||
post = post_fixture()
|
|
||||||
assert %Ecto.Changeset{} = Blog.change_post(post)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -3,23 +3,47 @@ defmodule Bright.CacheTest do
|
||||||
|
|
||||||
alias Bright.Cache
|
alias Bright.Cache
|
||||||
|
|
||||||
|
@sample_url "https://example.com/my_video.mp4"
|
||||||
|
|
||||||
describe "cache" do
|
describe "cache" do
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@tag :unit
|
@tag :unit
|
||||||
test "generate_filename generates a random alphanumeric prefix with the correct basename and extension" do
|
test "generate_basename/1" do
|
||||||
# Test with a URL
|
# Test with a URL
|
||||||
url = "https://example.com/my_video.mp4"
|
url = @sample_url
|
||||||
filename = Cache.generate_filename(url)
|
filename = Cache.generate_basename(url)
|
||||||
|
|
||||||
assert Regex.match?(~r/^[a-zA-Z0-9]+-my_video\.mp4$/, filename)
|
assert Regex.match?(~r/^[a-zA-Z0-9]+-my_video\.mp4$/, filename)
|
||||||
|
|
||||||
# Test with a file path
|
# Test with a file path
|
||||||
path = "/home/cj/Downloads/taco.mp4"
|
path = "/home/cj/Downloads/taco.mp4"
|
||||||
filename = Cache.generate_filename(path)
|
filename = Cache.generate_basename(path)
|
||||||
|
|
||||||
assert Regex.match?(~r/^[a-zA-Z0-9]+-taco\.mp4$/, filename)
|
assert Regex.match?(~r/^[a-zA-Z0-9]+-taco\.mp4$/, filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@tag :unit
|
||||||
|
test "generate_basename/2" do
|
||||||
|
filename = Cache.generate_basename(@sample_url, "png")
|
||||||
|
assert Regex.match?(~r/^[a-zA-Z0-9]+-my_video\.png/, filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :unit
|
||||||
|
test "generate_filename/1" do
|
||||||
|
filename = Cache.generate_filename(@sample_url)
|
||||||
|
assert Regex.match?(~r/.cache\/futureporn\/.+-my_video\.mp4/, filename)
|
||||||
|
|
||||||
|
filename = Cache.generate_filename("/home/cj/Downloads/test.mp4")
|
||||||
|
assert Regex.match?(~r/.cache\/futureporn\/.+-test\.mp4/, filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :unit
|
||||||
|
test "generate_filename/2" do
|
||||||
|
filename = Cache.generate_filename(@sample_url, "png")
|
||||||
|
assert Regex.match?(~r/.cache\/futureporn\/.+-my_video\.png/, filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
defmodule Bright.CatalogTest do
|
|
||||||
use Bright.DataCase
|
|
||||||
|
|
||||||
alias Bright.Catalog
|
|
||||||
|
|
||||||
describe "products" do
|
|
||||||
alias Bright.Catalog.Product
|
|
||||||
|
|
||||||
import Bright.CatalogFixtures
|
|
||||||
|
|
||||||
@invalid_attrs %{description: nil, title: nil, price: nil, views: nil}
|
|
||||||
|
|
||||||
test "list_products/0 returns all products" do
|
|
||||||
product = product_fixture()
|
|
||||||
assert Catalog.list_products() == [product]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "get_product!/1 returns the product with given id" do
|
|
||||||
product = product_fixture()
|
|
||||||
assert Catalog.get_product!(product.id) == product
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_product/1 with valid data creates a product" do
|
|
||||||
valid_attrs = %{description: "some description", title: "some title", price: "120.5", views: 42}
|
|
||||||
|
|
||||||
assert {:ok, %Product{} = product} = Catalog.create_product(valid_attrs)
|
|
||||||
assert product.description == "some description"
|
|
||||||
assert product.title == "some title"
|
|
||||||
assert product.price == Decimal.new("120.5")
|
|
||||||
assert product.views == 42
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_product/1 with invalid data returns error changeset" do
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Catalog.create_product(@invalid_attrs)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_product/2 with valid data updates the product" do
|
|
||||||
product = product_fixture()
|
|
||||||
update_attrs = %{description: "some updated description", title: "some updated title", price: "456.7", views: 43}
|
|
||||||
|
|
||||||
assert {:ok, %Product{} = product} = Catalog.update_product(product, update_attrs)
|
|
||||||
assert product.description == "some updated description"
|
|
||||||
assert product.title == "some updated title"
|
|
||||||
assert product.price == Decimal.new("456.7")
|
|
||||||
assert product.views == 43
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_product/2 with invalid data returns error changeset" do
|
|
||||||
product = product_fixture()
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Catalog.update_product(product, @invalid_attrs)
|
|
||||||
assert product == Catalog.get_product!(product.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "delete_product/1 deletes the product" do
|
|
||||||
product = product_fixture()
|
|
||||||
assert {:ok, %Product{}} = Catalog.delete_product(product)
|
|
||||||
assert_raise Ecto.NoResultsError, fn -> Catalog.get_product!(product.id) end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "change_product/1 returns a product changeset" do
|
|
||||||
product = product_fixture()
|
|
||||||
assert %Ecto.Changeset{} = Catalog.change_product(product)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "categories" do
|
|
||||||
alias Bright.Catalog.Category
|
|
||||||
|
|
||||||
import Bright.CatalogFixtures
|
|
||||||
|
|
||||||
@invalid_attrs %{title: nil}
|
|
||||||
|
|
||||||
test "list_categories/0 returns all categories" do
|
|
||||||
category = category_fixture()
|
|
||||||
assert Catalog.list_categories() == [category]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "get_category!/1 returns the category with given id" do
|
|
||||||
category = category_fixture()
|
|
||||||
assert Catalog.get_category!(category.id) == category
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_category/1 with valid data creates a category" do
|
|
||||||
valid_attrs = %{title: "some title"}
|
|
||||||
|
|
||||||
assert {:ok, %Category{} = category} = Catalog.create_category(valid_attrs)
|
|
||||||
assert category.title == "some title"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_category/1 with invalid data returns error changeset" do
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Catalog.create_category(@invalid_attrs)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_category/2 with valid data updates the category" do
|
|
||||||
category = category_fixture()
|
|
||||||
update_attrs = %{title: "some updated title"}
|
|
||||||
|
|
||||||
assert {:ok, %Category{} = category} = Catalog.update_category(category, update_attrs)
|
|
||||||
assert category.title == "some updated title"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_category/2 with invalid data returns error changeset" do
|
|
||||||
category = category_fixture()
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Catalog.update_category(category, @invalid_attrs)
|
|
||||||
assert category == Catalog.get_category!(category.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "delete_category/1 deletes the category" do
|
|
||||||
category = category_fixture()
|
|
||||||
assert {:ok, %Category{}} = Catalog.delete_category(category)
|
|
||||||
assert_raise Ecto.NoResultsError, fn -> Catalog.get_category!(category.id) end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "change_category/1 returns a category changeset" do
|
|
||||||
category = category_fixture()
|
|
||||||
assert %Ecto.Changeset{} = Catalog.change_category(category)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
|
||||||
|
defmodule Bright.DownloaderTest do
|
||||||
|
use Bright.DataCase
|
||||||
|
|
||||||
|
alias Bright.Downloader
|
||||||
|
|
||||||
|
@test_fixture "https://futureporn-b2.b-cdn.net/projekt-melody.jpg"
|
||||||
|
|
||||||
|
describe "downloader" do
|
||||||
|
test "get/1" do
|
||||||
|
|
||||||
|
{:ok, local_file} = Downloader.get(@test_fixture)
|
||||||
|
assert File.exists?(local_file)
|
||||||
|
{:ok, stat} = File.stat(local_file)
|
||||||
|
assert stat.size > 0, "File is empty"
|
||||||
|
assert Regex.match?(~r/.cache\/futureporn\/.+-projekt-melody\.jpg/, local_file)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -9,7 +9,17 @@ defmodule Bright.ImagesTest do
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
test "should generate a 5x5 thumbnail using a local file" do
|
@tag :unit
|
||||||
|
test "create_thumbnail/1" do
|
||||||
|
{:ok, %{:output => output, :filename => filename}} = Images.create_thumbnail(@test_fixture)
|
||||||
|
assert output === ""
|
||||||
|
assert Regex.match?(~r/[a-zA-Z0-9]+-.*\.png$/, filename)
|
||||||
|
assert File.exists?(filename)
|
||||||
|
assert File.stat!(filename).size > 0, "thumbnail file is empty"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :unit
|
||||||
|
test "create_thumbnail/2" do
|
||||||
# ffmpeg -y -i ~/Videos/moose-encounter_75.mp4 -frames:v 1 -vf 'select=not(mod(n\,257)),scale=160:-1,tile=5x5' -update 1 -fps_mode passthrough ~/Videos/thumb.jpg
|
# ffmpeg -y -i ~/Videos/moose-encounter_75.mp4 -frames:v 1 -vf 'select=not(mod(n\,257)),scale=160:-1,tile=5x5' -update 1 -fps_mode passthrough ~/Videos/thumb.jpg
|
||||||
|
|
||||||
basename = "thumb.jpg"
|
basename = "thumb.jpg"
|
||||||
|
@ -17,13 +27,11 @@ defmodule Bright.ImagesTest do
|
||||||
output_file = "/tmp/#{random_string}-#{basename}"
|
output_file = "/tmp/#{random_string}-#{basename}"
|
||||||
IO.puts "output_file=#{inspect(output_file)} @test_fixture=#{inspect(@test_fixture)}"
|
IO.puts "output_file=#{inspect(output_file)} @test_fixture=#{inspect(@test_fixture)}"
|
||||||
|
|
||||||
Images.create_thumbnail(@test_fixture, output_file)
|
{:ok, output } = Images.create_thumbnail(@test_fixture, output_file)
|
||||||
|
|
||||||
assert File.exists?(output_file)
|
assert File.exists?(output_file)
|
||||||
{:ok, stat} = File.stat(output_file)
|
{:ok, stat} = File.stat(output_file)
|
||||||
assert stat.size > 0, "File is empty"
|
assert stat.size > 0, "File is empty"
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Feature creep! Download the image for now. Make it work, first. THen make it right. THEN make it fast.
|
# Feature creep! Download the image for now. Make it work, first. THen make it right. THEN make it fast.
|
||||||
|
|
|
@ -13,6 +13,8 @@ defmodule Bright.CreateHlsPlaylistTest do
|
||||||
|
|
||||||
describe "CreateHlsPlaylist" do
|
describe "CreateHlsPlaylist" do
|
||||||
|
|
||||||
|
import Bright.StreamsFixtures
|
||||||
|
|
||||||
@tag :integration
|
@tag :integration
|
||||||
test "sheduling upon vod creation" do
|
test "sheduling upon vod creation" do
|
||||||
|
|
||||||
|
@ -43,88 +45,4 @@ defmodule Bright.CreateHlsPlaylistTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
describe "perform/1" do
|
|
||||||
# test "throw when vod_id is missing" do
|
|
||||||
# job_args = %{"vod_id" => 1}
|
|
||||||
# {:error, reason} = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
|
|
||||||
# assert Regex.match?(~r/missing.*vod_id/i, reason)
|
|
||||||
# end
|
|
||||||
|
|
||||||
# test "evergreen?" do
|
|
||||||
# job_args = %{"vod_id" => 1, "input_url" => "https://example.com/my_video.mp4"}
|
|
||||||
# assert :ok = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
|
|
||||||
# end
|
|
||||||
|
|
||||||
# test "bypassing activation when sign up fails" do
|
|
||||||
# {:error, _reason} = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
|
|
||||||
|
|
||||||
# refute_enqueued worker: MyApp.ActivationWorker
|
|
||||||
# end
|
|
||||||
|
|
||||||
# test "successfully creates an HLS playlist and updates the VOD" do
|
|
||||||
# # Mock the VOD to be returned by Repo.get!/2
|
|
||||||
# vod = %Vod{id: 1, playlist_url: nil}
|
|
||||||
# expect(RepoMock, :get!, fn Vod, 1 -> vod end)
|
|
||||||
|
|
||||||
# # Mock the start_transcode function
|
|
||||||
# expect(HTTPoisonMock, :post, fn url, body, headers ->
|
|
||||||
# assert url == "#{System.get_env("SUPERSTREAMER_URL")}/transcode"
|
|
||||||
# assert headers == [
|
|
||||||
# {"authorization", "Bearer #{System.get_env("SUPERSTREAMER_AUTH_TOKEN")}"},
|
|
||||||
# {"content-type", "application/json"}
|
|
||||||
# ]
|
|
||||||
# {:ok, %HTTPoison.Response{status_code: 200, body: ~s({"jobId": "transcode-job-id"})}}
|
|
||||||
# end)
|
|
||||||
|
|
||||||
# # Mock the polling of the transcode job
|
|
||||||
# expect(HTTPoisonMock, :get, fn url, headers ->
|
|
||||||
# assert url == "#{System.get_env("SUPERSTREAMER_URL")}/jobs/transcode-job-id"
|
|
||||||
# {:ok, %HTTPoison.Response{
|
|
||||||
# status_code: 200,
|
|
||||||
# body: ~s({"state": "completed", "outputData": {"assetId": "asset-id"}})
|
|
||||||
# }}
|
|
||||||
# end)
|
|
||||||
|
|
||||||
# # Mock the start_package function
|
|
||||||
# expect(HTTPoisonMock, :post, fn url, body, headers ->
|
|
||||||
# assert url == "#{System.get_env("SUPERSTREAMER_URL")}/package"
|
|
||||||
# {:ok, %HTTPoison.Response{status_code: 200, body: ~s({"jobId": "package-job-id"})}}
|
|
||||||
# end)
|
|
||||||
|
|
||||||
# # Mock the polling of the package job
|
|
||||||
# expect(HTTPoisonMock, :get, fn url, headers ->
|
|
||||||
# assert url == "#{System.get_env("SUPERSTREAMER_URL")}/jobs/package-job-id"
|
|
||||||
# {:ok, %HTTPoison.Response{
|
|
||||||
# status_code: 200,
|
|
||||||
# body: ~s({"state": "completed", "outputData": {"assetId": "asset-id"}})
|
|
||||||
# }}
|
|
||||||
# end)
|
|
||||||
|
|
||||||
|
|
||||||
# # Mock the Repo.update!/1 call
|
|
||||||
# expect(RepoMock, :update!, fn changeset ->
|
|
||||||
# assert changeset.changes.playlist_url == "#{System.get_env("PUBLIC_S3_ENDPOINT")}/package/asset-id/hls/master.m3u8"
|
|
||||||
# {:ok, changeset}
|
|
||||||
# end)
|
|
||||||
|
|
||||||
# # Call the worker's perform function
|
|
||||||
# job_args = %{"vod_id" => 1, "input_url" => "https://example.com/input.mp4"}
|
|
||||||
# assert :ok = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
|
|
||||||
# end
|
|
||||||
|
|
||||||
# test "handles errors gracefully" do
|
|
||||||
# # Mock the VOD to be returned by Repo.get!/2
|
|
||||||
# vod = %Vod{id: 1, playlist_url: nil}
|
|
||||||
# expect(RepoMock, :get!, fn Vod, 1 -> vod end)
|
|
||||||
|
|
||||||
# # Mock the start_transcode function to return an error
|
|
||||||
# expect(HTTPoisonMock, :post, fn _url, _body, _headers ->
|
|
||||||
# {:error, %HTTPoison.Error{reason: "transcoding failed"}}
|
|
||||||
# end)
|
|
||||||
|
|
||||||
# # Call the worker's perform function
|
|
||||||
# job_args = %{"vod_id" => 1, "input_url" => "https://example.com/input.mp4"}
|
|
||||||
# assert {:error, _reason} = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
|
|
||||||
# end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,31 +1,67 @@
|
||||||
defmodule Bright.ObanWorkers.CreateS3AssetTest do
|
defmodule Bright.ObanWorkers.CreateS3AssetTest do
|
||||||
use Bright.DataCase
|
use Bright.DataCase
|
||||||
use Oban.Testing, repo: Bright.Repo
|
use Oban.Testing, repo: Bright.Repo
|
||||||
alias Bright.ObanWorkers.CreateS3Asset
|
alias Bright.ObanWorkers.{
|
||||||
|
CreateS3Asset,
|
||||||
|
ProcessVod,
|
||||||
|
CreateThumbnail
|
||||||
|
}
|
||||||
|
alias Bright.Cache
|
||||||
|
alias Bright.Streams
|
||||||
|
alias Bright.Streams.Stream
|
||||||
|
|
||||||
@tag :unit
|
# @tag :unit
|
||||||
test "creating a new s3 asset (unit test)" do
|
# test "creating a new s3 asset (unit test)" do
|
||||||
|
|
||||||
url = "https://example.com/video.ts"
|
|
||||||
key = "video.ts"
|
|
||||||
{:ok, asset} = perform_job(CreateS3Asset, %{url: url, key: key})
|
|
||||||
end
|
|
||||||
|
|
||||||
@tag :acceptance
|
|
||||||
test "creating a new s3 asset (acceptance test)" do
|
|
||||||
|
|
||||||
|
|
||||||
url = "http://38.242.193.246:8081/fixtures/2024-12-19T03-10-30Z.ts"
|
# example_video = "http://example.com/video.ts"
|
||||||
key = unique_filename
|
# stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
|
||||||
|
# {:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
|
||||||
|
# {:ok, vod} = Streams.create_vod(%{stream_id: stream.id, origin_temp_input_url: example_video})
|
||||||
|
# assert :ok
|
||||||
|
# {:ok, asset} = perform_job(CreateS3Asset, %{input_url: example_video, vod_id: vod.id})
|
||||||
|
# assert :ok
|
||||||
|
|
||||||
|
# end
|
||||||
|
|
||||||
|
|
||||||
|
@tag :integration
|
||||||
|
test "sheduling upon vod creation" do
|
||||||
example_video = "http://example.com/video.ts"
|
example_video = "http://example.com/video.ts"
|
||||||
stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
|
stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
|
||||||
{:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
|
{:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
|
||||||
{:ok, _vod} = Streams.create_vod(%{stream_id: stream.id, origin_temp_input_url: example_video})
|
{:ok, _vod} = Streams.create_vod(%{stream_id: stream.id, origin_temp_input_url: example_video})
|
||||||
|
assert_enqueued worker: ProcessVod, queue: :default
|
||||||
|
Oban.drain_queue(queue: :default) # ProcessVod is what queues CreateS3Asset so we need to make it run
|
||||||
perform_job(CreateS3Asset, %{url: url, key: key})
|
assert_enqueued worker: CreateS3Asset, queue: :default
|
||||||
{:ok, asset} = Oban.drain_queue(queue: :default)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@tag :integration
|
||||||
|
test "not scheduled when origin_temp_input_url is missing" do
|
||||||
|
|
||||||
|
stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
|
||||||
|
{:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
|
||||||
|
{:ok, _vod} = Streams.create_vod(%{stream_id: stream.id})
|
||||||
|
|
||||||
|
refute_enqueued worker: CreateS3Asset
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :acceptance
|
||||||
|
# test "creating a new s3 asset (acceptance test)" do
|
||||||
|
|
||||||
|
|
||||||
|
# url = "http://38.242.193.246:8081/fixtures/2024-12-19T03-10-30Z.ts"
|
||||||
|
# key = Cache.generate_filename(url)
|
||||||
|
|
||||||
|
# example_video = "http://example.com/video.ts"
|
||||||
|
# stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
|
||||||
|
# {:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
|
||||||
|
# {:ok, vod} = Streams.create_vod(%{stream_id: stream.id, origin_temp_input_url: example_video})
|
||||||
|
|
||||||
|
|
||||||
|
# perform_job(CreateS3Asset, %{input_url: example_video, vod_id: vod.id})
|
||||||
|
# {:ok, asset} = Oban.drain_queue(queue: :default)
|
||||||
|
|
||||||
|
# end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,10 +4,28 @@ defmodule Bright.ObanWorkers.CreateThumbnailTest do
|
||||||
alias Bright.ObanWorkers.CreateThumbnail
|
alias Bright.ObanWorkers.CreateThumbnail
|
||||||
alias Bright.ObanWorkers.ProcessVod
|
alias Bright.ObanWorkers.ProcessVod
|
||||||
alias Bright.Streams
|
alias Bright.Streams
|
||||||
alias Bright.Streams.Stream
|
alias Bright.Streams.{
|
||||||
|
Stream,
|
||||||
|
Vod
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
describe "CreateThumbnail" do
|
describe "CreateThumbnail" do
|
||||||
|
|
||||||
|
import Bright.StreamsFixtures
|
||||||
|
@example_url "https://futureporn-b2.b-cdn.net/big_buck_bunny_720p_1mb.mp4"
|
||||||
|
|
||||||
|
@tag :integration
|
||||||
|
test "thumbnail creation" do
|
||||||
|
stream = stream_fixture()
|
||||||
|
vod = vod_fixture(%{thumbnail_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
|
||||||
|
{:ok, %Vod{thumbnail_url: thumbnail_url}} = perform_job(Bright.ObanWorkers.CreateThumbnail, %{vod_id: vod.id})
|
||||||
|
assert Regex.match?(~r/^https:\/\/.*\.png$/, thumbnail_url)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@tag :integration
|
@tag :integration
|
||||||
test "sheduling upon vod creation" do
|
test "sheduling upon vod creation" do
|
||||||
|
|
||||||
|
@ -35,5 +53,7 @@ defmodule Bright.ObanWorkers.CreateThumbnailTest do
|
||||||
|
|
||||||
refute_enqueued worker: CreateThumbnail
|
refute_enqueued worker: CreateThumbnail
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
defmodule Bright.ObanWorkers.ProcessVodTest do
|
||||||
|
use Bright.DataCase
|
||||||
|
use Oban.Testing, repo: Bright.Repo
|
||||||
|
alias Bright.ObanWorkers.{
|
||||||
|
CreateThumbnail,
|
||||||
|
ProcessVod,
|
||||||
|
CreateS3Asset,
|
||||||
|
CreateHlsPlaylist
|
||||||
|
}
|
||||||
|
alias Bright.Streams
|
||||||
|
alias Bright.Streams.{Stream,Vod}
|
||||||
|
|
||||||
|
@example_url "https://example.com/my-video.mp4"
|
||||||
|
|
||||||
|
describe "ProcessVod" do
|
||||||
|
|
||||||
|
import Bright.StreamsFixtures
|
||||||
|
|
||||||
|
@tag :unit
|
||||||
|
test "processing a new vod" do
|
||||||
|
stream = stream_fixture()
|
||||||
|
vod = vod_fixture(%{thumbnail_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
|
||||||
|
:ok = perform_job(Bright.ObanWorkers.ProcessVod, %{vod_id: vod.id})
|
||||||
|
assert :ok
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :integration
|
||||||
|
test "schedule ProcessVod when a new vod is created" do
|
||||||
|
stream = stream_fixture()
|
||||||
|
vod_fixture(%{thumbnail_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
|
||||||
|
assert_enqueued worker: ProcessVod, queue: :default
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :integration
|
||||||
|
test "schedule CreateThumbnail when thumbnail_url is nil" do
|
||||||
|
stream = stream_fixture()
|
||||||
|
vod_fixture(%{thumbnail_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
|
||||||
|
assert_enqueued worker: ProcessVod, queue: :default
|
||||||
|
assert %{success: 1} = Oban.drain_queue(queue: :default, with_safety: false) # ProcessVod is what queues CreateThumbnail so we need to make it run
|
||||||
|
assert_enqueued worker: CreateThumbnail, queue: :default
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :integration
|
||||||
|
test "schedule CreateS3Asset when s3_cdn_url is nil" do
|
||||||
|
stream = stream_fixture()
|
||||||
|
vod_fixture(%{s3_cdn_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
|
||||||
|
assert_enqueued worker: ProcessVod, queue: :default
|
||||||
|
assert %{success: 1} = Oban.drain_queue(queue: :default, with_safety: false) # ProcessVod is what queues CreateThumbnail so we need to make it run
|
||||||
|
assert_enqueued worker: CreateS3Asset, queue: :default
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :integration
|
||||||
|
test "schedule CreateHlsPlaylist when playlist_url is nil" do
|
||||||
|
stream = stream_fixture()
|
||||||
|
vod_fixture(%{playlist_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
|
||||||
|
|
||||||
|
assert_enqueued worker: ProcessVod, queue: :default
|
||||||
|
assert %{success: 1} = Oban.drain_queue(queue: :default, with_safety: false) # ProcessVod is what queues CreateThumbnail so we need to make it run
|
||||||
|
assert_enqueued worker: CreateHlsPlaylist, queue: :default
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,117 +0,0 @@
|
||||||
defmodule Bright.OrdersTest do
|
|
||||||
use Bright.DataCase
|
|
||||||
|
|
||||||
alias Bright.Orders
|
|
||||||
|
|
||||||
describe "orders" do
|
|
||||||
alias Bright.Orders.Order
|
|
||||||
|
|
||||||
import Bright.OrdersFixtures
|
|
||||||
|
|
||||||
@invalid_attrs %{user_uuid: nil, total_price: nil}
|
|
||||||
|
|
||||||
test "list_orders/0 returns all orders" do
|
|
||||||
order = order_fixture()
|
|
||||||
assert Orders.list_orders() == [order]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "get_order!/1 returns the order with given id" do
|
|
||||||
order = order_fixture()
|
|
||||||
assert Orders.get_order!(order.id) == order
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_order/1 with valid data creates a order" do
|
|
||||||
valid_attrs = %{user_uuid: "7488a646-e31f-11e4-aace-600308960662", total_price: "120.5"}
|
|
||||||
|
|
||||||
assert {:ok, %Order{} = order} = Orders.create_order(valid_attrs)
|
|
||||||
assert order.user_uuid == "7488a646-e31f-11e4-aace-600308960662"
|
|
||||||
assert order.total_price == Decimal.new("120.5")
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_order/1 with invalid data returns error changeset" do
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Orders.create_order(@invalid_attrs)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_order/2 with valid data updates the order" do
|
|
||||||
order = order_fixture()
|
|
||||||
update_attrs = %{user_uuid: "7488a646-e31f-11e4-aace-600308960668", total_price: "456.7"}
|
|
||||||
|
|
||||||
assert {:ok, %Order{} = order} = Orders.update_order(order, update_attrs)
|
|
||||||
assert order.user_uuid == "7488a646-e31f-11e4-aace-600308960668"
|
|
||||||
assert order.total_price == Decimal.new("456.7")
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_order/2 with invalid data returns error changeset" do
|
|
||||||
order = order_fixture()
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Orders.update_order(order, @invalid_attrs)
|
|
||||||
assert order == Orders.get_order!(order.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "delete_order/1 deletes the order" do
|
|
||||||
order = order_fixture()
|
|
||||||
assert {:ok, %Order{}} = Orders.delete_order(order)
|
|
||||||
assert_raise Ecto.NoResultsError, fn -> Orders.get_order!(order.id) end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "change_order/1 returns a order changeset" do
|
|
||||||
order = order_fixture()
|
|
||||||
assert %Ecto.Changeset{} = Orders.change_order(order)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "order_line_items" do
|
|
||||||
alias Bright.Orders.LineItem
|
|
||||||
|
|
||||||
import Bright.OrdersFixtures
|
|
||||||
|
|
||||||
@invalid_attrs %{price: nil, quantity: nil}
|
|
||||||
|
|
||||||
test "list_order_line_items/0 returns all order_line_items" do
|
|
||||||
line_item = line_item_fixture()
|
|
||||||
assert Orders.list_order_line_items() == [line_item]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "get_line_item!/1 returns the line_item with given id" do
|
|
||||||
line_item = line_item_fixture()
|
|
||||||
assert Orders.get_line_item!(line_item.id) == line_item
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_line_item/1 with valid data creates a line_item" do
|
|
||||||
valid_attrs = %{price: "120.5", quantity: 42}
|
|
||||||
|
|
||||||
assert {:ok, %LineItem{} = line_item} = Orders.create_line_item(valid_attrs)
|
|
||||||
assert line_item.price == Decimal.new("120.5")
|
|
||||||
assert line_item.quantity == 42
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_line_item/1 with invalid data returns error changeset" do
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Orders.create_line_item(@invalid_attrs)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_line_item/2 with valid data updates the line_item" do
|
|
||||||
line_item = line_item_fixture()
|
|
||||||
update_attrs = %{price: "456.7", quantity: 43}
|
|
||||||
|
|
||||||
assert {:ok, %LineItem{} = line_item} = Orders.update_line_item(line_item, update_attrs)
|
|
||||||
assert line_item.price == Decimal.new("456.7")
|
|
||||||
assert line_item.quantity == 43
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_line_item/2 with invalid data returns error changeset" do
|
|
||||||
line_item = line_item_fixture()
|
|
||||||
assert {:error, %Ecto.Changeset{}} = Orders.update_line_item(line_item, @invalid_attrs)
|
|
||||||
assert line_item == Orders.get_line_item!(line_item.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "delete_line_item/1 deletes the line_item" do
|
|
||||||
line_item = line_item_fixture()
|
|
||||||
assert {:ok, %LineItem{}} = Orders.delete_line_item(line_item)
|
|
||||||
assert_raise Ecto.NoResultsError, fn -> Orders.get_line_item!(line_item.id) end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "change_line_item/1 returns a line_item changeset" do
|
|
||||||
line_item = line_item_fixture()
|
|
||||||
assert %Ecto.Changeset{} = Orders.change_line_item(line_item)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -21,11 +21,11 @@ defmodule Bright.PlatformsTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "create_platform/1 with valid data creates a platform" do
|
test "create_platform/1 with valid data creates a platform" do
|
||||||
valid_attrs = %{name: "some name", url: true, icon: "<svg></svg>"}
|
valid_attrs = %{name: "some name", url: "some url", icon: "<svg></svg>"}
|
||||||
|
|
||||||
assert {:ok, %Platform{} = platform} = Platforms.create_platform(valid_attrs)
|
assert {:ok, %Platform{} = platform} = Platforms.create_platform(valid_attrs)
|
||||||
assert platform.name == "some name"
|
assert platform.name == "some name"
|
||||||
assert platform.url == true
|
assert platform.url == "some url"
|
||||||
assert platform.icon == "<svg></svg>"
|
assert platform.icon == "<svg></svg>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ defmodule Bright.PlatformsTest do
|
||||||
|
|
||||||
test "update_platform/2 with valid data updates the platform" do
|
test "update_platform/2 with valid data updates the platform" do
|
||||||
platform = platform_fixture()
|
platform = platform_fixture()
|
||||||
update_attrs = %{name: "some updated name", url: false, icon: "<svg>blah</svg>"}
|
update_attrs = %{name: "some updated name", url: "https://example.com", icon: "<svg>blah</svg>"}
|
||||||
|
|
||||||
assert {:ok, %Platform{} = platform} = Platforms.update_platform(platform, update_attrs)
|
assert {:ok, %Platform{} = platform} = Platforms.update_platform(platform, update_attrs)
|
||||||
assert platform.name == "some updated name"
|
assert platform.name == "some updated name"
|
||||||
assert platform.url == false
|
assert platform.url == "https://example.com"
|
||||||
assert platform.icon == "<svg>blah</svg>"
|
assert platform.icon == "<svg>blah</svg>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
defmodule Bright.ShoppingCartTest do
|
|
||||||
use Bright.DataCase
|
|
||||||
|
|
||||||
alias Bright.ShoppingCart
|
|
||||||
|
|
||||||
describe "carts" do
|
|
||||||
alias Bright.ShoppingCart.Cart
|
|
||||||
|
|
||||||
import Bright.ShoppingCartFixtures
|
|
||||||
|
|
||||||
@invalid_attrs %{user_uuid: nil}
|
|
||||||
|
|
||||||
test "list_carts/0 returns all carts" do
|
|
||||||
cart = cart_fixture()
|
|
||||||
assert ShoppingCart.list_carts() == [cart]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "get_cart!/1 returns the cart with given id" do
|
|
||||||
cart = cart_fixture()
|
|
||||||
assert ShoppingCart.get_cart!(cart.id) == cart
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_cart/1 with valid data creates a cart" do
|
|
||||||
valid_attrs = %{user_uuid: "7488a646-e31f-11e4-aace-600308960662"}
|
|
||||||
|
|
||||||
assert {:ok, %Cart{} = cart} = ShoppingCart.create_cart(valid_attrs)
|
|
||||||
assert cart.user_uuid == "7488a646-e31f-11e4-aace-600308960662"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_cart/1 with invalid data returns error changeset" do
|
|
||||||
assert {:error, %Ecto.Changeset{}} = ShoppingCart.create_cart(@invalid_attrs)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_cart/2 with valid data updates the cart" do
|
|
||||||
cart = cart_fixture()
|
|
||||||
update_attrs = %{user_uuid: "7488a646-e31f-11e4-aace-600308960668"}
|
|
||||||
|
|
||||||
assert {:ok, %Cart{} = cart} = ShoppingCart.update_cart(cart, update_attrs)
|
|
||||||
assert cart.user_uuid == "7488a646-e31f-11e4-aace-600308960668"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_cart/2 with invalid data returns error changeset" do
|
|
||||||
cart = cart_fixture()
|
|
||||||
assert {:error, %Ecto.Changeset{}} = ShoppingCart.update_cart(cart, @invalid_attrs)
|
|
||||||
assert cart == ShoppingCart.get_cart!(cart.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "delete_cart/1 deletes the cart" do
|
|
||||||
cart = cart_fixture()
|
|
||||||
assert {:ok, %Cart{}} = ShoppingCart.delete_cart(cart)
|
|
||||||
assert_raise Ecto.NoResultsError, fn -> ShoppingCart.get_cart!(cart.id) end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "change_cart/1 returns a cart changeset" do
|
|
||||||
cart = cart_fixture()
|
|
||||||
assert %Ecto.Changeset{} = ShoppingCart.change_cart(cart)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "cart_items" do
|
|
||||||
alias Bright.ShoppingCart.CartItem
|
|
||||||
|
|
||||||
import Bright.ShoppingCartFixtures
|
|
||||||
|
|
||||||
@invalid_attrs %{price_when_carted: nil, quantity: nil}
|
|
||||||
|
|
||||||
test "list_cart_items/0 returns all cart_items" do
|
|
||||||
cart_item = cart_item_fixture()
|
|
||||||
assert ShoppingCart.list_cart_items() == [cart_item]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "get_cart_item!/1 returns the cart_item with given id" do
|
|
||||||
cart_item = cart_item_fixture()
|
|
||||||
assert ShoppingCart.get_cart_item!(cart_item.id) == cart_item
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_cart_item/1 with valid data creates a cart_item" do
|
|
||||||
valid_attrs = %{price_when_carted: "120.5", quantity: 42}
|
|
||||||
|
|
||||||
assert {:ok, %CartItem{} = cart_item} = ShoppingCart.create_cart_item(valid_attrs)
|
|
||||||
assert cart_item.price_when_carted == Decimal.new("120.5")
|
|
||||||
assert cart_item.quantity == 42
|
|
||||||
end
|
|
||||||
|
|
||||||
test "create_cart_item/1 with invalid data returns error changeset" do
|
|
||||||
assert {:error, %Ecto.Changeset{}} = ShoppingCart.create_cart_item(@invalid_attrs)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_cart_item/2 with valid data updates the cart_item" do
|
|
||||||
cart_item = cart_item_fixture()
|
|
||||||
update_attrs = %{price_when_carted: "456.7", quantity: 43}
|
|
||||||
|
|
||||||
assert {:ok, %CartItem{} = cart_item} = ShoppingCart.update_cart_item(cart_item, update_attrs)
|
|
||||||
assert cart_item.price_when_carted == Decimal.new("456.7")
|
|
||||||
assert cart_item.quantity == 43
|
|
||||||
end
|
|
||||||
|
|
||||||
test "update_cart_item/2 with invalid data returns error changeset" do
|
|
||||||
cart_item = cart_item_fixture()
|
|
||||||
assert {:error, %Ecto.Changeset{}} = ShoppingCart.update_cart_item(cart_item, @invalid_attrs)
|
|
||||||
assert cart_item == ShoppingCart.get_cart_item!(cart_item.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "delete_cart_item/1 deletes the cart_item" do
|
|
||||||
cart_item = cart_item_fixture()
|
|
||||||
assert {:ok, %CartItem{}} = ShoppingCart.delete_cart_item(cart_item)
|
|
||||||
assert_raise Ecto.NoResultsError, fn -> ShoppingCart.get_cart_item!(cart_item.id) end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "change_cart_item/1 returns a cart_item changeset" do
|
|
||||||
cart_item = cart_item_fixture()
|
|
||||||
assert %Ecto.Changeset{} = ShoppingCart.change_cart_item(cart_item)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -66,20 +66,23 @@ defmodule Bright.StreamsTest do
|
||||||
|
|
||||||
import Bright.StreamsFixtures
|
import Bright.StreamsFixtures
|
||||||
|
|
||||||
@invalid_attrs %{s3_cdn_url: nil, s3_upload_id: nil, s3_key: nil, s3_bucket: nil, mux_asset_id: nil, mux_playback_id: nil, ipfs_cid: nil, torrent: nil}
|
@invalid_attrs %{stream_id: nil, s3_cdn_url: nil, s3_upload_id: nil, s3_key: nil, s3_bucket: nil, mux_asset_id: nil, mux_playback_id: nil, ipfs_cid: nil, torrent: nil}
|
||||||
|
|
||||||
test "list_vods/0 returns all vods" do
|
test "list_vods/0 returns all vods" do
|
||||||
vod = vod_fixture()
|
stream = stream_fixture()
|
||||||
|
vod = vod_fixture(%{stream_id: stream.id})
|
||||||
assert Streams.list_vods() == [vod]
|
assert Streams.list_vods() == [vod]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "get_vod!/1 returns the vod with given id" do
|
test "get_vod!/1 returns the vod with given id" do
|
||||||
vod = vod_fixture()
|
stream = stream_fixture()
|
||||||
|
vod = vod_fixture(%{stream_id: stream.id})
|
||||||
assert Streams.get_vod!(vod.id) == vod
|
assert Streams.get_vod!(vod.id) == vod
|
||||||
end
|
end
|
||||||
|
|
||||||
test "create_vod/1 with valid data creates a vod" do
|
test "create_vod/1 with valid data creates a vod" do
|
||||||
valid_attrs = %{s3_cdn_url: "some s3_cdn_url", s3_upload_id: "some s3_upload_id", s3_key: "some s3_key", s3_bucket: "some s3_bucket", mux_asset_id: "some mux_asset_id", mux_playback_id: "some mux_playback_id", ipfs_cid: "some ipfs_cid", torrent: "some torrent"}
|
stream = stream_fixture()
|
||||||
|
valid_attrs = %{stream_id: stream.id, s3_cdn_url: "some s3_cdn_url", s3_upload_id: "some s3_upload_id", s3_key: "some s3_key", s3_bucket: "some s3_bucket", mux_asset_id: "some mux_asset_id", mux_playback_id: "some mux_playback_id", ipfs_cid: "some ipfs_cid", torrent: "some torrent"}
|
||||||
|
|
||||||
assert {:ok, %Vod{} = vod} = Streams.create_vod(valid_attrs)
|
assert {:ok, %Vod{} = vod} = Streams.create_vod(valid_attrs)
|
||||||
assert vod.s3_cdn_url == "some s3_cdn_url"
|
assert vod.s3_cdn_url == "some s3_cdn_url"
|
||||||
|
@ -97,7 +100,8 @@ defmodule Bright.StreamsTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "update_vod/2 with valid data updates the vod" do
|
test "update_vod/2 with valid data updates the vod" do
|
||||||
vod = vod_fixture()
|
stream = stream_fixture()
|
||||||
|
vod = vod_fixture(%{stream_id: stream.id})
|
||||||
update_attrs = %{s3_cdn_url: "some updated s3_cdn_url", s3_upload_id: "some updated s3_upload_id", s3_key: "some updated s3_key", s3_bucket: "some updated s3_bucket", mux_asset_id: "some updated mux_asset_id", mux_playback_id: "some updated mux_playback_id", ipfs_cid: "some updated ipfs_cid", torrent: "some updated torrent"}
|
update_attrs = %{s3_cdn_url: "some updated s3_cdn_url", s3_upload_id: "some updated s3_upload_id", s3_key: "some updated s3_key", s3_bucket: "some updated s3_bucket", mux_asset_id: "some updated mux_asset_id", mux_playback_id: "some updated mux_playback_id", ipfs_cid: "some updated ipfs_cid", torrent: "some updated torrent"}
|
||||||
|
|
||||||
assert {:ok, %Vod{} = vod} = Streams.update_vod(vod, update_attrs)
|
assert {:ok, %Vod{} = vod} = Streams.update_vod(vod, update_attrs)
|
||||||
|
@ -112,19 +116,22 @@ defmodule Bright.StreamsTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "update_vod/2 with invalid data returns error changeset" do
|
test "update_vod/2 with invalid data returns error changeset" do
|
||||||
vod = vod_fixture()
|
stream = stream_fixture()
|
||||||
|
vod = vod_fixture(%{stream_id: stream.id})
|
||||||
assert {:error, %Ecto.Changeset{}} = Streams.update_vod(vod, @invalid_attrs)
|
assert {:error, %Ecto.Changeset{}} = Streams.update_vod(vod, @invalid_attrs)
|
||||||
assert vod == Streams.get_vod!(vod.id)
|
assert vod == Streams.get_vod!(vod.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "delete_vod/1 deletes the vod" do
|
test "delete_vod/1 deletes the vod" do
|
||||||
vod = vod_fixture()
|
stream = stream_fixture()
|
||||||
|
vod = vod_fixture(%{stream_id: stream.id})
|
||||||
assert {:ok, %Vod{}} = Streams.delete_vod(vod)
|
assert {:ok, %Vod{}} = Streams.delete_vod(vod)
|
||||||
assert_raise Ecto.NoResultsError, fn -> Streams.get_vod!(vod.id) end
|
assert_raise Ecto.NoResultsError, fn -> Streams.get_vod!(vod.id) end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "change_vod/1 returns a vod changeset" do
|
test "change_vod/1 returns a vod changeset" do
|
||||||
vod = vod_fixture()
|
stream = stream_fixture()
|
||||||
|
vod = vod_fixture(%{stream_id: stream.id})
|
||||||
assert %Ecto.Changeset{} = Streams.change_vod(vod)
|
assert %Ecto.Changeset{} = Streams.change_vod(vod)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ defmodule Bright.TagsTest do
|
||||||
|
|
||||||
test "list_tag/0 returns all tag" do
|
test "list_tag/0 returns all tag" do
|
||||||
tag = tag_fixture()
|
tag = tag_fixture()
|
||||||
assert Tags.list_tag() == [tag]
|
assert Tags.list_tags() == [tag]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "get_tag!/1 returns the tag with given id" do
|
test "get_tag!/1 returns the tag with given id" do
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
defmodule Bright.CatalogFixtures do
|
|
||||||
@moduledoc """
|
|
||||||
This module defines test helpers for creating
|
|
||||||
entities via the `Bright.Catalog` context.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Generate a product.
|
|
||||||
"""
|
|
||||||
def product_fixture(attrs \\ %{}) do
|
|
||||||
{:ok, product} =
|
|
||||||
attrs
|
|
||||||
|> Enum.into(%{
|
|
||||||
description: "some description",
|
|
||||||
price: "120.5",
|
|
||||||
title: "some title",
|
|
||||||
views: 42
|
|
||||||
})
|
|
||||||
|> Bright.Catalog.create_product()
|
|
||||||
|
|
||||||
product
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Generate a unique category title.
|
|
||||||
"""
|
|
||||||
def unique_category_title, do: "some title#{System.unique_integer([:positive])}"
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Generate a category.
|
|
||||||
"""
|
|
||||||
def category_fixture(attrs \\ %{}) do
|
|
||||||
{:ok, category} =
|
|
||||||
attrs
|
|
||||||
|> Enum.into(%{
|
|
||||||
title: unique_category_title()
|
|
||||||
})
|
|
||||||
|> Bright.Catalog.create_category()
|
|
||||||
|
|
||||||
category
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,36 +0,0 @@
|
||||||
defmodule Bright.OrdersFixtures do
|
|
||||||
@moduledoc """
|
|
||||||
This module defines test helpers for creating
|
|
||||||
entities via the `Bright.Orders` context.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Generate a order.
|
|
||||||
"""
|
|
||||||
def order_fixture(attrs \\ %{}) do
|
|
||||||
{:ok, order} =
|
|
||||||
attrs
|
|
||||||
|> Enum.into(%{
|
|
||||||
total_price: "120.5",
|
|
||||||
user_uuid: "7488a646-e31f-11e4-aace-600308960662"
|
|
||||||
})
|
|
||||||
|> Bright.Orders.create_order()
|
|
||||||
|
|
||||||
order
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Generate a line_item.
|
|
||||||
"""
|
|
||||||
def line_item_fixture(attrs \\ %{}) do
|
|
||||||
{:ok, line_item} =
|
|
||||||
attrs
|
|
||||||
|> Enum.into(%{
|
|
||||||
price: "120.5",
|
|
||||||
quantity: 42
|
|
||||||
})
|
|
||||||
|> Bright.Orders.create_line_item()
|
|
||||||
|
|
||||||
line_item
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,42 +0,0 @@
|
||||||
defmodule Bright.ShoppingCartFixtures do
|
|
||||||
@moduledoc """
|
|
||||||
This module defines test helpers for creating
|
|
||||||
entities via the `Bright.ShoppingCart` context.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Generate a unique cart user_uuid.
|
|
||||||
"""
|
|
||||||
def unique_cart_user_uuid do
|
|
||||||
raise "implement the logic to generate a unique cart user_uuid"
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Generate a cart.
|
|
||||||
"""
|
|
||||||
def cart_fixture(attrs \\ %{}) do
|
|
||||||
{:ok, cart} =
|
|
||||||
attrs
|
|
||||||
|> Enum.into(%{
|
|
||||||
user_uuid: unique_cart_user_uuid()
|
|
||||||
})
|
|
||||||
|> Bright.ShoppingCart.create_cart()
|
|
||||||
|
|
||||||
cart
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Generate a cart_item.
|
|
||||||
"""
|
|
||||||
def cart_item_fixture(attrs \\ %{}) do
|
|
||||||
{:ok, cart_item} =
|
|
||||||
attrs
|
|
||||||
|> Enum.into(%{
|
|
||||||
price_when_carted: "120.5",
|
|
||||||
quantity: 42
|
|
||||||
})
|
|
||||||
|> Bright.ShoppingCart.create_cart_item()
|
|
||||||
|
|
||||||
cart_item
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -34,10 +34,14 @@ defmodule Bright.StreamsFixtures do
|
||||||
s3_cdn_url: "some s3_cdn_url",
|
s3_cdn_url: "some s3_cdn_url",
|
||||||
s3_key: "some s3_key",
|
s3_key: "some s3_key",
|
||||||
s3_upload_id: "some s3_upload_id",
|
s3_upload_id: "some s3_upload_id",
|
||||||
torrent: "some torrent"
|
torrent: "some torrent",
|
||||||
|
playlist_url: "some playlist_url",
|
||||||
|
thumbnail_url: "some thumbnail_url"
|
||||||
})
|
})
|
||||||
|> Bright.Streams.create_vod()
|
|> Bright.Streams.create_vod()
|
||||||
|
|
||||||
vod
|
vod
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue