Rename project, fix playback issue

This commit is contained in:
Nova 2023-02-22 14:14:25 +01:00
parent 61cdbd495f
commit 7d18f6cf91
13 changed files with 68 additions and 56 deletions

3
.env
View file

@ -1,3 +1,2 @@
#FEDIPLAY_NO_CHECK_CERTIFICATE=1
FEDIPLAY_PLAY_COMMAND="ffplay -v 0 -nostats -hide_banner -autoexit -nodisp {filename}"
#FEDIPLAY_PLAY_COMMAND="afplay {filename}"
FEDIPLAY_PLAY_COMMAND="ffplay -v 0 -nostats -hide_banner -autoexit -nodisp"

View file

@ -1,12 +1,12 @@
# fediplay
# fediplug
A Mastodon client that automatically plays your friends' music as they toot links to it.
## What's new in 2.2
If you've been using fediplay before, the all-new version 2.2 will be a little different!
If you've been using fediplug before, the all-new version 2.2 will be a little different!
- You now specify the instance you want to stream from on the command line, instead of setting it in the environment. fediplay has been upgraded with the power of [Click](http://click.pocoo.org/) to give it a more modern command-line interface.
- You now specify the instance you want to stream from on the command line, instead of setting it in the environment. fediplug has been upgraded with the power of [Click](http://click.pocoo.org/) to give it a more modern command-line interface.
- We use [appdirs](https://pypi.org/project/appdirs/) to keep downloaded music files in your operating system's user cache directory.
@ -16,33 +16,33 @@ Be sure to follow all the instructions, including re-running `pipenv install` to
## Getting started
fediplay comes configured to use `ffplay` from [FFmpeg](https://ffmpeg.org/) to actually play music.
fediplug comes configured to use `ffplay` from [FFmpeg](https://ffmpeg.org/) to actually play music.
- On macOS, `ffplay` is part of the [Homebrew](https://brew.sh/) `ffmpeg` package, but you need to build it with `brew install ffmpeg --with-sdl2`.
- On Windows, `ffplay` is part of the [Scoop](http://scoop.sh/) `ffmpeg` package.
Use `pipenv install` from [Pipenv](https://docs.pipenv.org/) to install the Python dependencies and set up the fediplay script inside the virtual environment.
Use `pipenv install` from [Pipenv](https://docs.pipenv.org/) to install the Python dependencies and set up the fediplug script inside the virtual environment.
You can use the fediplay script with either `pipenv run fediplay` or by entering the Pipenv shell with `pipenv shell` and just running `fediplay`.
You can use the fediplug script with either `pipenv run fediplug` or by entering the Pipenv shell with `pipenv shell` and just running `fediplug`.
## Registering and logging in
To register fediplay to your instance, use `fediplay register example.com`.
To register fediplug to your instance, use `fediplug register example.com`.
To log in to your instance, use `fediplay login example.com`.
To log in to your instance, use `fediplug login example.com`.
## Streaming
Use `fediplay stream example.com` to start the stream. You'll need to log in the first time.
Use `fediplug stream example.com` to start the stream. You'll need to log in the first time.
Toots that include the hashtag #fediplay and have as their first link something that [youtube-dl](https://rg3.github.io/youtube-dl/) can play, will!
Toots that include the hashtag #fediplug and have as their first link something that [youtube-dl](https://rg3.github.io/youtube-dl/) can play, will!
If new #fediplay toots come in while music is playing, they'll be downloaded immediately and queued to be played later.
If new #fediplug toots come in while music is playing, they'll be downloaded immediately and queued to be played later.
Since version 2.2, thanks to [@bbonf](https://github.com/bbonf), if there's a recent #fediplay toot in your timeline, it'll be pulled up and played before the stream starts. Great if you just missed a song before starting your stream!
Since version 2.2, thanks to [@bbonf](https://github.com/bbonf), if there's a recent #fediplug toot in your timeline, it'll be pulled up and played before the stream starts. Great if you just missed a song before starting your stream!
### Filtering
Since version 2.2, you can also, thanks to [@Jenkyrados](https://github.com/Jenkyrados), specify users to filter! Just add them to the command line after the server name, e.g. `fediplay stream example.com @user @otheruser@example.net`.
Since version 2.2, you can also, thanks to [@Jenkyrados](https://github.com/Jenkyrados), specify users to filter! Just add them to the command line after the server name, e.g. `fediplug stream example.com @user @otheruser@example.net`.

View file

@ -1,5 +0,0 @@
'''Hook for running fediplay module as a script.'''
from fediplay.cli import cli
cli()

View file

@ -1,3 +1,3 @@
'''A Mastodon client for playing your friends' music.'''
from fediplay.cli import cli
from fediplug.cli import cli

5
fediplug/__main__.py Normal file
View file

@ -0,0 +1,5 @@
'''Hook for running fediplug module as a script.'''
from fediplug.cli import cli
cli()

View file

@ -11,9 +11,9 @@ import click
import atexit
from mastodon import Mastodon
from fediplay.dirs import DIRS
import fediplay.mastodon as mastodon
import fediplay.keyring as keyring
from fediplug.dirs import DIRS
import fediplug.mastodon as mastodon
import fediplug.keyring as keyring
def ensure_dirs():
'''Make sure the application directories exist.'''
@ -30,7 +30,7 @@ def get_access_token(instance):
keyring.migrate_access_token(instance)
if not keyring.has_credential(instance, keyring.CREDENTIAL_ACCESS_TOKEN):
click.echo('user credential for {} does not exist; try `fediplay login`'.format(instance))
click.echo('user credential for {} does not exist; try `fediplug login`'.format(instance))
sys.exit(1)
return keyring.get_credential(instance, keyring.CREDENTIAL_ACCESS_TOKEN)
@ -42,7 +42,7 @@ def get_client_credentials(instance):
if not (keyring.has_credential(instance, keyring.CREDENTIAL_CLIENT_ID) and
keyring.has_credential(instance, keyring.CREDENTIAL_CLIENT_SECRET)):
click.echo('client credentials for {} do not exist; try `fediplay register`'.format(instance))
click.echo('client credentials for {} do not exist; try `fediplug register`'.format(instance))
sys.exit(1)
return (
@ -62,7 +62,7 @@ def cli(debug):
@cli.command()
@click.argument('instance')
def register(instance):
'''Register fediplay on your Mastodon instance.'''
'''Register fediplug on your Mastodon instance.'''
mastodon.register(instance)

View file

@ -3,4 +3,4 @@
from appdirs import AppDirs
DIRS = AppDirs('fediplay', 'zigg')
DIRS = AppDirs('fediplug', 'zigg')

View file

@ -6,12 +6,12 @@ from dotenv import load_dotenv, find_dotenv
def no_check_certificate():
'''Returns whether fediplay should check TLS certificates.'''
'''Returns whether fediplug should check TLS certificates.'''
return bool(getenv('FEDIPLAY_NO_CHECK_CERTIFICATE'))
def play_command():
'''Returns the play command fediplay should use to play a file.'''
'''Returns the play command fediplug should use to play a file.'''
return (getenv('FEDIPLAY_PLAY_COMMAND') or
'ffplay -v 0 -nostats -hide_banner -autoexit -nodisp {filename}')

View file

@ -7,10 +7,10 @@ import appdirs
import click
from keyring import get_password, set_password
from fediplay.dirs import DIRS
from fediplug.dirs import DIRS
SERVICE_NAME = 'fediplay'
SERVICE_NAME = 'fediplug'
CREDENTIAL_CLIENT_ID = 'client_id'
CREDENTIAL_CLIENT_SECRET = 'client_secret'
CREDENTIAL_ACCESS_TOKEN = 'access_token'

View file

@ -1,6 +1,6 @@
'''Mastodon interface.'''
LISTEN_TO_HASHTAG = 'fediplay'
LISTEN_TO_HASHTAG = 'fediplug'
from os import umask
@ -9,9 +9,9 @@ from lxml.etree import HTML # pylint: disable=no-name-in-module
import mastodon
from youtube_dl.utils import DownloadError
from fediplay.cli import options
import fediplay.keyring as keyring
from fediplay.queue import Queue
from fediplug.cli import options
import fediplug.keyring as keyring
from fediplug.queue import Queue
Mastodon = mastodon.Mastodon
@ -59,9 +59,9 @@ class StreamListener(mastodon.StreamListener):
pass
def register(instance):
'''Register fediplay to a Mastodon server and save the client credentials.'''
'''Register fediplug to a Mastodon server and save the client credentials.'''
client_id, client_secret = Mastodon.create_app('fediplay', scopes=['read'], api_base_url=api_base_url(instance))
client_id, client_secret = Mastodon.create_app('fediplug', scopes=['read'], api_base_url=api_base_url(instance))
keyring.set_credential(instance, keyring.CREDENTIAL_CLIENT_ID, client_id)
keyring.set_credential(instance, keyring.CREDENTIAL_CLIENT_SECRET, client_secret)

View file

@ -2,15 +2,14 @@
from os import path, listdir, makedirs, remove, utime
from time import time, localtime
import shlex
from subprocess import run
from subprocess import Popen, run
from threading import Thread, Lock
import click
from youtube_dl import YoutubeDL, utils
from fediplay.cli import options
import fediplay.env as env
from fediplug.cli import options
import fediplug.env as env
class Queue(object):
@ -39,8 +38,12 @@ class Queue(object):
def _run_thread(filename, cb_complete):
play_command = build_play_command(filename)
click.echo('==> Playing {} with {}'.format(filename, play_command))
run(play_command, shell=True)
if options['debug']:
click.echo(f'==> Playing {filename} with {play_command}')
else:
click.echo(f'==> Playing {filename}')
run(play_command)
click.echo('==> Playback complete')
cb_complete()
@ -76,13 +79,21 @@ class Getter(object):
'''deleting files here'''
auto_delete_files(self.cache_dir)
options = {
ytdl_options = {
'format': 'mp3/mp4',
'nocheckcertificate': env.no_check_certificate(),
'outtmpl': path.join(self.cache_dir, utils.DEFAULT_OUTTMPL),
'progress_hooks': [self._progress_hook]
'progress_hooks': [self._progress_hook],
'restrictfilenames': True,
'quiet': True,
'no_warnings': True
}
with YoutubeDL(options) as downloader:
if options['debug']:
ytdl_options['quiet'] = False
ytdl_options['no_warnings'] = False
with YoutubeDL(ytdl_options) as downloader:
downloader.download([url])
for file in self.filenames:
@ -93,9 +104,11 @@ class Getter(object):
def build_play_command(filename):
'''Builds a play command for the given filename.'''
escaped_filename = shlex.quote(filename)
template = env.play_command()
return template.format(filename=escaped_filename)
filename = rf"{filename}"
command_args = env.play_command().split()
command_args.append(filename)
return command_args
def auto_delete_files(cache_dir):
for the_file in listdir(cache_dir):

View file

@ -1,9 +1,9 @@
from setuptools import setup
setup(
name='fediplay',
name='fediplug',
version='2.0',
py_modules=['fediplay'],
py_modules=['fediplug'],
install_requires=[
'appdirs',
'click',
@ -15,7 +15,7 @@ setup(
],
entry_points={
'console_scripts': [
'fediplay = fediplay:cli'
'fediplug = fediplug:cli'
]
}
)

View file

@ -1,12 +1,12 @@
from os import environ
from fediplay.mastodon import extract_links
from fediplay.queue import build_play_command
from fediplug.mastodon import extract_links
from fediplug.queue import build_play_command
def test_extract_links():
toot = {
'content': "<p><a href=\"https://cybre.space/tags/nowplaying\" class=\"mention hashtag\" rel=\"tag\">#<span>nowplaying</span></a> <a href=\"https://cybre.space/tags/fediplay\" class=\"mention hashtag\" rel=\"tag\">#<span>fediplay</span></a> Grimes ft. Janelle Mon\u00e1e - Venus Fly <a href=\"https://www.youtube.com/watch?v=eTLTXDHrgtw\" rel=\"nofollow noopener\" target=\"_blank\"><span class=\"invisible\">https://www.</span><span class=\"ellipsis\">youtube.com/watch?v=eTLTXDHrgt</span><span class=\"invisible\">w</span></a></p>"
'content': "<p><a href=\"https://cybre.space/tags/nowplaying\" class=\"mention hashtag\" rel=\"tag\">#<span>nowplaying</span></a> <a href=\"https://cybre.space/tags/fediplug\" class=\"mention hashtag\" rel=\"tag\">#<span>fediplug</span></a> Grimes ft. Janelle Mon\u00e1e - Venus Fly <a href=\"https://www.youtube.com/watch?v=eTLTXDHrgtw\" rel=\"nofollow noopener\" target=\"_blank\"><span class=\"invisible\">https://www.</span><span class=\"ellipsis\">youtube.com/watch?v=eTLTXDHrgt</span><span class=\"invisible\">w</span></a></p>"
}
urls = extract_links(toot)
assert urls == ['https://www.youtube.com/watch?v=eTLTXDHrgtw']