aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVidhu Kant Sharma <vidhukant@vidhukant.com>2025-06-03 22:25:01 +0530
committerVidhu Kant Sharma <vidhukant@vidhukant.com>2025-06-03 22:25:01 +0530
commit68a449da1aff148ad500f448e7d753e7745ba845 (patch)
tree5ee9320aae379eb68aa3ec98645d97cf2f09c3cd
first commit
-rw-r--r--.gitignore4
-rw-r--r--.gitmodules12
-rw-r--r--README.md14
-rw-r--r--macli/.hugo_build.lock0
-rw-r--r--macli/.hugo_upload3
-rw-r--r--macli/content/_index.md24
-rw-r--r--macli/content/releases/1.21.0.md16
-rw-r--r--macli/hugo.toml14
-rw-r--r--macli/static/favicon.icobin0 -> 1150 bytes
-rw-r--r--macli/static/sitemap.xml11
m---------macli/themes/zt_hugo0
-rw-r--r--meow/.hugo_build.lock0
-rw-r--r--meow/.hugo_upload3
-rw-r--r--meow/content/_index.md91
-rw-r--r--meow/hugo.toml27
-rw-r--r--meow/static/favicon.icobin0 -> 1150 bytes
m---------meow/themes/zt_hugo0
-rw-r--r--mg/.hugo_build.lock0
-rw-r--r--mg/.hugo_upload3
-rw-r--r--mg/content/_index.md630
-rw-r--r--mg/hugo.toml27
-rw-r--r--mg/static/favicon.icobin0 -> 1150 bytes
m---------mg/themes/zt_hugo0
-rw-r--r--openbills/.hugo_build.lock0
-rw-r--r--openbills/.hugo_upload3
-rw-r--r--openbills/content/_index.md5
-rw-r--r--openbills/hugo.toml13
-rw-r--r--openbills/static/favicon.icobin0 -> 1150 bytes
m---------openbills/themes/zt_hugo0
29 files changed, 900 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2a6c340
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/macli/public
+/meow/public
+/mg/public
+/openbills/public
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..abae6d9
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "macli/themes/zt_hugo"]
+ path = macli/themes/zt_hugo
+ url = https://git.vidhukant.com/zt_hugo
+[submodule "meow/themes/zt_hugo"]
+ path = meow/themes/zt_hugo
+ url = https://git.vidhukant.com/zt_hugo
+[submodule "mg/themes/zt_hugo"]
+ path = mg/themes/zt_hugo
+ url = https://git.vidhukant.com/zt_hugo
+[submodule "openbills/themes/zt_hugo"]
+ path = openbills/themes/zt_hugo
+ url = https://git.vidhukant.com/zt_hugo
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f321802
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+# Projects
+
+This repository holds some websites that I have made to showcase my projects
+or to provide documentation.
+
+It doesn't really make sense to have a different repo for each site, so I'm
+storing them here. Check out the [zt\_hugo](/zt_hugo) hugo theme, too.
+
+## These sites in action (sorted alphabetically)
+
+- <https://macli.vidhukant.com>
+- <https://meow.vidhukant.com>
+- <https://mg.vidhukant.com>
+- <https://openbills.vidhukant.com>
diff --git a/macli/.hugo_build.lock b/macli/.hugo_build.lock
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/macli/.hugo_build.lock
diff --git a/macli/.hugo_upload b/macli/.hugo_upload
new file mode 100644
index 0000000..2e3b47d
--- /dev/null
+++ b/macli/.hugo_upload
@@ -0,0 +1,3 @@
+user=vidhukant
+host=vidhukant.com
+target_dir=/var/www/macli-website
diff --git a/macli/content/_index.md b/macli/content/_index.md
new file mode 100644
index 0000000..c6b5905
--- /dev/null
+++ b/macli/content/_index.md
@@ -0,0 +1,24 @@
+# MyAnimeListCLIent
+
+macli is a free and open source (FOSS) unofficial [MyAnimeList](https://myanimelist.net/) client for use inside the terminal.
+It's supported on Linux, Android (Termux), MacOS (untested), Windows and probably any other OS that Go would compile on!
+
+## How to install
+
+### Pre-built binaries
+
+Grab a build from [releases](/releases) and (optionally) move the binary file into the path.
+
+### Installing from source
+
+Either clone the [git repo](https://git.vidhukant.com/macli) and do a `go build` or directly install with `go install vidhukant.com/macli@latest`.
+
+You can also use the [macli](https://aur.archlinux.org/packages/macli) and [macli-git](https://aur.archlinux.org/packages/macli-git) AUR packages.
+
+## License
+
+Licenced under GNU General Public Licence V3
+
+GNU GPL License: [LICENSE](https://git.vidhukant.com/macli/about/LICENSE)
+
+Copyright (c) 2022-2023 Vidhu Kant Sharma
diff --git a/macli/content/releases/1.21.0.md b/macli/content/releases/1.21.0.md
new file mode 100644
index 0000000..6fd64ba
--- /dev/null
+++ b/macli/content/releases/1.21.0.md
@@ -0,0 +1,16 @@
+---
+date: 2023-11-24
+version_number: "1.21.0"
+version_name: "v1.21.0"
+---
+
+## Logging in now made easy!
+
+These builds have a pre-configured MyAnimeList Client ID so you can just download and run and log in!
+
+**Download links:**
+
+- [Linux .tar.gz (64bit)](/releases/1.21.0/macli-v1.21.0-linux_amd64.tar.gz)
+- [Linux .zip (64bit)](/releases/1.21.0/macli-v1.21.0-linux_amd64.zip)
+- [Windows .zip (64bit)](/releases/1.21.0/macli-v1.21.0-windows_amd64.zip)
+- [sha256sums.txt](/releases/1.21.0/sha256sums.txt)
diff --git a/macli/hugo.toml b/macli/hugo.toml
new file mode 100644
index 0000000..3ea1b6b
--- /dev/null
+++ b/macli/hugo.toml
@@ -0,0 +1,14 @@
+baseURL = 'https://macli.vidhukant.com/'
+languageCode = 'en-us'
+title = 'Official macli Website.'
+theme = "zt_hugo"
+disableKinds = ["taxonomy", "term", "sitemap"]
+enableRobotsTXT = true
+
+[params]
+projectTitle = "macli"
+projectDescription = "Unofficial CLI-based MyAnimeList client."
+gitURL = "https://git.vidhukant.com/macli/about"
+extraNavLinks = [
+ ["GitHub", "https://github.com/VidhuKant/macli"]
+]
diff --git a/macli/static/favicon.ico b/macli/static/favicon.ico
new file mode 100644
index 0000000..4927520
--- /dev/null
+++ b/macli/static/favicon.ico
Binary files differ
diff --git a/macli/static/sitemap.xml b/macli/static/sitemap.xml
new file mode 100644
index 0000000..a5f1763
--- /dev/null
+++ b/macli/static/sitemap.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
+ xmlns:xhtml="http://www.w3.org/1999/xhtml">
+ <url>
+ <loc>https://macli.vidhukant.com/</loc>
+ <lastmod>2023-09-19T00:00:00+00:00</lastmod>
+ </url><url>
+ <loc>https://macli.vidhukant.com/releases/</loc>
+ <lastmod>2023-09-19T00:00:00+00:00</lastmod>
+ </url>
+</urlset>
diff --git a/macli/themes/zt_hugo b/macli/themes/zt_hugo
new file mode 160000
+Subproject f7175a61b6f1c8dbe5525c29081d0b00bce998d
diff --git a/meow/.hugo_build.lock b/meow/.hugo_build.lock
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/meow/.hugo_build.lock
diff --git a/meow/.hugo_upload b/meow/.hugo_upload
new file mode 100644
index 0000000..0bda291
--- /dev/null
+++ b/meow/.hugo_upload
@@ -0,0 +1,3 @@
+user=vidhukant
+host=vidhukant.com
+target_dir=/var/www/meow-website
diff --git a/meow/content/_index.md b/meow/content/_index.md
new file mode 100644
index 0000000..425e42f
--- /dev/null
+++ b/meow/content/_index.md
@@ -0,0 +1,91 @@
+# Meow
+
+Search nyaa (or any proxy/mirrors) with web scraping.
+
+``` go
+package main
+
+import (
+ "fmt"
+ "vidhukant.com/meow"
+)
+
+func main() {
+ q := meow.SearchQuery {
+ SearchString: "mushishi",
+
+ BaseURL: "nyaa.si", // default
+ Filter: 0, // none (default)
+ Category: meow.CategoryAll, // default
+ Page: 1, // default (range 1-100)
+ }
+
+ res, err := meow.Search(q)
+ if err != nil {
+ panic(err)
+ }
+
+ for _, i := range res {
+ fmt.Println(i.Title)
+ fmt.Println(i.Category)
+ fmt.Println(i.Flag)
+ fmt.Println(i.URL)
+ fmt.Println(i.TorrentURL)
+ fmt.Println(i.MagnetURL)
+ fmt.Println(i.FileSize)
+ fmt.Println(i.TimeStamp)
+ fmt.Println(i.Seeders)
+ fmt.Println(i.Leechers)
+ fmt.Println(i.Downloads)
+ }
+}
+```
+
+## Available categories
+
+Pretty self explanatory
+
+- `CategoryAll`
+
+- `CategoryAnime`
+- `CategoryAnimeAMV`
+- `CategoryAnimeEnglish`
+- `CategoryAnimeNonEnglish`
+- `CategoryAnimeRaw`
+
+- `CategoryAudio`
+- `CategoryAudioLossless`
+- `CategoryAudioLossy`
+
+- `CategoryLiterature`
+- `CategoryLiteratureEnglish`
+- `CategoryLiteratureNonEnglish`
+- `CategoryLiteratureRaw`
+
+- `CategoryLiveAction`
+- `CategoryLiveActionEnglish`
+- `CategoryLiveActionIdolPV`
+- `CategoryLiveActionNonEnglish`
+- `CategoryLiveActionRaw`
+
+- `CategoryPictures`
+- `CategoryPicturesGraphics`
+- `CategoryPicturesPhotos`
+
+- `CategorySoftware`
+- `CategorySoftwareApps`
+- `CategorySoftwareGames`
+
+## Available filters
+
+- `FilterNone`
+- `FilterNoRemakes`
+- `FilterTrustedOnly`
+
+# License
+
+Licenced under GNU General Public Licence
+
+GNU GPL License: [LICENSE](https://git.vidhukant.com/meow/tree/LICENSE)
+
+Copyright (c) 2024 Vidhu Kant Sharma
diff --git a/meow/hugo.toml b/meow/hugo.toml
new file mode 100644
index 0000000..2921522
--- /dev/null
+++ b/meow/hugo.toml
@@ -0,0 +1,27 @@
+baseURL = 'https://meow.vidhukant.com/'
+languageCode = 'en-us'
+title = 'Meow - Nyaa web scraper for Go'
+theme = "zt_hugo"
+disableKinds = ["taxonomy", "term"]
+enableRobotsTXT = true
+
+[params]
+projectTitle = "Meow"
+projectDescription = "Get search results from Nyaa through web scraping with GoLang"
+gitURL = "https://git.vidhukant.com/meow"
+extraNavLinks = [
+]
+
+[markup]
+ [markup.highlight]
+ anchorLineNos = false
+ codeFences = true
+ guessSyntax = true
+ hl_Lines = ''
+ hl_inline = false
+ lineAnchors = ''
+ lineNoStart = 1
+ lineNos = true
+ lineNumbersInTable = false
+ noClasses = false
+ tabWidth = 4
diff --git a/meow/static/favicon.ico b/meow/static/favicon.ico
new file mode 100644
index 0000000..4927520
--- /dev/null
+++ b/meow/static/favicon.ico
Binary files differ
diff --git a/meow/themes/zt_hugo b/meow/themes/zt_hugo
new file mode 160000
+Subproject f7175a61b6f1c8dbe5525c29081d0b00bce998d
diff --git a/mg/.hugo_build.lock b/mg/.hugo_build.lock
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mg/.hugo_build.lock
diff --git a/mg/.hugo_upload b/mg/.hugo_upload
new file mode 100644
index 0000000..8e07ce8
--- /dev/null
+++ b/mg/.hugo_upload
@@ -0,0 +1,3 @@
+user=vidhukant
+host=vidhukant.com
+target_dir=/var/www/mg-website
diff --git a/mg/content/_index.md b/mg/content/_index.md
new file mode 100644
index 0000000..fe8ef69
--- /dev/null
+++ b/mg/content/_index.md
@@ -0,0 +1,630 @@
+# mg
+
+mg is a free and open source library for accessing the official MyAnimeList V2 API using Go. All endpoints are supported except forums as of now.
+
+If you find any bugs, please write to me at <vidhukant@vidhukant.com>
+
+# License
+
+Licenced under GNU General Public Licence V3
+
+GNU GPL License: [link](https://git.vidhukant.com/mg/tree/LICENSE)
+
+Copyright (c) 2022-2023 Vidhu Kant Sharma
+
+# Documentation
+
+***for v1.0.1+***
+
+*Documentation might be incomplete or buggy. If you want to submit any changes, or need any help, please feel free to contact me at the given E-mail address.*
+
+## Initializing the mg client
+
+There are 2 ways to authenticate with mg:
+- ClientAuth
+
+ With ClientAuth, you just need to use your MyAnimeList Client ID to access the read-only resources.
+ You cannot do actions that require logging in. To use ClientAuth, set `client.ClientAuthOnly` to `true`.
+- MainAuth
+
+ With MainAuth, you can perform actions like getting recommendations, or editing an anime/manga list.
+ For this, you need to generate a Bearer token; for which a Client ID is still needed.
+ `ClientAuthOnly` must be set to `false` to use MainAuth.
+
+Check out [Authentication](#authentication) for more details.
+
+``` go
+package main
+
+import (
+ "vidhukant.com/mg"
+)
+
+func main() {
+ var client mg.Client
+
+ // either this
+ client.MainAuth = "Bearer <your token here>"
+
+ // or this
+ client.ClientAuth = "<your client id here>"
+ client.ClientAuthOnly = true
+
+ // ...
+}
+```
+
+# Anime
+
+## Searching for an anime
+
+`MainAuth` or `ClientAuth`
+
+``` go
+// ...
+
+var animes []mg.Anime
+
+params := mg.SearchParamsNew()
+params.SearchString = "mushishi"
+
+// optional; these are the default values
+params.Limit = 100 // max = 100
+params.Offset = 0
+params.NSFW = false
+params.Fields = []string{}
+
+err := client.SearchAnime(&animes, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+for _, anime := range animes {
+ fmt.Println(anime.Title)
+}
+
+// ...
+```
+
+## Getting an anime's information
+
+`MainAuth` or `ClientAuth`
+
+_searching can be a bit inaccurate, if you know the anime's ID (obtain it with SearchAnime!) and want to get detailed information, use this._
+
+``` go
+// ...
+
+var anime mg.Anime
+
+err := client.GetAnimeById(&anime, /*anime id*/ 457, /*fields*/ []string{})
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Getting anime ranking list
+
+`MainAuth` or `ClientAuth`
+
+Accepted ranking types:
+| Ranking Type | Description |
+|----------------------------|-------------------------|
+| mg.RankingTypeAll | Top Anime Series |
+| mg.RankingTypeByPopularity | Top Anime by Popularity |
+| mg.RankingTypeFavorite | Top Favorited Anime |
+| mg.RankingTypeAiring | Top Airing Anime |
+| mg.RankingTypeUpcoming | Top Upcoming Anime |
+| mg.RankingTypeTV | Top Anime TV Series |
+| mg.RankingTypeOVA | Top Anime OVA Series |
+| mg.RankingTypeMovie | Top Anime Movies |
+| mg.RankingTypeSpecial | Top Anime Specials |
+
+## Getting seasonal animes
+
+`MainAuth` or `ClientAuth`
+
+Accepted seasons:
+- `mg.SeasonWinter`
+- `mg.SeasonSpring`
+- `mg.SeasonSummer`
+- `mg.SeasonFall`
+
+Accepted sorts:
+- `mg.SeasonSortByAnimeScore` (descending)
+- `mg.SeasonSortByNumListUsers` (descending)
+
+
+``` go
+// ...
+
+var seasonals []mg.Anime
+
+params := mg.SeasonalParamsNew()
+
+params.Year = "2023" // required
+params.Season = mg.SeasonFall // required
+
+// optional; these are the default values
+params.Sort = mg.SeasonSortByAnimeScore
+params.Limit = 100 // max = 500
+params.Offset = 0
+params.NSFW = false
+params.Fields = []string{}
+
+err := client.GetSeasonalAnime(&seasonals, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Getting suggested animes
+
+`MainAuth` only
+
+``` go
+// ...
+
+var suggestedAnimes []mg.Anime
+
+params := mg.SuggestedParamsNew()
+
+// optional; these are the default values
+params.Limit = 100 // max = 100
+params.Offset = 0
+params.NSFW = false
+params.Fields = []string{}
+
+err := client.GetSeasonalAnime(&suggestedAnimes, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Get any user's anime list
+
+`MainAuth` or `ClientAuth`
+
+This returns a boolean telling us if there is a next page on this user's list.
+Simply increment the offset by the limit and create a new request in order to get the next page.
+
+In order to get the complete list, repeat the process until `nextPageExists` becomes false.
+
+Accepted statuses:
+- `mg.ListStatusAll`
+- `mg.ListStatusWatching`
+- `mg.ListStatusCompleted`
+- `mg.ListStatusOnHold`
+- `mg.ListStatusDropped`
+- `mg.ListStatusPTW`
+
+Accepted list sorts:
+- `mg.SortByListScore` (descending)
+- `mg.SortByListUpdatedAt` (descending)
+- `mg.SortByAnimeTitle` (ascending)
+- `mg.SortByAnimeStartDate` (descending)
+- `mg.SortByAnimeId` (ascending) (beta according to MAL)
+
+``` go
+// ...
+
+var animes []mg.Anime
+
+params := mg.ListParamsNew()
+
+// optional; these are the default values
+params.Username = "@me" // can speciy any public account
+params.Status = mg.ListStatusAll
+params.Sort = mg.SortByListScore
+params.Limit = 100 // max = 1000
+params.Offset = 0
+params.NSFW = false
+params.Fields = []string{}
+
+nextPageExists, err := client.GetAnimeList(&animes, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Updating an anime
+
+`MainAuth` only
+
+Updates an anime in the the currently logged in user's anime list.
+Adds the anime if it's not in the list.
+
+Accepted statuses:
+- `mg.ListStatusWatching`
+- `mg.ListStatusCompleted`
+- `mg.ListStatusOnHold`
+- `mg.ListStatusDropped`
+- `mg.ListStatusPTW`
+
+Score range: `0` - `10`
+
+Priority range: `0` - `2`
+| Priority | Description |
+|----------|-------------|
+| 0 | Low |
+| 1 | Medium |
+| 2 | High |
+
+RewatchValue range: `0` - `5`
+| RewatchValue | Description |
+|--------------|-------------|
+| 0 | None |
+| 1 | Very Low |
+| 2 | Low |
+| 3 | Medium |
+| 4 | High |
+| 5 | Very High |
+
+``` go
+// ...
+
+var res AnimeUpdateResponse
+
+// can omit any field but keep at least 1!
+params := map[string]interface{} {
+ mg.Status: mg.ListStatusCompleted,
+ mg.IsRewatching: false,
+ mg.Score: 10,
+ mg.EpisodesWatched: 26,
+ mg.Priority: 2,
+ mg.TimesRewatched: 2,
+ mg.RewatchValue: 5,
+ mg.Tags: "tags",
+ mg.Comments: "comments",
+}
+
+err := client.UpdateAnime(&res, /*anime id*/ 457, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Deleting an anime from list
+
+`MainAuth` only
+
+Deletes the anime from currently logged in user's anime list.
+Returns an error if anime is already not in the list.
+
+``` go
+// ...
+
+err := client.DeleteAnime(/*anime id*/ 457)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+# Manga
+
+## Searching for a manga
+
+`MainAuth` or `ClientAuth`
+
+_also works for light novels, etc_
+
+``` go
+// ...
+
+var mangas []mg.Manga
+
+carams := mg.SearchParamsNew()
+carams.SearchString = "empty box and zeroth maria"
+
+// optional; these are the default values
+params.Limit = 100
+params.Offset = 0
+params.NSFW = false
+params.Fields = []string{}
+
+err := client.SearchManga(&mangas, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+for _, manga range mangas {
+ fmt.Println(manga.Title)
+}
+
+// ...
+```
+
+## Getting a manga's information
+
+`MainAuth` or `ClientAuth`
+
+_searching can be a bit inaccurate, if you know the manga's ID (obtain it with SearchManga!) and want to get detailed information, use this._
+
+``` go
+// ...
+
+var manga mg.Manga
+
+err := client.GetMangaById(&manga, /*manga id*/ 55215, /*fields*/ []string{})
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Getting manga ranking list
+
+`MainAuth` or `ClientAuth`
+
+Accepted ranking types:
+| RankingType | Description |
+|----------------------------|----------------|
+| mg.RankingTypeAll | All |
+| mg.RankingTypeByPopularity | Most Popular |
+| mg.RankingTypeFavorite | Most Favorited |
+| mg.RankingTypeManga | Top Manga |
+| mg.RankingTypeNovel | Top Novels |
+| mg.RankingTypeOneShot | Top One-shots |
+| mg.RankingTypeDoujin | Top Doujinshi |
+| mg.RankingTypeManhwa | Top Manhwa |
+| mg.RankingTypeManhua | Top Manhua |
+
+*RankedManga is just the Manga struct with an extra field `RankNum int`*
+
+``` go
+// ...
+
+var rankingList []mg.RankedManga
+
+params := mg.RankingParamsNew()
+
+// optional; these are the default values
+params.RankingType = mg.RankingTypeAll
+params.Limit = 100 // max = 500
+params.Offset = 0
+params.NSFW = false
+params.Fields = []string{}
+
+err := client.GetAnimeRanking(&rankingList, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Get any user's manga list
+
+`MainAuth` or `ClientAuth`
+
+This returns a boolean telling us if there is a next page on this user's list.
+Simply increment the offset by the limit and create a new request in order to get the next page.
+
+In order to get the complete list, repeat the process until `nextPageExists` becomes false.
+
+Accepted statuses:
+- `mg.ListStatusAll`
+- `mg.ListStatusReading`
+- `mg.ListStatusCompleted`
+- `mg.ListStatusOnHold`
+- `mg.ListStatusDropped`
+- `mg.ListStatusPTR`
+
+Accepted list sorts:
+- `mg.SortByListScore` (descending)
+- `mg.SortByListUpdatedAt` (descending)
+- `mg.SortByMangaTitle` (ascending)
+- `mg.SortByMangaStartDate` (descending)
+- `mg.SortByMangaId` (ascending) (beta according to MAL)
+
+``` go
+// ...
+
+var mangas []mg.Manga
+
+params := mg.ListParamsNew()
+
+// optional; these are the default values
+params.Username = "@me" // can speciy any public account
+params.Status = mg.ListStatusAll
+params.Sort = mg.SortByListScore
+params.Limit = 100 // max = 1000
+params.Offset = 0
+params.NSFW = false
+params.Fields = []string{}
+
+nextPageExists, err := client.GetMangaList(&mangas, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Updating a manga
+
+`MainAuth` only
+
+Updates a manga in the the currently logged in user's manga list.
+Adds the manga if it's not in the list.
+
+Accepted statuses:
+- `mg.ListStatusReading`
+- `mg.ListStatusCompleted`
+- `mg.ListStatusOnHold`
+- `mg.ListStatusDropped`
+- `mg.ListStatusPTR`
+
+Score range: `0` - `10`
+
+Priority range: `0` - `2`
+| Priority | Description |
+|----------|-------------|
+| 0 | Low |
+| 1 | Medium |
+| 2 | High |
+
+RereadValue range: `0` - `5`
+| RereadValue | Description |
+|-------------|-------------|
+| 0 | None |
+| 1 | Very Low |
+| 2 | Low |
+| 3 | Medium |
+| 4 | High |
+| 5 | Very High |
+
+``` go
+// ...
+
+var res MangaUpdateResponse
+
+// can omit any field but keep at least 1!
+params := map[string]interface{} {
+ mg.Status: mg.ListStatusReading,
+ mg.IsRereading: false,
+ mg.Score: 10,
+ mg.VolumesRead: 2,
+ mg.ChaptersRead: 20,
+ mg.Priority: 2,
+ mg.TimesReread: 0,
+ mg.RereadValue: 5,
+ mg.Tags: "tags",
+ mg.Comments: "comments",
+}
+
+err := client.UpdateManga(&res, /*manga id*/ 55215, params)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+## Deleting a manga from list
+
+`MainAuth` only
+
+Deletes the manga from currently logged in user's manga list.
+Returns an error if manga is already not in the list.
+
+``` go
+// ...
+
+err := client.DeleteManga(/*manga id*/ 55215)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+# User
+
+## Get logged in user's details
+
+`MainAuth` only
+
+MyAnimeList's official API doesn't support getting another user's details. Only the currently logged in user.
+
+``` go
+// ...
+
+var user mg.User
+
+// to get user's list statistics or not
+getStatistics := true
+
+err := client.GetSelfInfo(&user, getStatistics)
+if err != nil {
+ fmt.Println(err.Error())
+}
+
+// ...
+```
+
+# Authentication
+
+## With maltoken
+
+You can use [maltoken](https://git.vidhukant.com/maltoken/about), which provides an easy way to automate this whole process.
+Here's an example:
+
+Go to <https://myanimelist.net/apiconfig> to generate your very own Client ID.
+- Enter all the required details, for the app's homepage you can use the URL for the repository
+- For the App Redirect URL, use `localhost:PORT` (or your domain if you want to run mg on a server)
+
+Then use this code to authenticate:
+
+*replace PORT with the port you set as the App Redirect URL while creating a Client ID*
+
+``` go
+package main
+
+import (
+ "fmt"
+ mt "vidhukant.com/maltoken"
+)
+
+func main() {
+ // optionally change the HTML that is shown in the browser
+ mt.SuccessHTML = "<p>Yee haw</p>"
+ mt.BadRequestHTML = "<p>Y u do this</p>"
+
+ // The %s is optional
+ mt.ErrHTML = `
+ <style>
+ body {
+ color: red;
+ }
+ </style>
+ <p>An error occoured: %s</p>
+ `
+
+ cid := "<your_client_id_here>"
+ challenge, link := mt.GetChallengeLink(cid)
+
+ fmt.Println("Open this link in your browser: ", link)
+
+ res, err := mt.Listen(cid, challenge, PORT)
+ if err != nil {
+ fmt.Println(err.Error())
+ }
+
+ fmt.Println("API Response:", res)
+}
+```
+
+## With maltoken-cli
+
+Install maltoken-cli:
+
+``` fish
+go install vidhukant.com/maltoken-cli@latest
+```
+
+Then run like this (flags are optional):
+
+``` fish
+maltoken-cli --launch --client-id "<your_client_id_here>" --port 8000
+```
+
+Run `maltoken-cli -h` for more info.
+
+## Manually/other options
+
+Otherwise, check out [this guide](https://myanimelist.net/blog.php?eid=835707)
+to know more about how this whole process works.
diff --git a/mg/hugo.toml b/mg/hugo.toml
new file mode 100644
index 0000000..4a70e3a
--- /dev/null
+++ b/mg/hugo.toml
@@ -0,0 +1,27 @@
+baseURL = 'https://mg.vidhukant.com/'
+languageCode = 'en-us'
+title = 'Official mg Website.'
+theme = "zt_hugo"
+disableKinds = ["taxonomy", "term"]
+enableRobotsTXT = true
+
+[params]
+projectTitle = "mg"
+projectDescription = "MyAnimeList V2 API Wrapper for Go"
+gitURL = "https://git.vidhukant.com/mg"
+extraNavLinks = [
+]
+
+[markup]
+ [markup.highlight]
+ anchorLineNos = false
+ codeFences = true
+ guessSyntax = true
+ hl_Lines = ''
+ hl_inline = false
+ lineAnchors = ''
+ lineNoStart = 1
+ lineNos = true
+ lineNumbersInTable = false
+ noClasses = false
+ tabWidth = 4
diff --git a/mg/static/favicon.ico b/mg/static/favicon.ico
new file mode 100644
index 0000000..4927520
--- /dev/null
+++ b/mg/static/favicon.ico
Binary files differ
diff --git a/mg/themes/zt_hugo b/mg/themes/zt_hugo
new file mode 160000
+Subproject f7175a61b6f1c8dbe5525c29081d0b00bce998d
diff --git a/openbills/.hugo_build.lock b/openbills/.hugo_build.lock
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/openbills/.hugo_build.lock
diff --git a/openbills/.hugo_upload b/openbills/.hugo_upload
new file mode 100644
index 0000000..f6b3b67
--- /dev/null
+++ b/openbills/.hugo_upload
@@ -0,0 +1,3 @@
+user=vidhukant
+host=vidhukant.com
+target_dir=/var/www/openbills-website
diff --git a/openbills/content/_index.md b/openbills/content/_index.md
new file mode 100644
index 0000000..6d01c02
--- /dev/null
+++ b/openbills/content/_index.md
@@ -0,0 +1,5 @@
+# OpenBills
+
+OpenBills is an under construction, highly bespoke libre billing software geared towards small businesses.
+
+More to be added!
diff --git a/openbills/hugo.toml b/openbills/hugo.toml
new file mode 100644
index 0000000..b592b51
--- /dev/null
+++ b/openbills/hugo.toml
@@ -0,0 +1,13 @@
+baseURL = 'https://openbills.vidhukant.com/'
+languageCode = 'en-us'
+title = 'Official OpenBills Website.'
+theme = "zt_hugo"
+disableKinds = ["taxonomy", "term"]
+enableRobotsTXT = true
+
+[params]
+projectTitle = "OpenBills"
+projectDescription = "Libre Billing Software"
+gitURL = "https://git.vidhukant.com/openbills"
+extraNavLinks = [
+]
diff --git a/openbills/static/favicon.ico b/openbills/static/favicon.ico
new file mode 100644
index 0000000..4927520
--- /dev/null
+++ b/openbills/static/favicon.ico
Binary files differ
diff --git a/openbills/themes/zt_hugo b/openbills/themes/zt_hugo
new file mode 160000
+Subproject f7175a61b6f1c8dbe5525c29081d0b00bce998d