Compare commits
23 commits
Author | SHA1 | Date | |
---|---|---|---|
|
d0634a315f | ||
|
acc70e6a83 | ||
|
9203335963 | ||
|
3a88d983fc | ||
|
63ab17ce4c | ||
|
021c326fae | ||
|
07c37f396f | ||
|
3ed371fbda | ||
|
bda2a1f3d1 | ||
|
6564dec7a8 | ||
|
e9f43d47ea | ||
|
420374ea58 | ||
|
8b64b70be4 | ||
|
f5e9f696b8 | ||
|
929e691a68 | ||
|
19588c67d6 | ||
|
2617a4ed19 | ||
|
cb2b7285b5 | ||
|
7ac1637e86 | ||
|
c1c012438c | ||
|
e1db5506ab | ||
|
3f25702e8e | ||
|
b8d9c1f28d |
10 changed files with 2721 additions and 0 deletions
19
.eslintrc.js
Normal file
19
.eslintrc.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
commonjs: true,
|
||||||
|
es6: true,
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'standard'
|
||||||
|
],
|
||||||
|
globals: {
|
||||||
|
Atomics: 'readonly',
|
||||||
|
SharedArrayBuffer: 'readonly'
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2018
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
}
|
||||||
|
}
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
local.sh
|
21
LICENCE.txt
Normal file
21
LICENCE.txt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Damien Broqua and contributors (https://framagit.org/dbroqua/rx3-to-mastodon/-/graphs/master)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
45
README.md
45
README.md
|
@ -1,2 +1,47 @@
|
||||||
# rx3-to-mastodon
|
# rx3-to-mastodon
|
||||||
|
|
||||||
|
Bot permettant de publier sur Mastodon le titre en cours de lecture sur [Real Rebel Radio](https://www.real-rebel-radio.net/).
|
||||||
|
|
||||||
|
## Pré requis
|
||||||
|
|
||||||
|
* Un compte mastodon
|
||||||
|
* Un compte discogs
|
||||||
|
* Un serveur avec NodeJS
|
||||||
|
* Une base de données MongDB
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Le bot a besoin de quelques variables d'environnement pour tourner en totale autonomie :
|
||||||
|
|
||||||
|
```json
|
||||||
|
"streamUrl": "Url du flux rx3 (facultatif)",
|
||||||
|
"mongoUrl": "Url de connexion à mongoDb, par défaut : mongodb://localhost/rx3-to-mastodon",
|
||||||
|
"mastodonToken": "Token Mastodon (https://mamot.fr/settings/applications, autorisations requises : write:media, write:statuses)",
|
||||||
|
"mastondonApi": "Url de l'instance Mastodon utilisées, par défaut : https://mamot.fr/api/v1/",
|
||||||
|
"discogsToken": "Token d'accès l'API Discogs (https://www.discogs.com/settings/developers)",
|
||||||
|
"delay": "Délai en millisecondes entre 2 scans au flux rx3, par défaut 4000ms"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lancement du BOT
|
||||||
|
|
||||||
|
Une fois les variables d'environnement appliquées il faut installer les dépendances nécessaires au programe via npm ou yarn :
|
||||||
|
|
||||||
|
```
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
Une fois cela fait on peut lancer le bot via la commande start :
|
||||||
|
|
||||||
|
```
|
||||||
|
yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Crédits
|
||||||
|
|
||||||
|
Ce bot est une idée originale de Rx3 et [Brunus](https://framapiaf.org/@Brunus).
|
||||||
|
|
||||||
|
Développé par [DarKou](https://mamot.fr/@DarKou).
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
|
||||||
|
Rx3 to Mastodon est distribué sous [licence MIT](LICENCE.txt)
|
37
config.js
Normal file
37
config.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
module.exports = {
|
||||||
|
streamUrl: process.env.streamUrl || 'http://37.59.28.208/rpc/realrebe/streaminfo.get',
|
||||||
|
mongoUrl: process.env.mongoUrl || 'mongodb://localhost/rx3-to-mastodon',
|
||||||
|
mastodonToken: process.env.mastodonToken,
|
||||||
|
mastondonApi: process.env.mastondonApi || 'https://mamot.fr/api/v1/',
|
||||||
|
discogsToken: process.env.discogsToken,
|
||||||
|
delay: process.env.delay || 4000,
|
||||||
|
rx3List: ['Rx3', 'REAL REBEL RADIO', 'REAL REBEL RADIO homemade'],
|
||||||
|
rx3CoverBaseUrl: process.env.rx3CoverBaseUrl,
|
||||||
|
colors: {
|
||||||
|
Reset: '\x1b[0m',
|
||||||
|
Bright: '\x1b[1m',
|
||||||
|
Dim: '\x1b[2m',
|
||||||
|
Underscore: '\x1b[4m',
|
||||||
|
Blink: '\x1b[5m',
|
||||||
|
Reverse: '\x1b[7m',
|
||||||
|
Hidden: '\x1b[8m',
|
||||||
|
|
||||||
|
FgBlack: '\x1b[30m',
|
||||||
|
FgRed: '\x1b[31m',
|
||||||
|
FgGreen: '\x1b[32m',
|
||||||
|
FgYellow: '\x1b[33m',
|
||||||
|
FgBlue: '\x1b[34m',
|
||||||
|
FgMagenta: '\x1b[35m',
|
||||||
|
FgCyan: '\x1b[36m',
|
||||||
|
FgWhite: '\x1b[37m',
|
||||||
|
|
||||||
|
BgBlack: '\x1b[40m',
|
||||||
|
BgRed: '\x1b[41m',
|
||||||
|
BgGreen: '\x1b[42m',
|
||||||
|
BgYellow: '\x1b[43m',
|
||||||
|
BgBlue: '\x1b[44m',
|
||||||
|
BgMagenta: '\x1b[45m',
|
||||||
|
BgCyan: '\x1b[46m',
|
||||||
|
BgWhite: '\x1b[47m'
|
||||||
|
}
|
||||||
|
}
|
42
index.js
Normal file
42
index.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
const moment = require('moment')
|
||||||
|
const libs = require('./libs')
|
||||||
|
const config = require('./config')
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
// Récupération du morceau en cours de diffusion
|
||||||
|
libs.getStream((error, currentSong) => {
|
||||||
|
if (!error) {
|
||||||
|
// On récupére en base le précédent morceau joué
|
||||||
|
libs.getLastSong((err, last) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(config.colors.FgRed, '[ERR] GET LAST SONG:', moment().format(), err, config.colors.Reset)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Le morceau actuel est différent du précedent morceau
|
||||||
|
if (last.length === 0 ||
|
||||||
|
(last[0] !== undefined && last[0].id !== currentSong.id)
|
||||||
|
) {
|
||||||
|
// On sauvegarde en base le morceau en cours de diffusion
|
||||||
|
libs.saveSong(currentSong, (err, savedSond) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(config.colors.FgRed, '[ERR] SAVE SONG:', moment().format(), err, config.colors.Reset)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// On récupère la cover du morceau actuel
|
||||||
|
libs.findCover(currentSong, (err, coverUrl) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(config.colors.FgRed, '[ERR] FIND COVER:', moment().format(), err, config.colors.Reset)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// On publie sur Mastodon
|
||||||
|
libs.publishMessage(currentSong, coverUrl)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, config.delay)
|
285
libs.js
Normal file
285
libs.js
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
const request = require('request')
|
||||||
|
const Discogs = require('disconnect').Client
|
||||||
|
const Masto = require('mastodon')
|
||||||
|
|
||||||
|
const mongo = require('./mongo')
|
||||||
|
const config = require('./config')
|
||||||
|
|
||||||
|
// Instanciation de Mastodon
|
||||||
|
const M = new Masto({
|
||||||
|
access_token: config.mastodonToken,
|
||||||
|
api_url: config.mastondonApi
|
||||||
|
})
|
||||||
|
|
||||||
|
// Instanciation de Disgocs
|
||||||
|
const dis = new Discogs({ userToken: config.discogsToken }).database()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de sauvegarder en historique le morceau en cours de diffusion
|
||||||
|
* @param {Object} values
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
const saveSong = (values, callback) => {
|
||||||
|
mongo.Histories
|
||||||
|
.find({})
|
||||||
|
.sort({
|
||||||
|
createdAt: 'desc'
|
||||||
|
})
|
||||||
|
.limit(1)
|
||||||
|
.exec(function (err, last) {
|
||||||
|
if (err ||
|
||||||
|
last.length === 0 ||
|
||||||
|
(last[0] !== undefined && last[0].stringId !== values.stringId)
|
||||||
|
) {
|
||||||
|
console.log(config.colors.FgBlue, '[INFO][saveSong] song not found:', values.title, values.artist, config.colors.Reset)
|
||||||
|
|
||||||
|
const history = new mongo.Histories(values)
|
||||||
|
history.save(callback)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de retrouver le dernier morceau sauvegardé en base
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
const getLastSong = (callback) => {
|
||||||
|
mongo.Histories
|
||||||
|
.find({})
|
||||||
|
.sort({
|
||||||
|
createdAt: 'desc'
|
||||||
|
})
|
||||||
|
.limit(1)
|
||||||
|
.exec(function (err, last) {
|
||||||
|
if (err) {
|
||||||
|
callback(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, last)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de retrouver la cover d'un titre Rx3
|
||||||
|
* @param {Object} song
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
const getRx3Cover = (song, callback) => {
|
||||||
|
let cover = null
|
||||||
|
// Cas des GSU
|
||||||
|
if (song.title.indexOf('GSU') === 0) {
|
||||||
|
const year = song.title.split(' ')[1]
|
||||||
|
|
||||||
|
if (!isNaN(parseInt(year))) {
|
||||||
|
cover = `${config.rx3CoverBaseUrl}gsu${year}.jpg`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, cover)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de chercher sur Discogs la pochette d'un album
|
||||||
|
* @param {Object} song
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
const getRemoteCover = (song, callback) => {
|
||||||
|
if (config.rx3List.indexOf(song.artist) !== -1) {
|
||||||
|
getRx3Cover(song, callback)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si c'est KOЯN on remplace par KORN (merci discogs)
|
||||||
|
if (song.artist === 'KOЯN') {
|
||||||
|
song.artist = 'KORN'
|
||||||
|
}
|
||||||
|
|
||||||
|
dis.search({ q: song.album, artist: song.artist, page: 1, per_page: 1 }, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(config.colors.FgRed, 'ERR:', err, config.colors.Reset)
|
||||||
|
callback(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Une pochette est trouvée
|
||||||
|
if (res.results && res.results.length === 1) {
|
||||||
|
callback(null, res.results[0].cover_image)
|
||||||
|
} else {
|
||||||
|
console.log(config.colors.FgBlue, '[INFO] No cover found for:', song.album, song.artist, config.colors.Reset)
|
||||||
|
callback(null, null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de retourner l'url de la pochette d'un album
|
||||||
|
* @param {Object} song
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
const findCover = (song, callback) => {
|
||||||
|
mongo.Metadata.findOne({
|
||||||
|
stringId: song.stringId
|
||||||
|
})
|
||||||
|
.exec((err, metadata) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ce morceau est déjà en base
|
||||||
|
if (metadata) {
|
||||||
|
// On a déjà une pochette pour ce morceau
|
||||||
|
if (metadata.cover) {
|
||||||
|
console.log(config.colors.FgBlue, '[INFO][findCover] cover exists:', metadata._id, metadata.cover, config.colors.Reset)
|
||||||
|
|
||||||
|
callback(null, metadata.cover)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aucune pochette trouvée, on interroge Discogs (peut être que cette fois ils auront une cover...)
|
||||||
|
getRemoteCover(song, (err, coverUrl) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
console.log(config.colors.FgBlue, '[INFO][findCover] cover does not exists but found on discogs:', coverUrl, config.colors.Reset)
|
||||||
|
metadata.updateOne({ cover: coverUrl })
|
||||||
|
callback(null, coverUrl)
|
||||||
|
})
|
||||||
|
} else { // Première fois que ce morceau est jouée, on rempli sa fiche
|
||||||
|
getRemoteCover(song, (err, coverUrl) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
console.log(config.colors.FgBlue, '[INFO][findCover] cover does not exists but found on discogs (2):', coverUrl, config.colors.Reset)
|
||||||
|
|
||||||
|
song.cover = coverUrl
|
||||||
|
const metadata = new mongo.Metadata(song)
|
||||||
|
metadata.save()
|
||||||
|
callback(null, coverUrl)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de récupérer le titre diffusé
|
||||||
|
* @param {Funtion} callback
|
||||||
|
*/
|
||||||
|
const getStream = (callback) => {
|
||||||
|
request.get(config.streamUrl,
|
||||||
|
(error, response, body) => {
|
||||||
|
if (!error && response.statusCode === 200) {
|
||||||
|
let res = null
|
||||||
|
try {
|
||||||
|
const _body = JSON.parse(body)
|
||||||
|
|
||||||
|
res = {
|
||||||
|
artist: _body.data[0].track.artist,
|
||||||
|
title: _body.data[0].track.title,
|
||||||
|
album: _body.data[0].track.album,
|
||||||
|
royaltytrackid: _body.data[0].track.royaltytrackid,
|
||||||
|
id: _body.data[0].track.id,
|
||||||
|
stringId: _body.data[0].track.id || `FAKEID_${_body.data[0].track.artist}_${_body.data[0].track.title}_${_body.data[0].track.album}`,
|
||||||
|
playlistId: _body.data[0].track.playlist ? _body.data[0].track.playlist.id : null,
|
||||||
|
thumbCover: _body.data[0].track.imageurl
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res !== null && res.artist !== undefined && res.title !== undefined) {
|
||||||
|
callback(null, res)
|
||||||
|
} else {
|
||||||
|
error = true
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
error = e
|
||||||
|
console.error('getStream error:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
callback(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de télécharger la pochette d'un album selon une URL donnée
|
||||||
|
* @param {String} coverUrl
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
const getMedia = (coverUrl, callback) => {
|
||||||
|
const dest = '/tmp/attachment.jpg'
|
||||||
|
const file = fs.createWriteStream(dest)
|
||||||
|
|
||||||
|
try {
|
||||||
|
request({
|
||||||
|
uri: coverUrl,
|
||||||
|
headers: {
|
||||||
|
'Cache-Control': 'max-age=0',
|
||||||
|
Connection: 'keep-alive',
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('error', (error) => {
|
||||||
|
console.log(config.colors.FgRed, 'ERR:', error, config.colors.Reset)
|
||||||
|
callback(error)
|
||||||
|
})
|
||||||
|
.pipe(file)
|
||||||
|
.on('finish', () => {
|
||||||
|
callback(null, dest)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
callback(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction formattant le texte à publier
|
||||||
|
* @param {Object} values
|
||||||
|
*/
|
||||||
|
const formatMessage = (values) => {
|
||||||
|
return `#rx3 #nowplaying ${values.artist} - ${values.title}`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction publiant un message (et média si attaché) sur Mastdon
|
||||||
|
* @param {Object} song
|
||||||
|
* @param {String} cover
|
||||||
|
*/
|
||||||
|
const publishMessage = (song, cover) => {
|
||||||
|
const status = formatMessage(song)
|
||||||
|
const callback = (err, res) => {
|
||||||
|
if ( err ) {
|
||||||
|
console.log(config.colors.FgRed, 'ERR on publishMessage:', err, config.colors.Reset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cover) {
|
||||||
|
getMedia(cover, (err, dest) => {
|
||||||
|
if (err) {
|
||||||
|
M.post('statuses', { status }, callback)
|
||||||
|
} else {
|
||||||
|
M.post('media', { file: fs.createReadStream(dest) }).then(resp => {
|
||||||
|
const id = resp.data.id
|
||||||
|
M.post('statuses', { status, media_ids: [id] }, callback)
|
||||||
|
})
|
||||||
|
.catch( () => {
|
||||||
|
M.post('statuses', { status }, callback)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
M.post('statuses', { status }, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
saveSong: saveSong,
|
||||||
|
getLastSong: getLastSong,
|
||||||
|
findCover: findCover,
|
||||||
|
getStream: getStream,
|
||||||
|
getMedia: getMedia,
|
||||||
|
formatMessage: formatMessage,
|
||||||
|
publishMessage: publishMessage
|
||||||
|
}
|
50
mongo.js
Normal file
50
mongo.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
const mongoose = require('mongoose')
|
||||||
|
|
||||||
|
const config = require('./config')
|
||||||
|
|
||||||
|
const schemas = {
|
||||||
|
histories: mongoose.Schema({
|
||||||
|
artist: String,
|
||||||
|
title: String,
|
||||||
|
album: String,
|
||||||
|
royaltytrackid: Number,
|
||||||
|
id: Number,
|
||||||
|
stringId: String,
|
||||||
|
playlistId: Number,
|
||||||
|
thumbCover: String,
|
||||||
|
createdAt: {
|
||||||
|
type: Date,
|
||||||
|
default: Date.now
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
metadata: mongoose.Schema({
|
||||||
|
artist: String,
|
||||||
|
title: String,
|
||||||
|
album: String,
|
||||||
|
royaltytrackid: Number,
|
||||||
|
id: Number,
|
||||||
|
stringId: String,
|
||||||
|
playlistId: Number,
|
||||||
|
thumbCover: String,
|
||||||
|
cover: String,
|
||||||
|
createdAt: {
|
||||||
|
type: Date,
|
||||||
|
default: Date.now
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const Histories = mongoose.model('histories', schemas.histories)
|
||||||
|
const Metadata = mongoose.model('metadata', schemas.metadata)
|
||||||
|
|
||||||
|
mongoose.set('debug', true)
|
||||||
|
|
||||||
|
mongoose.connect(config.mongoUrl, { useNewUrlParser: true, useUnifiedTopology: true })
|
||||||
|
|
||||||
|
const db = mongoose.connection
|
||||||
|
db.on('error', console.error.bind(console, 'connection error:'))
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Histories: Histories,
|
||||||
|
Metadata: Metadata
|
||||||
|
}
|
24
package.json
Normal file
24
package.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "rx3-to-mastodon",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"start": "./node_modules/.bin/nodemon ./index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"disconnect": "^1.2.1",
|
||||||
|
"mastodon": "^1.2.2",
|
||||||
|
"moment": "^2.24.0",
|
||||||
|
"mongoose": "^5.7.13",
|
||||||
|
"request": "^2.88.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^6.7.1",
|
||||||
|
"eslint-config-standard": "^14.1.0",
|
||||||
|
"eslint-plugin-import": "^2.18.2",
|
||||||
|
"eslint-plugin-node": "^10.0.0",
|
||||||
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
|
"eslint-plugin-standard": "^4.0.1",
|
||||||
|
"nodemon": "^2.0.1"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue