Mangadex
Welcome to mangadex
, your next favourite Ruby gem for interacting with Mangadex.
Important information
By using this gem you accept:
- To credit Mangadex. This gem is your friendly neighbourhood wrapper on their API.
- To credit scanlation groups, especially if you offer the ability to read chapters.
- Not to run any ads on the service that will use this gem. Please do not make money off of Mangadex's services.
These are Mangadex's rules, please follow them.
Installation
Add this line to your application's Gemfile:
gem 'mangadex'
And then execute:
$ bundle
Or install it yourself as:
$ gem install mangadex
Usage
Please note that I tried my best to follow Mangadex's naming conventions for their documentation. Track the progress here in an issue. Although a work a in progress, feel free to check this out.
Basic Usage
Here's a couple of cool things you can do with the gem:
Get a list of manga
response = Mangadex::Manga.list
manga = response.data # Array of #<Mangadex::Manga>
Get a manga by id, with cover_art
manga_id = 'd86cf65b-5f6c-437d-a0af-19a31f94ec55'
response = Mangadex::Manga.get(manga_id, includes: :cover_art)
entity = response.data # Object of #<Mangadex::Manga>
# Original size
entity.cover_art.image_url(size: :original)
entity.cover_art.image_url(size: :medium)
entity.cover_art.image_url(size: :small) # default size
Get a manga's chapter list, ordered by volume and chapter number
manga_id = 'd86cf65b-5f6c-437d-a0af-19a31f94ec55'
manga_response = Mangadex::Manga.get(manga_id, includes: :cover_art)
entity = manga_response.data
chapter_response = Mangadex::Chapter.list(
manga: entity.id,
order: { volume: 'asc', chapter: 'asc' },
translated_language: 'en',
)
chapters = chapter_response.data # Array of #<Mangadex::Chapter>
Get a chapter's pages
chapter_id = 'e7bb1892-7f83-4a89-bccc-0d6d403a85fc'
chapter = Mangadex::Chapter.get(chapter_id).data
pages = chapter.page_urls # Data saver true by default
Search for manga by title
response = Mangadex::Manga.list(title: 'Ijiranaide nagatoro')
found_manga = response.data
Authenticate
with a block...:
Mangadex::Auth.login(username: 'username', password: 'password') do |user|
# `user` is of type Mangadex::Api::User
puts(user.mangadex_user_id)
puts(user.session)
puts(user.refresh)
puts(user.session_valid_until)
end
...or inline...:
# `user` is of type Mangadex::Api::User
user = Mangadex::Auth.login(username: 'username', password: 'password')
puts(user.mangadex_user_id)
puts(user.session)
puts(user.refresh)
puts(user.session_valid_until)
You can access the authenticated user by using context:
user = Mangadex.context.user
Refresh the user's token
Mangadex.context.user.refresh_session! do |user|
# `user` is of type Mangadex::Api::User
puts(user.mangadex_user_id)
puts(user.session)
puts(user.refresh)
puts(user.session_valid_until)
end
Create an public MDList, add then remove a manga
Mangadex::Auth.login(...)
response = Mangadex::CustomList.create(name: 'My awesome list!', visibility: 'public')
custom_list = response.data
manga_id = 'd86cf65b-5f6c-437d-a0af-19a31f94ec55'
# Add the manga
custom_list.add_manga(manga_id)
# Remove the manga
custom_list.remove_manga(manga_id)
# Get manga list
manga = custom_list.manga_details.data # Array of #<Mangadex::Manga>
Are you on Rails?
This gem tries its best to be agnostic to popular frameworks like Rails. Here's however a couple of things to can do to integrate the gem to your project.
First, add the gem to your Gemfile
.
Configurating the gem
Create a initilizer file to config/initializers/mangadex.rb
. You can add the following:
Mangadex.configure do |config|
# Override the default content ratings
config.default_content_ratings = %w(safe suggestive)
# Override the Mangadex API URL (ie: proxy)
config.mangadex_url = 'https://my-proxy-mangadex-url.com'
end
Authenticate your users
This could be useful if you want to support authentication. You will need to persist your user's session, refresh token and session expiry date.
Persist the user information
If you haven't done so, create your user.
class CreateUsers < ActiveRecord::Migration[6.1]
def change
create_table :users do |t|
t.string :mangadex_user_id, null: false
t.string :username
t.string :session
t.string :refresh
t.datetime :session_valid_until
t.timestamps
end
end
end
Already created your User
class? Make sure it has all of the following:
-
mangade_user_id
: ID used to identify your user on Mangadex -
username
: Your username -
session
: The session token (valid for 15 minutes) -
refresh
: The refresh token, used to refresh the session (valid for 1 month) -
session_valid_until
: The timesession
session expires at
If anything is missing, create a migration.
Authentication flow on the controller
Add these methods to your controller's helper (ie: ApplicationHelper
):
module ApplicationHelper
def current_user
@current_user ||= User.find_by(id: session[:id])
end
def logged_in?
current_user.present?
end
def log_in(user)
# `user` is an instance of your `User` class
session[:id] = user.id
end
def log_out
# Logout from Mangadex
Mangadex::Auth.logout
# Remove the session
session.delete(:id)
end
end
First make sure ApplicationController
includes the helper above
class ApplicationController < ActionController::Base
include ApplicationHelper
# ...
end
We recommend creating a controller for authentication. Here's how you can implement the login and logout actions:
# app/controllers/session_controller.rb
class SessionController < ApplicationController
# GET /login
def new
# render the login form
end
# POST /login
def create
username = params[:username]
password = params[:password]
# You can also use `email` instead of `username` to log in
user = Mangadex::Auth.login(username: username, password: password) do |mangadex_user|
# Find the user by mangadex user id (or initialize if it doesn't exist)
our_user = User.find_or_initialize_by(mangadex_user_id: mangadex_user.mangadex_user_id) do |new_user|
new_user.username = mangadex_user.data.username
end
# Update the session info data
our_user.session = mangadex_user.session
our_user.refresh = mangadex_user.refresh
our_user.session_valid_until = mangadex_user.session_valid_until
# ...then save the user
our_user.save!
our_user
end
# `user` will be an instance of your `User` class
# Now, we can log in then redirect to the root.
log_in(user)
redirect_to(root_path)
rescue Mangadex::Errors::AuthenticationError => error
# See https://api.mangadex.org/docs.html to learn more about errors
Rails.logger.error(error.response.errors)
# Handle authentication errors here
end
# DELETE /logout
def destroy
log_out
redirect_to(root_path)
end
end
Finally, add the routes.
# config/routes.rb
Rails.application.routes.draw do
# ...
get '/login' => 'session#new'
post '/login' => 'session#create'
delete '/logout' => 'session#destroy'
end
Protected resources
Here's an example of a controller that requires every action to be logged in. This is based on the steps above.
class ProtectedController < ApplicationController
before_action :ensure_logged_in!
private
def ensure_logged_in!
return if logged_in?
redirect_to(login_path) # go to /login
end
end
We're going with managing (list, create, show, edit, delete) MDLists (ie: custom lists). We're not using strong params below to keep things simple, but you should, especially when mutating data (ie: creating and editing).
class CustomListsController < ProtectedController
# GET /custom_list
def index
@custom_lists = Mangadex::CustomList.list
end
# GET /custom_list/new
def new
# new custom list form
end
# POST /custom_list
def create
@custom_list = Mangadex::CustomList.create(
name: params[:name],
visibility: params[:visibility],
manga: params[:manga], # Manga ID
)
end
# GET /custom_list/<id>
def show
@custom_list = Mangadex::CustomList.get(params[:id])
end
# GET /custom_list/<id>/edit
def edit
@custom_list = Mangadex::CustomList.get(params[:id])
# edit custom list form
end
# PUT /custom_list/<id>
# PATCH /custom_list/<id>
def update
# Note: when updating the custom list, be sure to pass in
# the current version number!
@custom_list = Mangadex::CustomList.update(
params[:id],
{
name: params[:name],
visibility: params[:visibility],
manga: params[:manga],
version: params[:version].to_i,
}
)
end
# DELETE /custom_list/<id>
def destroy
Mangadex::CustomList.delete(params[:id])
end
end
Development
Docker
You can use Docker to get started with dev work on the repo. After installing Dcoker, you can build the image:
docker build -t mangadex .
Then run the ruby console with the gem loaded:
docker run --rm -it mangadex:latest
You can also log in directly when setting the MD_USERNAME
and MD_PASSWORD
(or MD_EMAIL
) environment variables:
docker run --rm -e MD_USERNAME=username -e MD_PASSWORD=password -it mangadex:latest
Docker Compose
If it's simpler, you can simply use Compose and get started quickly.
Note: You may have to use
docker-compose
if you're using Compose V1. This project should be compatible with both Compose V1 and V2. See the Compose migration docs to learn more.
Build the image:
docker compose build
And run the ruby console with the gem loaded:
docker compose run gem
Create a docker-compose.override.yml
to add environment secrets (and anything else you'd like to customize):
# docker-compose.override.yml
version: '3'
services:
gem:
environment:
MD_USERNAME: username
MD_PASSWORD: password
Running docker compose run gem
, which launches the ruby console, will attempt logging in the user username
.
Locally
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
You can also
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/thedrummeraki/mangadex. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the Mangadex project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.