Skip to content

Commit e891dc4

Browse files
committed
add Duel Links format
1 parent 9106671 commit e891dc4

File tree

7 files changed

+178
-6
lines changed

7 files changed

+178
-6
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 🎴 Cardian
22

3-
Yu-Gi-Oh! Paper and Master Duel Discord Bot
3+
Yu-Gi-Oh! Paper, Master Duel and Duel Links Discord Bot
44

55
Fetches data from the [YGOPRODeck](https://ygoprodeck.com/) and [Master Duel Meta](https://masterduelmeta.com/) APIs
66

lib/cardian/api/duellinksmeta.ex

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
defmodule Cardian.Api.Duellinksmeta do
2+
alias Cardian.Struct.{Card, Set}
3+
4+
@url "https://www.duellinksmeta.com/api/v1"
5+
6+
@rarity_mapping %{
7+
"N" => :normal,
8+
"R" => :rare,
9+
"SR" => :super,
10+
"UR" => :ultra
11+
}
12+
13+
@status_mapping %{
14+
"Limited 2" => :semilimited,
15+
"Limited 1" => :limited,
16+
"Forbidden" => :forbidden
17+
}
18+
19+
def get_all_cards_raw() do
20+
pages = ceil(get_card_amount() / 3000)
21+
22+
1..pages
23+
|> Task.async_stream(fn page ->
24+
url =
25+
"#{@url}/cards?limit=3000&page=#{page}"
26+
|> URI.encode()
27+
28+
Req.request(url: url)
29+
|> handle_response()
30+
end)
31+
|> Stream.flat_map(fn {:ok, res} -> res end)
32+
|> Stream.filter(&(&1["alternateArt"] != true))
33+
|> Stream.filter(&(&1["konamiID"] != nil))
34+
|> Enum.to_list()
35+
end
36+
37+
def update_card_details(cards, raw_dl_cards) do
38+
dl_cards_by_id = raw_dl_cards |> Enum.map(&{&1["konamiID"], &1}) |> Enum.into(%{})
39+
40+
Enum.map(cards, &cast_dl_details(&1, dl_cards_by_id))
41+
end
42+
43+
def get_card_amount() do
44+
url =
45+
(@url <> "/cards?collectionCount=true")
46+
|> URI.encode()
47+
48+
Req.request(url: url)
49+
|> case do
50+
{:ok, res} ->
51+
String.to_integer(res.body)
52+
53+
{:error, reason} ->
54+
raise(inspect(reason))
55+
end
56+
end
57+
58+
def get_all_sets() do
59+
pages = ceil(get_sets_amount() / 3000)
60+
61+
1..pages
62+
|> Stream.flat_map(fn page ->
63+
url =
64+
"#{@url}/sets?limit=3000&page=#{page}"
65+
|> URI.encode()
66+
67+
Req.request(url: url)
68+
|> handle_response()
69+
end)
70+
|> Stream.map(&cast_set/1)
71+
|> Enum.to_list()
72+
end
73+
74+
def get_sets_amount() do
75+
url =
76+
(@url <> "/sets?collectionCount=true")
77+
|> URI.encode()
78+
79+
Req.request(url: url)
80+
|> case do
81+
{:ok, res} ->
82+
String.to_integer(res.body)
83+
84+
{:error, reason} ->
85+
raise(inspect(reason))
86+
end
87+
end
88+
89+
defp get_set_link(url_path) when is_binary(url_path) do
90+
("https://www.duellinksmeta.com/articles" <> url_path)
91+
|> URI.encode()
92+
end
93+
94+
defp get_set_link(_), do: nil
95+
96+
defp handle_response(resp) do
97+
case resp do
98+
{:ok, res} ->
99+
res.body
100+
101+
{:error, reason} ->
102+
raise(inspect(reason))
103+
end
104+
end
105+
106+
defp cast_dl_details(card, dl_cards) do
107+
case Map.fetch(dl_cards, card.id) do
108+
{:ok, dl_card} ->
109+
%Card{
110+
card
111+
| status_dl: @status_mapping[dl_card["banStatus"]],
112+
rarity_dl: @rarity_mapping[dl_card["rarity"]],
113+
sets_dl: Enum.map(dl_card["obtain"], & &1["source"]["_id"])
114+
}
115+
116+
:error ->
117+
card
118+
end
119+
end
120+
121+
defp cast_set(resp) do
122+
%Set{
123+
id: resp["_id"],
124+
name: resp["name"],
125+
type: resp["type"],
126+
url: get_set_link(resp["linkedArticle"]["url"]),
127+
image_url: "https://s3.duellinksmeta.com" <> resp["bannerImage"]
128+
}
129+
end
130+
end

lib/cardian/api/masterduelmeta.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ defmodule Cardian.Api.Masterduelmeta do
3434
|> Enum.to_list()
3535
end
3636

37-
def update_all_md_details(cards, raw_md_cards) do
37+
def update_card_details(cards, raw_md_cards) do
3838
md_cards_by_id = raw_md_cards |> Enum.map(&{&1["konamiID"], &1}) |> Enum.into(%{})
3939

4040
Enum.map(cards, &cast_md_details(&1, md_cards_by_id))
@@ -108,7 +108,7 @@ defmodule Cardian.Api.Masterduelmeta do
108108
{:ok, md_card} ->
109109
%Card{
110110
card
111-
| status_md: @status_mapping[md_card["banStatus"]] || "Unlimited",
111+
| status_md: @status_mapping[md_card["banStatus"]],
112112
rarity_md: @rarity_mapping[md_card["rarity"]],
113113
sets_md: Enum.map(md_card["obtain"], & &1["source"]["_id"])
114114
}

lib/cardian/builder.ex

+29-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ defmodule Cardian.Builder do
6565
|> try_put_field("Arrows", card.arrows, true)
6666
|> put_monster_atk(card)
6767
|> try_put_field("Released in", build_sets(card, format))
68+
|> put_format_footer(format)
6869
end
6970

7071
def build_art_message(%Card{} = card, image_url) when is_binary(image_url) do
@@ -83,6 +84,10 @@ defmodule Cardian.Builder do
8384
}
8485
end
8586

