init
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Environment variables service
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The `Env.create` method creates an instance of the Env service. The
|
||||
| service validates the environment variables and also cast values
|
||||
| to JavaScript data types.
|
||||
|
|
||||
*/
|
||||
|
||||
import { Env } from '@adonisjs/core/env'
|
||||
|
||||
export default await Env.create(new URL('../', import.meta.url), {
|
||||
NODE_ENV: Env.schema.enum(['development', 'production', 'test'] as const),
|
||||
PORT: Env.schema.number(),
|
||||
APP_KEY: Env.schema.string(),
|
||||
HOST: Env.schema.string({ format: 'host' }),
|
||||
LOG_LEVEL: Env.schema.string(),
|
||||
|
||||
/*
|
||||
|----------------------------------------------------------
|
||||
| Variables for configuring session package
|
||||
|----------------------------------------------------------
|
||||
*/
|
||||
SESSION_DRIVER: Env.schema.enum(['cookie', 'memory'] as const),
|
||||
|
||||
/*
|
||||
|----------------------------------------------------------
|
||||
| Variables for configuring database connection
|
||||
|----------------------------------------------------------
|
||||
*/
|
||||
DB_HOST: Env.schema.string({ format: 'host' }),
|
||||
DB_PORT: Env.schema.number(),
|
||||
DB_USER: Env.schema.string(),
|
||||
DB_PASSWORD: Env.schema.string.optional(),
|
||||
DB_DATABASE: Env.schema.string(),
|
||||
|
||||
/*
|
||||
|----------------------------------------------------------
|
||||
| Variables for Telegram bot
|
||||
|----------------------------------------------------------
|
||||
*/
|
||||
TELEGRAM_BOT_TOKEN: Env.schema.string(),
|
||||
})
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTP kernel file
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The HTTP kernel file is used to register the middleware with the server
|
||||
| or the router.
|
||||
|
|
||||
*/
|
||||
|
||||
import router from '@adonisjs/core/services/router'
|
||||
import server from '@adonisjs/core/services/server'
|
||||
|
||||
/**
|
||||
* The error handler is used to convert an exception
|
||||
* to an HTTP response.
|
||||
*/
|
||||
server.errorHandler(() => import('#exceptions/handler'))
|
||||
|
||||
/**
|
||||
* The server middleware stack runs middleware on all the HTTP
|
||||
* requests, even if there is no route registered for
|
||||
* the request URL.
|
||||
*/
|
||||
server.use([
|
||||
() => import('#middleware/container_bindings_middleware'),
|
||||
() => import('@adonisjs/static/static_middleware'),
|
||||
() => import('@adonisjs/vite/vite_middleware'),
|
||||
])
|
||||
|
||||
/**
|
||||
* The router middleware stack runs middleware on all the HTTP
|
||||
* requests with a registered route.
|
||||
*/
|
||||
router.use([
|
||||
() => import('@adonisjs/core/bodyparser_middleware'),
|
||||
() => import('@adonisjs/session/session_middleware'),
|
||||
() => import('@adonisjs/shield/shield_middleware'),
|
||||
() => import('@adonisjs/auth/initialize_auth_middleware')
|
||||
])
|
||||
|
||||
/**
|
||||
* Named middleware collection must be explicitly assigned to
|
||||
* the routes or the routes group.
|
||||
*/
|
||||
export const middleware = router.named({
|
||||
guest: () => import('#middleware/guest_middleware'),
|
||||
auth: () => import('#middleware/auth_middleware')
|
||||
})
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Routes file
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The routes file is used for defining the HTTP routes.
|
||||
|
|
||||
*/
|
||||
|
||||
import router from '@adonisjs/core/services/router'
|
||||
|
||||
const KeywordsController = () => import('#controllers/keywords_controller')
|
||||
const AuctionsController = () => import('#controllers/auctions_controller')
|
||||
const ParseLogsController = () => import('#controllers/parse_logs_controller')
|
||||
|
||||
router.on('/').render('pages/home')
|
||||
|
||||
// Health check endpoint for Docker
|
||||
router.get('/health', async ({ response }) => {
|
||||
return response.ok({ status: 'ok', timestamp: new Date().toISOString() })
|
||||
})
|
||||
|
||||
// List recent auctions (last 3 days)
|
||||
router.get('/list', [AuctionsController, 'list'])
|
||||
|
||||
// HTML view of recent auctions (last 3 days)
|
||||
router.get('/list-view', [AuctionsController, 'listView'])
|
||||
|
||||
// Trigger auction parsing
|
||||
router.post('/trigger-parse', [AuctionsController, 'triggerParse'])
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Routes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
router.group(() => {
|
||||
// Keywords
|
||||
router.get('/keywords', [KeywordsController, 'index'])
|
||||
router.post('/keywords', [KeywordsController, 'store'])
|
||||
router.delete('/keywords/:id', [KeywordsController, 'destroy'])
|
||||
|
||||
// Auctions
|
||||
router.get('/auctions/search', [AuctionsController, 'search'])
|
||||
router.get('/auctions/:id', [AuctionsController, 'show'])
|
||||
router.get('/auctions', [AuctionsController, 'index'])
|
||||
|
||||
// Parse Logs
|
||||
router.get('/parse-logs', [ParseLogsController, 'index'])
|
||||
}).prefix('/api')
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Scheduler configuration
|
||||
*
|
||||
* This file defines all scheduled tasks for the application.
|
||||
* The scheduler runs in a separate process using: node ace scheduler:work
|
||||
*
|
||||
* Learn more: https://github.com/kabbouchi/adonisjs-scheduler
|
||||
*/
|
||||
|
||||
import scheduler from 'adonisjs-scheduler/services/main'
|
||||
import ParseAuctions from '../commands/parse_auctions.js'
|
||||
|
||||
/**
|
||||
* Schedule auction parsing every 6 hours
|
||||
*
|
||||
* This task will:
|
||||
* 1. Scrape auctions from icetrade.by
|
||||
* 2. Upsert them to the database
|
||||
* 3. Create notifications for keyword matches
|
||||
*
|
||||
* Configuration:
|
||||
* - Runs every 6 hours
|
||||
* - Prevents overlapping executions
|
||||
* - Scrapes 1 page by default (can be adjusted)
|
||||
*/
|
||||
scheduler
|
||||
.command(ParseAuctions, ['--pages=1'])
|
||||
.everySixHours()
|
||||
.withoutOverlapping()
|
||||
|
||||
/**
|
||||
* Alternative schedule options (uncomment to use):
|
||||
*
|
||||
* Run every hour:
|
||||
*/
|
||||
// scheduler.command(ParseAuctions).everyHour().withoutOverlapping()
|
||||
|
||||
/**
|
||||
* Run every 3 hours using cron:
|
||||
*/
|
||||
// scheduler.command(ParseAuctions).cron('0 *\/3 * * *').withoutOverlapping()
|
||||
|
||||
/**
|
||||
* Run at specific times (6am, 12pm, 6pm, 12am):
|
||||
*/
|
||||
// scheduler.command(ParseAuctions).cron('0 6,12,18,0 * * *').withoutOverlapping()
|
||||
|
||||
/**
|
||||
* Run every 30 minutes:
|
||||
*/
|
||||
// scheduler.command(ParseAuctions).everyThirtyMinutes().withoutOverlapping()
|
||||
|
||||
/**
|
||||
* Run daily at 3am:
|
||||
*/
|
||||
// scheduler.command(ParseAuctions).dailyAt('3:00').withoutOverlapping()
|
||||
Reference in New Issue
Block a user