Compare commits

...

2 Commits

Author SHA1 Message Date
daru
022ff8d0f9 Implement MovieManager connection 2022-06-29 00:43:55 +02:00
daru
2b12e63637 Update mods 2022-06-28 20:33:25 +02:00
12 changed files with 286 additions and 83 deletions

1
.gitignore vendored
View File

@@ -16,3 +16,4 @@
huso
nuts/*
mm.cred

View File

@@ -1,2 +1,3 @@
#!/bin/bash
date=$(date '+%Y-%m-%dT%H:%M:%S')
go build -ldflags "-X main.buildTime=$date"
go build -ldflags "-X main.buildTime=$date"

18
go.mod
View File

@@ -4,22 +4,24 @@ go 1.18
require (
github.com/allegro/bigcache/v3 v3.0.2
github.com/fasthttp/router v1.4.9
github.com/gookit/color v1.5.0
github.com/valyala/fasthttp v1.37.0
github.com/fasthttp/router v1.4.10
github.com/go-sql-driver/mysql v1.6.0
github.com/gookit/color v1.5.1
github.com/valyala/fasthttp v1.38.0
github.com/valyala/quicktemplate v1.7.0
github.com/xujiajun/nutsdb v0.8.0
golang.org/x/time v0.0.0-20220411224347-583f2d630306
github.com/xujiajun/nutsdb v0.9.0
golang.org/x/time v0.0.0-20220609170525-579cf78fd858
)
require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/klauspost/compress v1.15.5 // indirect
github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 // indirect
github.com/klauspost/compress v1.15.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
github.com/xujiajun/mmap-go v1.0.1 // indirect
github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b // indirect
)

45
go.sum
View File

@@ -9,30 +9,35 @@ github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fasthttp/router v1.4.9 h1:8s1HEqP+GvsC2B8vPdLAPHJegs4s28z7UsraPuHM1K8=
github.com/fasthttp/router v1.4.9/go.mod h1:oWPrQCi9QOrzxKC+rZuliS1+JhYj2bpR01J6T8vUDUQ=
github.com/fasthttp/router v1.4.10 h1:C8z6K1pTqhLjSv97/qCY9tZiiPT8JuFwDoO9E2HJFWQ=
github.com/fasthttp/router v1.4.10/go.mod h1:FGSUOg9SQ/tU864SfD23kG/HwfD0akXqOqhTQ27gTFQ=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/gookit/color v1.5.1 h1:Vjg2VEcdHpwq+oY63s/ksHrgJYCTo0bwWvmmYWdE9fQ=
github.com/gookit/color v1.5.1/go.mod h1:wZFzea4X8qN6vHOSP2apMb4/+w/orMznEzYsIHPaqKM=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.5 h1:qyCLMz2JCrKADihKOh9FxnW3houKeNsp2h5OEz0QSEA=
github.com/klauspost/compress v1.15.5/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY=
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 h1:sfTahD3f2BSjx9U3R4K09PkNuZZWthT7g6vzTIXNWkM=
github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo=
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
github.com/valyala/fasthttp v1.36.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
github.com/valyala/fasthttp v1.37.0 h1:7WHCyI7EAkQMVmrfBhWTCOaeROb1aCBiTopx63LkMbE=
github.com/valyala/fasthttp v1.37.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
github.com/valyala/fasthttp v1.38.0 h1:yTjSSNjuDi2PPvXY2836bIwLmiTS2T4T9p1coQshpco=
github.com/valyala/fasthttp v1.38.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
github.com/valyala/quicktemplate v1.7.0 h1:LUPTJmlVcb46OOUY3IeD9DojFpAVbsG+5WFTcjMJzCM=
github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
@@ -41,8 +46,8 @@ github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1z
github.com/xujiajun/gorouter v1.2.0/go.mod h1:yJrIta+bTNpBM/2UT8hLOaEAFckO+m/qmR3luMIQygM=
github.com/xujiajun/mmap-go v1.0.1 h1:7Se7ss1fLPPRW+ePgqGpCkfGIZzJV6JPq9Wq9iv/WHc=
github.com/xujiajun/mmap-go v1.0.1/go.mod h1:CNN6Sw4SL69Sui00p0zEzcZKbt+5HtEnYUsc6BKKRMg=
github.com/xujiajun/nutsdb v0.8.0 h1:BkXjifwlF3akHVoTQ8B3gdF183oq4QI0JQywazEZXkM=
github.com/xujiajun/nutsdb v0.8.0/go.mod h1:KOdR/RLPELQ6611VTMsSOUBSO2s7kXPINOiA/+1dlgc=
github.com/xujiajun/nutsdb v0.9.0 h1:vy8rjDp0Sk/SnTAqg61i+G4NIN/3tBKSdZ6rIyKYVIo=
github.com/xujiajun/nutsdb v0.9.0/go.mod h1:8ZdTTF0cEQO+wN940htfHYKswFql2iB6Osckx+GmOoU=
github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b h1:jKG9OiL4T4xQN3IUrhUpc1tG+HfDXppkgVcrAiiaI/0=
github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b/go.mod h1:AZd87GYJlUzl82Yab2kTjx1EyXSQCAfZDhpTo1SQC4k=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
@@ -59,16 +64,18 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8=
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

39
huso.go
View File

@@ -1,6 +1,7 @@
package main
import (
"database/sql"
"flag"
"fmt"
"log"
@@ -11,6 +12,7 @@ import (
"time"
"github.com/allegro/bigcache/v3"
_ "github.com/go-sql-driver/mysql"
"github.com/gookit/color"
"github.com/xujiajun/nutsdb"
"golang.org/x/time/rate"
@@ -45,12 +47,16 @@ var (
jikanApiBaseUri = flag.String("jikanApiBaseUri", "https://api.jikan.moe/v4/", "Jikan API base URL")
malApiId = flag.String("malApiId", "cc17dcf40581b9dfc8a5a12dba458153", "MyAnimeList API Client ID")
localServer = flag.Bool("localServer", false, "Set varius headers for running locally")
mmDbServer = flag.String("mmDbServer", "hanami.family:3306", "MovieManager db server")
mmDbUser = flag.String("mmDbUser", "yui", "MovieManager db user")
animeCache *bigcache.BigCache
seasoncache *bigcache.BigCache
userCache *bigcache.BigCache
searchCache *bigcache.BigCache
animeListCache *bigcache.BigCache
mmCache *bigcache.BigCache
db *nutsdb.DB
mmDb *sql.DB
jikanLimiter *rate.Limiter
logOut *RingBuf
buildTime string
@@ -66,7 +72,7 @@ func main() {
logOut = NewRingBuf(10101)
color.Notice.Printf("huso %s built on %s with %s\n", husoVersion, buildTime, runtime.Version())
logOut.WriteLine(fmt.Sprintf("🎉 huso %s built on %s with %s\n", husoVersion, buildTime, runtime.Version()))
logOut.WriteLine(fmt.Sprintf("🎉 huso %s built on %s with %s", husoVersion, buildTime, runtime.Version()))
jikanLimiter = rate.NewLimiter(rate.Every(time.Second), 1)
@@ -97,6 +103,11 @@ func main() {
log.Fatal(err)
}
defer animeListCache.Close()
mmCache, err = bigcache.NewBigCache(bigcache.DefaultConfig(time.Minute))
if err != nil {
log.Fatal(err)
}
defer mmCache.Close()
nutsOpt := nutsdb.DefaultOptions
nutsOpt.Dir = "nuts"
@@ -106,6 +117,32 @@ func main() {
}
defer db.Close()
color.Infoln("NutsDB connected")
logOut.WriteLine("🗃️ NutsDB connected")
conns, err := GetMmConnString()
if err != nil {
color.Errorln(err.Error())
} else {
mmDb, err = sql.Open("mysql", conns)
if err != nil || mmDb == nil {
color.Errorln(err.Error())
} else {
mmDb.SetConnMaxLifetime(time.Minute * 3)
mmDb.SetMaxOpenConns(10)
mmDb.SetMaxIdleConns(10)
defer mmDb.Close()
err = mmDb.Ping()
if err != nil {
color.Errorln(err.Error())
} else {
color.Infoln("MovieManager DB connected")
logOut.WriteLine("🗃️ MovieManager DB connected")
}
}
}
Arbeit()
LangeArbeit()

View File

@@ -310,3 +310,10 @@ type SeasonJikan struct {
} `json:"pagination"`
Data []SeasonAnimeJikan `json:"data"`
}
type MmOracle struct {
Id int `json:"id"`
Title string `json:"title"`
Anime int64 `json:"anime"`
AvgScore int `json:"avgScore"`
}

View File

@@ -44,7 +44,13 @@ func Start(ctx *fasthttp.RequestCtx) {
return
}
WriteIndex(ctx, season, logOut.String())
oracles, err := MmReadOracle()
if err != nil {
addErrorToCtx(ctx, err)
return
}
WriteIndex(ctx, season, oracles, logOut.String())
ctx.SetContentType("text/html; charset=utf-8")
ctx.SetStatusCode(fasthttp.StatusOK)

View File

@@ -43,3 +43,7 @@ func BytesToInt64AndDate(bytes []byte) (int64, time.Time, error) {
func Int64AndDateToBytes(num int64, appoint time.Time) []byte {
return []byte(fmt.Sprintf("%d%s%s", num, AppointSplit, appoint.Format(time.RFC3339)))
}
func PrintDate(t time.Time) string {
return t.Format("2006-01-02")
}

View File

@@ -1,5 +1,5 @@
{% package main %}
{% func Index(animes []Anime, log string) %}
{% func Index(animes []Anime, oracles []MmOracle, log string) %}
{% collapsespace %}
<!DOCTYPE html>
<html lang="en">
@@ -19,6 +19,8 @@ body { background-color: #1a1a1a; color: #fff; }
</head>
<body>
<h1>HUSO - Hanami universeller Serien Organizer</h1>
<h2>Log</h2>
<pre>{%s log %}</pre>
<h2>Anime</h2>
<table>
<tr>
@@ -30,16 +32,24 @@ body { background-color: #1a1a1a; color: #fff; }
<table>
{% for _, anime := range animes %}
<tr>
<td><a href="{%s anime.URL %}" target="_blank" rel="noopener noreferrer">{%dl anime.Anime %}</a></td>
<td><strong>{%s anime.Title %}</strong></td>
<td>{%dl anime.Anime %}</td>
<td>{%d anime.Episodes %}</td>
<td>{%f anime.Score %}</td>
</tr>
{% endfor %}
</table>
<h2>MovieManager Oracle</h2>
<table>
{% for _, oracle := range oracles %}
<tr>
<td><a href="https://movies.hanami.family/movie/{%d oracle.Id %}" target="_blank" rel="noopener noreferrer">{%d oracle.Id %}</a></td>
<td>{%d oracle.AvgScore %}</td>
<td><strong>{%s oracle.Title %}</strong></td>
<td>{%dl oracle.Anime %}</td>
</tr>
{% endfor %}
</table>
<h2>Log</h2>
<pre>
{%s log %}
</pre>
</body>
</html>
{% endcollapsespace %}

View File

@@ -18,68 +18,104 @@ var (
)
//line season.qtpl:2
func StreamIndex(qw422016 *qt422016.Writer, animes []Anime, log string) {
func StreamIndex(qw422016 *qt422016.Writer, animes []Anime, oracles []MmOracle, log string) {
//line season.qtpl:2
qw422016.N().S(`
`)
//line season.qtpl:3
qw422016.N().S(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { font-family: sans-serif; } table { border-spacing: 0; } td, th { text-align: left; padding: 0 0.5em; } td:first-child, th:first-child { padding-left: 0; } td:last-child, th:first-child { padding-right: 0; } body { background-color: #1a1a1a; color: #fff; } </style> <title>HUSO - Hanami universeller Serien Organizer</title> </head> <body> <h1>HUSO - Hanami universeller Serien Organizer</h1> <h2>Anime</h2> <table> <tr> <td><strong>Airing 📺</strong></td> <td>`)
//line season.qtpl:26
qw422016.N().D(len(animes))
//line season.qtpl:26
qw422016.N().S(`</td> </tr> </table> </br> <table> `)
//line season.qtpl:31
for _, anime := range animes {
//line season.qtpl:31
qw422016.N().S(` <tr> <td><strong>`)
//line season.qtpl:33
qw422016.E().S(anime.Title)
//line season.qtpl:33
qw422016.N().S(`</strong></td> <td>`)
//line season.qtpl:34
qw422016.N().DL(anime.Anime)
//line season.qtpl:34
qw422016.N().S(`</td> <td>`)
//line season.qtpl:35
qw422016.N().D(anime.Episodes)
//line season.qtpl:35
qw422016.N().S(`</td> </tr> `)
//line season.qtpl:37
}
//line season.qtpl:37
qw422016.N().S(` </table> <h2>Log</h2> <pre> `)
//line season.qtpl:41
qw422016.N().S(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { font-family: sans-serif; } table { border-spacing: 0; } td, th { text-align: left; padding: 0 0.5em; } td:first-child, th:first-child { padding-left: 0; } td:last-child, th:first-child { padding-right: 0; } body { background-color: #1a1a1a; color: #fff; } </style> <title>HUSO - Hanami universeller Serien Organizer</title> </head> <body> <h1>HUSO - Hanami universeller Serien Organizer</h1> <h2>Log</h2> <pre>`)
//line season.qtpl:23
qw422016.E().S(log)
//line season.qtpl:41
qw422016.N().S(` </pre> </body> </html> `)
//line season.qtpl:45
//line season.qtpl:23
qw422016.N().S(`</pre> <h2>Anime</h2> <table> <tr> <td><strong>Airing 📺</strong></td> <td>`)
//line season.qtpl:28
qw422016.N().D(len(animes))
//line season.qtpl:28
qw422016.N().S(`</td> </tr> </table> </br> <table> `)
//line season.qtpl:33
for _, anime := range animes {
//line season.qtpl:33
qw422016.N().S(` <tr> <td><a href="`)
//line season.qtpl:35
qw422016.E().S(anime.URL)
//line season.qtpl:35
qw422016.N().S(`" target="_blank" rel="noopener noreferrer">`)
//line season.qtpl:35
qw422016.N().DL(anime.Anime)
//line season.qtpl:35
qw422016.N().S(`</a></td> <td><strong>`)
//line season.qtpl:36
qw422016.E().S(anime.Title)
//line season.qtpl:36
qw422016.N().S(`</strong></td> <td>`)
//line season.qtpl:37
qw422016.N().D(anime.Episodes)
//line season.qtpl:37
qw422016.N().S(`</td> <td>`)
//line season.qtpl:38
qw422016.N().F(anime.Score)
//line season.qtpl:38
qw422016.N().S(`</td> </tr> `)
//line season.qtpl:40
}
//line season.qtpl:40
qw422016.N().S(` </table> <h2>MovieManager Oracle</h2> <table> `)
//line season.qtpl:44
for _, oracle := range oracles {
//line season.qtpl:44
qw422016.N().S(` <tr> <td><a href="https://movies.hanami.family/movie/`)
//line season.qtpl:46
qw422016.N().D(oracle.Id)
//line season.qtpl:46
qw422016.N().S(`" target="_blank" rel="noopener noreferrer">`)
//line season.qtpl:46
qw422016.N().D(oracle.Id)
//line season.qtpl:46
qw422016.N().S(`</a></td> <td>`)
//line season.qtpl:47
qw422016.N().D(oracle.AvgScore)
//line season.qtpl:47
qw422016.N().S(`</td> <td><strong>`)
//line season.qtpl:48
qw422016.E().S(oracle.Title)
//line season.qtpl:48
qw422016.N().S(`</strong></td> <td>`)
//line season.qtpl:49
qw422016.N().DL(oracle.Anime)
//line season.qtpl:49
qw422016.N().S(`</td> </tr> `)
//line season.qtpl:51
}
//line season.qtpl:51
qw422016.N().S(` </table> </body> </html> `)
//line season.qtpl:55
qw422016.N().S(`
`)
//line season.qtpl:46
//line season.qtpl:56
}
//line season.qtpl:46
func WriteIndex(qq422016 qtio422016.Writer, animes []Anime, log string) {
//line season.qtpl:46
//line season.qtpl:56
func WriteIndex(qq422016 qtio422016.Writer, animes []Anime, oracles []MmOracle, log string) {
//line season.qtpl:56
qw422016 := qt422016.AcquireWriter(qq422016)
//line season.qtpl:46
StreamIndex(qw422016, animes, log)
//line season.qtpl:46
//line season.qtpl:56
StreamIndex(qw422016, animes, oracles, log)
//line season.qtpl:56
qt422016.ReleaseWriter(qw422016)
//line season.qtpl:46
//line season.qtpl:56
}
//line season.qtpl:46
func Index(animes []Anime, log string) string {
//line season.qtpl:46
//line season.qtpl:56
func Index(animes []Anime, oracles []MmOracle, log string) string {
//line season.qtpl:56
qb422016 := qt422016.AcquireByteBuffer()
//line season.qtpl:46
WriteIndex(qb422016, animes, log)
//line season.qtpl:46
//line season.qtpl:56
WriteIndex(qb422016, animes, oracles, log)
//line season.qtpl:56
qs422016 := string(qb422016.B)
//line season.qtpl:46
//line season.qtpl:56
qt422016.ReleaseByteBuffer(qb422016)
//line season.qtpl:46
//line season.qtpl:56
return qs422016
//line season.qtpl:46
//line season.qtpl:56
}

2
template.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
~/go/bin/qtc

90
zecke.go Normal file
View File

@@ -0,0 +1,90 @@
package main
import (
"database/sql"
_ "embed"
"encoding/base64"
"encoding/json"
"fmt"
"time"
)
//go:embed mm.cred
var mmDbCred string
func GetMmConnString() (string, error) {
pw, err := base64.StdEncoding.DecodeString(mmDbCred)
if err != nil {
return "", err
}
return fmt.Sprintf("%s:%s@tcp(%s)/moviemanager?parseTime=true", *mmDbUser, pw, *mmDbServer), err
}
func MmReadOracle() ([]MmOracle, error) {
key := "oracle"
var oracles []MmOracle
data, err := mmCache.Get(key)
if err == nil {
err = json.Unmarshal(data, &oracles)
if err == nil {
return oracles, err
}
}
oracleQuery := `SELECT m.id, m.title, m.mal_id, COALESCE(SUM(pv.score), 0) AS avgScore FROM movie m
INNER JOIN vote pv ON (m.id = pv.movie_id)
INNER JOIN promise pp ON (pp.user_id = pv.user_id)
INNER JOIN evening me ON (pp.evening_id = me.id)
WHERE m.id NOT IN (
SELECT m2.id FROM movie m2
INNER JOIN evening_movie em2 ON (m2.id = em2.movie_id)
INNER JOIN evening e2 ON (em2.evening_id = e2.id)
WHERE e2.date < ?
) AND (
m.id IN (
SELECT mm.movie_source FROM movie m3
INNER JOIN movie_movie mm ON (m3.id = mm.movie_target)
INNER JOIN evening_movie em3 ON (mm.movie_target = em3.movie_id)
INNER JOIN evening e3 ON (em3.evening_id = e3.id)
WHERE e3.date < ? GROUP BY m3.id
)
OR
m.id NOT IN (
SELECT mm.movie_source FROM movie m4
INNER JOIN movie_movie mm ON (m4.id = mm.movie_source)
)
)
AND pp.promised = 1 AND m.aired = 1 AND me.date >= ? AND me.date < ? GROUP BY m.id ORDER BY avgScore DESC, m.id ASC;`
today := PrintDate(time.Now())
nextWeek := PrintDate(time.Now().AddDate(0, 0, 7))
rows, err := mmDb.Query(oracleQuery, today, today, today, nextWeek)
if err != nil {
return nil, err
}
defer rows.Close()
oracles = make([]MmOracle, 0)
for rows.Next() {
var oracle MmOracle
var qMalId sql.NullInt64
err = rows.Scan(&oracle.Id, &oracle.Title, &qMalId, &oracle.AvgScore)
if err != nil {
return oracles, err
}
if qMalId.Valid {
oracle.Anime = qMalId.Int64
}
oracles = append(oracles, oracle)
}
err = rows.Err()
if err == nil {
bytes, err := json.Marshal(oracles)
if err == nil {
mmCache.Set(key, bytes)
}
}
return oracles, err
}