87+
defp put_format_footer(embed, :paper), do: put_footer(embed, "Format: Paper")
88+
defp put_format_footer(embed, :md), do: put_footer(embed, "Format: Master Duel")
89+
defp put_format_footer(embed, :dl), do: put_footer(embed, "Format: Duel Links")
90+
8691
defp put_ocg_footer(embed, %Card{ocg: true}) do
8792
embed
8893
|> put_footer("OCG Art")
@@ -163,6 +168,9 @@ defmodule Cardian.Builder do
163168

164169
:md ->
165170
"**Attribute**: #{@attribute_icons[card.attribute]} #{put_card_rarity(card.rarity_md)}"
171+
172+
:dl ->
173+
"**Attribute**: #{@attribute_icons[card.attribute]} #{put_card_rarity(card.rarity_dl)}"
166174
end
167175

168176
put_description(
@@ -186,6 +194,9 @@ defmodule Cardian.Builder do
186194

187195
:md ->
188196
"**Type**: #{@spell_trap_icons[card.type]} #{@card_type_icons[card.race]} #{put_card_rarity(card.rarity_md)}"
197+
198+
:dl ->
199+
"**Type**: #{@spell_trap_icons[card.type]} #{@card_type_icons[card.race]} #{put_card_rarity(card.rarity_dl)}"
189200
end
190201

191202
put_description(
@@ -207,13 +218,17 @@ defmodule Cardian.Builder do
207218
defp put_card_rarity(_), do: ""
208219

209220
defp put_card_status(%Card{} = card, :paper) do
210-
"**TCG Status**: #{status_icon(card.status_tcg)} **OCG Status**: #{status_icon(card.status_ocg)}"
221+
"**TCG Status**: #{status_icon(card.status_tcg)}\n**OCG Status**: #{status_icon(card.status_ocg)}"
211222
end
212223

213224
defp put_card_status(%Card{} = card, :md) do
214225
"**Status**: #{status_icon(card.status_md)}"
215226
end
216227

228+
defp put_card_status(%Card{} = card, :dl) do
229+
"**Status**: #{status_icon(card.status_dl)}"
230+
end
231+
217232
defp status_icon(status) when is_map_key(@status_icons, status) do
218233
@status_icons[status]
219234
end
@@ -264,6 +279,19 @@ defmodule Cardian.Builder do
264279
|> Enum.join(", ")
265280
end
266281

282+
defp build_sets(%Card{} = card, :dl) when is_list(card.sets_dl) and length(card.sets_dl) > 0 do
283+
card.sets_dl
284+
|> Enum.flat_map(&CardRegistry.get_set_by_id(&1))
285+
|> Enum.map(
286+
&if &1.url do
287+
"[#{&1.name}](#{&1.url})"
288+
else
289+
&1.name
290+
end
291+
)
292+
|> Enum.join(", ")
293+
end
294+
267295
defp build_sets(_, _), do: "Unreleased"
268296

269297
defp try_put_color(embed, color) when is_integer(color) do

lib/cardian/card_registry.ex

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
defmodule Cardian.CardRegistry do
22
use GenServer
33
require Logger
4+
alias Cardian.Api.Duellinksmeta
45
alias Cardian.Api.Ygoprodeck
56
alias Cardian.Api.Masterduelmeta
67

@@ -148,7 +149,7 @@ defmodule Cardian.CardRegistry do
148149
end
149150

150151
defp update_sets() do
151-
sets = @extra_sets ++ Masterduelmeta.get_all_sets()
152+
sets = @extra_sets ++ Masterduelmeta.get_all_sets() ++ Duellinksmeta.get_all_sets()
152153

153154
true = :ets.insert(:sets, Enum.map(sets, &{&1.id, &1}))
154155

@@ -158,7 +159,12 @@ defmodule Cardian.CardRegistry do
158159
defp update_cards() do
159160
ygopro_cards = Ygoprodeck.get_all_cards()
160161
md_cards_raw = Masterduelmeta.get_all_cards_raw()
161-
updated_cards = Masterduelmeta.update_all_md_details(ygopro_cards, md_cards_raw)
162+
dl_cards_raw = Duellinksmeta.get_all_cards_raw()
163+
164+
updated_cards =
165+
ygopro_cards
166+
|> Masterduelmeta.update_card_details(md_cards_raw)
167+
|> Duellinksmeta.update_card_details(dl_cards_raw)
162168

163169
cards = @extra_cards ++ updated_cards
164170

lib/cardian/interactions.ex

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ defmodule Cardian.Interactions do
4141
%{
4242
name: "Master Duel",
4343
value: "md"
44+
},
45+
%{
46+
name: "Duel Links",
47+
value: "dl"
4448
}
4549
]
4650
}
@@ -107,6 +111,7 @@ defmodule Cardian.Interactions do
107111
format =
108112
case Enum.find(options, &(&1.name == "format")) do
109113
%{name: "format", value: "md"} -> :md
114+
%{name: "format", value: "dl"} -> :dl
110115
_ -> :paper
111116
end
112117

lib/cardian/struct/card.ex

+3
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ defmodule Cardian.Struct.Card do
1515
:scale,
1616
:arrows,
1717
:status_md,
18+
:status_dl,
1819
:status_tcg,
1920
:status_ocg,
2021
:status_goat,
2122
:rarity_md,
23+
:rarity_dl,
2224
:image_url,
2325
:url,
2426
:sets_paper,
2527
:sets_md,
28+
:sets_dl,
2629
:ocg
2730
]
2831
end

0 commit comments

Comments
 (0)