mirror of
https://repo.getmonero.org/AnonDev/xmrmemes.git
synced 2024-12-22 06:05:02 -05:00
Finish rough draft of website
Update the payment code so everything is working now Improve DB structure Improve design Add API Validate XMR Address upon registration And Much More... Still Need to work on: - SEO - Dropdown in menu (bug, not dropping down)
This commit is contained in:
parent
dbfda5cf9e
commit
821fb9b1ed
@ -51,3 +51,5 @@ MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
|||||||
XMR_NETWORK_PORT=28083
|
XMR_NETWORK_PORT=28083
|
||||||
XMR_WALLET_NAME=test
|
XMR_WALLET_NAME=test
|
||||||
XMR_TIP_ADDRESS=
|
XMR_TIP_ADDRESS=
|
||||||
|
XMR_EXPLORER_BASE_URL=https://testnet.xmrchain.net/tx/
|
||||||
|
XMR_DAEMON_IP=127.0.0.1
|
||||||
|
12
README.md
12
README.md
@ -22,16 +22,16 @@ sudo apt install php-bcmath supervisor
|
|||||||
./monero-wallet-rpc --testnet --rpc-bind-port 28083 --disable-rpc-login --wallet-dir .
|
./monero-wallet-rpc --testnet --rpc-bind-port 28083 --disable-rpc-login --wallet-dir .
|
||||||
```
|
```
|
||||||
|
|
||||||
## Seeding the Database
|
## Creating the Database
|
||||||
|
|
||||||
You must seed addresses first and be connected to the daemon.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
php artisan migrate
|
php artisan migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Creating Initial Wallet (Set Wallet Name in .env)
|
||||||
|
|
||||||
```
|
```
|
||||||
php artisan db:seed --class=AddressSeeder
|
php artisan db:seed --class=WalletSeeder
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cron Job to process payments
|
## Cron Job to process payments
|
||||||
@ -44,6 +44,10 @@ Then set up 1 cron job to call
|
|||||||
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
|
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Config file
|
||||||
|
|
||||||
|
Config options are in the .env.example file which should copied into a .env file
|
||||||
|
|
||||||
## This Project Uses Laravel
|
## This Project Uses Laravel
|
||||||
|
|
||||||
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
|
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Address;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class AddressController extends Controller
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Display a listing of the resource.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*
|
|
||||||
* @param \App\Models\Address $address
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function show(Address $address)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*
|
|
||||||
* @param \App\Models\Address $address
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function edit(Address $address)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \App\Models\Address $address
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function update(Request $request, Address $address)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*
|
|
||||||
* @param \App\Models\Address $address
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function destroy(Address $address)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,7 +10,7 @@ class ApiController extends Controller
|
|||||||
public function documentation()
|
public function documentation()
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
'memes_example' => json_encode(Meme::get(), JSON_PRETTY_PRINT),
|
'memes_example' => json_encode(Meme::limit(1)->get(), JSON_PRETTY_PRINT),
|
||||||
'memes_endpoint' => url('api/memes'),
|
'memes_endpoint' => url('api/memes'),
|
||||||
];
|
];
|
||||||
return view('api', ['data' => $data]);
|
return view('api', ['data' => $data]);
|
||||||
|
14
app/Http/Controllers/ContactController.php
Normal file
14
app/Http/Controllers/ContactController.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ContactController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$data = [];
|
||||||
|
return view('contact', ['data' => $data]);
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ use App\Models\User;
|
|||||||
use App\Models\Address;
|
use App\Models\Address;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use chillerlan\QRCode\{QRCode, QROptions};
|
use chillerlan\QRCode\{QRCode, QROptions};
|
||||||
|
use MoneroIntegrations\MoneroPhp\walletRPC;
|
||||||
|
|
||||||
class MemeController extends Controller
|
class MemeController extends Controller
|
||||||
{
|
{
|
||||||
@ -77,11 +78,8 @@ class MemeController extends Controller
|
|||||||
'image' => ['required', 'image'],
|
'image' => ['required', 'image'],
|
||||||
]);
|
]);
|
||||||
$user = \Auth::user();
|
$user = \Auth::user();
|
||||||
$used_ids = Meme::pluck('address_id')->toArray();
|
Meme::create([
|
||||||
$address = Address::whereNotIn('id', $used_ids)->first('id');
|
|
||||||
return Meme::create([
|
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
'address_id' => $address->id,
|
|
||||||
'title' => $request->input('title'),
|
'title' => $request->input('title'),
|
||||||
'caption' => $request->input('caption'),
|
'caption' => $request->input('caption'),
|
||||||
'image' => $request->file('image'),
|
'image' => $request->file('image'),
|
||||||
@ -96,7 +94,7 @@ class MemeController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$meme = Meme::where('id', $id)->with(['user', 'tips', 'address'])->firstOrFail();
|
$meme = Meme::where('id', $id)->with(['user', 'tips'])->firstOrFail();
|
||||||
|
|
||||||
$share = \Share::page(url()->current(), $meme->title, ['class' => 'fa-lg', 'target' => '_blank'])
|
$share = \Share::page(url()->current(), $meme->title, ['class' => 'fa-lg', 'target' => '_blank'])
|
||||||
->facebook()
|
->facebook()
|
||||||
@ -108,7 +106,7 @@ class MemeController extends Controller
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'meme' => $meme,
|
'meme' => $meme,
|
||||||
'qr' => (new QRCode)->render($meme->address->address),
|
'qr' => (new QRCode)->render($meme->address),
|
||||||
'share' => preg_replace("/<a(.*?)>/", "<a$1 target=\"_blank\">", $share),
|
'share' => preg_replace("/<a(.*?)>/", "<a$1 target=\"_blank\">", $share),
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -141,10 +139,19 @@ class MemeController extends Controller
|
|||||||
public function approve($id)
|
public function approve($id)
|
||||||
{
|
{
|
||||||
if (\Auth::user()->is_admin === 1) {
|
if (\Auth::user()->is_admin === 1) {
|
||||||
|
try {
|
||||||
|
$walletRPC = new walletRPC(config('app.xmr_daemon_ip'), config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||||
|
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
||||||
|
$account = $walletRPC->create_account();
|
||||||
$meme = Meme::withoutGlobalScope('approved')->find($id);
|
$meme = Meme::withoutGlobalScope('approved')->find($id);
|
||||||
$meme->is_approved = 1;
|
$meme->is_approved = 1;
|
||||||
|
$meme->account_index = $account['account_index'];
|
||||||
|
$meme->address = $account['address'];
|
||||||
$meme->save();
|
$meme->save();
|
||||||
return redirect()->away(url()->previous());
|
return redirect()->away(url()->previous());
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,15 +14,12 @@ use App\Models\Address;
|
|||||||
use App\Models\Meme;
|
use App\Models\Meme;
|
||||||
use MoneroIntegrations\MoneroPhp\walletRPC;
|
use MoneroIntegrations\MoneroPhp\walletRPC;
|
||||||
|
|
||||||
// Can put code below inside functions to debug the Monero library
|
|
||||||
// ini_set('display_errors', 1);
|
|
||||||
// ini_set('display_startup_errors', 1);
|
|
||||||
// error_reporting(E_ALL);
|
|
||||||
|
|
||||||
class ProcessPayments implements ShouldQueue
|
class ProcessPayments implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $timeout = 3600;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
*
|
*
|
||||||
@ -47,26 +44,29 @@ class ProcessPayments implements ShouldQueue
|
|||||||
public function get_transactions()
|
public function get_transactions()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$walletRPC = new walletRPC('127.0.0.1', config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
$walletRPC = new walletRPC(config('app.xmr_daemon_ip'), config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||||
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
||||||
$get_transfers = $walletRPC->get_transfers('all', true);
|
$account_indexes = Meme::pluck('account_index')->toArray();
|
||||||
|
foreach ($account_indexes as $account_index) {
|
||||||
|
$get_transfers = $walletRPC->get_transfers('in', $account_index);
|
||||||
if (isset($get_transfers['in'])) {
|
if (isset($get_transfers['in'])) {
|
||||||
foreach ($get_transfers['in'] as $transfer) {
|
foreach ($get_transfers['in'] as $transfer) {
|
||||||
$address = Address::where('address', $transfer['address'])->first();
|
$meme = Meme::where('address', $transfer['address'])->first();
|
||||||
$tip_exists = Tip::where('txid', $transfer['txid'])->first();
|
$tip_exists = Tip::where('txid', $transfer['txid'])->first();
|
||||||
if ($address && !$tip_exists) {
|
if ($meme && !$tip_exists) {
|
||||||
$tip = new Tip();
|
$tip = new Tip();
|
||||||
$tip->address_id = $address->id;
|
$tip->meme_id = $meme->id;
|
||||||
$tip->amount = $transfer['amount'];
|
$tip->amount = $transfer['amount'];
|
||||||
$tip->txid = $transfer['txid'];
|
$tip->txid = $transfer['txid'];
|
||||||
$tip->is_deposit = 1;
|
$tip->is_deposit = 1;
|
||||||
$tip->save();
|
$tip->save();
|
||||||
$meme = Meme::where('address_id', $address->id)->firstOrFail();
|
$meme = Meme::where('address', $transfer['address'])->firstOrFail();
|
||||||
$meme->payment_pending = 1;
|
$meme->payment_pending = 1;
|
||||||
$meme->save();
|
$meme->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$walletRPC->close_wallet();
|
$walletRPC->close_wallet();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
echo 'Caught exception: ', $e->getMessage(), "\n";
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
||||||
@ -76,14 +76,16 @@ class ProcessPayments implements ShouldQueue
|
|||||||
public function payout()
|
public function payout()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$walletRPC = new walletRPC('127.0.0.1', config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
$walletRPC = new walletRPC(config('app.xmr_daemon_ip'), config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||||
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
||||||
$meme = Meme::where('payment_pending', 1)->firstOrFail();
|
$memes = Meme::where('payment_pending', 1)->get();
|
||||||
if ($meme->user->address) {
|
foreach ($memes as $meme) {
|
||||||
$send_funds = $walletRPC->sweep_all($meme->user->address, $meme->address->address_index);
|
$balance = $walletRPC->get_balance($meme->account_index);
|
||||||
|
if ($balance['balance'] === $balance['unlocked_balance']) {
|
||||||
|
$send_funds = $walletRPC->sweep_all($meme->user->address, '', $meme->account_index);
|
||||||
if ($send_funds['amount_list']) {
|
if ($send_funds['amount_list']) {
|
||||||
$tip = new Tip;
|
$tip = new Tip;
|
||||||
$tip->address_id = $meme->address_id;
|
$tip->meme_id = $meme->id;
|
||||||
$tip->amount = $send_funds['amount_list'][0];
|
$tip->amount = $send_funds['amount_list'][0];
|
||||||
$tip->txid = $send_funds['tx_hash_list'][0];
|
$tip->txid = $send_funds['tx_hash_list'][0];
|
||||||
$tip->is_deposit = 0;
|
$tip->is_deposit = 0;
|
||||||
@ -92,6 +94,7 @@ class ProcessPayments implements ShouldQueue
|
|||||||
$meme->save();
|
$meme->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$walletRPC->close_wallet();
|
$walletRPC->close_wallet();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
echo 'Caught exception: ', $e->getMessage(), "\n";
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Address extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
}
|
|
@ -14,7 +14,14 @@ class Meme extends Model
|
|||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
protected $appends = ['meme_tips_total'];
|
protected $appends = ['meme_tips_total', 'image_url'];
|
||||||
|
protected $hidden = [
|
||||||
|
'payment_pending',
|
||||||
|
'account_index',
|
||||||
|
'is_approved',
|
||||||
|
'deleted_at',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
protected static function booted()
|
protected static function booted()
|
||||||
{
|
{
|
||||||
@ -28,14 +35,9 @@ class Meme extends Model
|
|||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function address()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Address::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tips()
|
public function tips()
|
||||||
{
|
{
|
||||||
return $this->hasManyThrough(Tip::class, Address::class, 'id', 'address_id', 'address_id', 'id')->orderBy('created_at', 'DESC');
|
return $this->hasMany(Tip::class)->orderByDesc('created_at');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMemeTipsTotalAttribute()
|
public function getMemeTipsTotalAttribute()
|
||||||
@ -43,6 +45,11 @@ class Meme extends Model
|
|||||||
return $this->tips->where('is_deposit', 1)->sum('amount_formatted');
|
return $this->tips->where('is_deposit', 1)->sum('amount_formatted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getImageUrlAttribute()
|
||||||
|
{
|
||||||
|
return url($this->image);
|
||||||
|
}
|
||||||
|
|
||||||
public function setImageAttribute($value)
|
public function setImageAttribute($value)
|
||||||
{
|
{
|
||||||
$attribute_name = "image";
|
$attribute_name = "image";
|
||||||
|
@ -9,13 +9,18 @@ class Tip extends Model
|
|||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $appends = ['amount_formatted'];
|
protected $appends = ['amount_formatted', 'tx_url'];
|
||||||
|
|
||||||
public function getAmountFormattedAttribute()
|
public function getAmountFormattedAttribute()
|
||||||
{
|
{
|
||||||
return number_format(($this->amount)*(pow(10, -12)), 8, '.', '');
|
return number_format(($this->amount)*(pow(10, -12)), 8, '.', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTxUrlAttribute()
|
||||||
|
{
|
||||||
|
return config('app.xmr_explorer_base_url') . $this->txid;
|
||||||
|
}
|
||||||
|
|
||||||
public function address()
|
public function address()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Address::class);
|
return $this->belongsTo(Address::class);
|
||||||
|
@ -51,8 +51,7 @@ class User extends Authenticatable
|
|||||||
|
|
||||||
public function tips()
|
public function tips()
|
||||||
{
|
{
|
||||||
return $this->hasManyThrough(Tip::class, Meme::class, 'address_id', 'id', 'id', 'address_id');
|
return $this->hasManyThrough(Tip::class, Meme::class, 'user_id');
|
||||||
return $this->hasManyThrough(Tip::class, Meme::class, 'id', 'address_id');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMemesTotalAttribute()
|
public function getMemesTotalAttribute()
|
||||||
|
@ -26,7 +26,7 @@ class ValidateAddress implements Rule
|
|||||||
*/
|
*/
|
||||||
public function passes($attribute, $value)
|
public function passes($attribute, $value)
|
||||||
{
|
{
|
||||||
$walletRPC = new walletRPC('127.0.0.1', config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
$walletRPC = new walletRPC(config('app.xmr_daemon_ip'), config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||||
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
||||||
$validate_address = $walletRPC->validate_address($value);
|
$validate_address = $walletRPC->validate_address($value);
|
||||||
return $validate_address['valid'];
|
return $validate_address['valid'];
|
||||||
|
@ -11,6 +11,8 @@ return [
|
|||||||
'xmr_wallet_name' => env('XMR_WALLET_NAME', 'Test'),
|
'xmr_wallet_name' => env('XMR_WALLET_NAME', 'Test'),
|
||||||
'xmr_network_port' => env('XMR_NETWORK_PORT', 28083),
|
'xmr_network_port' => env('XMR_NETWORK_PORT', 28083),
|
||||||
'xmr_tip_address' => env('XMR_TIP_ADDRESS', null),
|
'xmr_tip_address' => env('XMR_TIP_ADDRESS', null),
|
||||||
|
'xmr_explorer_base_url' => env('XMR_EXPLORER_BASE_URL', 'https://testnet.xmrchain.net/tx/'),
|
||||||
|
'xmr_daemon_ip' => env('XMR_DAEMON_IP', '127.0.0.1'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class CreateAddressesTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('addresses', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->string('address', 95)->unique();
|
|
||||||
$table->integer('address_index');
|
|
||||||
$table->string('label');
|
|
||||||
$table->boolean('used');
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('addresses');
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,12 +16,13 @@ class CreateMemesTable extends Migration
|
|||||||
Schema::create('memes', function (Blueprint $table) {
|
Schema::create('memes', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignId('user_id')->constrained();
|
$table->foreignId('user_id')->constrained();
|
||||||
$table->foreignId('address_id')->constrained();
|
|
||||||
$table->string('title');
|
$table->string('title');
|
||||||
$table->string('caption')->nullable();
|
$table->string('caption')->nullable();
|
||||||
$table->string('image')->nullable();
|
$table->string('image')->nullable();
|
||||||
$table->boolean('is_approved')->default(0);
|
$table->boolean('is_approved')->default(0);
|
||||||
$table->boolean('payment_pending')->default(0);
|
$table->boolean('payment_pending')->default(0);
|
||||||
|
$table->string('address', 95)->nullable()->unique();
|
||||||
|
$table->integer('account_index')->nullable()->unique();
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@ class CreateTipsTable extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('tips', function (Blueprint $table) {
|
Schema::create('tips', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignId('address_id')->constrained();
|
$table->foreignId('meme_id')->constrained();
|
||||||
$table->bigInteger('amount');
|
$table->bigInteger('amount');
|
||||||
$table->string('txid')->unique();
|
$table->string('txid')->unique();
|
||||||
$table->boolean('is_deposit');
|
$table->boolean('is_deposit');
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Seeders;
|
|
||||||
|
|
||||||
use Illuminate\Database\Seeder;
|
|
||||||
use MoneroIntegrations\MoneroPhp\walletRPC;
|
|
||||||
|
|
||||||
class AddressSeeder extends Seeder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the database seeds.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function run()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$walletRPC = new walletRPC('127.0.0.1', config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
|
||||||
$create_wallet = $walletRPC->create_wallet(config('app.xmr_wallet_name'), ''); // Creates a new wallet named memes with no passphrase. Comment this line and edit the next line to use your own wallet
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
dump($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
|
||||||
for ($i=0; $i < 100; $i++) {
|
|
||||||
$create_address = $walletRPC->create_address(0, 'Example');
|
|
||||||
}
|
|
||||||
$get_address = $walletRPC->get_address();
|
|
||||||
\DB::table('addresses')->insertOrIgnore($get_address['addresses']);
|
|
||||||
$walletRPC->close_wallet();
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
dump($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
24
database/seeders/WalletSeeder.php
Normal file
24
database/seeders/WalletSeeder.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use MoneroIntegrations\MoneroPhp\walletRPC;
|
||||||
|
|
||||||
|
class WalletSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create Initial Wallet
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$walletRPC = new walletRPC(config('app.xmr_daemon_ip'), config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||||
|
$create_wallet = $walletRPC->create_wallet(config('app.xmr_wallet_name'), ''); // Creates a new wallet named memes with no passphrase. Comment this line and edit the next line to use your own wallet
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
dump($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
public/css/app_dark.css
vendored
5
public/css/app_dark.css
vendored
@ -16142,8 +16142,9 @@ readers do not read off random characters that represent icons */
|
|||||||
|
|
||||||
.grid-memes .card-img-top {
|
.grid-memes .card-img-top {
|
||||||
max-width: 100% !important;
|
max-width: 100% !important;
|
||||||
width: inherit;
|
-o-object-fit: cover;
|
||||||
max-height: 20vw;
|
object-fit: cover;
|
||||||
|
max-height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#social-links li {
|
#social-links li {
|
||||||
|
5
public/css/app_light.css
vendored
5
public/css/app_light.css
vendored
@ -16142,8 +16142,9 @@ readers do not read off random characters that represent icons */
|
|||||||
|
|
||||||
.grid-memes .card-img-top {
|
.grid-memes .card-img-top {
|
||||||
max-width: 100% !important;
|
max-width: 100% !important;
|
||||||
width: inherit;
|
-o-object-fit: cover;
|
||||||
max-height: 20vw;
|
object-fit: cover;
|
||||||
|
max-height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#social-links li {
|
#social-links li {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"/js/app.js": "/js/app.js?id=a4f7ea48d857a5e8d88e",
|
"/js/app.js": "/js/app.js?id=a4f7ea48d857a5e8d88e",
|
||||||
"/js/manifest.js": "/js/manifest.js?id=d7335e682eb6c876d5bc",
|
"/js/manifest.js": "/js/manifest.js?id=d7335e682eb6c876d5bc",
|
||||||
"/css/app_dark.css": "/css/app_dark.css?id=77995f3b0798a182ca9f",
|
"/css/app_dark.css": "/css/app_dark.css?id=e9edb5a2a73bc761692d",
|
||||||
"/css/app_light.css": "/css/app_light.css?id=8971b6e0fc76badb2856",
|
"/css/app_light.css": "/css/app_light.css?id=da42f1c3ae153b59ac52",
|
||||||
"/js/vendor.js": "/js/vendor.js?id=964b623e0af1bb38e06e"
|
"/js/vendor.js": "/js/vendor.js?id=964b623e0af1bb38e06e"
|
||||||
}
|
}
|
||||||
|
4
resources/sass/_common.scss
vendored
4
resources/sass/_common.scss
vendored
@ -23,8 +23,8 @@
|
|||||||
|
|
||||||
.grid-memes .card-img-top {
|
.grid-memes .card-img-top {
|
||||||
max-width: 100% !important;
|
max-width: 100% !important;
|
||||||
width: inherit;
|
object-fit: cover;
|
||||||
max-height: 20vw;
|
max-height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#social-links li {
|
#social-links li {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
Rate Limit: 60 Request Per Hour
|
Rate Limit: 60 Request Per Hour
|
||||||
</p>
|
</p>
|
||||||
<code>
|
<code>
|
||||||
<pre class="bg-white p-1">{{ $data['memes_example'] }}</pre>
|
<pre class="bg-light p-1">{{ $data['memes_example'] }}</pre>
|
||||||
</code>
|
</code>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
22
resources/views/contact.blade.php
Normal file
22
resources/views/contact.blade.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-12 text-center">
|
||||||
|
<h1>FAQ</h1>
|
||||||
|
<hr>
|
||||||
|
<h3>I recieved a tip but I haven't been paid yet. When will I get paid?</h3>
|
||||||
|
<p>Payments usually go out a few times an hour however there can be a delay. Please submit an issue if you have not been paid after 24 hours.</p>
|
||||||
|
<hr>
|
||||||
|
<h3>Is this website created by Monero?</h3>
|
||||||
|
<p>Monero is a decentralized organization. This website was created by a developer who likes Monero and should not be seen as "official".</p>
|
||||||
|
<hr>
|
||||||
|
<h3>Someone stole my memes. What can I do?</h3>
|
||||||
|
<p>Please submit an issue with proof you are the creator of the meme.</p>
|
||||||
|
<hr>
|
||||||
|
<a class="btn btn-primary" href="https://repo.getmonero.org/AnonDev/xmrmemes/-/issues" target="_blank" role="button">Submit Issues on Gitlab</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@if ($data['memes_pending'])
|
@if ($data['memes_pending'])
|
||||||
<div class="row row-cols-1 row-cols-md-4 grid-memes mt-3">
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-4 grid-memes mt-3">
|
||||||
@foreach ($data['memes_pending'] as $meme)
|
@foreach ($data['memes_pending'] as $meme)
|
||||||
<div class="col mb-4">
|
<div class="col mb-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
@ -5,17 +5,12 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-4 grid-memes">
|
||||||
<div class="row row-cols-1 row-cols-md-4 grid-memes">
|
|
||||||
@foreach ($data['memes'] as $meme)
|
@foreach ($data['memes'] as $meme)
|
||||||
<div class="col mb-4">
|
<div class="col mb-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<a href="{{ url('/meme/' . $meme->id) }}">
|
<a href="{{ url('/meme/' . $meme->id) }}">
|
||||||
@if ($meme->image)
|
|
||||||
<img src="{{ url($meme->image) }}" class="card-img-top mx-auto d-block" alt="{{ $meme->title }} Meme">
|
<img src="{{ url($meme->image) }}" class="card-img-top mx-auto d-block" alt="{{ $meme->title }} Meme">
|
||||||
@else
|
|
||||||
<img src="https://picsum.photos/200" class="card-img-top" alt="{{ $meme->title }} Meme">
|
|
||||||
@endif
|
|
||||||
</a>
|
</a>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<a href="{{ url('/meme/' . $meme->id) }}">
|
<a href="{{ url('/meme/' . $meme->id) }}">
|
||||||
@ -29,11 +24,9 @@
|
|||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex justify-content-center w-100">
|
<div class="d-flex justify-content-center w-100">
|
||||||
{{ $data['memes']->links() }}
|
{{ $data['memes']->links() }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -138,9 +138,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-6 col-md">
|
<div class="col-6 col-md">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li><a href="#">Contact</a></li>
|
<li><a href="https://repo.getmonero.org/AnonDev/xmrmemes" target="_blank">Source Code</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6 col-md">
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li><a href="{{ route('contact') }}">Contact</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mt-4">
|
||||||
|
<a class="small text-muted" href="https://ccs.getmonero.org/" target="_blank">Proudly crowd funded by Monero's Community Crowdfunding System (CCS)</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
@ -21,13 +21,9 @@
|
|||||||
@endif
|
@endif
|
||||||
<p class="card-text">By: <a href="{{ url('/user/' . $data['meme']->user->id) }}">{{ $data['meme']->user->name }}</a></p>
|
<p class="card-text">By: <a href="{{ url('/user/' . $data['meme']->user->id) }}">{{ $data['meme']->user->name }}</a></p>
|
||||||
</div>
|
</div>
|
||||||
@if ($data['meme']->image)
|
|
||||||
<a href="{{ url($data['meme']->image) }}">
|
<a href="{{ url($data['meme']->image) }}">
|
||||||
<img src="{{ url($data['meme']->image) }}" class="card-img-top" alt="{{ $data['meme']->title }} Meme">
|
<img src="{{ url($data['meme']->image) }}" class="card-img-top" alt="{{ $data['meme']->title }} Meme">
|
||||||
</a>
|
</a>
|
||||||
@else
|
|
||||||
<img src="https://picsum.photos/800" class="card-img-top" alt="{{ $data['meme']->title }} Meme">
|
|
||||||
@endif
|
|
||||||
<div class="card-body p-0 pt-3">
|
<div class="card-body p-0 pt-3">
|
||||||
{!!html_entity_decode($data['share'])!!}
|
{!!html_entity_decode($data['share'])!!}
|
||||||
</div>
|
</div>
|
||||||
@ -42,7 +38,7 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<h3 class="mt-4 mb-0">Tip The Creator</h3>
|
<h3 class="mt-4 mb-0">Tip The Creator</h3>
|
||||||
<img class="img-qr" src="{{ $data['qr'] }}" alt="QR code">
|
<img class="img-qr" src="{{ $data['qr'] }}" alt="QR code">
|
||||||
<p class="text-break">{{ $data['meme']->address->address }}</p>
|
<p class="text-break">{{ $data['meme']->address }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-lg-6">
|
<div class="col-12 col-lg-6">
|
||||||
<h4 class="mt-4">Monero Tips Recieved</h4>
|
<h4 class="mt-4">Monero Tips Recieved</h4>
|
||||||
@ -62,7 +58,7 @@
|
|||||||
<td>{{ $tip->amount_formatted }}</td>
|
<td>{{ $tip->amount_formatted }}</td>
|
||||||
<td>{{ $tip->created_at->diffForHumans() }}</td>
|
<td>{{ $tip->created_at->diffForHumans() }}</td>
|
||||||
<td class="text-truncate">
|
<td class="text-truncate">
|
||||||
<a href="https://testnet.xmrchain.net/tx/{{ $tip->txid }}" target="_blank">
|
<a href="{{ $tip->tx_url }}" target="_blank">
|
||||||
{{ $tip->txid }}
|
{{ $tip->txid }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
@ -91,7 +87,7 @@
|
|||||||
<td>{{ $tip->amount_formatted }}</td>
|
<td>{{ $tip->amount_formatted }}</td>
|
||||||
<td>{{ $tip->created_at->diffForHumans() }}</td>
|
<td>{{ $tip->created_at->diffForHumans() }}</td>
|
||||||
<td class="text-truncate">
|
<td class="text-truncate">
|
||||||
<a href="https://testnet.xmrchain.net/tx/{{ $tip->txid }}" target="_blank">
|
<a href="{{ $tip->tx_url }}" target="_blank">
|
||||||
{{ $tip->txid }}
|
{{ $tip->txid }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<h3 class="text-center mb-4">Memes By {{ $data['user']->name }}</h3>
|
<h3 class="text-center mb-3">Memes By {{ $data['user']->name }}</h3>
|
||||||
<p class="text-center">Total Earnings: {{ $data['user']->tips_total }}</h3>
|
<p class="text-center">Total Earnings: {{ $data['user']->tips_total }}</h3>
|
||||||
<p class="text-center">Total Memes: {{ $data['user']->memes_total }}</h3>
|
<p class="text-center">Total Memes: {{ $data['user']->memes_total }}</h3>
|
||||||
<div class="row row-cols-1 row-cols-md-4 grid-memes">
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-4 grid-memes">
|
||||||
@foreach ($data['memes'] as $meme)
|
@foreach ($data['memes'] as $meme)
|
||||||
<div class="col mb-4">
|
<div class="col mb-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
@ -17,6 +17,7 @@ use Illuminate\Support\Facades\Route;
|
|||||||
Auth::routes();
|
Auth::routes();
|
||||||
Route::get('/', [App\Http\Controllers\MemeController::class, 'index'])->name('homepage');
|
Route::get('/', [App\Http\Controllers\MemeController::class, 'index'])->name('homepage');
|
||||||
Route::get('/about', [App\Http\Controllers\AboutController::class, 'index'])->name('about');
|
Route::get('/about', [App\Http\Controllers\AboutController::class, 'index'])->name('about');
|
||||||
|
Route::get('/contact', [App\Http\Controllers\ContactController::class, 'index'])->name('contact');
|
||||||
Route::get('meme/{id}', [App\Http\Controllers\MemeController::class, 'show'])->name('meme');
|
Route::get('meme/{id}', [App\Http\Controllers\MemeController::class, 'show'])->name('meme');
|
||||||
Route::get('meme/approve/{id}', [App\Http\Controllers\MemeController::class, 'approve']);
|
Route::get('meme/approve/{id}', [App\Http\Controllers\MemeController::class, 'approve']);
|
||||||
Route::get('meme/destroy/{id}', [App\Http\Controllers\MemeController::class, 'destroy']);
|
Route::get('meme/destroy/{id}', [App\Http\Controllers\MemeController::class, 'destroy']);
|
||||||
|
Loading…
Reference in New Issue
Block a user