Project

mangadex

0.0
There's a lot of open issues
No release in over a year
Your next favourite Ruby gem for interacting with Mangadex.org
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 2.2.19
>= 0
~> 13.0
~> 3.0
>= 0

Runtime

>= 4.0.1, < 5.2.0
 Project Readme

Docker Image CI

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 time session 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.