-
Notifications
You must be signed in to change notification settings - Fork 0
TWA 세팅 및 적용 #270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TWA 세팅 및 적용 #270
Changes from all commits
d7eeeed
41028fd
dbc2683
ef5604d
f4a3a54
86e6458
867866f
5c63807
6062f39
ed606e2
485a1e2
cc68f33
5482119
6c0db75
2da3d2f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| name: Crawl All TJ Song By Number | ||
|
|
||
| on: | ||
| workflow_dispatch: # 수동 실행 전용 | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| run-npm-task: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| # 6시간 잡 제한 안에서 전 대역을 커버하기 위해 1만 단위로 구간을 나눠 병렬 실행 | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| range: | ||
| - { start: 1, end: 10000 } | ||
| - { start: 10001, end: 20000 } | ||
| - { start: 20001, end: 30000 } | ||
| - { start: 30001, end: 40000 } | ||
| - { start: 40001, end: 50000 } | ||
| - { start: 50001, end: 60000 } | ||
| - { start: 60001, end: 70000 } | ||
| - { start: 70001, end: 80000 } | ||
| - { start: 80001, end: 90000 } | ||
| - { start: 90001, end: 99999 } | ||
|
|
||
| name: "crawl ${{ matrix.range.start }}-${{ matrix.range.end }}" | ||
|
|
||
| steps: | ||
| - name: Checkout branch | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Use Node.js 20 | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "20" | ||
|
|
||
| - name: Install pnpm | ||
| uses: pnpm/action-setup@v2 | ||
| with: | ||
| version: 9 | ||
| run_install: false | ||
|
|
||
| - name: Install dependencies | ||
| working-directory: packages/crawling | ||
| run: pnpm install | ||
|
|
||
| - name: Create .env file | ||
| working-directory: packages/crawling | ||
| run: | | ||
| echo "SUPABASE_URL=${{ secrets.SUPABASE_URL }}" >> .env | ||
| echo "SUPABASE_KEY=${{ secrets.SUPABASE_KEY }}" >> .env | ||
|
|
||
| - name: run script - crawlAllTJSongByNumber.ts | ||
| working-directory: packages/crawling | ||
| env: | ||
| START_NUMBER: ${{ matrix.range.start }} | ||
| END_NUMBER: ${{ matrix.range.end }} | ||
| run: pnpm run tj-all-number | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,27 @@ | ||
| # Android keystore — 외부 백업 필수, git에 절대 커밋하지 않는다 | ||
| *.keystore | ||
| *.jks | ||
| *.keystore.bak* | ||
| android.keystore.bak* | ||
|
|
||
| # Bubblewrap 빌드 산출물 | ||
| android/ | ||
| output/ | ||
| app/ | ||
| *.aab | ||
| *.apk | ||
| *.apk.idsig | ||
|
|
||
| # Gradle 생성물 | ||
| .gradle/ | ||
| gradle/ | ||
| gradlew | ||
| gradlew.bat | ||
| build.gradle | ||
| settings.gradle | ||
| gradle.properties | ||
| manifest-checksum.txt | ||
| store_icon.png | ||
|
|
||
| # 수동 백업/복사본 | ||
| twa-manifest copy.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,17 @@ | ||
| { | ||
| "packageId": "kr.singcode.app", | ||
| "host": "singcode.kr", | ||
| "name": "Singcode - 당신의 노래방 메모장", | ||
| "name": "싱코드(singcode) - 노래방 번호 검색", | ||
| "launcherName": "Singcode", | ||
| "display": "standalone", | ||
| "themeColor": "#1a1a2e", | ||
| "navigationColor": "#1a1a2e", | ||
| "navigationColorDark": "#1a1a2e", | ||
| "navigationDividerColor": "#1a1a2e", | ||
| "navigationDividerColorDark": "#1a1a2e", | ||
| "backgroundColor": "#1a1a2e", | ||
| "enableNotifications": false, | ||
| "themeColor": "#1A1A2E", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. themecolor not #1a1a2e apps/twa/twa-manifest.json sets themeColor to #1A1A2E instead of the required lowercase #1a1a2e. This can break enforcement checks that expect the exact string and violates the mandated theme color value. Agent Prompt
|
||
| "themeColorDark": "#1A1A2E", | ||
| "navigationColor": "#1A1A2E", | ||
| "navigationColorDark": "#1A1A2E", | ||
| "navigationDividerColor": "#1A1A2E", | ||
| "navigationDividerColorDark": "#1A1A2E", | ||
| "backgroundColor": "#1A1A2E", | ||
| "enableNotifications": true, | ||
| "startUrl": "/", | ||
| "iconUrl": "https://singcode.kr/icons/icon-512.png", | ||
| "maskableIconUrl": "https://singcode.kr/icons/icon-maskable-512.png", | ||
|
|
@@ -20,20 +21,13 @@ | |
| "path": "./android.keystore", | ||
| "alias": "singcode" | ||
| }, | ||
| "appVersionCode": 1, | ||
| "appVersionName": "1.0.0", | ||
| "appVersionName": "3", | ||
| "appVersionCode": 3, | ||
| "shortcuts": [], | ||
| "generatorApp": "bubblewrap-cli", | ||
| "webManifestUrl": "https://singcode.kr/manifest.webmanifest", | ||
| "fallbackType": "customtabs", | ||
| "features": { | ||
| "locationDelegation": { | ||
| "enabled": false | ||
| }, | ||
| "playBilling": { | ||
| "enabled": false | ||
| } | ||
| }, | ||
| "features": {}, | ||
| "alphaDependencies": { | ||
| "enabled": false | ||
| }, | ||
|
|
@@ -42,5 +36,13 @@ | |
| "isMetaQuest": false, | ||
| "fullScopeUrl": "https://singcode.kr/", | ||
| "minSdkVersion": 21, | ||
| "orientation": "portrait" | ||
| "orientation": "portrait", | ||
| "fingerprints": [], | ||
| "additionalTrustedOrigins": [], | ||
| "retainedBundles": [], | ||
| "protocolHandlers": [], | ||
| "fileHandlers": [], | ||
| "launchHandlerClientMode": "", | ||
| "displayOverride": [], | ||
| "appVersion": "3" | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,8 +22,10 @@ export const crawlTJSongByNumber = async ( | |
|
|
||
| const gridContainer = $('.grid-container.list.ico').first(); | ||
|
|
||
| const title = gridContainer.find('.grid-item.title3').text().trim(); | ||
| const artist = gridContainer.find('.grid-item.title4').text().trim(); | ||
| // title3 내부에는 아이콘용 <p class="no-ico">가 div.flex-box > ul 안에 중첩돼 있으므로 | ||
| // 자손 셀렉터(' p') 대신 직계 자식(' > p')만 선택해 실제 제목만 추출한다. | ||
| const title = gridContainer.find('.grid-item.title3 span').text().trim(); | ||
| const artist = gridContainer.find('.grid-item.title4 span').text().trim(); | ||
|
Comment on lines
+25
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 5. Misleading tj selector comment The comment says to use a direct-child > p selector to avoid nested icon markup, but the implementation selects span elements instead. This mismatch makes future maintenance risky because the rationale and the actual selector no longer align. Agent Prompt
|
||
|
|
||
| if (!title || !artist) { | ||
| console.log('❌ TJ 검색 결과 없음'); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,7 @@ export async function getSongsJpnDB() { | |
| return hasJapaneseData; | ||
| } | ||
|
|
||
| export async function getSongsKyNullDB(max: number = 50000) { | ||
| export async function getSongsKyNullDB(max: number = 100000) { | ||
| const supabase = getClient(); | ||
|
|
||
| const { data, error } = await supabase | ||
|
|
@@ -48,7 +48,7 @@ export async function getSongsKyNullDB(max: number = 50000) { | |
| return data; | ||
| } | ||
|
|
||
| export async function getSongsKyNotNullDB(max: number = 50000) { | ||
| export async function getSongsKyNotNullDB(max: number = 100000) { | ||
| const supabase = getClient(); | ||
|
|
||
| const { data, error } = await supabase | ||
|
Comment on lines
+51
to
54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3. Excessive supabase overfetch The default max for several DB fetch functions was increased to 100,000, but callers often process only a small prefix (e.g., verify job stops at 5,000; tagging stops at 20,000). This creates unnecessary data transfer and memory usage each run. Agent Prompt
|
||
|
|
@@ -85,7 +85,7 @@ export async function getVerifyKySongsDB(): Promise<Set<string>> { | |
| return new Set(data.map(row => row.id)); | ||
| } | ||
|
|
||
| export async function getSongsAllDB(max: number = 50000) { | ||
| export async function getSongsAllDB(max: number = 100000) { | ||
| const supabase = getClient(); | ||
|
|
||
| const { data, error } = await supabase | ||
|
Comment on lines
+88
to
91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Db queries truncate silently Several getDB() helpers use .limit(100000) without pagination, but callers treat the results as complete (e.g., building num_tj maps or “already tagged” sets). Once tables exceed 100k rows, this silently breaks dedupe/skip logic and can lead to duplicate inserts or redundant processing. Agent Prompt
|
||
|
|
@@ -121,7 +121,7 @@ export async function getJpopSongsForTranslationDB() { | |
| .from('songs') | ||
| .select('id, title, artist, title_ko, artist_ko, song_tags!inner(tag_id)') | ||
| .eq('song_tags.tag_id', 101) | ||
| .limit(50000); | ||
| .limit(100000); | ||
|
|
||
| if (error) throw error; | ||
|
|
||
|
|
@@ -138,7 +138,7 @@ export async function getArtistKoMapDB(): Promise<Map<string, string>> { | |
| .select('artist, artist_ko, song_tags!inner(tag_id)') | ||
| .eq('song_tags.tag_id', 101) | ||
| .not('artist_ko', 'is', null) | ||
| .limit(50000); | ||
| .limit(100000); | ||
|
|
||
| if (error) throw error; | ||
|
|
||
|
|
@@ -155,7 +155,7 @@ export async function getArtistKoMapDB(): Promise<Map<string, string>> { | |
| export async function getSongTagSongIdsDB(): Promise<Set<string>> { | ||
| const supabase = getClient(); | ||
|
|
||
| const { data, error } = await supabase.from('song_tags').select('song_id').limit(50000); | ||
| const { data, error } = await supabase.from('song_tags').select('song_id').limit(100000); | ||
|
|
||
| if (error) throw error; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4. Workflow has write permission
🐞 Bug⛨ SecurityAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools