add bittorrent url encoding
This commit is contained in:
parent
5ebea988fa
commit
1e539d908d
@ -6,7 +6,7 @@ services:
|
||||
dockerfile: dockerfiles/opentracker.dockerfile
|
||||
container_name: opentracker
|
||||
environment:
|
||||
- WHITELIST_FEED_URL=http://bright:4000/torrents/whitelist?type=json
|
||||
- WHITELIST_FEED_URL=http://bright:4000/torrents
|
||||
ports:
|
||||
- "6969:6969/tcp"
|
||||
- "6969:6969/udp"
|
||||
@ -63,6 +63,7 @@ services:
|
||||
SUPERSTREAMER_URL: http://superstreamer-api:52001
|
||||
PUBLIC_S3_ENDPOINT: https://fp-dev.b-cdn.net
|
||||
BT_TRACKER_URL: https://tracker.futureporn.net/announce
|
||||
BT_TRACKER_ACCESSLIST_URL: http://opentracker:8666
|
||||
SITE_URL: https://futureporn.net
|
||||
env_file:
|
||||
- .kamal/secrets.development
|
||||
|
@ -30,7 +30,8 @@ config :bright,
|
||||
superstreamer_auth_token: System.get_env("SUPERSTREAMER_AUTH_TOKEN"),
|
||||
public_s3_endpoint: System.get_env("PUBLIC_S3_ENDPOINT"),
|
||||
s3_cdn_endpoint: System.get_env("PUBLIC_S3_ENDPOINT"),
|
||||
bittorrent_tracker_url: System.get_env("BT_TRACKER_URL"),
|
||||
bt_tracker_url: System.get_env("BT_TRACKER_URL"),
|
||||
bt_tracker_accesslist_url: System.get_env("BT_TRACKER_ACCESSLIST_URL"),
|
||||
site_url: System.get_env("SITE_URL")
|
||||
|
||||
config :bright, :buckets,
|
||||
|
39
services/bright/lib/bright/bittorrent_url_encode.ex
Normal file
39
services/bright/lib/bright/bittorrent_url_encode.ex
Normal file
@ -0,0 +1,39 @@
|
||||
defmodule Bright.BittorrentUrlEncode do
|
||||
@moduledoc """
|
||||
URL encoding for Bittorrent Info hash v1. https://www.bittorrent.org/beps/bep_0003.html
|
||||
Contains deviations from Elixir's URI.encode(). https://github.com/elixir-lang/elixir/blob/78f63d08313677a680868685701ae79a2459dcc1/lib/elixir/lib/uri.ex#L395
|
||||
Contains deviations from RFC3986 Section 2.2. https://datatracker.ietf.org/doc/html/rfc3986#section-2.2
|
||||
Designed to be compatible with qBittorrent's percent encoding.
|
||||
"""
|
||||
import Bitwise
|
||||
|
||||
|
||||
@spec encode(binary()) :: binary()
|
||||
def encode(string) when is_binary(string) do
|
||||
string = Base.decode16!(string, case: :lower)
|
||||
enc(string, &char_allowed?/1)
|
||||
end
|
||||
|
||||
@spec enc(binary, (byte -> as_boolean(term))) :: binary
|
||||
defp enc(string, predicate)
|
||||
when is_binary(string) and is_function(predicate, 1) do
|
||||
for <<byte <- string>>, into: "", do: percent(byte, predicate)
|
||||
end
|
||||
|
||||
defp char_allowed?(character) do
|
||||
character in ?0..?9 or character in ?a..?z or character in ?A..?Z or character in ~c"~_-.!"
|
||||
end
|
||||
|
||||
defp percent(char, predicate) do
|
||||
if predicate.(char) do
|
||||
<<char>>
|
||||
else
|
||||
<<"%", hex(bsr(char, 4)), hex(band(char, 15))>>
|
||||
end
|
||||
end
|
||||
|
||||
defp hex(n) when n <= 9, do: n + ?0
|
||||
defp hex(n), do: n + ?a - 10
|
||||
|
||||
|
||||
end
|
@ -9,8 +9,9 @@ defmodule Bright.ObanWorkers.CreateTorrent do
|
||||
B2,
|
||||
Images,
|
||||
Cache,
|
||||
Torrent,
|
||||
Tracker
|
||||
Torrents,
|
||||
Tracker,
|
||||
Torrentfile
|
||||
}
|
||||
require Logger
|
||||
import Ecto.Query, warn: false
|
||||
@ -18,13 +19,16 @@ defmodule Bright.ObanWorkers.CreateTorrent do
|
||||
|
||||
|
||||
def perform(%Oban.Job{args: %{"vod_id" => vod_id}}) do
|
||||
IO.puts "hello this is Oban.Job and we are testing to see if we can get env vars here. Application.fetch_env!(:bright, :bt_tracker_accesslist_url)=#{Application.fetch_env!(:bright, :bt_tracker_accesslist_url)} System.get_env('BT_TRACKER_ACCESSLIST_URL')=#{System.get_env("BT_TRACKER_ACCESSLIST_URL")}"
|
||||
vod = Streams.get_vod!(vod_id)
|
||||
with {:ok, filename} <- B2.get(vod),
|
||||
{:ok, torrent} <- Torrent.create_torrent(vod),
|
||||
{:ok, %{cdn_url: cdn_url}} <- B2.put(torrent.local_path, torrent.basename),
|
||||
:ok <- Tracker.whitelist_info_hash(torrent.info_hash),
|
||||
:ok <- Tracker.announce_torrent(torrent.magnet_link),
|
||||
{:ok, updated_vod} <- Streams.update_vod(vod, %{torrent: cdn_url, magnet_link: torrent.magnet_link}) do
|
||||
{:ok, tf} <- Torrentfile.create(vod, filename),
|
||||
{:ok, %{cdn_url: cdn_url}} <- B2.put(tf.save_path, Path.basename(tf.save_path)),
|
||||
{:ok, torrent} <- Torrents.create_torrent(%{info_hash_v1: tf.btih, info_hash_v2: tf.btmh, cdn_url: cdn_url, magnet: tf.magnet}),
|
||||
:ok <- Tracker.whitelist_info_hash(torrent.info_hash_v1),
|
||||
:ok <- Tracker.whitelist_info_hash(torrent.info_hash_v2),
|
||||
:ok <- Tracker.announce_torrent(torrent.magnet),
|
||||
{:ok, updated_vod} <- Streams.update_vod(vod, %{torrent_id: torrent.id}) do
|
||||
{:ok, updated_vod}
|
||||
end
|
||||
end
|
||||
|
@ -1,44 +0,0 @@
|
||||
defmodule Bright.Torrent do
|
||||
|
||||
|
||||
alias Bright.Streams.Vod
|
||||
alias Bright.{Cache,Torrentfile,B2}
|
||||
|
||||
|
||||
def bittorrent_tracker_url do
|
||||
Application.fetch_env!(:bright, :bittorrent_tracker_url)
|
||||
end
|
||||
|
||||
def site_url do
|
||||
Application.fetch_env!(:bright, :site_url)
|
||||
end
|
||||
|
||||
|
||||
|
||||
def create_torrent(input_path, output_path, web_seed_url, vod_id) do
|
||||
IO.puts "site_url=#{site_url()}"
|
||||
IO.puts "bittorrent_tracker_url=#{bittorrent_tracker_url()}"
|
||||
tracker_url = bittorrent_tracker_url()
|
||||
source_url = URI.append_path(URI.parse(site_url()), "/vods/#{vod_id}") |> URI.to_string()
|
||||
comment = site_url()
|
||||
meta_version = 3 # hybrid BT v1 & v2
|
||||
|
||||
{:ok, %{btih: btih, btmh: btmh, magnet: magnet, save_path: save_path} = torrentfile} = Torrentfile.create(input_path, output_path, tracker_url, source_url, comment, web_seed_url, meta_version)
|
||||
|
||||
|
||||
# upload to s3
|
||||
basename = Path.basename(save_path)
|
||||
{:ok, asset} = B2.put(save_path, basename)
|
||||
|
||||
{:ok, %{basename: basename, local_path: save_path, magnet_link: magnet, info_hash_v1: btih, info_hash_v2: btmh}}
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
@ -4,6 +4,16 @@ defmodule Bright.Torrentfile do
|
||||
"""
|
||||
|
||||
alias Bright.Cache
|
||||
alias Bright.Streams.Vod
|
||||
|
||||
|
||||
def bittorrent_tracker_url do
|
||||
Application.fetch_env!(:bright, :bt_tracker_url)
|
||||
end
|
||||
|
||||
def site_url do
|
||||
Application.fetch_env!(:bright, :site_url)
|
||||
end
|
||||
|
||||
# @spec execute(command :: Command.t) :: {:ok, binary()} | {:error, {Collectable.t, exit_status :: non_neg_integer}}
|
||||
# def execute(%Command{} = command) do
|
||||
@ -66,7 +76,19 @@ defmodule Bright.Torrentfile do
|
||||
defp extract_last(nil), do: nil
|
||||
defp extract_last(list) when is_list(list), do: List.last(list)
|
||||
|
||||
def create(%Vod{} = vod, input_path) do
|
||||
output_path = Cache.generate_filename("vod-#{vod.id}", "torrent")
|
||||
tracker_url = bittorrent_tracker_url()
|
||||
site_url = site_url()
|
||||
comment = site_url
|
||||
source_url = URI.parse(site_url) |> URI.append_path("/vods/#{vod.id}") |> URI.to_string()
|
||||
web_seed_url = vod.s3_cdn_url
|
||||
meta_version = 3
|
||||
create(input_path, output_path, tracker_url, comment, source_url, web_seed_url, meta_version)
|
||||
end
|
||||
|
||||
def create(input_path, output_path, tracker_url, source_url, comment, web_seed_url, meta_version) do
|
||||
IO.puts "Torrentfile.create called with args input_path=#{input_path}, output_path=#{output_path}, tracker_url=#{tracker_url}, source_url=#{source_url}, comment=#{comment}, web_seed_url=#{web_seed_url}, meta_version=#{meta_version}"
|
||||
case Rambo.run(torrentfile_path(), [
|
||||
"--magnet",
|
||||
"--prog", "0",
|
||||
|
@ -4,20 +4,24 @@ defmodule Bright.Torrents do
|
||||
"""
|
||||
|
||||
import Ecto.Query, warn: false
|
||||
alias Bright.Repo
|
||||
|
||||
alias Bright.Streams.Vod
|
||||
alias Bright.{Repo,Cache,Torrentfile,B2}
|
||||
alias Bright.Torrents.Torrent
|
||||
|
||||
|
||||
|
||||
|
||||
@doc """
|
||||
Returns the list of torrent.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_torrent()
|
||||
iex> list_torrents()
|
||||
[%Torrent{}, ...]
|
||||
|
||||
"""
|
||||
def list_torrent do
|
||||
def list_torrents do
|
||||
Repo.all(Torrent)
|
||||
end
|
||||
|
||||
@ -37,6 +41,7 @@ defmodule Bright.Torrents do
|
||||
"""
|
||||
def get_torrent!(id), do: Repo.get!(Torrent, id)
|
||||
|
||||
|
||||
@doc """
|
||||
Creates a torrent.
|
||||
|
||||
@ -55,6 +60,10 @@ defmodule Bright.Torrents do
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@doc """
|
||||
Updates a torrent.
|
||||
|
||||
@ -101,4 +110,31 @@ defmodule Bright.Torrents do
|
||||
def change_torrent(%Torrent{} = torrent, attrs \\ %{}) do
|
||||
Torrent.changeset(torrent, attrs)
|
||||
end
|
||||
|
||||
|
||||
|
||||
# @doc """
|
||||
# Generates a torrent file on disk, then uploads it to S3
|
||||
# """
|
||||
# def generate_torrent_file(input_path, output_path, web_seed_url, vod_id) do
|
||||
# s3_asset_key = Cache.deterministic_filename("vod", attrs.vod_id, "mp4")
|
||||
# output_path = Cache.generate_filename(s3_asset_key, "torrent")
|
||||
# input_path = Cache.get(s3_asset_key).local_path
|
||||
# tracker_url = bittorrent_tracker_url()
|
||||
# source_url = URI.append_path(URI.parse(site_url()), "/vods/#{vod_id}") |> URI.to_string()
|
||||
# comment = site_url()
|
||||
# meta_version = 3 # hybrid BT v1 & v2
|
||||
|
||||
# {:ok, %{btih: btih, btmh: btmh, magnet: magnet, save_path: save_path} = torrentfile} = Torrentfile.create(input_path, output_path, tracker_url, source_url, comment, web_seed_url, meta_version)
|
||||
|
||||
|
||||
# # upload to s3
|
||||
# {:ok, asset} = B2.put(save_path, s3_asset_key)
|
||||
|
||||
# # {:ok, %{basename: basename, local_path: save_path, magnet_link: magnet, info_hash_v1: btih, info_hash_v2: btmh}}
|
||||
# end
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
@ -1,25 +1,117 @@
|
||||
defmodule Bright.Tracker do
|
||||
|
||||
@unreserved_chars 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~'
|
||||
|
||||
alias Bright.Streams.Vod
|
||||
alias Bright.{Cache,Torrentfile,B2}
|
||||
|
||||
def tracker_url do
|
||||
Application.get_env!(:bright, :bt_tracker_url)
|
||||
def bt_tracker_url do
|
||||
Application.fetch_env!(:bright, :bt_tracker_url)
|
||||
end
|
||||
|
||||
def bt_tracker_accesslist_url do
|
||||
Application.fetch_env!(:bright, :bt_tracker_accesslist_url)
|
||||
end
|
||||
|
||||
|
||||
|
||||
# We start with the `Info hash v1` of the torrent, as copied from qBittorrent.
|
||||
info_hash_v1 = "acc3b2e433d7c7475abb5941b5681cb7a1ea26e2"
|
||||
|
||||
# Next we decode into binary.
|
||||
binary = Base.decode16!(info_hash_v1, case: :lower)
|
||||
|
||||
# Next we
|
||||
|
||||
|
||||
|
||||
|
||||
@doc """
|
||||
Encodes `string` as BEP3's weird URL encoded string.
|
||||
|
||||
## Example
|
||||
|
||||
iex> bep3_encode("a88fda5954e89178c372716a6a78b8180ed4dad3")
|
||||
"%A8%8F%DAYT%E8%91x%C3rqjjx%B8%18%0E%D4%DA%D3"
|
||||
|
||||
"""
|
||||
@spec bep3_encode(binary) :: binary
|
||||
def bep3_encode(string) when is_binary(string) do
|
||||
string = Base.decode16!(string, case: :lower)
|
||||
URI.encode(string, &URI.char_unreserved?/1)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# @spec bep3_encode(binary) :: binary
|
||||
# def bep3_encode(string) when is_binary(string) do
|
||||
# string = Base.decode16!(string, case: :lower)
|
||||
# IO.puts inspect(string)
|
||||
# for <<byte <- string>>, into: "" do
|
||||
# percent(byte, &URI.char_unreserved?/1)
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
|
||||
# defp percent(char, predicate) do
|
||||
# if predicate.(char) do
|
||||
# <<char>>
|
||||
# else
|
||||
# <<"%", hex(Bitwise.bsr(char, 4)), hex(Bitwise.band(char, 15))>>
|
||||
# end
|
||||
# end
|
||||
|
||||
# defp hex(n) when n <= 9, do: n + ?0
|
||||
# defp hex(n), do: n + ?A - 10
|
||||
|
||||
# def url_encode_info_hash(info_hash) do
|
||||
# info_hash |> Base.decode16!(case: :lower) |> URI.encode_www_form() |> String.replace("+", "%20")
|
||||
# end
|
||||
|
||||
def announce_torrent(info_hash) do
|
||||
encoded_info_hash = bep3_encode(info_hash)
|
||||
url = bt_tracker_url() |> URI.parse() |> URI.append_query("info_hash=#{encoded_info_hash}") |> URI.to_string()
|
||||
body = []
|
||||
headers = []
|
||||
|
||||
case HTTPoison.get(url, body, headers) do
|
||||
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
|
||||
IO.puts inspect(Bento.decode(body))
|
||||
{:ok, body}
|
||||
|
||||
{: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 POST. #{inspect(failed)}")
|
||||
{:error, :failed}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def whitelist_info_hash(info_hash) do
|
||||
|
||||
server = "tcp://ncat:8666"
|
||||
port = 8666
|
||||
IO.puts "bt_tracker_accesslist_url=#{bt_tracker_accesslist_url()}"
|
||||
{host, port} = case URI.parse(bt_tracker_accesslist_url()) do
|
||||
%URI{host: host, port: port} when not is_nil(host) and not is_nil(port) ->
|
||||
{host, port}
|
||||
|
||||
_ ->
|
||||
raise "Invalid bt_tracker_accesslist_url: #{bt_tracker_accesslist_url()}"
|
||||
end
|
||||
|
||||
host = String.to_charlist(host)
|
||||
|
||||
# Open a TCP connection
|
||||
{:ok, socket} = :gen_tcp.connect(server, port, [:binary, packet: :raw, active: false])
|
||||
{:ok, socket} = :gen_tcp.connect(host, port, [:binary, packet: :raw, active: false])
|
||||
|
||||
# Send the "hello world" data to the server
|
||||
:gen_tcp.send(socket, "#{info_hash}\n")
|
||||
@ -28,12 +120,6 @@ defmodule Bright.Tracker do
|
||||
:gen_tcp.close(socket)
|
||||
|
||||
|
||||
# url = "http://ncat:6868"
|
||||
# body = [
|
||||
|
||||
# ]
|
||||
# headers = []
|
||||
# HTTPoison.post(url, body, headers)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -0,0 +1,62 @@
|
||||
defmodule BrightWeb.TorrentController do
|
||||
use BrightWeb, :controller
|
||||
|
||||
alias Bright.Torrents
|
||||
alias Bright.Torrents.Torrent
|
||||
|
||||
def index(conn, _params) do
|
||||
torrent = Torrents.list_torrents()
|
||||
render(conn, :index, torrents: torrent)
|
||||
end
|
||||
|
||||
def new(conn, _params) do
|
||||
changeset = Torrents.change_torrent(%Torrent{})
|
||||
render(conn, :new, changeset: changeset)
|
||||
end
|
||||
|
||||
def create(conn, %{"torrent" => torrent_params}) do
|
||||
case Torrents.create_torrent(torrent_params) do
|
||||
{:ok, torrent} ->
|
||||
conn
|
||||
|> put_flash(:info, "Torrent created successfully.")
|
||||
|> redirect(to: ~p"/torrent/#{torrent}")
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
render(conn, :new, changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
torrent = Torrents.get_torrent!(id)
|
||||
render(conn, :show, torrent: torrent)
|
||||
end
|
||||
|
||||
def edit(conn, %{"id" => id}) do
|
||||
torrent = Torrents.get_torrent!(id)
|
||||
changeset = Torrents.change_torrent(torrent)
|
||||
render(conn, :edit, torrent: torrent, changeset: changeset)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, "torrent" => torrent_params}) do
|
||||
torrent = Torrents.get_torrent!(id)
|
||||
|
||||
case Torrents.update_torrent(torrent, torrent_params) do
|
||||
{:ok, torrent} ->
|
||||
conn
|
||||
|> put_flash(:info, "Torrent updated successfully.")
|
||||
|> redirect(to: ~p"/torrent/#{torrent}")
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
render(conn, :edit, torrent: torrent, changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
torrent = Torrents.get_torrent!(id)
|
||||
{:ok, _torrent} = Torrents.delete_torrent(torrent)
|
||||
|
||||
conn
|
||||
|> put_flash(:info, "Torrent deleted successfully.")
|
||||
|> redirect(to: ~p"/torrent")
|
||||
end
|
||||
end
|
13
services/bright/lib/bright_web/controllers/torrent_html.ex
Normal file
13
services/bright/lib/bright_web/controllers/torrent_html.ex
Normal file
@ -0,0 +1,13 @@
|
||||
defmodule BrightWeb.TorrentHTML do
|
||||
use BrightWeb, :html
|
||||
|
||||
embed_templates "torrent_html/*"
|
||||
|
||||
@doc """
|
||||
Renders a torrent form.
|
||||
"""
|
||||
attr :changeset, Ecto.Changeset, required: true
|
||||
attr :action, :string, required: true
|
||||
|
||||
def torrent_form(assigns)
|
||||
end
|
@ -0,0 +1,8 @@
|
||||
<.header>
|
||||
Edit Torrent {@torrent.id}
|
||||
<:subtitle>Use this form to manage torrent records in the database.</:subtitle>
|
||||
</.header>
|
||||
|
||||
<.torrent_form changeset={@changeset} action={~p"/torrent/#{@torrent}"} />
|
||||
|
||||
<.back navigate={~p"/torrent"}>Back to torrent</.back>
|
@ -0,0 +1,26 @@
|
||||
<.header>
|
||||
Listing Torrent
|
||||
<:actions>
|
||||
<.link href={~p"/torrent/new"}>
|
||||
<.button>New Torrent</.button>
|
||||
</.link>
|
||||
</:actions>
|
||||
</.header>
|
||||
|
||||
<.table id="torrent" rows={@torrents} row_click={&JS.navigate(~p"/torrent/#{&1}")}>
|
||||
<:col :let={torrent} label="Info hash v1">{torrent.info_hash_v1}</:col>
|
||||
<:col :let={torrent} label="Info hash v2">{torrent.info_hash_v2}</:col>
|
||||
<:col :let={torrent} label="Cdn url">{torrent.cdn_url}</:col>
|
||||
<:col :let={torrent} label="Magnet">{torrent.magnet}</:col>
|
||||
<:action :let={torrent}>
|
||||
<div class="sr-only">
|
||||
<.link navigate={~p"/torrent/#{torrent}"}>Show</.link>
|
||||
</div>
|
||||
<.link navigate={~p"/torrent/#{torrent}/edit"}>Edit</.link>
|
||||
</:action>
|
||||
<:action :let={torrent}>
|
||||
<.link href={~p"/torrent/#{torrent}"} method="delete" data-confirm="Are you sure?">
|
||||
Delete
|
||||
</.link>
|
||||
</:action>
|
||||
</.table>
|
@ -0,0 +1,8 @@
|
||||
<.header>
|
||||
New Torrent
|
||||
<:subtitle>Use this form to manage torrent records in the database.</:subtitle>
|
||||
</.header>
|
||||
|
||||
<.torrent_form changeset={@changeset} action={~p"/torrent"} />
|
||||
|
||||
<.back navigate={~p"/torrent"}>Back to torrent</.back>
|
@ -0,0 +1,18 @@
|
||||
<.header>
|
||||
Torrent {@torrent.id}
|
||||
<:subtitle>This is a torrent record from the database.</:subtitle>
|
||||
<:actions>
|
||||
<.link href={~p"/torrent/#{@torrent}/edit"}>
|
||||
<.button>Edit torrent</.button>
|
||||
</.link>
|
||||
</:actions>
|
||||
</.header>
|
||||
|
||||
<.list>
|
||||
<:item title="Info hash v1">{@torrent.info_hash_v1}</:item>
|
||||
<:item title="Info hash v2">{@torrent.info_hash_v2}</:item>
|
||||
<:item title="Cdn url">{@torrent.cdn_url}</:item>
|
||||
<:item title="Magnet">{@torrent.magnet}</:item>
|
||||
</.list>
|
||||
|
||||
<.back navigate={~p"/torrent"}>Back to torrent</.back>
|
@ -0,0 +1,12 @@
|
||||
<.simple_form :let={f} for={@changeset} action={@action}>
|
||||
<.error :if={@changeset.action}>
|
||||
Oops, something went wrong! Please check the errors below.
|
||||
</.error>
|
||||
<.input field={f[:info_hash_v1]} type="text" label="Info hash v1" />
|
||||
<.input field={f[:info_hash_v2]} type="text" label="Info hash v2" />
|
||||
<.input field={f[:cdn_url]} type="text" label="Cdn url" />
|
||||
<.input field={f[:magnet]} type="text" label="Magnet" />
|
||||
<:actions>
|
||||
<.button>Save Torrent</.button>
|
||||
</:actions>
|
||||
</.simple_form>
|
26
services/bright/lib/bright_web/controllers/torrent_json.ex
Normal file
26
services/bright/lib/bright_web/controllers/torrent_json.ex
Normal file
@ -0,0 +1,26 @@
|
||||
defmodule BrightWeb.TorrentJSON do
|
||||
alias Bright.Torrents.Torrent
|
||||
@doc """
|
||||
Renders a list of torrents.
|
||||
"""
|
||||
def index(%{torrents: torrents}) do
|
||||
%{data: for(torrent <- torrents, do: data(torrent))}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a single torrent.
|
||||
"""
|
||||
def show(%{torrent: torrent}) do
|
||||
%{data: data(torrent)}
|
||||
end
|
||||
|
||||
defp data(%Torrent{} = torrent) do
|
||||
%{
|
||||
id: torrent.id,
|
||||
info_hash_v1: torrent.info_hash_v1,
|
||||
info_hash_v2: torrent.info_hash_v2,
|
||||
cdn_url: torrent.cdn_url,
|
||||
magnet: torrent.magnet
|
||||
}
|
||||
end
|
||||
end
|
@ -88,7 +88,7 @@ defmodule BrightWeb.Router do
|
||||
post("/join", UserController, :join)
|
||||
post("/join", UserController, :join)
|
||||
|
||||
resources("/orders", OrderController, only: [:create, :show])
|
||||
resources("/torrents", TorrentController, only: [:index, :show])
|
||||
|
||||
get("/streams", StreamController, :index)
|
||||
get("/streams/:id", StreamController, :show)
|
||||
|
@ -67,6 +67,7 @@ defmodule Bright.MixProject do
|
||||
{:sweet_xml, "~> 0.6"},
|
||||
{:ex_m3u8, "~> 0.14.2"},
|
||||
{:atomex, "~> 0.3.0"},
|
||||
{:bento, "~> 1.0"},
|
||||
# {:membrane_core, "~> 1.0"},
|
||||
# {:membrane_mpeg_ts_plugin, "~> 1.0.3"},
|
||||
# {:membrane_file_plugin, "~> 0.17.2"},
|
||||
|
@ -2,6 +2,7 @@
|
||||
"atomex": {:hex, :atomex, "0.3.0", "19b5d1a2aef8706dbd307385f7d5d9f6f273869226d317492c396c7bacf26402", [:mix], [{:xml_builder, "~> 2.0.0", [hex: :xml_builder, repo: "hexpm", optional: false]}], "hexpm", "025dbc3a3e99380894791a093019f535d0ef6cf1916f6ec1b778ac107fcfc3e4"},
|
||||
"bandit": {:hex, :bandit, "1.6.6", "f2019a95261d400579075df5bc15641ba8e446cc4777ede6b4ec19e434c3340d", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "ceb19bf154bc2c07ee0c9addf407d817c48107e36a66351500846fc325451bf9"},
|
||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.2.0", "feab711974beba4cb348147170346fe097eea2e840db4e012a145e180ed4ab75", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "563e92a6c77d667b19c5f4ba17ab6d440a085696bdf4c68b9b0f5b30bc5422b8"},
|
||||
"bento": {:hex, :bento, "1.0.0", "5097e6f02e4980b72d08bf0270026f6f5c9bf5d8ca606b43d41321b549d49de8", [:mix], [], "hexpm", "b921b335a555f7570adfac0cc41864c76377f6852617cf1f25fbb88578b993c8"},
|
||||
"bimap": {:hex, :bimap, "1.3.0", "3ea4832e58dc83a9b5b407c6731e7bae87458aa618e6d11d8e12114a17afa4b3", [:mix], [], "hexpm", "bf5a2b078528465aa705f405a5c638becd63e41d280ada41e0f77e6d255a10b4"},
|
||||
"bulma": {:hex, :bulma, "1.0.2", "50dfffe8d28b0bd527418560223b407f9e80e990e187e1653b17eff818f8fcbe", [:mix], [], "hexpm", "27745727ff7f451d140a2438c0ca4448bc8ca73e0a6d2d4f24e1b5b9ced8a774"},
|
||||
"bunch": {:hex, :bunch, "1.6.1", "5393d827a64d5f846092703441ea50e65bc09f37fd8e320878f13e63d410aec7", [:mix], [], "hexpm", "286cc3add551628b30605efbe2fca4e38cc1bea89bcd0a1a7226920b3364fe4a"},
|
||||
|
55
services/bright/test/bright/bittorrent_url_encode_test.ex
Normal file
55
services/bright/test/bright/bittorrent_url_encode_test.ex
Normal file
@ -0,0 +1,55 @@
|
||||
defmodule Bright.BittorrentUrlEncodeTest do
|
||||
use ExUnit.Case
|
||||
doctest Bright.BittorrentUrlEncode
|
||||
alias Bright.BittorrentUrlEncode
|
||||
|
||||
test "The WIRED CD - Rip. Sample. Mash. Share a8 8f da 59 54 e8 91 78 c3 72 71 6a 6a 78 b8 18 0e d4 da d3" do
|
||||
actual = BittorrentUrlEncode.encode("a88fda5954e89178c372716a6a78b8180ed4dad3")
|
||||
expected = "%a8%8f%daYT%e8%91x%c3rqjjx%b8%18%0e%d4%da%d3"
|
||||
assert actual === expected
|
||||
end
|
||||
|
||||
test "tails-amd64-6.10-img 07 b4 51 63 36 e4 af e9 23 2c 73 bc 31 26 42 59 0a 7d 7e 95" do
|
||||
actual = BittorrentUrlEncode.encode("07b4516336e4afe9232c73bc312642590a7d7e95")
|
||||
expected = "%07%b4Qc6%e4%af%e9%23%2cs%bc1%26BY%0a%7d~%95"
|
||||
assert actual === expected
|
||||
end
|
||||
|
||||
test "linuxmint-22-mate-64bit.iso e0 a4 05 8e 40 7d dd ad 1c ac f8 c9 ce db 0b 27 21 c0 7f 92" do
|
||||
actual = BittorrentUrlEncode.encode("e0a4058e407dddad1cacf8c9cedb0b2721c07f92")
|
||||
expected = "%e0%a4%05%8e%40%7d%dd%ad%1c%ac%f8%c9%ce%db%0b%27!%c0%7f%92"
|
||||
assert actual === expected
|
||||
end
|
||||
|
||||
test "debian-12.8.0-amd64-DVD-1.iso 56 3e 72 81 c0 00 e1 80 91 e5 c0 d3 9d 09 8c ff 13 5d ab 26" do
|
||||
actual = BittorrentUrlEncode.encode("563e7281c000e18091e5c0d39d098cff135dab26")
|
||||
expected = "V%3er%81%c0%00%e1%80%91%e5%c0%d3%9d%09%8c%ff%13%5d%ab%26"
|
||||
assert actual === expected
|
||||
end
|
||||
|
||||
test "KNOPPIX_V9.1DVD-2021-01-25-EN c0 3b b7 09 bd 7e fe 79 68 87 75 c4 fc 92 51 41 e4 1d b2 87" do
|
||||
actual = BittorrentUrlEncode.encode("c03bb709bd7efe79688775c4fc925141e41db287")
|
||||
expected = "%c0%3b%b7%09%bd~%feyh%87u%c4%fc%92QA%e4%1d%b2%87"
|
||||
assert actual === expected
|
||||
end
|
||||
|
||||
test "Peppermint-7-20160616-i386.iso 72 c3 7d bf e4 39 0f 1b 74 b9 b4 25 07 e8 97 01 b4 9e c7 a3" do
|
||||
actual = BittorrentUrlEncode.encode("72c37dbfe4390f1b74b9b42507e89701b49ec7a3")
|
||||
expected = "r%c3%7d%bf%e49%0f%1bt%b9%b4%25%07%e8%97%01%b4%9e%c7%a3"
|
||||
assert actual === expected
|
||||
end
|
||||
|
||||
test "crunchbang-11-20130506-i686.iso 88 fa 85 16 ca 2b 3d 3d 41 86 75 20 84 f9 3a 59 91 8f a3 51" do
|
||||
actual = BittorrentUrlEncode.encode("88fa8516ca2b3d3d4186752084f93a59918fa351")
|
||||
expected = "%88%fa%85%16%ca%2b%3d%3dA%86u%20%84%f9%3aY%91%8f%a3Q"
|
||||
assert actual === expected
|
||||
end
|
||||
|
||||
test "kali-linux-2024.3-installer-amd64.iso 7b 14 90 47 4e 51 53 6e 1a 7a c0 df ec 24 67 e8 6d a2 32 a4" do
|
||||
actual = BittorrentUrlEncode.encode("7b1490474e51536e1a7ac0dfec2467e86da232a4")
|
||||
expected = "%7b%14%90GNQSn%1az%c0%df%ec%24g%e8m%a22%a4"
|
||||
assert actual === expected
|
||||
end
|
||||
|
||||
|
||||
end
|
@ -14,19 +14,11 @@ defmodule Bright.CacheTest do
|
||||
## To implement this cache before the system works is pre-mature optimization!
|
||||
|
||||
# describe "cache k/v" do
|
||||
# test "get/1 with string cache key" do
|
||||
# test "get/1 with string cache key" do
|
||||
|
||||
# end
|
||||
# end
|
||||
|
||||
# test "get/1 with %Vod{}" do
|
||||
# stream = stream_fixture()
|
||||
# vod = vod_fixture(%{stream_id: stream.id})
|
||||
# Cache.get(vod)
|
||||
# end
|
||||
|
||||
# test "put/2" do
|
||||
|
||||
# end
|
||||
# end
|
||||
|
||||
describe "cache" do
|
||||
|
@ -20,7 +20,7 @@ defmodule Bright.CreateTorrentTest do
|
||||
@tag :integration
|
||||
test "torrent creation" do
|
||||
stream = stream_fixture()
|
||||
vod = vod_fixture(%{torrent: nil, stream_id: stream.id, origin_temp_input_url: @test_video_url})
|
||||
vod = vod_fixture(%{torrent: nil, stream_id: stream.id, s3_cdn_url: @test_video_url})
|
||||
{:ok, %Vod{torrent: torrent, magnet_link: magnet_link, info_hash_v1: info_hash_v1, info_hash_v2: info_hash_v2}}
|
||||
= perform_job(Bright.ObanWorkers.CreateTorrent, %{vod_id: vod.id})
|
||||
assert Regex.match?(~r/^https:\/\/.*\.torrent$/, torrent)
|
||||
|
@ -1,49 +0,0 @@
|
||||
defmodule Bright.TorrentTest do
|
||||
use Bright.DataCase
|
||||
|
||||
alias Bright.Torrent
|
||||
|
||||
|
||||
describe "torrent" do
|
||||
|
||||
import Bright.StreamsFixtures
|
||||
alias Bright.{Downloader,Cache}
|
||||
|
||||
@test_fixture "https://futureporn-b2.b-cdn.net/test-fixture.ts"
|
||||
|
||||
# @tag :integration
|
||||
# test "create_torrent/1" do
|
||||
# stream = stream_fixture()
|
||||
# vod = vod_fixture(%{stream_id: stream.id, s3_cdn_url: "https://futureporn-b2.b-cdn.net/test-fixture.ts"})
|
||||
# {:ok, _} = Torrent.create_torrent(vod)
|
||||
# assert :ok
|
||||
# end
|
||||
|
||||
@tag :integration
|
||||
test "create_torrent/7" do
|
||||
stream = stream_fixture()
|
||||
vod = vod_fixture(%{stream_id: stream.id, s3_cdn_url: "https://futureporn-b2.b-cdn.net/test-fixture.ts"})
|
||||
input_path = Path.absname("./test/fixtures/test-fixture.ts")
|
||||
output_path = Cache.generate_filename("test", "torrent")
|
||||
tracker_url = "https://tracker.futureporn.net/announce"
|
||||
source_url = "https://futureporn.net/vods/69"
|
||||
comment = "https://futureporn.net"
|
||||
web_seed_url = @test_fixture
|
||||
meta_version = 3
|
||||
IO.puts "input_path=#{input_path} output_path=#{output_path} tracker_url=#{tracker_url} source_url=#{source_url}"
|
||||
{:ok, %{local_path: local_path, magnet_link: magnet_link, basename: basename, info_hash_v1: info_hash_v1, info_hash_v2: info_hash_v2}}
|
||||
= Torrent.create_torrent(input_path, output_path, web_seed_url, vod.id)
|
||||
assert :ok
|
||||
assert local_path === output_path
|
||||
assert File.exists?(output_path)
|
||||
assert String.starts_with?(magnet_link, "magnet:")
|
||||
assert String.ends_with?(basename, ".torrent")
|
||||
assert is_binary(info_hash_v1)
|
||||
assert is_binary(info_hash_v2)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
end
|
@ -23,6 +23,15 @@ defmodule Bright.TorrentfileTest do
|
||||
assert Regex.match?(~r"\/torrentfile", Torrentfile.torrentfile_path())
|
||||
end
|
||||
|
||||
test "create/2" do
|
||||
{:ok, output} = Torrentfile.create(vod, input_path)
|
||||
assert :ok
|
||||
assert is_binary(output.save_path)
|
||||
assert output.save_path === output_path
|
||||
assert is_binary(output.btih)
|
||||
assert is_binary(output.btmh)
|
||||
assert File.exists?(output_path)
|
||||
end
|
||||
|
||||
test "create/7" do
|
||||
input_path = @test_ts_fixture
|
||||
@ -30,9 +39,9 @@ defmodule Bright.TorrentfileTest do
|
||||
tracker_url = @test_tracker_url
|
||||
comment = @test_comment
|
||||
source_url = @test_source_url
|
||||
web_Seed_url = @test_web_seed_url
|
||||
web_seed_url = @test_web_seed_url
|
||||
meta_version = 3
|
||||
{:ok, output} = Torrentfile.create(input_path, output_path, tracker_url, comment, source_url, web_Seed_url, meta_version)
|
||||
{:ok, output} = Torrentfile.create(input_path, output_path, tracker_url, comment, source_url, web_seed_url, meta_version)
|
||||
|
||||
assert :ok
|
||||
assert is_binary(output.save_path)
|
||||
|
@ -2,17 +2,21 @@ defmodule Bright.TorrentsTest do
|
||||
use Bright.DataCase
|
||||
|
||||
alias Bright.Torrents
|
||||
alias Bright.{Downloader,Cache}
|
||||
|
||||
describe "torrent" do
|
||||
@test_fixture "https://futureporn-b2.b-cdn.net/test-fixture.ts"
|
||||
|
||||
|
||||
describe "torrents" do
|
||||
alias Bright.Torrents.Torrent
|
||||
|
||||
import Bright.TorrentsFixtures
|
||||
|
||||
@invalid_attrs %{info_hash_v1: nil, info_hash_v2: nil, cdn_url: nil, magnet: nil}
|
||||
|
||||
test "list_torrent/0 returns all torrent" do
|
||||
test "list_torrents/0 returns all torrent" do
|
||||
torrent = torrent_fixture()
|
||||
assert Torrents.list_torrent() == [torrent]
|
||||
assert Torrents.list_torrents() == [torrent]
|
||||
end
|
||||
|
||||
test "get_torrent!/1 returns the torrent with given id" do
|
||||
@ -61,5 +65,32 @@ defmodule Bright.TorrentsTest do
|
||||
torrent = torrent_fixture()
|
||||
assert %Ecto.Changeset{} = Torrents.change_torrent(torrent)
|
||||
end
|
||||
|
||||
|
||||
|
||||
@tag :integration
|
||||
test "generate_torrent_file/7" do
|
||||
stream = stream_fixture()
|
||||
vod = vod_fixture(%{stream_id: stream.id, s3_cdn_url: "https://futureporn-b2.b-cdn.net/test-fixture.ts"})
|
||||
input_path = Path.absname("./test/fixtures/test-fixture.ts")
|
||||
output_path = Cache.generate_filename("test", "torrent")
|
||||
tracker_url = "https://tracker.futureporn.net/announce"
|
||||
source_url = "https://futureporn.net/vods/69"
|
||||
comment = "https://futureporn.net"
|
||||
web_seed_url = @test_fixture
|
||||
meta_version = 3
|
||||
IO.puts "input_path=#{input_path} output_path=#{output_path} tracker_url=#{tracker_url} source_url=#{source_url}"
|
||||
{:ok, %{local_path: local_path, magnet_link: magnet_link, basename: basename, info_hash_v1: info_hash_v1, info_hash_v2: info_hash_v2}}
|
||||
= Torrent.create_torrent(input_path, output_path, web_seed_url, vod.id)
|
||||
assert :ok
|
||||
assert local_path === output_path
|
||||
assert File.exists?(output_path)
|
||||
assert String.starts_with?(magnet_link, "magnet:")
|
||||
assert String.ends_with?(basename, ".torrent")
|
||||
assert is_binary(info_hash_v1)
|
||||
assert is_binary(info_hash_v2)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -2,39 +2,60 @@ defmodule Bright.TrackerTest do
|
||||
use Bright.DataCase
|
||||
|
||||
alias Bright.Tracker
|
||||
alias Bright.URLEncoder
|
||||
|
||||
describe "tracker" do
|
||||
|
||||
import Bright.StreamsFixtures
|
||||
|
||||
@info_hash_fixture "723886c0b0d9d41bfaa5276a9b2552d84ba09dd8a77d9ddcab5c9fa16cdb9770" # test-fixture.ts (BT info_hash v2)
|
||||
@info_hash_v2_fixture "723886c0b0d9d41bfaa5276a9b2552d84ba09dd8a77d9ddcab5c9fa16cdb9770" # test-fixture.ts (BT info_hash v2)
|
||||
@info_hash_v1_fixture "157835a64d398fd63d83b5fd6dac5612bd60b6c6" # test-fixture.ts (BT info_hash v1)
|
||||
|
||||
|
||||
@tag :integration
|
||||
test "whitelist_info_hash/1 using a string info_hash" do
|
||||
:ok = Tracker.whitelist_info_hash(@info_hash_fixture)
|
||||
assert :ok
|
||||
end
|
||||
|
||||
@tag :integration
|
||||
test "whitelist_info_hash/1 using a %Vod{}" do
|
||||
stream = stream_fixture()
|
||||
vod = vod_fixture(%{stream_id: stream.id})
|
||||
:ok = Tracker.whitelist_info_hash(vod)
|
||||
:ok = Tracker.whitelist_info_hash(@info_hash_v2_fixture)
|
||||
assert :ok
|
||||
end
|
||||
|
||||
@tag :integration
|
||||
test "announce_torrent/1 using a string info_hash" do
|
||||
:ok = Tracker.announce_torrent(@info_hash_fixture)
|
||||
{:ok, body} = Tracker.announce_torrent(@info_hash_v1_fixture)
|
||||
assert :ok
|
||||
end
|
||||
|
||||
@tag :integration
|
||||
test "announce_torrent/1 using a %Vod{}" do
|
||||
stream = stream_fixture()
|
||||
vod = vod_fixture(%{stream_id: stream.id, info_hash: @info_hash_fixture})
|
||||
:ok = Tracker.announce_torrent(vod)
|
||||
assert :ok
|
||||
@tag :unit
|
||||
@tag :bep3
|
||||
test "bep3_encode/1 projekt-melody.jpg" do
|
||||
|
||||
## projekt-melody.jpg
|
||||
info_hash_v1 = "4a7620a29789ca70c6e461a11da810bd1d253fc6"
|
||||
expected_output = "Jv%20%a2%97%89%cap%c6%e4a%a1%1d%a8%10%bd%1d%25%3f%c6"
|
||||
assert Tracker.bep3_encode(info_hash_v1) === expected_output
|
||||
|
||||
end
|
||||
|
||||
@tag :unit
|
||||
@tag :bep3
|
||||
test "bep3_encode/1 StackOverflow" do
|
||||
|
||||
## @see https://stackoverflow.com/a/40000337/1004931
|
||||
info_hash_v1 = "acc3b2e433d7c7475abb5941b5681cb7a1ea26e2"
|
||||
expected_output = "%ac%c3%b2%e43%d7%c7GZ%bbYA%b5h%1c%b7%a1%ea%26%e2"
|
||||
assert Tracker.bep3_encode(info_hash_v1) === expected_output
|
||||
|
||||
end
|
||||
|
||||
@tag :unit
|
||||
@tag :bep3
|
||||
test "bep3_encode/1 WIRED CD" do
|
||||
|
||||
info_hash_v1 = "a88fda5954e89178c372716a6a78b8180ed4dad3"
|
||||
expected_output = "%A8%8F%DAYT%E8%91x%C3rqjjx%B8%18%0E%D4%DA%D3"
|
||||
actual = Tracker.bep3_encode(info_hash_v1)
|
||||
IO.puts actual
|
||||
assert actual === expected_output
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -0,0 +1,84 @@
|
||||
defmodule BrightWeb.TorrentControllerTest do
|
||||
use BrightWeb.ConnCase
|
||||
|
||||
import Bright.TorrentsFixtures
|
||||
|
||||
@create_attrs %{info_hash_v1: "some info_hash_v1", info_hash_v2: "some info_hash_v2", cdn_url: "some cdn_url", magnet: "some magnet"}
|
||||
@update_attrs %{info_hash_v1: "some updated info_hash_v1", info_hash_v2: "some updated info_hash_v2", cdn_url: "some updated cdn_url", magnet: "some updated magnet"}
|
||||
@invalid_attrs %{info_hash_v1: nil, info_hash_v2: nil, cdn_url: nil, magnet: nil}
|
||||
|
||||
describe "index" do
|
||||
test "lists all torrent", %{conn: conn} do
|
||||
conn = get(conn, ~p"/torrent")
|
||||
assert html_response(conn, 200) =~ "Listing Torrent"
|
||||
end
|
||||
end
|
||||
|
||||
describe "new torrent" do
|
||||
test "renders form", %{conn: conn} do
|
||||
conn = get(conn, ~p"/torrent/new")
|
||||
assert html_response(conn, 200) =~ "New Torrent"
|
||||
end
|
||||
end
|
||||
|
||||
describe "create torrent" do
|
||||
test "redirects to show when data is valid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/torrent", torrent: @create_attrs)
|
||||
|
||||
assert %{id: id} = redirected_params(conn)
|
||||
assert redirected_to(conn) == ~p"/torrent/#{id}"
|
||||
|
||||
conn = get(conn, ~p"/torrent/#{id}")
|
||||
assert html_response(conn, 200) =~ "Torrent #{id}"
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/torrent", torrent: @invalid_attrs)
|
||||
assert html_response(conn, 200) =~ "New Torrent"
|
||||
end
|
||||
end
|
||||
|
||||
describe "edit torrent" do
|
||||
setup [:create_torrent]
|
||||
|
||||
test "renders form for editing chosen torrent", %{conn: conn, torrent: torrent} do
|
||||
conn = get(conn, ~p"/torrent/#{torrent}/edit")
|
||||
assert html_response(conn, 200) =~ "Edit Torrent"
|
||||
end
|
||||
end
|
||||
|
||||
describe "update torrent" do
|
||||
setup [:create_torrent]
|
||||
|
||||
test "redirects when data is valid", %{conn: conn, torrent: torrent} do
|
||||
conn = put(conn, ~p"/torrent/#{torrent}", torrent: @update_attrs)
|
||||
assert redirected_to(conn) == ~p"/torrent/#{torrent}"
|
||||
|
||||
conn = get(conn, ~p"/torrent/#{torrent}")
|
||||
assert html_response(conn, 200) =~ "some updated info_hash_v1"
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, torrent: torrent} do
|
||||
conn = put(conn, ~p"/torrent/#{torrent}", torrent: @invalid_attrs)
|
||||
assert html_response(conn, 200) =~ "Edit Torrent"
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete torrent" do
|
||||
setup [:create_torrent]
|
||||
|
||||
test "deletes chosen torrent", %{conn: conn, torrent: torrent} do
|
||||
conn = delete(conn, ~p"/torrent/#{torrent}")
|
||||
assert redirected_to(conn) == ~p"/torrent"
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, ~p"/torrent/#{torrent}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp create_torrent(_) do
|
||||
torrent = torrent_fixture()
|
||||
%{torrent: torrent}
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user