moira_db/moira_db.go
2026-07-03 00:26:06 +02:00

305 lines
8.5 KiB
Go

package main
import (
"fmt"
"html/template"
"io"
"log"
"net/http"
"net/url"
"os"
"strings"
"time"
"encoding/json"
"errors"
"github.com/tidwall/gjson"
//"path/filepath"
//"regexp"
//"strings"
//"maps"
//"slices"
)
var templates *template.Template = template.New("")
var client = &http.Client{Timeout: 2*time.Second}
type Film struct{
Title_orig,
Title_EN,
Title_PL,
Desc,
Img,
Source string
Year int
}
var db_film = make(map[string]any)
func findURL_in_msg(in_msg string) (_ string,err error){
i := strings.Index(in_msg, "http")
if(i == -1){
err = errors.New("No URL found in: " + in_msg)
return
}
j := strings.Index(in_msg[i:], " ")
if(j == -1){
j = len(in_msg)-i
}
return in_msg[i:i+j], nil
}
func resolve_redirs(in_url string) (string,error){
resp, err := client.Get(in_url)
if(err != nil){
return "", err
}
defer resp.Body.Close()
return resp.Request.URL.String(), nil
}
func fetch_filmInfo(in_url string) (_ Film, err error){
parsedUrl, err := url.Parse(in_url)
if err != nil{ return }
parsedUrl.RawQuery = ""
var in_url_api string
switch(parsedUrl.Hostname()){
case "www.filmweb.pl":
in_url_api = fmt.Sprintf(
"https://www.filmweb.pl/api/v1/film/%s/preview",
in_url[strings.LastIndex(in_url, "-")+1:],
)
case "www.imdb.com":
t_parsedUrl, _ := url.Parse(in_url)
t_parsedUrl.RawQuery = ""
t_parsedUrl.Host = "api.imdbapi.dev"
in_url_api = strings.Replace(t_parsedUrl.String(), "/title/", "/titles/", 1)
if in_url_api[len(in_url_api)-1] == '/'{
in_url_api = in_url_api[:len(in_url_api)-1]
}
default:
err = errors.New("[0] Film database unsupported " + parsedUrl.Hostname())
return
}
fmt.Println("in_url_api:", in_url_api);
req,err := http.NewRequest("GET", in_url_api, nil)
if err != nil{ return }
req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; MoiraBot/1.0)")
resp,err := client.Do(req)
if err != nil{ return }
defer resp.Body.Close()
resp_text, err := io.ReadAll(resp.Body)
if err != nil{ return }
//fmt.Printf("%+v\n", string(resp_text))
titles := make(map[string]string)
switch(parsedUrl.Hostname()){
case "www.filmweb.pl":
if(len(gjson.GetBytes(resp_text, "internationalTitle").String())>0){
titles[gjson.GetBytes(resp_text, "internationalTitle.lang").String()] = gjson.GetBytes(resp_text, "internationalTitle.title").String()
titles["_int"] = gjson.GetBytes(resp_text, "internationalTitle.title").String()
}
if(len(gjson.GetBytes(resp_text, "originalTitle").String())>0){
titles[gjson.GetBytes(resp_text, "originalTitle.lang").String()] = gjson.GetBytes(resp_text, "originalTitle.title").String()
titles["_orig"] = gjson.GetBytes(resp_text, "originalTitle.title").String()
}
if(len(gjson.GetBytes(resp_text, "title").String())>0){
titles[gjson.GetBytes(resp_text, "title.lang").String()] = gjson.GetBytes(resp_text, "title.title").String()
}
return Film{
Title_orig: (func()string{
if val,ok:=titles["_orig"]; ok{
return val
}else{
return ""
}
})(),
Title_EN: (func()string{
if val,ok:=titles["en"]; ok{
return val
}else{
return ""
}
})(),
Title_PL: (func()string{
if val,ok:=titles["pl"]; ok{
return val
}else{
return ""
}
})(),
Desc: gjson.GetBytes(resp_text, "plotOrDescriptionSynopsis").String(),
Year: int(gjson.GetBytes(resp_text,"year").Int()),
Img: "https://fwcdn.pl/fpo"+gjson.GetBytes(resp_text, "poster.path").String(),
Source: in_url,
}, err
case "www.imdb.com":
if(len(gjson.GetBytes(resp_text, "primaryTitle").String())>0){
titles["en"] = gjson.GetBytes(resp_text, "primaryTitle").String()
titles["_int"] = gjson.GetBytes(resp_text, "primaryTitle").String()
}
if(len(gjson.GetBytes(resp_text, "originalTitle").String())>0){
if(len(gjson.GetBytes(resp_text, "originCountries.0.code").String())>0){
titles[strings.ToLower(gjson.GetBytes(resp_text, "originCountries.0.code").String())] = gjson.GetBytes(resp_text, "originalTitle").String()
}
titles["_orig"] = gjson.GetBytes(resp_text, "originalTitle").String()
}else{
if val,ok:=titles["_int"]; ok{
titles["_orig"] = val
}
}
return Film{
Title_orig: (func()string{
if val,ok:=titles["_orig"]; ok{
return val
}else{
return ""
}
})(),
Title_EN: (func()string{
if val,ok:=titles["en"]; ok{
return val
}else{
return ""
}
})(),
Title_PL: (func()string{
if val,ok:=titles["pl"]; ok{
return val
}else{
return ""
}
})(),
Desc: gjson.GetBytes(resp_text, "plot").String(),
Year: int(gjson.GetBytes(resp_text,"startYear").Int()),
Img: gjson.GetBytes(resp_text, "primaryImage.url").String(),
Source: in_url,
}, err
default:
err = errors.New("[1] Film database unsupported " + parsedUrl.Hostname())
return
}
}
func hdlr_root(template_renders map[string]struct{Template string;Context *map[string]any}) http.HandlerFunc{
fSrv := http.FileServer(http.Dir("./website/static"))
return func (resp http.ResponseWriter, req *http.Request){
if fileName, ok := template_renders[req.URL.Path]; ok{
fmt.Println("[srv] template", req.URL.Path, fileName.Template)
url_query := req.URL.Query()
url_query_id := url_query.Get("id")
var context any
if(url_query_id != ""){
context = (*fileName.Context)[url_query_id]
}else{
context = nil
}
err := templates.ExecuteTemplate(resp, fileName.Template, context)
if(err != nil){
http.Error(resp, err.Error(), http.StatusInternalServerError)
}
}else{
fmt.Println("[srv] static", req.URL.Path)
fSrv.ServeHTTP(resp, req)
}
}
}
func templates_register(template_renders map[string]struct{Template string;Context *map[string]any}){
for _,i_file := range template_renders{
text, err := os.ReadFile("./website/templates/" + i_file.Template)
if(err != nil){
panic(err)
}
templates.New(i_file.Template).Parse(string(text))
}
}
func hdlr_film_parseMsg(resp http.ResponseWriter, req *http.Request){
fmt.Println("[srv] util", req.URL)
url_query := req.URL.Query()
t_url, _ := findURL_in_msg(url_query.Get("text"))
fmt.Println(t_url)
t_url_noRed, _ := resolve_redirs(t_url)
fmt.Println(t_url_noRed)
t_film, _ := fetch_filmInfo(t_url_noRed)
db_film[string(len(db_film)-1)] = t_film
t_json, _ := json.MarshalIndent(db_film, "", " ")
fmt.Printf("%+v\n", string(t_json))
http.Redirect(resp, req, "/film/view/?id="+string(len(db_film)-1), http.StatusFound)
}
func main(){
//t_film, _ := fetch_filmInfo("https://www.filmweb.pl/film/Spirited+Away%3A+W+krainie+Bog%C3%B3w-2001-33288")
//t_film, _ := fetch_filmInfo("https://www.filmweb.pl/film/Pulp+Fiction-1994-1039")
//t_film, _ := fetch_filmInfo("https://www.filmweb.pl/film/Kl%C4%85twa+Doliny+W%C4%99%C5%BCy-1987-6785")
//t_film, _ := fetch_filmInfo("https://www.imdb.com/title/tt0245429/?ref_=nv_sr_srsg_0_tt_8_nm_0_in_0_q_spirited")
//t_film, _ := fetch_filmInfo("https://www.imdb.com/title/tt0110912/")
//t_film, _ := fetch_filmInfo("https://www.imdb.com/title/tt8814476/")
//t_url_noRed, _ := resolve_redirs("https://www.imdb.com/title/tt0095456/?ref_=nv_sr_srsg_0_tt_1_nm_0_in_0_q_kl%C4%85twa%20doliny%20w%C4%99%C5%BC")
//t_url_noRed, _ := resolve_redirs("https://share.google/EsMXhLYol3eQTKcQH")
//t_url, _ := findURL_in_msg("https://share.google/EsMXhLYol3eQTKcQH")
//t_url, _ := findURL_in_msg("abcabc https://share.google/EsMXhLYol3eQTKcQH abcabc")
//t_url, _ := findURL_in_msg("abcabchttps://share.google/EsMXhLYol3eQTKcQH abcabc")
//t_url, _ := findURL_in_msg("abcabchttps://share.google/EsMXhLYol3eQTKcQH")
//t_url, _ := findURL_in_msg("Fantastyczny Pan Lis (2009) - Filmweb https://share.google/EsMXhLYol3eQTKcQH")
//fmt.Println(t_url)
//t_url_noRed, _ := resolve_redirs(t_url)
//fmt.Println(t_url_noRed)
//t_film, _ := fetch_filmInfo(t_url_noRed)
//t_json, _ := json.MarshalIndent(t_film, "", " ")
//fmt.Printf("%+v\n", string(t_json))
template_renders := map[string]struct{Template string;Context *map[string]any} {
"/": {"index.html", nil},
"/film/view/": {"index.html", &db_film},
"/film/edit/": {"index.html", nil},
//"/list/view/": {"index.html", nil},
//"/list/edit/": {"index.html", nil},
//"/group/view/": {"index.html", nil},
//"/group/edit/": {"index.html", nil},
}
templates_register(template_renders)
http.HandleFunc("/", hdlr_root(template_renders))
http.HandleFunc("/film/parse_msg/", hdlr_film_parseMsg)
//fmt.Println("Welcome to moira_db!");
log.Fatal(http.ListenAndServe("127.0.0.1:8099", nil))
}