Compare commits
3 commits
a7b5f6de14
...
551fcee088
Author | SHA1 | Date | |
---|---|---|---|
551fcee088 | |||
5b6cf19548 | |||
3f07894052 |
7 changed files with 137 additions and 52 deletions
48
assets/drip.css
Normal file
48
assets/drip.css
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
max-width: 45rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img,
|
||||||
|
video {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr {
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: solid 3px;
|
||||||
|
margin: auto .5em;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dinero {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
body {
|
||||||
|
background: black;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
abbr {
|
||||||
|
color: lightgray;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: gold;
|
||||||
|
}
|
||||||
|
a:visited {
|
||||||
|
color: #ff9;
|
||||||
|
}
|
||||||
|
.dinero {
|
||||||
|
color: lightgreen;
|
||||||
|
}
|
||||||
|
}
|
54
main.go
54
main.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -19,7 +20,7 @@ import (
|
||||||
type Status struct {
|
type Status struct {
|
||||||
NFTNum int
|
NFTNum int
|
||||||
TotalUSDValue float64
|
TotalUSDValue float64
|
||||||
NFTs []string
|
NFTs []downloadedOpenSeaAsset
|
||||||
}
|
}
|
||||||
|
|
||||||
const NFTS_DIR = "./nfts"
|
const NFTS_DIR = "./nfts"
|
||||||
|
@ -64,7 +65,7 @@ func getStatus() (Status, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(status.NFTs) <= 20 {
|
if len(status.NFTs) <= 20 {
|
||||||
status.NFTs = append(status.NFTs, id)
|
status.NFTs = append(status.NFTs, asset)
|
||||||
}
|
}
|
||||||
|
|
||||||
status.NFTNum += 1
|
status.NFTNum += 1
|
||||||
|
@ -99,33 +100,34 @@ func getRandomOpenSeaAsset() (Asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type downloadedOpenSeaAsset struct {
|
type downloadedOpenSeaAsset struct {
|
||||||
|
Id string `json:"Id"`
|
||||||
Asset `json:"Asset"`
|
Asset `json:"Asset"`
|
||||||
Transaction `json:"Transaction"`
|
Transaction `json:"Transaction"`
|
||||||
|
FileName string `json:"FileName"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d downloadedOpenSeaAsset) GetUSDPrice() float64 {
|
func (d downloadedOpenSeaAsset) GetUSDPrice() float64 {
|
||||||
return d.Transaction.Value * d.Asset.LastSale.TokenUSDPrice
|
return d.Transaction.Value * d.Asset.LastSale.TokenUSDPrice
|
||||||
}
|
}
|
||||||
|
func (d downloadedOpenSeaAsset) IsVideo() bool {
|
||||||
|
return path.Ext(d.FileName) == ".mp4"
|
||||||
|
}
|
||||||
|
|
||||||
func downloadOpenSeaAsset(asset Asset, transaction Transaction) (string, error) {
|
func downloadOpenSeaAsset(asset Asset, transaction Transaction) (string, error) {
|
||||||
id := getOpenSeaId(asset.TokenId)
|
id := getOpenSeaId(asset.TokenId)
|
||||||
jsonFile, err := os.Create(filepath.Join(NFTS_DIR, id+".json"))
|
|
||||||
if err != nil {
|
u, err := url.Parse(asset.ImageUrl)
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
err = json.NewEncoder(jsonFile).Encode(downloadedOpenSeaAsset{
|
|
||||||
Asset: asset,
|
|
||||||
Transaction: transaction,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
ext := path.Ext(u.Path)
|
||||||
|
filename := id + ext
|
||||||
|
|
||||||
imageRes, err := http.DefaultClient.Get(asset.ImageUrl)
|
imageRes, err := http.DefaultClient.Get(asset.ImageUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
file, err := os.Create(filepath.Join(NFTS_DIR, id))
|
file, err := os.Create(filepath.Join(NFTS_DIR, filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -134,6 +136,20 @@ func downloadOpenSeaAsset(asset Asset, transaction Transaction) (string, error)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jsonFile, err := os.Create(filepath.Join(NFTS_DIR, id+".json"))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = json.NewEncoder(jsonFile).Encode(downloadedOpenSeaAsset{
|
||||||
|
Id: id,
|
||||||
|
Asset: asset,
|
||||||
|
Transaction: transaction,
|
||||||
|
FileName: filename,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,13 +160,13 @@ func must(err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
indexTmpl, err := template.ParseFiles("./index.tmpl")
|
indexTmpl, err := template.ParseFiles("./templates/base.tmpl", "./templates/embed-nft.tmpl", "./templates/index.tmpl")
|
||||||
must(err)
|
must(err)
|
||||||
nftsTmpl, err := template.ParseFiles("./nft.tmpl")
|
nftsTmpl, err := template.ParseFiles("./templates/base.tmpl", "./templates/embed-nft.tmpl", "./templates/nft.tmpl")
|
||||||
must(err)
|
must(err)
|
||||||
|
|
||||||
fs := http.FileServer(http.Dir(NFTS_DIR))
|
http.Handle("/static/nfts/", http.StripPrefix("/static/nfts/", http.FileServer(http.Dir(NFTS_DIR))))
|
||||||
http.Handle("/static/nfts/", http.StripPrefix("/static/nfts/", fs))
|
http.Handle("/static/assets/", http.StripPrefix("/static/assets/", http.FileServer(http.Dir("./assets"))))
|
||||||
|
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
status, err := getStatus()
|
status, err := getStatus()
|
||||||
|
@ -200,13 +216,7 @@ func main() {
|
||||||
log.Panicln("No pude conseguir NFT", err)
|
log.Panicln("No pude conseguir NFT", err)
|
||||||
}
|
}
|
||||||
w.Header().Add("Content-Type", "text/html")
|
w.Header().Add("Content-Type", "text/html")
|
||||||
err = nftsTmpl.Execute(w, struct {
|
err = nftsTmpl.Execute(w, nft)
|
||||||
Id string
|
|
||||||
NFT downloadedOpenSeaAsset
|
|
||||||
}{
|
|
||||||
Id: id,
|
|
||||||
NFT: nft,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln("No pude escribir nft", err)
|
log.Panicln("No pude escribir nft", err)
|
||||||
}
|
}
|
||||||
|
|
13
nft.tmpl
13
nft.tmpl
|
@ -1,13 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<meta charset=utf8>
|
|
||||||
<meta name=viewport content='width=device-width, initial-scale=1.0'>
|
|
||||||
<link rel=stylesheet href=https://nulo.in/drip.css>
|
|
||||||
<title>{{ .NFT.Asset.Name }}</title>
|
|
||||||
|
|
||||||
<h1>{{ .NFT.Asset.Name }}</h1>
|
|
||||||
<p>Vendido por <span style=color:green>USD ${{ printf "%.2f" .NFT.GetUSDPrice }}</span></p>
|
|
||||||
<a href="{{ .NFT.Asset.Permalink }}" rel="noreferrer noopener">Abrir en OpenSea</a>
|
|
||||||
<figure>
|
|
||||||
<img src="/static/nfts/{{ .Id }}">
|
|
||||||
</figure>
|
|
||||||
<a href=/>Volver</a>
|
|
|
@ -1,22 +1,19 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<meta charset=utf8>
|
<meta charset=utf8>
|
||||||
<meta name=viewport content='width=device-width, initial-scale=1.0'>
|
<meta name=viewport content='width=device-width, initial-scale=1.0'>
|
||||||
<link rel=stylesheet href=https://nulo.in/drip.css>
|
<link rel=stylesheet href=/static/assets/drip.css>
|
||||||
<title>NFTmashin</title>
|
|
||||||
<section style=text-align:center>
|
{{template "meta" .}}
|
||||||
<h1>NFTmashin</h1>
|
|
||||||
<p><em>Beta: las copias pueden ser eliminadas en el futuro.</em></p>
|
{{template "body" .}}
|
||||||
<p>NFTs descargados: {{ .NFTNum }}</p>
|
|
||||||
<p>Valor total: <span style=color:green>USD ${{ printf "%.2f" .TotalUSDValue }}</span></p>
|
<footer>
|
||||||
<a style=font-size:3rem href=/copiar>¡Copiar un NFT!</a>
|
|
||||||
<p>Inspirado en <a href="https://konsthack.se/portfolio/kh000-kopimashin/" rel="noreferrer noopener">Kopimashin</a> de brokep.</p>
|
<p>Inspirado en <a href="https://konsthack.se/portfolio/kh000-kopimashin/" rel="noreferrer noopener">Kopimashin</a> de brokep.</p>
|
||||||
<p><a href="https://es.wikipedia.org/wiki/Kopimismo" rel="noreferrer noopener"><img style="width: 5rem;box-shadow: 0 0 10px #555;border-radius: 10px;background: #555;padding: .5em;" src="data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8' standalone='no'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' height='602.67' width='579.07' stroke='%23ffffff' stroke-width='1.3028' viewBox='0 0 612 792'%3E%3Cpath d='m441.08 720.52l-93.24 66.61-417.03-295.1 0.004-251.03 93.239-65.58 149.6 104.51v-210.05l93.24-66.6 94.27 66.604v210.05l67.62-47.13 79.93 56.36 80.94-57.39 94.26 66.61v251.03l-94.26 65.58-80.94-57.38-67.63 48.15z'/%3E%3Cpath d='m-43.573 241l67.626 48.16 68.65-48.16-68.65-48.16zm80.948 57.38l67.625 48.15 68.65-48.15-67.62-48.17zm79.925 57.37l68.64 48.16 68.66-48.16-68.66-48.15zm149.59-334.03l-68.65 48.16 68.65 48.156 68.65-48.156zm0 114.76l-68.65 48.16 68.65 48.16 67.63-49.18zm0 113.74l-68.65 48.16 68.65 48.15 67.63-48.15zm-68.65 162.91l68.65 47.14 67.63-48.16-67.63-47.14zm80.95 56.35l68.65 48.16 67.62-48.16-67.62-48.15zm149.59-219.26l-68.65 48.16 67.63 48.15 68.65-48.15zm160.87 0l-67.63 48.16 67.63 48.15 68.65-48.15z' fill='%23fff'/%3E%3C/svg%3E" alt="Kopimi"></a></p>
|
<p><a href="https://es.wikipedia.org/wiki/Kopimismo" rel="noreferrer noopener"><img style="width: 5rem;box-shadow: 0 0 10px #555;border-radius: 10px;background: #555;padding: .5em;" src="data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8' standalone='no'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' height='602.67' width='579.07' stroke='%23ffffff' stroke-width='1.3028' viewBox='0 0 612 792'%3E%3Cpath d='m441.08 720.52l-93.24 66.61-417.03-295.1 0.004-251.03 93.239-65.58 149.6 104.51v-210.05l93.24-66.6 94.27 66.604v210.05l67.62-47.13 79.93 56.36 80.94-57.39 94.26 66.61v251.03l-94.26 65.58-80.94-57.38-67.63 48.15z'/%3E%3Cpath d='m-43.573 241l67.626 48.16 68.65-48.16-68.65-48.16zm80.948 57.38l67.625 48.15 68.65-48.15-67.62-48.17zm79.925 57.37l68.64 48.16 68.66-48.16-68.66-48.15zm149.59-334.03l-68.65 48.16 68.65 48.156 68.65-48.156zm0 114.76l-68.65 48.16 68.65 48.16 67.63-49.18zm0 113.74l-68.65 48.16 68.65 48.15 67.63-48.15zm-68.65 162.91l68.65 47.14 67.63-48.16-67.63-47.14zm80.95 56.35l68.65 48.16 67.62-48.16-67.62-48.15zm149.59-219.26l-68.65 48.16 67.63 48.15 68.65-48.15zm160.87 0l-67.63 48.16 67.63 48.15 68.65-48.15z' fill='%23fff'/%3E%3C/svg%3E" alt="Kopimi"></a></p>
|
||||||
</section>
|
</footer>
|
||||||
<section>
|
|
||||||
<h2>Algunos NFTs descargados</h2>
|
{{define "meta"}}
|
||||||
{{range .NFTs}}
|
<title>NFTmashin</title>
|
||||||
<a href="/nfts/{{.}}">
|
{{end}}
|
||||||
<img src="/static/nfts/{{.}}">
|
{{define "body"}}
|
||||||
</a>
|
{{end}}
|
||||||
{{end}}
|
|
||||||
</section>
|
|
7
templates/embed-nft.tmpl
Normal file
7
templates/embed-nft.tmpl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{{define "embed-nft"}}
|
||||||
|
{{if .IsVideo}}
|
||||||
|
<video controls loop src="/static/nfts/{{.FileName}}"></video>
|
||||||
|
{{else}}
|
||||||
|
<img src="/static/nfts/{{.FileName}}">
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
19
templates/index.tmpl
Normal file
19
templates/index.tmpl
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{{define "body"}}
|
||||||
|
<section style=text-align:center>
|
||||||
|
<h1>NFTmashin</h1>
|
||||||
|
<p><em>Beta: las copias pueden ser eliminadas en el futuro.</em></p>
|
||||||
|
<p>NFTs descargados: {{ .NFTNum }}</p>
|
||||||
|
<p>Valor total: <span class=dinero>USD ${{ printf "%.2f" .TotalUSDValue }}</span></p>
|
||||||
|
<a style=font-size:3rem href=/copiar>¡Copiar un NFT!</a>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>Algunos NFTs descargados</h2>
|
||||||
|
{{range .NFTs}}
|
||||||
|
<figure>
|
||||||
|
<h3><a href="/nfts/{{.Id}}">{{.Asset.Name}}</a></h3>
|
||||||
|
{{template "embed-nft" .}}
|
||||||
|
</figure>
|
||||||
|
<hr>
|
||||||
|
{{end}}
|
||||||
|
</section>
|
||||||
|
{{end}}
|
17
templates/nft.tmpl
Normal file
17
templates/nft.tmpl
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{{define "meta"}}
|
||||||
|
<title>{{ .Asset.Name }}</title>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "body"}}
|
||||||
|
<h1>{{ .Asset.Name }}</h1>
|
||||||
|
<p>Vendido por <span style=color:green>USD ${{ printf "%.2f" .GetUSDPrice }}</span></p>
|
||||||
|
<a href="{{ .Asset.Permalink }}" rel="noreferrer noopener">Abrir en OpenSea</a>
|
||||||
|
<figure>
|
||||||
|
{{if .IsVideo}}
|
||||||
|
<video controls loop src="/static/nfts/{{.FileName}}"></video>
|
||||||
|
{{else}}
|
||||||
|
<img src="/static/nfts/{{.FileName}}">
|
||||||
|
{{end}}
|
||||||
|
</figure>
|
||||||
|
<a href=/>Volver</a>
|
||||||
|
{{end}}
|
Loading…
Reference in a new issue