Initial commit

This commit is contained in:
lolamtisch 2021-06-15 09:52:18 +02:00
commit 258c2e8ff1
6 changed files with 417 additions and 0 deletions

37
.github/workflows/backup.yml vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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"
}
}