diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 61ef328..64e7e5b --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,15 @@ /**/*/__pycache__ log/ venv/ - +nodejs/node_modules +nodejs/assets +nodejs/pid *.py[cod] db.sqlite3 - -config/rufy_SUPERVISOR.conf \ No newline at end of file +*.torrent +config/rufy_SUPERVISOR.conf +static/assets +assets/ +.bash_history +.cache/ +.idea/ diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..1f56939 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..9856833 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/rufy.iml b/.idea/rufy.iml new file mode 100644 index 0000000..6f32fbb --- /dev/null +++ b/.idea/rufy.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..128fba6 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,792 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1469536174521 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 5083585..4b836f0 --- a/README.md +++ b/README.md @@ -1,6 +1,48 @@ # RuFy Web-application to download T411 Tracker's torrents from your seedbox + +## Particularité de la branche torrentStream +Cette branche est encore à l'étape de la preuve de concept. Elle permet de streamer directement dans le navigateur un torrent est de l'afficher dans un player. Pour ce faire un nouveau backend en nodejs a été implémenter utilisant la librairie webTorrent. + +### Procédure de fonctionnement +- Lancer apache ou nginx comme d'habitude. +- installer les dependances du backend nodejs. pour ce faire, aller dans le dossier nodejs, et executer : +```sh +sudo npm install +``` + +- Lancer le backend nodejs. Si vous utiliser le module wsgi pour lancer rufy, il faut executer : +```sh +sudo -H -u www-data -c 'node /var/www/rufy/nodejs/index.js' +``` +ou +```sh +sudo -H -u rufy -c 'node /var/www/rufy/nodejs/index.js' +``` +Si vous êtes sous nginx, ou si vous avez mis rufy derrière un reverse proxy. + +-Il faut ensuite, dans rufy, configurer le dossier de téléchargement temporaire. Cette config ce trouve sous le même menu que la configuration du dossier de téléchargement en blackhole de rutorrent (le nom du dossier doit finir par un '/'), conseillé (/var/www/rufy/nodejs/assets/) + +-Il ne vous reste plus qu'a aller sur votre torrent, et de cliquer sur streaming. + +### Limitation de la POC +- Pour le moment, le stream ne fonctionne que sur les fichier mp4. Donc bien choisir un torrent en mp4 (les mkv ne fonctionneront pas) +- Le backend est encore bugué de partout, donc s'assurer que la stdout de la console n'affiche pas d'erreur. Si vous rencontreze des erreurs dans le fonctionnement, merci d'ouvrir une issue la plus explicite possible afin que je puiise reproduire le bug, et fixée tout cela au fure et à mesure. +- Le port utilisé par nodejs doit être ouvert (port 3000 par défaut) afin que le client puisse récuperer le fichier video en cours de stream). +- Il n'y a aucune loading screen pour le moment, donc la video peut mettre un certain temps à s'afficher (dépendant de votre connexion internet). Si elle met vraiment trop de temps, ouvrir le débuggueur de votre navigateur, est assurer vous qu'il n'y a pas d'erreur 500 ou 404 vers les requêtes sur le backend nodejs (les paths finissent pas /torrentstream, ça vous aidera à les voir). Si il y a bien une erreur, relancer le backend et actualisé la page +- N'a pas l'air de fonctionner sur un navigateur mobile pour le moment. Bug a corriger car il n'y a pas de raison à cela. + +### TODO +- Corriger les nombreux bugs possible. +- Ajouter la loading screen, ainsi qu'un peu plus de verbose sur les differentes erreurs possible directement dans la page web. +- Afficher le status du backend nodejs sur la page web, et pouvoir le relancer depuis la page web en cas de problème. +- Mettre en place du la conversion à la volée du flux video, dans le cas ou la video n'est pas compatible avec html5 (pour les mkv par exemple). +- Ajouter de l'info, via websocket, sur le nombre de peer connecté, la vitesse d'UP et de DOWN, etc... + +### Invitation +Je ne suis pas un expert du javascript, ni du nodejs. Si quelqu'un à envie de s'impliquer, n'hésitez pas à forker ce repo, et à proposer des améliorations. Elles sont bien evidemment les biencenues. + ## Installation ### Via Docker diff --git a/RuFy/__init__.py b/RuFy/__init__.py old mode 100644 new mode 100755 diff --git a/RuFy/settings.py b/RuFy/settings.py old mode 100644 new mode 100755 index c76beb6..39f0806 --- a/RuFy/settings.py +++ b/RuFy/settings.py @@ -23,7 +23,7 @@ SECRET_KEY = '_nz^-9its$w6e97)c2$b#8!e8pon@nl*!jw-q&s)fhrqj&8y%h' # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = False +DEBUG = True ALLOWED_HOSTS = ["*"] diff --git a/RuFy/urls.py b/RuFy/urls.py old mode 100644 new mode 100755 diff --git a/RuFy/wsgi.py b/RuFy/wsgi.py old mode 100644 new mode 100755 diff --git a/config/db-init.sqlite3 b/config/db-init.sqlite3 old mode 100644 new mode 100755 diff --git a/config/rufy-apache.conf b/config/rufy-apache.conf old mode 100644 new mode 100755 diff --git a/config/rufy-stream.conf b/config/rufy-stream.conf new file mode 100644 index 0000000..4ce23e9 --- /dev/null +++ b/config/rufy-stream.conf @@ -0,0 +1,170 @@ +#!/bin/sh + +USER="www-data" +NODE_ENV="production" +APP_DIR="/var/www/rufy/nodejs" +NODE_APP="index.js" +CONFIG_DIR="$APP_DIR" +PID_DIR="$APP_DIR/pid" +PID_FILE="$PID_DIR/app.pid" +LOG_DIR="$APP_DIR/log" +LOG_FILE="$LOG_DIR/app.log" +NODE_EXEC=$(which node) +APP_NAME="rufy-stream" + +############### + +# REDHAT chkconfig header + +# chkconfig: - 58 74 +# description: node-app is the script for starting a node app on boot. +### BEGIN INIT INFO +# Provides: node +# Required-Start: $network $remote_fs $local_fs +# Required-Stop: $network $remote_fs $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop node +# Description: Node process for app +### END INIT INFO + +############### + +USAGE="Usage: $0 {start|stop|restart|status} [--force]" +FORCE_OP=false + +pid_file_exists() { + [ -f "$PID_FILE" ] +} + +get_pid() { + echo "$(cat "$PID_FILE")" +} + +is_running() { + PID=$(get_pid) + ! [ -z "$(ps aux | awk '{print $2}' | grep "^$PID$")" ] +} + +start_it() { + mkdir -p "$PID_DIR" + chown $USER:$USER "$PID_DIR" + mkdir -p "$LOG_DIR" + chown $USER:$USER "$LOG_DIR" + + echo "Starting $APP_NAME ..." + echo "cd $APP_DIR && NODE_ENV=$NODE_ENV NODE_CONFIG_DIR=$CONFIG_DIR $NODE_EXEC $APP_DIR/$NODE_APP 1>$LOG_FILE 2>&1 & echo \$! > $PID_FILE" | sudo -H -u $USER bash + echo "$APP_NAME started with pid $(get_pid)" +} + +stop_process() { + PID=$(get_pid) + echo "Killing process $PID" + pkill -P $PID +} + +remove_pid_file() { + echo "Removing pid file" + rm -f "$PID_FILE" +} + +start_app() { + if pid_file_exists + then + if is_running + then + PID=$(get_pid) + echo "$APP_NAME already running with pid $PID" + exit 1 + else + echo "$APP_NAME stopped, but pid file exists" + if [ $FORCE_OP = true ] + then + echo "Forcing start anyways" + remove_pid_file + start_it + fi + fi + else + start_it + fi +} + +stop_app() { + if pid_file_exists + then + if is_running + then + echo "Stopping $APP_NAME ..." + stop_process + remove_pid_file + echo "$APP_NAME stopped" + else + echo "$APP_NAME already stopped, but pid file exists" + if [ $FORCE_OP = true ] + then + echo "Forcing stop anyways ..." + remove_pid_file + echo "$APP_NAME stopped" + else + exit 1 + fi + fi + else + echo "$APP_NAME already stopped, pid file does not exist" + exit 1 + fi +} + +status_app() { + if pid_file_exists + then + if is_running + then + PID=$(get_pid) + echo "$APP_NAME running with pid $PID" + else + echo "$APP_NAME stopped, but pid file exists" + fi + else + echo "$APP_NAME stopped" + fi +} + +case "$2" in + --force) + FORCE_OP=true + ;; + + "") + ;; + + *) + echo $USAGE + exit 1 + ;; +esac + +case "$1" in + start) + start_app + ;; + + stop) + stop_app + ;; + + restart) + stop_app + start_app + ;; + + status) + status_app + ;; + + *) + echo $USAGE + exit 1 + ;; +esac diff --git a/config/rufy_nginx_URI.conf b/config/rufy_nginx_URI.conf old mode 100644 new mode 100755 diff --git a/config/rufy_nginx_domaine.conf b/config/rufy_nginx_domaine.conf old mode 100644 new mode 100755 diff --git a/gunicorn_start b/gunicorn_start old mode 100644 new mode 100755 diff --git a/install.sh b/install.sh old mode 100644 new mode 100755 index 1cbb84e..13232b4 --- a/install.sh +++ b/install.sh @@ -6,6 +6,7 @@ GROUP=web VIRTUALDIR="venv" mkdir -p ${INSTALLDIR}/log/ +mkdir /var/run/forever exec 2>${INSTALLDIR}/log/install.log diff --git a/manage.py b/manage.py old mode 100644 new mode 100755 diff --git a/nodejs/index.js b/nodejs/index.js new file mode 100755 index 0000000..a474c91 --- /dev/null +++ b/nodejs/index.js @@ -0,0 +1,126 @@ +var express = require('express'); +var webtorrent = require('webtorrent'); +var path = require('path'); +var http = require('http'); +var app = express(); +var bodyParser = require("body-parser"); +var fs = require('fs'); + +var port = 3000; + +var client = new webtorrent(); + +var listOfTorrents = {}; + +app.use(function(request, response, next) { + response.header('Access-Control-Allow-Origin', '*') + response.header('Access-Control-Allow-Methods', 'OPTIONS, POST, GET, PUT, DELETE'); + response.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); + next(); +}); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })); + + +var getLargestFile = function(torrent) { + var file; + for (var i = 0; i< torrent.files.length; i++ ) { + if( !file || file.length < torrent.files[i].length) { + file = torrent.files[i]; + } + } + return file; +}; + + +//var io = require('socket.io').listen(server); +//console.log('Socket opened on http://127.0.0.1:' ); + +var torrentID; +app.post('/streamtorrent/add', function(request, response, next) { + try { + + if(!request.body.torrent || !request.body.id ){ + response.status(500).send('Missing torrent info in request!'); return; + } + var id = request.body.id; + if(listOfTorrents.id !== undefined) { + console.log("torrent not added, because it seems to already exist"); + response.status(200).send("torrent already exists, skipping..."); return; + } + torrentID = fs.readFileSync(request.body.torrent); + client.add(torrentID, function(torrent){ + var file = getLargestFile(torrent); + torrent.swarm.on('upload', function() { + if(torrent.length == torrent.downloaded) { + torrent.swarm.destroy(); + torrent.discovery.stop(); + delete listOfTorrents.id; + } + + }); + var id = request.body.id; + listOfTorrents.id = request.body.torrent; + response.status(200).send('Added torrent!'); + }); + console.log("Torrent added"); + } + catch (err) { + response.status(500).send('Error: ' + err.toString()); + console.log("adding torrent failed"); + } +}); + +app.get('/streamtorrent/:id.mp4', function(request, response){ + + + try { + var id = request.params.id; + var path = listOfTorrents.id; + var torrent = client.get(fs.readFileSync(listOfTorrents.id)); + var file = getLargestFile(torrent); + var total = file.length; + + if(typeof request.headers.range != 'undefined') { + var range = request.headers.range; + var parts = range.replace(/bytes=/, "").split("-"); + var partialstart = parts[0]; + var partialend = parts[1]; + var start = parseInt(partialstart, 10); + var end = partialend ? parseInt(partialend, 10) : total - 1; + var chunksize = (end - start) + 1; + } else { + var start = 0; var end = total; + } + var stream = file.createReadStream({start: start, end: end}); + response.writeHead(206, { 'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/mp4' }); + stream.pipe(response); + } catch (err) { + response.status(500).send('Error: ' + err.toString()); + console.log('getting stream failed' + err.toString()); + } +}); + +app.get('/delete/:id', function(request, response){ + console.log(listOfTorrents); + if(request.params.id =='undefined' || request.params.id == ''){ + response.status(500).send('Missing torrent ID in your request'); return; + } + try { + var id = request.params.id; + var torrent = client.remove(fs.readFileSync(listOfTorrents.id)); + console.log('Removed torrent' + listOfTorrents.id); + delete listOfTorrents.id; + response.status(200).send('Removed torrent ' + listOfTorrents.id); + } catch( err ) { + response.status(500).send('Error : ' + err.toString() + listOfTorrents.id); + console.log('Removing torrent error : ' + err.toString()); + } +}); + +var server = http.createServer(app); +server.listen(port, function() { + console.log('Listening on http://127.0.0.1:' + port); +}); + + diff --git a/nodejs/package.json b/nodejs/package.json new file mode 100755 index 0000000..668e9b6 --- /dev/null +++ b/nodejs/package.json @@ -0,0 +1,28 @@ +{ + "name": "rufy-stream", + "version": "1.0.0", + "description": "Nodejs Backend for Rufy, able to stream torrent from t411 and from server directly into the browser", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "torrent", + "t411", + "rufy" + ], + "author": "shyne", + "license": "ISC", + "dependencies": { + "body-parser": "^1.15.2", + "express": "^4.14.0", + "forever": "^0.15.2", + "fs-extra": "^0.30.0", + "http": "0.0.0", + "mkdirp": "^0.5.1", + "socket.io": "^1.4.8", + "tap": "^6.2.0", + "torrent-stream": "^1.0.3", + "webtorrent": "^0.95.5" + } +} diff --git a/nodejs/pid/app.pid b/nodejs/pid/app.pid new file mode 100644 index 0000000..b4732da --- /dev/null +++ b/nodejs/pid/app.pid @@ -0,0 +1 @@ +3220 diff --git a/nodejs/rufy-stream.conf b/nodejs/rufy-stream.conf new file mode 100755 index 0000000..68a183b --- /dev/null +++ b/nodejs/rufy-stream.conf @@ -0,0 +1,89 @@ +#!/bin/bash +### BEGIN INIT INFO +# If you wish the Daemon to be lauched at boot / stopped at shutdown : +# +# On Debian-based distributions: +# INSTALL : update-rc.d scriptname defaults +# (UNINSTALL : update-rc.d -f scriptname remove) +# +# On RedHat-based distributions (CentOS, OpenSUSE...): +# INSTALL : chkconfig --level 35 scriptname on +# (UNINSTALL : chkconfig --level 35 scriptname off) +# +# chkconfig: 2345 90 60 +# Provides: /var/www/rufy/nodejs/index.js +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: forever running /var/www/rufy/nodejs/index.js +# Description: /var/www/rufy/nodejs/index.js +### END INIT INFO +# +# initd a node app +# Based on a script posted by https://gist.github.com/jinze at https://gist.github.com/3748766 +# + +if [ -e /lib/lsb/init-functions ]; then + # LSB source function library. + . /lib/lsb/init-functions +fi; + +pidFile="/var/run/rufy-stream.pid" +logFile="/var/www/rufy/log/rufy-stream.log" + +command="node" +nodeApp="/var/www/rufy/nodejs/index.js" +foreverApp="forever" + +start() { + echo "Starting $nodeApp" + + # Notice that we change the PATH because on reboot + # the PATH does not include the path to node. + # Launching forever with a full path + # does not work unless we set the PATH. + PATH=/usr/local/bin:$PATH + export NODE_ENV=production + #PORT=80 + $foreverApp start --pidFile $pidFile -l $logFile -a -d -c "$command" $nodeApp + RETVAL=$? +} + +restart() { + echo -n "Restarting $nodeApp" + $foreverApp restart $nodeApp + RETVAL=$? +} + +stop() { + echo -n "Shutting down $nodeApp" + $foreverApp stop $nodeApp + RETVAL=$? +} + +status() { + echo -n "Status $nodeApp" + $foreverApp list + RETVAL=$? +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status + ;; + restart) + restart + ;; + *) + echo "Usage: {start|stop|status|restart}" + exit 1 + ;; +esac +exit $RETVAL diff --git a/requirements.txt b/requirements.txt old mode 100644 new mode 100755 diff --git a/t411/__init__.py b/t411/__init__.py old mode 100644 new mode 100755 diff --git a/t411/admin.py b/t411/admin.py old mode 100644 new mode 100755 diff --git a/t411/apps.py b/t411/apps.py old mode 100644 new mode 100755 diff --git a/t411/forms.py b/t411/forms.py old mode 100644 new mode 100755 index 93c56d0..9ae0b05 --- a/t411/forms.py +++ b/t411/forms.py @@ -13,6 +13,7 @@ class ConfigForm(forms.Form): username = forms.CharField(label="Nom d'utilisateur T411") password = forms.CharField(label="Mot de passe (non stocké)", widget=forms.PasswordInput) dossier = forms.CharField(label="Dossier blackhole Rutorrent") + dossier_temp = forms.CharField(label="Dossier temporaire de streaming") class T411Form(forms.ModelForm): class Meta: @@ -24,9 +25,10 @@ class Meta: class DossierForm(forms.ModelForm): class Meta: model = Profil - fields = ('dossier',) + fields = ('dossier', 'dossier_temp') widgets = { 'dossier': TextInput(attrs={'size': 80}), + 'dossier_temp': TextInput(attrs={'size': 80}) } class MenuForm(forms.ModelForm): diff --git a/t411/migrations/0001_initial.py b/t411/migrations/0001_initial.py old mode 100644 new mode 100755 diff --git a/t411/migrations/0002_auto_20160403_0137.py b/t411/migrations/0002_auto_20160403_0137.py old mode 100644 new mode 100755 diff --git a/t411/migrations/0003_auto_20160403_2201.py b/t411/migrations/0003_auto_20160403_2201.py old mode 100644 new mode 100755 diff --git a/t411/migrations/0004_auto_20160403_2056.py b/t411/migrations/0004_auto_20160403_2056.py old mode 100644 new mode 100755 diff --git a/t411/migrations/0005_categorie.py b/t411/migrations/0005_categorie.py old mode 100644 new mode 100755 diff --git a/t411/migrations/0006_auto_20160408_2334.py b/t411/migrations/0006_auto_20160408_2334.py old mode 100644 new mode 100755 diff --git a/t411/migrations/0007_auto_20160409_0006.py b/t411/migrations/0007_auto_20160409_0006.py old mode 100644 new mode 100755 diff --git a/t411/migrations/0008_profil_dossier_temp.py b/t411/migrations/0008_profil_dossier_temp.py new file mode 100644 index 0000000..9db02ed --- /dev/null +++ b/t411/migrations/0008_profil_dossier_temp.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2016-07-26 13:38 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('t411', '0007_auto_20160409_0006'), + ] + + operations = [ + migrations.AddField( + model_name='profil', + name='dossier_temp', + field=models.CharField(blank=True, max_length=200, null=True), + ), + ] diff --git a/t411/migrations/__init__.py b/t411/migrations/__init__.py old mode 100644 new mode 100755 diff --git a/t411/models.py b/t411/models.py old mode 100644 new mode 100755 index 97f3fb4..187d18e --- a/t411/models.py +++ b/t411/models.py @@ -14,7 +14,8 @@ class Profil(models.Model): user = models.OneToOneField(User) # La liaison OneToOne vers le modèle User dossier = models.CharField(max_length=200,null=True, blank = True) - + dossier_temp = models.CharField(max_length=200,null=True, blank = True) + pseudoT411 = models.CharField(max_length=42,null=True) uid = models.IntegerField(null=True) token = models.CharField(max_length=50,null=True) diff --git a/t411/scripts/categories.json b/t411/scripts/categories.json old mode 100644 new mode 100755 diff --git a/t411/scripts/db_cats.py b/t411/scripts/db_cats.py old mode 100644 new mode 100755 diff --git a/t411/templates/t411/accueil.html b/t411/templates/t411/accueil.html old mode 100644 new mode 100755 diff --git a/t411/templates/t411/config.html b/t411/templates/t411/config.html old mode 100644 new mode 100755 diff --git a/t411/templates/t411/configMenu.html b/t411/templates/t411/configMenu.html old mode 100644 new mode 100755 diff --git a/t411/templates/t411/connexion.html b/t411/templates/t411/connexion.html old mode 100644 new mode 100755 diff --git a/t411/templates/t411/detail_torrents.html b/t411/templates/t411/detail_torrents.html old mode 100644 new mode 100755 index 7b9aed3..7ca3c99 --- a/t411/templates/t411/detail_torrents.html +++ b/t411/templates/t411/detail_torrents.html @@ -2,7 +2,9 @@ {% block content %}

