aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVidhu Kant Sharma <bokuwakanojogahoshii@yahoo.com>2022-02-17 14:51:50 +0000
committerGitHub <noreply@github.com>2022-02-17 14:51:50 +0000
commitb1ad199abaf9684b120d73acb04dddc213c87af8 (patch)
treea4c0a4650a94859eb256204dec25aa04ac8caf15
parent541c75949e862f6fd1081bc4081b08187fa7da7b (diff)
parent5c94f2f8e7026b9a4dff874edbf3b4fa3b266516 (diff)
Merge pull request #4 from MikunoNaka/user-animelist
Added all the endpoints to access user info and also update user animelist
-rw-r--r--errhandlers/validators.go24
-rw-r--r--go.mod4
-rw-r--r--go.sum2
-rw-r--r--user/anime/animelist.go24
-rw-r--r--user/anime/animelist.structs.go20
-rw-r--r--user/anime/client.go6
-rw-r--r--user/anime/request_handler.go34
-rw-r--r--user/anime/update_animelist.go203
-rw-r--r--user/client.go27
-rw-r--r--user/request_handler.go48
-rw-r--r--user/user.go36
-rw-r--r--user/user.structs.go30
12 files changed, 415 insertions, 43 deletions
diff --git a/errhandlers/validators.go b/errhandlers/validators.go
index 6bf7a3f..1be61cb 100644
--- a/errhandlers/validators.go
+++ b/errhandlers/validators.go
@@ -122,3 +122,27 @@ func IsValidListStatus(status string) bool {
}
return false
}
+
+// Checks if given anime score is valid
+func IsValidScore(score int) bool {
+ if score >= 0 && score <= 10 {
+ return true
+ }
+ return false
+}
+
+// Checks if given anime priority is valid
+func IsValidPriority(priority int) bool {
+ if priority >= 0 && priority <= 2 {
+ return true
+ }
+ return false
+}
+
+// Checks if given rewatch value is valid
+func IsValidRewatchValue(r int) bool {
+ if r >= 0 && r <= 5 {
+ return true
+ }
+ return false
+}
diff --git a/go.mod b/go.mod
index 5fe48c9..5bf033b 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,5 @@
-module github.com/MikunoNaka/mal2go
+module github.com/MikunoNaka/MAL2Go
go 1.17
+
+require github.com/MikunoNaka/mal2go v0.0.0-20220213112712-541c75949e86
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..8148e90
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+github.com/MikunoNaka/mal2go v0.0.0-20220213112712-541c75949e86 h1:hpz3DsUPkaznnO3a1nZZTQeIll0yKTGGWKM0fxvnCxc=
+github.com/MikunoNaka/mal2go v0.0.0-20220213112712-541c75949e86/go.mod h1:fKunJNVMPoiH/yahvQDy9cFdjRkL+w+DDzeOlL4lMEU=
diff --git a/user/anime/animelist.go b/user/anime/animelist.go
index 4f5eac5..bbc7d7a 100644
--- a/user/anime/animelist.go
+++ b/user/anime/animelist.go
@@ -1,4 +1,4 @@
-/* mal2go - MyAnimeList V2 API wrapper for Go
+/* 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
@@ -29,35 +29,19 @@ const BASE_URL string = "https://api.myanimelist.net/v2"
const maxListLimit int = 1000
// Delete an anime from user's anime list
-func (c AnimeListClient)DeleteAnime(id int) string {
+func (c Client)DeleteAnime(id int) string {
endpoint := fmt.Sprintf("%s/anime/%d/my_list_status", BASE_URL, id)
/* Returns 200 if anime successfully deleted
* Alternatively returns 404 if anime not in user's anime list */
return c.requestHandler(endpoint, "DELETE")
}
-// Update/Add an anime to user's anime list
-func (c AnimeListClient)UpdateAnime(id int, data UpdateAnimeData) string {
- endpoint := fmt.Sprintf("%s/anime/%d/my_list_status", BASE_URL, id)
-
- // turn data struct into json
- pepe, err := json.Marshal(data)
- if err != nil {
- fmt.Println(err)
- }
-
- // finally make API request
- res := c.putRequestHandler(endpoint, pepe)
- return res
-}
-
// Get authenticated user's anime list
-func (c AnimeListClient) GetAnimeList(user, status, sort string, limit, offset int) (a.AnimeList, error){
+func (c Client) GetAnimeList(user, status, sort string, limit, offset int) (a.AnimeList, error){
var userAnimeList a.AnimeList
// error handling for limit and offset
limitsErr := e.LimitsErrHandler(limit, offset, maxListLimit)
- if limitsErr != nil {
- return userAnimeList, limitsErr
+ if limitsErr != nil { return userAnimeList, limitsErr
}
// checks if valid sort is specified
diff --git a/user/anime/animelist.structs.go b/user/anime/animelist.structs.go
index d874f7b..cee47d2 100644
--- a/user/anime/animelist.structs.go
+++ b/user/anime/animelist.structs.go
@@ -1,4 +1,4 @@
-/* mal2go - MyAnimeList V2 API wrapper for Go
+/* 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
@@ -29,14 +29,14 @@ type AnimeListRaw struct {
}
type UpdateAnimeData struct {
- Status string `json:"status"`
- IsRewatching bool `json:"is_rewatching"`
- Score int `json:"score"`
- EpWatched int `json:"num_watched_episodes"`
- Priority int `json:"priority"`
- TimesRewatched int `json:"num_times_rewatched"`
+ Status string
+ IsRewatching bool
+ Score int
+ EpWatched int
+ Priority int
+ TimesRewatched int
// NOTE: idk what RewatchValue is
- RewatchValue int `json:"rewatch_value"`
- Tags string `json:"tags"`
- Comments string `json:"comments"`
+ RewatchValue int
+ Tags string
+ Comments string
}
diff --git a/user/anime/client.go b/user/anime/client.go
index e9a99d3..eeba194 100644
--- a/user/anime/client.go
+++ b/user/anime/client.go
@@ -1,4 +1,4 @@
-/* mal2go - MyAnimeList V2 API wrapper for Go
+/* 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
@@ -20,8 +20,8 @@ import (
"net/http"
)
-// MyAnimeList Client for mal2go/anime package
-type AnimeListClient struct {
+// MyAnimeList Client for mal2go/user/anime package
+type Client struct {
AuthToken, RefreshToken string
HttpClient http.Client
}
diff --git a/user/anime/request_handler.go b/user/anime/request_handler.go
index 22c6e0b..abc0afc 100644
--- a/user/anime/request_handler.go
+++ b/user/anime/request_handler.go
@@ -1,9 +1,8 @@
-/* mal2go - MyAnimeList V2 API wrapper for Go
+/* 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
+ * 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,
@@ -17,15 +16,22 @@
package anime
import (
+ "encoding/json"
"io/ioutil"
"log"
"net/http"
+ "net/url"
"strconv"
- "bytes"
+ "strings"
)
+type serverResponse struct {
+ Message string
+ Error string
+}
+
// Handles HTTP request with your OAuth token as a Header
-func (c AnimeListClient) requestHandler(endpoint, method string) string {
+func (c Client) requestHandler(endpoint, method string) string {
// generate request
req, err := http.NewRequest(method, endpoint, nil)
if err != nil {
@@ -54,14 +60,19 @@ func (c AnimeListClient) requestHandler(endpoint, method string) string {
return string(body)
}
-// for PUT requests (used by UpdateAnime)
-func (c AnimeListClient) putRequestHandler(endpoint string, data []uint8) string {
+// 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, bytes.NewBuffer(data))
+ 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)
@@ -76,5 +87,10 @@ func (c AnimeListClient) putRequestHandler(endpoint string, data []uint8) string
log.Fatal(err)
}
- return string(body)
+ // TODO: there are other serverResponses. Add them
+ // server response, ie message / error
+ var resp serverResponse
+ json.Unmarshal(body, &resp)
+
+ return resp
}
diff --git a/user/anime/update_animelist.go b/user/anime/update_animelist.go
new file mode 100644
index 0000000..5a6883c
--- /dev/null
+++ b/user/anime/update_animelist.go
@@ -0,0 +1,203 @@
+/* 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 anime
+
+import (
+ e "github.com/MikunoNaka/mal2go/errhandlers"
+ "errors"
+ "fmt"
+ "net/url"
+ "strconv"
+)
+
+// generate the endpoint url with the anime id
+func endpointGenerator(id int) string {
+ return fmt.Sprintf("%s/anime/%d/my_list_status", BASE_URL, id)
+}
+
+// update just an anime's status
+func (c Client)SetStatus(id int, status string) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // checks if specified list status is valid
+ if !e.IsValidListStatus(status) {
+ return serverResponse{}, errors.New(fmt.Sprintf("SetStatus: Invalid list status: \"%s\"", status))
+ }
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("status", status)
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+// update just an anime's num of episodes watched
+func (c Client)SetWatchedEpisodes(id int, episodesWatched int) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("num_watched_episodes", strconv.Itoa(episodesWatched))
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+// update just an anime's rewatching status
+func (c Client)SetIsRewatching(id int, isRewatching bool) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("is_rewatching", strconv.FormatBool(isRewatching))
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+// update just the anime's score
+func (c Client)SetScore(id int, score int) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // checks if specified score is valid
+ if !e.IsValidScore(score) {
+ return serverResponse{}, errors.New(fmt.Sprintf("SetScore: Invalid score: %d doesn't lie within 0-10", score))
+ }
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("score", strconv.Itoa(score))
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+// update just an anime's priority
+func (c Client)SetPriority(id int, priority int) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // checks if specified priority is valid
+ if !e.IsValidPriority(priority) {
+ return serverResponse{}, errors.New(fmt.Sprintf("SetPriority: Invalid priority: %d doesn't lie within 0-2", priority))
+ }
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("priority", strconv.Itoa(priority))
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+// update just an anime's rewatch value
+func (c Client)SetRewatchValue(id int, rewatchValue int) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // checks if specified rewatch value is valid
+ if !e.IsValidRewatchValue(rewatchValue) {
+ return serverResponse{}, errors.New(fmt.Sprintf("SetRewatchValue: Invalid rewatch value: %d doesn't lie within 0-5", rewatchValue))
+ }
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("rewatch_value", strconv.Itoa(rewatchValue))
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+// update just an anime's rewatch count
+func (c Client)UpdateRewatchCount(id int, rewatchCount int) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("num_times_rewatched", strconv.Itoa(rewatchCount))
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+// update just an anime's tags
+func (c Client)UpdateTags(id int, tags string) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("tags", tags)
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+// update just an anime's comments
+func (c Client)UpdateComments(id int, comments string) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // data to be sent to the server
+ params := url.Values{}
+ params.Set("comments", comments)
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
+/* This will overwrite everything
+ * i won't use it.. but it's pretty flexible
+ * so this will stay here */
+// Update/Add an anime to user's anime list
+func (c Client)UpdateAnime(id int, data UpdateAnimeData) (serverResponse, error) {
+ endpoint := endpointGenerator(id)
+
+ // checks if specified list status is valid
+ if !e.IsValidListStatus(data.Status) {
+ return serverResponse{}, errors.New(fmt.Sprintf("UpdateAnime: Invalid list status: \"%s\"", data.Status))
+ }
+
+ // checks if specified score is valid
+ if !e.IsValidScore(data.Score) {
+ return serverResponse{}, errors.New(fmt.Sprintf("UpdateAnime: Invalid score: %d doesn't lie within 0-10", data.Score))
+ }
+
+ // checks if specified priority is valid
+ if !e.IsValidPriority(data.Priority) {
+ return serverResponse{}, errors.New(fmt.Sprintf("UpdateAnime: Invalid priority: %d doesn't lie within 0-2", data.Priority))
+ }
+
+ // checks if specified rewatch value is valid
+ if !e.IsValidRewatchValue(data.RewatchValue) {
+ return serverResponse{}, errors.New(fmt.Sprintf("UpdateAnime: Invalid rewatch value: %d doesn't lie within 0-5", data.RewatchValue))
+ }
+
+ params := url.Values{}
+
+ /* NOTE: THIS WILL OVERWRITE ANY DATA THAT
+ * IS NOT SPECIFIED AND SET IT TO NULL */
+ params.Set("status", data.Status)
+ params.Set("is_rewatching", strconv.FormatBool(data.IsRewatching))
+ params.Set("score", strconv.Itoa(data.Score))
+ params.Set("num_watched_episodes", strconv.Itoa(data.EpWatched))
+ params.Set("priority", strconv.Itoa(data.Priority))
+ params.Set("num_times_rewatched", strconv.Itoa(data.TimesRewatched))
+ params.Set("rewatch_value", strconv.Itoa(data.RewatchValue))
+ params.Set("tags", data.Tags)
+ params.Set("comments", data.Comments)
+
+ // make API request
+ return c.putRequestHandler(endpoint, params), nil
+}
+
diff --git a/user/client.go b/user/client.go
new file mode 100644
index 0000000..7d5b800
--- /dev/null
+++ b/user/client.go
@@ -0,0 +1,27 @@
+/* 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 user
+
+import (
+ "net/http"
+)
+
+// MyAnimeList Client for mal2go/anime package
+type MALUserClient struct {
+ AuthToken, RefreshToken string
+ HttpClient http.Client
+}
diff --git a/user/request_handler.go b/user/request_handler.go
new file mode 100644
index 0000000..da8c5f7
--- /dev/null
+++ b/user/request_handler.go
@@ -0,0 +1,48 @@
+/* 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 user
+
+import (
+ "io/ioutil"
+ "log"
+ "net/http"
+)
+
+// Handles HTTP request with your OAuth token as a Header
+func (c MALUserClient) requestHandler(endpoint string) string {
+ // generate request
+ req, err := http.NewRequest("GET", 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)
+ }
+
+ return string(body)
+}
diff --git a/user/user.go b/user/user.go
new file mode 100644
index 0000000..31ac8dc
--- /dev/null
+++ b/user/user.go
@@ -0,0 +1,36 @@
+/* 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 user
+
+import (
+ "encoding/json"
+)
+
+const BASE_URL string = "https://api.myanimelist.net/v2/users"
+
+// Get info of logged in user
+func (c *MALUserClient) GetSelfUserInfo() UserInfo {
+ /* MAL only supports @me for this */
+ endpoint := BASE_URL + "/@me?fields=anime_statistics"
+
+ // get data from API
+ var userData UserInfo
+ data := c.requestHandler(endpoint)
+ json.Unmarshal([]byte(data), &userData)
+
+ return userData
+}
diff --git a/user/user.structs.go b/user/user.structs.go
new file mode 100644
index 0000000..b730033
--- /dev/null
+++ b/user/user.structs.go
@@ -0,0 +1,30 @@
+/* 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 user
+
+type UserInfo struct {
+ Id int `json:"id"`
+ Name string `json:"name"`
+ Picture string `json:"picture"`
+ Gender string `json:"gender"`
+ Birthday string `json:"birthday"`
+ Location string `json:"location"`
+ JoinedAt string `json:"joined_at"`
+ // TODO: Add AnimeStatistics
+ TimeZone string `json:"time_zone"`
+ IsSupporter bool `json:"is_supporter"`
+}