Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ https://t.me/save_it_playground

- [Elixir](https://elixir-lang.org/)
- [ex_gram](https://github.com/rockneurotiko/ex_gram)
- [cobalt api](https://github.com/imputnet/cobalt/blob/current/docs/api.md)
- [cobalt api](https://github.com/imputnet/cobalt)
- [Typesense](https://typesense.org/)

## Development
Expand All @@ -61,6 +61,7 @@ docker compose up

```sh
# Run
export COBALT_API_URL=<your_cobalt_api_url>
export TELEGRAM_BOT_TOKEN=<YOUR_TELEGRAM_BOT_TOKEN>

iex -S mix run --no-halt
Expand Down
4 changes: 3 additions & 1 deletion config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import Config
config :save_it, :telegram_bot_token, System.get_env("TELEGRAM_BOT_TOKEN")
config :ex_gram, token: System.get_env("TELEGRAM_BOT_TOKEN")

config :save_it, :typesense_url, System.get_env("TYPESENSE_URL", "http://localhost:8100")
config :save_it, :cobalt_api_url, System.get_env("COBALT_API_URL", "http://localhost:9001")

config :save_it, :typesense_url, System.get_env("TYPESENSE_URL", "http://localhost:8101")
config :save_it, :typesense_api_key, System.get_env("TYPESENSE_API_KEY", "xyz")

# optional
Expand Down
19 changes: 16 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
services:
cobalt-api:
image: ghcr.io/imputnet/cobalt:10

init: true
read_only: true
restart: unless-stopped

ports:
- 9001:9000/tcp
environment:
API_URL: "http://localhost:9001/"

typesense:
image: typesense/typesense:27.1

restart: on-failure
hostname: typesense

ports:
- "8100:8108"
- "8101:8108"
volumes:
- ./data/typesense-data:/data
command: "--data-dir /data --api-key=xyz --enable-cors"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8100/health"]
test: ["CMD", "curl", "-f", "http://localhost:8101/health"]
interval: 30s
timeout: 10s
retries: 5
9 changes: 5 additions & 4 deletions lib/save_it/bot.ex
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
defmodule SaveIt.Bot do
require Logger
alias SaveIt.CobaltClient

alias SaveIt.FileHelper
alias SaveIt.GoogleDrive
alias SaveIt.GoogleOAuth2DeviceFlow

alias SaveIt.PhotoService

alias SmallSdk.Telegram
alias SmallSdk.Cobalt

@bot :save_it_bot

Expand Down Expand Up @@ -225,8 +226,8 @@ defmodule SaveIt.Bot do
{:ok, progress_message} = send_message(chat.id, Enum.at(@progress, 0))
url = List.first(urls)

case CobaltClient.get_download_url(url) do
{:ok, url, download_urls} ->
case Cobalt.get_download_url(url) do
{:ok, purge_url, download_urls} ->
case FileHelper.get_downloaded_files(download_urls) do
nil ->
update_message(chat.id, progress_message.message_id, Enum.slice(@progress, 0..1))
Expand All @@ -244,7 +245,7 @@ defmodule SaveIt.Bot do
bot_send_files(chat.id, files)

delete_messages(chat.id, [message_id, progress_message.message_id])
FileHelper.write_folder(url, files)
FileHelper.write_folder(purge_url, files)
# TODO: 给图片添加 emoji
GoogleDrive.upload_files(chat.id, files)

Expand Down
73 changes: 0 additions & 73 deletions lib/save_it/cobalt_client.ex

This file was deleted.

2 changes: 1 addition & 1 deletion lib/save_it/migration/typesense.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule SaveIt.Migration.Typesense do
alias SmallSdk.Typesense

import Tj.UrlHelper, only: [validate_url!: 1]
import SaveIt.SmallHelper.UrlHelper, only: [validate_url!: 1]

def create_collection!(schema) do
req = build_request("/collections")
Expand Down
2 changes: 1 addition & 1 deletion lib/save_it/photo_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule SaveIt.PhotoService do
require Logger
alias SmallSdk.Typesense

import Tj.UrlHelper, only: [validate_url!: 1]
import SaveIt.SmallHelper.UrlHelper, only: [validate_url!: 1]

def create_photo!(
%{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Tj.UrlHelper do
defmodule SaveIt.SmallHelper.UrlHelper do
def validate_url!(url) do
uri = URI.parse(url)

Expand Down
98 changes: 98 additions & 0 deletions lib/small_sdk/cobalt.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
defmodule SmallSdk.Cobalt do
require Logger

import SaveIt.SmallHelper.UrlHelper, only: [validate_url!: 1]

def get_download_url(text) do
url = String.split(text, "?") |> hd()

req = build_request("/")
res = Req.post(req, json: %{url: url})

body = handle_response(res)

case body do
%{"url" => download_url} ->
{:ok, download_url}

%{"status" => "picker", "picker" => picker_items} ->
{:ok, url, Enum.map(picker_items, &Map.get(&1, "url"))}

%{"status" => "error", "text" => msg} ->
Logger.warning("response.body is status error, text: #{msg}")
{:error, msg}

_ ->
Logger.warning("response.body: #{inspect(body)}")
{:error, "inner service error"}
end
end

defp get_env() do
api_url = Application.fetch_env!(:save_it, :cobalt_api_url) |> validate_url!()

{api_url}
end

defp build_request(path) do
{api_url} = get_env()

Req.new(
base_url: api_url,
url: path,
headers: [
{"Accept", "application/json"},
{"Content-Type", "application/json"}
]
)
end

@doc """
Handle response from Cobalt API return body if status is 200..209
"""
def handle_response({:ok, %{status: status, body: body}}) do
case status do
status when status in 200..209 ->
body

400 ->
Logger.warning("Bad Request: #{inspect(body)}")
raise "Bad Request"

401 ->
raise "Unauthorized"

404 ->
nil

409 ->
raise "Conflict"

422 ->
raise "Unprocessable Entity"

503 ->
raise "Service Unavailable"

_ ->
Logger.error("Unhandled status code #{status}: #{inspect(body)}")
raise "Unknown error: #{status}"
end
end

def handle_response({:error, reason}) do
Logger.error("Request failed: #{inspect(reason)}")
raise "Request failed"
end

def handle_response!(%{status: status, body: body}) do
case status do
status when status in 200..209 ->
body

status ->
Logger.warning("Request failed with status #{status}: #{inspect(body)}")
raise "Request failed with status #{status}"
end
end
end
2 changes: 1 addition & 1 deletion lib/small_sdk/typesense.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule SmallSdk.Typesense do
require Logger

import Tj.UrlHelper, only: [validate_url!: 1]
import SaveIt.SmallHelper.UrlHelper, only: [validate_url!: 1]

def create_document!(collection_name, document) do
req = build_request("/collections/#{collection_name}/documents")
Expand Down
Loading