Détails du torrent : {{ detail.name }}

-

+ Streaming + +

{{ detail.description|safe }}

diff --git a/t411/templates/t411/search.html b/t411/templates/t411/search.html old mode 100644 new mode 100755 diff --git a/t411/templates/t411/stream_torrent.html b/t411/templates/t411/stream_torrent.html new file mode 100644 index 0000000..5300e45 --- /dev/null +++ b/t411/templates/t411/stream_torrent.html @@ -0,0 +1,48 @@ +{% extends "base.html" %} +{% block content %} +

Streaming torrent

+

+ + +

+ + + +
+ + +
+
+ + +{% endblock %} diff --git a/t411/templates/t411/torrents.html b/t411/templates/t411/torrents.html old mode 100644 new mode 100755 diff --git a/t411/templatetags/__init__.py b/t411/templatetags/__init__.py old mode 100644 new mode 100755 diff --git a/t411/templatetags/t411_extras.py b/t411/templatetags/t411_extras.py old mode 100644 new mode 100755 diff --git a/t411/tests.py b/t411/tests.py old mode 100644 new mode 100755 diff --git a/t411/urls.py b/t411/urls.py old mode 100644 new mode 100755 index 599069e..23c2daf --- a/t411/urls.py +++ b/t411/urls.py @@ -14,6 +14,7 @@ url(r'^top/$', views.top_torrents, name='top_torrents'), url(r'^top/(?P\w+)$', views.top_torrents, name='top_torrents'), url(r'^torrent/(?P\d+)$', views.detail_torrent, name='detail_torrent'), + url(r'^torrent/(?P\d+)/stream$', views.stream_torrent, name='stream_torrent'), url(r'^search$', views.search, name='search'), url(r'^search/(?P[\w\ ]+)/$', views.search, name='search'), url(r'^search/(?P[\w\ ]+)/(?P\d+)$', views.search, name='search'), diff --git a/t411/views.py b/t411/views.py old mode 100644 new mode 100755 index 6512207..5e1bd9e --- a/t411/views.py +++ b/t411/views.py @@ -9,8 +9,11 @@ from t411.models import Profil,T411, Menu, Categorie,SousCategorie from django.forms import modelformset_factory, inlineformset_factory - +import socket +import hashlib import json +import base64 +import urllib, requests import time, datetime from math import floor def connexion(request): @@ -149,9 +152,55 @@ def detail_torrent(request,id_torrent): return configT411(request,True,detail['error']) return render(request, 't411/detail_torrents.html',locals()) - @login_required +def stream_torrent(request, id_torrent): + t411, utilisateur = connexionT411(request) + #detail = t411.details(id_torrent) + if t411.profil.dossier_temp == "" or t411.profil.dossier_temp == None: + return HttpResponse("dossier") + else: + dossier = t411.profil.dossier_temp + + fichier = t411.download(id_torrent) + torrent = fichier.content + + if 'error' in fichier: + return HttpResponse(fichier['error']) + + nomFichier = fichier.headers['Content-Disposition'].split('=')[1][1:-1] + nomFichier = nomFichier.decode('cp1252') + + chemin = dossier + nomFichier + chemin = chemin.encode('utf8') + + + + + with open(chemin, 'wb') as fd: + for chunk in fichier.iter_content(): + fd.write(chunk) + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(('8.8.8.8', 0)) # connecting to a UDP address doesn't send packets + ip_address = s.getsockname()[0] + # r = requests.post("http://localhost:3000/streamtorrent", data={'torrent': chemin}) + # status = r.status_code + # if r.status_code != 200: + # throw +# torrent = open(chemin, 'r').read() +# metadata = bencode.bdecode(torrent) +# hashcontents = bencode.bencode(metadata['info']) +# digest = hashlib.sha1(hashcontents).digest() +# b32hash = base64.b32encode(digest) + +# params = {'xt': 'urn:btih:%s' % b32hash, 'dn': metadata['info']['name'], 'tr': metadata['announce'], 'xl' : metadata['info']['length']} +# paramstr = urllib.urlencode(params) +# magneturi = 'magnet:?%s' % paramstr +# Les magnets ne supportent pas le DHT, d'ou l'abandon. Dans le cas du magnet, cela fonctionne mais le ratio n'est pas comptabilisé par le tracker de T411. + + return render(request, 't411/stream_torrent.html', locals()) +@login_required + def search(request,search="",cid = 1, page=1): page = int(page) @@ -273,4 +322,4 @@ def duree_ecoulee(date_from): elif jours: diff_day = "%.f"%jours + " jours" else : diff_day = "%.f"%floor(timedelta.seconds/3600)+" heures" - return diff_day \ No newline at end of file + return diff_day diff --git a/templates/base.html b/templates/base.html old mode 100644 new mode 100755 index d1a69d3..6a9c1d7 --- a/templates/base.html +++ b/templates/base.html @@ -10,6 +10,10 @@ + + + + {% bootstrap_css %} {% bootstrap_javascript %}