Skip to content

Commit

Permalink
Merge pull request #109 from metafates/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
metafates authored Oct 23, 2022
2 parents 69e31cc + 801a82c commit 574a093
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 52 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to
[Semantic Versioning](https://semver.org).

## 3.14.0

- New commands related to the anilist manga linkage. Now you can set what anilist manga should be linked with what titles by id. See `mangal inline anilist` for more information. #106
- Increase default http timeout to 20 seconds #108
- Fixed nil panic when trying to resume reading from history with mini mode

## 3.13.0

- Support environment variables for `downloader.path` config field #103
Expand Down
2 changes: 1 addition & 1 deletion anilist/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func FindClosest(name string) (*Manga, error) {
}

// search for manga on anilist
mangas, err := Search(name)
mangas, err := SearchByName(name)
if err != nil {
log.Error(err)
return nil, err
Expand Down
95 changes: 54 additions & 41 deletions anilist/query.go
Original file line number Diff line number Diff line change
@@ -1,49 +1,62 @@
package anilist

var searchQuery = `
import "fmt"

var mangaSubquery = `
id
idMal
title {
romaji
english
native
}
description(asHtml: false)
tags {
name
}
genres
coverImage {
extraLarge
}
characters (page: 1, perPage: 10, role: MAIN) {
nodes {
name {
full
}
}
}
startDate {
year
month
day
}
endDate {
year
month
day
}
status
synonyms
siteUrl
countryOfOrigin
externalLinks {
url
}
`

var searchByNameQuery = fmt.Sprintf(`
query ($query: String) {
Page (page: 1, perPage: 30) {
media (search: $query, type: MANGA) {
id
idMal
title {
romaji
english
native
}
description(asHtml: false)
tags {
name
}
genres
coverImage {
extraLarge
}
characters (page: 1, perPage: 10, role: MAIN) {
nodes {
name {
full
}
}
}
startDate {
year
month
day
}
endDate {
year
month
day
}
status
synonyms
siteUrl
countryOfOrigin
externalLinks {
url
}
%s
}
}
}
`
`, mangaSubquery)

var searchByIDQuery = fmt.Sprintf(`
query ($id: Int) {
Media (id: $id, type: MANGA) {
%s
}
}`, mangaSubquery)
66 changes: 62 additions & 4 deletions anilist/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,83 @@ import (
"strconv"
)

type anilistResponse struct {
type searchByNameResponse struct {
Data struct {
Page struct {
Media []*Manga `json:"media"`
} `json:"page"`
} `json:"data"`
}

type searchByIDResponse struct {
Data struct {
Media *Manga `json:"media"`
} `json:"data"`
}

var searchCache = make(map[string][]*Manga)

func Search(name string) ([]*Manga, error) {
func GetByID(id int) (*Manga, error) {
// prepare body
log.Infof("Searching anilist for manga with id: %d", id)
body := map[string]interface{}{
"query": searchByIDQuery,
"variables": map[string]interface{}{
"id": id,
},
}

// parse body to json
jsonBody, err := json.Marshal(body)
if err != nil {
log.Error(err)
return nil, err
}

// send request
log.Info("Sending request to Anilist")
req, err := http.NewRequest(http.MethodPost, "https://graphql.anilist.co", bytes.NewBuffer(jsonBody))
if err != nil {
log.Error(err)
return nil, err
}

req.Header.Set("Content-Type", "application/json")

resp, err := network.Client.Do(req)

if err != nil {
log.Error(err)
return nil, err
}

if resp.StatusCode != http.StatusOK {
log.Error("Anilist returned status code " + strconv.Itoa(resp.StatusCode))
return nil, fmt.Errorf("invalid response code %d", resp.StatusCode)
}

// decode response
var response searchByIDResponse

if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
log.Error(err)
return nil, err
}

manga := response.Data.Media
log.Infof("Got response from Anilist, found manga with id %d", manga.ID)
return manga, nil
}

func SearchByName(name string) ([]*Manga, error) {
if mangas, ok := searchCache[name]; ok {
return mangas, nil
}

// prepare body
log.Info("Searching anilist for manga: " + name)
body := map[string]interface{}{
"query": searchQuery,
"query": searchByNameQuery,
"variables": map[string]interface{}{
"query": name,
},
Expand Down Expand Up @@ -64,7 +122,7 @@ func Search(name string) ([]*Manga, error) {
}

// decode response
var response anilistResponse
var response searchByNameResponse

if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
log.Error(err)
Expand Down
2 changes: 1 addition & 1 deletion anilist/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ func TestSearch(t *testing.T) {
Convey(`Given a query "Death Note"`, t, func() {
query := "Death Note"
Convey(`When I search for it`, func() {
results, err := Search(query)
results, err := SearchByName(query)
Convey(`Then I should get a result`, func() {
So(err, ShouldBeNil)
So(results, ShouldNotBeEmpty)
Expand Down
88 changes: 88 additions & 0 deletions cmd/inline.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package cmd

import (
"encoding/json"
"errors"
"fmt"
"github.com/metafates/mangal/anilist"
"github.com/metafates/mangal/constant"
"github.com/metafates/mangal/converter"
"github.com/metafates/mangal/filesystem"
Expand Down Expand Up @@ -122,3 +124,89 @@ When using the json flag manga selector could be omitted. That way, it will sele
handleErr(inline.Run(options))
},
}

func init() {
inlineCmd.AddCommand(inlineAnilistCmd)
}

var inlineAnilistCmd = &cobra.Command{
Use: "anilist",
Short: "Anilist related commands",
}

func init() {
inlineAnilistCmd.AddCommand(inlineAnilistSearchCmd)

inlineAnilistSearchCmd.Flags().StringP("name", "n", "", "manga name to search")
inlineAnilistSearchCmd.Flags().IntP("id", "i", 0, "anilist manga id")

inlineAnilistSearchCmd.MarkFlagsMutuallyExclusive("name", "id")
}

var inlineAnilistSearchCmd = &cobra.Command{
Use: "search",
Short: "Search anilist manga by name",
Run: func(cmd *cobra.Command, args []string) {
mangaName := lo.Must(cmd.Flags().GetString("name"))
mangaId := lo.Must(cmd.Flags().GetInt("id"))

var toEncode any

if mangaName != "" {
mangas, err := anilist.SearchByName(mangaName)
handleErr(err)
toEncode = mangas
} else {
manga, err := anilist.GetByID(mangaId)
handleErr(err)
toEncode = manga
}

handleErr(json.NewEncoder(os.Stdout).Encode(toEncode))
},
}

func init() {
inlineAnilistCmd.AddCommand(inlineAnilistGetCmd)

inlineAnilistGetCmd.Flags().StringP("name", "n", "", "manga name to get bind for")
}

var inlineAnilistGetCmd = &cobra.Command{
Use: "get",
Short: "Get anilist manga that is bind to manga name",
Run: func(cmd *cobra.Command, args []string) {
name := lo.Must(cmd.Flags().GetString("name"))
anilistManga, ok := anilist.GetRelation(name)

if !ok {
var err error
anilistManga, err = anilist.FindClosest(name)
handleErr(err)
}

handleErr(json.NewEncoder(os.Stdout).Encode(anilistManga))
},
}

func init() {
inlineAnilistCmd.AddCommand(inlineAnilistBindCmd)

inlineAnilistBindCmd.Flags().StringP("name", "n", "", "manga name")
inlineAnilistBindCmd.Flags().IntP("id", "i", 0, "anilist manga id")

inlineAnilistBindCmd.MarkFlagsRequiredTogether("name", "id")
}

var inlineAnilistBindCmd = &cobra.Command{
Use: "set",
Short: "Bind manga name to the anilist manga by id",
Run: func(cmd *cobra.Command, args []string) {
anilistManga, err := anilist.GetByID(lo.Must(cmd.Flags().GetInt("id")))
handleErr(err)

mangaName := lo.Must(cmd.Flags().GetString("name"))

handleErr(anilist.SetRelation(mangaName, anilistManga))
},
}
2 changes: 1 addition & 1 deletion constant/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ package constant

const (
Mangal = "mangal"
Version = "3.13.0"
Version = "3.14.0"
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
)
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/gocolly/colly/v2 v2.1.0
github.com/ivanpirog/coloredcobra v1.0.1
github.com/ka-weihe/fast-levenshtein v0.0.0-20201227151214-4c99ee36a1ba
github.com/metafates/mangal-lua-libs v0.4.1-0.20220920195433-ce228b4abd95
github.com/metafates/mangal-lua-libs v0.4.1
github.com/muesli/reflow v0.3.0
github.com/pdfcpu/pdfcpu v0.3.13
github.com/samber/lo v1.33.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWV
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/metafates/mangal-lua-libs v0.4.1-0.20220920195433-ce228b4abd95 h1:8EbMD890jS9WWjtgSzqnURJMTvX1Eat4BKq3Ydpqz6s=
github.com/metafates/mangal-lua-libs v0.4.1-0.20220920195433-ce228b4abd95/go.mod h1:/g3V2cAx3iZHdUcDt1Hr4O69xKhI+jlEiRdvwAReBiA=
github.com/metafates/mangal-lua-libs v0.4.1 h1:wqHgFbZ82gOqiPIFlWAeJGPMvZNSvA8CaQ98hVjPXOo=
github.com/metafates/mangal-lua-libs v0.4.1/go.mod h1:+0gexBk9l//rXWwjcPRmO222qnet+Akm3Sps4jNYnHk=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
Expand Down
2 changes: 1 addition & 1 deletion mini/states.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ func (m *mini) handleHistorySelectState() error {
defaultProviders := provider.Builtins()
customProviders := provider.Customs()

var providers = make([]*provider.Provider, len(defaultProviders)+len(customProviders))
var providers = make([]*provider.Provider, 0)
providers = append(providers, defaultProviders...)
providers = append(providers, customProviders...)

Expand Down
2 changes: 1 addition & 1 deletion network/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ func init() {
}

var Client = &http.Client{
Timeout: 10 * time.Second,
Timeout: 30 * time.Second,
Transport: transport,
}
2 changes: 1 addition & 1 deletion tui/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ func (b *statefulBubble) fetchAnilist(manga *source.Manga) tea.Cmd {
return func() tea.Msg {
log.Info("fetching anilist for " + manga.Name)
b.progressStatus = fmt.Sprintf("Fetching anilist for %s", style.Magenta(manga.Name))
mangas, err := anilist.Search(manga.Name)
mangas, err := anilist.SearchByName(manga.Name)
if err != nil {
log.Error(err)
b.errorChannel <- err
Expand Down

0 comments on commit 574a093

Please sign in to comment.