From a36d5514c068a5006e3a3aeda3e9ac13f03f07ba Mon Sep 17 00:00:00 2001 From: Vidhu Kant Sharma Date: Sun, 6 Feb 2022 18:18:35 +0530 Subject: initial commit for the script --- LICENSE | 4 +-- README.md | 12 +++++++ generator.py | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 generator.py diff --git a/LICENSE b/LICENSE index f288702..0eb113e 100644 --- a/LICENSE +++ b/LICENSE @@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - - Copyright (C) + mal-authtoken-generator will generate your own OAuth token to access MyAnimeList + Copyright (C) 2022 Vidhu Kant Sharma 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 diff --git a/README.md b/README.md index 21345aa..52bb0fc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,14 @@ # mal-authtoken-generator Simple python script to generate your own MyAnimeList OAuth authentication token. + +Heavily inspired with [this guide](https://myanimelist.net/blog.php?eid=835707), +you can use this simple python script to generate an OAuth token to get access +to MyAnimeList's API. + +## Licence + +Licenced under the GNU General Public Licence + +GNU GPL: https://www.gnu.org/licenses/gpl-3.0.en.html + +Copyright (c) 2022 Vidhu Kant Sharma diff --git a/generator.py b/generator.py new file mode 100644 index 0000000..9214ef4 --- /dev/null +++ b/generator.py @@ -0,0 +1,105 @@ +# mal-authtoken-generator will generate your own OAuth token to access MyAnimeList +# Copyright (C) 2022 Vidhu Kant Sharma +# +# 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 . + +import requests +import secrets +import webbrowser + +from http.server import BaseHTTPRequestHandler, HTTPServer +import urllib.parse + +client_id = "" +code_challenge = "" + +def get_access_token(code): + url = "https://myanimelist.net/v1/oauth2/token" + my_headers = { + "Content-Type": "application/x-www-form-urlencoded" + } + my_data = { + "client_id": client_id, + "code_verifier": code_challenge, + "grant_type": "authorization_code", + "code": code, + } + return requests.post(url, data=my_data, headers=my_headers) + +class MyServer(BaseHTTPRequestHandler): + def do_GET(self): + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + + # the flakiest shit ever + path = self.path + params = urllib.parse.parse_qs(path[7:]) + + try: + code = params["code"][0] + res = get_access_token(code) + print(res.json()) + except KeyError: + try: + error = params["error"][0] + error_message = params["message"][0] + error_hint = params["hint"][0] + + print("Error:", error, "<" + error_message + ">", "(" + error_hint + ")") + # write error message to browser window + self.wfile.write(bytes("Error", "utf-8")) + self.wfile.write(bytes("

Error: %s

" % error_hint, "utf-8")) + self.wfile.write(bytes("", "utf-8")) + except: + pass + exit(0) + +def get_new_code_challenge() -> str: + token = secrets.token_urlsafe(100) + return token[:128] + +def auth_link(): + return "https://myanimelist.net/v1/oauth2/authorize?response_type=code&client_id=" + client_id + "&code_challenge=" + code_challenge + +def ask_for_client_id(): + has_client_id = input("Do you already have a MyAnimeList Client ID? [Y/n] ").lower() + if has_client_id in ["y", ""]: + global client_id + client_id = input("Please enter your Client ID: \u001b[32m") + print("\u001b[0m") # reset color + else: + if has_client_id == "n": + print("Please create a new Client ID here: \u001b[36mhttps://myanimelist.net/apiconfig/create\u001b[0m") + print("\t\u001b[37;1m1. \u001b[0mSet the App Redirect URL to \u001b[36;1m\"http://localhost/oauth\"\u001b[0m") + print("\t\u001b[37;1m2. \u001b[0mRestart my script again and then enter your brand new Client ID!") + print("Refer to this guide for more details: \u001b[36mhttps://myanimelist.net/blog.php?eid=835707\u001b[0m") + else: + print("Error: Invalid Input.") + exit(2) + +if __name__ == '__main__': + # credits + print("This script implements the wonderful guide by ZeroCrystal: \u001b[36mhttps://myanimelist.net/blog.php?eid=835707\u001b[0m") + + ask_for_client_id() + code_challenge = get_new_code_challenge() + + auth_link = auth_link() + print("Opening authentication prompt in web browser. If a browser doesn't get launched, please click on this link:") + print("\u001b[36;1m" + auth_link + "\u001b[0m") + webbrowser.open(auth_link, new = 2) + + myServer = HTTPServer(('', 8080), MyServer) + myServer.serve_forever() -- cgit v1.2.3