oldj 4 lat temu
rodzic
commit
f3e3a4185b

Plik diff jest za duży
+ 630 - 8
package-lock.json


+ 2 - 0
package.json

@@ -20,6 +20,7 @@
     "compare-versions": "^3.6.0",
     "dayjs": "^1.10.4",
     "electron-window-state": "^5.0.3",
+    "express": "^4.17.1",
     "lodash": "^4.17.21",
     "md5": "^2.3.0",
     "md5-file": "^5.0.0",
@@ -37,6 +38,7 @@
     "@emotion/styled": "^11.1.5",
     "@types/assert": "^1.5.4",
     "@types/codemirror": "^0.0.108",
+    "@types/express": "^4.17.11",
     "@types/lodash": "^4.14.168",
     "@types/md5": "^2.3.0",
     "@types/mkdirp": "^1.0.1",

+ 1 - 0
src/common/constants.ts

@@ -9,3 +9,4 @@ export const homepage_url = `${server_url}/home/`
 export const download_url = `${server_url}/download/`
 export const source_url = 'https://github.com/oldj/SwitchHosts'
 export const feedback_url = 'https://github.com/oldj/SwitchHosts/issues'
+export const http_api_port = 50761

+ 1 - 0
src/common/default_configs.ts

@@ -24,6 +24,7 @@ const configs = {
   proxy_protocol: 'http' as ProtocolType,
   proxy_host: '',
   proxy_port: 0,
+  http_api_on: false,
 
   // other
   env: 'PROD' as 'PROD' | 'DEV',

+ 2 - 0
src/common/i18n/languages/en.ts

@@ -63,6 +63,8 @@ export default {
   hosts_updated: 'The Hosts file has been updated.',
   hour: 'hour',
   hours: 'hours',
+  http_api_on: 'HTTP API on',
+  http_api_on_desc: 'Runs on port {0}, can be used by third-party software such as Alfred to switch hosts',
   import: 'Import',
   import_done: 'The import is complete.',
   import_fail: 'Import failed!',

+ 2 - 0
src/common/i18n/languages/zh.ts

@@ -65,6 +65,8 @@ const lang: LanguageDict = {
   hosts_updated: 'Hosts 文件已更新。',
   hour: '小时',
   hours: '小时',
+  http_api_on: '开启 HTTP API',
+  http_api_on_desc: '运行于 {0} 端口,可用于 Alfred 等第三方软件切换 hosts',
   import: '导入',
   import_done: '导入已完成。',
   import_fail: '导入失败!',

+ 16 - 0
src/main/http/api/index.ts

@@ -0,0 +1,16 @@
+/**
+ * index
+ * @author: oldj
+ * @homepage: https://oldj.net
+ */
+
+import express from 'express'
+import list from './list'
+import toggle from './toggle'
+
+const router = express.Router()
+
+router.get('/list', list)
+router.get('/toggle', toggle)
+
+export default router

+ 33 - 0
src/main/http/api/list.ts

@@ -0,0 +1,33 @@
+/**
+ * list
+ * @author: oldj
+ * @homepage: https://oldj.net
+ */
+
+import { getList } from '@main/actions'
+import { IHostsListObject } from '@root/common/data'
+import { flatten } from '@root/common/hostsFn'
+import { Request, Response } from 'express'
+
+const list = async (req: Request, res: Response) => {
+  let list: IHostsListObject[]
+  try {
+    list = await getList()
+  } catch (e) {
+    res.end(JSON.stringify({
+      success: false,
+      message: e.message,
+    }))
+
+    return
+  }
+
+  list = flatten(list)
+
+  res.end(JSON.stringify({
+    success: true,
+    data: list,
+  }))
+}
+
+export default list

+ 31 - 0
src/main/http/api/toggle.ts

@@ -0,0 +1,31 @@
+/**
+ * toggle
+ * @author: oldj
+ * @homepage: https://oldj.net
+ */
+
+import { getList } from '@main/actions'
+import { broadcast } from '@main/core/agent'
+import { findItemById } from '@root/common/hostsFn'
+import { Request, Response } from 'express'
+
+const toggle = async (req: Request, res: Response) => {
+  let { id } = req.query
+  console.log(`http_api toggle: ${id}`)
+  if (!id) {
+    res.end('bad id.')
+    return
+  }
+
+  let list = await getList()
+  let item = findItemById(list, id.toString())
+  if (!item) {
+    res.end('not found.')
+    return
+  }
+
+  broadcast('toggle_item', id, !item.on)
+  res.end('ok')
+}
+
+export default toggle

+ 35 - 0
src/main/http/index.ts

@@ -0,0 +1,35 @@
+/**
+ * index
+ * @author: oldj
+ * @homepage: https://oldj.net
+ */
+
+import express from 'express'
+import { http_api_port } from '@root/common/constants'
+import api_router from './api/index'
+
+export const server = express()
+
+server.use((req, res, next) => {
+  console.log(`> "${(new Date()).toString()}"`, req.method, req.originalUrl, `"${req.headers['user-agent']}"`)
+  next()
+})
+
+server.get('/', (req, res) => {
+  res.send('Hello SwitchHosts!')
+})
+
+server.get('/remote-test', (req, res) => {
+  res.send(`# remote-test\n# ${(new Date()).toString()}`)
+})
+
+server.use('/api', api_router)
+
+try {
+  server.listen(http_api_port, '127.0.0.1', function () {
+    console.log(`SwitchHosts HTTP server is listening on port ${http_api_port}!`)
+    console.log(`-> http://127.0.0.1:${http_api_port}`)
+  })
+} catch (e) {
+  console.error(e)
+}

+ 1 - 0
src/main/main.ts

@@ -7,6 +7,7 @@ import * as cron from '@main/libs/cron'
 import getIndex from '@main/libs/getIndex'
 import isDev from '@main/libs/isDev'
 import { makeMainMenu } from '@main/libs/menu'
+import '@main/http'
 import '@main/tray'
 import version from '@root/version.json'
 import { app, BrowserWindow } from 'electron'

+ 1 - 1
src/renderer/components/List/index.tsx

@@ -50,7 +50,7 @@ const List = (props: Props) => {
   }, [ hosts_data ])
 
   const onToggleItem = async (id: string, on: boolean) => {
-    // console.log(`toggle hosts #${id} as ${on ? 'on' : 'off'}`)
+    console.log(`toggle hosts #${id} as ${on ? 'on' : 'off'}`)
     const new_list = setOnStateOfItem(hosts_data.list, id, on, configs?.choice_mode ?? 0)
     let success = await writeHostsToSystem(new_list)
     if (success) {

+ 14 - 1
src/renderer/components/Pref/General.tsx

@@ -20,6 +20,7 @@ import {
 import { ConfigsType, ThemeType } from '@root/common/default_configs'
 import { LocaleName } from '@root/common/i18n'
 import React from 'react'
+import { http_api_port } from '@root/common/constants'
 
 interface IProps {
   data: ConfigsType;
@@ -28,7 +29,7 @@ interface IProps {
 
 const General = (props: IProps) => {
   const { data, onChange } = props
-  const { lang } = useModel('useI18n')
+  const { i18n, lang } = useModel('useI18n')
 
   const label_width = 20
 
@@ -117,6 +118,18 @@ const General = (props: IProps) => {
           <FormHelperText pl="20px">{lang.remove_duplicate_records_desc}</FormHelperText>
         </VStack>
       </FormControl>
+
+      <FormControl>
+        <VStack align="left">
+          <Checkbox
+            isChecked={data.http_api_on}
+            onChange={e => onChange({ http_api_on: e.target.checked })}
+          >
+            {lang.http_api_on}
+          </Checkbox>
+          <FormHelperText pl="20px">{i18n.trans('http_api_on_desc', [http_api_port.toString()])}</FormHelperText>
+        </VStack>
+      </FormControl>
     </VStack>
   )
 }

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików