2024-05-19 20:57:04 +00:00
|
|
|
import { NostrEvent, NostrSigner, NStore, NUploader } from '@nostrify/nostrify';
|
2024-05-01 21:14:50 +00:00
|
|
|
import Debug from '@soapbox/stickynotes/debug';
|
2024-04-30 17:55:39 +00:00
|
|
|
import { type Context, Env as HonoEnv, type Handler, Hono, Input as HonoInput, type MiddlewareHandler } from 'hono';
|
2024-04-20 23:54:15 +00:00
|
|
|
import { cors, logger, serveStatic } from 'hono/middleware';
|
2024-04-19 21:39:35 +00:00
|
|
|
|
2024-05-14 21:25:24 +00:00
|
|
|
import { Conf } from '@/config.ts';
|
|
|
|
import { startFirehose } from '@/firehose.ts';
|
2023-12-04 19:19:20 +00:00
|
|
|
import { Time } from '@/utils.ts';
|
2023-03-05 01:55:28 +00:00
|
|
|
|
2023-04-29 21:35:44 +00:00
|
|
|
import {
|
|
|
|
accountController,
|
|
|
|
accountLookupController,
|
|
|
|
accountSearchController,
|
2023-05-03 20:22:24 +00:00
|
|
|
accountStatusesController,
|
2023-07-08 16:20:10 +00:00
|
|
|
createAccountController,
|
2023-09-01 18:14:27 +00:00
|
|
|
favouritesController,
|
2023-08-19 18:34:35 +00:00
|
|
|
followController,
|
2023-08-30 15:27:45 +00:00
|
|
|
followersController,
|
|
|
|
followingController,
|
2024-05-02 20:26:46 +00:00
|
|
|
muteController,
|
2023-04-29 22:59:42 +00:00
|
|
|
relationshipsController,
|
2024-01-01 18:50:09 +00:00
|
|
|
unfollowController,
|
2024-05-02 20:26:46 +00:00
|
|
|
unmuteController,
|
2023-06-11 19:41:16 +00:00
|
|
|
updateCredentialsController,
|
2023-05-20 19:44:18 +00:00
|
|
|
verifyCredentialsController,
|
2024-04-03 22:39:06 +00:00
|
|
|
} from '@/controllers/api/accounts.ts';
|
2024-05-08 23:08:44 +00:00
|
|
|
import { adminAccountAction, adminAccountsController } from '@/controllers/api/admin.ts';
|
2024-04-03 22:39:06 +00:00
|
|
|
import { appCredentialsController, createAppController } from '@/controllers/api/apps.ts';
|
2024-05-02 20:34:17 +00:00
|
|
|
import { blocksController } from '@/controllers/api/blocks.ts';
|
2024-04-03 22:39:06 +00:00
|
|
|
import { bookmarksController } from '@/controllers/api/bookmarks.ts';
|
2024-05-14 16:30:45 +00:00
|
|
|
import { adminRelaysController, adminSetRelaysController } from '@/controllers/api/ditto.ts';
|
2024-04-03 22:39:06 +00:00
|
|
|
import { emptyArrayController, emptyObjectController, notImplementedController } from '@/controllers/api/fallback.ts';
|
|
|
|
import { instanceController } from '@/controllers/api/instance.ts';
|
2024-05-03 21:17:36 +00:00
|
|
|
import { markersController, updateMarkersController } from '@/controllers/api/markers.ts';
|
2024-04-03 22:39:06 +00:00
|
|
|
import { mediaController } from '@/controllers/api/media.ts';
|
2024-05-02 20:26:46 +00:00
|
|
|
import { mutesController } from '@/controllers/api/mutes.ts';
|
2024-04-03 22:39:06 +00:00
|
|
|
import { notificationsController } from '@/controllers/api/notifications.ts';
|
|
|
|
import { createTokenController, oauthAuthorizeController, oauthController } from '@/controllers/api/oauth.ts';
|
2024-01-12 00:47:26 +00:00
|
|
|
import {
|
|
|
|
configController,
|
|
|
|
frontendConfigController,
|
|
|
|
pleromaAdminDeleteStatusController,
|
|
|
|
updateConfigController,
|
2024-04-03 22:39:06 +00:00
|
|
|
} from '@/controllers/api/pleroma.ts';
|
|
|
|
import { preferencesController } from '@/controllers/api/preferences.ts';
|
|
|
|
import { relayController } from '@/controllers/nostr/relay.ts';
|
2024-05-07 23:49:42 +00:00
|
|
|
import {
|
|
|
|
adminReportController,
|
|
|
|
adminReportResolveController,
|
|
|
|
adminReportsController,
|
2024-05-08 19:59:30 +00:00
|
|
|
reportController,
|
2024-05-07 23:49:42 +00:00
|
|
|
} from '@/controllers/api/reports.ts';
|
2024-04-03 22:39:06 +00:00
|
|
|
import { searchController } from '@/controllers/api/search.ts';
|
2023-05-07 17:32:24 +00:00
|
|
|
import {
|
2024-01-01 19:45:07 +00:00
|
|
|
bookmarkController,
|
2023-05-07 17:32:24 +00:00
|
|
|
contextController,
|
|
|
|
createStatusController,
|
2024-03-30 18:34:18 +00:00
|
|
|
deleteStatusController,
|
2023-05-07 17:32:24 +00:00
|
|
|
favouriteController,
|
2023-08-29 23:08:00 +00:00
|
|
|
favouritedByController,
|
2024-01-01 22:23:08 +00:00
|
|
|
pinController,
|
2023-08-29 23:08:00 +00:00
|
|
|
rebloggedByController,
|
2024-04-05 22:44:12 +00:00
|
|
|
reblogStatusController,
|
2023-05-07 17:32:24 +00:00
|
|
|
statusController,
|
2024-01-01 20:35:46 +00:00
|
|
|
unbookmarkController,
|
2024-01-01 22:23:08 +00:00
|
|
|
unpinController,
|
2024-04-09 21:27:17 +00:00
|
|
|
unreblogStatusController,
|
2024-01-15 22:43:56 +00:00
|
|
|
zapController,
|
2024-04-03 22:39:06 +00:00
|
|
|
} from '@/controllers/api/statuses.ts';
|
|
|
|
import { streamingController } from '@/controllers/api/streaming.ts';
|
2024-05-03 23:21:40 +00:00
|
|
|
import { suggestionsV1Controller, suggestionsV2Controller } from '@/controllers/api/suggestions.ts';
|
2023-08-29 17:41:14 +00:00
|
|
|
import {
|
|
|
|
hashtagTimelineController,
|
|
|
|
homeTimelineController,
|
|
|
|
publicTimelineController,
|
2024-04-03 22:39:06 +00:00
|
|
|
} from '@/controllers/api/timelines.ts';
|
2024-05-22 00:48:26 +00:00
|
|
|
import { trendingStatusesController, trendingTagsController } from '@/controllers/api/trends.ts';
|
2024-04-03 22:39:06 +00:00
|
|
|
import { indexController } from '@/controllers/site.ts';
|
|
|
|
import { nodeInfoController, nodeInfoSchemaController } from '@/controllers/well-known/nodeinfo.ts';
|
|
|
|
import { nostrController } from '@/controllers/well-known/nostr.ts';
|
2024-05-14 17:07:54 +00:00
|
|
|
import { auth98Middleware, requireProof, requireRole } from '@/middleware/auth98Middleware.ts';
|
|
|
|
import { cacheMiddleware } from '@/middleware/cacheMiddleware.ts';
|
|
|
|
import { cspMiddleware } from '@/middleware/cspMiddleware.ts';
|
2024-05-14 16:42:53 +00:00
|
|
|
import { requireSigner } from '@/middleware/requireSigner.ts';
|
2024-05-14 16:30:45 +00:00
|
|
|
import { signerMiddleware } from '@/middleware/signerMiddleware.ts';
|
2024-05-14 17:07:54 +00:00
|
|
|
import { storeMiddleware } from '@/middleware/storeMiddleware.ts';
|
2024-05-02 20:34:17 +00:00
|
|
|
import { blockController } from '@/controllers/api/accounts.ts';
|
|
|
|
import { unblockController } from '@/controllers/api/accounts.ts';
|
2024-05-19 03:00:24 +00:00
|
|
|
import { uploaderMiddleware } from '@/middleware/uploaderMiddleware.ts';
|
2023-03-05 02:19:57 +00:00
|
|
|
|
2023-04-29 20:22:10 +00:00
|
|
|
interface AppEnv extends HonoEnv {
|
|
|
|
Variables: {
|
2024-05-14 16:30:45 +00:00
|
|
|
/** Signer to get the logged-in user's pubkey, relays, and to sign events, or `undefined` if the user isn't logged in. */
|
|
|
|
signer?: NostrSigner;
|
2024-05-19 03:00:24 +00:00
|
|
|
/** Uploader for the user to upload files. */
|
2024-05-19 20:57:04 +00:00
|
|
|
uploader?: NUploader;
|
2023-07-08 23:41:11 +00:00
|
|
|
/** NIP-98 signed event proving the pubkey is owned by the user. */
|
2024-01-23 18:07:22 +00:00
|
|
|
proof?: NostrEvent;
|
2024-04-27 23:59:35 +00:00
|
|
|
/** Store */
|
2024-04-29 20:04:13 +00:00
|
|
|
store: NStore;
|
2023-04-29 20:22:10 +00:00
|
|
|
};
|
|
|
|
}
|
2023-03-05 01:55:28 +00:00
|
|
|
|
2023-04-29 20:22:10 +00:00
|
|
|
type AppContext = Context<AppEnv>;
|
|
|
|
type AppMiddleware = MiddlewareHandler<AppEnv>;
|
2024-04-20 23:54:15 +00:00
|
|
|
type AppController = Handler<AppEnv, any, HonoInput, Response | Promise<Response>>;
|
2023-04-29 20:22:10 +00:00
|
|
|
|
|
|
|
const app = new Hono<AppEnv>();
|
|
|
|
|
2023-12-28 03:57:10 +00:00
|
|
|
const debug = Debug('ditto:http');
|
|
|
|
|
2024-05-14 21:25:24 +00:00
|
|
|
if (Conf.firehoseEnabled) {
|
|
|
|
startFirehose();
|
|
|
|
}
|
|
|
|
|
2023-12-31 18:47:00 +00:00
|
|
|
app.use('/api/*', logger(debug));
|
|
|
|
app.use('/relay/*', logger(debug));
|
|
|
|
app.use('/.well-known/*', logger(debug));
|
|
|
|
app.use('/users/*', logger(debug));
|
|
|
|
app.use('/nodeinfo/*', logger(debug));
|
|
|
|
app.use('/oauth/*', logger(debug));
|
2023-05-13 22:41:21 +00:00
|
|
|
|
|
|
|
app.get('/api/v1/streaming', streamingController);
|
|
|
|
app.get('/api/v1/streaming/', streamingController);
|
2023-08-12 18:40:21 +00:00
|
|
|
app.get('/relay', relayController);
|
2023-05-13 22:41:21 +00:00
|
|
|
|
2024-05-14 16:30:45 +00:00
|
|
|
app.use(
|
|
|
|
'*',
|
2024-05-14 17:07:54 +00:00
|
|
|
cspMiddleware(),
|
2024-05-14 16:30:45 +00:00
|
|
|
cors({ origin: '*', exposeHeaders: ['link'] }),
|
2024-05-14 17:04:31 +00:00
|
|
|
signerMiddleware,
|
2024-05-19 03:00:24 +00:00
|
|
|
uploaderMiddleware,
|
2024-05-14 17:07:54 +00:00
|
|
|
auth98Middleware(),
|
2024-05-14 16:30:45 +00:00
|
|
|
storeMiddleware,
|
|
|
|
);
|
2023-03-05 04:49:08 +00:00
|
|
|
|
2023-07-10 01:32:45 +00:00
|
|
|
app.get('/.well-known/nodeinfo', nodeInfoController);
|
2023-07-09 17:55:37 +00:00
|
|
|
app.get('/.well-known/nostr.json', nostrController);
|
|
|
|
|
2023-07-10 01:32:45 +00:00
|
|
|
app.get('/nodeinfo/:version', nodeInfoSchemaController);
|
|
|
|
|
2024-05-14 17:07:54 +00:00
|
|
|
app.get('/api/v1/instance', cacheMiddleware({ cacheName: 'web', expires: Time.minutes(5) }), instanceController);
|
2023-03-05 01:55:28 +00:00
|
|
|
|
2023-03-05 03:49:33 +00:00
|
|
|
app.get('/api/v1/apps/verify_credentials', appCredentialsController);
|
2023-03-05 02:59:39 +00:00
|
|
|
app.post('/api/v1/apps', createAppController);
|
|
|
|
|
2023-03-05 03:36:53 +00:00
|
|
|
app.post('/oauth/token', createTokenController);
|
2023-03-05 06:36:37 +00:00
|
|
|
app.post('/oauth/revoke', emptyObjectController);
|
2023-04-30 18:28:49 +00:00
|
|
|
app.post('/oauth/authorize', oauthAuthorizeController);
|
|
|
|
app.get('/oauth/authorize', oauthController);
|
2023-03-05 03:36:53 +00:00
|
|
|
|
2023-11-20 23:57:47 +00:00
|
|
|
app.post('/api/v1/accounts', requireProof({ pow: 20 }), createAccountController);
|
2024-05-14 16:42:53 +00:00
|
|
|
app.get('/api/v1/accounts/verify_credentials', requireSigner, verifyCredentialsController);
|
|
|
|
app.patch('/api/v1/accounts/update_credentials', requireSigner, updateCredentialsController);
|
2023-04-29 21:28:53 +00:00
|
|
|
app.get('/api/v1/accounts/search', accountSearchController);
|
2023-04-29 21:23:23 +00:00
|
|
|
app.get('/api/v1/accounts/lookup', accountLookupController);
|
2024-05-14 16:42:53 +00:00
|
|
|
app.get('/api/v1/accounts/relationships', requireSigner, relationshipsController);
|
|
|
|
app.post('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/block', requireSigner, blockController);
|
|
|
|
app.post('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/unblock', requireSigner, unblockController);
|
|
|
|
app.post('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/mute', requireSigner, muteController);
|
|
|
|
app.post('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/unmute', requireSigner, unmuteController);
|
|
|
|
app.post('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/follow', requireSigner, followController);
|
|
|
|
app.post('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/unfollow', requireSigner, unfollowController);
|
2023-08-30 15:27:45 +00:00
|
|
|
app.get('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/followers', followersController);
|
|
|
|
app.get('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/following', followingController);
|
2023-05-03 20:22:24 +00:00
|
|
|
app.get('/api/v1/accounts/:pubkey{[0-9a-f]{64}}/statuses', accountStatusesController);
|
2023-04-29 21:35:44 +00:00
|
|
|
app.get('/api/v1/accounts/:pubkey{[0-9a-f]{64}}', accountController);
|
2023-03-05 03:49:33 +00:00
|
|
|
|
2023-08-29 23:08:00 +00:00
|
|
|
app.get('/api/v1/statuses/:id{[0-9a-f]{64}}/favourited_by', favouritedByController);
|
|
|
|
app.get('/api/v1/statuses/:id{[0-9a-f]{64}}/reblogged_by', rebloggedByController);
|
2023-04-30 01:23:51 +00:00
|
|
|
app.get('/api/v1/statuses/:id{[0-9a-f]{64}}/context', contextController);
|
2023-04-29 22:26:56 +00:00
|
|
|
app.get('/api/v1/statuses/:id{[0-9a-f]{64}}', statusController);
|
2024-05-14 16:42:53 +00:00
|
|
|
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/favourite', requireSigner, favouriteController);
|
|
|
|
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/bookmark', requireSigner, bookmarkController);
|
|
|
|
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unbookmark', requireSigner, unbookmarkController);
|
|
|
|
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/pin', requireSigner, pinController);
|
|
|
|
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unpin', requireSigner, unpinController);
|
|
|
|
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/zap', requireSigner, zapController);
|
|
|
|
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/reblog', requireSigner, reblogStatusController);
|
|
|
|
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unreblog', requireSigner, unreblogStatusController);
|
|
|
|
app.post('/api/v1/statuses', requireSigner, createStatusController);
|
|
|
|
app.delete('/api/v1/statuses/:id{[0-9a-f]{64}}', requireSigner, deleteStatusController);
|
2023-03-05 05:26:25 +00:00
|
|
|
|
2024-04-25 00:22:36 +00:00
|
|
|
app.post('/api/v1/media', mediaController);
|
|
|
|
app.post('/api/v2/media', mediaController);
|
2023-09-08 22:00:07 +00:00
|
|
|
|
2024-05-14 16:42:53 +00:00
|
|
|
app.get('/api/v1/timelines/home', requireSigner, homeTimelineController);
|
2024-04-29 20:04:13 +00:00
|
|
|
app.get('/api/v1/timelines/public', publicTimelineController);
|
2023-08-29 00:51:21 +00:00
|
|
|
app.get('/api/v1/timelines/tag/:hashtag', hashtagTimelineController);
|
2023-03-18 19:49:44 +00:00
|
|
|
|
2023-05-13 19:27:49 +00:00
|
|
|
app.get('/api/v1/preferences', preferencesController);
|
2023-05-13 19:45:13 +00:00
|
|
|
app.get('/api/v1/search', searchController);
|
|
|
|
app.get('/api/v2/search', searchController);
|
2023-05-13 19:27:49 +00:00
|
|
|
|
2024-04-19 14:37:53 +00:00
|
|
|
app.get('/api/pleroma/frontend_configurations', frontendConfigController);
|
2023-06-11 04:10:27 +00:00
|
|
|
|
2024-05-22 00:48:26 +00:00
|
|
|
app.get('/api/v1/trends/statuses', trendingStatusesController);
|
2024-05-21 23:15:17 +00:00
|
|
|
app.get('/api/v1/trends/tags', trendingTagsController);
|
|
|
|
app.get('/api/v1/trends', trendingTagsController);
|
2023-07-25 22:07:09 +00:00
|
|
|
|
2024-05-03 23:21:40 +00:00
|
|
|
app.get('/api/v1/suggestions', suggestionsV1Controller);
|
|
|
|
app.get('/api/v2/suggestions', suggestionsV2Controller);
|
|
|
|
|
2024-05-14 16:42:53 +00:00
|
|
|
app.get('/api/v1/notifications', requireSigner, notificationsController);
|
|
|
|
app.get('/api/v1/favourites', requireSigner, favouritesController);
|
|
|
|
app.get('/api/v1/bookmarks', requireSigner, bookmarksController);
|
|
|
|
app.get('/api/v1/blocks', requireSigner, blocksController);
|
|
|
|
app.get('/api/v1/mutes', requireSigner, mutesController);
|
2023-08-28 19:23:27 +00:00
|
|
|
|
2024-05-03 21:17:36 +00:00
|
|
|
app.get('/api/v1/markers', requireProof(), markersController);
|
|
|
|
app.post('/api/v1/markers', requireProof(), updateMarkersController);
|
|
|
|
|
2024-04-23 21:21:36 +00:00
|
|
|
app.get('/api/v1/admin/accounts', requireRole('admin'), adminAccountsController);
|
2024-01-09 00:01:24 +00:00
|
|
|
app.get('/api/v1/pleroma/admin/config', requireRole('admin'), configController);
|
2023-09-08 22:00:07 +00:00
|
|
|
app.post('/api/v1/pleroma/admin/config', requireRole('admin'), updateConfigController);
|
2024-01-12 00:47:26 +00:00
|
|
|
app.delete('/api/v1/pleroma/admin/statuses/:id', requireRole('admin'), pleromaAdminDeleteStatusController);
|
2023-09-03 23:49:45 +00:00
|
|
|
|
2024-04-23 21:21:36 +00:00
|
|
|
app.get('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysController);
|
2024-05-01 23:29:32 +00:00
|
|
|
app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysController);
|
2024-04-23 21:21:36 +00:00
|
|
|
|
2024-05-14 16:42:53 +00:00
|
|
|
app.post('/api/v1/reports', requireSigner, reportController);
|
|
|
|
app.get('/api/v1/admin/reports', requireSigner, requireRole('admin'), adminReportsController);
|
|
|
|
app.get('/api/v1/admin/reports/:id{[0-9a-f]{64}}', requireSigner, requireRole('admin'), adminReportController);
|
2024-05-07 23:49:42 +00:00
|
|
|
app.post(
|
|
|
|
'/api/v1/admin/reports/:id{[0-9a-f]{64}}/resolve',
|
2024-05-14 16:42:53 +00:00
|
|
|
requireSigner,
|
2024-05-07 23:49:42 +00:00
|
|
|
requireRole('admin'),
|
|
|
|
adminReportResolveController,
|
|
|
|
);
|
2024-05-01 23:38:30 +00:00
|
|
|
|
2024-05-14 16:42:53 +00:00
|
|
|
app.post('/api/v1/admin/accounts/:id{[0-9a-f]{64}}/action', requireSigner, requireRole('admin'), adminAccountAction);
|
2024-05-08 23:08:44 +00:00
|
|
|
|
2023-03-05 03:49:33 +00:00
|
|
|
// Not (yet) implemented.
|
2023-03-05 06:36:37 +00:00
|
|
|
app.get('/api/v1/custom_emojis', emptyArrayController);
|
|
|
|
app.get('/api/v1/filters', emptyArrayController);
|
|
|
|
app.get('/api/v1/domain_blocks', emptyArrayController);
|
2023-05-13 19:27:49 +00:00
|
|
|
app.get('/api/v1/conversations', emptyArrayController);
|
|
|
|
app.get('/api/v1/lists', emptyArrayController);
|
2023-03-05 03:49:33 +00:00
|
|
|
|
2023-09-11 09:55:15 +00:00
|
|
|
app.use('/api/*', notImplementedController);
|
|
|
|
|
2023-09-11 09:14:08 +00:00
|
|
|
app.get('*', serveStatic({ root: './public/' }));
|
2023-09-11 20:36:09 +00:00
|
|
|
app.get('*', serveStatic({ root: './static/' }));
|
2023-09-11 05:19:56 +00:00
|
|
|
app.get('*', serveStatic({ path: './public/index.html' }));
|
|
|
|
|
2023-04-30 19:51:56 +00:00
|
|
|
app.get('/', indexController);
|
|
|
|
|
2023-03-05 01:55:28 +00:00
|
|
|
export default app;
|
2023-04-29 20:22:10 +00:00
|
|
|
|
|
|
|
export type { AppContext, AppController, AppMiddleware };
|