Skip to content

Instantly share code, notes, and snippets.

@nkcmr
Last active April 23, 2017 10:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nkcmr/498c2455777f8102d04a to your computer and use it in GitHub Desktop.
Save nkcmr/498c2455777f8102d04a to your computer and use it in GitHub Desktop.
simple deluge complete scope that uploads stuff to google drive

deluge to google drive uploader

simple uploader script for deluge, assign this script to be called on torrent complete and it will walk a directory and upload it to your google drive

install dependencies:

npm install googleapis async winston lodash mime twilio
{
"TWILIO_SID": "",
"TWILIO_TOKEN": "",
"NOTIFY_FROM_NUMBER": "",
"NOTIFY_TO_NUMBER": "",
"GOOGLE_API_CLIENT_ID": "",
"GOOGLE_API_CLIENT_SECRET": "",
"GOOGLE_API_REFRESH_TOKEN": "",
"upload_concurrency": 5,
"root_folder": "deluge-completed"
}
#!/media/sdr1/home/exko/.nvm/versions/node/v4.0.0/bin/node
'use strict'
var config = require('./config')
const FOLDER = 'application/vnd.google-apps.folder'
const DEST_FOLDER = config.root_folder
var fs = require('fs')
var twilio = require('twilio')(config.TWILIO_SID, config.TWILIO_TOKEN)
var google = require('googleapis')
var async = require('async')
var winston = require('winston')
var _ = require('lodash')
var mime = require('mime')
var tid = process.argv[2]
var tname = process.argv[3]
var tpath = process.argv[4]
if (tpath.charAt(tpath.length - 1) !== '/') {
tpath += '/'
}
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ filename: './log' })
]
})
logger.info('starting upload!')
logger.info(`${tid} / ${tname} / ${tpath}`)
var auth = new google.auth.OAuth2(
config.GOOGLE_API_CLIENT_ID,
config.GOOGLE_API_CLIENT_SECRET
)
auth.credentials.refresh_token = config.GOOGLE_API_REFRESH_TOKEN
auth.refreshAccessToken(function (err, tokens) {
if (err) {
logger.error(`error retrieving access tokens ${err.error} - '${err.error_description}'`)
process.exit(1)
return
}
var rootFolder
var drive = google.drive({
version: 'v2',
auth: auth
})
var uploadQueue = async.queue(function (task, done) {
var filename = getLastPart(task.path)
logger.info('start uploading: %s', filename)
var insertOp = {
resource: {
title: filename,
mimeType: task.type,
parents: [
{ id: task.in }
]
}
}
if (task.type !== FOLDER) {
insertOp.media = {
mimeType: task.type,
body: fs.createReadStream(task.path)
}
}
drive.files.insert(insertOp, function (err, uploadedFile) {
logger.info('finished uploading: %s', filename)
done(err, uploadedFile)
})
}, config.upload_concurrency)
function upload (folder, _in, depth, done) {
var uploadedFolder
if (depth > 25) {
logger.warning('maximum depth reached!!!')
done(null)
}
if (fs.statSync(folder).isFile()) {
logger.info('torrent is just a single file: %s', folder)
uploadQueue.push({
path: folder,
type: mime.lookup(folder),
in: _in
}, done)
} else {
logger.info('uploading folder: %s', folder)
async.waterfall([
function (cb) {
uploadQueue.push({
path: folder,
type: FOLDER,
in: _in
}, cb)
},
function (newFolder, cb) {
uploadedFolder = newFolder
fs.readdir(folder, cb)
},
function (fileList, cb) {
var folders = _.filter(fileList, function (f) {
return fs.statSync(`${folder}/${f}`).isDirectory()
})
var files = _.filter(fileList, function (f) {
return fs.statSync(`${folder}/${f}`).isFile()
})
async.map(files, function (file, cb) {
uploadQueue.push({
path: `${folder}/${file}`,
type: mime.lookup(file),
in: uploadedFolder.id
}, cb)
}, function (err) {
if (err) return cb(err)
async.each(folders, function (subFolder, cb) {
upload(`${folder}/${subFolder}`, uploadedFolder.id, (depth + 1), cb)
}, cb)
})
}
], done)
}
}
async.series([
function findOrCreateFolder (cb) {
// find folder to put stuff in
logger.info('finding a folder to put stuff in')
/*
+----------------------+
| find folder with |
| "title=DEST_FOLDER" |
+----------------------+
|
+-(found one)--+-(didn't find one)-+
| |
v v
+------------------+ +------------------+
| is it in the | |create new folder |
| trash? |---+ | in root |--+
+------------------+ | +------------------+ |
| | |
+--(yes)-+ +------(no)--------+ |
| | |
v v |
+------------------+ +------------------+ |
| remove it from | |return destination| |
| trash |-->| folder |<----+
+------------------+ +------------------+
*/
drive.children.list({
folderId: 'root',
q: `title="${DEST_FOLDER}"`
}, function (err, childList) {
if (err) return cb(err)
if (childList.items.length > 0) {
var rootFolderId = childList.items[0].id
drive.files.get({
fileId: rootFolderId,
updateViewedDate: true
}, function (err, _root_folder) {
if (err) {
return cb(err)
}
rootFolder = _root_folder
if (rootFolder.labels.trashed) {
logger.info(`target folder was in the trash! untrashing...`)
drive.files.untrash({
fileId: rootFolder.id
}, function (err) {
if (err) {
return cb(err)
}
logger.info('cool! target folder out of the trash. moving on...')
cb(null)
})
return
}
logger.info(`found one! ${rootFolder.id}`)
cb(null)
})
return
}
logger.info('did not find one, creating one now...')
drive.files.insert({
resource: {
title: DEST_FOLDER,
mimeType: FOLDER
}
}, function (err, _new_folder) {
if (err) return cb(err)
rootFolder = _new_folder
cb(null)
})
})
},
function uploadStuff (cb) {
upload(`${tpath}${tname}`, rootFolder.id, 0, cb)
}
], function (err) {
if (err) {
logger.error('ERROR')
logger.error(err)
return
}
twilio.sendMessage({
to: config.NOTIFY_TO_NUMBER,
from: config.NOTIFY_FROM_NUMBER,
body: `so let it be said, so let it be done! '${tname}' finished downloading!`
}, function (err) {
if (err) {
logger.error('ERROR SENDING NOTIFICATION', err)
return
}
logger.info('sent notification')
})
logger.info('successfully finished uploading shit')
})
})
function getLastPart (path) {
if (path.charAt(path.length - 1) === '/') {
path = path.slice(0, -1)
}
return path.split('/').pop()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment