mirror of
https://koodu.h-i.works/projects/thebadspace
synced 2025-06-30 16:07:37 -05:00
Compare commits
4 Commits
a0.05
...
alcapurria
Author | SHA1 | Date | |
---|---|---|---|
971e744057 | |||
faef26e528 | |||
1f65756bdd | |||
a0b4f1759c |
@ -1,9 +1,7 @@
|
||||
# The Bad Space
|
||||
|
||||
A searcable catalog of the worst places on the web.
|
||||
A searchable catalog of the worst places on the web.
|
||||
|
||||
More features incoming
|
||||
|
||||
An Hi Project =)
|
||||
|
||||
|
||||
|
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Mail\LocationAppeal;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use App\Models\Appeal;
|
||||
|
||||
class AppealController extends Controller
|
||||
{
|
||||
/**
|
||||
* Send appeal request
|
||||
*/
|
||||
public function sendAppeal(Request $request)
|
||||
{
|
||||
//$order = Order::findOrFail($request->order_id);
|
||||
$token = csrf_token();
|
||||
|
||||
if ($request->h1 != '' || $request->question != 2) {
|
||||
return back()->withErrors([
|
||||
'error' => 'Invalid Request',
|
||||
]);
|
||||
} else {
|
||||
$check = Appeal::where("location", $request->location)->first();
|
||||
|
||||
if ($check) {
|
||||
return back()->withErrors([
|
||||
'error' => 'Appeal already in process for Location',
|
||||
]);
|
||||
} else {
|
||||
$clean = $request->validate([
|
||||
'location' => ['required'],
|
||||
'local_admin' => ['required'],
|
||||
'local_sponsor' => ['required'],
|
||||
'appeal_description' => ['required'],
|
||||
]);
|
||||
|
||||
$new = Appeal::create([
|
||||
'uuid' => Uuid::uuid4(),
|
||||
'location' => $request->location,
|
||||
'location_admin' => $request->location_admin,
|
||||
'sponsor' => $request->sponsor,
|
||||
'description' => $request->appeal_description,
|
||||
'approved' => false,
|
||||
'reviewed' => false,
|
||||
]);
|
||||
Mail::to(env('TBS_ADMIN_EMAIL'))->send(new LocationAppeal($request->location, $request->sponsor));
|
||||
}
|
||||
//return redirect('/appeals');
|
||||
return back()->with('message', "Appeal Filed");
|
||||
};
|
||||
}
|
||||
}
|
@ -2,81 +2,34 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Repositories\LocationRepository;
|
||||
use App\Models\Source;
|
||||
|
||||
class ExportController extends Controller
|
||||
{
|
||||
protected $locationRepository;
|
||||
|
||||
public function __construct(LocationRepository $locationRepository)
|
||||
{
|
||||
$this->locationRepository = $locationRepository;
|
||||
}
|
||||
|
||||
public function exportIndex()
|
||||
{
|
||||
$heatArray = [90, 80, 70, 60, 50, 40, 30, 20];
|
||||
$sources = Source::where("active", true)->get();
|
||||
$locations = $this->locationRepository->getActiveLocations();
|
||||
$list = [];
|
||||
foreach ($heatArray as $rating) {
|
||||
$count = 0;
|
||||
foreach ($locations as $location) {
|
||||
$rate = $location->actions_count / count($sources);
|
||||
if ($rate * 100 >= $rating) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
array_push($list, ["heatRating" => $rating, "ratingCount" => $count]);
|
||||
}
|
||||
return view('front.exports', [
|
||||
'title' => "Exports",
|
||||
'list' => $list
|
||||
]);
|
||||
}
|
||||
|
||||
//
|
||||
public function exportCSV($type, $percent)
|
||||
public function exportCSV()
|
||||
{
|
||||
$columns = [];
|
||||
$list = [];
|
||||
/*
|
||||
$columns = [
|
||||
'id',
|
||||
'product_name',
|
||||
'product_url',
|
||||
'price',
|
||||
'category'
|
||||
];
|
||||
|
||||
$locations = $this->locationRepository->getActiveLocations();
|
||||
$sources = Source::where("active", true)->get();
|
||||
if ($type == 'mastodon') {
|
||||
$columns = [
|
||||
'domain',
|
||||
'severity',
|
||||
'public_comment',
|
||||
'reject_media',
|
||||
'reject_reports',
|
||||
'obfuscate',
|
||||
];
|
||||
};
|
||||
|
||||
foreach ($locations as $location) {
|
||||
$rate = $location->actions_count / count($sources);
|
||||
if ($rate * 100 >= $percent) {
|
||||
if ($type == 'mastodon') {
|
||||
//comman break teh CSV so just take them out
|
||||
$comments = str_replace(",", ";", $location->description);
|
||||
|
||||
//remove extra white space
|
||||
$comments = str_replace(["\n\r", "\n", "\r"], " ", $comments);
|
||||
$comments = str_replace(['"', "'"], "", $comments);
|
||||
//add to the export list
|
||||
array_push($list, [$location->url, $location->rating, $comments, "FALSE", "FALSE", "FALSE"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$products = [
|
||||
[1, 'product 1', 'https://example.com/product-1', '9.99', 'category 1'],
|
||||
[2, 'product 2', 'https://example.com/product-2', '19.99', 'category 2'],
|
||||
[3, 'product 3', 'https://example.com/product-3', '29.99', 'category 3'],
|
||||
[4, 'product 4', 'https://example.com/product-4', '39.99', 'category 4'],
|
||||
];
|
||||
|
||||
header('Content-Type: text/csv');
|
||||
header('Content-Disposition: attachment; filename=' . $type . "-" . $percent);
|
||||
header('Content-Disposition: attachment; filename="products.csv"');
|
||||
|
||||
echo implode(',', $columns) . PHP_EOL;
|
||||
foreach ($list as $item) {
|
||||
echo implode(',', $item) . PHP_EOL;
|
||||
foreach ($products as $product) {
|
||||
echo implode(',', $product) . PHP_EOL;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -3,39 +3,50 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\Location;
|
||||
use App\Models\Source;
|
||||
use App\Repositories\LocationRepository;
|
||||
|
||||
class FrontIndexController extends Controller
|
||||
{
|
||||
protected $locationRepository;
|
||||
|
||||
public function __construct(LocationRepository $locationRepository)
|
||||
{
|
||||
$this->locationRepository = $locationRepository;
|
||||
}
|
||||
private $limit = 15;
|
||||
|
||||
public function start()
|
||||
{
|
||||
$locations = Location::where("active", true)->get();
|
||||
$count = count($locations);
|
||||
$recent = Location::where("active", true)
|
||||
->where('block_count', '>', 2)
|
||||
->limit(10)->orderByDesc('updated_at')->get();
|
||||
|
||||
//$result = DB::select("SELECT * FROM searchlocations('$terms')");
|
||||
|
||||
return view('front.index', [
|
||||
'count' => count($this->locationRepository->getActiveLocations()),
|
||||
'sources' => count(Source::where("active", true)->get()),
|
||||
'recent' => $this->locationRepository->getRecent(),
|
||||
'latest_date' => $this->locationRepository->getRecent()[0]->updated_at->format('Y M d'),
|
||||
'title' => "The Bad Space"
|
||||
'count' => $count,
|
||||
'recent' => $recent,
|
||||
'title' => "The Bad Space"
|
||||
]);
|
||||
}
|
||||
|
||||
public function indexSearch(Request $request)
|
||||
{
|
||||
$terms = $request->index_search;
|
||||
$rawSearch = $terms;
|
||||
$terms = str_replace(",", "", $terms);
|
||||
$terms = str_replace(" ", "|", $terms);
|
||||
$results = DB::select("SELECT * FROM searchlocations('$terms')");
|
||||
|
||||
$locations = Location::where("active", true)->get();
|
||||
$count = count($locations);
|
||||
$recent = Location::where("active", true)
|
||||
->where('block_count', '>', 2)
|
||||
->limit(10)->orderByDesc('updated_at')->get();
|
||||
|
||||
return view('front.index', [
|
||||
'count' => count($this->locationRepository->getActiveLocations()),
|
||||
'sources' => count(Source::where("active", true)->get()),
|
||||
'recent' => $this->locationRepository->getRecent(),
|
||||
'results' => $this->locationRepository->search($request),
|
||||
'terms' => $request->index_search,
|
||||
'latest_date' => $this->locationRepository->getRecent()[0]->updated_at->format('Y M d'),
|
||||
'title' => "Search Results",
|
||||
'count' => $count,
|
||||
'recent' => $recent,
|
||||
'title' => "The Bad Space",
|
||||
'results' => $results
|
||||
]);
|
||||
}
|
||||
|
||||
@ -48,43 +59,47 @@ class FrontIndexController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function appeals()
|
||||
{
|
||||
return view('front.appeals', [
|
||||
'title' => "LOCATION APPEALS",
|
||||
]);
|
||||
}
|
||||
|
||||
public function location(string $uuid = "1")
|
||||
{
|
||||
$location = $this->locationRepository->getLocation($uuid);
|
||||
$sources = Source::where("active", true)->get();
|
||||
$location = Location::where("uuid", $uuid)->first();
|
||||
$name = "NO LOCATION FOUND";
|
||||
if ($location) {
|
||||
$name = $location->name;
|
||||
}
|
||||
return view('front.location', [
|
||||
'title' => str_replace(".", " ", $name),
|
||||
'location' => $location,
|
||||
'actions' => $location->block_count + $location->silence_count,
|
||||
'sources_count' => count($sources),
|
||||
'images' => json_decode($location->images),
|
||||
'updated' => $location->updated_at->format('Y M d'),
|
||||
'title' => str_replace(".", " ", $name),
|
||||
'location' => $location,
|
||||
'images' => json_decode($location->images),
|
||||
'updated' => $location->updated_at->format('Y M d'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function listings(int $pageNum = 1)
|
||||
{
|
||||
$listing = $this->locationRepository->getPage($pageNum);
|
||||
$range = $pageNum * $this->limit - $this->limit;
|
||||
$active = Location::where("active", true)->where('block_count', '>', 2)->get();
|
||||
$locations = Location::where("active", true)->where('block_count', '>', 2)
|
||||
->limit($this->limit)->offset($range)->orderByDesc('id')->get();
|
||||
$pageCount = ceil(count($active) / $this->limit);
|
||||
|
||||
$next = $pageNum + 1;
|
||||
if ($next > $pageCount) {
|
||||
$next = 1;
|
||||
}
|
||||
|
||||
$prev = $pageNum - 1;
|
||||
|
||||
if ($prev <= 0) {
|
||||
$prev = $pageCount;
|
||||
}
|
||||
|
||||
return view('front.listing', [
|
||||
'title' => "Listings",
|
||||
'sources' => count(Source::where("active", true)->get()),
|
||||
"totalPages" => $listing[1],
|
||||
"prev" => $listing[2],
|
||||
"next" => $listing[3],
|
||||
"totalPages" => $pageCount,
|
||||
"prev" => $prev,
|
||||
"next" => $next,
|
||||
'pageNum' => $pageNum,
|
||||
'locations' => $listing[0]
|
||||
'locations' => $locations
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,17 @@ use Illuminate\Http\Request;
|
||||
use App\Models\Location;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use League\Csv\Reader;
|
||||
use App\Models\Source;
|
||||
|
||||
class LocationController extends Controller
|
||||
{
|
||||
//url to oli's unified tier 3 list
|
||||
private $three = 'https://codeberg.org/oliphant/blocklists/raw/branch/main/blocklists/_unified_tier3_blocklist.csv';
|
||||
|
||||
//url to oli's domain audit containin block counts per domain
|
||||
private $defed = 'https://codeberg.org/oliphant/blocklists/raw/branch/main/blocklists/other/domain_audit_file.csv';
|
||||
|
||||
public function addLocation(Request $request)
|
||||
{
|
||||
$fields = $request->validate([
|
||||
@ -38,59 +45,42 @@ class LocationController extends Controller
|
||||
return back()->with('message', 'New Location Added. Take a break!');
|
||||
} else {
|
||||
return back()->withErrors([
|
||||
'error' => 'Uh oh. There was an inssue',
|
||||
'error' => 'Uh oh. There was an issue.',
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
return back()->withErrors([
|
||||
'error' => 'All fields are required',
|
||||
'error' => 'All fields are required.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateLocations()
|
||||
{
|
||||
//$fresh = file($this->three);
|
||||
//$deny = Reader::createFromPath($fresh, "r");
|
||||
//$deny->setHeaderOffset(0);
|
||||
//$list = $deny->getRecords();
|
||||
//$recordCount = count($fresh);
|
||||
$duplicates = 0;
|
||||
$fresh = 0;
|
||||
$missing = [];
|
||||
// ['url' => "rage.love"],
|
||||
//['url' => "indiepocalypse.social"],
|
||||
|
||||
$unified = [];
|
||||
$cleanSources = [];
|
||||
$sources = Source::where("active", true)->get();
|
||||
|
||||
//checks source url to make sure they valid
|
||||
$unified = [];
|
||||
//$denycount = array_map('str_getcsv', file($this->defed));
|
||||
//$denylist = array_map('str_getcsv', file($this->three));
|
||||
$sources = Source::where("active", true)->get();
|
||||
foreach ($sources as $source) {
|
||||
if ($source->type == 'mastodon') {
|
||||
$url = 'https://' . $source->url;
|
||||
} else {
|
||||
$url = $source->url;
|
||||
}
|
||||
|
||||
if ($this->urlExists($url)) {
|
||||
array_push($cleanSources, [
|
||||
'url' => $source->url,
|
||||
'token' => $source->token,
|
||||
'type' => $source->type,
|
||||
'format' => $source->format]);
|
||||
} else {
|
||||
var_dump($url);
|
||||
array_push($missing, ['source' => $url]);
|
||||
}
|
||||
}
|
||||
|
||||
//valid source url get compiled for unified
|
||||
foreach ($cleanSources as $source) {
|
||||
//check url to make sure it's cool
|
||||
|
||||
//parsing for mastodon
|
||||
if ($source['type'] == 'mastodon') {
|
||||
if ($source->type == 'mastodon') {
|
||||
$result = [];
|
||||
if ($source['token'] == null) {
|
||||
$result = \Mastodon::domain('https://' . $source['url'])
|
||||
if ($source->token == null) {
|
||||
$result = \Mastodon::domain('https://' . $source->url)
|
||||
->get('/instance/domain_blocks');
|
||||
} else {
|
||||
$result = \Mastodon::domain('https://' . $source['url'])
|
||||
->token($source['token'])
|
||||
$result = \Mastodon::domain('https://' . $source->url)
|
||||
->token($source->token)
|
||||
->get('/instance/domain_blocks');
|
||||
}
|
||||
|
||||
@ -98,96 +88,39 @@ class LocationController extends Controller
|
||||
$index = array_search($item['domain'], array_column($unified, 'url'));
|
||||
if ($index) {
|
||||
//if there is a match, update the count
|
||||
if ($item['severity'] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$unified[$index]['block_count'];
|
||||
} else {
|
||||
++$unified[$index]['silence_count'];
|
||||
}
|
||||
++$unified[$index]['count'];
|
||||
} else {
|
||||
$silence = 0;
|
||||
$suspend = 0;
|
||||
if ($item['severity'] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$suspend;
|
||||
} else {
|
||||
++$silence;
|
||||
}
|
||||
array_push($unified, [
|
||||
'name' => $item['domain'],
|
||||
'url' => $item['domain'],
|
||||
'rating' => $item['severity'],
|
||||
'comment' => $item['comment'],
|
||||
'block_count' => $suspend,
|
||||
'silence_count' => $silence,
|
||||
'name' => $item['domain'],
|
||||
'url' => $item['domain'],
|
||||
'rating' => $item['severity'],
|
||||
'comment' => $item['comment'],
|
||||
'count' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
//parsing for custom csv
|
||||
if ($source['type'] == 'custom' && $source['format'] == 'csv') {
|
||||
$denylist = array_map('str_getcsv', file($source['url']));
|
||||
if ($source->type == 'custom' && $source->format == 'csv') {
|
||||
$denylist = array_map('str_getcsv', file($source->url));
|
||||
foreach ($denylist as $item) {
|
||||
$index = array_search($item[0], array_column($unified, 'url'));
|
||||
if ($index) {
|
||||
//if there is a match, update the count
|
||||
if ($item[1] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$unified[$index]['block_count'];
|
||||
} else {
|
||||
++$unified[$index]['silence_count'];
|
||||
}
|
||||
++$unified[$index]['count'];
|
||||
} else {
|
||||
$silence = 0;
|
||||
$suspend = 0;
|
||||
if ($item[1] == "suspend" || $item[1] == "defederate") {
|
||||
++$suspend;
|
||||
} else {
|
||||
++$silence;
|
||||
}
|
||||
array_push($unified, [
|
||||
'name' => $item[0],
|
||||
'url' => $item[0],
|
||||
'rating' => $item[1],
|
||||
'comment' => $item[2],
|
||||
'block_count' => $suspend,
|
||||
'silence_count' => $silence,
|
||||
'name' => $item[0],
|
||||
'url' => $item[0],
|
||||
'rating' => $item[1],
|
||||
'comment' => $item[2],
|
||||
'count' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: maintenance script to set locations to inactive if they haven't been updated
|
||||
// over 90 days
|
||||
|
||||
//$diff=date_diff($location->updated_at, new DateTime());
|
||||
//$days = $diff->format("%R%a days")
|
||||
|
||||
//$interval = $location->updated_at->diff(new DateTime());
|
||||
//$days = $interval->format("%a");
|
||||
|
||||
//get all locations and sort which are present in unified or not
|
||||
/*
|
||||
$sorted = [];
|
||||
$listed = 0;
|
||||
$notlisted = 0;
|
||||
foreach (Location::all() as $location) {
|
||||
if (array_search($location->url, array_column($unified, 'url'))) {
|
||||
++$listed;
|
||||
// locations present in unfied, so updated
|
||||
array_push($sorted, [
|
||||
'location' => $location,
|
||||
'listed' => true
|
||||
]);
|
||||
} else {
|
||||
++$notlisted;
|
||||
//locations not present
|
||||
array_push($sorted, [
|
||||
'location' => $location,
|
||||
'listed' => false
|
||||
]);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
//once the unified list is created, update current entries or create fresh ones
|
||||
|
||||
foreach ($unified as $item) {
|
||||
@ -196,14 +129,7 @@ class LocationController extends Controller
|
||||
++$duplicates;
|
||||
//update block count for existing item
|
||||
|
||||
$location->block_count = $item['block_count'];
|
||||
$location->silence_count = $item['silence_count'];
|
||||
|
||||
$location->actions_count = $item['block_count'] + $item['silence_count'];
|
||||
|
||||
if (($item['block_count'] + $item['silence_count']) < 2) {
|
||||
$location->active = false;
|
||||
}
|
||||
$location->block_count = $item['count'];
|
||||
|
||||
//replace null with empty array
|
||||
if ($location->images == null) {
|
||||
@ -214,50 +140,41 @@ class LocationController extends Controller
|
||||
// make new entries for instances not present
|
||||
++$fresh;
|
||||
$images = [];
|
||||
$rating = ($item['rating'] == 'defederate') ? 'suspend' : $item['rating'];
|
||||
|
||||
$status = true;
|
||||
if (($item['block_count'] + $item['silence_count']) < 2) {
|
||||
$status = false;
|
||||
}
|
||||
|
||||
$new = Location::create([
|
||||
'uuid' => Uuid::uuid4(),
|
||||
'name' => $item['url'],
|
||||
'url' => $item['url'],
|
||||
'description' => ($item['comment'] != null) ? $item['comment'] : "no description",
|
||||
'active' => $status,
|
||||
'rating' => $rating,
|
||||
'added_by' => 1,
|
||||
'tags' => 'poor moderation, hate speech',
|
||||
'images' => json_encode($images),
|
||||
'block_count' => $item['block_count'],
|
||||
'silence_count' => $item['silence_count'],
|
||||
'actions_cont' => $item['block_count'] + $item['silence_count']
|
||||
'uuid' => Uuid::uuid4(),
|
||||
'name' => $item['url'],
|
||||
'url' => $item['url'],
|
||||
'description' => ($item['comment'] != null) ? $item['comment'] : "No description provided.",
|
||||
'active' => true,
|
||||
'rating' => $item['rating'],
|
||||
'added_by' => 1,
|
||||
'tags' => 'poor moderation, hate speech',
|
||||
'images' => json_encode($images),
|
||||
'block_count' => $item['count'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
//TODO: Send update post to TBS social account
|
||||
|
||||
return back()->with('message', $duplicates . ' UPDATED - ' . $fresh . ' CREATED - ' . count($missing) . ' SOURCE(S) NOT CHECKED');
|
||||
}
|
||||
//$lookfor = '0sint.social';
|
||||
//$index = array_search($lookfor, array_column($unified, 'url'));
|
||||
//return back()->with('message', 'TOTAL: ' . count($unified) . " - " . $unified[$index]['count'] . " COUNT");
|
||||
return back()->with('message', $duplicates . ' UPDATED - ' . $fresh . ' CREATED');
|
||||
|
||||
public function urlExists($url)
|
||||
{
|
||||
// Remove all illegal characters from a url
|
||||
$url = filter_var($url, FILTER_SANITIZE_URL);
|
||||
// Validate URI
|
||||
if (
|
||||
filter_var($url, FILTER_VALIDATE_URL) === false || // check only for http/https schemes.
|
||||
!in_array(
|
||||
strtolower(parse_url($url, PHP_URL_SCHEME)),
|
||||
["http", "https"],
|
||||
true
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
} // Check that URL exists
|
||||
$file_headers = @get_headers($url);
|
||||
return !(!$file_headers || $file_headers[0] === "HTTP/1.1 404 Not Found");
|
||||
//$domain = $csv[1000][0];
|
||||
//$record = null;
|
||||
|
||||
/*
|
||||
foreach ($blockcount as $line) {
|
||||
if ($line[0] == $domain) {
|
||||
$record = $line;
|
||||
}
|
||||
}
|
||||
if ($record != null) {
|
||||
return back()->with('message', $domain . ' has ' . $record[1] . ' blocks.');
|
||||
} else {
|
||||
return back()->with('message', 'NO MATCHES');
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class LocationCollection extends ResourceCollection
|
||||
{
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
//return parent::toArray($request);
|
||||
|
||||
return [
|
||||
'listingCount' => count($this->collection),
|
||||
'locations' => LocationResource::collection($this->collection),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class LocationResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'url' => $this->url,
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'rating' => $this->rating,
|
||||
'count' => $this->block_count,
|
||||
'link' => "/location/" . $this->uuid,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class LocationAppeal extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(public $location, public $sponsor)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
from: new Address(env('TBS_FROM_ADDRESS'), 'TBS Appeal Request'),
|
||||
subject: 'Location Appeal',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
view: 'email.appeal',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Appeal extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = "appeal";
|
||||
|
||||
protected $primaryKey = 'id';
|
||||
public $incrementing = true;
|
||||
protected $fillable = [
|
||||
"uuid",
|
||||
"location",
|
||||
"location_admin",
|
||||
"sponsor",
|
||||
"description",
|
||||
"approved",
|
||||
"reviewed",
|
||||
"created_at",
|
||||
"updated_at"
|
||||
];
|
||||
}
|
@ -4,12 +4,10 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Location extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
@ -31,9 +29,7 @@ class Location extends Model
|
||||
"added_by",
|
||||
"tags",
|
||||
"block_count",
|
||||
"silence_count",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"actions_count"
|
||||
"updated_at"
|
||||
];
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App\Repositories\LocationRepository;
|
||||
use App\Models\Location;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@ -13,9 +11,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->bind(LocationRepository::class, function ($app) {
|
||||
return new LocationRepository(new Location());
|
||||
});
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Models\Location;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class LocationRepository
|
||||
{
|
||||
protected $model;
|
||||
private $limit = 15;
|
||||
|
||||
public function __construct(Location $model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function search($request)
|
||||
{
|
||||
// this grabs the search results from the db
|
||||
$terms = $request->index_search;
|
||||
$rawSearch = $terms;
|
||||
$terms = str_replace(",", "", $terms);
|
||||
$terms = str_replace(" ", "|", $terms);
|
||||
$raw = DB::select("SELECT * FROM searchlocations(?)", [$terms]);
|
||||
$results = [];
|
||||
foreach ($raw as $item) {
|
||||
if (($item->block_count + $item->silence_count) >= 2) {
|
||||
array_push($results, $item);
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function getLocation($uuid)
|
||||
{
|
||||
return $this->model::where("uuid", $uuid)->first();
|
||||
}
|
||||
|
||||
public function getActiveLocations()
|
||||
{
|
||||
return $this->model::where("active", true)->where('actions_count', '>=', 2)->get();
|
||||
}
|
||||
|
||||
public function getRecent()
|
||||
{
|
||||
return $locations = $this->model::where("active", true)->where('actions_count', '>=', 2)
|
||||
->orderByDesc('updated_at')->limit(10)->get();
|
||||
}
|
||||
|
||||
public function getPage($pageNum)
|
||||
{
|
||||
$range = $pageNum * $this->limit - $this->limit;
|
||||
$active = $this->model::where("active", true)->where('actions_count', '>=', 2)->get();
|
||||
$locations = $this->model::where("active", true)->where('actions_count', '>=', 2)
|
||||
->limit($this->limit)->offset($range)->orderBy('id', 'asc')->get();
|
||||
$pageCount = ceil(count($active) / $this->limit);
|
||||
|
||||
$next = $pageNum + 1;
|
||||
if ($next > $pageCount) {
|
||||
$next = 1;
|
||||
}
|
||||
|
||||
$prev = $pageNum - 1;
|
||||
|
||||
if ($prev <= 0) {
|
||||
$prev = $pageCount;
|
||||
}
|
||||
|
||||
return $result = [$locations, $pageCount, $prev, $next];
|
||||
}
|
||||
}
|
1416
composer.lock
generated
1416
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -32,18 +32,6 @@ form.index-search-form > button {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
form.index-search-form > button > img#search-icon {
|
||||
float: none;
|
||||
}
|
||||
|
||||
form.index-search-form > button > label {
|
||||
font-weight: 500;
|
||||
top: 15px;
|
||||
position: relative;
|
||||
font-size: 1.5em;
|
||||
display: none;
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
/* Chrome, Firefox, Opera, Safari 10.1+ */
|
||||
color: var(--highlight);
|
||||
@ -53,23 +41,6 @@ section.index-meta article {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
div.index-meta {
|
||||
display: grid;
|
||||
grid-template-columns: 50% 50%;
|
||||
gap: 10px;
|
||||
width: 98%;
|
||||
font-weight: 500;
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
div.index-meta > label:nth-child(2),
|
||||
div.index-meta > label:nth-child(4),
|
||||
div.index-meta > label:nth-child(6) {
|
||||
color: var(--white);
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
form.index-search-form > input[type="text"] {
|
||||
width: 85%;
|
||||
@ -77,32 +48,3 @@ div.index-meta > label:nth-child(6) {
|
||||
font: 34px var(--base-type);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 650px) {
|
||||
form.index-search-form > input[type="text"] {
|
||||
width: 80%;
|
||||
height: 50px;
|
||||
font: 34px var(--base-type);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
form.index-search-form > input[type="text"] {
|
||||
width: 99%;
|
||||
height: 50px;
|
||||
font: 27px var(--base-type);
|
||||
}
|
||||
|
||||
form.index-search-form > button {
|
||||
width: 99%;
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
form.index-search-form > button > label {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
form.index-search-form > button > img#search-icon {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
@ -37,119 +37,7 @@ section[role="listings"] div[role="paginate"] span {
|
||||
|
||||
a.list-link {
|
||||
display: grid;
|
||||
grid-template-columns: 70px 1fr 80px 80px;
|
||||
gap: 10px;
|
||||
height: auto;
|
||||
padding-bottom: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.list-link > .item-rating {
|
||||
background: var(--secondary);
|
||||
border-radius: 3px;
|
||||
color: var(--white);
|
||||
font-weight: 500;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
a.list-link > .item-name {
|
||||
background: var(--white);
|
||||
border-radius: 3px;
|
||||
color: var(--black);
|
||||
font-weight: 400;
|
||||
padding: 9px 5px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
a.list-link > .item-silence {
|
||||
background: var(--silence);
|
||||
border-radius: 3px;
|
||||
color: var(--black);
|
||||
font-weight: 500;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
a.list-link > .item-block {
|
||||
background: var(--suspend);
|
||||
border-radius: 3px;
|
||||
color: var(--black);
|
||||
font-weight: 500;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
a.list-link > .item-silence > .item-icon,
|
||||
a.list-link > .item-block > .item-icon {
|
||||
width: 30px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/*
|
||||
responsive
|
||||
*/
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
a.list-link {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: 100% 100px 30px 30px;
|
||||
gap: 5px;
|
||||
height: auto;
|
||||
padding-bottom: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.list-link > .item-rating {
|
||||
grid-row: 3;
|
||||
grid-column: 1/4;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a.list-link > .item-name {
|
||||
grid-row: 2/3;
|
||||
grid-column: 1/6;
|
||||
}
|
||||
|
||||
a.list-link > .item-silence {
|
||||
grid-row: 3/4;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a.list-link > .item-block {
|
||||
grid-row: 3/4;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
a.list-link {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: 100% auto 30px 30px;
|
||||
gap: 5px;
|
||||
height: auto;
|
||||
padding-bottom: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.list-link > .item-rating {
|
||||
grid-row: 3;
|
||||
grid-column: 1/2;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a.list-link > .item-silence {
|
||||
grid-row: 3/4;
|
||||
grid-column: 2/4;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a.list-link > .item-block {
|
||||
grid-row: 3/4;
|
||||
height: 100%;
|
||||
grid-column: 4/6;
|
||||
}
|
||||
grid-template-columns: 30px 50px 300px;
|
||||
width: 80%;
|
||||
height: 45px;
|
||||
}
|
||||
|
@ -14,71 +14,8 @@ section[role="location"] img {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
div.location-rating {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 10px;
|
||||
width: 98%;
|
||||
font-weight: 500;
|
||||
font-size: 0.8em;
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
div.location-rating > div {
|
||||
border-radius: 3px;
|
||||
color: var(--primary);
|
||||
padding: 5px 5px 0;
|
||||
}
|
||||
|
||||
div.location-rating > div:nth-child(1) {
|
||||
background: var(--secondary);
|
||||
}
|
||||
|
||||
div.location-rating > div:nth-child(2) {
|
||||
background: var(--silence);
|
||||
}
|
||||
|
||||
div.location-rating > div:nth-child(3) {
|
||||
background: var(--suspend);
|
||||
}
|
||||
|
||||
div.location-rating > div > span {
|
||||
position: relative;
|
||||
top: 6px;
|
||||
float: right;
|
||||
width: 80%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rating-icon {
|
||||
width: 35px;
|
||||
width: 45px;
|
||||
top: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
div.location-rating {
|
||||
font-size: 0.65em;
|
||||
}
|
||||
|
||||
div.location-rating > div > span {
|
||||
width: 75%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 670px) {
|
||||
div.location-rating {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
font-size: 0.7em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
div.location-rating {
|
||||
grid-template-columns: 1fr;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
div.location-rating > div > span {
|
||||
width: 85%;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
:root {
|
||||
/* BASE COLORS */
|
||||
--primary: #0c1119;
|
||||
--secondary: #c3639e;
|
||||
--highlight: #4d7555;
|
||||
--white: #efded5;
|
||||
--primary: #140c08;
|
||||
--secondary: #d66365;
|
||||
--highlight: #69b04f;
|
||||
--white: #efebe3;
|
||||
--grey: #abb7b7;
|
||||
--black: #32302f;
|
||||
--error: #b62520;
|
||||
--silence: #d2896b;
|
||||
--suspend: #d94959;
|
||||
--silence: #ea6010;
|
||||
--suspend: #fb263a;
|
||||
--primary-rgb: 20 13 13;
|
||||
}
|
||||
|
@ -97,11 +97,6 @@ main > section > article {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
textarea[name="appeal_description"] {
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
/* NAV */
|
||||
|
||||
#main-nav {
|
||||
@ -186,32 +181,32 @@ sup {
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
color: var(--primary);
|
||||
background: var(--secondary);
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
footer > div:nth-child(1) {
|
||||
display: grid;
|
||||
grid-template-columns: 50% 48%;
|
||||
grid-template-columns: 50% 50%;
|
||||
padding: 10px;
|
||||
gap: 10px;
|
||||
height: auto;
|
||||
height: 200px;
|
||||
width: 80%;
|
||||
margin: 20px auto;
|
||||
margin: 0 auto;
|
||||
max-width: 1000px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
footer > div:nth-child(2) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/*
|
||||
responsive
|
||||
*/
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
header > div:nth-child(1) {
|
||||
}
|
||||
|
||||
header > div nav {
|
||||
bottom: 17px;
|
||||
}
|
||||
@ -228,29 +223,5 @@ footer > div:nth-child(2) {
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 650px) {
|
||||
header > div:nth-child(1) {
|
||||
grid-template-columns: 150px 65% 1fr;
|
||||
grid-template-rows: 75% 1fr;
|
||||
height: auto;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
header > div > div.header-left {
|
||||
grid-row: 1/2;
|
||||
position: relative;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
header > div > div.header-center {
|
||||
grid-row: 2/3;
|
||||
grid-column: 1/4;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 440px) {
|
||||
header > div:nth-child(1) {
|
||||
grid-template-columns: 150px 40% 1fr;
|
||||
}
|
||||
@media only screen and (max-width: 800px) {
|
||||
}
|
||||
|
@ -63,26 +63,6 @@ h2 {
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 650px) {
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
letter-spacing: -3px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
font-size: 1.5em;
|
||||
letter-spacing: -3px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated by Pixelmator Pro 3.4.3 -->
|
||||
<svg width="500" height="500" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="Ellipse" fill="#efebe3" stroke="none" d="M 250 500 C 111.928947 500 0 388.071045 0 250 C 0 111.928955 111.928947 0 250 0 C 388.071045 0 500 111.928955 500 250 C 500 388.071045 388.071045 500 250 500 Z M 249.5 425.849609 C 334.610199 425.849609 403 351.977203 403 264.537109 C 403 244.390259 393.74881 215.814362 379.837891 187.855469 C 365.721375 159.485382 345.643799 129.607941 321.933594 106.994141 C 316.519958 101.854614 308.159698 101.854797 302.746094 106.925781 C 293.494965 115.697205 284.928558 126.45636 277.390625 136.324219 C 260.807159 115.62915 243.057907 96.510132 224.144531 78.761719 C 218.799438 73.759277 210.509155 73.690887 205.164063 78.693359 C 173.230606 108.296906 146.230286 141.942657 127.111328 174.21875 C 108.197952 206.015137 96 238.15448 96 264.46875 C 96 351.908844 163.43045 425.849609 249.5 425.849609 Z M 250.664063 360.0625 C 207.423721 360.0625 172.750168 332.241577 172.681641 285.300781 C 172.681641 264.674225 184.33017 246.309418 207.492188 217.185547 C 211.877914 211.7034 220.102753 211.771759 224.419922 217.253906 C 235.932419 231.850098 256.14621 257.546875 267.453125 271.9375 C 271.701782 277.351105 279.858093 277.489319 284.380859 272.28125 L 301.648438 252.203125 C 306.102661 246.995087 313.98465 247.404846 317.068359 253.572266 C 334.405609 285.231598 326.660309 325.525024 297.810547 345.671875 C 283.35141 355.265625 268.001312 360.0625 250.664063 360.0625 Z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.6 KiB |
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated by Pixelmator Pro 3.4.3 -->
|
||||
<!-- Generated by Pixelmator Pro 3.3.8 -->
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="path2292" fill="#efebe3" stroke="none" d="M 11.931641 1.986328 C 6.851659 2.0299 2.1895 6.012724 2.005859 11.675781 L 2 12 L 2.00586 12.324219 C 2.161932 17.140404 5.551549 20.72867 9.675782 21.730469 C 9.588913 21.443272 9.558197 21.13777 9.597657 20.835938 C 9.47312 18.918024 9.545824 16.97234 10.00586 15.101562 C 8.788254 14.549991 8.926215 13.552958 10.486329 13.134766 C 10.688758 12.435676 11.011918 11.808259 11.775392 11.5625 C 12.475244 11.321042 13.30658 11.50242 13.822267 12.039062 C 14.182369 12.380361 14.347692 12.851138 14.367189 13.318359 C 15.557706 13.858945 15.447286 14.835346 13.984376 15.267578 C 13.876838 15.708144 13.794972 16.040434 13.751954 16.230469 C 14.035457 16.215448 14.343313 16.25919 14.525392 16.310549 C 15.273297 15.605935 16.559305 15.683684 17.234377 16.451174 C 18.030642 17.245865 17.777361 18.485273 17.160156 19.302736 C 16.834358 19.841322 16.59597 20.440948 16.324219 21.01758 C 16.59798 20.884926 16.870295 20.73892 17.138672 20.578127 C 23.68045 16.658728 23.604391 7.153141 17 3.339844 C 15.364385 2.395456 13.624967 1.971804 11.931641 1.986328 Z M 7.978516 7.474609 C 8.504453 7.484797 9.026345 7.633665 9.589844 7.914063 C 9.807306 8.022272 9.962496 8.065799 10.025391 8.089844 C 10.30621 8.197204 10.600216 8.074305 10.783203 8.117188 C 11.423864 8.267323 11.413255 9.201465 10.703123 9.310547 C 10.368721 9.361912 9.987375 9.327701 9.675781 9.240234 C 10.263738 9.753045 10.07576 10.87933 9.126953 10.992188 L 9 11 L 8.882813 10.992188 C 7.706968 10.852325 7.706968 9.147676 8.882813 9.007813 L 9.060547 9 C 8.389929 8.673583 7.954104 8.424998 6.910156 8.925781 C 6.097967 9.296431 5.682192 8.17984 6.337891 7.869141 C 6.921612 7.592548 7.452579 7.464422 7.978516 7.474609 Z M 16.025391 7.476559 C 16.551327 7.466373 17.082294 7.596451 17.666016 7.873043 C 18.321714 8.183743 17.905939 9.298381 17.09375 8.927732 C 16.049803 8.426949 15.612026 8.677486 14.941406 9.003903 L 15.119141 9.009764 C 16.294985 9.149627 16.294985 10.856229 15.119141 10.996092 L 15.003906 11.003892 L 14.876953 10.996092 C 13.928146 10.883233 13.738215 9.756949 14.326172 9.244139 C 14.014578 9.331604 13.635186 9.365818 13.300781 9.31445 C 12.590652 9.205368 12.578091 8.269274 13.218751 8.119138 C 13.401738 8.076256 13.697696 8.199155 13.978517 8.091794 C 14.041407 8.067749 14.196601 8.024221 14.414063 7.916012 C 14.977562 7.635616 15.499455 7.486746 16.025393 7.476559 Z"/>
|
||||
<path id="path1819" fill="#efebe3" stroke="none" d="M 11.711456 13.193301 L 10.960155 16.263454 L 10.723999 18.598185 L 10.817269 21.317106 C 10.888359 21.702995 11.090498 21.968763 11.535805 22.011623 C 12.458734 22.051924 13.518139 21.943733 14.323691 21.738602 C 14.589794 21.658991 14.723038 21.499723 14.821309 21.311239 L 16.050283 18.831099 L 16.454288 18.104069 C 16.90646 17.320887 15.688282 16.454172 15.087541 17.494686 L 14.908501 17.80386 C 13.974688 16.986099 12.358489 17.746168 12.358489 17.746168 L 12.426389 16.614141 L 13.161877 13.597538 C 13.372696 12.60058 11.976026 12.279035 11.711465 13.193299 Z"/>
|
||||
<path id="Path" fill="none" stroke="none" d="M 0 0 L 24 0 L 24 24 L 0 24 Z"/>
|
||||
<path id="path1" fill="#ea6010" stroke="none" d="M 17 3.34 C 21.1674 5.746208 23.030024 10.779379 21.433001 15.318825 C 19.835976 19.858273 15.232252 22.616514 10.476249 21.883377 C 5.720245 21.15024 2.160861 17.133654 2.005 12.324 L 2 12 L 2.005 11.676 C 2.118919 8.162982 4.068822 4.967705 7.140892 3.259882 C 10.212963 1.552061 13.95609 1.582479 17 3.34 Z M 15 14 L 9 14 L 8.883 14.007 C 8.37995 14.066836 8.001114 14.493402 8.001114 15 C 8.001114 15.506598 8.37995 15.933164 8.883 15.993 L 9 16 L 15 16 L 15.117 15.993 C 15.62005 15.933164 15.998886 15.506598 15.998886 15 C 15.998886 14.493402 15.62005 14.066836 15.117 14.007 L 15 14 Z M 9.01 9 L 8.883 9.007 C 8.37995 9.066836 8.001114 9.493402 8.001114 10 C 8.001114 10.506598 8.37995 10.933164 8.883 10.993 L 9 11 L 9.127 10.993 C 9.630051 10.933164 10.008885 10.506598 10.008885 10 C 10.008885 9.493402 9.630051 9.066836 9.127 9.007 L 9.01 9 Z M 15.01 9 L 14.883 9.007 C 14.37995 9.066836 14.001114 9.493402 14.001114 10 C 14.001114 10.506598 14.37995 10.933164 14.883 10.993 L 15 11 L 15.127 10.993 C 15.630051 10.933164 16.008886 10.506598 16.008886 10 C 16.008886 9.493402 15.630051 9.066836 15.127 9.007 L 15.01 9 Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.4 KiB |
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated by Pixelmator Pro 3.4.3 -->
|
||||
<!-- Generated by Pixelmator Pro 3.3.8 -->
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="path1" fill="#efebe3" stroke="none" d="M 14.865711 21.562855 C 13.484051 21.973886 11.977767 22.11401 10.475826 21.882484 C 5.720059 21.149376 2.160853 17.13295 2.005 12.323484 L 2 11.999497 L 2.005 11.67551 C 2.118913 8.162631 4.068719 4.96748 7.140635 3.259726 C 10.212553 1.551971 13.955494 1.582388 16.999252 3.33984 C 20.471048 5.344435 22.335369 9.211392 21.941496 13.063743 C 21.638853 12.282332 20.494862 12.311415 20.494862 12.311415 C 20.33622 10.935238 17.531656 10.99734 17.395786 12.263875 C 17.394386 12.277055 17.356598 12.320015 17.356598 12.320015 C 16.094175 12.350565 15.655445 13.278266 15.569292 13.501472 L 15.569296 13.50147 C 13.25033 13.340255 10.939906 13.917868 8.969625 15.151405 C 8.50131 15.444105 8.358945 16.061031 8.651641 16.529352 C 8.944338 16.997669 9.561259 17.140038 10.029573 16.847338 C 11.734911 15.86276 13.531968 15.365489 15.429303 15.497391 C 15.421703 15.655235 15.402763 15.934267 15.402763 15.934267 C 13.722934 15.730796 12.71482 17.372704 13.250748 18.700893 Z M 10.408088 8.316023 L 7.034182 7.900524 C 6.303076 7.827415 6.131269 8.98021 6.91 9.092553 C 7.125181 9.123596 8.310906 9.275673 8.310906 9.275673 C 8.11896 9.458725 8.000814 9.716671 8.000814 9.999577 C 8.000814 10.506154 8.379631 10.932703 8.882656 10.992537 L 8.99965 10.999537 L 9.126644 10.992537 C 9.62967 10.932697 10.008486 10.506154 10.008486 9.999577 C 10.008486 9.805412 9.997353 9.657336 9.855869 9.468498 C 9.855869 9.468498 9.999368 9.481016 10.294614 9.510522 C 10.994176 9.502202 11.148743 8.475587 10.408088 8.316023 Z M 13.556226 8.327742 C 12.888803 8.452742 12.975172 9.494161 13.694857 9.506617 C 13.804587 9.508516 14.176233 9.453409 14.176233 9.453409 C 14.079473 9.607802 14.000515 9.805637 14.000515 9.999578 C 14.000515 10.506154 14.379333 10.932703 14.882357 10.992537 L 14.999352 10.999537 L 15.126345 10.992537 C 15.629371 10.932697 16.008186 10.506154 16.008186 9.999578 C 16.008186 9.720305 15.873525 9.445825 15.685923 9.263232 C 15.685923 9.263232 16.734871 9.135027 17.114626 9.084742 C 17.836151 8.928703 17.728067 7.867409 16.94478 7.904829 Z"/>
|
||||
<path id="path1034" fill="#efebe3" stroke="none" d="M 21.293535 15.272347 C 21.293535 14.230235 22.856705 14.230235 22.856705 15.272347 L 22.856705 19.701324 C 22.856705 21.427954 21.456995 22.827662 19.730368 22.827662 L 18.688253 22.827662 L 18.796635 22.827662 C 17.7449 22.827839 16.763556 22.299183 16.185101 21.420811 C 16.150921 21.36879 16.11688 21.316687 16.082973 21.264494 C 15.920404 21.014908 15.349847 20.02021 14.370783 18.279884 C 14.163248 17.911001 14.287053 17.443947 14.650069 17.226309 C 15.03267 16.99674 15.522393 17.056881 15.838077 17.372204 L 16.616611 18.138157 L 16.604033 14.230235 C 16.597332 13.188145 18.1672 13.188123 18.1672 14.230235 L 18.1672 15.923668 L 18.1672 13.188123 C 18.1672 12.146011 19.73037 12.146011 19.73037 13.188123 L 19.73037 14.222953 C 19.73037 13.188123 21.293537 13.188123 21.293537 14.230253 L 21.293537 15.27504"/>
|
||||
<path id="Path" fill="none" stroke="none" d="M 0 0 L 24 0 L 24 24 L 0 24 Z"/>
|
||||
<path id="path1" fill="#fb263a" stroke="none" d="M 17 3.34 C 21.1674 5.746208 23.030024 10.779379 21.433001 15.318825 C 19.835976 19.858273 15.232252 22.616514 10.476249 21.883377 C 5.720245 21.15024 2.160861 17.133654 2.005 12.324 L 2 12 L 2.005 11.676 C 2.118919 8.162982 4.068822 4.967705 7.140892 3.259882 C 10.212963 1.552061 13.95609 1.582479 17 3.34 Z M 15.57 13.502 C 13.250918 13.340779 10.940379 13.918414 8.97 15.152 C 8.501662 15.444711 8.359289 16.061663 8.652 16.530001 C 8.944711 16.998337 9.561663 17.140711 10.03 16.848 C 11.642129 15.838702 13.53257 15.366092 15.43 15.498 C 15.98118 15.53666 16.459339 15.121181 16.497999 14.57 C 16.536659 14.01882 16.12118 13.54066 15.57 13.502 Z M 9.01 9 L 8.883 9.007 C 8.37995 9.066836 8.001114 9.493402 8.001114 10 C 8.001114 10.506598 8.37995 10.933164 8.883 10.993 L 9 11 L 9.127 10.993 C 9.630051 10.933164 10.008885 10.506598 10.008885 10 C 10.008885 9.493402 9.630051 9.066836 9.127 9.007 L 9.01 9 Z M 15.01 9 L 14.883 9.007 C 14.37995 9.066836 14.001114 9.493402 14.001114 10 C 14.001114 10.506598 14.37995 10.933164 14.883 10.993 L 15 11 L 15.127 10.993 C 15.630051 10.933164 16.008886 10.506598 16.008886 10 C 16.008886 9.493402 15.630051 9.066836 15.127 9.007 L 15.01 9 Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.5 KiB |
@ -1,3 +0,0 @@
|
||||
<div>
|
||||
Appeal filed for: {{$location}}<br />
|
||||
</div>
|
@ -42,12 +42,6 @@
|
||||
<a href="/listings/1" title="instance listing" class="nav-links">
|
||||
Listings
|
||||
</a><br />
|
||||
<a href="/exports" title="list exports" class="nav-links">
|
||||
Exports
|
||||
</a><br />
|
||||
<a href="/appeals" title="location appeals" class="nav-links">
|
||||
Appeals
|
||||
</a><br />
|
||||
@if(Auth::check())
|
||||
<a href="/den" title="den-start" class="nav-links">
|
||||
Den
|
||||
@ -83,11 +77,7 @@
|
||||
</main>
|
||||
<footer>
|
||||
<div>
|
||||
The Bad Space © 2024<br />
|
||||
an <a href="https://h-i.works">h.i.</a> project
|
||||
</div>
|
||||
<div>
|
||||
a0.5
|
||||
<p>The Bad Space © 2023</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
|
@ -4,83 +4,71 @@
|
||||
@parent
|
||||
<section>
|
||||
<article>
|
||||
<h2 id="what">What is The Bad Space?</h2>
|
||||
<p>The Bad Space arose from a need to identify instances that house bad actors, are poorly moderated, and/or contain inappropriate/offensive content (CSAM, hate speech, fascist ideology, etc.) that puts marginalized communities at risk.
|
||||
<h2 id="what">What Is The Bad Space?</h2>
|
||||
<p>The Bad Space project was born from a need to effectively identify instances that house bad actors and are poorly moderated, which puts marginalized communities at risk.
|
||||
</p>
|
||||
<p>
|
||||
It is an extension of the
|
||||
<strong>#fediblock</strong>
|
||||
hashtag - orginally created by
|
||||
<a href="https://www.artistmarciax.com/">Artist Marcia X</a>
|
||||
hashtag created by
|
||||
<a href="https://www.artistmarciax.com/" target="_new">Artist Marcia X</a>,
|
||||
with additional support from
|
||||
<a href="https://digital.rooting.garden">Ginger</a>
|
||||
<a href="https://digital.rooting.garden" target="_new">Ginger</a>,
|
||||
to provide a catalog of instances that seek to cause harm and reduce the quality of experience in the fediverse.
|
||||
</p>
|
||||
<p>
|
||||
The searchable online catalog is built and maintained by
|
||||
<a href="https://roiskinda.cool/profile.html">Ro</a>. The repo can be found <a href="https://koodu.h-i.works/projects/thebadspace">here</a>.
|
||||
Technical support provided by
|
||||
<a href="https://roiskinda.cool/profile.html" target="_new">Ro</a>.
|
||||
</p>
|
||||
<p>Custom silence and suspend icons graciously provided by <a href="https://rage.love/@puf">puf</a>.</p>
|
||||
<h2 id="how">How does it work?</h2>
|
||||
<p>The Bad Space is a collaboration of communities, referred to as Current Sources, committed to actively moderating against racism, sexism, heterosexism, transphobia, ableism, casteism, or religion.</p>
|
||||
<h2 id="how">How Does It Work?</h2>
|
||||
<p>The Bad Space is a collaboration of instances committed to actively moderating against racism, sexism, heterosexism, transphobia, ableism, casteism, and religion.</p>
|
||||
|
||||
<p>These communities have permitted The Bad Space to ingest their respective blocklists detailing their silences and suspension to create a composite directory of sites that engage in the behavior(s) listed in the section above. For each behavior, the directory of locations can be searched and, through The Bad Space's public API, integrated into external services.</p>
|
||||
|
||||
<h2>Adding Locations</h2>
|
||||
<p>
|
||||
Current Sources continually review the #fediblock hashtag and update their silences and suspensions when warranted. If an instance meets the criteria of a Current Source to be suspended or silenced, The Bad Space will automatically be updated according to said Current Sources' curated data.
|
||||
|
||||
For an instance to be listed on The Bad Space, at least two (2) Current Sources must have that location silenced and/or suspended. Instances will not display in the directory until two (2) Current Sources have taken moderation action against them.
|
||||
</p>
|
||||
<h2>Removing Locations</h2>
|
||||
Locations that are displayed in The Bad Space may petition to be removed from the catalog by sending an appeal request to The Bad Space. The appeal process is outlined <a href="/appeals">here</a>.
|
||||
<p>These instances have permitted The Bad Space to read their respective blocklists to create a composite directory of sites tagged for the behavior above that can be searched and, through a public API, can be integrated into external services.</p>
|
||||
|
||||
<p><strong>Current Sources:</strong></p>
|
||||
Maston:<br />
|
||||
Mastodon:<br />
|
||||
@foreach($sources as $source)
|
||||
@if($source->format == 'json')
|
||||
<a href="https://{{$source->url}}">{{$source->url}}</a><br />
|
||||
@endif
|
||||
@endforeach
|
||||
Custom CSV<br />
|
||||
@endforeach<br />
|
||||
Custom CSV:<br />
|
||||
@foreach($sources as $source)
|
||||
@if($source->format == 'csv')
|
||||
<a href="{{$source->url}}">{{$source->url}}</a><br />
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
<h2>How do I use it?</h2>
|
||||
<h2>How Do I Use It?</h2>
|
||||
<p>
|
||||
The Bad Space is meant to be a resource for anyone looking to improve the quality of their online experience by creating a tool that catalogs sources for harassment and abuse. There are several options for how it can be used.
|
||||
<h3>Search</h3>
|
||||
To see if a site is listed in the database, use the
|
||||
To see if an instance is listed in the database, use the
|
||||
<a href="/">search feature</a>
|
||||
to search for that URL. If it is in the database, information for that instance will be returned and associated instances if applicable.
|
||||
to search for its URL. If it is in the database, information for that instance will be returned and include associated instances, if applicable.
|
||||
<h3>CSV Exports</h3>
|
||||
For a list of the current locations being tracked, click on one of the links below to download a dynamically generated CSV file that can be consumed as a blocklist. More formats will be added over time.
|
||||
<br />
|
||||
For a list of the current instances being tracked, click on one of the links below to download a dynamically generated CSV file that can be consumed as a blocklist. More formats will be added over time.
|
||||
<br /><br />
|
||||
<a href="/exports/mastodon">For Mastodon</a>
|
||||
<h3>API</h3>
|
||||
The Bad Space has a public api that can be used to search the database programatically and return results in the JSON format. The API can be accsess at<br />
|
||||
The Bad Space has a public API that can be used to search the database programatically and return results in the JSON format. The API can be accessed at<br />
|
||||
<code>https://thebad.space/api/v1/search</code>
|
||||
by posting a JSON object with the following format:
|
||||
<code>{"url":"search.url"}</code><br />
|
||||
Data from API request will be returned in the follow format:<br />
|
||||
<code>{"url":"search.url"}</code><br /><br />
|
||||
Data from API requests will be returned in the following format:<br />
|
||||
|
||||
<pre>
|
||||
<code>{
|
||||
data:{
|
||||
"listingCount":1,
|
||||
"locations":
|
||||
[
|
||||
{
|
||||
"url":"search.url",
|
||||
"name":"Instance Name",
|
||||
"description":"instance description",
|
||||
"link":"bad-space-instance-link"
|
||||
}
|
||||
]
|
||||
"listingCount":1,
|
||||
"locations":
|
||||
[
|
||||
{
|
||||
"url":"search.url",
|
||||
"name":"Instance Name",
|
||||
"description":"instance description",
|
||||
"link":"bad-space-instance-link"
|
||||
}
|
||||
]
|
||||
}</code>
|
||||
</pre>
|
||||
</p>
|
||||
|
@ -1,62 +0,0 @@
|
||||
@extends('frame')
|
||||
@section('title', 'The Bad Space|Appeals')
|
||||
@section('main-content')
|
||||
@parent
|
||||
<section>
|
||||
<article>
|
||||
<h2>Appeals</h2>
|
||||
|
||||
Locations listed in The Bad Space have the right to appeal their inclusion if they feel they have been added unfairly.
|
||||
|
||||
<h3>Starting the Appeals Process</h3>
|
||||
|
||||
<p>This process can be initiated by sending an Official Appeal to The Bad Space using the Appeal Form (found below) stating why they should not be included. All appeal requests must be sponsored by at least one Current Source, and their name(s) must be included in the submission.</p>
|
||||
|
||||
<p>The Bad Space will validate the appeal request by contacting a moderator or administrator of the respective instance. If no moderator or administrator is detailed in the appeal request, it will be immediately disqualified.</p>
|
||||
|
||||
<p>If the Appeal contains any threats, hate speech, microaggressions, taunts, or slurs, the Appeal will be automatically disqualified.</p>
|
||||
|
||||
An Appeal can only be made once every three (3) months.
|
||||
|
||||
<h3>Process Description</h3>
|
||||
|
||||
<p>After an appeal request is validated, it will be reviewed by all Current Sources. Each Current Source will vote on whether to approve the requesting instance's appeal request.</p>
|
||||
|
||||
<p>80% of Current Sources must vote in favor of the request to proceed to the next step. Appeals that do not meet this threshold will be rejected, and the administrator or moderator who petitioned for the appeal will be notified.
|
||||
</p>
|
||||
|
||||
<p>If an appeal is approved to proceed, a chat room will be created on the h.i. cloud community for the petitioner to be interviewed by Current Sources. Here, they will explain why they feel their instance should be removed from the database.</p>
|
||||
|
||||
The petitioner must include the following:
|
||||
<ul>
|
||||
<li>Verification of problematic content and members have been removed.</li>
|
||||
<li>A public explanation of steps to recognize and remove problematic content and members.</li>
|
||||
<li>A working plan to keep said location as free as possible from problematic members and content finding a home there.</li>
|
||||
</ul>
|
||||
|
||||
<p>The petitioner also must be available to answer any questions from a member of Current Sources concerning the information provided.</p>
|
||||
|
||||
<p>Failure to provide any of this information or refusing to be interviewed by Current Sources will result in an automatic disqualification.</p>
|
||||
|
||||
<p>Upon completing the interview process, each Current Source will choose to remove or maintain their current block or silence action. The result of each choice will be reflected in the database itself, which can be publicly reviewed at any time.</p>
|
||||
|
||||
<h2>Appeals Form</h2>
|
||||
|
||||
<form action="/appeal" method="post" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<label>Appeal Location</label><br />
|
||||
<input type="text" name="location" value="" /><br />
|
||||
<label>Appeal Location Admin</label><br />
|
||||
<input type="text" name="location_admin" value="" /><br />
|
||||
<label>Appeal Sponsor</label><br />
|
||||
<input type="text" name="sponsor" value="" /><br />
|
||||
<label>What is 1+1?</label><br />
|
||||
<input type="text" name="question" value="" /><br />
|
||||
<label>Appeal Summary</label><br />
|
||||
<textarea name="appeal_description">Appeal Summary</textarea>
|
||||
<input type="hidden" name="h1" value="" /><br />
|
||||
<input type="submit" value="File Appeal" name="submit_button">
|
||||
</form>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
@ -1,23 +0,0 @@
|
||||
@extends('frame')
|
||||
@section('title', 'The Bad Space|Exports')
|
||||
@section('main-content')
|
||||
@parent
|
||||
<section>
|
||||
<article>
|
||||
<h2>CSV Exports</h2>
|
||||
Heat Rating is the percentage of Current Sources that have taken action against an instance. The higher the number of Sources that have silenced and/or suspended an instance, the higher the Heat Rating.*
|
||||
<h3>For Mastodon</h3>
|
||||
|
||||
@foreach($list as $item)
|
||||
|
||||
<a href="/exports/mastodon/{{$item['heatRating']}}">Heat Rating: {{$item['heatRating']}}% - Location Count: {{$item['ratingCount']}}</a><br />
|
||||
|
||||
@endforeach
|
||||
<br />
|
||||
<i>* Heating Ratings are still a work in progress so please review list before using.</i>
|
||||
<br /><br />
|
||||
|
||||
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
@ -6,8 +6,7 @@
|
||||
<form class="index-search-form" action="/search" method="post" enctype="multipart/form-data">
|
||||
<input type="text" name="index_search" value="" placeholder="Hi! This is where you search." />
|
||||
<button aria-label="search-button">
|
||||
<label id="search-label">LOOK FOR IT</label>
|
||||
<img id="search-icon" class="button-icon" src="assets/images/global/icon-search.svg" />
|
||||
<img class="button-icon" src="assets/images/global/icon-search.svg" />
|
||||
</button>
|
||||
@csrf
|
||||
</form>
|
||||
@ -15,50 +14,32 @@
|
||||
@isset($results)
|
||||
<section>
|
||||
<article>
|
||||
<h2>Found {{count($results)}} results for {{$terms}}</h2>
|
||||
@foreach($results as $item)
|
||||
<a class="list-link" role="listitem" href="/location/{{$item->uuid}}">
|
||||
<span class="item-rating">{{($item->actions_count / $sources)*100}}%</span>
|
||||
<label class="item-name">{{$item->name}}</label>
|
||||
<div class="item-silence">
|
||||
<img class="item-icon" src="/assets/images/global/status-silence.svg" title="silenced" />
|
||||
{{$item->silence_count}}
|
||||
</div>
|
||||
<div class="item-block">
|
||||
<img class="item-icon" src="/assets/images/global/status-suspend.svg" title="suspended" />
|
||||
{{$item->block_count}}
|
||||
</div>
|
||||
</a>
|
||||
<strong>
|
||||
Found {{count($results)}} results:
|
||||
</strong><br>
|
||||
@foreach($results as $location)
|
||||
<a role="listitem" href="/location/{{$location->uuid}}">{{$location->name}}</a></a><br />
|
||||
@endforeach
|
||||
</article>
|
||||
</section>
|
||||
@endisset
|
||||
<section class="index-meta">
|
||||
<article>
|
||||
<h2>Bad Space Stats</h2>
|
||||
<strong>{{$count}}</strong><br />
|
||||
Instances being tracked.
|
||||
<h2>Recent Updates</h2>
|
||||
@foreach($recent as $item)
|
||||
<a class="list-link" role="listitem" href="/location/{{$item->uuid}}">
|
||||
<span class="item-rating">{{($item->actions_count / $sources)*100}}%</span>
|
||||
<label class="item-name">{{$item->name}}</label>
|
||||
<div class="item-silence">
|
||||
<img class="item-icon" src="/assets/images/global/status-silence.svg" title="silenced" />
|
||||
{{$item->silence_count}}
|
||||
</div>
|
||||
<div class="item-block">
|
||||
<img class="item-icon" src="/assets/images/global/status-suspend.svg" title="suspended" />
|
||||
{{$item->block_count}}
|
||||
</div>
|
||||
@foreach($recent as $location)
|
||||
<a class="list-link" role="listitem" href="/location/{{$location->uuid}}">
|
||||
<span>{{$location->block_count}}</span>
|
||||
@if($location->rating == 'silence')
|
||||
<img class="menu-icon" src="/assets/images/global/status-silence.svg" title="silenced" />
|
||||
@else
|
||||
<img class="menu-icon" src="/assets/images/global/status-suspend.svg" title="suspended" />
|
||||
@endif
|
||||
<label>{{$location->name}}</label>
|
||||
</a>
|
||||
@endforeach
|
||||
<h2>Info</h2>
|
||||
<div class="index-meta">
|
||||
<label>Locations Tracked</label>
|
||||
<label>{{$count}}</label>
|
||||
<label>Total Sources</label>
|
||||
<label>{{$sources}}</label>
|
||||
<label>Latest Update</label>
|
||||
<label>{{$latest_date}}</label>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
@ -9,21 +9,15 @@
|
||||
{{$pageNum}} of {{$totalPages}}
|
||||
<a href="/listings/{{$next}}">NEXT</a><br /><br />
|
||||
@foreach($locations as $location)
|
||||
@php
|
||||
$action = $location->block_count + $location->silence_count;
|
||||
$rating = ($action / $sources)*100;
|
||||
@endphp
|
||||
<a class="list-link" role="listitem" href="/location/{{$location->uuid}}">
|
||||
<span class="item-rating">{{$rating}}%</span>
|
||||
<label class="item-name">{{$location->name}}</label>
|
||||
<div class="item-silence">
|
||||
<img class="item-icon" src="/assets/images/global/status-silence.svg" title="silenced" />
|
||||
{{$location->silence_count}}
|
||||
</div>
|
||||
<div class="item-block">
|
||||
<img class="item-icon" src="/assets/images/global/status-suspend.svg" title="suspended" />
|
||||
{{$location->block_count}}
|
||||
</div>
|
||||
@if($location->rating == 'silence')
|
||||
<span>{{$location->block_count}}</span>
|
||||
<img class="menu-icon" src="/assets/images/global/status-silence.svg" title="silenced" />
|
||||
@else
|
||||
<span>{{$location->block_count}}</span>
|
||||
<img class="menu-icon" src="/assets/images/global/status-suspend.svg" title="suspended" />
|
||||
@endif
|
||||
<label>{{$location->name}}</label>
|
||||
</a>
|
||||
@endforeach
|
||||
<br />
|
||||
|
@ -6,42 +6,29 @@
|
||||
@parent
|
||||
<section>
|
||||
<article>
|
||||
<h1 class="location-title">{{$title}}</h1>
|
||||
<h2>Description</h2>
|
||||
{{$location->description}}<br />
|
||||
<h2>References</h2>
|
||||
<h3>Images</h3>
|
||||
<h2>Screens</h2>
|
||||
@if($images != null)
|
||||
@foreach($images as $image)
|
||||
<a href="/{{$image->path}}" class="location-image" style="background: url(/{{$image->path}}) no-repeat center center / cover #fc6399" />
|
||||
</a>
|
||||
@endforeach
|
||||
@endif
|
||||
@php
|
||||
$action = $location->block_count + $location->silence_count;
|
||||
$rating = ($action / $sources_count)*100;
|
||||
@endphp
|
||||
<h3>Links</h3>
|
||||
<div class="location-rating">
|
||||
<div>
|
||||
<img class="rating-icon" src="/assets/images/global/heat.svg" title="heat-rating" />
|
||||
<span>RATING: {{$rating}}%</span>
|
||||
</div>
|
||||
<div>
|
||||
<img class="rating-icon" src="/assets/images/global/status-silence.svg" title="silenced" />
|
||||
<span>SILENCED: {{$location->silence_count}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<img class="rating-icon" src="/assets/images/global/status-suspend.svg" title="suspended" />
|
||||
<span>SUSPENDED: {{$location->block_count}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<br />
|
||||
Heat Rating is the percentage of <a href="/about#how">Current Sources</a> that have taken action against an instance. The higher the number of Sources that have silenced and/or suspended an instance, the higher the Heat Rating.
|
||||
@if($location->rating == 'silence')
|
||||
<img class="rating-icon" src="/assets/images/global/status-silence.svg" title="silenced" />
|
||||
<strong>Silenced Count: {{$location->block_count}}</strong>
|
||||
@else
|
||||
<img class="rating-icon" src="/assets/images/global/status-suspend.svg" title="suspended" />
|
||||
<strong>Suspended Count: {{$location->block_count}}</strong>
|
||||
|
||||
<br />UPDATED : {{$updated}}
|
||||
@endif
|
||||
<br /><br />
|
||||
This count reflects the number of times this instance has been suspended or silenced by two or more <a href="/about#how">Current Sources</a>.
|
||||
|
||||
<br /><br />UPDATED: {{$updated}}
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
@ -2,8 +2,6 @@
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Resources\LocationCollection;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -19,13 +17,3 @@ use App\Http\Resources\LocationCollection;
|
||||
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
});
|
||||
|
||||
// public search API
|
||||
Route::post("/v1/search", function (Request $request) {
|
||||
$data = json_decode($request->getContent());
|
||||
$search = $data->url;
|
||||
$search = str_replace(",", "", $search);
|
||||
$search = str_replace(" ", "|", $search);
|
||||
$results = DB::select("SELECT * FROM searchlocations('$search')");
|
||||
return new LocationCollection($results);
|
||||
});
|
||||
|
@ -6,7 +6,6 @@ use App\Http\Controllers\AuthController;
|
||||
use App\Http\Controllers\DenController;
|
||||
use App\Http\Controllers\LocationController;
|
||||
use App\Http\Controllers\ExportController;
|
||||
use App\Http\Controllers\AppealController;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -24,13 +23,10 @@ Route::get("/", [FrontIndexController::class, 'start']);
|
||||
Route::get("/listings/{pageNum}", [FrontIndexController::class, 'listings']);
|
||||
Route::get("/about", [FrontIndexController::class, 'about']);
|
||||
Route::get("/location/{uuid}", [FrontIndexController::class, 'location']);
|
||||
Route::get("/appeals", [FrontIndexController::class, 'appeals']);
|
||||
Route::post("/search", [FrontIndexController::class, 'indexSearch']);
|
||||
Route::post("/appeal", [AppealController::class, 'sendAppeal']);
|
||||
|
||||
//exports
|
||||
Route::get("/exports", [ExportController::class, 'exportIndex']);
|
||||
Route::get("/exports/{type}/{rate}", [ExportController::class, 'exportCSV']);
|
||||
Route::get("/exports/test", [ExportController::class, 'exportCSV']);
|
||||
|
||||
//auth
|
||||
Route::get("/login", [AuthController::class, 'showLogin']);
|
||||
|
Reference in New Issue
Block a user