-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from ogarcia/setup
Several improvements and code fix
- Loading branch information
Showing
6 changed files
with
252 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# CONTRIBUTORS | ||
|
||
Alphabetically-ordered list of the people who contributed to FileTeaSend: | ||
|
||
- Óscar García Amor (@ogarcia) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,26 @@ | ||
FileTeaSend | ||
=========== | ||
# FileTeaSend | ||
|
||
Easy file transfer using FileTea service | ||
|
||
## Installation | ||
|
||
```bash | ||
git clone https://github.com/brechin/FileTeaSend.git | ||
virtualenv ./fileteavenv | ||
source ./fileteavenv/bin/activate | ||
cd FileTeaSend | ||
python setup.py install | ||
``` | ||
|
||
## Run | ||
|
||
Simply run `filetea` command with `-h` or `--help` to read the help of | ||
command. It's self explanatory. | ||
|
||
## Options and arguments | ||
|
||
You can specify FileTea server with `FILETEAURL` environment variable or | ||
with `-l` or `--url` arguments. | ||
|
||
The `-v` argument enable the verbose mode, you can repeat it to get more | ||
verbose output. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,96 +1,10 @@ | ||
#!/usr/bin/env python | ||
from __future__ import print_function | ||
import logging | ||
import sys | ||
import os | ||
import json | ||
#! /usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
# vim:fenc=utf-8 | ||
# | ||
# Distributed under terms of the GNU GPLv3 license. | ||
|
||
import requests | ||
import magic | ||
from fileteasend.app import main | ||
|
||
__FILETEA_URL = 'https://filetea.me/' | ||
logging.basicConfig(level=logging.DEBUG) | ||
|
||
|
||
def get_peer_id(session_obj): | ||
"""Perform handshake with endpoint to get a usable peer-id""" | ||
logger = logging.getLogger('get_peer_id') | ||
handshake_text = '{"mechanisms":["websocket","long-polling"],"url":"/transport/"}' | ||
handshake = session_obj.post('%stransport/handshake' % __FILETEA_URL, data=handshake_text, | ||
headers={'Content-Type': 'text/plain'}) | ||
logger.debug(handshake.headers) | ||
logger.debug(handshake.content) | ||
return handshake.json()['peer-id'] | ||
|
||
|
||
def send_file(session_obj, file_name_to_send, token): | ||
"""Send specified file to endpoint""" | ||
logger = logging.getLogger('send_file') | ||
logger.debug('Sending %s to %s' % (file_name_to_send, token)) | ||
logger.info('Sending file %s' % file_name_to_send) | ||
with open(file_name_to_send, 'rb') as f: | ||
resp = session_obj.put('%s%s' % (__FILETEA_URL, token), f) | ||
logger.debug(resp) | ||
return resp | ||
|
||
|
||
def register_file(session_obj, file_to_send): | ||
"""Register file with endpoint, returns url to use to download the file""" | ||
logger = logging.getLogger('register_file') | ||
ms = magic.open(magic.MIME_TYPE) | ||
ms.load() | ||
mime_type = ms.file(file_to_send) | ||
ms.close() | ||
send_url = '%stransport/lp/send?%s' % (__FILETEA_URL, my_uuid) | ||
send_data = 'X{"method":"addFileSources","params":[["%s","%s",%d]],"id":"1"}' % ( | ||
os.path.basename(file_to_send), mime_type, os.path.getsize(file_to_send)) | ||
logger.info('Sending %s' % send_data) | ||
sent_response = session_obj.post(send_url, data=send_data, headers={'Content-Type': 'text/plain'}) | ||
logger.debug(sent_response.headers) | ||
logger.debug(sent_response.text) | ||
send_return_data = sent_response.text | ||
assert send_return_data.startswith('@') | ||
send_return_data = send_return_data[1:] | ||
send_response_json = json.loads(send_return_data) | ||
logger.debug('Decoded JSON: %s' % send_response_json) | ||
file_download_url = '%s%s' % (__FILETEA_URL, send_response_json['result'][0][0]) | ||
return file_download_url | ||
|
||
if __name__ == '__main__': | ||
base_logger = logging.getLogger('filetea') | ||
session = requests.session() | ||
|
||
if len(sys.argv) < 2: | ||
sys.exit('Need to specify file to share') | ||
|
||
file_to_send = sys.argv[1] | ||
if not os.path.exists(file_to_send): | ||
sys.exit('File does not exist.') | ||
if not os.path.isfile(file_to_send): | ||
sys.exit('Path is not a file.') | ||
|
||
# Get a peer-id registered with endpoint | ||
my_uuid = get_peer_id(session) | ||
# Register specified file with endpoint, which returns the URL to download the file | ||
url = register_file(session, file_to_send) | ||
base_logger.info('URL for file %s: %s' % (file_to_send, url)) | ||
print('URL: %s', url) | ||
|
||
while True: | ||
# Try recv, might 404 | ||
base_logger.info('Waiting to send recv') | ||
recv_url = '%stransport/lp/receive?%s' % (__FILETEA_URL, my_uuid) | ||
recv_response = session.get(recv_url) | ||
base_logger.debug(recv_response.content) | ||
|
||
recv_return_data = recv_response.content | ||
if recv_return_data.startswith('w'): | ||
base_logger.debug('Got file transfer request') | ||
recv_return_data = recv_return_data[1:] | ||
|
||
r = json.loads(recv_return_data) | ||
|
||
if r['method'] == "fileTransferNew": | ||
send_file(session, file_to_send, r['params'][-1]) | ||
else: | ||
base_logger.debug('Not a file transfer') | ||
if __name__ == "__main__": | ||
main() |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
# -*- coding: utf-8 -*- | ||
# vim:fenc=utf-8 | ||
# | ||
# Distributed under terms of the GNU GPLv3 license. | ||
|
||
from __future__ import print_function | ||
try: | ||
from urllib.parse import urljoin, urlparse | ||
except ImportError: | ||
from urlparse import urljoin, urlparse | ||
import argparse | ||
import json | ||
import logging | ||
import os | ||
import signal | ||
import sys | ||
|
||
import magic | ||
import requests | ||
|
||
class FileTeaClient(object): | ||
"""Base client class for FileTea access""" | ||
def __init__(self, url=None): | ||
logger = logging.getLogger('filetea.FileTeaClient') | ||
# Set URL to default if not URL is passed | ||
self.url = 'https://filetea.me/' if url is None else url | ||
logger.debug('Using FileTea server {}'.format(self.url)) | ||
self.session = requests.session() | ||
|
||
def get_peer_id(self): | ||
""" | ||
Perform handshake with endpoint to get a usable peer-id | ||
:return: peer-id | ||
:rtype: string | ||
""" | ||
logger = logging.getLogger('filetea.FileTeaClient.get_peer_id') | ||
handshake_headers = {'Content-Type': 'text/plain'} | ||
handshake_text = '{"mechanisms":["websocket","long-polling"],"url":"/transport/"}' | ||
url = urljoin(self.url, 'transport/handshake') | ||
handshake = self.session.post(url, data=handshake_text, headers=handshake_headers) | ||
logger.debug(handshake.headers) | ||
logger.debug(handshake.content) | ||
return handshake.json()['peer-id'] | ||
|
||
def register_file(self, peer_id, file_to_send): | ||
""" | ||
Register file with endpoint and returns url to use to download the file | ||
:return: url | ||
:rtype: string | ||
""" | ||
logger = logging.getLogger('filetea.FileTeaClient.register_file') | ||
file_name = os.path.basename(file_to_send) | ||
file_size = os.path.getsize(file_to_send) | ||
if hasattr(magic, 'open'): # use magic-file-extensions | ||
ms = magic.open(magic.MIME_TYPE) | ||
ms.load() | ||
mime_type = ms.file(file_to_send) | ||
ms.close() | ||
else: # use python-magic | ||
mime_type = magic.from_file(file_to_send, mime=True) | ||
send_headers = {'Content-Type': 'text/plain'} | ||
send_url = urljoin(self.url, 'transport/lp/send') | ||
send_data = { | ||
"method": "addFileSources", | ||
"params": [[ | ||
file_name, | ||
mime_type, | ||
file_size | ||
]], | ||
"id": "1" } | ||
send_data = 'X{}'.format(json.dumps(send_data)) | ||
logger.info('Sending: {}'.format(send_data)) | ||
send_response = self.session.post(send_url, data=send_data, params=peer_id, headers=send_headers) | ||
logger.debug(send_response.headers) | ||
logger.debug(send_response.text) | ||
send_response_text = send_response.text | ||
assert send_response_text.startswith('@') | ||
send_response_text = send_response_text[1:] | ||
send_response_json = json.loads(send_response_text) | ||
logger.debug('Decoded JSON response: {}'.format(send_response_json)) | ||
file_download_url = urljoin(self.url, send_response_json['result'][0][0]) | ||
return file_download_url | ||
|
||
def send_file(self, file_to_send, token): | ||
""" | ||
Send specified file to endpoint | ||
""" | ||
logger = logging.getLogger('filetea.FileTeaClient.send_file') | ||
logger.info('Sending file {} to {}'.format(file_to_send, token)) | ||
send_url = urljoin(self.url, token) | ||
with open(file_to_send, 'rb') as f: | ||
send_response = self.session.put(send_url, f) | ||
logger.debug(send_response) | ||
|
||
def receive_response(self, peer_id, file_to_send): | ||
""" | ||
Wait for server response to send file | ||
""" | ||
logger = logging.getLogger('filetea.FileTeaClient.receive_response') | ||
receive_url = urljoin(self.url, 'transport/lp/receive') | ||
receive_response = self.session.get(receive_url, params=peer_id) | ||
receive_response_text = receive_response.text | ||
logger.debug(receive_response_text) | ||
try: | ||
receive_response_text = receive_response_text[1:] | ||
receive_response_json = json.loads(receive_response_text) | ||
logger.debug('Decoded JSON response: {}'.format(receive_response_json)) | ||
if receive_response_json['method'] == 'fileTransferNew': | ||
token = receive_response_json['params'][-1] | ||
logger.debug('Got a file transfer request from token {}'.format(token)) | ||
print('File transfer request received from token {}'.format(token)) | ||
self.send_file(file_to_send, token) | ||
else: | ||
logger.info('Not a file transfer request') | ||
except Exception as e: | ||
logger.info('Not a file transfer request: {}'.format(e)) | ||
pass | ||
|
||
def exit(signal, frame): | ||
sys.exit(0) | ||
|
||
def run(args): | ||
logger = logging.getLogger('filetea') | ||
# Set FileTea server URL | ||
server_url = args.url if args.url != None else os.getenv('FILETEAURL', 'https://filetea.me/') | ||
if not urlparse(server_url).netloc: | ||
sys.exit('No schema supplied on URL.') | ||
|
||
file_tea_client = FileTeaClient(server_url) | ||
# Get a peer-id registered with endpoint | ||
peer_id = file_tea_client.get_peer_id() | ||
# Register specified file with endpoint, which returns the URL to download the file | ||
file_url = file_tea_client.register_file(peer_id, args.file) | ||
logger.info('URL for file {}: {}'.format(args.file, file_url)) | ||
print('URL: {}'.format(file_url)) | ||
print('Press CTRL+C to stop sharing...') | ||
|
||
while True: | ||
# Main loop | ||
logger.info('Waiting for a server response') | ||
file_tea_client.receive_response(peer_id, args.file) | ||
|
||
def main(): | ||
signal.signal(signal.SIGINT, exit) | ||
parser = argparse.ArgumentParser(description='Easy file transfer using the FileTea service') | ||
parser.add_argument('--url', '-l', help='filetea server url (also FILETEAURL)') | ||
parser.add_argument('--verbose', '-v', action='count', default=0, help='be verbose (vv to increase verbosity)') | ||
parser.add_argument('file', help='file to send') | ||
parser.set_defaults(func=run) | ||
args = parser.parse_args() | ||
|
||
# Set loglevel equivalents | ||
log_levels = { | ||
0: logging.ERROR, | ||
1: logging.INFO, | ||
2: logging.DEBUG } | ||
|
||
# Maximum loglevel is 2 if user sends more vvv we ignore it | ||
args.verbose = 2 if args.verbose >= 2 else args.verbose | ||
logging.basicConfig(level=log_levels[args.verbose]) | ||
|
||
# Check if file exists and can be read | ||
if not os.path.exists(args.file): | ||
sys.exit('File does not exist.') | ||
if not os.path.isfile(args.file): | ||
sys.exit('Path is not a file.') | ||
if not os.access(args.file, os.R_OK): | ||
sys.exit('File can not be read.') | ||
|
||
args.func(args) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#! /usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
# vim:fenc=utf-8 | ||
# | ||
# Distributed under terms of the GNU GPLv3 license. | ||
|
||
import os | ||
from setuptools import setup | ||
|
||
# Utility function to read the README file. | ||
# Used for the long_description. It's nice, because now 1) we have a top level | ||
# README file and 2) it's easier to type in the README file than to put a raw | ||
# string in below ... | ||
def read(fname): | ||
return open(os.path.join(os.path.dirname(__file__), fname)).read() | ||
|
||
setup( | ||
name = "fileteasend", | ||
version = "1.0", | ||
author = "Jason Brechin", | ||
author_email = "[email protected]", | ||
description = ("Easy file transfer using the FileTea service"), | ||
license = "GPLv3", | ||
keywords = "file web transfer easy FileTea", | ||
url = "https://github.com/brechin/FileTeaSend", | ||
packages=['fileteasend'], | ||
long_description=read('README.md'), | ||
entry_points={ | ||
'console_scripts': [ | ||
'filetea = fileteasend.app:main' | ||
] | ||
}, | ||
install_requires = [ | ||
"requests>=2.13.0", | ||
"python-magic>=0.4.0" | ||
], | ||
classifiers=[ | ||
"Development Status :: 3 - Alpha", | ||
"Topic :: Utilities", | ||
"License :: OSI Approved :: GNU General Public License (GPLv3)", | ||
'Programming Language :: Python :: 3', | ||
], | ||
) |