Skip to content

Commit 4654a40

Browse files
committed
Initial Commit
0 parents  commit 4654a40

6 files changed

Lines changed: 2190 additions & 0 deletions

File tree

.gitignore

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Created by https://www.toptal.com/developers/gitignore/api/intellij+all,node
2+
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+all,node
3+
4+
### Intellij+all ###
5+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
6+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
7+
.idea/
8+
9+
# User-specific stuff
10+
.idea/**/workspace.xml
11+
.idea/**/tasks.xml
12+
.idea/**/usage.statistics.xml
13+
.idea/**/dictionaries
14+
.idea/**/shelf
15+
16+
# AWS User-specific
17+
.idea/**/aws.xml
18+
19+
# Generated files
20+
.idea/**/contentModel.xml
21+
22+
# Sensitive or high-churn files
23+
.idea/**/dataSources/
24+
.idea/**/dataSources.ids
25+
.idea/**/dataSources.local.xml
26+
.idea/**/sqlDataSources.xml
27+
.idea/**/dynamic.xml
28+
.idea/**/uiDesigner.xml
29+
.idea/**/dbnavigator.xml
30+
31+
# Gradle
32+
.idea/**/gradle.xml
33+
.idea/**/libraries
34+
35+
# Gradle and Maven with auto-import
36+
# When using Gradle or Maven with auto-import, you should exclude module files,
37+
# since they will be recreated, and may cause churn. Uncomment if using
38+
# auto-import.
39+
# .idea/artifacts
40+
# .idea/compiler.xml
41+
# .idea/jarRepositories.xml
42+
# .idea/modules.xml
43+
# .idea/*.iml
44+
# .idea/modules
45+
# *.iml
46+
# *.ipr
47+
48+
# CMake
49+
cmake-build-*/
50+
51+
# Mongo Explorer plugin
52+
.idea/**/mongoSettings.xml
53+
54+
# File-based project format
55+
*.iws
56+
57+
# IntelliJ
58+
out/
59+
60+
# mpeltonen/sbt-idea plugin
61+
.idea_modules/
62+
63+
# JIRA plugin
64+
atlassian-ide-plugin.xml
65+
66+
# Cursive Clojure plugin
67+
.idea/replstate.xml
68+
69+
# SonarLint plugin
70+
.idea/sonarlint/
71+
72+
# Crashlytics plugin (for Android Studio and IntelliJ)
73+
com_crashlytics_export_strings.xml
74+
crashlytics.properties
75+
crashlytics-build.properties
76+
fabric.properties
77+
78+
# Editor-based Rest Client
79+
.idea/httpRequests
80+
81+
# Android studio 3.1+ serialized cache file
82+
.idea/caches/build_file_checksums.ser
83+
84+
### Intellij+all Patch ###
85+
# Ignore everything but code style settings and run configurations
86+
# that are supposed to be shared within teams.
87+
88+
.idea/*
89+
90+
!.idea/codeStyles
91+
!.idea/runConfigurations
92+
93+
### Node ###
94+
# Logs
95+
logs
96+
*.log
97+
npm-debug.log*
98+
yarn-debug.log*
99+
yarn-error.log*
100+
lerna-debug.log*
101+
.pnpm-debug.log*
102+
103+
# Diagnostic reports (https://nodejs.org/api/report.html)
104+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
105+
106+
# Runtime data
107+
pids
108+
*.pid
109+
*.seed
110+
*.pid.lock
111+
112+
# Directory for instrumented libs generated by jscoverage/JSCover
113+
lib-cov
114+
115+
# Coverage directory used by tools like istanbul
116+
coverage
117+
*.lcov
118+
119+
# nyc test coverage
120+
.nyc_output
121+
122+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
123+
.grunt
124+
125+
# Bower dependency directory (https://bower.io/)
126+
bower_components
127+
128+
# node-waf configuration
129+
.lock-wscript
130+
131+
# Compiled binary addons (https://nodejs.org/api/addons.html)
132+
build/Release
133+
134+
# Dependency directories
135+
node_modules/
136+
jspm_packages/
137+
138+
# Snowpack dependency directory (https://snowpack.dev/)
139+
web_modules/
140+
141+
# TypeScript cache
142+
*.tsbuildinfo
143+
144+
# Optional npm cache directory
145+
.npm
146+
147+
# Optional eslint cache
148+
.eslintcache
149+
150+
# Optional stylelint cache
151+
.stylelintcache
152+
153+
# Microbundle cache
154+
.rpt2_cache/
155+
.rts2_cache_cjs/
156+
.rts2_cache_es/
157+
.rts2_cache_umd/
158+
159+
# Optional REPL history
160+
.node_repl_history
161+
162+
# Output of 'npm pack'
163+
*.tgz
164+
165+
# Yarn Integrity file
166+
.yarn-integrity
167+
168+
# dotenv environment variable files
169+
.env
170+
.env.development.local
171+
.env.test.local
172+
.env.production.local
173+
.env.local
174+
175+
# parcel-bundler cache (https://parceljs.org/)
176+
.cache
177+
.parcel-cache
178+
179+
# Next.js build output
180+
.next
181+
out
182+
183+
# Nuxt.js build / generate output
184+
.nuxt
185+
dist
186+
187+
# Gatsby files
188+
.cache/
189+
# Comment in the public line in if your project uses Gatsby and not Next.js
190+
# https://nextjs.org/blog/next-9-1#public-directory-support
191+
# public
192+
193+
# vuepress build output
194+
.vuepress/dist
195+
196+
# vuepress v2.x temp and cache directory
197+
.temp
198+
199+
# Docusaurus cache and generated files
200+
.docusaurus
201+
202+
# Serverless directories
203+
.serverless/
204+
205+
# FuseBox cache
206+
.fusebox/
207+
208+
# DynamoDB Local files
209+
.dynamodb/
210+
211+
# TernJS port file
212+
.tern-port
213+
214+
# Stores VSCode versions used for testing VSCode extensions
215+
.vscode-test
216+
217+
# yarn v2
218+
.yarn/cache
219+
.yarn/unplugged
220+
.yarn/build-state.yml
221+
.yarn/install-state.gz
222+
.pnp.*
223+
224+
### Node Patch ###
225+
# Serverless Webpack directories
226+
.webpack/
227+
228+
# Optional stylelint cache
229+
230+
# SvelteKit build / generate output
231+
.svelte-kit
232+
233+
# End of https://www.toptal.com/developers/gitignore/api/intellij+all,node

dpc-version-rss.iml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="GENERAL_MODULE" version="4">
3+
<component name="NewModuleRootManager" inherit-compiler-output="true">
4+
<exclude-output />
5+
<content url="file://$MODULE_DIR$" />
6+
<orderEntry type="sourceFolder" forTests="false" />
7+
</component>
8+
</module>

index.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import puppeteer from 'puppeteer-extra';
2+
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
3+
import { create } from 'xmlbuilder2';
4+
import { XMLParser } from 'fast-xml-parser';
5+
import fs from 'fs';
6+
7+
puppeteer.use(StealthPlugin());
8+
9+
const URL = 'https://apkpure.com/android-device-policy/com.google.android.apps.work.clouddpc/versions';
10+
11+
(async () => {
12+
const browser = await puppeteer.launch({headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox']});
13+
const page = await browser.newPage();
14+
15+
await page.goto(URL, {waitUntil: 'networkidle2'}); // more aggressive wait
16+
17+
const versions = await page.evaluate(() => {
18+
const items = document.querySelectorAll('li a.ver_download_link');
19+
const result = [];
20+
21+
items.forEach(link => {
22+
const versionDiv = link.querySelector('.ver-item-n');
23+
const dateSpan = link.querySelector('.update-on');
24+
25+
const version = versionDiv ? versionDiv.textContent.trim().replace(/\s+/g, ' ') : null;
26+
const date = dateSpan ? dateSpan.textContent.trim() : null;
27+
const href = link.getAttribute('href');
28+
29+
if (version && date && href) {
30+
result.push({
31+
version,
32+
date,
33+
link: href.startsWith('http') ? href : `https://apkpure.com${href}`
34+
});
35+
}
36+
});
37+
38+
return result;
39+
});
40+
41+
42+
await browser.close();
43+
44+
console.log(`✅ Scraped ${versions.length} versions`);
45+
//console.log(versions);
46+
47+
let existingItems = [];
48+
49+
if (fs.existsSync('rss.xml')) {
50+
const xmlData = fs.readFileSync('rss.xml', 'utf-8');
51+
const parser = new XMLParser();
52+
const parsed = parser.parse(xmlData);
53+
const items = parsed?.rss?.channel?.item || [];
54+
existingItems = Array.isArray(items) ? items : [items];
55+
}
56+
57+
// Use a Set for fast version-date matching
58+
const existingKeys = new Set(
59+
existingItems.map(i => `${i.title}`)
60+
);
61+
62+
// Add only new entries
63+
const newItems = versions
64+
.map(v => ({
65+
title: `${v.version} - ${v.date}`,
66+
link: v.link,
67+
description: `Version ${v.version} released on ${v.date}`
68+
}))
69+
.filter(item => !existingKeys.has(item.title));
70+
71+
// Combine and sort
72+
const allItems = [...newItems, ...existingItems].slice(0, 50); // keep only latest 50
73+
74+
const rss = {
75+
rss: {
76+
'@version': '2.0',
77+
channel: {
78+
title: 'Android Device Policy Versions',
79+
link: 'https://apkpure.com/android-device-policy/com.google.android.apps.work.clouddpc/versions',
80+
description: 'Tracks version updates on APKPure',
81+
item: allItems
82+
}
83+
}
84+
};
85+
86+
const xml = create({version: '1.0', encoding: 'UTF-8'}, rss).end({prettyPrint: true});
87+
fs.writeFileSync('rss.xml', xml);
88+
})();

0 commit comments

Comments
 (0)