mirror of
https://github.com/immich-app/data.immich.app.git
synced 2026-09-30 13:23:26 +08:00
feat: authenticated reddit requests (#365)
This commit is contained in:
Vendored
+2
@@ -9,4 +9,6 @@ interface WorkerEnv extends Omit<Env, 'ENVIRONMENT' | 'STAGE' | 'DEPLOYMENT_KEY'
|
||||
GITHUB_APP_ID: string;
|
||||
GITHUB_APP_PEM: string;
|
||||
GITHUB_APP_INSTALLATION_ID: string;
|
||||
REDDIT_OAUTH_CLIENT_ID: string;
|
||||
REDDIT_OAUTH_CLIENT_SECRET: string;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,10 @@ export default {
|
||||
scheduled: async (event, env) => {
|
||||
const influxProvider = new InfluxMetricsPushProvider(env.VMETRICS_DATA_API_URL, env.VMETRICS_DATA_WRITE_TOKEN);
|
||||
const metricsRepository = new MetricsPushRepository('immich_data_repository', {}, [influxProvider]);
|
||||
const redditWorker = new RedditIngestWorker(metricsRepository, asEnvTag(env));
|
||||
const redditWorker = new RedditIngestWorker(metricsRepository, asEnvTag(env), {
|
||||
clientId: env.REDDIT_OAUTH_CLIENT_ID,
|
||||
clientSecret: env.REDDIT_OAUTH_CLIENT_SECRET,
|
||||
});
|
||||
const discordWorker = new DiscordIngestWorker(metricsRepository, asEnvTag(env));
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import fetchRetry from 'fetch-retry';
|
||||
import { Buffer } from 'node:buffer';
|
||||
|
||||
const fetch = fetchRetry(globalThis.fetch, {
|
||||
retries: 3,
|
||||
@@ -14,14 +15,33 @@ export interface RedditAboutResponse {
|
||||
}
|
||||
|
||||
export class RedditRepository {
|
||||
private readonly userAgent = 'Mozilla/5.0 (compatible; ImmichDataBot/1.0)';
|
||||
private readonly userAgent = 'web:app.immich.data:v1.0.0 (by u/immichapp)';
|
||||
|
||||
async getSubredditData(subreddit: string): Promise<RedditSubredditData> {
|
||||
const url = `https://www.reddit.com/r/${subreddit}/about.json`;
|
||||
async getSubredditData(
|
||||
subreddit: string,
|
||||
oauthCredentials: { clientId: string; clientSecret: string },
|
||||
): Promise<RedditSubredditData> {
|
||||
const tokenRequest = await fetch('https://www.reddit.com/api/v1/access_token', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'User-Agent': this.userAgent,
|
||||
Authorization: `Basic ${Buffer.from(`${oauthCredentials.clientId}:${oauthCredentials.clientSecret}`).toString('base64')}`,
|
||||
},
|
||||
body: new URLSearchParams({ grant_type: 'client_credentials' }),
|
||||
});
|
||||
|
||||
if (!tokenRequest.ok) {
|
||||
throw new Error(`Failed to authenticate against Reddit: ${tokenRequest.status} ${tokenRequest.statusText}`);
|
||||
}
|
||||
|
||||
const { access_token } = (await tokenRequest.json()) as { access_token: string };
|
||||
|
||||
const url = `https://oauth.reddit.com/r/${subreddit}/about.json`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'User-Agent': this.userAgent,
|
||||
Authorization: `Bearer ${access_token}`,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -7,11 +7,12 @@ export class RedditIngestWorker {
|
||||
constructor(
|
||||
private metricsRepository: IMetricsPushRepository,
|
||||
private envTag: string,
|
||||
private oauthCredentials: { clientId: string; clientSecret: string },
|
||||
) {}
|
||||
|
||||
async fetchAndStoreCurrentMetrics(subreddit: string = 'immich') {
|
||||
try {
|
||||
const data = await this.redditRepository.getSubredditData(subreddit);
|
||||
const data = await this.redditRepository.getSubredditData(subreddit, this.oauthCredentials);
|
||||
|
||||
const metric = new Metric('reddit_subscriber')
|
||||
.intField('total', data.subscribers)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"module": "es2022" /* Specify what module code is generated. */,
|
||||
"baseUrl": "./",
|
||||
"moduleResolution": "Bundler" /* Specify how TypeScript looks up a file from a given module specifier. */,
|
||||
"types": ["@cloudflare/workers-types"],
|
||||
"types": ["@cloudflare/workers-types", "node"],
|
||||
"resolveJsonModule": true /* Enable importing .json files */,
|
||||
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
|
||||
"checkJs": false /* Enable error reporting in type-checked JavaScript files. */,
|
||||
|
||||
@@ -12,4 +12,6 @@ export TF_VAR_github_app_tofu_pem_file="op://tf/GITHUB_APP_IMMICH_TOFU/pkcs1"
|
||||
export TF_VAR_github_app_read_only_installation_id="op://tf/GITHUB_APP_IMMICH_READ_ONLY/installation_id"
|
||||
export TF_VAR_github_app_read_only_id="op://tf/GITHUB_APP_IMMICH_READ_ONLY/app_id"
|
||||
export TF_VAR_github_app_read_only_pem_file_pkcs8="op://tf/GITHUB_APP_IMMICH_READ_ONLY/pkcs8"
|
||||
export TF_VAR_reddit_oauth_client_id="op://tf/REDDIT_OAUTH_CLIENT/client_id"
|
||||
export TF_VAR_reddit_oauth_client_secret="op://tf/REDDIT_OAUTH_CLIENT/client_secret"
|
||||
export TF_VAR_env=$ENVIRONMENT
|
||||
|
||||
@@ -10,3 +10,5 @@ variable "stage" {
|
||||
variable "github_app_read_only_id" {}
|
||||
variable "github_app_read_only_installation_id" {}
|
||||
variable "github_app_read_only_pem_file_pkcs8" {}
|
||||
variable "reddit_oauth_client_id" {}
|
||||
variable "reddit_oauth_client_secret" {}
|
||||
|
||||
@@ -165,6 +165,16 @@ resource "cloudflare_workers_script" "data_ingest_cron" {
|
||||
text = var.vmetrics_data_write_token
|
||||
}
|
||||
|
||||
secret_text_binding {
|
||||
name = "REDDIT_OAUTH_CLIENT_ID"
|
||||
text = var.reddit_oauth_client_id
|
||||
}
|
||||
|
||||
secret_text_binding {
|
||||
name = "REDDIT_OAUTH_CLIENT_SECRET"
|
||||
text = var.reddit_oauth_client_secret
|
||||
}
|
||||
|
||||
compatibility_date = "2025-09-17"
|
||||
compatibility_flags = ["nodejs_compat"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user