Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49b8dc0079 | ||
|
|
ab83c3a551 | ||
|
|
98c6093674 | ||
|
|
e1f51521bf | ||
|
|
e85bc98dcc | ||
|
|
4ba52baa5c | ||
|
|
a82077b4de | ||
|
|
b8f04f3d11 | ||
|
|
e91f65f833 | ||
|
|
575ab9be2d | ||
|
|
64071bb60f | ||
|
|
44621a1a61 | ||
|
|
c56043e1f9 | ||
|
|
e8e4cbfd41 | ||
|
|
4b2bbe0614 | ||
|
|
9adfa14e62 | ||
|
|
067f82b632 | ||
|
|
e24e7979be | ||
|
|
c7c2b6e6f2 | ||
|
|
96798963d6 | ||
|
|
75508a81ef | ||
|
|
f7f4efadb7 | ||
|
|
4cc80b98db | ||
|
|
b07efaa7d0 | ||
|
|
7ba8ea6dd4 | ||
|
|
479461821f | ||
|
|
d25aea38fb | ||
|
|
0067502b37 | ||
|
|
d321af6085 | ||
|
|
b30f1730e4 | ||
|
|
7a02986982 | ||
|
|
a4107cba25 | ||
|
|
ba187aa345 | ||
|
|
b400cef734 | ||
|
|
03b72b8d2e | ||
|
|
0c7e20dee0 | ||
|
|
aa42c71a06 | ||
|
|
041c0b81a3 | ||
|
|
fe6776ee9d | ||
|
|
125b9f4160 | ||
|
|
488fee7b4b | ||
|
|
4fba596909 | ||
|
|
af04781830 | ||
|
|
2507cda94c | ||
|
|
21c1401859 | ||
|
|
4351f55225 | ||
|
|
d1956c4e88 | ||
|
|
d76d056ed1 | ||
|
|
e081cc31a2 | ||
|
|
88153b0e32 | ||
|
|
2b2d51cb6f | ||
|
|
abd8c7227d | ||
|
|
b4a1ecc305 | ||
|
|
540bead0db | ||
|
|
6e9f25d680 | ||
|
|
268afe7006 | ||
|
|
4fb59385b7 | ||
|
|
40d6808067 | ||
|
|
380a0e8623 | ||
|
|
4f6a0cb7c6 |
63
app/Application.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Application extends Model
|
||||
{
|
||||
public $incrementing = false;
|
||||
|
||||
protected $primaryKey = 'appid';
|
||||
|
||||
//
|
||||
public function icon()
|
||||
{
|
||||
if(!file_exists(storage_path('app/public/'.$this->icon))) {
|
||||
$img_src = app_path('SupportedApps/'.$this->name.'/'.str_replace('icons/', '', $this->icon));
|
||||
$img_dest = storage_path('app/public/'.$this->icon);
|
||||
//die("i: ".$img_src);
|
||||
@copy($img_src, $img_dest);
|
||||
}
|
||||
|
||||
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function iconView()
|
||||
{
|
||||
return asset('storage/'.$this->icon);
|
||||
}
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
// check if light or dark
|
||||
if($this->tile_background == 'light') return '#fafbfc';
|
||||
return '#161b1f';
|
||||
}
|
||||
|
||||
public function class()
|
||||
{
|
||||
$name = $this->name;
|
||||
$name = preg_replace('/\PL/u', '', $name);
|
||||
|
||||
$class = '\App\SupportedApps\\'.$name.'\\'.$name;
|
||||
return $class;
|
||||
}
|
||||
|
||||
public static function applist()
|
||||
{
|
||||
$list = [];
|
||||
$all = self::orderBy('name')->get()->sortBy('name', SORT_NATURAL|SORT_FLAG_CASE);
|
||||
$list['null'] = 'None';
|
||||
foreach($all as $app) {
|
||||
$name = $app->name;
|
||||
$name = preg_replace('/\PL/u', '', $name);
|
||||
|
||||
$list['\App\SupportedApps\\'.$name.'\\'.$name] = $app->name;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
79
app/Console/Commands/RegisterApp.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Application;
|
||||
use App\SupportedApps;
|
||||
|
||||
class RegisterApp extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'register:app {folder}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Add a local app to the registry';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$folder = $this->argument('folder');
|
||||
if($folder == 'all') {
|
||||
$apps = scandir(app_path('SupportedApps'));
|
||||
foreach($apps as $folder) {
|
||||
if($folder == '.' || $folder == '..') continue;
|
||||
$this->addApp($folder);
|
||||
}
|
||||
|
||||
} else {
|
||||
$this->addApp($folder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function addApp($folder)
|
||||
{
|
||||
$json = app_path('SupportedApps/'.$folder.'/app.json');
|
||||
if(file_exists($json)) {
|
||||
$app = json_decode(file_get_contents($json));
|
||||
if(isset($app->appid)) {
|
||||
$exists = Application::find($app->appid);
|
||||
if($exists) {
|
||||
$this->error('Application already registered - '.$exists->name." - ".$exists->appid);
|
||||
} else {
|
||||
// Doesn't exist so add it
|
||||
SupportedApps::saveApp($app, new Application);
|
||||
$this->info("Application Added - ".$app->name." - ".$app->appid);
|
||||
}
|
||||
} else {
|
||||
$this->error('No App ID for - '.$folder);
|
||||
}
|
||||
|
||||
} else {
|
||||
$this->error('Could not find '.$json);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
12
app/EnhancedApps.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
interface EnhancedApps
|
||||
{
|
||||
public function test();
|
||||
public function livestats();
|
||||
public function url($endpoint);
|
||||
|
||||
}
|
||||
@@ -33,4 +33,12 @@ function title_color($hex)
|
||||
} else {
|
||||
return ' white';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function className($name)
|
||||
{
|
||||
$name = preg_replace('/\PL/u', '', $name);
|
||||
return $name;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Artisan;
|
||||
use App\Application;
|
||||
use App\Item;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use App\SupportedApps\Nzbget;
|
||||
use GrahamCampbell\GitHub\Facades\GitHub;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\SupportedApps;
|
||||
use App\Jobs\ProcessApps;
|
||||
|
||||
class ItemController extends Controller
|
||||
{
|
||||
@@ -41,9 +45,8 @@ class ItemController extends Controller
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Pin item on the dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
@@ -154,6 +157,12 @@ class ItemController extends Controller
|
||||
'user_id' => $current_user->id
|
||||
]);
|
||||
|
||||
if($request->input('class') === 'null') {
|
||||
$request->merge([
|
||||
'class' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
//die(print_r($request->input('config')));
|
||||
|
||||
@@ -222,6 +231,13 @@ class ItemController extends Controller
|
||||
'user_id' => $current_user->id
|
||||
]);
|
||||
|
||||
if($request->input('class') === 'null') {
|
||||
$request->merge([
|
||||
'class' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$item = Item::find($id);
|
||||
$item->update($request->all());
|
||||
|
||||
@@ -273,16 +289,6 @@ class ItemController extends Controller
|
||||
->with('success',__('app.alert.success.item_restored'));
|
||||
}
|
||||
|
||||
public function isSupportedAppByKey($app)
|
||||
{
|
||||
$output = false;
|
||||
$all_supported = Item::supportedList();
|
||||
if(array_key_exists($app, $all_supported)) {
|
||||
$output = new $all_supported[$app];
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return details for supported apps
|
||||
*
|
||||
@@ -291,19 +297,25 @@ class ItemController extends Controller
|
||||
public function appload(Request $request)
|
||||
{
|
||||
$output = [];
|
||||
$app = $request->input('app');
|
||||
$appname = $request->input('app');
|
||||
//die($appname);
|
||||
|
||||
if(($app_details = $this->isSupportedAppByKey($app)) !== false) {
|
||||
// basic details
|
||||
$output['icon'] = $app_details->icon();
|
||||
$output['colour'] = $app_details->defaultColour();
|
||||
$app_details = Application::where('name', $appname)->firstOrFail();
|
||||
$appclass = $app_details->class();
|
||||
$app = new $appclass;
|
||||
|
||||
// live details
|
||||
if($app_details instanceof \App\SupportedApps\Contracts\Livestats) {
|
||||
$output['config'] = $app_details->configDetails();
|
||||
} else {
|
||||
$output['config'] = null;
|
||||
}
|
||||
// basic details
|
||||
$output['icon'] = $app_details->icon();
|
||||
$output['name'] = $app_details->name;
|
||||
$output['iconview'] = $app_details->iconView();
|
||||
$output['colour'] = $app_details->defaultColour();
|
||||
$output['class'] = $appclass;
|
||||
|
||||
// live details
|
||||
if($app instanceof \App\EnhancedApps) {
|
||||
$output['config'] = className($app_details->name).'.config';
|
||||
} else {
|
||||
$output['config'] = null;
|
||||
}
|
||||
|
||||
return json_encode($output);
|
||||
@@ -318,25 +330,34 @@ class ItemController extends Controller
|
||||
|
||||
$app_details = new $app();
|
||||
$app_details->config = (object)$data;
|
||||
$app_details->testConfig();
|
||||
$app_details->test();
|
||||
}
|
||||
|
||||
public function getStats($id)
|
||||
{
|
||||
$item = Item::find($id);
|
||||
|
||||
$config = json_decode($item->description);
|
||||
if(isset($config->type)) {
|
||||
$config->url = $item->url;
|
||||
if(isset($config->override_url) && !empty($config->override_url)) {
|
||||
$config->url = $config->override_url;
|
||||
}
|
||||
$app_details = new $config->type;
|
||||
$app_details->config = $config;
|
||||
echo $app_details->executeConfig();
|
||||
$config = $item->getconfig();
|
||||
if(isset($item->class)) {
|
||||
$application = new $item->class;
|
||||
$application->config = $config;
|
||||
echo $application->livestats();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function checkAppList()
|
||||
{
|
||||
ProcessApps::dispatch();
|
||||
$route = route('items.index');
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.updating'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ class SettingsController extends Controller
|
||||
if (!is_null($setting)) {
|
||||
$data = Setting::getInput();
|
||||
|
||||
$setting_value = null;
|
||||
|
||||
if ($setting->type == 'image') {
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Item;
|
||||
use App\User;
|
||||
use DB;
|
||||
|
||||
class TagController extends Controller
|
||||
@@ -62,10 +63,13 @@ class TagController extends Controller
|
||||
|
||||
$slug = str_slug($request->title, '-');
|
||||
|
||||
$current_user = User::currentUser();
|
||||
|
||||
// set item type to tag
|
||||
$request->merge([
|
||||
'type' => '1',
|
||||
'url' => $slug
|
||||
'url' => $slug,
|
||||
'user_id' => $current_user->id
|
||||
]);
|
||||
//die(print_r($request->all()));
|
||||
Item::create($request->all());
|
||||
|
||||
160
app/Item.php
@@ -24,7 +24,7 @@ class Item extends Model
|
||||
|
||||
//
|
||||
protected $fillable = [
|
||||
'title', 'url', 'colour', 'icon', 'description', 'pinned', 'order', 'type', 'user_id'
|
||||
'title', 'url', 'colour', 'icon', 'description', 'pinned', 'order', 'type', 'class', 'user_id'
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -34,82 +34,6 @@ class Item extends Model
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
public static function supportedList()
|
||||
{
|
||||
return [
|
||||
'AirSonic' => \App\SupportedApps\AirSonic::class,
|
||||
'Cardigann' => \App\SupportedApps\Cardigann::class,
|
||||
'CouchPotato' => \App\SupportedApps\CouchPotato::class,
|
||||
'Bazarr' => \App\SupportedApps\Bazarr::class,
|
||||
'Bitwarden' => \App\SupportedApps\Bitwarden::class,
|
||||
'Booksonic' => \App\SupportedApps\Booksonic::class,
|
||||
'BookStack' => \App\SupportedApps\BookStack::class,
|
||||
'Deluge' => \App\SupportedApps\Deluge::class,
|
||||
'Dokuwiki' => \App\SupportedApps\Dokuwiki::class,
|
||||
'Duplicati' => \App\SupportedApps\Duplicati::class,
|
||||
'Emby' => \App\SupportedApps\Emby::class,
|
||||
'Flood' => \App\SupportedApps\Flood::class,
|
||||
'FreshRSS' => \App\SupportedApps\FreshRSS::class,
|
||||
'Gitea' => \App\SupportedApps\Gitea::class,
|
||||
'Glances' => \App\SupportedApps\Glances::class,
|
||||
'Grafana' => \App\SupportedApps\Grafana::class,
|
||||
'Graylog' => \App\SupportedApps\Graylog::class,
|
||||
'Headphones' => \App\SupportedApps\Headphones::class,
|
||||
'Home Assistant' => \App\SupportedApps\HomeAssistant::class,
|
||||
'Jackett' => \App\SupportedApps\Jackett::class,
|
||||
'Jdownloader' => \App\SupportedApps\Jdownloader::class,
|
||||
'Krusader' => \App\SupportedApps\Krusader::class,
|
||||
'LibreNMS' => \App\SupportedApps\LibreNMS::class,
|
||||
'Lidarr' => \App\SupportedApps\Lidarr::class,
|
||||
'Mailcow' => \App\SupportedApps\Mailcow::class,
|
||||
'Mcmyadmin' => \App\SupportedApps\Mcmyadmin::class,
|
||||
'Medusa' => \App\SupportedApps\Medusa::class,
|
||||
'Monica' => \App\SupportedApps\Monica::class,
|
||||
'MusicBrainz' => \App\SupportedApps\MusicBrainz::class,
|
||||
'Mylar' => \App\SupportedApps\Mylar::class,
|
||||
'NZBGet' => \App\SupportedApps\Nzbget::class,
|
||||
'Netdata' => \App\SupportedApps\Netdata::class,
|
||||
'Nextcloud' => \App\SupportedApps\Nextcloud::class,
|
||||
'Now Showing' => \App\SupportedApps\NowShowing::class,
|
||||
'Nzbhydra' => \App\SupportedApps\Nzbhydra::class,
|
||||
'OPNSense' => \App\SupportedApps\Opnsense::class,
|
||||
'Ombi' => \App\SupportedApps\Ombi::class,
|
||||
'Openhab' => \App\SupportedApps\Openhab::class,
|
||||
'OpenMediaVault' => \App\SupportedApps\OpenMediaVault::class,
|
||||
'Pihole' => \App\SupportedApps\Pihole::class,
|
||||
'Plex' => \App\SupportedApps\Plex::class,
|
||||
'Plexpy' => \App\SupportedApps\Plexpy::class,
|
||||
'Plexrequests' => \App\SupportedApps\Plexrequests::class,
|
||||
'Portainer' => \App\SupportedApps\Portainer::class,
|
||||
'Proxmox' => \App\SupportedApps\Proxmox::class,
|
||||
'Radarr' => \App\SupportedApps\Radarr::class,
|
||||
'Rancher' => \App\SupportedApps\Rancher::class,
|
||||
'Runeaudio' => \App\SupportedApps\Runeaudio::class,
|
||||
'Sabnzbd' => \App\SupportedApps\Sabnzbd::class,
|
||||
'Sickrage' => \App\SupportedApps\Sickrage::class,
|
||||
'Sonarr' => \App\SupportedApps\Sonarr::class,
|
||||
'Syncthing' => \App\SupportedApps\Syncthing::class,
|
||||
'Tautulli' => \App\SupportedApps\Tautulli::class,
|
||||
'Transmission' => \App\SupportedApps\Transmission::class,
|
||||
'Traefik' => \App\SupportedApps\Traefik::class,
|
||||
'tt-rss' => \App\SupportedApps\Ttrss::class,
|
||||
'TVheadend' => \App\SupportedApps\TVheadend::class,
|
||||
'UniFi' => \App\SupportedApps\Unifi::class,
|
||||
'unRAID' => \App\SupportedApps\Unraid::class,
|
||||
'pfSense' => \App\SupportedApps\Pfsense::class,
|
||||
'pyLoad' => \App\SupportedApps\pyLoad::class,
|
||||
'ruTorrent' => \App\SupportedApps\ruTorrent::class,
|
||||
'Virtualmin' => \App\SupportedApps\Virtualmin::class,
|
||||
'Watcher3' => \App\SupportedApps\Watcher3::class,
|
||||
'Webmin' => \App\SupportedApps\Webmin::class,
|
||||
'WebTools' => \App\SupportedApps\WebTools::class,
|
||||
];
|
||||
}
|
||||
public static function supportedOptions()
|
||||
{
|
||||
return array_keys(self::supportedList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope a query to only include pinned items.
|
||||
*
|
||||
@@ -121,24 +45,6 @@ class Item extends Model
|
||||
return $query->where('pinned', 1);
|
||||
}
|
||||
|
||||
public function getConfigAttribute()
|
||||
{
|
||||
$output = null;
|
||||
$view = null;
|
||||
if(isset($this->description) && !empty($this->description)){
|
||||
$output = json_decode($this->description);
|
||||
$output = is_object($output) ? $output : new \stdClass();
|
||||
if(isset($output->type) && !empty($output->type)) {
|
||||
$class = $output->type;
|
||||
$sap = new $class();
|
||||
$view = $sap->configDetails();
|
||||
$output->view = $view;
|
||||
}
|
||||
if(!isset($output->dataonly)) $output->dataonly = '0';
|
||||
|
||||
}
|
||||
return (object)$output;
|
||||
}
|
||||
public static function checkConfig($config)
|
||||
{
|
||||
if(empty($config)) {
|
||||
@@ -218,6 +124,14 @@ class Item extends Model
|
||||
}
|
||||
}
|
||||
|
||||
public static function nameFromClass($class)
|
||||
{
|
||||
$explode = explode('\\', $class);
|
||||
$name = end($explode);
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
public function scopeOfType($query, $type)
|
||||
{
|
||||
switch($type) {
|
||||
@@ -232,6 +146,62 @@ class Item extends Model
|
||||
return $query->where('type', $typeid);
|
||||
}
|
||||
|
||||
public function enhanced()
|
||||
{
|
||||
if(isset($this->class) && !empty($this->class)) {
|
||||
$app = new $this->class;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return (bool)($app instanceof \App\EnhancedApps);
|
||||
}
|
||||
|
||||
public static function isEnhanced($class)
|
||||
{
|
||||
$app = new $class;
|
||||
return (bool)($app instanceof \App\EnhancedApps);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
if($this->enhanced()) {
|
||||
$config = $this->getconfig();
|
||||
if($config) {
|
||||
return (bool) $config->enabled;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getconfig()
|
||||
{
|
||||
$explode = explode('\\', $this->class);
|
||||
|
||||
|
||||
if(!isset($this->description) || empty($this->description)) {
|
||||
$config = new \stdClass;
|
||||
$config->name = end($explode);
|
||||
$config->enabled = false;
|
||||
return $config;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$config = json_decode($this->description);
|
||||
|
||||
$config->name = end($explode);
|
||||
|
||||
|
||||
$config->url = $this->url;
|
||||
if(isset($config->override_url) && !empty($config->override_url)) {
|
||||
$config->url = $config->override_url;
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the user that owns the item.
|
||||
*/
|
||||
|
||||
66
app/Jobs/ProcessApps.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use App\Application;
|
||||
use App\SupportedApps;
|
||||
|
||||
class ProcessApps implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$localapps = Application::all();
|
||||
$list = json_decode(SupportedApps::getList()->getBody());
|
||||
$validapps = [];
|
||||
|
||||
foreach($list->apps as $app) {
|
||||
$validapps[] = $app->appid;
|
||||
$localapp = $localapps->where('appid', $app->appid)->first();
|
||||
|
||||
$application = ($localapp) ? $localapp : new Application;
|
||||
|
||||
if(!file_exists(app_path('SupportedApps/'.className($app->name)))) {
|
||||
SupportedApps::getFiles($app);
|
||||
SupportedApps::saveApp($app, $application);
|
||||
} else {
|
||||
// check if there has been an update for this app
|
||||
$localapp = $localapps->where('appid', $app->appid)->first();
|
||||
if($localapp) {
|
||||
if($localapp->sha !== $app->sha) {
|
||||
SupportedApps::getFiles($app);
|
||||
SupportedApps::saveApp($app, $application);
|
||||
}
|
||||
} else {
|
||||
SupportedApps::getFiles($app);
|
||||
SupportedApps::saveApp($app, $application);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//$delete = Application::whereNotIn('appid', $validapps)->delete(); // delete any apps not in list
|
||||
// removed the delete so local apps can be added
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ use Artisan;
|
||||
use Schema;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use App\Application;
|
||||
use App\Jobs\ProcessApps;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -17,7 +19,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
|
||||
|
||||
if(!is_file(base_path('.env'))) {
|
||||
touch(base_path('.env'));
|
||||
@@ -40,15 +41,27 @@ class AppServiceProvider extends ServiceProvider
|
||||
if(version_compare($app_version, $db_version) == 1) { // app is higher than db, so need to run migrations etc
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
}
|
||||
|
||||
} else {
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!is_file(public_path('storage'))) {
|
||||
Artisan::call('storage:link');
|
||||
\Session::put('current_user', null);
|
||||
}
|
||||
|
||||
$applications = Application::all();
|
||||
if($applications->count() <= 0) {
|
||||
if (class_exists('ZipArchive')) {
|
||||
ProcessApps::dispatch();
|
||||
} else {
|
||||
die("You are missing php-zip");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// User specific settings need to go here as session isn't available at this point in the app
|
||||
view()->composer('*', function ($view)
|
||||
@@ -91,6 +104,8 @@ class AppServiceProvider extends ServiceProvider
|
||||
|
||||
});
|
||||
|
||||
$this->app['view']->addNamespace('SupportedApps', app_path('SupportedApps'));
|
||||
|
||||
|
||||
if (env('FORCE_HTTPS') === true) {
|
||||
\URL::forceScheme('https');
|
||||
|
||||
172
app/SupportedApps.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php namespace App;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
abstract class SupportedApps
|
||||
{
|
||||
|
||||
protected $jar = false;
|
||||
protected $method = 'GET';
|
||||
protected $error;
|
||||
|
||||
public function appTest($url, $attrs = [], $overridevars=false)
|
||||
{
|
||||
if(empty($this->config->url)) {
|
||||
return (object)[
|
||||
'code' => 404,
|
||||
'status' => 'No URL has been specified',
|
||||
'response' => 'No URL has been specified',
|
||||
];
|
||||
}
|
||||
$res = $this->execute($url, $attrs);
|
||||
if($res == null) {
|
||||
return (object)[
|
||||
'code' => null,
|
||||
'status' => $this->error,
|
||||
'response' => 'Connection failed',
|
||||
];
|
||||
}
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$status = 'Successfully communicated with the API';
|
||||
break;
|
||||
case 401:
|
||||
$status = 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
$status = 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
$status = 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
return (object)[
|
||||
'code' => $res->getStatusCode(),
|
||||
'status' => $status,
|
||||
'response' => $res->getBody(),
|
||||
];
|
||||
}
|
||||
|
||||
public function execute($url, $attrs = [], $overridevars=false, $overridemethod=false)
|
||||
{
|
||||
$res = null;
|
||||
|
||||
$vars = ($overridevars !== false) ?
|
||||
$overridevars : [
|
||||
'http_errors' => false,
|
||||
'timeout' => 15,
|
||||
'connect_timeout' => 15,
|
||||
];
|
||||
|
||||
$client = new Client($vars);
|
||||
|
||||
$method = ($overridemethod !== false) ? $overridemethod : $this->method;
|
||||
|
||||
try {
|
||||
return $client->request($method, $url, $attrs);
|
||||
} catch (\GuzzleHttp\Exception\ConnectException $e) {
|
||||
Log::error("Connection refused");
|
||||
Log::debug($e->getMessage());
|
||||
$this->error = "Connection refused - ".(string) $e->getMessage();
|
||||
} catch (\GuzzleHttp\Exception\ServerException $e) {
|
||||
Log::debug($e->getMessage());
|
||||
$this->error = (string) $e->getResponse()->getBody();
|
||||
}
|
||||
$this->error = 'General error connecting with API';
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function login()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function normaliseurl($url, $addslash=true)
|
||||
{
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
if($addslash) $url .= '/';
|
||||
|
||||
return $url;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function getLiveStats($status, $data)
|
||||
{
|
||||
$className = get_class($this);
|
||||
$explode = explode('\\', $className);
|
||||
$name = end($explode);
|
||||
|
||||
$html = view('SupportedApps::'.$name.'.livestats', $data)->with('data', $data)->render();
|
||||
return json_encode(['status' => $status, 'html' => $html]);
|
||||
//return
|
||||
}
|
||||
|
||||
public static function getList()
|
||||
{
|
||||
$list_url = 'https://apps.heimdall.site/list';
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
return $client->request('GET', $list_url);
|
||||
}
|
||||
|
||||
public static function configValue($item=null, $key=null)
|
||||
{
|
||||
if(isset($item) && !empty($item)) {
|
||||
return $item->getconfig()->$key;
|
||||
} else return null;
|
||||
}
|
||||
|
||||
public static function getFiles($app)
|
||||
{
|
||||
$zipurl = $app->files;
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 60, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $zipurl);
|
||||
|
||||
if(!file_exists(app_path('SupportedApps'))) {
|
||||
mkdir(app_path('SupportedApps'), 0777, true);
|
||||
}
|
||||
|
||||
$src = app_path('SupportedApps/'.className($app->name).'.zip');
|
||||
file_put_contents($src, $res->getBody());
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
$x = $zip->open($src); // open the zip file to extract
|
||||
if ($x === true) {
|
||||
$zip->extractTo(app_path('SupportedApps')); // place in the directory with same name
|
||||
$zip->close();
|
||||
unlink($src); //Deleting the Zipped file
|
||||
}
|
||||
}
|
||||
|
||||
public static function saveApp($details, $app)
|
||||
{
|
||||
if(!file_exists(storage_path('app/public/icons'))) {
|
||||
mkdir(storage_path('app/public/icons'), 0777, true);
|
||||
}
|
||||
|
||||
$img_src = app_path('SupportedApps/'.className($details->name).'/'.$details->icon);
|
||||
$img_dest = storage_path('app/public/icons/'.$details->icon);
|
||||
//die("i: ".$img_src);
|
||||
@copy($img_src, $img_dest);
|
||||
|
||||
$app->appid = $details->appid;
|
||||
$app->name = $details->name;
|
||||
$app->sha = $details->sha ?? null;
|
||||
$app->icon = 'icons/'.$details->icon;
|
||||
$app->website = $details->website;
|
||||
$app->license = $details->license;
|
||||
$app->description = $details->description;
|
||||
|
||||
$appclass = $app->class();
|
||||
$application = new $appclass;
|
||||
$enhanced = (bool)($application instanceof \App\EnhancedApps);
|
||||
|
||||
$app->enhanced = $enhanced;
|
||||
$app->tile_background = $details->tile_background;
|
||||
$app->save();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class AirSonic implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#08F';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/airsonic.png';
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Bazarr implements Contracts\Applications {
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#222';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/bazarr.png';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Bitwarden implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#3c8dbc';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/bitwarden.png';
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class BookStack implements Contracts\Applications {
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#02679E';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/bookstack.png';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Booksonic implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#58a';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/booksonic.png';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class Cardigann implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#753';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/cardigann.png';
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php namespace App\SupportedApps\Contracts;
|
||||
|
||||
interface Applications {
|
||||
|
||||
public function defaultColour();
|
||||
|
||||
public function icon();
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps\Contracts;
|
||||
|
||||
interface Livestats {
|
||||
|
||||
public function configDetails();
|
||||
|
||||
public function testConfig();
|
||||
|
||||
public function executeConfig();
|
||||
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CouchPotato implements Contracts\Applications, Contracts\Livestats
|
||||
{
|
||||
|
||||
private $_client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->_client = new Client(
|
||||
['http_errors' => false,
|
||||
'timeout' => 10]
|
||||
);
|
||||
}
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#363840';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/couchpotato.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'couchpotato';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
echo 'CouchPotato connection failed';
|
||||
return;
|
||||
}
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo "Successfully connected to CouchPotato";
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and includes the port';
|
||||
break;
|
||||
case 409:
|
||||
echo 'Failed: Incorrect session id';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
Log::debug('CouchPotato connection failed');
|
||||
return '';
|
||||
}
|
||||
$data = json_decode($res->getBody());
|
||||
if (! isset($data->movies)) {
|
||||
Log::debug('Failed to fetch data from CouchPotato');
|
||||
return '';
|
||||
}
|
||||
$movies = $data->movies;
|
||||
$wantedMovies = $availableMovies = 0;
|
||||
foreach ($movies as $v) {
|
||||
switch ($v->status) {
|
||||
case 'active':
|
||||
$wantedMovies++;
|
||||
break;
|
||||
case 'done':
|
||||
$availableMovies++;
|
||||
break;
|
||||
default:
|
||||
Log::warning('Unexpected CouchPotato status received: '.$v['status']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Wanted</span><sub>'.$wantedMovies.'</sub></li>
|
||||
<li><span class="title">Available</span><sub>'.$availableMovies.'</sub></li>
|
||||
</ul>
|
||||
';
|
||||
return json_encode(['status' => 'inactive', 'html' => $html]);
|
||||
}
|
||||
|
||||
private function sendRequest()
|
||||
{
|
||||
$res = null;
|
||||
try{
|
||||
$res = $this->_client->request(
|
||||
'GET',
|
||||
$this->getApiUrl()
|
||||
);
|
||||
}catch(\GuzzleHttp\Exception\BadResponseException $e){
|
||||
Log::error("Connection to {$e->getRequest()->getUrl()} failed");
|
||||
Log::debug($e->getMessage());
|
||||
$res = $e->getRequest();
|
||||
}catch(\GuzzleHttp\Exception\ConnectException $e) {
|
||||
Log::error("CouchPotato connection refused");
|
||||
Log::debug($e->getMessage());
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
private function getApiUrl()
|
||||
{
|
||||
$url = $this->config->url;
|
||||
$url = rtrim($url, '/');
|
||||
$apiUrl = $url.'/api/'.$this->config->apikey.'/movie.list';
|
||||
return $apiUrl;
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
class Deluge implements Contracts\Applications, Contracts\Livestats {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#357';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/deluge.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
return 'deluge';
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->login()[0];
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
if(!isset($data->result) || is_null($data->result) || $data->result == false) {
|
||||
echo 'Failed: Invalid Credentials';
|
||||
} else {
|
||||
echo 'Successfully connected to the API';
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$jar = $this->login()[1];
|
||||
$res = $this->getDetails($jar);
|
||||
$data = json_decode($res->getBody());
|
||||
$download_rate = $data->result->stats->download_rate;
|
||||
$upload_rate = $data->result->stats->upload_rate;
|
||||
$seed_count = $data->result->filters->state[2];
|
||||
$leech_count = $data->result->filters->state[1];
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title"><i class="fas fa-arrow-down"></i> '.$this->formatBytes($download_rate).'</span></li>
|
||||
<li><span class="title"><i class="fas fa-arrow-up"></i> '.$this->formatBytes($upload_rate).'</span></li>
|
||||
</ul>
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Leech: '.$leech_count[1].'</span></li>
|
||||
<li><span class="title">Seed: '.$seed_count[1].'</span></li>
|
||||
</ul>
|
||||
';
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function getDetails($jar)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$url = rtrim($url, '/');
|
||||
$api_url = $url.'/json';
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('POST', $api_url, [
|
||||
'body' => '{"method": "web.update_ui", "params": [["none"], {}], "id": 1}',
|
||||
'cookies' => $jar,
|
||||
'headers' => ['content-type' => 'application/json', 'Accept' => 'application/json']
|
||||
]);
|
||||
return $res;
|
||||
}
|
||||
public function login()
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$password = $config->password;
|
||||
$url = rtrim($url, '/');
|
||||
$api_url = $url.'/json';
|
||||
$jar = new \GuzzleHttp\Cookie\CookieJar();
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('POST', $api_url, [
|
||||
'body' => '{"method": "auth.login", "params": ["'.$password.'"], "id": 1}',
|
||||
'cookies' => $jar,
|
||||
'headers' => ['content-type' => 'application/json', 'Accept' => 'application/json']
|
||||
]);
|
||||
return array($res,$jar);
|
||||
}
|
||||
|
||||
function formatBytes($bytes, $precision = 2) {
|
||||
$units = array('B', 'KB', 'MB', 'GB', 'TB');
|
||||
|
||||
$bytes = max($bytes, 0);
|
||||
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
||||
$pow = min($pow, count($units) - 1);
|
||||
|
||||
// Uncomment one of the following alternatives
|
||||
$bytes /= pow(1024, $pow);
|
||||
// $bytes /= (1 << (10 * $pow));
|
||||
|
||||
return round($bytes, $precision) . ' ' . $units[$pow] . 'ps';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Dokuwiki implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#9d7056';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/dokuwiki.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Duplicati implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2c3744';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/duplicati.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Emby implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#222';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/emby.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Flood implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '##00D091';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/Flood.png';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class FreshRSS implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#003B73';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/freshrss.png';
|
||||
}
|
||||
}
|
||||
5
app/SupportedApps/Ghost/Ghost.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php namespace App\SupportedApps\Ghost;
|
||||
|
||||
class Ghost extends \App\SupportedApps {
|
||||
|
||||
}
|
||||
10
app/SupportedApps/Ghost/app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"appid": "c4745785181de931cfd5bd79294cb1687d82aea9",
|
||||
"name": "Ghost",
|
||||
"website": "https://github.com/tryghost/ghost",
|
||||
"license": "MIT License",
|
||||
"description": "Fiercely independent, professional publishing. A fully open source, powerful platform for building and running modern publications, we power serious blogs, magazines and journalism from DuckDuckGo to OpenAI & Sky News.",
|
||||
"enhanced": false,
|
||||
"tile_background": "light",
|
||||
"icon": "ghost.png"
|
||||
}
|
||||
BIN
app/SupportedApps/Ghost/ghost.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Gitea implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#585e52';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/gitea.png';
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Glances implements Contracts\Applications {
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2c363f';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/glances.png';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Grafana implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#a56e4d';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/grafana.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Graylog implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#158';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/graylog.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Headphones implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#185';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/headphones.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class HomeAssistant implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#073c52';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/homeassistant.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Jackett implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#484814';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/jackett.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Jdownloader implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2b494f';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/jdownloader.png';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class Krusader implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#5A5';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/krusader.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Lidarr implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#183c18';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/lidarr.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Mailcow implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#161b1f';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/mailcow.svg';
|
||||
}
|
||||
}
|
||||
5
app/SupportedApps/MailcowSOGo/MailcowSOGo.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php namespace App\SupportedApps\MailcowSOGo;
|
||||
|
||||
class MailcowSOGo extends \App\SupportedApps {
|
||||
|
||||
}
|
||||
10
app/SupportedApps/MailcowSOGo/app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"appid": "1ec48781d2c87a9e6dc9ee99e5eff0ab5958df09",
|
||||
"name": "Mailcow - SOGo",
|
||||
"website": "https://sogo.nu/",
|
||||
"license": "GNU GPL/LGPL v2 and above",
|
||||
"description": "SOGo is a fully supported and trusted groupware server with a focus on scalability and open standards.\r\n\r\nPart of the Mailcow stack.",
|
||||
"enhanced": false,
|
||||
"tile_background": "dark",
|
||||
"icon": "mailcowsogo.svg"
|
||||
}
|
||||
3
app/SupportedApps/MailcowSOGo/mailcowsogo.svg
Normal file
|
After Width: | Height: | Size: 10 KiB |
5
app/SupportedApps/Mattermost/Mattermost.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php namespace App\SupportedApps\Mattermost;
|
||||
|
||||
class Mattermost extends \App\SupportedApps {
|
||||
|
||||
}
|
||||
10
app/SupportedApps/Mattermost/app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"appid": "b3e1424fb69ca08481b03ad9d81e95488421997f",
|
||||
"name": "Mattermost",
|
||||
"website": "https://mattermost.com/",
|
||||
"license": "MIT License",
|
||||
"description": "Mattermost provides high trust collaboration and messaging solutions through an open source, community-powered approach. Enjoy all the productivity benefits of workplace messaging across web, mobile and PC, with unlimited archiving, search and integrations within IT-controlled private environments in public clouds, including AWS and Azure, as well as on-premise in private clouds and virtual or physical servers.",
|
||||
"enhanced": false,
|
||||
"tile_background": "light",
|
||||
"icon": "mattermost.png"
|
||||
}
|
||||
BIN
app/SupportedApps/Mattermost/mattermost.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
5
app/SupportedApps/MayanEDMS/MayanEDMS.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php namespace App\SupportedApps\MayanEDMS;
|
||||
|
||||
class MayanEDMS extends \App\SupportedApps {
|
||||
|
||||
}
|
||||
10
app/SupportedApps/MayanEDMS/app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"appid": "6b9e062ff02ea610df64e9b0eca1c973faf1b51d",
|
||||
"name": "Mayan EDMS",
|
||||
"website": "https://github.com/tryghost/ghost",
|
||||
"license": "Apache License 2.0",
|
||||
"description": "Mayan EDMS is an open-source document management system. Its main purpose is to store, introspect, and categorize files, with a strong emphasis on preserving the contextual and business information of documents. It can also OCR, preview, label, sign, send, and receive thoses files. Other features of interest are its workflow system, role based access control, and REST API.",
|
||||
"enhanced": false,
|
||||
"tile_background": "light",
|
||||
"icon": "mayanedms.png"
|
||||
}
|
||||
BIN
app/SupportedApps/MayanEDMS/mayanedms.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Mcmyadmin implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#30404b';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/mcmyadmin.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Medusa implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#4b5e55';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/medusa.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Monica implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#fafbfc';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/monica.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class MusicBrainz implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#a0a';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/musicbrainz.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Mylar implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#aa0';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/mylar.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Netdata implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#543737';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/netdata.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Nextcloud implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#0e2c3e';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/nextcloud.png';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class NowShowing implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#690000';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/nowshowing.png';
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Nzbget implements Contracts\Applications, Contracts\Livestats {
|
||||
|
||||
public $config;
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#253827';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/nzbget.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'nzbget';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('status');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo 'Successfully connected to the API';
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'inactive';
|
||||
$res = $this->buildRequest('status');
|
||||
$data = json_decode($res->getBody());
|
||||
//$data->result->RemainingSizeMB = '10000000';
|
||||
//$data->result->DownloadRate = '100000000';
|
||||
if($data) {
|
||||
$size = $data->result->RemainingSizeMB;
|
||||
$rate = $data->result->DownloadRate;
|
||||
$queue_size = format_bytes($size*1000*1000, false, ' <span>', '</span>');
|
||||
$current_speed = format_bytes($rate, false, ' <span>');
|
||||
|
||||
$active = ($size > 0 || $rate > 0) ? 'active' : 'inactive';
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Queue</span><strong>'.$queue_size.'</strong></li>
|
||||
<li><span class="title">Speed</span><strong>'.$current_speed.'/s</span></strong></li>
|
||||
</ul>
|
||||
';
|
||||
}
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$username = $config->username;
|
||||
$password = $config->password;
|
||||
|
||||
$rebuild_url = str_replace('http://', 'http://'.$username.':'.$password.'@', $url);
|
||||
$rebuild_url = str_replace('https://', 'https://'.$username.':'.$password.'@', $rebuild_url);
|
||||
$rebuild_url = rtrim($rebuild_url, '/');
|
||||
|
||||
|
||||
$api_url = $rebuild_url.'/jsonrpc/'.$endpoint;
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
45
app/SupportedApps/Nzbget/Nzbget.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php namespace App\SupportedApps\Nzbget;
|
||||
|
||||
class Nzbget extends \App\SupportedApps implements \App\EnhancedApps {
|
||||
|
||||
public $config;
|
||||
|
||||
public function test()
|
||||
{
|
||||
$test = parent::appTest($this->url('status'));
|
||||
echo $test->status;
|
||||
}
|
||||
|
||||
public function livestats()
|
||||
{
|
||||
$status = 'inactive';
|
||||
$res = parent::execute($this->url('status'));
|
||||
$details = json_decode($res->getBody());
|
||||
|
||||
$data = [];
|
||||
|
||||
if($details) {
|
||||
$size = $details->result->RemainingSizeMB;
|
||||
$rate = $details->result->DownloadRate;
|
||||
$data['queue_size'] = format_bytes($size*1000*1000, false, ' <span>', '</span>');
|
||||
$data['current_speed'] = format_bytes($rate, false, ' <span>');
|
||||
$status = ($size > 0 || $rate > 0) ? 'active' : 'inactive';
|
||||
}
|
||||
|
||||
return parent::getLiveStats($status, $data);
|
||||
|
||||
}
|
||||
|
||||
public function url($endpoint)
|
||||
{
|
||||
$api_url = parent::normaliseurl($this->config->url);
|
||||
$username = $this->config->username;
|
||||
$password = $this->config->password;
|
||||
$rebuild_url = str_replace('http://', 'http://'.$username.':'.$password.'@', $api_url);
|
||||
$rebuild_url = str_replace('https://', 'https://'.$username.':'.$password.'@', $rebuild_url);
|
||||
$rebuild_url = rtrim($rebuild_url, '/');
|
||||
|
||||
$api_url = $rebuild_url.'/jsonrpc/'.$endpoint;
|
||||
return $api_url;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Nzbhydra implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#53644d';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/nzbhydra.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Ombi implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#150f09';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/ombi.png';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class OpenMediaVault implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#5AF';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/openmediavault.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Openhab implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2b2525';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/openhab.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Opnsense implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#211914';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/opnsense.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Pfsense implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#243699';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/pfsense.png';
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Pihole implements Contracts\Applications, Contracts\Livestats {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#352222';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/pihole.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
return 'pihole';
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest();
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo 'Successfully connected to the API';
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$res = $this->buildRequest();
|
||||
$data = json_decode($res->getBody());
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Domains<br />Blocked</span><strong>'.$data->domains_being_blocked.'</strong></li>
|
||||
<li><span class="title">Blocked<br />Today</span><strong>'.$data->ads_blocked_today.'</span></strong></li>
|
||||
</ul>
|
||||
';
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
|
||||
public function buildRequest()
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api.php';
|
||||
//die( $api_url.' --- ');
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Plex implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#222';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/plex.png';
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Plexpy implements Contracts\Applications, Contracts\Livestats {
|
||||
|
||||
public $config;
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2d2208';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/plexpy.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'plexpy';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('arnold');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
if(isset($data->error) && !empty($data->error)) {
|
||||
echo 'Failed: '.$data->error;
|
||||
} else {
|
||||
echo 'Successfully connected to the API';
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$res = $this->buildRequest('get_activity');
|
||||
$data = json_decode($res->getBody());
|
||||
$stream_count = $data->response->data->stream_count;
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Stream Count</span><strong>'.$stream_count.'</strong></li>
|
||||
</ul>
|
||||
';
|
||||
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$apikey = $config->apikey;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api/v2?apikey='.$apikey.'&cmd='.$endpoint;
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Plexrequests implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#3c2d1c';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/plexrequests.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Portainer implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#283f44';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/portainer.png';
|
||||
}
|
||||
}
|
||||
5
app/SupportedApps/Privatebin/Privatebin.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php namespace App\SupportedApps\Privatebin;
|
||||
|
||||
class Privatebin extends \App\SupportedApps {
|
||||
|
||||
}
|
||||
10
app/SupportedApps/Privatebin/app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"appid": "87ecbead58e42b5ab9e1a92ccc0b42075f4fba91",
|
||||
"name": "Privatebin",
|
||||
"website": "https://privatebin.info/",
|
||||
"license": "zlib/libpng License with Acknowledgement",
|
||||
"description": "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data.\r\n\r\nData is encrypted and decrypted in the browser using 256bit AES in Galois Counter mode.",
|
||||
"enhanced": false,
|
||||
"tile_background": "light",
|
||||
"icon": "privatebin.png"
|
||||
}
|
||||
BIN
app/SupportedApps/Privatebin/privatebin.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
@@ -1,80 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Proxmox implements Contracts\Applications, Contracts\Livestats {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#542e0a';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/proxmox.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
//return 'proxmox';
|
||||
return null;
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
/*$res = $this->buildRequest();
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo 'Successfully connected to the API';
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
/*
|
||||
$output = '';
|
||||
$res = $this->buildRequest();
|
||||
$data = json_decode($res->getBody());
|
||||
|
||||
$output = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Domains<br />Blocked</span><strong>'.$data->domains_being_blocked.'</strong></li>
|
||||
<li><span class="title">Blocked<br />Today</span><strong>'.$data->ads_blocked_today.'</span></strong></li>
|
||||
</ul>
|
||||
';
|
||||
return $output;
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public function buildRequest($endpoint='')
|
||||
{
|
||||
$config = $this->config;
|
||||
|
||||
$username = $config->username;
|
||||
$password = $config->password;
|
||||
|
||||
$url = $config->url;
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api2/json/'.$endpoint.'?username='.$username.'&password='.$password;
|
||||
//die( $api_url.' --- ');
|
||||
|
||||
$client = new Client(['http_errors' => false, 'verify' => false ]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Radarr implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#3e3726';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/radarr.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Rancher implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#78c9cf';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/rancher.png';
|
||||
}
|
||||
}
|
||||
5
app/SupportedApps/Rspamd/Rspamd.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php namespace App\SupportedApps\Rspamd;
|
||||
|
||||
class Rspamd extends \App\SupportedApps {
|
||||
|
||||
}
|
||||
10
app/SupportedApps/Rspamd/app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"appid": "5876529d5d47f91c435d9230576044bc4cad8547",
|
||||
"name": "Rspamd",
|
||||
"website": "https://rspamd.com/",
|
||||
"license": "Apache 2.0",
|
||||
"description": "Fast, free and open-source spam filtering system.",
|
||||
"enhanced": false,
|
||||
"tile_background": "dark",
|
||||
"icon": "rspamd.png"
|
||||
}
|
||||
BIN
app/SupportedApps/Rspamd/rspamd.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
@@ -1,95 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Runeaudio implements Contracts\Applications, Contracts\Livestats {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#05A';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/runeaudio.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
return 'runeaudio';
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('status');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo 'Successfully connected to the API';
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$output = '';
|
||||
$active = 'active';
|
||||
$artist = '';
|
||||
$song_title = '';
|
||||
$res = $this->buildRequest('currentsong');
|
||||
$array = explode("\n", $res->getBody());
|
||||
foreach($array as $item) {
|
||||
$item_array = explode(": ", $item);
|
||||
if ($item_array[0] == 'Artist') {
|
||||
$artist = $item_array[1];
|
||||
} elseif ($item_array[0] == 'Title') {
|
||||
$song_title = $item_array[1];
|
||||
}
|
||||
}
|
||||
|
||||
$output = '<ul class="livestats">';
|
||||
|
||||
if (strlen($artist) > 12) {
|
||||
$output = $output.'<li><span class="title-marquee"><span>'.$artist.'</span></span></li>';
|
||||
} else {
|
||||
$output = $output.'<li><span class="title">'.$artist.'</span></li>';
|
||||
}
|
||||
|
||||
$output = $output.'</ul><ul class="livestats">';
|
||||
|
||||
if (strlen($song_title) > 12) {
|
||||
$output = $output.'<li><span class="title-marquee"><span>'.$song_title.'</span></span></li>';
|
||||
} else {
|
||||
$output = $output.'<li><span class="title">'.$song_title.'</span></li>';
|
||||
}
|
||||
|
||||
$output = $output.'</ul>';
|
||||
|
||||
return json_encode(['status' => $active, 'html' => $output]);
|
||||
}
|
||||
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/command/?cmd='.$endpoint;
|
||||
//die( $api_url.' --- ');
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
5
app/SupportedApps/SOGo/SOGo.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php namespace App\SupportedApps\SOGo;
|
||||
|
||||
class SOGo extends \App\SupportedApps {
|
||||
|
||||
}
|
||||
10
app/SupportedApps/SOGo/app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"appid": "d143b3a76b72591495655c5257c7523456bdd736",
|
||||
"name": "SOGo",
|
||||
"website": "https://sogo.nu/",
|
||||
"license": "GNU GPL/LGPL v2 and above",
|
||||
"description": "SOGo is a fully supported and trusted groupware server with a focus on scalability and open standards.",
|
||||
"enhanced": false,
|
||||
"tile_background": "light",
|
||||
"icon": "sogo.svg"
|
||||
}
|
||||
11
app/SupportedApps/SOGo/sogo.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="792px" height="464px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M643.711,144.938C633.849,144.938 626.847,137.721 626.847,128.035C626.847,118.341 633.849,111.123 643.711,111.123C653.65,111.123 660.652,118.341 660.652,128.035C660.652,137.721 653.65,144.938 643.711,144.938ZM643.681,94.5835C624.154,94.5835 610.288,108.861 610.288,128.035C610.288,147.2 624.154,161.478 643.681,161.478C663.335,161.478 677.202,147.2 677.202,128.035C677.202,108.861 663.335,94.5835 643.681,94.5835ZM643.652,178.811C614.019,178.811 592.965,157.13 592.965,128.035C592.965,98.9315 614.019,77.2602 643.652,77.2602C673.48,77.2602 694.525,98.9315 694.525,128.035C694.525,157.13 673.48,178.811 643.652,178.811ZM643.613,58.4876C603.032,58.4876 574.212,88.1791 574.212,128.035C574.212,167.882 603.032,197.564 643.613,197.564C684.458,197.564 713.288,167.882 713.288,128.035C713.288,88.1791 684.458,58.4876 643.613,58.4876ZM157.492,182.836L136.653,177.871C117.684,173.513 108.048,168.538 108.048,154.858C108.048,139.307 123.903,133.079 138.21,133.079C152.752,133.079 163.377,140.345 169.635,151.656C169.654,151.704 169.684,151.753 169.723,151.812C169.85,152.057 169.997,152.292 170.124,152.537L170.154,152.517C172.122,155.494 175.432,157.482 178.997,157.482C185.068,157.482 189.465,153.095 189.465,147.024C189.465,144.703 188.966,142.245 187.879,140.394C177.205,122.248 159.607,114.424 139.454,114.424C112.093,114.424 85.6524,128.104 85.6524,158.266C85.6524,185.95 113.023,194.038 122.972,196.516L142.871,201.187C158.109,204.918 170.546,209.903 170.546,224.504C170.546,241.298 153.134,248.77 136.34,248.77C119.241,248.77 106.579,240.025 97.8541,227.118L97.8443,227.118C95.9054,224.288 92.899,222.3 89.2169,222.3C83.2826,222.3 78.5037,227.177 78.7191,233.102C78.8171,235.52 79.6201,237.567 80.854,239.32C94.5246,259.777 114.296,267.425 136.34,267.425C164.641,267.425 192.942,254.362 192.942,222.643C192.942,202.127 177.704,187.507 157.492,182.836ZM296.617,248.682C263.038,248.682 241.886,223.495 241.886,190.846C241.886,158.187 263.038,133 296.617,133C330.52,133 351.662,158.187 351.662,190.846C351.662,223.495 330.52,248.682 296.617,248.682ZM296.617,114.345C251.531,114.345 219.499,146.994 219.499,190.846C219.499,234.688 251.531,267.337 296.617,267.337C342.016,267.337 374.048,234.688 374.048,190.846C374.048,146.994 342.016,114.345 296.617,114.345ZM514.985,232.818C514.221,233.552 513.448,234.277 512.606,234.972C511.509,235.981 510.236,237.068 508.786,238.155C500.032,244.491 488.976,248.163 476.049,248.163C442.46,248.163 421.318,222.976 421.318,190.327C421.318,157.668 442.46,132.481 476.049,132.481C509.942,132.481 531.084,157.668 531.084,190.327C531.084,207.376 525.316,222.369 514.985,232.818ZM464.797,315.733C467.304,315.733 469.899,315.566 472.592,315.233C477.567,314.607 482.101,314.332 486.204,314.332C505.281,314.44 514.995,319.983 520.851,326.387C526.697,332.831 528.95,341.566 528.94,348.989C528.95,352.544 528.391,355.726 527.774,357.636C524.856,366.488 518.961,372.511 509.932,377.045C500.972,381.491 489.015,383.763 476.51,383.743C472.034,383.743 467.481,383.459 462.986,382.921C454.486,381.941 443.244,378.289 435.096,371.923C430.993,368.751 427.614,364.99 425.235,360.534C422.875,356.059 421.406,350.869 421.396,344.23L421.396,343.495C421.651,331.254 427.272,323.126 433.431,317.221C436.477,314.342 439.611,312.198 441.892,310.836C442.255,310.621 442.597,310.425 442.911,310.249C448.953,313.823 456.454,315.762 464.797,315.733ZM476.049,113.826C430.964,113.826 398.922,146.475 398.922,190.327C398.922,219.96 413.562,244.461 436.976,257.241C436.663,257.554 436.359,257.877 436.066,258.2C430.014,264.83 426.919,273.32 426.909,281.909C426.9,285.698 427.526,289.586 428.868,293.307C425.832,295.246 422.209,297.9 418.497,301.386C409.547,309.72 399.921,323.733 399.637,343.123C399.627,343.573 399.627,343.946 399.627,344.23C399.617,354.218 401.987,363.227 406.031,370.778C412.113,382.147 421.582,390.059 431.355,395.338C441.187,400.626 451.44,403.436 460.381,404.533C465.708,405.17 471.114,405.512 476.51,405.512C491.532,405.493 506.514,402.957 519.549,396.572C532.524,390.285 543.678,379.464 548.496,364.285C549.926,359.771 550.689,354.649 550.709,348.989C550.689,337.492 547.389,323.449 537.058,311.855C526.727,300.221 509.638,292.455 486.204,292.563C481.112,292.563 475.687,292.916 469.919,293.63C468.058,293.856 466.354,293.963 464.797,293.963C457.619,293.915 454.016,291.927 451.871,289.899C449.756,287.833 448.698,285.101 448.669,281.909C448.659,278.657 449.942,275.24 452.106,272.909C454.319,270.598 457.071,269.031 461.869,268.972C462.3,268.972 462.761,268.982 463.231,269.021C466.306,269.237 469.292,269.345 472.191,269.345C496.173,269.393 514.212,261.961 526.482,251.737C538.791,241.514 545.294,229.077 548.369,219.255L548.329,219.245C551.669,210.422 553.48,200.688 553.48,190.327C553.48,146.475 521.448,113.826 476.049,113.826Z" style="fill:rgb(80,189,55);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
@@ -1,89 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Sabnzbd implements Contracts\Applications, Contracts\Livestats {
|
||||
|
||||
public $config;
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#3e3924';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/sabnzbd.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'sabnzbd';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('queue');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
if(isset($data->error) && !empty($data->error)) {
|
||||
echo 'Failed: '.$data->error;
|
||||
} else {
|
||||
echo 'Successfully connected to the API';
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'inactive';
|
||||
$res = $this->buildRequest('queue');
|
||||
$data = json_decode($res->getBody());
|
||||
//$data->result->RemainingSizeMB = '10000000';
|
||||
//$data->result->DownloadRate = '100000000';
|
||||
if($data) {
|
||||
$size = $data->queue->mbleft;
|
||||
$rate = $data->queue->kbpersec;
|
||||
$queue_size = format_bytes($size*1000*1000, false, ' <span>', '</span>');
|
||||
$current_speed = format_bytes($rate*1000, false, ' <span>');
|
||||
|
||||
$active = ($size > 0 || $rate > 0) ? 'active' : 'inactive';
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Queue</span><strong>'.$queue_size.'</strong></li>
|
||||
<li><span class="title">Speed</span><strong>'.$current_speed.'/s</span></strong></li>
|
||||
</ul>
|
||||
';
|
||||
}
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$apikey = $config->apikey;
|
||||
|
||||
//print_r($config);
|
||||
//die();
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api?output=json&apikey='.$apikey.'&mode='.$endpoint;
|
||||
//die( $api_url.' --- ');
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Sickrage implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#6185a6';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/sickrage.png';
|
||||
}
|
||||
}
|
||||
5
app/SupportedApps/Snibox/Snibox.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php namespace App\SupportedApps\Snibox;
|
||||
|
||||
class Snibox extends \App\SupportedApps {
|
||||
|
||||
}
|
||||
10
app/SupportedApps/Snibox/app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"appid": "6c050d5bdf522fa20599560ff0f6b74e7dcd97a8",
|
||||
"name": "Snibox",
|
||||
"website": "https://github.com/snibox/snibox",
|
||||
"license": "MIT License",
|
||||
"description": "Snibox is a self-hosted, single-user (for now) snippet manager. Developed to collect and organize code snippets. Supports various programming languages, markdown, plain text.",
|
||||
"enhanced": false,
|
||||
"tile_background": "dark",
|
||||
"icon": "snibox.png"
|
||||
}
|
||||
BIN
app/SupportedApps/Snibox/snibox.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Sonarr implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#163740';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/sonarr.png';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class Syncthing implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#888';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/syncthing.png';
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class TVheadend implements Contracts\Applications {
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#006080';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/tvheadend.png';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Tautulli implements Contracts\Applications, Contracts\Livestats {
|
||||
|
||||
public $config;
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2d2208';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/tautulli.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'tautulli';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('arnold');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
if(isset($data->error) && !empty($data->error)) {
|
||||
echo 'Failed: '.$data->error;
|
||||
} else {
|
||||
echo 'Successfully connected to the API';
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$res = $this->buildRequest('get_activity');
|
||||
$data = json_decode($res->getBody());
|
||||
$stream_count = $data->response->data->stream_count;
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Stream Count</span><strong>'.$stream_count.'</strong></li>
|
||||
</ul>
|
||||
';
|
||||
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$apikey = $config->apikey;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api/v2?apikey='.$apikey.'&cmd='.$endpoint;
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
class Traefik implements Contracts\Applications, Contracts\Livestats
|
||||
{
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#28434a';
|
||||
}
|
||||
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/traefik.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
return 'traefik';
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
echo 'Traefik connection failed';
|
||||
return;
|
||||
}
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
echo "Successfully connected with status: ".$data->result."\n";
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and includes the port';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'inactive';
|
||||
$res = $this->sendRequest();
|
||||
$data = json_decode($res->getBody());
|
||||
if ($data) {
|
||||
$avg_response_time = $data->average_response_time_sec;
|
||||
$time = $avg_response_time*1000;
|
||||
$time_output = number_format($time, 2);
|
||||
$active = ($time > 0) ? 'active' : 'inactive';
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Avg. Response Time</span><sub><i class="fas fa-heartbeat"></i> '.$time_output.' ms</sub></li>
|
||||
</ul>
|
||||
';
|
||||
}
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
|
||||
public function sendRequest()
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
$api_url = $url.'/health';
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class Transmission implements Contracts\Applications, Contracts\Livestats
|
||||
{
|
||||
|
||||
private $_client;
|
||||
private $_clientOptions = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$body = array();
|
||||
$body["method"] = "torrent-get";
|
||||
$body["arguments"] = array("fields" => ["percentDone","status","rateDownload","rateUpload"]);
|
||||
$this->_client = new Client(
|
||||
['http_errors' => false,
|
||||
'timeout' => 10,
|
||||
'body' => json_encode($body)]
|
||||
);
|
||||
}
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#950003';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/transmission.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'transmission';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
echo 'Transmission connection failed';
|
||||
return;
|
||||
}
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
echo "Successfully connected with status: ".$data->result."\n";
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and includes the port';
|
||||
break;
|
||||
case 409:
|
||||
echo 'Failed: Incorrect session id';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
Log::debug('Transmission connection failed');
|
||||
return '';
|
||||
}
|
||||
$data = json_decode($res->getBody());
|
||||
if (! isset($data->arguments)) {
|
||||
Log::debug('Failed to fetch data from Transmission');
|
||||
return '';
|
||||
}
|
||||
$torrents = $data->arguments->torrents;
|
||||
$torrentCount = count($torrents);
|
||||
$rateDownload = $rateUpload = $completedTorrents = 0;
|
||||
foreach ($torrents as $thisTorrent) {
|
||||
$rateDownload += $thisTorrent->rateDownload;
|
||||
$rateUpload += $thisTorrent->rateUpload;
|
||||
if ($thisTorrent->percentDone == 1) {
|
||||
$completedTorrents += 1;
|
||||
}
|
||||
}
|
||||
if ($torrentCount - $completedTorrents == 0) {
|
||||
// Don't poll as frequently if we don't have any active torrents
|
||||
$active = 'inactive';
|
||||
}
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Done</span><sub>'.$completedTorrents.' / '.$torrentCount.'</sub></li>
|
||||
<li><span class="title">Down</span><sub>'.format_bytes($rateDownload).'</sub></li>
|
||||
<li><span class="title">Up</span><sub>'.format_bytes($rateUpload).'</sub></li>
|
||||
</ul>
|
||||
';
|
||||
return json_encode(['status' => $active, 'html' => $html]);;
|
||||
}
|
||||
|
||||
private function sendRequest()
|
||||
{
|
||||
$optionsSet = $this->setClientOptions();
|
||||
if (! $optionsSet) {
|
||||
// Pass the failed response back up the chain
|
||||
return null;
|
||||
}
|
||||
$res = $this->torrentGet();
|
||||
if ($res->getStatusCode() == 409) {
|
||||
$this->setClientOptions();
|
||||
$res = $this->torrentGet();
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
private function torrentGet()
|
||||
{
|
||||
$res = null;
|
||||
try{
|
||||
$res = $this->_client->request(
|
||||
'POST',
|
||||
$this->getApiUrl(),
|
||||
$this->_clientOptions
|
||||
);
|
||||
}catch(\GuzzleHttp\Exception\BadResponseException $e){
|
||||
Log::error("Connection to {$e->getRequest()->getUrl()} failed");
|
||||
Log::debug($e->getMessage());
|
||||
$res = $e->getRequest();
|
||||
}catch(\GuzzleHttp\Exception\ConnectException $e) {
|
||||
Log::error("Transmission connection refused");
|
||||
Log::debug($e->getMessage());
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
private function setClientOptions()
|
||||
{
|
||||
if ($this->config->username != '' || $this->config->password != '') {
|
||||
$this->_clientOptions = ['auth'=> [$this->config->username, $this->config->password, 'Basic']];
|
||||
}
|
||||
try{
|
||||
$res = $this->_client->request('HEAD', $this->getApiUrl(), $this->_clientOptions);
|
||||
$xtId = $res->getHeaderLine('X-Transmission-Session-Id');
|
||||
if ($xtId != null) {
|
||||
$this->_clientOptions['headers'] = ['X-Transmission-Session-Id' => $xtId];
|
||||
} else {
|
||||
Log::error("Unable to get Transmission session information");
|
||||
Log::debug("Status Code: ".$res->getStatusCode());
|
||||
}
|
||||
}catch(\GuzzleHttp\Exception\ConnectException $e){
|
||||
Log::error("Failed connection to Transmission");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getApiUrl()
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
$api_url = $url.'/transmission/rpc';
|
||||
|
||||
return $api_url;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Ttrss implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#9d704c';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/tt-rss.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Unifi implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#363840';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/unifi.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Unraid implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#A12624';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/unraid.png';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Virtualmin implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#161b1f';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/virtualmin.svg';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class Watcher3 implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#500';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/watcher3.png';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class WebTools implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#555';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/webtools.png';
|
||||
}
|
||||
}
|
||||