mirror of
https://github.com/MALSync/MAL-Sync-Backup.git
synced 2023-09-22 11:52:49 +02:00
Initial commit
This commit is contained in:
commit
258c2e8ff1
6 changed files with 417 additions and 0 deletions
37
.github/workflows/backup.yml
vendored
Normal file
37
.github/workflows/backup.yml
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
name: Backup
|
||||||
|
jobs:
|
||||||
|
backup:
|
||||||
|
name: Backup
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
with:
|
||||||
|
ref: master
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '14.x'
|
||||||
|
- name: Build
|
||||||
|
run: npm install
|
||||||
|
- name: Backup
|
||||||
|
run: npm run backup
|
||||||
|
env:
|
||||||
|
DOMAIN: ${{ secrets.DOMAIN }}
|
||||||
|
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||||
|
- name: Commit files
|
||||||
|
run: |
|
||||||
|
git add data/*
|
||||||
|
git add README.md
|
||||||
|
git config --local user.email "action@github.com"
|
||||||
|
git config --local user.name "GitHub Action"
|
||||||
|
git commit -m "weekly backup" -a
|
||||||
|
- name: Push changes
|
||||||
|
uses: ad-m/github-push-action@master
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
branch: 'master'
|
104
.gitignore
vendored
Normal file
104
.gitignore
vendored
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
113
README.md
Normal file
113
README.md
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
# MAL-Sync Backup
|
||||||
|
The main purppose of this repository is have a backup of the <a href="https://github.com/MALSync/MALSync">MAL-Sync</a> MAL to Streaming page mapping database. But using the data for other uses is allowed.
|
||||||
|
The data is updated once a week. Wrong/missing mappings are not seldom, specially mangas, but because they are generated through all the users of MAL-Sync it should correct itself over time.
|
||||||
|
|
||||||
|
## Stats
|
||||||
|
|
||||||
|
<!--statstable-->
|
||||||
|
| Page | Total | MalID | noMalID | AniID | noAniID |
|
||||||
|
| --------- | ----- | ----- | ------- | ----- | ------- |
|
||||||
|
| 9anime | 12558 | 12384 | 174 | 12041 | 517 |
|
||||||
|
| Gogoanime | 7477 | 7369 | 108 | 7313 | 164 |
|
||||||
|
| Mangadex | 45631 | 25354 | 20277 | 26655 | 18976 |
|
||||||
|
| MangaNato | 4839 | 2678 | 2161 | 2928 | 1911 |
|
||||||
|
| Twistmoe | 1992 | 1971 | 21 | 1966 | 26 |
|
||||||
|
| animepahe | 3701 | 3699 | 2 | 3623 | 78 |
|
||||||
|
| MangaFox | 6256 | 3891 | 2365 | 3861 | 2395 |
|
||||||
|
| MangaSee | 5403 | 4565 | 838 | 4626 | 777 |
|
||||||
|
<!--/statstable-->
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
An _index.json can be found in every folder containing an array of all ids
|
||||||
|
|
||||||
|
### MAL -> Streaming Page Structure:
|
||||||
|
`data/myanimelist/(anime|manga)/[id].json`
|
||||||
|
|
||||||
|
anime/19815
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"altTitle": [
|
||||||
|
"No Game, No Life",
|
||||||
|
"NGNL",
|
||||||
|
"ノーゲーム・ノーライフ"
|
||||||
|
],
|
||||||
|
"id": 19815,
|
||||||
|
"type": "anime",
|
||||||
|
"title": "No Game No Life",
|
||||||
|
"url": "https://myanimelist.net/anime/19815/No_Game_No_Life",
|
||||||
|
"image": "https://cdn.myanimelist.net/images/anime/5/65187.jpg",
|
||||||
|
"category": "TV",
|
||||||
|
"hentai": false,
|
||||||
|
"createdAt": "2020-10-12T12:36:13.580Z",
|
||||||
|
"updatedAt": "2020-10-15T11:36:06.203Z",
|
||||||
|
"Pages": {
|
||||||
|
"Aniwatch": {
|
||||||
|
"350": {
|
||||||
|
"...": "..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"9anime": {
|
||||||
|
"4qkm": {
|
||||||
|
"...": "..."
|
||||||
|
},
|
||||||
|
"y2p0": {
|
||||||
|
"...": "..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Gogoanime": {
|
||||||
|
"no-game-no-life": {
|
||||||
|
"...": "..."
|
||||||
|
},
|
||||||
|
"no-game-no-life-dub": {
|
||||||
|
"...": "..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Twistmoe": {
|
||||||
|
"no-game-no-life": {
|
||||||
|
"...": "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Streaming Page -> MAL Structure:
|
||||||
|
`data/pages/[streaming page key]/[id].json`
|
||||||
|
|
||||||
|
9anime/214
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"identifier": "214",
|
||||||
|
"malUrl": "https://myanimelist.net/anime/9617/K-On_Movie",
|
||||||
|
"type": "anime",
|
||||||
|
"page": "9anime",
|
||||||
|
"title": "K-On! Movie",
|
||||||
|
"url": "...",
|
||||||
|
"image": "....",
|
||||||
|
"hentai": false,
|
||||||
|
"sticky": false,
|
||||||
|
"active": true,
|
||||||
|
"actor": null,
|
||||||
|
"malId": 9617,
|
||||||
|
"createdAt": "...",
|
||||||
|
"updatedAt": "...",
|
||||||
|
"Mal": {
|
||||||
|
"altTitle": [],
|
||||||
|
"id": 9617,
|
||||||
|
"type": "anime",
|
||||||
|
"title": "K-On! Movie",
|
||||||
|
"url": "...",
|
||||||
|
"image": "...",
|
||||||
|
"category": "-",
|
||||||
|
"hentai": false,
|
||||||
|
"createdAt": "...",
|
||||||
|
"updatedAt": "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
How to find the IDs can be checked in <a href="https://github.com/lolamtisch/MALSync/tree/master/src/pages">here</a>.
|
||||||
|
`[PageKey]/main.ts -> (overview|sync):getIdentifier(url)`
|
83
index.js
Normal file
83
index.js
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
const fetch = require('node-fetch');
|
||||||
|
const fs = require('fs-extra')
|
||||||
|
const path = require('path');
|
||||||
|
const table = require('markdown-table');
|
||||||
|
|
||||||
|
async function start() {
|
||||||
|
fs.removeSync('data');
|
||||||
|
await backup('/page/export', 'pages');
|
||||||
|
await backup('/mal/export', 'myanimelist');
|
||||||
|
await backup('/ani/export', 'anilist');
|
||||||
|
await updateReadme();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function backup(url, name, type = 'anime', page = 0, ids = {}) {
|
||||||
|
await getData(url + '/' + type + '/' + page).then(async (json) => {
|
||||||
|
const promises = json.data.map(data => {
|
||||||
|
if(!ids[data.page ?? type]) {
|
||||||
|
ids[data.page ?? type] = [];
|
||||||
|
}
|
||||||
|
ids[data.page ?? type].push(data.identifier ?? data.id);
|
||||||
|
return fs.outputFile(`data/${name}/${data.page ?? type}/${data.identifier ?? data.id}.json`, JSON.stringify(data, null, 2))
|
||||||
|
})
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
if(json.next) {
|
||||||
|
return await backup(url, name, type, page + 1, ids);
|
||||||
|
} else {
|
||||||
|
for(item in ids) {
|
||||||
|
await fs.outputFile(`data/${name}/${item}/_index.json`, JSON.stringify(ids[item].sort(), null, 2))
|
||||||
|
}
|
||||||
|
if(type === 'anime') {
|
||||||
|
return await backup(url, name, 'manga')
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}).catch((e) => {throw 'backup error'});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getData(url) {
|
||||||
|
return fetch(process.env.DOMAIN + url, {
|
||||||
|
headers: {
|
||||||
|
'x-access-token': process.env.ACCESS_TOKEN
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
if(res.status !== 200) {
|
||||||
|
throw "response status not 200";
|
||||||
|
}
|
||||||
|
return res.json()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateReadme() {
|
||||||
|
getData('/stats/db').then(json => {
|
||||||
|
let stats = [['Page', 'Total', 'MalID', 'noMalID', 'AniID', 'noAniID']];
|
||||||
|
|
||||||
|
for (const pageName in json.pages) {
|
||||||
|
const page = json.pages[pageName];
|
||||||
|
stats.push([pageName, page.total, page.mal, page.noMal, page.ani, page.noAni])
|
||||||
|
}
|
||||||
|
|
||||||
|
const statstable = table(stats);
|
||||||
|
const descFile = path.resolve('./README.md');
|
||||||
|
|
||||||
|
fs.readFile(descFile, 'utf8', function(err, data) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
const result = data.replace(/<!--statstable-->((.|\n|\r)*)<!--\/statstable-->/g, `<!--statstable-->\n${statstable}\n<!--/statstable-->`);
|
||||||
|
|
||||||
|
fs.writeFile(descFile, result, 'utf8', function(err) {
|
||||||
|
if (err) throw err;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('unhandledRejection', err => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
start();
|
55
package-lock.json
generated
Normal file
55
package-lock.json
generated
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
"name": "mal-sync-backup",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fs-extra": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.2.0",
|
||||||
|
"jsonfile": "^6.0.1",
|
||||||
|
"universalify": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"graceful-fs": {
|
||||||
|
"version": "4.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
|
||||||
|
"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
|
||||||
|
},
|
||||||
|
"jsonfile": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.6",
|
||||||
|
"universalify": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"markdown-table": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
|
||||||
|
"requires": {
|
||||||
|
"repeat-string": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "2.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||||
|
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||||
|
},
|
||||||
|
"repeat-string": {
|
||||||
|
"version": "1.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||||
|
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
|
||||||
|
},
|
||||||
|
"universalify": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
package.json
Normal file
25
package.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"name": "mal-sync-backup",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "The main purppose of this repository is have a backup of the <a href=\"https://github.com/lolamtisch/MALSync\">MAL-Sync</a> MAL to Streaming page mapping database. But using the data for other uses is allowed. \r The data is updated once a week. Wrong/missing mappings are not seldom, specially mangas, but because they are generated throght all the users of MAL-Sync it should correct itself over time.",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"backup": "node index.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/MALSync/MAL-Sync-Backup.git"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/MALSync/MAL-Sync-Backup/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/MALSync/MAL-Sync-Backup#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
|
"markdown-table": "^2.0.0",
|
||||||
|
"node-fetch": "^2.6.1"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue