summaryrefslogtreecommitdiff
path: root/lib/plugins/link
diff options
context:
space:
mode:
Diffstat (limited to 'lib/plugins/link')
-rw-r--r--lib/plugins/link/github.ex18
-rw-r--r--lib/plugins/link/image.ex110
-rw-r--r--lib/plugins/link/img_debrid_link.ex16
-rw-r--r--lib/plugins/link/imgur.ex37
-rw-r--r--lib/plugins/link/pdf.ex24
-rw-r--r--lib/plugins/link/redacted.ex6
-rw-r--r--lib/plugins/link/reddit.ex149
-rw-r--r--lib/plugins/link/scraper.ex39
-rw-r--r--lib/plugins/link/store.ex1
-rw-r--r--lib/plugins/link/twitter.ex127
-rw-r--r--lib/plugins/link/youtube.ex53
11 files changed, 361 insertions, 219 deletions
diff --git a/lib/plugins/link/github.ex b/lib/plugins/link/github.ex
index 77fa81f..fcd76a0 100644
--- a/lib/plugins/link/github.ex
+++ b/lib/plugins/link/github.ex
@@ -45,10 +45,14 @@ defmodule Nola.Plugins.Link.Github do
end
defp build_start(info) do
- parts = []
- |> maybe_add(info.disabled, " (disabled)")
- |> maybe_add(info.archived, " (archived)")
- |> maybe_add(info.source && info.source["full_name"] != info.full_name, " (⑂ #{info.source["full_name"]})")
+ parts =
+ []
+ |> maybe_add(info.disabled, " (disabled)")
+ |> maybe_add(info.archived, " (archived)")
+ |> maybe_add(
+ info.source && info.source["full_name"] != info.full_name,
+ " (⑂ #{info.source["full_name"]})"
+ )
"#{info.full_name}#{parts} - #{info.description}"
end
@@ -58,8 +62,9 @@ defmodule Nola.Plugins.Link.Github do
end
defp build_network(info) do
- lang = info.language && "#{info.language} - " || ""
- issues = info.open_issues_count && "#{info.open_issues_count} issues - " || ""
+ lang = (info.language && "#{info.language} - ") || ""
+ issues = (info.open_issues_count && "#{info.open_issues_count} issues - ") || ""
+
last_push =
if at = info.pushed_at do
{:ok, date, _} = DateTime.from_iso8601(at)
@@ -67,6 +72,7 @@ defmodule Nola.Plugins.Link.Github do
else
""
end
+
"#{lang}#{issues}#{info.stargazers_count} stars - #{info.subscribers_count} watchers - #{info.forks_count} forks#{last_push}"
end
diff --git a/lib/plugins/link/image.ex b/lib/plugins/link/image.ex
index cf3d9b0..2fb6862 100644
--- a/lib/plugins/link/image.ex
+++ b/lib/plugins/link/image.ex
@@ -6,7 +6,7 @@ defmodule Nola.Plugins.Link.Image do
def match(_, _), do: false
@impl true
- def post_match(_url, "image/"<>_, _header, _opts) do
+ def post_match(_url, "image/" <> _, _header, _opts) do
{:body, nil}
end
@@ -16,65 +16,77 @@ defmodule Nola.Plugins.Link.Image do
def post_expand(_url, bytes, _, opts) do
pil_process = Keyword.get(opts, :pil_process, {:pil, :"py@127.0.0.1"})
clip_ask_process = Keyword.get(opts, :clip_ask_process, {:clip_ask, :"py@127.0.0.1"})
- img2txt_process = Keyword.get(opts, :img2txt_process, {:image_to_text_vit_gpt2, :"py@127.0.0.1"})
-
- tasks = [
- Task.async(fn ->
- {:ok, pil} = GenServer.call(pil_process, {:run, bytes})
- pil = pil
- |> Enum.map(fn({k, v}) -> {String.to_atom(to_string(k)), v} end)
- pil
- end),
- Task.async(fn ->
- {:ok, descr} = GenServer.call(img2txt_process, {:run, bytes})
- {:img2txt, to_string(descr)}
- end),
- Task.async(fn ->
- {:ok, prompts} = GenServer.call(clip_ask_process, {:run, bytes})
-
- prompts = prompts
- |> Enum.sort_by(& elem(&1, 1), &>=/2)
- |> Enum.take(3)
- |> Enum.map(& to_string(elem(&1, 0)))
- |> Enum.join(", ")
- {:prompts, prompts}
+
+ img2txt_process =
+ Keyword.get(opts, :img2txt_process, {:image_to_text_vit_gpt2, :"py@127.0.0.1"})
+
+ tasks =
+ [
+ Task.async(fn ->
+ {:ok, pil} = GenServer.call(pil_process, {:run, bytes})
+
+ pil =
+ pil
+ |> Enum.map(fn {k, v} -> {String.to_atom(to_string(k)), v} end)
+
+ pil
+ end),
+ Task.async(fn ->
+ {:ok, descr} = GenServer.call(img2txt_process, {:run, bytes})
+ {:img2txt, to_string(descr)}
+ end),
+ Task.async(fn ->
+ {:ok, prompts} = GenServer.call(clip_ask_process, {:run, bytes})
+
+ prompts =
+ prompts
+ |> Enum.sort_by(&elem(&1, 1), &>=/2)
+ |> Enum.take(3)
+ |> Enum.map(&to_string(elem(&1, 0)))
+ |> Enum.join(", ")
+
+ {:prompts, prompts}
+ end)
+ ]
+ |> Task.yield_many(5000)
+ |> Enum.map(fn {task, res} ->
+ res || Task.shutdown(task, :brutal_kill)
end)
- ]
- |> Task.yield_many(5000)
- |> Enum.map(fn {task, res} ->
- res || Task.shutdown(task, :brutal_kill)
- end)
- results = Enum.into(List.flatten(for({:ok, value} <- tasks, do: value)), Map.new)
+ results = Enum.into(List.flatten(for({:ok, value} <- tasks, do: value)), Map.new())
img2txt = Map.get(results, :img2txt)
prompts = Map.get(results, :prompts)
- pil = if Map.get(results, :width) do
- animated = if Map.get(results, :animated), do: " animated", else: ""
- "#{Map.get(results, :width, 0)}x#{Map.get(results, :height, 0)}#{animated} — "
- else
- ""
- end
+ pil =
+ if Map.get(results, :width) do
+ animated = if Map.get(results, :animated), do: " animated", else: ""
+ "#{Map.get(results, :width, 0)}x#{Map.get(results, :height, 0)}#{animated} — "
+ else
+ ""
+ end
- descr = cond do
- img2txt && prompts ->
- "#{pil}#{prompts} — #{img2txt}"
- img2txt ->
- "#{pil}#{img2txt}"
- prompts ->
- "#{pil}#{prompts}"
- pil != "" ->
- "#{pil}"
- true ->
- nil
- end
+ descr =
+ cond do
+ img2txt && prompts ->
+ "#{pil}#{prompts} — #{img2txt}"
+
+ img2txt ->
+ "#{pil}#{img2txt}"
+
+ prompts ->
+ "#{pil}#{prompts}"
+
+ pil != "" ->
+ "#{pil}"
+
+ true ->
+ nil
+ end
if descr do
{:ok, "image: #{descr}"}
else
:error
end
-
end
-
end
diff --git a/lib/plugins/link/img_debrid_link.ex b/lib/plugins/link/img_debrid_link.ex
index a2972eb..b46c430 100644
--- a/lib/plugins/link/img_debrid_link.ex
+++ b/lib/plugins/link/img_debrid_link.ex
@@ -16,17 +16,17 @@ defmodule Nola.Plugins.Link.ImgDebridLink do
@impl true
def expand(_uri, %{id: ids}, _opts) do
- with \
- {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- HTTPoison.get("https://img.debrid-link.fr/api/v1/images/#{ids}/infos", [], []),
- {:ok, %{"success" => true, "value" => values}} <- Jason.decode(body)
- do
- items = for %{"name" => name, "url" => %{"direct" => direct_url}} <- values do
- "#{name}: #{direct_url}"
- end
+ with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
+ HTTPoison.get("https://img.debrid-link.fr/api/v1/images/#{ids}/infos", [], []),
+ {:ok, %{"success" => true, "value" => values}} <- Jason.decode(body) do
+ items =
+ for %{"name" => name, "url" => %{"direct" => direct_url}} <- values do
+ "#{name}: #{direct_url}"
+ end
+
{:ok, items}
else
_ -> :error
end
end
-
end
diff --git a/lib/plugins/link/imgur.ex b/lib/plugins/link/imgur.ex
index 9fe9354..49bbb7d 100644
--- a/lib/plugins/link/imgur.ex
+++ b/lib/plugins/link/imgur.ex
@@ -19,19 +19,24 @@ defmodule Nola.Plugins.Link.Imgur do
def match(uri = %URI{host: "imgur.io"}, arg) do
match(%URI{uri | host: "imgur.com"}, arg)
end
+
def match(uri = %URI{host: "i.imgur.io"}, arg) do
match(%URI{uri | host: "i.imgur.com"}, arg)
end
- def match(uri = %URI{host: "imgur.com", path: "/a/"<>album_id}, _) do
+
+ def match(uri = %URI{host: "imgur.com", path: "/a/" <> album_id}, _) do
{true, %{album_id: album_id}}
end
- def match(uri = %URI{host: "imgur.com", path: "/gallery/"<>album_id}, _) do
+
+ def match(uri = %URI{host: "imgur.com", path: "/gallery/" <> album_id}, _) do
{true, %{album_id: album_id}}
end
- def match(uri = %URI{host: "i.imgur.com", path: "/"<>image}, _) do
+
+ def match(uri = %URI{host: "i.imgur.com", path: "/" <> image}, _) do
[hash, _] = String.split(image, ".", parts: 2)
{true, %{image_id: hash}}
end
+
def match(_, _), do: false
@impl true
@@ -49,6 +54,7 @@ defmodule Nola.Plugins.Link.Imgur do
client_id = Keyword.get(Application.get_env(:nola, :imgur, []), :client_id, "42")
headers = [{"Authorization", "Client-ID #{client_id}"}]
options = []
+
case HTTPoison.get("https://api.imgur.com/3/image/#{image_id}", headers, options) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
{:ok, json} = Jason.decode(body)
@@ -59,6 +65,7 @@ defmodule Nola.Plugins.Link.Imgur do
width = Map.get(data, "width")
size = Map.get(data, "size")
{:ok, "image, #{width}x#{height}, #{size} bytes #{nsfw}#{title}"}
+
other ->
:error
end
@@ -68,6 +75,7 @@ defmodule Nola.Plugins.Link.Imgur do
client_id = Keyword.get(Application.get_env(:nola, :imgur, []), :client_id, "42")
headers = [{"Authorization", "Client-ID #{client_id}"}]
options = []
+
case HTTPoison.get("https://api.imgur.com/3/album/#{album_id}", headers, options) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
{:ok, json} = Jason.decode(body)
@@ -75,22 +83,31 @@ defmodule Nola.Plugins.Link.Imgur do
title = data["title"]
nsfw = data["nsfw"]
nsfw = if nsfw, do: "(NSFW) - ", else: ""
+
if data["images_count"] == 1 do
[image] = data["images"]
- title = if title || data["title"] do
- title = [title, data["title"]] |> Enum.filter(fn(x) -> x end) |> Enum.uniq() |> Enum.join(" — ")
- "#{title} — "
- else
- ""
- end
+
+ title =
+ if title || data["title"] do
+ title =
+ [title, data["title"]]
+ |> Enum.filter(fn x -> x end)
+ |> Enum.uniq()
+ |> Enum.join(" — ")
+
+ "#{title} — "
+ else
+ ""
+ end
+
{:ok, "#{nsfw}#{title}#{image["link"]}"}
else
title = if title, do: title, else: "Untitled album"
{:ok, "#{nsfw}#{title} - #{data["images_count"]} images"}
end
+
other ->
:error
end
end
-
end
diff --git a/lib/plugins/link/pdf.ex b/lib/plugins/link/pdf.ex
index e91dcc2..bb14594 100644
--- a/lib/plugins/link/pdf.ex
+++ b/lib/plugins/link/pdf.ex
@@ -6,7 +6,7 @@ defmodule Nola.Plugins.Link.PDF do
def match(_, _), do: false
@impl true
- def post_match(_url, "application/pdf"<>_, _header, _opts) do
+ def post_match(_url, "application/pdf" <> _, _header, _opts) do
{:file, nil}
end
@@ -16,24 +16,32 @@ defmodule Nola.Plugins.Link.PDF do
def post_expand(url, file, _, _) do
case System.cmd("pdftitle", ["-p", file]) do
{text, 0} ->
- text = text
- |> String.trim()
+ text =
+ text
+ |> String.trim()
if text == "" do
:error
else
basename = Path.basename(url, ".pdf")
- text = "[#{basename}] " <> text
- |> String.split("\n")
+
+ text =
+ ("[#{basename}] " <> text)
+ |> String.split("\n")
+
{:ok, text}
end
+
{_, 127} ->
- Logger.error("dependency `pdftitle` is missing, please install it: `pip3 install pdftitle`.")
+ Logger.error(
+ "dependency `pdftitle` is missing, please install it: `pip3 install pdftitle`."
+ )
+
:error
+
{error, code} ->
- Logger.warn("command `pdftitle` exited with status code #{code}:\n#{inspect error}")
+ Logger.warn("command `pdftitle` exited with status code #{code}:\n#{inspect(error)}")
:error
end
end
-
end
diff --git a/lib/plugins/link/redacted.ex b/lib/plugins/link/redacted.ex
index a7cfe74..0c14520 100644
--- a/lib/plugins/link/redacted.ex
+++ b/lib/plugins/link/redacted.ex
@@ -2,7 +2,10 @@ defmodule Nola.Plugins.Link.Redacted do
@behaviour Nola.Plugins.Link
@impl true
- def match(uri = %URI{host: "redacted.ch", path: "/torrent.php", query: query = "id="<>id}, _opts) do
+ def match(
+ uri = %URI{host: "redacted.ch", path: "/torrent.php", query: query = "id=" <> id},
+ _opts
+ ) do
%{"id" => id} = URI.decode_query(id)
{true, %{torrent: id}}
end
@@ -14,5 +17,4 @@ defmodule Nola.Plugins.Link.Redacted do
def expand(_uri, %{torrent: id}, _opts) do
end
-
end
diff --git a/lib/plugins/link/reddit.ex b/lib/plugins/link/reddit.ex
index 707e284..bd38084 100644
--- a/lib/plugins/link/reddit.ex
+++ b/lib/plugins/link/reddit.ex
@@ -6,14 +6,18 @@ defmodule Nola.Plugins.Link.Reddit do
case String.split(path, "/") do
["", "r", sub, "comments", post_id, _slug] ->
{true, %{mode: :post, path: path, sub: sub, post_id: post_id}}
+
["", "r", sub, "comments", post_id, _slug, ""] ->
{true, %{mode: :post, path: path, sub: sub, post_id: post_id}}
+
["", "r", sub, ""] ->
{true, %{mode: :sub, path: path, sub: sub}}
+
["", "r", sub] ->
{true, %{mode: :sub, path: path, sub: sub}}
-# ["", "u", user] ->
-# {true, %{mode: :user, path: path, user: user}}
+
+ # ["", "u", user] ->
+ # {true, %{mode: :user, path: path, user: user}}
_ ->
false
end
@@ -33,32 +37,47 @@ defmodule Nola.Plugins.Link.Reddit do
@impl true
def expand(_, %{mode: :sub, sub: sub}, _opts) do
url = "https://api.reddit.com/r/#{sub}/about"
+
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
- sr = Jason.decode!(body)
- |> Map.get("data")
- |> IO.inspect(limit: :infinity)
- description = Map.get(sr, "public_description")||Map.get(sr, "description", "")
- |> String.split("\n")
- |> List.first()
- name = if title = Map.get(sr, "title") do
- Map.get(sr, "display_name_prefixed") <> ": " <> title
- else
- Map.get(sr, "display_name_prefixed")
- end
- nsfw = if Map.get(sr, "over18") do
- "[NSFW] "
- else
- ""
- end
- quarantine = if Map.get(sr, "quarantine") do
- "[Quarantined] "
- else
- ""
- end
- count = "#{Map.get(sr, "subscribers")} subscribers, #{Map.get(sr, "active_user_count")} active"
+ sr =
+ Jason.decode!(body)
+ |> Map.get("data")
+ |> IO.inspect(limit: :infinity)
+
+ description =
+ Map.get(sr, "public_description") ||
+ Map.get(sr, "description", "")
+ |> String.split("\n")
+ |> List.first()
+
+ name =
+ if title = Map.get(sr, "title") do
+ Map.get(sr, "display_name_prefixed") <> ": " <> title
+ else
+ Map.get(sr, "display_name_prefixed")
+ end
+
+ nsfw =
+ if Map.get(sr, "over18") do
+ "[NSFW] "
+ else
+ ""
+ end
+
+ quarantine =
+ if Map.get(sr, "quarantine") do
+ "[Quarantined] "
+ else
+ ""
+ end
+
+ count =
+ "#{Map.get(sr, "subscribers")} subscribers, #{Map.get(sr, "active_user_count")} active"
+
preview = "#{quarantine}#{nsfw}#{name} — #{description} (#{count})"
{:ok, preview}
+
_ ->
:error
end
@@ -68,52 +87,66 @@ defmodule Nola.Plugins.Link.Reddit do
case HTTPoison.get("https://api.reddit.com#{path}?sr_detail=true") do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
json = Jason.decode!(body)
- op = List.first(json)
- |> Map.get("data")
- |> Map.get("children")
- |> List.first()
- |> Map.get("data")
- |> IO.inspect(limit: :infinity)
+
+ op =
+ List.first(json)
+ |> Map.get("data")
+ |> Map.get("children")
+ |> List.first()
+ |> Map.get("data")
+ |> IO.inspect(limit: :infinity)
+
sr = get_in(op, ["sr_detail", "display_name_prefixed"])
- {self?, url} = if Map.get(op, "selftext") == "" do
- {false, Map.get(op, "url")}
- else
- {true, nil}
- end
+
+ {self?, url} =
+ if Map.get(op, "selftext") == "" do
+ {false, Map.get(op, "url")}
+ else
+ {true, nil}
+ end
self_str = if(self?, do: "text", else: url)
up = Map.get(op, "ups")
down = Map.get(op, "downs")
comments = Map.get(op, "num_comments")
- nsfw = if Map.get(op, "over_18") do
- "[NSFW] "
- else
- ""
- end
- state = cond do
- Map.get(op, "hidden") -> "hidden"
- Map.get(op, "archived") -> "archived"
- Map.get(op, "locked") -> "locked"
- Map.get(op, "quarantine") -> "quarantined"
- Map.get(op, "removed_by") || Map.get(op, "removed_by_category") -> "removed"
- Map.get(op, "banned_by") -> "banned"
- Map.get(op, "pinned") -> "pinned"
- Map.get(op, "stickied") -> "stickied"
- true -> nil
- end
- flair = if flair = Map.get(op, "link_flair_text") do
- "[#{flair}] "
- else
- ""
- end
+
+ nsfw =
+ if Map.get(op, "over_18") do
+ "[NSFW] "
+ else
+ ""
+ end
+
+ state =
+ cond do
+ Map.get(op, "hidden") -> "hidden"
+ Map.get(op, "archived") -> "archived"
+ Map.get(op, "locked") -> "locked"
+ Map.get(op, "quarantine") -> "quarantined"
+ Map.get(op, "removed_by") || Map.get(op, "removed_by_category") -> "removed"
+ Map.get(op, "banned_by") -> "banned"
+ Map.get(op, "pinned") -> "pinned"
+ Map.get(op, "stickied") -> "stickied"
+ true -> nil
+ end
+
+ flair =
+ if flair = Map.get(op, "link_flair_text") do
+ "[#{flair}] "
+ else
+ ""
+ end
+
title = "#{nsfw}#{sr}: #{flair}#{Map.get(op, "title")}"
state_str = if(state, do: "#{state}, ")
- content = "by u/#{Map.get(op, "author")} - #{state_str}#{up} up, #{comments} comments - #{self_str}"
+
+ content =
+ "by u/#{Map.get(op, "author")} - #{state_str}#{up} up, #{comments} comments - #{self_str}"
{:ok, [title, content]}
+
err ->
:error
end
end
-
end
diff --git a/lib/plugins/link/scraper.ex b/lib/plugins/link/scraper.ex
index f5487e3..c30ae5f 100644
--- a/lib/plugins/link/scraper.ex
+++ b/lib/plugins/link/scraper.ex
@@ -1,5 +1,4 @@
defmodule Nola.Plugins.Link.Scraper do
-
defmodule UseScraper do
require Logger
@@ -7,28 +6,50 @@ defmodule Nola.Plugins.Link.Scraper do
base_url = Keyword.get(config, :base_url, "https://api.usescraper.com")
api_key = Keyword.get(config, :api_key, "unset api key")
options = Keyword.get(config, :http_options, [])
- headers = [{"user-agent", "nola, href@random.sh"},
- {"content-type", "application/json"},
- {"authorization", "Bearer " <> api_key}]
+
+ headers = [
+ {"user-agent", "nola, href@random.sh"},
+ {"content-type", "application/json"},
+ {"authorization", "Bearer " <> api_key}
+ ]
+
Logger.debug("scraper: use_scraper: get: #{url}")
+
with {:ok, json} <- Poison.encode(%{"url" => url, "format" => "html"}),
- {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- HTTPoison.post("#{base_url}/scraper/scrape", json, headers, options),
- {:ok, %{"status" => "scraped", "html" => body, "meta" => meta = %{"fetchedUrlStatusCode" => 200}}} <- Poison.decode(body) do
+ {:ok, %HTTPoison.Response{status_code: 200, body: body}} <-
+ HTTPoison.post("#{base_url}/scraper/scrape", json, headers, options),
+ {:ok,
+ %{
+ "status" => "scraped",
+ "html" => body,
+ "meta" => meta = %{"fetchedUrlStatusCode" => 200}
+ }} <- Poison.decode(body) do
{:ok, body, meta}
else
- {:ok, %{"status" => "scraped", "text" => body, "meta" => meta = %{"fetchedUrlStatusCode" => code}}} ->
+ {:ok,
+ %{
+ "status" => "scraped",
+ "text" => body,
+ "meta" => meta = %{"fetchedUrlStatusCode" => code}
+ }} ->
Logger.error("scraper: use_scraper: scraper got http #{code} for #{url}")
status = Plug.Conn.Status.reason_atom(code)
{:error, status}
+
{:ok, %{"status" => "failed"}} ->
Logger.error("scraper: use_scraper: scraper service failed for #{url}")
{:error, :scrape_failed}
+
{:ok, %HTTPoison.Response{status_code: code, body: body}} ->
Logger.error("scraper: use_scraper: scraper service failed (http #{code}) for #{url}")
status = Plug.Conn.Status.reason_atom(code)
{:error, status}
+
{:error, %HTTPoison.Error{reason: reason}} ->
- Logger.error("scraper: use_scraper: scraper service failed (http #{inspect reason}) for #{url}")
+ Logger.error(
+ "scraper: use_scraper: scraper service failed (http #{inspect(reason)}) for #{url}"
+ )
+
{:error, reason}
end
end
@@ -36,10 +57,10 @@ defmodule Nola.Plugins.Link.Scraper do
def get(url) do
config = Keyword.get(Application.get_env(:nola, Nola.Plugins.Link, []), :scraper) || []
+
case config[:service] do
"usescraper" -> UseScraper.get(url, config[:config] || [])
_ -> {:error, :scraping_disabled}
end
end
-
end
diff --git a/lib/plugins/link/store.ex b/lib/plugins/link/store.ex
index 566cc9a..ea43070 100644
--- a/lib/plugins/link/store.ex
+++ b/lib/plugins/link/store.ex
@@ -26,5 +26,4 @@ defmodule Nola.Plugins.Link.Store do
[] -> nil
end
end
-
end
diff --git a/lib/plugins/link/twitter.ex b/lib/plugins/link/twitter.ex
index 48e6bae..ac2efe7 100644
--- a/lib/plugins/link/twitter.ex
+++ b/lib/plugins/link/twitter.ex
@@ -22,12 +22,15 @@ defmodule Nola.Plugins.Link.Twitter do
* `expand_quoted`: Add the quoted tweet instead of its URL. Default: true.
"""
- def match(uri = %URI{host: twitter, path: path}, _opts) when twitter in ["twitter.com", "m.twitter.com", "mobile.twitter.com"] do
+ def match(uri = %URI{host: twitter, path: path}, _opts)
+ when twitter in ["twitter.com", "m.twitter.com", "mobile.twitter.com"] do
case String.split(path, "/", parts: 4) do
["", _username, "status", status_id] ->
{status_id, _} = Integer.parse(status_id)
{true, %{status_id: status_id}}
- _ -> false
+
+ _ ->
+ false
end
end
@@ -62,56 +65,75 @@ defmodule Nola.Plugins.Link.Twitter do
# Format tweet text
text = expand_twitter_text(tweet, opts)
- text = if tweet.quoted_status do
- quote_url = link_tweet(tweet.quoted_status, opts, true)
- String.replace(text, quote_url, "")
- else
- text
- end
+
+ text =
+ if tweet.quoted_status do
+ quote_url = link_tweet(tweet.quoted_status, opts, true)
+ String.replace(text, quote_url, "")
+ else
+ text
+ end
+
text = Nola.Irc.Message.splitlong(text)
- reply_to = if tweet.in_reply_to_status_id do
- reply_url = link_tweet({tweet.in_reply_to_screen_name, tweet.in_reply_to_status_id}, opts)
- text = if tweet.in_reply_to_screen_name == tweet.user.screen_name, do: "continued from", else: "replying to"
- <<3, 15, " ↪ ", text::binary, " ", reply_url::binary, 3>>
- end
+ reply_to =
+ if tweet.in_reply_to_status_id do
+ reply_url = link_tweet({tweet.in_reply_to_screen_name, tweet.in_reply_to_status_id}, opts)
- quoted = if tweet.quoted_status do
- full_text = tweet.quoted_status
- |> expand_twitter_text(opts)
- |> Nola.Irc.Message.splitlong_with_prefix(">")
+ text =
+ if tweet.in_reply_to_screen_name == tweet.user.screen_name,
+ do: "continued from",
+ else: "replying to"
- head = format_tweet_header(tweet.quoted_status, opts, details: false, prefix: "↓ quoting")
+ <<3, 15, " ↪ ", text::binary, " ", reply_url::binary, 3>>
+ end
- [head | full_text]
- else
- []
- end
+ quoted =
+ if tweet.quoted_status do
+ full_text =
+ tweet.quoted_status
+ |> expand_twitter_text(opts)
+ |> Nola.Irc.Message.splitlong_with_prefix(">")
+
+ head = format_tweet_header(tweet.quoted_status, opts, details: false, prefix: "↓ quoting")
+
+ [head | full_text]
+ else
+ []
+ end
- #<<2, "#{tweet.user.name} (@#{tweet.user.screen_name})", 2, " ", 3, 61, "#{foot} #{nitter_link}", 3>>, reply_to] ++ text ++ quoted
+ # <<2, "#{tweet.user.name} (@#{tweet.user.screen_name})", 2, " ", 3, 61, "#{foot} #{nitter_link}", 3>>, reply_to] ++ text ++ quoted
+
+ text =
+ ([head, reply_to | text] ++ quoted)
+ |> Enum.filter(& &1)
- text = [head, reply_to | text] ++ quoted
- |> Enum.filter(& &1)
{:ok, text}
end
defp expand_twitter_text(tweet, _opts) do
- text = Enum.reduce(tweet.entities.urls, tweet.full_text, fn(entity, text) ->
- String.replace(text, entity.url, entity.expanded_url)
- end)
+ text =
+ Enum.reduce(tweet.entities.urls, tweet.full_text, fn entity, text ->
+ String.replace(text, entity.url, entity.expanded_url)
+ end)
+
extended = tweet.extended_entities || %{media: []}
- text = Enum.reduce(extended.media, text, fn(entity, text) ->
- url = Enum.filter(extended.media, fn(e) -> entity.url == e.url end)
- |> Enum.map(fn(e) ->
- cond do
- e.type == "video" -> e.expanded_url
- true -> e.media_url_https
- end
+
+ text =
+ Enum.reduce(extended.media, text, fn entity, text ->
+ url =
+ Enum.filter(extended.media, fn e -> entity.url == e.url end)
+ |> Enum.map(fn e ->
+ cond do
+ e.type == "video" -> e.expanded_url
+ true -> e.media_url_https
+ end
+ end)
+ |> Enum.join(" ")
+
+ String.replace(text, entity.url, url)
end)
- |> Enum.join(" ")
- String.replace(text, entity.url, url)
- end)
- |> HtmlEntities.decode()
+ |> HtmlEntities.decode()
end
defp format_tweet_header(tweet, opts, format_opts \\ []) do
@@ -134,25 +156,28 @@ defmodule Nola.Plugins.Link.Twitter do
replies = if tweet.reply_count && tweet.reply_count > 0, do: "#{tweet.reply_count} Reps"
dmcad = if tweet.withheld_copyright, do: <<3, 52, "DMCA", 3>>
- withheld_local = if tweet.withheld_in_countries && length(tweet.withheld_in_countries) > 0 do
- "Withheld in #{length(tweet.withheld_in_countries)} countries"
- end
+
+ withheld_local =
+ if tweet.withheld_in_countries && length(tweet.withheld_in_countries) > 0 do
+ "Withheld in #{length(tweet.withheld_in_countries)} countries"
+ end
verified = if tweet.user.verified, do: <<3, 51, "✔", 3>>
- meta = if details do
- [verified, nsfw, formatted_time, dmcad, withheld_local, rts, qrts, likes, replies]
- else
- [verified, nsfw, formatted_time, dmcad, withheld_local]
- end
+ meta =
+ if details do
+ [verified, nsfw, formatted_time, dmcad, withheld_local, rts, qrts, likes, replies]
+ else
+ [verified, nsfw, formatted_time, dmcad, withheld_local]
+ end
- meta = meta
- |> Enum.filter(& &1)
- |> Enum.join(" - ")
+ meta =
+ meta
+ |> Enum.filter(& &1)
+ |> Enum.join(" - ")
meta = <<3, 15, meta::binary, " → #{link}", 3>>
<<author::binary, " — ", meta::binary>>
end
-
end
diff --git a/lib/plugins/link/youtube.ex b/lib/plugins/link/youtube.ex
index 0114940..adf9337 100644
--- a/lib/plugins/link/youtube.ex
+++ b/lib/plugins/link/youtube.ex
@@ -17,11 +17,12 @@ defmodule Nola.Plugins.Link.YouTube do
"""
@impl true
- def match(uri = %URI{host: yt, path: "/watch", query: "v="<>video_id}, _opts) when yt in ["youtube.com", "www.youtube.com"] do
+ def match(uri = %URI{host: yt, path: "/watch", query: "v=" <> video_id}, _opts)
+ when yt in ["youtube.com", "www.youtube.com"] do
{true, %{video_id: video_id}}
end
- def match(%URI{host: "youtu.be", path: "/"<>video_id}, _opts) do
+ def match(%URI{host: "youtu.be", path: "/" <> video_id}, _opts) do
{true, %{video_id: video_id}}
end
@@ -33,40 +34,58 @@ defmodule Nola.Plugins.Link.YouTube do
@impl true
def expand(_uri, %{video_id: video_id}, opts) do
key = Application.get_env(:nola, :youtube)[:api_key]
+
params = %{
"part" => "snippet,contentDetails,statistics",
"id" => video_id,
"key" => key
}
+
headers = []
options = [params: params]
+
case HTTPoison.get("https://www.googleapis.com/youtube/v3/videos", [], options) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
case Jason.decode(body) do
{:ok, json} ->
item = List.first(json["items"])
+
if item do
snippet = item["snippet"]
- duration = item["contentDetails"]["duration"] |> String.replace("PT", "") |> String.downcase
- date = snippet["publishedAt"]
- |> DateTime.from_iso8601()
- |> elem(1)
- |> Timex.format("{relative}", :relative)
- |> elem(1)
-
- line = if host = Keyword.get(opts, :invidious) do
- ["-> https://#{host}/watch?v=#{video_id}"]
- else
+
+ duration =
+ item["contentDetails"]["duration"]
+ |> String.replace("PT", "")
+ |> String.downcase()
+
+ date =
+ snippet["publishedAt"]
+ |> DateTime.from_iso8601()
+ |> elem(1)
+ |> Timex.format("{relative}", :relative)
+ |> elem(1)
+
+ line =
+ if host = Keyword.get(opts, :invidious) do
+ ["-> https://#{host}/watch?v=#{video_id}"]
+ else
[]
- end
- {:ok, line ++ ["#{snippet["title"]}", "— #{duration} — uploaded by #{snippet["channelTitle"]} — #{date}"
- <> " — #{item["statistics"]["viewCount"]} views, #{item["statistics"]["likeCount"]} likes"]}
+ end
+
+ {:ok,
+ line ++
+ [
+ "#{snippet["title"]}",
+ "— #{duration} — uploaded by #{snippet["channelTitle"]} — #{date}" <>
+ " — #{item["statistics"]["viewCount"]} views, #{item["statistics"]["likeCount"]} likes"
+ ]}
else
:error
end
- _ -> :error
+
+ _ ->
+ :error
end
end
end
-
end