aboutsummaryrefslogtreecommitdiff
path: root/user/manga
diff options
context:
space:
mode:
Diffstat (limited to 'user/manga')
-rw-r--r--user/manga/README.md19
-rw-r--r--user/manga/mangalist.go92
-rw-r--r--user/manga/mangalist.structs.go9
-rw-r--r--user/manga/request_handler.go96
4 files changed, 215 insertions, 1 deletions
diff --git a/user/manga/README.md b/user/manga/README.md
new file mode 100644
index 0000000..1a6c636
--- /dev/null
+++ b/user/manga/README.md
@@ -0,0 +1,19 @@
+# MAL2Go/user
+MAL2Go `user/anime` package has functionality related to updating the user's anime list.
+
+## Usage
+Firstly, import this package and instanciate the client.
+``` go
+import (
+ "github.com/MikunoNaka/MAL2Go/user/anime"
+)
+```
+
+Now instanciate with
+``` go
+myClient := anime.Client {
+ AuthToken: "Bearer " + yourTokenHere,
+}
+```
+
+**More to be added later**
diff --git a/user/manga/mangalist.go b/user/manga/mangalist.go
new file mode 100644
index 0000000..392e844
--- /dev/null
+++ b/user/manga/mangalist.go
@@ -0,0 +1,92 @@
+/* MAL2Go - MyAnimeList V2 API wrapper for Go
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@protonmail.ch>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+package manga
+
+import (
+ "encoding/json"
+ "strconv"
+ "fmt"
+ "errors"
+ e "github.com/MikunoNaka/MAL2Go/errhandlers"
+)
+
+const BASE_URL string = "https://api.myanimelist.net/v2"
+const maxListLimit int = 1000
+
+// Delete a manga from user's manga list
+func (c Client)DeleteManga(id int) string {
+ endpoint := fmt.Sprintf("%s/manga/%d/my_list_status", BASE_URL, id)
+ /* Returns 200 if manga successfully deleted
+ * Alternatively returns 404 if manga not in user's manga list */
+ return c.requestHandler(endpoint, "DELETE")
+}
+
+// Get authenticated user's manga list
+func (c Client) GetMangaList(user, status, sort string, limit, offset int) (MangaList, error){
+ var userMangaList MangaList
+ // error handling for limit
+ limitErr := e.LimitErrHandler(limit, maxListLimit)
+ if limitErr != nil {
+ return userMangaList, limitErr
+ }
+
+ // checks if valid sort is specified
+ if !e.IsValidMangaListSort(sort) {
+ return userMangaList, errors.New(fmt.Sprintf("GetMangaList: Invalid sort specified: \"%s\"", sort))
+ }
+
+ // checks if valid status is specified
+ if status != "" && !e.IsValidMangaListStatus(status) {
+ return userMangaList, errors.New(fmt.Sprintf("GetMangaList: Invalid status specified: \"%s\"", status))
+ }
+
+ // get own list if user not specified
+ if user == "" {
+ user = "@me"
+ }
+
+ // if status is "" it returns all anime
+ var endpoint string
+ if status == "" {
+ endpoint = BASE_URL + "/users/" + user + "/mangalist?sort=" + sort + "&limit=" + strconv.Itoa(limit) + "&offset=" + strconv.Itoa(offset)
+ } else {
+ endpoint = BASE_URL + "/users/" + user + "/mangalist?status=" + status + "&sort=" + sort + "&limit=" + strconv.Itoa(limit) + "&offset=" + strconv.Itoa(offset)
+ }
+
+ // get data from API
+ var mangaListData MangaListRaw
+ data := c.requestHandler(endpoint, "GET")
+ json.Unmarshal([]byte(data), &mangaListData)
+
+ // set MyListStatus for each element and add it to array
+ var mangas []Manga
+ for _, element := range mangaListData.Data {
+ a := element.Manga
+ a.ListStatus = element.ListStatus
+
+ mangas = append(mangas, a)
+ }
+
+ // finally create AnimeList
+ userMangaList = MangaList {
+ Mangas: mangas,
+ Paging: mangaListData.Paging,
+ }
+
+ return userMangaList, nil
+}
+
diff --git a/user/manga/mangalist.structs.go b/user/manga/mangalist.structs.go
index 860163b..0ea7d70 100644
--- a/user/manga/mangalist.structs.go
+++ b/user/manga/mangalist.structs.go
@@ -21,14 +21,21 @@ import (
"github.com/MikunoNaka/MAL2Go/manga"
)
+type Manga manga.Manga
+
type MangaListRaw struct {
Data []struct {
- Manga manga.Manga `json:"node"`
+ Manga Manga `json:"node"`
ListStatus manga.ListStatus `json:"list_status"`
} `json:"data"`
Paging util.ListPaging `json:"paging"`
}
+type MangaList struct {
+ Mangas []Manga
+ Paging util.ListPaging
+}
+
type UpdateMangaData struct {
Status string
IsRereading bool
diff --git a/user/manga/request_handler.go b/user/manga/request_handler.go
new file mode 100644
index 0000000..ff2b0df
--- /dev/null
+++ b/user/manga/request_handler.go
@@ -0,0 +1,96 @@
+/* MAL2Go - MyAnimeList V2 API wrapper for Go
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@protonmail.ch>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+package manga
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+)
+
+type serverResponse struct {
+ Message string
+ Error string
+}
+
+// Handles HTTP request with your OAuth token as a Header
+func (c Client) requestHandler(endpoint, method string) string {
+ // generate request
+ req, err := http.NewRequest(method, endpoint, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ req.Header.Add("Authorization", c.AuthToken)
+
+ // do request
+ res, err := c.HttpClient.Do(req)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer res.Body.Close()
+
+ // read body
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // for DeleteAnime, its endpoint returns null data
+ if method == "DELETE" {
+ return strconv.Itoa(res.StatusCode)
+ }
+
+ return string(body)
+}
+
+// for PUT requests (used for updating anime)
+func (c Client) putRequestHandler(endpoint string, params url.Values) serverResponse {
+ paramsEncoded := params.Encode()
+
+ // generate request
+ req, err := http.NewRequest(http.MethodPut, endpoint, strings.NewReader(paramsEncoded))
+ if err != nil {
+ log.Fatal(err)
+ }
+ req.Header.Add("Authorization", c.AuthToken)
+ // this makes the sending-data-to-server magic work
+ req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ req.Header.Add("Content-Length", strconv.Itoa(len(paramsEncoded)))
+
+ // do request
+ res, err := c.HttpClient.Do(req)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer res.Body.Close()
+
+ // read body
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // TODO: there are other serverResponses. Add them
+ // server response, ie message / error
+ var resp serverResponse
+ json.Unmarshal(body, &resp)
+
+ return resp
+}