서버 정상 동작 확인! 이제 Reddit 앱 발급이 필요해요.

---

## Reddit 앱 발급 (2분)

**1단계**: https://www.reddit.com/prefs/apps 접속 → **"are you a developer? create an app..."** 클릭

**2단계** 양식 입력:
- **name**: `WosCouponBot`
- **type**: `script` 선택
- **redirect uri**: `http://localhost` (아무거나 OK)

**3단계** 생성 후 표시되는 값 복사:
```
client_id:     앱 이름 아래 짧은 문자열 (14자리)
client_secret: "secret" 옆 긴 문자열
```

**4단계** EC2 서버 `.env`에 추가:
```bash
ssh -i ~/Desktop/hyoseung.pem ubuntu@3.34.1.212
echo "REDDIT_CLIENT_ID=여기" >> ~/autoCoupon/back/.env
echo "REDDIT_CLIENT_SECRET=여기" >> ~/autoCoupon/back/.env
```

**5단계** 서버 재시작 후 테스트:
```bash
kill $(ps aux | grep 'autoCoupon' | grep node | awk '{print $2}')
cd ~/autoCoupon/back && nohup node dist/main.js >> ~/autoCoupon/back.log 2>&1 &
curl -X POST http://localhost:3002/api/crawler/trigger
```

Reddit 앱 만들면 바로 테스트해볼 수 있어요!
This commit is contained in:
hyoseung930 2026-05-08 10:27:33 +09:00
parent 4514a26575
commit 07dfaaf71b
2 changed files with 43 additions and 4 deletions

View File

@ -5,3 +5,5 @@ DB_PASSWORD=486251daKWON@
DB_DATABASE=kakao
APP_PORT=3000
DISCORD_WEBHOOK_URL=
REDDIT_CLIENT_ID=
REDDIT_CLIENT_SECRET=

View File

@ -6,8 +6,8 @@ import axios from 'axios';
import { WosCoupon } from '../entities/wos-coupon.entity';
import { WosService } from '../wos/wos.service';
const REDDIT_SEARCH_URL =
'https://www.reddit.com/r/WhiteoutSurvival/search.json?q=gift+code+OR+redeem+code+OR+coupon&sort=new&restrict_sr=1&limit=25&t=week';
const REDDIT_OAUTH_URL = 'https://oauth.reddit.com/r/WhiteoutSurvival/search.json?q=gift+code+OR+redeem+code+OR+coupon&sort=new&restrict_sr=1&limit=25&t=week';
const REDDIT_TOKEN_URL = 'https://www.reddit.com/api/v1/access_token';
const COMMON_WORDS = new Set([
'THE', 'AND', 'FOR', 'ARE', 'BUT', 'NOT', 'YOU', 'ALL', 'ANY', 'CAN',
@ -33,6 +33,8 @@ const COMMON_WORDS = new Set([
export class CrawlerService {
private readonly logger = new Logger(CrawlerService.name);
private seenPostIds = new Set<string>();
private redditAccessToken: string | null = null;
private redditTokenExpiry = 0;
constructor(
@InjectRepository(WosCoupon)
@ -40,6 +42,34 @@ export class CrawlerService {
private readonly wosService: WosService,
) {}
private async getRedditToken(): Promise<string | null> {
const clientId = process.env.REDDIT_CLIENT_ID;
const clientSecret = process.env.REDDIT_CLIENT_SECRET;
if (!clientId || !clientSecret) return null;
if (this.redditAccessToken && Date.now() < this.redditTokenExpiry) {
return this.redditAccessToken;
}
try {
const resp = await axios.post(
REDDIT_TOKEN_URL,
new URLSearchParams({ grant_type: 'client_credentials' }),
{
auth: { username: clientId, password: clientSecret },
headers: { 'User-Agent': 'WosCouponBot/1.0 by wageulwageul' },
timeout: 10000,
},
);
this.redditAccessToken = resp.data.access_token;
this.redditTokenExpiry = Date.now() + (resp.data.expires_in - 60) * 1000;
return this.redditAccessToken;
} catch (err: any) {
this.logger.error(`Reddit 토큰 발급 실패: ${err.message}`);
return null;
}
}
private extractCodes(text: string): string[] {
const codePattern = /\b([A-Z][A-Z0-9]{4,19})\b/g;
const found = new Set<string>();
@ -97,9 +127,16 @@ export class CrawlerService {
let posts: any[] = [];
try {
const resp = await axios.get(REDDIT_SEARCH_URL, {
const token = await this.getRedditToken();
if (!token) {
this.logger.warn('Reddit OAuth 토큰 없음 - REDDIT_CLIENT_ID/SECRET 환경변수를 설정하세요');
return { found: 0, added: [] };
}
const resp = await axios.get(REDDIT_OAUTH_URL, {
headers: {
'User-Agent': 'WosCouponBot/1.0',
'Authorization': `Bearer ${token}`,
'User-Agent': 'WosCouponBot/1.0 by wageulwageul',
'Accept': 'application/json',
},
timeout: 10000,