├── .gitignore ├── conf ├── local.example.json ├── reel2bits.target ├── front.src ├── audiowaveform.src ├── pythonz.src ├── googletest.src ├── app.src ├── reel2bits-worker.service ├── reel2bits-web.service ├── nginx.conf └── prod_secret.py ├── .travis.yml ├── pull_request_template.md ├── check_process ├── scripts ├── _common.sh ├── ynh_add_swap ├── backup ├── remove ├── change_url ├── restore ├── upgrade └── install ├── README.md ├── manifest.json └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.sw[op] 3 | -------------------------------------------------------------------------------- /conf/local.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "target": "http://127.0.0.1:5000/", 3 | "host": "__DOMAIN__" 4 | } 5 | -------------------------------------------------------------------------------- /conf/reel2bits.target: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=reel2bits 3 | Wants=reel2bits-web.service reel2bits-worker.service -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | before_install: 4 | - git clone https://github.com/YunoHost/package_linter /tmp/package_linter 5 | 6 | script: 7 | - /tmp/package_linter/package_linter.py ./ -------------------------------------------------------------------------------- /conf/front.src: -------------------------------------------------------------------------------- 1 | SOURCE_URL=https://assets.reel2bits.org/front-dist-master.zip 2 | SOURCE_SUM=fa9f53337c2a4fddd82695922989e8c904007780874972390bc4f07406c33790 3 | SOURCE_SUM_PRG=sha256sum 4 | SOURCE_FORMAT=zip 5 | SOURCE_IN_SUBDIR=true 6 | SOURCE_FILENAME= 7 | -------------------------------------------------------------------------------- /conf/audiowaveform.src: -------------------------------------------------------------------------------- 1 | SOURCE_URL=https://github.com/bbc/audiowaveform/archive/1.4.2.tar.gz 2 | SOURCE_SUM=3fc6b995d1ae0e5bf735a76e681e3e0df85eeabc06e7f253b5e28eff2c842354 3 | SOURCE_SUM_PRG=sha256sum 4 | SOURCE_FORMAT=tar.gz 5 | SOURCE_IN_SUBDIR=true 6 | SOURCE_FILENAME= 7 | -------------------------------------------------------------------------------- /conf/pythonz.src: -------------------------------------------------------------------------------- 1 | SOURCE_URL=https://github.com/saghul/pythonz/archive/9067f35e0253b015eb51b8a4d60c0bd1a06dcc83.tar.gz 2 | SOURCE_SUM=ce9eb5400fff81e4877e04dd7166c764d8adc999d9ca6b06ce933ee9375b8652 3 | SOURCE_SUM_PRG=sha256sum 4 | SOURCE_FORMAT=tar.gz 5 | SOURCE_IN_SUBDIR=true 6 | SOURCE_FILENAME= 7 | -------------------------------------------------------------------------------- /conf/googletest.src: -------------------------------------------------------------------------------- 1 | SOURCE_URL=https://github.com/google/googletest/archive/011959aafddcd30611003de96cfd8d7a7685c700.tar.gz 2 | SOURCE_SUM=0e34ac9e3aac3af3977a7ca45c27bb941fbf3a803877a7e440f93a6f9dc9235f 3 | SOURCE_SUM_PRG=sha256sum 4 | SOURCE_FORMAT=tar.gz 5 | SOURCE_IN_SUBDIR=true 6 | SOURCE_FILENAME= 7 | -------------------------------------------------------------------------------- /conf/app.src: -------------------------------------------------------------------------------- 1 | SOURCE_URL=https://github.com/rhaamo/reel2bits/archive/680765b772ef394e225aa1cada315adef425e0cd.tar.gz 2 | SOURCE_SUM=5052c5ca938ee7f24b838947532e5a9d6a09f17a3a0d81c1c0ea5e0a3c1ed2c9 3 | SOURCE_SUM_PRG=sha256sum 4 | SOURCE_FORMAT=tar.gz 5 | SOURCE_IN_SUBDIR=true 6 | SOURCE_FILENAME=0.0.1-2020-02-04.tar.gz 7 | -------------------------------------------------------------------------------- /conf/reel2bits-worker.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=reel2bits-worker 3 | After=network.target 4 | PartOf=reel2bits.target 5 | 6 | [Service] 7 | Type=simple 8 | User=__APP__ 9 | WorkingDirectory=__FINALPATH__/api 10 | Environment="FLASK_ENV=production" 11 | Environment="APP_SETTINGS=config.prod_secret.Config" 12 | ExecStart=__FINALPATH__/api/ve3/bin/celery worker -A tasks.celery -l INFO 13 | TimeoutSec=15 14 | Restart=always 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /conf/reel2bits-web.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=reel2bits-web 3 | After=network.target 4 | PartOf=reel2bits.target 5 | 6 | [Service] 7 | Type=simple 8 | User=__APP__ 9 | WorkingDirectory=__FINALPATH__/api 10 | Environment="FLASK_ENV=production" 11 | Environment="APP_SETTINGS=config.prod_secret.Config" 12 | ExecStart=__FINALPATH__/api/ve3/bin/waitress-serve --host 127.0.0.1 --port __PORT__ --call 'app:create_app' 13 | TimeoutSec=15 14 | Restart=always 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Problem 2 | - *Description of why you made this PR* 3 | 4 | ## Solution 5 | - *And how do you fix that problem* 6 | 7 | ## PR Status 8 | - [ ] Code finished. 9 | - [ ] Tested with Package_check. 10 | - [ ] Fix or enhancement tested. 11 | - [ ] Upgrade from last version tested. 12 | - [ ] Can be reviewed and tested. 13 | 14 | ## Package_check results 15 | --- 16 | *If you have access to [App Continuous Integration for packagers](https://yunohost.org/#/packaging_apps_ci) you can provide a link to the package_check results like below, replacing '-NUM-' in this link by the PR number and USERNAME by your username on the ci-apps-dev. Or you provide a screenshot or a pastebin of the results* 17 | 18 | [![Build Status](https://ci-apps-dev.yunohost.org/jenkins/job/reel2bits_ynh%20PR-NUM-%20(USERNAME)/badge/icon)](https://ci-apps-dev.yunohost.org/jenkins/job/reel2bits_ynh%20PR-NUM-%20(USERNAME)/) 19 | -------------------------------------------------------------------------------- /check_process: -------------------------------------------------------------------------------- 1 | ;; Test complet 2 | ; Manifest 3 | domain="domain.tld" (DOMAIN) 4 | admin="john" (USER) 5 | language="fr" 6 | is_public=1 (PUBLIC|public=1|private=0) 7 | password="pass" 8 | ; Checks 9 | pkg_linter=1 10 | setup_sub_dir=0 11 | setup_root=1 12 | setup_nourl=0 13 | setup_private=1 14 | setup_public=1 15 | upgrade=1 16 | # 0.0.1-2020-02-04~ynh1 17 | upgrade=1 from_commit=0fc25106736e824bd984b26f0c2146a6685904e0 18 | backup_restore=1 19 | multi_instance=1 20 | # This test is no longer necessary since the version 2.7 (PR: https://github.com/YunoHost/yunohost/pull/304), you can still do it if your app could be installed with this version. 21 | # incorrect_path=1 22 | port_already_use=0 23 | change_url=0 24 | ;;; Levels 25 | # If the level 5 (Package linter) is forced to 1. Please add justifications here. 26 | Level 5=auto 27 | ;;; Options 28 | Email=yalh@yahoo.com 29 | Notification=all 30 | ;;; Upgrade options 31 | ; commit=0fc25106736e824bd984b26f0c2146a6685904e0 32 | name=0.0.1-2020-02-04~ynh1 33 | -------------------------------------------------------------------------------- /scripts/_common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #================================================= 4 | # COMMON VARIABLES 5 | #================================================= 6 | 7 | # dependencies used by the app 8 | pkg_dependencies="postgresql postgresql-contrib python-virtualenv libffi-dev libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libffi6 sox libtag1v5 libmagic1 tzdata libmad0 libboost-all-dev libsndfile1 libid3tag0 ffmpeg redis-server" 9 | 10 | build_dependencies="libffi-dev cmake make pkg-config git libboost-all-dev libgd-dev libmad0-dev libsndfile-dev libid3tag0-dev libffi-dev" 11 | 12 | swap_needed=2048 13 | 14 | python_version=3.8.3 15 | 16 | #================================================= 17 | # PERSONAL HELPERS 18 | #================================================= 19 | 20 | #================================================= 21 | # EXPERIMENTAL HELPERS 22 | #================================================= 23 | 24 | #================================================= 25 | # FUTURE OFFICIAL HELPERS 26 | #================================================= 27 | -------------------------------------------------------------------------------- /conf/nginx.conf: -------------------------------------------------------------------------------- 1 | # add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:"; 2 | # add_header Referrer-Policy "strict-origin-when-cross-origin"; 3 | 4 | client_max_body_size 1G; 5 | 6 | location /static { 7 | alias __FINALPATH__/front/dist/static; 8 | try_files $uri $uri/ @proxy; 9 | } 10 | 11 | location / { 12 | 13 | try_files $request_uri @proxy; 14 | 15 | # Include SSOWAT user panel. 16 | include conf.d/yunohost_panel.conf.inc; 17 | } 18 | 19 | location @proxy { 20 | proxy_set_header Host $host; 21 | proxy_set_header X-Real-IP $remote_addr; 22 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 23 | proxy_set_header X-Forwarded-Proto $scheme; 24 | proxy_set_header X-Forwarded-Host $host:$server_port; 25 | proxy_set_header X-Forwarded-Port $server_port; 26 | proxy_redirect off; 27 | 28 | proxy_http_version 1.1; 29 | proxy_set_header Upgrade $http_upgrade; 30 | proxy_set_header Connection $connection_upgrade; 31 | 32 | proxy_pass http://127.0.0.1:__PORT__; 33 | } 34 | 35 | location /_protected/media/sounds { 36 | alias __DATADIR__/uploads/sounds; 37 | } 38 | 39 | location /_protected/media/artwork_sounds { 40 | alias __DATADIR__/uploads/artwork_sounds; 41 | } 42 | 43 | location /_protected/media/artwork_albums { 44 | alias __DATADIR__/uploads/artwork_albums; 45 | } 46 | 47 | location /_protected/media/avatars { 48 | alias __DATADIR__/uploads/avatars; 49 | } 50 | -------------------------------------------------------------------------------- /conf/prod_secret.py: -------------------------------------------------------------------------------- 1 | from .development import Config as BaseConfig 2 | 3 | 4 | class Config(BaseConfig): 5 | # See the Configuration documentation at: 6 | # https://docs-develop.reel2bits.org/installation/configuration.html 7 | # For all the config keys you can use 8 | 9 | # Please generate me with: openssl rand -hex 42 10 | SECRET_KEY = "__SECRET_KEY__" 11 | # Please generate me with: openssl rand -hex 5 12 | SECURITY_PASSWORD_SALT = "__SECURITY_PASSWORD_SALT__" 13 | # Set your DB URI 14 | SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://__DB_USER__:__DB_PWD__@localhost/__DB_NAME__" 15 | 16 | # Don't forget that SOUNDS and ARTWORKS, etc. have to be under DEFAULT path folder 17 | UPLOADS_DEFAULT_DEST = "__DATADIR__/uploads" 18 | UPLOADED_SOUNDS_DEST = "__DATADIR__/uploads/sounds" 19 | UPLOADED_ARTWORKALBUMS_DEST = "__DATADIR__/uploads/artwork_albums" 20 | UPLOADED_ARTWORKSOUNDS_DEST = "__DATADIR__/uploads/artwork_sounds" 21 | UPLOADED_AVATARS_DEST = "__DATADIR__/uploads/avatars" 22 | 23 | # Where is the audiowaveform binary located 24 | AUDIOWAVEFORM_BIN = "__FINAL_PATH__/audiowaveform" 25 | 26 | # If you are using Sentry, otherwise, set to None 27 | SENTRY_DSN = None 28 | 29 | # The domain name your instance will be using 30 | REEL2BITS_HOSTNAME = "__DOMAIN__" 31 | # Is the ActivityPub backend active ? 32 | # Even at False, you needs to setup the AP_DOMAIN because it is used 33 | # by more things than just ActivityPub 34 | AP_DOMAIN = "__DOMAIN__" 35 | AP_ENABLED = True 36 | 37 | # Can the users register on your instance ? 38 | REGISTRATION_ENABLED = True 39 | 40 | # If you are using a modified instance, please set your own repository URL 41 | SOURCES_REPOSITORY_URL = "https://github.com/YunoHost-Apps/reel2bits_ynh" 42 | 43 | # Email settings 44 | MAIL_SERVER = "localhost" 45 | MAIL_PORT = 25 46 | MAIL_USE_TLS = False 47 | MAIL_USE_SSL = False 48 | # MAIL_USERNAME = None 49 | # MAIL_PASSWORD = None 50 | 51 | CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0' 52 | CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0' 53 | 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reel2Bits for YunoHost 2 | 3 | [![Integration level](https://dash.yunohost.org/integration/reel2bits.svg)](https://dash.yunohost.org/appci/app/reel2bits) 4 | [![Install Reel2Bits with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=reel2bits) 5 | 6 | > *This package allow you to install Reel2Bits quickly and simply on a YunoHost server. 7 | If you don't have YunoHost, please see [here](https://yunohost.org/#/install) to know how to install and enjoy it.* 8 | 9 | ## Overview 10 | Soundcloud-like but simple, easy and KISS (and ActivityPub). 11 | 12 | **Shipped version:** 0.0.1-2020-02-04 13 | 14 | ## Important points to read before installing 15 | 16 | 1. **Reel2Bits** is under development 17 | 1. **Reel2Bits** require a dedicated **root domain**, eg. reel2bits.domain.tld 18 | 1. Even if requested during installation: admin, language and password variables are not used 19 | 1. When your Reel2Bits instance is installed, you need to execute the following command to create a first user and give it admin rights: `(cd /var/www/reel2bits/api && export APP_SETTINGS=config.prod_secret.Config && ve3/bin/flask users create)` 20 | 21 | ## Screenshots 22 | 23 | ![](https://user-images.githubusercontent.com/30271971/71564281-89018900-2a9e-11ea-88be-c12034c5350b.png) 24 | 25 | ## Demo 26 | 27 | * [Official demo](https://demo.reel2bits.org/) 28 | 29 | ## YunoHost specific features 30 | 31 | #### Supported architectures 32 | 33 | * x86-64b - [![Build Status](https://ci-apps.yunohost.org/ci/logs/reel2bits%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/reel2bits/) 34 | * ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/reel2bits%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/reel2bits/) 35 | 36 | ## Links 37 | 38 | * Report a bug: https://github.com/YunoHost-Apps/reel2bits_ynh/issues 39 | * Upstream app repository: https://github.com/rhaamo/reel2bits 40 | * YunoHost website: https://yunohost.org/ 41 | 42 | --- 43 | 44 | Developers info 45 | ---------------- 46 | 47 | Please do your pull request to the [testing branch](https://github.com/YunoHost-Apps/reel2bits_ynh/tree/testing). 48 | 49 | To try the testing branch, please proceed like that. 50 | ``` 51 | sudo yunohost app install https://github.com/YunoHost-Apps/reel2bits_ynh/tree/testing --debug 52 | or 53 | sudo yunohost app upgrade reel2bits -u https://github.com/YunoHost-Apps/reel2bits_ynh/tree/testing --debug 54 | ``` 55 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Reel2bits", 3 | "id": "reel2bits", 4 | "packaging_format": 1, 5 | "description": { 6 | "en": "Soundcloud-like but simple, easy and KISS (and ActivityPub).", 7 | "fr": "Soundcloud-like mais simple, facile et KISS (et ActivityPub)." 8 | }, 9 | "version": "0.0.1-2020-02-04~ynh2", 10 | "url": "https://sound.otter.sh/user/dashie", 11 | "license": "AGPL-3.0-or-later", 12 | "maintainer": { 13 | "name": "" 14 | }, 15 | "previous_maintainer": { 16 | "name": "yalh76" 17 | }, 18 | "requirements": { 19 | "yunohost": ">= 3.5" 20 | }, 21 | "multi_instance": true, 22 | "services": [ 23 | "nginx", 24 | "php7.0-fpm", 25 | "mysql" 26 | ], 27 | "arguments": { 28 | "install" : [ 29 | { 30 | "name": "domain", 31 | "type": "domain", 32 | "ask": { 33 | "en": "Choose a domain name for Reel2Bits", 34 | "fr": "Choisissez un nom de domaine pour Reel2Bits" 35 | }, 36 | "example": "example.com" 37 | }, 38 | { 39 | "name": "admin", 40 | "type": "user", 41 | "ask": { 42 | "en": "Choose an admin user", 43 | "fr": "Choisissez l’administrateur" 44 | }, 45 | "example": "johndoe" 46 | }, 47 | { 48 | "name": "is_public", 49 | "type": "boolean", 50 | "ask": { 51 | "en": "Is it a public application?", 52 | "fr": "Est-ce une application publique ?" 53 | }, 54 | "default": true 55 | }, 56 | { 57 | "name": "language", 58 | "type": "string", 59 | "ask": { 60 | "en": "Choose the application language", 61 | "fr": "Choisissez la langue de l'application" 62 | }, 63 | "choices": ["fr", "en"], 64 | "default": "en" 65 | }, 66 | { 67 | "name": "password", 68 | "type": "password", 69 | "ask": { 70 | "en": "Set the administrator password", 71 | "fr": "Définissez le mot de passe administrateur" 72 | }, 73 | "example": "Choose a password" 74 | } 75 | ] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /scripts/ynh_add_swap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Add swap 4 | # 5 | # usage: ynh_add_swap --size=SWAP in Mb 6 | # | arg: -s, --size= - Amount of SWAP to add in Mb. 7 | ynh_add_swap () { 8 | # Declare an array to define the options of this helper. 9 | declare -Ar args_array=( [s]=size= ) 10 | local size 11 | # Manage arguments with getopts 12 | ynh_handle_getopts_args "$@" 13 | 14 | local swap_max_size=$(( $size * 1024 )) 15 | 16 | local free_space=$(df --output=avail / | sed 1d) 17 | # Because we don't want to fill the disk with a swap file, divide by 2 the available space. 18 | local usable_space=$(( $free_space / 2 )) 19 | 20 | SD_CARD_CAN_SWAP=${SD_CARD_CAN_SWAP:-0} 21 | 22 | # Swap on SD card only if it's is specified 23 | if ynh_is_main_device_a_sd_card && [ "$SD_CARD_CAN_SWAP" == "0" ] 24 | then 25 | ynh_print_warn --message="The main mountpoint of your system '/' is on an SD card, swap will not be added to prevent some damage of this one, but that can cause troubles for the app $app. If you still want activate the swap, you can relaunch the command preceded by 'SD_CARD_CAN_SWAP=1'" 26 | return 27 | fi 28 | 29 | # Compare the available space with the size of the swap. 30 | # And set a acceptable size from the request 31 | if [ $usable_space -ge $swap_max_size ] 32 | then 33 | local swap_size=$swap_max_size 34 | elif [ $usable_space -ge $(( $swap_max_size / 2 )) ] 35 | then 36 | local swap_size=$(( $swap_max_size / 2 )) 37 | elif [ $usable_space -ge $(( $swap_max_size / 3 )) ] 38 | then 39 | local swap_size=$(( $swap_max_size / 3 )) 40 | elif [ $usable_space -ge $(( $swap_max_size / 4 )) ] 41 | then 42 | local swap_size=$(( $swap_max_size / 4 )) 43 | else 44 | echo "Not enough space left for a swap file" >&2 45 | local swap_size=0 46 | fi 47 | 48 | # If there's enough space for a swap, and no existing swap here 49 | if [ $swap_size -ne 0 ] && [ ! -e /swap_$app ] 50 | then 51 | # Preallocate space for the swap file, fallocate may sometime not be used, use dd instead in this case 52 | if ! fallocate -l ${swap_size}K /swap_$app 53 | then 54 | dd if=/dev/zero of=/swap_$app bs=1024 count=${swap_size} 55 | fi 56 | chmod 0600 /swap_$app 57 | # Create the swap 58 | mkswap /swap_$app 59 | # And activate it 60 | swapon /swap_$app 61 | # Then add an entry in fstab to load this swap at each boot. 62 | echo -e "/swap_$app swap swap defaults 0 0 #Swap added by $app" >> /etc/fstab 63 | fi 64 | } 65 | 66 | ynh_del_swap () { 67 | # If there a swap at this place 68 | if [ -e /swap_$app ] 69 | then 70 | # Clean the fstab 71 | sed -i "/#Swap added by $app/d" /etc/fstab 72 | # Desactive the swap file 73 | swapoff /swap_$app 74 | # And remove it 75 | rm /swap_$app 76 | fi 77 | } 78 | 79 | # Check if the device of the main mountpoint "/" is an SD card 80 | # 81 | # [internal] 82 | # 83 | # return 0 if it's an SD card, else 1 84 | ynh_is_main_device_a_sd_card () { 85 | local main_device=$(lsblk --output PKNAME --noheadings $(findmnt / --nofsroot --uniq --output source --noheadings --first-only)) 86 | 87 | if echo $main_device | grep --quiet "mmc" && [ $(tail -n1 /sys/block/$main_device/queue/rotational) == "0" ] 88 | then 89 | return 0 90 | else 91 | return 1 92 | fi 93 | } 94 | -------------------------------------------------------------------------------- /scripts/backup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #================================================= 4 | # GENERIC START 5 | #================================================= 6 | # IMPORT GENERIC HELPERS 7 | #================================================= 8 | 9 | #Keep this path for calling _common.sh inside the execution's context of backup and restore scripts 10 | source ../settings/scripts/_common.sh 11 | source /usr/share/yunohost/helpers 12 | 13 | #================================================= 14 | # MANAGE SCRIPT FAILURE 15 | #================================================= 16 | ynh_print_info --message="Managing script failure..." 17 | 18 | ynh_clean_setup () { 19 | ynh_clean_check_starting 20 | } 21 | # Exit if an error occurs during the execution of the script 22 | ynh_abort_if_errors 23 | 24 | #================================================= 25 | # LOAD SETTINGS 26 | #================================================= 27 | ynh_print_info --message="Loading installation settings..." 28 | 29 | app=$YNH_APP_INSTANCE_NAME 30 | 31 | final_path=$(ynh_app_setting_get --app=$app --key=final_path) 32 | domain=$(ynh_app_setting_get --app=$app --key=domain) 33 | db_name=$(ynh_app_setting_get --app=$app --key=db_name) 34 | 35 | #================================================= 36 | # STANDARD BACKUP STEPS 37 | #================================================= 38 | # STOP SYSTEMD SERVICE 39 | #================================================= 40 | ynh_print_info --message="Stopping a systemd service..." 41 | 42 | ynh_systemd_action --service_name=${app}-web --action="stop" --log_path=systemd --line_match="Stopped ${app}-web" 43 | ynh_systemd_action --service_name=${app}-worker --action="stop" --log_path=systemd --line_match="Stopped ${app}-worker" 44 | 45 | #================================================= 46 | # BACKUP THE APP MAIN DIR 47 | #================================================= 48 | ynh_print_info --message="Backing up the main app directory..." 49 | 50 | ynh_backup --src_path="$final_path" 51 | 52 | #================================================= 53 | # BACKUP THE NGINX CONFIGURATION 54 | #================================================= 55 | ynh_print_info --message="Backing up nginx web server configuration..." 56 | 57 | ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" 58 | 59 | #================================================= 60 | # BACKUP THE POSTGRESQL DATABASE 61 | #================================================= 62 | ynh_print_info --message="Backing up the PostgreSQL database..." 63 | 64 | ynh_psql_dump_db --database="$db_name" > db.sql 65 | 66 | #================================================= 67 | # SPECIFIC BACKUP 68 | #================================================= 69 | # BACKUP SYSTEMD 70 | #================================================= 71 | ynh_print_info --message="Backing up systemd configuration..." 72 | 73 | ynh_backup --src_path="/etc/systemd/system/$app.target" 74 | ynh_backup --src_path="/etc/systemd/system/$app-web.service" 75 | ynh_backup --src_path="/etc/systemd/system/$app-worker.service" 76 | 77 | #================================================= 78 | # START SYSTEMD SERVICE 79 | #================================================= 80 | ynh_print_info --message="Starting a systemd service..." 81 | 82 | ynh_systemd_action --service_name=${app}-web --action="start" --log_path=systemd --line_match="Started ${app}-web" 83 | ynh_systemd_action --service_name=${app}-worker --action="start" --log_path=systemd --line_match="Started ${app}-worker" 84 | systemctl start $app.target 85 | 86 | #================================================= 87 | # END OF SCRIPT 88 | #================================================= 89 | 90 | ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." 91 | -------------------------------------------------------------------------------- /scripts/remove: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #================================================= 4 | # GENERIC START 5 | #================================================= 6 | # IMPORT GENERIC HELPERS 7 | #================================================= 8 | 9 | source _common.sh 10 | source ynh_add_swap 11 | source /usr/share/yunohost/helpers 12 | 13 | #================================================= 14 | # LOAD SETTINGS 15 | #================================================= 16 | ynh_print_info --message="Loading installation settings..." 17 | 18 | app=$YNH_APP_INSTANCE_NAME 19 | 20 | domain=$(ynh_app_setting_get --app=$app --key=domain) 21 | port=$(ynh_app_setting_get --app=$app --key=port) 22 | db_name=$(ynh_app_setting_get --app=$app --key=db_name) 23 | db_user=$db_name 24 | final_path=$(ynh_app_setting_get --app=$app --key=final_path) 25 | 26 | #================================================= 27 | # STANDARD REMOVE 28 | #================================================= 29 | # REMOVE SERVICE INTEGRATION IN YUNOHOST 30 | #================================================= 31 | ynh_print_info --message="Removing service integration in YunoHost..." 32 | 33 | # Remove a service from the admin panel, added by `yunohost service add` 34 | if yunohost service status "$app-web" >/dev/null 2>&1 35 | then 36 | ynh_print_info --message="Removing $app-web service..." 37 | yunohost service remove "$app-web" 38 | fi 39 | 40 | if yunohost service status "$app-worker" >/dev/null 2>&1 41 | then 42 | ynh_print_info --message="Removing $app-worker service..." 43 | yunohost service remove "$app-worker" 44 | fi 45 | 46 | if yunohost service status "$app" >/dev/null 2>&1 47 | then 48 | ynh_print_info --message="Removing $app service..." 49 | yunohost service remove "$app" 50 | fi 51 | 52 | #================================================= 53 | # STOP AND REMOVE SERVICE 54 | #================================================= 55 | ynh_print_info --message="Stopping and removing the systemd service..." 56 | 57 | # Remove the dedicated systemd config 58 | ynh_remove_systemd_config --service="$app-web" 59 | ynh_remove_systemd_config --service="$app-worker" 60 | ynh_remove_systemd_config --service="$app" 61 | 62 | #================================================= 63 | # REMOVE THE POSTGRESQL DATABASE 64 | #================================================= 65 | ynh_print_info --message="Removing the PostgreSQL database..." 66 | 67 | # Remove a database if it exists, along with the associated user 68 | ynh_psql_remove_db --db_user="$db_user" --db_name="$db_name" 69 | 70 | #================================================= 71 | # REMOVE DEPENDENCIES 72 | #================================================= 73 | ynh_print_info --message="Removing dependencies..." 74 | 75 | # Remove metapackage and its dependencies 76 | ynh_remove_app_dependencies 77 | 78 | #================================================= 79 | # REMOVE SWAP 80 | #================================================= 81 | ynh_print_info --message="Removing $swap_needed Mo to swap..." 82 | 83 | ynh_del_swap 84 | 85 | #================================================= 86 | # REMOVE APP MAIN DIR 87 | #================================================= 88 | ynh_print_info --message="Removing app main directory..." 89 | 90 | # Remove the app directory securely 91 | ynh_secure_remove --file="$final_path" 92 | 93 | #================================================= 94 | # REMOVE NGINX CONFIGURATION 95 | #================================================= 96 | ynh_print_info --message="Removing nginx web server configuration..." 97 | 98 | # Remove the dedicated nginx config 99 | ynh_remove_nginx_config 100 | 101 | #================================================= 102 | # CLOSE A PORT 103 | #================================================= 104 | ynh_print_info --message="Closing a port" 105 | 106 | if yunohost firewall list | grep -q "\- $port$" 107 | then 108 | ynh_print_info --message="Closing port $port..." 109 | ynh_exec_warn_less yunohost firewall disallow TCP $port 110 | fi 111 | 112 | #================================================= 113 | # GENERIC FINALIZATION 114 | #================================================= 115 | # REMOVE DEDICATED USER 116 | #================================================= 117 | ynh_print_info --message="Removing the dedicated system user..." 118 | 119 | # Delete a system user 120 | ynh_system_user_delete --username=$app 121 | 122 | #================================================= 123 | # END OF SCRIPT 124 | #================================================= 125 | 126 | ynh_print_info --message="Removal of $app completed" 127 | -------------------------------------------------------------------------------- /scripts/change_url: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #================================================= 4 | # GENERIC STARTING 5 | #================================================= 6 | # IMPORT GENERIC HELPERS 7 | #================================================= 8 | 9 | source _common.sh 10 | source /usr/share/yunohost/helpers 11 | 12 | #================================================= 13 | # RETRIEVE ARGUMENTS 14 | #================================================= 15 | 16 | old_domain=$YNH_APP_OLD_DOMAIN 17 | old_path=$YNH_APP_OLD_PATH 18 | 19 | new_domain=$YNH_APP_NEW_DOMAIN 20 | new_path="/" 21 | 22 | app=$YNH_APP_INSTANCE_NAME 23 | 24 | #================================================= 25 | # LOAD SETTINGS 26 | #================================================= 27 | ynh_print_info --message="Loading installation settings..." 28 | 29 | # Needed for helper "ynh_add_nginx_config" 30 | final_path=$(ynh_app_setting_get --app=$app --key=final_path) 31 | 32 | # Add settings here as needed by your application 33 | #db_name=$(ynh_app_setting_get --app=$app --key=db_name) 34 | #db_user=$db_name 35 | #db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) 36 | 37 | #================================================= 38 | # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP 39 | #================================================= 40 | ynh_print_info --message="Backing up the app before changing its url (may take a while)..." 41 | 42 | # Backup the current version of the app 43 | ynh_backup_before_upgrade 44 | ynh_clean_setup () { 45 | # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. 46 | ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" 47 | 48 | # restore it if the upgrade fails 49 | ynh_restore_upgradebackup 50 | } 51 | # Exit if an error occurs during the execution of the script 52 | ynh_abort_if_errors 53 | 54 | #================================================= 55 | # CHECK WHICH PARTS SHOULD BE CHANGED 56 | #================================================= 57 | 58 | change_domain=0 59 | if [ "$old_domain" != "$new_domain" ] 60 | then 61 | change_domain=1 62 | fi 63 | 64 | change_path=0 65 | if [ "$old_path" != "$new_path" ] 66 | then 67 | change_path=1 68 | fi 69 | 70 | #================================================= 71 | # STANDARD MODIFICATIONS 72 | #================================================= 73 | # STOP SYSTEMD SERVICE 74 | #================================================= 75 | ynh_print_info --message="Stopping a systemd service..." 76 | 77 | ynh_systemd_action --service_name=${app}-web --action="stop" --log_path=systemd --line_match="Stopped ${app}-web" 78 | ynh_systemd_action --service_name=${app}-worker --action="stop" --log_path=systemd --line_match="Stopped ${app}-worker" 79 | 80 | #================================================= 81 | # MODIFY URL IN NGINX CONF 82 | #================================================= 83 | ynh_print_info --message="Updating nginx web server configuration..." 84 | 85 | nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf 86 | 87 | # Change the path in the nginx config file 88 | if [ $change_path -eq 1 ] 89 | then 90 | # Make a backup of the original nginx config file if modified 91 | ynh_backup_if_checksum_is_different --file="$nginx_conf_path" 92 | # Set global variables for nginx helper 93 | domain="$old_domain" 94 | path_url="$new_path" 95 | # Create a dedicated nginx config 96 | ynh_add_nginx_config 97 | fi 98 | 99 | # Change the domain for nginx 100 | if [ $change_domain -eq 1 ] 101 | then 102 | # Delete file checksum for the old conf file location 103 | ynh_delete_file_checksum --file="$nginx_conf_path" 104 | mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf 105 | # Store file checksum for the new config file location 106 | ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" 107 | fi 108 | 109 | #================================================= 110 | # SPECIFIC MODIFICATIONS 111 | #================================================= 112 | # MODIFY A CONFIG FILE 113 | #================================================= 114 | 115 | api_config="$final_path/config.py" 116 | 117 | ynh_replace_string --match_string="$old_domain" "--replace_string=$new_domain" --target_file="$api_config" 118 | 119 | ynh_backup_if_checksum_is_different --file="$api_config" 120 | # Recalculate and store the checksum of the file for the next upgrade. 121 | ynh_store_file_checksum --file="$api_config" 122 | 123 | #================================================= 124 | # GENERIC FINALISATION 125 | #================================================= 126 | # START SYSTEMD SERVICE 127 | #================================================= 128 | ynh_print_info --message="Starting a systemd service..." 129 | 130 | ynh_systemd_action --service_name=${app}-web --action="start" --log_path=systemd --line_match="Started ${app}-web" 131 | ynh_systemd_action --service_name=${app}-worker --action="start" --log_path=systemd --line_match="Started ${app}-worker" 132 | systemctl start $app.target 133 | 134 | #================================================= 135 | # RELOAD NGINX 136 | #================================================= 137 | ynh_print_info --message="Reloading nginx web server..." 138 | 139 | ynh_systemd_action --service_name=nginx --action=reload 140 | 141 | #================================================= 142 | # END OF SCRIPT 143 | #================================================= 144 | 145 | ynh_print_info --message="Change of URL completed for $app" 146 | -------------------------------------------------------------------------------- /scripts/restore: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #================================================= 4 | # GENERIC START 5 | #================================================= 6 | # IMPORT GENERIC HELPERS 7 | #================================================= 8 | 9 | #Keep this path for calling _common.sh inside the execution's context of backup and restore scripts 10 | source ../settings/scripts/_common.sh 11 | source ../settings/scripts/ynh_add_swap 12 | source /usr/share/yunohost/helpers 13 | 14 | #================================================= 15 | # MANAGE SCRIPT FAILURE 16 | #================================================= 17 | ynh_print_info --message="Managing script failure..." 18 | 19 | ynh_clean_setup () { 20 | ynh_clean_check_starting 21 | } 22 | # Exit if an error occurs during the execution of the script 23 | ynh_abort_if_errors 24 | 25 | #================================================= 26 | # LOAD SETTINGS 27 | #================================================= 28 | ynh_print_info --message="Loading settings..." 29 | 30 | app=$YNH_APP_INSTANCE_NAME 31 | 32 | domain=$(ynh_app_setting_get --app=$app --key=domain) 33 | path_url=$(ynh_app_setting_get --app=$app --key=path) 34 | final_path=$(ynh_app_setting_get --app=$app --key=final_path) 35 | db_name=$(ynh_app_setting_get --app=$app --key=db_name) 36 | db_user=$db_name 37 | db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) 38 | datadir=$(ynh_app_setting_get --app=$app --key=datadir) 39 | 40 | #================================================= 41 | # CHECK IF THE APP CAN BE RESTORED 42 | #================================================= 43 | ynh_print_info --message="Validating restoration parameters..." 44 | 45 | ynh_webpath_available --domain=$domain --path_url=$path_url \ 46 | || ynh_die --message="Path not available: ${domain}${path_url}" 47 | test ! -d $final_path \ 48 | || ynh_die --message="There is already a directory: $final_path " 49 | 50 | #================================================= 51 | # STANDARD RESTORATION STEPS 52 | #================================================= 53 | # RESTORE THE NGINX CONFIGURATION 54 | #================================================= 55 | 56 | ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" 57 | 58 | #================================================= 59 | # RESTORE THE APP MAIN DIR 60 | #================================================= 61 | ynh_print_info --message="Restoring the app main directory..." 62 | 63 | ynh_restore_file --origin_path="$final_path" 64 | 65 | #================================================= 66 | # RECREATE THE DEDICATED USER 67 | #================================================= 68 | ynh_print_info --message="Recreating the dedicated system user..." 69 | 70 | # Create the dedicated user (if not existing) 71 | ynh_system_user_create --username=$app --home_dir="$final_path" 72 | 73 | #================================================= 74 | # RESTORE USER RIGHTS 75 | #================================================= 76 | ynh_print_info --message="Restoring user rights..." 77 | 78 | # Restore permissions on app files 79 | chown -R "$app": "$final_path" 80 | 81 | #================================================= 82 | # RECREATE THE DATA DIRECTORY 83 | #================================================= 84 | ynh_print_info --message="Recreate the data directory..." 85 | 86 | # Create app folders 87 | mkdir -p "$datadir" 88 | mkdir -p "$datadir/uploads/sounds" 89 | mkdir -p "$datadir/uploads/waveforms" 90 | mkdir -p "$datadir/uploads/artwork_albums" 91 | mkdir -p "$datadir/uploads/artwork_sounds" 92 | mkdir -p "$datadir/uploads/avatars" 93 | 94 | # Give permission to the datadir 95 | chown -R "$app": "$datadir" 96 | 97 | #================================================= 98 | # SPECIFIC RESTORATION 99 | #================================================= 100 | # ADD SWAP 101 | #================================================= 102 | ynh_print_info --message="Adding $swap_needed Mo to swap..." 103 | 104 | ynh_add_swap --size=$swap_needed 105 | 106 | #================================================= 107 | # REINSTALL DEPENDENCIES 108 | #================================================= 109 | ynh_print_info --message="Reinstalling dependencies..." 110 | 111 | # Define and install dependencies 112 | ynh_install_app_dependencies $pkg_dependencies 113 | 114 | #================================================= 115 | # RESTORE THE POSTGRESQL DATABASE 116 | #================================================= 117 | ynh_print_info --message="Restoring the PostgreSQL database..." 118 | 119 | ynh_psql_test_if_first_run 120 | ynh_psql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd 121 | ynh_psql_execute_as_root --sql="CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";" --database=$db_name 122 | ynh_psql_execute_file_as_root --file="./db.sql" --database="$db_name" 123 | 124 | #================================================= 125 | # RESTORE SYSTEMD 126 | #================================================= 127 | ynh_print_info --message="Restoring the systemd configuration..." 128 | 129 | ynh_restore_file --origin_path="/etc/systemd/system/$app-web.service" 130 | ynh_restore_file --origin_path="/etc/systemd/system/$app-worker.service" 131 | ynh_restore_file --origin_path="/etc/systemd/system/$app.target" 132 | systemctl enable $app-web.service 133 | systemctl enable $app-worker.service 134 | systemctl enable $app.target 135 | 136 | #================================================= 137 | # INTEGRATE SERVICE IN YUNOHOST 138 | #================================================= 139 | ynh_print_info --message="Integrating service in YunoHost..." 140 | 141 | yunohost service add "$app-web" --description "$app-web daemon for Reel2Bits" 142 | yunohost service add "$app-worker" --description "$app-worker daemon for Reel2Bits" 143 | yunohost service add "$app" --description "$app daemon for Reel2Bits" 144 | 145 | #================================================= 146 | # START SYSTEMD SERVICE 147 | #================================================= 148 | ynh_print_info --message="Starting a systemd service..." 149 | 150 | ynh_systemd_action --service_name=${app}-web --action="start" --log_path=systemd --line_match="Started ${app}-web" 151 | ynh_systemd_action --service_name=${app}-worker --action="start" --log_path=systemd --line_match="Started ${app}-worker" 152 | systemctl start $app.target 153 | 154 | #================================================= 155 | # GENERIC FINALIZATION 156 | #================================================= 157 | # RELOAD NGINX 158 | #================================================= 159 | ynh_print_info --message="Reloading nginx web server..." 160 | 161 | ynh_systemd_action --service_name=nginx --action=reload 162 | 163 | #================================================= 164 | # END OF SCRIPT 165 | #================================================= 166 | 167 | ynh_print_info --message="Restoration completed for $app" 168 | -------------------------------------------------------------------------------- /scripts/upgrade: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #================================================= 4 | # GENERIC START 5 | #================================================= 6 | # IMPORT GENERIC HELPERS 7 | #================================================= 8 | 9 | source _common.sh 10 | source ynh_add_swap 11 | source /usr/share/yunohost/helpers 12 | 13 | #================================================= 14 | # LOAD SETTINGS 15 | #================================================= 16 | ynh_print_info --message="Loading installation settings..." 17 | 18 | app=$YNH_APP_INSTANCE_NAME 19 | 20 | domain=$(ynh_app_setting_get --app=$app --key=domain) 21 | path_url=$(ynh_app_setting_get --app=$app --key=path) 22 | admin=$(ynh_app_setting_get --app=$app --key=admin) 23 | is_public=$(ynh_app_setting_get --app=$app --key=is_public) 24 | final_path=$(ynh_app_setting_get --app=$app --key=final_path) 25 | language=$(ynh_app_setting_get --app=$app --key=language) 26 | db_name=$(ynh_app_setting_get --app=$app --key=db_name) 27 | db_user=$db_name 28 | db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) 29 | datadir=$(ynh_app_setting_get --app=$app --key=datadir) 30 | security_password_salt=$(ynh_app_setting_get --app=$app --key=security_password_salt) 31 | secret_key=$(ynh_app_setting_get --app=$app --key=secret_key) 32 | port=$(ynh_app_setting_get --app=$app --key=port) 33 | 34 | #================================================= 35 | # CHECK VERSION 36 | #================================================= 37 | 38 | upgrade_type=$(ynh_check_app_version_changed) 39 | 40 | #================================================= 41 | # ENSURE DOWNWARD COMPATIBILITY 42 | #================================================= 43 | ynh_print_info --message="Ensuring downward compatibility..." 44 | 45 | # Fix is_public as a boolean value 46 | if [ "$is_public" = "Yes" ]; then 47 | ynh_app_setting_set --app=$app --key=is_public --value=1 48 | is_public=1 49 | elif [ "$is_public" = "No" ]; then 50 | ynh_app_setting_set --app=$app --key=is_public --value=0 51 | is_public=0 52 | fi 53 | 54 | # If db_name doesn't exist, create it 55 | if [ -z "$db_name" ]; then 56 | db_name=$(ynh_sanitize_dbid --db_name=$app) 57 | ynh_app_setting_set --app=$app --key=db_name --value=$db_name 58 | fi 59 | 60 | # If final_path doesn't exist, create it 61 | if [ -z "$final_path" ]; then 62 | final_path=/var/www/$app 63 | ynh_app_setting_set --app=$app --key=final_path --value=$final_path 64 | fi 65 | 66 | #================================================= 67 | # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP 68 | #================================================= 69 | ynh_print_info --message="Backing up the app before upgrading (may take a while)..." 70 | 71 | # Backup the current version of the app 72 | ynh_backup_before_upgrade 73 | ynh_clean_setup () { 74 | ynh_clean_check_starting 75 | # restore it if the upgrade fails 76 | ynh_restore_upgradebackup 77 | } 78 | # Exit if an error occurs during the execution of the script 79 | ynh_abort_if_errors 80 | 81 | #================================================= 82 | # STANDARD UPGRADE STEPS 83 | #================================================= 84 | # STOP SYSTEMD SERVICE 85 | #================================================= 86 | ynh_print_info --message="Stopping a systemd service..." 87 | 88 | ynh_systemd_action --service_name=${app}-web --action="stop" --log_path=systemd --line_match="Stopped ${app}-web" 89 | ynh_systemd_action --service_name=${app}-worker --action="stop" --log_path=systemd --line_match="Stopped ${app}-worker" 90 | 91 | #================================================= 92 | # DOWNLOAD, CHECK AND UNPACK SOURCE 93 | #================================================= 94 | 95 | if [ "$upgrade_type" == "UPGRADE_APP" ] 96 | then 97 | ynh_print_info --message="Upgrading source files..." 98 | 99 | # Download, check integrity, uncompress and patch the source from app.src 100 | ynh_setup_source --dest_dir="$final_path" 101 | ynh_replace_string --match_string="flasgger==0.9.3" --replace_string="flasgger==0.9.4" --target_file="$final_path/api/requirements.txt" 102 | ynh_replace_string --match_string="Flask_Babelex==0.9.3" --replace_string="Flask_Babelex>=0.9.4" --target_file="$final_path/api/requirements.txt" 103 | ynh_replace_string --match_string="flask_uploads==0.2.1" --replace_string="flask_uploads>=0.2.1" --target_file="$final_path/api/requirements.txt" 104 | 105 | ynh_setup_source --dest_dir="$final_path/front/dist" --source_id=front 106 | fi 107 | 108 | #================================================= 109 | # NGINX CONFIGURATION 110 | #================================================= 111 | ynh_print_info --message="Upgrading nginx web server configuration..." 112 | 113 | # Create a dedicated nginx config 114 | ynh_add_nginx_config "datadir" 115 | 116 | #================================================= 117 | # UPGRADE DEPENDENCIES 118 | #================================================= 119 | ynh_print_info --message="Upgrading dependencies..." 120 | 121 | ynh_install_app_dependencies $pkg_dependencies 122 | 123 | #================================================= 124 | # CREATE DEDICATED USER 125 | #================================================= 126 | ynh_print_info --message="Making sure dedicated system user exists..." 127 | 128 | # Create a dedicated user (if not existing) 129 | ynh_system_user_create --username=$app --home_dir="$final_path" 130 | 131 | #================================================= 132 | # SPECIFIC UPGRADE 133 | #================================================= 134 | # ADD SWAP 135 | #================================================= 136 | ynh_print_info --message="Adding $swap_needed Mo to swap..." 137 | 138 | ynh_add_swap --size=$swap_needed 139 | 140 | #================================================= 141 | # CREATE THE DATA DIRECTORY 142 | #================================================= 143 | ynh_print_info --message="Create the data directory..." 144 | 145 | # Create app folders 146 | mkdir -p "$datadir" 147 | mkdir -p "$datadir/uploads/sounds" 148 | mkdir -p "$datadir/uploads/waveforms" 149 | mkdir -p "$datadir/uploads/artwork_albums" 150 | mkdir -p "$datadir/uploads/artwork_sounds" 151 | mkdir -p "$datadir/uploads/avatars" 152 | 153 | # Give permission to the datadir 154 | chown -R "$app": "$datadir" 155 | 156 | #================================================= 157 | # MODIFY A CONFIG FILE 158 | #================================================= 159 | ynh_print_info --message="Modifying a config file..." 160 | 161 | api_config="$final_path/api/config/prod_secret.py" 162 | ynh_backup_if_checksum_is_different --file="$api_config" 163 | cp ../conf/prod_secret.py "$api_config" 164 | 165 | ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$api_config" 166 | ynh_replace_string --match_string="__DATADIR__" --replace_string="$datadir" --target_file="$api_config" 167 | ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$api_config" 168 | ynh_replace_string --match_string="__SECURITY_PASSWORD_SALT__" --replace_string="$security_password_salt" --target_file="$api_config" 169 | ynh_replace_string --match_string="__SECRET_KEY__" --replace_string="$secret_key" --target_file="$api_config" 170 | ynh_replace_string --match_string="__DB_USER__" --replace_string="$db_user" --target_file="$api_config" 171 | ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$api_config" 172 | ynh_replace_string --match_string="__DB_NAME__" --replace_string="$db_name" --target_file="$api_config" 173 | ynh_replace_string --match_string="__FINAL_PATH__" --replace_string="$final_path" --target_file="$api_config" 174 | 175 | front_config="$final_path/front/config/local.json" 176 | ynh_backup_if_checksum_is_different --file="$front_config" 177 | cp ../conf/local.example.json "$front_config" 178 | ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$front_config" 179 | 180 | #================================================= 181 | # STORE THE CONFIG FILE CHECKSUM 182 | #================================================= 183 | ynh_print_info --message="Storing the config file checksum..." 184 | 185 | # Recalculate and store the checksum of the file for the next upgrade. 186 | ynh_store_file_checksum --file="$api_config" 187 | 188 | #================================================= 189 | # INSTALL PYTHONZ TO GET PYTHON 190 | #================================================= 191 | ynh_print_info --message="Installing Python..." 192 | 193 | # Get pythonz 194 | # curl -kL https://raw.githubusercontent.com/saghul/pythonz/master/pythonz-install 195 | # ./pythonz-install 196 | ynh_setup_source --dest_dir="$final_path/.pythonz" --source_id=pythonz 197 | export PYTHONZ_ROOT="$final_path/.pythonz" 198 | # Then install it 199 | python $final_path/.pythonz/pythonz_install.py 200 | 201 | # Install Python 202 | $final_path/.pythonz/bin/pythonz install $python_version 203 | 204 | #================================================= 205 | # INSTALL REEL2BITS 206 | #================================================= 207 | ynh_print_info --message="Installing Reel2Bits..." 208 | 209 | pushd $final_path/api 210 | virtualenv -p $($final_path/.pythonz/bin/pythonz locate $python_version) ve3 211 | ve3/bin/pip3 install wheel 212 | ve3/bin/pip3 install werkzeug==0.16.1 213 | ve3/bin/pip3 install --requirement requirements.txt 214 | #ve3/bin/python3 setup.py install 215 | export APP_SETTINGS='config.prod_secret.Config' 216 | ve3/bin/flask db upgrade 217 | ve3/bin/pip3 install waitress 218 | #ve3/bin/flask users create --password TEXT -a IDENTITY 219 | #ve3/bin/flask roles add yalh@yh.yalh.net admin 220 | popd 221 | 222 | #================================================= 223 | # SETUP SYSTEMD 224 | #================================================= 225 | ynh_print_info --message="Upgrading systemd configuration..." 226 | 227 | ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="../conf/reel2bits-web.service" 228 | 229 | # Create a dedicated systemd config 230 | cp ../conf/reel2bits.target /etc/systemd/system/reel2bits.target 231 | ynh_add_systemd_config --service="$app-web" --template="reel2bits-web.service" 232 | ynh_add_systemd_config --service="$app-worker" --template="reel2bits-worker.service" 233 | 234 | #================================================= 235 | # GENERIC FINALIZATION 236 | #================================================= 237 | # SECURE FILES AND DIRECTORIES 238 | #================================================= 239 | ynh_print_info --message="Securing files and directories..." 240 | 241 | # Set permissions on app files 242 | chown -R "$app": "$final_path" 243 | 244 | #================================================= 245 | # SETUP SSOWAT 246 | #================================================= 247 | ynh_print_info --message="Upgrading SSOwat configuration..." 248 | 249 | # Make app public if necessary 250 | if [ $is_public -eq 1 ] 251 | then 252 | # unprotected_uris allows SSO credentials to be passed anyway 253 | ynh_app_setting_set --app=$app --key=unprotected_uris --value="/" 254 | fi 255 | 256 | #================================================= 257 | # START SYSTEMD SERVICE 258 | #================================================= 259 | ynh_print_info --message="Starting a systemd service..." 260 | 261 | ynh_systemd_action --service_name=${app}-web --action="start" --log_path=systemd --line_match="Started ${app}-web" 262 | ynh_systemd_action --service_name=${app}-worker --action="start" --log_path=systemd --line_match="Started ${app}-worker" 263 | systemctl start $app.target 264 | 265 | #================================================= 266 | # RELOAD NGINX 267 | #================================================= 268 | ynh_print_info --message="Reloading nginx web server..." 269 | 270 | ynh_systemd_action --service_name=nginx --action=reload 271 | 272 | #================================================= 273 | # END OF SCRIPT 274 | #================================================= 275 | 276 | ynh_print_info --message="Upgrade of $app completed" 277 | -------------------------------------------------------------------------------- /scripts/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #================================================= 4 | # GENERIC START 5 | #================================================= 6 | # IMPORT GENERIC HELPERS 7 | #================================================= 8 | 9 | source _common.sh 10 | source ynh_add_swap 11 | source /usr/share/yunohost/helpers 12 | 13 | #================================================= 14 | # MANAGE SCRIPT FAILURE 15 | #================================================= 16 | ynh_print_info --message="Managing script failure..." 17 | 18 | ynh_clean_setup () { 19 | ynh_clean_check_starting 20 | } 21 | # Exit if an error occurs during the execution of the script 22 | ynh_abort_if_errors 23 | 24 | #================================================= 25 | # RETRIEVE ARGUMENTS FROM THE MANIFEST 26 | #================================================= 27 | ynh_print_info --message="Retrieving arguments from the manifest..." 28 | 29 | domain=$YNH_APP_ARG_DOMAIN 30 | path_url="/" 31 | admin=$YNH_APP_ARG_ADMIN 32 | is_public=$YNH_APP_ARG_IS_PUBLIC 33 | language=$YNH_APP_ARG_LANGUAGE 34 | password=$YNH_APP_ARG_PASSWORD 35 | security_password_salt=$(ynh_string_random 30) 36 | secret_key=$(ynh_string_random 30) 37 | 38 | app=$YNH_APP_INSTANCE_NAME 39 | 40 | # Define app's data directory 41 | datadir="/home/yunohost.app/${app}" 42 | 43 | #================================================= 44 | # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS 45 | #================================================= 46 | ynh_print_info --message="Validating installation parameters..." 47 | 48 | final_path=/var/www/$app 49 | test ! -e "$final_path" || ynh_die --message="This path already contains a folder" 50 | 51 | # Register (book) web path 52 | ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url 53 | 54 | #================================================= 55 | # STORE SETTINGS FROM MANIFEST 56 | #================================================= 57 | ynh_print_info --message="Storing installation settings..." 58 | 59 | ynh_app_setting_set --app=$app --key=domain --value=$domain 60 | ynh_app_setting_set --app=$app --key=path --value=$path_url 61 | ynh_app_setting_set --app=$app --key=admin --value=$admin 62 | ynh_app_setting_set --app=$app --key=is_public --value=$is_public 63 | ynh_app_setting_set --app=$app --key=language --value=$language 64 | ynh_app_setting_set --app=$app --key=security_password_salt --value=$security_password_salt 65 | ynh_app_setting_set --app=$app --key=secret_key --value=$secret_key 66 | ynh_app_setting_set --app=$app --key=datadir --value=$datadir 67 | 68 | #================================================= 69 | # STANDARD MODIFICATIONS 70 | #================================================= 71 | # FIND AND OPEN A PORT 72 | #================================================= 73 | ynh_print_info --message="Configuring firewall..." 74 | 75 | # Find an available port 76 | port=$(ynh_find_port --port=8095) 77 | ynh_app_setting_set --app=$app --key=port --value=$port 78 | 79 | #================================================= 80 | # ADD SWAP 81 | #================================================= 82 | ynh_print_info --message="Adding $swap_needed Mo to swap..." 83 | 84 | ynh_add_swap --size=$swap_needed 85 | 86 | #================================================= 87 | # INSTALL BUILD DEPENDENCIES 88 | #================================================= 89 | ynh_print_info --message="Installing build dependencies..." 90 | 91 | ynh_install_app_dependencies $build_dependencies 92 | 93 | #================================================= 94 | # BUILD AUDIOWAVEFORM 95 | #================================================= 96 | ynh_print_info --message="Building audiowaveform..." 97 | 98 | ynh_setup_source --dest_dir="$final_path/audiowaveform.d/audiowaveform" --source_id=audiowaveform 99 | ynh_setup_source --dest_dir="$final_path/audiowaveform.d/googletest" --source_id=googletest 100 | 101 | pushd "$final_path/audiowaveform.d/audiowaveform" 102 | ln -s $final_path/audiowaveform.d/googletest/googletest googletest 103 | ln -s $final_path/audiowaveform.d/googletest/googlemock googlemock 104 | mkdir build 105 | cd build 106 | cmake .. 107 | make 108 | cp $final_path/audiowaveform.d/audiowaveform/build/audiowaveform $final_path/. 109 | popd 110 | 111 | ynh_secure_remove --file="$final_path/audiowaveform.d" 112 | 113 | #================================================= 114 | # REMOVE BUILD DEPENDENCIES 115 | #================================================= 116 | ynh_print_info --message="Removing build dependencies" 117 | 118 | # Remove metapackage and its dependencies 119 | ynh_remove_app_dependencies 120 | 121 | #================================================= 122 | # INSTALL DEPENDENCIES 123 | #================================================= 124 | ynh_print_info --message="Installing dependencies..." 125 | 126 | ynh_install_app_dependencies $pkg_dependencies 127 | 128 | #================================================= 129 | # CREATE A POSTGRESQL DATABASE 130 | #================================================= 131 | ynh_print_info --message="Creating a PostgreSQL database..." 132 | 133 | db_name=$(ynh_sanitize_dbid --db_name=$app) 134 | db_user=$db_name 135 | db_pwd=$(ynh_string_random --length=30) 136 | ynh_app_setting_set --app=$app --key=db_name --value=$db_name 137 | ynh_app_setting_set --app=$app --key=db_pwd --value=$db_pwd 138 | ynh_psql_test_if_first_run 139 | ynh_psql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd 140 | ynh_psql_execute_as_root --sql="CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";" --database=$db_name 141 | 142 | #================================================= 143 | # DOWNLOAD, CHECK AND UNPACK SOURCE 144 | #================================================= 145 | ynh_print_info --message="Setting up source files..." 146 | 147 | ynh_app_setting_set --app=$app --key=final_path --value=$final_path 148 | # Download, check integrity, uncompress and patch the source from app.src 149 | ynh_setup_source --dest_dir="$final_path" 150 | ynh_replace_string --match_string="flasgger==0.9.3" --replace_string="flasgger==0.9.4" --target_file="$final_path/api/requirements.txt" 151 | ynh_replace_string --match_string="Flask_Babelex==0.9.3" --replace_string="Flask_Babelex>=0.9.4" --target_file="$final_path/api/requirements.txt" 152 | ynh_replace_string --match_string="flask_uploads==0.2.1" --replace_string="flask_uploads>=0.2.1" --target_file="$final_path/api/requirements.txt" 153 | 154 | ynh_setup_source --dest_dir="$final_path/front/dist" --source_id=front 155 | 156 | #================================================= 157 | # NGINX CONFIGURATION 158 | #================================================= 159 | ynh_print_info --message="Configuring nginx web server..." 160 | 161 | # Create a dedicated nginx config 162 | ynh_add_nginx_config "datadir" 163 | 164 | #================================================= 165 | # CREATE DEDICATED USER 166 | #================================================= 167 | ynh_print_info --message="Configuring system user..." 168 | 169 | # Create a system user 170 | ynh_system_user_create --username=$app --home_dir="$final_path" 171 | 172 | #================================================= 173 | # SPECIFIC SETUP 174 | #================================================= 175 | # CREATE THE DATA DIRECTORY 176 | #================================================= 177 | ynh_print_info --message="Create the data directory..." 178 | 179 | # Create app folders 180 | mkdir -p "$datadir" 181 | mkdir -p "$datadir/uploads/sounds" 182 | mkdir -p "$datadir/uploads/waveforms" 183 | mkdir -p "$datadir/uploads/artwork_albums" 184 | mkdir -p "$datadir/uploads/artwork_sounds" 185 | mkdir -p "$datadir/uploads/avatars" 186 | 187 | # Give permission to the datadir 188 | chown -R "$app": "$datadir" 189 | 190 | #================================================= 191 | # MODIFY A CONFIG FILE 192 | #================================================= 193 | ynh_print_info --message="Modifying a config file..." 194 | 195 | api_config="$final_path/api/config/prod_secret.py" 196 | cp ../conf/prod_secret.py "$api_config" 197 | ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$api_config" 198 | ynh_replace_string --match_string="__DATADIR__" --replace_string="$datadir" --target_file="$api_config" 199 | ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$api_config" 200 | ynh_replace_string --match_string="__SECURITY_PASSWORD_SALT__" --replace_string="$security_password_salt" --target_file="$api_config" 201 | ynh_replace_string --match_string="__SECRET_KEY__" --replace_string="$secret_key" --target_file="$api_config" 202 | ynh_replace_string --match_string="__DB_USER__" --replace_string="$db_user" --target_file="$api_config" 203 | ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$api_config" 204 | ynh_replace_string --match_string="__DB_NAME__" --replace_string="$db_name" --target_file="$api_config" 205 | ynh_replace_string --match_string="__FINAL_PATH__" --replace_string="$final_path" --target_file="$api_config" 206 | 207 | front_config="$final_path/front/config/local.json" 208 | cp ../conf/local.example.json "$front_config" 209 | ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$front_config" 210 | 211 | #================================================= 212 | # INSTALL PYTHONZ TO GET PYTHON 213 | #================================================= 214 | ynh_print_info --message="Installing Python..." 215 | 216 | # Get pythonz 217 | # curl -kL https://raw.githubusercontent.com/saghul/pythonz/master/pythonz-install 218 | # ./pythonz-install 219 | ynh_setup_source --dest_dir="$final_path/.pythonz" --source_id=pythonz 220 | export PYTHONZ_ROOT="$final_path/.pythonz" 221 | # Then install it 222 | python $final_path/.pythonz/pythonz_install.py 223 | 224 | # Install Python 225 | $final_path/.pythonz/bin/pythonz install $python_version 226 | 227 | #================================================= 228 | # INSTALL REEL2BITS 229 | #================================================= 230 | ynh_print_info --message="Installing Reel2Bits..." 231 | 232 | # Set permissions to app files 233 | chown -R "$app": "$final_path" 234 | 235 | pushd $final_path/api 236 | virtualenv -p $($final_path/.pythonz/bin/pythonz locate $python_version) ve3 237 | ve3/bin/pip3 install wheel 238 | ve3/bin/pip3 install werkzeug==0.16.1 239 | ve3/bin/pip3 install --requirement requirements.txt 240 | #ve3/bin/python3 setup.py install 241 | export APP_SETTINGS=config.prod_secret.Config 242 | ve3/bin/flask db upgrade 243 | ve3/bin/flask db-datas 000-seeds 244 | #ve3/bin/flask seed 245 | ve3/bin/pip3 install waitress 246 | #ve3/bin/flask users create --password TEXT -a IDENTITY 247 | #ve3/bin/flask roles add yalh@yh.yalh.net admin 248 | popd 249 | 250 | #================================================= 251 | # SETUP SYSTEMD 252 | #================================================= 253 | ynh_print_info --message="Configuring a systemd service..." 254 | 255 | ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="../conf/reel2bits-web.service" 256 | 257 | # Create a dedicated systemd config 258 | cp ../conf/reel2bits.target /etc/systemd/system/$app.target 259 | ynh_add_systemd_config --service="$app-web" --template="reel2bits-web.service" 260 | ynh_add_systemd_config --service="$app-worker" --template="reel2bits-worker.service" 261 | 262 | #================================================= 263 | # STORE THE CONFIG FILE CHECKSUM 264 | #================================================= 265 | ynh_print_info --message="Storing the config file checksum..." 266 | 267 | # Calculate and store the config file checksum into the app settings 268 | ynh_store_file_checksum --file="$api_config" 269 | ynh_store_file_checksum --file="$front_config" 270 | 271 | #================================================= 272 | # GENERIC FINALIZATION 273 | #================================================= 274 | # SECURE FILES AND DIRECTORIES 275 | #================================================= 276 | ynh_print_info --message="Securing files and directories..." 277 | 278 | # Set permissions to app files 279 | chown -R "$app": "$final_path" 280 | 281 | #================================================= 282 | # INTEGRATE SERVICE IN YUNOHOST 283 | #================================================= 284 | ynh_print_info --message="Integrating service in YunoHost..." 285 | 286 | yunohost service add $app-web --description "$app-web daemon for Reel2Bits" 287 | yunohost service add $app-worker --description "$app-worker daemon for Reel2Bits" 288 | yunohost service add $app --description "$app daemon for Reel2Bits" 289 | 290 | #================================================= 291 | # START SYSTEMD SERVICE 292 | #================================================= 293 | ynh_print_info --message="Starting a systemd service..." 294 | 295 | # Start a systemd service 296 | ynh_systemd_action --service_name=${app}-web --action="start" --log_path=systemd --line_match="Started ${app}-web" 297 | ynh_systemd_action --service_name=${app}-worker --action="start" --log_path=systemd --line_match="Started ${app}-worker" 298 | systemctl start $app.target 299 | 300 | #================================================= 301 | # SETUP SSOWAT 302 | #================================================= 303 | ynh_print_info --message="Configuring SSOwat..." 304 | 305 | # Make app public if necessary 306 | if [ $is_public -eq 1 ] 307 | then 308 | # unprotected_uris allows SSO credentials to be passed anyway. 309 | ynh_app_setting_set --app=$app --key=unprotected_uris --value="/" 310 | fi 311 | 312 | #================================================= 313 | # RELOAD NGINX 314 | #================================================= 315 | ynh_print_info --message="Reloading nginx web server..." 316 | 317 | ynh_systemd_action --service_name=nginx --action=reload 318 | 319 | #================================================= 320 | # END OF SCRIPT 321 | #================================================= 322 | 323 | ynh_print_info --message="Installation of $app completed" 324 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | reel2bit - selfhosted federated audio publishing application 633 | Copyright (C) 2016-2019 dashie 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | --------------------------------------------------------------------------------