Skip to content

Commit 4aae2ec

Browse files
committed
feat(proxy):添加http代理支持来获取外媒新闻功能
- 在设置中添加 http 代理相关配置 - 优化 TradingView 新闻获取逻辑 - 添加 Reuters 新闻获取功能 - 调整行业报告信息获取方法 - 更新前端设置组件以支持 http 代理配置
1 parent 369d140 commit 4aae2ec

File tree

8 files changed

+111
-16
lines changed

8 files changed

+111
-16
lines changed

app.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ func (a *App) CheckUpdate(flag int) {
272272
}
273273
body := resp.Body()
274274

275-
if len(body) < 1024 {
275+
if len(body) < 1024*500 {
276276
go runtime.EventsEmit(a.ctx, "newsPush", map[string]any{
277277
"time": "新版本:" + releaseVersion.TagName,
278278
"isRed": true,
@@ -438,7 +438,7 @@ func (a *App) domReady(ctx context.Context) {
438438
//检查新版本
439439
go func() {
440440
a.CheckUpdate(0)
441-
//a.CheckStockBaseInfo(a.ctx)
441+
a.CheckStockBaseInfo(a.ctx)
442442
a.cron.AddFunc("30 05 8,12,20 * * *", func() {
443443
logger.SugaredLogger.Errorf("Checking for updates...")
444444
a.CheckUpdate(0)

backend/data/market_news_api.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,9 +551,14 @@ func (m MarketNewsApi) EMDictCode(code string, cache *freecache.Cache) []any {
551551
}
552552

553553
func (m MarketNewsApi) TradingViewNews() *[]models.TVNews {
554+
client := resty.New()
555+
config := GetSettingConfig()
556+
if config.HttpProxyEnabled && config.HttpProxy != "" {
557+
client.SetProxy(config.HttpProxy)
558+
}
554559
TVNews := &[]models.TVNews{}
555560
url := "https://news-mediator.tradingview.com/news-flow/v2/news?filter=lang:zh-Hans&filter=provider:panews,reuters&client=screener&streaming=false"
556-
resp, err := resty.New().SetProxy("http://127.0.0.1:10809").SetTimeout(time.Duration(30)*time.Second).R().
561+
resp, err := client.SetTimeout(time.Duration(5)*time.Second).R().
557562
SetHeader("Host", "news-mediator.tradingview.com").
558563
SetHeader("Origin", "https://cn.tradingview.com").
559564
SetHeader("Referer", "https://cn.tradingview.com/").
@@ -833,7 +838,7 @@ func (m MarketNewsApi) GetPMI() *models.PMIResp {
833838
return res
834839

835840
}
836-
func (m MarketNewsApi) GetIndustryReportInfo(infoCode string) {
841+
func (m MarketNewsApi) GetIndustryReportInfo(infoCode string) string {
837842
url := "https://data.eastmoney.com/report/zw_industry.jshtml?infocode=" + infoCode
838843
resp, err := resty.New().SetTimeout(time.Duration(30)*time.Second).R().
839844
SetHeader("Host", "data.eastmoney.com").
@@ -843,7 +848,7 @@ func (m MarketNewsApi) GetIndustryReportInfo(infoCode string) {
843848
Get(url)
844849
if err != nil {
845850
logger.SugaredLogger.Errorf("GetIndustryReportInfo err:%s", err.Error())
846-
return
851+
return ""
847852
}
848853
body := resp.Body()
849854
//logger.SugaredLogger.Debugf("GetIndustryReportInfo:%s", body)
@@ -853,7 +858,25 @@ func (m MarketNewsApi) GetIndustryReportInfo(infoCode string) {
853858
//logger.SugaredLogger.Infof("GetIndustryReportInfo:\n%s\n%s", title, content)
854859
markdown, err := util.HTMLToMarkdown(title + content)
855860
if err != nil {
856-
return
861+
return ""
857862
}
858863
logger.SugaredLogger.Infof("GetIndustryReportInfo markdown:\n%s", markdown)
864+
return markdown
865+
}
866+
867+
func (m MarketNewsApi) ReutersNew() {
868+
url := "https://www.reuters.com/pf/api/v3/content/fetch/articles-by-section-alias-or-id-v1?query=%7B%22arc-site%22%3A%22reuters%22%2C%22fetch_type%22%3A%22collection%22%2C%22offset%22%3A20%2C%22section_id%22%3A%22%2Fworld%2Fchina%2F%22%2C%22size%22%3A9%2C%22uri%22%3A%22%2Fworld%2Fchina%2F%22%2C%22website%22%3A%22reuters%22%7D&d=300&mxId=00000000&_website=reuters"
869+
resp, err := resty.New().SetProxy("http://127.0.0.1:10809").SetTimeout(time.Duration(30)*time.Second).R().
870+
SetHeader("Host", "www.reuters.com").
871+
SetHeader("Origin", "https://www.reuters.com").
872+
SetHeader("Referer", "https://www.reuters.com/world/china/").
873+
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
874+
Get(url)
875+
if err != nil {
876+
logger.SugaredLogger.Errorf("ReutersNew err:%s", err.Error())
877+
return
878+
}
879+
body := resp.Body()
880+
logger.SugaredLogger.Debugf("ReutersNew:%s", body)
881+
859882
}

backend/data/market_news_api_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,13 @@ func TestStockResearchReport(t *testing.T) {
7979

8080
func TestIndustryResearchReport(t *testing.T) {
8181
db.Init("../../data/stock.db")
82-
resp := NewMarketNewsApi().IndustryResearchReport("", 7)
82+
resp := NewMarketNewsApi().IndustryResearchReport("735", 7)
8383
for _, a := range resp {
8484
logger.SugaredLogger.Debugf("value: %+v", a)
85+
data := a.(map[string]any)
86+
logger.SugaredLogger.Debugf("value: %s infoCode:%s", data["title"], data["infoCode"])
87+
NewMarketNewsApi().GetIndustryReportInfo(data["infoCode"].(string))
8588
}
86-
8789
}
8890

8991
func TestStockNotice(t *testing.T) {
@@ -101,14 +103,19 @@ func TestEMDictCode(t *testing.T) {
101103
for _, a := range resp {
102104
logger.SugaredLogger.Debugf("value: %+v", a)
103105
}
106+
bytes, err := json.Marshal(resp)
107+
if err != nil {
108+
return
109+
}
110+
logger.SugaredLogger.Debugf("value: %s", string(bytes))
104111

105112
}
106113

107114
func TestTradingViewNews(t *testing.T) {
108115
db.Init("../../data/stock.db")
109116
resp := NewMarketNewsApi().TradingViewNews()
110117
for _, a := range *resp {
111-
logger.SugaredLogger.Debugf("value: %+v", a)
118+
logger.SugaredLogger.Debugf("value: %s", a.Title)
112119
}
113120
}
114121

@@ -204,3 +211,7 @@ func TestGetPMI(t *testing.T) {
204211
func TestGetIndustryReportInfo(t *testing.T) {
205212
NewMarketNewsApi().GetIndustryReportInfo("AP202507151709216483")
206213
}
214+
215+
func TestReutersNew(t *testing.T) {
216+
NewMarketNewsApi().ReutersNew()
217+
}

backend/data/openai_api.go

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ func (o *OpenAi) NewSummaryStockNewsStream(userQuestion string, sysPromptId *int
338338
"content": "当前本地时间是:" + time.Now().Format("2006-01-02 15:04:05"),
339339
})
340340
wg := &sync.WaitGroup{}
341-
wg.Add(1)
341+
wg.Add(2)
342342
go func() {
343343
defer wg.Done()
344344
var market strings.Builder
@@ -355,6 +355,25 @@ func (o *OpenAi) NewSummaryStockNewsStream(userQuestion string, sysPromptId *int
355355
"content": "当前市场指数行情情况如下:\n" + market.String(),
356356
})
357357
}()
358+
go func() {
359+
defer wg.Done()
360+
resp := NewMarketNewsApi().TradingViewNews()
361+
var newsText strings.Builder
362+
363+
for _, a := range *resp {
364+
logger.SugaredLogger.Debugf("value: %s", a.Title)
365+
newsText.WriteString(a.Title + "\n")
366+
}
367+
msg = append(msg, map[string]interface{}{
368+
"role": "user",
369+
"content": "外媒全球新闻资讯",
370+
})
371+
msg = append(msg, map[string]interface{}{
372+
"role": "assistant",
373+
"content": newsText.String(),
374+
})
375+
}()
376+
358377
wg.Wait()
359378

360379
news := NewMarketNewsApi().GetNewsList("", 100)
@@ -468,9 +487,8 @@ func (o *OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptI
468487
logger.SugaredLogger.Infof("NewChatStream stock:%s stockCode:%s", stock, stockCode)
469488
logger.SugaredLogger.Infof("Prompt:%s", sysPrompt)
470489
logger.SugaredLogger.Infof("final question:%s", question)
471-
472490
wg := &sync.WaitGroup{}
473-
wg.Add(7)
491+
wg.Add(8)
474492

475493
go func() {
476494
defer wg.Done()
@@ -714,6 +732,25 @@ func (o *OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptI
714732
})
715733
}()
716734

735+
go func() {
736+
defer wg.Done()
737+
resp := NewMarketNewsApi().TradingViewNews()
738+
var newsText strings.Builder
739+
740+
for _, a := range *resp {
741+
logger.SugaredLogger.Debugf("value: %s", a.Title)
742+
newsText.WriteString(a.Title + "\n")
743+
}
744+
msg = append(msg, map[string]interface{}{
745+
"role": "user",
746+
"content": "外媒全球新闻资讯",
747+
})
748+
msg = append(msg, map[string]interface{}{
749+
"role": "assistant",
750+
"content": newsText.String(),
751+
})
752+
}()
753+
717754
wg.Wait()
718755
msg = append(msg, map[string]interface{}{
719756
"role": "user",

backend/data/settings_api.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ type Settings struct {
3232
EnableFund bool `json:"enableFund"`
3333
EnablePushNews bool `json:"enablePushNews"`
3434
SponsorCode string `json:"sponsorCode"`
35+
HttpProxy string `json:"httpProxy"`
36+
HttpProxyEnabled bool `json:"httpProxyEnabled"`
3537
}
3638

3739
func (receiver Settings) TableName() string {
@@ -99,6 +101,8 @@ func UpdateConfig(s *SettingConfig) string {
99101
"enable_fund": s.EnableFund,
100102
"enable_push_news": s.EnablePushNews,
101103
"sponsor_code": s.SponsorCode,
104+
"http_proxy": s.HttpProxy,
105+
"http_proxy_enabled": s.HttpProxyEnabled,
102106
})
103107

104108
//更新AiConfig

backend/data/tushare_data_api_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import (
1111
// -----------------------------------------------------------------------------------
1212
func TestGetDaily(t *testing.T) {
1313
db.Init("../../data/stock.db")
14-
tushareApi := NewTushareApi(GetConfig())
14+
tushareApi := NewTushareApi(GetSettingConfig())
1515
res := tushareApi.GetDaily("00927.HK", "20250101", "20250217", 30)
1616
t.Log(res)
1717

1818
}
1919

2020
func TestGetUSDaily(t *testing.T) {
2121
db.Init("../../data/stock.db")
22-
tushareApi := NewTushareApi(GetConfig())
22+
tushareApi := NewTushareApi(GetSettingConfig())
2323

2424
res := tushareApi.GetDaily("gb_AAPL", "20250101", "20250217", 30)
2525
t.Log(res)

frontend/src/components/settings.vue

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ const formValue = ref({
4242
enableFund: false,
4343
enablePushNews: false,
4444
sponsorCode: "",
45+
httpProxy:"",
46+
httpProxyEnabled:false,
4547
})
4648
4749
// 添加一个新的AI配置到列表
@@ -97,6 +99,8 @@ onMounted(() => {
9799
formValue.value.enableFund = res.enableFund
98100
formValue.value.enablePushNews = res.enablePushNews
99101
formValue.value.sponsorCode = res.sponsorCode
102+
formValue.value.httpProxy=res.httpProxy;
103+
formValue.value.httpProxyEnabled=res.httpProxyEnabled;
100104
})
101105
102106
GetPromptTemplates("", "").then(res => {
@@ -131,7 +135,9 @@ function saveConfig() {
131135
darkTheme: formValue.value.darkTheme,
132136
enableFund: formValue.value.enableFund,
133137
enablePushNews: formValue.value.enablePushNews,
134-
sponsorCode: formValue.value.sponsorCode
138+
sponsorCode: formValue.value.sponsorCode,
139+
httpProxy:formValue.value.httpProxy,
140+
httpProxyEnabled:formValue.value.httpProxyEnabled,
135141
})
136142
137143
if (config.sponsorCode) {
@@ -218,6 +224,8 @@ function importConfig() {
218224
formValue.value.enableFund = config.enableFund
219225
formValue.value.enablePushNews = config.enablePushNews
220226
formValue.value.sponsorCode = config.sponsorCode
227+
formValue.value.httpProxy=config.httpProxy
228+
formValue.value.httpProxyEnabled=config.httpProxyEnabled
221229
};
222230
reader.readAsText(file);
223231
};
@@ -354,10 +362,18 @@ function deletePrompt(ID) {
354362
title="资讯采集超时时间(秒)" path="openAI.crawlTimeOut">
355363
<n-input-number min="30" step="1" v-model:value="formValue.openAI.crawlTimeOut"/>
356364
</n-form-item-gi>
357-
<n-form-item-gi :span="6" v-if="formValue.openAI.enable" title="天数越多消耗tokens越多"
365+
<n-form-item-gi :span="4" v-if="formValue.openAI.enable" title="天数越多消耗tokens越多"
358366
label="日K线数据(天)" path="openAI.kDays">
359367
<n-input-number min="30" step="1" max="365" v-model:value="formValue.openAI.kDays"/>
360368
</n-form-item-gi>
369+
<n-form-item-gi :span="2" label="http代理" path="httpProxyEnabled">
370+
<n-switch v-model:value="formValue.httpProxyEnabled"/>
371+
</n-form-item-gi>
372+
<n-form-item-gi :span="10" v-if="formValue.httpProxyEnabled" title="http代理地址"
373+
label="http代理地址" path="httpProxy">
374+
<n-input type="text" placeholder="http代理地址" v-model:value="formValue.httpProxy" clearable/>
375+
</n-form-item-gi>
376+
361377

362378
<n-gi :span="24" v-if="formValue.openAI.enable">
363379
<n-divider title-placement="left">Prompt 内容设置</n-divider>

frontend/wailsjs/go/models.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ export namespace data {
390390
enableFund: boolean;
391391
enablePushNews: boolean;
392392
sponsorCode: string;
393+
httpProxy: string;
394+
httpProxyEnabled: boolean;
393395
aiConfigs: AIConfig[];
394396

395397
static createFrom(source: any = {}) {
@@ -422,6 +424,8 @@ export namespace data {
422424
this.enableFund = source["enableFund"];
423425
this.enablePushNews = source["enablePushNews"];
424426
this.sponsorCode = source["sponsorCode"];
427+
this.httpProxy = source["httpProxy"];
428+
this.httpProxyEnabled = source["httpProxyEnabled"];
425429
this.aiConfigs = this.convertValues(source["aiConfigs"], AIConfig);
426430
}
427431

0 commit comments

Comments
 (0)