diff --git a/docs/en/program-update.md b/docs/en/program-update.md
index 099911a74..1c1c49d2e 100644
--- a/docs/en/program-update.md
+++ b/docs/en/program-update.md
@@ -198,6 +198,12 @@ Language
+## FossHub
+
+### Software Update
+
+
+
## Greasy Fork
### Script Update
diff --git a/docs/program-update.md b/docs/program-update.md
index fdfd470fc..f23d9dfc0 100644
--- a/docs/program-update.md
+++ b/docs/program-update.md
@@ -240,6 +240,12 @@ pageClass: routes
+## FossHub
+
+### Software Update
+
+
+
## Greasy Fork
### 脚本更新
diff --git a/lib/v2/fosshub/index.js b/lib/v2/fosshub/index.js
new file mode 100644
index 000000000..7599032e5
--- /dev/null
+++ b/lib/v2/fosshub/index.js
@@ -0,0 +1,49 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const { art } = require('@/utils/render');
+const path = require('path');
+
+module.exports = async (ctx) => {
+ const id = ctx.params.id ?? '';
+
+ const rootUrl = 'https://www.fosshub.com';
+ const currentUrl = `${rootUrl}/${id}.html`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const version = $('dd[itemprop="softwareVersion"]').first().text();
+
+ const items = [
+ {
+ title: version,
+ link: `${currentUrl}#${version}`,
+ description: art(path.join(__dirname, 'templates/description.art'), {
+ links: $('.dwn-dl')
+ .toArray()
+ .map((l) =>
+ $(l)
+ .find('.w')
+ .toArray()
+ .map((w) => ({
+ dt: $(w).find('dt').text(),
+ dd: $(w).find('dd').html(),
+ }))
+ ),
+ changelog: $('div[itemprop="releaseNotes"]').html(),
+ }),
+ pubDate: parseDate($('.ma__upd .v').text(), 'MMM DD, YYYY'),
+ },
+ ];
+
+ ctx.state.data = {
+ title: `${$('#fh-ssd__hl').text()} - FossHub`,
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/v2/fosshub/maintainer.js b/lib/v2/fosshub/maintainer.js
new file mode 100644
index 000000000..b3ac0c5ab
--- /dev/null
+++ b/lib/v2/fosshub/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/:id': ['nczitzk'],
+};
diff --git a/lib/v2/fosshub/radar.js b/lib/v2/fosshub/radar.js
new file mode 100644
index 000000000..1371e150f
--- /dev/null
+++ b/lib/v2/fosshub/radar.js
@@ -0,0 +1,13 @@
+module.exports = {
+ 'fosshub.com': {
+ _name: 'FossHub',
+ '.': [
+ {
+ title: 'Software Update',
+ docs: 'https://docs.rsshub.app/program-update.html#fosshub-software-update',
+ source: ['/'],
+ target: (params, url) => `/fosshub/${new URL(url).match(/\/(.*?)\.html$/)[1]}`,
+ },
+ ],
+ },
+};
diff --git a/lib/v2/fosshub/router.js b/lib/v2/fosshub/router.js
new file mode 100644
index 000000000..641c23df3
--- /dev/null
+++ b/lib/v2/fosshub/router.js
@@ -0,0 +1,3 @@
+module.exports = function (router) {
+ router.get('/:id', require('./index'));
+};
diff --git a/lib/v2/fosshub/templates/description.art b/lib/v2/fosshub/templates/description.art
new file mode 100644
index 000000000..878b87d04
--- /dev/null
+++ b/lib/v2/fosshub/templates/description.art
@@ -0,0 +1,20 @@
+
+
+{{ each links link }}
+
+{{ each link l }}
+| {{ l.dt }} |
+{{ /each }}
+
+
+{{ each link l }}
+| {{@ l.dd }} |
+{{ /each }}
+
+{{ /each }}
+
+
+{{ if changelog }}
+
+{{@ changelog }}
+{{ /if }}
\ No newline at end of file